@griddo/ax 10.3.23 → 10.3.25

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 (126) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/components/Gallery/GalleryFilters/Orientation/Orientation.test.tsx +5 -2
  3. package/src/__tests__/components/Gallery/GalleryFilters/SortBy/SortBy.test.tsx +5 -4
  4. package/src/__tests__/components/Gallery/GalleryFilters/Type/Type.test.tsx +5 -2
  5. package/src/__tests__/components/TableFilters/CategoryFilter/CategoryFilter.test.tsx +12 -11
  6. package/src/__tests__/components/TableFilters/DateFilter/DateFilter.test.tsx +17 -16
  7. package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +14 -13
  8. package/src/__tests__/components/TableFilters/NameFilter/NameFilter.test.tsx +21 -20
  9. package/src/__tests__/components/TableFilters/RoleFilter/RoleFilter.test.tsx +6 -5
  10. package/src/__tests__/components/TableFilters/SiteFilter/SiteFilter.test.tsx +8 -7
  11. package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +21 -20
  12. package/src/__tests__/components/TableFilters/TranslationsFilter/TranslationsFilter.test.tsx +24 -23
  13. package/src/__tests__/components/TableFilters/TypeFilter/TypeFilter.test.tsx +6 -5
  14. package/src/__tests__/components/TableFilters/UsersFilter/UsersFilter.test.tsx +17 -16
  15. package/src/api/sites.tsx +5 -9
  16. package/src/components/Button/index.tsx +3 -1
  17. package/src/components/Button/style.tsx +6 -0
  18. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx +2 -2
  19. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +1 -1
  20. package/src/components/Fields/ArrayFieldGroup/ArrayFieldInline/index.tsx +3 -2
  21. package/src/components/Fields/ArrayFieldGroup/ArrayFieldItem/index.tsx +3 -1
  22. package/src/components/Fields/ArrayFieldGroup/index.tsx +5 -2
  23. package/src/components/Fields/CheckField/style.tsx +2 -2
  24. package/src/components/Fields/ColorPicker/index.tsx +4 -2
  25. package/src/components/Fields/ColorPicker/style.tsx +4 -0
  26. package/src/components/Fields/DateField/DatePickerInput/index.tsx +1 -1
  27. package/src/components/Fields/FileField/index.tsx +3 -1
  28. package/src/components/Fields/FileField/style.tsx +9 -4
  29. package/src/components/Fields/SliderField/index.tsx +4 -2
  30. package/src/components/Fields/SliderField/style.tsx +53 -4
  31. package/src/components/Fields/TimeField/style.tsx +6 -5
  32. package/src/components/FileGallery/index.tsx +26 -16
  33. package/src/components/FileGallery/style.tsx +12 -1
  34. package/src/components/FilterTagsBar/index.tsx +61 -0
  35. package/src/components/FilterTagsBar/style.tsx +30 -0
  36. package/src/components/FloatingMenu/index.tsx +5 -1
  37. package/src/components/Gallery/GalleryFilters/Orientation/index.tsx +14 -6
  38. package/src/components/Gallery/GalleryFilters/SortBy/index.tsx +24 -8
  39. package/src/components/Gallery/GalleryFilters/Type/index.tsx +22 -9
  40. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +2 -1
  41. package/src/components/Gallery/hooks.tsx +37 -23
  42. package/src/components/Gallery/index.tsx +38 -20
  43. package/src/components/Gallery/style.tsx +15 -2
  44. package/src/components/MainWrapper/AppBar/index.tsx +3 -0
  45. package/src/components/MainWrapper/index.tsx +1 -0
  46. package/src/components/SearchTagsBar/index.tsx +43 -0
  47. package/src/components/SearchTagsBar/style.tsx +30 -0
  48. package/src/components/TableFilters/CategoryFilter/index.tsx +17 -10
  49. package/src/components/TableFilters/CheckGroupFilter/index.tsx +12 -9
  50. package/src/components/TableFilters/DateFilter/index.tsx +3 -2
  51. package/src/components/TableFilters/LastAccessFilter/index.tsx +4 -4
  52. package/src/components/TableFilters/LiveFilter/index.tsx +26 -22
  53. package/src/components/TableFilters/NameFilter/index.tsx +4 -3
  54. package/src/components/TableFilters/PermissionsFilter/index.tsx +4 -3
  55. package/src/components/TableFilters/RoleFilter/index.tsx +17 -7
  56. package/src/components/TableFilters/SiteFilter/index.tsx +23 -8
  57. package/src/components/TableFilters/StateFilter/index.tsx +15 -6
  58. package/src/components/TableFilters/StatusFilter/index.tsx +3 -2
  59. package/src/components/TableFilters/TranslationsFilter/index.tsx +19 -11
  60. package/src/components/TableFilters/TypeFilter/index.tsx +9 -5
  61. package/src/components/TableFilters/UsersFilter/index.tsx +4 -3
  62. package/src/components/Tag/index.tsx +5 -4
  63. package/src/components/index.tsx +4 -0
  64. package/src/containers/Navigation/Menu/actions.tsx +1 -13
  65. package/src/containers/Navigation/Menu/constants.tsx +0 -1
  66. package/src/containers/Navigation/Menu/interfaces.tsx +1 -7
  67. package/src/containers/Navigation/Menu/reducer.tsx +0 -4
  68. package/src/containers/Sites/actions.tsx +2 -1
  69. package/src/containers/Sites/interfaces.tsx +2 -2
  70. package/src/containers/Sites/reducer.tsx +2 -2
  71. package/src/containers/StructuredData/actions.tsx +2 -1
  72. package/src/forms/editor.tsx +1 -1
  73. package/src/modules/Categories/CategoriesList/CategoryItem/style.tsx +2 -0
  74. package/src/modules/Content/BulkHeader/TableHeader/index.tsx +26 -14
  75. package/src/modules/Content/BulkHeader/index.tsx +3 -3
  76. package/src/modules/Content/PageItem/index.tsx +21 -23
  77. package/src/modules/Content/PageItem/style.tsx +2 -0
  78. package/src/modules/Content/hooks.tsx +23 -13
  79. package/src/modules/Content/index.tsx +44 -11
  80. package/src/modules/Content/style.tsx +19 -1
  81. package/src/modules/FileDrive/Breadcrumb/style.tsx +1 -1
  82. package/src/modules/FileDrive/FileDragAndDrop/index.tsx +7 -6
  83. package/src/modules/FileDrive/FileDragAndDrop/style.tsx +2 -0
  84. package/src/modules/FileDrive/FileFilters/SortBy/index.tsx +24 -8
  85. package/src/modules/FileDrive/FileFilters/Type/index.tsx +26 -22
  86. package/src/modules/FileDrive/hooks.tsx +28 -13
  87. package/src/modules/FileDrive/index.tsx +31 -18
  88. package/src/modules/FileDrive/style.tsx +20 -1
  89. package/src/modules/Navigation/Defaults/Item/style.tsx +2 -0
  90. package/src/modules/Navigation/Menus/List/Nav/index.tsx +10 -12
  91. package/src/modules/Navigation/Menus/List/Table/SidePanel/index.tsx +0 -2
  92. package/src/modules/Navigation/Menus/List/index.tsx +8 -5
  93. package/src/modules/Redirects/BulkHeader/TableHeader/index.tsx +4 -2
  94. package/src/modules/Redirects/BulkHeader/index.tsx +3 -2
  95. package/src/modules/Redirects/hooks.tsx +23 -15
  96. package/src/modules/Redirects/index.tsx +61 -44
  97. package/src/modules/Redirects/style.tsx +10 -0
  98. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/index.tsx +7 -11
  99. package/src/modules/Settings/Integrations/BulkHeader/index.tsx +4 -8
  100. package/src/modules/Settings/Integrations/hooks.tsx +23 -19
  101. package/src/modules/Settings/Integrations/index.tsx +22 -26
  102. package/src/modules/Settings/Integrations/style.tsx +7 -0
  103. package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/index.tsx +8 -7
  104. package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +10 -5
  105. package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +4 -3
  106. package/src/modules/Sites/SitesList/hooks.tsx +26 -20
  107. package/src/modules/Sites/SitesList/index.tsx +53 -22
  108. package/src/modules/Sites/SitesList/style.tsx +16 -0
  109. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +3 -3
  110. package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +3 -3
  111. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +3 -3
  112. package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/style.tsx +2 -0
  113. package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/style.tsx +2 -0
  114. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +25 -15
  115. package/src/modules/StructuredData/StructuredDataList/index.tsx +57 -14
  116. package/src/modules/StructuredData/StructuredDataList/style.tsx +10 -1
  117. package/src/modules/Users/Roles/BulkHeader/TableHeader/index.tsx +2 -2
  118. package/src/modules/Users/Roles/BulkHeader/index.tsx +2 -5
  119. package/src/modules/Users/Roles/hooks.tsx +24 -15
  120. package/src/modules/Users/Roles/index.tsx +7 -18
  121. package/src/modules/Users/UserList/BulkHeader/TableHeader/index.tsx +5 -18
  122. package/src/modules/Users/UserList/BulkHeader/index.tsx +15 -13
  123. package/src/modules/Users/UserList/hooks.tsx +27 -25
  124. package/src/modules/Users/UserList/index.tsx +69 -43
  125. package/src/modules/Users/UserList/style.tsx +10 -1
  126. package/src/types/index.tsx +19 -13
