@griddo/ax 11.15.7 → 11.15.8-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.atoms.test.tsx +409 -0
  3. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.helpers.test.tsx +418 -0
  4. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.test.tsx +776 -29
  5. package/src/__tests__/components/FieldsBehavior/FieldsBehavior.test.tsx +368 -11
  6. package/src/__tests__/modules/Users/UserList/UserList.test.tsx +6 -6
  7. package/src/components/Fields/IntegrationsField/IntegrationItem/atoms.tsx +14 -5
  8. package/src/components/Fields/IntegrationsField/IntegrationItem/index.tsx +1 -8
  9. package/src/components/Fields/UrlField/index.tsx +5 -4
  10. package/src/components/Fields/Wysiwyg/atoms.tsx +140 -0
  11. package/src/components/Fields/Wysiwyg/config.tsx +190 -9
  12. package/src/components/Fields/Wysiwyg/helpers.tsx +54 -1
  13. package/src/components/Fields/Wysiwyg/index.tsx +210 -61
  14. package/src/components/Fields/Wysiwyg/style.tsx +32 -1
  15. package/src/components/Fields/Wysiwyg/vendors.tsx +0 -1
  16. package/src/components/FieldsBehavior/index.tsx +66 -31
  17. package/src/components/Icon/components/Sync.js +16 -0
  18. package/src/components/Icon/svgs/Sync.svg +3 -0
  19. package/src/components/RestoreModal/index.tsx +1 -3
  20. package/src/components/ScheduleModal/index.tsx +3 -3
  21. package/src/components/TableList/index.tsx +5 -3
  22. package/src/containers/FileDrive/actions.tsx +5 -5
  23. package/src/containers/Forms/actions.tsx +40 -38
  24. package/src/containers/Gallery/actions.tsx +27 -27
  25. package/src/containers/Integrations/actions.tsx +2 -2
  26. package/src/containers/Navigation/Defaults/actions.tsx +1 -1
  27. package/src/containers/PageEditor/actions.tsx +3 -5
  28. package/src/containers/Redirects/actions.tsx +2 -2
  29. package/src/containers/Sites/actions.tsx +15 -8
  30. package/src/containers/StructuredData/actions.tsx +5 -5
  31. package/src/containers/Users/actions.tsx +2 -2
  32. package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +36 -43
  33. package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +15 -11
  34. package/src/modules/Categories/CategoriesList/atoms.tsx +42 -12
  35. package/src/modules/Categories/CategoriesList/index.tsx +8 -30
  36. package/src/modules/Content/PageItem/index.tsx +6 -5
  37. package/src/modules/Content/atoms.tsx +7 -3
  38. package/src/modules/Content/index.tsx +8 -16
  39. package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +14 -14
  40. package/src/modules/FileDrive/FolderItem/index.tsx +46 -54
  41. package/src/modules/FileDrive/GridItem/index.tsx +32 -37
  42. package/src/modules/FileDrive/ListItem/index.tsx +31 -37
  43. package/src/modules/FileDrive/atoms.tsx +59 -12
  44. package/src/modules/FileDrive/index.tsx +88 -98
  45. package/src/modules/Forms/FormCategoriesList/CategoryItem/index.tsx +42 -34
  46. package/src/modules/Forms/FormCategoriesList/atoms.tsx +17 -6
  47. package/src/modules/Forms/FormCategoriesList/index.tsx +30 -34
  48. package/src/modules/Forms/FormEditor/index.tsx +14 -6
  49. package/src/modules/Forms/FormList/FormItem/index.tsx +5 -1
  50. package/src/modules/Forms/FormList/index.tsx +15 -9
  51. package/src/modules/Forms/atoms.tsx +7 -4
  52. package/src/modules/GlobalEditor/atoms.tsx +77 -0
  53. package/src/modules/GlobalEditor/index.tsx +24 -7
  54. package/src/modules/MediaGallery/FolderItem/index.tsx +36 -52
  55. package/src/modules/MediaGallery/GridItem/index.tsx +27 -38
  56. package/src/modules/MediaGallery/ImageModal/DetailPanel/index.tsx +13 -13
  57. package/src/modules/MediaGallery/ImageModal/index.tsx +2 -16
  58. package/src/modules/MediaGallery/ListItem/index.tsx +25 -37
  59. package/src/modules/MediaGallery/atoms.tsx +84 -15
  60. package/src/modules/MediaGallery/index.tsx +62 -122
  61. package/src/modules/Navigation/Defaults/Item/atoms.tsx +2 -4
  62. package/src/modules/Navigation/Defaults/Item/index.tsx +80 -94
  63. package/src/modules/Navigation/Defaults/atoms.tsx +179 -7
  64. package/src/modules/Navigation/Defaults/index.tsx +51 -18
  65. package/src/modules/Navigation/Defaults/style.tsx +10 -7
  66. package/src/modules/Navigation/Menus/List/Table/Item/atoms.tsx +33 -19
  67. package/src/modules/Navigation/Menus/List/Table/Item/index.tsx +18 -19
  68. package/src/modules/Navigation/Menus/List/Table/index.tsx +15 -13
  69. package/src/modules/Navigation/Menus/List/index.tsx +1 -1
  70. package/src/modules/PageEditor/atoms.tsx +14 -11
  71. package/src/modules/PageEditor/index.tsx +11 -16
  72. package/src/modules/Redirects/RedirectItem/index.tsx +37 -39
  73. package/src/modules/Redirects/atoms.tsx +58 -12
  74. package/src/modules/Redirects/index.tsx +30 -58
  75. package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/index.tsx +1 -1
  76. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +57 -69
  77. package/src/modules/Settings/Integrations/atoms.tsx +72 -8
  78. package/src/modules/Settings/Integrations/index.tsx +34 -48
  79. package/src/modules/StructuredData/Form/index.tsx +25 -8
  80. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/atoms.tsx +26 -75
  81. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +15 -33
  82. package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +63 -41
  83. package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/style.tsx +13 -8
  84. package/src/modules/StructuredData/StructuredDataList/index.tsx +11 -16
  85. package/src/modules/StructuredData/{StructuredDataList/atoms.tsx → atoms.tsx} +25 -28
  86. package/src/modules/Users/UserList/UserItem/index.tsx +18 -35
  87. package/src/modules/Users/UserList/atoms.tsx +61 -0
  88. package/src/modules/Users/UserList/index.tsx +12 -32
