@griddo/ax 1.69.9 → 1.72.1

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 (165) hide show
  1. package/config/jest/componentsMock.js +0 -26
  2. package/package.json +4 -3
  3. package/src/Style/index.tsx +1 -1
  4. package/src/__tests__/components/ElementsTooltip/ElementsTooltip.test.tsx +97 -0
  5. package/src/__tests__/components/EmptyState/EmptyState.test.tsx +78 -0
  6. package/src/__tests__/components/FieldContainer/FieldContainer.test.tsx +82 -0
  7. package/src/__tests__/components/Fields/AnalyticsField/AnalyticsField.test.tsx +1 -1
  8. package/src/__tests__/components/Fields/AnalyticsField/PageAnalytics/PageAnalytics.test.tsx +1 -15
  9. package/src/__tests__/components/Fields/AnalyticsField/StructuredDataAnalytics/StructuredDataAnalytics.test.tsx +1 -16
  10. package/src/__tests__/components/Fields/ArrayFieldGroup/ArrayFieldGroup.test.tsx +8 -17
  11. package/src/__tests__/components/Fields/AsyncCheckGroup/AsyncCheckGroup.test.tsx +4 -16
  12. package/src/__tests__/components/Fields/AsyncSelect/AsyncSelect.test.tsx +2 -20
  13. package/src/__tests__/components/Fields/CheckField/CheckField.test.tsx +6 -6
  14. package/src/__tests__/components/Fields/CheckGroup/CheckGroup.test.tsx +15 -15
  15. package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +7 -16
  16. package/src/__tests__/components/Fields/ComponentArray/ComponentArray.test.tsx +2 -23
  17. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +11 -31
  18. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +15 -21
  19. package/src/__tests__/components/Fields/ComponentArray/SameComponentArray/SameComponentArray.test.tsx +6 -25
  20. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +559 -0
  21. package/src/__tests__/components/Fields/ConditionalField/ConditionalField.test.tsx +1 -1
  22. package/src/__tests__/components/Fields/DateField/DateField.test.tsx +1 -1
  23. package/src/__tests__/components/Fields/FieldGroup/FieldGroup.test.tsx +1 -1
  24. package/src/__tests__/components/Fields/FieldsDivider/FieldsDivider.test.tsx +1 -1
  25. package/src/__tests__/components/Fields/FileField/FileField.test.tsx +3 -3
  26. package/src/__tests__/components/Fields/HeadingField/HeadingField.test.tsx +6 -6
  27. package/src/__tests__/components/Fields/HiddenField/HiddenField.test.tsx +2 -8
  28. package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +471 -0
  29. package/src/__tests__/components/Fields/MultiCheckSelect/MultiCheckSelect.test.tsx +2 -16
  30. package/src/__tests__/components/Fields/MultiCheckSelectGroup/MultiCheckSelectGroup.test.tsx +2 -2
  31. package/src/__tests__/components/Fields/NoteField/NoteField.test.tsx +2 -7
  32. package/src/__tests__/components/Fields/NumberField/NumberField.test.tsx +2 -15
  33. package/src/__tests__/components/Fields/RadioField/RadioField.test.tsx +2 -12
  34. package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +171 -19
  35. package/src/__tests__/components/Fields/RichText/RichText.test.tsx +2 -13
  36. package/src/__tests__/components/Fields/Select/Select.test.tsx +3 -23
  37. package/src/__tests__/components/Fields/SliderField/SliderField.test.tsx +2 -15
  38. package/src/__tests__/components/Fields/TagField/TagField.test.tsx +4 -4
  39. package/src/__tests__/components/Fields/TextArea/TextArea.test.tsx +1 -1
  40. package/src/__tests__/components/Fields/TextField/TextField.test.tsx +6 -6
  41. package/src/__tests__/components/Fields/TimeField/HourInput/HourInput.test.tsx +142 -0
  42. package/src/__tests__/components/Fields/TimeField/TimeField.test.tsx +100 -0
  43. package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +2 -10
  44. package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +152 -0
  45. package/src/__tests__/components/Fields/UniqueCheck/UniqueCheck.test.tsx +3 -3
  46. package/src/__tests__/components/Fields/UrlField/UrlField.test.tsx +4 -4
  47. package/src/__tests__/components/Fields/VisualUniqueSelection/ImageSelection/ImageSelection.test.tsx +2 -14
  48. package/src/__tests__/components/Fields/VisualUniqueSelection/ScrollableSelection/ScrollableSelection.test.tsx +6 -20
  49. package/src/__tests__/components/Fields/VisualUniqueSelection/VisualUniqueSelection.test.tsx +3 -29
  50. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.test.tsx +1 -1
  51. package/src/__tests__/components/FieldsBehavior/FieldsBehavior.test.tsx +149 -0
  52. package/src/__tests__/components/SubNav/SubNav.test.tsx +37 -0
  53. package/src/__tests__/components/TableCounter/TableCounter.test.tsx +51 -0
  54. package/src/__tests__/components/TableFilters/CategoryFilter/CategoryFilter.test.tsx +241 -0
  55. package/src/__tests__/components/TableFilters/CustomizeFilters/CustomizeFilters.test.tsx +131 -0
  56. package/src/__tests__/components/TableFilters/DateFilter/DateFilter.test.tsx +148 -0
  57. package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +266 -0
  58. package/src/__tests__/components/TableFilters/NameFilter/NameFilter.test.tsx +196 -0
  59. package/src/__tests__/components/TableFilters/SiteFilter/SiteFilter.test.tsx +318 -0
  60. package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +195 -0
  61. package/src/__tests__/components/TableFilters/TranslationsFilter/TranslationsFilter.test.tsx +157 -0
  62. package/src/__tests__/components/TableFilters/TypeFilter/TypeFilter.test.tsx +165 -0
  63. package/src/__tests__/components/TableList/TableList.test.tsx +119 -0
  64. package/src/__tests__/components/Tabs/Tabs.test.tsx +205 -0
  65. package/src/__tests__/components/Tag/Tag.test.tsx +140 -0
  66. package/src/__tests__/components/Toast/Toast.test.tsx +102 -0
  67. package/src/api/navigation.tsx +1 -1
  68. package/src/components/Browser/index.tsx +1 -1
  69. package/src/components/Button/index.tsx +3 -3
  70. package/src/components/ConfigPanel/NavigationForm/Field/index.tsx +14 -3
  71. package/src/components/ElementsTooltip/index.tsx +10 -9
  72. package/src/components/EmptyState/index.tsx +2 -2
  73. package/src/components/FieldContainer/index.tsx +3 -3
  74. package/src/components/Fields/ArrayFieldGroup/index.tsx +1 -1
  75. package/src/components/Fields/AsyncCheckGroup/index.tsx +1 -1
  76. package/src/components/Fields/AsyncSelect/index.tsx +1 -1
  77. package/src/components/Fields/CheckField/index.tsx +3 -3
  78. package/src/components/Fields/CheckGroup/index.tsx +2 -2
  79. package/src/components/Fields/ComponentContainer/index.tsx +7 -6
  80. package/src/components/Fields/ComponentContainer/style.tsx +2 -2
  81. package/src/components/Fields/HeadingField/index.tsx +1 -1
  82. package/src/components/Fields/HiddenField/index.tsx +1 -1
  83. package/src/components/Fields/ImageField/index.tsx +10 -5
  84. package/src/components/Fields/MultiCheckSelect/index.tsx +3 -3
  85. package/src/components/Fields/NumberField/index.tsx +2 -1
  86. package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +5 -7
  87. package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +2 -2
  88. package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
  89. package/src/components/Fields/RichText/index.tsx +10 -6
  90. package/src/components/Fields/Select/index.tsx +2 -2
  91. package/src/components/Fields/SliderField/index.tsx +1 -1
  92. package/src/components/Fields/TextField/index.tsx +2 -7
  93. package/src/components/Fields/TimeField/HourInput/index.tsx +103 -0
  94. package/src/components/Fields/TimeField/HourInput/style.tsx +19 -0
  95. package/src/components/Fields/TimeField/HourInput/utils.tsx +35 -0
  96. package/src/components/Fields/TimeField/index.tsx +57 -0
  97. package/src/components/Fields/TimeField/style.tsx +37 -0
  98. package/src/components/Fields/index.tsx +2 -0
  99. package/src/components/FieldsBehavior/index.tsx +1 -1
  100. package/src/components/FloatingMenu/index.tsx +2 -2
  101. package/src/components/Gallery/GalleryFilters/Type/index.tsx +50 -0
  102. package/src/components/Gallery/GalleryFilters/Type/style.tsx +39 -0
  103. package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +2 -1
  104. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +3 -3
  105. package/src/components/Gallery/hooks.tsx +10 -4
  106. package/src/components/Gallery/index.tsx +2 -0
  107. package/src/components/Icon/index.tsx +1 -1
  108. package/src/components/IconAction/index.tsx +1 -1
  109. package/src/components/Lists/index.tsx +1 -1
  110. package/src/components/Loading/index.tsx +1 -1
  111. package/src/components/Pagination/index.tsx +1 -1
  112. package/src/components/SideModal/SideModalOption/index.tsx +4 -2
  113. package/src/components/SideModal/index.tsx +1 -1
  114. package/src/components/SubNav/index.tsx +3 -3
  115. package/src/components/SubNav/style.tsx +1 -3
  116. package/src/components/TableCounter/index.tsx +7 -2
  117. package/src/components/TableFilters/CategoryFilter/index.tsx +2 -2
  118. package/src/components/TableFilters/CategoryFilter/style.tsx +1 -10
  119. package/src/components/TableFilters/CustomizeFilters/index.tsx +2 -3
  120. package/src/components/TableFilters/DateFilter/index.tsx +4 -4
  121. package/src/components/TableFilters/LiveFilter/index.tsx +1 -1
  122. package/src/components/TableFilters/LiveFilter/style.tsx +2 -10
  123. package/src/components/TableFilters/NameFilter/index.tsx +4 -4
  124. package/src/components/TableFilters/SiteFilter/index.tsx +16 -13
  125. package/src/components/TableFilters/SiteFilter/style.tsx +1 -10
  126. package/src/components/TableFilters/StatusFilter/index.tsx +3 -3
  127. package/src/components/TableFilters/TranslationsFilter/index.tsx +4 -7
  128. package/src/components/TableFilters/TranslationsFilter/style.tsx +1 -10
  129. package/src/components/TableFilters/TypeFilter/index.tsx +2 -2
  130. package/src/components/TableFilters/TypeFilter/style.tsx +1 -10
  131. package/src/components/TableList/index.tsx +6 -6
  132. package/src/components/TableList/style.tsx +1 -1
  133. package/src/components/Tabs/index.tsx +19 -7
  134. package/src/components/Tag/index.tsx +6 -6
  135. package/src/components/Toast/index.tsx +4 -4
  136. package/src/components/Tooltip/index.tsx +5 -3
  137. package/src/components/index.tsx +2 -0
  138. package/src/containers/Navigation/Defaults/actions.tsx +10 -5
  139. package/src/containers/Navigation/Defaults/utils.tsx +13 -4
  140. package/src/containers/Sites/actions.tsx +7 -0
  141. package/src/containers/Sites/constants.tsx +1 -0
  142. package/src/containers/Sites/interfaces.tsx +6 -0
  143. package/src/containers/Sites/reducer.tsx +4 -0
  144. package/src/containers/StructuredData/actions.tsx +21 -8
  145. package/src/containers/StructuredData/constants.tsx +2 -0
  146. package/src/containers/StructuredData/interfaces.tsx +7 -1
  147. package/src/containers/StructuredData/reducer.tsx +5 -1
  148. package/src/helpers/fields.tsx +2 -2
  149. package/src/helpers/index.tsx +3 -0
  150. package/src/helpers/parseTheme.js +456 -0
  151. package/src/helpers/schemas.tsx +2 -2
  152. package/src/hooks/forms.tsx +2 -1
  153. package/src/modules/App/Routing/NavMenu/index.tsx +9 -1
  154. package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -1
  155. package/src/modules/Content/hooks.tsx +19 -12
  156. package/src/modules/Content/index.tsx +23 -14
  157. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -0
  158. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +3 -1
  159. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +16 -18
  160. package/src/modules/Navigation/Defaults/DefaultsEditor/utils.tsx +37 -0
  161. package/src/modules/StructuredData/Form/ConnectedField/index.tsx +3 -2
  162. package/src/modules/StructuredData/Form/index.tsx +22 -17
  163. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +30 -20
  164. package/src/modules/StructuredData/StructuredDataList/index.tsx +24 -14
  165. package/src/types/index.tsx +8 -7
