@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
@@ -4,7 +4,7 @@ import { connect } from "react-redux";
4
4
  import { EmptyState, ErrorToast, FilterTagsBar, MainWrapper, TableList, Toast } from "@ax/components";
5
5
  import { appActions } from "@ax/containers/App";
6
6
  import { integrationsActions } from "@ax/containers/Integrations";
7
- import { useBulkSelection, useEmptyState, useModal, usePermission, useToast } from "@ax/hooks";
7
+ import { useBulkSelection, useEmptyState, useModals, usePermissions, useToast } from "@ax/hooks";
8
8
  import type { IEmptyStateProps, IIntegration, IQueryValue, IRootState } from "@ax/types";
9
9
 
10
10
  import {
@@ -33,6 +33,7 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
33
33
  integrations,
34
34
  totalItems,
35
35
  currentSite,
36
+ isSaving,
36
37
  resetIntegrations,
37
38
  deleteIntegration,
38
39
  changeIntegrationState,
@@ -45,12 +46,10 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
45
46
  throw new Error(`ERROR: User reached Integrations with null site info`);
46
47
  }
47
48
 
48
- const [isBulkLoading, setIsBulkLoading] = useState(false);
49
49
  const [isScrolling, setIsScrolling] = useState(false);
50
50
  const tableRef = useRef<HTMLDivElement>(null);
51
51
  const { setFiltersSelection, resetFilterQuery, filterValues, filterQuery, isFiltered } = useFilterQuery();
52
- const { isOpen: isOpenDelete, toggleModal: toggleModalDelete } = useModal();
53
- const { isOpen: isOpenDeactivate, toggleModal: toggleModalDeactivate } = useModal();
52
+ const { isOpen, toggleModal } = useModals(["delete", "deactivate"]);
54
53
  const {
55
54
  isVisible: isVisibleDelete,
56
55
  toggleToast: toggleToastDelete,
@@ -64,9 +63,11 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
64
63
  state: stateToastChange,
65
64
  } = useToast();
66
65
 
67
- const isAllowedToManageIntegrations = usePermission("general.manageSiteThirdPartyIntegrations");
68
- const isAllowedToDeactivateIntegrations = usePermission("general.deactivateSiteThirdPartyIntegrations");
69
- const isAllowedToDeleteIntegrations = usePermission("general.deleteSiteThirdPartyIntegrations");
66
+ const isAllowedTo = usePermissions({
67
+ manage: "general.manageSiteThirdPartyIntegrations",
68
+ deactivate: "general.deactivateSiteThirdPartyIntegrations",
69
+ delete: "general.deleteSiteThirdPartyIntegrations",
70
+ });
70
71
 
71
72
  const sensors = useSensors(
72
73
  useSensor(PointerSensor, {
@@ -126,27 +127,23 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
126
127
  } = useBulkSelection(filteredIntegrationsIds);
127
128
 
128
129
  const bulkDelete = async () => {
129
- setIsBulkLoading(true);
130
130
  const params = getParams();
131
131
  const deleted = await deleteIntegration(selectedItems.all, params);
132
132
  if (deleted) {
133
133
  toggleToastDelete({ total: selectedItems.all.length });
134
134
  }
135
- toggleModalDelete();
135
+ toggleModal("delete");
136
136
  resetBulkSelection();
137
- setIsBulkLoading(false);
138
137
  };
139
138
 
140
139
  const bulkDeactivate = async () => {
141
- setIsBulkLoading(true);
142
140
  const params = getParams();
143
141
  const changed = await changeIntegrationState(selectedItems.all, false, params);
144
142
  if (changed) {
145
143
  toggleToastChange({ total: selectedItems.all.length, active: false });
146
144
  }
147
- toggleModalDeactivate();
145
+ toggleModal("deactivate");
148
146
  resetBulkSelection();
149
- setIsBulkLoading(false);
150
147
  };
151
148
 
152
149
  const unselectAllItems = () => resetBulkSelection();
@@ -158,22 +155,21 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
158
155
  const filterItems = async (filterPointer: string, filtersSelected: IQueryValue[]) =>
159
156
  setFiltersSelection(filterPointer, filtersSelected);
160
157
 
161
- const bulkActions: { icon: string; text: string; action: () => void | Promise<void> }[] =
162
- isAllowedToDeleteIntegrations
163
- ? [
164
- {
165
- icon: "delete",
166
- text: "delete",
167
- action: toggleModalDelete,
168
- },
169
- ]
170
- : [];
171
-
172
- if (isAllowedToDeactivateIntegrations) {
158
+ const bulkActions: { icon: string; text: string; action: () => void | Promise<void> }[] = isAllowedTo.delete
159
+ ? [
160
+ {
161
+ icon: "delete",
162
+ text: "delete",
163
+ action: () => toggleModal("delete"),
164
+ },
165
+ ]
166
+ : [];
167
+
168
+ if (isAllowedTo.deactivate) {
173
169
  bulkActions.push({
174
170
  icon: "deactivate",
175
171
  text: "Deactivate",
176
- action: toggleModalDeactivate,
172
+ action: () => toggleModal("deactivate"),
177
173
  });
178
174
  }
179
175
 
@@ -190,7 +186,7 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
190
186
  bulkActions={bulkActions}
191
187
  setHoverCheck={setHoverCheck}
192
188
  selectedItems={selectedItems}
193
- isLoading={isBulkLoading}
189
+ isLoading={isSaving}
194
190
  />
195
191
  );
196
192
 
@@ -209,18 +205,6 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
209
205
  }
210
206
  };
