@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.
- package/package.json +2 -2
- package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.atoms.test.tsx +409 -0
- package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.helpers.test.tsx +418 -0
- package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.test.tsx +776 -29
- package/src/__tests__/components/FieldsBehavior/FieldsBehavior.test.tsx +368 -11
- package/src/__tests__/modules/Users/UserList/UserList.test.tsx +6 -6
- package/src/components/Fields/IntegrationsField/IntegrationItem/atoms.tsx +14 -5
- package/src/components/Fields/IntegrationsField/IntegrationItem/index.tsx +1 -8
- package/src/components/Fields/UrlField/index.tsx +5 -4
- package/src/components/Fields/Wysiwyg/atoms.tsx +140 -0
- package/src/components/Fields/Wysiwyg/config.tsx +190 -9
- package/src/components/Fields/Wysiwyg/helpers.tsx +54 -1
- package/src/components/Fields/Wysiwyg/index.tsx +210 -61
- package/src/components/Fields/Wysiwyg/style.tsx +32 -1
- package/src/components/Fields/Wysiwyg/vendors.tsx +0 -1
- package/src/components/FieldsBehavior/index.tsx +66 -31
- package/src/components/Icon/components/Sync.js +16 -0
- package/src/components/Icon/svgs/Sync.svg +3 -0
- package/src/components/RestoreModal/index.tsx +1 -3
- package/src/components/ScheduleModal/index.tsx +3 -3
- package/src/components/TableList/index.tsx +5 -3
- package/src/containers/FileDrive/actions.tsx +5 -5
- package/src/containers/Forms/actions.tsx +40 -38
- package/src/containers/Gallery/actions.tsx +27 -27
- package/src/containers/Integrations/actions.tsx +2 -2
- package/src/containers/Navigation/Defaults/actions.tsx +1 -1
- package/src/containers/PageEditor/actions.tsx +3 -5
- package/src/containers/Redirects/actions.tsx +2 -2
- package/src/containers/Sites/actions.tsx +15 -8
- package/src/containers/StructuredData/actions.tsx +5 -5
- package/src/containers/Users/actions.tsx +2 -2
- package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +36 -43
- package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +15 -11
- package/src/modules/Categories/CategoriesList/atoms.tsx +42 -12
- package/src/modules/Categories/CategoriesList/index.tsx +8 -30
- package/src/modules/Content/PageItem/index.tsx +6 -5
- package/src/modules/Content/atoms.tsx +7 -3
- package/src/modules/Content/index.tsx +8 -16
- package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +14 -14
- package/src/modules/FileDrive/FolderItem/index.tsx +46 -54
- package/src/modules/FileDrive/GridItem/index.tsx +32 -37
- package/src/modules/FileDrive/ListItem/index.tsx +31 -37
- package/src/modules/FileDrive/atoms.tsx +59 -12
- package/src/modules/FileDrive/index.tsx +88 -98
- package/src/modules/Forms/FormCategoriesList/CategoryItem/index.tsx +42 -34
- package/src/modules/Forms/FormCategoriesList/atoms.tsx +17 -6
- package/src/modules/Forms/FormCategoriesList/index.tsx +30 -34
- package/src/modules/Forms/FormEditor/index.tsx +14 -6
- package/src/modules/Forms/FormList/FormItem/index.tsx +5 -1
- package/src/modules/Forms/FormList/index.tsx +15 -9
- package/src/modules/Forms/atoms.tsx +7 -4
- package/src/modules/GlobalEditor/atoms.tsx +77 -0
- package/src/modules/GlobalEditor/index.tsx +24 -7
- package/src/modules/MediaGallery/FolderItem/index.tsx +36 -52
- package/src/modules/MediaGallery/GridItem/index.tsx +27 -38
- package/src/modules/MediaGallery/ImageModal/DetailPanel/index.tsx +13 -13
- package/src/modules/MediaGallery/ImageModal/index.tsx +2 -16
- package/src/modules/MediaGallery/ListItem/index.tsx +25 -37
- package/src/modules/MediaGallery/atoms.tsx +84 -15
- package/src/modules/MediaGallery/index.tsx +62 -122
- package/src/modules/Navigation/Defaults/Item/atoms.tsx +2 -4
- package/src/modules/Navigation/Defaults/Item/index.tsx +80 -94
- package/src/modules/Navigation/Defaults/atoms.tsx +179 -7
- package/src/modules/Navigation/Defaults/index.tsx +51 -18
- package/src/modules/Navigation/Defaults/style.tsx +10 -7
- package/src/modules/Navigation/Menus/List/Table/Item/atoms.tsx +33 -19
- package/src/modules/Navigation/Menus/List/Table/Item/index.tsx +18 -19
- package/src/modules/Navigation/Menus/List/Table/index.tsx +15 -13
- package/src/modules/Navigation/Menus/List/index.tsx +1 -1
- package/src/modules/PageEditor/atoms.tsx +14 -11
- package/src/modules/PageEditor/index.tsx +11 -16
- package/src/modules/Redirects/RedirectItem/index.tsx +37 -39
- package/src/modules/Redirects/atoms.tsx +58 -12
- package/src/modules/Redirects/index.tsx +30 -58
- package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/index.tsx +1 -1
- package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +57 -69
- package/src/modules/Settings/Integrations/atoms.tsx +72 -8
- package/src/modules/Settings/Integrations/index.tsx +34 -48
- package/src/modules/StructuredData/Form/index.tsx +25 -8
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/atoms.tsx +26 -75
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +15 -33
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +63 -41
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/style.tsx +13 -8
- package/src/modules/StructuredData/StructuredDataList/index.tsx +11 -16
- package/src/modules/StructuredData/{StructuredDataList/atoms.tsx → atoms.tsx} +25 -28
- package/src/modules/Users/UserList/UserItem/index.tsx +18 -35
- package/src/modules/Users/UserList/atoms.tsx +61 -0
- package/src/modules/Users/UserList/index.tsx +12 -32
|
@@ -3,8 +3,8 @@ import { connect } from "react-redux";
|
|
|
3
3
|
|
|
4
4
|
import { CheckField, Icon, TruncatedTooltip } from "@ax/components";
|
|
5
5
|
import { formsActions } from "@ax/containers/Forms";
|
|
6
|
-
import {
|
|
7
|
-
import type { FormCategory, ICheck } from "@ax/types";
|
|
6
|
+
import { useModals, usePermissions } from "@ax/hooks";
|
|
7
|
+
import type { FormCategory, ICheck, IRootState } from "@ax/types";
|
|
8
8
|
|
|
9
9
|
import { useSortable } from "@dnd-kit/sortable";
|
|
10
10
|
|
|
@@ -14,17 +14,29 @@ import CategoryPanel from "../CategoryPanel";
|
|
|
14
14
|
import * as S from "./style";
|
|
15
15
|
|
|
16
16
|
const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const {
|
|
18
|
+
category,
|
|
19
|
+
isSelected,
|
|
20
|
+
hoverCheck,
|
|
21
|
+
isDragging,
|
|
22
|
+
isSiteView,
|
|
23
|
+
isSaving,
|
|
24
|
+
deleteFormCategory,
|
|
25
|
+
onChange,
|
|
26
|
+
toggleToast,
|
|
27
|
+
} = props;
|
|
28
|
+
|
|
29
|
+
const { isOpen, toggleModal } = useModals(["edit", "delete"]);
|
|
30
|
+
|
|
31
|
+
const isAllowedTo = usePermissions({
|
|
32
|
+
editSiteCategory: "forms.editFormsCategories",
|
|
33
|
+
editGlobalCategory: "global.forms.editFormsCategories",
|
|
34
|
+
deleteSiteCategory: "forms.deleteFormsCategories",
|
|
35
|
+
deleteGlobalCategory: "global.forms.deleteFormsCategories",
|
|
36
|
+
});
|
|
21
37
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
? "forms.deleteFormsCategories"
|
|
25
|
-
: "global.forms.deleteFormsCategories";
|
|
26
|
-
const isAllowedToEditFormCategory = usePermission(editFormCategoryPermission);
|
|
27
|
-
const isAllowedToDeleteFormCategory = usePermission(deleteFormCategoryPermission);
|
|
38
|
+
const isAllowedToEditFormCategory = isSiteView ? isAllowedTo.editSiteCategory : isAllowedTo.editGlobalCategory;
|
|
39
|
+
const isAllowedToDeleteFormCategory = isSiteView ? isAllowedTo.deleteSiteCategory : isAllowedTo.deleteGlobalCategory;
|
|
28
40
|
|
|
29
41
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
|
|
30
42
|
id: category.id,
|
|
@@ -32,10 +44,10 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
|
|
|
32
44
|
|
|
33
45
|
const { content } = category;
|
|
34
46
|
|
|
35
|
-
const handleClick = () => !isDragging && isAllowedToEditFormCategory && toggleModal();
|
|
47
|
+
const handleClick = () => !isDragging && isAllowedToEditFormCategory && toggleModal("edit");
|
|
36
48
|
|
|
37
49
|
const handleCloseModal = () => {
|
|
38
|
-
toggleModal();
|
|
50
|
+
toggleModal("edit");
|
|
39
51
|
};
|
|
40
52
|
|
|
41
53
|
const handleOnChange = (value: ICheck) => onChange(value);
|
|
@@ -46,7 +58,7 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
|
|
|
46
58
|
const deleted = await deleteFormCategory(category.id, category.categoryType);
|
|
47
59
|
|
|
48
60
|
if (deleted) {
|
|
49
|
-
|
|
61
|
+
isOpen("delete") && toggleModal("delete");
|
|
50
62
|
toggleToast("1 form category deleted");
|
|
51
63
|
}
|
|
52
64
|
};
|
|
@@ -56,18 +68,11 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
|
|
|
56
68
|
{
|
|
57
69
|
label: "delete",
|
|
58
70
|
icon: "delete",
|
|
59
|
-
action:
|
|
71
|
+
action: () => toggleModal("delete"),
|
|
60
72
|
},
|
|
61
73
|
]
|
|
62
74
|
: [];
|
|
63
75
|
|
|
64
|
-
const mainDeleteModalAction = {
|
|
65
|
-
title: "delete",
|
|
66
|
-
onClick: removeCategory,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
70
|
-
|
|
71
76
|
return (
|
|
72
77
|
<>
|
|
73
78
|
<S.CategoryRow
|
|
@@ -101,23 +106,21 @@ const CategoryItem = (props: ICategoryItemProps): JSX.Element => {
|
|
|
101
106
|
<S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
|
|
102
107
|
</S.ActionsCell>
|
|
103
108
|
</S.CategoryRow>
|
|
104
|
-
{isOpen && (
|
|
109
|
+
{isOpen("edit") && (
|
|
105
110
|
<CategoryPanel
|
|
106
|
-
isOpen={isOpen}
|
|
111
|
+
isOpen={isOpen("edit")}
|
|
107
112
|
toggleModal={handleCloseModal}
|
|
108
113
|
item={category}
|
|
109
114
|
toggleToast={toggleToast}
|
|
110
115
|
type={category.categoryType}
|
|
111
116
|
/>
|
|
112
117
|
)}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/>
|
|
120
|
-
)}
|
|
118
|
+
<DeleteModal
|
|
119
|
+
isOpen={isOpen("delete")}
|
|
120
|
+
toggleModal={() => toggleModal("delete")}
|
|
121
|
+
onDelete={removeCategory}
|
|
122
|
+
isDeleting={isSaving}
|
|
123
|
+
/>
|
|
121
124
|
</>
|
|
122
125
|
);
|
|
123
126
|
};
|
|
@@ -130,6 +133,7 @@ interface IProps {
|
|
|
130
133
|
hoverCheck?: boolean;
|
|
131
134
|
isDragging: boolean;
|
|
132
135
|
isSiteView: boolean;
|
|
136
|
+
isSaving: boolean;
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
interface IDispatchProps {
|
|
@@ -138,8 +142,12 @@ interface IDispatchProps {
|
|
|
138
142
|
|
|
139
143
|
type ICategoryItemProps = IProps & IDispatchProps;
|
|
140
144
|
|
|
145
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
146
|
+
isSaving: state.app.isSaving,
|
|
147
|
+
});
|
|
148
|
+
|
|
141
149
|
const mapDispatchToProps = {
|
|
142
150
|
deleteFormCategory: formsActions.deleteFormCategory,
|
|
143
151
|
};
|
|
144
152
|
|
|
145
|
-
export default connect(
|
|
153
|
+
export default connect(mapStateToProps, mapDispatchToProps)(CategoryItem);
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { IModal } from "@ax/types";
|
|
4
1
|
import { Modal } from "@ax/components";
|
|
2
|
+
import type { IModal } from "@ax/types";
|
|
5
3
|
|
|
6
4
|
import * as S from "./style";
|
|
7
5
|
|
|
8
|
-
const DeleteModal = (props:
|
|
9
|
-
const { isOpen, toggleModal,
|
|
6
|
+
const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
7
|
+
const { isOpen, toggleModal, onDelete, isDeleting } = props;
|
|
8
|
+
|
|
9
|
+
const mainModalAction = {
|
|
10
|
+
title: isDeleting ? "Deleting" : "delete",
|
|
11
|
+
onClick: onDelete,
|
|
12
|
+
disabled: isDeleting,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
|
|
10
16
|
|
|
11
17
|
return (
|
|
12
18
|
<Modal
|
|
@@ -16,7 +22,7 @@ const DeleteModal = (props: IModal): JSX.Element => {
|
|
|
16
22
|
secondaryAction={secondaryModalAction}
|
|
17
23
|
mainAction={mainModalAction}
|
|
18
24
|
size="S"
|
|
19
|
-
height=
|
|
25
|
+
height="auto"
|
|
20
26
|
>
|
|
21
27
|
<S.ModalContent>
|
|
22
28
|
<p>
|
|
@@ -30,4 +36,9 @@ const DeleteModal = (props: IModal): JSX.Element => {
|
|
|
30
36
|
);
|
|
31
37
|
};
|
|
32
38
|
|
|
39
|
+
interface IDeleteModal extends IModal {
|
|
40
|
+
onDelete: () => void;
|
|
41
|
+
isDeleting?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
export { DeleteModal };
|
|
@@ -5,7 +5,7 @@ import { useParams } from "react-router-dom";
|
|
|
5
5
|
import { EmptyState, ErrorToast, MainWrapper, SearchTagsBar, TableList, Toast } from "@ax/components";
|
|
6
6
|
import { formsActions } from "@ax/containers/Forms";
|
|
7
7
|
import { getSchemaFormCategories } from "@ax/helpers";
|
|
8
|
-
import { useBulkSelection,
|
|
8
|
+
import { useBulkSelection, useModals, usePermissions, useToast } from "@ax/hooks";
|
|
9
9
|
import type { FormCategoriesOrderParams, FormCategory, IRootState } from "@ax/types";
|
|
10
10
|
|
|
11
11
|
import {
|
|
@@ -29,7 +29,7 @@ import CategoryPanel from "./CategoryPanel";
|
|
|
29
29
|
import * as S from "./style";
|
|
30
30
|
|
|
31
31
|
const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
32
|
-
const { categories, currentSiteID, getFormCategories, deleteFormCategory, orderFormCategory } = props;
|
|
32
|
+
const { categories, currentSiteID, isSaving, getFormCategories, deleteFormCategory, orderFormCategory } = props;
|
|
33
33
|
|
|
34
34
|
const schemaCategories = getSchemaFormCategories();
|
|
35
35
|
const { cat: urlCategory } = useParams<{ cat: string }>();
|
|
@@ -42,23 +42,22 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
42
42
|
const isSiteView = !!currentSiteID;
|
|
43
43
|
|
|
44
44
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
45
|
-
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
46
45
|
const [draggingId, setDraggingId] = useState<number | null>(null);
|
|
47
46
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
48
47
|
const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
|
|
49
|
-
const { isOpen, toggleModal } =
|
|
50
|
-
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
48
|
+
const { isOpen, toggleModal } = useModals(["panel", "delete"]);
|
|
51
49
|
const tableRef = useRef<HTMLDivElement>(null);
|
|
52
50
|
const isSearching = searchQuery.length > 0;
|
|
53
51
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
: "global.forms.createFormsCategories"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
52
|
+
const isAllowedTo = usePermissions({
|
|
53
|
+
createSiteCategory: "forms.createFormsCategories",
|
|
54
|
+
createGlobalCategory: "global.forms.createFormsCategories",
|
|
55
|
+
deleteSiteCategory: "forms.deleteFormsCategories",
|
|
56
|
+
deleteGlobalCategory: "global.forms.deleteFormsCategories",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const isAllowedToCreateFormCategory = isSiteView ? isAllowedTo.createSiteCategory : isAllowedTo.createGlobalCategory;
|
|
60
|
+
const isAllowedToDeleteFormCategory = isSiteView ? isAllowedTo.deleteSiteCategory : isAllowedTo.deleteGlobalCategory;
|
|
62
61
|
|
|
63
62
|
const sensors = useSensors(
|
|
64
63
|
useSensor(PointerSensor, {
|
|
@@ -97,19 +96,17 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
97
96
|
const rightButtonProps = isAllowedToCreateFormCategory
|
|
98
97
|
? {
|
|
99
98
|
label: "New",
|
|
100
|
-
action: toggleModal,
|
|
99
|
+
action: () => toggleModal("panel"),
|
|
101
100
|
}
|
|
102
101
|
: undefined;
|
|
103
102
|
|
|
104
103
|
const bulkDelete = async () => {
|
|
105
|
-
setIsBulkLoading(true);
|
|
106
104
|
const deleted = await deleteFormCategory(selectedItems.all, category);
|
|
107
105
|
if (deleted) {
|
|
108
106
|
resetBulkSelection();
|
|
109
107
|
toggleToast(`${selectedItems.all.length} categor${selectedItems.all.length > 1 ? "ies" : "y"} deleted`);
|
|
110
|
-
|
|
108
|
+
toggleModal("delete");
|
|
111
109
|
}
|
|
112
|
-
setIsBulkLoading(false);
|
|
113
110
|
};
|
|
114
111
|
|
|
115
112
|
const selectItems = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());
|
|
@@ -126,7 +123,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
126
123
|
{
|
|
127
124
|
icon: "delete",
|
|
128
125
|
text: "delete",
|
|
129
|
-
action:
|
|
126
|
+
action: () => toggleModal("delete"),
|
|
130
127
|
},
|
|
131
128
|
]
|
|
132
129
|
: [];
|
|
@@ -141,7 +138,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
141
138
|
isScrolling={isScrolling}
|
|
142
139
|
bulkActions={bulkActions}
|
|
143
140
|
setHoverCheck={setHoverCheck}
|
|
144
|
-
isLoading={
|
|
141
|
+
isLoading={isSaving}
|
|
145
142
|
/>
|
|
146
143
|
);
|
|
147
144
|
|
|
@@ -178,7 +175,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
178
175
|
? "To start using categories in your forms, create as many categories as you need."
|
|
179
176
|
: "",
|
|
180
177
|
button: isAllowedToCreateFormCategory ? "New Category" : "",
|
|
181
|
-
action: toggleModal,
|
|
178
|
+
action: () => toggleModal("panel"),
|
|
182
179
|
};
|
|
183
180
|
|
|
184
181
|
const emptySearchStateProps = {
|
|
@@ -187,14 +184,6 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
187
184
|
message: "We couldn’t find what you are looking for. Please, try another search.",
|
|
188
185
|
};
|
|
189
186
|
|
|
190
|
-
const mainDeleteModalAction = {
|
|
191
|
-
title: isBulkLoading ? "Deleting" : "delete",
|
|
192
|
-
onClick: bulkDelete,
|
|
193
|
-
disabled: isBulkLoading,
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
197
|
-
|
|
198
187
|
return (
|
|
199
188
|
<MainWrapper title="Forms" rightButton={rightButtonProps} searchAction={setSearchQuery} searchValue={searchQuery}>
|
|
200
189
|
<S.CategoryListWrapper>
|
|
@@ -252,13 +241,18 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
252
241
|
</TableList>
|
|
253
242
|
</S.TableWrapper>
|
|
254
243
|
</S.CategoryListWrapper>
|
|
255
|
-
<CategoryPanel
|
|
256
|
-
|
|
244
|
+
<CategoryPanel
|
|
245
|
+
isOpen={isOpen("panel")}
|
|
246
|
+
toggleModal={() => toggleModal("panel")}
|
|
247
|
+
toggleToast={toggleToast}
|
|
248
|
+
type={category}
|
|
249
|
+
/>
|
|
250
|
+
{isOpen("delete") && (
|
|
257
251
|
<DeleteModal
|
|
258
|
-
isOpen={
|
|
259
|
-
toggleModal={
|
|
260
|
-
|
|
261
|
-
|
|
252
|
+
isOpen={isOpen("delete")}
|
|
253
|
+
toggleModal={() => toggleModal("delete")}
|
|
254
|
+
onDelete={bulkDelete}
|
|
255
|
+
isDeleting={isSaving}
|
|
262
256
|
/>
|
|
263
257
|
)}
|
|
264
258
|
{isVisible && <Toast {...toastProps} />}
|
|
@@ -268,6 +262,7 @@ const FormCategoriesList = (props: IProps): JSX.Element => {
|
|
|
268
262
|
|
|
269
263
|
const mapStateToProps = (state: IRootState) => ({
|
|
270
264
|
categories: state.forms.currentFormCategories,
|
|
265
|
+
isSaving: state.app.isSaving,
|
|
271
266
|
// biome-ignore lint/complexity/useOptionalChain: TODO: fix this
|
|
272
267
|
currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
|
|
273
268
|
});
|
|
@@ -281,6 +276,7 @@ interface IDispatchProps {
|
|
|
281
276
|
interface ICategoriesProps {
|
|
282
277
|
categories: FormCategory[];
|
|
283
278
|
currentSiteID: number | null;
|
|
279
|
+
isSaving: boolean;
|
|
284
280
|
}
|
|
285
281
|
|
|
286
282
|
type IProps = ICategoriesProps & IDispatchProps;
|
|
@@ -155,10 +155,13 @@ const FormEditor = (props: IProps) => {
|
|
|
155
155
|
onClick: () => toggleModal("use"),
|
|
156
156
|
});
|
|
157
157
|
} else {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
try {
|
|
159
|
+
const allFormVersions = dataLanguages.map((lang: FormLanguage) => lang.id);
|
|
160
|
+
const isDeleted = deleteAllVersions ? await deleteForm(allFormVersions) : await deleteForm(id);
|
|
161
|
+
if (isDeleted) {
|
|
162
|
+
setHistoryPush(backLinkRoute, false);
|
|
163
|
+
}
|
|
164
|
+
} finally {
|
|
162
165
|
toggleModal("delete");
|
|
163
166
|
}
|
|
164
167
|
}
|
|
@@ -258,7 +261,6 @@ const FormEditor = (props: IProps) => {
|
|
|
258
261
|
action: () => (formInUse ? toggleModal("update") : handleSavePage()),
|
|
259
262
|
};
|
|
260
263
|
|
|
261
|
-
|
|
262
264
|
return isLoading ? (
|
|
263
265
|
<Loading />
|
|
264
266
|
) : (
|
|
@@ -317,6 +319,7 @@ const FormEditor = (props: IProps) => {
|
|
|
317
319
|
isOpen={isOpen("delete")}
|
|
318
320
|
toggleModal={() => toggleModal("delete")}
|
|
319
321
|
onDelete={removeItem}
|
|
322
|
+
isDeleting={isSaving}
|
|
320
323
|
{...{ title, isTranslated, deleteAllVersions, setDeleteAllVersions }}
|
|
321
324
|
/>
|
|
322
325
|
<UnPublishModal
|
|
@@ -324,9 +327,14 @@ const FormEditor = (props: IProps) => {
|
|
|
324
327
|
toggleModal={() => toggleModal("unpublish")}
|
|
325
328
|
onUnpublish={unpublishForm}
|
|
326
329
|
title={title}
|
|
330
|
+
isUnpublishing={isSaving}
|
|
327
331
|
/>
|
|
328
332
|
{isOpen("update") && (
|
|
329
|
-
<UpdateModal
|
|
333
|
+
<UpdateModal
|
|
334
|
+
isOpen={isOpen("update")}
|
|
335
|
+
toggleModal={() => toggleModal("update")}
|
|
336
|
+
onUpdate={() => handleSavePage()}
|
|
337
|
+
/>
|
|
330
338
|
)}
|
|
331
339
|
{isOpen("use") && (
|
|
332
340
|
<FormUseModal
|
|
@@ -44,6 +44,7 @@ const FormItem = (props: IFormItemProps): JSX.Element => {
|
|
|
44
44
|
currentSiteInfo,
|
|
45
45
|
hoverCheck,
|
|
46
46
|
skipReviewOnPublish,
|
|
47
|
+
isSaving,
|
|
47
48
|
addCategoryColors,
|
|
48
49
|
onChange,
|
|
49
50
|
onClick,
|
|
@@ -288,13 +289,14 @@ const FormItem = (props: IFormItemProps): JSX.Element => {
|
|
|
288
289
|
isOpen={isOpen("delete")}
|
|
289
290
|
toggleModal={() => toggleModal("delete")}
|
|
290
291
|
onDelete={removeItem}
|
|
291
|
-
{...{ title, isTranslated, deleteAllVersions, setDeleteAllVersions }}
|
|
292
|
+
{...{ title, isTranslated, deleteAllVersions, setDeleteAllVersions, isDeleting: isSaving }}
|
|
292
293
|
/>
|
|
293
294
|
<UnPublishModal
|
|
294
295
|
isOpen={isOpen("unpublish")}
|
|
295
296
|
toggleModal={() => toggleModal("unpublish")}
|
|
296
297
|
onUnpublish={unpublishForm}
|
|
297
298
|
title={title}
|
|
299
|
+
isUnpublishing={isSaving}
|
|
298
300
|
/>
|
|
299
301
|
<DuplicateModal
|
|
300
302
|
isOpen={isOpen("duplicate")}
|
|
@@ -334,6 +336,7 @@ interface IFormItemProps {
|
|
|
334
336
|
currentSiteInfo: ISite | null;
|
|
335
337
|
hoverCheck?: boolean;
|
|
336
338
|
skipReviewOnPublish?: boolean;
|
|
339
|
+
isSaving: boolean;
|
|
337
340
|
addCategoryColors(cats: string[]): void;
|
|
338
341
|
onChange: (value: ICheck) => void;
|
|
339
342
|
onClick: (id: number) => void;
|
|
@@ -351,6 +354,7 @@ interface IFormItemProps {
|
|
|
351
354
|
const mapStateToProps = (state: IRootState) => ({
|
|
352
355
|
currentSiteInfo: state.sites.currentSiteInfo,
|
|
353
356
|
skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
|
|
357
|
+
isSaving: state.app.isSaving,
|
|
354
358
|
});
|
|
355
359
|
|
|
356
360
|
const mapDispatchToProps = {
|
|
@@ -47,6 +47,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
47
47
|
lang,
|
|
48
48
|
globalLangs,
|
|
49
49
|
siteLanguages,
|
|
50
|
+
isSaving,
|
|
50
51
|
setHistoryPush,
|
|
51
52
|
addTemplate,
|
|
52
53
|
getForms,
|
|
@@ -71,7 +72,6 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
71
72
|
|
|
72
73
|
const [page, setPage] = useState(firstPage);
|
|
73
74
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
74
|
-
const [isBulkLoading, setIsBulkLoading] = useState(false);
|
|
75
75
|
const [selectedTemplate, setSelectedTemplate] = useState<ISchema | null>(null);
|
|
76
76
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
77
77
|
const [arePagesTranslated, setArePagesTranslated] = useState(false);
|
|
@@ -85,6 +85,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
85
85
|
|
|
86
86
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
87
87
|
const tableRef = useRef<HTMLDivElement>(null);
|
|
88
|
+
const notificationRef = useRef<HTMLDivElement>(null);
|
|
88
89
|
const formIds = forms.map((form) => form.id);
|
|
89
90
|
const isSearching = searchQuery.length > 0;
|
|
90
91
|
const isFiltering = currentFilterQuery.length > 0;
|
|
@@ -132,6 +133,12 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
132
133
|
handleGetForms();
|
|
133
134
|
}, [getParams, lang]);
|
|
134
135
|
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (notification && notificationRef.current) {
|
|
138
|
+
notificationRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
139
|
+
}
|
|
140
|
+
}, [notification]);
|
|
141
|
+
|
|
135
142
|
const onScroll = (e: any) => setIsScrolling(e.target.scrollTop > 0);
|
|
136
143
|
|
|
137
144
|
const handleSelectAll = () => selectAllItems();
|
|
@@ -174,17 +181,14 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
174
181
|
};
|
|
175
182
|
|
|
176
183
|
const publishForm = async () => {
|
|
177
|
-
setIsBulkLoading(true);
|
|
178
184
|
const isUpdated = await updateFormState(selectedItems.all, "active");
|
|
179
185
|
if (isUpdated) {
|
|
180
186
|
resetBulkSelection();
|
|
181
187
|
toggleToast(`${selectedItems.all.length} form${selectedItems.all.length > 1 ? "s" : ""} published`);
|
|
182
188
|
}
|
|
183
|
-
setIsBulkLoading(false);
|
|
184
189
|
};
|
|
185
190
|
|
|
186
191
|
const unpublishForm = async () => {
|
|
187
|
-
setIsBulkLoading(true);
|
|
188
192
|
const isUsed = forms.some((form) => selectedItems.all.includes(form.id) && !!form.formInUse);
|
|
189
193
|
if (isUsed) {
|
|
190
194
|
setNotification({
|
|
@@ -198,11 +202,10 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
198
202
|
toggleToast(`${selectedItems.all.length} form${selectedItems.all.length > 1 ? "s" : ""} unpublished`);
|
|
199
203
|
}
|
|
200
204
|
}
|
|
201
|
-
|
|
205
|
+
isOpen("unpublish") && toggleModal("unpublish");
|
|
202
206
|
};
|
|
203
207
|
|
|
204
208
|
const handleDeleteForm = async () => {
|
|
205
|
-
setIsBulkLoading(true);
|
|
206
209
|
const idsToBeDeleted = getAllLangFormsIds(forms, selectedItems.all, deleteAllVersions);
|
|
207
210
|
const isUsed = forms.some((form) => idsToBeDeleted.includes(form.id) && !!form.formInUse);
|
|
208
211
|
if (isUsed) {
|
|
@@ -217,7 +220,6 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
217
220
|
toggleModal("delete");
|
|
218
221
|
}
|
|
219
222
|
}
|
|
220
|
-
setIsBulkLoading(false);
|
|
221
223
|
};
|
|
222
224
|
|
|
223
225
|
const handleToggleBulkDelete = () => {
|
|
@@ -273,7 +275,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
273
275
|
featuredCategory={featuredCategory}
|
|
274
276
|
bulkActions={bulkActions}
|
|
275
277
|
siteID={currentSiteInfo?.id || null}
|
|
276
|
-
isLoading={
|
|
278
|
+
isLoading={isSaving}
|
|
277
279
|
/>
|
|
278
280
|
);
|
|
279
281
|
|
|
@@ -330,7 +332,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
330
332
|
<FormsMenu />
|
|
331
333
|
<S.TableListWrapper>
|
|
332
334
|
{notification && (
|
|
333
|
-
<S.NotificationWrapper>
|
|
335
|
+
<S.NotificationWrapper ref={notificationRef}>
|
|
334
336
|
<Notification
|
|
335
337
|
type={notification.type}
|
|
336
338
|
text={notification.text}
|
|
@@ -413,6 +415,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
413
415
|
toggleModal={() => toggleModal("unpublish")}
|
|
414
416
|
onUnpublish={unpublishForm}
|
|
415
417
|
title={selectedItems.all.length > 1 ? "these forms" : "this form"}
|
|
418
|
+
isUnpublishing={isSaving}
|
|
416
419
|
/>
|
|
417
420
|
)}
|
|
418
421
|
{isOpen("delete") && (
|
|
@@ -421,6 +424,7 @@ const FormList = (props: IUserListProps): JSX.Element => {
|
|
|
421
424
|
toggleModal={() => toggleModal("delete")}
|
|
422
425
|
onDelete={handleDeleteForm}
|
|
423
426
|
title={selectedItems.all.length > 1 ? "these forms" : "this form"}
|
|
427
|
+
isDeleting={isSaving}
|
|
424
428
|
{...{ isTranslated: arePagesTranslated, deleteAllVersions, setDeleteAllVersions }}
|
|
425
429
|
/>
|
|
426
430
|
)}
|
|
@@ -436,6 +440,7 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
436
440
|
siteLanguages: state.sites.currentSiteLanguages,
|
|
437
441
|
globalLangs: state.app.globalLangs,
|
|
438
442
|
lang: state.app.lang,
|
|
443
|
+
isSaving: state.app.isSaving,
|
|
439
444
|
});
|
|
440
445
|
|
|
441
446
|
const mapDispatchToProps = {
|
|
@@ -465,6 +470,7 @@ interface IProps {
|
|
|
465
470
|
lang: { locale: string; id: number };
|
|
466
471
|
siteLanguages: ILanguage[];
|
|
467
472
|
globalLangs: ILanguage[];
|
|
473
|
+
isSaving: boolean;
|
|
468
474
|
}
|
|
469
475
|
|
|
470
476
|
export type IUserListProps = IProps & IDispatchProps;
|
|
@@ -6,7 +6,8 @@ import type { IModal } from "@ax/types";
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
8
8
|
const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
9
|
-
const { isOpen, toggleModal, onDelete, isTranslated, deleteAllVersions, setDeleteAllVersions, title } =
|
|
9
|
+
const { isOpen, toggleModal, onDelete, isTranslated, deleteAllVersions, setDeleteAllVersions, title, isDeleting } =
|
|
10
|
+
props;
|
|
10
11
|
|
|
11
12
|
const options = [
|
|
12
13
|
{
|
|
@@ -23,7 +24,7 @@ const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
|
23
24
|
|
|
24
25
|
const formTitle = title ? <strong>{title}</strong> : "this form";
|
|
25
26
|
|
|
26
|
-
const mainAction = { title: "Delete form", onClick: onDelete };
|
|
27
|
+
const mainAction = { title: isDeleting ? "Deleting" : "Delete form", onClick: onDelete, disabled: isDeleting };
|
|
27
28
|
const secondaryAction = { title: "Cancel", onClick: toggleModal };
|
|
28
29
|
|
|
29
30
|
return (
|
|
@@ -66,11 +67,11 @@ const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
const UnPublishModal = (props: IUnpublishModal): JSX.Element => {
|
|
69
|
-
const { isOpen, toggleModal, onUnpublish, title } = props;
|
|
70
|
+
const { isOpen, toggleModal, onUnpublish, title, isUnpublishing } = props;
|
|
70
71
|
|
|
71
72
|
const formTitle = title ? <strong>{title}</strong> : "this form";
|
|
72
73
|
|
|
73
|
-
const mainAction = { title: "Unpublish form", onClick: onUnpublish };
|
|
74
|
+
const mainAction = { title: isUnpublishing ? "Unpublishing" : "Unpublish form", onClick: onUnpublish, disabled: isUnpublishing };
|
|
74
75
|
const secondaryAction = { title: "Cancel", onClick: toggleModal };
|
|
75
76
|
|
|
76
77
|
return (
|
|
@@ -201,11 +202,13 @@ interface IDeleteModal extends IModal {
|
|
|
201
202
|
deleteAllVersions: boolean;
|
|
202
203
|
setDeleteAllVersions: Dispatch<SetStateAction<boolean>>;
|
|
203
204
|
title?: string;
|
|
205
|
+
isDeleting?: boolean;
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
interface IUnpublishModal extends IModal {
|
|
207
209
|
onUnpublish(): void;
|
|
208
210
|
title?: string;
|
|
211
|
+
isUnpublishing?: boolean;
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
interface IDuplicateModal extends IModal {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldsBehavior, Modal } from "@ax/components";
|
|
4
|
+
import type { IModal } from "@ax/types";
|
|
5
|
+
|
|
6
|
+
import * as S from "./style";
|
|
7
|
+
|
|
8
|
+
const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
9
|
+
const { isOpen, toggleModal, isTranslated, deleteAllVersions, setDeleteAllVersions, onDelete, isDeleting } = props;
|
|
10
|
+
|
|
11
|
+
const options = [
|
|
12
|
+
{
|
|
13
|
+
title: "Delete only this version",
|
|
14
|
+
name: "deletePage",
|
|
15
|
+
value: false,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
title: "Delete all languages versions",
|
|
19
|
+
name: "deleteAll",
|
|
20
|
+
value: true,
|
|
21
|
+
},
|
|
22
|
+
];
|
|
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
|
+
return (
|
|
33
|
+
<Modal
|
|
34
|
+
isOpen={isOpen}
|
|
35
|
+
hide={toggleModal}
|
|
36
|
+
title="Delete Page?"
|
|
37
|
+
secondaryAction={secondaryAction}
|
|
38
|
+
mainAction={mainAction}
|
|
39
|
+
size="S"
|
|
40
|
+
height="auto"
|
|
41
|
+
>
|
|
42
|
+
{isTranslated ? (
|
|
43
|
+
<>
|
|
44
|
+
<S.ModalContent>
|
|
45
|
+
<p>
|
|
46
|
+
You are going to delete this page that have some translations associated. Choose if you want to delete all
|
|
47
|
+
languages versions or only this one.
|
|
48
|
+
</p>
|
|
49
|
+
<FieldsBehavior
|
|
50
|
+
name="removeAllVersions"
|
|
51
|
+
fieldType="RadioGroup"
|
|
52
|
+
value={deleteAllVersions}
|
|
53
|
+
options={options}
|
|
54
|
+
onChange={setDeleteAllVersions}
|
|
55
|
+
/>
|
|
56
|
+
</S.ModalContent>
|
|
57
|
+
</>
|
|
58
|
+
) : (
|
|
59
|
+
<S.ModalContent>
|
|
60
|
+
Are you sure you want to delete this page?
|
|
61
|
+
<br />
|
|
62
|
+
This action <strong>cannot be undone</strong>.
|
|
63
|
+
</S.ModalContent>
|
|
64
|
+
)}
|
|
65
|
+
</Modal>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
interface IDeleteModal extends IModal {
|
|
70
|
+
isTranslated: boolean;
|
|
71
|
+
deleteAllVersions: boolean;
|
|
72
|
+
setDeleteAllVersions: React.Dispatch<React.SetStateAction<boolean>>;
|
|
73
|
+
onDelete: () => void;
|
|
74
|
+
isDeleting?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { DeleteModal };
|