FolderItem.hooks.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { foldersActions, IFolder } from '../../../stores/reducers/folders/slice';
  2. import { useEffect, useState } from 'react';
  3. import { useAppDispatch, useAppSelector } from '../../../stores/store';
  4. import { IPage, pagesActions } from '../../../stores/reducers/pages/slice';
  5. import { AppPB, ViewLayoutTypePB } from '../../../../services/backend';
  6. import { AppBackendService } from '../../../stores/effects/folder/app/app_bd_svc';
  7. import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc';
  8. import { useError } from '../../error/Error.hooks';
  9. import { AppObserver } from '../../../stores/effects/folder/app/app_observer';
  10. import { activePageIdActions } from '../../../stores/reducers/activePageId/slice';
  11. import { useNavigate } from 'react-router-dom';
  12. import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants';
  13. export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
  14. const appDispatch = useAppDispatch();
  15. const workspace = useAppSelector((state) => state.workspace);
  16. const foldersStore = useAppSelector((state) => state.folders);
  17. const navigate = useNavigate();
  18. // Actions
  19. const [showPages, setShowPages] = useState(false);
  20. const [showFolderOptions, setShowFolderOptions] = useState(false);
  21. const [showNewPageOptions, setShowNewPageOptions] = useState(false);
  22. const [showRenamePopup, setShowRenamePopup] = useState(false);
  23. // UI configurations
  24. const [folderHeight, setFolderHeight] = useState(`${INITIAL_FOLDER_HEIGHT}px`);
  25. // Observers
  26. const appObserver = new AppObserver(folder.id);
  27. // Backend services
  28. const appBackendService = new AppBackendService(folder.id);
  29. const workspaceBackendService = new WorkspaceBackendService(workspace.id || '');
  30. // Error
  31. const error = useError();
  32. useEffect(() => {
  33. void appObserver.subscribe({
  34. onAppChanged: (change) => {
  35. if (change.ok) {
  36. const app: AppPB = change.val;
  37. const updatedPages: IPage[] = app.belongings.items.map((view) => ({
  38. id: view.id,
  39. folderId: view.app_id,
  40. pageType: view.layout,
  41. title: view.name,
  42. }));
  43. appDispatch(pagesActions.didReceivePages(updatedPages));
  44. }
  45. },
  46. });
  47. return () => {
  48. // Unsubscribe when the component is unmounted.
  49. void appObserver.unsubscribe();
  50. };
  51. }, []);
  52. useEffect(() => {
  53. if (showPages) {
  54. setFolderHeight(`${INITIAL_FOLDER_HEIGHT + pages.length * PAGE_ITEM_HEIGHT}px`);
  55. }
  56. }, [pages]);
  57. const onFolderNameClick = () => {
  58. appDispatch(foldersActions.toggleShowPages({ id: folder.id }));
  59. if (showPages) {
  60. setFolderHeight(`${INITIAL_FOLDER_HEIGHT}px`);
  61. } else {
  62. setFolderHeight(`${INITIAL_FOLDER_HEIGHT + pages.length * PAGE_ITEM_HEIGHT}px`);
  63. }
  64. setShowPages(!showPages);
  65. };
  66. const onFolderOptionsClick = () => {
  67. setShowFolderOptions(!showFolderOptions);
  68. };
  69. const onNewPageClick = () => {
  70. setShowNewPageOptions(!showNewPageOptions);
  71. };
  72. const startFolderRename = () => {
  73. closePopup();
  74. setShowRenamePopup(true);
  75. };
  76. const changeFolderTitle = async (newTitle: string) => {
  77. try {
  78. await appBackendService.update({ name: newTitle });
  79. appDispatch(foldersActions.renameFolder({ id: folder.id, newTitle }));
  80. } catch (e: any) {
  81. error.showError(e?.message);
  82. }
  83. };
  84. const closeRenamePopup = () => {
  85. setShowRenamePopup(false);
  86. };
  87. const deleteFolder = async () => {
  88. closePopup();
  89. try {
  90. await appBackendService.delete();
  91. appDispatch(foldersActions.deleteFolder({ id: folder.id }));
  92. } catch (e: any) {
  93. error.showError(e?.message);
  94. }
  95. };
  96. const duplicateFolder = async () => {
  97. closePopup();
  98. try {
  99. const newApp = await workspaceBackendService.createApp({
  100. name: folder.title,
  101. });
  102. appDispatch(foldersActions.addFolder({ id: newApp.id, title: folder.title }));
  103. } catch (e: any) {
  104. error.showError(e?.message);
  105. }
  106. };
  107. const closePopup = () => {
  108. setShowFolderOptions(false);
  109. setShowNewPageOptions(false);
  110. };
  111. const onAddNewDocumentPage = async () => {
  112. closePopup();
  113. try {
  114. const newView = await appBackendService.createView({
  115. name: 'New Document 1',
  116. layoutType: ViewLayoutTypePB.Document,
  117. });
  118. appDispatch(
  119. pagesActions.addPage({
  120. folderId: folder.id,
  121. pageType: ViewLayoutTypePB.Document,
  122. title: newView.name,
  123. id: newView.id,
  124. })
  125. );
  126. appDispatch(activePageIdActions.setActivePageId(newView.id));
  127. navigate(`/page/document/${newView.id}`);
  128. } catch (e: any) {
  129. error.showError(e?.message);
  130. }
  131. };
  132. const onAddNewBoardPage = async () => {
  133. closePopup();
  134. try {
  135. const newView = await appBackendService.createView({
  136. name: 'New Board 1',
  137. layoutType: ViewLayoutTypePB.Board,
  138. });
  139. appDispatch(
  140. pagesActions.addPage({
  141. folderId: folder.id,
  142. pageType: ViewLayoutTypePB.Board,
  143. title: newView.name,
  144. id: newView.id,
  145. })
  146. );
  147. appDispatch(activePageIdActions.setActivePageId(newView.id));
  148. navigate(`/page/board/${newView.id}`);
  149. } catch (e: any) {
  150. error.showError(e?.message);
  151. }
  152. };
  153. const onAddNewGridPage = async () => {
  154. closePopup();
  155. try {
  156. const newView = await appBackendService.createView({
  157. name: 'New Grid 1',
  158. layoutType: ViewLayoutTypePB.Grid,
  159. });
  160. appDispatch(
  161. pagesActions.addPage({
  162. folderId: folder.id,
  163. pageType: ViewLayoutTypePB.Grid,
  164. title: newView.name,
  165. id: newView.id,
  166. })
  167. );
  168. appDispatch(activePageIdActions.setActivePageId(newView.id));
  169. navigate(`/page/grid/${newView.id}`);
  170. } catch (e: any) {
  171. error.showError(e?.message);
  172. }
  173. };
  174. return {
  175. showPages,
  176. onFolderNameClick,
  177. showFolderOptions,
  178. onFolderOptionsClick,
  179. showNewPageOptions,
  180. onNewPageClick,
  181. showRenamePopup,
  182. startFolderRename,
  183. changeFolderTitle,
  184. closeRenamePopup,
  185. deleteFolder,
  186. duplicateFolder,
  187. onAddNewDocumentPage,
  188. onAddNewBoardPage,
  189. onAddNewGridPage,
  190. closePopup,
  191. folderHeight,
  192. };
  193. };