@griddo/ax 10.3.18 → 10.3.19
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/package.json +2 -2
- package/scripts/griddo-sync-schemas.js +21 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx +51 -37
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +3 -4
- package/src/components/Fields/TextArea/index.tsx +2 -2
- package/src/components/TableFilters/TypeFilter/index.tsx +9 -6
- package/src/containers/PageEditor/actions.tsx +22 -5
- package/src/containers/PageEditor/constants.tsx +1 -0
- package/src/containers/PageEditor/interfaces.tsx +6 -0
- package/src/containers/PageEditor/reducer.tsx +5 -1
- package/src/containers/StructuredData/actions.tsx +21 -6
- package/src/containers/StructuredData/constants.tsx +1 -1
- package/src/containers/StructuredData/reducer.tsx +1 -1
- package/src/containers/StructuredData/utils.tsx +14 -1
- package/src/forms/editor.tsx +14 -1
- package/src/forms/index.tsx +2 -0
- package/src/modules/FileDrive/FileFilters/Type/index.tsx +3 -3
- package/src/modules/FileDrive/index.tsx +17 -21
- package/src/modules/StructuredData/Form/ConnectedField/index.tsx +12 -5
- package/src/modules/StructuredData/Form/index.tsx +21 -19
- package/src/types/index.tsx +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.3.
|
|
4
|
+
"version": "10.3.19",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -230,5 +230,5 @@
|
|
|
230
230
|
"publishConfig": {
|
|
231
231
|
"access": "public"
|
|
232
232
|
},
|
|
233
|
-
"gitHead": "
|
|
233
|
+
"gitHead": "7528f70fec302460e645be69d6b7765ac7e45c10"
|
|
234
234
|
}
|
|
@@ -50,6 +50,10 @@ async function main() {
|
|
|
50
50
|
|
|
51
51
|
const _griddoConfig = require(path.resolve(__dirname, `./${tempFile}`));
|
|
52
52
|
const griddoConfig = _griddoConfig.default || _griddoConfig;
|
|
53
|
+
|
|
54
|
+
// La propiedad computed en los schemas de datos estructurados se perderá si no la stringificamos primero
|
|
55
|
+
checkComputedSchemas(griddoConfig.schemas)
|
|
56
|
+
|
|
53
57
|
const { version } = require(resolveComponentsPath("package.json"));
|
|
54
58
|
|
|
55
59
|
const emptySchemas = {
|
|
@@ -77,4 +81,21 @@ async function main() {
|
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
const checkComputedSchemas = schemas => {
|
|
85
|
+
const structuredDataSchemas = schemas.structuredData;
|
|
86
|
+
|
|
87
|
+
for (const structuredData in structuredDataSchemas) {
|
|
88
|
+
const value = structuredDataSchemas[structuredData];
|
|
89
|
+
const fields = value.schema?.fields;
|
|
90
|
+
|
|
91
|
+
if (!fields) continue;
|
|
92
|
+
|
|
93
|
+
for (const field of fields) {
|
|
94
|
+
const { computed = null } = field;
|
|
95
|
+
|
|
96
|
+
if (computed) field.computed = computed.toString();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
80
101
|
main();
|
package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
|
-
import { IDataPack, IErrorItem, IRootState, ISite } from "@ax/types";
|
|
4
|
+
import { IDataPack, IErrorItem, IRootState, ISchemaField, ISite } from "@ax/types";
|
|
5
5
|
import { getModuleCategories } from "@ax/helpers";
|
|
6
6
|
import Field from "../Field";
|
|
7
7
|
|
|
@@ -36,7 +36,7 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
36
36
|
const templateContent = selectedContent.template;
|
|
37
37
|
const modulesDataPacks = activatedPacks.map((pack: IDataPack) => pack.modules).flat();
|
|
38
38
|
|
|
39
|
-
const getFieldProps = (field:
|
|
39
|
+
const getFieldProps = (field: ISchemaField) => {
|
|
40
40
|
const { key, type, whiteList = [], slugTo, readonly } = field;
|
|
41
41
|
const isArr = type === "ComponentArray";
|
|
42
42
|
const currentContent = isArr ? templateContent[key] : templateContent;
|
|
@@ -45,8 +45,9 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
45
45
|
const handleUpdate = (fieldKey: string, value: any) =>
|
|
46
46
|
updateValue(fieldKey, value, templateContent.editorID, slugTo);
|
|
47
47
|
const error = errors.find((err: any) => err.editorID === templateContent.editorID && err.key === key);
|
|
48
|
+
const isComputedField = Object.prototype.hasOwnProperty.call(field, "computed");
|
|
48
49
|
|
|
49
|
-
const addedModules = modulesDataPacks.reduce((acc: string[], current: any) => {
|
|
50
|
+
const addedModules: string[] = modulesDataPacks.reduce((acc: string[], current: any) => {
|
|
50
51
|
if (
|
|
51
52
|
current.sectionList &&
|
|
52
53
|
current.sectionList[template.component] &&
|
|
@@ -58,7 +59,7 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
58
59
|
return acc;
|
|
59
60
|
}, []);
|
|
60
61
|
|
|
61
|
-
const mappedWhiteList = whiteList ? [...whiteList, ...addedModules].sort() : [...addedModules.sort()];
|
|
62
|
+
const mappedWhiteList: string[] = whiteList ? [...whiteList, ...addedModules].sort() : [...addedModules.sort()];
|
|
62
63
|
const categories = getModuleCategories(mappedWhiteList);
|
|
63
64
|
|
|
64
65
|
return {
|
|
@@ -70,7 +71,8 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
70
71
|
currentContent,
|
|
71
72
|
handleUpdate,
|
|
72
73
|
error,
|
|
73
|
-
readonly
|
|
74
|
+
readonly,
|
|
75
|
+
disabledField: isComputedField,
|
|
74
76
|
};
|
|
75
77
|
};
|
|
76
78
|
|
|
@@ -78,39 +80,51 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
78
80
|
<>
|
|
79
81
|
{isConfig && templateFields && <S.Title>Template Options</S.Title>}
|
|
80
82
|
{templateFields &&
|
|
81
|
-
templateFields
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
templateFields
|
|
84
|
+
.filter((templateField: ISchemaField) => !templateField.hidden)
|
|
85
|
+
.map((templateField: ISchemaField, index: number) => {
|
|
86
|
+
const {
|
|
87
|
+
whiteList,
|
|
88
|
+
categories,
|
|
89
|
+
key,
|
|
90
|
+
fieldObjKey,
|
|
91
|
+
mappedField,
|
|
92
|
+
currentContent,
|
|
93
|
+
handleUpdate,
|
|
94
|
+
error,
|
|
95
|
+
readonly,
|
|
96
|
+
disabledField
|
|
97
|
+
} = getFieldProps(templateField);
|
|
84
98
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
99
|
+
return (
|
|
100
|
+
<Field
|
|
101
|
+
whiteList={whiteList}
|
|
102
|
+
key={`${objKey}.${key}${index}`}
|
|
103
|
+
objKey={fieldObjKey}
|
|
104
|
+
field={mappedField}
|
|
105
|
+
selectedContent={currentContent}
|
|
106
|
+
goTo={goTo}
|
|
107
|
+
updateValue={handleUpdate}
|
|
108
|
+
pages={pages}
|
|
109
|
+
actions={actions}
|
|
110
|
+
site={site}
|
|
111
|
+
disabled={disabled || disabledField}
|
|
112
|
+
activatedModules={activatedModules}
|
|
113
|
+
isTemplateActivated={isTemplateActivated}
|
|
114
|
+
categories={categories}
|
|
115
|
+
error={error}
|
|
116
|
+
deleteError={deleteError}
|
|
117
|
+
errors={errors}
|
|
118
|
+
theme={theme}
|
|
119
|
+
moduleCopy={moduleCopy}
|
|
120
|
+
availableDataPacks={availableDataPacks}
|
|
121
|
+
template={template}
|
|
122
|
+
setHistoryPush={setHistoryPush}
|
|
123
|
+
lang={lang}
|
|
124
|
+
readonly={readonly}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
})}
|
|
114
128
|
</>
|
|
115
129
|
);
|
|
116
130
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { memo, useEffect } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { getTemplate, isModuleDisabled, slugify, areEqual } from "@ax/helpers";
|
|
@@ -70,8 +70,7 @@ const PageConnectedField = (props: any) => {
|
|
|
70
70
|
|
|
71
71
|
const hasDefaultIndex = isTemplateActivated && templateConfig && templateConfig.indexDefault !== undefined;
|
|
72
72
|
|
|
73
|
-
const isFieldReadOnly =
|
|
74
|
-
(["parent", "slug"].includes(objKey) && isPageHome) || parentIsReadOnly || field.readonly;
|
|
73
|
+
const isFieldReadOnly = (["parent", "slug"].includes(objKey) && isPageHome) || parentIsReadOnly || field.readonly;
|
|
75
74
|
|
|
76
75
|
const isDisabled =
|
|
77
76
|
(!isGlobal &&
|
|
@@ -218,4 +217,4 @@ const mapDispatchToProps = {
|
|
|
218
217
|
deleteError: pageEditorActions.deleteError,
|
|
219
218
|
};
|
|
220
219
|
|
|
221
|
-
export default connect(mapStateToProps, mapDispatchToProps)(
|
|
220
|
+
export default connect(mapStateToProps, mapDispatchToProps)(memo(PageConnectedField, areEqual));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import React, { memo, useEffect, useRef } from "react";
|
|
1
|
+
import React, { memo, useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import * as S from "./style";
|
|
4
4
|
|
|
5
5
|
const TextArea = (props: ITextAreaProps): JSX.Element => {
|
|
6
6
|
const { value, placeholder, error, name, onChange, disabled, handleValidation, editorID, rows = 1 } = props;
|
|
7
7
|
|
|
8
|
-
const [state, setState] =
|
|
8
|
+
const [state, setState] = useState<string>(value);
|
|
9
9
|
const timeOutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
10
10
|
|
|
11
11
|
useEffect(() => {
|
|
@@ -9,10 +9,13 @@ const TypeFilter = (props: ITypeFilterProps): JSX.Element => {
|
|
|
9
9
|
|
|
10
10
|
const initialState = ["all"];
|
|
11
11
|
const selectAllOption = "all";
|
|
12
|
-
const
|
|
12
|
+
const arrayValues = value ? value.split(",") : initialState;
|
|
13
|
+
const [selectedValue, setSelectedValue] = useState(arrayValues);
|
|
13
14
|
|
|
14
15
|
useEffect(() => {
|
|
15
|
-
value
|
|
16
|
+
const arrayValues = value ? value.split(","): initialState;
|
|
17
|
+
setSelectedValue(arrayValues);
|
|
18
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
19
|
}, [value]);
|
|
17
20
|
|
|
18
21
|
const setFilterQuery = (selection: any) => {
|
|
@@ -20,7 +23,7 @@ const TypeFilter = (props: ITypeFilterProps): JSX.Element => {
|
|
|
20
23
|
selection = initialState;
|
|
21
24
|
}
|
|
22
25
|
setSelectedValue(selection);
|
|
23
|
-
const queryFilters = selection.join("
|
|
26
|
+
const queryFilters = selection.join(",");
|
|
24
27
|
filterItems(pointer, queryFilters);
|
|
25
28
|
};
|
|
26
29
|
|
|
@@ -36,7 +39,7 @@ const TypeFilter = (props: ITypeFilterProps): JSX.Element => {
|
|
|
36
39
|
);
|
|
37
40
|
|
|
38
41
|
return (
|
|
39
|
-
<FloatingMenu Button={Header} position="left" closeOnSelect={
|
|
42
|
+
<FloatingMenu Button={Header} position="left" closeOnSelect={false}>
|
|
40
43
|
<ListTitle data-testid="type-filter-title">Filter by type</ListTitle>
|
|
41
44
|
<S.ChecksWrapper>
|
|
42
45
|
<CheckGroup
|
|
@@ -44,7 +47,7 @@ const TypeFilter = (props: ITypeFilterProps): JSX.Element => {
|
|
|
44
47
|
value={selectedValue}
|
|
45
48
|
onChange={setFilterQuery}
|
|
46
49
|
selectAllOption={selectAllOption}
|
|
47
|
-
multipleSelection={
|
|
50
|
+
multipleSelection={true}
|
|
48
51
|
/>
|
|
49
52
|
</S.ChecksWrapper>
|
|
50
53
|
</FloatingMenu>
|
|
@@ -61,7 +64,7 @@ export interface ITypeFilterProps {
|
|
|
61
64
|
filterItems(pointer: string, filter: string): void;
|
|
62
65
|
filters: IFilter[];
|
|
63
66
|
pointer: string;
|
|
64
|
-
value
|
|
67
|
+
value?: string;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
export default TypeFilter;
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
parseValidationErrors,
|
|
31
31
|
findPackagesActivationErrors,
|
|
32
32
|
checkMaxModules,
|
|
33
|
+
evalueComputedFields,
|
|
33
34
|
} from "@ax/forms";
|
|
34
35
|
import { appActions } from "@ax/containers/App";
|
|
35
36
|
import { navigationActions } from "@ax/containers/Navigation";
|
|
@@ -66,6 +67,7 @@ import {
|
|
|
66
67
|
SET_LAST_ELEMENT_ADDED_ID,
|
|
67
68
|
SET_COPY_MODULE,
|
|
68
69
|
SET_IS_IA_TRANSLATED,
|
|
70
|
+
SET_LAST_TIMEOUT,
|
|
69
71
|
} from "./constants";
|
|
70
72
|
|
|
71
73
|
import {
|
|
@@ -103,6 +105,7 @@ import {
|
|
|
103
105
|
ISetLastElementAddedId,
|
|
104
106
|
ISetCopyModule,
|
|
105
107
|
ISetIsIATranslated,
|
|
108
|
+
ISetLastTimeout,
|
|
106
109
|
} from "./interfaces";
|
|
107
110
|
|
|
108
111
|
const { setIsLoading, setIsSaving, handleError } = appActions;
|
|
@@ -204,6 +207,10 @@ function setIsIATranslated(isIATranslated: boolean): ISetIsIATranslated {
|
|
|
204
207
|
return { type: SET_IS_IA_TRANSLATED, payload: { isIATranslated } };
|
|
205
208
|
}
|
|
206
209
|
|
|
210
|
+
function setLastTimeout(lastTimeout: NodeJS.Timeout | null): ISetLastTimeout {
|
|
211
|
+
return { type: SET_LAST_TIMEOUT, payload: { lastTimeout } };
|
|
212
|
+
}
|
|
213
|
+
|
|
207
214
|
function setTranslatedParent(): (dispatch: Dispatch, getState: any) => void {
|
|
208
215
|
return async (dispatch, getState) => {
|
|
209
216
|
try {
|
|
@@ -401,9 +408,8 @@ function savePage(
|
|
|
401
408
|
} = getState();
|
|
402
409
|
|
|
403
410
|
const rootEditorID = 0;
|
|
404
|
-
const page = getPageData(getState, false);
|
|
405
|
-
|
|
406
|
-
const { values, id } = parseData(page, false);
|
|
411
|
+
const { values: page, id } = getPageData(getState, false);
|
|
412
|
+
const values = evalueComputedFields(page);
|
|
407
413
|
|
|
408
414
|
const isNewPage = !id;
|
|
409
415
|
|
|
@@ -995,17 +1001,28 @@ function updateEditorContent(
|
|
|
995
1001
|
): (dispatch: Dispatch, getState: any) => void {
|
|
996
1002
|
return (dispatch, getState) => {
|
|
997
1003
|
const {
|
|
998
|
-
pageEditor: { editorContent, selectedContent },
|
|
1004
|
+
pageEditor: { editorContent, selectedContent, lastTimeout },
|
|
999
1005
|
} = getState();
|
|
1000
1006
|
|
|
1001
1007
|
const clonedContent = deepClone(editorContent);
|
|
1002
1008
|
|
|
1003
1009
|
const updatedSelectedContent = updateByEditorID(selectedContent, selectedEditorID, key, value);
|
|
1004
|
-
|
|
1010
|
+
let updatedEditorContent = updateByEditorID(clonedContent, selectedEditorID, key, value);
|
|
1005
1011
|
|
|
1006
1012
|
setSelectedContent(updatedSelectedContent);
|
|
1007
1013
|
dispatch(setEditorContent(updatedEditorContent));
|
|
1008
1014
|
|
|
1015
|
+
if(lastTimeout){
|
|
1016
|
+
clearTimeout(lastTimeout);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const timeoutId = setTimeout(() => {
|
|
1020
|
+
updatedEditorContent = evalueComputedFields(updatedEditorContent);
|
|
1021
|
+
generatePageContent(updatedEditorContent, dispatch, getState);
|
|
1022
|
+
}, 3000);
|
|
1023
|
+
|
|
1024
|
+
dispatch(setLastTimeout(timeoutId));
|
|
1025
|
+
|
|
1009
1026
|
const isNavigation = ["header", "footer"].includes(key);
|
|
1010
1027
|
if (isNavigation || (value && typeof value === "object")) {
|
|
1011
1028
|
generatePageContent(updatedEditorContent, dispatch, getState);
|
|
@@ -21,6 +21,7 @@ export const SET_USER_EDITING = `${NAME}/SET_USER_EDITING`;
|
|
|
21
21
|
export const SET_LAST_ELEMENT_ADDED_ID = `${NAME}/SET_LAST_ELEMENT_ADDED_ID`;
|
|
22
22
|
export const SET_COPY_MODULE = `${NAME}/SET_COPY_MODULE`;
|
|
23
23
|
export const SET_IS_IA_TRANSLATED = `${NAME}/SET_IS_IA_TRANSLATED`;
|
|
24
|
+
export const SET_LAST_TIMEOUT = `${NAME}/SET_LAST_TIMEOUT`;
|
|
24
25
|
|
|
25
26
|
export const INITIAL_TEMPLATE = "BasicTemplate";
|
|
26
27
|
export const MULTIMEDIA_COMPONENTS = ["LinkableImage", "Video"];
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
SET_LAST_ELEMENT_ADDED_ID,
|
|
21
21
|
SET_COPY_MODULE,
|
|
22
22
|
SET_IS_IA_TRANSLATED,
|
|
23
|
+
SET_LAST_TIMEOUT,
|
|
23
24
|
} from "./constants";
|
|
24
25
|
import { IBreadcrumbItem, ISchema, IPage, IErrorItem, IUserEditing } from "@ax/types";
|
|
25
26
|
|
|
@@ -128,6 +129,11 @@ export interface ISetIsIATranslated {
|
|
|
128
129
|
payload: { isIATranslated: boolean };
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
export interface ISetLastTimeout {
|
|
133
|
+
type: typeof SET_LAST_TIMEOUT;
|
|
134
|
+
payload: { lastTimeout: NodeJS.Timeout | null };
|
|
135
|
+
}
|
|
136
|
+
|
|
131
137
|
export interface IFieldProps {
|
|
132
138
|
id: number;
|
|
133
139
|
key: string;
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
SET_LAST_ELEMENT_ADDED_ID,
|
|
24
24
|
SET_COPY_MODULE,
|
|
25
25
|
SET_IS_IA_TRANSLATED,
|
|
26
|
+
SET_LAST_TIMEOUT,
|
|
26
27
|
} from "./constants";
|
|
27
28
|
|
|
28
29
|
import { PageEditorActionsCreators } from "./interfaces";
|
|
@@ -49,6 +50,7 @@ export interface IPageEditorState {
|
|
|
49
50
|
lastElementAddedId: null | number;
|
|
50
51
|
moduleCopy: { date: string; element: Record<string, unknown> } | null;
|
|
51
52
|
isIATranslated: boolean;
|
|
53
|
+
lastTimeout: NodeJS.Timeout | null;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
export const initialState = {
|
|
@@ -73,9 +75,10 @@ export const initialState = {
|
|
|
73
75
|
lastElementAddedId: null,
|
|
74
76
|
moduleCopy: null,
|
|
75
77
|
isIATranslated: false,
|
|
78
|
+
lastTimeout: null,
|
|
76
79
|
};
|
|
77
80
|
|
|
78
|
-
export function reducer(state = initialState, action:
|
|
81
|
+
export function reducer(state = initialState, action: any): IPageEditorState {
|
|
79
82
|
switch (action.type) {
|
|
80
83
|
case SET_EDITOR_CONTENT:
|
|
81
84
|
return { ...state, ...action.payload };
|
|
@@ -99,6 +102,7 @@ export function reducer(state = initialState, action: PageEditorActionsCreators)
|
|
|
99
102
|
case SET_LAST_ELEMENT_ADDED_ID:
|
|
100
103
|
case SET_COPY_MODULE:
|
|
101
104
|
case SET_IS_IA_TRANSLATED:
|
|
105
|
+
case SET_LAST_TIMEOUT:
|
|
102
106
|
return { ...state, ...action.payload };
|
|
103
107
|
default:
|
|
104
108
|
return state;
|
|
@@ -35,7 +35,13 @@ import {
|
|
|
35
35
|
ISetContentFilters,
|
|
36
36
|
ISetIsIATranslated,
|
|
37
37
|
} from "./interfaces";
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
prepareStructuredDataContent,
|
|
40
|
+
getTaxonomies,
|
|
41
|
+
filterStructuredDataByID,
|
|
42
|
+
getTypes,
|
|
43
|
+
evalueDataComputedFields,
|
|
44
|
+
} from "./utils";
|
|
39
45
|
import {
|
|
40
46
|
IStructuredData,
|
|
41
47
|
IStructuredDataContent,
|
|
@@ -126,7 +132,8 @@ function updateFormValue(valueObj: any): (dispatch: Dispatch, getState: any) =>
|
|
|
126
132
|
const {
|
|
127
133
|
structuredData: { form },
|
|
128
134
|
} = getState();
|
|
129
|
-
|
|
135
|
+
let updatedForm = { ...form, content: { ...form?.content, ...valueObj } };
|
|
136
|
+
|
|
130
137
|
dispatch(updateForm(updatedForm));
|
|
131
138
|
};
|
|
132
139
|
}
|
|
@@ -326,12 +333,15 @@ function createStructuredDataContent(
|
|
|
326
333
|
): (dispatch: Dispatch, getState: any) => Promise<boolean> {
|
|
327
334
|
return async (dispatch, getState) => {
|
|
328
335
|
try {
|
|
329
|
-
let dataContent = prepareStructuredDataContent(structuredDataContent);
|
|
330
336
|
const {
|
|
331
337
|
app: { lang },
|
|
332
338
|
sites: { currentSiteInfo },
|
|
339
|
+
structuredData: { schema },
|
|
333
340
|
} = getState();
|
|
334
341
|
|
|
342
|
+
let dataContent = prepareStructuredDataContent(structuredDataContent);
|
|
343
|
+
dataContent = evalueDataComputedFields(structuredDataContent, schema.fields);
|
|
344
|
+
|
|
335
345
|
dataContent = {
|
|
336
346
|
...dataContent,
|
|
337
347
|
language: langId ? langId : lang.id,
|
|
@@ -356,10 +366,15 @@ function createStructuredDataContent(
|
|
|
356
366
|
|
|
357
367
|
function updateStructuredDataContent(
|
|
358
368
|
structuredDataContent: IStructuredDataContent
|
|
359
|
-
): (dispatch: Dispatch) => Promise<boolean> {
|
|
360
|
-
return async (dispatch) => {
|
|
369
|
+
): (dispatch: Dispatch, getState: any) => Promise<boolean> {
|
|
370
|
+
return async (dispatch, getState) => {
|
|
361
371
|
try {
|
|
362
|
-
const
|
|
372
|
+
const {
|
|
373
|
+
structuredData: { schema },
|
|
374
|
+
} = getState();
|
|
375
|
+
|
|
376
|
+
let dataContent = prepareStructuredDataContent(structuredDataContent);
|
|
377
|
+
dataContent = evalueDataComputedFields(structuredDataContent, schema.fields);
|
|
363
378
|
|
|
364
379
|
const responseActions = {
|
|
365
380
|
handleSuccess: (response: any) => dispatch(setForm(response)),
|
|
@@ -59,7 +59,7 @@ export const initialState = {
|
|
|
59
59
|
isIATranslated: false,
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
export function reducer(state = initialState, action:
|
|
62
|
+
export function reducer(state = initialState, action: any): IStructuredDataState {
|
|
63
63
|
switch (action.type) {
|
|
64
64
|
case SET_CATEGORIES:
|
|
65
65
|
case SET_STRUCTURED_DATA:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deepClone } from "@ax/helpers";
|
|
2
|
+
import { IStructuredDataContent, IStructuredData, ISchemaField } from "@ax/types";
|
|
2
3
|
|
|
3
4
|
const prepareStructuredDataContent = (structuredDataContent: IStructuredDataContent) => {
|
|
4
5
|
return { ...structuredDataContent, content: structuredDataContent.content };
|
|
@@ -31,6 +32,17 @@ const getTaxonomies = (data: IStructuredData[]) => data.filter((item: IStructure
|
|
|
31
32
|
const getTypes = (data: IStructuredData[]) => data.filter((item: IStructuredData) => !item.taxonomy);
|
|
32
33
|
const filterStructuredDataByID = (data: any, id: string) => data.find((item: any) => item.id === id);
|
|
33
34
|
|
|
35
|
+
const evalueDataComputedFields = (structuredData: any, schema: any) => {
|
|
36
|
+
const updatedData = deepClone(structuredData);
|
|
37
|
+
schema.forEach((field: ISchemaField) => {
|
|
38
|
+
if (field.hasOwnProperty("computed")) {
|
|
39
|
+
const computedFunction = eval(`(${field.computed})`);
|
|
40
|
+
updatedData.content[field.key] = computedFunction(structuredData.content);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return updatedData;
|
|
44
|
+
};
|
|
45
|
+
|
|
34
46
|
export {
|
|
35
47
|
prepareStructuredDataContent,
|
|
36
48
|
updateCurrentDataContent,
|
|
@@ -38,4 +50,5 @@ export {
|
|
|
38
50
|
getTaxonomies,
|
|
39
51
|
getTypes,
|
|
40
52
|
filterStructuredDataByID,
|
|
53
|
+
evalueDataComputedFields,
|
|
41
54
|
};
|
package/src/forms/editor.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deepClone, getSchema, getDisplayName } from "@ax/helpers";
|
|
1
|
+
import { deepClone, getSchema, getDisplayName, getTemplate } from "@ax/helpers";
|
|
2
2
|
import { IPage, IBreadcrumbItem } from "@ax/types";
|
|
3
3
|
|
|
4
4
|
const configKeys = ["headerConfig", "footerConfig"];
|
|
@@ -199,6 +199,18 @@ const checkMaxModules = (content: any, type: string): { isMaxModules: boolean; e
|
|
|
199
199
|
};
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
const evalueComputedFields = (page: any) => {
|
|
203
|
+
const updatedPage = deepClone(page);
|
|
204
|
+
const pageSchemaContent = getTemplate(page.template.templateType).content;
|
|
205
|
+
pageSchemaContent.forEach((field: any) => {
|
|
206
|
+
if(field.hasOwnProperty("computed")){
|
|
207
|
+
updatedPage.template[field.key] = field.computed(page);
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
return updatedPage;
|
|
212
|
+
}
|
|
213
|
+
|
|
202
214
|
export {
|
|
203
215
|
parseData,
|
|
204
216
|
cleanContent,
|
|
@@ -213,4 +225,5 @@ export {
|
|
|
213
225
|
getLastComponentEditorID,
|
|
214
226
|
getParentKey,
|
|
215
227
|
checkMaxModules,
|
|
228
|
+
evalueComputedFields,
|
|
216
229
|
};
|
package/src/forms/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
getLastComponentEditorID,
|
|
12
12
|
getParentKey,
|
|
13
13
|
checkMaxModules,
|
|
14
|
+
evalueComputedFields,
|
|
14
15
|
} from "./editor";
|
|
15
16
|
import {
|
|
16
17
|
getUpdatedComponents,
|
|
@@ -65,4 +66,5 @@ export {
|
|
|
65
66
|
checkH1content,
|
|
66
67
|
parseValidationErrors,
|
|
67
68
|
checkMaxModules,
|
|
69
|
+
evalueComputedFields,
|
|
68
70
|
};
|
|
@@ -10,7 +10,7 @@ const Type = (props: ITypeProps): JSX.Element => {
|
|
|
10
10
|
const initialState = ["all"];
|
|
11
11
|
const selectAllOption = "all";
|
|
12
12
|
const pointer = "filterType";
|
|
13
|
-
const cleanValue = value.replace(/docx|xlsx|csv/gi, "");
|
|
13
|
+
const cleanValue = value ? value.replace(/docx|xlsx|csv/gi, "") : "all";
|
|
14
14
|
const arrayValues = cleanValue.split(",");
|
|
15
15
|
const [selectedValue, setSelectedValue] = useState(arrayValues);
|
|
16
16
|
|
|
@@ -54,7 +54,7 @@ const Type = (props: ITypeProps): JSX.Element => {
|
|
|
54
54
|
];
|
|
55
55
|
|
|
56
56
|
return (
|
|
57
|
-
<FloatingMenu Button={Header} position="center" closeOnSelect={
|
|
57
|
+
<FloatingMenu Button={Header} position="center" closeOnSelect={false}>
|
|
58
58
|
<ListTitle>Filter by type</ListTitle>
|
|
59
59
|
<S.ChecksWrapper>
|
|
60
60
|
<CheckGroup
|
|
@@ -71,7 +71,7 @@ const Type = (props: ITypeProps): JSX.Element => {
|
|
|
71
71
|
|
|
72
72
|
export interface ITypeProps {
|
|
73
73
|
filterItems(pointer: string, filter: string): void;
|
|
74
|
-
value
|
|
74
|
+
value?: string;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export default Type;
|
|
@@ -580,7 +580,7 @@ const FileDrive = (props: IProps) => {
|
|
|
580
580
|
<></>
|
|
581
581
|
);
|
|
582
582
|
|
|
583
|
-
const
|
|
583
|
+
const filters = (
|
|
584
584
|
<S.Filters>
|
|
585
585
|
<Type filterItems={filterItems} value={filterValues["filterType"]} />
|
|
586
586
|
<SortBy sortItems={sortItems} sortedState={sortedListStatus} />
|
|
@@ -603,30 +603,26 @@ const FileDrive = (props: IProps) => {
|
|
|
603
603
|
</S.FolderPanel>
|
|
604
604
|
<S.ContentWrapper>
|
|
605
605
|
<ErrorToast />
|
|
606
|
+
<S.FiltersBar isSite={isSiteView && allowedToAccessGlobalFromSite}>
|
|
607
|
+
{isSiteView && allowedToAccessGlobalFromSite && (
|
|
608
|
+
<S.TabsWrapper>
|
|
609
|
+
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={handleSelectedTab} noMargins />
|
|
610
|
+
</S.TabsWrapper>
|
|
611
|
+
)}
|
|
612
|
+
{!isSiteView && filters}
|
|
613
|
+
<S.DisplayModeWrapper>
|
|
614
|
+
<IconAction icon="Grid2" onClick={() => changeDisplayMode("grid")} active={displayMode === "grid"} />
|
|
615
|
+
<IconAction icon="BulletList" onClick={() => changeDisplayMode("list")} active={displayMode === "list"} />
|
|
616
|
+
</S.DisplayModeWrapper>
|
|
617
|
+
</S.FiltersBar>
|
|
618
|
+
<S.FiltersBar isSite={false}>
|
|
619
|
+
{isSiteView && filters}
|
|
620
|
+
<SearchField onChange={setSearchQuery} placeholder="Search" value={searchQuery} autoFocus={false} />
|
|
621
|
+
</S.FiltersBar>
|
|
606
622
|
{isLoading ? (
|
|
607
623
|
<Loading />
|
|
608
624
|
) : (
|
|
609
625
|
<>
|
|
610
|
-
<S.FiltersBar isSite={isSiteView && allowedToAccessGlobalFromSite}>
|
|
611
|
-
{isSiteView && allowedToAccessGlobalFromSite && (
|
|
612
|
-
<S.TabsWrapper>
|
|
613
|
-
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={handleSelectedTab} noMargins />
|
|
614
|
-
</S.TabsWrapper>
|
|
615
|
-
)}
|
|
616
|
-
{!isSiteView && <Filters />}
|
|
617
|
-
<S.DisplayModeWrapper>
|
|
618
|
-
<IconAction icon="Grid2" onClick={() => changeDisplayMode("grid")} active={displayMode === "grid"} />
|
|
619
|
-
<IconAction
|
|
620
|
-
icon="BulletList"
|
|
621
|
-
onClick={() => changeDisplayMode("list")}
|
|
622
|
-
active={displayMode === "list"}
|
|
623
|
-
/>
|
|
624
|
-
</S.DisplayModeWrapper>
|
|
625
|
-
</S.FiltersBar>
|
|
626
|
-
<S.FiltersBar isSite={false}>
|
|
627
|
-
{isSiteView && <Filters />}
|
|
628
|
-
<SearchField onChange={setSearchQuery} placeholder="Search" value={searchQuery} autoFocus={false} />
|
|
629
|
-
</S.FiltersBar>
|
|
630
626
|
{!isRoot && <Breadcrumb breadcrumb={breadcrumb} onClick={handleUpdateCurrentFolder} />}
|
|
631
627
|
{(hasFolders || !isRoot) && (
|
|
632
628
|
<S.SectionWrapper>
|
|
@@ -11,13 +11,20 @@ import * as S from "./style";
|
|
|
11
11
|
const ConnectedField = (props: IProps) => {
|
|
12
12
|
const { field, site, form, fieldKey, updateFormValue, disabled, errors, deleteError, theme, lang } = props;
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const isConditional = field.type === "ConditionalField";
|
|
15
|
+
const isArrayGroup = field.type === "ArrayFieldGroup";
|
|
16
|
+
const isComputedField = Object.prototype.hasOwnProperty.call(field, "computed");
|
|
17
|
+
const isFieldDisabled = disabled || isComputedField;
|
|
18
|
+
|
|
19
|
+
let value = form?.content && form.content[fieldKey];
|
|
15
20
|
const error = errors.find((err: any) => err.key === field.key);
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
if(isComputedField && form?.content) {
|
|
23
|
+
const computedFunction = eval(`(${field.computed})`);
|
|
24
|
+
value = computedFunction(form.content);
|
|
25
|
+
}
|
|
18
26
|
|
|
19
|
-
const
|
|
20
|
-
const isArrayGroup = field.type === "ArrayFieldGroup";
|
|
27
|
+
const handleChange = (newValue: any) => updateFormValue({ [fieldKey]: newValue });
|
|
21
28
|
|
|
22
29
|
let innerFields: JSX.Element[] = [];
|
|
23
30
|
|
|
@@ -30,7 +37,7 @@ const ConnectedField = (props: IProps) => {
|
|
|
30
37
|
value,
|
|
31
38
|
onChange: handleChange,
|
|
32
39
|
site,
|
|
33
|
-
disabled,
|
|
40
|
+
disabled: isFieldDisabled,
|
|
34
41
|
fieldType: field.type,
|
|
35
42
|
...field,
|
|
36
43
|
innerFields,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
|
-
import { IDataPack, IErrorItem, ILanguage, INotification, IRootState, ISite } from "@ax/types";
|
|
4
|
+
import { IDataPack, IErrorItem, ILanguage, INotification, IRootState, ISchemaField, ISite } from "@ax/types";
|
|
5
5
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
6
6
|
import { MainWrapper, ErrorToast, Notification, Loading } from "@ax/components";
|
|
7
7
|
import { getActivatedDataPacksIds, getDefaultTheme } from "@ax/helpers";
|
|
@@ -48,7 +48,7 @@ const Form = (props: IProps) => {
|
|
|
48
48
|
|
|
49
49
|
const { fields } = schema;
|
|
50
50
|
|
|
51
|
-
const fieldsTranslate = [
|
|
51
|
+
const fieldsTranslate: ISchemaField[] = [
|
|
52
52
|
{
|
|
53
53
|
title: "",
|
|
54
54
|
type: "TranslateButton",
|
|
@@ -83,22 +83,24 @@ const Form = (props: IProps) => {
|
|
|
83
83
|
|
|
84
84
|
const Fields =
|
|
85
85
|
fieldsTranslate &&
|
|
86
|
-
fieldsTranslate
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
fieldsTranslate
|
|
87
|
+
.filter((field: ISchemaField) => !field.hidden)
|
|
88
|
+
.map((field: ISchemaField, i: number) => {
|
|
89
|
+
const { type, key } = field;
|
|
90
|
+
if (key === "title") {
|
|
91
|
+
title = form?.content && form.content[key] ? form.content[key] : "";
|
|
92
|
+
}
|
|
93
|
+
return (
|
|
94
|
+
<ConnectedField
|
|
95
|
+
fieldKey={key}
|
|
96
|
+
field={field}
|
|
97
|
+
key={`${type}${i}`}
|
|
98
|
+
site={site}
|
|
99
|
+
disabled={isDisabled}
|
|
100
|
+
theme={site ? site.theme : theme}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
});
|
|
102
104
|
|
|
103
105
|
const handleSave = async (publish: boolean) => {
|
|
104
106
|
const validated = publish && !skipReviewOnPublish ? await validateForm(true) : true;
|
|
@@ -371,4 +373,4 @@ const mapDispatchToProps = {
|
|
|
371
373
|
setFormValues: structuredDataActions.setFormValues,
|
|
372
374
|
};
|
|
373
375
|
|
|
374
|
-
export default connect(mapStateToProps, mapDispatchToProps)(Form);
|
|
376
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Form);
|
package/src/types/index.tsx
CHANGED