@griddo/ax 11.7.13 → 11.8.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/package.json +3 -2
  2. package/src/GlobalStore.tsx +3 -0
  3. package/src/api/index.tsx +4 -0
  4. package/src/api/logs.tsx +97 -0
  5. package/src/api/navigation.tsx +1 -1
  6. package/src/api/pages.tsx +1 -1
  7. package/src/api/schemas.tsx +18 -0
  8. package/src/api/users.tsx +17 -0
  9. package/src/components/ConfigPanel/Form/ConnectedField/NavConnectedField/index.tsx +3 -2
  10. package/src/components/ConfigPanel/Form/index.tsx +3 -1
  11. package/src/components/ConfigPanel/index.tsx +3 -0
  12. package/src/components/Fields/SummaryButton/index.tsx +6 -4
  13. package/src/components/Fields/TimeField/style.tsx +0 -1
  14. package/src/components/Fields/TranslateButton/index.tsx +3 -0
  15. package/src/components/FloatingMenu/index.tsx +25 -1
  16. package/src/components/FloatingMenu/style.tsx +3 -2
  17. package/src/components/LanguageMenu/index.tsx +1 -1
  18. package/src/components/MainWrapper/AppBar/index.tsx +4 -3
  19. package/src/components/RestoreModal/index.tsx +51 -0
  20. package/src/components/RestoreModal/style.tsx +7 -0
  21. package/src/components/SearchField/index.tsx +1 -1
  22. package/src/components/SearchField/style.tsx +4 -4
  23. package/src/components/TableFilters/CheckGroupFilter/index.tsx +42 -5
  24. package/src/components/TableFilters/CheckGroupFilter/style.tsx +8 -1
  25. package/src/components/TableFilters/SiteFilter/index.tsx +26 -57
  26. package/src/components/Tag/index.tsx +6 -3
  27. package/src/components/Tag/style.tsx +2 -2
  28. package/src/components/index.tsx +2 -0
  29. package/src/containers/ActivityLog/actions.tsx +262 -0
  30. package/src/containers/ActivityLog/constants.tsx +6 -0
  31. package/src/containers/ActivityLog/index.tsx +4 -0
  32. package/src/containers/ActivityLog/interfaces.tsx +12 -0
  33. package/src/containers/ActivityLog/reducer.tsx +25 -0
  34. package/src/containers/Navigation/Defaults/actions.tsx +4 -3
  35. package/src/containers/StructuredData/actions.tsx +7 -4
  36. package/src/containers/StructuredData/interfaces.tsx +2 -8
  37. package/src/containers/StructuredData/reducer.tsx +2 -8
  38. package/src/containers/Users/actions.tsx +22 -19
  39. package/src/modules/ActivityLog/DetailModal/index.tsx +108 -0
  40. package/src/modules/ActivityLog/DetailModal/style.tsx +52 -0
  41. package/src/modules/ActivityLog/DownloadModal/index.tsx +104 -0
  42. package/src/modules/ActivityLog/DownloadModal/style.tsx +12 -0
  43. package/src/modules/ActivityLog/ItemGroup/index.tsx +27 -0
  44. package/src/modules/ActivityLog/ItemGroup/style.tsx +39 -0
  45. package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +167 -0
  46. package/src/modules/ActivityLog/ItemLog/EventItem/style.tsx +79 -0
  47. package/src/modules/ActivityLog/ItemLog/index.tsx +24 -0
  48. package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +170 -0
  49. package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/style.tsx +79 -0
  50. package/src/modules/ActivityLog/ItemLogUser/UserItem/index.tsx +46 -0
  51. package/src/modules/ActivityLog/ItemLogUser/UserItem/style.tsx +60 -0
  52. package/src/modules/ActivityLog/ItemLogUser/index.tsx +25 -0
  53. package/src/modules/ActivityLog/LogFilters/ContentFilter/index.tsx +79 -0
  54. package/src/modules/ActivityLog/LogFilters/DateFilter/index.tsx +91 -0
  55. package/src/modules/ActivityLog/LogFilters/DateFilter/style.tsx +208 -0
  56. package/src/modules/ActivityLog/LogFilters/EventFilter/index.tsx +80 -0
  57. package/src/modules/ActivityLog/LogFilters/OrderFilter/index.tsx +49 -0
  58. package/src/modules/ActivityLog/LogFilters/OrderFilter/style.tsx +35 -0
  59. package/src/modules/ActivityLog/LogFilters/UserFilter/index.tsx +79 -0
  60. package/src/modules/ActivityLog/TableHeader/index.tsx +72 -0
  61. package/src/modules/ActivityLog/TableHeader/style.tsx +73 -0
  62. package/src/modules/ActivityLog/constants.tsx +10 -0
  63. package/src/modules/ActivityLog/hooks.tsx +53 -0
  64. package/src/modules/ActivityLog/index.tsx +313 -0
  65. package/src/modules/ActivityLog/style.tsx +57 -0
  66. package/src/modules/ActivityLog/utils.tsx +31 -0
  67. package/src/modules/Categories/CategoriesList/index.tsx +1 -1
  68. package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/index.tsx +3 -0
  69. package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/index.tsx +3 -0
  70. package/src/modules/Forms/FormEditor/Editor/index.tsx +5 -2
  71. package/src/modules/Forms/FormEditor/index.tsx +20 -3
  72. package/src/modules/GlobalEditor/Editor/index.tsx +3 -0
  73. package/src/modules/GlobalEditor/index.tsx +48 -9
  74. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -1
  75. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -1
  76. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +45 -6
  77. package/src/modules/PageEditor/Editor/index.tsx +4 -1
  78. package/src/modules/PageEditor/index.tsx +46 -7
  79. package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +1 -7
  80. package/src/modules/StructuredData/Form/index.tsx +56 -7
  81. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +2 -2
  82. package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +2 -8
  83. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +9 -9
  84. package/src/modules/StructuredData/StructuredDataList/index.tsx +3 -4
  85. package/src/modules/Users/Roles/index.tsx +0 -2
  86. package/src/modules/Users/UserEdit/index.tsx +12 -28
  87. package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +1 -0
  88. package/src/modules/Users/UserList/UserItem/index.tsx +10 -25
  89. package/src/modules/Users/UserList/index.tsx +8 -10
  90. package/src/routes/multisite.tsx +9 -0
  91. package/src/themes/theme.json +2 -1
  92. package/src/types/forms.tsx +1 -0
  93. package/src/types/index.tsx +8 -0
  94. package/src/types/logs.tsx +12 -0
  95. package/src/components/TableFilters/SiteFilter/style.tsx +0 -28
