@griddo/ax 1.75.258 → 10.1.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 (89) hide show
  1. package/package.json +2 -2
  2. package/src/GlobalStore.tsx +3 -0
  3. package/src/__tests__/components/ConfigPanel/GlobalPageForm/GlobalPageForm.test.tsx +10 -1
  4. package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +391 -0
  5. package/src/__tests__/modules/Settings/Integrations/Integrations.test.tsx +167 -0
  6. package/src/api/index.tsx +3 -1
  7. package/src/api/integrations.tsx +153 -0
  8. package/src/api/sites.tsx +4 -2
  9. package/src/components/ActionMenu/index.tsx +3 -1
  10. package/src/components/ActionMenu/style.tsx +1 -0
  11. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +4 -1
  12. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +3 -0
  13. package/src/components/ConfigPanel/GlobalPageForm/index.tsx +11 -2
  14. package/src/components/FieldContainer/index.tsx +2 -1
  15. package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/index.tsx +101 -0
  16. package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/style.tsx +23 -0
  17. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/helpers.ts +31 -0
  18. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/index.tsx +120 -0
  19. package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/style.tsx +23 -0
  20. package/src/components/Fields/IntegrationsField/IntegrationItem/atoms.tsx +27 -0
  21. package/src/components/Fields/IntegrationsField/IntegrationItem/index.tsx +132 -0
  22. package/src/components/Fields/IntegrationsField/IntegrationItem/style.tsx +63 -0
  23. package/src/components/Fields/IntegrationsField/PasteIntegrationButton/index.tsx +30 -0
  24. package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/index.tsx +52 -0
  25. package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/style.tsx +54 -0
  26. package/src/components/Fields/IntegrationsField/SideModal/index.tsx +57 -0
  27. package/src/components/Fields/IntegrationsField/SideModal/style.tsx +50 -0
  28. package/src/components/Fields/IntegrationsField/index.tsx +145 -0
  29. package/src/components/Fields/IntegrationsField/style.tsx +29 -0
  30. package/src/components/Fields/TextArea/index.tsx +1 -1
  31. package/src/components/Fields/ToggleField/index.tsx +5 -3
  32. package/src/components/Fields/UrlField/index.tsx +8 -8
  33. package/src/components/Fields/index.tsx +2 -0
  34. package/src/components/Icon/components/Deactivate.js +14 -0
  35. package/src/components/Icon/components/Lock.js +15 -0
  36. package/src/components/Icon/svgs/Deactivate.svg +8 -0
  37. package/src/components/Icon/svgs/Lock.svg +6 -0
  38. package/src/components/PageFinder/SelectionListItem/index.tsx +46 -0
  39. package/src/components/PageFinder/SelectionListItem/style.tsx +46 -0
  40. package/src/components/{Fields/UrlField/PageFinder → PageFinder}/index.tsx +99 -21
  41. package/src/components/{Fields/UrlField/PageFinder → PageFinder}/style.tsx +14 -1
  42. package/src/components/TableFilters/CheckGroupFilter/index.tsx +83 -0
  43. package/src/components/TableFilters/CheckGroupFilter/style.tsx +40 -0
  44. package/src/components/TableFilters/StateFilter/index.tsx +66 -0
  45. package/src/components/TableFilters/StateFilter/style.tsx +30 -0
  46. package/src/components/TableFilters/index.tsx +4 -0
  47. package/src/components/index.tsx +9 -1
  48. package/src/containers/Integrations/actions.tsx +190 -0
  49. package/src/containers/Integrations/constants.tsx +14 -0
  50. package/src/containers/Integrations/index.tsx +4 -0
  51. package/src/containers/Integrations/interfaces.tsx +24 -0
  52. package/src/containers/Integrations/reducer.tsx +31 -0
  53. package/src/containers/PageEditor/actions.tsx +11 -1
  54. package/src/containers/PageEditor/utils.tsx +30 -2
  55. package/src/hooks/content.tsx +46 -2
  56. package/src/hooks/index.tsx +2 -1
  57. package/src/hooks/modals.tsx +4 -2
  58. package/src/modules/App/Routing/NavMenu/NavItem/style.tsx +13 -12
  59. package/src/modules/Content/index.tsx +5 -0
  60. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/index.tsx +47 -0
  61. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/style.tsx +7 -0
  62. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/{Field → NavigationField}/index.tsx +2 -2
  63. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/index.tsx +7 -7
  64. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +1 -1
  65. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/index.tsx +81 -0
  66. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/style.tsx +35 -0
  67. package/src/modules/Settings/Integrations/BulkHeader/index.tsx +69 -0
  68. package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/index.tsx +95 -0
  69. package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/style.tsx +62 -0
  70. package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/index.tsx +138 -0
  71. package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/style.tsx +28 -0
  72. package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +319 -0
  73. package/src/modules/Settings/Integrations/IntegrationForm/style.tsx +77 -0
  74. package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/index.tsx +44 -0
  75. package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/style.tsx +13 -0
  76. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +197 -0
  77. package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +81 -0
  78. package/src/modules/Settings/Integrations/atoms.tsx +49 -0
  79. package/src/modules/Settings/Integrations/hooks.tsx +72 -0
  80. package/src/modules/Settings/Integrations/index.tsx +299 -0
  81. package/src/modules/Settings/Integrations/style.tsx +48 -0
  82. package/src/modules/Settings/Integrations/utils.tsx +39 -0
  83. package/src/routes/site.tsx +19 -0
  84. package/src/schemas/pages/Page.tsx +5 -0
  85. package/src/types/index.tsx +35 -0
  86. package/tsconfig.paths.json +2 -0
  87. package/src/components/Fields/UrlField/PageFinder/SelectionListItem/index.tsx +0 -34
  88. package/src/components/Fields/UrlField/PageFinder/SelectionListItem/style.tsx +0 -35
  89. /package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/{Field → NavigationField}/style.tsx +0 -0