211
207
 
212
- const mainDeleteModalAction = {
213
- title: isBulkLoading ? "Deleting" : "Delete",
214
- onClick: bulkDelete,
215
- disabled: isBulkLoading,
216
- };
217
- const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleModalDelete };
218
-
219
- const mainDeactivateModalAction = {
220
- title: "Deactivate",
221
- onClick: bulkDeactivate,
222
- };
223
- const secondaryDeactivateModalAction = { title: "Cancel", onClick: toggleModalDeactivate };
224
208
 
225
209
  const deletedToastProps = {
226
210
  setIsVisible: setIsVisibleDelete,
@@ -234,7 +218,7 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
234
218
  }`,
235
219
  };
236
220
 
237
- const rightButtonProps = isAllowedToManageIntegrations
221
+ const rightButtonProps = isAllowedTo.manage
238
222
  ? {
239
223
  label: "New Custom Code",
240
224
  action: () => setHistoryPush(`/sites/settings/addons/new`),
@@ -310,20 +294,20 @@ const Integrations = (props: IIntegrationsProps): JSX.Element => {
310
294
  </S.ContentWrapper>
311
295
  </S.Wrapper>
312
296
  <DeleteModal
313
- isOpen={isOpenDelete}
314
- toggleModal={toggleModalDelete}
315
- secondaryModalAction={secondaryDeleteModalAction}
316
- mainModalAction={mainDeleteModalAction}
297
+ isOpen={isOpen("delete")}
298
+ toggleModal={() => toggleModal("delete")}
299
+ onDelete={bulkDelete}
300
+ isDeleting={isSaving}
317
301
  integrations={integrations}
318
302
  selectedIds={selectedItems.all}
319
303
  />
320
304
  <DeactivateModal
321
- isOpen={isOpenDeactivate}
322
- toggleModal={toggleModalDeactivate}
323
- secondaryModalAction={secondaryDeactivateModalAction}
324
- mainModalAction={mainDeactivateModalAction}
305
+ isOpen={isOpen("deactivate")}
306
+ toggleModal={() => toggleModal("deactivate")}
325
307
  integrations={integrations}
326
308
  selectedIds={selectedItems.all}
309
+ onDeactivate={bulkDeactivate}
310
+ isDeactivating={isSaving}
327
311
  />
328
312
  </MainWrapper>
329
313
  );
@@ -334,6 +318,7 @@ const mapStateToProps = (state: IRootState) => ({
334
318
  integrations: state.integrations.integrations,
335
319
  totalItems: state.integrations.totalItems,
336
320
  currentSite: state.sites.currentSiteInfo?.id ?? null,
321
+ isSaving: state.app.isSaving,
337
322
  });
338
323
 
339
324
  const mapDispatchToProps = {
@@ -351,6 +336,7 @@ interface IStateProps {
351
336
  integrations: IIntegration[];
352
337
  totalItems: number;
353
338
  currentSite: number | null;
339
+ isSaving: boolean;
354
340
  }
355
341
 
356
342
  interface IDispatchProps {
@@ -27,6 +27,7 @@ import type {
27
27
  ISite,
28
28
  } from "@ax/types";
29
29
 
30
+ import { DeleteModal } from "../atoms";
30
31
  import ConnectedField from "./ConnectedField";
31
32
 
32
33
  import * as S from "./style";
@@ -70,12 +71,16 @@ const Form = (props: IProps) => {
70
71
  const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
71
72
  const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
72
73
  const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
74
+ const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
75
+ const [isDeleting, setIsDeleting] = useState(false);
76
+ const [deleteAllVersions, setDeleteAllVersions] = useState(false);
73
77
  const { isDirty, resetDirty, setIsDirty } = useIsDirty(form);
74
78
  const path = site ? "/sites/pages" : "/data";
75
79
 
76
80
  const { fields } = schema;
77
81
  const inversed = !site;
78
82
  const languages = site ? siteLanguages : globalLangs;
83
+ const arePagesTranslated = (form?.dataLanguages?.length ?? 0) > 1;
79
84
 
80
85
  const fieldsTranslate: ISchemaField[] = [
81
86
  {
@@ -207,12 +212,14 @@ const Form = (props: IProps) => {
207
212
  setHistoryPush("/sites/settings/content-types", false);
208
213
  };
209
214
 
210
- const removeItem = () => {
211
- deleteStructuredDataContent(form.id).then((deleted: boolean) => {
212
- if (deleted) {
213
- setHistoryPush(path, true);
214
- }
215
- });
215
+ const removeItem = async () => {
216
+ setIsDeleting(true);
217
+ const deleted = await deleteStructuredDataContent(form.id);
218
+ setIsDeleting(false);
219
+ toggleDeleteModal();
220
+ if (deleted) {
221
+ setHistoryPush(path, true);
222
+ }
216
223
  };
217
224
 
218
225
  const publishItem = async () => {
@@ -280,7 +287,7 @@ const Form = (props: IProps) => {
280
287
  {
281
288
  label: "Delete",
282
289
  icon: "delete",
283
- action: removeItem,
290
+ action: toggleDeleteModal,
284
291
  },
285
292
  ],
286
293
  };
@@ -350,7 +357,7 @@ const Form = (props: IProps) => {
350
357
  onClick: toggleCancelScheduleModal,
351
358
  };
352
359
 
353
- return isLoading ? (
360
+ return isLoading && !isDeleting ? (
354
361
  <Loading />
355
362
  ) : (
356
363
  <>
@@ -421,6 +428,16 @@ const Form = (props: IProps) => {
421
428
  mainModalAction={mainCancelScheduleModalAction}
422
429
  secondaryModalAction={secondaryCancelScheduleModalAction}
423
430
  />
431
+ <DeleteModal
432
+ isOpen={isDeleteOpen}
433
+ toggleModal={toggleDeleteModal}
434
+ title={title || "this item"}
435
+ arePagesTranslated={arePagesTranslated}
436
+ deleteAllVersions={deleteAllVersions}
437
+ setDeleteAllVersions={setDeleteAllVersions}
438
+ onDelete={removeItem}
439
+ isDeleting={isDeleting}
440
+ />
424
441
  <RestoreModal
425
442
  isOpen={isRestoreOpen}
426
443
  toggleModal={toggleRestoreModal}
@@ -1,74 +1,13 @@
1
- import React from "react";
1
+ import type React from "react";
2
2
 
3
- import type { IModal } from "@ax/types";
4
- import { Modal, FieldsBehavior, ErrorToast } from "@ax/components";
3
+ import { ErrorToast, FieldsBehavior, Modal } from "@ax/components";
5
4
  import { slugify } from "@ax/helpers";
5
+ import type { IModal } from "@ax/types";
6
6
 
7
7
  import * as S from "./style";
8
8
 
9
- const DeleteModal = (props: IDeleteModal): JSX.Element => {
10
- const {
11
- isOpen,
12
- toggleModal,
13
- mainModalAction,
14
- secondaryModalAction,
15
- title,
16
- isTranslated,
17
- deleteAllVersions,
18
- setDeleteAllVersions,
19
- } = props;
20
-
21
- const options = [
22
- {
23
- title: "Delete only this version",
24
- name: "deletePage",
25
- value: false,
26
- },
27
- {
28
- title: "Delete all languages versions",
29
- name: "deleteAll",
30
- value: true,
31
- },
32
- ];
33
-
34
- return (
35
- <Modal
36
- isOpen={isOpen}
37
- hide={toggleModal}
38
- title="Delete Global Data?"
39
- secondaryAction={secondaryModalAction}
40
- mainAction={mainModalAction}
41
- size="S"
42
- >
43
- {isTranslated ? (
44
- <>
45
- <S.ModalContent>
46
- <p>
47
- Are you sure you want to delete <strong>{title}</strong> page? If you delete it, this page does not appear
48
- in the sites associated. Also, this page has some translations associated.
49
- </p>
50
- <FieldsBehavior
51
- name="removeAllVersions"
52
- fieldType="RadioGroup"
53
- value={deleteAllVersions}
54
- options={options}
55
- onChange={setDeleteAllVersions}
56
- />
57
- </S.ModalContent>
58
- </>
59
- ) : (
60
- <S.ModalContent>
61
- Are you sure you want to delete <strong>{title}</strong> page? If you delete it, this page does not appear in
62
- the sites associated. This action <strong>cannot be undone</strong>.
63
- </S.ModalContent>
64
- )}
65
- </Modal>
66
- );
67
- };
68
-
69
9
  const DuplicateModal = (props: IDuplicateModal): JSX.Element => {
70
- const { isOpen, toggleModal, mainModalAction, secondaryModalAction, duplicateModalState, setDuplicateModalState } =
71
- props;
10
+ const { isOpen, toggleModal, duplicateModalState, setDuplicateModalState, onDuplicate, isSaving } = props;
72
11
 
73
12
  const handleNameChange = (value: string) => {
74
13
  setDuplicateModalState({ title: value, slug: slugify(value) });
@@ -78,6 +17,19 @@ const DuplicateModal = (props: IDuplicateModal): JSX.Element => {
78
17
  setDuplicateModalState((state: { title: string; slug: string }) => ({ ...state, slug: value }));
79
18
  };
80
19
 
20
+ const handleCloseDuplicate = () => {
21
+ toggleModal();
22
+ setDuplicateModalState({ title: "", slug: "" });
23
+ };
24
+
25
+ const mainModalAction = {
26
+ title: isSaving ? "Duplicating" : "Duplicate",
27
+ onClick: onDuplicate,
28
+ disabled: !duplicateModalState.title.trim() || !duplicateModalState.slug.trim() || isSaving,
29
+ };
30
+
31
+ const secondaryModalAction = { title: "Cancel", onClick: handleCloseDuplicate };
32
+
81
33
  return (
82
34
  <Modal
83
35
  isOpen={isOpen}
@@ -110,8 +62,10 @@ const DuplicateModal = (props: IDuplicateModal): JSX.Element => {
110
62
  );
111
63
  };
112
64
 
113
- const UnpublishModal = (props: IModal): JSX.Element => {
114
- const { isOpen, toggleModal, mainModalAction } = props;
65
+ const UnpublishModal = (props: IUnpublishModal): JSX.Element => {
66
+ const { isOpen, toggleModal } = props;
67
+
68
+ const mainModalAction = { title: "Ok", onClick: toggleModal };
115
69
 
116
70
  return (
117
71
  <Modal isOpen={isOpen} hide={toggleModal} title="Unpublish Modified Page" mainAction={mainModalAction} size="S">
@@ -125,16 +79,13 @@ const UnpublishModal = (props: IModal): JSX.Element => {
125
79
  );
126
80
  };
127
81
 
128
- interface IDeleteModal extends IModal {
129
- title: string;
130
- isTranslated: boolean;
131
- deleteAllVersions: boolean;
132
- setDeleteAllVersions: React.Dispatch<React.SetStateAction<boolean>>;
133
- }
134
-
135
82
  interface IDuplicateModal extends IModal {
136
83
  duplicateModalState: { title: string; slug: string };
137
84
  setDuplicateModalState: React.Dispatch<React.SetStateAction<{ title: string; slug: string }>>;
85
+ onDuplicate: () => void;
86
+ isSaving: boolean;
138
87
  }
139
88
 
140
- export { DeleteModal, DuplicateModal, UnpublishModal };
89
+ interface IUnpublishModal extends IModal {}
90
+
91
+ export { DuplicateModal, UnpublishModal };
@@ -34,7 +34,8 @@ import type {
34
34
  ISchemaField,
35
35
  } from "@ax/types";
36
36
 
37
- import { DeleteModal, DuplicateModal, UnpublishModal } from "./atoms";
37
+ import { DeleteModal } from "../../atoms";
38
+ import { DuplicateModal, UnpublishModal } from "./atoms";
38
39
  import { getCurrentLanguages } from "./utils";
39
40
 
40
41
  import * as S from "./style";
@@ -292,27 +293,8 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
292
293
 
293
294
  menuOptions = globalPage.liveStatus?.status === pageStatus.PUBLISHED ? [viewOption, ...menuOptions] : menuOptions;
294
295
 
295
- const handleCloseDuplicate = () => {
296
- toggleModal("duplicate");
297
- setDuplicateModalState({ title: "", slug: "" });
298
- };
299
-
300
- const mainDuplicateModalAction = {
301
- title: "Duplicate",
302
- onClick: handleDuplicatePage,
303
- disabled: !duplicateModalState.title.trim() || !duplicateModalState.slug.trim() || isSaving,
304
- };
305
-
306
- const secondaryDuplicateModalAction = { title: "Cancel", onClick: handleCloseDuplicate };
307
-
308
296
  const isTranslated = globalPage.pageLanguages.length > 1;
309
297
 
310
- const mainDeleteModalAction = {
311
- title: "Delete page",
312
- onClick: removeItem,
313
- };
314
- const secondaryDeleteModalAction = { title: "Cancel", onClick: () => toggleModal("delete") };
315
-
316
298
  const currentLanguages = getCurrentLanguages(languages, pageLanguages);
317
299
 
318
300
  const changeLanguage = (language: { locale: string; id: number | null }) => {
@@ -376,8 +358,6 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
376
358
 
377
359
  const getLiveStatus = () => (isScheduledPub ? "scheduled" : haveDraftPage ? "modified" : liveStatus.status);
378
360
 
379
- const mainUnpublishAction = { title: "Ok", onClick: () => toggleModal("unpublish") };
380
-
381
361
  const CategoryColumns = buildCategoryColumns(
382
362
  categoryColumns,
383
363
  activeColumns,
@@ -445,22 +425,22 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
445
425
  <DuplicateModal
446
426
  isOpen={isOpen("duplicate")}
447
427
  toggleModal={() => toggleModal("duplicate")}
448
- mainModalAction={mainDuplicateModalAction}
449
- secondaryModalAction={secondaryDuplicateModalAction}
450
- {...{ duplicateModalState, setDuplicateModalState }}
428
+ duplicateModalState={duplicateModalState}
429
+ setDuplicateModalState={setDuplicateModalState}
430
+ onDuplicate={handleDuplicatePage}
431
+ isSaving={isSaving}
451
432
  />
452
433
  <DeleteModal
453
434
  isOpen={isOpen("delete")}
454
435
  toggleModal={() => toggleModal("delete")}
455
- mainModalAction={mainDeleteModalAction}
456
- secondaryModalAction={secondaryDeleteModalAction}
457
- {...{ title: globalPage.title, isTranslated, deleteAllVersions, setDeleteAllVersions }}
458
- />
459
- <UnpublishModal
460
- isOpen={isOpen("unpublish")}
461
- toggleModal={() => toggleModal("unpublish")}
462
- mainModalAction={mainUnpublishAction}
436
+ title={globalPage.title}
437
+ arePagesTranslated={isTranslated}
438
+ deleteAllVersions={deleteAllVersions}
439
+ setDeleteAllVersions={setDeleteAllVersions}
440
+ onDelete={removeItem}
441
+ isDeleting={isSaving}
463
442
  />
443
+ <UnpublishModal isOpen={isOpen("unpublish")} toggleModal={() => toggleModal("unpublish")} />
464
444
  </>
465
445
  );
466
446
  };
@@ -504,6 +484,8 @@ interface IGlobalPageItemProps {
504
484
  skipReview?: boolean;
505
485
  hoverCheck?: boolean;
506
486
  isSaving: boolean;
487
+ isDeleting?: boolean;
488
+ onDeletingChange?(isDeleting: boolean): void;
507
489
  }
508
490
 
509
491
  const mapStateToProps = (state: IRootState) => ({
@@ -1,3 +1,4 @@
1
+ import { useState } from "react";
1
2
  import { connect } from "react-redux";
2
3
 
3
4
  import { CheckField, Flag, FloatingMenu, Icon, LanguageMenu, Tooltip, TruncatedTooltip } from "@ax/components";
@@ -9,7 +10,7 @@ import {
9
10
  getHumanLastModifiedDate,
10
11
  getScheduleFormatDate,
11
12
  } from "@ax/helpers";
12
- import { usePermissions } from "@ax/hooks";
13
+ import { useModal, usePermissions } from "@ax/hooks";
13
14
  import type {
14
15
  ICheck,
15
16
  IColumn,
@@ -23,6 +24,7 @@ import type {
23
24
  IStructuredDataContent,
24
25
  } from "@ax/types";
25
26
 
27
+ import { DeleteModal } from "../../atoms";
26
28
  import { getPermission } from "./utils";
27
29
 
28
30
  import * as S from "./style";
@@ -54,6 +56,7 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
54
56
  currentSiteInfo,
55
57
  hoverCheck,
56
58
  getDataContent,
59
+ isSaving,
57
60
  } = props;
58
61
 
59
62
  const isPrivateData = currentStructuredData?.private || false;
@@ -66,11 +69,15 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
66
69
  deletePages: getPermission("delete", isGlobal, isPrivateData),
67
70
  });
68
71
 
72
+ const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
73
+ const [deleteAllVersions, setDeleteAllVersions] = useState(false);
74
+
69
75
  const { locale } = lang;
70
76
  const { dataLanguages, publicationScheduled } = structuredData;
71
77
 
72
78
  const isScheduledPub = !!publicationScheduled && structuredData.draft;
73
79
  const activeColumns = columns.filter((col) => col.show).map((col) => col.id);
80
+ const arePagesTranslated = dataLanguages.length > 1;
74
81
 
75
82
  const publishedTooltip: Record<string, string> = {
76
83
  active: "Live",
@@ -88,13 +95,14 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
88
95
 
89
96
  const handleOnChange = (value: ICheck) => onChange(value);
90
97
 
91
- const removeItem = async () =>
92
- deleteStructuredDataContent(structuredData.id).then((deleted: boolean) => {
93
- if (deleted) {
94
- setDeletedItem(structuredData.id);
95
- toggleToast();
96
- }
97
- });
98
+ const removeItem = async () => {
99
+ const deleted = await deleteStructuredDataContent(structuredData.id);
100
+ if (deleted) {
101
+ setDeletedItem(structuredData.id);
102
+ toggleToast();
103
+ }
104
+ toggleDeleteModal();
105
+ };
98
106
 
99
107
  const publishItem = async () => setDataStatus(structuredData.id, "undraft");
100
108
 
@@ -200,7 +208,7 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
200
208
  menuOptions.push({
201
209
  label: "delete",
202
210
  icon: "delete",
203
- action: removeItem,
211
+ action: toggleDeleteModal,
204
212
  });
205
213
  }
206
214
 
@@ -222,38 +230,50 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
222
230
  );
223
231
 
224
232
  return (
225
- <S.StructuredDataRow role="rowgroup" selected={isSelected} disabled={!isEditable}>
226
- <S.CheckCell role="cell">
227
- <CheckField
228
- name="check"
229
- value={structuredData.id}
230
- checked={isSelected || hoverCheck}
231
- onChange={handleOnChange}
232
- />
233
- </S.CheckCell>
234
- <S.NameCell role="cell" onClick={_handleClick}>
235
- <TruncatedTooltip content={structuredData.content.title} expanded top={1}>
236
- <S.Title>{structuredData.content.title}</S.Title>
237
- </TruncatedTooltip>
238
- </S.NameCell>
239
- {activeColumns.includes("live") && (
240
- <S.LiveCell role="cell" onClick={_handleClick}>
241
- <Tooltip content={publishedTooltip[checkStatus()]}>
242
- <Icon name={checkStatus()} />
243
- </Tooltip>
244
- </S.LiveCell>
245
- )}
246
- {CategoryColumns}
247
- {activeColumns.includes("status") && (
248
- <S.StatusCell role="cell" onClick={_handleClick}>
249
- <S.ModDate>{`Mod. ${getHumanLastModifiedDate(structuredData.modified)}`}</S.ModDate>
250
- </S.StatusCell>
251
- )}
252
- {activeColumns.includes("translation") && <S.TransCell role="cell">{translations}</S.TransCell>}
253
- <S.ActionsCell role="cell">
254
- <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
255
- </S.ActionsCell>
256
- </S.StructuredDataRow>
233
+ <>
234
+ <S.StructuredDataRow role="rowgroup" selected={isSelected} disabled={!isEditable}>
235
+ <S.CheckCell role="cell">
236
+ <CheckField
237
+ name="check"
238
+ value={structuredData.id}
239
+ checked={isSelected || hoverCheck}
240
+ onChange={handleOnChange}
241
+ />
242
+ </S.CheckCell>
243
+ <S.NameCell role="cell" onClick={_handleClick}>
244
+ <TruncatedTooltip content={structuredData.content.title} expanded top={1}>
245
+ <S.Title>{structuredData.content.title}</S.Title>
246
+ </TruncatedTooltip>
247
+ </S.NameCell>
248
+ {activeColumns.includes("live") && (
249
+ <S.LiveCell role="cell" onClick={_handleClick}>
250
+ <Tooltip content={publishedTooltip[checkStatus()]}>
251
+ <Icon name={checkStatus()} />
252
+ </Tooltip>
253
+ </S.LiveCell>
254
+ )}
255
+ {CategoryColumns}
256
+ {activeColumns.includes("status") && (
257
+ <S.StatusCell role="cell" onClick={_handleClick}>
258
+ <S.ModDate>{`Mod. ${getHumanLastModifiedDate(structuredData.modified)}`}</S.ModDate>
259
+ </S.StatusCell>
260
+ )}
261
+ {activeColumns.includes("translation") && <S.TransCell role="cell">{translations}</S.TransCell>}
262
+ <S.ActionsCell role="cell">
263
+ <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
264
+ </S.ActionsCell>
265
+ </S.StructuredDataRow>
266
+ <DeleteModal
267
+ isOpen={isDeleteOpen}
268
+ toggleModal={toggleDeleteModal}
269
+ title={structuredData.content.title}
270
+ arePagesTranslated={arePagesTranslated}
271
+ deleteAllVersions={deleteAllVersions}
272
+ setDeleteAllVersions={setDeleteAllVersions}
273
+ onDelete={removeItem}
274
+ isDeleting={isSaving}
275
+ />
276
+ </>
257
277
  );
258
278
  };
259
279
 
@@ -283,11 +303,13 @@ interface IStructuredDataItemProps {
283
303
  setCurrentDataID(id: number | null): void;
284
304
  currentSiteInfo: ISite | null;
285
305
  hoverCheck?: boolean;
306
+ isSaving: boolean;
286
307
  }
287
308
 
288
309
  const mapStateToProps = (state: IRootState) => ({
289
310
  currentStructuredData: state.structuredData.currentStructuredData,
290
311
  currentSiteInfo: state.sites.currentSiteInfo,
312
+ isSaving: state.app.isSaving,
291
313
  });
292
314
 
293
315
  const mapDispatchToProps = {