@@ -49,11 +49,20 @@ const FormEditor = (props: IProps) => {
49
49
  setSelectedContent,
50
50
  } = props;
51
51
 
52
- const { id, title, state, dataLanguages, formInUse } = formContent || { dataLanguages: [], formInUse: null };
52
+ const {
53
+ id,
54
+ title,
55
+ state,
56
+ dataLanguages,
57
+ formInUse,
58
+ deleted = false,
59
+ } = formContent || { dataLanguages: [], formInUse: null };
53
60
  const formStatus = state === "active" ? "active" : "offline";
54
61
  const isTranslated = dataLanguages.length > 1;
55
62
  const isSiteView = !!currentSiteInfo;
56
63
  const errorNotificationText = "There are some errors on the form so you can not publish yet. Please review them.";
64
+ const deletedNotificationText =
65
+ "This form has been deleted and can’t be edited. It will be permanently removed from the trash after 30 days.";
57
66
  const isPublishedForm = state === "active";
58
67
 
59
68
  const formLanguages: ILanguage[] = [];
@@ -64,6 +73,8 @@ const FormEditor = (props: IProps) => {
64
73
  }
65
74
  });
66
75
 
76
+ const availableLanguages = deleted ? formLanguages : isSiteView ? siteLangs : globalLangs;
77
+
67
78
  const [notification, setNotification] = useState<INotification | null>(null);
68
79
  const [deleteAllVersions, setDeleteAllVersions] = useState(false);
69
80
  const [errors, setErrors] = useState<IErrorItem[]>([]);
