@griddo/ax 1.69.8 → 1.72.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 (160) hide show
  1. package/config/jest/componentsMock.js +0 -26
  2. package/package.json +4 -3
  3. package/src/Style/index.tsx +1 -1
  4. package/src/__tests__/components/ElementsTooltip/ElementsTooltip.test.tsx +97 -0
  5. package/src/__tests__/components/EmptyState/EmptyState.test.tsx +78 -0
  6. package/src/__tests__/components/FieldContainer/FieldContainer.test.tsx +82 -0
  7. package/src/__tests__/components/Fields/AnalyticsField/AnalyticsField.test.tsx +1 -1
  8. package/src/__tests__/components/Fields/AnalyticsField/PageAnalytics/PageAnalytics.test.tsx +1 -15
  9. package/src/__tests__/components/Fields/AnalyticsField/StructuredDataAnalytics/StructuredDataAnalytics.test.tsx +1 -16
  10. package/src/__tests__/components/Fields/ArrayFieldGroup/ArrayFieldGroup.test.tsx +8 -17
  11. package/src/__tests__/components/Fields/AsyncCheckGroup/AsyncCheckGroup.test.tsx +4 -16
  12. package/src/__tests__/components/Fields/AsyncSelect/AsyncSelect.test.tsx +2 -20
  13. package/src/__tests__/components/Fields/CheckField/CheckField.test.tsx +6 -6
  14. package/src/__tests__/components/Fields/CheckGroup/CheckGroup.test.tsx +15 -15
  15. package/src/__tests__/components/Fields/ColorPicker/ColorPicker.test.tsx +7 -16
  16. package/src/__tests__/components/Fields/ComponentArray/ComponentArray.test.tsx +2 -23
  17. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/MixableComponentArray.test.tsx +11 -31
  18. package/src/__tests__/components/Fields/ComponentArray/MixableComponentArray/PasteModuleButton/PasteModuleButton.test.tsx +15 -21
  19. package/src/__tests__/components/Fields/ComponentArray/SameComponentArray/SameComponentArray.test.tsx +6 -25
  20. package/src/__tests__/components/Fields/ComponentContainer/ComponentContainer.test.tsx +559 -0
  21. package/src/__tests__/components/Fields/ConditionalField/ConditionalField.test.tsx +1 -1
  22. package/src/__tests__/components/Fields/DateField/DateField.test.tsx +1 -1
  23. package/src/__tests__/components/Fields/FieldGroup/FieldGroup.test.tsx +1 -1
  24. package/src/__tests__/components/Fields/FieldsDivider/FieldsDivider.test.tsx +1 -1
  25. package/src/__tests__/components/Fields/FileField/FileField.test.tsx +3 -3
  26. package/src/__tests__/components/Fields/HeadingField/HeadingField.test.tsx +6 -6
  27. package/src/__tests__/components/Fields/HiddenField/HiddenField.test.tsx +2 -8
  28. package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +471 -0
  29. package/src/__tests__/components/Fields/MultiCheckSelect/MultiCheckSelect.test.tsx +2 -16
  30. package/src/__tests__/components/Fields/MultiCheckSelectGroup/MultiCheckSelectGroup.test.tsx +2 -2
  31. package/src/__tests__/components/Fields/NoteField/NoteField.test.tsx +2 -7
  32. package/src/__tests__/components/Fields/NumberField/NumberField.test.tsx +2 -15
  33. package/src/__tests__/components/Fields/RadioField/RadioField.test.tsx +2 -12
  34. package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +171 -19
  35. package/src/__tests__/components/Fields/RichText/RichText.test.tsx +2 -13
  36. package/src/__tests__/components/Fields/Select/Select.test.tsx +3 -23
  37. package/src/__tests__/components/Fields/SliderField/SliderField.test.tsx +2 -15
  38. package/src/__tests__/components/Fields/TagField/TagField.test.tsx +4 -4
  39. package/src/__tests__/components/Fields/TextArea/TextArea.test.tsx +1 -1
  40. package/src/__tests__/components/Fields/TextField/TextField.test.tsx +6 -6
  41. package/src/__tests__/components/Fields/TimeField/HourInput/HourInput.test.tsx +142 -0
  42. package/src/__tests__/components/Fields/TimeField/TimeField.test.tsx +100 -0
  43. package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +2 -10
  44. package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +152 -0
  45. package/src/__tests__/components/Fields/UniqueCheck/UniqueCheck.test.tsx +3 -3
  46. package/src/__tests__/components/Fields/UrlField/UrlField.test.tsx +4 -4
  47. package/src/__tests__/components/Fields/VisualUniqueSelection/ImageSelection/ImageSelection.test.tsx +2 -14
  48. package/src/__tests__/components/Fields/VisualUniqueSelection/ScrollableSelection/ScrollableSelection.test.tsx +6 -20
  49. package/src/__tests__/components/Fields/VisualUniqueSelection/VisualUniqueSelection.test.tsx +3 -29
  50. package/src/__tests__/components/Fields/Wysiwyg/Wysiwyg.test.tsx +1 -1
  51. package/src/__tests__/components/FieldsBehavior/FieldsBehavior.test.tsx +149 -0
  52. package/src/__tests__/components/TableFilters/CategoryFilter/CategoryFilter.test.tsx +241 -0
  53. package/src/__tests__/components/TableFilters/CustomizeFilters/CustomizeFilters.test.tsx +131 -0
  54. package/src/__tests__/components/TableFilters/DateFilter/DateFilter.test.tsx +148 -0
  55. package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +265 -0
  56. package/src/__tests__/components/TableFilters/NameFilter/NameFilter.test.tsx +197 -0
  57. package/src/__tests__/components/TableFilters/SiteFilter/SiteFilter.test.tsx +317 -0
  58. package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +197 -0
  59. package/src/__tests__/components/TableFilters/TranslationsFilter/TranslationsFilter.test.tsx +157 -0
  60. package/src/__tests__/components/TableFilters/TypeFilter/TypeFilter.test.tsx +164 -0
  61. package/src/__tests__/components/TableList/TableList.test.tsx +119 -0
  62. package/src/__tests__/components/Tabs/Tabs.test.tsx +205 -0
  63. package/src/__tests__/components/Tag/Tag.test.tsx +140 -0
  64. package/src/__tests__/components/Toast/Toast.test.tsx +102 -0
  65. package/src/api/navigation.tsx +1 -1
  66. package/src/components/Browser/index.tsx +1 -1
  67. package/src/components/Button/index.tsx +3 -3
  68. package/src/components/ConfigPanel/NavigationForm/Field/index.tsx +14 -3
  69. package/src/components/ElementsTooltip/index.tsx +10 -9
  70. package/src/components/EmptyState/index.tsx +2 -2
  71. package/src/components/FieldContainer/index.tsx +3 -3
  72. package/src/components/Fields/ArrayFieldGroup/index.tsx +1 -1
  73. package/src/components/Fields/AsyncCheckGroup/index.tsx +1 -1
  74. package/src/components/Fields/AsyncSelect/index.tsx +1 -1
  75. package/src/components/Fields/CheckField/index.tsx +3 -3
  76. package/src/components/Fields/CheckGroup/index.tsx +2 -2
  77. package/src/components/Fields/ComponentContainer/index.tsx +7 -6
  78. package/src/components/Fields/ComponentContainer/style.tsx +2 -2
  79. package/src/components/Fields/HeadingField/index.tsx +1 -1
  80. package/src/components/Fields/HiddenField/index.tsx +1 -1
  81. package/src/components/Fields/ImageField/index.tsx +10 -5
  82. package/src/components/Fields/MultiCheckSelect/index.tsx +3 -3
  83. package/src/components/Fields/NumberField/index.tsx +2 -1
  84. package/src/components/Fields/ReferenceField/ItemList/Item/index.tsx +5 -7
  85. package/src/components/Fields/ReferenceField/ItemList/Item/style.tsx +2 -2
  86. package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
  87. package/src/components/Fields/RichText/index.tsx +10 -6
  88. package/src/components/Fields/Select/index.tsx +2 -2
  89. package/src/components/Fields/SliderField/index.tsx +1 -1
  90. package/src/components/Fields/TextField/index.tsx +2 -7
  91. package/src/components/Fields/TimeField/HourInput/index.tsx +103 -0
  92. package/src/components/Fields/TimeField/HourInput/style.tsx +19 -0
  93. package/src/components/Fields/TimeField/HourInput/utils.tsx +35 -0
  94. package/src/components/Fields/TimeField/index.tsx +57 -0
  95. package/src/components/Fields/TimeField/style.tsx +37 -0
  96. package/src/components/Fields/index.tsx +2 -0
  97. package/src/components/FieldsBehavior/index.tsx +1 -1
  98. package/src/components/FloatingMenu/index.tsx +2 -2
  99. package/src/components/Gallery/GalleryFilters/Type/index.tsx +50 -0
  100. package/src/components/Gallery/GalleryFilters/Type/style.tsx +39 -0
  101. package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +2 -1
  102. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +3 -3
  103. package/src/components/Gallery/hooks.tsx +10 -4
  104. package/src/components/Gallery/index.tsx +2 -0
  105. package/src/components/Icon/index.tsx +1 -1
  106. package/src/components/IconAction/index.tsx +1 -1
  107. package/src/components/Lists/index.tsx +1 -1
  108. package/src/components/Loading/index.tsx +1 -1
  109. package/src/components/Pagination/index.tsx +1 -1
  110. package/src/components/SideModal/SideModalOption/index.tsx +4 -2
  111. package/src/components/SideModal/index.tsx +1 -1
  112. package/src/components/TableFilters/CategoryFilter/index.tsx +2 -2
  113. package/src/components/TableFilters/CategoryFilter/style.tsx +1 -10
  114. package/src/components/TableFilters/CustomizeFilters/index.tsx +2 -3
  115. package/src/components/TableFilters/DateFilter/index.tsx +4 -4
  116. package/src/components/TableFilters/LiveFilter/index.tsx +1 -1
  117. package/src/components/TableFilters/LiveFilter/style.tsx +2 -10
  118. package/src/components/TableFilters/NameFilter/index.tsx +4 -4
  119. package/src/components/TableFilters/SiteFilter/index.tsx +16 -13
  120. package/src/components/TableFilters/SiteFilter/style.tsx +1 -10
  121. package/src/components/TableFilters/StatusFilter/index.tsx +3 -3
  122. package/src/components/TableFilters/TranslationsFilter/index.tsx +4 -7
  123. package/src/components/TableFilters/TranslationsFilter/style.tsx +1 -10
  124. package/src/components/TableFilters/TypeFilter/index.tsx +2 -2
  125. package/src/components/TableFilters/TypeFilter/style.tsx +1 -10
  126. package/src/components/TableList/index.tsx +6 -6
  127. package/src/components/TableList/style.tsx +1 -1
  128. package/src/components/Tabs/index.tsx +19 -7
  129. package/src/components/Tag/index.tsx +6 -6
  130. package/src/components/Toast/index.tsx +4 -4
  131. package/src/components/Tooltip/index.tsx +5 -3
  132. package/src/components/index.tsx +2 -0
  133. package/src/containers/Navigation/Defaults/actions.tsx +10 -5
  134. package/src/containers/Navigation/Defaults/utils.tsx +13 -4
  135. package/src/containers/Sites/actions.tsx +7 -0
  136. package/src/containers/Sites/constants.tsx +1 -0
  137. package/src/containers/Sites/interfaces.tsx +6 -0
  138. package/src/containers/Sites/reducer.tsx +4 -0
  139. package/src/containers/StructuredData/actions.tsx +21 -8
  140. package/src/containers/StructuredData/constants.tsx +2 -0
  141. package/src/containers/StructuredData/interfaces.tsx +7 -1
  142. package/src/containers/StructuredData/reducer.tsx +5 -1
  143. package/src/helpers/fields.tsx +2 -2
  144. package/src/helpers/index.tsx +3 -0
  145. package/src/helpers/parseTheme.js +456 -0
  146. package/src/helpers/schemas.tsx +2 -2
  147. package/src/hooks/forms.tsx +2 -1
  148. package/src/modules/App/Routing/NavMenu/index.tsx +9 -1
  149. package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -1
  150. package/src/modules/Content/hooks.tsx +19 -12
  151. package/src/modules/Content/index.tsx +23 -14
  152. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -0
  153. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +3 -1
  154. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +16 -18
  155. package/src/modules/Navigation/Defaults/DefaultsEditor/utils.tsx +37 -0
  156. package/src/modules/StructuredData/Form/ConnectedField/index.tsx +3 -2
  157. package/src/modules/StructuredData/Form/index.tsx +22 -17
  158. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +30 -20
  159. package/src/modules/StructuredData/StructuredDataList/index.tsx +24 -14
  160. package/src/types/index.tsx +8 -7