@@ -38,6 +38,7 @@ import UrlField from "./UrlField";
38
38
  import VisualOption from "./VisualOption";
39
39
  import VisualUniqueSelection from "./VisualUniqueSelection";
40
40
  import Wysiwyg from "./Wysiwyg";
41
+ import IntegrationsField from "./IntegrationsField";
41
42
 
42
43
  export {
43
44
  AnalyticsField,
@@ -80,4 +81,5 @@ export {
80
81
  VisualOption,
81
82
  VisualUniqueSelection,
82
83
  Wysiwyg,
84
+ IntegrationsField,
83
85
  };
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+
3
+ const SvgDeactivate = (props) => (
4
+ <svg width={24} height={24} fill="none" {...props}>
5
+ <g>
6
+ <path
7
+ d="M19,6.3H4.9C2.2,6.3,0,8.8,0,12s2.2,5.7,4.9,5.7H19c2.8,0,4.9-2.5,4.9-5.7S21.7,6.3,19,6.3z M5.8,16.4 c-2.3,0-4.2-1.9-4.2-4.4s1.9-4.4,4.2-4.4C8.2,7.6,10,9.5,10,12S8.1,16.4,5.8,16.4z"
8
+ fill="#C7C8D0"
9
+ />
10
+ </g>
11
+ </svg>
12
+ );
13
+
14
+ export default SvgDeactivate;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+
3
+ const SvgLock = (props) => (
4
+ <svg width={24} height={24} fill="none" {...props}>
5
+ <path
6
+ fill="#20224C"
7
+ fillOpacity="0.2"
8
+ d="M18.9,8h-1.1V5.7C17.7,2.6,15.2,0,12,0S6.3,2.6,6.3,5.7V8H5.1c-1.3,0-2.3,1-2.3,2.3v11.4c0,1.3,1,2.3,2.3,2.3
9
+ h13.7c1.3,0,2.3-1,2.3-2.3V10.3C21.1,9,20.1,8,18.9,8z M8.6,5.7c0-1.9,1.5-3.4,3.4-3.4s3.4,1.5,3.4,3.4V8H8.6V5.7z M18.9,21.7H5.1
10
+ V10.3h13.7V21.7z M12,18.3c1.3,0,2.3-1,2.3-2.3c0-1.3-1-2.3-2.3-2.3s-2.3,1-2.3,2.3C9.7,17.3,10.7,18.3,12,18.3z"
11
+ />
12
+ </svg>
13
+ );
14
+
15
+ export default SvgLock;
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g>
3
+ <path
4
+ d="M19,6.3H4.9C2.2,6.3,0,8.8,0,12s2.2,5.7,4.9,5.7H19c2.8,0,4.9-2.5,4.9-5.7S21.7,6.3,19,6.3z M5.8,16.4 c-2.3,0-4.2-1.9-4.2-4.4s1.9-4.4,4.2-4.4C8.2,7.6,10,9.5,10,12S8.1,16.4,5.8,16.4z"
5
+ fill="#C7C8D0"
6
+ />
7
+ </g>
8
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
+ viewBox="0 0 24 24">
3
+ <path fill="#20224C" fill-opacity="0.2" d="M18.9,8h-1.1V5.7C17.7,2.6,15.2,0,12,0S6.3,2.6,6.3,5.7V8H5.1c-1.3,0-2.3,1-2.3,2.3v11.4c0,1.3,1,2.3,2.3,2.3
4
+ h13.7c1.3,0,2.3-1,2.3-2.3V10.3C21.1,9,20.1,8,18.9,8z M8.6,5.7c0-1.9,1.5-3.4,3.4-3.4s3.4,1.5,3.4,3.4V8H8.6V5.7z M18.9,21.7H5.1
5
+ V10.3h13.7V21.7z M12,18.3c1.3,0,2.3-1,2.3-2.3c0-1.3-1-2.3-2.3-2.3s-2.3,1-2.3,2.3C9.7,17.3,10.7,18.3,12,18.3z"/>
6
+ </svg>
@@ -0,0 +1,46 @@
1
+ import React from "react";
2
+ import { getFormattedDateWithTimezone } from "@ax/helpers";
3
+ import { CheckField } from "@ax/components";
4
+ import { ICheck, IPage } from "@ax/types";
5
+
6
+ import * as S from "./style";
7
+
8
+ const SelectionListItem = (props: ISelectionListItemProps): JSX.Element => {
9
+ const { option, title, type, date, onClick, pageID, isSelected, onChange, multiple } = props;
10
+
11
+ const handleClick = () => (multiple ? onChange({ value: option, isChecked: !isSelected }) : onClick(option));
12
+ const handleChange = (value: ICheck) => onChange({ value: option, isChecked: value.isChecked });
13
+
14
+ const pageType = type || "Page";
15
+
16
+ return (
17
+ <S.ListItem>
18
+ {multiple && (
19
+ <S.CheckWrapper>
20
+ <CheckField name="check" value={pageID} checked={isSelected} onChange={handleChange} />
21
+ </S.CheckWrapper>
22
+ )}
23
+ <S.Content onClick={handleClick} data-testid="selection-list-item">
24
+ <S.Header>
25
+ <S.Type>{pageType}</S.Type>
26
+ <S.Date>{getFormattedDateWithTimezone(date, "d MMM Y")}</S.Date>
27
+ </S.Header>
28
+ <S.Title>{title}</S.Title>
29
+ </S.Content>
30
+ </S.ListItem>
31
+ );
32
+ };
33
+
34
+ interface ISelectionListItemProps {
35
+ option: any;
36
+ title: string;
37
+ type: string;
38
+ date: Date;
39
+ onClick: (value: any) => void;
40
+ pageID: number;
41
+ isSelected: boolean;
42
+ onChange: (item: { value: IPage; isChecked: boolean }) => void;
43
+ multiple?: boolean;
44
+ }
45
+
46
+ export default SelectionListItem;
@@ -0,0 +1,46 @@
1
+ import styled from "styled-components";
2
+
3
+ const ListItem = styled.li`
4
+ display: flex;
5
+ width: 100%;
6
+ padding: ${(p) => p.theme.spacing.s};
7
+ background-color: ${(p) => p.theme.color.uiBarBackground};
8
+ border: 1px solid ${(p) => p.theme.color.uiLine};
9
+ border-radius: ${(p) => p.theme.radii.s};
10
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
11
+ :hover {
12
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
13
+ cursor: pointer;
14
+ }
15
+ `;
16
+
17
+ const Title = styled.div`
18
+ ${(p) => p.theme.textStyle.fieldContent}
19
+ color: ${(p) => p.theme.colors.textHighEmphasis};
20
+ `;
21
+
22
+ const Header = styled.div`
23
+ display: flex;
24
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
25
+ `;
26
+
27
+ const Type = styled.div`
28
+ ${(p) => p.theme.textStyle.headingXXS};
29
+ color: ${(p) => p.theme.colors.textLowEmphasis};
30
+ `;
31
+
32
+ const Date = styled.div`
33
+ ${(p) => p.theme.textStyle.uiXS};
34
+ color: ${(p) => p.theme.colors.textLowEmphasis};
35
+ margin-left: auto;
36
+ `;
37
+
38
+ const CheckWrapper = styled.div`
39
+ display: flex;
40
+ `;
41
+
42
+ const Content = styled.div`
43
+ width: 100%;
44
+ `;
45
+
46
+ export { ListItem, Title, Header, Type, Date, CheckWrapper, Content };
@@ -5,13 +5,13 @@ import { IContentType, IGlobalLanguage, IPage, IRootState, ISite } from "@ax/typ
5
5
  import { useDebounce } from "@ax/hooks";
6
6
  import { getStructuredDataTitle, isReqOk } from "@ax/helpers";
7
7
  import { sites, structuredData } from "@ax/api";
8
- import { Loader, Pagination, TextField, Select } from "@ax/components";
8
+ import { Loader, Pagination, TextField, Select, Button } from "@ax/components";
9
9
  import SelectionListItem from "./SelectionListItem";
10
10
 
11
11
  import * as S from "./style";
12
12
 
13
13
  const PageFinder = (props: IPageFinderProps): JSX.Element => {
14
- const { onClick, currentSiteID, isOpen, allSites, lang, globalLangs } = props;
14
+ const { onClick, currentSiteID, isOpen, allSites, lang, globalLangs, multiple, hideSites, pages } = props;
15
15
 
16
16
  const siteOptions = allSites.map((site) => ({ label: site.name, value: site.id.toString() }));
17
17
  const langOptions = globalLangs.map((lang) => ({ label: lang.label, value: lang.id.toString() }));
@@ -27,11 +27,18 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
27
27
  };
28
28
  const [state, setState] = useState(initialState);
29
29
  const [isLoading, setIsLoading] = useState(false);
30
+ const [selectedPages, setSelectedPages] = useState<IPage[]>([]);
31
+ const [selectedPagesIds, setSelectedPagesIds] = useState<number[]>(pages ? pages : []);
32
+ const [showSelected, setShowSelected] = useState(false);
30
33
  const debouncedSearch = useDebounce(state.query);
31
34
 
32
35
  const allTypesOption = { label: "All content", value: "all" };
33
- const [contentTypeOptions, setContentTypeOptions] = useState<{ label: string, value: string }[]>([{ ...allTypesOption }]);
34
- const changeContentTypeOptions = (types: { label: string, value: string }[]) => setContentTypeOptions([allTypesOption, ...types]);
36
+ const [contentTypeOptions, setContentTypeOptions] = useState<{ label: string; value: string }[]>([
37
+ { ...allTypesOption },
38
+ ]);
39
+
40
+ const changeContentTypeOptions = (types: { label: string; value: string }[]) =>
41
+ setContentTypeOptions([allTypesOption, ...types]);
35
42
 
36
43
  const itemsPerPage = 50;
37
44
 
@@ -44,6 +51,35 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
44
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
45
52
  }, [isOpen]);
