@griddo/ax 1.66.13 → 1.67.2

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 (76) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Fields/ConditionalField/ConditionalField.test.tsx +95 -0
  3. package/src/api/pages.tsx +15 -3
  4. package/src/api/redirects.tsx +4 -2
  5. package/src/api/sites.tsx +12 -4
  6. package/src/components/Browser/index.tsx +9 -22
  7. package/src/components/Browser/style.tsx +1 -6
  8. package/src/components/ErrorCenter/index.tsx +8 -5
  9. package/src/components/ErrorCenter/style.tsx +21 -8
  10. package/src/components/Fields/ComponentArray/MixableComponentArray/AddItemButton/index.tsx +3 -3
  11. package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +60 -25
  12. package/src/components/Fields/ComponentContainer/index.tsx +21 -7
  13. package/src/components/Fields/ConditionalField/index.tsx +1 -1
  14. package/src/components/Fields/LinkField/index.tsx +111 -0
  15. package/src/components/Fields/ReferenceField/ItemList/index.tsx +4 -0
  16. package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +12 -2
  17. package/src/components/Fields/ReferenceField/index.tsx +24 -12
  18. package/src/components/Fields/ReferenceField/style.tsx +12 -1
  19. package/src/components/Fields/UrlField/index.tsx +13 -1
  20. package/src/components/Fields/VisualUniqueSelection/utils.tsx +1 -6
  21. package/src/components/Fields/index.tsx +2 -0
  22. package/src/components/FieldsBehavior/index.tsx +14 -1
  23. package/src/components/Icon/components/Copy.js +14 -0
  24. package/src/components/Icon/components/Copy2.js +14 -0
  25. package/src/components/Icon/components/Duplicate.js +3 -5
  26. package/src/components/Icon/components/Page.js +12 -0
  27. package/src/components/Icon/svgs/Copy.svg +3 -0
  28. package/src/components/Icon/svgs/Copy2.svg +3 -0
  29. package/src/components/Icon/svgs/Duplicate.svg +1 -1
  30. package/src/components/Icon/svgs/page.svg +3 -0
  31. package/src/components/MainWrapper/AppBar/index.tsx +21 -10
  32. package/src/components/MainWrapper/AppBar/style.tsx +11 -3
  33. package/src/components/MainWrapper/index.tsx +2 -0
  34. package/src/components/Notification/index.tsx +1 -3
  35. package/src/components/SearchField/index.tsx +37 -4
  36. package/src/components/SearchField/style.tsx +23 -10
  37. package/src/components/index.tsx +2 -0
  38. package/src/containers/Navigation/Defaults/actions.tsx +2 -0
  39. package/src/containers/PageEditor/actions.tsx +101 -19
  40. package/src/containers/PageEditor/utils.tsx +2 -1
  41. package/src/containers/Sites/actions.tsx +53 -24
  42. package/src/containers/Sites/constants.tsx +2 -0
  43. package/src/containers/Sites/interfaces.tsx +12 -5
  44. package/src/containers/Sites/reducer.tsx +8 -0
  45. package/src/containers/StructuredData/actions.tsx +5 -8
  46. package/src/forms/errors.tsx +1 -0
  47. package/src/forms/index.tsx +13 -1
  48. package/src/forms/validators.tsx +181 -13
  49. package/src/helpers/dataPacks.tsx +8 -1
  50. package/src/helpers/index.tsx +4 -1
  51. package/src/helpers/objects.tsx +10 -2
  52. package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +3 -1
  53. package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +15 -9
  54. package/src/modules/Categories/CategoriesList/index.tsx +2 -1
  55. package/src/modules/Content/PageItem/index.tsx +52 -2
  56. package/src/modules/Content/atoms.tsx +41 -3
  57. package/src/modules/Content/index.tsx +44 -2
  58. package/src/modules/Content/style.tsx +8 -1
  59. package/src/modules/FramePreview/index.tsx +85 -0
  60. package/src/modules/FramePreview/style.tsx +18 -0
  61. package/src/modules/GlobalEditor/Editor/index.tsx +3 -1
  62. package/src/modules/GlobalEditor/PageBrowser/index.tsx +3 -0
  63. package/src/modules/GlobalEditor/index.tsx +22 -6
  64. package/src/modules/PageEditor/Editor/index.tsx +5 -1
  65. package/src/modules/PageEditor/PageBrowser/index.tsx +4 -5
  66. package/src/modules/PageEditor/index.tsx +40 -12
  67. package/src/modules/Redirects/index.tsx +40 -10
  68. package/src/modules/Settings/Globals/index.tsx +1 -1
  69. package/src/modules/Sites/index.tsx +2 -2
  70. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +1 -1
  71. package/src/modules/StructuredData/StructuredDataList/index.tsx +19 -2
  72. package/src/modules/Users/Profile/index.tsx +3 -3
  73. package/src/routes/multisite.tsx +12 -4
  74. package/src/routes/site.tsx +1 -1
  75. package/src/types/index.tsx +13 -4
  76. package/tsconfig.paths.json +2 -1