@@ -114,6 +114,7 @@ const Content = (props: IProps): JSX.Element => {
114
114
  setFilter,
115
115
  setDataStatus,
116
116
  isLoading,
117
+ isSaving,
117
118
  resetPageEditor,
118
119
  removePageFromSite,
119
120
  importPageFromGlobal,
@@ -205,9 +206,6 @@ const Content = (props: IProps): JSX.Element => {
205
206
  const initialColumns = getColumns(categoryColumns, isStructuredData, isGlobalPages, maxColumns.value);
206
207
  const [columnsState, setColumnsState] = useState(initialColumns);
207
208
 
208
- const [isDeleting, setIsDeleting] = useState<boolean>(false);
209
- const [isBulkLoading, setIsBulkLoading] = useState<boolean>(false);
210
-
211
209
  const createPermission = isDataPrivate ? "content.createPrivateContentTypes" : "content.createPages";
212
210
  const exportPermission = isDataPrivate ? "content.exportPrivateContentTypes" : "content.exportContentTypes";
213
211
  const isAllowedToCreatePages = usePermission(createPermission);
@@ -488,8 +486,6 @@ const Content = (props: IProps): JSX.Element => {
488
486
 
489
487
  const bulkDelete = async () => {
490
488
  let allPageVersions: number[] = [];
491
- setIsBulkLoading(true); // se podría usar setIsDeleting pero por seguridad prefiero usar uno propio
492
- setIsDeleting(true);
493
489
  if (deleteAllVersions) {
494
490
  const selectedPages = currentSitePages.filter((page) => selectedItems.all.includes(page.id));
495
491
  const pageLanguages = selectedPages.map((element) => element.pageLanguages);
@@ -514,8 +510,6 @@ const Content = (props: IProps): JSX.Element => {
514
510
  const previousPage = page - 1;
515
511
  page > 1 && (isLastItem || allPageItemsSelected) ? setPage(previousPage) : getSiteContent();
516
512
  unselectAllItems();
517
- setIsBulkLoading(false);
518
- setIsDeleting(false);
519
513
  };
520
514
 
521
515
  const handleToggleDeleteModal = () => {
@@ -526,7 +520,6 @@ const Content = (props: IProps): JSX.Element => {
526
520
  };
527
521
 
528
522
  const bulkPublishAction = async (isPublish: boolean) => {
529
- setIsBulkLoading(true);
530
523
  const { notPublished, published, drafts } = selectedItems;
531
524
 
532
525
  if (drafts && drafts.length > 0) {
@@ -555,15 +548,12 @@ const Content = (props: IProps): JSX.Element => {
555
548
 
556
549
  getSiteContent();
557
550
  unselectAllItems();
558
- setIsBulkLoading(false);
559
551
  };
560
552
 
561
553
  const bulkPublish = () => {
562
554
  if (isStructuredData) {
563
- setIsBulkLoading(true);
564
555
  setDataStatus(selectedItems.all, "undraft");
565
556
  unselectAllItems();
566
- setIsBulkLoading(false);
567
557
  } else {
568
558
  bulkPublishAction(true);
569
559
  }
@@ -571,10 +561,8 @@ const Content = (props: IProps): JSX.Element => {
571
561
 
572
562
  const bulkUnpublish = () => {
573
563
  if (isStructuredData) {
574
- setIsBulkLoading(true);
575
564
  setDataStatus(selectedItems.all, "draft");
576
565
  unselectAllItems();
577
- setIsBulkLoading(false);
578
566
  } else {
579
567
  bulkPublishAction(false);
580
568
  }
@@ -619,7 +607,7 @@ const Content = (props: IProps): JSX.Element => {
619
607
  sortedListStatus={sortedListStatus}
620
608
  filterItems={filterItems}
621
609
  isEditable={isDataEditable}
622
- isLoading={isBulkLoading}
610
+ isLoading={isSaving}
623
611
  filterValues={filterValues}
624
612
  categoryColumns={categoryColumns}
625
613
  columns={columnsState}
@@ -706,6 +694,7 @@ const Content = (props: IProps): JSX.Element => {
706
694
  toggleDeletedToast();
707
695
  }
708
696
  isLastItem && previousPage !== 1 ? setPage(previousPage) : getSiteContent();
697
+ return deleted;
709
698
  };
710
699
 
711
700
  const deleteCurrentPageBulk = async (ids: number[]) => {
@@ -717,6 +706,7 @@ const Content = (props: IProps): JSX.Element => {
717
706
  toggleDeletedToast();
718
707
  }
719
708
  isLastItem && previousPage !== 1 ? setPage(previousPage) : getSiteContent();
709
+ return deleted;
720
710
  };
721
711
 
722
712
  const pageItemFunctions = {
@@ -815,7 +805,6 @@ const Content = (props: IProps): JSX.Element => {
815
805
 
816
806
  const resetFilter = () => resetFilterQuery();
817
807
 
818
-
819
808
  const undoDeleteAction = async () => {
820
809
  if (deletedItem) {
821
810
  await restorePage(deletedItem);
@@ -943,6 +932,7 @@ const Content = (props: IProps): JSX.Element => {
943
932
  onScroll={onScroll}
944
933
  hasFixedHeader={true}
945
934
  tableRef={tableRef}
935
+ skipLoading={isSaving}
946
936
  >
947
937
  <S.SearchTags>
948
938
  <SearchTagsBar query={currentSearch} setQuery={handleSearch} />
@@ -984,7 +974,7 @@ const Content = (props: IProps): JSX.Element => {
984
974
  isOpen={isDeleteOpen}
985
975
  toggleModal={toggleDeleteModal}
986
976
  onDelete={bulkDelete}
987
- isDeleting={isDeleting}
977
+ isDeleting={isSaving}
988
978
  {...{ isTranslated: arePagesTranslated, deleteAllVersions, setDeleteAllVersions }}
989
979
  />
990
980
  {isVisible && <Toast {...toastProps} />}
@@ -1012,6 +1002,7 @@ const mapStateToProps = (state: IRootState) => ({
1012
1002
  activatedDataPacks: state.dataPacks.activated,
1013
1003
  activatedTemplates: state.dataPacks.templates,
1014
1004
  isLoading: state.app.isLoading,
1005
+ isSaving: state.app.isSaving,
1015
1006
  currentSiteErrorPages: state.sites.currentSiteErrorPages,
1016
1007
  sitesByLang: state.sites.sitesByLang,
1017
1008
  user: state.users.currentUser,
@@ -1121,6 +1112,7 @@ interface IPagesProps {
1121
1112
  activatedDataPacks: IDataPack[];
1122
1113
  activatedTemplates: any[];
1123
1114
  isLoading: boolean;
1115
+ isSaving: boolean;
1124
1116
  currentSiteErrorPages: number[];
1125
1117
  sites: ISite[];
1126
1118
  sitesByLang: ISite[];
@@ -9,9 +9,10 @@ import { LOCALE } from "@ax/locales";
9
9
  import type { IFile, IRootState } from "@ax/types";
10
10
 
11
11
  import { DeleteFileModal } from "../../atoms";
12
- import * as S from "./style";
13
12
  import UsageContent from "./UsageContent";
14
13
 
14
+ import * as S from "./style";
15
+
15
16
  const DetailPanel = (props: IProps) => {
16
17
  const {
17
18
  file,
@@ -29,6 +30,7 @@ const DetailPanel = (props: IProps) => {
29
30
  const { title, alt, tags, site } = file;
30
31
 
31
32
  const [selectedTab, setSelectedTab] = useState("details");
33
+ const [isDeleting, setIsDeleting] = useState(false);
32
34
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
33
35
 
34
36
  // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
@@ -57,10 +59,15 @@ const DetailPanel = (props: IProps) => {
57
59
 
58
60
  const handleCopyUrl = () => navigator.clipboard.writeText(file.url);
59
61
 
60
- const handleDeleteFile = () => {
61
- onDelete(file.id);
62
- isDeleteOpen && toggleDeleteModal();
63
- toggleModal();
62
+ const handleDeleteFile = async () => {
63
+ setIsDeleting(true);
64
+ try {
65
+ await onDelete(file.id);
66
+ } finally {
67
+ setIsDeleting(false);
68
+ toggleDeleteModal();
69
+ toggleModal();
70
+ }
64
71
  };
65
72
 
66
73
  const handleSelectedTab = (tab: "details" | "in use") => {
@@ -69,13 +76,6 @@ const DetailPanel = (props: IProps) => {
69
76
  }
70
77
  };
71
78
 
72
- const mainNewModalAction = {
73
- title: "Delete document",
74
- onClick: () => handleDeleteFile(),
75
- };
76
-
77
- const secondaryNewModalAction = { title: "Cancel", onClick: toggleDeleteModal };
78
-
79
79
  const tabs = ["details", "in use"];
80
80
 
81
81
  return (
@@ -165,9 +165,9 @@ const DetailPanel = (props: IProps) => {
165
165
  <DeleteFileModal
166
166
  isOpen={isDeleteOpen}
167
167
  toggleModal={toggleDeleteModal}
168
- mainModalAction={mainNewModalAction}
169
- secondaryModalAction={secondaryNewModalAction}
170
168
  title={file.fileName}
169
+ onDelete={handleDeleteFile}
170
+ isDeleting={isDeleting}
171
171
  isChild={true}
172
172
  />
173
173
  )}
@@ -1,25 +1,33 @@
1
- import React, { useState } from "react";
1
+ import { useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { IActionMenuOption, IFolder } from "@ax/types";
5
4
  import { Icon, Tooltip } from "@ax/components";
6
- import { useModal } from "@ax/hooks";
7
5
  import { fileDriveActions } from "@ax/containers/FileDrive";
8
- import { DeleteFolderModal, MoveItemModal, RenameFolderModal } from "../atoms";
9
6
  import { trimText } from "@ax/helpers";
7
+ import { useModals } from "@ax/hooks";
8
+ import type { IActionMenuOption, IFolder, IRootState } from "@ax/types";
9
+
10
+ import { DeleteFolderModal, MoveItemModal, RenameFolderModal } from "../atoms";
10
11
 
11
12
  import * as S from "./style";
12
13
 
13
14
  const FolderItem = (props: IProps) => {
14
- const { folder, isAllowedToDelete, isAllowedToEdit, isAllowedToMove, onClick, onDelete, toggleToast, updateFolder } =
15
- props;
15
+ const {
16
+ folder,
17
+ isAllowedToDelete,
18
+ isAllowedToEdit,
19
+ isAllowedToMove,
20
+ isSaving,
21
+ onClick,
22
+ onDelete,
23
+ toggleToast,
24
+ updateFolder,
25
+ } = props;
16
26
  const { id, folderName, parentId, site } = folder;
17
27
 
18
28
  const initState = { folderName, parentId };
19
29
  const [folderForm, setFolderForm] = useState(initState);
20
- const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
21
- const { isOpen: isRenameOpen, toggleModal: toggleRenameModal } = useModal();
22
- const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
30
+ const { isOpen, toggleModal } = useModals(["delete", "rename", "move"]);
23
31
 
24
32
  const setName = (name: string) => setFolderForm({ ...folderForm, folderName: name });
25
33
  const setParent = (folderID: number) => setFolderForm({ ...folderForm, parentId: folderID });
@@ -31,7 +39,7 @@ const FolderItem = (props: IProps) => {
31
39
  {
32
40
  label: "Rename",
33
41
  icon: "edit",
34
- action: () => toggleRenameModal(),
42
+ action: () => toggleModal("rename"),
35
43
  },
36
44
  ];
37
45
 
@@ -41,7 +49,7 @@ const FolderItem = (props: IProps) => {
41
49
  {
42
50
  label: "Move to...",
43
51
  icon: "change",
44
- action: () => toggleMoveModal(),
52
+ action: () => toggleModal("move"),
45
53
  },
46
54
  ];
47
55
  }
@@ -53,16 +61,16 @@ const FolderItem = (props: IProps) => {
53
61
  {
54
62
  label: "Delete",
55
63
  icon: "delete",
56
- action: () => toggleDeleteModal(),
64
+ action: () => toggleModal("delete"),
57
65
  },
58
66
  ];
59
67
  }
60
68
 
61
69
  const handleClick = () => onClick(id);
62
70
 
63
- const handleDeleteFolder = () => {
64
- onDelete(folder);
65
- isDeleteOpen && toggleDeleteModal();
71
+ const handleDeleteFolder = async () => {
72
+ await onDelete(folder);
73
+ isOpen("delete") && toggleModal("delete");
66
74
  };
67
75
 
68
76
  const handleUpdateFolder = async (toast = false) => {
@@ -72,39 +80,17 @@ const FolderItem = (props: IProps) => {
72
80
  site || "global",
73
81
  );
74
82
  if (updated) {
75
- isRenameOpen && toggleRenameModal();
83
+ isOpen("rename") && toggleModal("rename");
76
84
  toast && toggleToast();
77
85
  }
78
86
  };
79
87
 
80
88
  const handleModalClose = () => {
81
89
  setFolderForm(initState);
82
- isMoveOpen && toggleMoveModal();
83
- isRenameOpen && toggleRenameModal();
90
+ isOpen("move") && toggleModal("move");
91
+ isOpen("rename") && toggleModal("rename");
84
92
  };
85
93
 
86
- const mainDeleteModalAction = {
87
- title: "Delete Folder",
88
- onClick: () => handleDeleteFolder(),
89
- };
90
-
91
- const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
92
-
93
- const mainRenameModalAction = {
94
- title: "Rename Folder",
95
- onClick: () => handleUpdateFolder(),
96
- disabled: folderForm.folderName.trim().length === 0,
97
- };
98
-
99
- const secondaryRenameModalAction = { title: "Cancel", onClick: handleModalClose };
100
-
101
- const mainMoveModalAction = {
102
- title: "Move",
103
- onClick: () => handleUpdateFolder(true),
104
- };
105
-
106
- const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
107
-
108
94
  const FolderTitle = () =>
109
95
  folderName.length > 15 ? (
110
96
  <Tooltip content={folderName}>
@@ -123,35 +109,36 @@ const FolderItem = (props: IProps) => {
123
109
  <FolderTitle />
124
110
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="File actions" />
125
111
  </S.Wrapper>
126
- {isDeleteOpen && (
112
+ {isOpen("delete") && (
127
113
  <DeleteFolderModal
128
- isOpen={isDeleteOpen}
129
- toggleModal={toggleDeleteModal}
130
- mainModalAction={mainDeleteModalAction}
131
- secondaryModalAction={secondaryDeleteModalAction}
114
+ isOpen={isOpen("delete")}
115
+ toggleModal={() => toggleModal("delete")}
132
116
  title={folderName}
117
+ onDelete={handleDeleteFolder}
118
+ isDeleting={isSaving}
133
119
  />
134
120
  )}
135
- {isRenameOpen && (
121
+ {isOpen("rename") && (
136
122
  <RenameFolderModal
137
- isOpen={isRenameOpen}
123
+ isOpen={isOpen("rename")}
138
124
  toggleModal={handleModalClose}
139
- mainModalAction={mainRenameModalAction}
140
- secondaryModalAction={secondaryRenameModalAction}
141
125
  value={folderForm.folderName}
142
126
  setValue={setName}
127
+ onUpdateFolder={() => handleUpdateFolder()}
128
+ isNameEmpty={folderForm.folderName.trim().length === 0}
129
+ isUpdating={isSaving}
143
130
  />
144
131
  )}
145
- {isMoveOpen && (
132
+ {isOpen("move") && (
146
133
  <MoveItemModal
147
- isOpen={isMoveOpen}
134
+ isOpen={isOpen("move")}
148
135
  toggleModal={handleModalClose}
149
- mainModalAction={mainMoveModalAction}
150
- secondaryModalAction={secondaryMoveModalAction}
151
136
  folder={folderForm.parentId}
152
137
  setFolder={setParent}
153
138
  hidden={[folder.id]}
154
139
  hideRoot={!parentId}
140
+ onMove={() => handleUpdateFolder(true)}
141
+ isMoving={isSaving}
155
142
  />
156
143
  )}
157
144
  </>
@@ -163,6 +150,7 @@ interface IProps {
163
150
  isAllowedToEdit: boolean;
164
151
  isAllowedToDelete: boolean;
165
152
  isAllowedToMove: boolean;
153
+ isSaving: boolean;
166
154
  onClick(folderID: number): void;
167
155
  onDelete(folder: IFolder): void;
168
156
  toggleToast(): void;
@@ -173,8 +161,12 @@ interface IProps {
173
161
  ): Promise<boolean>;
174
162
  }
175
163
 
164
+ const mapStateToProps = (state: IRootState) => ({
165
+ isSaving: state.app.isSaving,
166
+ });
167
+
176
168
  const mapDispatchToProps = {
177
169
  updateFolder: fileDriveActions.updateFolder,
178
170
  };
179
171
 
180
- export default connect(null, mapDispatchToProps)(FolderItem);
172
+ export default connect(mapStateToProps, mapDispatchToProps)(FolderItem);
@@ -1,8 +1,10 @@
1
- import React, { useState } from "react";
1
+ import type React from "react";
2
+ import { useState } from "react";
3
+
2
4
  import { CheckField, Tag, Tooltip } from "@ax/components";
3
- import { IActionMenuOption, ICheck, IFile } from "@ax/types";
4
5
  import { formatBytes, getFileIcon, getFormattedDateWithTimezone, trimText } from "@ax/helpers";
5
- import { useModal } from "@ax/hooks";
6
+ import { useModals } from "@ax/hooks";
7
+ import type { IActionMenuOption, ICheck, IFile } from "@ax/types";
6
8
 
7
9
  import { DeleteFileModal, MoveItemModal } from "../atoms";
8
10
 
@@ -17,6 +19,7 @@ const GridItem = (props: IProps) => {
17
19
  isAllowedToEdit,
18
20
  isAllowedToMove,
19
21
  isSearching,
22
+ isSaving,
20
23
  onChange,
21
24
  onClick,
22
25
  onDelete,
@@ -26,8 +29,8 @@ const GridItem = (props: IProps) => {
26
29
  const { id, fileName, fileType, sizeBytes, uploadDate, folder } = file;
27
30
 
28
31
  const [selectedFolder, setSelectedFolder] = useState<number>(currentFolderID || 0);
29
- const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
30
- const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
32
+ const [isDeleting, setIsDeleting] = useState(false);
33
+ const { isOpen, toggleModal } = useModals(["delete", "move"]);
31
34
 
32
35
  const handleChange = (value: ICheck) => onChange(value);
33
36
  const handleClick = () => onClick(file);
@@ -50,7 +53,7 @@ const GridItem = (props: IProps) => {
50
53
  {
51
54
  label: "Move to...",
52
55
  icon: "change",
53
- action: () => toggleMoveModal(),
56
+ action: () => toggleModal("move"),
54
57
  },
55
58
  ];
56
59
  }
@@ -62,45 +65,36 @@ const GridItem = (props: IProps) => {
62
65
  {
63
66
  label: "Delete",
64
67
  icon: "delete",
65
- action: () => toggleDeleteModal(),
68
+ action: () => toggleModal("delete"),
66
69
  },
67
70
  ];
68
71
  }
69
72
 
70
73
  const iconUrl = `/img/icons/${getFileIcon(fileType)}`;
71
74
 
72
- const handleDeleteFile = () => {
73
- onDelete(id);
74
- isDeleteOpen && toggleDeleteModal();
75
+ const handleDeleteFile = async () => {
76
+ setIsDeleting(true);
77
+ try {
78
+ await onDelete(id);
79
+ } finally {
80
+ setIsDeleting(false);
81
+ toggleModal("delete");
82
+ }
75
83
  };
76
84
 
77
- const handleMoveFile = () => {
85
+ const handleMoveFile = async () => {
78
86
  if (folder?.folderId !== selectedFolder) {
79
- onMove(id, selectedFolder);
80
- isMoveOpen && toggleMoveModal();
87
+ await onMove(id, selectedFolder);
88
+ isOpen("move") && toggleModal("move");
81
89
  setSelectedFolder(0);
82
90
  }
83
91
  };
84
92
 
85
93
  const handleModalClose = () => {
86
94
  setSelectedFolder(0);
87
- isMoveOpen && toggleMoveModal();
88
- };
89
-
90
- const mainDeleteModalAction = {
91
- title: "Delete document",
92
- onClick: () => handleDeleteFile(),
95
+ isOpen("move") && toggleModal("move");
93
96
  };
94
97
 
95
- const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
96
-
97
- const mainMoveModalAction = {
98
- title: "Move",
99
- onClick: () => handleMoveFile(),
100
- };
101
-
102
- const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
103
-
104
98
  const FileTitle = () =>
105
99
  fileName.length > 40 ? (
106
100
  <Tooltip content={fileName}>
@@ -144,24 +138,24 @@ const GridItem = (props: IProps) => {
144
138
  </S.TagWrapper>
145
139
  )}
146
140
  </S.Wrapper>
147
- {isDeleteOpen && (
141
+ {isOpen("delete") && (
148
142
  <DeleteFileModal
149
- isOpen={isDeleteOpen}
150
- toggleModal={toggleDeleteModal}
151
- mainModalAction={mainDeleteModalAction}
152
- secondaryModalAction={secondaryDeleteModalAction}
143
+ isOpen={isOpen("delete")}
144
+ toggleModal={() => toggleModal("delete")}
153
145
  title={fileName}
146
+ onDelete={handleDeleteFile}
147
+ isDeleting={isDeleting}
154
148
  />
155
149
  )}
156
- {isMoveOpen && (
150
+ {isOpen("move") && (
157
151
  <MoveItemModal
158
- isOpen={isMoveOpen}
152
+ isOpen={isOpen("move")}
159
153
  toggleModal={handleModalClose}
160
- mainModalAction={mainMoveModalAction}
161
- secondaryModalAction={secondaryMoveModalAction}
162
154
  folder={selectedFolder}
163
155
  setFolder={setSelectedFolder}
164
156
  hideRoot={!folder}
157
+ onMove={handleMoveFile}
158
+ isMoving={isSaving}
165
159
  />
166
160
  )}
167
161
  </>
@@ -176,6 +170,7 @@ interface IProps {
176
170
  isAllowedToDelete: boolean;
177
171
  isAllowedToMove: boolean;
178
172
  isSearching: boolean;
173
+ isSaving: boolean;
179
174
  onChange(e: ICheck): void;
180
175
  onClick(file: IFile): void;
181
176
  onDelete(fileID: number): void;
@@ -1,8 +1,9 @@
1
- import React, { useState } from "react";
1
+ import { useState } from "react";
2
+
2
3
  import { CheckField, ElementsTooltip, Tag, Tooltip } from "@ax/components";
3
- import { IActionMenuOption, ICheck, IFile } from "@ax/types";
4
4
  import { formatBytes, getFileIcon, getFormattedDateWithTimezone, trimText } from "@ax/helpers";
5
- import { useModal } from "@ax/hooks";
5
+ import { useModals } from "@ax/hooks";
6
+ import type { IActionMenuOption, ICheck, IFile } from "@ax/types";
6
7
 
7
8
  import { DeleteFileModal, MoveItemModal } from "../atoms";
8
9
 
@@ -18,6 +19,7 @@ const ListItem = (props: IProps) => {
18
19
  isAllowedToMove,
19
20
  isSearching,
20
21
  hoverCheck,
22
+ isSaving,
21
23
  onChange,
22
24
  onClick,
23
25
  onDelete,
@@ -26,8 +28,8 @@ const ListItem = (props: IProps) => {
26
28
  const { id, fileName, fileType, sizeBytes, uploadDate, tags, folder } = file;
27
29
 
28
30
  const [selectedFolder, setSelectedFolder] = useState<number>(currentFolderID || 0);
29
- const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
30
- const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
31
+ const [isDeleting, setIsDeleting] = useState(false);
32
+ const { isOpen, toggleModal } = useModals(["delete", "move"]);
31
33
 
32
34
  const handleChange = (value: ICheck) => onChange(value);
33
35
  const handleClick = () => onClick(file);
@@ -49,7 +51,7 @@ const ListItem = (props: IProps) => {
49
51
  {
50
52
  label: "Move to...",
51
53
  icon: "change",
52
- action: () => toggleMoveModal(),
54
+ action: () => toggleModal("move"),
53
55
  },
54
56
  ];
55
57
  }
@@ -61,45 +63,36 @@ const ListItem = (props: IProps) => {
61
63
  {
62
64
  label: "Delete",
63
65
  icon: "delete",
64
- action: () => toggleDeleteModal(),
66
+ action: () => toggleModal("delete"),
65
67
  },
66
68
  ];
67
69
  }
68
70
 
69
71
  const iconUrl = `/img/icons/${getFileIcon(fileType)}`;
70
72
 
71
- const handleDeleteFile = () => {
72
- onDelete(id);
73
- isDeleteOpen && toggleDeleteModal();
73
+ const handleDeleteFile = async () => {
74
+ setIsDeleting(true);
75
+ try {
76
+ await onDelete(id);
77
+ } finally {
78
+ setIsDeleting(false);
79
+ toggleModal("delete");
80
+ }
74
81
  };
75
82
 
76
- const handleMoveFile = () => {
83
+ const handleMoveFile = async () => {
77
84
  if (folder?.folderId !== selectedFolder) {
78
- onMove(id, selectedFolder);
79
- isMoveOpen && toggleMoveModal();
85
+ await onMove(id, selectedFolder);
86
+ isOpen("move") && toggleModal("move");
80
87
  setSelectedFolder(0);
81
88
  }
82
89
  };
83
90
 
84
91
  const handleModalClose = () => {
85
92
  setSelectedFolder(0);
86
- isMoveOpen && toggleMoveModal();
87
- };
88
-
89
- const mainDeleteModalAction = {
90
- title: "Delete document",
91
- onClick: () => handleDeleteFile(),
93
+ isOpen("move") && toggleModal("move");
92
94
  };
93
95
 
94
- const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
95
-
96
- const mainMoveModalAction = {
97
- title: "Move",
98
- onClick: () => handleMoveFile(),
99
- };
100
-
101
- const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
102
-
103
96
  const FileTitle = () =>
104
97
  fileName.length > 50 ? <Tooltip content={fileName}>{trimText(fileName, 50)}</Tooltip> : <>{fileName}</>;
105
98
 
@@ -157,24 +150,24 @@ const ListItem = (props: IProps) => {
157
150
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="File actions" />
158
151
  </S.ActionsCell>
159
152
  </S.ItemRow>
160
- {isDeleteOpen && (
153
+ {isOpen("delete") && (
161
154
  <DeleteFileModal
162
- isOpen={isDeleteOpen}
163
- toggleModal={toggleDeleteModal}
164
- mainModalAction={mainDeleteModalAction}
165
- secondaryModalAction={secondaryDeleteModalAction}
155
+ isOpen={isOpen("delete")}
156
+ toggleModal={() => toggleModal("delete")}
166
157
  title={fileName}
158
+ onDelete={handleDeleteFile}
159
+ isDeleting={isSaving}
167
160
  />
168
161
  )}
169
- {isMoveOpen && (
162
+ {isOpen("move") && (
170
163
  <MoveItemModal
171
- isOpen={isMoveOpen}
164
+ isOpen={isOpen("move")}
172
165
  toggleModal={handleModalClose}
173
- mainModalAction={mainMoveModalAction}
174
- secondaryModalAction={secondaryMoveModalAction}
175
166
  folder={selectedFolder}
176
167
  setFolder={setSelectedFolder}
177
168
  hideRoot={!folder}
169
+ onMove={handleMoveFile}
170
+ isMoving={isSaving}
178
171
  />
179
172
  )}
180
173
  </>
@@ -194,6 +187,7 @@ interface IProps {
194
187
  onDelete(fileID: number): void;
195
188
  onMove(fileID: number, folderID: number): void;
196
189
  hoverCheck: boolean;
190
+ isSaving: boolean;
197
191
  }
198
192
 
199
193
  export default ListItem;