46
53
 
54
+ useEffect(() => {
55
+ let isMounted = true;
56
+ const params = {
57
+ deleted: false,
58
+ filterPages: selectedPagesIds,
59
+ siteID: state.site,
60
+ ignoreLang: true,
61
+ };
62
+
63
+ const getSelectedItems = async () => {
64
+ if (!isMounted) return;
65
+ const response: { status: number; data: { totalItems: number; items: any } } = await sites.getSitePages(params);
66
+ if (isReqOk(response.status)) {
67
+ setSelectedPages(response.data.items);
68
+ } else {
69
+ console.log("Error en getSelectedItems");
70
+ }
71
+ };
72
+
73
+ if (selectedPagesIds && selectedPagesIds.length > 0) {
74
+ getSelectedItems();
75
+ }
76
+
77
+ return function cleanup() {
78
+ isMounted = false;
79
+ };
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ }, []);
82
+
47
83
  useEffect(() => {
48
84
  let isMounted = true;
49
85
  const params = {
@@ -61,9 +97,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
61
97
  if (!isMounted) return;
62
98
 
63
99
  setIsLoading(true);
64
- const response: { status: number; data: { totalItems: number; items: any } } = await sites.getSitePages(
65
- params
66
- );
100
+ const response: { status: number; data: { totalItems: number; items: any } } = await sites.getSitePages(params);
67
101
  if (isReqOk(response.status)) {
68
102
  setState((state) => ({ ...state, items: response.data.items, totalItems: response.data.totalItems }));
69
103
  } else {
@@ -85,7 +119,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
85
119
  const contentTypes = data.items.map((type: IContentType) => ({ label: type.title, value: type.id }));
86
120
  changeContentTypeOptions(contentTypes);
87
121
  changeState("type", "all");
88
- }
122
+ };
89
123
 
90
124
  useEffect(() => {
91
125
  getAndSetContentTypes();
@@ -102,9 +136,28 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
102
136
 
103
137
  const setPage = (newPage: number) => changeState("page", newPage);
104
138
 
105
- const PageList =
106
- state.items &&
107
- state.items.map((page: IPage) => (
139
+ const handleChange = (item: { value: IPage; isChecked: boolean }) => {
140
+ const { value, isChecked } = item;
141
+
142
+ let newSelection: IPage[] = [...selectedPages];
143
+ isChecked ? newSelection.push(value) : (newSelection = newSelection.filter((page: IPage) => page.id !== value.id));
144
+ const newSelectionIDs = newSelection.map((page: IPage) => page.id);
145
+
146
+ setSelectedPages(newSelection);
147
+ setSelectedPagesIds(newSelectionIDs);
148
+
149
+ if (showSelected && newSelection.length === 0) {
150
+ setShowSelected(false);
151
+ }
152
+ };
153
+
154
+ const handleSelectedClick = () => setShowSelected(!showSelected);
155
+
156
+ const handleButtonClick = () => onClick(selectedPages);
157
+
158
+ const getPageList = (items: IPage[]) =>
159
+ items &&
160
+ items.map((page: IPage) => (
108
161
  <SelectionListItem
109
162
  option={page}
110
163
  key={page.id}
@@ -112,6 +165,10 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
112
165
  type={getStructuredDataTitle(page.structuredData)}
113
166
  date={page.modified}
114
167
  onClick={onClick}
168
+ pageID={page.id}
169
+ isSelected={selectedPagesIds.includes(page.id)}
170
+ onChange={handleChange}
171
+ multiple={multiple}
115
172
  />
116
173
  ));
117
174
 
@@ -119,6 +176,8 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
119
176
 
120
177
  const hasQuery = state.query.length > 0;
121
178
 
179
+ const buttonText = !showSelected ? `view selected (${selectedPages.length})` : "hide selected";
180
+
122
181
  return (
123
182
  <S.Wrapper>
124
183
  <S.LanguageSiteFilters>
@@ -129,13 +188,22 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
129
188
  value={state.lang.toString()}
130
189
  type="inline"
131
190
  />
132
- <Select
133
- name="select"
134
- options={siteOptions}
135
- onChange={(value) => changeState("site", value)}
136
- value={state.site.toString()}
137
- type="inline"
138
- />
191
+ {!hideSites && (
192
+ <Select
193
+ name="select"
194
+ options={siteOptions}
195
+ onChange={(value) => changeState("site", value)}
196
+ value={state.site.toString()}
197
+ type="inline"
198
+ />
199
+ )}
200
+ {selectedPages.length > 0 && (
201
+ <S.ButtonWrapper>
202
+ <Button type="button" buttonStyle="text" onClick={handleSelectedClick}>
203
+ {buttonText}
204
+ </Button>
205
+ </S.ButtonWrapper>
206
+ )}
139
207
  </S.LanguageSiteFilters>
140
208
  <S.ContentTypeFilter>
141
209
  <S.Text>Content type</S.Text>
@@ -146,7 +214,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
146
214
  value={state.type}
147
215
  mandatory
148
216
  />
149
- </ S.ContentTypeFilter>
217
+ </S.ContentTypeFilter>
150
218
  <S.SearchWrapper>
151
219
  {hasQuery ? (
152
220
  <TextField {...textFieldProps} onClickIcon={resetQuery} icon="close" />
@@ -161,7 +229,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
161
229
  </S.LoadingWrapper>
162
230
  ) : (
163
231
  <S.ListWrapper>
164
- <S.PageList>{PageList}</S.PageList>
232
+ <S.PageList>{getPageList(showSelected ? selectedPages : state.items)}</S.PageList>
165
233
  <S.PaginationWrapper>
166
234
  {showPagination && (
167
235
  <Pagination
@@ -175,17 +243,27 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
175
243
  </S.PaginationWrapper>
176
244
  </S.ListWrapper>
177
245
  )}
246
+ {selectedPages.length > 0 && (
247
+ <S.ActionWrapper>
248
+ <Button type="button" onClick={handleButtonClick}>
249
+ Add pages
250
+ </Button>
251
+ </S.ActionWrapper>
252
+ )}
178
253
  </S.Wrapper>
179
254
  );
180
255
  };
181
256
 
182
257
  interface IPageFinderProps {
183
- onClick: (value: IPage) => void;
258
+ onClick: (value: IPage | IPage[]) => void;
184
259
  currentSiteID: number;
185
260
  isOpen: boolean;
186
261
  allSites: ISite[];
187
262
  lang: { locale: string; id: number };
188
263
  globalLangs: IGlobalLanguage[];
264
+ multiple?: boolean;
265
+ hideSites?: boolean;
266
+ pages?: number[];
189
267
  }
190
268
 
191
269
  const mapStateToProps = (state: IRootState) => ({
@@ -5,7 +5,7 @@ const Wrapper = styled.div`
5
5
  position: relative;
6
6
  width: 100%;
7
7
  height: 100%;
8
- padding-bottom: ${p => p.theme.spacing.xl};
8
+ padding-bottom: ${(p) => p.theme.spacing.xl};
9
9
  flex-direction: column;
10
10
  `;
11
11
 
@@ -67,6 +67,17 @@ const ContentTypeFilter = styled.div`
67
67
  margin-bottom: ${(p) => p.theme.spacing.s};
68
68
  `;
69
69
 
70
+ const ActionWrapper = styled.div`
71
+ display: flex;
72
+ justify-content: flex-end;
73
+ padding-top: ${(p) => p.theme.spacing.s};
74
+ `;
75
+
76
+ const ButtonWrapper = styled.div`
77
+ display: flex;
78
+ justify-content: flex-end;
79
+ `;
80
+
70
81
  export {
71
82
  Wrapper,
72
83
  ListWrapper,
@@ -78,4 +89,6 @@ export {
78
89
  PaginationWrapper,
79
90
  LanguageSiteFilters,
80
91
  ContentTypeFilter,
92
+ ActionWrapper,
93
+ ButtonWrapper,
81
94
  };
@@ -0,0 +1,83 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { CheckGroup, FloatingMenu, Icon, ListTitle } from "@ax/components";
3
+ import { areEquals } from "@ax/helpers";
4
+
5
+ import * as S from "./style";
6
+
7
+ const CheckGroupFilter = (props: ITypeFilterProps): JSX.Element => {
8
+ const {
9
+ label,
10
+ description,
11
+ filterItems,
12
+ filters,
13
+ pointer,
14
+ value,
15
+ selectAllOption,
16
+ initialState,
17
+ multipleSelection = true,
18
+ } = props;
19
+
20
+ const [selectedValue, setSelectedValue] = useState(initialState);
21
+
22
+ useEffect(() => {
23
+ if (value) {
24
+ const valueArray = typeof value === "string" ? value.split(",") : value;
25
+ setSelectedValue(valueArray);
26
+ }
27
+ }, [value]);
28
+
29
+ const setFilterQuery = (selection: any) => {
30
+ if (!selection.length) {
31
+ selection = initialState;
32
+ }
33
+ setSelectedValue(selection);
34
+ const queryFilters = selection.join(",");
35
+ filterItems(pointer, queryFilters);
36
+ };
37
+
38
+ const isActive = !areEquals(selectedValue, initialState);
39
+
40
+ const Header = () => (
41
+ <S.StyledHeader isActive={isActive}>
42
+ {label}
43
+ <S.IconsWrapper>
44
+ {isActive ? <Icon name="Filter" size="16" /> : <Icon name="DownArrow" size="16" />}
45
+ </S.IconsWrapper>
46
+ </S.StyledHeader>
47
+ );
48
+
49
+ return (
50
+ <FloatingMenu Button={Header} closeOnSelect={true} isCheckGroup={true} position="center">
51
+ <ListTitle>{description}</ListTitle>
52
+ <S.ChecksWrapper>
53
+ <CheckGroup
54
+ options={filters}
55
+ value={selectedValue}
56
+ onChange={setFilterQuery}
57
+ selectAllOption={selectAllOption}
58
+ multipleSelection={multipleSelection}
59
+ />
60
+ </S.ChecksWrapper>
61
+ </FloatingMenu>
62
+ );
63
+ };
64
+
65
+ interface IFilter {
66
+ name: string;
67
+ value: string;
68
+ title: string;
69
+ }
70
+
71
+ interface ITypeFilterProps {
72
+ label: string;
73
+ description: string;
74
+ filterItems(pointer: string, filter: string): void;
75
+ filters: IFilter[];
76
+ pointer: string;
77
+ value: any;
78
+ selectAllOption: string;
79
+ initialState: string[];
80
+ multipleSelection?: boolean;
81
+ }
82
+
83
+ export default CheckGroupFilter;
@@ -0,0 +1,40 @@
1
+ import styled from "styled-components";
2
+
3
+ const StyledHeader = styled.div<{ isActive: boolean }>`
4
+ ${(p) => p.theme.textStyle.uiS};
5
+ box-sizing: border-box;
6
+ display: flex;
7
+ flex-flow: column wrap;
8
+ flex-direction: row;
9
+ color: ${(p) => (p.isActive ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis)};
10
+ width: 100%;
11
+ justify-content: center;
12
+ position: relative;
13
+ &:hover {
14
+ color: ${(p) => p.theme.color.interactive01};
15
+ }
16
+ `;
17
+
18
+ const IconsWrapper = styled.div`
19
+ display: flex;
20
+ align-items: center;
21
+ flex-direction: row;
22
+ svg {
23
+ margin-left: 4px;
24
+ }
25
+ `;
26
+
27
+ const InteractiveArrow = styled.div`
28
+ display: flex;
29
+ svg {
30
+ path {
31
+ fill: ${(p) => p.theme.color.interactive01};
32
+ }
33
+ }
34
+ `;
35
+
36
+ const ChecksWrapper = styled.div`
37
+ padding: ${(p) => p.theme.spacing.xs} ${(p) => p.theme.spacing.s};
38
+ `;
39
+
40
+ export { StyledHeader, IconsWrapper, InteractiveArrow, ChecksWrapper };
@@ -0,0 +1,66 @@
1
+ import React, { useEffect, useState } from "react";
2
+
3
+ import { Icon, FloatingMenu, ListTitle, ListItem } from "@ax/components";
4
+
5
+ import * as S from "./style";
6
+
7
+ const StateFilter = (props: IProps): JSX.Element => {
8
+ const { value, filterItems } = props;
9
+
10
+ const [selectedValue, setSelectedValue] = useState<string>("all");
11
+
12
+ const isFilterActived = selectedValue !== "all";
13
+
14
+ useEffect(() => {
15
+ value && setSelectedValue(value);
16
+ }, [value]);
17
+
18
+ const setFilterQuery = (selection: any) => {
19
+ if (!selection.length) {
20
+ selection = "";
21
+ }
22
+ setSelectedValue(selection);
23
+ filterItems("filterState", selection);
24
+ };
25
+
26
+ const sortAllStates = () => setFilterQuery("all");
27
+ const sortEnableState = () => setFilterQuery("enable");
28
+ const sortDisableState = () => setFilterQuery("disable");
29
+
30
+ const Header = () => (
31
+ <S.State isActive={isFilterActived}>
32
+ State
33
+ <S.IconsWrapper>
34
+ {isFilterActived ? (
35
+ <Icon name="Filter" size="16" />
36
+ ) : (
37
+ <S.InteractiveArrow>
38
+ <Icon name="DownArrow" size="16" />
39
+ </S.InteractiveArrow>
40
+ )}
41
+ </S.IconsWrapper>
42
+ </S.State>
43
+ );
44
+
45
+ return (
46
+ <FloatingMenu Button={Header} position="center">
47
+ <ListTitle>Filter by state</ListTitle>
48
+ <ListItem isSelected={!isFilterActived} onClick={sortAllStates}>
49
+ ALL
50
+ </ListItem>
51
+ <ListItem isSelected={selectedValue === "enable"} onClick={sortEnableState}>
52
+ Enabled
53
+ </ListItem>
54
+ <ListItem isSelected={selectedValue === "disable"} onClick={sortDisableState}>
55
+ Disabled
56
+ </ListItem>
57
+ </FloatingMenu>
58
+ );
59
+ };
60
+
61
+ interface IProps {
62
+ filterItems(pointer: string, filter: string): void;
63
+ value: string;
64
+ }
65
+
66
+ export default StateFilter;
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import styled from "styled-components";
3
+ import { Header } from "@ax/components/TableList/style";
4
+
5
+ const State = styled((props) => <Header {...props} />)<{ isActive: boolean }>`
6
+ width: 170px;
7
+ &:hover {
8
+ color: ${(p) => p.theme.color.interactive01};
9
+ }
10
+ `;
11
+
12
+ const IconsWrapper = styled.div`
13
+ display: flex;
14
+ align-items: center;
15
+ flex-direction: row;
16
+ svg {
17
+ margin-left: 4px;
18
+ }
19
+ `;
20
+
21
+ const InteractiveArrow = styled.div`
22
+ display: flex;
23
+ svg {
24
+ path {
25
+ fill: ${(p) => p.theme.color.interactive01};
26
+ }
27
+ }
28
+ `;
29
+
30
+ export { State, IconsWrapper, InteractiveArrow };
@@ -7,6 +7,8 @@ import StatusFilter from "./StatusFilter";
7
7
  import TranslationsFilter from "./TranslationsFilter";
8
8
  import TypeFilter from "./TypeFilter";
9
9
  import DateFilter from "./DateFilter";
10
+ import CheckGroupFilter from "./CheckGroupFilter";
11
+ import StateFilter from "./StateFilter";
10
12
  import LastAccessFilter from "./LastAccessFilter";
11
13
 
12
14
  export {
@@ -19,5 +21,7 @@ export {
19
21
  TranslationsFilter,
20
22
  TypeFilter,
21
23
  DateFilter,
24
+ CheckGroupFilter,
25
+ StateFilter,
22
26
  LastAccessFilter,
23
27
  };