sagas.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  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 {
  21. call,
  22. put,
  23. all,
  24. select,
  25. takeLatest,
  26. takeEvery,
  27. take
  28. } from 'redux-saga/effects'
  29. import produce from 'immer'
  30. import request from 'utils/request'
  31. import api from 'utils/api'
  32. import { errorHandler } from 'utils/util'
  33. import { ActionTypes, DragTriggerTypes } from './constants'
  34. import DisplayActions, { DisplayActionType } from './actions'
  35. import {
  36. ILayerRaw,
  37. ILayerParams,
  38. Layer,
  39. ILayerFormed,
  40. LayersOperationInfo,
  41. DeltaPosition,
  42. DeltaSize
  43. } from './components/types'
  44. import { IWidgetRaw } from '../Widget/types'
  45. import VizActions from 'containers/Viz/actions'
  46. import ViewActions from 'containers/View/actions'
  47. import { getViewsDetail } from 'containers/View/sagas'
  48. import {
  49. makeSelectLayersBySlide,
  50. makeSelectCurrentSelectedLayerList,
  51. makeSelectCurrentLayerList,
  52. makeSelectCurrentSelectedLayerIds,
  53. makeSelectCurrentOperatingLayerList,
  54. makeSelectCurrentOtherLayerList,
  55. makeSelectClipboardLayers,
  56. makeSelectCurrentOperateItemParams,
  57. makeSelectCurrentEditLayerOperationInfo
  58. } from './selectors'
  59. import { makeSelectFormedViews } from 'containers/View/selectors'
  60. import { bringToFront, sendToBottom, bringToUpper, sendToNext } from './util'
  61. import { LayerOperations } from './components/constants'
  62. import {
  63. makeSelectCurrentDisplay,
  64. makeSelectCurrentSlide
  65. } from '../Viz/selectors'
  66. import { computeEditorBaselines, setLayersAlignment } from './components/util'
  67. import { DefaultDisplayParams } from './components/Setting/constants'
  68. import { IDisplayFormed } from '../Viz/types'
  69. import { IWidgetConfig } from '../Widget/components/Widget'
  70. import {
  71. widgetConfigMigrationRecorder,
  72. displayParamsMigrationRecorder
  73. } from 'app/utils/migrationRecorders'
  74. import { OperationInfo } from './components/Layer/types'
  75. import { SecondaryGraphTypes } from './components/Setting'
  76. import { IFormedViews } from '../View/types'
  77. export function* getSlideDetail (action: DisplayActionType) {
  78. if (action.type !== ActionTypes.LOAD_SLIDE_DETAIL) {
  79. return
  80. }
  81. const { displayId, slideId } = action.payload
  82. const layers: LayersOperationInfo = yield select((state) =>
  83. makeSelectLayersBySlide()(state, slideId)
  84. )
  85. if (layers) {
  86. return
  87. }
  88. const { slideDetailLoaded, loadSlideDetailFail } = DisplayActions
  89. try {
  90. const slideDetail = yield call(
  91. request,
  92. `${api.display}/${displayId}/slides/${slideId}`
  93. )
  94. const { items, views, widgets } = slideDetail.payload || {
  95. items: [],
  96. views: [],
  97. widgets: []
  98. }
  99. items.forEach((item: ILayerRaw) => {
  100. const { subType } = item
  101. const parsedParams: ILayerParams = JSON.parse(item.params)
  102. item.params =
  103. SecondaryGraphTypes.Label === subType
  104. ? displayParamsMigrationRecorder(parsedParams)
  105. : parsedParams
  106. })
  107. widgets.forEach((widget: IWidgetRaw) => {
  108. const parsedConfig: IWidgetConfig = JSON.parse(widget.config)
  109. widget.config = widgetConfigMigrationRecorder(parsedConfig, {
  110. viewId: widget.viewId
  111. })
  112. })
  113. const formedViews: IFormedViews = views.reduce(
  114. (obj, view) => {
  115. obj[view.id] = {
  116. ...view,
  117. model: JSON.parse(view.model || '{}'),
  118. variable: JSON.parse(view.variable || '[]')
  119. }
  120. return obj
  121. },
  122. {}
  123. )
  124. yield put(slideDetailLoaded(slideId, items, widgets, formedViews))
  125. } catch (err) {
  126. yield put(loadSlideDetailFail(err))
  127. }
  128. }
  129. export function* uploadCurrentSlideCover (action: DisplayActionType) {
  130. if (action.type !== ActionTypes.UPLOAD_CURRENT_SLIDE_COVER) {
  131. return
  132. }
  133. const { cover, slide } = action.payload
  134. const {
  135. currentSlideCoverUploaded,
  136. uploadCurrentSlideCoverFail
  137. } = DisplayActions
  138. try {
  139. const formData = new FormData()
  140. formData.append('coverImage', new File([cover], 'coverImage.png'))
  141. const asyncData = yield call(request, `${api.display}/upload/coverImage`, {
  142. method: 'post',
  143. data: formData
  144. })
  145. const coverPath = asyncData.payload
  146. yield put(currentSlideCoverUploaded(coverPath))
  147. const editedSlide = produce(slide, (draft) => {
  148. draft.config.slideParams.avatar = coverPath
  149. })
  150. yield put(VizActions.editSlides([editedSlide]))
  151. } catch (err) {
  152. yield put(uploadCurrentSlideCoverFail(err))
  153. errorHandler(err)
  154. }
  155. }
  156. export function* addSlideLayers (action: DisplayActionType) {
  157. if (action.type !== ActionTypes.ADD_SLIDE_LAYERS) {
  158. return
  159. }
  160. const { displayId, slideId, layers, widgets } = action.payload
  161. const { slideLayersAdded, addSlideLayersFail } = DisplayActions
  162. const formedViews = yield select(makeSelectFormedViews())
  163. const requestViewIds = []
  164. if (Array.isArray(widgets)) {
  165. widgets.forEach((w) => {
  166. if (w.viewId && !formedViews[w.viewId]) {
  167. requestViewIds.push(w.viewId)
  168. }
  169. })
  170. }
  171. try {
  172. if (requestViewIds.length) {
  173. yield getViewsDetail(ViewActions.loadViewsDetail(requestViewIds))
  174. }
  175. const asyncData = yield call(
  176. request,
  177. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  178. {
  179. method: 'post',
  180. data: layers.map<Omit<ILayerRaw, 'id'>>((layer) => ({
  181. ...layer,
  182. params: JSON.stringify(layer.params)
  183. }))
  184. }
  185. )
  186. const result: Layer[] = asyncData.payload
  187. result.forEach((item) => (item.params = JSON.parse(item.params as string)))
  188. yield put(slideLayersAdded(slideId, result as ILayerFormed[], widgets))
  189. return result
  190. } catch (err) {
  191. yield put(addSlideLayersFail())
  192. errorHandler(err)
  193. }
  194. }
  195. export function* editSlideLayers (action: DisplayActionType) {
  196. if (action.type !== ActionTypes.EDIT_SLIDE_LAYERS) {
  197. return
  198. }
  199. const { displayId, slideId, layers, layerParamsUnChanged } = action.payload
  200. const { slideLayersEdited, editSlideLayersFail } = DisplayActions
  201. try {
  202. if (!layerParamsUnChanged) {
  203. yield call(
  204. request,
  205. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  206. {
  207. method: 'put',
  208. data: layers.map<ILayerRaw>((layer) => ({
  209. ...layer,
  210. params: JSON.stringify(layer.params)
  211. }))
  212. }
  213. )
  214. }
  215. yield put(slideLayersEdited(slideId, layers))
  216. } catch (err) {
  217. yield put(editSlideLayersFail())
  218. errorHandler(err)
  219. }
  220. }
  221. export function* editSlideLayerParams (action: DisplayActionType) {
  222. if (action.type !== ActionTypes.EDIT_SLIDE_LAYER_PARAMS) {
  223. return
  224. }
  225. const layerList: ILayerFormed[] = yield select(makeSelectCurrentLayerList())
  226. if (!layerList.length) {
  227. return
  228. }
  229. const layer = layerList.find(({ id }) => id === action.payload.layerId)
  230. const { id: displayId } = yield select(makeSelectCurrentDisplay())
  231. const { id: slideId } = yield select(makeSelectCurrentSlide())
  232. const updateLayer = {
  233. ...layer,
  234. params: {
  235. ...layer.params,
  236. ...action.payload.changedParams
  237. }
  238. }
  239. yield put(DisplayActions.editSlideLayers(displayId, slideId, [updateLayer]))
  240. }
  241. export function* deleteSlideLayers (action: DisplayActionType) {
  242. if (action.type !== ActionTypes.DELETE_SLIDE_LAYERS) {
  243. return
  244. }
  245. const { displayId, slideId } = action.payload
  246. const { slideLayersDeleted, deleteSlideLayersFail } = DisplayActions
  247. const selectedLayerIds: number[] = yield select(
  248. makeSelectCurrentSelectedLayerIds()
  249. )
  250. const editedLayerInfo: OperationInfo[] = yield select(
  251. makeSelectCurrentEditLayerOperationInfo()
  252. )
  253. if (editedLayerInfo.length) {
  254. return
  255. }
  256. if (!selectedLayerIds.length) {
  257. return
  258. }
  259. try {
  260. yield call(
  261. request,
  262. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  263. {
  264. method: 'delete',
  265. data: selectedLayerIds
  266. }
  267. )
  268. yield put(slideLayersDeleted(slideId, selectedLayerIds))
  269. } catch (err) {
  270. yield put(deleteSlideLayersFail())
  271. errorHandler(err)
  272. }
  273. }
  274. export function* dragLayer (action: DisplayActionType) {
  275. if (action.type !== ActionTypes.DRAG_LAYER) {
  276. return
  277. }
  278. const {
  279. deltaPosition,
  280. layerId,
  281. finish,
  282. slideSize,
  283. scale,
  284. eventTrigger
  285. } = action.payload
  286. const movingLayers: ILayerFormed[] = yield select((state) =>
  287. makeSelectCurrentOperatingLayerList()(state, layerId)
  288. )
  289. const editedLayerInfo: OperationInfo[] = yield select(
  290. makeSelectCurrentEditLayerOperationInfo()
  291. )
  292. if (!movingLayers.length) {
  293. return
  294. }
  295. if (editedLayerInfo.length) {
  296. return
  297. }
  298. const operateItemParams = yield select(makeSelectCurrentOperateItemParams())
  299. const layerParamsUnChanged = operateItemParams.length === 0
  300. const operateParamsMap = new Map()
  301. operateItemParams.forEach((item) => {
  302. operateParamsMap.set(item.id, item)
  303. })
  304. const updateMovingLayers = movingLayers.map((layer) => {
  305. const id = layer.id
  306. if (operateParamsMap.has(id)) {
  307. layer.params = operateParamsMap.get(id).params
  308. return { ...{}, ...layer, ...{ params: operateParamsMap.get(id).params } }
  309. }
  310. return layer
  311. })
  312. const otherLayers = yield select((state) =>
  313. makeSelectCurrentOtherLayerList()(state, layerId)
  314. )
  315. const {
  316. id: displayId,
  317. config: { displayParams }
  318. }: IDisplayFormed = yield select(makeSelectCurrentDisplay())
  319. const { id: slideId } = yield select(makeSelectCurrentSlide())
  320. const [updateMovingLayerItem] = updateMovingLayers
  321. const { subType } = updateMovingLayerItem
  322. const baselines = computeEditorBaselines(
  323. updateMovingLayers,
  324. otherLayers,
  325. slideSize,
  326. (displayParams || DefaultDisplayParams).grid,
  327. scale,
  328. { ...deltaPosition, deltaWidth: 0, deltaHeight: 0 },
  329. 'position'
  330. )
  331. const { deltaX, deltaY } = deltaPosition
  332. const needSnapToGrid = eventTrigger === DragTriggerTypes.MouseMove
  333. const deltaPositionAdjusted: DeltaPosition = baselines.reduce<DeltaPosition>(
  334. (acc, bl) => ({
  335. deltaX: acc.deltaX + (needSnapToGrid && bl.adjust[0]),
  336. deltaY: acc.deltaY + (needSnapToGrid && bl.adjust[1])
  337. }),
  338. { deltaX, deltaY }
  339. )
  340. yield put(
  341. DisplayActions.dragLayerAdjusted(
  342. updateMovingLayers.map(({ id }) => id),
  343. slideSize,
  344. deltaPositionAdjusted,
  345. finish
  346. )
  347. )
  348. if (subType !== SecondaryGraphTypes.Label) {
  349. yield put(DisplayActions.showEditorBaselines(baselines))
  350. }
  351. if (finish) {
  352. const updateLayers = produce(updateMovingLayers, (draft) => {
  353. draft.forEach((layer) => {
  354. const item = operateParamsMap.get(layer.id)
  355. if (item) {
  356. layer.params.positionX += deltaX
  357. layer.params.positionY += deltaY
  358. }
  359. })
  360. })
  361. yield put(
  362. DisplayActions.editSlideLayers(
  363. displayId,
  364. slideId,
  365. updateLayers,
  366. layerParamsUnChanged
  367. )
  368. )
  369. yield take(ActionTypes.EDIT_SLIDE_LAYERS_SUCCESS)
  370. yield put(DisplayActions.clearEditorBaselines())
  371. }
  372. }
  373. export function* resizeLayer (action: DisplayActionType) {
  374. if (action.type !== ActionTypes.RESIZE_LAYER) {
  375. return
  376. }
  377. const { deltaSize, layerId, finish, slideSize, scale } = action.payload
  378. const resizingLayers: ILayerFormed[] = yield select((state) =>
  379. makeSelectCurrentOperatingLayerList()(state, layerId)
  380. )
  381. if (!resizingLayers.length) {
  382. return
  383. }
  384. const otherLayers = yield select((state) =>
  385. makeSelectCurrentOtherLayerList()(state, layerId)
  386. )
  387. const {
  388. id: displayId,
  389. config: { displayParams }
  390. }: IDisplayFormed = yield select(makeSelectCurrentDisplay())
  391. const { id: slideId } = yield select(makeSelectCurrentSlide())
  392. const [resizingLayerItem] = resizingLayers
  393. const { subType } = resizingLayerItem
  394. const baselines = computeEditorBaselines(
  395. resizingLayers,
  396. otherLayers,
  397. slideSize,
  398. (displayParams || DefaultDisplayParams).grid,
  399. scale,
  400. { ...deltaSize, deltaX: 0, deltaY: 0 },
  401. 'size'
  402. )
  403. const { deltaWidth, deltaHeight } = deltaSize
  404. const deltaSizeAdjusted: DeltaSize = baselines.reduce<DeltaSize>(
  405. (acc, bl) => ({
  406. deltaWidth: acc.deltaWidth + bl.adjust[0],
  407. deltaHeight: acc.deltaHeight + bl.adjust[1]
  408. }),
  409. { deltaWidth, deltaHeight }
  410. )
  411. if (finish) {
  412. const updateLayers = produce(resizingLayers, (draft) => {
  413. draft.forEach((layer) => {
  414. layer.params.width += deltaWidth
  415. layer.params.height += deltaHeight
  416. })
  417. })
  418. yield put(DisplayActions.editSlideLayers(displayId, slideId, updateLayers))
  419. yield put(DisplayActions.clearEditorBaselines())
  420. } else {
  421. if (subType !== SecondaryGraphTypes.Label) {
  422. yield put(DisplayActions.showEditorBaselines(baselines))
  423. }
  424. }
  425. yield put(
  426. DisplayActions.resizeLayerAdjusted(
  427. resizingLayers.map(({ id }) => id),
  428. deltaSizeAdjusted,
  429. finish
  430. )
  431. )
  432. }
  433. export function* copySlideLayers (action: DisplayActionType) {
  434. if (action.type !== ActionTypes.COPY_SLIDE_LAYERS) {
  435. return
  436. }
  437. const selectedLayers: ILayerFormed[] = yield select(
  438. makeSelectCurrentSelectedLayerList()
  439. )
  440. if (!selectedLayers) {
  441. return
  442. }
  443. yield put(DisplayActions.slideLayersCopied(selectedLayers))
  444. }
  445. export function* pasteSlideLayers (action: DisplayActionType) {
  446. if (action.type !== ActionTypes.PASTE_SLIDE_LAYERS) {
  447. return
  448. }
  449. const clipboardLayers: ILayerFormed[] = yield select(
  450. makeSelectClipboardLayers()
  451. )
  452. if (!clipboardLayers.length) {
  453. return
  454. }
  455. const { id: displayId } = yield select(makeSelectCurrentDisplay())
  456. const { id: slideId } = yield select(makeSelectCurrentSlide())
  457. const layers = produce(clipboardLayers, (draft) => {
  458. draft.forEach((layer) => {
  459. layer.id = undefined
  460. layer.displaySlideId = slideId
  461. })
  462. })
  463. yield put(DisplayActions.addSlideLayers(displayId, slideId, layers))
  464. }
  465. export function* changeLayersStack (action: DisplayActionType) {
  466. if (action.type !== ActionTypes.CHANGE_LAYERS_STACK) {
  467. return
  468. }
  469. const selectedLayerList = yield select(makeSelectCurrentSelectedLayerList())
  470. if (!selectedLayerList.length) {
  471. return
  472. }
  473. const { operation } = action.payload
  474. const { id: displayId } = yield select(makeSelectCurrentDisplay())
  475. const { id: slideId } = yield select(makeSelectCurrentSlide())
  476. const layers = yield select(makeSelectCurrentLayerList())
  477. let updateLayers: ILayerFormed[]
  478. switch (operation) {
  479. case LayerOperations.BringToFront:
  480. updateLayers = bringToFront(selectedLayerList, layers)
  481. break
  482. case LayerOperations.SendToBottom:
  483. updateLayers = sendToBottom(selectedLayerList, layers)
  484. break
  485. case LayerOperations.BringToUpper:
  486. updateLayers = bringToUpper(selectedLayerList, layers)
  487. break
  488. case LayerOperations.SendToNext:
  489. updateLayers = sendToNext(selectedLayerList, layers)
  490. break
  491. }
  492. if (!updateLayers.length) {
  493. return
  494. }
  495. yield put(DisplayActions.editSlideLayers(displayId, slideId, updateLayers))
  496. }
  497. export function* updateLayersAlignment (action: DisplayActionType) {
  498. if (action.type !== ActionTypes.SET_LAYERS_ALIGNMENT) {
  499. return
  500. }
  501. const selectedLayerList = yield select(makeSelectCurrentSelectedLayerList())
  502. if (!selectedLayerList.length) {
  503. return
  504. }
  505. const { id: displayId } = yield select(makeSelectCurrentDisplay())
  506. const { id: slideId } = yield select(makeSelectCurrentSlide())
  507. const updateLayers = setLayersAlignment(
  508. selectedLayerList,
  509. action.payload.alignmentType
  510. )
  511. yield put(DisplayActions.editSlideLayers(displayId, slideId, updateLayers))
  512. }
  513. export function* getDisplayShareLink (action: DisplayActionType) {
  514. if (action.type !== ActionTypes.LOAD_DISPLAY_SHARE_LINK) {
  515. return
  516. }
  517. const { id, mode, expired, permission, roles, viewers } = action.payload.params
  518. const {
  519. displayAuthorizedShareLinkLoaded,
  520. displayShareLinkLoaded,
  521. loadDisplayShareLinkFail,
  522. displayPasswordShareLinkLoaded
  523. } = DisplayActions
  524. let requestData = null
  525. switch (mode) {
  526. case 'AUTH':
  527. requestData = { mode, expired, permission, roles, viewers }
  528. break
  529. case 'PASSWORD':
  530. case 'NORMAL':
  531. requestData = { mode, expired }
  532. break
  533. default:
  534. break
  535. }
  536. try {
  537. const asyncData = yield call(request, {
  538. method: 'POST',
  539. url: `${api.display}/${id}/share`,
  540. data: requestData
  541. })
  542. const { token, password } = asyncData.payload
  543. switch (mode) {
  544. case 'AUTH':
  545. yield put(displayAuthorizedShareLinkLoaded(token))
  546. break
  547. case 'PASSWORD':
  548. yield put(displayPasswordShareLinkLoaded(token, password))
  549. break
  550. case 'NORMAL':
  551. yield put(displayShareLinkLoaded(token))
  552. break
  553. default:
  554. break
  555. }
  556. } catch (err) {
  557. yield put(loadDisplayShareLinkFail())
  558. errorHandler(err)
  559. }
  560. }
  561. export function* undoOperation (action: DisplayActionType) {
  562. if (action.type !== ActionTypes.UNDO_OPERATION) {
  563. return
  564. }
  565. const { currentState } = action.payload
  566. const { displayId, slide, lastOperationType, lastLayers } = currentState
  567. const slideId = slide.id
  568. const { undoOperationDone, undoOperationFail } = DisplayActions
  569. try {
  570. switch (lastOperationType) {
  571. // case ActionTypes.EDIT_CURRENT_SLIDE_SUCCESS:
  572. // yield call(request, `${api.display}/${displayId}/slides`, {
  573. // method: 'put',
  574. // data: [
  575. // {
  576. // ...slide,
  577. // displayId
  578. // }
  579. // ]
  580. // })
  581. // break
  582. case ActionTypes.ADD_SLIDE_LAYERS_SUCCESS:
  583. // case ActionTypes.PASTE_SLIDE_LAYERS_SUCCESS:
  584. const deleteLayerIds = lastLayers.map((l) => l.id)
  585. yield call(
  586. request,
  587. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  588. {
  589. method: 'delete',
  590. data: deleteLayerIds
  591. }
  592. )
  593. break
  594. case ActionTypes.DELETE_SLIDE_LAYERS_SUCCESS:
  595. yield call(
  596. request,
  597. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  598. {
  599. method: 'post',
  600. data: lastLayers
  601. }
  602. )
  603. break
  604. case ActionTypes.EDIT_SLIDE_LAYERS_SUCCESS:
  605. yield call(
  606. request,
  607. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  608. {
  609. method: 'put',
  610. data: lastLayers
  611. }
  612. )
  613. break
  614. }
  615. yield put(undoOperationDone())
  616. } catch (err) {
  617. yield put(undoOperationFail())
  618. errorHandler(err)
  619. }
  620. }
  621. export function* redoOperation (action: DisplayActionType) {
  622. if (action.type !== ActionTypes.REDO_OPERATION) {
  623. return
  624. }
  625. const { nextState } = action.payload
  626. const { displayId, slide, lastOperationType, lastLayers } = nextState
  627. const slideId = slide.id
  628. const { redoOperationDone, redoOperationFail } = DisplayActions
  629. try {
  630. switch (lastOperationType) {
  631. // case ActionTypes.EDIT_CURRENT_SLIDE_SUCCESS:
  632. // yield call(request, `${api.display}/${displayId}/slides`, {
  633. // method: 'put',
  634. // data: [
  635. // {
  636. // ...slide,
  637. // displayId
  638. // }
  639. // ]
  640. // })
  641. // break
  642. case ActionTypes.ADD_SLIDE_LAYERS_SUCCESS:
  643. // case ActionTypes.PASTE_SLIDE_LAYERS_SUCCESS:
  644. yield call(
  645. request,
  646. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  647. {
  648. method: 'post',
  649. data: lastLayers
  650. }
  651. )
  652. break
  653. case ActionTypes.DELETE_SLIDE_LAYERS_SUCCESS:
  654. const deleteLayerIds = lastLayers.map((l) => l.id)
  655. yield call(
  656. request,
  657. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  658. {
  659. method: 'delete',
  660. data: deleteLayerIds
  661. }
  662. )
  663. break
  664. case ActionTypes.EDIT_SLIDE_LAYERS_SUCCESS:
  665. yield call(
  666. request,
  667. `${api.display}/${displayId}/slides/${slideId}/widgets`,
  668. {
  669. method: 'put',
  670. data: lastLayers
  671. }
  672. )
  673. break
  674. }
  675. yield put(redoOperationDone())
  676. } catch (err) {
  677. yield put(redoOperationFail())
  678. errorHandler(err)
  679. }
  680. }
  681. export default function* rootDisplaySaga () {
  682. yield all([
  683. takeLatest(ActionTypes.LOAD_SLIDE_DETAIL, getSlideDetail),
  684. takeEvery(ActionTypes.UPLOAD_CURRENT_SLIDE_COVER, uploadCurrentSlideCover),
  685. takeEvery(ActionTypes.ADD_SLIDE_LAYERS, addSlideLayers),
  686. takeEvery(ActionTypes.EDIT_SLIDE_LAYERS, editSlideLayers),
  687. takeEvery(ActionTypes.EDIT_SLIDE_LAYER_PARAMS, editSlideLayerParams),
  688. takeEvery(ActionTypes.DELETE_SLIDE_LAYERS, deleteSlideLayers),
  689. takeEvery(ActionTypes.COPY_SLIDE_LAYERS, copySlideLayers),
  690. takeEvery(ActionTypes.PASTE_SLIDE_LAYERS, pasteSlideLayers),
  691. takeLatest(ActionTypes.DRAG_LAYER, dragLayer),
  692. takeLatest(ActionTypes.RESIZE_LAYER, resizeLayer),
  693. takeEvery(ActionTypes.CHANGE_LAYERS_STACK, changeLayersStack),
  694. takeLatest(ActionTypes.SET_LAYERS_ALIGNMENT, updateLayersAlignment),
  695. takeLatest(ActionTypes.LOAD_DISPLAY_SHARE_LINK, getDisplayShareLink),
  696. takeEvery(ActionTypes.UNDO_OPERATION, undoOperation),
  697. takeEvery(ActionTypes.REDO_OPERATION, redoOperation)
  698. ])
  699. }