@griddo/ax 1.63.5 → 1.64.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 (130) hide show
  1. package/config/griddo-config/cx-polyfills/builder.ssr.js +6 -0
  2. package/config/griddo-config/cx-polyfills/componentsBundle.js +4 -0
  3. package/config/{griddo-config.js → griddo-config/index.js} +36 -15
  4. package/config/griddo-config/ssrHelpers.js +47 -0
  5. package/config/jest/componentsMock.js +29 -0
  6. package/config/jest/fileMock.js +1 -0
  7. package/config/jest/setup.js +5 -0
  8. package/config/jest/styleMock.js +1 -0
  9. package/config/jest/test-utils.js +17 -0
  10. package/config/paths.js +36 -5
  11. package/config/webpack.config.js +1 -1
  12. package/config/webpackDevServer.config.js +4 -1
  13. package/config/webpackSchemas.config.js +4 -1
  14. package/package.json +33 -59
  15. package/scripts/build.js +9 -2
  16. package/src/__mocks__/reducers/analyticsState.tsx +14 -0
  17. package/src/__mocks__/reducers/pageEditor.tsx +30 -0
  18. package/src/api/sites.tsx +28 -6
  19. package/src/api/structuredData.tsx +1 -1
  20. package/src/api/users.tsx +5 -4
  21. package/src/components/ActionMenu/style.tsx +2 -0
  22. package/src/components/Browser/index.tsx +9 -5
  23. package/src/{modules/Content/PageItem/atoms.tsx → components/CategoryCell/index.tsx} +4 -6
  24. package/src/components/CategoryCell/style.tsx +11 -0
  25. package/src/components/Fields/AnalyticsField/PageAnalytics/index.tsx +19 -19
  26. package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/atoms.tsx +26 -16
  27. package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/index.tsx +8 -13
  28. package/src/components/Fields/AnalyticsField/index.test.tsx +100 -0
  29. package/src/components/Fields/AnalyticsField/index.tsx +9 -2
  30. package/src/components/Fields/AnalyticsField/utils.tsx +2 -2
  31. package/src/components/Fields/ArrayFieldGroup/ArrayFieldItem/style.tsx +2 -1
  32. package/src/components/Fields/CheckField/index.test.tsx +95 -0
  33. package/src/components/Fields/CheckField/index.tsx +9 -3
  34. package/src/components/Fields/CheckField/style.tsx +32 -24
  35. package/src/components/Fields/CheckGroup/index.test.tsx +274 -0
  36. package/src/components/Fields/CheckGroup/index.tsx +2 -1
  37. package/src/components/Fields/FileField/FileDragAndDrop/style.tsx +3 -2
  38. package/src/components/Fields/FileField/style.tsx +2 -1
  39. package/src/components/Fields/MultiCheckSelect/style.tsx +18 -18
  40. package/src/components/Fields/NoteField/style.tsx +9 -9
  41. package/src/components/Fields/ReferenceField/AutoPanel/AutoItem/index.tsx +1 -1
  42. package/src/components/Fields/Select/style.tsx +41 -37
  43. package/src/components/Fields/TagField/index.test.tsx +136 -0
  44. package/src/components/Fields/TagField/index.tsx +8 -12
  45. package/src/components/Fields/TextArea/index.test.tsx +69 -0
  46. package/src/components/Fields/TextArea/index.tsx +4 -13
  47. package/src/components/Fields/TextArea/style.tsx +2 -2
  48. package/src/components/Fields/TextField/index.test.tsx +144 -0
  49. package/src/components/Fields/TextField/index.tsx +23 -19
  50. package/src/components/Fields/TextField/style.tsx +16 -7
  51. package/src/components/Fields/UniqueCheck/index.test.tsx +43 -0
  52. package/src/components/Fields/UrlField/utils.tsx +8 -6
  53. package/src/components/FieldsBehavior/index.tsx +0 -2
  54. package/src/components/FieldsBehavior/style.tsx +21 -21
  55. package/src/components/Gallery/GalleryFilters/Orientation/style.tsx +2 -1
  56. package/src/components/Gallery/GalleryFilters/SortBy/style.tsx +2 -1
  57. package/src/components/Icon/index.tsx +12 -10
  58. package/src/components/IconAction/index.tsx +7 -1
  59. package/src/components/IconAction/style.tsx +10 -10
  60. package/src/components/SearchField/index.tsx +11 -8
  61. package/src/components/SearchField/style.tsx +21 -12
  62. package/src/components/TableFilters/CategoryFilter/index.tsx +1 -1
  63. package/src/components/TableFilters/CategoryFilter/style.tsx +2 -1
  64. package/src/components/TableFilters/DateFilter/style.tsx +2 -1
  65. package/src/components/TableFilters/LiveFilter/index.tsx +2 -2
  66. package/src/components/TableFilters/LiveFilter/style.tsx +2 -1
  67. package/src/components/TableFilters/NameFilter/style.tsx +2 -1
  68. package/src/components/TableFilters/SiteFilter/index.tsx +38 -24
  69. package/src/components/TableFilters/SiteFilter/style.tsx +2 -1
  70. package/src/components/TableFilters/StatusFilter/style.tsx +2 -1
  71. package/src/components/TableFilters/TranslationsFilter/style.tsx +2 -1
  72. package/src/components/TableFilters/TypeFilter/style.tsx +2 -1
  73. package/src/components/Tag/index.tsx +9 -7
  74. package/src/components/Tag/style.tsx +20 -8
  75. package/src/components/index.tsx +4 -2
  76. package/src/containers/App/reducer.tsx +0 -2
  77. package/src/containers/PageEditor/actions.tsx +2 -2
  78. package/src/containers/Sites/actions.tsx +30 -19
  79. package/src/containers/Users/actions.tsx +10 -2
  80. package/src/containers/Users/reducer.tsx +3 -1
  81. package/src/helpers/fields.tsx +2 -4
  82. package/src/helpers/index.tsx +3 -0
  83. package/src/helpers/themes.tsx +9 -0
  84. package/src/modules/Analytics/GroupPanel/utils.tsx +3 -3
  85. package/src/modules/App/Routing/NavMenu/index.tsx +13 -12
  86. package/src/modules/Content/PageItem/index.tsx +31 -9
  87. package/src/modules/Content/PageItem/style.tsx +0 -7
  88. package/src/modules/Content/atoms.tsx +78 -0
  89. package/src/modules/Content/index.tsx +104 -33
  90. package/src/modules/Content/style.tsx +10 -7
  91. package/src/modules/GlobalEditor/PageBrowser/index.tsx +0 -4
  92. package/src/modules/GlobalEditor/index.tsx +3 -3
  93. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +0 -4
  94. package/src/modules/PageEditor/PageBrowser/index.tsx +0 -4
  95. package/src/modules/PageEditor/atoms.tsx +74 -0
  96. package/src/modules/PageEditor/index.tsx +30 -9
  97. package/src/modules/PageEditor/style.tsx +4 -0
  98. package/src/modules/PublicPreview/index.tsx +3 -5
  99. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/TemplateBrowser/index.tsx +0 -4
  100. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/index.tsx +2 -3
  101. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +1 -1
  102. package/src/modules/Settings/Globals/index.tsx +3 -3
  103. package/src/modules/StructuredData/Form/index.tsx +2 -4
  104. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +22 -18
  105. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/atoms.tsx +3 -24
  106. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +2 -2
  107. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/style.tsx +0 -7
  108. package/src/modules/StructuredData/StructuredDataList/OptionTable/index.tsx +2 -4
  109. package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +46 -14
  110. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +21 -9
  111. package/src/modules/StructuredData/StructuredDataList/index.tsx +48 -20
  112. package/src/modules/Users/Profile/index.tsx +12 -7
  113. package/src/modules/Users/UserCreate/SiteItem/index.tsx +44 -0
  114. package/src/modules/Users/UserCreate/SiteItem/style.tsx +30 -0
  115. package/src/modules/Users/UserCreate/index.tsx +120 -10
  116. package/src/modules/Users/UserCreate/style.tsx +54 -1
  117. package/src/modules/Users/UserEdit/index.tsx +53 -15
  118. package/src/modules/Users/UserForm/index.tsx +152 -5
  119. package/src/modules/Users/UserForm/style.tsx +40 -2
  120. package/src/modules/Users/UserList/BulkHeader/TableHeader/index.tsx +40 -2
  121. package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +0 -1
  122. package/src/modules/Users/UserList/BulkHeader/index.tsx +10 -1
  123. package/src/modules/Users/UserList/UserItem/index.tsx +70 -15
  124. package/src/modules/Users/UserList/hooks.tsx +58 -1
  125. package/src/modules/Users/UserList/index.tsx +80 -34
  126. package/src/modules/Users/index.tsx +18 -11
  127. package/src/routes/site.tsx +8 -0
  128. package/src/types/index.tsx +7 -0
  129. package/tsconfig.json +2 -0
  130. package/scripts/test.js +0 -45
