@griddo/ax 1.66.3 → 1.66.4

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 (71) hide show
  1. package/package.json +2 -2
  2. package/src/api/pages.tsx +15 -3
  3. package/src/api/redirects.tsx +4 -2
  4. package/src/api/sites.tsx +4 -2
  5. package/src/components/Browser/index.tsx +3 -1
  6. package/src/components/Browser/style.tsx +2 -2
  7. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +0 -1
  8. package/src/components/ErrorCenter/index.tsx +8 -5
  9. package/src/components/ErrorCenter/style.tsx +21 -8
  10. package/src/components/Fields/ColorPicker/index.tsx +1 -0
  11. package/src/components/Fields/LinkField/index.tsx +85 -0
  12. package/src/components/Fields/ReferenceField/ItemList/index.tsx +5 -1
  13. package/src/components/Fields/ReferenceField/index.tsx +18 -14
  14. package/src/components/Fields/UrlField/index.tsx +13 -1
  15. package/src/components/Fields/index.tsx +2 -0
  16. package/src/components/FieldsBehavior/index.tsx +14 -1
  17. package/src/components/Icon/components/Copy.js +14 -0
  18. package/src/components/Icon/svgs/Copy2.svg +3 -0
  19. package/src/components/MainWrapper/AppBar/index.tsx +21 -10
  20. package/src/components/MainWrapper/AppBar/style.tsx +11 -3
  21. package/src/components/MainWrapper/index.tsx +2 -0
  22. package/src/components/Modal/style.tsx +0 -1
  23. package/src/components/SearchField/index.tsx +36 -4
  24. package/src/components/SearchField/style.tsx +23 -10
  25. package/src/components/SideModal/style.tsx +6 -6
  26. package/src/components/TableFilters/StatusFilter/index.tsx +2 -2
  27. package/src/components/index.tsx +2 -0
  28. package/src/containers/App/actions.tsx +3 -7
  29. package/src/containers/PageEditor/actions.tsx +91 -22
  30. package/src/containers/PageEditor/constants.tsx +1 -1
  31. package/src/containers/PageEditor/interfaces.tsx +6 -6
  32. package/src/containers/PageEditor/reducer.tsx +4 -4
  33. package/src/containers/PageEditor/utils.tsx +2 -1
  34. package/src/containers/Sites/actions.tsx +35 -23
  35. package/src/containers/Sites/constants.tsx +1 -0
  36. package/src/containers/Sites/interfaces.tsx +6 -0
  37. package/src/containers/Sites/reducer.tsx +4 -0
  38. package/src/forms/editor.tsx +34 -1
  39. package/src/forms/errors.tsx +1 -0
  40. package/src/forms/index.tsx +15 -1
  41. package/src/forms/validators.tsx +168 -9
  42. package/src/guards/error/index.tsx +1 -1
  43. package/src/helpers/dataPacks.tsx +8 -1
  44. package/src/helpers/index.tsx +2 -1
  45. package/src/modules/Content/PageItem/index.tsx +54 -4
  46. package/src/modules/Content/atoms.tsx +41 -3
  47. package/src/modules/Content/index.tsx +111 -64
  48. package/src/modules/Content/style.tsx +8 -1
  49. package/src/modules/GlobalEditor/Editor/index.tsx +3 -1
  50. package/src/modules/GlobalEditor/PageBrowser/index.tsx +3 -0
  51. package/src/modules/GlobalEditor/index.tsx +8 -6
  52. package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +8 -0
  53. package/src/modules/PageEditor/Editor/index.tsx +6 -2
  54. package/src/modules/PageEditor/PageBrowser/index.tsx +3 -0
  55. package/src/modules/PageEditor/index.tsx +29 -15
  56. package/src/modules/Redirects/index.tsx +40 -10
  57. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/index.tsx +1 -1
  58. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +1 -1
  59. package/src/modules/Settings/ContentTypes/DataPacks/Config/index.tsx +1 -1
  60. package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +1 -1
  61. package/src/modules/Sites/index.tsx +3 -3
  62. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +1 -1
  63. package/src/modules/StructuredData/StructuredDataList/atoms.tsx +1 -1
  64. package/src/modules/Users/Profile/index.tsx +3 -4
  65. package/src/modules/Users/UserCreate/SiteItem/index.tsx +1 -1
  66. package/src/modules/Users/UserCreate/SiteItem/style.tsx +1 -1
  67. package/src/modules/Users/UserForm/style.tsx +3 -3
  68. package/src/modules/Users/UserList/UserItem/index.tsx +3 -1
  69. package/src/modules/Users/UserList/hooks.tsx +1 -1
  70. package/src/modules/Users/UserList/index.tsx +2 -2
  71. package/src/types/index.tsx +16 -3
