@griddo/ax 1.69.7 → 1.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/config/jest/componentsMock.js +0 -26
  2. package/package.json +4 -3
  3. package/src/__tests__/components/ElementsTooltip/ElementsTooltip.test.tsx +97 -0
  4. package/src/__tests__/components/EmptyState/EmptyState.test.tsx +78 -0
  5. package/src/__tests__/components/Fields/AnalyticsField/PageAnalytics/PageAnalytics.test.tsx +0 -14
  6. package/src/__tests__/components/Fields/AnalyticsField/StructuredDataAnalytics/StructuredDataAnalytics.test.tsx +0 -15
  7. package/src/__tests__/components/Fields/ArrayFieldGroup/ArrayFieldGroup.test.tsx +6 -15
  8. package/src/__tests__/components/Fields/AsyncCheckGroup/AsyncCheckGroup.test.tsx +1 -13
  9. package/src/__tests__/components/Fields/AsyncSelect/AsyncSelect.test.tsx +1 -19
  10. package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +1 -10
  11. package/src/__tests__/components/Fields/ComponentArray/ComponentArray.test.tsx +1 -22
  12. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +4 -24
  13. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +6 -12
  14. package/src/__tests__/components/Fields/ComponentArray/SameComponentArray/SameComponentArray.test.tsx +1 -20
  15. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +559 -0
  16. package/src/__tests__/components/Fields/HiddenField/HiddenField.test.tsx +1 -7
  17. package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +471 -0
  18. package/src/__tests__/components/Fields/MultiCheckSelect/MultiCheckSelect.test.tsx +1 -15
  19. package/src/__tests__/components/Fields/NoteField/NoteField.test.tsx +1 -6
  20. package/src/__tests__/components/Fields/NumberField/NumberField.test.tsx +1 -14
  21. package/src/__tests__/components/Fields/RadioField/RadioField.test.tsx +1 -11
  22. package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +77 -13
  23. package/src/__tests__/components/Fields/RichText/RichText.test.tsx +1 -12
  24. package/src/__tests__/components/Fields/Select/Select.test.tsx +1 -21
  25. package/src/__tests__/components/Fields/SliderField/SliderField.test.tsx +1 -14
  26. package/src/__tests__/components/Fields/TagField/TagField.test.tsx +3 -3
  27. package/src/__tests__/components/Fields/TimeField/HourInput/HourInput.test.tsx +142 -0
  28. package/src/__tests__/components/Fields/TimeField/TimeField.test.tsx +100 -0
  29. package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +1 -9
  30. package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +151 -0
  31. package/src/__tests__/components/Fields/VisualUniqueSelection/ImageSelection/ImageSelection.test.tsx +1 -13
  32. package/src/__tests__/components/Fields/VisualUniqueSelection/ScrollableSelection/ScrollableSelection.test.tsx +3 -17
  33. package/src/__tests__/components/Fields/VisualUniqueSelection/VisualUniqueSelection.test.tsx +2 -28
  34. package/src/__tests__/components/TableList/TableList.test.tsx +119 -0
  35. package/src/__tests__/components/Tabs/Tabs.test.tsx +202 -0
  36. package/src/__tests__/components/Tag/Tag.test.tsx +138 -0
  37. package/src/__tests__/components/Toast/Toast.test.tsx +100 -0
  38. package/src/api/navigation.tsx +1 -1
  39. package/src/components/Browser/index.tsx +1 -1
  40. package/src/components/Button/index.tsx +3 -3
  41. package/src/components/ConfigPanel/NavigationForm/Field/index.tsx +14 -3
  42. package/src/components/ElementsTooltip/index.tsx +10 -9
  43. package/src/components/EmptyState/index.tsx +2 -2
  44. package/src/components/Fields/ArrayFieldGroup/index.tsx +1 -1
  45. package/src/components/Fields/AsyncCheckGroup/index.tsx +1 -1
  46. package/src/components/Fields/AsyncSelect/index.tsx +1 -1
  47. package/src/components/Fields/ComponentContainer/index.tsx +7 -6
  48. package/src/components/Fields/ComponentContainer/style.tsx +2 -2
  49. package/src/components/Fields/HiddenField/index.tsx +1 -1
  50. package/src/components/Fields/ImageField/index.tsx +10 -5
  51. package/src/components/Fields/MultiCheckSelect/index.tsx +3 -3
  52. package/src/components/Fields/NumberField/index.tsx +2 -1
  53. package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +5 -7
  54. package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +2 -2
  55. package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
  56. package/src/components/Fields/RichText/index.tsx +10 -6
  57. package/src/components/Fields/Select/index.tsx +1 -1
  58. package/src/components/Fields/SliderField/index.tsx +1 -1
  59. package/src/components/Fields/TimeField/HourInput/index.tsx +103 -0
  60. package/src/components/Fields/TimeField/HourInput/style.tsx +19 -0
  61. package/src/components/Fields/TimeField/HourInput/utils.tsx +35 -0
  62. package/src/components/Fields/TimeField/index.tsx +57 -0
  63. package/src/components/Fields/TimeField/style.tsx +37 -0
  64. package/src/components/Fields/index.tsx +2 -0
  65. package/src/components/FloatingMenu/index.tsx +1 -1
  66. package/src/components/Gallery/GalleryFilters/Type/index.tsx +50 -0
  67. package/src/components/Gallery/GalleryFilters/Type/style.tsx +39 -0
  68. package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +2 -1
  69. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +3 -3
  70. package/src/components/Gallery/hooks.tsx +10 -4
  71. package/src/components/Gallery/index.tsx +2 -0
  72. package/src/components/Icon/index.tsx +1 -1
  73. package/src/components/Loading/index.tsx +1 -1
  74. package/src/components/Pagination/index.tsx +1 -1
  75. package/src/components/SideModal/SideModalOption/index.tsx +4 -2
  76. package/src/components/SideModal/index.tsx +1 -1
  77. package/src/components/TableList/index.tsx +6 -6
  78. package/src/components/TableList/style.tsx +1 -1
  79. package/src/components/Tabs/index.tsx +19 -7
  80. package/src/components/Tag/index.tsx +6 -6
  81. package/src/components/Toast/index.tsx +4 -4
  82. package/src/components/Tooltip/index.tsx +5 -3
  83. package/src/components/index.tsx +2 -0
  84. package/src/containers/Navigation/Defaults/actions.tsx +10 -5
  85. package/src/containers/Navigation/Defaults/utils.tsx +13 -4
  86. package/src/containers/Sites/actions.tsx +7 -0
  87. package/src/containers/Sites/constants.tsx +1 -0
  88. package/src/containers/Sites/interfaces.tsx +6 -0
  89. package/src/containers/Sites/reducer.tsx +4 -0
  90. package/src/containers/StructuredData/actions.tsx +21 -8
  91. package/src/containers/StructuredData/constants.tsx +2 -0
  92. package/src/containers/StructuredData/interfaces.tsx +7 -1
  93. package/src/containers/StructuredData/reducer.tsx +5 -1
  94. package/src/helpers/fields.tsx +2 -2
  95. package/src/helpers/schemas.tsx +2 -2
  96. package/src/hooks/forms.tsx +2 -1
  97. package/src/modules/App/Routing/NavMenu/index.tsx +9 -1
  98. package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -1
  99. package/src/modules/Content/hooks.tsx +19 -12
  100. package/src/modules/Content/index.tsx +23 -14
  101. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -0
  102. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +3 -1
  103. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +16 -18
  104. package/src/modules/Navigation/Defaults/DefaultsEditor/utils.tsx +37 -0
  105. package/src/modules/StructuredData/Form/ConnectedField/index.tsx +3 -2
  106. package/src/modules/StructuredData/Form/index.tsx +22 -17
  107. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +30 -20
  108. package/src/modules/StructuredData/StructuredDataList/index.tsx +24 -14
  109. package/src/types/index.tsx +8 -7
