@griddo/ax 10.4.8 → 10.4.10
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/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +31 -28
- package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +6 -3
- package/src/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/index.tsx +3 -3
- package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +4 -4
- package/src/components/Fields/ComponentContainer/index.tsx +1 -1
- package/src/components/Fields/ComponentContainer/style.tsx +1 -0
- package/src/components/MainWrapper/AppBar/index.tsx +54 -7
- package/src/components/MainWrapper/AppBar/style.tsx +11 -0
- package/src/components/MainWrapper/index.tsx +1 -0
- package/src/components/Modal/index.tsx +13 -2
- package/src/containers/Navigation/Defaults/actions.tsx +2 -2
- package/src/containers/PageEditor/actions.tsx +4 -4
- package/src/modules/GlobalEditor/Editor/index.tsx +1 -1
- package/src/modules/GlobalEditor/index.tsx +9 -11
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +1 -1
- package/src/modules/PageEditor/Editor/index.tsx +1 -1
- package/src/modules/PageEditor/index.tsx +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.4.
|
|
4
|
+
"version": "10.4.10",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -231,5 +231,5 @@
|
|
|
231
231
|
"publishConfig": {
|
|
232
232
|
"access": "public"
|
|
233
233
|
},
|
|
234
|
-
"gitHead": "
|
|
234
|
+
"gitHead": "5ebecf976ceff5858e8395eea3ec113a488a1876"
|
|
235
235
|
}
|
|
@@ -128,7 +128,8 @@ describe("ComponentArraySelector component rendering", () => {
|
|
|
128
128
|
mixableProps.field = {
|
|
129
129
|
contentType: "modules",
|
|
130
130
|
key: "mainContent",
|
|
131
|
-
title: "",
|
|
131
|
+
title: "",
|
|
132
|
+
type: "",
|
|
132
133
|
};
|
|
133
134
|
mixableProps.objKey = "elements";
|
|
134
135
|
mixableProps.disabled = false;
|
|
@@ -211,34 +212,36 @@ describe("ComponentArraySelector component rendering", () => {
|
|
|
211
212
|
const actualDate = new Date();
|
|
212
213
|
mixableProps.moduleCopy = {
|
|
213
214
|
date: actualDate,
|
|
214
|
-
elements: [
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
215
|
+
elements: [
|
|
216
|
+
{
|
|
217
|
+
editorID: 1,
|
|
218
|
+
component: "ArticlesDistributor",
|
|
219
|
+
anchorID: null,
|
|
220
|
+
verticalSpacing: "medium",
|
|
221
|
+
hasDistributorData: true,
|
|
222
|
+
data: {
|
|
223
|
+
mode: "auto",
|
|
224
|
+
source: ["ARTICLES"],
|
|
225
|
+
order: "alpha",
|
|
226
|
+
quantity: 2,
|
|
227
|
+
},
|
|
228
|
+
layout: "L001",
|
|
229
|
+
title: {
|
|
230
|
+
content: "Title",
|
|
231
|
+
tag: "h2",
|
|
232
|
+
},
|
|
233
|
+
subtitle: "subtitle",
|
|
234
|
+
detail: "detail",
|
|
235
|
+
primaryLinkStyle: "primary",
|
|
236
|
+
groupingLink: {
|
|
237
|
+
component: "Link",
|
|
238
|
+
text: "View all",
|
|
239
|
+
style: "secondary",
|
|
240
|
+
editorID: 40,
|
|
241
|
+
parentEditorID: 39,
|
|
242
|
+
},
|
|
240
243
|
},
|
|
241
|
-
|
|
244
|
+
],
|
|
242
245
|
};
|
|
243
246
|
mixableProps.mandatory = true;
|
|
244
247
|
|
|
@@ -26,6 +26,7 @@ const mockedFunction = defaultProps.pasteModule as jest.MockedFunction<
|
|
|
26
26
|
>;
|
|
27
27
|
const mockedNotification = defaultProps.setNotification as jest.MockedFunction<(notification: INotification) => void>;
|
|
28
28
|
defaultProps.editorID = 1;
|
|
29
|
+
defaultProps.modulesToPaste = [{ editorID: 1, component: "BasicContent" }];
|
|
29
30
|
|
|
30
31
|
describe("ComponentArraySelector component rendering", () => {
|
|
31
32
|
test("should render the component", async () => {
|
|
@@ -92,7 +93,7 @@ describe("ComponentArraySelector trigger events", () => {
|
|
|
92
93
|
});
|
|
93
94
|
expect(mockedFunction).toHaveBeenCalled();
|
|
94
95
|
await expect(mockedFunction(1, "", [{ editorID: 1, component: "BasicContent" }])).resolves.toEqual({});
|
|
95
|
-
expect(screen.getByTestId("toast-message")).toHaveTextContent("
|
|
96
|
+
expect(screen.getByTestId("toast-message")).toHaveTextContent("1 module pasted from clipboard");
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
test("should trigger the onClick and resolve promise without error", async () => {
|
|
@@ -110,7 +111,9 @@ describe("ComponentArraySelector trigger events", () => {
|
|
|
110
111
|
fireEvent.click(iconButton);
|
|
111
112
|
});
|
|
112
113
|
expect(mockedFunction).toHaveBeenCalled();
|
|
113
|
-
await expect(mockedFunction(1, "", [{ editorID: 1, component: "BasicContent" }])).resolves.toEqual({
|
|
114
|
-
|
|
114
|
+
await expect(mockedFunction(1, "", [{ editorID: 1, component: "BasicContent" }])).resolves.toEqual({
|
|
115
|
+
error: undefined,
|
|
116
|
+
});
|
|
117
|
+
expect(screen.getByTestId("toast-message")).toHaveTextContent("1 module pasted from clipboard");
|
|
115
118
|
});
|
|
116
119
|
});
|
package/src/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/index.tsx
CHANGED
|
@@ -16,7 +16,7 @@ const PasteModuleButton = (props: IPasteModuleProps): JSX.Element => {
|
|
|
16
16
|
slots,
|
|
17
17
|
} = props;
|
|
18
18
|
|
|
19
|
-
const { isVisible, toggleToast, setIsVisible } = useToast();
|
|
19
|
+
const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
|
|
20
20
|
|
|
21
21
|
const handlePasteModule = async () => {
|
|
22
22
|
if (isModuleCopyUnavailable) {
|
|
@@ -41,7 +41,7 @@ const PasteModuleButton = (props: IPasteModuleProps): JSX.Element => {
|
|
|
41
41
|
const { type, text } = pasteResult.error;
|
|
42
42
|
setNotification && setNotification({ type, text });
|
|
43
43
|
} else {
|
|
44
|
-
toggleToast();
|
|
44
|
+
toggleToast(`${modulesToPaste.length} module${modulesToPaste.length > 1 ? "s" : ""} pasted from clipboard`);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
};
|
|
@@ -51,7 +51,7 @@ const PasteModuleButton = (props: IPasteModuleProps): JSX.Element => {
|
|
|
51
51
|
<Tooltip content="Paste from clipboard">
|
|
52
52
|
<IconAction icon="paste" onClick={handlePasteModule} />
|
|
53
53
|
</Tooltip>
|
|
54
|
-
{isVisible && <Toast message=
|
|
54
|
+
{isVisible && <Toast message={`${toastState}`} setIsVisible={setIsVisible} />}
|
|
55
55
|
</>
|
|
56
56
|
);
|
|
57
57
|
};
|
|
@@ -187,9 +187,9 @@ const MixableComponentArray = (props: IMixableComponentArrayProps): JSX.Element
|
|
|
187
187
|
const onBeforeCapture = (start: BeforeCapture) => setDraggingId(parseInt(start.draggableId));
|
|
188
188
|
|
|
189
189
|
const handleCopy = () => {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
toggleToast(`${
|
|
190
|
+
const modulesCopied = copyModuleAction && copyModuleAction(selectedItems.all);
|
|
191
|
+
modulesCopied &&
|
|
192
|
+
toggleToast(`${modulesCopied} module${selectedItems.all.length > 1 ? "s" : ""} copied to clipboard`);
|
|
193
193
|
};
|
|
194
194
|
|
|
195
195
|
const handleDuplicate = () => {
|
|
@@ -318,7 +318,7 @@ export interface IMixableComponentArrayProps {
|
|
|
318
318
|
addModuleAction: (moduleType: string, key: string, selectedID: number, isComponentModule?: boolean) => void;
|
|
319
319
|
deleteModuleAction: (editorID: number[], key?: string) => void;
|
|
320
320
|
duplicateModuleAction: (editorID: number[], key?: string) => number;
|
|
321
|
-
copyModuleAction: (editorID: number[]) => boolean;
|
|
321
|
+
copyModuleAction: (editorID: number[]) => boolean | number;
|
|
322
322
|
replaceElementsInCollectionAction: (newValue: string, reference?: string) => void;
|
|
323
323
|
moveModuleAction: (moduleID: number[], selectedContent: any, newIndex: number, key: string) => void;
|
|
324
324
|
pasteModuleAction: (editorID: number, key: string, modulesToPaste: IModule[]) => Promise<{ error?: INotification }>;
|
|
@@ -234,7 +234,7 @@ export interface IComponentContainerProps {
|
|
|
234
234
|
addComponentAction: (componentType: any, key?: string) => void;
|
|
235
235
|
deleteModuleAction: (editorID: number[], key?: string) => void;
|
|
236
236
|
duplicateModuleAction: (editorID: number[], key?: string) => number;
|
|
237
|
-
copyModuleAction: (editorID: number[]) => boolean;
|
|
237
|
+
copyModuleAction: (editorID: number[]) => boolean | number;
|
|
238
238
|
replaceModuleAction: (module: any, parent: any, objKey: string) => void;
|
|
239
239
|
};
|
|
240
240
|
disabled?: boolean;
|
|
@@ -139,6 +139,7 @@ const Title = styled.span<{ disabled?: boolean }>`
|
|
|
139
139
|
const HandleWrapper = styled.div<{ hidden?: boolean }>`
|
|
140
140
|
display: ${(p) => (p.hidden ? "none" : "flex")};
|
|
141
141
|
align-items: center;
|
|
142
|
+
z-index: 1;
|
|
142
143
|
`;
|
|
143
144
|
|
|
144
145
|
const IconHandleWrapper = styled.div`
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import { withRouter, RouteComponentProps } from "react-router-dom";
|
|
3
3
|
|
|
4
4
|
import { IErrorItem } from "@ax/types";
|
|
5
5
|
import { trimText } from "@ax/helpers";
|
|
6
|
+
import { useModal } from "@ax/hooks";
|
|
6
7
|
import {
|
|
7
8
|
Button,
|
|
8
9
|
Icon,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
Tooltip,
|
|
15
16
|
ErrorCenter,
|
|
16
17
|
SearchField,
|
|
18
|
+
Modal,
|
|
17
19
|
} from "@ax/components";
|
|
18
20
|
|
|
19
21
|
import { ActionMenu, ActionSimpleMenu, DownArrowButton } from "./atoms";
|
|
@@ -47,6 +49,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
47
49
|
searchFilters,
|
|
48
50
|
hasAnimation,
|
|
49
51
|
searchValue,
|
|
52
|
+
isDirty,
|
|
50
53
|
} = props;
|
|
51
54
|
|
|
52
55
|
const publishedTooltip: any = {
|
|
@@ -59,6 +62,9 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
59
62
|
|
|
60
63
|
const fixedClass = fixedAppBar ? "fixed" : "";
|
|
61
64
|
|
|
65
|
+
const { isOpen, toggleModal } = useModal();
|
|
66
|
+
const [langSelected, setLangSelected] = useState(language);
|
|
67
|
+
|
|
62
68
|
const goToPages = () => {
|
|
63
69
|
typeof backLink === "string" ? props.history.push(backLink, { isFromEditor }) : props.history.goBack();
|
|
64
70
|
};
|
|
@@ -67,6 +73,11 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
67
73
|
pageLanguages && pageLanguages.find((pageLang: any) => pageLang.locale === lang);
|
|
68
74
|
|
|
69
75
|
const handleLanguage = (item: any) => async () => {
|
|
76
|
+
if (langSelected && langSelected.locale !== item.locale && isDirty) {
|
|
77
|
+
setLangSelected(item);
|
|
78
|
+
toggleModal();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
70
81
|
if (!languageActions || !languageActions.setLanguage) return;
|
|
71
82
|
|
|
72
83
|
const lang = {
|
|
@@ -144,7 +155,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
144
155
|
};
|
|
145
156
|
|
|
146
157
|
const PageStatus = () => {
|
|
147
|
-
const offset = rightButton || rightLineButton
|
|
158
|
+
const offset = rightButton || rightLineButton ? -20 : -135;
|
|
148
159
|
return statusMenu.options && statusMenu.options.length > 0 ? (
|
|
149
160
|
<FloatingMenu Button={StatusBtn} isInAppBar={true} position="left" offset={offset}>
|
|
150
161
|
<ActionSimpleMenu menu={statusMenu} />
|
|
@@ -152,11 +163,40 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
152
163
|
) : (
|
|
153
164
|
<Icon name={pageStatus ?? "offline"} size="24" />
|
|
154
165
|
);
|
|
155
|
-
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const modalText = <>If you change without saving it, it will be lost. Do you want to discard your changes?</>;
|
|
169
|
+
|
|
170
|
+
const mainAction = {
|
|
171
|
+
title: "Change language",
|
|
172
|
+
onClick: handleLanguage(langSelected),
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const secondaryAction = {
|
|
176
|
+
title: "Cancel",
|
|
177
|
+
onClick: () => {
|
|
178
|
+
setLangSelected(language);
|
|
179
|
+
toggleModal();
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const changeLanguageModalProps = {
|
|
184
|
+
isOpen,
|
|
185
|
+
hide: toggleModal,
|
|
186
|
+
title: "Change language",
|
|
187
|
+
mainAction,
|
|
188
|
+
secondaryAction,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const ChangeLanguageModal = () => (
|
|
192
|
+
<Modal {...changeLanguageModalProps}>
|
|
193
|
+
<S.ModalContent>{modalText}</S.ModalContent>
|
|
194
|
+
</Modal>
|
|
195
|
+
);
|
|
156
196
|
|
|
157
197
|
const languageTooltip = typeof currentPageID === "number" && "Add language";
|
|
158
198
|
|
|
159
|
-
const classes = hasAnimation ? `${fixedClass} ${additionalClass} animate` : `${fixedClass} ${additionalClass}
|
|
199
|
+
const classes = hasAnimation ? `${fixedClass} ${additionalClass} animate` : `${fixedClass} ${additionalClass}`;
|
|
160
200
|
|
|
161
201
|
return (
|
|
162
202
|
<S.Header className={classes} inversed={inversed} data-testid="appbar-header">
|
|
@@ -204,14 +244,20 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
204
244
|
)}
|
|
205
245
|
{language && (
|
|
206
246
|
<>
|
|
247
|
+
<ChangeLanguageModal />
|
|
207
248
|
<S.LanguageWrapper data-testid="language-wrapper">
|
|
208
249
|
<Tooltip content={languageTooltip} hideOnClick bottom>
|
|
209
|
-
<FloatingMenu
|
|
250
|
+
<FloatingMenu
|
|
251
|
+
Button={LanguageBtn}
|
|
252
|
+
isInAppBar={true}
|
|
253
|
+
position="left"
|
|
254
|
+
offset={rightButton || rightLineButton ? 0 : -85}
|
|
255
|
+
>
|
|
210
256
|
{languageMenu}
|
|
211
257
|
</FloatingMenu>
|
|
212
258
|
</Tooltip>
|
|
213
259
|
</S.LanguageWrapper>
|
|
214
|
-
{(pageStatus || rightButton || rightLineButton
|
|
260
|
+
{(pageStatus || rightButton || rightLineButton) && <S.Separator />}
|
|
215
261
|
</>
|
|
216
262
|
)}
|
|
217
263
|
{pageStatus && (
|
|
@@ -221,7 +267,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
221
267
|
<PageStatus />
|
|
222
268
|
</Tooltip>
|
|
223
269
|
</S.IconStatusWrapper>
|
|
224
|
-
{(rightButton || rightLineButton
|
|
270
|
+
{(rightButton || rightLineButton) && <S.Separator />}
|
|
225
271
|
</>
|
|
226
272
|
)}
|
|
227
273
|
{isFromEditor && errors && errors.length > 0 && (
|
|
@@ -297,6 +343,7 @@ export interface IAppBarProps {
|
|
|
297
343
|
pageStatusActions?: any[];
|
|
298
344
|
hasAnimation?: boolean;
|
|
299
345
|
searchValue?: string;
|
|
346
|
+
isDirty?: boolean;
|
|
300
347
|
}
|
|
301
348
|
|
|
302
349
|
type IProps = IAppBarProps & RouteComponentProps;
|
|
@@ -208,6 +208,16 @@ const SearchWrapper = styled.div<{ length: number }>`
|
|
|
208
208
|
justify-content: flex-end;
|
|
209
209
|
`;
|
|
210
210
|
|
|
211
|
+
const ModalContent = styled.div`
|
|
212
|
+
padding: ${(p) => p.theme.spacing.m};
|
|
213
|
+
p {
|
|
214
|
+
margin-bottom: ${(p) => p.theme.spacing.m};
|
|
215
|
+
}
|
|
216
|
+
div {
|
|
217
|
+
margin-bottom: 0;
|
|
218
|
+
}
|
|
219
|
+
`;
|
|
220
|
+
|
|
211
221
|
const StatusBtn = styled.span``;
|
|
212
222
|
|
|
213
223
|
export {
|
|
@@ -233,4 +243,5 @@ export {
|
|
|
233
243
|
TabsContent,
|
|
234
244
|
StatusBtn,
|
|
235
245
|
HelpText,
|
|
246
|
+
ModalContent,
|
|
236
247
|
};
|
|
@@ -6,7 +6,18 @@ import Button from "../Button";
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
8
8
|
const Modal = (props: IModalProps): JSX.Element | null => {
|
|
9
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
isOpen,
|
|
11
|
+
hide,
|
|
12
|
+
children,
|
|
13
|
+
title,
|
|
14
|
+
size,
|
|
15
|
+
mainAction,
|
|
16
|
+
secondaryAction,
|
|
17
|
+
height,
|
|
18
|
+
overflow = "auto",
|
|
19
|
+
isChild,
|
|
20
|
+
} = props;
|
|
10
21
|
|
|
11
22
|
const titleContent = title ? <S.Title>{title}</S.Title> : "";
|
|
12
23
|
|
|
@@ -73,7 +84,7 @@ export interface IModalProps {
|
|
|
73
84
|
|
|
74
85
|
interface IAction {
|
|
75
86
|
title: string;
|
|
76
|
-
onClick: () => void;
|
|
87
|
+
onClick: (item?: any) => void;
|
|
77
88
|
disabled?: boolean;
|
|
78
89
|
icon?: string;
|
|
79
90
|
}
|
|
@@ -669,7 +669,7 @@ function moveModule(
|
|
|
669
669
|
};
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
-
function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) => boolean {
|
|
672
|
+
function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) => boolean | number {
|
|
673
673
|
return (dispatch, getState) => {
|
|
674
674
|
const {
|
|
675
675
|
navigation: { editorContent },
|
|
@@ -691,7 +691,7 @@ function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) =>
|
|
|
691
691
|
elements: modulesToCopy,
|
|
692
692
|
};
|
|
693
693
|
dispatch(setCopyModule(payload));
|
|
694
|
-
return
|
|
694
|
+
return payload.elements.length;
|
|
695
695
|
} else {
|
|
696
696
|
return false;
|
|
697
697
|
}
|
|
@@ -878,7 +878,7 @@ function duplicateModule(editorID: number[], key?: string): (dispatch: Dispatch,
|
|
|
878
878
|
};
|
|
879
879
|
}
|
|
880
880
|
|
|
881
|
-
function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) => boolean {
|
|
881
|
+
function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) => boolean | number {
|
|
882
882
|
return (dispatch, getState) => {
|
|
883
883
|
const { sections } = getStateValues(getState);
|
|
884
884
|
const modulesToCopy: Record<string, unknown>[] = [];
|
|
@@ -899,7 +899,7 @@ function copyModule(editorID: number[]): (dispatch: Dispatch, getState: any) =>
|
|
|
899
899
|
|
|
900
900
|
dispatch(setCopyModule(payload));
|
|
901
901
|
|
|
902
|
-
return
|
|
902
|
+
return payload.elements.length;
|
|
903
903
|
} else {
|
|
904
904
|
return false;
|
|
905
905
|
}
|
|
@@ -924,7 +924,7 @@ function pasteModule(
|
|
|
924
924
|
|
|
925
925
|
let error: INotification | undefined;
|
|
926
926
|
|
|
927
|
-
|
|
927
|
+
for (const element of modulesToPaste) {
|
|
928
928
|
const { isMaxModules, errorMessage } = checkMaxModules(editorContent, element.component);
|
|
929
929
|
if (isMaxModules && errorMessage) {
|
|
930
930
|
error = {
|
|
@@ -958,7 +958,7 @@ function pasteModule(
|
|
|
958
958
|
}
|
|
959
959
|
|
|
960
960
|
itemsArr.push(validatedModuleCopy);
|
|
961
|
-
}
|
|
961
|
+
}
|
|
962
962
|
|
|
963
963
|
const updatedPageContent = {
|
|
964
964
|
...editorContent,
|
|
@@ -95,7 +95,7 @@ interface IPageBrowserDispatchProps {
|
|
|
95
95
|
moveElement(moduleID: number[], selectedContent: any, newIndex: number, key: string): void;
|
|
96
96
|
replaceModule(module: any, parent: any, objKey: string): void;
|
|
97
97
|
replaceElementsInCollection(newValue: string, reference: string): void;
|
|
98
|
-
copyModule(editorID: number[]): boolean;
|
|
98
|
+
copyModule(editorID: number[]): boolean | number;
|
|
99
99
|
pasteModule(editorID: number, key: string, modulesToPaste: IModule[]): Promise<{ error?: INotification }>;
|
|
100
100
|
setNotification: (notification: INotification) => void;
|
|
101
101
|
isGlobal: boolean;
|
|
@@ -346,11 +346,13 @@ const GlobalEditor = (props: IProps) => {
|
|
|
346
346
|
}
|
|
347
347
|
};
|
|
348
348
|
|
|
349
|
-
const rightButtonProps = isAllowedToEditContentPage
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
349
|
+
const rightButtonProps = isAllowedToEditContentPage
|
|
350
|
+
? {
|
|
351
|
+
label: isSaving ? "Saving" : getSaveLabel(),
|
|
352
|
+
disabled: (!isDirty && pageID !== null && !isNewTranslation) || isSaving || isReadOnly,
|
|
353
|
+
action: isPublished ? publishChanges : handleSavePage,
|
|
354
|
+
}
|
|
355
|
+
: undefined;
|
|
354
356
|
|
|
355
357
|
const goToLivePage = () => {
|
|
356
358
|
const currentPageUrl = editorContent.fullUrl;
|
|
@@ -453,6 +455,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
453
455
|
isFromEditor={true}
|
|
454
456
|
pageStatusActions={pageStatusActions}
|
|
455
457
|
tabs={tabsPreview}
|
|
458
|
+
isDirty={isDirty}
|
|
456
459
|
>
|
|
457
460
|
{selectedTab === "edit" ? (
|
|
458
461
|
<>
|
|
@@ -463,12 +466,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
463
466
|
)}
|
|
464
467
|
{sitePageID && (
|
|
465
468
|
<S.NotificationWrapper>
|
|
466
|
-
<Notification
|
|
467
|
-
type="info"
|
|
468
|
-
text={globalNotificationText}
|
|
469
|
-
btnText="Go Back"
|
|
470
|
-
onClick={goBackToSite}
|
|
471
|
-
/>
|
|
469
|
+
<Notification type="info" text={globalNotificationText} btnText="Go Back" onClick={goBackToSite} />
|
|
472
470
|
</S.NotificationWrapper>
|
|
473
471
|
)}
|
|
474
472
|
{notification && (
|
|
@@ -92,7 +92,7 @@ interface IPageBrowserDispatchProps {
|
|
|
92
92
|
replaceModule(module: any, parent: any, objKey: string): void;
|
|
93
93
|
replaceElementsInCollection(newValue: string, reference: string): void;
|
|
94
94
|
moveModule(moduleID: number[], selectedContent: any, newIndex: number, key: string): void;
|
|
95
|
-
copyModule(editorID: number[]): boolean;
|
|
95
|
+
copyModule(editorID: number[]): boolean | number;
|
|
96
96
|
pasteModule(editorID: number, key: string, modulesToPaste: IModule[]): Promise<{ error?: INotification }>;
|
|
97
97
|
setNotification: (notification: INotification) => void;
|
|
98
98
|
browserRef?: React.RefObject<HTMLDivElement>;
|
|
@@ -133,7 +133,7 @@ interface IPageBrowserDispatchProps {
|
|
|
133
133
|
setHistoryPush(path: string, isEditor: boolean): void;
|
|
134
134
|
getGlobalFromLocalPage(): void;
|
|
135
135
|
saveCurrentSiteInfo(): void;
|
|
136
|
-
copyModule(editorID: number[]): boolean;
|
|
136
|
+
copyModule(editorID: number[]): boolean | number;
|
|
137
137
|
pasteModule(editorID: number, key: string, modulesToPaste: IModule[]): Promise<{ error?: INotification }>;
|
|
138
138
|
setNotification: (notification: INotification) => void;
|
|
139
139
|
restorePageNavigation: (key: string) => void;
|