modal.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. import { useCallback, useMemo } from 'react';
  2. import type {
  3. IAttachmentHasId, IPageToDeleteWithMeta, IPageToRenameWithMeta, IUserGroupHasId,
  4. } from '@growi/core';
  5. import { useSWRStatic } from '@growi/core/dist/swr';
  6. import { MarkdownTable } from '@growi/editor';
  7. import type { SWRResponse } from 'swr';
  8. import type { BookmarkFolderItems } from '~/interfaces/bookmark-info';
  9. import type {
  10. OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction, onDeletedBookmarkFolderFunction, OnSelectedFunction,
  11. } from '~/interfaces/ui';
  12. import loggerFactory from '~/utils/logger';
  13. const logger = loggerFactory('growi:stores:modal');
  14. /*
  15. * PageCreateModal
  16. */
  17. type CreateModalStatus = {
  18. isOpened: boolean,
  19. path?: string,
  20. }
  21. type CreateModalStatusUtils = {
  22. open(path?: string): Promise<CreateModalStatus | undefined>
  23. close(): Promise<CreateModalStatus | undefined>
  24. }
  25. export const usePageCreateModal = (status?: CreateModalStatus): SWRResponse<CreateModalStatus, Error> & CreateModalStatusUtils => {
  26. const initialData: CreateModalStatus = { isOpened: false };
  27. const swrResponse = useSWRStatic<CreateModalStatus, Error>('pageCreateModalStatus', status, { fallbackData: initialData });
  28. return {
  29. ...swrResponse,
  30. open: (path?: string) => swrResponse.mutate({ isOpened: true, path }),
  31. close: () => swrResponse.mutate({ isOpened: false }),
  32. };
  33. };
  34. /*
  35. * GrantedGroupsInheritanceSelectModal
  36. */
  37. type GrantedGroupsInheritanceSelectModalStatus = {
  38. isOpened: boolean,
  39. onCreateBtnClick?: (onlyInheritUserRelatedGrantedGroups?: boolean) => Promise<void>,
  40. }
  41. type GrantedGroupsInheritanceSelectModalStatusUtils = {
  42. open(onCreateBtnClick?: (onlyInheritUserRelatedGrantedGroups?: boolean) => Promise<void>): Promise<GrantedGroupsInheritanceSelectModalStatus | undefined>
  43. close(): Promise<GrantedGroupsInheritanceSelectModalStatus | undefined>
  44. }
  45. export const useGrantedGroupsInheritanceSelectModal = (
  46. status?: GrantedGroupsInheritanceSelectModalStatus,
  47. ): SWRResponse<GrantedGroupsInheritanceSelectModalStatus, Error> & GrantedGroupsInheritanceSelectModalStatusUtils => {
  48. const initialData: GrantedGroupsInheritanceSelectModalStatus = { isOpened: false };
  49. const swrResponse = useSWRStatic<GrantedGroupsInheritanceSelectModalStatus, Error>(
  50. 'grantedGroupsInheritanceSelectModalStatus', status, { fallbackData: initialData },
  51. );
  52. const { mutate } = swrResponse;
  53. return {
  54. ...swrResponse,
  55. open: useCallback(
  56. (onCreateBtnClick?: (onlyInheritUserRelatedGrantedGroups?: boolean) => Promise<void>) => mutate({ isOpened: true, onCreateBtnClick }), [mutate],
  57. ),
  58. close: useCallback(() => mutate({ isOpened: false }), [mutate]),
  59. };
  60. };
  61. /*
  62. * PageDeleteModal
  63. */
  64. export type IDeleteModalOption = {
  65. onDeleted?: OnDeletedFunction,
  66. }
  67. type DeleteModalStatus = {
  68. isOpened: boolean,
  69. pages?: IPageToDeleteWithMeta[],
  70. opts?: IDeleteModalOption,
  71. }
  72. type DeleteModalStatusUtils = {
  73. open(
  74. pages?: IPageToDeleteWithMeta[],
  75. opts?: IDeleteModalOption,
  76. ): Promise<DeleteModalStatus | undefined>,
  77. close(): Promise<DeleteModalStatus | undefined>,
  78. }
  79. export const usePageDeleteModal = (status?: DeleteModalStatus): SWRResponse<DeleteModalStatus, Error> & DeleteModalStatusUtils => {
  80. const initialData: DeleteModalStatus = {
  81. isOpened: false,
  82. pages: [],
  83. };
  84. const swrResponse = useSWRStatic<DeleteModalStatus, Error>('deleteModalStatus', status, { fallbackData: initialData });
  85. return {
  86. ...swrResponse,
  87. open: (
  88. pages?: IPageToDeleteWithMeta[],
  89. opts?: IDeleteModalOption,
  90. ) => swrResponse.mutate({
  91. isOpened: true, pages, opts,
  92. }),
  93. close: () => swrResponse.mutate({ isOpened: false }),
  94. };
  95. };
  96. /*
  97. * EmptyTrashModal
  98. */
  99. type IEmptyTrashModalOption = {
  100. onEmptiedTrash?: () => void,
  101. canDeleteAllPages: boolean,
  102. }
  103. type EmptyTrashModalStatus = {
  104. isOpened: boolean,
  105. pages?: IPageToDeleteWithMeta[],
  106. opts?: IEmptyTrashModalOption,
  107. }
  108. type EmptyTrashModalStatusUtils = {
  109. open(
  110. pages?: IPageToDeleteWithMeta[],
  111. opts?: IEmptyTrashModalOption,
  112. ): Promise<EmptyTrashModalStatus | undefined>,
  113. close(): Promise<EmptyTrashModalStatus | undefined>,
  114. }
  115. export const useEmptyTrashModal = (status?: EmptyTrashModalStatus): SWRResponse<EmptyTrashModalStatus, Error> & EmptyTrashModalStatusUtils => {
  116. const initialData: EmptyTrashModalStatus = {
  117. isOpened: false,
  118. pages: [],
  119. };
  120. const swrResponse = useSWRStatic<EmptyTrashModalStatus, Error>('emptyTrashModalStatus', status, { fallbackData: initialData });
  121. return {
  122. ...swrResponse,
  123. open: (
  124. pages?: IPageToDeleteWithMeta[],
  125. opts?: IEmptyTrashModalOption,
  126. ) => swrResponse.mutate({
  127. isOpened: true, pages, opts,
  128. }),
  129. close: () => swrResponse.mutate({ isOpened: false }),
  130. };
  131. };
  132. /*
  133. * PageDuplicateModal
  134. */
  135. export type IPageForPageDuplicateModal = {
  136. pageId: string,
  137. path: string
  138. }
  139. export type IDuplicateModalOption = {
  140. onDuplicated?: OnDuplicatedFunction,
  141. }
  142. type DuplicateModalStatus = {
  143. isOpened: boolean,
  144. page?: IPageForPageDuplicateModal,
  145. opts?: IDuplicateModalOption,
  146. }
  147. type DuplicateModalStatusUtils = {
  148. open(
  149. page?: IPageForPageDuplicateModal,
  150. opts?: IDuplicateModalOption
  151. ): Promise<DuplicateModalStatus | undefined>
  152. close(): Promise<DuplicateModalStatus | undefined>
  153. }
  154. export const usePageDuplicateModal = (status?: DuplicateModalStatus): SWRResponse<DuplicateModalStatus, Error> & DuplicateModalStatusUtils => {
  155. const initialData: DuplicateModalStatus = { isOpened: false };
  156. const swrResponse = useSWRStatic<DuplicateModalStatus, Error>('duplicateModalStatus', status, { fallbackData: initialData });
  157. return {
  158. ...swrResponse,
  159. open: (
  160. page?: IPageForPageDuplicateModal,
  161. opts?: IDuplicateModalOption,
  162. ) => swrResponse.mutate({ isOpened: true, page, opts }),
  163. close: () => swrResponse.mutate({ isOpened: false }),
  164. };
  165. };
  166. /*
  167. * PageRenameModal
  168. */
  169. export type IRenameModalOption = {
  170. onRenamed?: OnRenamedFunction,
  171. }
  172. type RenameModalStatus = {
  173. isOpened: boolean,
  174. page?: IPageToRenameWithMeta,
  175. opts?: IRenameModalOption
  176. }
  177. type RenameModalStatusUtils = {
  178. open(
  179. page?: IPageToRenameWithMeta,
  180. opts?: IRenameModalOption
  181. ): Promise<RenameModalStatus | undefined>
  182. close(): Promise<RenameModalStatus | undefined>
  183. }
  184. export const usePageRenameModal = (status?: RenameModalStatus): SWRResponse<RenameModalStatus, Error> & RenameModalStatusUtils => {
  185. const initialData: RenameModalStatus = { isOpened: false };
  186. const swrResponse = useSWRStatic<RenameModalStatus, Error>('renameModalStatus', status, { fallbackData: initialData });
  187. return {
  188. ...swrResponse,
  189. open: (
  190. page?: IPageToRenameWithMeta,
  191. opts?: IRenameModalOption,
  192. ) => swrResponse.mutate({
  193. isOpened: true, page, opts,
  194. }),
  195. close: () => swrResponse.mutate({ isOpened: false }),
  196. };
  197. };
  198. /*
  199. * PutBackPageModal
  200. */
  201. export type IPageForPagePutBackModal = {
  202. pageId: string,
  203. path: string
  204. }
  205. export type IPutBackPageModalOption = {
  206. onPutBacked?: OnPutBackedFunction,
  207. }
  208. type PutBackPageModalStatus = {
  209. isOpened: boolean,
  210. page?: IPageForPagePutBackModal,
  211. opts?: IPutBackPageModalOption,
  212. }
  213. type PutBackPageModalUtils = {
  214. open(
  215. page?: IPageForPagePutBackModal,
  216. opts?: IPutBackPageModalOption,
  217. ): Promise<PutBackPageModalStatus | undefined>
  218. close(): Promise<PutBackPageModalStatus | undefined>
  219. }
  220. export const usePutBackPageModal = (status?: PutBackPageModalStatus): SWRResponse<PutBackPageModalStatus, Error> & PutBackPageModalUtils => {
  221. const initialData: PutBackPageModalStatus = useMemo(() => ({
  222. isOpened: false,
  223. page: { pageId: '', path: '' },
  224. }), []);
  225. const swrResponse = useSWRStatic<PutBackPageModalStatus, Error>('putBackPageModalStatus', status, { fallbackData: initialData });
  226. return {
  227. ...swrResponse,
  228. open: (
  229. page: IPageForPagePutBackModal, opts?: IPutBackPageModalOption,
  230. ) => swrResponse.mutate({
  231. isOpened: true, page, opts,
  232. }),
  233. close: () => swrResponse.mutate({ isOpened: false, page: { pageId: '', path: '' } }),
  234. };
  235. };
  236. /*
  237. * PagePresentationModal
  238. */
  239. type PresentationModalStatus = {
  240. isOpened: boolean,
  241. }
  242. type PresentationModalStatusUtils = {
  243. open(): Promise<PresentationModalStatus | undefined>
  244. close(): Promise<PresentationModalStatus | undefined>
  245. }
  246. export const usePagePresentationModal = (
  247. status?: PresentationModalStatus,
  248. ): SWRResponse<PresentationModalStatus, Error> & PresentationModalStatusUtils => {
  249. const initialData: PresentationModalStatus = {
  250. isOpened: false,
  251. };
  252. const swrResponse = useSWRStatic<PresentationModalStatus, Error>('presentationModalStatus', status, { fallbackData: initialData });
  253. return {
  254. ...swrResponse,
  255. open: () => swrResponse.mutate({ isOpened: true }, { revalidate: true }),
  256. close: () => swrResponse.mutate({ isOpened: false }),
  257. };
  258. };
  259. /*
  260. * PrivateLegacyPagesMigrationModal
  261. */
  262. export type ILegacyPrivatePage = { pageId: string, path: string };
  263. export type PrivateLegacyPagesMigrationModalSubmitedHandler = (pages: ILegacyPrivatePage[], isRecursively?: boolean) => void;
  264. type PrivateLegacyPagesMigrationModalStatus = {
  265. isOpened: boolean,
  266. pages?: ILegacyPrivatePage[],
  267. onSubmited?: PrivateLegacyPagesMigrationModalSubmitedHandler,
  268. }
  269. type PrivateLegacyPagesMigrationModalStatusUtils = {
  270. open(pages: ILegacyPrivatePage[], onSubmited?: PrivateLegacyPagesMigrationModalSubmitedHandler): Promise<PrivateLegacyPagesMigrationModalStatus | undefined>,
  271. close(): Promise<PrivateLegacyPagesMigrationModalStatus | undefined>,
  272. }
  273. export const usePrivateLegacyPagesMigrationModal = (
  274. status?: PrivateLegacyPagesMigrationModalStatus,
  275. ): SWRResponse<PrivateLegacyPagesMigrationModalStatus, Error> & PrivateLegacyPagesMigrationModalStatusUtils => {
  276. const initialData: PrivateLegacyPagesMigrationModalStatus = {
  277. isOpened: false,
  278. pages: [],
  279. };
  280. const swrResponse = useSWRStatic<PrivateLegacyPagesMigrationModalStatus, Error>('privateLegacyPagesMigrationModal', status, { fallbackData: initialData });
  281. return {
  282. ...swrResponse,
  283. open: (pages, onSubmited?) => swrResponse.mutate({
  284. isOpened: true, pages, onSubmited,
  285. }),
  286. close: () => swrResponse.mutate({ isOpened: false, pages: [], onSubmited: undefined }),
  287. };
  288. };
  289. /*
  290. * DescendantsPageListModal
  291. */
  292. type DescendantsPageListModalStatus = {
  293. isOpened: boolean,
  294. path?: string,
  295. }
  296. type DescendantsPageListUtils = {
  297. open(path: string): Promise<DescendantsPageListModalStatus | undefined>
  298. close(): Promise<DuplicateModalStatus | undefined>
  299. }
  300. export const useDescendantsPageListModal = (
  301. status?: DescendantsPageListModalStatus,
  302. ): SWRResponse<DescendantsPageListModalStatus, Error> & DescendantsPageListUtils => {
  303. const initialData: DescendantsPageListModalStatus = { isOpened: false };
  304. const swrResponse = useSWRStatic<DescendantsPageListModalStatus, Error>('descendantsPageListModalStatus', status, { fallbackData: initialData });
  305. return {
  306. ...swrResponse,
  307. open: (path: string) => swrResponse.mutate({ isOpened: true, path }),
  308. close: () => swrResponse.mutate({ isOpened: false }),
  309. };
  310. };
  311. /*
  312. * PageAccessoriesModal
  313. */
  314. export const PageAccessoriesModalContents = {
  315. PageHistory: 'PageHistory',
  316. Attachment: 'Attachment',
  317. ShareLink: 'ShareLink',
  318. } as const;
  319. export type PageAccessoriesModalContents = typeof PageAccessoriesModalContents[keyof typeof PageAccessoriesModalContents];
  320. type PageAccessoriesModalStatus = {
  321. isOpened: boolean,
  322. activatedContents?: PageAccessoriesModalContents,
  323. }
  324. type PageAccessoriesModalUtils = {
  325. open(activatedContents: PageAccessoriesModalContents): void
  326. close(): void
  327. selectContents(activatedContents: PageAccessoriesModalContents): void
  328. }
  329. export const usePageAccessoriesModal = (): SWRResponse<PageAccessoriesModalStatus, Error> & PageAccessoriesModalUtils => {
  330. const initialStatus = { isOpened: false };
  331. const swrResponse = useSWRStatic<PageAccessoriesModalStatus, Error>('pageAccessoriesModalStatus', undefined, { fallbackData: initialStatus });
  332. const { data, mutate } = swrResponse;
  333. return Object.assign(swrResponse, {
  334. open: useCallback((activatedContents) => {
  335. if (data == null) {
  336. return;
  337. }
  338. mutate({
  339. isOpened: true,
  340. activatedContents,
  341. });
  342. }, [data, mutate]),
  343. close: useCallback(() => {
  344. if (data == null) {
  345. return;
  346. }
  347. mutate({ isOpened: false });
  348. }, [data, mutate]),
  349. selectContents: useCallback((activatedContents) => {
  350. if (data == null) {
  351. return;
  352. }
  353. mutate({
  354. isOpened: data.isOpened,
  355. activatedContents,
  356. });
  357. }, [data, mutate]),
  358. });
  359. };
  360. /*
  361. * UpdateUserGroupConfirmModal
  362. */
  363. type UpdateUserGroupConfirmModalStatus = {
  364. isOpened: boolean,
  365. targetGroup?: IUserGroupHasId,
  366. updateData?: Partial<IUserGroupHasId>,
  367. onConfirm?: (targetGroup: IUserGroupHasId, updateData: Partial<IUserGroupHasId>, forceUpdateParents: boolean) => any,
  368. }
  369. type UpdateUserGroupConfirmModalUtils = {
  370. open(targetGroup: IUserGroupHasId, updateData: Partial<IUserGroupHasId>, onConfirm?: (...args: any[]) => any): Promise<void>,
  371. close(): Promise<void>,
  372. }
  373. export const useUpdateUserGroupConfirmModal = (): SWRResponse<UpdateUserGroupConfirmModalStatus, Error> & UpdateUserGroupConfirmModalUtils => {
  374. const initialStatus: UpdateUserGroupConfirmModalStatus = { isOpened: false };
  375. const swrResponse = useSWRStatic<UpdateUserGroupConfirmModalStatus, Error>('updateParentConfirmModal', undefined, { fallbackData: initialStatus });
  376. return {
  377. ...swrResponse,
  378. async open(targetGroup: IUserGroupHasId, updateData: Partial<IUserGroupHasId>, onConfirm?: (...args: any[]) => any) {
  379. await swrResponse.mutate({
  380. isOpened: true, targetGroup, updateData, onConfirm,
  381. });
  382. },
  383. async close() {
  384. await swrResponse.mutate({ isOpened: false });
  385. },
  386. };
  387. };
  388. /*
  389. * ShortcutsModal
  390. */
  391. type ShortcutsModalStatus = {
  392. isOpened: boolean,
  393. }
  394. type ShortcutsModalUtils = {
  395. open(): void,
  396. close(): void,
  397. }
  398. export const useShortcutsModal = (): SWRResponse<ShortcutsModalStatus, Error> & ShortcutsModalUtils => {
  399. const initialStatus: ShortcutsModalStatus = { isOpened: false };
  400. const swrResponse = useSWRStatic<ShortcutsModalStatus, Error>('shortcutsModal', undefined, { fallbackData: initialStatus });
  401. return {
  402. ...swrResponse,
  403. open() {
  404. swrResponse.mutate({ isOpened: true });
  405. },
  406. close() {
  407. swrResponse.mutate({ isOpened: false });
  408. },
  409. };
  410. };
  411. /*
  412. * DrawioModal
  413. */
  414. type DrawioModalSaveHandler = (drawioMxFile: string) => void;
  415. type DrawioModalStatus = {
  416. isOpened: boolean,
  417. drawioMxFile: string,
  418. onSave?: DrawioModalSaveHandler,
  419. }
  420. type DrawioModalStatusUtils = {
  421. open(
  422. drawioMxFile: string,
  423. onSave?: DrawioModalSaveHandler,
  424. ): void,
  425. close(): void,
  426. }
  427. export const useDrawioModal = (status?: DrawioModalStatus): SWRResponse<DrawioModalStatus, Error> & DrawioModalStatusUtils => {
  428. const initialData: DrawioModalStatus = {
  429. isOpened: false,
  430. drawioMxFile: '',
  431. };
  432. const swrResponse = useSWRStatic<DrawioModalStatus, Error>('drawioModalStatus', status, { fallbackData: initialData });
  433. const { mutate } = swrResponse;
  434. const open = useCallback((drawioMxFile: string, onSave?: DrawioModalSaveHandler): void => {
  435. mutate({ isOpened: true, drawioMxFile, onSave });
  436. }, [mutate]);
  437. const close = useCallback((): void => {
  438. mutate({ isOpened: false, drawioMxFile: '', onSave: undefined });
  439. }, [mutate]);
  440. return {
  441. ...swrResponse,
  442. open,
  443. close,
  444. };
  445. };
  446. /*
  447. * HandsonTableModal
  448. */
  449. type HandsonTableModalSaveHandler = (table: MarkdownTable) => void;
  450. type HandsontableModalStatus = {
  451. isOpened: boolean,
  452. table: MarkdownTable,
  453. autoFormatMarkdownTable?: boolean,
  454. // onSave is passed only when editing table directly from the page.
  455. onSave?: HandsonTableModalSaveHandler
  456. }
  457. type HandsontableModalStatusUtils = {
  458. open(
  459. table: MarkdownTable,
  460. autoFormatMarkdownTable?: boolean,
  461. onSave?: HandsonTableModalSaveHandler
  462. ): void
  463. close(): void
  464. }
  465. const defaultMarkdownTable = () => {
  466. return new MarkdownTable(
  467. [
  468. ['col1', 'col2', 'col3'],
  469. ['', '', ''],
  470. ['', '', ''],
  471. ],
  472. {
  473. align: ['', '', ''],
  474. },
  475. );
  476. };
  477. export const useHandsontableModal = (status?: HandsontableModalStatus): SWRResponse<HandsontableModalStatus, Error> & HandsontableModalStatusUtils => {
  478. const initialData: HandsontableModalStatus = {
  479. isOpened: false,
  480. table: defaultMarkdownTable(),
  481. autoFormatMarkdownTable: false,
  482. };
  483. const swrResponse = useSWRStatic<HandsontableModalStatus, Error>('handsontableModalStatus', status, { fallbackData: initialData });
  484. const { mutate } = swrResponse;
  485. const open = useCallback((table: MarkdownTable, autoFormatMarkdownTable?: boolean, onSave?: HandsonTableModalSaveHandler): void => {
  486. mutate({
  487. isOpened: true, table, autoFormatMarkdownTable, onSave,
  488. });
  489. }, [mutate]);
  490. const close = useCallback((): void => {
  491. mutate({
  492. isOpened: false, table: defaultMarkdownTable(), autoFormatMarkdownTable: false, onSave: undefined,
  493. });
  494. }, [mutate]);
  495. return {
  496. ...swrResponse,
  497. open,
  498. close,
  499. };
  500. };
  501. /*
  502. * ConflictDiffModal
  503. */
  504. type ResolveConflictHandler = (newMarkdown: string) => Promise<void> | void;
  505. type ConflictDiffModalStatus = {
  506. isOpened: boolean,
  507. requestRevisionBody?: string,
  508. onResolve?: ResolveConflictHandler
  509. }
  510. type ConflictDiffModalUtils = {
  511. open(requestRevisionBody: string, onResolveConflict: ResolveConflictHandler): void,
  512. close(): void,
  513. }
  514. export const useConflictDiffModal = (): SWRResponse<ConflictDiffModalStatus, Error> & ConflictDiffModalUtils => {
  515. const initialStatus: ConflictDiffModalStatus = { isOpened: false };
  516. const swrResponse = useSWRStatic<ConflictDiffModalStatus, Error>('conflictDiffModal', undefined, { fallbackData: initialStatus });
  517. const { mutate } = swrResponse;
  518. const open = useCallback((requestRevisionBody: string, onResolve: ResolveConflictHandler) => {
  519. mutate({ isOpened: true, requestRevisionBody, onResolve });
  520. }, [mutate]);
  521. const close = useCallback(() => {
  522. mutate({ isOpened: false });
  523. }, [mutate]);
  524. return {
  525. ...swrResponse,
  526. open,
  527. close,
  528. };
  529. };
  530. /*
  531. * BookmarkFolderDeleteModal
  532. */
  533. export type IDeleteBookmarkFolderModalOption = {
  534. onDeleted?: onDeletedBookmarkFolderFunction,
  535. }
  536. type DeleteBookmarkFolderModalStatus = {
  537. isOpened: boolean,
  538. bookmarkFolder?: BookmarkFolderItems,
  539. opts?: IDeleteBookmarkFolderModalOption,
  540. }
  541. type DeleteModalBookmarkFolderStatusUtils = {
  542. open(
  543. bookmarkFolder?: BookmarkFolderItems,
  544. opts?: IDeleteBookmarkFolderModalOption,
  545. ): Promise<DeleteBookmarkFolderModalStatus | undefined>,
  546. close(): Promise<DeleteBookmarkFolderModalStatus | undefined>,
  547. }
  548. export const useBookmarkFolderDeleteModal = (status?: DeleteBookmarkFolderModalStatus):
  549. SWRResponse<DeleteBookmarkFolderModalStatus, Error> & DeleteModalBookmarkFolderStatusUtils => {
  550. const initialData: DeleteBookmarkFolderModalStatus = {
  551. isOpened: false,
  552. };
  553. const swrResponse = useSWRStatic<DeleteBookmarkFolderModalStatus, Error>('deleteBookmarkFolderModalStatus', status, { fallbackData: initialData });
  554. return {
  555. ...swrResponse,
  556. open: (
  557. bookmarkFolder?: BookmarkFolderItems,
  558. opts?: IDeleteBookmarkFolderModalOption,
  559. ) => swrResponse.mutate({
  560. isOpened: true, bookmarkFolder, opts,
  561. }),
  562. close: () => swrResponse.mutate({ isOpened: false }),
  563. };
  564. };
  565. /**
  566. * DeleteAttachmentModal
  567. */
  568. type Remove =
  569. (body: {
  570. attachment_id: string;
  571. }) => Promise<void>
  572. type DeleteAttachmentModalStatus = {
  573. isOpened: boolean,
  574. attachment?: IAttachmentHasId,
  575. remove?: Remove,
  576. }
  577. type DeleteAttachmentModalUtils = {
  578. open(
  579. attachment: IAttachmentHasId,
  580. remove: Remove,
  581. ): void,
  582. close(): void,
  583. }
  584. export const useDeleteAttachmentModal = (): SWRResponse<DeleteAttachmentModalStatus, Error> & DeleteAttachmentModalUtils => {
  585. const initialStatus: DeleteAttachmentModalStatus = {
  586. isOpened: false,
  587. attachment: undefined,
  588. remove: undefined,
  589. };
  590. const swrResponse = useSWRStatic<DeleteAttachmentModalStatus, Error>('deleteAttachmentModal', undefined, { fallbackData: initialStatus });
  591. const { mutate } = swrResponse;
  592. const open = useCallback((attachment: IAttachmentHasId, remove: Remove) => {
  593. mutate({ isOpened: true, attachment, remove });
  594. }, [mutate]);
  595. const close = useCallback(() => {
  596. mutate({ isOpened: false });
  597. }, [mutate]);
  598. return {
  599. ...swrResponse,
  600. open,
  601. close,
  602. };
  603. };
  604. /*
  605. * PageSelectModal
  606. */
  607. type IPageSelectModalOption = {
  608. isHierarchicalSelectionMode?: boolean,
  609. onSelected?: OnSelectedFunction,
  610. }
  611. type PageSelectModalStatus = {
  612. isOpened: boolean
  613. opts?: IPageSelectModalOption
  614. }
  615. type PageSelectModalStatusUtils = {
  616. open(opts?: IPageSelectModalOption): void
  617. close(): void
  618. }
  619. export const usePageSelectModal = (
  620. status?: PageSelectModalStatus,
  621. ): SWRResponse<PageSelectModalStatus, Error> & PageSelectModalStatusUtils => {
  622. const initialStatus = { isOpened: false };
  623. const swrResponse = useSWRStatic<PageSelectModalStatus, Error>('PageSelectModal', status, { fallbackData: initialStatus });
  624. return {
  625. ...swrResponse,
  626. open: (
  627. opts?: IPageSelectModalOption,
  628. ) => swrResponse.mutate({
  629. isOpened: true, opts,
  630. }),
  631. close: () => swrResponse.mutate({ isOpened: false }),
  632. };
  633. };
  634. /*
  635. * TagEditModal
  636. */
  637. export type TagEditModalStatus = {
  638. isOpen: boolean,
  639. tags: string[],
  640. pageId: string,
  641. revisionId: string,
  642. }
  643. type TagEditModalUtils = {
  644. open(tags: string[], pageId: string, revisionId: string): Promise<void>,
  645. close(): Promise<void>,
  646. }
  647. export const useTagEditModal = (): SWRResponse<TagEditModalStatus, Error> & TagEditModalUtils => {
  648. const initialStatus: TagEditModalStatus = useMemo(() => {
  649. return {
  650. isOpen: false,
  651. tags: [],
  652. pageId: '',
  653. revisionId: '',
  654. };
  655. }, []);
  656. const swrResponse = useSWRStatic<TagEditModalStatus, Error>('TagEditModal', undefined, { fallbackData: initialStatus });
  657. const { mutate } = swrResponse;
  658. const open = useCallback(async(tags: string[], pageId: string, revisionId: string) => {
  659. mutate({
  660. isOpen: true,
  661. tags,
  662. pageId,
  663. revisionId,
  664. });
  665. }, [mutate]);
  666. const close = useCallback(async() => {
  667. mutate(initialStatus);
  668. }, [initialStatus, mutate]);
  669. return {
  670. ...swrResponse,
  671. open,
  672. close,
  673. };
  674. };