@@ -97,6 +97,8 @@ const Content = (props: IProps): JSX.Element => {
97
97
  sitesByLang,
98
98
  user,
99
99
  skipReviewOnPublish,
100
+ setContentFilters,
101
+ contentFilters,
100
102
  } = props;
101
103
 
102
104
  const itemsPerPage = 50;
@@ -107,7 +109,12 @@ const Content = (props: IProps): JSX.Element => {
107
109
  const { isOpen: isImporterOpen, toggleModal: toggleImporterModal } = useModal();
108
110
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
109
111
  const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
110
- const { setFiltersSelection, setFilterQuery, resetFilterQuery, filterValues } = useFilterQuery();
112
+ const {
113
+ setFiltersSelection,
114
+ resetFilterQuery,
115
+ filterValues,
116
+ query: currentFilterQuery,
117
+ } = useFilterQuery(contentFilters);
111
118
  const { state: locationState } = useLocation<{ isFromEditor: boolean }>();
112
119
 
113
120
  const currentFilter = getCurrentFilter(structuredData, filter);
@@ -150,7 +157,6 @@ const Content = (props: IProps): JSX.Element => {
150
157
  const isLastItem = page === lastPage && currentSitePages.length === 1;
151
158
 
152
159
  const [isScrolling, setIsScrolling] = useState(false);
153
- const [currentFilterQuery, setCurrentFilterQuery] = useState("");
154
160
  const [deletedItem, setDeletedItem] = useState<number | number[] | null>(null);
155
161
  const [searchQuery, setSearchQuery] = useState<string>("");
156
162
  const [pagesToImport, setPagesToImport] = useState([]);
@@ -258,6 +264,7 @@ const Content = (props: IProps): JSX.Element => {
258
264
  resetPageEditor();
259
265
  resetCurrentSiteErrorPages();
260
266
  fetchSitesByLang();
267
+ resetForm();
261
268
  // eslint-disable-next-line react-hooks/exhaustive-deps
262
269
  }, []);
263
270
 
@@ -284,6 +291,11 @@ const Content = (props: IProps): JSX.Element => {
284
291
  // eslint-disable-next-line react-hooks/exhaustive-deps
285
292
  }, [isLoading, currentSitePages]);