@@ -11,7 +11,7 @@ import {
11
11
  LiveFilter,
12
12
  TranslationsFilter,
13
13
  } from "@ax/components";
14
- import { IColumn } from "@ax/types";
14
+ import { IColumn, IQueryValue } from "@ax/types";
15
15
 
16
16
  import * as S from "./style";
17
17
 
@@ -84,13 +84,25 @@ const TableHeader = (props: IProps): JSX.Element => {
84
84
  </S.CheckHeader>
85
85
  {isStructuredData ? (
86
86
  <>
87
- <S.NameHeader>Name</S.NameHeader>
88
- <S.LiveHeader>Live</S.LiveHeader>
89
- <S.StatusHeader>Status</S.StatusHeader>
90
- <S.TransHeader>Translations</S.TransHeader>
91
- <S.ActionsHeader>
92
- <TableCounter totalItems={totalItems} />
93
- </S.ActionsHeader>
87
+ <S.NameWrapper>
88
+ <NameFilter sortItems={sortItems} sortedState={sortedListStatus} />
89
+ </S.NameWrapper>
90
+ {activeColumns.includes("live") && (
91
+ <S.HeaderWrapper>
92
+ <LiveFilter filterItems={filterItems} value={filterValues.liveStatus} hasBasicStatus={true} />
93
+ </S.HeaderWrapper>
94
+ )}
95
+ {CategoryColumns}
96
+ {activeColumns.includes("status") && (
97
+ <S.HeaderWrapper>
98
+ <StatusFilter sortItems={sortItems} sortedState={sortedListStatus} isStructuredData={true} />
99
+ </S.HeaderWrapper>
100
+ )}
101
+ {activeColumns.includes("translation") && (
102
+ <S.HeaderWrapper>
103
+ <TranslationsFilter filterItems={filterItems} value={filterValues.translated} />
104
+ </S.HeaderWrapper>
105
+ )}
94
106
  </>
95
107
  ) : (
96
108
  <>
@@ -120,12 +132,12 @@ const TableHeader = (props: IProps): JSX.Element => {
120
132
  )}
121
133
  {activeColumns.includes("seo") && <S.SeoHeader>SEO</S.SeoHeader>}
122
134
  <S.GlobalMark />
123
- <S.ActionsHeader>
124
- <TableCounter totalItems={totalItems} />
125
- <CustomizeFilters columns={columns} setColumns={setColumns} value={activeColumns} />
126
- </S.ActionsHeader>
127
135
  </>
128
136
  )}