@@ -15,6 +15,7 @@ import {
15
15
  IGetSitePagesParams,
16
16
  IColumn,
17
17
  ISite,
18
+ IUser,
18
19
  } from "@ax/types";
19
20
  import { MainWrapper, Modal, TableList, ErrorToast, Toast, EmptyState, Notification } from "@ax/components";
20
21
  import { getFilteredStructuredData, isGlobalStructuredData, isStructuredDataFromPage } from "@ax/helpers";
@@ -86,6 +87,11 @@ const Content = (props: IProps): JSX.Element => {
86
87
  restorePage,
87
88
  getDataPack,
88
89
  dataPacks,
90
+ resetCurrentSiteErrorPages,
91
+ currentSiteErrorPages,
92
+ getSitesByLang,
93
+ sitesByLang,
94
+ user,
89
95
  } = props;
90
96
 
91
97
  const itemsPerPage = 50;
@@ -109,7 +115,9 @@ const Content = (props: IProps): JSX.Element => {
109
115
  const dataIds = currentDataContent && currentDataContent.map((data: any) => data.id);
110
116
  const contentIds = isStructuredData ? dataIds : pagesIds;
111
117
  const currentSitePagesTemplatesIds = currentSitePages && currentSitePages.map((page: any) => page.templateId);
112
-
118
+ const currentSitesByLang = sitesByLang?.filter(
119
+ (site) => user?.sites?.includes("all") || user.sites.includes(site.id)
120
+ );
113
121
  const categoryColumns =
114
122
  currentStructuredData && currentStructuredData.schema
115
123
  ? currentStructuredData.schema.fields.filter((field: any) => field.showList)
@@ -171,6 +179,11 @@ const Content = (props: IProps): JSX.Element => {
171
179
  } = useToast();
172
180
 
173
181
  const { categoryColors, addCategoryColors } = useCategoryColors();
182
+ const {
183
+ isVisible: isVisibleCopiedToast,
184
+ toggleToast: toggleCopiedToast,
185
+ setIsVisible: setIsVisibleCopiedToast,
186
+ } = useToast();
174
187
 
175
188
  const getParams = useCallback(() => {
176
189
  const siteID = currentSiteInfo ? currentSiteInfo.id : null;
@@ -231,11 +244,15 @@ const Content = (props: IProps): JSX.Element => {
231
244
  // eslint-disable-next-line react-hooks/exhaustive-deps
232
245
  }, [filter]);
233
246
 
247
+ const fetchSitesByLang = async () => await getSitesByLang(lang.id);
248
+
234
249
  useEffect(() => {
235
250
  if (!locationState || locationState.isFromEditor !== true) {
236
251
  setFilter("unique-pages");
237
252
  }
238
253
  resetPageEditor();
254
+ resetCurrentSiteErrorPages();
255
+ fetchSitesByLang();
239
256
  // eslint-disable-next-line react-hooks/exhaustive-deps
240
257
  }, []);
241
258
 
@@ -533,6 +550,7 @@ const Content = (props: IProps): JSX.Element => {
533
550
  deleteBulk: deleteCurrentPageBulk,
534
551
  getDataPack: getDataPack,
535
552
  setTemplateInstanceError,
553
+ toggleCopiedToast,
536
554
  };
537
555
 
538
556
  return (
@@ -540,6 +558,7 @@ const Content = (props: IProps): JSX.Element => {
540
558
  item={item}
541
559
  key={pageItem.id}
542
560
  functions={pageItemFunctions}
561
+ sites={currentSitesByLang}
543
562
  activatedTemplates={activatedTemplates}
544
563
  toggleToast={toggleRemovedToast}
545
564
  setRemovedPage={setRemovedPage}
@@ -650,8 +669,18 @@ const Content = (props: IProps): JSX.Element => {
650
669
  message: "Page deleted.",
651
670
  };
652
671
 
672
+ const copiedToastProps = {
673
+ setIsVisible: setIsVisibleCopiedToast,
674
+ message: "1 Page copied to another Site",
675
+ };
676
+
653
677
  const addNewAction = filter === "unique-pages" || isGlobalPages ? toggleNewModal : addNewData;
654
678
 
679
+ const errorPagesText =
680
+ currentSiteErrorPages.length > 1
681
+ ? "These pages contains some errors, so you can not publish them yet. Please, review the errors on the pages."
682
+ : "This page contains some errors, so you can not publish it yet. Please, review the errors on the page.";
683
+
655
684
  return (
656
685
  <MainWrapper
657
686
  title={title}
@@ -671,6 +700,7 @@ const Content = (props: IProps): JSX.Element => {
671
700
  text={`There can be only one ${templateInstanceError.templateName} page and you already have it.`}
672
701
  />
673
702
  )}
703
+ {!!currentSiteErrorPages.length && <Notification type="error" text={errorPagesText} />}
674
704
  <TableList
675
705
  tableHeader={Header}
676
706
  pagination={pagination}
@@ -720,6 +750,7 @@ const Content = (props: IProps): JSX.Element => {
720
750
  {isVisible && <Toast {...toastProps} />}
721
751
  {isVisibleRemovedToast && <Toast {...removedToastProps} />}
722
752
  {isVisibleDeletedToast && <Toast {...deletedToastProps} />}
753
+ {isVisibleCopiedToast && <Toast {...copiedToastProps} />}
723
754
  </MainWrapper>
724
755
  );
725
756
  };
@@ -741,6 +772,9 @@ const mapStateToProps = (state: IRootState) => ({
741
772
  activatedTemplates: state.dataPacks.templates,
742
773
  isLoading: state.app.isLoading,
743
774
  dataPacks: state.dataPacks.activated,
775
+ currentSiteErrorPages: state.sites.currentSiteErrorPages,
776
+ sitesByLang: state.sites.sitesByLang,
777
+ user: state.users.currentUser,
744
778
  });
745
779
 
746
780
  interface IDispatchProps {
@@ -760,7 +794,7 @@ interface IDispatchProps {
760
794
  getStructuredDataContents(params: any, siteID: number): Promise<void>;
761
795
  resetForm(): void;
762
796
  deleteBulk(ids: any): Promise<boolean>;
763
- duplicatePage(pageID: number, data: any): Promise<void>;
797
+ duplicatePage(pageID: number, data?: any, siteID?: number): Promise<boolean>;
764
798
  deleteDataContent(dataID: number[]): Promise<boolean>;
765
799
  restoreDataContent(catID: number | number[]): void;
766
800
  setFilter(value: string): void;
@@ -770,6 +804,8 @@ interface IDispatchProps {
770
804
  importPageFromGlobal(pageID: number | number[]): Promise<boolean>;
771
805
  restorePage(id: number | number[]): Promise<boolean>;
772
806
  getDataPack: (id: string) => Promise<void>;
807
+ resetCurrentSiteErrorPages: () => Promise<void>;
808
+ getSitesByLang(language: number): Promise<void>;
773
809
  }
774
810
 
775
811
  const mapDispatchToProps = {
@@ -798,6 +834,8 @@ const mapDispatchToProps = {
798
834
  importPageFromGlobal: sitesActions.importPageFromGlobal,
799
835
  restorePage: pageEditorActions.restorePage,
800
836
  getDataPack: dataPacksActions.getSiteDataPack,
837
+ resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
838
+ getSitesByLang: sitesActions.getSitesByLang,
801
839
  };
802
840
 
803
841
  interface IPagesProps {
@@ -819,6 +857,10 @@ interface IPagesProps {
819
857
  activatedTemplates: any[];
820
858
  isLoading: boolean;
821
859
  dataPacks: IDataPack[];
860
+ currentSiteErrorPages: number[];
861
+ sites: ISite[];
862
+ sitesByLang: ISite[];
863
+ user: IUser;
822
864
  }
823
865
 
824
866
  type IProps = IPagesProps & IDispatchProps;
@@ -35,4 +35,11 @@ const ModalContent = styled.div`
35
35
  }
36
36
  `;
37
37
 
38
- export { ContentListWrapper, TableWrapper, PaginationWrapper, EmptyWrapper, ModalContent };
38
+ const SelectWrapper = styled.div`
39
+ & .react-select__control,
40
+ .react-select__menu {
41
+ min-width: 100%;
42
+ }
43
+ `;
44
+
45
+ export { ContentListWrapper, TableWrapper, PaginationWrapper, EmptyWrapper, ModalContent, SelectWrapper };
@@ -0,0 +1,85 @@
1
+ import React from "react";
2
+ import { connect } from "react-redux";
3
+
4
+ import * as components from "components";
5
+ import { SiteProvider } from "components";
6
+ import { Preview } from "@griddo/core";
7
+ import { getDefaultTheme } from "@ax/helpers";
8
+ import { Loading } from "@ax/components";
9
+ import { ILanguage, IRootState, ISocialState } from "@ax/types";
10
+
11
+ import * as S from "./style";
12
+
13
+ const FramePreview = (props: IProps) => {
14
+ const { content, socials, selectedEditorID, cloudinaryName, isLoading, currentSiteInfo, siteLangs, globalLangs } =
15
+ props;
16
+
17
+ const {
18
+ editorContent: { canonicalSite, language, pageLanguages },
19
+ header,
20
+ footer,
21
+ } = content;
22
+
23
+ document.body.classList.add("preview");
24
+
25
+ const API_URL = process.env.REACT_APP_API_ENDPOINT;
26
+ const PUBLIC_API_URL = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
27
+
28
+ const globalTheme = getDefaultTheme();
29
+ const theme = currentSiteInfo ? currentSiteInfo.theme : globalTheme;
30
+ const langs = currentSiteInfo ? siteLangs : globalLangs;
31
+ const siteID = currentSiteInfo ? currentSiteInfo.id : canonicalSite;
32
+
33
+ if (isLoading) return <Loading />;
34
+
35
+ return (
36
+ <SiteProvider
37
+ cloudinaryCloudName={cloudinaryName}
38
+ theme={theme}
39
+ socials={socials}
40
+ siteLangs={langs}
41
+ selectEditorID={selectedEditorID}
42
+ renderer="editor"
43
+ apiUrl={API_URL}
44
+ publicApiUrl={PUBLIC_API_URL}
45
+ siteId={siteID}
46
+ >
47
+ <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
48
+ <Preview
49
+ isPage={true}
50
+ apiUrl={API_URL}
51
+ library={components}
52
+ content={content.editorContent}
53
+ header={currentSiteInfo && header}
54
+ footer={currentSiteInfo && footer}
55
+ languageId={language}
56
+ pageLanguages={pageLanguages}
57
+ />
58
+ </S.Wrapper>
59
+ </SiteProvider>
60
+ );
61
+ };
62
+
63
+ interface IProps {
64
+ content: any;
65
+ selectedEditorID: number;
66
+ socials: ISocialState;
67
+ cloudinaryName: string | null;
68
+ currentSiteInfo: any;
69
+ siteLangs: ILanguage[];
70
+ globalLangs: ILanguage[];
71
+ isLoading: boolean;
72
+ }
73
+
74
+ const mapStateToProps = (state: IRootState) => ({
75
+ content: { ...state.pageEditor.editorContent },
76
+ selectedEditorID: state.pageEditor.selectedEditorID as number,
77
+ socials: state.social,
78
+ cloudinaryName: state.app.globalSettings.cloudinaryName,
79
+ currentSiteInfo: state.sites.currentSiteInfo,
80
+ siteLangs: state.sites.currentSiteLanguages,
81
+ globalLangs: state.app.globalLangs,
82
+ isLoading: state.app.isLoading,
83
+ });
84
+
85
+ export default connect(mapStateToProps)(FramePreview);
@@ -0,0 +1,18 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div`
4
+ overflow: auto;
5
+ scroll-behavior: smooth;
6
+ height: 100%;
7
+ position: relative;
8
+
9
+ .headroom {
10
+ position: relative !important;
11
+ }
12
+
13
+ body.preview:not(&) {
14
+ min-width: 0 !important;
15
+ }
16
+ `;
17
+
18
+ export { Wrapper };
@@ -29,6 +29,7 @@ const Editor = (props: IProps) => {
29
29
  copyModule,
30
30
  pasteModule,
31
31
  theme,
32
+ browserRef,
32
33
  setNotification,
33
34
  } = props;
34
35
 
@@ -47,7 +48,7 @@ const Editor = (props: IProps) => {
47
48
 
48
49
  return (
49
50
  <ResizePanel
50
- leftPanel={<PageBrowser isReadOnly={isReadOnly} theme={theme} />}
51
+ leftPanel={<PageBrowser isReadOnly={isReadOnly} theme={theme} browserRef={browserRef} />}
51
52
  rightPanel={
52
53
  <ConfigPanel
53
54
  schema={schema}
@@ -99,6 +100,7 @@ interface IPageBrowserDispatchProps {
99
100
  isEditable: boolean;
100
101
  isReadOnly: boolean;
101
102
  theme: string;
103
+ browserRef: any;
102
104
  }
103
105
 
104
106
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -18,6 +18,7 @@ const PageBrowser = (props: IProps) => {
18
18
  theme,
19
19
  isReadOnly,
20
20
  isPreview,
21
+ browserRef,
21
22
  } = props;
22
23
 
23
24
  const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
@@ -38,6 +39,7 @@ const PageBrowser = (props: IProps) => {
38
39
  disabled={isReadOnly}
39
40
  siteID={canonicalSite}
40
41
  isPreview={isPreview}
42
+ browserRef={browserRef}
41
43
  />
42
44
  );
43
45
  };
@@ -60,6 +62,7 @@ interface IPageBrowserDispatchProps {
60
62
  theme: string;
61
63
  isReadOnly: boolean;
62
64
  isPreview?: boolean;
65
+ browserRef?: any;
63
66
  }
64
67
 
65
68
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from "react";
1
+ import React, { useEffect, useState, useRef } from "react";
2
2
  import { connect } from "react-redux";
3
3
  import { RouteComponentProps } from "react-router-dom";
4
4
 
@@ -42,6 +42,7 @@ const GlobalEditor = (props: IProps) => {
42
42
  savedSiteInfo,
43
43
  userEditing,
44
44
  isNewTranslation,
45
+ currentSiteErrorPages,
45
46
  } = props;
46
47
 
47
48
  const { isOpen, toggleModal } = useModal();
@@ -50,6 +51,8 @@ const GlobalEditor = (props: IProps) => {
50
51
  const [selectedTab, setSelectedTab] = useState("edit");
51
52
  const [notification, setNotification] = useState<INotification | null>(null);
52
53
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
54
+ const [errorPagesChecked, setErrorPagesChecked] = useState(false);
55
+ const browserRef = useRef<HTMLDivElement>(null);
53
56
 
54
57
  const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
55
58
  const isDraft = props.pageStatus === pageStatus.MODIFIED;
@@ -98,6 +101,16 @@ const GlobalEditor = (props: IProps) => {
98
101
  // eslint-disable-next-line react-hooks/exhaustive-deps
99
102
  }, [userEditing]);
100
103
 
104
+ useEffect(() => {
105
+ if (!errorPagesChecked && !isLoading && editorContent.editorContent) {
106
+ const pageId = editorContent.editorContent.id;
107
+ const hasErrors = currentSiteErrorPages.some((errorPageId) => pageId === errorPageId);
108
+ hasErrors && reviewPage();
109
+ setErrorPagesChecked(true);
110
+ }
111
+ // eslint-disable-next-line react-hooks/exhaustive-deps
112
+ }, [editorContent]);
113
+
101
114
  const setRoute = (path: string) => props.setHistoryPush(path, true);
102
115
 
103
116
  const removePage = async () => {
@@ -114,7 +127,7 @@ const GlobalEditor = (props: IProps) => {
114
127
  const publishPage = async () => {
115
128
  const { updatePageStatus, savePage, pageID, validatePage } = props;
116
129
 
117
- const validated = await validatePage(true);
130
+ const validated = await validatePage(true, browserRef);
118
131
 
119
132
  if (validated) {
120
133
  const publishPage = {
@@ -134,7 +147,7 @@ const GlobalEditor = (props: IProps) => {
134
147
  const publishChanges = async () => {
135
148
  const { savePage, validatePage } = props;
136
149
 
137
- const validated = await validatePage(true);
150
+ const validated = await validatePage(true, browserRef);
138
151
 
139
152
  if (validated) {
140
153
  const publishPage = {
@@ -163,13 +176,13 @@ const GlobalEditor = (props: IProps) => {
163
176
 
164
177
  const reviewPage = () => {
165
178
  const { validatePage } = props;
166
- validatePage();
179
+ validatePage(undefined, browserRef);
167
180
  };
168
181
 
169
182
  const handlePublishDraft = async () => {
170
183
  const { savePage, validatePage } = props;
171
184
 
172
- const validated = await validatePage(true);
185
+ const validated = await validatePage(true, browserRef);
173
186
 
174
187
  if (validated) {
175
188
  const isSaved = await savePage(false, null, true);
@@ -462,6 +475,7 @@ const GlobalEditor = (props: IProps) => {
462
475
  isEditable={isEditable}
463
476
  isReadOnly={isReadOnly}
464
477
  theme={theme}
478
+ browserRef={browserRef}
465
479
  setNotification={setNotification}
466
480
  />
467
481
  </S.Content>
@@ -524,6 +538,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
524
538
  userEditing: state.pageEditor.userEditing,
525
539
  currentUserID: state.users.currentUser.id,
526
540
  isNewTranslation: state.pageEditor.isNewTranslation,
541
+ currentSiteErrorPages: state.sites.currentSiteErrorPages,
527
542
  });
528
543
 
529
544
  interface IPageEditorStateProps {
@@ -543,6 +558,7 @@ interface IPageEditorStateProps {
543
558
  userEditing: IUserEditing | null;
544
559
  currentUserID: number | null;
545
560
  isNewTranslation: boolean;
561
+ currentSiteErrorPages: number[];
546
562
  }
547
563
 
548
564
  const mapDispatchToProps = {
@@ -567,7 +583,7 @@ interface IPageEditorDispatchProps {
567
583
  getPage(pageID?: number, global?: boolean): Promise<void>;
568
584
  savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
569
585
  deletePage(params?: ISavePageParams): Promise<boolean>;
570
- validatePage(publish?: boolean): Promise<boolean>;
586
+ validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
571
587
  updatePageStatus(id: number[], status: string): Promise<boolean>;
572
588
  setHistoryPush(path: string, isEditor: boolean): void;
573
589
  setLanguage?(lang: { locale: string; id: number | null }): void;
@@ -35,6 +35,7 @@ const Editor = (props: IProps) => {
35
35
  isReadOnly,
36
36
  userEditing,
37
37
  site,
38
+ browserRef,
38
39
  lastElementAddedId,
39
40
  copyModule,
40
41
  pasteModule,
@@ -58,7 +59,9 @@ const Editor = (props: IProps) => {
58
59
 
59
60
  return (
60
61
  <ResizePanel
61
- leftPanel={<PageBrowser isTemplateActivated={isTemplateActivated} isReadOnly={isReadOnly} />}
62
+ leftPanel={
63
+ <PageBrowser isTemplateActivated={isTemplateActivated} isReadOnly={isReadOnly} browserRef={browserRef} />
64
+ }
62
65
  rightPanel={
63
66
  <ConfigPanel
64
67
  schema={schema}
@@ -119,6 +122,7 @@ interface IPageBrowserDispatchProps {
119
122
  isEditable: boolean;
120
123
  pageTitle: string;
121
124
  isReadOnly: boolean;
125
+ browserRef: any;
122
126
  }
123
127
 
124
128
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -3,7 +3,7 @@ import { connect } from "react-redux";
3
3
  import { pageEditorActions } from "@ax/containers/PageEditor";
4
4
 
5
5
  import { Browser } from "@ax/components";
6
- import { IBreadcrumbItem, ILanguage, IRootState, ISchema, ISocialState } from "@ax/types";
6
+ import { ILanguage, IRootState, ISocialState } from "@ax/types";
7
7
 
8
8
  const PageBrowser = (props: IProps) => {
9
9
  const {
@@ -21,6 +21,7 @@ const PageBrowser = (props: IProps) => {
21
21
  isTemplateActivated,
22
22
  isReadOnly,
23
23
  isPreview,
24
+ browserRef,
24
25
  } = props;
25
26
 
26
27
  const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
@@ -44,6 +45,7 @@ const PageBrowser = (props: IProps) => {
44
45
  disabled={disabled}
45
46
  siteID={siteID}
46
47
  isPreview={isPreview}
48
+ browserRef={browserRef}
47
49
  />
48
50
  );
49
51
  };
@@ -56,8 +58,6 @@ interface IEditorStateProps {
56
58
  socials: ISocialState;
57
59
  cloudinaryName: string | null;
58
60
  siteLangs: ILanguage[];
59
- schema: ISchema | Record<string, unknown>;
60
- breadcrumb: IBreadcrumbItem[];
61
61
  selectedParent: any;
62
62
  activatedModules: string[];
63
63
  }
@@ -67,6 +67,7 @@ interface IPageBrowserDispatchProps {
67
67
  isTemplateActivated: boolean;
68
68
  isReadOnly: boolean;
69
69
  isPreview?: boolean;
70
+ browserRef?: any;
70
71
  }
71
72
 
72
73
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -78,8 +79,6 @@ const mapStateToProps = (state: IRootState): IEditorStateProps => ({
78
79
  socials: state.social,
79
80
  cloudinaryName: state.app.globalSettings.cloudinaryName,
80
81
  siteLangs: state.sites.currentSiteLanguages,
81
- schema: state.pageEditor.schema,
82
- breadcrumb: state.pageEditor.breadcrumb,
83
82
  selectedParent: state.pageEditor.selectedParent,
84
83
  activatedModules: state.dataPacks.modules,
85
84
  });
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from "react";
1
+ import React, { useEffect, useState, useRef } from "react";
2
2
  import { connect } from "react-redux";
3
3
  import { RouteComponentProps } from "react-router-dom";
4
4
 
@@ -10,7 +10,7 @@ import { navigationActions } from "@ax/containers/Navigation";
10
10
  import { pageStatus } from "@ax/containers/PageEditor/interfaces";
11
11
  import { RouteLeavingGuard } from "@ax/guards";
12
12
  import { useIsDirty, useModal } from "@ax/hooks";
13
- import { isModuleDisabled } from "@ax/helpers";
13
+ import { isModuleDisabled, getDeactivatedModules } from "@ax/helpers";
14
14
  import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
15
15
  import { DeleteModal } from "./atoms";
16
16
  import Editor from "./Editor";
@@ -44,6 +44,7 @@ const PageEditor = (props: IProps) => {
44
44
  pageEditor: { editorContent, schema },
45
45
  userEditing,
46
46
  isNewTranslation,
47
+ currentSiteErrorPages,
47
48
  } = props;
48
49
 
49
50
  const [deleteAllVersions, setDeleteAllVersions] = useState(false);
@@ -54,6 +55,8 @@ const PageEditor = (props: IProps) => {
54
55
  const { isOpen, toggleModal } = useModal();
55
56
  const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
56
57
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
58
+ const [errorPagesChecked, setErrorPagesChecked] = useState(false);
59
+ const browserRef = useRef<HTMLDivElement>(null);
57
60
 
58
61
  const isGlobal = editorContent.editorContent && editorContent.editorContent.origin === "GLOBAL";
59
62
  const isEditable = editorContent.editorContent && editorContent.editorContent.editable;
@@ -101,6 +104,16 @@ const PageEditor = (props: IProps) => {
101
104
  // eslint-disable-next-line react-hooks/exhaustive-deps
102
105
  }, [lang]);
103
106
 
107
+ useEffect(() => {
108
+ if (!errorPagesChecked && !isLoading && editorContent.editorContent) {
109
+ const pageId = editorContent.editorContent.id;
110
+ const hasErrors = currentSiteErrorPages.some((errorPageId) => pageId === errorPageId);
111
+ hasErrors && reviewPage();
112
+ setErrorPagesChecked(true);
113
+ }
114
+ // eslint-disable-next-line react-hooks/exhaustive-deps
115
+ }, [editorContent]);
116
+
104
117
  const setRoute = (path: string) => props.setHistoryPush(path, true);
105
118
 
106
119
  const removePage = async () => {
@@ -118,7 +131,7 @@ const PageEditor = (props: IProps) => {
118
131
  const publishPage = async () => {
119
132
  const { updatePageStatus, savePage, pageID, validatePage } = props;
120
133
 
121
- const validated = await validatePage(true);
134
+ const validated = await validatePage(true, browserRef);
122
135
 
123
136
  if (validated) {
124
137
  const publishPage = {
@@ -138,7 +151,7 @@ const PageEditor = (props: IProps) => {
138
151
  const publishChanges = async () => {
139
152
  const { savePage, validatePage } = props;
140
153
 
141
- const validated = await validatePage(true);
154
+ const validated = await validatePage(true, browserRef);
142
155
 
143
156
  if (validated) {
144
157
  const publishPage = {
@@ -167,13 +180,13 @@ const PageEditor = (props: IProps) => {
167
180
 
168
181
  const reviewPage = () => {
169
182
  const { validatePage } = props;
170
- validatePage();
183
+ validatePage(false, browserRef);
171
184
  };
172
185
 
173
186
  const handlePublishDraft = async () => {
174
187
  const { savePage, validatePage } = props;
175
188
 
176
- const validated = await validatePage(true);
189
+ const validated = await validatePage(true, browserRef);
177
190
 
178
191
  if (validated) {
179
192
  const isSaved = await savePage(false, null, true);
@@ -295,10 +308,12 @@ const PageEditor = (props: IProps) => {
295
308
 
296
309
  const goToPages = (path: string) => setRoute(path);
297
310
 
298
- const goToError = (editorID: number, tab: string, template: boolean) => {
311
+ const goToError = (editorID: number | null, tab: string, template: boolean) => {
299
312
  const realEditorID = template ? 0 : editorID;
300
- setSelectedContent(realEditorID);
301
- setTab(tab);
313
+ if (realEditorID !== null) {
314
+ setSelectedContent(realEditorID);
315
+ setTab(tab);
316
+ }
302
317
  };
303
318
 
304
319
  const modalText = (
@@ -309,9 +324,18 @@ const PageEditor = (props: IProps) => {
309
324
 
310
325
  let isTemplateActivated = true;
311
326
  let hasDeactivatedModules = false;
327
+ let deactivatedModules: string[] = [];
312
328
  if (editorContent.editorContent && editorContent.editorContent.template) {
313
329
  const editorTemplate = editorContent.editorContent.template;
314
- hasDeactivatedModules = isModuleDisabled(selectedComponent, schema.schemaType, activatedModules);
330
+ const mainContentModules = editorTemplate?.mainContent?.modules;
331
+
332
+ if (mainContentModules) {
333
+ deactivatedModules = getDeactivatedModules(activatedModules, mainContentModules);
334
+ hasDeactivatedModules = deactivatedModules.length > 0;
335
+ } else {
336
+ hasDeactivatedModules = isModuleDisabled(selectedComponent, schema.schemaType, activatedModules);
337
+ }
338
+
315
339
  isTemplateActivated = activatedTemplates.find((temp: any) => temp.id === editorTemplate.templateType)
316
340
  ? true
317
341
  : false;
@@ -395,7 +419,8 @@ const PageEditor = (props: IProps) => {
395
419
  if (!isTemplateActivated) {
396
420
  getSiteDataPackbyTemplate(editorTemplate.templateType);
397
421
  } else if (hasDeactivatedModules) {
398
- getSiteDataPackbyModule(selectedComponent);
422
+ const currentModule = deactivatedModules.length === 1 ? deactivatedModules[0] : selectedComponent;
423
+ getSiteDataPackbyModule(currentModule);
399
424
  }
400
425
  setHistoryPush("/sites/settings/content-types", false);
401
426
  }
@@ -506,6 +531,7 @@ const PageEditor = (props: IProps) => {
506
531
  isEditable={isEditable}
507
532
  pageTitle={pageName}
508
533
  isReadOnly={isReadOnly}
534
+ browserRef={browserRef}
509
535
  setNotification={setNotification}
510
536
  />
511
537
  </S.Content>
@@ -576,6 +602,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
576
602
  userEditing: state.pageEditor.userEditing,
577
603
  currentUserID: state.users.currentUser.id,
578
604
  isNewTranslation: state.pageEditor.isNewTranslation,
605
+ currentSiteErrorPages: state.sites.currentSiteErrorPages,
579
606
  });
580
607
 
581
608
  interface IPageEditorStateProps {
@@ -596,6 +623,7 @@ interface IPageEditorStateProps {
596
623
  userEditing: IUserEditing | null;
597
624
  currentUserID: number | null;
598
625
  isNewTranslation: boolean;
626
+ currentSiteErrorPages: number[];
599
627
  }
600
628
 
601
629
  const mapDispatchToProps = {
@@ -622,7 +650,7 @@ interface IPageEditorDispatchProps {
622
650
  getPage(pageID?: number): Promise<void>;
623
651
  savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
624
652
  deletePage(params?: ISavePageParams): Promise<boolean>;
625
- validatePage(publish?: boolean): Promise<boolean>;
653
+ validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
626
654
  updatePageStatus(id: number[], status: string): Promise<boolean>;
627
655
  setHistoryPush(path: string, isEditor: boolean): void;
628
656
  setLanguage?(lang: { locale: string; id: number | null }): void;