@@ -0,0 +1,102 @@
1
+ import * as React from "react";
2
+
3
+ import { ThemeProvider } from "styled-components";
4
+ import { mock } from "jest-mock-extended";
5
+ import { render, screen, cleanup, fireEvent } from "@testing-library/react";
6
+ import { parseTheme } from "@ax/helpers";
7
+
8
+ import Toast, { IToastProps } from "@ax/components/Toast";
9
+ import globalTheme from "@ax/themes/theme.json";
10
+
11
+ afterEach(cleanup);
12
+
13
+ const defaultProps = mock<IToastProps>();
14
+
15
+ describe("Toast component rendering", () => {
16
+ jest.useFakeTimers();
17
+ jest.spyOn(global, "setTimeout");
18
+
19
+ it("should render the component", () => {
20
+ defaultProps.message = "1 module copied to clipboard";
21
+
22
+ render(
23
+ <ThemeProvider theme={parseTheme(globalTheme)}>
24
+ <Toast {...defaultProps} />
25
+ </ThemeProvider>
26
+ );
27
+
28
+ const toastWrapper = screen.getByTestId("toast-wrapper");
29
+ expect(toastWrapper).toBeTruthy();
30
+ });
31
+
32
+ it("should render the component's message", () => {
33
+ defaultProps.message = "1 module copied to clipboard";
34
+
35
+ render(
36
+ <ThemeProvider theme={parseTheme(globalTheme)}>
37
+ <Toast {...defaultProps} />
38
+ </ThemeProvider>
39
+ );
40
+
41
+ const toastMessage = screen.getByTestId("toast-message");
42
+ expect(toastMessage.textContent).toEqual("1 module copied to clipboard");
43
+ });
44
+
45
+ it("should not render the undo button when no action", () => {
46
+ defaultProps.message = "1 module copied to clipboard";
47
+
48
+ render(
49
+ <ThemeProvider theme={parseTheme(globalTheme)}>
50
+ <Toast {...defaultProps} />
51
+ </ThemeProvider>
52
+ );
53
+
54
+ const button = screen.queryByTestId("button-line-inverse");
55
+ expect(button).toBeFalsy();
56
+ });
57
+ });
58
+
59
+ describe("Toast component events", () => {
60
+ it("should render the undo button when action", () => {
61
+ defaultProps.message = "1 module copied to clipboard";
62
+ defaultProps.action = jest.fn();
63
+
64
+ render(
65
+ <ThemeProvider theme={parseTheme(globalTheme)}>
66
+ <Toast {...defaultProps} />
67
+ </ThemeProvider>
68
+ );
69
+
70
+ const button = screen.getByTestId("button-line-inverse");
71
+ expect(button).toBeTruthy();
72
+ });
73
+
74
+ it("should change visibility after 5000 ms", async () => {
75
+ defaultProps.message = "1 module copied to clipboard";
76
+
77
+ render(
78
+ <ThemeProvider theme={parseTheme(globalTheme)}>
79
+ <Toast {...defaultProps} />
80
+ </ThemeProvider>
81
+ );
82
+
83
+ expect(setTimeout).toHaveBeenCalled();
84
+ expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 5000);
85
+ });
86
+
87
+ it("should contain closing animation class on click close button", async () => {
88
+ defaultProps.message = "1 module copied to clipboard";
89
+
90
+ render(
91
+ <ThemeProvider theme={parseTheme(globalTheme)}>
92
+ <Toast {...defaultProps} />
93
+ </ThemeProvider>
94
+ );
95
+
96
+ const toastWrapper = screen.getByTestId("toast-wrapper");
97
+ const closeButton = screen.getByTestId("icon-action-component");
98
+ expect(closeButton).toBeTruthy();
99
+ fireEvent.click(closeButton);
100
+ expect(toastWrapper.classList.contains("close-animation")).toBeTruthy();
101
+ });
102
+ });
@@ -105,7 +105,7 @@ const updateNavigation = (navID: number, data: any) => {
105
105
 
106
106
  SERVICES.UPDATE_NAVIGATION.dynamicUrl = `${host}${endpoint}${navID}`;
107
107
 
108
- return sendRequest(SERVICES.UPDATE_NAVIGATION, { ...data });
108
+ return sendRequest(SERVICES.UPDATE_NAVIGATION, data);
109
109
  };