@@ -2,16 +2,17 @@ import React, { useEffect, useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
  import { RouteComponentProps } from "react-router-dom";
4
4
 
5
- import { IErrorItem, IRootState, ISavePageParams, IUserEditing } from "@ax/types";
5
+ import { IErrorItem, IPageLanguage, IRootState, ISavePageParams, IUserEditing } from "@ax/types";
6
6
  import { MainWrapper, Loading, ErrorToast, Notification, Modal } from "@ax/components";
7
7
  import { pageEditorActions } from "@ax/containers/PageEditor";
8
8
  import { appActions } from "@ax/containers/App";
9
9
  import { navigationActions } from "@ax/containers/Navigation";
10
10
  import { pageStatus } from "@ax/containers/PageEditor/interfaces";
11
11
  import { RouteLeavingGuard } from "@ax/guards";
12
- import { useIsDirty, useModal, useToast } from "@ax/hooks";
12
+ import { useIsDirty, useModal } from "@ax/hooks";
13
13
  import { isModuleDisabled } from "@ax/helpers";
14
14
  import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
15
+ import { DeleteModal } from "./atoms";
15
16
  import Editor from "./Editor";
16
17
  import Preview from "./Preview";
17
18
 
@@ -45,11 +46,13 @@ const PageEditor = (props: IProps) => {
45
46
  isNewTranslation,
46
47
  } = props;
47
48
 
49
+ const [deleteAllVersions, setDeleteAllVersions] = useState(false);
48
50
  const [isReadOnly, setIsReadOnly] = useState(false);
49
51
  const [selectedTab, setSelectedTab] = useState("edit");
50
52
  const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
51
53
  const { isOpen, toggleModal } = useModal();
52
54
  const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
55
+ const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
53
56
 
54
57
  const isGlobal = editorContent.editorContent && editorContent.editorContent.origin === "GLOBAL";
55
58
  const isEditable = editorContent.editorContent && editorContent.editorContent.editable;
@@ -57,6 +60,7 @@ const PageEditor = (props: IProps) => {
57
60
  const isDraft = props.pageStatus === pageStatus.MODIFIED;
58
61
  const hasDraft = editorContent.editorContent && editorContent.editorContent.haveDraftPage;
59
62
  const isLivePageChanged = editorContent.editorContent && editorContent.editorContent.liveChanged;
63
+ const isTranslated = pageLanguages.length > 1;
60
64
  const structuredData = editorContent.editorContent ? editorContent.editorContent.structuredData : "";
61
65
 
62
66
  useEffect(() => {
@@ -99,14 +103,15 @@ const PageEditor = (props: IProps) => {
99
103
  const setRoute = (path: string) => props.setHistoryPush(path, true);
100
104
 
101
105
  const removePage = async () => {
102
- const { deletePage } = props;
106
+ const { deletePage, deleteBulk } = props;
103
107
  const path = "/sites/pages";
104
108
 
105
- await deletePage().then((deleted: boolean) => {
106
- if (deleted) {
107
- setRoute(path);
108
- }
109
- });
109
+ const allPageVersions = pageLanguages.map((lang: IPageLanguage) => lang.pageId);
110
+ const isDeleted = deleteAllVersions ? await deleteBulk(allPageVersions) : await deletePage();
111
+ toggleDeleteModal();
112
+ if (isDeleted) {
113
+ setRoute(path);
114
+ }
110
115
  };
111
116
 
112
117
  const publishPage = async () => {
@@ -249,7 +254,7 @@ const PageEditor = (props: IProps) => {
249
254
  {
250
255
  label: "Delete",
251
256
  icon: "delete",
252
- action: removePage,
257
+ action: toggleDeleteModal,
253
258
  },
254
259
  ]
255
260
  : [];
@@ -401,6 +406,13 @@ const PageEditor = (props: IProps) => {
401
406
 
402
407
  const mainUnpublishAction = { title: "Ok", onClick: toggleUnpublishModal };
403
408
 
409
+ const mainDeleteModalAction = {
410
+ title: "Delete page",
411
+ onClick: removePage,
412
+ };
413
+
414
+ const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
415
+
404
416
  const tabsPreview = {
405
417
  icons: [
406
418
  { name: "edit", text: "Edit mode" },
@@ -508,6 +520,13 @@ const PageEditor = (props: IProps) => {
508
520
  </S.ModalContent>
509
521
  )}
510
522
  </Modal>
523
+ <DeleteModal
524
+ isOpen={isDeleteOpen}
525
+ toggleModal={toggleDeleteModal}
526
+ mainModalAction={mainDeleteModalAction}
527
+ secondaryModalAction={secondaryDeleteModalAction}
528
+ {...{ isTranslated, deleteAllVersions, setDeleteAllVersions }}
529
+ />
511
530
  </MainWrapper>
512
531
  </>
513
532
  );
@@ -570,6 +589,7 @@ const mapDispatchToProps = {
570
589
  setSelectedContent: pageEditorActions.setSelectedContent,
571
590
  sendPagePing: pageEditorActions.sendPagePing,
572
591
  discardDraft: pageEditorActions.discardDraft,
592
+ deleteBulk: pageEditorActions.deleteBulk,
573
593
  };
574
594
 
575
595
  interface IPageEditorDispatchProps {
@@ -589,6 +609,7 @@ interface IPageEditorDispatchProps {
589
609
  setSelectedContent(editorID: number): void;
590
610
  sendPagePing(pageID: number): Promise<boolean>;
591
611
  discardDraft(): Promise<void>;
612
+ deleteBulk(ids: number[]): Promise<boolean>;
592
613
  }
593
614
 
594
615
  type IProps = IPageEditorStateProps & IPageEditorDispatchProps & RouteComponentProps;
@@ -16,6 +16,10 @@ const NotificationWrapper = styled.div`
16
16
 
17
17
  const ModalContent = styled.div`
18
18
  padding: ${(p) => p.theme.spacing.m};
19
+
20
+ p {
21
+ margin-bottom: ${(p) => p.theme.spacing.m};
22
+ }
19
23
  `;
20
24
 
21
25
  export { Content, NotificationWrapper, ModalContent };
@@ -2,10 +2,10 @@ import React, { useEffect, useState } from "react";
2
2
  import { useParams } from "react-router-dom";
3
3
 
4
4
  import * as components from "components";
5
- import { providers, translations, cloudinaryDefaults, themes, griddoDamDefaults } from "components";
5
+ import { providers, translations, cloudinaryDefaults, griddoDamDefaults } from "components";
6
6
  import { Preview } from "@griddo/core";
7
7
  import { pages } from "@ax/api";
8
- import { isReqOk } from "@ax/helpers";
8
+ import { getDefaultTheme, isReqOk } from "@ax/helpers";
9
9
  import { Loading } from "@ax/components";
10
10
 
11
11
  import * as S from "./style";
@@ -45,8 +45,7 @@ const PublicPreview = () => {
45
45
  const PUBLIC_API_URL = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
46
46
  const { SiteProvider, AnimationProvider } = providers;
47
47
 
48
- const defaultTheme = themes.find((theme: any) => theme.default);
49
- const globalTheme = defaultTheme ? defaultTheme.value : themes[0].value;
48
+ const globalTheme = getDefaultTheme();
50
49
  const theme = state && state.site ? state.siteInfo.theme : globalTheme;
51
50
  const socials = state && state.site ? state.siteInfo.socials : [];
52
51
  const langs = state && state.site ? state.siteInfo.siteLanguages : [];
@@ -56,7 +55,6 @@ const PublicPreview = () => {
56
55
  return (
57
56
  <SiteProvider
58
57
  cloudinaryCloudName={state && state.cloudinaryName}
59
- damDomain={state && state.damDomain}
60
58
  theme={theme}
61
59
  socials={socials}
62
60
  siteLangs={langs}
@@ -8,7 +8,6 @@ const TemplateBrowser = (props: IProps) => {
8
8
  const {
9
9
  socials,
10
10
  cloudinaryName,
11
- damDomain,
12
11
  content: { editorContent, header, footer },
13
12
  selectedEditorID,
14
13
  currentSiteInfo: { theme, id: siteID },
@@ -26,7 +25,6 @@ const TemplateBrowser = (props: IProps) => {
26
25
  url=""
27
26
  theme={theme}
28
27
  cloudinaryName={cloudinaryName}
29
- damDomain={damDomain}
30
28
  siteLangs={siteLangs}
31
29
  siteID={siteID}
32
30
  header={header}
@@ -41,7 +39,6 @@ interface IProps {
41
39
  currentSiteInfo: any;
42
40
  socials: ISocialState;
43
41
  cloudinaryName: string | null;
44
- damDomain: string | null;
45
42
  siteLangs: ILanguage[];
46
43
  }
47
44
 
@@ -51,7 +48,6 @@ const mapStateToProps = (state: IRootState): IProps => ({
51
48
  currentSiteInfo: state.sites.currentSiteInfo,
52
49
  socials: state.social,
53
50
  cloudinaryName: state.app.globalSettings.cloudinaryName,
54
- damDomain: state.app.globalSettings.damDomain,
55
51
  siteLangs: state.sites.currentSiteLanguages,
56
52
  });
57
53
 
@@ -1,9 +1,9 @@
1
1
  import React from "react";
2
2
  import { connect } from "react-redux";
3
- import { themes } from "components";
4
3
 
5
4
  import { ResizePanel } from "@ax/components";
6
5
  import { IRootState } from "@ax/types";
6
+ import { getDefaultTheme } from "@ax/helpers";
7
7
 
8
8
  import TemplateBrowser from "./TemplateBrowser";
9
9
  import ConfigPanel from "./ConfigPanel";
@@ -11,8 +11,7 @@ import ConfigPanel from "./ConfigPanel";
11
11
  const Editor = (props: IProps) => {
12
12
  const { isLoading, template } = props;
13
13
 
14
- const defaultTheme = themes.find((theme: any) => theme.default);
15
- const theme = defaultTheme ? defaultTheme.value : themes[0].value;
14
+ const theme = getDefaultTheme();
16
15
 
17
16
  return (
18
17
  <ResizePanel
@@ -120,7 +120,7 @@ const Form = (props: IProps): JSX.Element => {
120
120
  <Tag
121
121
  key={`${categoryText}-${category.title}`}
122
122
  text={`${categoryText}: ${category.title}`}
123
- deleteAction={handleDeleteTag}
123
+ onDeleteAction={handleDeleteTag}
124
124
  />
125
125
  );
126
126
  })
@@ -13,8 +13,7 @@ import { timezones } from "./constants";
13
13
  import * as S from "./style";
14
14
 
15
15
  const Globals = (props: IProps): JSX.Element => {
16
- const { isSaving, currentSiteInfo, saveSettings, setHistoryPush, navItems, currentNavItem } =
17
- props;
16
+ const { isSaving, currentSiteInfo, saveSettings, setHistoryPush, navItems, currentNavItem } = props;
18
17
 
19
18
  const title = "General settings";
20
19
 
@@ -23,7 +22,8 @@ const Globals = (props: IProps): JSX.Element => {
23
22
 
24
23
  const { isDirty, setIsDirty } = useIsDirty(form);
25
24
 
26
- const setValue = (newValue: Record<string, string | null>) => setForm((state: ISettingsForm) => ({ ...state, ...newValue }));
25
+ const setValue = (newValue: Record<string, string | null>) =>
26
+ setForm((state: ISettingsForm) => ({ ...state, ...newValue }));
27
27
 
28
28
  const setNameValue = (value: string) => setValue({ name: value });
29
29
  const setTimezoneValue = (value: string) => setValue({ timezone: value });
@@ -1,11 +1,10 @@
1
1
  import React, { useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { themes } from "components";
5
4
  import { IDataPack, IErrorItem, IRootState, ISite } from "@ax/types";
6
5
  import { structuredDataActions } from "@ax/containers/StructuredData";
7
6
  import { MainWrapper, ErrorToast, Notification, Loading } from "@ax/components";
8
- import { getActivatedDataPacksIds } from "@ax/helpers";
7
+ import { getActivatedDataPacksIds, getDefaultTheme } from "@ax/helpers";
9
8
  import { appActions } from "@ax/containers/App";
10
9
  import { RouteLeavingGuard } from "@ax/guards";
11
10
  import { useIsDirty } from "@ax/hooks";
@@ -52,8 +51,7 @@ const Form = (props: IProps) => {
52
51
 
53
52
  let title = "";
54
53
 
55
- const defaultTheme = themes.find((theme: any) => theme.default);
56
- const theme = defaultTheme ? defaultTheme.value : themes[0].value;
54
+ const theme = getDefaultTheme();
57
55
 
58
56
  const Fields =
59
57
  fields &&
@@ -35,14 +35,14 @@ const TableHeader = (props: IProps): JSX.Element => {
35
35
  } = props;
36
36
 
37
37
  const activeColumns = Object.keys(columns).filter((col: string) => columns[col].show);
38
-
38
+ const filterCategories = isFromPage ? filterValues.categories : filterValues.related;
39
39
  const CategoryColumns =
40
40
  !isAllPages &&
41
41
  categoryColumns.map(
42
42
  (col: any) =>
43
43
  activeColumns.includes(col.key) && (
44
44
  <S.HeaderWrapper key={col.key}>
45
- <CategoryFilter filterItems={filterItems} value={filterValues.categories} structuredData={col} />
45
+ <CategoryFilter filterItems={filterItems} value={filterCategories} structuredData={col} />
46
46
  </S.HeaderWrapper>
47
47
  )
48
48
  );
@@ -97,30 +97,34 @@ const TableHeader = (props: IProps): JSX.Element => {
97
97
  </S.HeaderWrapper>
98
98
  )}
99
99
  {activeColumns.includes("seo") && <S.SeoHeader>SEO</S.SeoHeader>}
100
- <S.ActionsHeader>
101
- <TableCounter totalItems={totalItems} />
102
- <CustomizeFilters columns={columns} setColumns={setColumns} value={activeColumns} />
103
- </S.ActionsHeader>
104
100
  </>
105
101
  ) : (
106
102
  <>
107
103
  <S.NameWrapper>
108
104
  <NameFilter sortItems={sortItems} sortedState={sortedListStatus} />
109
105
  </S.NameWrapper>
110
- <S.HeaderWrapper>
111
- <LiveFilter filterItems={filterItems} value={filterValues.liveStatus} isStructuredData={true} />
112
- </S.HeaderWrapper>
113
- <S.HeaderWrapper>
114
- <StatusFilter sortItems={sortItems} sortedState={sortedListStatus} isStructuredData={true} />
115
- </S.HeaderWrapper>
116
- <S.HeaderWrapper>
117
- <TranslationsFilter filterItems={filterItems} value={filterValues.translated} />
118
- </S.HeaderWrapper>
119
- <S.ActionsHeader>
120
- <TableCounter totalItems={totalItems} />
121
- </S.ActionsHeader>
106
+ {activeColumns.includes("live") && (
107
+ <S.HeaderWrapper>
108
+ <LiveFilter filterItems={filterItems} value={filterValues.liveStatus} isStructuredData={true} />
109
+ </S.HeaderWrapper>
110
+ )}
111
+ {CategoryColumns}
112
+ {activeColumns.includes("status") && (
113
+ <S.HeaderWrapper>
114
+ <StatusFilter sortItems={sortItems} sortedState={sortedListStatus} isStructuredData={true} />
115
+ </S.HeaderWrapper>
116
+ )}
117
+ {activeColumns.includes("translation") && (
118
+ <S.HeaderWrapper>
119
+ <TranslationsFilter filterItems={filterItems} value={filterValues.translated} />
120
+ </S.HeaderWrapper>
121
+ )}
122
122
  </>
123
123
  )}
124
+ <S.ActionsHeader>
125
+ <TableCounter totalItems={totalItems} />
126
+ <CustomizeFilters columns={columns} setColumns={setColumns} value={activeColumns} />
127
+ </S.ActionsHeader>
124
128
  </S.TableHeader>
125
129
  );
126
130
  };
@@ -1,7 +1,7 @@
1
- import React, { useEffect } from "react";
1
+ import React from "react";
2
2
 
3
3
  import { IModal } from "@ax/types";
4
- import { Modal, FieldsBehavior, ElementsTooltip } from "@ax/components";
4
+ import { Modal, FieldsBehavior } from "@ax/components";
5
5
  import { slugify } from "@ax/helpers";
6
6
 
7
7
  import * as S from "./style";
@@ -124,27 +124,6 @@ const UnpublishModal = (props: IModal): JSX.Element => {
124
124
  );
125
125
  };
126
126
 
127
- const CategoryCell = (props: ICategoryCellProps): JSX.Element => {
128
- const { categories, categoryColors, addCategoryColors } = props;
129
-
130
- useEffect(() => {
131
- addCategoryColors(categories);
132
- // eslint-disable-next-line react-hooks/exhaustive-deps
133
- }, [categories]);
134
-
135
- return (
136
- <S.CategoryCell>
137
- <ElementsTooltip elements={categories} colors={categoryColors} maxChar={30} rounded={true} />
138
- </S.CategoryCell>
139
- );
140
- };
141
-
142
- interface ICategoryCellProps {
143
- categories: any;
144
- categoryColors: any;
145
- addCategoryColors(cats: string[]): void;
146
- }
147
-
148
127
  interface IDeleteModal extends IModal {
149
128
  title: string;
150
129
  isTranslated: boolean;
@@ -157,4 +136,4 @@ interface IDuplicateModal extends IModal {
157
136
  setDuplicateModalState: React.Dispatch<React.SetStateAction<{ title: string; slug: string }>>;
158
137
  }
159
138
 
160
- export { DeleteModal, DuplicateModal, UnpublishModal, CategoryCell };
139
+ export { DeleteModal, DuplicateModal, UnpublishModal };
@@ -5,10 +5,10 @@ import { ICheck, IAvailableSites, ISavePageParams, ILanguage, IPageLanguage, IPa
5
5
  import { getHumanLastModifiedDate, getStructuredDataTitle } from "@ax/helpers";
6
6
  import { appActions } from "@ax/containers/App";
7
7
  import { pageStatus, ISetCurrentPageIDAction } from "@ax/containers/PageEditor/interfaces";
8
- import { CheckField, FloatingMenu, Icon, Flag, LanguageMenu, Tooltip, ElementsTooltip } from "@ax/components";
8
+ import { CheckField, FloatingMenu, Icon, Flag, LanguageMenu, Tooltip, ElementsTooltip, CategoryCell } from "@ax/components";
9
9
  import { pageEditorActions } from "@ax/containers/PageEditor";
10
10
  import { useModal } from "@ax/hooks";
11
- import { DeleteModal, DuplicateModal, UnpublishModal, CategoryCell } from "./atoms";
11
+ import { DeleteModal, DuplicateModal, UnpublishModal } from "./atoms";
12
12
  import { getCurrentLanguages } from "./utils";
13
13
 
14
14
  import * as S from "./style";
@@ -74,12 +74,6 @@ const StyledActionMenu = styled(ActionMenu)`
74
74
  margin-left: auto;
75
75
  `;
76
76
 
77
- const CategoryCell = styled(Cell)`
78
- flex: 0 0 150px;
79
- align-items: center;
80
- position: relative;
81
- `;
82
-
83
77
  const StructuredDataRow = styled(Row)<{ disabled: boolean }>`
84
78
  cursor: ${(p) => (p.disabled ? "default" : "pointer")};
85
79
  &:hover {
@@ -171,5 +165,4 @@ export {
171
165
  StyledClose,
172
166
  FloatingSeo,
173
167
  ModalContent,
174
- CategoryCell,
175
168
  };
@@ -1,8 +1,7 @@
1
1
  import React, { useReducer, useEffect } from "react";
2
- import { themes } from "components";
3
2
 
4
3
  import { IStructuredDataFilter, IStructuredDataValue } from "@ax/types";
5
- import { getThumbnailProps } from "@ax/helpers";
4
+ import { getDefaultTheme, getThumbnailProps } from "@ax/helpers";
6
5
  import { MenuItem, RadioGroup } from "@ax/components";
7
6
 
8
7
  import { reducer, IOptionTableStore, setColumnValues, setShowThumbnail, setSelectedType, setOption } from "./store";
@@ -49,8 +48,7 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
49
48
  return columns.includes(optionValues[0]);
50
49
  };
51
50
 
52
- const defaultTheme = themes.find((theme: any) => theme.default);
53
- const theme = defaultTheme ? defaultTheme.value : themes[0].value;
51
+ const theme = getDefaultTheme();
54
52
 
55
53
  const thumbnailProps =
56
54
  state.showThumbnail &&
@@ -1,12 +1,12 @@
1
1
  import React, { memo } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { IRootState, IStructuredDataContent, ICheck, IDataPack, ILanguage, IDataLanguage } from "@ax/types";
4
+ import { IRootState, IStructuredDataContent, ICheck, IDataPack, ILanguage, IDataLanguage, IColumn } from "@ax/types";
5
5
  import { getActivatedDataPacksIds, getHumanLastModifiedDate } from "@ax/helpers";
6
6
  import { setIsSavedData } from "@ax/forms";
7
7
  import { structuredDataActions } from "@ax/containers/StructuredData";
8
8
  import { appActions } from "@ax/containers/App";
9
- import { CheckField, FloatingMenu, Icon, Flag, LanguageMenu, Tooltip } from "@ax/components";
9
+ import { CheckField, FloatingMenu, Icon, Flag, LanguageMenu, Tooltip, CategoryCell } from "@ax/components";
10
10
 
11
11
  import * as S from "./style";
12
12
 
@@ -29,11 +29,21 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
29
29
  isEditable,
30
30
  activatedDataPacks,
31
31
  setDataStatus,
32
+ categoryColumns,
33
+ columns,
34
+ categoryColors,
35
+ addCategoryColors,
32
36
  } = props;
33
37
 
34
38
  const { locale } = lang;
35
39
  const { dataLanguages } = structuredData;
36
40
 
41
+ const currentStructuredDataColumns: any = columns[currentStructuredData.id] || columns["all"];
42
+
43
+ const activeColumns = Object.keys(currentStructuredDataColumns).filter(
44
+ (col: string) => currentStructuredDataColumns[col].show
45
+ );
46
+
37
47
  const publishedTooltip: Record<string, string> = {
38
48
  active: "Live",
39
49
  "upload-pending": "Publication pending",
@@ -141,9 +151,7 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
141
151
 
142
152
  const translations =
143
153
  currentStructuredData && currentStructuredData.translate ? (
144
- <FloatingMenu Button={FlagsButton}>
145
- {languageMenu()}
146
- </FloatingMenu>
154
+ <FloatingMenu Button={FlagsButton}>{languageMenu()}</FloatingMenu>
147
155
  ) : (
148
156
  "Not translatable"
149
157
  );
@@ -169,6 +177,21 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
169
177
  const menuOptionsNoDuplicate = isEditable ? [deleteOption, publishOption] : [publishOption];
170
178
  const menuOptions = isDisabled || !isEditable ? menuOptionsNoDuplicate : [duplicateOption, ...menuOptionsNoDuplicate];
171
179
 
180
+ const CategoryColumns = categoryColumns.map((col: any) => {
181
+ const type = structuredData && structuredData.content && structuredData.content[col.from];
182
+ const categories = Array.isArray(type) && type.map((cat: any) => cat.label || cat.title);
183
+ return (
184
+ activeColumns.includes(col.key) && (
185
+ <CategoryCell
186
+ key={col.key}
187
+ categories={categories}
188
+ categoryColors={categoryColors}
189
+ addCategoryColors={addCategoryColors}
190
+ />
191
+ )
192
+ );
193
+ });
194
+
172
195
  return (
173
196
  <S.StructuredDataRow role="rowgroup" selected={isSelected} disabled={!isEditable}>
174
197
  <S.CheckCell role="cell">
@@ -177,15 +200,20 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
177
200
  <S.NameCell role="cell" onClick={_handleClick}>
178
201
  {structuredData.content.title}
179
202
  </S.NameCell>
180
- <S.LiveCell role="cell" onClick={_handleClick}>
181
- <Tooltip content={publishedTooltip[checkStatus()]}>
182
- <Icon name={checkStatus()} />
183
- </Tooltip>
184
- </S.LiveCell>
185
- <S.StatusCell role="cell" onClick={_handleClick}>
186
- <S.ModDate>{`Mod. ${getHumanLastModifiedDate(structuredData.modified)}`}</S.ModDate>
187
- </S.StatusCell>
188
- <S.TransCell role="cell">{translations}</S.TransCell>
203
+ {activeColumns.includes("live") && (
204
+ <S.LiveCell role="cell" onClick={_handleClick}>
205
+ <Tooltip content={publishedTooltip[checkStatus()]}>
206
+ <Icon name={checkStatus()} />
207
+ </Tooltip>
208
+ </S.LiveCell>
209
+ )}
210
+ {CategoryColumns}
211
+ {activeColumns.includes("status") && (
212
+ <S.StatusCell role="cell" onClick={_handleClick}>
213
+ <S.ModDate>{`Mod. ${getHumanLastModifiedDate(structuredData.modified)}`}</S.ModDate>
214
+ </S.StatusCell>
215
+ )}
216
+ {activeColumns.includes("translation") && <S.TransCell role="cell">{translations}</S.TransCell>}
189
217
  <S.ActionsCell role="cell">
190
218
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
191
219
  </S.ActionsCell>
@@ -212,6 +240,10 @@ interface IStructuredDataItemProps {
212
240
  isEditable?: boolean | null;
213
241
  activatedDataPacks?: IDataPack[];
214
242
  setDataStatus(id: number, status: string): void;
243
+ categoryColumns: any[];
244
+ columns: Record<string, IColumn>;
245
+ categoryColors: any;
246
+ addCategoryColors(cats: string[]): void;
215
247
  }
216
248
 
217
249
  const mapStateToProps = (state: IRootState) => ({
@@ -1,5 +1,5 @@
1
- import { useState } from "react";
2
- import { IStructuredDataQueryValues, IStructuredDataSortedInitialState } from "@ax/types";
1
+ import { useEffect, useState } from "react";
2
+ import { IStructuredData, IStructuredDataQueryValues, IStructuredDataSortedInitialState } from "@ax/types";
3
3
 
4
4
  const useSortedListStatus = (): IUseSortedListStatus => {
5
5
  const sortedInitialState: IStructuredDataSortedInitialState = {
@@ -17,7 +17,8 @@ const useSortedListStatus = (): IUseSortedListStatus => {
17
17
  };
18
18
  };
19
19
 
20
- const useFilterQuery = (): IUseFilterQuery => {
20
+ const useFilterQuery = (currentStructuredData: IStructuredData | null): IUseFilterQuery => {
21
+ const structuredDataType = currentStructuredData ? currentStructuredData.id : "all";
21
22
  const initialQueryValues = {
22
23
  types: "all",
23
24
  translated: "all",
@@ -25,12 +26,20 @@ const useFilterQuery = (): IUseFilterQuery => {
25
26
  order: "",
26
27
  filterSites: "all",
27
28
  categories: "all",
29
+ related: "all",
28
30
  };
29
31
 
30
- const [query, setQuery] = useState(initialQueryValues);
32
+ const [query, setQuery] = useState<Record<string, IStructuredDataQueryValues>>({ all: initialQueryValues });
33
+
34
+ useEffect(() => {
35
+ if (!query[structuredDataType]) {
36
+ setQuery((state) => ({ [structuredDataType]: initialQueryValues, ...state }));
37
+ }
38
+ // eslint-disable-next-line react-hooks/exhaustive-deps
39
+ }, [structuredDataType]);
31
40
 
32
41
  const setFilterQuery = (filterValues: IStructuredDataQueryValues) => {
33
- const { types, translated, liveStatus, order, filterSites, categories } = filterValues;
42
+ const { types, translated, liveStatus, order, filterSites, categories, related } = filterValues;
34
43
  let filterQuery = "";
35
44
 
36
45
  const currentQuery = (pointer: string, values: string) => {
@@ -47,12 +56,14 @@ const useFilterQuery = (): IUseFilterQuery => {
47
56
  if (isNotInitialValue("order")) filterQuery = currentQuery("order", order);
48
57
  if (isNotInitialValue("filterSites")) filterQuery = currentQuery("filterSites", filterSites);
49
58
  if (isNotInitialValue("categories")) filterQuery = currentQuery("categories", categories);
59
+ if (isNotInitialValue("related")) filterQuery = currentQuery("related", related);
50
60
 
51
61
  return filterQuery;
52
62
  };
53
63
 
54
64
  const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
55
- const { types, translated, liveStatus, order, filterSites, categories } = query;
65
+ const { types, translated, liveStatus, order, filterSites, categories, related } =
66
+ query[structuredDataType] || initialQueryValues;
56
67
  const orderMethod = isAscendent ? "asc" : "desc";
57
68
  const filterValues = {
58
69
  types: pointer === "types" ? filter : types,
@@ -61,14 +72,15 @@ const useFilterQuery = (): IUseFilterQuery => {
61
72
  order: pointer === "order" ? `${filter}-${orderMethod}` : order,
62
73
  filterSites: pointer === "filterSites" ? filter : filterSites,
63
74
  categories: pointer === "categories" ? filter : categories,
75
+ related: pointer === "related" ? filter : related,
64
76
  };
65
77
 
66
- setQuery(filterValues);
78
+ setQuery((state) => ({ ...state, [structuredDataType]: filterValues }));
67
79
 
68
80
  return filterValues;
69
81
  };
70
82
 
71
- const resetFilterQuery = () => setQuery(initialQueryValues);
83
+ const resetFilterQuery = () => setQuery({ [structuredDataType]: initialQueryValues });
72
84
 
73
85
  return {
74
86
  setFiltersSelection,
@@ -87,7 +99,7 @@ interface IUseFilterQuery {
87
99
  setFiltersSelection(pointer: string, filter: string, isAscendent?: boolean): IStructuredDataQueryValues;
88
100
  setFilterQuery(filterValues: IStructuredDataQueryValues): string;
89
101
  resetFilterQuery(): void;
90
- filterValues: IStructuredDataQueryValues;
102
+ filterValues: Record<string, IStructuredDataQueryValues>;
91
103
  }
92
104
 
93
105
  export { useSortedListStatus, useFilterQuery };