Portal.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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, useCallback, useState } from 'react'
  21. import { createStructuredSelector } from 'reselect'
  22. import { useDispatch, useSelector } from 'react-redux'
  23. import {
  24. makeSelectDownloadList
  25. } from 'containers/App/selectors'
  26. import {
  27. makeSelectPortals,
  28. makeSelectCurrentPortal,
  29. makeSelectCurrentDashboards
  30. } from './selectors'
  31. import {
  32. hideNavigator,
  33. loadDownloadList,
  34. downloadFile
  35. } from 'containers/App/actions'
  36. import { VizActions } from './actions'
  37. import { Route } from 'react-router-dom'
  38. import { RouteComponentWithParams } from 'utils/types'
  39. import {
  40. Layout,
  41. Result,
  42. PageHeader,
  43. Tree,
  44. Icon,
  45. Button,
  46. Menu,
  47. Dropdown
  48. } from 'antd'
  49. const { Header, Sider, Content } = Layout
  50. const { DirectoryTree } = Tree
  51. import SplitPane from 'components/SplitPane'
  52. import DownloadList from 'components/DownloadList'
  53. import useDashboardConfigMenu from './hooks/dashboardConfigMenu'
  54. import { Grid } from 'containers/Dashboard/Loadable'
  55. import useDashboardTreeNodes from './hooks/dashboardTreeNodes'
  56. import { AntTreeNodeMouseEvent } from 'antd/lib/tree'
  57. const mapStateToProps = createStructuredSelector({
  58. downloadList: makeSelectDownloadList(),
  59. portals: makeSelectPortals(),
  60. currentPortal: makeSelectCurrentPortal(),
  61. currentDashboards: makeSelectCurrentDashboards()
  62. })
  63. interface IVizPortalProps extends RouteComponentWithParams {}
  64. const VizPortal: React.FC<IVizPortalProps> = (props) => {
  65. const dispatch = useDispatch()
  66. const {
  67. portals,
  68. currentPortal,
  69. currentDashboards,
  70. downloadList
  71. } = useSelector(mapStateToProps)
  72. const {
  73. history,
  74. match: { params }
  75. } = props
  76. const portalId = +params.portalId
  77. const projectId = +params.projectId
  78. useEffect(() => {
  79. dispatch(hideNavigator())
  80. if (!portals.length) {
  81. dispatch(VizActions.loadPortals(projectId))
  82. }
  83. }, [])
  84. useEffect(() => {
  85. dispatch(VizActions.loadPortalDashboards(portalId))
  86. }, [portalId])
  87. const goToViz = useCallback(() => {
  88. const prefix = window.localStorage.getItem('inDataService') ?? ''
  89. const prefixPath = prefix ? '/' + prefix : prefix
  90. history.replace(`/project/${projectId}${prefixPath}/vizs`)
  91. }, [])
  92. const onLoadDownloadList = useCallback(() => dispatch(loadDownloadList()), [])
  93. const onDownloadFile = useCallback((id) => dispatch(downloadFile(id)), [])
  94. const [dashboardTreeNodes, firstDashboardKey] = useDashboardTreeNodes(currentDashboards)
  95. const [dashboardMenuVisible, setDashboardMenuVisible] = useState(false)
  96. const [dashboardMenuStyle, setDashboardMenuStyle] = useState({})
  97. const dashboardConfigMenu = useDashboardConfigMenu(dashboardMenuStyle)
  98. const closeDashboardMenu = useCallback(() => {
  99. setDashboardMenuVisible(false)
  100. }, [])
  101. useEffect(() => {
  102. document.addEventListener('click', closeDashboardMenu, false)
  103. return () => {
  104. document.removeEventListener('click', closeDashboardMenu, false)
  105. }
  106. }, [])
  107. const showDashboardContextMenu = useCallback((options: AntTreeNodeMouseEvent) => {
  108. const { node, event } = options
  109. const { pageX, pageY } = event
  110. const menuStyle: React.CSSProperties = {
  111. position: 'absolute',
  112. left: pageX,
  113. top: pageY
  114. }
  115. setDashboardMenuStyle(menuStyle)
  116. setDashboardMenuVisible(true)
  117. }, [])
  118. return (
  119. <Layout>
  120. <PageHeader
  121. ghost={false}
  122. title={currentPortal.name}
  123. subTitle={currentPortal.description}
  124. onBack={goToViz}
  125. extra={
  126. <DownloadList
  127. downloadList={downloadList}
  128. onLoadDownloadList={onLoadDownloadList}
  129. onDownloadFile={onDownloadFile}
  130. />
  131. }
  132. />
  133. {dashboardMenuVisible && dashboardConfigMenu}
  134. {Array.isArray(currentDashboards) &&
  135. (currentDashboards.length ? (
  136. <SplitPane
  137. spliter
  138. className="ant-layout-content"
  139. type="horizontal"
  140. initialSize={150}
  141. minSize={150}
  142. >
  143. <DirectoryTree
  144. defaultExpandAll
  145. blockNode
  146. defaultSelectedKeys={firstDashboardKey}
  147. onRightClick={showDashboardContextMenu}
  148. >
  149. {dashboardTreeNodes}
  150. </DirectoryTree>
  151. <Route
  152. path="/project/:projectId/portal/:portalId/dashboard/:dashboardId"
  153. component={Grid}
  154. />
  155. </SplitPane>
  156. ) : (
  157. <Content
  158. style={{
  159. display: 'flex',
  160. flexDirection: 'column',
  161. alignItems: 'center',
  162. justifyContent: 'center'
  163. }}
  164. >
  165. <Result
  166. icon={<img src={require('assets/images/noDashboard.png')} />}
  167. extra={
  168. <p>
  169. <Button size="small" type="link">
  170. 创建文件夹
  171. </Button>
  172. <Button size="small" type="link">
  173. 创建 Dashboard
  174. </Button>
  175. </p>
  176. }
  177. />
  178. </Content>
  179. ))}
  180. </Layout>
  181. )
  182. }
  183. export default VizPortal