Sidebar.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React, { useEffect, useMemo, PropsWithChildren } from 'react'
  21. import { useDispatch, useSelector } from 'react-redux'
  22. import {
  23. useLocation,
  24. matchPath,
  25. useHistory
  26. } from 'react-router-dom'
  27. import { showNavigator } from 'containers/App/actions'
  28. import { makeSelectCurrentProject } from 'containers/Projects/selectors'
  29. import { Icon } from 'antd'
  30. import SidebarOption from 'components/SidebarOption'
  31. import Sidebar from 'components/Sidebar'
  32. import { SidebarPermissions } from './constants'
  33. import { IRouteParams } from 'utils/types'
  34. import useProjectPermission from '../Projects/hooks/projectPermission'
  35. import styles from './Main.less'
  36. const sidebarSource: Array<{
  37. icon: React.ReactNode
  38. routes: string[]
  39. permissionName: typeof SidebarPermissions[number]
  40. }> = [
  41. {
  42. icon: <i className="iconfont icon-dashboard" />,
  43. routes: ['vizs'],
  44. permissionName: 'vizPermission'
  45. },
  46. {
  47. icon: <i className="iconfont icon-widget-gallery" />,
  48. routes: ['widgets'],
  49. permissionName: 'widgetPermission'
  50. },
  51. {
  52. icon: <i className="iconfont icon-custom-business" />,
  53. routes: ['views'],
  54. permissionName: 'viewPermission'
  55. },
  56. {
  57. icon: <i className="iconfont icon-datasource24" />,
  58. routes: ['sources'],
  59. permissionName: 'sourcePermission'
  60. },
  61. {
  62. icon: <Icon type="clock-circle" />,
  63. routes: ['schedules'],
  64. permissionName: 'schedulePermission'
  65. }
  66. ]
  67. const MainSidebar: React.FC<PropsWithChildren<{}>> = (props) => {
  68. const dispatch = useDispatch()
  69. useEffect(() => {
  70. dispatch(showNavigator())
  71. }, [])
  72. const location = useLocation()
  73. const { pathname } = location
  74. const history = useHistory()
  75. const currentProject = useSelector(makeSelectCurrentProject())
  76. useEffect(() => {
  77. if (!currentProject) {
  78. return
  79. }
  80. const { id: projectId, permission } = currentProject
  81. const match = matchPath<IRouteParams>(pathname, {
  82. path: `/project/:projectId`,
  83. exact: true,
  84. strict: false
  85. })
  86. if (match) {
  87. const hasPermission = SidebarPermissions.some((sidebarPermission) => {
  88. if (permission[sidebarPermission] > 0) {
  89. const path = sidebarPermission.slice(0, -10)
  90. history.replace(`/project/${projectId}/${path}s`)
  91. return true
  92. }
  93. })
  94. !hasPermission && history.replace('/noAuthorization')
  95. }
  96. }, [pathname, currentProject])
  97. const AuthorizedSidebarOptions = useProjectPermission(
  98. SidebarOption,
  99. sidebarSource.map(({ permissionName }) => permissionName)
  100. )
  101. const sidebar = useMemo(() => {
  102. if (!currentProject) {
  103. return null
  104. }
  105. const { id: projectId, permission } = currentProject
  106. const vizOnly = SidebarPermissions.every((permissionName) =>
  107. permissionName == 'vizPermission'
  108. ? permission[permissionName]
  109. : !permission[permissionName]
  110. )
  111. if (vizOnly) {
  112. return null
  113. }
  114. const sidebarOptions = sidebarSource.map(
  115. ({ permissionName, routes, icon }, idx) => {
  116. if (!permission[permissionName]) {
  117. return null
  118. }
  119. const active = routes.some((route) => pathname.includes(route))
  120. const AuthorizedSidebarOption = AuthorizedSidebarOptions[idx]
  121. return (
  122. <AuthorizedSidebarOption
  123. key={permissionName}
  124. active={active}
  125. indexRoute={routes[0]}
  126. projectId={projectId}
  127. icon={icon}
  128. />
  129. )
  130. }
  131. )
  132. return <Sidebar>{sidebarOptions}</Sidebar>
  133. }, [currentProject, pathname])
  134. return (
  135. <div className={styles.sidebar}>
  136. {sidebar}
  137. <div className={styles.content}>{props.children}</div>
  138. </div>
  139. )
  140. }
  141. export default MainSidebar