@@ -227,7 +238,7 @@ const FormEditor = (props: IProps) => {
227
238
  const downArrowMenu = {
228
239
  button: isAllowedToPublishForm ? publishButton : undefined,
229
240
  options: menuOptions,
230
- displayed: true,
241
+ displayed: !deleted,
231
242
  };
232
243
 
233
244
  const modalText = (
@@ -274,7 +285,7 @@ const FormEditor = (props: IProps) => {
274
285
  pageStatus={formStatus}
275
286
  language={lang}
276
287
  languageAction={handleLanguage}
277
- availableLanguages={isSiteView ? siteLangs : globalLangs}
288
+ availableLanguages={availableLanguages}
278
289
  currentLanguages={formLanguages}
279
290
  currentPageID={0}
280
291
  fullWidth={true}
@@ -295,6 +306,11 @@ const FormEditor = (props: IProps) => {
295
306
  />
296
307
  </S.NotificationWrapper>
297
308
  )}
309
+ {deleted && (
310
+ <S.NotificationWrapper>
311
+ <Notification type="error" text={deletedNotificationText} />
312
+ </S.NotificationWrapper>
313
+ )}
298
314
  <ErrorToast size="l" fixed />
299
315
  <S.Content>
300
316
  <Editor
@@ -304,6 +320,7 @@ const FormEditor = (props: IProps) => {
304
320
  browserRef={browserRef}
305
321
  setNotification={setNotification}
306
322
  setErrors={setErrors}
323
+ isDisabled={deleted}
307
324
  />
308
325
  </S.Content>
309
326
  </MainWrapper>
@@ -32,6 +32,7 @@ const Editor = (props: IProps) => {
32
32
  browserRef,
33
33
  setNotification,
34
34
  isEditLive,
35
+ isDisabled,
35
36
  } = props;
36
37
 
37
38
  const actions = {
@@ -68,6 +69,7 @@ const Editor = (props: IProps) => {
68
69
  userEditing={userEditing}
69
70
  theme={theme}
70
71
  isEditLive={isEditLive}
72
+ isDisabled={isDisabled}
71
73
  />
72
74
  }
73
75
  />
@@ -104,6 +106,7 @@ interface IPageBrowserDispatchProps {
104
106
  theme: string;
105
107
  browserRef: any;
106
108
  isEditLive: boolean;
109
+ isDisabled: boolean;
107
110
  }
108
111
 
109
112
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -22,6 +22,7 @@ import {
22
22
  ErrorPage,
23
23
  CancelScheduleModal,
24
24
  ScheduleModal,
25
+ RestoreModal,
25
26
  } from "@ax/components";
26
27
  import { pageEditorActions } from "@ax/containers/PageEditor";
27
28
  import { structuredDataActions } from "@ax/containers/StructuredData";
@@ -64,6 +65,8 @@ const GlobalEditor = (props: IProps) => {
64
65
  currentSiteErrorPages,
65
66
  getUserCurrentPermissions,
66
67
  schedulePublication,
68
+ restorePage,
69
+ schemaVersion,
67
70
  } = props;
68
71
 
69
72
  const isAllowedToPublishPages = usePermission("global.globalData.publishUnpublishAllGlobalData");
@@ -83,6 +86,7 @@ const GlobalEditor = (props: IProps) => {
83
86
  const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
84
87
  const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
85
88
  const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
89
+ const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
86
90
  const browserRef = useRef<HTMLDivElement>(null);
87
91
 
88
92
  const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
@@ -92,11 +96,21 @@ const GlobalEditor = (props: IProps) => {
92
96
  const structuredData = editorContent ? editorContent.structuredData : "";
93
97
  const isEditLive = isPublished && hasDraft;
94
98
  const isScheduled = props.pageStatus === pageStatus.SCHEDULED;
99
+ const isDeleted = editorContent.deleted;
95
100
 
96
101
  const errorNotificationText =
97
102
  "There are some errors on the page so you can not publish yet. Please review them in the error panel.";
98
103
  const validatedNotificationText = "Everything seems ok, you can publish the page.";
99
104
 
105
+ const deletedNotificationText =
106
+ "This page has been deleted and can’t be edited. It will be permanently removed from the trash after 30 days.";
107
+ const globalNotificationText = "You’ re working on the Global Page. Make sure you want to make changes to this page.";
108
+
109
+ const modifiedNotificationText =
110
+ "You made some changes to the Live version that aren't implemented on this Draft. Check it out before you continue working.";
111
+
112
+ const backLinkRoute = "/data";
113
+
100
114
  const theme = getDefaultTheme();
101
115
 
102
116
  useEffect(() => {
@@ -359,7 +373,7 @@ const GlobalEditor = (props: IProps) => {
359
373
  }
360
374
 
361
375
  const downArrowMenu = {
362
- displayed: !isReadOnly,
376
+ displayed: !isReadOnly && !isDeleted,
363
377
  button: isAllowedToPublishPages ? getPublishButton(props.pageStatus) : undefined,
364
378
  options: menuOptions,
365
379
  };
@@ -460,13 +474,6 @@ const GlobalEditor = (props: IProps) => {
460
474
  }
461
475
  };
462
476
 
463
- const globalNotificationText = "You’ re working on the Global Page. Make sure you want to make changes to this page.";
464
-
465
- const modifiedNotificationText =
466
- "You made some changes to the Live version that aren't implemented on this Draft. Check it out before you continue working.";
467
-
468
- const backLinkRoute = "/data";
469
-
470
477
  const handleGoBack = () => {
471
478
  props.setHistoryPush(backLinkRoute, false);
472
479
  };
@@ -536,6 +543,14 @@ const GlobalEditor = (props: IProps) => {
536
543
  }
537
544
  };
538
545
 
546
+ const handleRestorePage = async () => {
547
+ const isRestored = await restorePage(pageID);
548
+ if (isRestored) {
549
+ isRestoreOpen && toggleRestoreModal();
550
+ await getPage(pageID);
551
+ }
552
+ };
553
+
539
554
  return isLoading ? (
540
555
  <Loading />
541
556
  ) : (
@@ -551,7 +566,7 @@ const GlobalEditor = (props: IProps) => {
551
566
  pageStatus={props.pageStatus}
552
567
  language={lang}
553
568
  languageAction={handleLanguage}
554
- availableLanguages={isAllowedToCreatePages ? globalLangs : filteredLanguages}
569
+ availableLanguages={isAllowedToCreatePages && !isDeleted ? globalLangs : filteredLanguages}
555
570
  currentLanguages={contentLanguages}
556
571
  currentPageID={pageID}
557
572
  fullWidth={true}
@@ -571,6 +586,16 @@ const GlobalEditor = (props: IProps) => {
571
586
  <Notification type="warning" text={modifiedNotificationText} />
572
587
  </S.NotificationWrapper>
573
588
  )}
589
+ {isDeleted && (
590
+ <S.NotificationWrapper>
591
+ <Notification
592
+ type="error"
593
+ text={deletedNotificationText}
594
+ btnText="Restore page"
595
+ onClick={toggleRestoreModal}
596
+ />
597
+ </S.NotificationWrapper>
598
+ )}
574
599
  {sitePageID && (
575
600
  <S.NotificationWrapper>
576
601
  <Notification type="info" text={globalNotificationText} btnText="Go Back" onClick={goBackToSite} />
@@ -597,6 +622,7 @@ const GlobalEditor = (props: IProps) => {
597
622
  browserRef={browserRef}
598
623
  setNotification={setNotification}
599
624
  isEditLive={isEditLive}
625
+ isDisabled={isDeleted}
600
626
  />
601
627
  </S.Content>
602
628
  </>
@@ -651,6 +677,15 @@ const GlobalEditor = (props: IProps) => {
651
677
  mainModalAction={mainCancelScheduleModalAction}
652
678
  secondaryModalAction={secondaryCancelScheduleModalAction}
653
679
  />
680
+ <RestoreModal
681
+ isOpen={isRestoreOpen}
682
+ toggleModal={toggleRestoreModal}
683
+ {...{
684
+ isChild: false,
685
+ hasIssues: schemaVersion !== editorContent.schemaVersionTimestamp,
686
+ restorePage: handleRestorePage,
687
+ }}
688
+ />
654
689
  </MainWrapper>
655
690
  </>
656
691
  );
@@ -674,6 +709,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
674
709
  isNewTranslation: state.pageEditor.isNewTranslation,
675
710
  currentSiteErrorPages: state.sites.currentSiteErrorPages,
676
711
  skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
712
+ schemaVersion: state.structuredData.schemaVersion,
677
713
  });
678
714
 
679
715
  interface IPageEditorStateProps {
@@ -694,6 +730,7 @@ interface IPageEditorStateProps {
694
730
  isNewTranslation: boolean;
695
731
  currentSiteErrorPages: number[];
696
732
  skipReviewOnPublish?: boolean;
733
+ schemaVersion: string;
697
734
  }
698
735
 
699
736
  const mapDispatchToProps = {
@@ -714,6 +751,7 @@ const mapDispatchToProps = {
714
751
  discardDraft: pageEditorActions.discardDraft,
715
752
  getUserCurrentPermissions: usersActions.getUserCurrentPermissions,
716
753
  schedulePublication: pageEditorActions.schedulePublication,
754
+ restorePage: pageEditorActions.restorePage,
717
755
  };
718
756
 
719
757
  interface IPageEditorDispatchProps {
@@ -734,6 +772,7 @@ interface IPageEditorDispatchProps {
734
772
  discardDraft(): Promise<void>;
735
773
  getUserCurrentPermissions(): Promise<void>;
736
774
  schedulePublication(date: string | null, isDraft: boolean): Promise<boolean>;
775
+ restorePage(id: number | number[]): Promise<boolean>;
737
776
  }
738
777
 
739
778
  type IProps = IPageEditorStateProps & IPageEditorDispatchProps & RouteComponentProps;
@@ -6,7 +6,7 @@ import { Browser } from "@ax/components";
6
6
  import { ILanguage, IRootState, ISite, ISocialState } from "@ax/types";
7
7
 
8
8
  const DefaultsBrowser = (props: IProps) => {
9
- const { socials, cloudinaryName, content, currentSiteInfo, siteLangs, browserRef, actions } = props;
9
+ const { socials, cloudinaryName, content, currentSiteInfo, siteLangs, browserRef, actions, isDisabled } = props;
10
10
 
11
11
  if (!currentSiteInfo) {
12
12
  throw new Error(`ERROR: User reached Page Editor with null site info`);
@@ -28,6 +28,7 @@ const DefaultsBrowser = (props: IProps) => {
28
28
  siteLangs={siteLangs}
29
29
  siteID={siteID}
30
30
  actions={actions}
31
+ disabled={isDisabled}
31
32
  />
32
33
  );
33
34
  };
@@ -35,6 +36,7 @@ const DefaultsBrowser = (props: IProps) => {
35
36
  interface IDefaultsBrowserProps {
36
37
  actions: any;
37
38
  browserRef?: React.RefObject<HTMLDivElement>;
39
+ isDisabled: boolean;
38
40
  }
39
41
 
40
42
  interface IDefaultsBrowserStateProps {
@@ -28,6 +28,7 @@ const Editor = (props: IProps) => {
28
28
  isLoading,
29
29
  site,
30
30
  browserRef,
31
+ isDisabled,
31
32
  } = props;
32
33
 
33
34
  if (!site) {
@@ -50,7 +51,7 @@ const Editor = (props: IProps) => {
50
51
 
51
52
  return (
52
53
  <ResizePanel
53
- leftPanel={<DefaultsBrowser browserRef={browserRef} actions={actions} />}
54
+ leftPanel={<DefaultsBrowser browserRef={browserRef} actions={actions} isDisabled={isDisabled} />}
54
55
  rightPanel={
55
56
  <ConfigPanel
56
57
  schema={schema}
@@ -65,6 +66,7 @@ const Editor = (props: IProps) => {
65
66
  isLoading={isLoading}
66
67
  isEditable={true}
67
68
  theme={site.theme}
69
+ isDisabled={isDisabled}
68
70
  />
69
71
  }
70
72
  />
@@ -96,6 +98,7 @@ interface IPageBrowserDispatchProps {
96
98
  pasteModule(editorID: number, key: string, modulesToPaste: IModule[]): Promise<{ error?: INotification }>;
97
99
  setNotification: (notification: INotification) => void;
98
100
  browserRef?: React.RefObject<HTMLDivElement>;
101
+ isDisabled: boolean;
99
102
  }
100
103
 
101
104
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -8,7 +8,7 @@ import { RouteLeavingGuard } from "@ax/guards";
8
8
 
9
9
  import { appActions } from "@ax/containers/App";
10
10
  import { navigationActions, menuActions } from "@ax/containers/Navigation";
11
- import { ErrorPage, ErrorToast, Loading, MainWrapper, Modal, Notification } from "@ax/components";
11
+ import { ErrorPage, ErrorToast, Loading, MainWrapper, Modal, Notification, RestoreModal } from "@ax/components";
12
12
  import Editor from "./Editor";
13
13
 
14
14
  import * as S from "./style";
@@ -34,13 +34,18 @@ const DefaultsEditor = (props: IProps) => {
34
34
  setHistoryPush,
35
35
  getMenus,
36
36
  currentSiteInfo,
37
+ restoreNavigation,
37
38
  } = props;
38
39
 
39
40
  const [notification, setNotification] = useState<INotification | null>(null);
40
41
  const { isOpen, toggleModal } = useModal();
42
+ const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
41
43
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
42
44
  const currentDefaultNav = currentDefaultsContent.find((item: any) => item.setAsDefault);
43
45
  const isNew = !editorContent?.id;
46
+ const isDeleted = !!editorContent?.deleted;
47
+
48
+ const deletedNotificationText = `This ${editorContent?.type} has been deleted and can’t be edited. It will be permanently removed from the trash after 30 days.`;
44
49
 
45
50
  const currentLanguages: ILanguage[] = [];
46
51
  navLanguages?.forEach((navLang) => {
@@ -57,7 +62,8 @@ const DefaultsEditor = (props: IProps) => {
57
62
  const isAllowedToCreateFooters = usePermission("navigation.createSiteFooters") && selectedDefault === "Footers";
58
63
 
59
64
  useEffect(() => {
60
- getValues();
65
+ const handleGetValues = async () => await getValues();
66
+ handleGetValues();
61
67
  if (isNew) {
62
68
  setIsDirty(false);
63
69
  }
@@ -133,11 +139,20 @@ const DefaultsEditor = (props: IProps) => {
133
139
  }
134
140
  };
135
141
 
142
+ const handleRestorePage = async () => {
143
+ const isRestored = await restoreNavigation(editorContent.id, editorContent.type);
144
+ if (isRestored) {
145
+ isRestoreOpen && toggleRestoreModal();
146
+ await getValues();
147
+ }
148
+ };
149
+
136
150
  const leavingGuardText = (
137
151
  <>
138
152
  Some content <strong>is not saved</strong> on this page.
139
153
  </>
140
154
  );
155
+
141
156
  const setDefaultModalText = editorContent && (
142
157
  <p>{`There is already a ${editorContent.type} defined as default. If you change it to this one, it will be shown on all the pages on this site. Are you sure your want to make this change?`}</p>
143
158
  );
@@ -146,16 +161,19 @@ const DefaultsEditor = (props: IProps) => {
146
161
  const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
147
162
  const goBack = (path: string) => setHistoryPush(path, true);
148
163
 
149
- const availableLanguages = isAllowedToCreateHeaders || isAllowedToCreateFooters ? siteLanguages : currentLanguages;
164
+ const availableLanguages =
165
+ (isAllowedToCreateHeaders || isAllowedToCreateFooters) && !isDeleted ? siteLanguages : currentLanguages;
166
+
167
+ const backLinkRoute = "/sites/navigations/modules";
150
168
 
151
169
  return isLoading ? (
152
170
  <Loading />
153
171
  ) : (
154
172
  <>
155
- <RouteLeavingGuard when={isDirty} action={goBack} text={leavingGuardText} />
173
+ <RouteLeavingGuard when={isDirty || isSaving} action={goBack} text={leavingGuardText} />
156
174
  <MainWrapper
157
175
  title={editorContent.title}
158
- backLink={true}
176
+ backLink={backLinkRoute}
159
177
  rightButton={rightButtonProps}
160
178
  fixedAppBar={true}
161
179
  language={lang}
@@ -175,6 +193,16 @@ const DefaultsEditor = (props: IProps) => {
175
193
  />
176
194
  </S.NotificationWrapper>
177
195
  )}
196
+ {isDeleted && (
197
+ <S.NotificationWrapper>
198
+ <Notification
199
+ type="error"
200
+ text={deletedNotificationText}
201
+ btnText={`Restore ${editorContent?.type}`}
202
+ onClick={toggleRestoreModal}
203
+ />
204
+ </S.NotificationWrapper>
205
+ )}
178
206
  <ErrorToast size="l" />
179
207
  <Modal
180
208
  isOpen={isOpen}
@@ -187,8 +215,17 @@ const DefaultsEditor = (props: IProps) => {
187
215
  {isOpen ? <S.ModalContent>{setDefaultModalText}</S.ModalContent> : null}
188
216
  </Modal>
189
217
  <S.Content>
190
- <Editor browserRef={browserRef} setNotification={setNotification} />
218
+ <Editor browserRef={browserRef} setNotification={setNotification} isDisabled={isDeleted} />
191
219
  </S.Content>
220
+ <RestoreModal
221
+ isOpen={isRestoreOpen}
222
+ toggleModal={toggleRestoreModal}
223
+ {...{
224
+ isChild: false,
225
+ hasIssues: false,
226
+ restorePage: handleRestorePage,
227
+ }}
228
+ />
192
229
  </MainWrapper>
193
230
  </>
194
231
  );
@@ -235,6 +272,7 @@ const mapDispatchToProps = {
235
272
  setHeader: navigationActions.setHeader,
236
273
  setFooter: navigationActions.setFooter,
237
274
  getMenus: menuActions.getMenus,
275
+ restoreNavigation: navigationActions.restoreNavigation,
238
276
  };
239
277
 
240
278
  interface IDispatchProps {
@@ -247,6 +285,7 @@ interface IDispatchProps {
247
285
  setHeader(id: number | null): void;
248
286
  setFooter(id: number | null): void;
249
287
  getMenus(): Promise<void>;
288
+ restoreNavigation(navID: number | number[], type: string): Promise<boolean>;
250
289
  }
251
290
 
252
291
  type IProps = IStateProps & IDispatchProps;
@@ -43,6 +43,7 @@ const Editor = (props: IProps) => {
43
43
  restorePageNavigation,
44
44
  content,
45
45
  isEditLive,
46
+ isDisabled,
46
47
  } = props;
47
48
 
48
49
  if (!site) {
@@ -73,7 +74,7 @@ const Editor = (props: IProps) => {
73
74
  leftPanel={
74
75
  <PageBrowser
75
76
  isTemplateActivated={isTemplateActivated}
76
- isReadOnly={isReadOnly || isEditLive}
77
+ isReadOnly={isReadOnly || isEditLive || isDisabled}
77
78
  browserRef={browserRef}
78
79
  />
79
80
  }
@@ -100,6 +101,7 @@ const Editor = (props: IProps) => {
100
101
  header={header}
101
102
  footer={footer}
102
103
  isEditLive={isEditLive}
104
+ isDisabled={isDisabled}
103
105
  />
104
106
  }
105
107
  />
@@ -144,6 +146,7 @@ interface IPageBrowserDispatchProps {
144
146
  isReadOnly: boolean;
145
147
  browserRef: any;
146
148
  isEditLive: boolean;
149
+ isDisabled: boolean;
147
150
  }
148
151
 
149
152
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -21,6 +21,7 @@ import {
21
21
  ErrorPage,
22
22
  CancelScheduleModal,
23
23
  ScheduleModal,
24
+ RestoreModal,
24
25
  } from "@ax/components";
25
26
  import { pageEditorActions } from "@ax/containers/PageEditor";
26
27
  import { appActions } from "@ax/containers/App";
@@ -65,6 +66,8 @@ const PageEditor = (props: IProps) => {
65
66
  currentSiteErrorPages,
66
67
  schedulePublication,
67
68
  setCurrentPageID,
69
+ restorePage,
70
+ schemaVersion,
68
71
  } = props;
69
72
 
70
73
  const isAllowedToPublishPages = usePermission("content.publishUnpublishPages");
@@ -86,6 +89,7 @@ const PageEditor = (props: IProps) => {
86
89
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
87
90
  const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
88
91
  const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
92
+ const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
89
93
  const [errorPagesChecked, setErrorPagesChecked] = useState(false);
90
94
  const browserRef = useRef<HTMLDivElement>(null);
91
95
 
@@ -102,10 +106,18 @@ const PageEditor = (props: IProps) => {
102
106
  const canBeUnpublished = editorContent && editorContent.canBeUnpublished;
103
107
  const deleteHelpText = !canBeUnpublished ? "This is the canonical site of the page. You cannot unpublish it." : null;
104
108
  const isScheduled = !!editorContent && !!editorContent.publicationScheduled;
109
+ const isDeleted = editorContent.deleted;
105
110
 
106
111
  const errorNotificationText =
107
112
  "There are some errors on the page so you can not publish yet. Please review them in the error panel.";
108
113
  const validatedNotificationText = "Everything seems ok, you can publish the page.";
114
+ const modifiedNotificationText =
115
+ "You made some changes to the Live version that aren't implemented on this Draft. Check it out before you continue working.";
116
+
117
+ const deletedNotificationText =
118
+ "This page has been deleted and can’t be edited. It will be permanently removed from the trash after 30 days.";
119
+
120
+ const backLinkRoute = "/sites/pages";
109
121
 
110
122
  useEffect(() => {
111
123
  const { pageID, getPage, setTab, sendPagePing } = props;
@@ -369,7 +381,7 @@ const PageEditor = (props: IProps) => {
369
381
  }
370
382
 
371
383
  const downArrowMenu = {
372
- displayed: !isReadOnly,
384
+ displayed: !isReadOnly && !isDeleted,
373
385
  button: isAllowedToPublishPages ? getPublishButton(props.pageStatus) : undefined,
374
386
  options: !isGlobal ? menuOptions : [],
375
387
  };
@@ -415,7 +427,7 @@ const PageEditor = (props: IProps) => {
415
427
  }
416
428
 
417
429
  let availableLanguages = siteLanguages;
418
- if (!isTemplateActivated || hasDeactivatedModules || !isAllowedToCreatePages) {
430
+ if (!isTemplateActivated || hasDeactivatedModules || !isAllowedToCreatePages || isDeleted) {
419
431
  const pageLanguagesIDs = pageLanguages.map((language) => language.languageId);
420
432
  availableLanguages = siteLanguages.filter((language) => {
421
433
  return pageLanguagesIDs.includes(language.id);
@@ -505,11 +517,6 @@ const PageEditor = (props: IProps) => {
505
517
  }
506
518
  };
507
519
 
508
- const modifiedNotificationText =
509
- "You made some changes to the Live version that aren't implemented on this Draft. Check it out before you continue working.";
510
-
511
- const backLinkRoute = "/sites/pages";
512
-
513
520
  const handleGoBack = () => {
514
521
  props.setHistoryPush(backLinkRoute, false);
515
522
  };
@@ -584,6 +591,14 @@ const PageEditor = (props: IProps) => {
584
591
  }
585
592
  };
586
593
 
594
+ const handleRestorePage = async () => {
595
+ const isRestored = await restorePage(pageID);
596
+ if (isRestored) {
597
+ isRestoreOpen && toggleRestoreModal();
598
+ await getPage(pageID);
599
+ }
600
+ };
601
+
587
602
  return isLoading ? (
588
603
  <Loading />
589
604
  ) : (
@@ -623,6 +638,16 @@ const PageEditor = (props: IProps) => {
623
638
  />
624
639
  </S.NotificationWrapper>
625
640
  )}
641
+ {isDeleted && (
642
+ <S.NotificationWrapper>
643
+ <Notification
644
+ type="error"
645
+ text={deletedNotificationText}
646
+ btnText="Restore page"
647
+ onClick={toggleRestoreModal}
648
+ />
649
+ </S.NotificationWrapper>
650
+ )}
626
651
  {isLivePageChanged && (
627
652
  <S.NotificationWrapper>
628
653
  <Notification type="warning" text={modifiedNotificationText} />
@@ -650,6 +675,7 @@ const PageEditor = (props: IProps) => {
650
675
  browserRef={browserRef}
651
676
  setNotification={setNotification}
652
677
  isEditLive={isEditLive}
678
+ isDisabled={isDeleted}
653
679
  />
654
680
  </S.Content>
655
681
  </>
@@ -711,6 +737,15 @@ const PageEditor = (props: IProps) => {
711
737
  mainModalAction={mainCancelScheduleModalAction}
712
738
  secondaryModalAction={secondaryCancelScheduleModalAction}
713
739
  />
740
+ <RestoreModal
741
+ isOpen={isRestoreOpen}
742
+ toggleModal={toggleRestoreModal}
743
+ {...{
744
+ isChild: false,
745
+ hasIssues: schemaVersion !== editorContent.schemaVersionTimestamp,
746
+ restorePage: handleRestorePage,
747
+ }}
748
+ />
714
749
  </MainWrapper>
715
750
  </>
716
751
  );
@@ -736,6 +771,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
736
771
  isNewTranslation: state.pageEditor.isNewTranslation,
737
772
  currentSiteErrorPages: state.sites.currentSiteErrorPages,
738
773
  skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
774
+ schemaVersion: state.structuredData.schemaVersion,
739
775
  });
740
776
 
741
777
  interface IPageEditorStateProps {
@@ -758,6 +794,7 @@ interface IPageEditorStateProps {
758
794
  currentSiteErrorPages: number[];
759
795
  skipReviewOnPublish?: boolean;
760
796
  schema: any;
797
+ schemaVersion: string;
761
798
  }
762
799
 
763
800
  const mapDispatchToProps = {
@@ -779,6 +816,7 @@ const mapDispatchToProps = {
779
816
  deleteBulk: pageEditorActions.deleteBulk,
780
817
  schedulePublication: pageEditorActions.schedulePublication,
781
818
  setCurrentPageID: pageEditorActions.setCurrentPageID,
819
+ restorePage: pageEditorActions.restorePage,
782
820
  };
783
821
 
784
822
  interface IPageEditorDispatchProps {
@@ -800,6 +838,7 @@ interface IPageEditorDispatchProps {
800
838
  deleteBulk(ids: number[]): Promise<boolean>;
801
839
  schedulePublication(date: string | null, isDraft: boolean): Promise<boolean>;
802
840
  setCurrentPageID: (currentPageID: number | null) => void;
841
+ restorePage(id: number | number[]): Promise<boolean>;
803
842
  }
804
843
 
805
844
  type IProps = IPageEditorStateProps & IPageEditorDispatchProps & RouteComponentProps;
@@ -28,10 +28,4 @@ const ActionsHeader = styled(Header)`
28
28
  justify-content: flex-end;
29
29
  `;
30
30
 
31
- export {
32
- TableHeader,
33
- CheckHeader,
34
- SiteHeader,
35
- UrlHeader,
36
- ActionsHeader,
37
- };
31
+ export { TableHeader, CheckHeader, SiteHeader, UrlHeader, ActionsHeader };