@griddo/ax 1.66.13 → 1.67.2

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 (76) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Fields/ConditionalField/ConditionalField.test.tsx +95 -0
  3. package/src/api/pages.tsx +15 -3
  4. package/src/api/redirects.tsx +4 -2
  5. package/src/api/sites.tsx +12 -4
  6. package/src/components/Browser/index.tsx +9 -22
  7. package/src/components/Browser/style.tsx +1 -6
  8. package/src/components/ErrorCenter/index.tsx +8 -5
  9. package/src/components/ErrorCenter/style.tsx +21 -8
  10. package/src/components/Fields/ComponentArray/MixableComponentArray/AddItemButton/index.tsx +3 -3
  11. package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +60 -25
  12. package/src/components/Fields/ComponentContainer/index.tsx +21 -7
  13. package/src/components/Fields/ConditionalField/index.tsx +1 -1
  14. package/src/components/Fields/LinkField/index.tsx +111 -0
  15. package/src/components/Fields/ReferenceField/ItemList/index.tsx +4 -0
  16. package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +12 -2
  17. package/src/components/Fields/ReferenceField/index.tsx +24 -12
  18. package/src/components/Fields/ReferenceField/style.tsx +12 -1
  19. package/src/components/Fields/UrlField/index.tsx +13 -1
  20. package/src/components/Fields/VisualUniqueSelection/utils.tsx +1 -6
  21. package/src/components/Fields/index.tsx +2 -0
  22. package/src/components/FieldsBehavior/index.tsx +14 -1
  23. package/src/components/Icon/components/Copy.js +14 -0
  24. package/src/components/Icon/components/Copy2.js +14 -0
  25. package/src/components/Icon/components/Duplicate.js +3 -5
  26. package/src/components/Icon/components/Page.js +12 -0
  27. package/src/components/Icon/svgs/Copy.svg +3 -0
  28. package/src/components/Icon/svgs/Copy2.svg +3 -0
  29. package/src/components/Icon/svgs/Duplicate.svg +1 -1
  30. package/src/components/Icon/svgs/page.svg +3 -0
  31. package/src/components/MainWrapper/AppBar/index.tsx +21 -10
  32. package/src/components/MainWrapper/AppBar/style.tsx +11 -3
  33. package/src/components/MainWrapper/index.tsx +2 -0
  34. package/src/components/Notification/index.tsx +1 -3
  35. package/src/components/SearchField/index.tsx +37 -4
  36. package/src/components/SearchField/style.tsx +23 -10
  37. package/src/components/index.tsx +2 -0
  38. package/src/containers/Navigation/Defaults/actions.tsx +2 -0
  39. package/src/containers/PageEditor/actions.tsx +101 -19
  40. package/src/containers/PageEditor/utils.tsx +2 -1
  41. package/src/containers/Sites/actions.tsx +53 -24
  42. package/src/containers/Sites/constants.tsx +2 -0
  43. package/src/containers/Sites/interfaces.tsx +12 -5
  44. package/src/containers/Sites/reducer.tsx +8 -0
  45. package/src/containers/StructuredData/actions.tsx +5 -8
  46. package/src/forms/errors.tsx +1 -0
  47. package/src/forms/index.tsx +13 -1
  48. package/src/forms/validators.tsx +181 -13
  49. package/src/helpers/dataPacks.tsx +8 -1
  50. package/src/helpers/index.tsx +4 -1
  51. package/src/helpers/objects.tsx +10 -2
  52. package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +3 -1
  53. package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +15 -9
  54. package/src/modules/Categories/CategoriesList/index.tsx +2 -1
  55. package/src/modules/Content/PageItem/index.tsx +52 -2
  56. package/src/modules/Content/atoms.tsx +41 -3
  57. package/src/modules/Content/index.tsx +44 -2
  58. package/src/modules/Content/style.tsx +8 -1
  59. package/src/modules/FramePreview/index.tsx +85 -0
  60. package/src/modules/FramePreview/style.tsx +18 -0
  61. package/src/modules/GlobalEditor/Editor/index.tsx +3 -1
  62. package/src/modules/GlobalEditor/PageBrowser/index.tsx +3 -0
  63. package/src/modules/GlobalEditor/index.tsx +22 -6
  64. package/src/modules/PageEditor/Editor/index.tsx +5 -1
  65. package/src/modules/PageEditor/PageBrowser/index.tsx +4 -5
  66. package/src/modules/PageEditor/index.tsx +40 -12
  67. package/src/modules/Redirects/index.tsx +40 -10
  68. package/src/modules/Settings/Globals/index.tsx +1 -1
  69. package/src/modules/Sites/index.tsx +2 -2
  70. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +1 -1
  71. package/src/modules/StructuredData/StructuredDataList/index.tsx +19 -2
  72. package/src/modules/Users/Profile/index.tsx +3 -3
  73. package/src/routes/multisite.tsx +12 -4
  74. package/src/routes/site.tsx +1 -1
  75. package/src/types/index.tsx +13 -4
  76. package/tsconfig.paths.json +2 -1
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { INavItem, IRedirect, IRootState } from "@ax/types";
4
+ import { IEmptyStateProps, INavItem, IRedirect, IRootState } from "@ax/types";
5
5
  import { appActions } from "@ax/containers/App";
