Header.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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, { useCallback, useState } from 'react'
  21. import { useDispatch, useSelector } from 'react-redux'
  22. import { useHistory } from 'react-router-dom'
  23. import widgetReducer from 'containers/Widget/reducer'
  24. import widgetSaga from 'containers/Widget/sagas'
  25. import { useInjectReducer } from 'utils/injectReducer'
  26. import { useInjectSaga } from 'utils/injectSaga'
  27. import { VizActions } from 'containers/Viz/actions'
  28. import { WidgetActions } from 'containers/Widget/actions'
  29. import {
  30. makeSelectCurrentDisplay,
  31. makeSelectCurrentSlide
  32. } from 'containers/Viz/selectors'
  33. import { makeSelectWidgets } from 'containers/Widget/selectors'
  34. import { makeSelectCurrentProject } from 'containers/Projects/selectors'
  35. import { GRID_ITEM_MARGIN } from 'app/globalConstants'
  36. import { uuid } from 'utils/util'
  37. import { IWidgetRaw, IWidgetFormed } from 'containers/Widget/types'
  38. import {
  39. GraphTypes,
  40. SecondaryGraphTypes,
  41. LayerOperations,
  42. slideSettings
  43. } from '../components/constants'
  44. import { getDefaultLayerSetting } from '../components/util'
  45. import { PollingSetting } from 'containers/Viz/components/PollingConfig'
  46. import Toolbar, {
  47. Slide,
  48. Setting,
  49. Chart,
  50. OperationBar,
  51. Preview,
  52. Share
  53. } from '../components/Toolbar'
  54. import { DisplaySettingModal } from '../components/Setting'
  55. import SharePanel from './SharePanel'
  56. import WidgetSelectModal from 'containers/Viz/components/WidgetSelectModal'
  57. import useProjectPermission from 'containers/Projects/hooks/projectPermission'
  58. import { makeSelectCurrentLayersMaxIndex } from '../selectors'
  59. import { ILayerFormed } from '../components/types'
  60. import DisplayActions from '../actions'
  61. import { LocationDescriptorObject } from 'history'
  62. const Header: React.FC = () => {
  63. const dispatch = useDispatch()
  64. useInjectReducer({ key: 'widget', reducer: widgetReducer })
  65. useInjectSaga({ key: 'widget', saga: widgetSaga })
  66. const currentDisplay = useSelector(makeSelectCurrentDisplay())
  67. const {
  68. id: currentDisplayId,
  69. name,
  70. config: { displayParams }
  71. } = currentDisplay
  72. const {
  73. id: slideId,
  74. config: {
  75. slideParams: { width: slideWidth, height: slideHeight }
  76. }
  77. } = useSelector(makeSelectCurrentSlide())
  78. const maxLayerIndex = useSelector(makeSelectCurrentLayersMaxIndex())
  79. const widgets = useSelector(makeSelectWidgets())
  80. const { id: projectId } = useSelector(makeSelectCurrentProject())
  81. const [widgetSelectModalVisible, setWidgetSelectModalVisible] = useState(
  82. false
  83. )
  84. const closeWidgetSelectModal = useCallback(() => {
  85. setWidgetSelectModalVisible(false)
  86. }, [])
  87. const [displaySettingModalVisible, setDisplaySettingModalVisible] = useState(
  88. false
  89. )
  90. const saveDisplayParams = useCallback((params) => {
  91. dispatch(
  92. VizActions.editDisplay(
  93. {
  94. ...currentDisplay,
  95. config: {
  96. ...currentDisplay.config,
  97. displayParams: params
  98. }
  99. },
  100. () => {
  101. setDisplaySettingModalVisible(false)
  102. }
  103. )
  104. )
  105. }, [])
  106. const openDisplaySettingModal = useCallback(() => {
  107. setDisplaySettingModalVisible(true)
  108. }, [])
  109. const closeDisplaySettingModal = useCallback(() => {
  110. setDisplaySettingModalVisible(false)
  111. }, [])
  112. const [
  113. AuthorizedSlide,
  114. AuthorizedSetting,
  115. AuthorizedChart,
  116. AuthorizedOperationBar
  117. ] = useProjectPermission(
  118. [Slide, Setting, Chart, OperationBar],
  119. 'vizPermission',
  120. 2
  121. )
  122. const AuthorizedPreview = useProjectPermission(Preview, 'vizPermission')
  123. const AuthorizedShare = useProjectPermission(Share, 'sharePermission')
  124. const addGraph = useCallback(
  125. (type: GraphTypes, subType?: SecondaryGraphTypes) => {
  126. switch (type) {
  127. case GraphTypes.Slide:
  128. dispatch(VizActions.addSlide())
  129. break
  130. case GraphTypes.Chart:
  131. dispatch(WidgetActions.loadWidgets(projectId))
  132. setWidgetSelectModalVisible(true)
  133. break
  134. case GraphTypes.Secondary:
  135. dispatch(
  136. DisplayActions.addSlideLayers(currentDisplayId, slideId, [
  137. {
  138. displaySlideId: slideId,
  139. index: maxLayerIndex + 1,
  140. name: `${slideSettings[subType].title}_${uuid(5)}`,
  141. type: GraphTypes.Secondary,
  142. subType,
  143. params: {
  144. ...getDefaultLayerSetting(GraphTypes.Secondary, subType),
  145. positionX: GRID_ITEM_MARGIN,
  146. positionY: GRID_ITEM_MARGIN
  147. }
  148. }
  149. ])
  150. )
  151. break
  152. }
  153. },
  154. [projectId, currentDisplayId, slideId, maxLayerIndex, widgets]
  155. )
  156. const addWidgetGraph = (
  157. selectedWidgets: IWidgetFormed[],
  158. pollingSetting: PollingSetting
  159. ) => {
  160. const { polling, frequency } = pollingSetting
  161. const newLayers = selectedWidgets.map<Omit<ILayerFormed, 'id'>>(
  162. ({ id, name }, idx) => ({
  163. displaySlideId: slideId,
  164. index: maxLayerIndex + idx + 1,
  165. widgetId: id,
  166. name,
  167. type: GraphTypes.Chart,
  168. params: {
  169. ...getDefaultLayerSetting(GraphTypes.Chart),
  170. width: (slideWidth - GRID_ITEM_MARGIN * 5) / 4,
  171. height: (slideHeight - GRID_ITEM_MARGIN * 5) / 4,
  172. positionX: Math.min(GRID_ITEM_MARGIN * (idx + 1), slideWidth),
  173. positionY: Math.min(GRID_ITEM_MARGIN * (idx + 1), slideHeight),
  174. polling,
  175. frequency
  176. }
  177. })
  178. )
  179. dispatch(
  180. DisplayActions.addSlideLayers(
  181. currentDisplayId,
  182. slideId,
  183. newLayers,
  184. selectedWidgets
  185. )
  186. )
  187. setWidgetSelectModalVisible(false)
  188. }
  189. const operateLayers = useCallback((operation: LayerOperations) => {
  190. switch (operation) {
  191. case LayerOperations.Copy:
  192. dispatch(DisplayActions.copySlideLayers())
  193. break
  194. case LayerOperations.Paste:
  195. dispatch(DisplayActions.pasteSlideLayers())
  196. break
  197. }
  198. }, [])
  199. const history = useHistory()
  200. const preview = useCallback(() => {
  201. const location: LocationDescriptorObject = {
  202. pathname: `/project/${projectId}/display/${currentDisplayId}/preview/slide/${slideId}`
  203. }
  204. const link = document.createElement('a')
  205. link.href = history.createHref(location)
  206. link.target = '_blank'
  207. link.click()
  208. }, [projectId, currentDisplayId, slideId])
  209. const openSharePanel = useCallback(() => {
  210. dispatch(DisplayActions.openSharePanel(currentDisplayId, name))
  211. }, [])
  212. return (
  213. <>
  214. <Toolbar>
  215. <AuthorizedSlide onAdd={addGraph} />
  216. <AuthorizedSetting onSetting={openDisplaySettingModal} />
  217. <AuthorizedChart onAdd={addGraph} />
  218. <AuthorizedOperationBar onOperate={operateLayers} />
  219. <AuthorizedPreview onPreview={preview} />
  220. <AuthorizedShare onShare={openSharePanel} />
  221. </Toolbar>
  222. <DisplaySettingModal
  223. visible={displaySettingModalVisible}
  224. displayParams={displayParams}
  225. onOk={saveDisplayParams}
  226. onCancel={closeDisplaySettingModal}
  227. />
  228. <WidgetSelectModal
  229. visible={widgetSelectModalVisible}
  230. multiple
  231. loading={false}
  232. widgets={widgets}
  233. onOk={addWidgetGraph}
  234. onCancel={closeWidgetSelectModal}
  235. />
  236. <SharePanel />
  237. </>
  238. )
  239. }
  240. export default Header