Editor.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 Helmet from 'react-helmet'
  22. import { useDispatch, useSelector } from 'react-redux'
  23. import { makeSelectCurrentProject } from 'containers/Projects/selectors'
  24. import {
  25. makeSelectCurrentDisplay,
  26. makeSelectCurrentSlides,
  27. makeSelectCurrentSlide
  28. } from '../selectors'
  29. import { VizActions } from '../actions'
  30. import { Route } from 'react-router-dom'
  31. import { RouteComponentWithParams } from 'utils/types'
  32. import { Layout, PageHeader } from 'antd'
  33. import SplitPane from 'components/SplitPane'
  34. import SlideThumbnailList from '../components/SlideThumbnail'
  35. import DisplayHeader from 'containers/Display/Editor/Header'
  36. import { Display } from 'containers/Display/Loadable'
  37. import { ISlideFormed } from 'containers/Viz/components/types'
  38. import styles from '../Viz.less'
  39. const VizDisplayEditor: React.FC<RouteComponentWithParams> = (props) => {
  40. const dispatch = useDispatch()
  41. const { id: projectId } = useSelector(makeSelectCurrentProject())
  42. const currentDisplay = useSelector(makeSelectCurrentDisplay())
  43. const displayId = currentDisplay.id
  44. const { id: slideId } = useSelector(makeSelectCurrentSlide())
  45. const currentSlides = useSelector(makeSelectCurrentSlides())
  46. const { history } = props
  47. const [selectedSlideIds, setSelectedSlideIds] = useState([])
  48. const clearSelectedSlide = useCallback(() => {
  49. setSelectedSlideIds([])
  50. }, [])
  51. useEffect(() => {
  52. window.addEventListener('click', clearSelectedSlide, false)
  53. return () => {
  54. window.removeEventListener('click', clearSelectedSlide, false)
  55. }
  56. }, [])
  57. const goToViz = useCallback(() => {
  58. history.replace(`/project/${projectId}/vizs`)
  59. }, [projectId])
  60. const selectSlide = useCallback(
  61. (slideId: number, append: boolean) => {
  62. if (append) {
  63. setSelectedSlideIds(
  64. selectedSlideIds.includes(slideId)
  65. ? selectedSlideIds.filter((id) => id !== slideId)
  66. : selectedSlideIds.concat(slideId)
  67. )
  68. } else {
  69. setSelectedSlideIds([slideId])
  70. history.replace(
  71. `/project/${projectId}/display/${displayId}/slide/${slideId}`
  72. )
  73. }
  74. },
  75. [projectId, displayId, selectedSlideIds]
  76. )
  77. const changeDisplayAvatar = useCallback(
  78. (avatar: string) => {
  79. dispatch(
  80. VizActions.editDisplay({
  81. ...currentDisplay,
  82. avatar
  83. })
  84. )
  85. },
  86. [currentDisplay]
  87. )
  88. const editSlides = useCallback((newSlides: ISlideFormed[]) => {
  89. dispatch(VizActions.editSlides(newSlides))
  90. }, [])
  91. const deleteSlides = useCallback(
  92. (targetSlideId?: number) => {
  93. if (!targetSlideId || selectedSlideIds.includes(targetSlideId)) {
  94. dispatch(VizActions.deleteSlides(displayId, selectedSlideIds))
  95. return
  96. }
  97. if (targetSlideId) {
  98. dispatch(VizActions.deleteSlides(displayId, [targetSlideId]))
  99. }
  100. },
  101. [displayId, selectedSlideIds]
  102. )
  103. return (
  104. <>
  105. <Helmet title={`${currentDisplay.name} - Display`} />
  106. <Layout>
  107. <PageHeader
  108. ghost={false}
  109. title={currentDisplay.name}
  110. subTitle={currentDisplay.description}
  111. avatar={{
  112. src: currentDisplay.avatar,
  113. shape: 'square'
  114. }}
  115. extra={<DisplayHeader />}
  116. onBack={goToViz}
  117. />
  118. <SplitPane
  119. className="ant-layout-content"
  120. type="horizontal"
  121. initialSize={120}
  122. minSize={120}
  123. maxSize={200}
  124. >
  125. <SlideThumbnailList
  126. className={styles.slides}
  127. currentSlideId={slideId}
  128. selectedSlideIds={selectedSlideIds}
  129. slides={currentSlides}
  130. onChange={editSlides}
  131. onSelect={selectSlide}
  132. onDelete={deleteSlides}
  133. onChangeDisplayAvatar={changeDisplayAvatar}
  134. />
  135. <Route
  136. path="/project/:projectId/display/:displayId/slide/:slideId"
  137. component={Display}
  138. />
  139. </SplitPane>
  140. </Layout>
  141. </>
  142. )
  143. }
  144. export default VizDisplayEditor