@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.
- package/package.json +2 -2
- package/src/GlobalStore.tsx +3 -0
- package/src/__tests__/components/ConfigPanel/GlobalPageForm/GlobalPageForm.test.tsx +10 -1
- package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +391 -0
- package/src/__tests__/modules/Settings/Integrations/Integrations.test.tsx +167 -0
- package/src/api/index.tsx +3 -1
- package/src/api/integrations.tsx +153 -0
- package/src/api/sites.tsx +4 -2
- package/src/components/ActionMenu/index.tsx +3 -1
- package/src/components/ActionMenu/style.tsx +1 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +4 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +3 -0
- package/src/components/ConfigPanel/GlobalPageForm/index.tsx +11 -2
- package/src/components/FieldContainer/index.tsx +2 -1
- package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/index.tsx +101 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/CustomPanel/style.tsx +23 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/helpers.ts +31 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/index.tsx +120 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/VariablesPanel/style.tsx +23 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/atoms.tsx +27 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/index.tsx +132 -0
- package/src/components/Fields/IntegrationsField/IntegrationItem/style.tsx +63 -0
- package/src/components/Fields/IntegrationsField/PasteIntegrationButton/index.tsx +30 -0
- package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/index.tsx +52 -0
- package/src/components/Fields/IntegrationsField/SideModal/SideModalOption/style.tsx +54 -0
- package/src/components/Fields/IntegrationsField/SideModal/index.tsx +57 -0
- package/src/components/Fields/IntegrationsField/SideModal/style.tsx +50 -0
- package/src/components/Fields/IntegrationsField/index.tsx +145 -0
- package/src/components/Fields/IntegrationsField/style.tsx +29 -0
- package/src/components/Fields/TextArea/index.tsx +1 -1
- package/src/components/Fields/ToggleField/index.tsx +5 -3
- package/src/components/Fields/UrlField/index.tsx +8 -8
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/Icon/components/Deactivate.js +14 -0
- package/src/components/Icon/components/Lock.js +15 -0
- package/src/components/Icon/svgs/Deactivate.svg +8 -0
- package/src/components/Icon/svgs/Lock.svg +6 -0
- package/src/components/PageFinder/SelectionListItem/index.tsx +46 -0
- package/src/components/PageFinder/SelectionListItem/style.tsx +46 -0
- package/src/components/{Fields/UrlField/PageFinder → PageFinder}/index.tsx +99 -21
- package/src/components/{Fields/UrlField/PageFinder → PageFinder}/style.tsx +14 -1
- package/src/components/TableFilters/CheckGroupFilter/index.tsx +83 -0
- package/src/components/TableFilters/CheckGroupFilter/style.tsx +40 -0
- package/src/components/TableFilters/StateFilter/index.tsx +66 -0
- package/src/components/TableFilters/StateFilter/style.tsx +30 -0
- package/src/components/TableFilters/index.tsx +4 -0
- package/src/components/index.tsx +9 -1
- package/src/containers/Integrations/actions.tsx +190 -0
- package/src/containers/Integrations/constants.tsx +14 -0
- package/src/containers/Integrations/index.tsx +4 -0
- package/src/containers/Integrations/interfaces.tsx +24 -0
- package/src/containers/Integrations/reducer.tsx +31 -0
- package/src/containers/PageEditor/actions.tsx +11 -1
- package/src/containers/PageEditor/utils.tsx +30 -2
- package/src/hooks/content.tsx +46 -2
- package/src/hooks/index.tsx +2 -1
- package/src/hooks/modals.tsx +4 -2
- package/src/modules/App/Routing/NavMenu/NavItem/style.tsx +13 -12
- package/src/modules/Content/index.tsx +5 -0
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/index.tsx +47 -0
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/IntegrationsField/style.tsx +7 -0
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/{Field → NavigationField}/index.tsx +2 -2
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/index.tsx +7 -7
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +1 -1
- package/src/modules/Settings/Integrations/BulkHeader/TableHeader/index.tsx +81 -0
- package/src/modules/Settings/Integrations/BulkHeader/TableHeader/style.tsx +35 -0
- package/src/modules/Settings/Integrations/BulkHeader/index.tsx +69 -0
- package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/index.tsx +95 -0
- package/src/modules/Settings/Integrations/IntegrationForm/VariableItem/style.tsx +62 -0
- package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/index.tsx +138 -0
- package/src/modules/Settings/Integrations/IntegrationForm/VariablePanel/style.tsx +28 -0
- package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +319 -0
- package/src/modules/Settings/Integrations/IntegrationForm/style.tsx +77 -0
- package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/index.tsx +44 -0
- package/src/modules/Settings/Integrations/IntegrationItem/CopyModal/style.tsx +13 -0
- package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +197 -0
- package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +81 -0
- package/src/modules/Settings/Integrations/atoms.tsx +49 -0
- package/src/modules/Settings/Integrations/hooks.tsx +72 -0
- package/src/modules/Settings/Integrations/index.tsx +299 -0
- package/src/modules/Settings/Integrations/style.tsx +48 -0
- package/src/modules/Settings/Integrations/utils.tsx +39 -0
- package/src/routes/site.tsx +19 -0
- package/src/schemas/pages/Page.tsx +5 -0
- package/src/types/index.tsx +35 -0
- package/tsconfig.paths.json +2 -0
- package/src/components/Fields/UrlField/PageFinder/SelectionListItem/index.tsx +0 -34
- package/src/components/Fields/UrlField/PageFinder/SelectionListItem/style.tsx +0 -35
- /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
|
|
34
|
-
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
</
|
|
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>{
|
|
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
|
};
|