286
293
 
294
+ useEffect(() => {
295
+ setContentFilters(filterValues);
296
+ // eslint-disable-next-line react-hooks/exhaustive-deps
297
+ }, [filterValues]);
298
+
287
299
  const bulkFilter = (bulkSelection: number[]) => filterByStatus(bulkSelection, currentSitePages);
288
300
 
289
301
  const handleAddToBulk = (item: ICheck) => addToBulkSelection(item, bulkFilter);
@@ -295,7 +307,7 @@ const Content = (props: IProps): JSX.Element => {
295
307
  const selectItems = () => (checkState.isAllSelected ? unselectAllItems() : handleSelectAll());
296
308
 
297
309
  const addNewData = () => {
298
- resetForm();
310
+ resetForm(true);
299
311
  const path = `/sites/data/${currentStructuredData.id}/editor`;
300
312
  setHistoryPush(path, false);
301
313
  };
@@ -402,16 +414,12 @@ const Content = (props: IProps): JSX.Element => {
402
414
  const sortedState = getSortedListStatus(orderPointer, isAscending);
403
415
  setSortedListStatus(sortedState);
404
416
 
405
- const filtersSelection = setFiltersSelection("order", orderPointer, isAscending);
406
- const filterQuery = setFilterQuery(filtersSelection);
407
- setCurrentFilterQuery(filterQuery);
417
+ setFiltersSelection("order", orderPointer, isAscending);
408
418
  };
409
419
 
410
420
  const filterItems = async (filterPointer: string, filtersSelected: string) => {
411
421
  setPage(firstPage);
412
- const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
413
- const filterQuery = setFilterQuery(filtersSelection);
414
- setCurrentFilterQuery(filterQuery);
422
+ setFiltersSelection(filterPointer, filtersSelected);
415
423
  };
416
424
 
417
425
  const Header = (
@@ -651,10 +659,7 @@ const Content = (props: IProps): JSX.Element => {
651
659
  ? { onClick: handleImport, title: "NEXT" }
652
660
  : { onClick: createContent, title: "Create new" };
653
661
 
654
- const resetFilter = () => {
655
- resetFilterQuery();
656
- setCurrentFilterQuery("");
657
- };
662
+ const resetFilter = () => resetFilterQuery();
658
663
 
659
664
  const mainDeleteModalAction = {
660
665
  title: "Delete pages",
@@ -786,6 +791,7 @@ const mapStateToProps = (state: IRootState) => ({
786
791
  sitesByLang: state.sites.sitesByLang,
787
792
  user: state.users.currentUser,
788
793
  skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
794
+ contentFilters: state.sites.contentFilters,
789
795
  });
790
796
 
791
797
  interface IDispatchProps {
@@ -803,7 +809,7 @@ interface IDispatchProps {
803
809
  createNewTranslation(isNewTranslation: boolean): void;
804
810
  getFilteredContent(filter: string | null): void;
805
811
  getStructuredDataContents(params: any, siteID: number): Promise<void>;
806
- resetForm(): void;
812
+ resetForm(setDefault?: boolean): void;
807
813
  deleteBulk(ids: any): Promise<boolean>;
808
814
  duplicatePage(pageID: number, data?: any, siteID?: number): Promise<boolean>;
809
815
  getPage(pageID?: number, global?: boolean): Promise<void>;
@@ -819,6 +825,7 @@ interface IDispatchProps {
819
825
  getDataPack: (id: string) => Promise<void>;
820
826
  resetCurrentSiteErrorPages: () => Promise<void>;
821
827
  getSitesByLang(language: number): Promise<void>;
828
+ setContentFilters(contentFilters: Record<string, string> | null): void;
822
829
  }
823
830
 
824
831
  const mapDispatchToProps = {
@@ -851,6 +858,7 @@ const mapDispatchToProps = {
851
858
  getDataPack: dataPacksActions.getSiteDataPack,
852
859
  resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
853
860
  getSitesByLang: sitesActions.getSitesByLang,
861
+ setContentFilters: sitesActions.setContentFilters,
854
862
  };
855
863
 
856
864
  interface IPagesProps {
@@ -878,6 +886,7 @@ interface IPagesProps {
878
886
  sitesByLang: ISite[];
879
887
  user: IUser;
880
888
  skipReviewOnPublish?: boolean;
889
+ contentFilters: Record<string, string> | null;
881
890
  }
882
891
 
883
892
  type IProps = IPagesProps & IDispatchProps;
@@ -13,12 +13,14 @@ const DefaultsBrowser = (props: IProps) => {
13
13
  setSelectedContent,
14
14
  currentSiteInfo: { theme, id: siteID },
15
15
  siteLangs,
16
+ browserRef,
16
17
  } = props;
17
18
 
18
19
  const updatedContent = { ...content };
19
20
 
20
21
  return (
21
22
  <Browser
23
+ browserRef={browserRef}
22
24
  isPage={false}
23
25
  socials={socials}
24
26
  content={updatedContent}
@@ -43,6 +45,7 @@ interface IEditorStateProps {
43
45
 
44
46
  interface IPageBrowserDispatchProps {
45
47
  setSelectedContent(editorID: number): void;
48
+ browserRef?: any;
46
49
  }
47
50
 
48
51
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -23,6 +23,7 @@ const Editor = (props: IProps) => {
23
23
  selectedTab,
24
24
  isLoading,
25
25
  site,
26
+ browserRef,
26
27
  } = props;
27
28
 
28
29
  const actions = {
@@ -36,7 +37,7 @@ const Editor = (props: IProps) => {
36
37
 
37
38
  return (
38
39
  <ResizePanel
39
- leftPanel={<DefaultsBrowser />}
40
+ leftPanel={<DefaultsBrowser browserRef={browserRef} />}
40
41
  rightPanel={
41
42
  <ConfigPanel
42
43
  schema={schema}
@@ -77,6 +78,7 @@ interface IPageBrowserDispatchProps {
77
78
  replaceModule(module: any, parent: any, objKey: string): void;
78
79
  replaceElementsInCollection(newValue: string, reference: string): void;
79
80
  moveModule(moduleID: number, selectedContent: any, newIndex: number, key: string): void;
81
+ browserRef?: any;
80
82
  }
81
83
 
82
84
  type IProps = IEditorStateProps & IPageBrowserDispatchProps;
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from "react";
1
+ import React, { useEffect, useRef } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
4
  import { IRootState } from "@ax/types";
@@ -11,6 +11,7 @@ import { ErrorToast, Loading, MainWrapper, Modal } from "@ax/components";
11
11
  import Editor from "./Editor";
12
12
 
13
13
  import * as S from "./style";
14
+ import { getImage } from "./utils";
14
15
 
15
16
  const DefaultsEditor = (props: IProps) => {
16
17
  const {
@@ -40,6 +41,7 @@ const DefaultsEditor = (props: IProps) => {
40
41
  const isNew = !editorContent?.id;
41
42
 
42
43
  const isSetAsDefault = editorContent && editorContent.setAsDefault;
44
+ const browserRef = useRef<any>(null);
43
45
 
44
46
  useEffect(() => {
45
47
  getValues();
@@ -64,18 +66,14 @@ const DefaultsEditor = (props: IProps) => {
64
66
  // eslint-disable-next-line react-hooks/exhaustive-deps
65
67
  }, [currentSiteInfo, editorContent?.id]);
66
68
 
67
- const save = () => {
68
- isNew || isNewTranslation
69
- ? createNavigation().then((isSaved: boolean) => {
70
- if (isSaved) {
71
- resetDirty();
72
- }
73
- })
74
- : updateNavigation(editorContent.id, editorContent, true).then((isSaved: boolean) => {
75
- if (isSaved) {
76
- resetDirty();
77
- }
78
- });
69
+ const save = async () => {
70
+ const image = await getImage(browserRef);
71
+
72
+ const isSaved =
73
+ isNew || isNewTranslation
74
+ ? await createNavigation(image)
75
+ : await updateNavigation(editorContent.id, editorContent, true, image);
76
+ if (isSaved) resetDirty();
79
77
  };
80
78
 
81
79
  const saveAsDefault = () => {
@@ -121,7 +119,7 @@ const DefaultsEditor = (props: IProps) => {
121
119
  <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>
122
120
  );
123
121
 
124
- const maintModalAction = { title: "Yes, set as default", onClick: saveAsDefault };
122
+ const mainModalAction = { title: "Yes, set as default", onClick: saveAsDefault };
125
123
  const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
126
124
  const goBack = (path: string) => setHistoryPush(path, true);
127
125
 
@@ -147,13 +145,13 @@ const DefaultsEditor = (props: IProps) => {
147
145
  hide={toggleModal}
148
146
  title={`Default ${editorContent.component}`}
149
147
  secondaryAction={secondaryModalAction}
150
- mainAction={maintModalAction}
148
+ mainAction={mainModalAction}
151
149
  size="S"
152
150
  >
153
151
  {isOpen ? <S.ModalContent>{setDefaultModalText}</S.ModalContent> : null}
154
152
  </Modal>
155
153
  <S.Content>
156
- <Editor />
154
+ <Editor browserRef={browserRef} />
157
155
  </S.Content>
158
156
  </MainWrapper>
159
157
  </>
@@ -206,8 +204,8 @@ interface IDispatchProps {
206
204
  setHistoryPush(path: string, isEditor?: boolean): void;
207
205
  setLanguage?(lang: { locale: string; id: number | null }): void;
208
206
  getValues(): void;
209
- createNavigation(): Promise<boolean>;
210
- updateNavigation(navID: number, data: any, fromEditor?: boolean): Promise<boolean>;
207
+ createNavigation(image: File | null): Promise<boolean>;
208
+ updateNavigation(navID: number, data: any, fromEditor?: boolean, image?: File | null): Promise<boolean>;
211
209
  createTranslation(isNewTranslation: boolean): void;
212
210
  setHeader(id: number | null): void;
213
211
  setFooter(id: number | null): void;
@@ -0,0 +1,37 @@
1
+ import { toBlob } from "html-to-image";
2
+
3
+ const getImage = async (browserRef: any): Promise<File | null> => {
4
+ if (browserRef?.current) {
5
+ const browserContent = browserRef.current.querySelector(".browser-content");
6
+
7
+ const { height, overflow } = getComputedStyle(browserContent);
8
+ browserContent.style.height = "auto";
9
+ browserContent.style.overflow = "visible";
10
+ const originalHeight = browserContent.clientHeight;
11
+
12
+ const elChildren = browserContent.querySelectorAll("*");
13
+ let maxAbsoluteElementHeight = 0;
14
+ [].forEach.call(elChildren, function (element: any) {
15
+ const isAbsolutePosition = getComputedStyle(element).position === "absolute";
16
+ const isMaxAbsolutePositionHeight = element.clientHeight > maxAbsoluteElementHeight;
17
+ if (isAbsolutePosition && isMaxAbsolutePositionHeight) {
18
+ maxAbsoluteElementHeight = element.clientHeight;
19
+ }
20
+ });
21
+ if (maxAbsoluteElementHeight) {
22
+ const actualHeight = originalHeight + maxAbsoluteElementHeight;
23
+ browserContent.style.height = `${actualHeight}px`;
24
+ }
25
+
26
+ const imageBlob = await toBlob(browserContent, { quality: 0.95, pixelRatio: 0.5 });
27
+ const imageFile = imageBlob && new File([imageBlob], "navigation-thumbnail.png", { type: "image/png" });
28
+
29
+ browserContent.style.height = height;
30
+ browserContent.style.overflow = overflow;
31
+
32
+ return imageFile;
33
+ }
34
+ return null;
35
+ };
36
+
37
+ export { getImage };
@@ -11,7 +11,7 @@ import * as S from "./style";
11
11
  const ConnectedField = (props: IProps) => {
12
12
  const { field, site, form, fieldKey, updateFormValue, disabled, errors, deleteError, theme } = props;
13
13
 
14
- const value = form.content && form.content[fieldKey];
14
+ const value = form?.content && form.content[fieldKey];
15
15
  const error = errors.find((err: any) => err.key === field.key);
16
16
 
17
17
  const handleChange = (newValue: any) => updateFormValue({ [fieldKey]: newValue });
@@ -22,7 +22,7 @@ const ConnectedField = (props: IProps) => {
22
22
  let innerFields: JSX.Element[] = [];
23
23
 
24
24
  if (isConditional || isArrayGroup) {
25
- innerFields = getStructuredDataInnerFields(field.fields, form.content, updateFormValue, theme, errors);
25
+ innerFields = getStructuredDataInnerFields(field.fields, form?.content, updateFormValue, theme, errors);
26
26
  }
27
27
 
28
28
  const fieldProps = {
@@ -37,6 +37,7 @@ const ConnectedField = (props: IProps) => {
37
37
  error,
38
38
  deleteError,
39
39
  theme,
40
+ delayed: false,
40
41
  };
41
42
 
42
43
  return (
@@ -40,12 +40,11 @@ const Form = (props: IProps) => {
40
40
  validated,
41
41
  validateForm,
42
42
  currentStructuredDataId,
43
- resetForm,
44
43
  skipReviewOnPublish,
45
44
  } = props;
46
45
 
47
- const [isNewStructuredData, setIsNewStructuredData] = useState(!form.id);
48
- const { isDirty, resetDirty } = useIsDirty(form);
46
+ const [isNewStructuredData, setIsNewStructuredData] = useState(!currentStructuredDataId);
47
+ const { isDirty, resetDirty, setIsDirty } = useIsDirty(form);
49
48
 
50
49
  const { fields } = schema;
51
50
 
@@ -60,17 +59,25 @@ const Form = (props: IProps) => {
60
59
  const theme = getDefaultTheme();
61
60
 
62
61
  useEffect(() => {
63
- resetForm();
64
- currentStructuredDataId && getDataContent(currentStructuredDataId);
62
+ const handleGetContent = async (dataID: number) => {
63
+ await getDataContent(dataID);
64
+ };
65
+
66
+ if (currentStructuredDataId) {
67
+ handleGetContent(currentStructuredDataId);
68
+ } else {
69
+ setIsDirty(true);
70
+ }
71
+
65
72
  // eslint-disable-next-line react-hooks/exhaustive-deps
66
- }, [currentStructuredDataId]);
73
+ }, []);
67
74
 
68
75
  const Fields =
69
76
  fields &&
70
77
  fields.map((field: any, i: number) => {
71
78
  const { type, key } = field;
72
79
  if (key === "title") {
73
- title = form.content && form.content[key] ? form.content[key] : "";
80
+ title = form?.content && form.content[key] ? form.content[key] : "";
74
81
  }
75
82
  return (
76
83
  <ConnectedField
@@ -116,14 +123,14 @@ const Form = (props: IProps) => {
116
123
 
117
124
  const getSaveLabel = () => {
118
125
  if (isNewStructuredData) return "Save";
119
- return form.draft ? "Save" : "Save & publish";
126
+ return form?.draft ? "Save" : "Save & publish";
120
127
  };
121
128
 
122
129
  const handleSaveAndPublish = () => (isNewStructuredData || form.draft ? handleSave(false) : handleSave(true));
123
130
 
124
131
  const rightButtonProps = {
125
132
  label: isSaving ? "Saving" : getSaveLabel(),
126
- disabled: isSaving || isDisabled,
133
+ disabled: isSaving || isDisabled || !isDirty,
127
134
  action: handleSaveAndPublish,
128
135
  };
129
136
 
@@ -142,7 +149,7 @@ const Form = (props: IProps) => {
142
149
  const getCurrentLanguages = () => {
143
150
  const availables: any[] = [];
144
151
 
145
- form.dataLanguages &&
152
+ form?.dataLanguages &&
146
153
  form.dataLanguages.forEach(
147
154
  (dataLang: any) =>
148
155
  languages &&
@@ -228,7 +235,7 @@ const Form = (props: IProps) => {
228
235
 
229
236
  const downArrowMenu = {
230
237
  displayed: true,
231
- button: getPublishButton(form.draft),
238
+ button: getPublishButton(form?.draft),
232
239
  options: [
233
240
  {
234
241
  label: "Review",
@@ -243,7 +250,7 @@ const Form = (props: IProps) => {
243
250
  ],
244
251
  };
245
252
 
246
- const status = form.draft === true || form.draft === undefined ? "offline" : "active";
253
+ const status = !form || form.draft === true || form.draft === undefined ? "offline" : "active";
247
254
 
248
255
  const languageProps = {
249
256
  lang: isDataTranslatable ? lang : null,
@@ -273,7 +280,7 @@ const Form = (props: IProps) => {
273
280
  pageStatus={status}
274
281
  downArrowMenu={downArrowMenu}
275
282
  isFromEditor={true}
276
- currentPageID={form.id}
283
+ currentPageID={form?.id}
277
284
  errors={errors}
278
285
  >
279
286
  {isDisabled && (
@@ -305,7 +312,7 @@ const Form = (props: IProps) => {
305
312
 
306
313
  interface IProps {
307
314
  schema: any;
308
- form: any;
315
+ form: any | null;
309
316
  site: ISite | null;
310
317
  currentStructuredData: any;
311
318
  isSaving: boolean;
@@ -322,13 +329,12 @@ interface IProps {
322
329
  createStructuredDataContent: (payload: any) => Promise<boolean>;
323
330
  updateStructuredDataContent: (payload: any) => Promise<boolean>;
324
331
  setLanguage(lang: { locale: string; id: number | null }): void;
325
- getDataContent(id: number): void;
332
+ getDataContent(id: number): Promise<void>;
326
333
  setHistoryPush(path: string, isEditor?: boolean): void;
327
334
  getSiteDataPack(packID: string): void;
328
335
  setDataStatus(id: number, status: string): Promise<boolean>;
329
336
  deleteStructuredDataContent(id: number): Promise<boolean>;
330
337
  validateForm(publish?: boolean): Promise<boolean>;
331
- resetForm(): void;
332
338
  }
333
339
 
334
340
  const mapStateToProps = (state: IRootState) => ({
@@ -359,7 +365,6 @@ const mapDispatchToProps = {
359
365
  setDataStatus: structuredDataActions.setStatusStructuredDataContent,
360
366
  deleteStructuredDataContent: structuredDataActions.deleteStructuredDataContent,
361
367
  validateForm: structuredDataActions.validateForm,
362
- resetForm: structuredDataActions.resetForm,
363
368
  };
364
369
 
365
370
  export default connect(mapStateToProps, mapDispatchToProps)(Form);
@@ -17,7 +17,10 @@ const useSortedListStatus = (): IUseSortedListStatus => {
17
17
  };
18
18
  };
19
19
 
20
- const useFilterQuery = (currentStructuredData: IStructuredData | null): IUseFilterQuery => {
20
+ const useFilterQuery = (
21
+ currentStructuredData: IStructuredData | null,
22
+ values: Record<string, IStructuredDataQueryValues> | null
23
+ ): IUseFilterQuery => {
21
24
  const structuredDataType = currentStructuredData ? currentStructuredData.id : "all";
22
25
  const initialQueryValues = {
23
26
  types: "all",
@@ -29,16 +32,7 @@ const useFilterQuery = (currentStructuredData: IStructuredData | null): IUseFilt
29
32
  related: "all",
30
33
  };
31
34
 
32
- const [query, setQuery] = useState<Record<string, IStructuredDataQueryValues>>({ all: initialQueryValues });
33
-
34
- useEffect(() => {
35
- if (!query[structuredDataType]) {
36
- setQuery((state) => ({ [structuredDataType]: initialQueryValues, ...state }));
37
- }
38
- // eslint-disable-next-line react-hooks/exhaustive-deps
39
- }, [structuredDataType]);
40
-
41
- const setFilterQuery = (filterValues: IStructuredDataQueryValues) => {
35
+ const getFilterQuery = (filterValues: IStructuredDataQueryValues) => {
42
36
  const { types, translated, liveStatus, order, filterSites, categories, related } = filterValues;
43
37
  let filterQuery = "";
44
38
 
@@ -61,9 +55,22 @@ const useFilterQuery = (currentStructuredData: IStructuredData | null): IUseFilt
61
55
  return filterQuery;
62
56
  };
63
57
 
58
+ const initState = values ? values : { all: initialQueryValues };
59
+ const [state, setState] = useState<Record<string, IStructuredDataQueryValues>>(initState);
60
+
61
+ const initQuery = values && values[structuredDataType] ? getFilterQuery(values[structuredDataType]) : "";
62
+ const [query, setQuery] = useState(initQuery);
63
+
64
+ useEffect(() => {
65
+ if (!state[structuredDataType]) {
66
+ setState((state) => ({ [structuredDataType]: initialQueryValues, ...state }));
67
+ }
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ }, [structuredDataType]);
70
+
64
71
  const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
65
72
  const { types, translated, liveStatus, order, filterSites, categories, related } =
66
- query[structuredDataType] || initialQueryValues;
73
+ state[structuredDataType] || initialQueryValues;
67
74
  const orderMethod = isAscendent ? "asc" : "desc";
68
75
  const filterValues = {
69
76
  types: pointer === "types" ? filter : types,
@@ -75,18 +82,21 @@ const useFilterQuery = (currentStructuredData: IStructuredData | null): IUseFilt
75
82
  related: pointer === "related" ? filter : related,
76
83
  };
77
84
 
78
- setQuery((state) => ({ ...state, [structuredDataType]: filterValues }));
79
-
80
- return filterValues;
85
+ setState((state) => ({ ...state, [structuredDataType]: filterValues }));
86
+ const filterQuery = getFilterQuery(filterValues);
87
+ setQuery(filterQuery);
81
88
  };
82
89
 
83
- const resetFilterQuery = () => setQuery({ [structuredDataType]: initialQueryValues });
90
+ const resetFilterQuery = () => {
91
+ setState({ [structuredDataType]: initialQueryValues });
92
+ setQuery("");
93
+ };
84
94
 
85
95
  return {
86
96
  setFiltersSelection,
87
- setFilterQuery,
88
97
  resetFilterQuery,
89
- filterValues: query,
98
+ filterValues: state,
99
+ query,
90
100
  };
91
101
  };
92
102
 
@@ -96,10 +106,10 @@ interface IUseSortedListStatus {
96
106
  }
97
107
 
98
108
  interface IUseFilterQuery {
99
- setFiltersSelection(pointer: string, filter: string, isAscendent?: boolean): IStructuredDataQueryValues;
100
- setFilterQuery(filterValues: IStructuredDataQueryValues): string;
109
+ setFiltersSelection(pointer: string, filter: string, isAscendent?: boolean): void;
101
110
  resetFilterQuery(): void;
102
111
  filterValues: Record<string, IStructuredDataQueryValues>;
112
+ query: string;
103
113
  }
104
114
 
105
115
  export { useSortedListStatus, useFilterQuery };
@@ -16,6 +16,7 @@ import {
16
16
  IPage,
17
17
  ICheck,
18
18
  IColumn,
19
+ IStructuredDataQueryValues,
19
20
  } from "@ax/types";
20
21
  import {
21
22
  ISetCurrentPageIDAction,
@@ -86,6 +87,8 @@ const StructuredDataList = (props: IProps): JSX.Element => {
86
87
  resetCurrentSiteErrorPages,
87
88
  currentSiteErrorPages,
88
89
  skipReviewOnPublish,
90
+ setContentFilters,
91
+ contentFilters,
89
92
  } = props;
90
93
 
91
94
  const itemsPerPage = 50;
@@ -108,8 +111,12 @@ const StructuredDataList = (props: IProps): JSX.Element => {
108
111
  const { isOpen: isNewOpen, toggleModal: toggleNewModal } = useModal();
109
112
  const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
110
113
  const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
111
- const { setFiltersSelection, setFilterQuery, filterValues, resetFilterQuery } = useFilterQuery(currentStructuredData);
112
- const [currentFilterQuery, setCurrentFilterQuery] = useState("");
114
+ const {
115
+ setFiltersSelection,
116
+ filterValues,
117
+ resetFilterQuery,
118
+ query: currentFilterQuery,
119
+ } = useFilterQuery(currentStructuredData, contentFilters);
113
120
  const history = useHistory();
114
121
  const [isFirstRender, setIsFirstRender] = useState(true);
115
122
  const [deleteAllVersions, setDeleteAllVersions] = useState(false);
@@ -218,6 +225,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
218
225
  setIsFirstRender(false);
219
226
  resetPageEditor();
220
227
  resetCurrentSiteErrorPages();
228
+ resetForm();
221
229
  // eslint-disable-next-line react-hooks/exhaustive-deps
222
230
  }, []);
223
231
 
@@ -264,10 +272,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
264
272
  // eslint-disable-next-line react-hooks/exhaustive-deps
265
273
  }, [currentDataContent]);
266
274
 
267
- const resetFilterValues = () => {
268
- resetFilterQuery();
269
- setCurrentFilterQuery("");
270
- };
275
+ const resetFilterValues = () => resetFilterQuery();
271
276
 
272
277
  useEffect(() => {
273
278
  if (!isFirstRender && !isLoading) {
@@ -296,6 +301,11 @@ const StructuredDataList = (props: IProps): JSX.Element => {
296
301
  // eslint-disable-next-line react-hooks/exhaustive-deps
297
302
  }, []);
298
303
 
304
+ useEffect(() => {
305
+ setContentFilters(filterValues);
306
+ // eslint-disable-next-line react-hooks/exhaustive-deps
307
+ }, [filterValues]);
308
+
299
309
  const handleClick = (isFromPage?: boolean, globalPage?: IPage, forceLive?: boolean) => {
300
310
  if (isFromPage && globalPage) {
301
311
  const pageID = globalPage.haveDraftPage && !forceLive ? globalPage.haveDraftPage : globalPage.id;
@@ -312,7 +322,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
312
322
 
313
323
  const createNewData = () => {
314
324
  setCurrentDataID(null);
315
- resetForm();
325
+ resetForm(true);
316
326
  handleClick();
317
327
  };
318
328
 
@@ -404,17 +414,13 @@ const StructuredDataList = (props: IProps): JSX.Element => {
404
414
  const sortedState = getSortedListStatus(orderPointer, isAscending);
405
415
  setSortedListStatus(sortedState);
406
416
 
407
- const filtersSelection = setFiltersSelection("order", orderPointer, isAscending);
408
- const filterQuery = setFilterQuery(filtersSelection);
409
- setCurrentFilterQuery(filterQuery);
417
+ setFiltersSelection("order", orderPointer, isAscending);
410
418
  };
411
419
 
412
420
  const filterItems = async (filterPointer: string, filtersSelected: string) => {
413
421
  setPage(firstPage);
414
422
  if (!isStructuredDataFromPage && filterPointer === "categories") filterPointer = "related";
415
- const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
416
- const filterQuery = setFilterQuery(filtersSelection);
417
- setCurrentFilterQuery(filterQuery);
423
+ setFiltersSelection(filterPointer, filtersSelected);
418
424
  };
419
425
 
420
426
  const currentDataColumnsState = currentStructuredData ? columnsState[structuredDataType] || [] : columnsState["all"];
@@ -637,6 +643,7 @@ const mapStateToProps = (state: IRootState) => ({
637
643
  currentSitePages: state.sites.currentSitePages,
638
644
  currentSiteErrorPages: state.sites.currentSiteErrorPages,
639
645
  skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
646
+ contentFilters: state.structuredData.contentFilters,
640
647
  });
641
648
 
642
649
  const mapDispatchToProps = {
@@ -661,11 +668,12 @@ const mapDispatchToProps = {
661
668
  getAnalytics: analyticsActions.getAnalytics,
662
669
  setCurrentDataID: structuredDataActions.setCurrentDataID,
663
670
  resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
671
+ setContentFilters: structuredDataActions.setContentFilters,
664
672
  };
665
673
 
666
674
  interface IDispatchProps {
667
675
  setHistoryPush(route: string, isEditor?: boolean): void;
668
- resetForm(): void;
676
+ resetForm(setDefault?: boolean): void;
669
677
  setLanguage(lang: { locale: string; id: number }): void;
670
678
  getStructuredDataContents(params: IGetStructuredDataParams): void;
671
679
  setSelectedStructuredData(id: string, scope: string): void;
@@ -685,6 +693,7 @@ interface IDispatchProps {
685
693
  getAnalytics(): void;
686
694
  setCurrentDataID(id: number | null): void;
687
695
  resetCurrentSiteErrorPages: () => Promise<void>;
696
+ setContentFilters(contentFilters: Record<string, IStructuredDataQueryValues> | null): void;
688
697
  }
689
698
 
690
699
  interface ICategoriesProps {
@@ -702,6 +711,7 @@ interface ICategoriesProps {
702
711
  currentSitePages: IPage[];
703
712
  currentSiteErrorPages: number[];
704
713
  skipReviewOnPublish?: boolean;
714
+ contentFilters: Record<string, IStructuredDataQueryValues> | null;
705
715
  }
706
716
 
707
717
  type IProps = ICategoriesProps & IDispatchProps;