@griddo/ax 11.9.15 → 11.9.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "11.9.15",
4
+ "version": "11.9.16",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Diego M. Béjar <diego.bejar@secuoyas.com>",
@@ -225,5 +225,5 @@
225
225
  "publishConfig": {
226
226
  "access": "public"
227
227
  },
228
- "gitHead": "5ede692b8bda54a9bd02ea09c902dcac5e5a1cfb"
228
+ "gitHead": "857db7ad8810574af06dad13496c06b656a416f3"
229
229
  }
@@ -1,9 +1,10 @@
1
1
  import React from "react";
2
+ import configureStore from "redux-mock-store";
2
3
  import ArrayFieldGroup, { IProps } from "@ax/components/Fields/ArrayFieldGroup";
3
4
  import { ThemeProvider } from "styled-components";
4
5
  import { parseTheme } from "@ax/helpers";
5
6
  import globalTheme from "@ax/themes/theme.json";
6
- import { render, screen, fireEvent, cleanup, act } from "@testing-library/react";
7
+ import { render, cleanup, screen, fireEvent, act } from "../../../../../config/jest/test-utils";
7
8
  import { mock } from "jest-mock-extended";
8
9
  import FieldsBehavior from "@ax/components/FieldsBehavior";
9
10
 
@@ -11,13 +12,22 @@ afterEach(cleanup);
11
12
 
12
13
  const defaultProps = mock<IProps>();
13
14
 
