@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
|
@@ -38,6 +38,7 @@ import type {
|
|
|
38
38
|
IUserEditing,
|
|
39
39
|
} from "@ax/types";
|
|
40
40
|
|
|
41
|
+
import { DeleteModal } from "./atoms";
|
|
41
42
|
import Editor from "./Editor";
|
|
42
43
|
import Preview from "./Preview";
|
|
43
44
|
|
|
@@ -83,6 +84,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
83
84
|
|
|
84
85
|
const defaultTab = isAllowedTo.editContentPages ? "edit" : "view";
|
|
85
86
|
|
|
87
|
+
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
86
88
|
const [isReadOnly, setIsReadOnly] = useState(false);
|
|
87
89
|
const [selectedTab, setSelectedTab] = useState(defaultTab);
|
|
88
90
|
const [notification, setNotification] = useState<INotification | null>(null);
|
|
@@ -106,6 +108,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
106
108
|
"headingsPreview",
|
|
107
109
|
"keywordsPreview",
|
|
108
110
|
"dirtyNavigate",
|
|
111
|
+
"delete",
|
|
109
112
|
]);
|
|
110
113
|
|
|
111
114
|
const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
|
|
@@ -118,6 +121,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
118
121
|
const isEditLive = isPublished && hasDraft;
|
|
119
122
|
const isScheduled = props.pageStatus === pageStatus.SCHEDULED;
|
|
120
123
|
const isDeleted = editorContent.deleted;
|
|
124
|
+
const isTranslated = pageLanguages.length > 1;
|
|
121
125
|
const defaultContentTab = "content";
|
|
122
126
|
|
|
123
127
|
const errorNotificationText =
|
|
@@ -185,13 +189,17 @@ const GlobalEditor = (props: IProps) => {
|
|
|
185
189
|
const setRoute = (path: string) => props.setHistoryPush(path, true);
|
|
186
190
|
|
|
187
191
|
const removePage = async () => {
|
|
188
|
-
const { deletePage } = props;
|
|
192
|
+
const { deletePage, deleteBulk } = props;
|
|
189
193
|
const path = "/data";
|
|
190
194
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
try {
|
|
196
|
+
const allPageVersions = pageLanguages.map((lang: IPageLanguage) => lang.pageId);
|
|
197
|
+
const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage();
|
|
198
|
+
if (isDeleted) {
|
|
199
|
+
setRoute(path);
|
|
200
|
+
}
|
|
201
|
+
} finally {
|
|
202
|
+
toggleModal("delete");
|
|
195
203
|
}
|
|
196
204
|
};
|
|
197
205
|
|
|
@@ -388,9 +396,9 @@ const GlobalEditor = (props: IProps) => {
|
|
|
388
396
|
|
|
389
397
|
if (!isDraft && isAllowedTo.deletePages) {
|
|
390
398
|
menuOptions.push({
|
|
391
|
-
label: "Delete
|
|
399
|
+
label: "Delete",
|
|
392
400
|
icon: "delete",
|
|
393
|
-
action:
|
|
401
|
+
action: () => toggleModal("delete"),
|
|
394
402
|
});
|
|
395
403
|
}
|
|
396
404
|
|
|
@@ -759,6 +767,13 @@ const GlobalEditor = (props: IProps) => {
|
|
|
759
767
|
</S.ModalContent>
|
|
760
768
|
)}
|
|
761
769
|
</Modal>
|
|
770
|
+
<DeleteModal
|
|
771
|
+
isOpen={isOpen("delete")}
|
|
772
|
+
toggleModal={() => toggleModal("delete")}
|
|
773
|
+
onDelete={removePage}
|
|
774
|
+
isDeleting={isSaving}
|
|
775
|
+
{...{ isTranslated, deleteAllVersions, setDeleteAllVersions }}
|
|
776
|
+
/>
|
|
762
777
|
<ScheduleModal
|
|
763
778
|
isOpen={isOpen("schedule")}
|
|
764
779
|
toggleModal={() => toggleModal("schedule")}
|
|
@@ -875,6 +890,7 @@ const mapDispatchToProps = {
|
|
|
875
890
|
sendPagePing: pageEditorActions.sendPagePing,
|
|
876
891
|
setStructuredDataFilter: structuredDataActions.setFilter,
|
|
877
892
|
discardDraft: pageEditorActions.discardDraft,
|
|
893
|
+
deleteBulk: pageEditorActions.deleteBulk,
|
|
878
894
|
getUserCurrentPermissions: usersActions.getUserCurrentPermissions,
|
|
879
895
|
schedulePublication: pageEditorActions.schedulePublication,
|
|
880
896
|
restorePage: pageEditorActions.restorePage,
|
|
@@ -902,6 +918,7 @@ interface IPageEditorDispatchProps {
|
|
|
902
918
|
sendPagePing(pageID: number): Promise<boolean>;
|
|
903
919
|
setStructuredDataFilter(filter: string | null): void;
|
|
904
920
|
discardDraft(): Promise<void>;
|
|
921
|
+
deleteBulk(ids: number[]): Promise<boolean>;
|
|
905
922
|
getUserCurrentPermissions(): Promise<void>;
|
|
906
923
|
schedulePublication(date: string | null, isDraft: boolean): Promise<boolean>;
|
|
907
924
|
restorePage(id: number | number[]): Promise<boolean>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
|
-
import { IActionMenuOption, IFolder, IGetFolderParams } from "@ax/types";
|
|
5
4
|
import { Icon, Tooltip } from "@ax/components";
|
|
6
|
-
import { useModal } from "@ax/hooks";
|
|
7
5
|
import { galleryActions } from "@ax/containers/Gallery";
|
|
8
|
-
import { DeleteFolderModal, MoveItemModal, RenameFolderModal } from "../atoms";
|
|
9
6
|
import { trimText } from "@ax/helpers";
|
|
7
|
+
import { useModals } from "@ax/hooks";
|
|
8
|
+
import type { IActionMenuOption, IFolder, IGetFolderParams, IRootState } from "@ax/types";
|
|
9
|
+
|
|
10
|
+
import { DeleteFolderModal, MoveItemModal, RenameFolderModal } from "../atoms";
|
|
10
11
|
|
|
11
12
|
import * as S from "./style";
|
|
12
13
|
|
|
@@ -16,6 +17,7 @@ const FolderItem = (props: IProps) => {
|
|
|
16
17
|
isAllowedToDelete,
|
|
17
18
|
isAllowedToEdit,
|
|
18
19
|
isAllowedToMove,
|
|
20
|
+
isSaving,
|
|
19
21
|
onClick,
|
|
20
22
|
onDelete,
|
|
21
23
|
toggleToast,
|
|
@@ -26,9 +28,7 @@ const FolderItem = (props: IProps) => {
|
|
|
26
28
|
|
|
27
29
|
const initState = { folderName, parentId };
|
|
28
30
|
const [folderForm, setFolderForm] = useState(initState);
|
|
29
|
-
const { isOpen
|
|
30
|
-
const { isOpen: isRenameOpen, toggleModal: toggleRenameModal } = useModal();
|
|
31
|
-
const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
|
|
31
|
+
const { isOpen, toggleModal } = useModals(["delete", "rename", "move"]);
|
|
32
32
|
|
|
33
33
|
const setName = (name: string) => setFolderForm({ ...folderForm, folderName: name });
|
|
34
34
|
const setParent = (folderID: number) => setFolderForm({ ...folderForm, parentId: folderID });
|
|
@@ -40,7 +40,7 @@ const FolderItem = (props: IProps) => {
|
|
|
40
40
|
{
|
|
41
41
|
label: "Rename",
|
|
42
42
|
icon: "edit",
|
|
43
|
-
action: () =>
|
|
43
|
+
action: () => toggleModal("rename"),
|
|
44
44
|
},
|
|
45
45
|
];
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ const FolderItem = (props: IProps) => {
|
|
|
50
50
|
{
|
|
51
51
|
label: "Move to...",
|
|
52
52
|
icon: "change",
|
|
53
|
-
action: () =>
|
|
53
|
+
action: () => toggleModal("move"),
|
|
54
54
|
},
|
|
55
55
|
];
|
|
56
56
|
}
|
|
@@ -62,16 +62,16 @@ const FolderItem = (props: IProps) => {
|
|
|
62
62
|
{
|
|
63
63
|
label: "Delete",
|
|
64
64
|
icon: "delete",
|
|
65
|
-
action: () =>
|
|
65
|
+
action: () => toggleModal("delete"),
|
|
66
66
|
},
|
|
67
67
|
];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
const handleClick = () => onClick(id);
|
|
71
71
|
|
|
72
|
-
const handleDeleteFolder = () => {
|
|
73
|
-
onDelete(folder);
|
|
74
|
-
|
|
72
|
+
const handleDeleteFolder = async () => {
|
|
73
|
+
await onDelete(folder);
|
|
74
|
+
isOpen("delete") && toggleModal("delete");
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
const handleUpdateFolder = async (toast = false) => {
|
|
@@ -82,39 +82,17 @@ const FolderItem = (props: IProps) => {
|
|
|
82
82
|
params,
|
|
83
83
|
);
|
|
84
84
|
if (updated) {
|
|
85
|
-
|
|
85
|
+
isOpen("rename") && toggleModal("rename");
|
|
86
86
|
toast && toggleToast("1 Folder moved to another folder");
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
const handleModalClose = () => {
|
|
91
91
|
setFolderForm(initState);
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
isOpen("move") && toggleModal("move");
|
|
93
|
+
isOpen("rename") && toggleModal("rename");
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
-
const mainDeleteModalAction = {
|
|
97
|
-
title: "Delete Folder",
|
|
98
|
-
onClick: () => handleDeleteFolder(),
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
102
|
-
|
|
103
|
-
const mainRenameModalAction = {
|
|
104
|
-
title: "Rename Folder",
|
|
105
|
-
onClick: () => handleUpdateFolder(),
|
|
106
|
-
disabled: folderForm.folderName.trim().length === 0,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const secondaryRenameModalAction = { title: "Cancel", onClick: handleModalClose };
|
|
110
|
-
|
|
111
|
-
const mainMoveModalAction = {
|
|
112
|
-
title: "Move",
|
|
113
|
-
onClick: () => handleUpdateFolder(true),
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
|
|
117
|
-
|
|
118
96
|
const FolderTitle = () =>
|
|
119
97
|
folderName.length > 15 ? (
|
|
120
98
|
<Tooltip content={folderName}>
|
|
@@ -133,35 +111,36 @@ const FolderItem = (props: IProps) => {
|
|
|
133
111
|
<FolderTitle />
|
|
134
112
|
<S.StyledActionMenu icon="more" options={menuOptions} tooltip="File actions" />
|
|
135
113
|
</S.Wrapper>
|
|
136
|
-
{
|
|
114
|
+
{isOpen("delete") && (
|
|
137
115
|
<DeleteFolderModal
|
|
138
|
-
isOpen={
|
|
139
|
-
toggleModal={
|
|
140
|
-
mainModalAction={mainDeleteModalAction}
|
|
141
|
-
secondaryModalAction={secondaryDeleteModalAction}
|
|
116
|
+
isOpen={isOpen("delete")}
|
|
117
|
+
toggleModal={() => toggleModal("delete")}
|
|
142
118
|
title={folderName}
|
|
119
|
+
onDelete={handleDeleteFolder}
|
|
120
|
+
isDeleting={isSaving}
|
|
143
121
|
/>
|
|
144
122
|
)}
|
|
145
|
-
{
|
|
123
|
+
{isOpen("rename") && (
|
|
146
124
|
<RenameFolderModal
|
|
147
|
-
isOpen={
|
|
125
|
+
isOpen={isOpen("rename")}
|
|
148
126
|
toggleModal={handleModalClose}
|
|
149
|
-
mainModalAction={mainRenameModalAction}
|
|
150
|
-
secondaryModalAction={secondaryRenameModalAction}
|
|
151
127
|
value={folderForm.folderName}
|
|
152
128
|
setValue={setName}
|
|
129
|
+
onUpdateFolder={() => handleUpdateFolder()}
|
|
130
|
+
isNameEmpty={folderForm.folderName.trim().length === 0}
|
|
131
|
+
isUpdating={isSaving}
|
|
153
132
|
/>
|
|
154
133
|
)}
|
|
155
|
-
{
|
|
134
|
+
{isOpen("move") && (
|
|
156
135
|
<MoveItemModal
|
|
157
|
-
isOpen={
|
|
136
|
+
isOpen={isOpen("move")}
|
|
158
137
|
toggleModal={handleModalClose}
|
|
159
|
-
mainModalAction={mainMoveModalAction}
|
|
160
|
-
secondaryModalAction={secondaryMoveModalAction}
|
|
161
138
|
folder={folderForm.parentId}
|
|
162
139
|
setFolder={setParent}
|
|
163
140
|
hidden={[folder.id]}
|
|
164
141
|
hideRoot={!parentId}
|
|
142
|
+
onMove={() => handleUpdateFolder(true)}
|
|
143
|
+
isMoving={isSaving}
|
|
165
144
|
/>
|
|
166
145
|
)}
|
|
167
146
|
</>
|
|
@@ -173,6 +152,7 @@ interface IProps {
|
|
|
173
152
|
isAllowedToEdit: boolean;
|
|
174
153
|
isAllowedToDelete: boolean;
|
|
175
154
|
isAllowedToMove: boolean;
|
|
155
|
+
isSaving: boolean;
|
|
176
156
|
onClick(folderID: number): void;
|
|
177
157
|
onDelete(folder: IFolder): void;
|
|
178
158
|
toggleToast(state: string): void;
|
|
@@ -184,8 +164,12 @@ interface IProps {
|
|
|
184
164
|
): Promise<boolean>;
|
|
185
165
|
}
|
|
186
166
|
|
|
167
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
168
|
+
isSaving: state.app.isSaving,
|
|
169
|
+
});
|
|
170
|
+
|
|
187
171
|
const mapDispatchToProps = {
|
|
188
172
|
updateFolder: galleryActions.updateFolder,
|
|
189
173
|
};
|
|
190
174
|
|
|
191
|
-
export default connect(
|
|
175
|
+
export default connect(mapStateToProps, mapDispatchToProps)(FolderItem);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
|
|
2
4
|
import { Icon } from "@ax/components";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
+
import { useModals } from "@ax/hooks";
|
|
6
|
+
import type { IActionMenuOption, ICheck, IImage } from "@ax/types";
|
|
5
7
|
|
|
6
8
|
import { DeleteFileModal, MoveItemModal } from "../atoms";
|
|
7
9
|
|
|
@@ -15,6 +17,7 @@ const GridItem = (props: IProps) => {
|
|
|
15
17
|
isAllowedToDelete,
|
|
16
18
|
isAllowedToEdit,
|
|
17
19
|
isAllowedToMove,
|
|
20
|
+
isSaving,
|
|
18
21
|
onChange,
|
|
19
22
|
onClick,
|
|
20
23
|
onDelete,
|
|
@@ -24,8 +27,7 @@ const GridItem = (props: IProps) => {
|
|
|
24
27
|
const { id, name, thumb, alt, folderId } = image;
|
|
25
28
|
|
|
26
29
|
const [selectedFolder, setSelectedFolder] = useState<number | null>(currentFolderID || null);
|
|
27
|
-
const { isOpen
|
|
28
|
-
const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
|
|
30
|
+
const { isOpen, toggleModal } = useModals(["delete", "move"]);
|
|
29
31
|
|
|
30
32
|
const handleCheckClick = (isChecked: boolean) => (e: React.MouseEvent<HTMLDivElement>) => {
|
|
31
33
|
e.stopPropagation();
|
|
@@ -51,7 +53,7 @@ const GridItem = (props: IProps) => {
|
|
|
51
53
|
{
|
|
52
54
|
label: "Move to...",
|
|
53
55
|
icon: "change",
|
|
54
|
-
action: () =>
|
|
56
|
+
action: () => toggleModal("move"),
|
|
55
57
|
},
|
|
56
58
|
];
|
|
57
59
|
}
|
|
@@ -63,70 +65,56 @@ const GridItem = (props: IProps) => {
|
|
|
63
65
|
{
|
|
64
66
|
label: "Delete",
|
|
65
67
|
icon: "delete",
|
|
66
|
-
action: () =>
|
|
68
|
+
action: () => toggleModal("delete"),
|
|
67
69
|
},
|
|
68
70
|
];
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
const handleDeleteFile = () => {
|
|
72
|
-
onDelete(id);
|
|
73
|
-
|
|
73
|
+
const handleDeleteFile = async () => {
|
|
74
|
+
await onDelete(id);
|
|
75
|
+
toggleModal("delete");
|
|
74
76
|
};
|
|
75
77
|
|
|
76
|
-
const handleMoveFile = () => {
|
|
78
|
+
const handleMoveFile = async () => {
|
|
77
79
|
if (folderId !== selectedFolder) {
|
|
78
|
-
onMove(id, selectedFolder || "root");
|
|
79
|
-
|
|
80
|
+
await onMove(id, selectedFolder || "root");
|
|
81
|
+
isOpen("move") && toggleModal("move");
|
|
80
82
|
setSelectedFolder(0);
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
85
|
|
|
84
86
|
const handleModalClose = () => {
|
|
85
87
|
setSelectedFolder(0);
|
|
86
|
-
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const mainDeleteModalAction = {
|
|
90
|
-
title: "Delete image",
|
|
91
|
-
onClick: () => handleDeleteFile(),
|
|
88
|
+
toggleModal("move");
|
|
92
89
|
};
|
|
93
90
|
|
|
94
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
95
|
-
|
|
96
|
-
const mainMoveModalAction = {
|
|
97
|
-
title: "Move",
|
|
98
|
-
onClick: () => handleMoveFile(),
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
|
|
102
|
-
|
|
103
91
|
return (
|
|
104
92
|
<>
|
|
105
93
|
<S.ImageWrapper data-testid="image-item" onClick={handleClick} selected={isSelected}>
|
|
106
94
|
<img src={thumb} alt={alt} />
|
|
107
|
-
<S.IconWrapper onClick={handleCheckClick(isSelected
|
|
95
|
+
<S.IconWrapper onClick={handleCheckClick(!isSelected)}>
|
|
108
96
|
<Icon name={isSelected ? "successSolid" : "emptyCheck"} size="24" />
|
|
109
97
|
</S.IconWrapper>
|
|
110
98
|
<S.StyledActionMenu icon="more" options={menuOptions} />
|
|
111
99
|
</S.ImageWrapper>
|
|
112
|
-
{
|
|
100
|
+
{isOpen("delete") && (
|
|
113
101
|
<DeleteFileModal
|
|
114
|
-
isOpen={
|
|
115
|
-
toggleModal={
|
|
116
|
-
mainModalAction={mainDeleteModalAction}
|
|
117
|
-
secondaryModalAction={secondaryDeleteModalAction}
|
|
102
|
+
isOpen={isOpen("delete")}
|
|
103
|
+
toggleModal={() => toggleModal("delete")}
|
|
118
104
|
title={name}
|
|
105
|
+
onDelete={handleDeleteFile}
|
|
106
|
+
isDeleting={isSaving}
|
|
119
107
|
/>
|
|
120
108
|
)}
|
|
121
|
-
{
|
|
109
|
+
{isOpen("move") && (
|
|
122
110
|
<MoveItemModal
|
|
123
|
-
isOpen={
|
|
111
|
+
isOpen={isOpen("move")}
|
|
124
112
|
toggleModal={handleModalClose}
|
|
125
|
-
mainModalAction={mainMoveModalAction}
|
|
126
|
-
secondaryModalAction={secondaryMoveModalAction}
|
|
127
113
|
folder={selectedFolder}
|
|
128
114
|
setFolder={setSelectedFolder}
|
|
115
|
+
onMove={handleMoveFile}
|
|
129
116
|
hideRoot={!folderId}
|
|
117
|
+
isMoving={isSaving}
|
|
130
118
|
/>
|
|
131
119
|
)}
|
|
132
120
|
</>
|
|
@@ -140,6 +128,7 @@ interface IProps {
|
|
|
140
128
|
isAllowedToEdit: boolean;
|
|
141
129
|
isAllowedToDelete: boolean;
|
|
142
130
|
isAllowedToMove: boolean;
|
|
131
|
+
isSaving: boolean;
|
|
143
132
|
onChange(e: ICheck): void;
|
|
144
133
|
onClick(image: IImage): void;
|
|
145
134
|
onDelete(imageID: number): void;
|
|
@@ -9,9 +9,10 @@ import { LOCALE } from "@ax/locales";
|
|
|
9
9
|
import type { IGetFolderParams, IImage, IRootState } from "@ax/types";
|
|
10
10
|
|
|
11
11
|
import { DeleteFileModal } from "../../atoms";
|
|
12
|
-
import * as S from "./style";
|
|
13
12
|
import UsageContent from "./UsageContent";
|
|
14
13
|
|
|
14
|
+
import * as S from "./style";
|
|
15
|
+
|
|
15
16
|
const DetailPanel = (props: IProps) => {
|
|
16
17
|
const {
|
|
17
18
|
image,
|
|
@@ -30,6 +31,7 @@ const DetailPanel = (props: IProps) => {
|
|
|
30
31
|
const { name, size, published, title, alt, tags, width, height } = image;
|
|
31
32
|
|
|
32
33
|
const [selectedTab, setSelectedTab] = useState("details");
|
|
34
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
33
35
|
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
34
36
|
|
|
35
37
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
@@ -59,9 +61,14 @@ const DetailPanel = (props: IProps) => {
|
|
|
59
61
|
|
|
60
62
|
const handleCopyUrl = () => navigator.clipboard.writeText(image.url);
|
|
61
63
|
|
|
62
|
-
const handleDeleteFile = () => {
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
const handleDeleteFile = async () => {
|
|
65
|
+
setIsDeleting(true);
|
|
66
|
+
try {
|
|
67
|
+
await onDelete(image.id);
|
|
68
|
+
} finally {
|
|
69
|
+
setIsDeleting(false);
|
|
70
|
+
toggleDeleteModal();
|
|
71
|
+
}
|
|
65
72
|
};
|
|
66
73
|
|
|
67
74
|
const handleSelectedTab = (tab: "details" | "in use") => {
|
|
@@ -70,13 +77,6 @@ const DetailPanel = (props: IProps) => {
|
|
|
70
77
|
}
|
|
71
78
|
};
|
|
72
79
|
|
|
73
|
-
const mainNewModalAction = {
|
|
74
|
-
title: "Delete image",
|
|
75
|
-
onClick: () => handleDeleteFile(),
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const secondaryNewModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
79
|
-
|
|
80
80
|
const tabs = ["details", "in use"];
|
|
81
81
|
|
|
82
82
|
return (
|
|
@@ -168,9 +168,9 @@ const DetailPanel = (props: IProps) => {
|
|
|
168
168
|
<DeleteFileModal
|
|
169
169
|
isOpen={isDeleteOpen}
|
|
170
170
|
toggleModal={toggleDeleteModal}
|
|
171
|
-
mainModalAction={mainNewModalAction}
|
|
172
|
-
secondaryModalAction={secondaryNewModalAction}
|
|
173
171
|
title={image.name}
|
|
172
|
+
onDelete={handleDeleteFile}
|
|
173
|
+
isDeleting={isDeleting}
|
|
174
174
|
isChild={true}
|
|
175
175
|
/>
|
|
176
176
|
)}
|
|
@@ -69,19 +69,12 @@ const ImageModal = (props: IProps) => {
|
|
|
69
69
|
message: "1 image replaced",
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const
|
|
72
|
+
const handleDiscard = () => {
|
|
73
73
|
toggleSaveModal();
|
|
74
74
|
resetDirty();
|
|
75
75
|
changeFile(isArrowPrev);
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
const mainModalAction = {
|
|
79
|
-
title: "Yes, discard changes",
|
|
80
|
-
onClick: () => handleMainAction(),
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const secondaryModalAction = { title: "Cancel", onClick: toggleSaveModal };
|
|
84
|
-
|
|
85
78
|
return (
|
|
86
79
|
<>
|
|
87
80
|
<S.Wrapper>
|
|
@@ -139,14 +132,7 @@ const ImageModal = (props: IProps) => {
|
|
|
139
132
|
/>
|
|
140
133
|
</S.Wrapper>
|
|
141
134
|
{isVisible && <Toast {...toastProps} />}
|
|
142
|
-
{isSaveOpen &&
|
|
143
|
-
<NotSavedModal
|
|
144
|
-
isOpen={isSaveOpen}
|
|
145
|
-
toggleModal={toggleSaveModal}
|
|
146
|
-
mainModalAction={mainModalAction}
|
|
147
|
-
secondaryModalAction={secondaryModalAction}
|
|
148
|
-
/>
|
|
149
|
-
)}
|
|
135
|
+
{isSaveOpen && <NotSavedModal isOpen={isSaveOpen} toggleModal={toggleSaveModal} onDiscard={handleDiscard} />}
|
|
150
136
|
</>
|
|
151
137
|
);
|
|
152
138
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
2
3
|
import { CheckField, ElementsTooltip, Tooltip } from "@ax/components";
|
|
3
|
-
import { IActionMenuOption, ICheck, IImage } from "@ax/types";
|
|
4
4
|
import { formatBytes, getFileExtension, trimText } from "@ax/helpers";
|
|
5
|
-
import {
|
|
5
|
+
import { useModals } from "@ax/hooks";
|
|
6
|
+
import type { IActionMenuOption, ICheck, IImage } from "@ax/types";
|
|
6
7
|
|
|
7
8
|
import { DeleteFileModal, MoveItemModal } from "../atoms";
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ const ListItem = (props: IProps) => {
|
|
|
17
18
|
isAllowedToEdit,
|
|
18
19
|
isAllowedToMove,
|
|
19
20
|
hoverCheck,
|
|
21
|
+
isSaving,
|
|
20
22
|
onChange,
|
|
21
23
|
onClick,
|
|
22
24
|
onDelete,
|
|
@@ -26,8 +28,7 @@ const ListItem = (props: IProps) => {
|
|
|
26
28
|
const imageType = getFileExtension(image.name);
|
|
27
29
|
|
|
28
30
|
const [selectedFolder, setSelectedFolder] = useState<number | null>(currentFolderID || null);
|
|
29
|
-
const { isOpen
|
|
30
|
-
const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
|
|
31
|
+
const { isOpen, toggleModal } = useModals(["delete", "move"]);
|
|
31
32
|
|
|
32
33
|
const handleChange = (value: ICheck) => onChange(value);
|
|
33
34
|
const handleClick = () => onClick(image);
|
|
@@ -49,7 +50,7 @@ const ListItem = (props: IProps) => {
|
|
|
49
50
|
{
|
|
50
51
|
label: "Move to...",
|
|
51
52
|
icon: "change",
|
|
52
|
-
action: () =>
|
|
53
|
+
action: () => toggleModal("move"),
|
|
53
54
|
},
|
|
54
55
|
];
|
|
55
56
|
}
|
|
@@ -61,43 +62,29 @@ const ListItem = (props: IProps) => {
|
|
|
61
62
|
{
|
|
62
63
|
label: "Delete",
|
|
63
64
|
icon: "delete",
|
|
64
|
-
action: () =>
|
|
65
|
+
action: () => toggleModal("delete"),
|
|
65
66
|
},
|
|
66
67
|
];
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
const handleDeleteFile = () => {
|
|
70
|
-
onDelete(id);
|
|
71
|
-
|
|
70
|
+
const handleDeleteFile = async () => {
|
|
71
|
+
await onDelete(id);
|
|
72
|
+
toggleModal("delete");
|
|
72
73
|
};
|
|
73
74
|
|
|
74
|
-
const handleMoveFile = () => {
|
|
75
|
+
const handleMoveFile = async () => {
|
|
75
76
|
if (folderId !== selectedFolder) {
|
|
76
|
-
onMove(id, selectedFolder || "root");
|
|
77
|
-
|
|
77
|
+
await onMove(id, selectedFolder || "root");
|
|
78
|
+
isOpen("move") && toggleModal("move");
|
|
78
79
|
setSelectedFolder(0);
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
const handleModalClose = () => {
|
|
83
84
|
setSelectedFolder(0);
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const mainDeleteModalAction = {
|
|
88
|
-
title: "Delete image",
|
|
89
|
-
onClick: () => handleDeleteFile(),
|
|
85
|
+
toggleModal("move");
|
|
90
86
|
};
|
|
91
87
|
|
|
92
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
|
|
93
|
-
|
|
94
|
-
const mainMoveModalAction = {
|
|
95
|
-
title: "Move",
|
|
96
|
-
onClick: () => handleMoveFile(),
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };
|
|
100
|
-
|
|
101
88
|
const FileTitle = () => (name.length > 50 ? <Tooltip content={name}>{trimText(name, 50)}</Tooltip> : <>{name}</>);
|
|
102
89
|
|
|
103
90
|
return (
|
|
@@ -140,24 +127,24 @@ const ListItem = (props: IProps) => {
|
|
|
140
127
|
<S.StyledActionMenu icon="more" options={menuOptions} tooltip="File actions" />
|
|
141
128
|
</S.ActionsCell>
|
|
142
129
|
</S.ItemRow>
|
|
143
|
-
{
|
|
130
|
+
{isOpen("delete") && (
|
|
144
131
|
<DeleteFileModal
|
|
145
|
-
isOpen={
|
|
146
|
-
toggleModal={
|
|
147
|
-
mainModalAction={mainDeleteModalAction}
|
|
148
|
-
secondaryModalAction={secondaryDeleteModalAction}
|
|
132
|
+
isOpen={isOpen("delete")}
|
|
133
|
+
toggleModal={() => toggleModal("delete")}
|
|
149
134
|
title={name}
|
|
135
|
+
onDelete={handleDeleteFile}
|
|
136
|
+
isDeleting={isSaving}
|
|
150
137
|
/>
|
|
151
138
|
)}
|
|
152
|
-
{
|
|
139
|
+
{isOpen("move") && (
|
|
153
140
|
<MoveItemModal
|
|
154
|
-
isOpen={
|
|
141
|
+
isOpen={isOpen("move")}
|
|
155
142
|
toggleModal={handleModalClose}
|
|
156
|
-
mainModalAction={mainMoveModalAction}
|
|
157
|
-
secondaryModalAction={secondaryMoveModalAction}
|
|
158
143
|
folder={selectedFolder}
|
|
159
144
|
setFolder={setSelectedFolder}
|
|
145
|
+
onMove={handleMoveFile}
|
|
160
146
|
hideRoot={!folderId}
|
|
147
|
+
isMoving={isSaving}
|
|
161
148
|
/>
|
|
162
149
|
)}
|
|
163
150
|
</>
|
|
@@ -176,6 +163,7 @@ interface IProps {
|
|
|
176
163
|
onDelete(fileID: number): void;
|
|
177
164
|
onMove(fileID: number, folderID: number | "root"): void;
|
|
178
165
|
hoverCheck: boolean;
|
|
166
|
+
isSaving: boolean;
|
|
179
167
|
}
|
|
180
168
|
|
|
181
169
|
export default ListItem;
|