@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
@@ -1,7 +1,7 @@
1
- import React, { useState } from "react";
1
+ import { useState } from "react";
2
2
 
3
- import { Modal, FieldsBehavior } from "@ax/components";
4
- import { IMenuItem } from "@ax/types";
3
+ import { FieldsBehavior, Modal } from "@ax/components";
4
+ import type { IMenuItem } from "@ax/types";
5
5
 
6
6
  import * as S from "./style";
7
7
 
@@ -10,6 +10,7 @@ const RemoveModal = (props: IRemoveModalProps) => {
10
10
 
11
11
  const [removeItemState, setRemoveItemState] = useState("deleteItem");
12
12
  const deleteChildren = removeItemState === "deleteChildren";
13
+ const hasChildren = !!item.children.length;
13
14
 
14
15
  const mainRemoveAction = {
15
16
  title: "Delete",
@@ -34,21 +35,33 @@ const RemoveModal = (props: IRemoveModalProps) => {
34
35
  },
35
36
  ];
36
37
 
37
- const RemoveModal = () => (
38
- <S.ModalContent>
39
- <p>
40
- You are going to delete an element that have some associated sections. Choose if you want to delete the element
41
- and the sections or only this one.
42
- </p>
43
- <FieldsBehavior
44
- name="removeItemChildren"
45
- fieldType="RadioGroup"
46
- value={removeItemState}
47
- options={removeItemOptions}
48
- onChange={setRemoveItemState}
49
- />
50
- </S.ModalContent>
51
- );
38
+ const RemoveModalContent = () => {
39
+ if (hasChildren) {
40
+ return (
41
+ <S.ModalContent>
42
+ <p>
43
+ You are going to delete an element that have some associated sections. Choose if you want to delete the
44
+ element and the sections or only this one.
45
+ </p>
46
+ <FieldsBehavior
47
+ name="removeItemChildren"
48
+ fieldType="RadioGroup"
49
+ value={removeItemState}
50
+ options={removeItemOptions}
51
+ onChange={setRemoveItemState}
52
+ />
53
+ </S.ModalContent>
54
+ );
55
+ }
56
+
57
+ return (
58
+ <S.ModalContent>
59
+ <p>
60
+ Are you sure you want to delete <strong>this item</strong>?
61
+ </p>
62
+ </S.ModalContent>
63
+ );
64
+ };
52
65
 
53
66
  return (
54
67
  <Modal
@@ -58,8 +71,9 @@ const RemoveModal = (props: IRemoveModalProps) => {
58
71
  title="Delete Item"
59
72
  mainAction={mainRemoveAction}
60
73
  secondaryAction={secondaryRemoveAction}
74
+ height="auto"
61
75
  >
62
- <RemoveModal />
76
+ <RemoveModalContent />
63
77
  </Modal>
64
78
  );
65
79
  };
@@ -1,14 +1,16 @@
1
- import React, { useState } from "react";
1
+ import type React from "react";
2
+ import { useState } from "react";
2
3
  import { connect } from "react-redux";
3
- import { AnimateLayoutChanges, useSortable } from "@dnd-kit/sortable";
4
4
 
5
- import { menuActions } from "@ax/containers/Navigation";
6
- import { useModal, usePermission } from "@ax/hooks";
7
- import { IMenuItem } from "@ax/types";
8
5
  import { Icon, IconAction, Tooltip } from "@ax/components";
6
+ import { menuActions } from "@ax/containers/Navigation";
7
+ import { useModals, usePermission } from "@ax/hooks";
8
+ import type { IMenuItem } from "@ax/types";
9
+
10
+ import { type AnimateLayoutChanges, useSortable } from "@dnd-kit/sortable";
9
11
 
10
- import SidePanel from "./../SidePanel";
11
12
  import ConfigPanel from "./../ConfigPanel";
13
+ import SidePanel from "./../SidePanel";
12
14
  import { RemoveModal } from "./atoms";
13
15
 
14
16
  import * as S from "./style";
@@ -31,7 +33,7 @@ const Item = (props: IItemProps): JSX.Element => {
31
33
 
32
34
  const isAllowedToMangageMenus = usePermission("navigation.manageSiteMenu");
33
35
 
34
- const removeItemAction = () => (hasChildren ? toggleRemoveModal() : deleteItem(item));
36
+ const removeItemAction = () => toggleModal("remove");
35
37
 
36
38
  const actionMenuOptions = [
37
39
  {
@@ -41,13 +43,10 @@ const Item = (props: IItemProps): JSX.Element => {
41
43
  },
42
44
  ];
43
45
 
44
- const { isOpen, toggleModal } = useModal(false);
45
- const { isOpen: isRemoveOpen, toggleModal: toggleRemoveModal } = useModal(false);
46
+ const { isOpen, toggleModal } = useModals(["sidePanel", "remove", "config"]);
46
47
  const [isOpenedSecond, setIsOpenedSecond] = useState(false);
47
- const { isOpen: isConfigOpen, toggleModal: toggleConfigModal } = useModal(false);
48
48
 
49
- const animateLayoutChanges: AnimateLayoutChanges = ({ isSorting, wasDragging }) =>
50
- isSorting || wasDragging ? false : true;
49
+ const animateLayoutChanges: AnimateLayoutChanges = ({ isSorting, wasDragging }) => !(isSorting || wasDragging);
51
50
 
52
51
  const { attributes, isDragging, listeners, setDraggableNodeRef, setDroppableNodeRef, transform, transition } =
53
52
  useSortable({
@@ -77,14 +76,14 @@ const Item = (props: IItemProps): JSX.Element => {
77
76
  resetValues();
78
77
  setItem(item);
79
78
  setIsOpenedSecond(false);
80
- toggleModal();
79
+ toggleModal("sidePanel");
81
80
  }
82
81
  };
83
82
 
84
83
  const openConfigModal = () => {
85
84
  resetValues();
86
85
  setItem(item);
87
- toggleConfigModal();
86
+ toggleModal("config");
88
87
  };
89
88
 
90
89
  const isGroupingElement = item.config !== null && item.config.type === "group";
@@ -136,18 +135,18 @@ const Item = (props: IItemProps): JSX.Element => {
136
135
  {isAllowedToMangageMenus && <S.StyledActionMenu options={actionMenuOptions} icon="more" />}
137
136
  </S.FlexWrapper>
138
137
  </S.Component>
139
- {isOpen && (
138
+ {isOpen("sidePanel") && (
140
139
  <SidePanel
141
- isOpen={isOpen}
140
+ isOpen={isOpen("sidePanel")}
142
141
  isOpenedSecond={isOpenedSecond}
143
- toggleModal={toggleModal}
142
+ toggleModal={() => toggleModal("sidePanel")}
144
143
  toggleSecondaryPanel={toggleSecondaryPanel}
145
144
  edit={true}
146
145
  />
147
146
  )}
148
- {isConfigOpen && <ConfigPanel isOpen={isConfigOpen} toggleModal={toggleConfigModal} />}
147
+ {isOpen("config") && <ConfigPanel isOpen={isOpen("config")} toggleModal={() => toggleModal("config")} />}
149
148
  </S.Container>
150
- <RemoveModal isOpen={isRemoveOpen} toggleModal={toggleRemoveModal} deleteItem={deleteItem} item={item} />
149
+ <RemoveModal isOpen={isOpen("remove")} toggleModal={() => toggleModal("remove")} deleteItem={deleteItem} item={item} />
151
150
  </>
152
151
  );
153
152
  };
@@ -1,16 +1,23 @@
1
- import React, { useMemo, useState } from "react";
1
+ import { useMemo, useState } from "react";
2
2
  import { connect } from "react-redux";
3
+
4
+ import { ErrorToast, Loading } from "@ax/components";
5
+ import { appActions } from "@ax/containers/App";
6
+ import { menuActions } from "@ax/containers/Navigation";
7
+ import { RouteLeavingGuard } from "@ax/guards";
8
+ import type { IMenuItem, IRootState } from "@ax/types";
9
+
3
10
  import {
4
11
  closestCenter,
5
12
  DndContext,
6
- DragEndEvent,
7
- DragMoveEvent,
8
- DragOverEvent,
9
- DragStartEvent,
13
+ type DragEndEvent,
14
+ type DragMoveEvent,
15
+ type DragOverEvent,
16
+ type DragStartEvent,
10
17
  KeyboardSensor,
11
18
  MeasuringStrategy,
12
19
  PointerSensor,
13
- UniqueIdentifier,
20
+ type UniqueIdentifier,
14
21
  useSensor,
15
22
  useSensors,
16
23
  } from "@dnd-kit/core";
@@ -21,15 +28,10 @@ import {
21
28
  verticalListSortingStrategy,
22
29
  } from "@dnd-kit/sortable";
23
30
 
24
- import { menuActions } from "@ax/containers/Navigation";
25
- import { appActions } from "@ax/containers/App";
26
- import { Loading, ErrorToast } from "@ax/components";
27
- import { RouteLeavingGuard } from "@ax/guards";
28
- import { IMenuItem, IRootState } from "@ax/types";
29
- import { buildTree, FlattenedItem, flattenTree, getProjection, removeChildrenOf, setProperty } from "./helpers";
30
-
31
31
  import Header from "./Header";
32
+ import { buildTree, type FlattenedItem, flattenTree, getProjection, removeChildrenOf, setProperty } from "./helpers";
32
33
  import Item from "./Item";
34
+
33
35
  import * as S from "./style";
34
36
 
35
37
  const ItemList = (props: IItemList): JSX.Element => {
@@ -53,7 +53,7 @@ const List = (props: IMenuList): JSX.Element => {
53
53
  };
54
54
 
55
55
  const mapStateToProps = (state: IRootState) => ({
56
- currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
56
+ currentSiteID: state.sites.currentSiteInfo?.id || null,
57
57
  lang: state.app.lang,
58
58
  editorMenu: state.menu.editorMenu?.elements || [],
59
59
  savedMenu: state.menu.savedMenu?.elements || [],
@@ -6,15 +6,7 @@ import { Modal, FieldsBehavior } from "@ax/components";
6
6
  import * as S from "./style";
7
7
 
8
8
  const DeleteModal = (props: IDeleteModal): JSX.Element => {
9
- const {
10
- isOpen,
11
- toggleModal,
12
- mainModalAction,
13
- secondaryModalAction,
14
- isTranslated,
15
- deleteAllVersions,
16
- setDeleteAllVersions,
17
- } = props;
9
+ const { isOpen, toggleModal, isTranslated, deleteAllVersions, setDeleteAllVersions, onDelete, isDeleting } = props;
18
10
 
19
11
  const options = [
20
12
  {
@@ -29,14 +21,23 @@ const DeleteModal = (props: IDeleteModal): JSX.Element => {
29
21
  },
30
22
  ];
31
23
 
24
+ const mainAction = {
25
+ title: isDeleting ? "Deleting" : "Delete page",
26
+ onClick: onDelete,
27
+ disabled: isDeleting,
28
+ };
29
+
30
+ const secondaryAction = { title: "Cancel", onClick: toggleModal };
31
+
32
32
  return (
33
33
  <Modal
34
34
  isOpen={isOpen}
35
35
  hide={toggleModal}
36
36
  title="Delete Page?"
37
- secondaryAction={secondaryModalAction}
38
- mainAction={mainModalAction}
37
+ secondaryAction={secondaryAction}
38
+ mainAction={mainAction}
39
39
  size="S"
40
+ height="auto"
40
41
  >
41
42
  {isTranslated ? (
42
43
  <>
@@ -69,6 +70,8 @@ interface IDeleteModal extends IModal {
69
70
  isTranslated: boolean;
70
71
  deleteAllVersions: boolean;
71
72
  setDeleteAllVersions: React.Dispatch<React.SetStateAction<boolean>>;
73
+ onDelete: () => void;
74
+ isDeleting?: boolean;
72
75
  }
73
76
 
74
77
  export { DeleteModal };
@@ -196,12 +196,14 @@ const PageEditor = (props: IProps) => {
196
196
  const { deletePage, deleteBulk } = props;
197
197
  const path = "/sites/pages";
198
198
 
199
- const allPageVersions = pageLanguages.map((lang: IPageLanguage) => lang.pageId);
200
- const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage();
201
-
202
- toggleModal("delete");
203
- if (isDeleted) {
204
- setRoute(path);
199
+ try {
200
+ const allPageVersions = pageLanguages.map((lang: IPageLanguage) => lang.pageId);
201
+ const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage();
202
+ if (isDeleted) {
203
+ setRoute(path);
204
+ }
205
+ } finally {
206
+ toggleModal("delete");
205
207
  }
206
208
  };
207
209
 
@@ -401,7 +403,7 @@ const PageEditor = (props: IProps) => {
401
403
 
402
404
  if (!isDraft && isAllowedToDelete) {
403
405
  menuOptions.push({
404
- label: "Delete page",
406
+ label: "Delete",
405
407
  icon: "delete",
406
408
  action: () => toggleModal("delete"),
407
409
  });
@@ -564,13 +566,6 @@ const PageEditor = (props: IProps) => {
564
566
 
565
567
  const mainUnpublishAction = { title: "Ok", onClick: () => toggleModal("unpublish") };
566
568
 
567
- const mainDeleteModalAction = {
568
- title: "Delete page",
569
- onClick: removePage,
570
- };
571
-
572
- const secondaryDeleteModalAction = { title: "Cancel", onClick: () => toggleModal("delete") };
573
-
574
569
  const mainScheduleModalAction = {
575
570
  title: "Schedule",
576
571
  onClick: handleSchedulePublication,
@@ -835,8 +830,8 @@ const PageEditor = (props: IProps) => {
835
830
  <DeleteModal
836
831
  isOpen={isOpen("delete")}
837
832
  toggleModal={() => toggleModal("delete")}
838
- mainModalAction={mainDeleteModalAction}
839
- secondaryModalAction={secondaryDeleteModalAction}
833
+ onDelete={removePage}
834
+ isDeleting={isSaving}
840
835
  {...{ isTranslated, deleteAllVersions, setDeleteAllVersions }}
841
836
  />
842
837
  <ScheduleModal
@@ -1,11 +1,14 @@
1
- import React, { useState } from "react";
1
+ import { useState } from "react";
2
2
  import { connect } from "react-redux";
3
- import { format } from "date-fns";
4
3
 
5
- import { useModal } from "@ax/hooks";
6
- import { ICheck, IRedirect } from "@ax/types";
7
- import { CheckField, ElementsTooltip, Modal } from "@ax/components";
4
+ import { CheckField, ElementsTooltip } from "@ax/components";
8
5
  import { redirectsActions } from "@ax/containers/Redirects";
6
+ import { useModals } from "@ax/hooks";
7
+ import type { ICheck, IRedirect, IRootState } from "@ax/types";
8
+
9
+ import { format } from "date-fns";
10
+
11
+ import { DeleteModal } from "../atoms";
9
12
  import RedirectPanel from "../RedirectPanel";
10
13
 
11
14
  import * as S from "./style";
@@ -23,11 +26,11 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
23
26
  currentFilter,
24
27
  isSiteItem,
25
28
  hoverCheck,
29
+ isSaving,
26
30
  } = props;
27
31
 
28
- const { isOpen, toggleModal } = useModal();
32
+ const { isOpen, toggleModal } = useModals(["edit", "delete"]);
29
33
  const [isOpenedSecond, setIsOpenedSecond] = useState(false);
30
- const { isOpen: isOpenDelete, toggleModal: toggleModalDelete } = useModal();
31
34
 
32
35
  const toggleSecondaryPanel = () => setIsOpenedSecond(!isOpenedSecond);
33
36
 
@@ -35,17 +38,21 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
35
38
  const mappedRedirect = { ...redirect, to: { ...redirect.to, linkTo: redirect.to.pageId, href: redirect.to.url } };
36
39
  setFormValues(mappedRedirect);
37
40
  setIsOpenedSecond(false);
38
- toggleModal();
41
+ toggleModal("edit");
39
42
  };
40
43
 
41
44
  const handleOnChange = (value: ICheck) => onChange(value);
42
45
 
43
46
  const removeItem = async () => {
44
- if (redirect.id) {
45
- const deleted = await deleteRedirect(redirect.id, currentFilter);
46
- if (deleted) {
47
- toggleToast();
47
+ try {
48
+ if (redirect.id) {
49
+ const deleted = await deleteRedirect(redirect.id, currentFilter);
50
+ if (deleted) {
51
+ toggleToast();
52
+ }
48
53
  }
54
+ } finally {
55
+ toggleModal("delete");
49
56
  }
50
57
  };
51
58
 
@@ -53,16 +60,10 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
53
60
  {
54
61
  label: "delete",
55
62
  icon: "delete",
56
- action: toggleModalDelete,
63
+ action: () => toggleModal("delete"),
57
64
  },
58
65
  ];
59
66
 
60
- const mainDeleteModalAction = {
61
- title: "Delete redirect",
62
- onClick: removeItem,
63
- };
64
-
65
- const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleModalDelete };
66
67
  const target =
67
68
  redirect.site?.siteUrl === "/"
68
69
  ? `(${redirect.domain || ""})`
@@ -94,9 +95,7 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
94
95
  </S.CheckCell>
95
96
  {!isSiteItem && (
96
97
  <S.SiteCell role="cell" onClick={handleClick}>
97
- {redirect.site && redirect.site.siteName && (
98
- <ElementsTooltip elements={[redirect.site.siteName]} maxChar={20} />
99
- )}
98
+ {redirect.site?.siteName && <ElementsTooltip elements={[redirect.site.siteName]} maxChar={20} />}
100
99
  </S.SiteCell>
101
100
  )}
102
101
  <S.UrlCell role="cell" onClick={handleClick}>
@@ -112,11 +111,11 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
112
111
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
113
112
  </S.ActionsCell>
114
113
  </S.ItemRow>
115
- {isOpen && (
114
+ {isOpen("edit") && (
116
115
  <RedirectPanel
117
- isOpen={isOpen}
116
+ isOpen={isOpen("edit")}
118
117
  isOpenedSecond={isOpenedSecond}
119
- toggleModal={toggleModal}
118
+ toggleModal={() => toggleModal("edit")}
120
119
  toggleSecondaryPanel={toggleSecondaryPanel}
121
120
  redirect={redirect}
122
121
  setFormValues={setFormValues}
@@ -125,19 +124,13 @@ const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
125
124
  currentFilter={currentFilter}
126
125
  />
127
126
  )}
128
- <Modal
129
- isOpen={isOpenDelete}
130
- hide={toggleModalDelete}
131
- title="Delete Redirect"
132
- secondaryAction={secondaryDeleteModalAction}
133
- mainAction={mainDeleteModalAction}
134
- size="S"
135
- >
136
- <S.ModalContent>
137
- Are you sure you want to delete <strong>{redirect.from} redirect</strong>? This action{" "}
138
- <strong>cannot be undone</strong>.
139
- </S.ModalContent>
140
- </Modal>
127
+ <DeleteModal
128
+ isOpen={isOpen("delete")}
129
+ toggleModal={() => toggleModal("delete")}
130
+ redirectFrom={redirect.from}
131
+ onDelete={removeItem}
132
+ isDeleting={isSaving}
133
+ />
141
134
  </>
142
135
  );
143
136
  };
@@ -153,6 +146,7 @@ interface IProps {
153
146
  currentFilter: string;
154
147
  isSiteItem: boolean;
155
148
  hoverCheck: boolean;
149
+ isSaving: boolean;
156
150
  }
157
151
 
158
152
  interface IDispatchProps {
@@ -161,8 +155,12 @@ interface IDispatchProps {
161
155
 
162
156
  type IRedirectItemProps = IProps & IDispatchProps;
163
157
 
158
+ const mapStateToProps = (state: IRootState) => ({
159
+ isSaving: state.app.isSaving,
160
+ });
161
+
164
162
  const mapDispatchToProps = {
165
163
  deleteRedirect: redirectsActions.deleteRedirect,
166
164
  };
167
165
 
168
- export default connect(null, mapDispatchToProps)(RedirectItem);
166
+ export default connect(mapStateToProps, mapDispatchToProps)(RedirectItem);
@@ -1,32 +1,63 @@
1
- import React, { useRef } from "react";
1
+ import type React from "react";
2
+ import { useRef } from "react";
2
3
 
3
- import { IModal, IRedirect } from "@ax/types";
4
4
  import { Button, Icon, Modal } from "@ax/components";
5
+ import type { IModal, IRedirect } from "@ax/types";
5
6
 
6
7
  import * as S from "./style";
7
8
 
8
- const DeleteModal = (props: IModal): JSX.Element => {
9
- const { isOpen, toggleModal, mainModalAction, secondaryModalAction } = props;
9
+ const DeleteModal = (props: IDeleteModalProps): JSX.Element => {
10
+ const { isOpen, toggleModal, onDelete, isDeleting = false, redirectFrom } = props;
11
+ const isSingle = !!redirectFrom;
12
+
13
+ const mainModalAction = {
14
+ title: isDeleting ? "Deleting" : "Delete",
15
+ onClick: onDelete,
16
+ disabled: isDeleting,
17
+ };
18
+
19
+ const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
10
20
 
11
21
  return (
12
22
  <Modal
13
23
  isOpen={isOpen}
14
24
  hide={toggleModal}
15
- title="Delete Redirects"
25
+ title={isSingle ? "Delete Redirect" : "Delete Redirects"}
16
26
  secondaryAction={secondaryModalAction}
17
27
  mainAction={mainModalAction}
18
28
  size="S"
29
+ height="auto"
19
30
  >
20
31
  <S.ModalContent>
21
- Are you sure you want to delete the selected <strong>redirects</strong>? This action{" "}
22
- <strong>cannot be undone</strong>.
32
+ {isSingle ? (
33
+ <>
34
+ Are you sure you want to delete <strong>{redirectFrom} redirect</strong>? This action{" "}
35
+ <strong>cannot be undone</strong>.
36
+ </>
37
+ ) : (
38
+ <>
39
+ Are you sure you want to delete the selected <strong>redirects</strong>? This action{" "}
40
+ <strong>cannot be undone</strong>.
41
+ </>
42
+ )}
23
43
  </S.ModalContent>
24
44
  </Modal>
25
45
  );
26
46
  };
27
47
 
28
- const OverwriteModal = (props: IModal): JSX.Element => {
29
- const { isOpen, toggleModal, mainModalAction, secondaryModalAction } = props;
48
+ interface IOverwriteModalProps extends IModal {
49
+ onOverwrite(): void;
50
+ }
51
+
52
+ const OverwriteModal = (props: IOverwriteModalProps): JSX.Element => {
53
+ const { isOpen, toggleModal, onOverwrite } = props;
54
+
55
+ const mainModalAction = {
56
+ title: "Overwrite redirect",
57
+ onClick: onOverwrite,
58
+ };
59
+
60
+ const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
30
61
 
31
62
  return (
32
63
  <Modal
@@ -36,6 +67,7 @@ const OverwriteModal = (props: IModal): JSX.Element => {
36
67
  secondaryAction={secondaryModalAction}
37
68
  mainAction={mainModalAction}
38
69
  size="S"
70
+ height="auto"
39
71
  >
40
72
  <S.ModalContent>
41
73
  This Redirect is already created. It will overwrite.
@@ -51,7 +83,7 @@ const ImportModal = (props: IImportModal): JSX.Element => {
51
83
 
52
84
  const fileInputRef = useRef<HTMLInputElement>(null);
53
85
 
54
- const handleUploadClick = () => fileInputRef.current && fileInputRef.current.click();
86
+ const handleUploadClick = () => fileInputRef.current?.click();
55
87
 
56
88
  const csvToArray = (str: string, delimiter = ";") => {
57
89
  const fixedStr = str.replace(/,/g, ";").replace(/\r/g, "");
@@ -114,7 +146,7 @@ const ImportModal = (props: IImportModal): JSX.Element => {
114
146
  />
115
147
  <Button className="button" type="button" buttonStyle="line">
116
148
  <a
117
- href={process.env.PUBLIC_URL + "/templates/template-redirects.csv"}
149
+ href={`${process.env.PUBLIC_URL}/templates/template-redirects.csv`}
118
150
  download={"template-redirects.csv"}
119
151
  >
120
152
  Download Template
@@ -132,7 +164,14 @@ const ImportModal = (props: IImportModal): JSX.Element => {
132
164
  };
133
165
 
134
166
  const ImportCheckModal = (props: IImportCheckModal): JSX.Element => {
135
- const { isOpen, toggleModal, mainModalAction, secondaryModalAction, imports, totalImports } = props;
167
+ const { isOpen, toggleModal, onImport, imports, totalImports } = props;
168
+
169
+ const mainModalAction = {
170
+ title: "Import correct directs",
171
+ onClick: onImport,
172
+ };
173
+
174
+ const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
136
175
 
137
176
  const mapModalItems = (items: IRedirect[], icon: string, type: "online" | "error" | "info") => {
138
177
  return items.map((item: IRedirect) => (
@@ -206,6 +245,13 @@ interface IImportCheckModal extends IModal {
206
245
  existing: IRedirect[];
207
246
  ok: IRedirect[];
208
247
  };
248
+ onImport(): void;
249
+ }
250
+
251
+ interface IDeleteModalProps extends IModal {
252
+ onDelete(): void;
253
+ isDeleting?: boolean;
254
+ redirectFrom?: string;
209
255
  }
210
256
 
211
257
  export { DeleteModal, ImportModal, OverwriteModal, ImportCheckModal };