@@ -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";
@@ -83,9 +84,14 @@ const Content = (props: IProps): JSX.Element => {
83
84
  resetPageEditor,
84
85
  removePageFromSite,
85
86
  importPageFromGlobal,
86
- restorePage,
87
87
  getDataPack,
88
+ getSitesByLang,
88
89
  dataPacks,
90
+ restorePage,
91
+ getAvailableDataPacks,
92
+ sitesByLang,
93
+ user,
94
+ setCurrentDataID,
89
95
  } = props;
90
96
 
91
97
  const itemsPerPage = 50;
@@ -106,10 +112,12 @@ const Content = (props: IProps): JSX.Element => {
106
112
  const isDataEditable = !isStructuredData || (currentStructuredData && currentStructuredData.editable);
107
113
 
108
114
  const pagesIds = currentSitePages && currentSitePages.map((page: any) => page.id);
115
+ const currentSitePagesTemplatesIds = currentSitePages && currentSitePages.map((page: any) => page.templateId);
109
116
  const dataIds = currentDataContent && currentDataContent.map((data: any) => data.id);
110
117
  const contentIds = isStructuredData ? dataIds : pagesIds;
111
- 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)
@@ -147,6 +155,7 @@ const Content = (props: IProps): JSX.Element => {
147
155
  const [deleteAllVersions, setDeleteAllVersions] = useState(false);
148
156
  const [arePagesTranslated, setArePagesTranslated] = useState(false);
149
157
  const [templateInstanceError, setTemplateInstanceError] = useState({ error: false, templateName: "" });
158
+ const [pagesTemplatesIds, setPagesTemplatesIds] = useState<any[]>([]);
150
159
 
151
160
  const {
152
161
  resetBulkSelection,
@@ -170,6 +179,12 @@ const Content = (props: IProps): JSX.Element => {
170
179
  setIsVisible: setIsVisibleDeletedToast,
171
180
  } = useToast();
172
181
 
182
+ const {
183
+ isVisible: isVisibleCopiedToast,
184
+ toggleToast: toggleCopiedToast,
185
+ setIsVisible: setIsVisibleCopiedToast,
186
+ } = useToast();
187
+
173
188
  const { categoryColors, addCategoryColors } = useCategoryColors();
174
189
 
175
190
  const getParams = useCallback(() => {
@@ -231,11 +246,16 @@ const Content = (props: IProps): JSX.Element => {
231
246
  // eslint-disable-next-line react-hooks/exhaustive-deps
232
247
  }, [filter]);
233
248
 
249
+ const fetchSitesByLang = async () => await getSitesByLang(lang.id);
250
+
234
251
  useEffect(() => {
235
252
  if (!locationState || locationState.isFromEditor !== true) {
236
253
  setFilter("unique-pages");
237
254
  }
238
255
  resetPageEditor();
256
+ fetchSitesByLang();
257
+ setCurrentDataID(null);
258
+ getAvailableDataPacks(null);
239
259
  // eslint-disable-next-line react-hooks/exhaustive-deps
240
260
  }, []);
241
261
 
@@ -262,6 +282,12 @@ const Content = (props: IProps): JSX.Element => {
262
282
  // eslint-disable-next-line react-hooks/exhaustive-deps
263
283
  }, [isLoading, currentSitePages]);
264
284
 
285
+ useEffect(() => {
286
+ if (pagesTemplatesIds?.length === 0) {
287
+ setPagesTemplatesIds(currentSitePagesTemplatesIds);
288
+ }
289
+ }, [currentSitePagesTemplatesIds]);
290
+
265
291
  const bulkFilter = (bulkSelection: number[]) => filterByStatus(bulkSelection, currentSitePages);
266
292
 
267
293
  const handleAddToBulk = (item: ICheck) => addToBulkSelection(item, bulkFilter);
@@ -530,13 +556,15 @@ const Content = (props: IProps): JSX.Element => {
530
556
  duplicatePage,
531
557
  removePageFromSite,
532
558
  languageActions: pageLanguageActions,
533
- deleteBulk: deleteCurrentPageBulk,
534
559
  getDataPack: getDataPack,
535
560
  setTemplateInstanceError,
561
+ deleteBulk: deleteCurrentPageBulk,
562
+ toggleCopiedToast,
536
563
  };
537
564
 
538
565
  return (
539
566
  <PageItem
567
+ sites={currentSitesByLang}
540
568
  item={item}
541
569
  key={pageItem.id}
542
570
  functions={pageItemFunctions}
@@ -650,6 +678,11 @@ const Content = (props: IProps): JSX.Element => {
650
678
  message: "Page deleted.",
651
679
  };
652
680
 
681
+ const copiedToastProps = {
682
+ setIsVisible: setIsVisibleCopiedToast,
683
+ message: "1 Page copied to another Site",
684
+ };
685
+
653
686
  const addNewAction = filter === "unique-pages" || isGlobalPages ? toggleNewModal : addNewData;
654
687
 
655
688
  return (
@@ -661,70 +694,74 @@ const Content = (props: IProps): JSX.Element => {
661
694
  rightButton={{ label: "New", action: addNewAction }}
662
695
  searchAction={setSearchQuery}
663
696
  >
664
- <S.ContentListWrapper>
665
- <ContentFilters current={filter} dynamicValues={structuredData} resetFilter={resetFilter} />
666
- <S.TableWrapper>
667
- <ErrorToast />
668
- {templateInstanceError.error && (
669
- <Notification
670
- type="error"
671
- text={`There can be only one ${templateInstanceError.templateName} page and you already have it.`}
672
- />
673
- )}
674
- <TableList
675
- tableHeader={Header}
676
- pagination={pagination}
677
- onScroll={onScroll}
678
- hasFixedHeader={true}
679
- tableRef={tableRef}
680
- >
681
- {!isEmpty ? (
682
- content
683
- ) : (
684
- <S.EmptyWrapper>
685
- <EmptyState {...emptyStateProps} />
686
- </S.EmptyWrapper>
697
+ <>
698
+ <S.ContentListWrapper>
699
+ <ContentFilters current={filter} dynamicValues={structuredData} resetFilter={resetFilter} />
700
+ <S.TableWrapper>
701
+ <ErrorToast />
702
+ {templateInstanceError.error && (
703
+ <Notification
704
+ type="error"
705
+ text={`There can be only one ${templateInstanceError.templateName} page and you already have it.`}
706
+ />
687
707
  )}
688
- </TableList>
689
- </S.TableWrapper>
690
- </S.ContentListWrapper>
691
- <Modal isOpen={isNewOpen} hide={toggleNewModal} size="M" title="New content">
692
- <OptionTable
693
- selectPage={addTemplate}
694
- selectData={addNewStructuredData}
695
- filters={options.filters}
696
- values={options.values}
697
- selectedValue={selectedOption}
698
- theme={currentSiteInfo.theme}
699
- mainAction={createContentAction}
700
- secondaryAction={{ title: "Cancel", onClick: toggleNewModal }}
708
+ <TableList
709
+ tableHeader={Header}
710
+ pagination={pagination}
711
+ onScroll={onScroll}
712
+ hasFixedHeader={true}
713
+ tableRef={tableRef}
714
+ >
715
+ {!isEmpty ? (
716
+ content
717
+ ) : (
718
+ <S.EmptyWrapper>
719
+ <EmptyState {...emptyStateProps} />
720
+ </S.EmptyWrapper>
721
+ )}
722
+ </TableList>
723
+ </S.TableWrapper>
724
+ </S.ContentListWrapper>
725
+ <Modal isOpen={isNewOpen} hide={toggleNewModal} size="M" title="New content">
726
+ <OptionTable
727
+ selectPage={addTemplate}
728
+ selectData={addNewStructuredData}
729
+ filters={options.filters}
730
+ values={options.values}
731
+ selectedValue={selectedOption}
732
+ theme={currentSiteInfo.theme}
733
+ mainAction={createContentAction}
734
+ secondaryAction={{ title: "Cancel", onClick: toggleNewModal }}
735
+ />
736
+ </Modal>
737
+ <Modal
738
+ isOpen={isImporterOpen}
739
+ hide={toggleImporterModal}
740
+ size="M"
741
+ title="New content"
742
+ mainAction={{ title: "Add Pages", onClick: importPage }}
743
+ secondaryAction={{ title: "Cancel", onClick: toggleImporterModal }}
744
+ >
745
+ <PageImporter structuredData={selectedOptionType} {...{ setPagesToImport }} />
746
+ </Modal>
747
+ <DeleteModal
748
+ isOpen={isDeleteOpen}
749
+ toggleModal={toggleDeleteModal}
750
+ mainModalAction={mainDeleteModalAction}
751
+ secondaryModalAction={secondaryDeleteModalAction}
752
+ {...{ isTranslated: arePagesTranslated, deleteAllVersions, setDeleteAllVersions }}
701
753
  />
702
- </Modal>
703
- <Modal
704
- isOpen={isImporterOpen}
705
- hide={toggleImporterModal}
706
- size="M"
707
- title="New content"
708
- mainAction={{ title: "Add Pages", onClick: importPage }}
709
- secondaryAction={{ title: "Cancel", onClick: toggleImporterModal }}
710
- >
711
- <PageImporter structuredData={selectedOptionType} {...{ setPagesToImport }} />
712
- </Modal>
713
- <DeleteModal
714
- isOpen={isDeleteOpen}
715
- toggleModal={toggleDeleteModal}
716
- mainModalAction={mainDeleteModalAction}
717
- secondaryModalAction={secondaryDeleteModalAction}
718
- {...{ isTranslated: arePagesTranslated, deleteAllVersions, setDeleteAllVersions }}
719
- />
720
- {isVisible && <Toast {...toastProps} />}
721
- {isVisibleRemovedToast && <Toast {...removedToastProps} />}
722
- {isVisibleDeletedToast && <Toast {...deletedToastProps} />}
754
+ {isVisible && <Toast {...toastProps} />}
755
+ {isVisibleRemovedToast && <Toast {...removedToastProps} />}
756
+ {isVisibleDeletedToast && <Toast {...deletedToastProps} />}
757
+ {isVisibleCopiedToast && <Toast {...copiedToastProps} />}
758
+ </>
723
759
  </MainWrapper>
724
760
  );
725
761
  };
726
762
 
727
763
  const mapStateToProps = (state: IRootState) => ({
764
+ sitesByLang: state.sites.sitesByLang,
728
765
  currentSiteInfo: state.sites.currentSiteInfo,
729
766
  currentSitePages: state.sites.currentSitePages,
730
767
  filter: state.sites.currentFilter,
@@ -741,6 +778,7 @@ const mapStateToProps = (state: IRootState) => ({
741
778
  activatedTemplates: state.dataPacks.templates,
742
779
  isLoading: state.app.isLoading,
743
780
  dataPacks: state.dataPacks.activated,
781
+ user: state.users.currentUser,
744
782
  });
745
783
 
746
784
  interface IDispatchProps {
@@ -760,7 +798,7 @@ interface IDispatchProps {
760
798
  getStructuredDataContents(params: any, siteID: number): Promise<void>;
761
799
  resetForm(): void;
762
800
  deleteBulk(ids: any): Promise<boolean>;
763
- duplicatePage(pageID: number, data: any): Promise<void>;
801
+ duplicatePage(pageID: number, data?: any, siteID?: number): Promise<boolean>;
764
802
  deleteDataContent(dataID: number[]): Promise<boolean>;
765
803
  restoreDataContent(catID: number | number[]): void;
766
804
  setFilter(value: string): void;
@@ -768,14 +806,18 @@ interface IDispatchProps {
768
806
  resetPageEditor(): Promise<void>;
769
807
  removePageFromSite(pageID: number | number[], refresh?: boolean): Promise<boolean>;
770
808
  importPageFromGlobal(pageID: number | number[]): Promise<boolean>;
771
- restorePage(id: number | number[]): Promise<boolean>;
772
809
  getDataPack: (id: string) => Promise<void>;
810
+ restorePage(id: number | number[]): Promise<boolean>;
811
+ getAvailableDataPacks: (queryParams: string | null) => void;
812
+ getSitesByLang(language: number): Promise<void>;
813
+ setCurrentDataID(id: number | null): void;
773
814
  }
774
815
 
775
816
  const mapDispatchToProps = {
776
817
  setHistoryPush: appActions.setHistoryPush,
777
818
  setLanguage: appActions.setLanguage,
778
819
  getSitePages: sitesActions.getSitePages,
820
+ getSitesByLang: sitesActions.getSitesByLang,
779
821
  setCurrentPageID: pageEditorActions.setCurrentPageID,
780
822
  setCurrentPageStatus: pageEditorActions.setCurrentPageStatus,
781
823
  setCurrentPageName: pageEditorActions.setCurrentPageName,
@@ -796,8 +838,10 @@ const mapDispatchToProps = {
796
838
  resetPageEditor: pageEditorActions.resetPageEditor,
797
839
  removePageFromSite: sitesActions.removePageFromSite,
798
840
  importPageFromGlobal: sitesActions.importPageFromGlobal,
799
- restorePage: pageEditorActions.restorePage,
800
841
  getDataPack: dataPacksActions.getSiteDataPack,
842
+ restorePage: pageEditorActions.restorePage,
843
+ getAvailableDataPacks: dataPacksActions.getAvailableSiteDataPacks,
844
+ setCurrentDataID: structuredDataActions.setCurrentDataID,
801
845
  };
802
846
 
803
847
  interface IPagesProps {
@@ -819,6 +863,9 @@ interface IPagesProps {
819
863
  activatedTemplates: any[];
820
864
  isLoading: boolean;
821
865
  dataPacks: IDataPack[];
866
+ sites: ISite[];
867
+ sitesByLang: ISite[];
868
+ user: IUser;
822
869
  }
823
870
 
824
871
  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 };
@@ -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
 
@@ -50,6 +50,7 @@ const GlobalEditor = (props: IProps) => {
50
50
  const [selectedTab, setSelectedTab] = useState("edit");
51
51
  const [notification, setNotification] = useState<INotification | null>(null);
52
52
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
53
+ const browserRef = useRef<HTMLDivElement>(null);
53
54
 
54
55
  const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
55
56
  const isDraft = props.pageStatus === pageStatus.MODIFIED;
@@ -114,7 +115,7 @@ const GlobalEditor = (props: IProps) => {
114
115
  const publishPage = async () => {
115
116
  const { updatePageStatus, savePage, pageID, validatePage } = props;
116
117
 
117
- const validated = await validatePage(true);
118
+ const validated = await validatePage(true, browserRef);
118
119
 
119
120
  if (validated) {
120
121
  const publishPage = {
@@ -134,7 +135,7 @@ const GlobalEditor = (props: IProps) => {
134
135
  const publishChanges = async () => {
135
136
  const { savePage, validatePage } = props;
136
137
 
137
- const validated = await validatePage(true);
138
+ const validated = await validatePage(true, browserRef);
138
139
 
139
140
  if (validated) {
140
141
  const publishPage = {
@@ -163,13 +164,13 @@ const GlobalEditor = (props: IProps) => {
163
164
 
164
165
  const reviewPage = () => {
165
166
  const { validatePage } = props;
166
- validatePage();
167
+ validatePage(false, browserRef);
167
168
  };
168
169
 
169
170
  const handlePublishDraft = async () => {
170
171
  const { savePage, validatePage } = props;
171
172
 
172
- const validated = await validatePage(true);
173
+ const validated = await validatePage(true, browserRef);
173
174
 
174
175
  if (validated) {
175
176
  const isSaved = await savePage(false, null, true);
@@ -462,6 +463,7 @@ const GlobalEditor = (props: IProps) => {
462
463
  isEditable={isEditable}
463
464
  isReadOnly={isReadOnly}
464
465
  theme={theme}
466
+ browserRef={browserRef}
465
467
  setNotification={setNotification}
466
468
  />
467
469
  </S.Content>
@@ -567,7 +569,7 @@ interface IPageEditorDispatchProps {
567
569
  getPage(pageID?: number, global?: boolean): Promise<void>;
568
570
  savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
569
571
  deletePage(params?: ISavePageParams): Promise<boolean>;
570
- validatePage(publish?: boolean): Promise<boolean>;
572
+ validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
571
573
  updatePageStatus(id: number[], status: string): Promise<boolean>;
572
574
  setHistoryPush(path: string, isEditor: boolean): void;
573
575
  setLanguage?(lang: { locale: string; id: number | null }): void;
@@ -79,6 +79,14 @@ const Form = (props: IProps): JSX.Element => {
79
79
  handlePanel={toggleSecondaryPanel}
80
80
  inFloatingPanel={true}
81
81
  />
82
+ <FieldsBehavior
83
+ title="Image"
84
+ name="image"
85
+ fieldType="ImageField"
86
+ value={itemImage || null}
87
+ onChange={setImageValue}
88
+ setIsGalleryOpened={setIsGalleryOpened}
89
+ />
82
90
  </>
83
91
  )}
84
92
  </>
@@ -35,10 +35,11 @@ const Editor = (props: IProps) => {
35
35
  isReadOnly,
36
36
  userEditing,
37
37
  site,
38
- lastElementAddedId,
39
38
  copyModule,
40
39
  pasteModule,
41
40
  setNotification,
41
+ lastElementAddedId,
42
+ browserRef,
42
43
  } = props;
43
44
 
44
45
  const actions = {
@@ -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;
@@ -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
  };
@@ -67,6 +69,7 @@ interface IPageBrowserDispatchProps {
67
69
  isTemplateActivated: boolean;
68
70
  isReadOnly: boolean;
69
71
  isPreview?: boolean;
72
+ browserRef?: any;
70
73
  }
71
74
 
72
75
  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
 
@@ -10,11 +10,11 @@ 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
- import { DeleteModal } from "./atoms";
16
15
  import Editor from "./Editor";
17
16
  import Preview from "./Preview";
17
+ import { DeleteModal } from "./atoms";
18
18
 
19
19
  import * as S from "./style";
20
20
 
@@ -46,14 +46,15 @@ const PageEditor = (props: IProps) => {
46
46
  isNewTranslation,
47
47
  } = props;
48
48
 
49
- const [deleteAllVersions, setDeleteAllVersions] = useState(false);
50
49
  const [isReadOnly, setIsReadOnly] = useState(false);
51
50
  const [selectedTab, setSelectedTab] = useState("edit");
51
+ const [deleteAllVersions, setDeleteAllVersions] = useState(false);
52
52
  const [notification, setNotification] = useState<INotification | null>(null);
53
53
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
54
54
  const { isOpen, toggleModal } = useModal();
55
55
  const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
56
56
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
57
+ const browserRef = useRef<HTMLDivElement>(null);
57
58
 
58
59
  const isGlobal = editorContent.editorContent && editorContent.editorContent.origin === "GLOBAL";
59
60
  const isEditable = editorContent.editorContent && editorContent.editorContent.editable;
@@ -61,8 +62,8 @@ const PageEditor = (props: IProps) => {
61
62
  const isDraft = props.pageStatus === pageStatus.MODIFIED;
62
63
  const hasDraft = editorContent.editorContent && editorContent.editorContent.haveDraftPage;
63
64
  const isLivePageChanged = editorContent.editorContent && editorContent.editorContent.liveChanged;
64
- const isTranslated = pageLanguages.length > 1;
65
65
  const structuredData = editorContent.editorContent ? editorContent.editorContent.structuredData : "";
66
+ const isTranslated = pageLanguages.length > 1;
66
67
 
67
68
  useEffect(() => {
68
69
  const { pageID, getPage, setTab, sendPagePing } = props;
@@ -118,7 +119,7 @@ const PageEditor = (props: IProps) => {
118
119
  const publishPage = async () => {
119
120
  const { updatePageStatus, savePage, pageID, validatePage } = props;
120
121
 
121
- const validated = await validatePage(true);
122
+ const validated = await validatePage(true, browserRef);
122
123
 
123
124
  if (validated) {
124
125
  const publishPage = {
@@ -138,7 +139,7 @@ const PageEditor = (props: IProps) => {
138
139
  const publishChanges = async () => {
139
140
  const { savePage, validatePage } = props;
140
141
 
141
- const validated = await validatePage(true);
142
+ const validated = await validatePage(true, browserRef);
142
143
 
143
144
  if (validated) {
144
145
  const publishPage = {
@@ -167,13 +168,13 @@ const PageEditor = (props: IProps) => {
167
168
 
168
169
  const reviewPage = () => {
169
170
  const { validatePage } = props;
170
- validatePage();
171
+ validatePage(false, browserRef);
171
172
  };
172
173
 
173
174
  const handlePublishDraft = async () => {
174
175
  const { savePage, validatePage } = props;
175
176
 
176
- const validated = await validatePage(true);
177
+ const validated = await validatePage(true, browserRef);
177
178
 
178
179
  if (validated) {
179
180
  const isSaved = await savePage(false, null, true);
@@ -295,10 +296,12 @@ const PageEditor = (props: IProps) => {
295
296
 
296
297
  const goToPages = (path: string) => setRoute(path);
297
298
 
298
- const goToError = (editorID: number, tab: string, template: boolean) => {
299
+ const goToError = (editorID: number | null, tab: string, template: boolean) => {
299
300
  const realEditorID = template ? 0 : editorID;
300
- setSelectedContent(realEditorID);
301
- setTab(tab);
301
+ if (realEditorID !== null) {
302
+ setSelectedContent(realEditorID);
303
+ setTab(tab);
304
+ }
302
305
  };
303
306
 
304
307
  const modalText = (
@@ -309,9 +312,18 @@ const PageEditor = (props: IProps) => {
309
312
 
310
313
  let isTemplateActivated = true;
311
314
  let hasDeactivatedModules = false;
315
+ let deactivatedModules: string[] = [];
312
316
  if (editorContent.editorContent && editorContent.editorContent.template) {
313
317
  const editorTemplate = editorContent.editorContent.template;
314
- hasDeactivatedModules = isModuleDisabled(selectedComponent, schema.schemaType, activatedModules);
318
+ const mainContentModules = editorTemplate?.mainContent?.modules;
319
+
320
+ if (mainContentModules) {
321
+ deactivatedModules = getDeactivatedModules(activatedModules, mainContentModules);
322
+ hasDeactivatedModules = deactivatedModules.length > 0;
323
+ } else {
324
+ hasDeactivatedModules = isModuleDisabled(selectedComponent, schema.schemaType, activatedModules);
325
+ }
326
+
315
327
  isTemplateActivated = activatedTemplates.find((temp: any) => temp.id === editorTemplate.templateType)
316
328
  ? true
317
329
  : false;
@@ -395,7 +407,8 @@ const PageEditor = (props: IProps) => {
395
407
  if (!isTemplateActivated) {
396
408
  getSiteDataPackbyTemplate(editorTemplate.templateType);
397
409
  } else if (hasDeactivatedModules) {
398
- getSiteDataPackbyModule(selectedComponent);
410
+ const currentModule = deactivatedModules.length === 1 ? deactivatedModules[0] : selectedComponent;
411
+ getSiteDataPackbyModule(currentModule);
399
412
  }
400
413
  setHistoryPush("/sites/settings/content-types", false);
401
414
  }
@@ -506,6 +519,7 @@ const PageEditor = (props: IProps) => {
506
519
  isEditable={isEditable}
507
520
  pageTitle={pageName}
508
521
  isReadOnly={isReadOnly}
522
+ browserRef={browserRef}
509
523
  setNotification={setNotification}
510
524
  />
511
525
  </S.Content>
@@ -622,7 +636,7 @@ interface IPageEditorDispatchProps {
622
636
  getPage(pageID?: number): Promise<void>;
623
637
  savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
624
638
  deletePage(params?: ISavePageParams): Promise<boolean>;
625
- validatePage(publish?: boolean): Promise<boolean>;
639
+ validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
626
640
  updatePageStatus(id: number[], status: string): Promise<boolean>;
627
641
  setHistoryPush(path: string, isEditor: boolean): void;
628
642
  setLanguage?(lang: { locale: string; id: number | null }): void;