6
6
  import { redirectsActions } from "@ax/containers/Redirects";
7
7
  import { MainWrapper, ErrorToast, Nav, TableList, EmptyState, Toast } from "@ax/components";
@@ -30,6 +30,7 @@ const Redirects = (props: IProps): JSX.Element => {
30
30
  importRedirects,
31
31
  imports,
32
32
  totalImports,
33
+ isLoading,
33
34
  } = props;
34
35
 
35
36
  const itemsPerPage = 50;
@@ -50,6 +51,10 @@ const Redirects = (props: IProps): JSX.Element => {
50
51
  const { isOpen: isOpenCheckImport, toggleModal: toggleCheckImportModal } = useModal();
51
52
  const [importData, setImportData] = useState<{ from: string; to: string }[]>([]);
52
53
  const [isUploading, setIsUploading] = useState(false);
54
+ const [searchQuery, setSearchQuery] = useState<string>("");
55
+ const [searchFilter, setSearchFilter] = useState<string>("");
56
+ const [isEmpty, setIsEmpty] = useState(false);
57
+ const [emptyStateProps, setEmptyStateProps] = useState<IEmptyStateProps>({});
53
58
 
54
59
  const initState = {
55
60
  from: "",
@@ -62,17 +67,18 @@ const Redirects = (props: IProps): JSX.Element => {
62
67
  const [formValues, setFormValues] = useState<IRedirect>(initState);
63
68
 
64
69
  const redIds = redirects && redirects.map((red: any) => red.id);
65
- const isEmpty = redirects && redirects.length === 0;
66
70
 
67
71
  const getParams = useCallback(() => {
68
72
  const params = {
69
73
  page,
70
74
  itemsPerPage,
71
75
  pagination: true,
76
+ query: searchQuery.trim(),
77
+ filterBy: searchFilter === "filterby" || searchQuery.trim() === "" ? "" : searchFilter,
72
78
  };
73
79
 
74
80
  return params;
75
- }, [page]);
81
+ }, [page, searchQuery, searchFilter]);
76
82
 
77
83
  useEffect(() => {
78
84
  const params = getParams();
@@ -81,7 +87,26 @@ const Redirects = (props: IProps): JSX.Element => {
81
87
  tableRef.current.scrollTo(0, 0);
82
88
  }
83
89
  // eslint-disable-next-line react-hooks/exhaustive-deps
84
- }, [page, currentFilterQuery]);
90
+ }, [page, currentFilterQuery, searchQuery, searchFilter]);
91
+
92
+ useEffect(() => {
93
+ if (!isLoading) {
94
+ const emptyState: IEmptyStateProps = {};
95
+ const isSearching = searchQuery.length > 0;
96
+ if (isSearching) {
97
+ emptyState.icon = "search";
98
+ emptyState.title = "Oh! No Results Found";
99
+ emptyState.message = "We couldn’t find what you are looking for. Please, try another search.";
100
+ } else {
101
+ emptyState.message = "To have a redirects on your site, create as many redirects as you want.";
102
+ emptyState.button = "Create New redirect";
103
+ emptyState.action = handleModal;
104
+ }
105
+ setIsEmpty(!redirects.length);
106
+ setEmptyStateProps(emptyState);
107
+ }
108
+ // eslint-disable-next-line react-hooks/exhaustive-deps
109
+ }, [isLoading]);
85
110
 