15
+ defaultProps.selectedContent = { component: "" };
16
+
17
+ const middlewares: any = [];
18
+ const mockStore = configureStore(middlewares);
19
+
20
+ const initialStore = {};
21
+ const store = mockStore(initialStore);
22
+
14
23
  describe("ArrayFieldGroup component rendering", () => {
15
24
  it("should render the component with no items and button", async () => {
16
25
  await act(async () => {
17
26
  render(
18
27
  <ThemeProvider theme={parseTheme(globalTheme)}>
19
28
  <ArrayFieldGroup {...defaultProps} />
20
- </ThemeProvider>
29
+ </ThemeProvider>,
30
+ { store }
21
31
  );
22
32
  });
23
33
 
@@ -67,7 +77,8 @@ describe("ArrayFieldGroup component rendering", () => {
67
77
  render(
68
78
  <ThemeProvider theme={parseTheme(globalTheme)}>
69
79
  <ArrayFieldGroup {...defaultProps} />
70
- </ThemeProvider>
80
+ </ThemeProvider>,
81
+ { store }
71
82
  );
72
83
  });
73
84
 
@@ -96,7 +107,8 @@ describe("ArrayFieldGroup component rendering", () => {
96
107
  render(
97
108
  <ThemeProvider theme={parseTheme(globalTheme)}>
98
109
  <ArrayFieldGroup {...defaultProps} />
99
- </ThemeProvider>
110
+ </ThemeProvider>,
111
+ { store }
100
112
  );
101
113
  });
102
114
 
@@ -143,7 +155,8 @@ describe("ArrayFieldGroup component rendering", () => {
143
155
  render(
144
156
  <ThemeProvider theme={parseTheme(globalTheme)}>
145
157
  <ArrayFieldGroup {...defaultProps} />
146
- </ThemeProvider>
158
+ </ThemeProvider>,
159
+ { store }
147
160
  );
148
161
  });
149
162
 
@@ -172,7 +185,8 @@ describe("ArrayFieldGroup component rendering", () => {
172
185
  render(
173
186
  <ThemeProvider theme={parseTheme(globalTheme)}>
174
187
  <ArrayFieldGroup {...defaultProps} />
175
- </ThemeProvider>
188
+ </ThemeProvider>,
189
+ { store }
176
190
  );
177
191
 
178
192
  expect(screen.getByText("A Title")).toBeTruthy();
@@ -205,7 +219,8 @@ describe("ArrayFieldGroup component events", () => {
205
219
  render(
206
220
  <ThemeProvider theme={parseTheme(globalTheme)}>
207
221
  <ArrayFieldGroup {...defaultProps} />
208
- </ThemeProvider>
222
+ </ThemeProvider>,
223
+ { store }
209
224
  );
210
225
  });
211
226
 
@@ -257,7 +272,8 @@ describe("ArrayFieldGroup component events", () => {
257
272
  render(
258
273
  <ThemeProvider theme={parseTheme(globalTheme)}>
259
274
  <ArrayFieldGroup {...defaultProps} />
260
- </ThemeProvider>
275
+ </ThemeProvider>,
276
+ { store }
261
277
  );
262
278
  });
263
279
 
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
 
3
3
  import { IPage, ISite, ILanguage } from "@ax/types";
4
- import { getNullValue, getDefaultSchema, getDefaultTemplate } from "@ax/helpers";
4
+ import { getNullValue, getDefaultSchema, getDefaultTemplate, findObjectValue } from "@ax/helpers";
5
5
 
6
6
  import { FieldsBehavior, HiddenField } from "@ax/components";
7
7
 
@@ -10,28 +10,29 @@ const FieldContainer = (props: IFieldContainerProps) => {
10
10
 
11
11
  const { type, key, title, hideable, slugTo } = field;
12
12
  const isContainer = field.type === "ComponentContainer";
13
-
14
- const hideField = () => updateValue(key, nullValue);
15
-
16
- const containerValue = selectedContent[objKey] !== undefined ? selectedContent[objKey] : null;
17
-
18
- const fieldProps = {
19
- fieldType: type,
20
- value: containerValue,
21
- hideField,
22
- onChange: (e: any) => updateValue(key, e, undefined, slugTo),
23
- goTo,
24
- editorID: selectedContent.editorID,
25
- lang,
26
- ...field,
27
- ...props,
28
- };
29
-
30
13
  const hasMultipleOptions = field.whiteList && field.whiteList.length > 1;
14
+ const containerValue = findObjectValue(selectedContent, objKey);
31
15
  const nullValue = isContainer && containerValue ? getNullValue(containerValue, hasMultipleOptions) : null;
32
16
  const hasNullValue = JSON.stringify(containerValue) === JSON.stringify(nullValue);
17
+ const isHiddenField = hasNullValue && hideable && !hasMultipleOptions && !isContainer;
18
+
19
+ const hideField = () => updateValue(key, nullValue);
33
20
 
34
- const getField = () => <FieldsBehavior {...fieldProps} key={key} />;
21
+ const getField = () => {
22
+ const fieldProps = {
23
+ fieldType: type,
24
+ value: containerValue,
25
+ hideField,
26
+ onChange: (e: any) => updateValue(key, e, undefined, slugTo),
27
+ goTo,
28
+ editorID: selectedContent.editorID,
29
+ lang,
30
+ ...field,
31
+ ...props,
32
+ };
33
+
34
+ return <FieldsBehavior {...fieldProps} key={key} />;
35
+ };
35
36
 
36
37
  const getDefaultValue = () => {
37
38
  const isTemplate = selectedContent.type === "template";
@@ -49,8 +50,6 @@ const FieldContainer = (props: IFieldContainerProps) => {
49
50
 
50
51
  const getHiddenField = () => <HiddenField key={props.objKey} title={title} showField={showField} />;
51
52
 
52
- const isHiddenField = hasNullValue && hideable && !hasMultipleOptions && !isContainer;
53
-
54
53
  return isHiddenField ? getHiddenField() : getField();
55
54
  };
56
55
 
@@ -1,12 +1,27 @@
1
1
  import React from "react";
2
+ import { connect } from "react-redux";
2
3
 
3
4
  import { IconAction } from "@ax/components";
4
5
  import { ISite } from "@ax/types";
6
+ import { pageEditorActions } from "@ax/containers/PageEditor";
7
+ import { getNullValue } from "@ax/helpers";
5
8
 
6
9
  import * as S from "./style";
7
10
 
8
11
  const ArrayFieldInline = (props: IProps): JSX.Element => {
9
- const { fields, item, index, onChange, handleDelete, site, disabled } = props;
12
+ const {
13
+ fields,
14
+ item,
15
+ index,
16
+ onChange,
17
+ handleDelete,
18
+ site,
19
+ disabled,
20
+ parentKey,
21
+ actions,
22
+ addComponentInArray,
23
+ replaceModuleInArray,
24
+ } = props;
10
25
 
11
26
  const deleteItem = () => handleDelete(index);
12
27
 
@@ -17,10 +32,35 @@ const ArrayFieldInline = (props: IProps): JSX.Element => {
17
32
  const handleChange = (newValue: any) => onChange({ [key]: newValue });
18
33
 
19
34
  const innerFields = field.props.innerFields ? getFields(field.props.innerFields) : undefined;
35
+ const hasMultipleOptions = field.props.whiteList && field.props.whiteList.length > 1;
36
+
37
+ const actionsField = {
38
+ ...actions,
39
+ addComponentAction: (component: any, key: string) =>
40
+ addComponentInArray(component, key, parentKey, index, hasMultipleOptions),
41
+ replaceModuleAction: (module: string, parent: any, key: string) =>
42
+ replaceModuleInArray(module, parent, key, parentKey, index),
43
+ };
44
+
45
+ const hideField = () => {
46
+ const isContainer = field.props.type === "ComponentContainer";
47
+
48
+ const nullValue = isContainer && item[key] ? getNullValue(item[key], hasMultipleOptions) : null;
49
+ onChange({ [key]: nullValue });
50
+ };
20
51
 
21
52
  return {
22
53
  ...field,
23
- props: { ...field.props, value: item[key], objKey: key, onChange: handleChange, innerFields, site },
54
+ props: {
55
+ ...field.props,
56
+ value: item[key],
57
+ objKey: key,
58
+ onChange: handleChange,
59
+ innerFields,
60
+ site,
61
+ actions: actionsField,
62
+ hideField,
63
+ },
24
64
  key,
25
65
  };
26
66
  });
@@ -46,6 +86,15 @@ interface IProps {
46
86
  handleDelete: (index: number) => void;
47
87
  site: ISite | null;
48
88
  disabled?: boolean;
89
+ parentKey: string;
90
+ actions: any;
91
+ addComponentInArray(type: string, key: string, parentKey: string, index: number, isMultiple: boolean): void;
92
+ replaceModuleInArray(module: string, parent: any, key: string, parentKey: string, index: number): void;
49
93
  }
50
94
 
51
- export default ArrayFieldInline;
95
+ const mapDispatchToProps = {
96
+ addComponentInArray: pageEditorActions.addComponentInArray,
97
+ replaceModuleInArray: pageEditorActions.replaceModuleInArray,
98
+ };
99
+
100
+ export default connect(null, mapDispatchToProps)(ArrayFieldInline);
@@ -1,10 +1,28 @@
1
1
  import React from "react";
2
+ import { connect } from "react-redux";
2
3
  import { ISite } from "@ax/types";
4
+ import { pageEditorActions } from "@ax/containers/PageEditor";
5
+ import { getNullValue } from "@ax/helpers";
3
6
 
4
7
  import * as S from "./style";
5
8
 
6
9
  const ArrayFieldItem = (props: IProps): JSX.Element => {
7
- const { fields, item, name, index, onChange, handleDelete, isOpen, setIsOpen, site, disabled } = props;
10
+ const {
11
+ fields,
12
+ item,
13
+ name,
14
+ index,
15
+ onChange,
16
+ handleDelete,
17
+ isOpen,
18
+ setIsOpen,
19
+ site,
20
+ disabled,
21
+ parentKey,
22
+ actions,
23
+ addComponentInArray,
24
+ replaceModuleInArray,
25
+ } = props;
8
26
 
9
27
  const handleClick = () => (isOpen === index ? setIsOpen(null) : setIsOpen(index));
10
28
 
@@ -15,7 +33,7 @@ const ArrayFieldItem = (props: IProps): JSX.Element => {
15
33
  label: "Delete",
16
34
  icon: "delete",
17
35
  action: deleteItem,
18
- disabled
36
+ disabled,
19
37
  },
20
38
  ];
21
39
 
@@ -30,14 +48,40 @@ const ArrayFieldItem = (props: IProps): JSX.Element => {
30
48
 
31
49
  const getFields = (fields: any[]): any[] => {
32
50
  return fields.map((field: any) => {
33
- const key = field.props.objKey;
51
+ const { key } = field;
52
+
34
53
  const handleChange = (newValue: any) => onChange({ [key]: newValue });
35
54
 
36
55
  const innerFields = field.props.innerFields ? getFields(field.props.innerFields) : undefined;
56
+ const hasMultipleOptions = field.props.whiteList && field.props.whiteList.length > 1;
57
+
58
+ const actionsField = {
59
+ ...actions,
60
+ addComponentAction: (component: any, key: string) =>
61
+ addComponentInArray(component, key, parentKey, index, hasMultipleOptions),
62
+ replaceModuleAction: (module: string, parent: any, key: string) =>
63
+ replaceModuleInArray(module, parent, key, parentKey, index),
64
+ };
65
+
66
+ const hideField = () => {
67
+ const isContainer = field.props.type === "ComponentContainer";
68
+
69
+ const nullValue = isContainer && item[key] ? getNullValue(item[key], hasMultipleOptions) : null;
70
+ onChange({ [key]: nullValue });
71
+ };
37
72
 
38
73
  return {
39
74
  ...field,
40
- props: { ...field.props, value: item[key], objKey: key, onChange: handleChange, innerFields, site },
75
+ props: {
76
+ ...field.props,
77
+ value: item[key],
78
+ objKey: key,
79
+ onChange: handleChange,
80
+ innerFields,
81
+ site,
82
+ actions: actionsField,
83
+ hideField,
84
+ },
41
85
  key,
42
86
  };
43
87
  });
@@ -65,6 +109,15 @@ interface IProps {
65
109
  setIsOpen: (index: number | null) => void;
66
110
  site: ISite | null;
67
111
  disabled?: boolean;
112
+ parentKey: string;
113
+ actions: any;
114
+ addComponentInArray(type: string, key: string, parentKey: string, index: number, isMultiple: boolean): void;
115
+ replaceModuleInArray(module: string, parent: any, key: string, parentKey: string, index: number): void;
68
116
  }
69
117
 
70
- export default ArrayFieldItem;
118
+ const mapDispatchToProps = {
119
+ addComponentInArray: pageEditorActions.addComponentInArray,
120
+ replaceModuleInArray: pageEditorActions.replaceModuleInArray,
121
+ };
122
+
123
+ export default connect(null, mapDispatchToProps)(ArrayFieldItem);
@@ -3,13 +3,27 @@ import { v4 as uuidv4 } from "uuid";
3
3
 
4
4
  import { Button, FieldsDivider } from "@ax/components";
5
5
  import { ISite } from "@ax/types";
6
+ import { getDefaultSchema } from "@ax/helpers";
6
7
  import ArrayFieldItem from "./ArrayFieldItem";
7
8
  import ArrayFieldInline from "./ArrayFieldInline";
8
9
 
9
10
  import * as S from "./style";
10
11
 
11
12
  const ArrayFieldGroup = (props: IProps): JSX.Element => {
12
- const { value, name, innerFields, onChange, divider, arrayType, site, disabled, editorID } = props;
13
+ const {
14
+ value,
15
+ name,
16
+ innerFields,
17
+ onChange,
18
+ divider,
19
+ arrayType,
20
+ site,
21
+ disabled,
22
+ editorID,
23
+ objKey,
24
+ selectedContent,
25
+ actions,
26
+ } = props;
13
27
 
14
28
  const [items, setItems] = useState<any[]>([]);
15
29
  const [isOpen, setIsOpen] = useState<number | null>(null);
@@ -23,7 +37,13 @@ const ArrayFieldGroup = (props: IProps): JSX.Element => {
23
37
  }, [editorID]);
24
38
 
25
39
  const handleClick = () => {
26
- const newItems = [...items, { id: uuidv4() }];
40
+ const defaultValues = getDefaultSchema(selectedContent.component);
41
+ const newComponent =
42
+ !!defaultValues[objKey] && defaultValues[objKey].length
43
+ ? { ...defaultValues[objKey][0], id: uuidv4() }
44
+ : { id: uuidv4() };
45
+
46
+ const newItems = [...items, newComponent];
27
47
  setItems(newItems);
28
48
  onChange(newItems);
29
49
  setIsOpen(newItems.length - 1);
@@ -65,6 +85,8 @@ const ArrayFieldGroup = (props: IProps): JSX.Element => {
65
85
  handleDelete={handleDelete}
66
86
  site={site}
67
87
  disabled={disabled}
88
+ parentKey={objKey}
89
+ actions={actions}
68
90
  />
69
91
  ) : (
70
92
  <ArrayFieldItem
@@ -79,6 +101,8 @@ const ArrayFieldGroup = (props: IProps): JSX.Element => {
79
101
  setIsOpen={setIsOpen}
80
102
  site={site}
81
103
  disabled={disabled}
104
+ parentKey={objKey}
105
+ actions={actions}
82
106
  />
83
107
  );
84
108
  })}
@@ -102,6 +126,9 @@ export interface IProps {
102
126
  site: ISite | null;
103
127
  disabled?: boolean;
104
128
  editorID: number;
129
+ objKey: string;
130
+ selectedContent: any;
131
+ actions: any;
105
132
  }
106
133
 
107
134
  export default ArrayFieldGroup;
@@ -46,6 +46,7 @@ import {
46
46
  getPageNavigation,
47
47
  getStateValues,
48
48
  addElementToCollection,
49
+ addElementToComponent,
49
50
  } from "./utils";
50
51
  import {
51
52
  SET_BREADCRUMB,
@@ -745,6 +746,29 @@ function addComponent(
745
746
  };
746
747
  }
747
748
 
749
+ function addComponentInArray(
750
+ type: string,
751
+ key: string,
752
+ parentKey: string,
753
+ index: number,
754
+ isMultiple: boolean
755
+ ): (dispatch: Dispatch, getState: () => IRootState) => void {
756
+ return (dispatch, getState) => {
757
+ const { editorContent, selectedContent } = getStateValues(getState);
758
+ const editorID = isMultiple
759
+ ? selectedContent[parentKey][index][key][type].editorID
760
+ : selectedContent[parentKey][index][key].editorID;
761
+
762
+ const clonedContent = deepClone(editorContent);
763
+ const { element, parent } = findByEditorID(clonedContent, editorID);
764
+
765
+ addElementToComponent(parent, element);
766
+
767
+ generatePageContent(clonedContent)(dispatch, getState);
768
+ setSelectedContent(element.editorID)(dispatch, getState);
769
+ };
770
+ }
771
+
748
772
  function addModule(
749
773
  type: string,
750
774
  key: string,
@@ -831,6 +855,41 @@ function replaceModule(
831
855
  };
832
856
  }
833
857
 
858
+ function replaceModuleInArray(
859
+ module: string,
860
+ parent: any,
861
+ key: string,
862
+ parentKey: string,
863
+ index: number
864
+ ): (dispatch: Dispatch, getState: () => IRootState) => void {
865
+ return async (dispatch, getState) => {
866
+ const { editorContent } = getStateValues(getState);
867
+ const clonedEditor = deepClone(editorContent);
868
+
869
+ const value = parent[parentKey][index][key];
870
+ const updatedVal = {
871
+ ...getNullValue(value, true),
872
+ };
873
+
874
+ Object.keys(updatedVal).forEach((key: string) => {
875
+ if (updatedVal[key].component === module) {
876
+ const defaultSchema = getDefaultSchema(module);
877
+ updatedVal[key] = {
878
+ ...defaultSchema,
879
+ ...updatedVal[key],
880
+ };
881
+ }
882
+ });
883
+
884
+ const { element } = findByEditorID(clonedEditor, parent.editorID);
885
+ element[parentKey][index][key] = updatedVal;
886
+ const editorID = element[parentKey][index][key][module].editorID;
887
+
888
+ generatePageContent(clonedEditor)(dispatch, getState);
889
+ setSelectedContent(editorID)(dispatch, getState);
890
+ };
891
+ }
892
+
834
893
  function replaceElementsInCollection(
835
894
  newValue: string,
836
895
  reference?: string
@@ -1599,4 +1658,6 @@ export {
1599
1658
  setIsTranslated,
1600
1659
  schedulePublication,
1601
1660
  setScrollEditorID,
1661
+ addComponentInArray,
1662
+ replaceModuleInArray,
1602
1663
  };
@@ -129,7 +129,7 @@ const addElementToComponent = (component: Record<string, any>, type: IComponent)
129
129
  const element = addElement(type);
130
130
  Object.keys(component).forEach((key: string) => {
131
131
  const containedValue = component[key];
132
- if (containedValue.editorID === type.editorID) {
132
+ if (containedValue?.editorID === type.editorID) {
133
133
  component[key] = element;
134
134
  }
135
135
  });
@@ -171,4 +171,5 @@ export {
171
171
  getDefaultIntegrations,
172
172
  getDefaultPageNavigation,
173
173
  addElementToCollection,
174
+ addElementToComponent,
174
175
  };
@@ -116,16 +116,20 @@ const encodeData = (data: Record<string, string | number | boolean>): string =>
116
116
  .join("&");
117
117
 
118
118
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
- const findObjectValue = (obj: Record<string, any>, key: string): any | undefined => {
120
- if (!obj || typeof obj !== "object") return undefined;
121
- if (key in obj) return obj[key];
122
-
123
- for (const prop of Object.values(obj)) {
124
- if (typeof prop === "object" && prop !== null) {
125
- const foundValue = findObjectValue(prop, key);
126
- if (foundValue) return foundValue;
119
+ const findObjectValue = (obj: any, key: string): any | undefined => {
120
+ if (obj == null) return undefined;
121
+
122
+ if (typeof obj === "object") {
123
+ if (key in obj) {
124
+ return obj[key];
125
+ }
126
+
127
+ for (const value of Array.isArray(obj) ? obj : Object.values(obj)) {
128
+ const found = findObjectValue(value, key);
129
+ if (found !== undefined) return found;
127
130
  }
128
131
  }
132
+
129
133
  return undefined;
130
134
  };
131
135
 
@@ -496,9 +496,8 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
496
496
  }
497
497
 
498
498
  const type: any = structuredDataContent && structuredDataContent[col.key];
499
- const checkGroups = ["MultiCheckSelect", "AsyncCheckGroup", "CheckGroup"];
500
499
 
501
- if (!checkGroups.includes(col.type)) {
500
+ if (typeof type !== "object") {
502
501
  return (
503
502
  <S.ColumnCell key={col.key} onClick={goToPage}>
504
503
  {type}
@@ -374,9 +374,8 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
374
374
  }
375
375
 
376
376
  const type: any = structuredDataContent && structuredDataContent[col.key];
377
- const checkGroups = ["MultiCheckSelect", "AsyncCheckGroup", "CheckGroup"];
378
377
 
379
- if (!checkGroups.includes(col.type)) {
378
+ if (typeof type !== "object") {
380
379
  return (
381
380
  <S.ColumnCell key={col.key} onClick={_handleClick}>
382
381
  {type}
@@ -219,9 +219,8 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
219
219
  }
220
220
 
221
221
  const type: any = structuredData && structuredData.content && structuredData.content[col.key];
222
- const checkGroups = ["MultiCheckSelect", "AsyncCheckGroup", "CheckGroup"];
223
222
 
224
- if (!checkGroups.includes(col.type)) {
223
+ if (typeof type !== "object") {
225
224
  return (
226
225
  <S.ColumnCell key={col.key} onClick={_handleClick}>
227
226
  {type}