@@ -10,6 +10,7 @@ export const SET_CURRENT_SITE_LANGUAGES: string | null = `${NAME}/SET_CURRENT_SI
10
10
  export const SET_INITIAL_VALUES = `${NAME}/SET_INITIAL_VALUES`;
11
11
  export const SET_SAVED_SITE_INFO = `${NAME}/SET_SAVED_SITE_INFO`;
12
12
  export const SET_CURRENT_SITE_ERROR_PAGES = `${NAME}/SET_CURRENT_SITE_ERROR_PAGES`;
13
+ export const SET_CONTENT_FILTERS = `${NAME}/SET_CONTENT_FILTERS`;
13
14
 
14
15
  export const ITEMS_PER_PAGE = 50;
15
16
 
@@ -9,6 +9,7 @@ import {
9
9
  SET_INITIAL_VALUES,
10
10
  SET_SAVED_SITE_INFO,
11
11
  SET_CURRENT_SITE_ERROR_PAGES,
12
+ SET_CONTENT_FILTERS,
12
13
  } from "./constants";
13
14
  import { ISite } from "@ax/types";
14
15
 
@@ -62,4 +63,9 @@ export interface ISetCurrentSiteErrorPages {
62
63
  payload: { currentSiteErrorPages: number[] };
63
64
  }
64
65
 
66
+ export interface ISetContentFilters {
67
+ type: typeof SET_CONTENT_FILTERS;
68
+ payload: { contentFilters: Record<string,string> | null };
69
+ }
70
+
65
71
  export type SitesActionsCreators = ISetSitesAction & ISetCurrentSiteInfoAction;
@@ -9,6 +9,7 @@ import {
9
9
  SET_INITIAL_VALUES,
10
10
  SET_SAVED_SITE_INFO,
11
11
  SET_CURRENT_SITE_ERROR_PAGES,
12
+ SET_CONTENT_FILTERS,
12
13
  } from "./constants";
13
14
 
14
15
  import { ISite, IPage, ILanguage } from "@ax/types";
@@ -26,6 +27,7 @@ export interface ISitesState {
26
27
  currentSiteLanguages: ILanguage[];
27
28
  savedSiteInfo: any;
28
29
  currentSiteErrorPages: number[];
30
+ contentFilters: Record<string, string> | null;
29
31
  }
30
32
 
31
33
  export const initialState = {
@@ -39,6 +41,7 @@ export const initialState = {
39
41
  currentSiteLanguages: [],
40
42
  savedSiteInfo: null,
41
43
  currentSiteErrorPages: [],
44
+ contentFilters: null,
42
45
  };
43
46
 
44
47
  export function reducer(state = initialState, action: SitesActionsCreators): ISitesState {
@@ -53,6 +56,7 @@ export function reducer(state = initialState, action: SitesActionsCreators): ISi
53
56
  case SET_INITIAL_VALUES:
54
57
  case SET_SAVED_SITE_INFO:
55
58
  case SET_CURRENT_SITE_ERROR_PAGES:
59
+ case SET_CONTENT_FILTERS:
56
60
  return { ...state, ...action.payload };
57
61
  default:
58
62
  return state;
@@ -16,6 +16,7 @@ import {
16
16
  SET_SCHEMA_VERSION,
17
17
  SET_ERRORS,
18
18
  SET_VALIDATED,
19
+ SET_CONTENT_FILTERS,
19
20
  } from "./constants";
20
21
 
21
22
  import {
@@ -30,9 +31,17 @@ import {
30
31
  ISetSchemaVersion,
31
32
  ISetErrors,
32
33
  ISetValidated,
34
+ ISetContentFilters,
33
35
  } from "./interfaces";
34
36
  import { prepareStructuredDataContent, getTaxonomies, filterStructuredDataByID, getTypes } from "./utils";
35
- import { IStructuredData, IStructuredDataContent, ICategory, IGetStructuredDataParams, IErrorItem } from "@ax/types";
37
+ import {
38
+ IStructuredData,
39
+ IStructuredDataContent,
40
+ ICategory,
41
+ IGetStructuredDataParams,
42
+ IErrorItem,
43
+ IStructuredDataQueryValues,
44
+ } from "@ax/types";
36
45
  import { structuredData } from "@ax/api";
37
46
  import { setTotalItems } from "@ax/containers/Sites/actions";
38
47
  import { appActions } from "@ax/containers/App";
@@ -102,30 +111,33 @@ function setValidated(validated: boolean): ISetValidated {
102
111
  return { type: SET_VALIDATED, payload: { validated } };
103
112
  }
104
113
 
114
+ function setContentFilters(contentFilters: Record<string, IStructuredDataQueryValues> | null): ISetContentFilters {
115
+ return { type: SET_CONTENT_FILTERS, payload: { contentFilters } };
116
+ }
117
+
105
118
  function updateFormValue(valueObj: any): (dispatch: Dispatch, getState: any) => void {
106
119
  return (dispatch, getState) => {
107
120
  const {
108
121
  structuredData: { form },
109
122
  } = getState();
110
- const updatedForm = { ...form, content: { ...form.content, ...valueObj } };
123
+ const updatedForm = { ...form, content: { ...form?.content, ...valueObj } };
111
124
  dispatch(updateForm(updatedForm));
112
125
  };
113
126
  }
114
127
 
115
- function resetForm(): (dispatch: Dispatch, getState: any) => void {
128
+ function resetForm(setDefault?: boolean): (dispatch: Dispatch, getState: any) => void {
116
129
  return (dispatch, getState) => {
117
130
  const {
118
- structuredData: {
119
- currentStructuredData: { defaultValues },
120
- },
131
+ structuredData: { currentStructuredData },
121
132
  } = getState();
122
133
 
123
- const updatedForm = { content: defaultValues };
134
+ const formContent = setDefault && currentStructuredData ? { content: currentStructuredData.defaultValues } : null;
124
135
 
125
136
  dispatch(setEntity(null));
126
- dispatch(updateForm(updatedForm));
137
+ dispatch(updateForm(formContent));
127
138
  dispatch(setErrors([]));
128
139
  dispatch(setValidated(false));
140
+ dispatch(setCurrentDataID(null));
129
141
  };
130
142
  }
131
143
 
@@ -559,4 +571,5 @@ export {
559
571
  setFilter,
560
572
  validateForm,
561
573
  deleteError,
574
+ setContentFilters,
562
575
  };
@@ -15,6 +15,7 @@ const SET_FILTER: string | null = `${NAME}/SET_FILTER`;
15
15
  const SET_SCHEMA_VERSION: string | null = `${NAME}/SET_SCHEMA_VERSION`;
16
16
  const SET_ERRORS = `${NAME}/SET_ERRORS`;
17
17
  const SET_VALIDATED = `${NAME}/SET_VALIDATED`;
18
+ const SET_CONTENT_FILTERS = `${NAME}/SET_CONTENT_FILTERS`;
18
19
 
19
20
  const ITEMS_PER_PAGE = 50;
20
21
 
@@ -45,4 +46,5 @@ export {
45
46
  SET_SCHEMA_VERSION,
46
47
  SET_ERRORS,
47
48
  SET_VALIDATED,
49
+ SET_CONTENT_FILTERS,
48
50
  };
@@ -12,9 +12,10 @@ import {
12
12
  SET_SCHEMA_VERSION,
13
13
  SET_ERRORS,
14
14
  SET_VALIDATED,
15
+ SET_CONTENT_FILTERS,
15
16
  } from "./constants";
16
17
 
17
- import { IStructuredData, IStructuredDataContent, ICategory, IErrorItem } from "@ax/types";
18
+ import { IStructuredData, IStructuredDataContent, ICategory, IErrorItem, IStructuredDataQueryValues } from "@ax/types";
18
19
 
19
20
  export interface ISetCategories {
20
21
  type: typeof SET_CATEGORIES;
@@ -80,6 +81,11 @@ export interface ISetValidated {
80
81
  payload: { validated: boolean };
81
82
  }
82
83
 
84
+ export interface ISetContentFilters {
85
+ type: typeof SET_CONTENT_FILTERS;
86
+ payload: { contentFilters: Record<string, IStructuredDataQueryValues> | null };
87
+ }
88
+
83
89
  export type CategoryActionsCreators = ISetCategories & ISetCurrentData;
84
90
 
85
91
  export type StructuredDataActionsCreators = CategoryActionsCreators &
@@ -1,4 +1,4 @@
1
- import { IStructuredData, IStructuredDataContent, ICategory, IErrorItem } from "@ax/types";
1
+ import { IStructuredData, IStructuredDataContent, ICategory, IErrorItem, IStructuredDataQueryValues } from "@ax/types";
2
2
  import {
3
3
  SET_CATEGORIES,
4
4
  SET_STRUCTURED_DATA,
@@ -15,6 +15,7 @@ import {
15
15
  SET_SCHEMA_VERSION,
16
16
  SET_ERRORS,
17
17
  SET_VALIDATED,
18
+ SET_CONTENT_FILTERS,
18
19
  } from "./constants";
19
20
 
20
21
  import { StructuredDataActionsCreators } from "./interfaces";
@@ -34,6 +35,7 @@ export interface IStructuredDataState {
34
35
  schemaVersion: string;
35
36
  errors: IErrorItem[];
36
37
  validated: boolean;
38
+ contentFilters: Record<string, IStructuredDataQueryValues> | null;
37
39
  }
38
40
 
39
41
  export const initialState = {
@@ -51,6 +53,7 @@ export const initialState = {
51
53
  schemaVersion: "",
52
54
  errors: [],
53
55
  validated: false,
56
+ contentFilters: null,
54
57
  };
55
58
 
56
59
  export function reducer(state = initialState, action: StructuredDataActionsCreators): IStructuredDataState {
@@ -70,6 +73,7 @@ export function reducer(state = initialState, action: StructuredDataActionsCreat
70
73
  case SET_SCHEMA_VERSION:
71
74
  case SET_ERRORS:
72
75
  case SET_VALIDATED:
76
+ case SET_CONTENT_FILTERS:
73
77
  return { ...state, ...action.payload };
74
78
  default:
75
79
  return state;
@@ -1,5 +1,5 @@
1
- const fields = require.context("./../components/Fields", true);
1
+ import * as components from "@ax/components/Fields";
2
2
 
3
- const getFieldByPath = (name: string) => fields(`./${name}/index.tsx`).default;
3
+ const getFieldByPath = (name: string): (() => JSX.Element) => (components as Record<string, any>)[name];
4
4
 
5
5
  export { getFieldByPath };
@@ -6,10 +6,10 @@ import { pageSchemas } from "@ax/schemas";
6
6
  const allSchemas = { ...schemas.all, ...pageSchemas };
7
7
 
8
8
  const getSchema = (name: string) => allSchemas[name];
9
- const getDefaultSchema = (name: string) => allSchemas[name].default;
9
+ const getDefaultSchema = (name: string) => (allSchemas[name] ? allSchemas[name].default : {});
10
10
 
11
11
  const getSchemaThumbnails = (name: string, theme?: string) => {
12
- if (!allSchemas[name].thumbnails) return null;
12
+ if (!allSchemas[name]?.thumbnails) return null;
13
13
 
14
14
  return theme && allSchemas[name].thumbnails[theme] ? allSchemas[name].thumbnails[theme] : allSchemas[name].thumbnails;
15
15
  };
@@ -63,7 +63,7 @@ const useIsDirty = (
63
63
 
64
64
  const prevContent = usePrevious(updatedValues, isSaved);
65
65
 
66
- const hasChanged = () => {
66
+ const hasChanged = (): boolean => {
67
67
  if (prevContent && updatedValues) {
68
68
  const updatedValuesCloned = updatedValues && deepClone(updatedValues);
69
69
  const originalValuesCloned = prevContent && deepClone(prevContent);
@@ -74,6 +74,7 @@ const useIsDirty = (
74
74
 
75
75
  return hasChanged;
76
76
  }
77
+ return false;
77
78
  };
78
79
 
79
80
  const resetDirty = () => {
@@ -15,7 +15,7 @@ import { NavProvider } from "./context";
15
15
  import * as S from "./style";
16
16
 
17
17
  const NavMenu = (props: IProps) => {
18
- const { location, setHistoryPush, logout, currentSiteInfo, siteLanguages, lang } = props;
18
+ const { location, setHistoryPush, logout, currentSiteInfo, siteLanguages, lang, categories } = props;
19
19
 
20
20
  const [isOpened, setIsOpened] = useState(false);
21
21
 
@@ -116,6 +116,12 @@ const NavMenu = (props: IProps) => {
116
116
 
117
117
  const isSitePublished = isSite && currentSiteInfo && currentSiteInfo.isPublished;
118
118
 
119
+ if (isSite) {
120
+ const isSiteCategoriesAvailable = categories.site.length;
121
+ const siteCategoriesRouteIdx = config.routes.findIndex((route: IRouter) => route.path === "/sites/categories");
122
+ config.routes[siteCategoriesRouteIdx].showInNav = isSiteCategoriesAvailable;
123
+ }
124
+
119
125
  return (
120
126
  <NavProvider value={{ state, toggleSubmenu }}>
121
127
  <S.NavWrapper type={config.type} isOpened={isOpened}>
@@ -182,12 +188,14 @@ interface IConfig {
182
188
  }
183
189
 
184
190
  interface INavMenuProps {
191
+ categories: any;
185
192
  currentSiteInfo: any;
186
193
  siteLanguages: any[];
187
194
  lang: any;
188
195
  }
189
196
 
190
197
  const mapStateToProps = (state: IRootState) => ({
198
+ categories: state.structuredData.categories,
191
199
  currentSiteInfo: state.sites.currentSiteInfo,
192
200
  siteLanguages: state.sites.currentSiteLanguages,
193
201
  lang: state.app.lang,
@@ -94,7 +94,7 @@ const TableHeader = (props: IProps): JSX.Element => {
94
94
  {CategoryColumns}
95
95
  {activeColumns.includes("type") && (
96
96
  <S.HeaderWrapper>
97
- <TypeFilter filterItems={filterItems} filters={typeFilters} value={filterValues.types} pointer="type" />
97
+ <TypeFilter filterItems={filterItems} filters={typeFilters} value={filterValues.type} pointer="type" />
98
98
  </S.HeaderWrapper>
99
99
  )}
100
100
  {activeColumns.includes("live") && (
@@ -1,4 +1,4 @@
1
- import { useState } from "react";
1
+ import { useEffect, useState } from "react";
2
2
 
3
3
  const useSortedListStatus = () => {
4
4
  const sortedInitialState: {
@@ -21,7 +21,7 @@ const useSortedListStatus = () => {
21
21
  };
22
22
  };
23
23
 
24
- const useFilterQuery = () => {
24
+ const useFilterQuery = (values?: Record<string, string> | null) => {
25
25
  const initialQueryValues = {
26
26
  type: "all",
27
27
  translated: "all",
@@ -30,9 +30,7 @@ const useFilterQuery = () => {
30
30
  categories: "all",
31
31
  };
32
32
 
33
- const [query, setQuery] = useState(initialQueryValues);
34
-
35
- const setFilterQuery = (filterValues: any) => {
33
+ const getFilterQuery = (filterValues: any) => {
36
34
  const { type, translated, liveStatus, order, categories } = filterValues;
37
35
  let filterQuery = "";
38
36
 
@@ -63,8 +61,14 @@ const useFilterQuery = () => {
63
61
  return filterQuery;
64
62
  };
65
63
 
64
+ const initState = values ? values : initialQueryValues;
65
+ const [state, setState] = useState(initState);
66
+
67
+ const initQuery = values ? getFilterQuery(values) : "";
68
+ const [query, setQuery] = useState(initQuery);
69
+
66
70
  const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
67
- const { type, translated, liveStatus, order, categories } = query;
71
+ const { type, translated, liveStatus, order, categories } = state;
68
72
  const orderMethod = isAscendent ? "asc" : "desc";
69
73
  const filterValues = {
70
74
  type: pointer === "type" ? filter : type,
@@ -74,18 +78,21 @@ const useFilterQuery = () => {
74
78
  categories: pointer === "categories" ? filter : categories,
75
79
  };
76
80
 
77
- setQuery(filterValues);
78
-
79
- return filterValues;
81
+ setState(filterValues);
82
+ const filterQuery = getFilterQuery(filterValues);
83
+ setQuery(filterQuery);
80
84
  };
81
85
 
82
- const resetFilterQuery = () => setQuery(initialQueryValues);
86
+ const resetFilterQuery = () => {
87
+ setState(initialQueryValues);
88
+ setQuery("");
89
+ };
83
90
 
84
91
  return {
85
92
  setFiltersSelection,
86
- setFilterQuery,
87
93
  resetFilterQuery,
88
- filterValues: query,
94
+ filterValues: state,
95
+ query,
89
96
  };
90
97
  };
91
98
 
@@ -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 };