@griddo/ax 1.69.9 → 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.
- package/config/jest/componentsMock.js +0 -26
- package/package.json +4 -3
- package/src/__tests__/components/ElementsTooltip/ElementsTooltip.test.tsx +97 -0
- package/src/__tests__/components/EmptyState/EmptyState.test.tsx +78 -0
- package/src/__tests__/components/Fields/AnalyticsField/PageAnalytics/PageAnalytics.test.tsx +0 -14
- package/src/__tests__/components/Fields/AnalyticsField/StructuredDataAnalytics/StructuredDataAnalytics.test.tsx +0 -15
- package/src/__tests__/components/Fields/ArrayFieldGroup/ArrayFieldGroup.test.tsx +6 -15
- package/src/__tests__/components/Fields/AsyncCheckGroup/AsyncCheckGroup.test.tsx +1 -13
- package/src/__tests__/components/Fields/AsyncSelect/AsyncSelect.test.tsx +1 -19
- package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +1 -10
- package/src/__tests__/components/Fields/ComponentArray/ComponentArray.test.tsx +1 -22
- package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +4 -24
- package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +6 -12
- package/src/__tests__/components/Fields/ComponentArray/SameComponentArray/SameComponentArray.test.tsx +1 -20
- package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +559 -0
- package/src/__tests__/components/Fields/HiddenField/HiddenField.test.tsx +1 -7
- package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +471 -0
- package/src/__tests__/components/Fields/MultiCheckSelect/MultiCheckSelect.test.tsx +1 -15
- package/src/__tests__/components/Fields/NoteField/NoteField.test.tsx +1 -6
- package/src/__tests__/components/Fields/NumberField/NumberField.test.tsx +1 -14
- package/src/__tests__/components/Fields/RadioField/RadioField.test.tsx +1 -11
- package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +77 -13
- package/src/__tests__/components/Fields/RichText/RichText.test.tsx +1 -12
- package/src/__tests__/components/Fields/Select/Select.test.tsx +1 -21
- package/src/__tests__/components/Fields/SliderField/SliderField.test.tsx +1 -14
- package/src/__tests__/components/Fields/TagField/TagField.test.tsx +3 -3
- package/src/__tests__/components/Fields/TimeField/HourInput/HourInput.test.tsx +142 -0
- package/src/__tests__/components/Fields/TimeField/TimeField.test.tsx +100 -0
- package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +1 -9
- package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +151 -0
- package/src/__tests__/components/Fields/VisualUniqueSelection/ImageSelection/ImageSelection.test.tsx +1 -13
- package/src/__tests__/components/Fields/VisualUniqueSelection/ScrollableSelection/ScrollableSelection.test.tsx +3 -17
- package/src/__tests__/components/Fields/VisualUniqueSelection/VisualUniqueSelection.test.tsx +2 -28
- package/src/__tests__/components/TableList/TableList.test.tsx +119 -0
- package/src/__tests__/components/Tabs/Tabs.test.tsx +202 -0
- package/src/__tests__/components/Tag/Tag.test.tsx +138 -0
- package/src/__tests__/components/Toast/Toast.test.tsx +100 -0
- package/src/api/navigation.tsx +1 -1
- package/src/components/Browser/index.tsx +1 -1
- package/src/components/Button/index.tsx +3 -3
- package/src/components/ConfigPanel/NavigationForm/Field/index.tsx +14 -3
- package/src/components/ElementsTooltip/index.tsx +10 -9
- package/src/components/EmptyState/index.tsx +2 -2
- package/src/components/Fields/ArrayFieldGroup/index.tsx +1 -1
- package/src/components/Fields/AsyncCheckGroup/index.tsx +1 -1
- package/src/components/Fields/AsyncSelect/index.tsx +1 -1
- package/src/components/Fields/ComponentContainer/index.tsx +7 -6
- package/src/components/Fields/ComponentContainer/style.tsx +2 -2
- package/src/components/Fields/HiddenField/index.tsx +1 -1
- package/src/components/Fields/ImageField/index.tsx +10 -5
- package/src/components/Fields/MultiCheckSelect/index.tsx +3 -3
- package/src/components/Fields/NumberField/index.tsx +2 -1
- package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +5 -7
- package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +2 -2
- package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
- package/src/components/Fields/RichText/index.tsx +10 -6
- package/src/components/Fields/Select/index.tsx +1 -1
- package/src/components/Fields/SliderField/index.tsx +1 -1
- package/src/components/Fields/TimeField/HourInput/index.tsx +103 -0
- package/src/components/Fields/TimeField/HourInput/style.tsx +19 -0
- package/src/components/Fields/TimeField/HourInput/utils.tsx +35 -0
- package/src/components/Fields/TimeField/index.tsx +57 -0
- package/src/components/Fields/TimeField/style.tsx +37 -0
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FloatingMenu/index.tsx +1 -1
- package/src/components/Gallery/GalleryFilters/Type/index.tsx +50 -0
- package/src/components/Gallery/GalleryFilters/Type/style.tsx +39 -0
- package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +2 -1
- package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +3 -3
- package/src/components/Gallery/hooks.tsx +10 -4
- package/src/components/Gallery/index.tsx +2 -0
- package/src/components/Icon/index.tsx +1 -1
- package/src/components/Loading/index.tsx +1 -1
- package/src/components/Pagination/index.tsx +1 -1
- package/src/components/SideModal/SideModalOption/index.tsx +4 -2
- package/src/components/SideModal/index.tsx +1 -1
- package/src/components/TableList/index.tsx +6 -6
- package/src/components/TableList/style.tsx +1 -1
- package/src/components/Tabs/index.tsx +19 -7
- package/src/components/Tag/index.tsx +6 -6
- package/src/components/Toast/index.tsx +4 -4
- package/src/components/Tooltip/index.tsx +5 -3
- package/src/components/index.tsx +2 -0
- package/src/containers/Navigation/Defaults/actions.tsx +10 -5
- package/src/containers/Navigation/Defaults/utils.tsx +13 -4
- package/src/containers/Sites/actions.tsx +7 -0
- package/src/containers/Sites/constants.tsx +1 -0
- package/src/containers/Sites/interfaces.tsx +6 -0
- package/src/containers/Sites/reducer.tsx +4 -0
- package/src/containers/StructuredData/actions.tsx +21 -8
- package/src/containers/StructuredData/constants.tsx +2 -0
- package/src/containers/StructuredData/interfaces.tsx +7 -1
- package/src/containers/StructuredData/reducer.tsx +5 -1
- package/src/helpers/fields.tsx +2 -2
- package/src/helpers/schemas.tsx +2 -2
- package/src/hooks/forms.tsx +2 -1
- package/src/modules/App/Routing/NavMenu/index.tsx +9 -1
- package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/modules/Content/hooks.tsx +19 -12
- package/src/modules/Content/index.tsx +23 -14
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -0
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +3 -1
- package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +16 -18
- package/src/modules/Navigation/Defaults/DefaultsEditor/utils.tsx +37 -0
- package/src/modules/StructuredData/Form/ConnectedField/index.tsx +3 -2
- package/src/modules/StructuredData/Form/index.tsx +22 -17
- package/src/modules/StructuredData/StructuredDataList/hooks.tsx +30 -20
- package/src/modules/StructuredData/StructuredDataList/index.tsx +24 -14
- 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 {
|
|
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
|
|
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
|
|
134
|
+
const formContent = setDefault && currentStructuredData ? { content: currentStructuredData.defaultValues } : null;
|
|
124
135
|
|
|
125
136
|
dispatch(setEntity(null));
|
|
126
|
-
dispatch(updateForm(
|
|
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;
|
package/src/helpers/fields.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import * as components from "@ax/components/Fields";
|
|
2
2
|
|
|
3
|
-
const getFieldByPath = (name: string) =>
|
|
3
|
+
const getFieldByPath = (name: string): (() => JSX.Element) => (components as Record<string, any>)[name];
|
|
4
4
|
|
|
5
5
|
export { getFieldByPath };
|
package/src/helpers/schemas.tsx
CHANGED
|
@@ -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]
|
|
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
|
};
|
package/src/hooks/forms.tsx
CHANGED
|
@@ -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.
|
|
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
|
|
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 } =
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
setState(filterValues);
|
|
82
|
+
const filterQuery = getFilterQuery(filterValues);
|
|
83
|
+
setQuery(filterQuery);
|
|
80
84
|
};
|
|
81
85
|
|
|
82
|
-
const resetFilterQuery = () =>
|
|
86
|
+
const resetFilterQuery = () => {
|
|
87
|
+
setState(initialQueryValues);
|
|
88
|
+
setQuery("");
|
|
89
|
+
};
|
|
83
90
|
|
|
84
91
|
return {
|
|
85
92
|
setFiltersSelection,
|
|
86
|
-
setFilterQuery,
|
|
87
93
|
resetFilterQuery,
|
|
88
|
-
filterValues:
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
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={
|
|
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 };
|