@griddo/ax 11.7.10 → 11.7.12-rc.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 (26) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Fields/DateField/DateField.test.tsx +1 -3
  3. package/src/__tests__/components/FloatingMenu/FloatingMenu.test.tsx +8 -8
  4. package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +41 -6
  5. package/src/components/Fields/DateField/index.tsx +0 -6
  6. package/src/components/Fields/IntegrationsField/SideModal/index.tsx +1 -1
  7. package/src/components/Fields/MultiCheckSelect/index.tsx +14 -2
  8. package/src/components/Fields/ReferenceField/index.tsx +0 -1
  9. package/src/components/Fields/Wysiwyg/style.tsx +6 -0
  10. package/src/components/FloatingMenu/index.tsx +17 -16
  11. package/src/components/MainWrapper/AppBar/atoms.tsx +2 -2
  12. package/src/components/MainWrapper/AppBar/index.tsx +6 -2
  13. package/src/components/TableFilters/LiveFilter/index.tsx +3 -4
  14. package/src/containers/Navigation/Defaults/actions.tsx +7 -2
  15. package/src/containers/StructuredData/actions.tsx +1 -0
  16. package/src/hooks/modals.tsx +1 -1
  17. package/src/modules/App/Routing/NavMenu/index.tsx +31 -6
  18. package/src/modules/Content/BulkHeader/TableHeader/index.tsx +5 -1
  19. package/src/modules/Forms/FormEditor/Editor/SideModal/SideModalOption/index.tsx +1 -1
  20. package/src/modules/Forms/FormEditor/Editor/SideModal/SideModalOption/style.tsx +6 -3
  21. package/src/modules/GlobalEditor/index.tsx +5 -4
  22. package/src/modules/PageEditor/index.tsx +6 -4
  23. package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +1 -1
  24. package/src/modules/Sites/SitesList/hooks.tsx +4 -1
  25. package/src/modules/StructuredData/Form/index.tsx +1 -1
  26. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +5 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "11.7.10",
4
+ "version": "11.7.12-rc.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Diego M. Béjar <diego.bejar@secuoyas.com>",
@@ -223,5 +223,5 @@
223
223
  "publishConfig": {
224
224
  "access": "public"
225
225
  },
226
- "gitHead": "4ce667004353325a0a481f74cab77e75ee55cd7b"
226
+ "gitHead": "c7e40c899abb683a6c53cbe36f1bd19135c9670e"
227
227
  }
@@ -63,7 +63,6 @@ describe("DateField component rendering", () => {
63
63
  defaultProps.value = "01/01/2022 - 10/01/2022";
64
64
  defaultProps.mandatory = false;
65
65
  const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: any) => void>;
66
- const handleValidationMock = defaultProps.handleValidation as jest.MockedFunction<(value: string) => void>;
67
66
 
68
67
  render(
69
68
  <ThemeProvider theme={parseTheme(globalTheme)}>
@@ -72,7 +71,6 @@ describe("DateField component rendering", () => {
72
71
  );
73
72
 
74
73
  expect(screen.getByTestId("dateWrapper")).toBeTruthy();
75
- expect(onChangeMock).toBeCalledWith("2022/01/01 - 2022/01/10");
76
- expect(handleValidationMock).toBeCalled();
74
+ expect(screen.getByDisplayValue("01/01/2022 - 10/01/2022")).toBeTruthy();
77
75
  });
78
76
  });
