@griddo/ax 11.12.0 → 11.12.1-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/config/jest/componentsMock.js +7 -5
- package/package.json +2 -2
- package/src/__tests__/components/Browser/Browser.test.tsx +438 -87
- package/src/__tests__/components/Browser/Browser.utils.test.ts +55 -0
- package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +1 -3
- package/src/__tests__/components/Fields/Button/Button.test.tsx +29 -27
- package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/ErrorItem.test.tsx +158 -0
- package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorsBanner.test.tsx +90 -0
- package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.test.tsx +178 -0
- package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.utils.test.tsx +150 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordItem/KeywordItem.test.tsx +91 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.test.tsx +122 -0
- package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.utils.test.ts +15 -0
- package/src/__tests__/components/KeywordsPreviewModal/atoms.test.tsx +101 -0
- package/src/__tests__/components/ResizePanel/ResizePanel.test.tsx +1 -1
- package/src/__tests__/modules/FramePreview/FramePreview.test.tsx +318 -0
- package/src/__tests__/modules/FramePreview/FramePreview.utils.test.ts +242 -0
- package/src/__tests__/modules/FramePreview/HeadingsOverlay/HeadingsOverlay.test.tsx +185 -0
- package/src/components/Browser/index.tsx +294 -149
- package/src/components/Browser/style.tsx +75 -6
- package/src/components/Browser/utils.tsx +13 -0
- package/src/components/Button/index.tsx +2 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +2 -4
- package/src/components/Fields/AsyncSelect/style.tsx +13 -0
- package/src/components/Fields/FieldGroup/index.tsx +5 -2
- package/src/components/Fields/FieldGroup/style.tsx +32 -7
- package/src/components/Fields/HeadingField/index.tsx +22 -22
- package/src/components/Fields/HiddenField/style.tsx +1 -1
- package/src/components/Fields/NumberField/index.tsx +15 -16
- package/src/components/Fields/NumberField/style.tsx +2 -0
- package/src/components/Fields/ReferenceField/index.tsx +1 -1
- package/src/components/Fields/SEOPreview/index.tsx +36 -0
- package/src/components/Fields/SEOPreview/style.tsx +24 -0
- package/src/components/Fields/Select/index.tsx +5 -1
- package/src/components/Fields/Select/style.tsx +56 -0
- package/src/components/Fields/SummaryButton/index.tsx +18 -9
- package/src/components/Fields/SummaryButton/style.tsx +1 -2
- package/src/components/Fields/TagsField/index.tsx +8 -9
- package/src/components/Fields/UrlField/index.tsx +26 -27
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FloatingNote/index.tsx +35 -0
- package/src/components/FloatingNote/style.tsx +26 -0
- package/src/components/FloatingPanel/index.tsx +5 -2
- package/src/components/FloatingPanel/style.tsx +2 -1
- package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/index.tsx +85 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/style.tsx +80 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/index.tsx +57 -0
- package/src/components/HeadingsPreviewModal/ErrorsBanner/style.tsx +82 -0
- package/src/components/HeadingsPreviewModal/HeadingItem/index.tsx +71 -0
- package/src/components/HeadingsPreviewModal/HeadingItem/style.tsx +77 -0
- package/src/components/HeadingsPreviewModal/index.tsx +148 -0
- package/src/components/HeadingsPreviewModal/style.tsx +82 -0
- package/src/components/HeadingsPreviewModal/utils.tsx +329 -0
- package/src/components/Icon/index.tsx +1 -2
- package/src/components/IconAction/index.tsx +1 -1
- package/src/components/KeywordsPreviewModal/KeywordItem/index.tsx +46 -0
- package/src/components/KeywordsPreviewModal/KeywordItem/style.tsx +64 -0
- package/src/components/KeywordsPreviewModal/atoms.tsx +96 -0
- package/src/components/KeywordsPreviewModal/index.tsx +99 -0
- package/src/components/KeywordsPreviewModal/style.tsx +87 -0
- package/src/components/KeywordsPreviewModal/utils.tsx +22 -0
- package/src/components/MainWrapper/AppBar/index.tsx +8 -1
- package/src/components/MainWrapper/index.tsx +7 -1
- package/src/components/Notification/index.tsx +2 -2
- package/src/components/PageFinder/index.tsx +1 -1
- package/src/components/ResizePanel/index.tsx +4 -3
- package/src/components/ResizePanel/style.tsx +1 -1
- package/src/components/SearchField/style.tsx +2 -2
- package/src/components/SideModal/index.tsx +2 -1
- package/src/components/Tabs/index.tsx +13 -4
- package/src/components/Tabs/style.tsx +7 -8
- package/src/components/Toast/index.tsx +4 -2
- package/src/components/Tooltip/index.tsx +4 -3
- package/src/components/index.tsx +8 -0
- package/src/forms/fields.tsx +70 -68
- package/src/hooks/forms.tsx +22 -1
- package/src/hooks/index.tsx +13 -3
- package/src/hooks/modals.tsx +103 -15
- package/src/hooks/users.tsx +25 -8
- package/src/modules/Forms/atoms.tsx +2 -2
- package/src/modules/FramePreview/HeadingsOverlay/index.tsx +116 -0
- package/src/modules/FramePreview/HeadingsOverlay/style.tsx +34 -0
- package/src/modules/FramePreview/index.tsx +55 -16
- package/src/modules/FramePreview/style.tsx +34 -2
- package/src/modules/FramePreview/utils.tsx +140 -0
- package/src/modules/GlobalEditor/Editor/index.tsx +37 -3
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +19 -2
- package/src/modules/GlobalEditor/Preview/index.tsx +0 -2
- package/src/modules/GlobalEditor/Preview/style.tsx +1 -1
- package/src/modules/GlobalEditor/index.tsx +119 -57
- package/src/modules/PageEditor/Editor/index.tsx +33 -2
- package/src/modules/PageEditor/PageBrowser/index.tsx +20 -2
- package/src/modules/PageEditor/Preview/index.tsx +0 -2
- package/src/modules/PageEditor/Preview/style.tsx +1 -1
- package/src/modules/PageEditor/atoms.tsx +1 -1
- package/src/modules/PageEditor/index.tsx +130 -66
- package/src/modules/PublicPreview/index.tsx +5 -2
- package/src/schemas/pages/GlobalPage.ts +87 -70
- package/src/schemas/pages/Page.ts +87 -70
- package/src/types/index.tsx +12 -0
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
CancelScheduleModal,
|
|
8
8
|
ErrorPage,
|
|
9
9
|
ErrorToast,
|
|
10
|
+
HeadingsPreviewModal,
|
|
11
|
+
KeywordsPreviewModal,
|
|
10
12
|
Loading,
|
|
11
13
|
MainWrapper,
|
|
12
14
|
Modal,
|
|
@@ -22,8 +24,9 @@ import { pageStatus } from "@ax/containers/PageEditor/interfaces";
|
|
|
22
24
|
import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
|
|
23
25
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
24
26
|
import { dateToString, getDeactivatedModules, isModuleDisabled } from "@ax/helpers";
|
|
25
|
-
import { useIsDirty,
|
|
27
|
+
import { useIsDirty, useModals, usePermissions } from "@ax/hooks";
|
|
26
28
|
import type {
|
|
29
|
+
HeadingFilter,
|
|
27
30
|
IErrorItem,
|
|
28
31
|
ILanguage,
|
|
29
32
|
INotification,
|
|
@@ -70,15 +73,18 @@ const PageEditor = (props: IProps) => {
|
|
|
70
73
|
setCurrentPageID,
|
|
71
74
|
restorePage,
|
|
72
75
|
schemaVersion,
|
|
76
|
+
updateEditorContent,
|
|
73
77
|
} = props;
|
|
74
78
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
const isAllowedTo = usePermissions({
|
|
80
|
+
publishPages: "content.publishUnpublishPages",
|
|
81
|
+
createPages: "content.createPages",
|
|
82
|
+
deletePages: "content.deletePages",
|
|
83
|
+
deletePublishedPages: "content.deletePublishedPages",
|
|
84
|
+
editContentPages: "content.editContentPages",
|
|
85
|
+
});
|
|
80
86
|
|
|
81
|
-
const defaultTab =
|
|
87
|
+
const defaultTab = isAllowedTo.editContentPages ? "edit" : "view";
|
|
82
88
|
|
|
83
89
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
84
90
|
const [isReadOnly, setIsReadOnly] = useState(false);
|
|
@@ -86,18 +92,26 @@ const PageEditor = (props: IProps) => {
|
|
|
86
92
|
const [notification, setNotification] = useState<INotification | null>(null);
|
|
87
93
|
const [toastMsg, setToastMsg] = useState<string | null>(null);
|
|
88
94
|
const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
|
|
89
|
-
const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
|
|
90
|
-
const { isOpen, toggleModal } = useModal();
|
|
91
|
-
const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
|
|
92
|
-
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
93
|
-
const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
|
|
94
|
-
const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
|
|
95
|
-
const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
|
|
96
|
-
const { isOpen: isDirtyNavigateOpen, toggleModal: toggleDirtyNavigateModal } = useModal();
|
|
97
95
|
const [pendingNavigateCallback, setPendingNavigateCallback] = useState<(() => void) | null>(null);
|
|
98
96
|
const [errorPagesChecked, setErrorPagesChecked] = useState(false);
|
|
97
|
+
const [headingsFilter, setHeadingsFilter] = useState<HeadingFilter>("all");
|
|
98
|
+
const [keywordsFilter, setKeywordsFilter] = useState<string[]>([]);
|
|
99
99
|
const browserRef = useRef<HTMLDivElement>(null);
|
|
100
100
|
|
|
101
|
+
const { isOpen, toggleModal } = useModals([
|
|
102
|
+
"userEditing",
|
|
103
|
+
"unpublish",
|
|
104
|
+
"delete",
|
|
105
|
+
"schedule",
|
|
106
|
+
"cancelSchedule",
|
|
107
|
+
"restore",
|
|
108
|
+
"headingsPreview",
|
|
109
|
+
"keywordsPreview",
|
|
110
|
+
"dirtyNavigate",
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
|
|
114
|
+
|
|
101
115
|
const isGlobal = editorContent && editorContent.origin === "GLOBAL";
|
|
102
116
|
const isEditable = editorContent?.editable;
|
|
103
117
|
const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
|
|
@@ -107,11 +121,13 @@ const PageEditor = (props: IProps) => {
|
|
|
107
121
|
const isTranslated = pageLanguages.length > 1;
|
|
108
122
|
const structuredData = editorContent ? editorContent.structuredData : "";
|
|
109
123
|
const isEditLive = isPublished && hasDraft;
|
|
110
|
-
const isAllowedToDelete =
|
|
124
|
+
const isAllowedToDelete =
|
|
125
|
+
(isPublished && isAllowedTo.deletePublishedPages) || (!isPublished && isAllowedTo.deletePages);
|
|
111
126
|
const canBeUnpublished = editorContent?.canBeUnpublished;
|
|
112
127
|
const deleteHelpText = !canBeUnpublished ? "This is the canonical site of the page. You cannot unpublish it." : null;
|
|
113
128
|
const isScheduled = !!editorContent && !!editorContent.publicationScheduled;
|
|
114
129
|
const isDeleted = editorContent.deleted;
|
|
130
|
+
const defaultContentTab = "content";
|
|
115
131
|
|
|
116
132
|
const errorNotificationText =
|
|
117
133
|
"There are some errors on the page so you can not publish yet. Please review them in the error panel.";
|
|
@@ -126,13 +142,13 @@ const PageEditor = (props: IProps) => {
|
|
|
126
142
|
|
|
127
143
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
128
144
|
useEffect(() => {
|
|
129
|
-
const { pageID, getPage,
|
|
130
|
-
|
|
145
|
+
const { pageID, getPage, sendPagePing } = props;
|
|
146
|
+
|
|
131
147
|
const handleGetPage = async () => {
|
|
132
148
|
await getPage(pageID);
|
|
133
149
|
};
|
|
134
150
|
|
|
135
|
-
setTab(
|
|
151
|
+
setTab(defaultContentTab);
|
|
136
152
|
resetDirty();
|
|
137
153
|
setToastMsg(null);
|
|
138
154
|
handleGetPage();
|
|
@@ -152,11 +168,11 @@ const PageEditor = (props: IProps) => {
|
|
|
152
168
|
const { pageID, sendPagePing, currentUserID } = props;
|
|
153
169
|
if (userEditing && userEditing.id !== currentUserID) {
|
|
154
170
|
setIsReadOnly(true);
|
|
155
|
-
!isOpen && toggleModal();
|
|
171
|
+
!isOpen("userEditing") && toggleModal("userEditing");
|
|
156
172
|
} else {
|
|
157
173
|
setIsReadOnly(false);
|
|
158
174
|
pageID && sendPagePing(pageID);
|
|
159
|
-
isOpen && toggleModal();
|
|
175
|
+
isOpen("userEditing") && toggleModal("userEditing");
|
|
160
176
|
}
|
|
161
177
|
}, [userEditing]);
|
|
162
178
|
|
|
@@ -179,7 +195,7 @@ const PageEditor = (props: IProps) => {
|
|
|
179
195
|
const allPageVersions = pageLanguages.map((lang: IPageLanguage) => lang.pageId);
|
|
180
196
|
const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage();
|
|
181
197
|
|
|
182
|
-
|
|
198
|
+
toggleModal("delete");
|
|
183
199
|
if (isDeleted) {
|
|
184
200
|
setRoute(path);
|
|
185
201
|
}
|
|
@@ -265,7 +281,7 @@ const PageEditor = (props: IProps) => {
|
|
|
265
281
|
discardDraft();
|
|
266
282
|
};
|
|
267
283
|
|
|
268
|
-
const
|
|
284
|
+
const handleDiscardChanges = () => {
|
|
269
285
|
const { getPage, pageID } = props;
|
|
270
286
|
resetDirty();
|
|
271
287
|
|
|
@@ -285,7 +301,7 @@ const PageEditor = (props: IProps) => {
|
|
|
285
301
|
const saved = await schedulePublication(dateString, isDraft);
|
|
286
302
|
if (saved) {
|
|
287
303
|
resetDirty();
|
|
288
|
-
|
|
304
|
+
toggleModal("schedule");
|
|
289
305
|
}
|
|
290
306
|
};
|
|
291
307
|
|
|
@@ -294,7 +310,7 @@ const PageEditor = (props: IProps) => {
|
|
|
294
310
|
if (saved) {
|
|
295
311
|
setScheduleDate({ date: "", time: "12:00 am" });
|
|
296
312
|
resetDirty();
|
|
297
|
-
|
|
313
|
+
toggleModal("cancelSchedule");
|
|
298
314
|
}
|
|
299
315
|
};
|
|
300
316
|
|
|
@@ -315,7 +331,7 @@ const PageEditor = (props: IProps) => {
|
|
|
315
331
|
}
|
|
316
332
|
: {
|
|
317
333
|
label: status === pageStatus.UPLOAD_PENDING ? "Cancel publication" : "Unpublish",
|
|
318
|
-
action: hasDraft ?
|
|
334
|
+
action: hasDraft ? () => toggleModal("unpublish") : unpublishPage,
|
|
319
335
|
disabled: !canBeUnpublished,
|
|
320
336
|
helpText: deleteHelpText,
|
|
321
337
|
};
|
|
@@ -332,24 +348,24 @@ const PageEditor = (props: IProps) => {
|
|
|
332
348
|
|
|
333
349
|
const menuOptions = [];
|
|
334
350
|
|
|
335
|
-
if (
|
|
351
|
+
if (isAllowedTo.publishPages && !isScheduled && !isPublished && props.pageStatus !== pageStatus.OFFLINE_PENDING) {
|
|
336
352
|
menuOptions.push({
|
|
337
353
|
label: "Schedule",
|
|
338
354
|
icon: "calendar",
|
|
339
|
-
action:
|
|
355
|
+
action: () => toggleModal("schedule"),
|
|
340
356
|
});
|
|
341
357
|
}
|
|
342
358
|
|
|
343
|
-
if (
|
|
359
|
+
if (isAllowedTo.publishPages && isScheduled) {
|
|
344
360
|
menuOptions.push({
|
|
345
361
|
label: "Cancel Schedule",
|
|
346
362
|
icon: "cancelEvent",
|
|
347
|
-
action:
|
|
363
|
+
action: () => toggleModal("cancelSchedule"),
|
|
348
364
|
});
|
|
349
365
|
}
|
|
350
366
|
|
|
351
367
|
if (
|
|
352
|
-
|
|
368
|
+
isAllowedTo.editContentPages &&
|
|
353
369
|
(props.pageStatus === pageStatus.PUBLISHED ||
|
|
354
370
|
props.pageStatus === pageStatus.OFFLINE ||
|
|
355
371
|
props.pageStatus === pageStatus.OFFLINE_PENDING ||
|
|
@@ -363,19 +379,19 @@ const PageEditor = (props: IProps) => {
|
|
|
363
379
|
});
|
|
364
380
|
}
|
|
365
381
|
|
|
366
|
-
if (props.pageStatus === pageStatus.PUBLISHED && !hasDraft && isDirty &&
|
|
382
|
+
if (props.pageStatus === pageStatus.PUBLISHED && !hasDraft && isDirty && isAllowedTo.publishPages) {
|
|
367
383
|
menuOptions.push({
|
|
368
384
|
label: "Unpublish",
|
|
369
385
|
icon: "offline",
|
|
370
|
-
action: isDraft ?
|
|
386
|
+
action: isDraft ? () => toggleModal("unpublish") : unpublishPage,
|
|
371
387
|
});
|
|
372
388
|
}
|
|
373
389
|
|
|
374
|
-
if (
|
|
390
|
+
if (isAllowedTo.editContentPages && !isScheduled && (isDraft || (isPublished && isDirty))) {
|
|
375
391
|
menuOptions.push({
|
|
376
392
|
label: "Discard changes",
|
|
377
393
|
icon: "close",
|
|
378
|
-
action: isDraft ? handleDiscardDraft :
|
|
394
|
+
action: isDraft ? handleDiscardDraft : handleDiscardChanges,
|
|
379
395
|
});
|
|
380
396
|
}
|
|
381
397
|
|
|
@@ -383,13 +399,13 @@ const PageEditor = (props: IProps) => {
|
|
|
383
399
|
menuOptions.push({
|
|
384
400
|
label: "Delete page",
|
|
385
401
|
icon: "delete",
|
|
386
|
-
action:
|
|
402
|
+
action: () => toggleModal("delete"),
|
|
387
403
|
});
|
|
388
404
|
}
|
|
389
405
|
|
|
390
406
|
const downArrowMenu = {
|
|
391
407
|
displayed: !isReadOnly && !isDeleted,
|
|
392
|
-
button:
|
|
408
|
+
button: isAllowedTo.publishPages ? getPublishButton(props.pageStatus) : undefined,
|
|
393
409
|
options: !isGlobal ? menuOptions : [],
|
|
394
410
|
};
|
|
395
411
|
|
|
@@ -437,7 +453,7 @@ const PageEditor = (props: IProps) => {
|
|
|
437
453
|
}
|
|
438
454
|
|
|
439
455
|
let availableLanguages = siteLanguages;
|
|
440
|
-
if (!isTemplateActivated || hasDeactivatedModules || !
|
|
456
|
+
if (!isTemplateActivated || hasDeactivatedModules || !isAllowedTo.createPages || isDeleted) {
|
|
441
457
|
const pageLanguagesIDs = pageLanguages.map((language) => language.languageId);
|
|
442
458
|
availableLanguages = siteLanguages.filter((language) => {
|
|
443
459
|
return pageLanguagesIDs.includes(language.id);
|
|
@@ -462,7 +478,7 @@ const PageEditor = (props: IProps) => {
|
|
|
462
478
|
}
|
|
463
479
|
};
|
|
464
480
|
|
|
465
|
-
const rightButtonProps =
|
|
481
|
+
const rightButtonProps = isAllowedTo.editContentPages
|
|
466
482
|
? {
|
|
467
483
|
label: isSaving ? "Saving" : getSaveLabel(),
|
|
468
484
|
disabled:
|
|
@@ -539,33 +555,33 @@ const PageEditor = (props: IProps) => {
|
|
|
539
555
|
props.setHistoryPush(backLinkRoute, false);
|
|
540
556
|
};
|
|
541
557
|
|
|
542
|
-
const mainAction = { title: "Preview Page", onClick: toggleModal };
|
|
558
|
+
const mainAction = { title: "Preview Page", onClick: () => toggleModal("userEditing") };
|
|
543
559
|
const secondaryAction = { title: "Ok, go back", onClick: handleGoBack };
|
|
544
560
|
|
|
545
|
-
const mainUnpublishAction = { title: "Ok", onClick:
|
|
561
|
+
const mainUnpublishAction = { title: "Ok", onClick: () => toggleModal("unpublish") };
|
|
546
562
|
|
|
547
563
|
const mainDeleteModalAction = {
|
|
548
564
|
title: "Delete page",
|
|
549
565
|
onClick: removePage,
|
|
550
566
|
};
|
|
551
567
|
|
|
552
|
-
const secondaryDeleteModalAction = { title: "Cancel", onClick:
|
|
568
|
+
const secondaryDeleteModalAction = { title: "Cancel", onClick: () => toggleModal("delete") };
|
|
553
569
|
|
|
554
570
|
const mainScheduleModalAction = {
|
|
555
571
|
title: "Schedule",
|
|
556
572
|
onClick: handleSchedulePublication,
|
|
557
573
|
};
|
|
558
574
|
|
|
559
|
-
const secondaryScheduleModalAction = { title: "Cancel", onClick:
|
|
575
|
+
const secondaryScheduleModalAction = { title: "Cancel", onClick: () => toggleModal("schedule") };
|
|
560
576
|
|
|
561
577
|
const mainCancelScheduleModalAction = {
|
|
562
578
|
title: "Cancel Schedule",
|
|
563
579
|
onClick: handleCancelSchedulePublication,
|
|
564
580
|
};
|
|
565
581
|
|
|
566
|
-
const secondaryCancelScheduleModalAction = { title: "Back", onClick:
|
|
582
|
+
const secondaryCancelScheduleModalAction = { title: "Back", onClick: () => toggleModal("cancelSchedule") };
|
|
567
583
|
|
|
568
|
-
const tabIcons =
|
|
584
|
+
const tabIcons = isAllowedTo.editContentPages
|
|
569
585
|
? [
|
|
570
586
|
{ name: "edit", text: "Edit mode" },
|
|
571
587
|
{ name: "view", text: "Preview mode" },
|
|
@@ -583,6 +599,7 @@ const PageEditor = (props: IProps) => {
|
|
|
583
599
|
icons: tabIcons,
|
|
584
600
|
selectedTab,
|
|
585
601
|
action: (tab: string) => handleSelectedTab(tab),
|
|
602
|
+
disabled: isOpen("headingsPreview") || isOpen("keywordsPreview"),
|
|
586
603
|
};
|
|
587
604
|
|
|
588
605
|
const contentLanguages: ILanguage[] = [];
|
|
@@ -610,7 +627,7 @@ const PageEditor = (props: IProps) => {
|
|
|
610
627
|
await getPage(selectedPageLanguage.pageId, false, isDraft);
|
|
611
628
|
resetDirty();
|
|
612
629
|
} else {
|
|
613
|
-
|
|
630
|
+
isAllowedTo.editContentPages && setSelectedTab("edit");
|
|
614
631
|
createNewTranslation(true);
|
|
615
632
|
await getPage(pageID);
|
|
616
633
|
}
|
|
@@ -619,18 +636,40 @@ const PageEditor = (props: IProps) => {
|
|
|
619
636
|
const handleRestorePage = async () => {
|
|
620
637
|
const isRestored = await restorePage(pageID);
|
|
621
638
|
if (isRestored) {
|
|
622
|
-
|
|
639
|
+
isOpen("restore") && toggleModal("restore");
|
|
623
640
|
await getPage(pageID);
|
|
624
641
|
}
|
|
625
642
|
};
|
|
626
643
|
|
|
644
|
+
const handleAddKeywords = (newKeywords: string[]) => {
|
|
645
|
+
const keywords: string[] = [...editorContent.metaKeywords, ...newKeywords];
|
|
646
|
+
updateEditorContent(0, "metaKeywords", keywords);
|
|
647
|
+
handleSavePage();
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
const handledeleteKeyword = (keyword: string) => {
|
|
651
|
+
const newKeywords = (editorContent.metaKeywords as string[]).filter((key) => key !== keyword);
|
|
652
|
+
updateEditorContent(0, "metaKeywords", newKeywords);
|
|
653
|
+
handleSavePage();
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const handleToggleHeadingsEditor = () => {
|
|
657
|
+
toggleModal("headingsPreview");
|
|
658
|
+
setTab(defaultContentTab);
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
const handleToggleKeywordsEditor = () => {
|
|
662
|
+
toggleModal("keywordsPreview");
|
|
663
|
+
setTab(defaultContentTab);
|
|
664
|
+
};
|
|
665
|
+
|
|
627
666
|
const onNavigateWithDirty = (navigateCallback: () => void) => {
|
|
628
667
|
setPendingNavigateCallback(() => navigateCallback);
|
|
629
|
-
|
|
668
|
+
toggleModal("dirtyNavigate");
|
|
630
669
|
};
|
|
631
670
|
|
|
632
671
|
const handleConfirmDirtyNavigation = () => {
|
|
633
|
-
|
|
672
|
+
toggleModal("dirtyNavigate");
|
|
634
673
|
if (pendingNavigateCallback) {
|
|
635
674
|
pendingNavigateCallback();
|
|
636
675
|
setPendingNavigateCallback(null);
|
|
@@ -638,7 +677,7 @@ const PageEditor = (props: IProps) => {
|
|
|
638
677
|
};
|
|
639
678
|
|
|
640
679
|
const handleCancelDirtyNavigation = () => {
|
|
641
|
-
|
|
680
|
+
toggleModal("dirtyNavigate");
|
|
642
681
|
setPendingNavigateCallback(null);
|
|
643
682
|
};
|
|
644
683
|
|
|
@@ -704,7 +743,7 @@ const PageEditor = (props: IProps) => {
|
|
|
704
743
|
type="error"
|
|
705
744
|
text={deletedNotificationText}
|
|
706
745
|
btnText="Restore page"
|
|
707
|
-
onClick={
|
|
746
|
+
onClick={() => toggleModal("restore")}
|
|
708
747
|
/>
|
|
709
748
|
</S.NotificationWrapper>
|
|
710
749
|
)}
|
|
@@ -736,6 +775,12 @@ const PageEditor = (props: IProps) => {
|
|
|
736
775
|
setNotification={setNotification}
|
|
737
776
|
isEditLive={isEditLive}
|
|
738
777
|
isDisabled={isDeleted}
|
|
778
|
+
toggleHeadingsPreview={handleToggleHeadingsEditor}
|
|
779
|
+
isHeadingsPreviewOpen={isOpen("headingsPreview")}
|
|
780
|
+
headingsFilter={headingsFilter}
|
|
781
|
+
toggleKeywordsPreview={handleToggleKeywordsEditor}
|
|
782
|
+
isKeywordsPreviewOpen={isOpen("keywordsPreview")}
|
|
783
|
+
keywordsFilter={keywordsFilter}
|
|
739
784
|
isDirty={isDirty}
|
|
740
785
|
onNavigateWithDirty={onNavigateWithDirty}
|
|
741
786
|
/>
|
|
@@ -749,14 +794,14 @@ const PageEditor = (props: IProps) => {
|
|
|
749
794
|
)}
|
|
750
795
|
|
|
751
796
|
<Modal
|
|
752
|
-
isOpen={isOpen}
|
|
753
|
-
hide={toggleModal}
|
|
797
|
+
isOpen={isOpen("userEditing")}
|
|
798
|
+
hide={() => toggleModal("userEditing")}
|
|
754
799
|
size="S"
|
|
755
800
|
title="This page is currently being edited"
|
|
756
801
|
mainAction={mainAction}
|
|
757
802
|
secondaryAction={secondaryAction}
|
|
758
803
|
>
|
|
759
|
-
{isOpen && (
|
|
804
|
+
{isOpen("userEditing") && (
|
|
760
805
|
<S.ModalContent>
|
|
761
806
|
<p>
|
|
762
807
|
<strong>{userEditing?.name}</strong> is currently working on this page. You can preview the page but{" "}
|
|
@@ -766,13 +811,13 @@ const PageEditor = (props: IProps) => {
|
|
|
766
811
|
)}
|
|
767
812
|
</Modal>
|
|
768
813
|
<Modal
|
|
769
|
-
isOpen={
|
|
770
|
-
hide={
|
|
814
|
+
isOpen={isOpen("unpublish")}
|
|
815
|
+
hide={() => toggleModal("unpublish")}
|
|
771
816
|
size="S"
|
|
772
817
|
title="Unpublish Modified Page"
|
|
773
818
|
mainAction={mainUnpublishAction}
|
|
774
819
|
>
|
|
775
|
-
{
|
|
820
|
+
{isOpen("unpublish") && (
|
|
776
821
|
<S.ModalContent>
|
|
777
822
|
<p>
|
|
778
823
|
There are some saved changes that are not published on this page. To Unpublish this page,{" "}
|
|
@@ -782,37 +827,54 @@ const PageEditor = (props: IProps) => {
|
|
|
782
827
|
)}
|
|
783
828
|
</Modal>
|
|
784
829
|
<DeleteModal
|
|
785
|
-
isOpen={
|
|
786
|
-
toggleModal={
|
|
830
|
+
isOpen={isOpen("delete")}
|
|
831
|
+
toggleModal={() => toggleModal("delete")}
|
|
787
832
|
mainModalAction={mainDeleteModalAction}
|
|
788
833
|
secondaryModalAction={secondaryDeleteModalAction}
|
|
789
834
|
{...{ isTranslated, deleteAllVersions, setDeleteAllVersions }}
|
|
790
835
|
/>
|
|
791
836
|
<ScheduleModal
|
|
792
|
-
isOpen={
|
|
793
|
-
toggleModal={
|
|
837
|
+
isOpen={isOpen("schedule")}
|
|
838
|
+
toggleModal={() => toggleModal("schedule")}
|
|
794
839
|
mainModalAction={mainScheduleModalAction}
|
|
795
840
|
secondaryModalAction={secondaryScheduleModalAction}
|
|
796
841
|
scheduleDate={scheduleDate}
|
|
797
842
|
setScheduleDate={setScheduleDate}
|
|
798
843
|
/>
|
|
799
844
|
<CancelScheduleModal
|
|
800
|
-
isOpen={
|
|
801
|
-
toggleModal={
|
|
845
|
+
isOpen={isOpen("cancelSchedule")}
|
|
846
|
+
toggleModal={() => toggleModal("cancelSchedule")}
|
|
802
847
|
mainModalAction={mainCancelScheduleModalAction}
|
|
803
848
|
secondaryModalAction={secondaryCancelScheduleModalAction}
|
|
804
849
|
/>
|
|
805
850
|
<RestoreModal
|
|
806
|
-
isOpen={
|
|
807
|
-
toggleModal={
|
|
851
|
+
isOpen={isOpen("restore")}
|
|
852
|
+
toggleModal={() => toggleModal("restore")}
|
|
808
853
|
{...{
|
|
809
854
|
isChild: false,
|
|
810
855
|
hasIssues: schemaVersion !== editorContent.schemaVersionTimestamp,
|
|
811
856
|
restorePage: handleRestorePage,
|
|
812
857
|
}}
|
|
813
858
|
/>
|
|
859
|
+
<HeadingsPreviewModal
|
|
860
|
+
isOpen={isOpen("headingsPreview")}
|
|
861
|
+
toggleModal={handleToggleHeadingsEditor}
|
|
862
|
+
browserRef={browserRef}
|
|
863
|
+
headingsFilter={headingsFilter}
|
|
864
|
+
setHeadingsFilter={setHeadingsFilter}
|
|
865
|
+
/>
|
|
866
|
+
<KeywordsPreviewModal
|
|
867
|
+
isOpen={isOpen("keywordsPreview")}
|
|
868
|
+
toggleModal={handleToggleKeywordsEditor}
|
|
869
|
+
browserRef={browserRef}
|
|
870
|
+
keywords={editorContent?.metaKeywords || []}
|
|
871
|
+
keywordsFilter={keywordsFilter}
|
|
872
|
+
setKeywordsFilter={setKeywordsFilter}
|
|
873
|
+
addKeywords={handleAddKeywords}
|
|
874
|
+
deleteKeyword={handledeleteKeyword}
|
|
875
|
+
/>
|
|
814
876
|
<Modal
|
|
815
|
-
isOpen={
|
|
877
|
+
isOpen={isOpen("dirtyNavigate")}
|
|
816
878
|
hide={handleCancelDirtyNavigation}
|
|
817
879
|
size="S"
|
|
818
880
|
title="Unsaved changes"
|
|
@@ -895,6 +957,7 @@ const mapDispatchToProps = {
|
|
|
895
957
|
schedulePublication: pageEditorActions.schedulePublication,
|
|
896
958
|
setCurrentPageID: pageEditorActions.setCurrentPageID,
|
|
897
959
|
restorePage: pageEditorActions.restorePage,
|
|
960
|
+
updateEditorContent: pageEditorActions.updateEditorContent,
|
|
898
961
|
};
|
|
899
962
|
|
|
900
963
|
interface IPageEditorDispatchProps {
|
|
@@ -922,6 +985,7 @@ interface IPageEditorDispatchProps {
|
|
|
922
985
|
schedulePublication(date: string | null, isDraft: boolean): Promise<boolean>;
|
|
923
986
|
setCurrentPageID: (currentPageID: number | null) => void;
|
|
924
987
|
restorePage(id: number | number[]): Promise<boolean>;
|
|
988
|
+
updateEditorContent(selectedEditorID: number, key: string, value: any): void;
|
|
925
989
|
}
|
|
926
990
|
|
|
927
991
|
type IProps = IPageEditorStateProps & IPageEditorDispatchProps & RouteComponentProps;
|
|
@@ -67,9 +67,12 @@ const PublicPreview = () => {
|
|
|
67
67
|
|
|
68
68
|
if (isLoading || !state) return <Loading />;
|
|
69
69
|
|
|
70
|
+
const setBrowserRef = (ref: any) => {
|
|
71
|
+
(window as any).browserRef = ref;
|
|
72
|
+
};
|
|
73
|
+
|
|
70
74
|
return (
|
|
71
|
-
|
|
72
|
-
<S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
|
|
75
|
+
<S.Wrapper ref={setBrowserRef}>
|
|
73
76
|
<BrowserContent
|
|
74
77
|
cloudinaryName={state?.cloudinaryName}
|
|
75
78
|
theme={theme}
|