137
+ <S.ActionsHeader>
138
+ <TableCounter totalItems={totalItems} />
139
+ <CustomizeFilters columns={columns} setColumns={setColumns} value={activeColumns} />
140
+ </S.ActionsHeader>
129
141
  </S.TableHeader>
130
142
  );
131
143
  };
@@ -136,8 +148,8 @@ interface IProps {
136
148
  totalItems: number;
137
149
  selectAllItems: () => void;
138
150
  checkState: Record<string, boolean>;
139
- sortItems: (orderPointer: string, isAscending: boolean) => void;
140
- filterItems: (filterPointer: string, filtersSelected: string) => void;
151
+ sortItems: (orderPointer: IQueryValue[], isAscending: boolean) => void;
152
+ filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
141
153
  sortedListStatus: { isAscending: boolean; sortedByDate: boolean; sortedByTitle: boolean; sortedByURL: boolean };
142
154
  categoryColumns: any[];
143
155
  columns: Record<string, IColumn>;
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { BulkSelectionOptions } from "@ax/components";
3
- import { IColumn } from "@ax/types";
3
+ import { IColumn, IQueryValue } from "@ax/types";
4
4
  import { usePermission } from "@ax/hooks";
5
5
  import TableHeader from "./TableHeader";
6
6
 
@@ -91,8 +91,8 @@ interface IProps {
91
91
  totalItems: number;
92
92
  isScrolling: boolean;
93
93
  isStructuredData: boolean;
94
- sortItems: (orderPointer: string, isAscending: boolean) => void;
95
- filterItems: (filterPointer: string, filtersSelected: string) => void;
94
+ sortItems: (orderPointer: IQueryValue[], isAscending: boolean) => void;
95
+ filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
96
96
  sortedListStatus: any;
97
97
  isEditable?: boolean | null;
98
98
  filterValues: any;
@@ -467,27 +467,25 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
467
467
 
468
468
  const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };
469
469
 
470
- const CategoryColumns =
471
- isGlobal &&
472
- categoryColumns.map((col: any) => {
473
- const type: any = structuredDataContent && structuredDataContent[col.key];
474
- const categories: string[] = !type
475
- ? []
476
- : Array.isArray(type)
477
- ? type.map((cat: any) => cat.label || cat.title)
478
- : [type.label || type.title];
470
+ const CategoryColumns = categoryColumns.map((col: any) => {
471
+ const type: any = structuredDataContent && structuredDataContent[col.key];
472
+ const categories: string[] = !type
473
+ ? []
474
+ : Array.isArray(type)
475
+ ? type.map((cat: any) => cat.label || cat.title)
476
+ : [type.label || type.title];
479
477
 
480
- return (
481
- activeColumns.includes(col.key) && (
482
- <CategoryCell
483
- key={col.key}
484
- categories={categories}
485
- categoryColors={categoryColors}
486
- addCategoryColors={addCategoryColors}
487
- />
488
- )
489
- );
490
- });
478
+ return (
479
+ activeColumns.includes(col.key) && (
480
+ <CategoryCell
481
+ key={col.key}
482
+ categories={categories}
483
+ categoryColors={categoryColors}
484
+ addCategoryColors={addCategoryColors}
485
+ />
486
+ )
487
+ );
488
+ });
491
489
 
492
490
  return (
493
491
  <>
@@ -504,11 +502,11 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
504
502
  )}
