sagas.ts 21 KB

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