86
111
  const {
87
112
  resetBulkSelection,
@@ -176,12 +201,6 @@ const Redirects = (props: IProps): JSX.Element => {
176
201
  toggleOverwriteModal();
177
202
  };
178
203
 
179
- const emptyStateProps = {
180
- message: "To have a redirects on your site, create as many redirects as you want.",
181
- button: "Create New redirect",
182
- action: handleModal,
183
- };
184
-
185
204
  const pagination = {
186
205
  setPage,
187
206
  itemsPerPage,
@@ -236,6 +255,12 @@ const Redirects = (props: IProps): JSX.Element => {
236
255
 
237
256
  const secondaryImportModalAction = { title: "Cancel", onClick: toggleCheckImportModal };
238
257
 
258
+ const searchFilters = [
259
+ { value: "filterby", label: "Filter by" },
260
+ { value: "from", label: "Old URL" },
261
+ { value: "to", label: "New URL" },
262
+ ];
263
+
239
264
  return (
240
265
  <>
241
266
  <MainWrapper
@@ -243,6 +268,9 @@ const Redirects = (props: IProps): JSX.Element => {
243
268
  title="SEO Settings"
244
269
  rightButton={rightButtonProps}
245
270
  rightLineButton={rightLineButtonProps}
271
+ searchAction={setSearchQuery}
272
+ filterSearchAction={setSearchFilter}
273
+ searchFilters={searchFilters}
246
274
  >
247
275
  <S.Wrapper>
248
276
  <Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
@@ -341,6 +369,7 @@ const mapStateToProps = (state: IRootState) => ({
341
369
  currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
342
370
  totalImports: state.redirects.totalImports,
343
371
  imports: state.redirects.imports,
372
+ isLoading: state.app.isLoading,
344
373
  });
345
374
 
346
375
  const mapDispatchToProps = {
@@ -357,6 +386,7 @@ interface IRedirectsProps {
357
386
  totalItems: number;
358
387
  currentSiteID: number | null;
359
388
  totalImports: number;
389
+ isLoading: boolean;
360
390
  imports: null | {
361
391
  error: IRedirect[];
362
392
  existing: IRedirect[];
@@ -87,7 +87,7 @@ const Globals = (props: IProps): JSX.Element => {
87
87
  text="The design of the navigation modules has changed. Please, check the previously created."
88
88
  btnText="Go to check"
89
89
  onClick={goToNavigationModules}
90
- onClose={closeNavigationNotification}
90
+ resetError={closeNavigationNotification}
91
91
  />
92
92
  )}
93
93
  <S.FormWrapper>
@@ -28,7 +28,7 @@ const Sites = (props: IProps): JSX.Element => {
28
28
  const fetchInitialData = async () => {
29
29
  setCurrentSiteInfo(null);
30
30
  await getStructuredData(token);
31
- await getSites(token);
31
+ await getSites();
32
32
  await getAllDataPacks();
33
33
  await getUser("me");
34
34
 
@@ -68,7 +68,7 @@ interface IStateProps {
68
68
 
69
69
  interface IDispatchProps {
70
70
  setCurrentSiteInfo(currentSiteInfo: any): void;
71
- getSites(token: string): Promise<void>;
71
+ getSites(): Promise<void>;
72
72
  getStructuredData(token: string, siteId?: number): Promise<void>;
73
73
  setLanguage(lang: { locale: string; id: number | null }): void;
74
74
  getAllDataPacks: () => Promise<void>;
@@ -405,7 +405,7 @@ interface IGlobalPageItemProps {
405
405
  isAllPages?: boolean;
406
406
  globalPage: IPage;
407
407
  updatePageStatus(ids: number[], status: string, updatedFromList: boolean): Promise<boolean>;
408
- duplicatePage(pageID: number, data: { title: string; slug: string }): Promise<void>;
408
+ duplicatePage(pageID: number, data: { title: string; slug: string }, siteID?: number): Promise<boolean>;
409
409
  setHistoryPush(path: string, isEditor: boolean): void;
410
410
  deletePage(params?: ISavePageParams, currentLanguage?: string): Promise<boolean>;
411
411
  getGlobalPages(): void;
@@ -82,6 +82,9 @@ const StructuredDataList = (props: IProps): JSX.Element => {
82
82
  restorePage,
83
83
  resetPageEditor,
84
84
  getAnalytics,
85
+ setCurrentDataID,
86
+ resetCurrentSiteErrorPages,
87
+ currentSiteErrorPages,
85
88
  } = props;
86
89
 
87
90
  const itemsPerPage = 50;
@@ -212,6 +215,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
212
215
  resetFilter();
213
216
  setIsFirstRender(false);
214
217
  resetPageEditor();
218
+ resetCurrentSiteErrorPages();
215
219
  // eslint-disable-next-line react-hooks/exhaustive-deps
216
220
  }, []);
217
221
 
@@ -283,7 +287,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
283
287
  setEmptyStateProps(emptyState);
284
288
  }
285
289
  // eslint-disable-next-line react-hooks/exhaustive-deps
286
- }, [isLoading]);
290
+ }, [isLoading, currentSitePages, currentDataContent]);
287
291
 
288
292
  useEffect(() => {
289
293
  getAnalytics();
@@ -305,6 +309,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
305
309
  };
306
310
 
307
311
  const createNewData = () => {
312
+ setCurrentDataID(null);
308
313
  resetForm();
309
314
  handleClick();
310
315
  };
@@ -537,6 +542,11 @@ const StructuredDataList = (props: IProps): JSX.Element => {
537
542
 
538
543
  const content = isStructuredDataFromPage ? mapGlobalPages() : mapCurrentDataContent();
539
544
 
545
+ const errorPagesText =
546
+ currentSiteErrorPages.length > 1
547
+ ? "These pages contains some errors, so you can not publish them yet. Please, review the errors on the pages."
548
+ : "This page contains some errors, so you can not publish it yet. Please, review the errors on the page.";
549
+
540
550
  return (
541
551
  <MainWrapper
542
552
  title="Global Data"
@@ -560,6 +570,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
560
570
  </S.NotificationWrapper>
561
571
  )}
562
572
  <ErrorToast />
573
+ {!!currentSiteErrorPages.length && <Notification type="error" text={errorPagesText} />}
563
574
  <TableList
564
575
  tableHeader={TableHeader}
565
576
  pagination={pagination}
@@ -621,6 +632,7 @@ const mapStateToProps = (state: IRootState) => ({
621
632
  isLoading: state.app.isLoading,
622
633
  template: state.pageEditor.template,
623
634
  currentSitePages: state.sites.currentSitePages,
635
+ currentSiteErrorPages: state.sites.currentSiteErrorPages,
624
636
  });
625
637
 
626
638
  const mapDispatchToProps = {
@@ -643,6 +655,8 @@ const mapDispatchToProps = {
643
655
  restorePage: pageEditorActions.restorePage,
644
656
  resetPageEditor: pageEditorActions.resetPageEditor,
645
657
  getAnalytics: analyticsActions.getAnalytics,
658
+ setCurrentDataID: structuredDataActions.setCurrentDataID,
659
+ resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
646
660
  };
647
661
 
648
662
  interface IDispatchProps {
@@ -665,6 +679,8 @@ interface IDispatchProps {
665
679
  restorePage(id: number | number[]): Promise<boolean>;
666
680
  resetPageEditor(): Promise<void>;
667
681
  getAnalytics(): void;
682
+ setCurrentDataID(id: number | null): void;
683
+ resetCurrentSiteErrorPages: () => Promise<void>;
668
684
  }
669
685
 
670
686
  interface ICategoriesProps {
@@ -680,8 +696,9 @@ interface ICategoriesProps {
680
696
  isLoading: boolean;
681
697
  template: string;
682
698
  currentSitePages: IPage[];
699
+ currentSiteErrorPages: number[];
683
700
  }
684
701
 
685
702
  type IProps = ICategoriesProps & IDispatchProps;
686
703
 
687
- export default connect(mapStateToProps, mapDispatchToProps)(StructuredDataList);
704
+ export default connect(mapStateToProps, mapDispatchToProps)(StructuredDataList);
@@ -11,14 +11,14 @@ import { useURLSearchParam } from "@ax/hooks";
11
11
  import UserForm from "../UserForm";
12
12
 
13
13
  const Profile = (props: IProps) => {
14
- const { user, getUser, updateUser, isSaving, isLoading, getSites, token } = props;
14
+ const { user, getUser, updateUser, isSaving, isLoading, getSites } = props;
15
15
 
16
16
  const isUserInit = useURLSearchParam("init");
17
17
 
18
18
  const [form, setForm] = useState<IUser>({ ...user });
19
19
 
20
20
  useEffect(() => {
21
- isUserInit ? getSites(token) : getUser("me");
21
+ isUserInit ? getSites() : getUser("me");
22
22
  // eslint-disable-next-line react-hooks/exhaustive-deps
23
23
  }, []);
24
24
 
@@ -58,7 +58,7 @@ const mapStateToProps = (state: IRootState) => ({
58
58
  interface IDispatchProps {
59
59
  setHistoryPush(path: string): any;
60
60
  getUser(id: string): any;
61
- getSites(token: string): Promise<void>;
61
+ getSites(): Promise<void>;
62
62
  updateUser(id: number, data: any, isProfile: boolean, isList: boolean): any;
63
63
  }
64
64
 
@@ -9,6 +9,7 @@ import UserEdit from "../modules/Users/UserEdit";
9
9
  import Editor from "./../modules/GlobalEditor";
10
10
  import GlobalSettings from "./../modules/GlobalSettings";
11
11
  import AnalyticsSettings from "../modules/Analytics";
12
+ import FramePreview from "../modules/FramePreview";
12
13
 
13
14
  export default [
14
15
  { path: "/sites", component: Sites, name: "Sites", showInNav: true, icon: "Project" },
@@ -46,10 +47,10 @@ export default [
46
47
  path: `/settings/analytics`,
47
48
  component: AnalyticsSettings,
48
49
  name: "Analytics tools",
49
- }
50
- ]
51
- }
52
- ]
50
+ },
51
+ ],
52
+ },
53
+ ],
53
54
  },
54
55
  {
55
56
  path: `/settings/redirects`,
@@ -57,4 +58,11 @@ export default [
57
58
  name: "Settings",
58
59
  showInNav: false,
59
60
  },
61
+ {
62
+ path: `/editor/page-preview`,
63
+ component: FramePreview,
64
+ name: "Preview",
65
+ showInNav: false,
66
+ hideNav: true,
67
+ },
60
68
  ];
@@ -17,7 +17,7 @@ import Profile from "./../modules/Users/Profile";
17
17
  const BASE_PATH = "/sites";
18
18
 
19
19
  export default [
20
- { path: `${BASE_PATH}/pages`, component: Content, name: "Content", showInNav: true, icon: "Data" },
20
+ { path: `${BASE_PATH}/pages`, component: Content, name: "Content", showInNav: true, icon: "page" },
21
21
  { path: `${BASE_PATH}/pages/editor`, component: Editor, name: "Page Editor", showInNav: false, hideNav: true },
22
22
  {
23
23
  path: `${BASE_PATH}/pages/editor/new`,
@@ -268,13 +268,14 @@ export interface ISavePageParams {
268
268
  export interface IGetSitePagesParams {
269
269
  siteID: number;
270
270
  deleted: boolean;
271
- page: number;
272
- itemsPerPage: number;
271
+ page?: number;
272
+ itemsPerPage?: number;
273
273
  langID?: number;
274
274
  query?: string;
275
275
  lang?: number;
276
276
  filterStructuredData?: string;
277
277
  format?: string;
278
+ filterPages?: number[];
278
279
  }
279
280
 
280
281
  export interface IGetGlobalPagesParams {
@@ -573,8 +574,8 @@ export interface IErrorItem {
573
574
  type: string;
574
575
  message: string;
575
576
  validator: Record<string, unknown>;
576
- editorID: number;
577
- component: string;
577
+ editorID: number | null;
578
+ component: string | null;
578
579
  name: string;
579
580
  key: string;
580
581
  tab: string;
@@ -740,6 +741,13 @@ export interface INotification {
740
741
  onClick?: () => void;
741
742
  }
742
743
 
744
+ export interface ILinkField {
745
+ text: string;
746
+ linkType: string;
747
+ url: IUrlField;
748
+ modal: any;
749
+ }
750
+
743
751
  export type Field =
744
752
  | "AsyncCheckGroup"
745
753
  | "AsyncSelect"
@@ -753,6 +761,7 @@ export type Field =
753
761
  | "HeadingField"
754
762
  | "HiddenField"
755
763
  | "ImageField"
764
+ | "LinkField"
756
765
  | "NumberField"
757
766
  | "RadioField"
758
767
  | "RadioGroup"
@@ -13,7 +13,8 @@
13
13
  "@ax/modules": ["src/modules"],
14
14
  "@ax/routes": ["src/routes"],
15
15
  "@ax/types": ["src/types"],
16
- "@ax/schemas": ["src/schemas"]
16
+ "@ax/schemas": ["src/schemas"],
17
+ "@ax/themes/*": ["src/themes/*"]
17
18
  }
18
19
  }
19
20
  }