110
110
 
111
111
  const deleteNavigation = (navID: number) => {
@@ -136,7 +136,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
136
136
  <iframe title="Preview" width={getWidth(resolution)} height="100%" src={urlPreview} loading="lazy" />
137
137
  </S.FrameWrapper>
138
138
  ) : (
139
- <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
139
+ <S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)} className="browser-content">
140
140
  <BrowserContent
141
141
  cloudinaryName={cloudinaryName}
142
142
  theme={theme}
@@ -36,7 +36,7 @@ const Button = ({ children, type, disabled, icon, buttonStyle, onClick, classNam
36
36
  case buttonStyles.TEXT:
37
37
  return (
38
38
  <S.TextButton
39
- data-testid="buttonText"
39
+ data-testid="button-text"
40
40
  className={className}
41
41
  type={type}
42
42
  disabled={disabled}
@@ -49,7 +49,7 @@ const Button = ({ children, type, disabled, icon, buttonStyle, onClick, classNam
49
49
  case buttonStyles.INVERSE:
50
50
  return (
51
51
  <S.LineButton
52
- data-testid="buttonLineInverse"
52
+ data-testid="button-line-inverse"
53
53
  className={className}
54
54
  type={type}
55
55
  disabled={disabled}
@@ -62,7 +62,7 @@ const Button = ({ children, type, disabled, icon, buttonStyle, onClick, classNam
62
62
  default:
63
63
  return (
64
64
  <S.Button
65
- data-testid="buttonDefault"
65
+ data-testid="button-default"
66
66
  className={className}
67
67
  type={type}
68
68
  disabled={disabled}
@@ -12,9 +12,20 @@ const pageEditorID = 0;
12
12
  const Field = (props: IProps) => {
13
13
  const { type, defaults, updateEditorContent, selectedContent, theme } = props;
14
14
  const { isOpen, toggleModal } = useModal();
15
+ const isDefault = selectedContent.setAsDefault;
16
+
17
+ const options = defaults.filter((component: any) => {
18
+ const isCurrentType = component.type === type;
19
+ const isNotSelected = component.id !== selectedContent.id;
20
+ return isCurrentType && isNotSelected;
21
+ });
22
+
23
+ const hasMultipleOptions: boolean | undefined = options && options.length > 0;
24
+ let filteredByDefaultOptions = options;
25
+ if (!isDefault && hasMultipleOptions) {
26
+ filteredByDefaultOptions = options.filter((component: any) => !component.setAsDefault);
27
+ }
15
28
 
16
- const options = defaults.filter((component: any) => component.type === type);
17
- const hasMultipleOptions: boolean | undefined = options && options.length > 1;
18
29
  const optionsType = `${type}s`;
19
30
 
20
31
  const actionMenuOptions = [
@@ -52,7 +63,7 @@ const Field = (props: IProps) => {
52
63
  {hasMultipleOptions && (
53
64
  <SideModal
54
65
  optionsType={optionsType}
55
- whiteList={options}
66
+ whiteList={filteredByDefaultOptions}
56
67
  handleClick={handleReplace}
57
68
  toggleModal={toggleModal}
58
69
  isOpen={isOpen}
@@ -3,12 +3,12 @@ import { trimText } from "@ax/helpers";
3
3
 
4
4
  import * as S from "./style";
5
5
 
6
- const ElementsTooltip = (props: IProps): JSX.Element => {
6
+ const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
7
7
  const { elements, maxChar, defaultElements = 1, colors, rounded = false, elementsPerRow = 1 } = props;
8
8
 
9
9
  if (!elements) return <></>;
10
10
 
11
- const visibleElements = elements?.slice(0, defaultElements);
11
+ const visibleElements = elements.slice(0, defaultElements);
12
12
  const remainingElements = elements.length - defaultElements;
13
13
 
14
14
  const elementsRows: string[][] = [];
@@ -16,30 +16,31 @@ const ElementsTooltip = (props: IProps): JSX.Element => {
16
16
  const row = Math.floor(idx / elementsPerRow);
17
17
  const isNewRow = idx % elementsPerRow === 0;
18
18
  elementsRows[row] = isNewRow ? [element] : [...elementsRows[row], element];
19
- })
19
+ });
20
20
 
21
21
  return (
22
- <S.Wrapper>
22
+ <S.Wrapper data-testid="elements-wrapper">
23
23
  {visibleElements.map((fullElement, idx) => {
24
24
  const element = defaultElements === 1 && maxChar ? trimText(fullElement, maxChar) : fullElement;
25
25
  const color = colors && colors[element] ? colors[element] : undefined;
26
+
26
27
  return (
27
- <S.Element key={idx} color={color} rounded={rounded}>
28
+ <S.Element data-testid="element" key={idx} color={color} rounded={rounded}>
28
29
  {element}
29
30
  </S.Element>
30
31
  );
31
32
  })}
32
33
  {remainingElements > 0 && (
33
- <S.Element rounded={rounded}>
34
+ <S.Element data-testid="remaining-element" rounded={rounded}>
34
35
  +{remainingElements}
35
36
  <S.Tooltip>
36
37
  {elementsRows.map((row, idx) => {
37
38
  return (
38
- <S.Row key={idx}>
39
+ <S.Row data-testid="row-element" key={idx}>
39
40
  {row.map((element, idx) => {
40
41
  const color = colors && colors[element] ? colors[element] : undefined;
41
42
  return (
42
- <S.Element key={idx} color={color} rounded={rounded}>
43
+ <S.Element data-testid="div-element" key={idx} color={color} rounded={rounded}>
43
44
  {element}
44
45
  </S.Element>
45
46
  );
@@ -54,7 +55,7 @@ const ElementsTooltip = (props: IProps): JSX.Element => {
54
55
  );
55
56
  };
56
57
 
57
- interface IProps {
58
+ export interface IElementsTooltipProps {
58
59
  elements?: string[];
59
60
  defaultElements?: number;
60
61
  maxChar?: number;
@@ -8,8 +8,8 @@ const EmptyState = (props: IEmptyStateProps) => {
8
8
  const { icon, title, message, button, action } = props;
9
9
 
10
10
  return (
11
- <S.Wrapper>
12
- <S.IconWrapper>
11
+ <S.Wrapper data-testid="wrapper">
12
+ <S.IconWrapper data-testid="icon-wrapper">
13
13
  <Icon name={icon || "empty"} size="26" />
14
14
  </S.IconWrapper>
15
15
  <S.Title>{title || "Oh! This Looks so empty"}</S.Title>
@@ -5,7 +5,7 @@ import { getNullValue, getDefaultSchema, getDefaultTemplate } from "@ax/helpers"
5
5
 
6
6
  import { FieldsBehavior, HiddenField } from "@ax/components";
7
7
 
8
- const FieldContainer = (props: IProps) => {
8
+ const FieldContainer = (props: IFieldContainerProps) => {
9
9
  const { selectedContent, updateValue, field, goTo, objKey, lang } = props;
10
10
 
11
11
  const { type, key, title, hideable, slugTo } = field;
@@ -28,9 +28,9 @@ const FieldContainer = (props: IProps) => {
28
28
  };
29
29
 
30
30
  const hasMultipleOptions = field.whiteList && field.whiteList.length > 1;
31
-
32
31
  const nullValue = isContainer ? getNullValue(containerValue, hasMultipleOptions) : null;
33
32
  const hasNullValue = JSON.stringify(containerValue) === JSON.stringify(nullValue);
33
+
34
34
  const getField = () => <FieldsBehavior {...fieldProps} key={key} />;
35
35
 
36
36
  const getDefaultValue = () => {
@@ -56,7 +56,7 @@ const FieldContainer = (props: IProps) => {
56
56
 
57
57
  export default FieldContainer;
58
58
 
59
- interface IProps {
59
+ export interface IFieldContainerProps {
60
60
  key: string;
61
61
  field: any;
62
62
  selectedContent: any;
@@ -84,7 +84,7 @@ const ArrayFieldGroup = (props: IProps): JSX.Element => {
84
84
  );
85
85
  };
86
86
 
87
- interface IProps {
87
+ export interface IProps {
88
88
  value: Record<string, unknown>[];
89
89
  name: string;
90
90
  onChange: (value: Record<string, unknown>[]) => void;
@@ -78,7 +78,7 @@ const AsyncCheckGroup = (props: IAsyncCheckGroup): JSX.Element => {
78
78
  return <S.FieldGroup full={fullHeight}>{checks}</S.FieldGroup>;
79
79
  };
80
80
 
81
- interface IAsyncCheckGroup {
81
+ export interface IAsyncCheckGroup {
82
82
  value: any[] | null;
83
83
  site?: ISite | null;
84
84
  source: string;
@@ -152,7 +152,7 @@ interface ICheck {
152
152
  name: string;
153
153
  title: string;
154
154
  }
155
- interface IAsyncSelectProps {
155
+ export interface IAsyncSelectProps {
156
156
  name: string;
157
157
  value: any;
158
158
  entity?: string;
@@ -24,9 +24,9 @@ const CheckField = ({
24
24
 
25
25
  return (
26
26
  <S.Wrapper>
27
- <S.Label data-testid={"checkFieldLabel"} disabled={disabled}>
27
+ <S.Label data-testid="check-field-label" disabled={disabled}>
28
28
  {icon ? (
29
- <S.IconLabelWrapper data-testid={"checkFieldIconLabel"}>
29
+ <S.IconLabelWrapper data-testid="check-field-icon-label">
30
30
  <S.IconWrapper>
31
31
  <Icon name={icon} />
32
32
  </S.IconWrapper>
@@ -36,7 +36,7 @@ const CheckField = ({
36
36
  title
37
37
  )}
38
38
  <S.Input
39
- data-testid={"checkFieldInput"}
39
+ data-testid="check-field-input"
40
40
  type="checkbox"
41
41
  name={`${name}`}
42
42
  value={value || ""}
@@ -38,7 +38,7 @@ const CheckGroup = (props: ICheckGroupProps): JSX.Element => {
38
38
  const checks = options
39
39
  ? options.map((item: ICheckFieldProps) => (
40
40
  <CheckField
41
- data-testid="CheckGroupCheckfield"
41
+ data-testid="check-group-checkfield"
42
42
  key={item.name}
43
43
  onChange={handleChange}
44
44
  checked={valueArray.includes(item.name)}
@@ -52,7 +52,7 @@ const CheckGroup = (props: ICheckGroupProps): JSX.Element => {
52
52
  ))
53
53
  : "";
54
54
 
55
- return <S.FieldGroup data-testid="CheckGroupFieldgroup">{checks}</S.FieldGroup>;
55
+ return <S.FieldGroup data-testid="check-group-field-group">{checks}</S.FieldGroup>;
56
56
  };
57
57
 
58
58
  interface ICheckGroupProps {
@@ -57,9 +57,9 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
57
57
  let componentID: number = editorID ? editorID : containerOptions.editorID;
58
58
 
59
59
  const containerInfo: any = !isArray && value && isEmptyContainer(value, hasMultipleOptions);
60
- const isEmpty: boolean = containerInfo.isEmpty;
60
+ const isEmpty: boolean = containerInfo?.isEmpty;
61
61
 
62
- const currentComponent: any = containerInfo.containedComponent;
62
+ const currentComponent: any = containerInfo?.containedComponent;
63
63
 
64
64
  if (currentComponent) {
65
65
  containerText = currentComponent.containerText;
@@ -152,17 +152,18 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
152
152
  className={`editorId-${editorID}`}
153
153
  onClick={handleClick}
154
154
  ref={innerRef}
155
+ data-testid="component-container"
155
156
  {...provided?.draggableProps}
156
157
  >
157
- {isArray && provided && arrayLength > 1 && (
158
- <S.HandleWrapper {...provided?.dragHandleProps}>
158
+ {isArray && provided && (
159
+ <S.HandleWrapper {...provided?.dragHandleProps} hidden={arrayLength < 2} data-testid="handle-wrapper">
159
160
  <S.IconHandleWrapper>
160
161
  <Icon name="drag" size="16" />
161
162
  </S.IconHandleWrapper>
162
163
  </S.HandleWrapper>
163
164
  )}
164
165
  {containerInfo && !disabled && (
165
- <S.IconWrapper>
166
+ <S.IconWrapper data-testid="icon-wrapper">
166
167
  <Icon name={containerText} />
167
168
  </S.IconWrapper>
168
169
  )}
@@ -195,7 +196,7 @@ const ComponentContainer = (props: IComponentContainerProps): JSX.Element => {
195
196
  );
196
197
  };
197
198
 
198
- interface IComponentContainerProps {
199
+ export interface IComponentContainerProps {
199
200
  text: string;
200
201
  editorID: number;
201
202
  whiteList: any[] | undefined;
@@ -76,8 +76,8 @@ const ButtonsWrapper = styled.span`
76
76
  margin-left: auto;
77
77
  `;
78
78
 
79
- const HandleWrapper = styled.div`
80
- display: flex;
79
+ const HandleWrapper = styled.div<{ hidden?: boolean }>`
80
+ display: ${(p) => (p.hidden ? "none" : "flex")};
81
81
  align-items: center;
82
82
  `;
83
83
 
@@ -16,7 +16,7 @@ const HeadingField = (props: IHeadingFieldProps): JSX.Element => {
16
16
  <>
17
17
  <TextField {...props} value={contentValue} onChange={handleChange} />
18
18
  {showAdvanced && (
19
- <S.AdvancedWrapper data-testid="textFieldAdvancedWrapper">
19
+ <S.AdvancedWrapper data-testid="text-field-advanced-wrapper">
20
20
  <FieldsBehavior fieldType="Select" options={options} value={value.tag} onChange={handleSelectChange} />
21
21
  </S.AdvancedWrapper>
22
22
  )}
@@ -19,7 +19,7 @@ const HiddenField = ({ title, showField, hasMultipleOptions }: IHiddenFieldProps
19
19
  );
20
20
  };
21
21
 
22
- interface IHiddenFieldProps {
22
+ export interface IHiddenFieldProps {
23
23
  title: string;
24
24
  showField: any;
25
25
  hasMultipleOptions?: boolean;
@@ -65,17 +65,22 @@ const ImageField = (props: IImageFieldProps) => {
65
65
  };
66
66
 
67
67
  const previewHeight = cropPreview ? { height: 190 } : {};
68
-
69
68
  return (
70
69
  <>
71
- <S.FieldWrapper error={error} preview={!!previewSrc} disabled={disabled} onClick={handleClick}>
70
+ <S.FieldWrapper
71
+ data-testid="fieldWrapper"
72
+ error={error}
73
+ preview={!!previewSrc}
74
+ disabled={disabled}
75
+ onClick={handleClick}
76
+ >
72
77
  <S.IconWrapper>
73
78
  <Icon name="image" size="18" />
74
79
  </S.IconWrapper>
75
80
  <S.Text>Add image</S.Text>
76
81
  </S.FieldWrapper>
77
82
  {value && Object.keys(value).length > 1 && typeof value !== "string" && (
78
- <S.ImageDataWrapper>
83
+ <S.ImageDataWrapper data-testid="imageDataWrapper">
79
84
  <S.FileName>{value.name}</S.FileName>
80
85
  <S.ImageData>
81
86
  Uploaded: {!!value.published && getFormattedDateWithTimezone(value.published, "d MMM Y")}
@@ -84,7 +89,7 @@ const ImageField = (props: IImageFieldProps) => {
84
89
  </S.ImageData>
85
90
  </S.ImageDataWrapper>
86
91
  )}
87
- <S.Preview preview={!!previewSrc}>
92
+ <S.Preview preview={!!previewSrc} data-testid="previewDiv">
88
93
  {previewSrc && <Image url={previewSrc} width={320} {...previewHeight} />}
89
94
  <S.PreviewActions>
90
95
  <IconAction icon="change" onClick={handleChange} />
@@ -98,7 +103,7 @@ const ImageField = (props: IImageFieldProps) => {
98
103
  );
99
104
  };
100
105
 
101
- interface IImageFieldProps {
106
+ export interface IImageFieldProps {
102
107
  value: IImage | null | string;
103
108
  error?: boolean;
104
109
  onChange: (value: any) => void;
@@ -6,7 +6,7 @@ import CheckGroup from "@ax/components/Fields/CheckGroup";
6
6
 
7
7
  import * as S from "./style";
8
8
 
9
- const MultiCheckSelect = (props: IProps) => {
9
+ const MultiCheckSelect = (props: IMultiCheckSelectProps) => {
10
10
  const { placeholder, source, value, onChange, site, className, mandatory, options, selectAllOption, floating } =
11
11
  props;
12
12
 
@@ -35,7 +35,7 @@ const MultiCheckSelect = (props: IProps) => {
35
35
  );
36
36
  };
37
37
 
38
- interface IProps {
38
+ export interface IMultiCheckSelectProps {
39
39
  value: (string | number)[];
40
40
  onChange: (value: string | (string | number)[]) => void;
41
41
  site?: ISite | null;
@@ -43,7 +43,7 @@ interface IProps {
43
43
  source?: string;
44
44
  className?: string;
45
45
  mandatory?: boolean;
46
- options?: { name: string, value: string, title: string }[];
46
+ options?: { name: string; value: string; title: string }[];
47
47
  selectAllOption?: string;
48
48
  floating?: boolean;
49
49
  }
@@ -37,6 +37,7 @@ const NumberField = (props: INumberFieldProps): JSX.Element => {
37
37
 
38
38
  setInputValue(updatedValue.toString());
39
39
  onChange(updatedValue);
40
+ handleValidation && handleValidation(updatedValue.toString(), validators);
40
41
  };
41
42
 
42
43
  let validators: Record<string, unknown> = maxValue ? { maxValue } : {};
@@ -81,7 +82,7 @@ const NumberField = (props: INumberFieldProps): JSX.Element => {
81
82
  );
82
83
  };
83
84
 
84
- interface INumberFieldProps {
85
+ export interface INumberFieldProps {
85
86
  value?: number;
86
87
  onChange: (value: number) => void;
87
88
  name?: string;
@@ -46,13 +46,11 @@ const Item = (props: IProps) => {
46
46
 
47
47
  return (
48
48
  <S.Item ref={innerRef} data-testid="reference-field-item" {...provided?.draggableProps}>
49
- {listLength > 1 && (
50
- <S.HandleWrapper {...provided?.dragHandleProps}>
51
- <S.IconHandleWrapper>
52
- <Icon name="drag" size="16" />
53
- </S.IconHandleWrapper>
54
- </S.HandleWrapper>
55
- )}
49
+ <S.HandleWrapper {...provided?.dragHandleProps} hidden={listLength < 2} data-testid="handle-wrapper">
50
+ <S.IconHandleWrapper>
51
+ <Icon name="drag" size="16" />
52
+ </S.IconHandleWrapper>
53
+ </S.HandleWrapper>
56
54
  <S.TextWrapper>
57
55
  <S.Header>
58
56
  <S.Type>{source?.title.toUpperCase()}</S.Type>
@@ -108,8 +108,8 @@ const ButtonsWrapper = styled.span`
108
108
  right: ${(p) => p.theme.spacing.xs};
109
109
  `;
110
110
 
111
- const HandleWrapper = styled.div`
112
- display: flex;
111
+ const HandleWrapper = styled.div<{ hidden?: boolean }>`
112
+ display: ${(p) => (p.hidden ? "none" : "flex")};
113
113
  align-items: center;
114
114
  padding-right: ${(p) => p.theme.spacing.xxs};
115
115
  `;
@@ -98,7 +98,7 @@ const ItemList = (props: IProps) => {
98
98
  <DragDropContext onDragEnd={onDragEnd}>
99
99
  <Droppable droppableId="referenceList">
100
100
  {(provided) => (
101
- <div ref={provided.innerRef} {...provided.droppableProps}>
101
+ <div ref={provided.innerRef} {...provided.droppableProps} data-testid="droppable">
102
102
  <ComponentList components={selectedItems} />
103
103
  {provided.placeholder}
104
104
  </div>
@@ -10,7 +10,7 @@ import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
10
10
  import * as S from "./style";
11
11
 
12
12
  const RichText = (props: IRichTextProps): JSX.Element => {
13
- const { value, error, placeholder, onChange, disabled, editorID, handleValidation, html = false } = props;
13
+ const { value, error, placeholder, onChange, disabled, editorID, handleValidation, html = false, delayed } = props;
14
14
 
15
15
  const rawData = html ? htmlToDraft(value || "") : markdownToDraft(value);
16
16
  const { contentBlocks, entityMap } = rawData;
@@ -28,15 +28,18 @@ const RichText = (props: IRichTextProps): JSX.Element => {
28
28
  }, [editorID]);
29
29
 
30
30
  useEffect(() => {
31
- timeOutRef.current && clearTimeout(timeOutRef.current);
32
- timeOutRef.current = setTimeout(() => {
33
- delayedChange();
34
- }, 300);
31
+ if (delayed !== false) {
32
+ timeOutRef.current && clearTimeout(timeOutRef.current);
33
+ timeOutRef.current = setTimeout(() => {
34
+ delayedChange();
35
+ }, 300);
36
+ }
35
37
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
38
  }, [editorState]);
37
39
 
38
40
  const handleOnChange = (editorState: EditorState) => {
39
41
  setEditorState(editorState);
42
+ delayed === false && delayedChange();
40
43
  };
41
44
 
42
45
  const delayedChange = () => {
@@ -106,7 +109,7 @@ const RichText = (props: IRichTextProps): JSX.Element => {
106
109
  );
107
110
  };
108
111
 
109
- interface IRichTextProps {
112
+ export interface IRichTextProps {
110
113
  editorID: number;
111
114
  value: string;
112
115
  error?: boolean;
@@ -115,6 +118,7 @@ interface IRichTextProps {
115
118
  onChange: (value: string) => void;
116
119
  handleValidation?: (value: string) => void;
117
120
  html: boolean;
121
+ delayed?: boolean;
118
122
  }
119
123
 
120
124
  export default memo(RichText);
@@ -47,7 +47,7 @@ const Select = (props: ISelectProps): JSX.Element => {
47
47
  const searchable = type === "inline" ? false : true;
48
48
 
49
49
  return (
50
- <div data-testid="selectComponent">
50
+ <div data-testid="select-component">
51
51
  <S.StyledSelect
52
52
  name={name}
53
53
  value={getObjectValue(value, optionValues)}
@@ -69,7 +69,7 @@ const Select = (props: ISelectProps): JSX.Element => {
69
69
  );
70
70
  };
71
71
 
72
- interface ISelectProps {
72
+ export interface ISelectProps {
73
73
  name: string;
74
74
  value: string;
75
75
  options: IOptionProps[];
@@ -41,7 +41,7 @@ const SliderField = (props: ITextFieldProps): JSX.Element => {
41
41
  );
42
42
  };
43
43
 
44
- interface ITextFieldProps {
44
+ export interface ITextFieldProps {
45
45
  title: string;
46
46
  value: number;
47
47
  defaultValue?: number;