@griddo/ax 10.3.6 → 10.3.8
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/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +35 -27
- package/src/components/Button/index.tsx +15 -2
- package/src/components/Button/style.tsx +14 -4
- package/src/components/Fields/ReferenceField/AutoPanel/AutoItem/index.tsx +233 -83
- package/src/components/Fields/ReferenceField/AutoPanel/AutoItem/style.tsx +36 -76
- package/src/components/Fields/ReferenceField/AutoPanel/index.tsx +100 -89
- package/src/components/Fields/ReferenceField/Context/index.tsx +28 -8
- package/src/components/Fields/ReferenceField/ItemList/index.tsx +7 -5
- package/src/components/Fields/ReferenceField/index.tsx +47 -25
- package/src/components/Fields/ReferenceField/style.tsx +1 -0
- package/src/components/Fields/Select/style.tsx +25 -25
- package/src/components/Tag/index.tsx +3 -2
- package/src/components/Tag/style.tsx +11 -9
- package/src/hooks/content.tsx +6 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.3.
|
|
4
|
+
"version": "10.3.8",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -230,5 +230,5 @@
|
|
|
230
230
|
"publishConfig": {
|
|
231
231
|
"access": "public"
|
|
232
232
|
},
|
|
233
|
-
"gitHead": "
|
|
233
|
+
"gitHead": "7e355ae2bd1b87bc210353cb2c891bd6aecb123c"
|
|
234
234
|
}
|
|
@@ -26,8 +26,8 @@ afterEach(() => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
const defaultProps = mock<IReferenceFieldProps>();
|
|
29
|
-
defaultProps.value = {
|
|
30
|
-
defaultProps.
|
|
29
|
+
defaultProps.value = { sources: [{ structuredData: "ARTICLES" }] };
|
|
30
|
+
defaultProps.sources = [{ structuredData: "ARTICLES" }];
|
|
31
31
|
|
|
32
32
|
const initialStore = {
|
|
33
33
|
structuredData: structuredDataMock,
|
|
@@ -134,7 +134,7 @@ describe("ReferenceField component rendering", () => {
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
test("should render the component ReferenceField with fixed is empty", async () => {
|
|
137
|
-
defaultProps.
|
|
137
|
+
defaultProps.sources = [{ structuredData: "ARTICLES" }];
|
|
138
138
|
defaultProps.value = {
|
|
139
139
|
mode: "manual",
|
|
140
140
|
fixed: [],
|
|
@@ -175,19 +175,23 @@ describe("ReferenceField component rendering", () => {
|
|
|
175
175
|
|
|
176
176
|
describe("onChange events", () => {
|
|
177
177
|
test("should apply change in AutoPanel", async () => {
|
|
178
|
-
defaultProps.
|
|
178
|
+
defaultProps.sources = [{ structuredData: "STORIES" }];
|
|
179
179
|
defaultProps.value = {
|
|
180
|
-
|
|
181
|
-
filter: [
|
|
182
|
-
{
|
|
183
|
-
id: 4418,
|
|
184
|
-
label: "Story Type 1",
|
|
185
|
-
source: "STORIES",
|
|
186
|
-
},
|
|
180
|
+
sources: [
|
|
187
181
|
{
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
182
|
+
structuredData: "STORIES",
|
|
183
|
+
filters: [
|
|
184
|
+
{
|
|
185
|
+
id: 4418,
|
|
186
|
+
label: "Story Type 1",
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: 4419,
|
|
190
|
+
label: "Story Type 2",
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
globalOperator: "AND",
|
|
194
|
+
filterOperator: "ANY",
|
|
191
195
|
},
|
|
192
196
|
],
|
|
193
197
|
quantity: 1,
|
|
@@ -257,7 +261,7 @@ describe("onChange events", () => {
|
|
|
257
261
|
});
|
|
258
262
|
|
|
259
263
|
test("should add item in manual mode", async () => {
|
|
260
|
-
defaultProps.
|
|
264
|
+
defaultProps.sources = [{ structuredData: "ARTICLES" }];
|
|
261
265
|
defaultProps.value = {
|
|
262
266
|
mode: "manual",
|
|
263
267
|
fixed: [4492, 4493],
|
|
@@ -309,7 +313,7 @@ describe("onChange events", () => {
|
|
|
309
313
|
});
|
|
310
314
|
|
|
311
315
|
test("should remove item in manual mode", async () => {
|
|
312
|
-
defaultProps.
|
|
316
|
+
defaultProps.sources = [{ structuredData: "ARTICLES" }];
|
|
313
317
|
defaultProps.value = {
|
|
314
318
|
mode: "manual",
|
|
315
319
|
fixed: [4492, 4493],
|
|
@@ -363,19 +367,23 @@ describe("onChange events", () => {
|
|
|
363
367
|
});
|
|
364
368
|
|
|
365
369
|
test("should delete filter tags", async () => {
|
|
366
|
-
defaultProps.
|
|
370
|
+
defaultProps.sources = [{ structuredData: "STORIES" }];
|
|
367
371
|
defaultProps.value = {
|
|
368
|
-
|
|
369
|
-
filter: [
|
|
370
|
-
{
|
|
371
|
-
id: 4418,
|
|
372
|
-
label: "Story Type 1",
|
|
373
|
-
source: "STORIES",
|
|
374
|
-
},
|
|
372
|
+
sources: [
|
|
375
373
|
{
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
374
|
+
structuredData: "STORIES",
|
|
375
|
+
filters: [
|
|
376
|
+
{
|
|
377
|
+
id: 4418,
|
|
378
|
+
label: "Story Type 1",
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
id: 4419,
|
|
382
|
+
label: "Story Type 2",
|
|
383
|
+
},
|
|
384
|
+
],
|
|
385
|
+
globalOperator: "AND",
|
|
386
|
+
filterOperator: "ANY",
|
|
379
387
|
},
|
|
380
388
|
],
|
|
381
389
|
};
|
|
@@ -8,6 +8,7 @@ enum buttonStyles {
|
|
|
8
8
|
TEXT = "text",
|
|
9
9
|
LINE = "line",
|
|
10
10
|
INVERSE = "lineInverse",
|
|
11
|
+
MINIMAL = "minimal",
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const Button = (props: IButtonProps): JSX.Element => {
|
|
@@ -60,6 +61,18 @@ const Button = (props: IButtonProps): JSX.Element => {
|
|
|
60
61
|
{buttonContent}
|
|
61
62
|
</S.LineButton>
|
|
62
63
|
);
|
|
64
|
+
case buttonStyles.MINIMAL:
|
|
65
|
+
return (
|
|
66
|
+
<S.MinimalButton
|
|
67
|
+
data-testid="button-minimal"
|
|
68
|
+
className={className}
|
|
69
|
+
type={type}
|
|
70
|
+
disabled={disabled}
|
|
71
|
+
onClick={handleOnClick}
|
|
72
|
+
>
|
|
73
|
+
{buttonContent}
|
|
74
|
+
</S.MinimalButton>
|
|
75
|
+
);
|
|
63
76
|
default:
|
|
64
77
|
return (
|
|
65
78
|
<S.Button
|
|
@@ -77,12 +90,12 @@ const Button = (props: IButtonProps): JSX.Element => {
|
|
|
77
90
|
|
|
78
91
|
export interface IButtonProps {
|
|
79
92
|
children: JSX.Element | string;
|
|
80
|
-
type
|
|
93
|
+
type?: "button" | "submit" | "reset";
|
|
81
94
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
82
95
|
icon?: string;
|
|
83
96
|
loader?: string;
|
|
84
97
|
disabled?: boolean;
|
|
85
|
-
buttonStyle?: "solid" | "text" | "line" | "lineInverse" |
|
|
98
|
+
buttonStyle?: "solid" | "text" | "line" | "lineInverse" | "minimal";
|
|
86
99
|
className?: string;
|
|
87
100
|
backIcon?: string;
|
|
88
101
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const Button = styled.button`
|
|
5
5
|
${(p) => p.theme.textStyle.uiButton};
|
|
6
6
|
background-color: ${(p) => p.theme.color.interactive01};
|
|
7
7
|
border-radius: 4px;
|
|
@@ -63,7 +63,7 @@ export const Button = styled.button`
|
|
|
63
63
|
}
|
|
64
64
|
`;
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
const TextButton = styled((props) => <Button {...props} />)`
|
|
67
67
|
background-color: transparent;
|
|
68
68
|
color: ${(p) => p.theme.color.interactive01};
|
|
69
69
|
padding: 0 ${(p) => p.theme.spacing.xs};
|
|
@@ -92,7 +92,7 @@ export const TextButton = styled((props) => <Button {...props} />)`
|
|
|
92
92
|
}
|
|
93
93
|
`;
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const LineButton = styled((props) => <Button {...props} />)<{ isInverse: boolean | undefined }>`
|
|
96
96
|
background-color: ${(p) => (p.isInverse ? p.theme.color.uiMainMenuBackground : p.theme.color.interactiveBackground)};
|
|
97
97
|
border: 1px solid ${(p) => (p.isInverse ? p.theme.color.interactiveInverse : p.theme.color.interactive01)};
|
|
98
98
|
color: ${(p) => (p.isInverse ? p.theme.color.interactiveInverse : p.theme.color.interactive01)};
|
|
@@ -123,7 +123,15 @@ export const LineButton = styled((props) => <Button {...props} />)<{ isInverse:
|
|
|
123
123
|
}
|
|
124
124
|
`;
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
const MinimalButton = styled.button`
|
|
127
|
+
${(p) => p.theme.textStyle.uiButton};
|
|
128
|
+
background-color: transparent;
|
|
129
|
+
color: ${(p) => p.theme.color.interactive01};
|
|
130
|
+
border: none;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
`;
|
|
133
|
+
|
|
134
|
+
const Label = styled.span<{ icon?: string; backIcon?: string }>`
|
|
127
135
|
outline: none;
|
|
128
136
|
position: relative;
|
|
129
137
|
z-index: 1;
|
|
@@ -133,3 +141,5 @@ export const Label = styled.span<{ icon?: string; backIcon?: string }>`
|
|
|
133
141
|
}
|
|
134
142
|
padding-right: ${(p) => (p.backIcon ? p.theme.spacing.s : `0`)};
|
|
135
143
|
`;
|
|
144
|
+
|
|
145
|
+
export { Button, TextButton, LineButton, MinimalButton, Label }
|
|
@@ -1,64 +1,58 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import { structuredData } from "@ax/api";
|
|
3
|
+
import { structuredData, selects } from "@ax/api";
|
|
4
4
|
import { isReqOk } from "@ax/helpers";
|
|
5
5
|
import { IGetStructuredDataParams, IDataSource, ISite, IStructuredData } from "@ax/types";
|
|
6
|
-
import { Button, CheckField, FieldsBehavior,
|
|
7
|
-
import {
|
|
6
|
+
import { Button, CheckField, FieldsBehavior, IconAction, Select, SearchField, Tag, Tooltip } from "@ax/components";
|
|
7
|
+
import { useCategoryColors } from "@ax/hooks";
|
|
8
|
+
|
|
9
|
+
import { ISource, IFilter } from "../../Context";
|
|
8
10
|
|
|
9
11
|
import * as S from "./style";
|
|
10
12
|
|
|
11
|
-
const AutoItem = (props: IProps) => {
|
|
12
|
-
const {
|
|
13
|
+
const AutoItem = (props: IProps): JSX.Element => {
|
|
14
|
+
const {
|
|
15
|
+
source,
|
|
16
|
+
canDelete,
|
|
17
|
+
filter,
|
|
18
|
+
handleDelete,
|
|
19
|
+
addFilter,
|
|
20
|
+
currentSite,
|
|
21
|
+
structuredDataSite,
|
|
22
|
+
filterOperator,
|
|
23
|
+
globalOperator,
|
|
24
|
+
siteID,
|
|
25
|
+
} = props;
|
|
13
26
|
|
|
14
27
|
const initState: IState = {
|
|
15
28
|
selected: "",
|
|
16
29
|
options: [],
|
|
17
|
-
filter,
|
|
18
30
|
isOpen: false,
|
|
31
|
+
isAdvancedOpen: false,
|
|
32
|
+
categories: [],
|
|
33
|
+
selectedCategories: [],
|
|
19
34
|
filteredOptions: [],
|
|
20
35
|
};
|
|
21
36
|
|
|
22
37
|
const [state, setState] = useState(initState);
|
|
23
38
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
};
|
|
39
|
+
const catIDs = state.categories.map((cat: ICategory) => cat.label);
|
|
40
|
+
const { categoryColors } = useCategoryColors(catIDs);
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
getCategories();
|
|
44
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
+
}, []);
|
|
33
46
|
|
|
34
|
-
const
|
|
35
|
-
const handleClick = () => item.action(source);
|
|
36
|
-
return (
|
|
37
|
-
<S.ActionItem key={item.icon} onClick={handleClick} data-testid="auto-item-action-item">
|
|
38
|
-
<Icon name={item.icon} />
|
|
39
|
-
<S.ActionText>{item.label}</S.ActionText>
|
|
40
|
-
</S.ActionItem>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
47
|
+
const removeItem = () => handleDelete(source.id);
|
|
43
48
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const ActionMenu = (props: any) => {
|
|
55
|
-
const { source } = props;
|
|
56
|
-
return (
|
|
57
|
-
<FloatingMenu Button={MoreInfoButton}>
|
|
58
|
-
<S.ActionMenu>{editMenu.options.map((item: any, i: number) => actionMenuItem(item, source))}</S.ActionMenu>
|
|
59
|
-
</FloatingMenu>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
49
|
+
const menuOptions = [
|
|
50
|
+
{
|
|
51
|
+
label: "delete",
|
|
52
|
+
icon: "delete",
|
|
53
|
+
action: removeItem,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
62
56
|
|
|
63
57
|
const getIsGlobal = (id: string): boolean => {
|
|
64
58
|
const data = structuredDataSite && structuredDataSite.find((elem: any) => elem.id === id);
|
|
@@ -89,6 +83,32 @@ const AutoItem = (props: IProps) => {
|
|
|
89
83
|
return false;
|
|
90
84
|
};
|
|
91
85
|
|
|
86
|
+
const getCategories = async (): Promise<boolean> => {
|
|
87
|
+
try {
|
|
88
|
+
const result = await selects.getSelectItems("categories", source.id);
|
|
89
|
+
if (isReqOk(result.status)) {
|
|
90
|
+
const selectedCategories = getFiltersCategories(filter, result.data);
|
|
91
|
+
setState({ ...state, categories: result.data, selectedCategories });
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.log(e);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const getFiltersCategories = (filters: any[], categories: ICategory[]) => {
|
|
101
|
+
let filterCategories: ICategory[] = [];
|
|
102
|
+
filters.forEach((filter: any) => {
|
|
103
|
+
const filterCategory = categories.find((cat: ICategory) => cat.label === filter.category);
|
|
104
|
+
filterCategories =
|
|
105
|
+
filterCategory && !filterCategories.includes(filterCategory)
|
|
106
|
+
? [...filterCategories, filterCategory]
|
|
107
|
+
: filterCategories;
|
|
108
|
+
});
|
|
109
|
+
return filterCategories;
|
|
110
|
+
};
|
|
111
|
+
|
|
92
112
|
const handleSelectOnChange = (newValue: string | null) => {
|
|
93
113
|
if (newValue) {
|
|
94
114
|
getCategoryContent(newValue);
|
|
@@ -99,35 +119,92 @@ const AutoItem = (props: IProps) => {
|
|
|
99
119
|
|
|
100
120
|
const handleCheckChange = (checkValue: any) => {
|
|
101
121
|
if (checkValue.isChecked) {
|
|
102
|
-
const newFilter: any = state.options.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
122
|
+
const newFilter: any = state.options.find((f: any) => checkValue.value === f.id);
|
|
123
|
+
if (newFilter) {
|
|
124
|
+
const filterCategory = state.categories.find((cat: ICategory) => cat.value === newFilter.structuredData);
|
|
125
|
+
const selectedCategories =
|
|
126
|
+
filterCategory && !state.selectedCategories.includes(filterCategory)
|
|
127
|
+
? [...state.selectedCategories, filterCategory]
|
|
128
|
+
: state.selectedCategories;
|
|
129
|
+
|
|
130
|
+
setState({
|
|
131
|
+
...state,
|
|
132
|
+
selectedCategories,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const updatedSource: ISource = {
|
|
136
|
+
structuredData: source.id,
|
|
137
|
+
filters: [
|
|
138
|
+
...filter,
|
|
139
|
+
{
|
|
140
|
+
id: newFilter.id,
|
|
141
|
+
label: newFilter.content.title,
|
|
142
|
+
category: filterCategory?.label || "",
|
|
143
|
+
color: categoryColors[filterCategory?.label || ""],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
globalOperator: globalOperator,
|
|
147
|
+
filterOperator: filterOperator,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
addFilter(updatedSource);
|
|
151
|
+
}
|
|
107
152
|
} else {
|
|
108
|
-
const newFilters =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
};
|
|
153
|
+
const newFilters = filter.filter((e) => e.id !== checkValue.value);
|
|
154
|
+
const selectedCategories = getFiltersCategories(newFilters, state.categories);
|
|
155
|
+
setState({ ...state, selectedCategories });
|
|
112
156
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
157
|
+
const updatedSource: ISource = {
|
|
158
|
+
structuredData: source.id,
|
|
159
|
+
filters: newFilters,
|
|
160
|
+
globalOperator: globalOperator,
|
|
161
|
+
filterOperator: filterOperator,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
addFilter(updatedSource);
|
|
165
|
+
}
|
|
116
166
|
};
|
|
117
167
|
|
|
118
168
|
const isChecked = (id: number) => {
|
|
119
|
-
const ids =
|
|
169
|
+
const ids = filter.map((a) => a.id);
|
|
120
170
|
return ids.includes(id);
|
|
121
171
|
};
|
|
122
172
|
|
|
123
|
-
const toggleFilters = () => {
|
|
124
|
-
|
|
125
|
-
};
|
|
173
|
+
const toggleFilters = () => setState({ ...state, isOpen: !state.isOpen });
|
|
174
|
+
|
|
175
|
+
const toggleAdvanced = () => setState({ ...state, isAdvancedOpen: !state.isAdvancedOpen });
|
|
126
176
|
|
|
127
177
|
const handleDeleteTag = (id: number) => {
|
|
128
|
-
const newFilters =
|
|
129
|
-
|
|
130
|
-
|
|
178
|
+
const newFilters = filter.filter((e) => e.id !== id);
|
|
179
|
+
const selectedCategories = getFiltersCategories(newFilters, state.categories);
|
|
180
|
+
setState({ ...state, selectedCategories });
|
|
181
|
+
const updatedSource: ISource = {
|
|
182
|
+
structuredData: source.id,
|
|
183
|
+
filters: newFilters,
|
|
184
|
+
globalOperator: globalOperator,
|
|
185
|
+
filterOperator: filterOperator,
|
|
186
|
+
};
|
|
187
|
+
addFilter(updatedSource);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const handleFilterOperator = (value: string) => {
|
|
191
|
+
const updatedSource: ISource = {
|
|
192
|
+
structuredData: source.id,
|
|
193
|
+
filters: filter,
|
|
194
|
+
globalOperator: globalOperator,
|
|
195
|
+
filterOperator: value,
|
|
196
|
+
};
|
|
197
|
+
addFilter(updatedSource);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const handleGlobalOperator = (value: string) => {
|
|
201
|
+
const updatedSource: ISource = {
|
|
202
|
+
structuredData: source.id,
|
|
203
|
+
filters: filter,
|
|
204
|
+
globalOperator: value,
|
|
205
|
+
filterOperator: filterOperator,
|
|
206
|
+
};
|
|
207
|
+
addFilter(updatedSource);
|
|
131
208
|
};
|
|
132
209
|
|
|
133
210
|
const handleSearchChange = (query: string) => {
|
|
@@ -137,33 +214,104 @@ const AutoItem = (props: IProps) => {
|
|
|
137
214
|
setState({ ...state, filteredOptions });
|
|
138
215
|
};
|
|
139
216
|
|
|
217
|
+
const handleClearFilters = () => {
|
|
218
|
+
setState({ ...state, selectedCategories: [] });
|
|
219
|
+
const updatedSource: ISource = {
|
|
220
|
+
structuredData: source.id,
|
|
221
|
+
filters: [],
|
|
222
|
+
};
|
|
223
|
+
addFilter(updatedSource);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const operatorOptions = [
|
|
227
|
+
{ value: "OR", label: "OR" },
|
|
228
|
+
{ value: "AND", label: "AND" },
|
|
229
|
+
];
|
|
230
|
+
|
|
140
231
|
return (
|
|
141
232
|
<S.TypeContainer key={source.id}>
|
|
142
|
-
<S.TypeWrapper>
|
|
233
|
+
<S.TypeWrapper data-testid="item-type-wrapper">
|
|
143
234
|
<S.TypeLabel>Type</S.TypeLabel>
|
|
144
235
|
<S.TypeName>{source.title}</S.TypeName>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
236
|
+
<S.ActionsWrapper>
|
|
237
|
+
<S.IconWrapper>
|
|
238
|
+
<Tooltip content="Filters">
|
|
239
|
+
<IconAction icon="filter" onClick={toggleFilters} active={state.isOpen} />
|
|
240
|
+
</Tooltip>
|
|
241
|
+
</S.IconWrapper>
|
|
242
|
+
<S.IconWrapper>
|
|
243
|
+
<Tooltip content="Advanced settings">
|
|
244
|
+
<IconAction icon="settings" onClick={toggleAdvanced} active={state.isAdvancedOpen} />
|
|
245
|
+
</Tooltip>
|
|
246
|
+
</S.IconWrapper>
|
|
247
|
+
{canDelete && <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Options" />}
|
|
248
|
+
</S.ActionsWrapper>
|
|
149
249
|
</S.TypeWrapper>
|
|
150
|
-
<S.FiltersWrapper>
|
|
250
|
+
<S.FiltersWrapper isActive={state.isAdvancedOpen} isEmpty={filter.length === 0}>
|
|
151
251
|
{filter &&
|
|
152
|
-
filter.map((e:
|
|
153
|
-
const handleClick = () =>
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
252
|
+
filter.map((e: IFilter) => {
|
|
253
|
+
const handleClick = () => handleDeleteTag(e.id);
|
|
254
|
+
return (
|
|
255
|
+
<Tag
|
|
256
|
+
key={e.label}
|
|
257
|
+
text={`${e.category}: ${e.label}`}
|
|
258
|
+
onDeleteAction={handleClick}
|
|
259
|
+
color={e.color || categoryColors[e.category || ""]}
|
|
260
|
+
/>
|
|
261
|
+
);
|
|
157
262
|
})}
|
|
263
|
+
{state.isAdvancedOpen && (
|
|
264
|
+
<S.OptionsBlock>
|
|
265
|
+
Relation between filters{" "}
|
|
266
|
+
<S.SelectWrapper>
|
|
267
|
+
<Select
|
|
268
|
+
name="filterOperator"
|
|
269
|
+
options={operatorOptions}
|
|
270
|
+
onChange={handleFilterOperator}
|
|
271
|
+
value={filterOperator || "OR"}
|
|
272
|
+
type="inline"
|
|
273
|
+
mandatory={true}
|
|
274
|
+
/>
|
|
275
|
+
</S.SelectWrapper>
|
|
276
|
+
</S.OptionsBlock>
|
|
277
|
+
)}
|
|
158
278
|
</S.FiltersWrapper>
|
|
279
|
+
{state.isAdvancedOpen && (
|
|
280
|
+
<S.FiltersWrapper isActive={state.isAdvancedOpen} isEmpty={state.selectedCategories.length === 0}>
|
|
281
|
+
{state.selectedCategories.map((e: ICategory) => {
|
|
282
|
+
return <Tag key={e.label} text={e.label} color={categoryColors[e.label]} rounded={false} />;
|
|
283
|
+
})}
|
|
284
|
+
<S.OptionsBlock>
|
|
285
|
+
Relation between categories{" "}
|
|
286
|
+
<S.SelectWrapper>
|
|
287
|
+
<Select
|
|
288
|
+
name="globalOperator"
|
|
289
|
+
options={operatorOptions}
|
|
290
|
+
onChange={handleGlobalOperator}
|
|
291
|
+
value={globalOperator || "AND"}
|
|
292
|
+
type="inline"
|
|
293
|
+
mandatory={true}
|
|
294
|
+
/>
|
|
295
|
+
</S.SelectWrapper>
|
|
296
|
+
</S.OptionsBlock>
|
|
297
|
+
</S.FiltersWrapper>
|
|
298
|
+
)}
|
|
299
|
+
{filter.length > 0 && (
|
|
300
|
+
<S.ClearWrapper>
|
|
301
|
+
<Button type="button" buttonStyle="minimal" onClick={handleClearFilters}>
|
|
302
|
+
Clear All Filters
|
|
303
|
+
</Button>
|
|
304
|
+
</S.ClearWrapper>
|
|
305
|
+
)}
|
|
159
306
|
<S.ActionsFilterWrapper isOpen={state.isOpen}>
|
|
160
307
|
<FieldsBehavior
|
|
161
308
|
title="Create filter by"
|
|
162
309
|
name="categorySelect"
|
|
163
|
-
fieldType="
|
|
310
|
+
fieldType="Select"
|
|
164
311
|
value={state.selected}
|
|
165
|
-
entity="categories"
|
|
166
312
|
onChange={handleSelectOnChange}
|
|
313
|
+
options={state.categories}
|
|
314
|
+
placeholder="Select..."
|
|
167
315
|
entityId={source.id}
|
|
168
316
|
site={currentSite}
|
|
169
317
|
/>
|
|
@@ -185,13 +333,6 @@ const AutoItem = (props: IProps) => {
|
|
|
185
333
|
/>
|
|
186
334
|
))}
|
|
187
335
|
</S.ChecksWrapper>
|
|
188
|
-
{state.options.length > 0 && (
|
|
189
|
-
<S.ButtonWrapper>
|
|
190
|
-
<Button type="button" buttonStyle="line" onClick={handleButtonClick}>
|
|
191
|
-
Add filter
|
|
192
|
-
</Button>
|
|
193
|
-
</S.ButtonWrapper>
|
|
194
|
-
)}
|
|
195
336
|
</S.ActionsFilterWrapper>
|
|
196
337
|
</S.TypeContainer>
|
|
197
338
|
);
|
|
@@ -200,19 +341,28 @@ const AutoItem = (props: IProps) => {
|
|
|
200
341
|
interface IState {
|
|
201
342
|
selected: string;
|
|
202
343
|
options: any[];
|
|
203
|
-
filter: any[];
|
|
204
344
|
isOpen: boolean;
|
|
345
|
+
isAdvancedOpen: boolean;
|
|
346
|
+
categories: ICategory[];
|
|
347
|
+
selectedCategories: ICategory[];
|
|
205
348
|
filteredOptions: any[];
|
|
206
349
|
}
|
|
207
350
|
|
|
351
|
+
interface ICategory {
|
|
352
|
+
value: string;
|
|
353
|
+
label: string;
|
|
354
|
+
}
|
|
355
|
+
|
|
208
356
|
interface IProps {
|
|
209
357
|
source: IDataSource;
|
|
210
358
|
canDelete: boolean;
|
|
211
359
|
filter: IFilter[];
|
|
212
360
|
currentSite: ISite | null;
|
|
213
361
|
structuredDataSite: IStructuredData[];
|
|
362
|
+
filterOperator?: string;
|
|
363
|
+
globalOperator?: string;
|
|
214
364
|
handleDelete: (value: string) => void;
|
|
215
|
-
addFilter: (
|
|
365
|
+
addFilter: (source: ISource) => void;
|
|
216
366
|
siteID?: number | null;
|
|
217
367
|
}
|
|
218
368
|
|