505
503
  <Tooltip
506
504
  content={[
507
- <>
505
+ <React.Fragment key="page-title">
508
506
  <strong>{page.title}</strong>
509
507
  <br />
510
- </>,
511
- <>{fullPath.page}</>,
508
+ </React.Fragment>,
509
+ <React.Fragment key="page-slug">{fullPath.page}</React.Fragment>,
512
510
  ]}
513
511
  left={0}
514
512
  top={1}
@@ -178,6 +178,8 @@ const FlagsWrapper = styled.div`
178
178
  svg {
179
179
  margin-right: 2px;
180
180
  margin-bottom: -3px;
181
+ display: inline;
182
+ vertical-align: baseline;
181
183
  }
182
184
  `;
183
185
 
@@ -1,4 +1,5 @@
1
1
  import { useState } from "react";
2
+ import { IQueryValue } from "@ax/types";
2
3
 
3
4
  const useSortedListStatus = () => {
4
5
  const sortedInitialState: {
@@ -21,21 +22,30 @@ const useSortedListStatus = () => {
21
22
  };
22
23
  };
23
24
 
24
- const useFilterQuery = (values?: Record<string, string> | null) => {
25
- const initialQueryValues = {
26
- type: "all",
27
- translated: "all",
28
- liveStatus: "all",
29
- order: "",
30
- categories: "all",
25
+ const useFilterQuery = (values?: Record<string, IQueryValue[]> | null) => {
26
+ const initialQueryValues: Record<string, IQueryValue[]> = {
27
+ type: [{ value: "all", label: "All" }],
28
+ translated: [{ value: "all", label: "All" }],
29
+ liveStatus: [{ value: "all", label: "All" }],
30
+ order: [],
31
+ categories: [{ value: "all", label: "All" }],
31
32
  };
32
33
 
33
- const getFilterQuery = (filterValues: any) => {
34
+ const getFilterQuery = (filterValues: Record<string, IQueryValue[]>): string => {
34
35
  const { type, translated, liveStatus, order, categories } = filterValues;
35
36
  let filterQuery = "";
36
37
 
37
- const currentQuery = (pointer: string, values: string) => {
38
- return filterQuery ? filterQuery.concat(`&${pointer}=${values}`) : `?${pointer}=${values}`;
38
+ const currentQuery = (pointer: string, values: IQueryValue[]): string => {
39
+ const stringValues =
40
+ Array.isArray(values) && values.length
41
+ ? values.map((value) => (value.value !== "all" ? value.value : "")).join(",")
42
+ : "";
43
+
44
+ return !stringValues.length
45
+ ? filterQuery
46
+ : filterQuery.length
47
+ ? filterQuery.concat(`&${pointer}=${stringValues}`)
48
+ : `&${pointer}=${stringValues}`;
39
49
  };
40
50
 
41
51
  if (type) {
@@ -67,14 +77,14 @@ const useFilterQuery = (values?: Record<string, string> | null) => {
67
77
  const initQuery = values ? getFilterQuery(values) : "";
68
78
  const [query, setQuery] = useState(initQuery);
69
79
 
70
- const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
80
+ const setFiltersSelection = (pointer: string, filter: IQueryValue[], isAscendent?: boolean) => {
71
81
  const { type, translated, liveStatus, order, categories } = state;
72
82
  const orderMethod = isAscendent ? "asc" : "desc";
73
- const filterValues = {
83
+ const filterValues: Record<string, IQueryValue[]> = {
74
84
  type: pointer === "type" ? filter : type,
75
85
  translated: pointer === "translated" ? filter : translated,
76
86
  liveStatus: pointer === "liveStatus" ? filter : liveStatus,
77
- order: pointer === "order" ? `${filter}-${orderMethod}` : order,
87
+ order: pointer === "order" ? [{ value: `${filter[0].value}-${orderMethod}`, label: filter[0].label }] : order,
78
88
  categories: pointer === "categories" ? filter : categories,
79
89
  };
80
90
 
@@ -20,8 +20,19 @@ import {
20
20
  IGetSitesParams,
21
21
  ISiteRoles,
22
22
  IPageLanguage,
23
+ IQueryValue,
23
24
  } from "@ax/types";
24
- import { MainWrapper, Modal, TableList, ErrorToast, Toast, EmptyState, Notification } from "@ax/components";
25
+ import {
26
+ MainWrapper,
27
+ Modal,
28
+ TableList,
29
+ ErrorToast,
30
+ Toast,
31
+ EmptyState,
32
+ Notification,
33
+ SearchTagsBar,
34
+ FilterTagsBar,
35
+ } from "@ax/components";
25
36
  import { isGlobalStructuredData, isStructuredDataFromPage } from "@ax/helpers";
26
37
 
27
38
  import { appActions } from "@ax/containers/App";
@@ -256,7 +267,7 @@ const Content = (props: IProps): JSX.Element => {
256
267
  async (filterQuery?: any) => {
257
268
  const params = getParams();
258
269
  isStructuredData && params.siteID
259
- ? await getStructuredDataContents(params, params.siteID)
270
+ ? await getStructuredDataContents({...params, filterQuery }, params.siteID)
260
271
  : getPages(params, filterQuery);
261
272
  },
262
273
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -290,7 +301,7 @@ const Content = (props: IProps): JSX.Element => {
290
301
  resetPageEditor();
291
302
  resetCurrentSiteErrorPages();
292
303
  fetchSitesByLang();
293
- getIntegrations(currentSiteInfo.id);
304
+ getIntegrations(currentSiteInfo.id, {}, true);
294
305
  getDefaults();
295
306
  resetForm();
296
307
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -301,7 +312,12 @@ const Content = (props: IProps): JSX.Element => {
301
312
  const isContentType = filter !== "unique-pages";
302
313
  const emptyState: IEmptyStateProps = {};
303
314
  const { liveStatus, translated, type } = filterValues;
304
- const isSearching = searchQuery.length > 0 || liveStatus !== "all" || translated !== "all" || type !== "all";
315
+ const isSearching =
316
+ searchQuery.length > 0 ||
317
+ (liveStatus.length && liveStatus[0].value !== "all") ||
318
+ (translated.length && translated[0].value !== "all") ||
319
+ (type.length && type[0].value !== "all");
320
+
305
321
  if (isSearching) {
306
322
  emptyState.icon = "search";
307
323
  emptyState.title = "Oh! No Results Found";
@@ -499,15 +515,15 @@ const Content = (props: IProps): JSX.Element => {
499
515
 
500
516
  const bulkUnpublish = () => (isStructuredData ? setDataStatus(selectedItems.all, "draft") : bulkPublishAction(false));
501
517
 
502
- const sortItems = async (orderPointer: string, isAscending: boolean) => {
518
+ const sortItems = (orderPointer: IQueryValue[], isAscending: boolean) => {
503
519
  setPage(firstPage);
504
- const sortedState = getSortedListStatus(orderPointer, isAscending);
520
+ const sortedState = getSortedListStatus(orderPointer[0].value.toString(), isAscending);
505
521
  setSortedListStatus(sortedState);
506
522
 
507
523
  setFiltersSelection("order", orderPointer, isAscending);
508
524
  };
509
525
 
510
- const filterItems = async (filterPointer: string, filtersSelected: string) => {
526
+ const filterItems = (filterPointer: string, filtersSelected: IQueryValue[]) => {
511
527
  setPage(firstPage);
512
528
  setFiltersSelection(filterPointer, filtersSelected);
513
529
  };
@@ -794,6 +810,13 @@ const Content = (props: IProps): JSX.Element => {
794
810
  const notEditableText =
795
811
  "Sorry, this content cannot be edited because it comes from an external source or belongs to a preconfigured system.";
796
812
 
813
+ const filterLabels = {
814
+ type: "Type",
815
+ liveStatus: "Live",
816
+ translated: "Translated",
817
+ categories: "Category",
818
+ };
819
+
797
820
  return (
798
821
  <MainWrapper
799
822
  title={title}
@@ -803,6 +826,7 @@ const Content = (props: IProps): JSX.Element => {
803
826
  rightButton={rightButtonProps}
804
827
  searchAction={setSearchQuery}
805
828
  errors={errors}
829
+ searchValue={searchQuery}
806
830
  >
807
831
  <S.ContentListWrapper>
808
832
  <ContentFilters current={filter} dynamicValues={structuredData} resetFilter={resetFilter} />
@@ -835,8 +859,17 @@ const Content = (props: IProps): JSX.Element => {
835
859
  hasFixedHeader={true}
836
860
  tableRef={tableRef}
837
861
  >
862
+ <S.SearchTags>
863
+ <SearchTagsBar query={searchQuery} setQuery={setSearchQuery} />
864
+ <FilterTagsBar
865
+ filters={filterValues}
866
+ setFilters={setFiltersSelection}
867
+ resetFilters={resetFilterQuery}
868
+ labels={filterLabels}
869
+ />
870
+ </S.SearchTags>
838
871
  {!isEmpty ? (
839
- content
872
+ <>{content}</>
840
873
  ) : (
841
874
  <S.EmptyWrapper>
842
875
  <EmptyState {...emptyStateProps} />
@@ -938,9 +971,9 @@ interface IDispatchProps {
938
971
  restorePage(id: number | number[]): Promise<boolean>;
939
972
  getDataPack: (id: string) => Promise<void>;
940
973
  resetCurrentSiteErrorPages: () => Promise<void>;
941
- getIntegrations(site: number): Promise<void>;
974
+ getIntegrations(site: number, params?: any, skipLoading?: boolean): Promise<void>;
942
975
  getSitesByLang(params: IGetSitesParams): Promise<void>;
943
- setContentFilters(contentFilters: Record<string, string> | null): void;
976
+ setContentFilters(contentFilters: Record<string, IQueryValue[]> | null): void;
944
977
  deleteAndRemoveFromSiteBulk(pageIds: number[], globalPageIds: number[]): Promise<boolean>;
945
978
  checkUserSession(): Promise<void>;
946
979
  getDefaults(): Promise<void>;
@@ -1008,7 +1041,7 @@ interface IPagesProps {
1008
1041
  sitesByLang: ISite[];
1009
1042
  user: IUser | null;
1010
1043
  skipReviewOnPublish?: boolean;
1011
- contentFilters: Record<string, string> | null;
1044
+ contentFilters: Record<string, IQueryValue[]> | null;
1012
1045
  error: IError;
1013
1046
  }
1014
1047
 
@@ -46,4 +46,22 @@ const NotificationWrapper = styled.div`
46
46
  width: 100%;
47
47
  `;
48
48
 
49
- export { ContentListWrapper, TableWrapper, PaginationWrapper, EmptyWrapper, ModalContent, SelectWrapper, NotificationWrapper };
49
+ const SearchTags = styled.div`
50
+ & > div:nth-child(1) {
51
+ margin-bottom: ${(p) => p.theme.spacing.xs};
52
+ }
53
+ & > div:nth-child(2) {
54
+ margin-bottom: ${(p) => p.theme.spacing.xs};
55
+ }
56
+ `;
57
+
58
+ export {
59
+ ContentListWrapper,
60
+ TableWrapper,
61
+ PaginationWrapper,
62
+ EmptyWrapper,
63
+ ModalContent,
64
+ SelectWrapper,
65
+ NotificationWrapper,
66
+ SearchTags,
67
+ };
@@ -4,7 +4,7 @@ const BreadcrumbGroup = styled.div`
4
4
  display: flex;
5
5
  align-items: center;
6
6
  flex-wrap: wrap;
7
- padding: ${p => `${p.theme.spacing.s} ${p.theme.spacing.m} 0 ${p.theme.spacing.m}`};
7
+ padding-top: ${p => p.theme.spacing.s};
8
8
  `;
9
9
 
10
10
  const BreadcrumbItem = styled.div<{isLastItem: boolean}>`
@@ -54,9 +54,10 @@ const FileDragAndDrop = (props: IProps) => {
54
54
  setInDropZone(true);
55
55
  };
56
56
 
57
- const checkType = (type: string) => {
58
- for (const i in validFormats) {
59
- if (type.includes(validFormats[i])) return true;
57
+ const checkType = (fileName: string) => {
58
+ const fileNameArray = fileName.split(".");
59
+ if(validFormats.includes(fileNameArray[fileNameArray.length - 1])){
60
+ return true;
60
61
  }
61
62
  return false;
62
63
  };
@@ -64,7 +65,7 @@ const FileDragAndDrop = (props: IProps) => {
64
65
  const handleDrop = async (e: React.DragEvent<HTMLDivElement>) => {
65
66
  const files = Array.from(e.dataTransfer.files);
66
67
  if (handleMultipleUpload && files.length > 1) {
67
- if (!files.every((file) => checkType(file.type))) {
68
+ if (!files.every((file) => checkType(file.name))) {
68
69
  uploadError(true, "Invalid format");
69
70
  } else {
70
71
  handleMultipleUpload(files);
@@ -78,7 +79,7 @@ const FileDragAndDrop = (props: IProps) => {
78
79
  const handleFilesUpload = async (e: any) => {
79
80
  const files: File[] = Array.from(e.currentTarget.files);
80
81
  if (handleMultipleUpload && files.length > 1) {
81
- if (!files.every((file) => checkType(file.type))) {
82
+ if (!files.every((file) => checkType(file.name))) {
82
83
  uploadError(true, "Invalid format");
83
84
  } else {
84
85
  handleMultipleUpload(files);
@@ -90,7 +91,7 @@ const FileDragAndDrop = (props: IProps) => {
90
91
 
91
92
  const uploadFiles = async (files: File[]) => {
92
93
  try {
93
- if (!files.every((file) => checkType(file.type))) {
94
+ if (!files.every((file) => checkType(file.name))) {
94
95
  uploadError(true, "Invalid format");
95
96
  return;
96
97
  }
@@ -36,6 +36,8 @@ const DragSubtitle = styled.div`
36
36
  const DragIcon = styled.div`
37
37
  height: ${(p) => p.theme.spacing.l};
38
38
  margin-bottom: ${(p) => p.theme.spacing.s};
39
+ display: flex;
40
+ justify-content: center;
39
41
  `;
40
42
 
41
43
  const DropIcon = styled.div`
@@ -1,12 +1,16 @@
1
1
  import React from "react";
2
2
 
3
3
  import { Icon, FloatingMenu, ListTitle, ListItem } from "@ax/components";
4
+ import { IQueryValue } from "@ax/types";
4
5
 
5
6
  import * as S from "./style";
6
7
 
7
8
  const SortBy = ({ sortItems, sortedState }: ISortByProps): JSX.Element => {
8
9
  const { isAscending, sortedByName, sortedByDate, sortedBySize } = sortedState;
9
- const sortBy = (pointer: string, isAscending: boolean) => sortItems(pointer, isAscending);
10
+
11
+ const sortBy = (pointer: string, isAscending: boolean) =>
12
+ sortItems([{ value: pointer, label: pointer }], isAscending);
13
+
10
14
  const sortAscendingName = () => sortBy("name", true);
11
15
  const sortDescendingName = () => sortBy("name", false);
12
16
  const sortAscendingDate = () => sortBy("date", true);
@@ -33,21 +37,33 @@ const SortBy = ({ sortItems, sortedState }: ISortByProps): JSX.Element => {
33
37
  return (
34
38
  <FloatingMenu Button={Header} position="center">
35
39
  <ListTitle>Name Sorting</ListTitle>
36
- <ListItem isSelected={sortedByName && isAscending} onClick={sortAscendingName}>Ascendent</ListItem>
37
- <ListItem isSelected={sortedByName && !isAscending} onClick={sortDescendingName}>Descendent</ListItem>
40
+ <ListItem isSelected={sortedByName && isAscending} onClick={sortAscendingName}>
41
+ Ascendent
42
+ </ListItem>
43
+ <ListItem isSelected={sortedByName && !isAscending} onClick={sortDescendingName}>
44
+ Descendent
45
+ </ListItem>
38
46
  <ListTitle>Date sorting</ListTitle>
39
- <ListItem isSelected={sortedByDate && !isAscending} onClick={sortDescendingDate}>Newest first</ListItem>
40
- <ListItem isSelected={sortedByDate && isAscending} onClick={sortAscendingDate}>Oldest first</ListItem>
47
+ <ListItem isSelected={sortedByDate && !isAscending} onClick={sortDescendingDate}>
48
+ Newest first
49
+ </ListItem>
50
+ <ListItem isSelected={sortedByDate && isAscending} onClick={sortAscendingDate}>
51
+ Oldest first
52
+ </ListItem>
41
53
  <ListTitle>Size sorting</ListTitle>
42
- <ListItem isSelected={sortedBySize && isAscending} onClick={sortAscendingSize}>Ascendent</ListItem>
43
- <ListItem isSelected={sortedBySize && !isAscending} onClick={sortDescendingSize}>Descendent</ListItem>
54
+ <ListItem isSelected={sortedBySize && isAscending} onClick={sortAscendingSize}>
55
+ Ascendent
56
+ </ListItem>
57
+ <ListItem isSelected={sortedBySize && !isAscending} onClick={sortDescendingSize}>
58
+ Descendent
59
+ </ListItem>
44
60
  </FloatingMenu>
45
61
  );
46
62
  };
47
63
 
48
64
  export interface ISortByProps {
49
65
  sortedState: ISortedListStatus;
50
- sortItems(orderPointer: string, isAscendent: boolean): void;
66
+ sortItems(orderPointer: IQueryValue[], isAscendent: boolean): void;
51
67
  }
52
68
 
53
69
  interface ISortedListStatus {
@@ -1,6 +1,7 @@
1
- import React, { useState } from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import { FloatingMenu, Icon, ListTitle, CheckGroup } from "@ax/components";
3
3
  import { areEquals } from "@ax/helpers";
4
+ import { IFilterValue, IQueryValue } from "@ax/types";
4
5
 
5
6
  import * as S from "./style";
6
7
 
@@ -10,25 +11,34 @@ const Type = (props: ITypeProps): JSX.Element => {
10
11
  const initialState = ["all"];
11
12
  const selectAllOption = "all";
12
13
  const pointer = "filterType";
13
- const cleanValue = value ? value.replace(/docx|xlsx|csv/gi, "") : "all";
14
- const arrayValues = cleanValue.split(",");
14
+ const arrayValues = Array.isArray(value) && value.length ? value.map((val) => val.value) : initialState;
15
15
  const [selectedValue, setSelectedValue] = useState(arrayValues);
16
16
 
17
+ const filters = [
18
+ { name: "all", value: "all", title: "ALL" },
19
+ { name: "pdf", value: "pdf", title: "PDF" },
20
+ { name: "doc", value: "doc", title: "DOC" },
21
+ { name: "xls", value: "xls", title: "XLS" },
22
+ { name: "csv", value: "csv", title: "CSV" },
23
+ { name: "zip", value: "zip", title: "ZIP" },
24
+ ];
25
+
26
+ useEffect(() => {
27
+ const arrayValues = Array.isArray(value) && value.length ? value.map((val) => val.value) : initialState;
28
+ setSelectedValue(arrayValues);
29
+ // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ }, [value]);
31
+
17
32
  const setQuery = (selection: any) => {
18
33
  if (!selection.length) {
19
34
  selection = initialState;
20
35
  }
21
36
  setSelectedValue(selection);
22
- const queryFilters = selection.join(",");
23
-
24
- var mapObj: Record<string, string> = {
25
- doc: "doc,docx",
26
- xls: "xls,xlsx,csv",
27
- };
28
-
29
- const fullFilters = queryFilters.replace(/doc|xls/gi, (matched: string) => mapObj[matched]);
30
-
31
- filterItems(pointer, fullFilters);
37
+ const queryFilters: IQueryValue[] = selection.map((value: string | number) => {
38
+ const label = filters.find((opt: IFilterValue) => opt.value === value);
39
+ return { value, label: label?.title || "" };
40
+ });
41
+ filterItems(pointer, queryFilters);
32
42
  };
33
43
 
34
44
  const isActive = !areEquals(selectedValue, initialState);
@@ -45,13 +55,7 @@ const Type = (props: ITypeProps): JSX.Element => {
45
55
  </S.Type>
46
56
  );
47
57
 
48
- const filters = [
49
- { name: "all", value: "all", title: "ALL" },
50
- { name: "pdf", value: "pdf", title: "PDF" },
51
- { name: "doc", value: "doc", title: "DOC, DOCX" },
52
- { name: "xls", value: "xls", title: "XLS, XLSX, CSV" },
53
- { name: "zip", value: "zip", title: "ZIP" },
54
- ];
58
+
55
59
 
56
60
  return (
57
61
  <FloatingMenu Button={Header} position="center" closeOnSelect={false}>
@@ -70,8 +74,8 @@ const Type = (props: ITypeProps): JSX.Element => {
70
74
  };
71
75
 
72
76
  export interface ITypeProps {
73
- filterItems(pointer: string, filter: string): void;
74
- value?: string;
77
+ filterItems(pointer: string, filter: IQueryValue[]): void;
78
+ value?: IQueryValue[];
75
79
  }
76
80
 
77
81
  export default Type;
@@ -1,4 +1,5 @@
1
1
  import { useState } from "react";
2
+ import { IQueryValue } from "@ax/types";
2
3
 
3
4
  const useSortedListStatus = () => {
4
5
  const sortedInitialState: {
@@ -22,20 +23,29 @@ const useSortedListStatus = () => {
22
23
  };
23
24
 
24
25
  const useFilterQuery = () => {
25
- const initialQueryValues = {
26
- order: "",
27
- filterType: "all",
28
- filterUsage: "",
26
+ const initialQueryValues: Record<string, IQueryValue[]> = {
27
+ order: [],
28
+ filterType: [],
29
+ filterUsage: [],
29
30
  };
30
31
 
31
32
  const [query, setQuery] = useState(initialQueryValues);
33
+ const [currentFilterQuery, setCurrentFilterQuery] = useState("");
32
34
 
33
- const setFilterQuery = (filterValues: any) => {
35
+ const setFilterQuery = (filterValues: Record<string, IQueryValue[]>) => {
34
36
  const { order, filterType, filterUsage } = filterValues;
35
37
  let filterQuery = "";
36
38
 
37
- const currentQuery = (pointer: string, values: string) => {
38
- return filterQuery ? filterQuery.concat(`&${pointer}=${values}`) : `${pointer}=${values}`;
39
+ const currentQuery = (pointer: string, values: IQueryValue[]): string => {
40
+ const stringValues = Array.isArray(values)
41
+ ? values.map((value) => (value.value !== "all" ? value.value : "")).join(",")
42
+ : "";
43
+
44
+ return !stringValues.length
45
+ ? filterQuery
46
+ : filterQuery.length
47
+ ? filterQuery.concat(`&${pointer}=${stringValues}`)
48
+ : `${pointer}=${stringValues}`;
39
49
  };
40
50
 
41
51
  if (order) {
@@ -50,27 +60,32 @@ const useFilterQuery = () => {
50
60
  filterQuery = currentQuery("filterUsage", filterUsage);
51
61
  }
52
62
 
53
- return filterQuery;
63
+ setCurrentFilterQuery(filterQuery);
54
64
  };
55
65
 
56
- const setFiltersSelection = (pointer: string, filter: string, isAscendent?: boolean) => {
66
+ const setFiltersSelection = (pointer: string, filter: IQueryValue[], isAscendent?: boolean) => {
57
67
  const { order, filterType, filterUsage } = query;
58
68
  const orderMethod = isAscendent ? "asc" : "desc";
59
69
  const filterValues = {
60
- order: pointer === "order" ? `${filter}-${orderMethod}` : order,
70
+ order: pointer === "order" ? [{ value: `${filter[0].value}-${orderMethod}`, label: filter[0].label }] : order,
61
71
  filterType: pointer === "filterType" ? filter : filterType,
62
72
  filterUsage: pointer === "filterUsage" ? filter : filterUsage,
63
73
  };
64
74
 
75
+ setFilterQuery(filterValues);
65
76
  setQuery(filterValues);
66
-
67
- return filterValues;
68
77
  };
69
78
 
79
+ const resetFilterQuery = () => {
80
+ setQuery(initialQueryValues);
81
+ setCurrentFilterQuery("");
82
+ }
83
+
70
84
  return {
71
85
  setFiltersSelection,
72
- setFilterQuery,
86
+ resetFilterQuery,
73
87
  filterValues: query,
88
+ filterQuery: currentFilterQuery,
74
89
  };
75
90
  };
76
91