@@ -30,7 +30,7 @@ describe("FloatingMenu component rendering", () => {
30
30
  );
31
31
 
32
32
  const defaultProps: IFloatingProps = {
33
- children: "<div>hola</div>",
33
+ children: <div>hola</div>,
34
34
  Button: buttonContent,
35
35
  isInAppBar: true,
36
36
  position: "left",
@@ -58,7 +58,7 @@ describe("FloatingMenu component rendering", () => {
58
58
  );
59
59
 
60
60
  const defaultProps: IFloatingProps = {
61
- children: "<div>hola</div>",
61
+ children: <div>hola</div>,
62
62
  Button: buttonContent,
63
63
  isInAppBar: true,
64
64
  isCheckGroup: true,
@@ -138,7 +138,7 @@ describe("FloatingMenu component rendering", () => {
138
138
  );
139
139
 
140
140
  const defaultProps: IFloatingProps = {
141
- children: "<div>hola</div>",
141
+ children: <div>hola</div>,
142
142
  Button: buttonContent,
143
143
  isInAppBar: true,
144
144
  isCheckGroup: true,
@@ -228,7 +228,7 @@ describe("FloatingMenu component rendering", () => {
228
228
  const buttonContent = () => <input type="checkbox" data-testid="menu-children" />;
229
229
 
230
230
  const defaultProps: IFloatingProps = {
231
- children: "<div>hola</div>",
231
+ children: <div>hola</div>,
232
232
  Button: buttonContent,
233
233
  isInAppBar: true,
234
234
  isCheckGroup: true,
@@ -343,7 +343,7 @@ describe("FloatingMenu component rendering", () => {
343
343
  const buttonContent = () => <span data-testid="menu-children">texto</span>;
344
344
 
345
345
  const defaultProps: IFloatingProps = {
346
- children: "<div>hola</div>",
346
+ children: <div>hola</div>,
347
347
  Button: buttonContent,
348
348
  isInAppBar: true,
349
349
  isCheckGroup: false,
@@ -458,7 +458,7 @@ describe("FloatingMenu component rendering", () => {
458
458
  const buttonContent = () => <span data-testid="menu-children">texto</span>;
459
459
 
460
460
  const defaultProps: IFloatingProps = {
461
- children: "<div>hola</div>",
461
+ children: <div>hola</div>,
462
462
  Button: buttonContent,
463
463
  isInAppBar: true,
464
464
  isCheckGroup: false,
@@ -574,7 +574,7 @@ describe("FloatingMenu component rendering", () => {
574
574
  const buttonContent = () => <span data-testid="menu-children">texto</span>;
575
575
 
576
576
  const defaultProps: IFloatingProps = {
577
- children: "<div>hola</div>",
577
+ children: <div>hola</div>,
578
578
  Button: buttonContent,
579
579
  isInAppBar: true,
580
580
  isCheckGroup: false,
@@ -644,7 +644,7 @@ describe("FloatingMenu component rendering", () => {
644
644
  const buttonContent = () => <span data-testid="menu-children">texto</span>;
645
645
 
646
646
  const defaultProps: IFloatingProps = {
647
- children: "<div>hola</div>",
647
+ children: <div>hola</div>,
648
648
  Button: buttonContent,
649
649
  isInAppBar: true,
650
650
  isCheckGroup: false,
@@ -17,7 +17,6 @@ const defaultProps = mock<ILiveFilterProps>();
17
17
 
18
18
  describe("LiveFilter component rendering", () => {
19
19
  it("should render live filter", async () => {
20
- defaultProps.hasBasicStatus = false;
21
20
  defaultProps.value = [{ value: "all", label: "All" }];
22
21
  const filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
23
22
 
@@ -53,7 +52,6 @@ describe("LiveFilter component rendering", () => {
53
52
  });
54
53
 
55
54
  it("should render the component with no options", async () => {
56
- defaultProps.hasBasicStatus = false;
57
55
  defaultProps.value = [{ value: "all", label: "All" }];
58
56
  const filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
59
57
 
@@ -91,7 +89,6 @@ describe("LiveFilter component rendering", () => {
91
89
 
92
90
  describe("LiveFilter events", () => {
93
91
  it("should render check group on click", async () => {
94
- defaultProps.hasBasicStatus = false;
95
92
  defaultProps.value = [{ value: "all", label: "All" }];
96
93
  const filterItemsMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
97
94
 
@@ -132,7 +129,6 @@ describe("LiveFilter events", () => {
132
129
  });
133
130
 
134
131
  it("should check option on click", async () => {
135
- defaultProps.hasBasicStatus = false;
136
132
  defaultProps.value = [{ value: "all", label: "All" }];
137
133
  const filterItemsMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
138
134
 
@@ -176,7 +172,6 @@ describe("LiveFilter events", () => {
176
172
  });
177
173
 
178
174
  it("should uncheck selected option on click and select 'All' option", async () => {
179
- defaultProps.hasBasicStatus = false;
180
175
  defaultProps.value = [{ value: "all", label: "All" }];
181
176
  const filterItemsMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
182
177
 
@@ -225,7 +220,6 @@ describe("LiveFilter events", () => {
225
220
  });
226
221
 
227
222
  it("should call filterItems action on change", async () => {
228
- defaultProps.hasBasicStatus = false;
229
223
  defaultProps.value = [{ value: "all", label: "All" }];
230
224
  const filterItemsMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
231
225
 
@@ -264,4 +258,45 @@ describe("LiveFilter events", () => {
264
258
  expect(filterItemsMock).toHaveBeenCalledTimes(1);
265
259
  expect(filterItemsMock).toBeCalledWith("liveStatus", [{ label: "Offline", value: "offline" }]);
266
260
  });
261
+
262
+ it("should render live filter with filter options", async () => {
263
+ defaultProps.value = [{ value: "all", label: "All" }];
264
+ const filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
265
+ defaultProps.filterOptions = ["offline", "active", "scheduled"];
266
+ defaultProps.filterItems = filterItems;
267
+ const data = {
268
+ data: [
269
+ { id: 1, title: "Offline", status: "offline" },
270
+ { id: 2, title: "Publication pending", status: "upload-pending" },
271
+ { id: 3, title: "Live", status: "active" },
272
+ { id: 4, title: "Offline pending", status: "offline-pending" },
273
+ { id: 5, title: "Live & modified", status: "modified" },
274
+ { id: 6, title: "Publication scheduled", status: "scheduled" },
275
+ ],
276
+ status: 200,
277
+ statusText: "Ok",
278
+ headers: {},
279
+ config: {},
280
+ };
281
+
282
+ mockedAxios.mockResolvedValue(data);
283
+
284
+ await act(async () => {
285
+ render(
286
+ <ThemeProvider theme={parseTheme(globalTheme)}>
287
+ <LiveFilter {...defaultProps} />
288
+ </ThemeProvider>
289
+ );
290
+ });
291
+
292
+ const liveFilterButton = screen.getByTestId("floating-menu-button");
293
+ expect(liveFilterButton).toBeTruthy();
294
+ fireEvent.click(liveFilterButton);
295
+ const floatingMenu = screen.getByTestId("floating-menu");
296
+ expect(floatingMenu).toBeTruthy();
297
+ const checkGroupFieldGroup = screen.getByTestId("check-group-field-group");
298
+ expect(checkGroupFieldGroup).toBeTruthy();
299
+ const checkFieldLabels = screen.getAllByTestId("check-field-label");
300
+ expect(checkFieldLabels).toHaveLength(4);
301
+ });
267
302
  });
@@ -61,12 +61,6 @@ const DateField = (props: IDateFieldProps): JSX.Element => {
61
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
62
62
  }, [editorID]);
63
63
 
64
- useEffect(() => {
65
- const { start, end } = initialDate;
66
- handleOnChange([start, end]);
67
- // eslint-disable-next-line react-hooks/exhaustive-deps
68
- }, []);
69
-
70
64
  registerLocale("en", en);
71
65
 
72
66
  const handleOnChange = (dates: any) => {
@@ -12,7 +12,7 @@ const SideModal = (props: ISideModalProps): JSX.Element | null => {
12
12
  const { integrations, isOpen, toggleModal, handleClick } = props;
13
13
 
14
14
  const node = useRef<HTMLDivElement>(null);
15
- const handleClickOutside = (e: React.MouseEvent) => {
15
+ const handleClickOutside = (e: MouseEvent) => {
16
16
  if (node.current?.contains(e.target as Node)) {
17
17
  return;
18
18
  }
@@ -1,8 +1,9 @@
1
- import React, { useState, memo } from "react";
1
+ import React, { useState, memo, useRef } from "react";
2
2
 
3
3
  import { ILanguage, ISite } from "@ax/types";
4
4
  import AsyncCheckGroup from "@ax/components/Fields/AsyncCheckGroup";
5
5
  import CheckGroup from "@ax/components/Fields/CheckGroup";
6
+ import { useHandleClickOutside } from "@ax/hooks";
6
7
 
7
8
  import * as S from "./style";
8
9
 
@@ -26,13 +27,24 @@ const MultiCheckSelect = (props: IMultiCheckSelectProps) => {
26
27
  } = props;
27
28
 
28
29
  const [isOpen, setIsOpen] = useState(false);
30
+ const wrapperRef = useRef<HTMLDivElement | null>(null);
29
31
 
30
32
  const handleClick = () => setIsOpen(!isOpen);
31
33
 
34
+ const handleClickOutside = (e: MouseEvent) => {
35
+ if (wrapperRef.current?.contains(e.target as HTMLElement)) {
36
+ return;
37
+ }
38
+
39
+ setIsOpen(false);
40
+ };
41
+
42
+ useHandleClickOutside(isOpen, handleClickOutside);
43
+
32
44
  const Asterisk = () => (mandatory ? <S.Asterisk>*</S.Asterisk> : null);
33
45
 
34
46
  return (
35
- <S.Wrapper className={className} data-testid="multi-check-select-wrapper">
47
+ <S.Wrapper ref={wrapperRef} className={className} data-testid="multi-check-select-wrapper">
36
48
  <S.Field isOpen={isOpen} onClick={handleClick} disabled={disabled} data-testid="field">
37
49
  {placeholder} <Asterisk />
38
50
  </S.Field>
@@ -72,7 +72,6 @@ const ReferenceField = (props: IReferenceFieldProps) => {
72
72
  }
73
73
  : {
74
74
  mode,
75
- sources,
76
75
  fixed,
77
76
  fullRelations,
78
77
  };
@@ -76,6 +76,8 @@ export const EditorWrapper = styled.div<{ error: boolean | undefined; disabled?:
76
76
  border-radius: 0 0 4px 4px;
77
77
  }
78
78
  .fr-wrapper {
79
+ max-height: 50vh;
80
+ overflow: auto;
79
81
  border-left: 1px solid
80
82
  ${(p) =>
81
83
  p.error === true
@@ -91,6 +93,7 @@ export const EditorWrapper = styled.div<{ error: boolean | undefined; disabled?:
91
93
  ? p.theme.color.interactiveDisabled
92
94
  : p.theme.color.uiLine};
93
95
  }
96
+
94
97
  .fr-disabled {
95
98
  color: ${(p) => p.theme.color.interactiveDisabled};
96
99
  }
@@ -122,6 +125,9 @@ export const EditorWrapper = styled.div<{ error: boolean | undefined; disabled?:
122
125
  }
123
126
  }
124
127
  }
128
+ .fr-fullscreen .fr-wrapper {
129
+ max-height: none !important;
130
+ }
125
131
  .fr-inline {
126
132
  .fr-wrapper {
127
133
  background: ${(p) => p.theme.color.uiBackground02};
@@ -15,27 +15,28 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
15
15
  reactiveToHover,
16
16
  offset,
17
17
  } = props;
18
- const wrapper = useRef<any>(null);
19
- const button = useRef<any>(null);
20
- const menuOptions = useRef<any>(null);
18
+ const wrapperRef = useRef<HTMLDivElement | null>(null);
19
+ const buttonRef = useRef<HTMLDivElement | null>(null);
20
+ const menuOptionsRef = useRef<HTMLDivElement | null>(null);
21
21
  const [isOpen, setOpen] = useState(false);
22
22
 
23
23
  useEffect(() => {
24
- if (isOpen && menuOptions?.current) {
25
- const bounding = menuOptions.current.children[0].getBoundingClientRect();
26
- const boundingChild = menuOptions.current.children[0] && menuOptions.current.children[0].getBoundingClientRect();
24
+ if (isOpen && menuOptionsRef?.current) {
25
+ const bounding = menuOptionsRef.current.children[0].getBoundingClientRect();
26
+ const boundingChild =
27
+ menuOptionsRef.current.children[0] && menuOptionsRef.current.children[0].getBoundingClientRect();
27
28
  if (bounding.bottom > (window.innerHeight || document.documentElement.clientHeight)) {
28
- menuOptions.current.scrollIntoView({ block: "end", behavior: "smooth" });
29
+ menuOptionsRef.current.scrollIntoView({ block: "end", behavior: "smooth" });
29
30
  }
30
31
  if (boundingChild && boundingChild.right > window.innerWidth) {
31
- menuOptions.current.style.right = "130px";
32
+ menuOptionsRef.current.style.right = "130px";
32
33
  }
33
34
  }
34
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
35
36
  }, [isOpen]);
36
37
 
37
- const handleClickOutside = (e: any) => {
38
- if (wrapper.current.contains(e.target)) {
38
+ const handleClickOutside = (e: MouseEvent) => {
39
+ if (wrapperRef.current?.contains(e.target as HTMLElement)) {
39
40
  return;
40
41
  }
41
42
 
@@ -50,8 +51,8 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
50
51
 
51
52
  const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
52
53
  e.stopPropagation();
53
- const buttonWasClicked = button.current.contains(e.target);
54
- const optionWasSelected = isOpen && menuOptions.current.contains(e.target);
54
+ const buttonWasClicked = buttonRef.current?.contains(e.target as HTMLElement);
55
+ const optionWasSelected = isOpen && menuOptionsRef.current?.contains(e.target as HTMLElement);
55
56
 
56
57
  if (buttonWasClicked) {
57
58
  setOpen(!isOpen);
@@ -71,20 +72,20 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
71
72
 
72
73
  return (
73
74
  <S.Wrapper
74
- ref={wrapper}
75
+ ref={wrapperRef}
75
76
  onClick={handleClick}
76
77
  onMouseEnter={handleMouseEnter}
77
78
  onMouseLeave={handleMouseLeave}
78
79
  data-testid="floating-menu"
79
80
  >
80
- <S.ButtonWrapper ref={button} data-testid="floating-menu-button">
81
+ <S.ButtonWrapper ref={buttonRef} data-testid="floating-menu-button">
81
82
  <Button />
82
83
  </S.ButtonWrapper>
83
84
 
84
85
  {isOpen && (
85
86
  <S.MenuWrapper
86
87
  isInAppBar={isInAppBar}
87
- ref={menuOptions}
88
+ ref={menuOptionsRef}
88
89
  position={position}
89
90
  offset={offset}
90
91
  data-testid="floating-menu-wrapper"
@@ -98,7 +99,7 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
98
99
 
99
100
  export interface IFloatingProps {
100
101
  children: JSX.Element | (JSX.Element | boolean | JSX.Element[])[] | boolean;
101
- Button: any;
102
+ Button: (props?: any) => React.JSX.Element;
102
103
  isInAppBar?: boolean;
103
104
  position?: string;
104
105
  closeOnSelect?: boolean;
@@ -34,7 +34,7 @@ const ActionMenu = (props: any) => {
34
34
  <S.ActionMenu>
35
35
  <S.ActionMenuTitle> More actions </S.ActionMenuTitle>
36
36
  <ActionMenuBtn menu={menu} />
37
- {menu && menu.options.map((item: any, i: number) => item && ActionMenuItem(item))}
37
+ {menu && menu.options.map((item: any) => item && ActionMenuItem(item))}
38
38
  </S.ActionMenu>
39
39
  );
40
40
  };
@@ -51,7 +51,7 @@ const ActionSimpleMenu = (props: any) => {
51
51
  menu &&
52
52
  menu.options.length > 0 && (
53
53
  <S.ActionMenu data-testid="action-simple-menu">
54
- {menu.options.map((item: any, i: number) => ActionMenuItem(item, true))}
54
+ {menu.options.map((item: any) => ActionMenuItem(item, true))}
55
55
  </S.ActionMenu>
56
56
  )
57
57
  );
@@ -87,7 +87,7 @@ const AppBar = (props: IProps): JSX.Element => {
87
87
  };
88
88
 
89
89
  const LanguageBtn = () =>
90
- language && (
90
+ language ? (
91
91
  <>
92
92
  <S.FlagWrapper data-testid="language-menu-btn">
93
93
  <Flag name={language.locale} size="24" />
@@ -95,6 +95,8 @@ const AppBar = (props: IProps): JSX.Element => {
95
95
  <S.LanguageTextWrapper data-testid="language-locale-label">{language.locale}</S.LanguageTextWrapper>
96
96
  <DownArrowButton />
97
97
  </>
98
+ ) : (
99
+ <></>
98
100
  );
99
101
 
100
102
  const ErrorCenterBtn = () => (
@@ -106,10 +108,12 @@ const AppBar = (props: IProps): JSX.Element => {
106
108
  );
107
109
 
108
110
  const StatusBtn = () =>
109
- pageStatus && (
111
+ pageStatus ? (
110
112
  <S.StatusBtn data-testid="status-button">
111
113
  <Icon name={pageStatus} size="24" />
112
114
  </S.StatusBtn>
115
+ ) : (
116
+ <></>
113
117
  );
114
118
 
115
119
  const statusMenu = {
@@ -8,7 +8,7 @@ import { IFilterValue, IPageLiveStatus, IQueryValue } from "@ax/types";
8
8
  import * as S from "./style";
9
9
 
10
10
  const LiveFilter = (props: ILiveFilterProps): JSX.Element => {
11
- const { filterItems, value, hasBasicStatus } = props;
11
+ const { filterItems, value, filterOptions } = props;
12
12
 
13
13
  const filters: IFilterValue[] = [
14
14
  {
@@ -24,7 +24,6 @@ const LiveFilter = (props: ILiveFilterProps): JSX.Element => {
24
24
  const parsedValue = Array.isArray(value) && value.length ? value.map((value) => value.value) : initialState;
25
25
  const [selectedValue, setSelectedValue] = useState(parsedValue);
26
26
  const [options, setOptions] = useState(filters);
27
- const basicStatus = ["offline", "active", "scheduled"];
28
27
 
29
28
  useEffect(() => {
30
29
  const parsedValue = Array.isArray(value) && value.length ? value.map((value) => value.value) : initialState;
@@ -55,7 +54,7 @@ const LiveFilter = (props: ILiveFilterProps): JSX.Element => {
55
54
  title: item.title,
56
55
  icon: item.status,
57
56
  };
58
- if ((hasBasicStatus && basicStatus.includes(newFilter.value)) || !hasBasicStatus) {
57
+ if ((filterOptions && filterOptions.includes(newFilter.value)) || !filterOptions) {
59
58
  filters.push(newFilter);
60
59
  }
61
60
  });
@@ -112,8 +111,8 @@ const LiveFilter = (props: ILiveFilterProps): JSX.Element => {
112
111
  export interface ILiveFilterProps {
113
112
  filterItems(pointer: string, filter: IQueryValue[]): void;
114
113
  value: IQueryValue[];
115
- hasBasicStatus?: boolean;
116
114
  isSite?: boolean;
115
+ filterOptions?: string[];
117
116
  }
118
117
 
119
118
  export default LiveFilter;
@@ -531,7 +531,7 @@ const getUpdatedComponents = (editorContent: any, element: any, key: string) =>
531
531
  const mapValues = (item: any) => {
532
532
  if (item.editorID !== undefined && item.editorID === editorID) {
533
533
  if (isCollectionItem) {
534
- item[key] = updateCollection(type, item[key]);
534
+ item[key] = updateCollection(type, item[key] || []);
535
535
  } else {
536
536
  addElement(type);
537
537
  }
@@ -553,7 +553,9 @@ const getUpdatedComponents = (editorContent: any, element: any, key: string) =>
553
553
  function addModule(
554
554
  type: string,
555
555
  key: string,
556
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
556
557
  selectedID: number,
558
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
557
559
  isComponentModule?: boolean
558
560
  ): (dispatch: Dispatch, getState: () => IRootState) => void {
559
561
  return (dispatch, getState) => {
@@ -760,6 +762,10 @@ function replaceElementsInCollection(
760
762
  const updatedContent = replaceElements(selectedContent[key], newValue);
761
763
 
762
764
  updateEditorContent(selectedContent.editorID, key, updatedContent)(dispatch, getState);
765
+
766
+ const { editorContent } = getStateValues(getState);
767
+ if (!editorContent) return;
768
+ generateContent(editorContent)(dispatch, getState);
763
769
  };
764
770
  }
765
771
 
@@ -778,7 +784,6 @@ function generateContent(editorContent: INavigation): (dispatch: Dispatch, getSt
778
784
  dispatch(updateBreadcrumb(selectedEditorID || 0));
779
785
  dispatch(setSelectedDefaultContent(selectedContent));
780
786
  dispatch(setSelectedDefaultParentContent(selectedParent));
781
- dispatch(setTab("content"));
782
787
  dispatch(setCurrentNavigationLanguages(editorContent.navigationLanguages));
783
788
  dispatch(setIsLoading(false));
784
789
  };
@@ -634,6 +634,7 @@ function resetCurrentData(): (dispatch: Dispatch) => Promise<void> {
634
634
  dispatch(setCurrentDataID(null));
635
635
  dispatch(setCurrentDataContent([]));
636
636
  dispatch(setSchema({}));
637
+ dispatch(setFilter("all-pages"));
637
638
  //dispatch(setCurrentSearch(""));
638
639
  } catch (e) {
639
640
  console.log("Error", e);
@@ -18,7 +18,7 @@ const useModal = (initialState?: boolean, bodyBlock = true) => {
18
18
  };
19
19
  };
20
20
 
21
- const useHandleClickOutside = (isOpen: boolean, handleClickOutside: any) => {
21
+ const useHandleClickOutside = (isOpen: boolean, handleClickOutside: (e: MouseEvent) => void) => {
22
22
  useEffect(() => {
23
23
  if (isOpen) {
24
24
  document.addEventListener("mousedown", handleClickOutside);
@@ -5,7 +5,7 @@ import { version } from "./../../../../../package.json";
5
5
 
6
6
  import { IRouter, multisite, site } from "@ax/routes";
7
7
 
8
- import { ILanguage, IRootState, ISite } from "@ax/types";
8
+ import { ILanguage, IRootState, ISite, IStructuredData } from "@ax/types";
9
9
  import { IGlobalSettings } from "@ax/containers/App/reducer";
10
10
  import { appActions } from "@ax/containers/App";
11
11
  import { Icon, Tag } from "@ax/components";
@@ -17,7 +17,17 @@ import { NavProvider } from "./context";
17
17
  import * as S from "./style";
18
18
 
19
19
  const NavMenu = (props: IProps) => {
20
- const { location, setHistoryPush, logout, currentSiteInfo, siteLanguages, lang, categories, globalSettings } = props;
20
+ const {
21
+ location,
22
+ setHistoryPush,
23
+ logout,
24
+ currentSiteInfo,
25
+ siteLanguages,
26
+ lang,
27
+ categories,
28
+ globalSettings,
29
+ structuredData,
30
+ } = props;
21
31
 
22
32
  const { useForms } = globalSettings;
23
33
 
@@ -129,9 +139,16 @@ const NavMenu = (props: IProps) => {
129
139
  const isSitePublished = isSite && currentSiteInfo && currentSiteInfo.isPublished;
130
140
 
131
141
  if (isSite) {
132
- const isSiteCategoriesAvailable = categories.site.length;
142
+ const isSiteCategoriesAvailable = !!categories.site.length;
133
143
  const siteCategoriesRouteIdx = config.routes.findIndex((route: IRouter) => route.path === "/sites/categories");
134
144
  config.routes[siteCategoriesRouteIdx].showInNav = isSiteCategoriesAvailable;
145
+ } else {
146
+ const isGlobalCategoriesAvailable = !!categories.global.length;
147
+ const isGlobalDataAvailable = !!structuredData.global.length;
148
+ const globalCategoriesRouteIdx = config.routes.findIndex((route: IRouter) => route.path === "/categories");
149
+ const globalDataRouteIdx = config.routes.findIndex((route: IRouter) => route.path === "/data");
150
+ config.routes[globalCategoriesRouteIdx].showInNav = isGlobalCategoriesAvailable;
151
+ config.routes[globalDataRouteIdx].showInNav = isGlobalDataAvailable;
135
152
  }
136
153
 
137
154
  return (
@@ -197,18 +214,25 @@ const NavMenu = (props: IProps) => {
197
214
  };
198
215
 
199
216
  interface IDispatchProps {
200
- logout(): any;
217
+ logout(): void;
201
218
  setHistoryPush(path: string): void;
202
219
  }
203
220
 
204
221
  interface IConfig {
205
222
  routes: IRouter[];
206
223
  type: string;
207
- logo: any;
224
+ logo: JSX.Element;
208
225
  }
209
226
 
210
227
  interface INavMenuProps {
211
- categories: any;
228
+ categories: {
229
+ global: IStructuredData[];
230
+ site: IStructuredData[];
231
+ };
232
+ structuredData: {
233
+ global: IStructuredData[];
234
+ site: IStructuredData[];
235
+ };
212
236
  currentSiteInfo: ISite | null;
213
237
  siteLanguages: ILanguage[];
214
238
  lang: { locale: string; id: number };
@@ -217,6 +241,7 @@ interface INavMenuProps {
217
241
 
218
242
  const mapStateToProps = (state: IRootState) => ({
219
243
  categories: state.structuredData.categories,
244
+ structuredData: state.structuredData.structuredData,
220
245
  currentSiteInfo: state.sites.currentSiteInfo,
221
246
  siteLanguages: state.sites.currentSiteLanguages,
222
247
  lang: state.app.lang,
@@ -84,7 +84,11 @@ const TableHeader = (props: IProps): JSX.Element => {
84
84
  </S.NameWrapper>
85
85
  {activeColumns.includes("live") && (
86
86
  <S.HeaderWrapper>
87
- <LiveFilter filterItems={filterItems} value={filterValues.liveStatus} hasBasicStatus={true} />
87
+ <LiveFilter
88
+ filterItems={filterItems}
89
+ value={filterValues.liveStatus}
90
+ filterOptions={["offline", "active", "scheduled"]}
91
+ />
88
92
  </S.HeaderWrapper>
89
93
  )}
90
94
  {CategoryColumns}
@@ -18,7 +18,7 @@ const SideModalOption = (props: IProps) => {
18
18
 
19
19
  return (
20
20
  <S.Item onClick={setOption} data-testid="side-modal-option">
21
- <S.Thumbnail data-testid="side-modal-option-img" {...thumbnailProps} />
21
+ {thumbnailProps && <S.Thumbnail data-testid="side-modal-option-img" {...thumbnailProps} />}
22
22
  {label}
23
23
  </S.Item>
24
24
  );
@@ -1,14 +1,17 @@
1
1
  import styled from "styled-components";
2
2
 
3
3
  const Item = styled.li`
4
+ ${(p) => p.theme.textStyle.uiS};
4
5
  cursor: pointer;
5
6
  padding: ${(p) => p.theme.spacing.xs};
6
- padding-bottom: ${(p) => p.theme.spacing.s};
7
+ padding-bottom: ${(p) => p.theme.spacing.xs};
8
+ padding-top: ${(p) => p.theme.spacing.xs};
7
9
  margin-bottom: ${(p) => p.theme.spacing.xs};
8
10
  box-shadow: ${(p) => p.theme.shadow.shadowS};
9
11
  border-radius: ${(p) => p.theme.radii.s};
10
- ${(p) => p.theme.textStyle.uiS};
11
12
  background-color: ${(p) => p.theme.color.interactiveBackground};
13
+ min-height: ${(p) => p.theme.spacing.l};
14
+ align-content: center;
12
15
  &:hover {
13
16
  background: ${(p) => p.theme.color.overlayHoverPrimary};
14
17
  }
@@ -19,7 +22,7 @@ const Item = styled.li`
19
22
 
20
23
  const Thumbnail = styled.img`
21
24
  cursor: pointer;
22
- padding-bottom: ${(p) => p.theme.spacing.s};
25
+ padding-bottom: ${(p) => p.theme.spacing.xs};
23
26
  `;
24
27
 
25
28
  const TagWrapper = styled.div`
@@ -80,7 +80,7 @@ const GlobalEditor = (props: IProps) => {
80
80
  const [notification, setNotification] = useState<INotification | null>(null);
81
81
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
82
82
  const [errorPagesChecked, setErrorPagesChecked] = useState(false);
83
- const [scheduleDate, setScheduleDate] = useState({ date: "", time: "12:00 am" });
83
+ const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
84
84
  const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
85
85
  const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
86
86
  const browserRef = useRef<HTMLDivElement>(null);
@@ -169,9 +169,10 @@ const GlobalEditor = (props: IProps) => {
169
169
  status: pageStatus.UPLOAD_PENDING,
170
170
  };
171
171
 
172
- const isSaved = pageID
173
- ? await updatePageStatus([pageID], pageStatus.UPLOAD_PENDING)
174
- : await savePage(false, publishPage);
172
+ const isSaved =
173
+ pageID && !isNewTranslation
174
+ ? await updatePageStatus([pageID], pageStatus.UPLOAD_PENDING)
175
+ : await savePage(false, publishPage);
175
176
 
176
177
  if (isSaved) {
177
178
  resetDirty();
@@ -79,7 +79,7 @@ const PageEditor = (props: IProps) => {
79
79
  const [isReadOnly, setIsReadOnly] = useState(false);
80
80
  const [selectedTab, setSelectedTab] = useState(defaultTab);
81
81
  const [notification, setNotification] = useState<INotification | null>(null);
82
- const [scheduleDate, setScheduleDate] = useState({ date: "", time: "12:00 am" });
82
+ const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
83
83
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent, isNewTranslation);
84
84
  const { isOpen, toggleModal } = useModal();
85
85
  const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
@@ -175,9 +175,10 @@ const PageEditor = (props: IProps) => {
175
175
  status: pageStatus.UPLOAD_PENDING,
176
176
  };
177
177
 
178
- const isSaved = pageID
179
- ? await updatePageStatus([pageID], pageStatus.UPLOAD_PENDING)
180
- : await savePage(false, publishPage);
178
+ const isSaved =
179
+ pageID && !isNewTranslation
180
+ ? await updatePageStatus([pageID], pageStatus.UPLOAD_PENDING)
181
+ : await savePage(false, publishPage);
181
182
 
182
183
  if (isSaved) {
183
184
  resetDirty();
@@ -259,6 +260,7 @@ const PageEditor = (props: IProps) => {
259
260
  };
260
261
 
261
262
  const handleSchedulePublication = async () => {
263
+ console.log(scheduleDate, "scheduleDate");
262
264
  const date = new Date(`${scheduleDate.date} ${scheduleDate.time}`);
263
265
  const dateString = dateToString(date, "dd/MM/yyyy HH:mm:ss");
264
266
  const saved = await schedulePublication(dateString, isDraft);
@@ -49,7 +49,7 @@ const TableHeader = (props: IProps): JSX.Element => {
49
49
  </S.NameWrapper>
50
50
  <S.DomainHeader>Domain</S.DomainHeader>
51
51
  <S.LiveHeader>
52
- <LiveFilter filterItems={filterItems} value={liveFilterValue} hasBasicStatus={true} />
52
+ <LiveFilter filterItems={filterItems} value={liveFilterValue} filterOptions={["offline", "active"]} />
53
53
  </S.LiveHeader>
54
54
  <S.LastAccessCell>
55
55
  <LastAccessFilter sortItems={sortItems} sortedState={sortedListStatus} />
@@ -33,7 +33,10 @@ const useFilterQuery = (defaultValues?: { order: IQueryValue[]; liveStatus: IQue
33
33
 
34
34
  let filterQuery = "";
35
35
  const currentQuery = (pointer: string, values: IQueryValue[]) => {
36
- return values.length && values[0].value !== "all" ? `&${pointer}=${values[0].value}` : "";
36
+ if (!values.length || !values[0].value || values[0].value === "all") {
37
+ return "";
38
+ }
39
+ return `&${pointer}=${values[0].value}`;
37
40
  };
38
41
 
39
42
  const isNotInitialValue = (pointer: keyof Record<string, IQueryValue[]>) => {
@@ -54,7 +54,7 @@ const Form = (props: IProps) => {
54
54
 
55
55
  const [isNewStructuredData, setIsNewStructuredData] = useState(!currentStructuredDataId);
56
56
  const [notification, setNotification] = useState<INotification | null>(null);
57
- const [scheduleDate, setScheduleDate] = useState({ date: "", time: "12:00 am" });
57
+ const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
58
58
  const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
59
59
  const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
60
60
  const { isDirty, resetDirty, setIsDirty } = useIsDirty(form);
@@ -115,7 +115,11 @@ const TableHeader = (props: IProps): JSX.Element => {
115
115
  </S.NameWrapper>
116
116
  {activeColumns.includes("live") && (
117
117
  <S.HeaderWrapper>
118
- <LiveFilter filterItems={filterItems} value={filterValues.liveStatus} hasBasicStatus={true} />
118
+ <LiveFilter
119
+ filterItems={filterItems}
120
+ value={filterValues.liveStatus}
121
+ filterOptions={["offline", "active", "scheduled"]}
122
+ />
119
123
  </S.HeaderWrapper>
120
124
  )}
121
125
  {CategoryColumns}