@griddo/ax 10.4.17 → 10.4.19
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/components/Fields/CheckField/style.tsx +1 -0
- package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +1 -1
- package/src/components/Fields/ComponentArray/SameComponentArray/index.tsx +107 -22
- package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +8 -3
- package/src/components/Fields/ReferenceField/index.tsx +1 -0
- package/src/components/SearchField/index.tsx +2 -2
- package/src/containers/Sites/actions.tsx +18 -0
- package/src/containers/Sites/constants.tsx +1 -0
- package/src/containers/Sites/interfaces.tsx +6 -0
- package/src/containers/Sites/reducer.tsx +4 -0
- package/src/containers/StructuredData/actions.tsx +18 -0
- package/src/containers/StructuredData/constants.tsx +2 -0
- package/src/containers/StructuredData/interfaces.tsx +6 -0
- package/src/containers/StructuredData/reducer.tsx +4 -0
- package/src/helpers/schemas.tsx +1 -1
- package/src/modules/Content/PageImporter/style.tsx +7 -3
- package/src/modules/Content/index.tsx +15 -10
- package/src/modules/Sites/SitesList/index.tsx +23 -34
- package/src/modules/Sites/index.tsx +4 -0
- package/src/modules/StructuredData/StructuredDataList/index.tsx +14 -13
- package/src/types/index.tsx +1 -0
- /package/src/components/Fields/ComponentArray/{MixableComponentArray/BulkHeader → BulkHeader}/index.tsx +0 -0
- /package/src/components/Fields/ComponentArray/{MixableComponentArray/BulkHeader → BulkHeader}/style.tsx +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.4.
|
|
4
|
+
"version": "10.4.19",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -231,5 +231,5 @@
|
|
|
231
231
|
"publishConfig": {
|
|
232
232
|
"access": "public"
|
|
233
233
|
},
|
|
234
|
-
"gitHead": "
|
|
234
|
+
"gitHead": "b383bcb76a78076ab65ed5768ffea987adc18a5e"
|
|
235
235
|
}
|
|
@@ -8,7 +8,7 @@ import { useBulkSelection, useModal, useToast } from "@ax/hooks";
|
|
|
8
8
|
import { getComponentProps, containerToComponentArray, getTypefromKey, getModulesToPaste } from "../helpers";
|
|
9
9
|
import AddItemButton from "./AddItemButton";
|
|
10
10
|
import PasteModuleButton from "./PasteModuleButton";
|
|
11
|
-
import BulkHeader from "
|
|
11
|
+
import BulkHeader from "../BulkHeader";
|
|
12
12
|
|
|
13
13
|
import * as S from "./style";
|
|
14
14
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { DragDropContext, Droppable, Draggable, DropResult } from "react-beautiful-dnd";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { DragDropContext, Droppable, Draggable, DropResult, BeforeCapture } from "react-beautiful-dnd";
|
|
3
3
|
|
|
4
|
-
import { IModule } from "@ax/types";
|
|
4
|
+
import { IModule, INotification, ISchemaField } from "@ax/types";
|
|
5
5
|
import { ComponentContainer } from "@ax/components";
|
|
6
|
+
import { useBulkSelection } from "@ax/hooks";
|
|
6
7
|
|
|
7
8
|
import AddItemButton from "./AddItemButton";
|
|
8
9
|
import { getComponentProps, getTypefromKey } from "../helpers";
|
|
10
|
+
import BulkHeader from "../BulkHeader";
|
|
9
11
|
|
|
10
12
|
import * as S from "./style";
|
|
11
13
|
|
|
@@ -13,7 +15,7 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
13
15
|
const {
|
|
14
16
|
whiteList,
|
|
15
17
|
title,
|
|
16
|
-
value,
|
|
18
|
+
value = [],
|
|
17
19
|
goTo,
|
|
18
20
|
selectedContent,
|
|
19
21
|
editorID,
|
|
@@ -30,27 +32,35 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
30
32
|
|
|
31
33
|
const type = getTypefromKey(objKey);
|
|
32
34
|
const { contentType = type } = field;
|
|
35
|
+
const componentIDs: number[] = value && value.length ? value.map((element) => element.editorID) : [];
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
const { addModuleAction, addComponentAction, setNotificationAction, duplicateModuleAction, deleteModuleAction } =
|
|
38
|
+
actions || {};
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const [isBulkOpen, setIsBulkOpen] = useState(false);
|
|
41
|
+
const [draggingId, setDraggingId] = useState<number | null>(null);
|
|
42
|
+
const { resetBulkSelection, selectedItems, isSelected, checkState, addToBulkSelection, selectAllItems } =
|
|
43
|
+
useBulkSelection(componentIDs);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (selectedItems.all.length) {
|
|
47
|
+
setIsBulkOpen(true);
|
|
48
|
+
}
|
|
49
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
|
+
}, [selectedItems.all]);
|
|
41
51
|
|
|
42
52
|
const getText = (name: string, index: number) => {
|
|
43
53
|
return value && value.length > 1 ? `#${index + 1} ${name}` : name;
|
|
44
54
|
};
|
|
45
55
|
|
|
46
|
-
const
|
|
56
|
+
const componentType = field.reference ? selectedContent[field.reference] : selectedContent["kind"];
|
|
47
57
|
|
|
48
58
|
const isModuleArr = contentType === "modules";
|
|
49
59
|
const isComponentModule = contentType === "components";
|
|
50
60
|
|
|
51
61
|
const handleAddModule = (moduleType: string) => addModuleAction(moduleType, objKey, editorID, isComponentModule);
|
|
52
62
|
|
|
53
|
-
const handleAddComponent = () => addComponentAction && addComponentAction(
|
|
63
|
+
const handleAddComponent = () => addComponentAction && addComponentAction(componentType, objKey);
|
|
54
64
|
|
|
55
65
|
const handleAdd = isModuleArr ? handleAddModule : handleAddComponent;
|
|
56
66
|
|
|
@@ -59,19 +69,24 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
59
69
|
const Asterisk = () => (mandatory ? <S.Asterisk>*</S.Asterisk> : null);
|
|
60
70
|
|
|
61
71
|
const onDragEnd = (result: DropResult) => {
|
|
62
|
-
const { moveModuleAction } = actions;
|
|
72
|
+
const { moveModuleAction } = actions || {};
|
|
63
73
|
|
|
64
|
-
if (!result.destination) {
|
|
74
|
+
if (!moveModuleAction || !result.destination || result.destination.index === result.source.index) {
|
|
75
|
+
setDraggingId(null);
|
|
65
76
|
return;
|
|
66
77
|
}
|
|
67
78
|
|
|
68
|
-
if (
|
|
69
|
-
|
|
79
|
+
if (selectedItems.all.length > 0 && selectedItems.all.includes(parseInt(result.draggableId))) {
|
|
80
|
+
moveModuleAction(selectedItems.all, selectedContent, result.destination.index, objKey);
|
|
81
|
+
} else {
|
|
82
|
+
moveModuleAction([parseInt(result.draggableId)], selectedContent, result.destination.index, objKey);
|
|
70
83
|
}
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
setDraggingId(null);
|
|
73
86
|
};
|
|
74
87
|
|
|
88
|
+
const onBeforeCapture = (start: BeforeCapture) => setDraggingId(parseInt(start.draggableId));
|
|
89
|
+
|
|
75
90
|
const ComponentList = React.memo(function ComponentList({ components }: any) {
|
|
76
91
|
return components.map((element: any, i: number) => {
|
|
77
92
|
const { editorID } = element;
|
|
@@ -81,9 +96,14 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
81
96
|
isModuleArr
|
|
82
97
|
);
|
|
83
98
|
const text = getText(componentTitle || displayName, i);
|
|
99
|
+
const isItemSelected = isSelected(editorID);
|
|
100
|
+
const isDraggingSelected = selectedItems.all.includes(draggingId);
|
|
101
|
+
const isGhosting = isItemSelected && !!draggingId && draggingId !== editorID && isDraggingSelected;
|
|
102
|
+
const isMultiDragging = selectedItems.all.length > 1 && draggingId === editorID;
|
|
103
|
+
|
|
84
104
|
return (
|
|
85
105
|
<Draggable draggableId={`${editorID}`} index={i} key={editorID}>
|
|
86
|
-
{(provided) => (
|
|
106
|
+
{(provided, snapshot) => (
|
|
87
107
|
<ComponentContainer
|
|
88
108
|
isArray={true}
|
|
89
109
|
key={editorID}
|
|
@@ -103,6 +123,12 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
103
123
|
innerRef={provided.innerRef}
|
|
104
124
|
provided={provided}
|
|
105
125
|
isModule={isModule}
|
|
126
|
+
isSelected={isItemSelected}
|
|
127
|
+
onChange={addToBulkSelection}
|
|
128
|
+
hasMenu={selectedItems.all.length > 0}
|
|
129
|
+
isMultiDragging={snapshot.isDragging && isMultiDragging}
|
|
130
|
+
draggingCount={selectedItems.all.length}
|
|
131
|
+
className={`${isGhosting ? "ghosting" : ""} ${snapshot.isDragging && isMultiDragging ? "dragging" : ""}`}
|
|
106
132
|
/>
|
|
107
133
|
)}
|
|
108
134
|
</Draggable>
|
|
@@ -110,19 +136,67 @@ const SameComponentArray = (props: ISameComponentArrayProps): JSX.Element => {
|
|
|
110
136
|
});
|
|
111
137
|
});
|
|
112
138
|
|
|
139
|
+
const handleDuplicate = () => {
|
|
140
|
+
if (maxItems && maxItems - value.length < selectedItems.all.length) {
|
|
141
|
+
const notification: INotification = {
|
|
142
|
+
type: "error",
|
|
143
|
+
text: "Unable to duplicate modules: The destination area has a limit on the number of modules allowed. Please adjust the selection accordingly.",
|
|
144
|
+
};
|
|
145
|
+
setNotificationAction && setNotificationAction(notification);
|
|
146
|
+
} else {
|
|
147
|
+
duplicateModuleAction && duplicateModuleAction(selectedItems.all, objKey);
|
|
148
|
+
resetBulkSelection();
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const handleDelete = () => {
|
|
153
|
+
deleteModuleAction && deleteModuleAction(selectedItems.all, objKey);
|
|
154
|
+
resetBulkSelection();
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const bulkActions = [
|
|
158
|
+
{
|
|
159
|
+
icon: "duplicate",
|
|
160
|
+
text: "duplicate",
|
|
161
|
+
action: handleDuplicate,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
icon: "delete",
|
|
165
|
+
text: "delete",
|
|
166
|
+
action: handleDelete,
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
const selectItems = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());
|
|
171
|
+
|
|
172
|
+
const toggleBulk = () => {
|
|
173
|
+
setIsBulkOpen(false);
|
|
174
|
+
resetBulkSelection();
|
|
175
|
+
};
|
|
176
|
+
|
|
113
177
|
return (
|
|
114
178
|
<S.Wrapper data-testid="sameComponentWrapper">
|
|
115
179
|
<S.Title>
|
|
116
180
|
{title} <Asterisk />
|
|
117
181
|
</S.Title>
|
|
118
182
|
<S.ItemRow>
|
|
119
|
-
|
|
183
|
+
{isBulkOpen ? (
|
|
184
|
+
<BulkHeader
|
|
185
|
+
selectItems={selectItems}
|
|
186
|
+
checkState={checkState}
|
|
187
|
+
totalItems={selectedItems.all.length}
|
|
188
|
+
toggleBulk={toggleBulk}
|
|
189
|
+
actions={bulkActions}
|
|
190
|
+
/>
|
|
191
|
+
) : (
|
|
192
|
+
<S.Subtitle>{value?.length || 0} items</S.Subtitle>
|
|
193
|
+
)}
|
|
120
194
|
{showAddItemButton && !disabled && (
|
|
121
195
|
<AddItemButton handleClick={handleAdd} tooltipText={isModuleArr ? "Add module" : "Add component"} />
|
|
122
196
|
)}
|
|
123
197
|
</S.ItemRow>
|
|
124
198
|
{value && Array.isArray(value) && (
|
|
125
|
-
<DragDropContext onDragEnd={onDragEnd}>
|
|
199
|
+
<DragDropContext onDragEnd={onDragEnd} onBeforeCapture={onBeforeCapture}>
|
|
126
200
|
<Droppable droppableId="list">
|
|
127
201
|
{(provided) => (
|
|
128
202
|
<div ref={provided.innerRef} {...provided.droppableProps}>
|
|
@@ -146,12 +220,23 @@ export interface ISameComponentArrayProps {
|
|
|
146
220
|
selectedContent: any;
|
|
147
221
|
editorID: number;
|
|
148
222
|
goTo: (editorID: string) => void;
|
|
149
|
-
actions:
|
|
223
|
+
actions: {
|
|
224
|
+
addComponentAction: (componentType: any, key?: string) => void;
|
|
225
|
+
addModuleAction: (moduleType: string, key: string, selectedID: number, isComponentModule?: boolean) => void;
|
|
226
|
+
deleteModuleAction: (editorID: number[], key?: string) => void;
|
|
227
|
+
duplicateModuleAction: (editorID: number[], key?: string) => number;
|
|
228
|
+
copyModuleAction: (editorID: number[]) => boolean | number;
|
|
229
|
+
replaceElementsInCollectionAction: (newValue: string, reference?: string) => void;
|
|
230
|
+
moveModuleAction: (moduleID: number[], selectedContent: any, newIndex: number, key: string) => void;
|
|
231
|
+
pasteModuleAction: (editorID: number, key: string, modulesToPaste: IModule[]) => Promise<{ error?: INotification }>;
|
|
232
|
+
setNotificationAction: (notification: INotification) => void;
|
|
233
|
+
replaceModuleAction: (module: any, parent: any, objKey: string) => void;
|
|
234
|
+
};
|
|
150
235
|
categories?: any;
|
|
151
236
|
disabled?: boolean;
|
|
152
237
|
activatedModules: string[];
|
|
153
238
|
objKey: string;
|
|
154
|
-
field:
|
|
239
|
+
field: ISchemaField;
|
|
155
240
|
mandatory?: boolean;
|
|
156
241
|
theme: string;
|
|
157
242
|
}
|
|
@@ -19,7 +19,7 @@ import Item from "./Item";
|
|
|
19
19
|
import * as S from "./style";
|
|
20
20
|
|
|
21
21
|
const ManualPanel = (props: IProps) => {
|
|
22
|
-
const { onChange, currentSite, hasMaxItems, handleValidation, validators, lang, globalLangs } = props;
|
|
22
|
+
const { onChange, currentSite, hasMaxItems, handleValidation, validators, lang, globalLangs, maxItems } = props;
|
|
23
23
|
|
|
24
24
|
const { state, setState } = useReference();
|
|
25
25
|
|
|
@@ -83,7 +83,7 @@ const ManualPanel = (props: IProps) => {
|
|
|
83
83
|
if (itemSelectedID) {
|
|
84
84
|
newSelIds = state.fixed.filter((a: number) => a !== itemSelectedID);
|
|
85
85
|
selItems = state.selectedItems.filter((b: IStructuredDataContent) => b.id !== itemSelectedID);
|
|
86
|
-
if(selItems.length === 0) {
|
|
86
|
+
if (selItems.length === 0) {
|
|
87
87
|
setItemSite(form.site);
|
|
88
88
|
}
|
|
89
89
|
} else {
|
|
@@ -213,7 +213,11 @@ const ManualPanel = (props: IProps) => {
|
|
|
213
213
|
(dataLang: IDataLanguage) => state.fixed.includes(dataLang.id) && dataLang.language !== form.lang
|
|
214
214
|
);
|
|
215
215
|
const source = state.sourceTitles.find((el: IDataSource) => el.id === item.structuredData);
|
|
216
|
-
const disabled =
|
|
216
|
+
const disabled =
|
|
217
|
+
(hasMaxItems && !isChecked) ||
|
|
218
|
+
!!hasVersionInPageLanguage ||
|
|
219
|
+
(maxItems && state.fixed.length >= maxItems && !isChecked) ||
|
|
220
|
+
hasContentFromOtherSite;
|
|
217
221
|
return (
|
|
218
222
|
<React.Fragment key={`${item.content.title}-${item.id}`}>
|
|
219
223
|
{source && (
|
|
@@ -251,6 +255,7 @@ interface IProps {
|
|
|
251
255
|
validators?: Record<string, unknown>;
|
|
252
256
|
lang: { locale: string; id: number };
|
|
253
257
|
globalLangs: ILanguage[];
|
|
258
|
+
maxItems?: number;
|
|
254
259
|
}
|
|
255
260
|
|
|
256
261
|
interface IFormState {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Icon } from "@ax/components";
|
|
2
|
-
import React, { useEffect,
|
|
2
|
+
import React, { useEffect, useState } from "react";
|
|
3
3
|
import { Select } from "../Fields";
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
@@ -19,7 +19,7 @@ const SearchField = (props: ISearchFieldProps): JSX.Element => {
|
|
|
19
19
|
value,
|
|
20
20
|
} = props;
|
|
21
21
|
|
|
22
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
22
|
+
const [isOpen, setIsOpen] = useState(value && value.trim() !== "" ? true : false);
|
|
23
23
|
const [inputValue, setInputValue] = useState(value || "");
|
|
24
24
|
const [selectValue, setSelectValue] = useState<string>("");
|
|
25
25
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
SET_CURRENT_SITE_ERROR_PAGES,
|
|
15
15
|
SET_CONTENT_FILTERS,
|
|
16
16
|
SET_CONFIG,
|
|
17
|
+
SET_CURRENT_SEARCH,
|
|
17
18
|
} from "./constants";
|
|
18
19
|
|
|
19
20
|
import {
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
ISetContentFilters,
|
|
31
32
|
ISetSitesTotalItems,
|
|
32
33
|
ISetConfig,
|
|
34
|
+
ISetCurrentSearch,
|
|
33
35
|
} from "./interfaces";
|
|
34
36
|
|
|
35
37
|
import {
|
|
@@ -113,6 +115,10 @@ function setConfig(config: ISiteListConfig): ISetConfig {
|
|
|
113
115
|
return { type: SET_CONFIG, payload: { config } };
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
function setCurrentSearch(currentSearch: string): ISetCurrentSearch {
|
|
119
|
+
return { type: SET_CURRENT_SEARCH, payload: { currentSearch } };
|
|
120
|
+
}
|
|
121
|
+
|
|
116
122
|
// TODO: hay que controlar que cuando da error la API borrar los sites ya guardados y sacar el error (ver los siguientes FIXME)
|
|
117
123
|
function getSites(params: IGetSitesParams = { recentSitesNumber: 7 }): (dispatch: Dispatch) => Promise<void> {
|
|
118
124
|
return async (dispatch) => {
|
|
@@ -479,6 +485,7 @@ function resetSiteValues(siteID: number): (dispatch: Dispatch) => void {
|
|
|
479
485
|
dispatch(setCurrentSitePages([]));
|
|
480
486
|
dispatch(setTotalItems(0));
|
|
481
487
|
getAnalytics(siteID)(dispatch);
|
|
488
|
+
dispatch(setCurrentSearch(""));
|
|
482
489
|
};
|
|
483
490
|
}
|
|
484
491
|
|
|
@@ -695,6 +702,16 @@ function setListConfig(config: ISiteListConfig): (dispatch: Dispatch) => Promise
|
|
|
695
702
|
};
|
|
696
703
|
}
|
|
697
704
|
|
|
705
|
+
function updateCurrentSearch(query: string): (dispatch: Dispatch) => Promise<void> {
|
|
706
|
+
return async (dispatch) => {
|
|
707
|
+
try {
|
|
708
|
+
dispatch(setCurrentSearch(query));
|
|
709
|
+
} catch (e) {
|
|
710
|
+
console.log(e);
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
698
715
|
export {
|
|
699
716
|
setCurrentSiteInfo,
|
|
700
717
|
setCurrentSitePages,
|
|
@@ -725,4 +742,5 @@ export {
|
|
|
725
742
|
deleteAndRemoveFromSiteBulk,
|
|
726
743
|
setListConfig,
|
|
727
744
|
getSite,
|
|
745
|
+
updateCurrentSearch,
|
|
728
746
|
};
|
|
@@ -14,6 +14,7 @@ export const SET_SAVED_SITE_INFO = `${NAME}/SET_SAVED_SITE_INFO`;
|
|
|
14
14
|
export const SET_CURRENT_SITE_ERROR_PAGES = `${NAME}/SET_CURRENT_SITE_ERROR_PAGES`;
|
|
15
15
|
export const SET_CONTENT_FILTERS = `${NAME}/SET_CONTENT_FILTERS`;
|
|
16
16
|
export const SET_CONFIG = `${NAME}/SET_CONFIG`;
|
|
17
|
+
export const SET_CURRENT_SEARCH = `${NAME}/SET_CURRENT_SEARCH`;
|
|
17
18
|
|
|
18
19
|
export const ITEMS_PER_PAGE = 50;
|
|
19
20
|
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
SET_CONTENT_FILTERS,
|
|
14
14
|
SET_SITES_TOTAL_ITEMS,
|
|
15
15
|
SET_CONFIG,
|
|
16
|
+
SET_CURRENT_SEARCH,
|
|
16
17
|
} from "./constants";
|
|
17
18
|
import { IQueryValue, ISite, ISiteListConfig } from "@ax/types";
|
|
18
19
|
|
|
@@ -86,4 +87,9 @@ export interface ISetConfig {
|
|
|
86
87
|
payload: { config: ISiteListConfig };
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
export interface ISetCurrentSearch {
|
|
91
|
+
type: typeof SET_CURRENT_SEARCH;
|
|
92
|
+
payload: { currentSearch: string };
|
|
93
|
+
}
|
|
94
|
+
|
|
89
95
|
export type SitesActionsCreators = ISetSitesAction & ISetCurrentSiteInfoAction;
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
SET_CURRENT_SITE_ERROR_PAGES,
|
|
14
14
|
SET_CONTENT_FILTERS,
|
|
15
15
|
SET_CONFIG,
|
|
16
|
+
SET_CURRENT_SEARCH,
|
|
16
17
|
} from "./constants";
|
|
17
18
|
|
|
18
19
|
import { ISite, IPage, ILanguage, ISiteListConfig, IQueryValue } from "@ax/types";
|
|
@@ -34,6 +35,7 @@ export interface ISitesState {
|
|
|
34
35
|
currentSiteErrorPages: number[];
|
|
35
36
|
contentFilters: Record<string, IQueryValue[]> | null;
|
|
36
37
|
config: ISiteListConfig;
|
|
38
|
+
currentSearch: string;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
const config = {
|
|
@@ -64,6 +66,7 @@ export const initialState = {
|
|
|
64
66
|
currentSiteErrorPages: [],
|
|
65
67
|
contentFilters: null,
|
|
66
68
|
config,
|
|
69
|
+
currentSearch: "",
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
export function reducer(state = initialState, action: any): ISitesState {
|
|
@@ -82,6 +85,7 @@ export function reducer(state = initialState, action: any): ISitesState {
|
|
|
82
85
|
case SET_CURRENT_SITE_ERROR_PAGES:
|
|
83
86
|
case SET_CONTENT_FILTERS:
|
|
84
87
|
case SET_CONFIG:
|
|
88
|
+
case SET_CURRENT_SEARCH:
|
|
85
89
|
return { ...state, ...action.payload };
|
|
86
90
|
default:
|
|
87
91
|
return state;
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
SET_VALIDATED,
|
|
19
19
|
SET_CONTENT_FILTERS,
|
|
20
20
|
SET_IS_IA_TRANSLATED,
|
|
21
|
+
SET_CURRENT_SEARCH,
|
|
21
22
|
} from "./constants";
|
|
22
23
|
|
|
23
24
|
import {
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
ISetValidated,
|
|
35
36
|
ISetContentFilters,
|
|
36
37
|
ISetIsIATranslated,
|
|
38
|
+
ISetCurrentSearch,
|
|
37
39
|
} from "./interfaces";
|
|
38
40
|
import {
|
|
39
41
|
prepareStructuredDataContent,
|
|
@@ -127,6 +129,10 @@ function setIsIATranslated(isIATranslated: boolean): ISetIsIATranslated {
|
|
|
127
129
|
return { type: SET_IS_IA_TRANSLATED, payload: { isIATranslated } };
|
|
128
130
|
}
|
|
129
131
|
|
|
132
|
+
function setCurrentSearch(currentSearch: string): ISetCurrentSearch {
|
|
133
|
+
return { type: SET_CURRENT_SEARCH, payload: { currentSearch } };
|
|
134
|
+
}
|
|
135
|
+
|
|
130
136
|
function updateFormValue(valueObj: any): (dispatch: Dispatch, getState: any) => void {
|
|
131
137
|
return (dispatch, getState) => {
|
|
132
138
|
const {
|
|
@@ -651,12 +657,23 @@ function resetCurrentData(): (dispatch: Dispatch) => Promise<void> {
|
|
|
651
657
|
dispatch(setCurrentData(null));
|
|
652
658
|
dispatch(setCurrentDataID(null));
|
|
653
659
|
dispatch(setCurrentDataContent([]));
|
|
660
|
+
//dispatch(setCurrentSearch(""));
|
|
654
661
|
} catch (e) {
|
|
655
662
|
console.log("Error", e);
|
|
656
663
|
}
|
|
657
664
|
};
|
|
658
665
|
}
|
|
659
666
|
|
|
667
|
+
function updateCurrentSearch(query: string): (dispatch: Dispatch) => Promise<void> {
|
|
668
|
+
return async (dispatch) => {
|
|
669
|
+
try {
|
|
670
|
+
dispatch(setCurrentSearch(query));
|
|
671
|
+
} catch (e) {
|
|
672
|
+
console.log(e);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
660
677
|
export {
|
|
661
678
|
setIsActive,
|
|
662
679
|
setCategories,
|
|
@@ -694,4 +711,5 @@ export {
|
|
|
694
711
|
setFormValues,
|
|
695
712
|
setIsTranslated,
|
|
696
713
|
resetCurrentData,
|
|
714
|
+
updateCurrentSearch,
|
|
697
715
|
};
|
|
@@ -17,6 +17,7 @@ const SET_ERRORS = `${NAME}/SET_ERRORS`;
|
|
|
17
17
|
const SET_VALIDATED = `${NAME}/SET_VALIDATED`;
|
|
18
18
|
const SET_CONTENT_FILTERS = `${NAME}/SET_CONTENT_FILTERS`;
|
|
19
19
|
const SET_IS_IA_TRANSLATED = `${NAME}/SET_IS_IA_TRANSLATED`;
|
|
20
|
+
const SET_CURRENT_SEARCH = `${NAME}/SET_CURRENT_SEARCH`;
|
|
20
21
|
|
|
21
22
|
const ITEMS_PER_PAGE = 50;
|
|
22
23
|
|
|
@@ -49,4 +50,5 @@ export {
|
|
|
49
50
|
SET_VALIDATED,
|
|
50
51
|
SET_CONTENT_FILTERS,
|
|
51
52
|
SET_IS_IA_TRANSLATED,
|
|
53
|
+
SET_CURRENT_SEARCH,
|
|
52
54
|
};
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
SET_VALIDATED,
|
|
15
15
|
SET_CONTENT_FILTERS,
|
|
16
16
|
SET_IS_IA_TRANSLATED,
|
|
17
|
+
SET_CURRENT_SEARCH,
|
|
17
18
|
} from "./constants";
|
|
18
19
|
|
|
19
20
|
import { IStructuredData, IStructuredDataContent, ICategory, IErrorItem, IStructuredDataQueryValues } from "@ax/types";
|
|
@@ -92,6 +93,11 @@ export interface ISetIsIATranslated {
|
|
|
92
93
|
payload: { isIATranslated: boolean };
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
export interface ISetCurrentSearch {
|
|
97
|
+
type: typeof SET_CURRENT_SEARCH;
|
|
98
|
+
payload: { currentSearch: string };
|
|
99
|
+
}
|
|
100
|
+
|
|
95
101
|
export type CategoryActionsCreators = ISetCategories & ISetCurrentData;
|
|
96
102
|
|
|
97
103
|
export type StructuredDataActionsCreators = CategoryActionsCreators &
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
SET_VALIDATED,
|
|
18
18
|
SET_CONTENT_FILTERS,
|
|
19
19
|
SET_IS_IA_TRANSLATED,
|
|
20
|
+
SET_CURRENT_SEARCH,
|
|
20
21
|
} from "./constants";
|
|
21
22
|
|
|
22
23
|
import { StructuredDataActionsCreators } from "./interfaces";
|
|
@@ -38,6 +39,7 @@ export interface IStructuredDataState {
|
|
|
38
39
|
validated: boolean;
|
|
39
40
|
contentFilters: Record<string, IStructuredDataQueryValues> | null;
|
|
40
41
|
isIATranslated: boolean;
|
|
42
|
+
currentSearch: string;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export const initialState = {
|
|
@@ -57,6 +59,7 @@ export const initialState = {
|
|
|
57
59
|
validated: false,
|
|
58
60
|
contentFilters: null,
|
|
59
61
|
isIATranslated: false,
|
|
62
|
+
currentSearch: "",
|
|
60
63
|
};
|
|
61
64
|
|
|
62
65
|
export function reducer(state = initialState, action: any): IStructuredDataState {
|
|
@@ -78,6 +81,7 @@ export function reducer(state = initialState, action: any): IStructuredDataState
|
|
|
78
81
|
case SET_VALIDATED:
|
|
79
82
|
case SET_CONTENT_FILTERS:
|
|
80
83
|
case SET_IS_IA_TRANSLATED:
|
|
84
|
+
case SET_CURRENT_SEARCH:
|
|
81
85
|
return { ...state, ...action.payload };
|
|
82
86
|
default:
|
|
83
87
|
return state;
|
package/src/helpers/schemas.tsx
CHANGED
|
@@ -74,7 +74,7 @@ const getTemplateDisplayName = (template: string) => {
|
|
|
74
74
|
return schema ? schema.displayName : undefined;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const getMenuItems = (type: string):
|
|
77
|
+
const getMenuItems = (type: string): { fields: any[] } | undefined => schemas.menuItems[type];
|
|
78
78
|
|
|
79
79
|
const filterByCategory = (options: any, category: string) =>
|
|
80
80
|
options.filter((option: any) => allSchemas[option].category === category);
|
|
@@ -10,6 +10,7 @@ const Column = styled.div`
|
|
|
10
10
|
width: 100%;
|
|
11
11
|
padding: 0 ${(p) => p.theme.spacing.m};
|
|
12
12
|
height: calc(100% - ${(p) => p.theme.spacing.xs} * 4);
|
|
13
|
+
padding-bottom: ${(p) => p.theme.spacing.l};
|
|
13
14
|
|
|
14
15
|
&:first-child {
|
|
15
16
|
width: calc(${(p) => p.theme.spacing.m} * 18);
|
|
@@ -38,15 +39,18 @@ const Header = styled.div`
|
|
|
38
39
|
`;
|
|
39
40
|
|
|
40
41
|
const Check = styled.div`
|
|
41
|
-
padding-right:
|
|
42
|
+
padding-right: ${(p) => p.theme.spacing.xs};
|
|
42
43
|
padding-left: ${(p) => p.theme.spacing.xs};
|
|
44
|
+
padding-top: ${(p) => p.theme.spacing.xs};
|
|
43
45
|
`;
|
|
44
46
|
|
|
45
47
|
const CheckAll = styled.div`
|
|
46
|
-
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
margin: ${(p) => p.theme.spacing.xs} calc(${(p) => p.theme.spacing.xxs} * 3.5);
|
|
47
51
|
|
|
48
52
|
& > span {
|
|
49
|
-
margin-left: ${(p) => p.theme.spacing.
|
|
53
|
+
margin-left: ${(p) => p.theme.spacing.xs};
|
|
50
54
|
${(p) => p.theme.textStyle.fieldContent};
|
|
51
55
|
color: ${(p) => p.theme.color.textHighEmphasis};
|
|
52
56
|
}
|
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
pageStatus,
|
|
50
50
|
} from "@ax/containers/PageEditor/interfaces";
|
|
51
51
|
import { integrationsActions } from "@ax/containers/Integrations";
|
|
52
|
+
import { IError } from "@ax/containers/App/reducer";
|
|
52
53
|
|
|
53
54
|
import { getOptionValues, getOptionFilters, getCurrentFilter, filterByStatus, getSortedListStatus } from "./utils";
|
|
54
55
|
import { useSortedListStatus, useFilterQuery } from "./hooks";
|
|
@@ -61,7 +62,6 @@ import PageImporter from "./PageImporter";
|
|
|
61
62
|
import { DeleteModal } from "./atoms";
|
|
62
63
|
|
|
63
64
|
import * as S from "./style";
|
|
64
|
-
import { IError } from "@ax/containers/App/reducer";
|
|
65
65
|
|
|
66
66
|
// TODO: Make this monster manageable
|
|
67
67
|
const Content = (props: IProps): JSX.Element => {
|
|
@@ -122,6 +122,8 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
122
122
|
getDefaults,
|
|
123
123
|
getAvailableSiteDataPacks,
|
|
124
124
|
error,
|
|
125
|
+
currentSearch,
|
|
126
|
+
updateCurrentSearch,
|
|
125
127
|
} = props;
|
|
126
128
|
|
|
127
129
|
if (!currentSiteInfo) {
|
|
@@ -190,7 +192,6 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
190
192
|
|
|
191
193
|
const [isScrolling, setIsScrolling] = useState(false);
|
|
192
194
|
const [deletedItem, setDeletedItem] = useState<number | number[] | null>(null);
|
|
193
|
-
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
194
195
|
const [pagesToImport, setPagesToImport] = useState([]);
|
|
195
196
|
const [isEmpty, setIsEmpty] = useState(false);
|
|
196
197
|
const [emptyStateProps, setEmptyStateProps] = useState<IEmptyStateProps>({});
|
|
@@ -245,7 +246,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
245
246
|
pagination: true,
|
|
246
247
|
deleted: false,
|
|
247
248
|
include_draft: true,
|
|
248
|
-
query:
|
|
249
|
+
query: currentSearch,
|
|
249
250
|
format: "list",
|
|
250
251
|
}
|
|
251
252
|
: {
|
|
@@ -253,12 +254,12 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
253
254
|
deleted: false,
|
|
254
255
|
page,
|
|
255
256
|
itemsPerPage,
|
|
256
|
-
query:
|
|
257
|
+
query: currentSearch,
|
|
257
258
|
format: "list",
|
|
258
259
|
};
|
|
259
260
|
|
|
260
261
|
return params;
|
|
261
|
-
}, [filter, currentSiteInfo, isStructuredData, page,
|
|
262
|
+
}, [filter, currentSiteInfo, isStructuredData, page, currentSearch, lang]);
|
|
262
263
|
|
|
263
264
|
const getPages = async (params: any, filterQuery?: any) => {
|
|
264
265
|
const isStructuredDataPage = filter !== "unique-pages";
|
|
@@ -284,7 +285,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
284
285
|
tableRef.current.scrollTo(0, 0);
|
|
285
286
|
}
|
|
286
287
|
// eslint-disable-next-line
|
|
287
|
-
}, [page, filter, currentFilterQuery,
|
|
288
|
+
}, [page, filter, currentFilterQuery, currentSearch]);
|
|
288
289
|
|
|
289
290
|
useLayoutEffect(() => {
|
|
290
291
|
setPage(firstPage);
|
|
@@ -317,7 +318,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
317
318
|
const emptyState: IEmptyStateProps = {};
|
|
318
319
|
const { liveStatus, translated, type } = filterValues;
|
|
319
320
|
const isSearching =
|
|
320
|
-
|
|
321
|
+
currentSearch.length > 0 ||
|
|
321
322
|
(liveStatus.length && liveStatus[0].value !== "all") ||
|
|
322
323
|
(translated.length && translated[0].value !== "all") ||
|
|
323
324
|
(type.length && type[0].value !== "all");
|
|
@@ -831,9 +832,9 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
831
832
|
languageActions={languageActions}
|
|
832
833
|
availableLanguages={siteLanguages}
|
|
833
834
|
rightButton={rightButtonProps}
|
|
834
|
-
searchAction={
|
|
835
|
+
searchAction={updateCurrentSearch}
|
|
835
836
|
errors={errors}
|
|
836
|
-
searchValue={
|
|
837
|
+
searchValue={currentSearch}
|
|
837
838
|
>
|
|
838
839
|
<S.ContentListWrapper>
|
|
839
840
|
<ContentFilters current={filter} dynamicValues={structuredData} resetFilter={resetFilter} />
|
|
@@ -867,7 +868,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
867
868
|
tableRef={tableRef}
|
|
868
869
|
>
|
|
869
870
|
<S.SearchTags>
|
|
870
|
-
<SearchTagsBar query={
|
|
871
|
+
<SearchTagsBar query={currentSearch} setQuery={updateCurrentSearch} />
|
|
871
872
|
<FilterTagsBar
|
|
872
873
|
filters={filterValues}
|
|
873
874
|
setFilters={setFiltersSelection}
|
|
@@ -946,6 +947,7 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
946
947
|
skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
|
|
947
948
|
contentFilters: state.sites.contentFilters,
|
|
948
949
|
error: state.app.error,
|
|
950
|
+
currentSearch: state.sites.currentSearch,
|
|
949
951
|
});
|
|
950
952
|
|
|
951
953
|
interface IDispatchProps {
|
|
@@ -985,6 +987,7 @@ interface IDispatchProps {
|
|
|
985
987
|
checkUserSession(): Promise<void>;
|
|
986
988
|
getDefaults(): Promise<void>;
|
|
987
989
|
getAvailableSiteDataPacks(queryParams: string | null, loading?: boolean): Promise<void>;
|
|
990
|
+
updateCurrentSearch(query: string): Promise<void>;
|
|
988
991
|
}
|
|
989
992
|
|
|
990
993
|
const mapDispatchToProps = {
|
|
@@ -1023,6 +1026,7 @@ const mapDispatchToProps = {
|
|
|
1023
1026
|
checkUserSession: appActions.checkUserSession,
|
|
1024
1027
|
getDefaults: navigationActions.getDefaults,
|
|
1025
1028
|
getAvailableSiteDataPacks: dataPacksActions.getAvailableSiteDataPacks,
|
|
1029
|
+
updateCurrentSearch: sitesActions.updateCurrentSearch,
|
|
1026
1030
|
};
|
|
1027
1031
|
|
|
1028
1032
|
interface IPagesProps {
|
|
@@ -1052,6 +1056,7 @@ interface IPagesProps {
|
|
|
1052
1056
|
skipReviewOnPublish?: boolean;
|
|
1053
1057
|
contentFilters: Record<string, IQueryValue[]> | null;
|
|
1054
1058
|
error: IError;
|
|
1059
|
+
currentSearch: string;
|
|
1055
1060
|
}
|
|
1056
1061
|
|
|
1057
1062
|
type IProps = IPagesProps & IDispatchProps;
|
|
@@ -59,7 +59,6 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
59
59
|
|
|
60
60
|
const itemsPerPage = 30;
|
|
61
61
|
const firstPage = 1;
|
|
62
|
-
const [sitesIds, setsitesIds] = useState<number[]>([]);
|
|
63
62
|
|
|
64
63
|
const [page, setPage] = useState(firstPage);
|
|
65
64
|
const [form, setForm] = useState(initialState);
|
|
@@ -74,6 +73,8 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
74
73
|
const tableRef = useRef<HTMLDivElement>(null);
|
|
75
74
|
const errorRef = useRef<HTMLDivElement>(null);
|
|
76
75
|
|
|
76
|
+
const sitesIds = sites?.map((site: ISite) => site.id);
|
|
77
|
+
|
|
77
78
|
const allowedToCreateSite = usePermission("general.createSite");
|
|
78
79
|
|
|
79
80
|
const pagination = {
|
|
@@ -123,13 +124,6 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
123
124
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
124
125
|
}, [token, getParams]);
|
|
125
126
|
|
|
126
|
-
useEffect(() => {
|
|
127
|
-
if (sites.length > 0) {
|
|
128
|
-
const currentSitesId = sites?.map((site: ISite) => site.id);
|
|
129
|
-
setsitesIds(currentSitesId);
|
|
130
|
-
}
|
|
131
|
-
}, [sites]);
|
|
132
|
-
|
|
133
127
|
useEffect(() => {
|
|
134
128
|
if (tableRef.current) {
|
|
135
129
|
tableRef.current.scrollTo(0, 0);
|
|
@@ -316,30 +310,29 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
316
310
|
</S.EmptyStateWrapper>
|
|
317
311
|
);
|
|
318
312
|
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
};
|
|
313
|
+
const showPagination = totalItems > itemsPerPage;
|
|
314
|
+
|
|
315
|
+
const gridList = (
|
|
316
|
+
<>
|
|
317
|
+
<S.SearchTagsGrid>
|
|
318
|
+
<SearchTagsBar query={searchQuery} setQuery={setSearchQuery} />
|
|
319
|
+
</S.SearchTagsGrid>
|
|
320
|
+
<S.GridList data-testid="sites-grid-list" isEmpty={sites.length === 0} fullWidth={sites.length >= 5}>
|
|
321
|
+
{mappedSites}
|
|
322
|
+
</S.GridList>
|
|
323
|
+
{showPagination && (
|
|
324
|
+
<S.PaginationWrapper>
|
|
325
|
+
<Pagination totalItems={totalItems} setPage={setPage} itemsPerPage={itemsPerPage} currPage={page} />
|
|
326
|
+
</S.PaginationWrapper>
|
|
327
|
+
)}
|
|
328
|
+
</>
|
|
329
|
+
);
|
|
337
330
|
|
|
338
331
|
const filterLabels = {
|
|
339
332
|
liveStatus: "Live",
|
|
340
333
|
};
|
|
341
334
|
|
|
342
|
-
const
|
|
335
|
+
const listTable = (
|
|
343
336
|
<TableList tableHeader={Header} pagination={pagination} hasFixedHeader={true} tableRef={tableRef}>
|
|
344
337
|
<>
|
|
345
338
|
<S.SearchTags>
|
|
@@ -356,12 +349,6 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
356
349
|
</TableList>
|
|
357
350
|
);
|
|
358
351
|
|
|
359
|
-
const AllSitesList = () => (
|
|
360
|
-
<S.AllSitesListWrapper className={hasAnimation ? "animate" : ""} onAnimationEnd={handleAnimationEnd}>
|
|
361
|
-
{displayMode === "grid" ? <GridList /> : <ListTable />}
|
|
362
|
-
</S.AllSitesListWrapper>
|
|
363
|
-
);
|
|
364
|
-
|
|
365
352
|
const handleAnimationEnd = () => setHasAnimation(false);
|
|
366
353
|
|
|
367
354
|
return (
|
|
@@ -376,7 +363,9 @@ const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
|
376
363
|
<S.SitesListWrapper className={hasAnimation ? "animate" : ""}>
|
|
377
364
|
{recentSites?.length > 0 ? <RecentSitesList /> : null}
|
|
378
365
|
<AllSitesHeader />
|
|
379
|
-
<
|
|
366
|
+
<S.AllSitesListWrapper className={hasAnimation ? "animate" : ""} onAnimationEnd={handleAnimationEnd}>
|
|
367
|
+
{displayMode === "grid" ? <>{gridList}</> : <>{listTable}</>}
|
|
368
|
+
</S.AllSitesListWrapper>
|
|
380
369
|
</S.SitesListWrapper>
|
|
381
370
|
<Modal
|
|
382
371
|
isOpen={isOpen}
|
|
@@ -25,11 +25,13 @@ const Sites = (props: ISitesProps): JSX.Element => {
|
|
|
25
25
|
globalLangs,
|
|
26
26
|
getRoles,
|
|
27
27
|
hasAnimation,
|
|
28
|
+
updateCurrentSearch,
|
|
28
29
|
} = props;
|
|
29
30
|
|
|
30
31
|
useLayoutEffect(() => {
|
|
31
32
|
const fetchInitialData = async () => {
|
|
32
33
|
setCurrentSiteInfo(null);
|
|
34
|
+
updateCurrentSearch("");
|
|
33
35
|
await getRoles({ siteId: "global" }, token);
|
|
34
36
|
await getUser("me", token);
|
|
35
37
|
await getStructuredData(token);
|
|
@@ -75,6 +77,7 @@ interface IDispatchProps {
|
|
|
75
77
|
getAllDataPacks: () => Promise<void>;
|
|
76
78
|
getUser: (id: string, token?: string) => Promise<void>;
|
|
77
79
|
getRoles: (params: IGetRoles, token?: string) => Promise<void>;
|
|
80
|
+
updateCurrentSearch(query: string): Promise<void>;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
export type ISitesProps = IStateProps & IDispatchProps & RouteComponentProps;
|
|
@@ -86,6 +89,7 @@ const mapDispatchToProps = {
|
|
|
86
89
|
getAllDataPacks: dataPacksActions.getAllDataPacks,
|
|
87
90
|
getUser: usersActions.getUser,
|
|
88
91
|
getRoles: usersActions.getRoles,
|
|
92
|
+
updateCurrentSearch: structuredDataActions.updateCurrentSearch,
|
|
89
93
|
};
|
|
90
94
|
|
|
91
95
|
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Sites));
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
ICheck,
|
|
18
18
|
IColumn,
|
|
19
19
|
IStructuredDataQueryValues,
|
|
20
|
-
ISite,
|
|
21
20
|
IQueryValue,
|
|
22
21
|
} from "@ax/types";
|
|
23
22
|
import {
|
|
@@ -102,7 +101,8 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
102
101
|
setContentFilters,
|
|
103
102
|
contentFilters,
|
|
104
103
|
checkUserSession,
|
|
105
|
-
|
|
104
|
+
currentSearch,
|
|
105
|
+
updateCurrentSearch,
|
|
106
106
|
} = props;
|
|
107
107
|
|
|
108
108
|
const itemsPerPage = 50;
|
|
@@ -119,7 +119,6 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
119
119
|
const { isVisible: isPageToast, toggleToast: togglePageToast, setIsVisible: setIsPageToast } = useToast();
|
|
120
120
|
const tableRef = useRef<HTMLDivElement>(null);
|
|
121
121
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
122
|
-
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
123
122
|
const [isEmpty, setIsEmpty] = useState(false);
|
|
124
123
|
const [emptyStateProps, setEmptyStateProps] = useState<IEmptyStateProps>({});
|
|
125
124
|
const { isOpen: isNewOpen, toggleModal: toggleNewModal } = useModal();
|
|
@@ -199,13 +198,13 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
199
198
|
pagination: true,
|
|
200
199
|
deleted: false,
|
|
201
200
|
include_draft: true,
|
|
202
|
-
query:
|
|
201
|
+
query: currentSearch,
|
|
203
202
|
format: "list",
|
|
204
203
|
relatedFields: true,
|
|
205
204
|
};
|
|
206
205
|
|
|
207
206
|
return params;
|
|
208
|
-
}, [page,
|
|
207
|
+
}, [page, currentSearch]);
|
|
209
208
|
|
|
210
209
|
const getStructuredData = useCallback(
|
|
211
210
|
async (id: string, filterQuery?: string) => {
|
|
@@ -280,7 +279,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
280
279
|
tableRef.current.scrollTo(0, 0);
|
|
281
280
|
}
|
|
282
281
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
283
|
-
}, [lang.locale, page,
|
|
282
|
+
}, [lang.locale, page, currentSearch, filterValues]);
|
|
284
283
|
|
|
285
284
|
useEffect(() => {
|
|
286
285
|
if (wrapperRef.current) {
|
|
@@ -294,7 +293,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
294
293
|
useEffect(() => {
|
|
295
294
|
if (!isFirstRender && !isLoading) {
|
|
296
295
|
const emptyState: IEmptyStateProps = {};
|
|
297
|
-
const isSearching =
|
|
296
|
+
const isSearching = currentSearch.length > 0;
|
|
298
297
|
if (isSearching) {
|
|
299
298
|
emptyState.icon = "search";
|
|
300
299
|
emptyState.title = "Oh! No Results Found";
|
|
@@ -597,7 +596,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
597
596
|
|
|
598
597
|
const labelCategory = isStructuredDataFromPage ? { categories: "Category" } : { related: "Category " };
|
|
599
598
|
|
|
600
|
-
|
|
599
|
+
const filterLabels = {
|
|
601
600
|
types: "Type",
|
|
602
601
|
liveStatus: "Live",
|
|
603
602
|
translated: "Translated",
|
|
@@ -612,8 +611,8 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
612
611
|
availableLanguages={languageProps.globalLangs}
|
|
613
612
|
language={languageProps.lang}
|
|
614
613
|
languageActions={languageProps.languageActions}
|
|
615
|
-
searchAction={
|
|
616
|
-
searchValue={
|
|
614
|
+
searchAction={updateCurrentSearch}
|
|
615
|
+
searchValue={currentSearch}
|
|
617
616
|
>
|
|
618
617
|
<S.StructuredDataWrapper ref={wrapperRef}>
|
|
619
618
|
<ContentFilters
|
|
@@ -648,7 +647,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
648
647
|
>
|
|
649
648
|
<>
|
|
650
649
|
<S.SearchTags>
|
|
651
|
-
<SearchTagsBar query={
|
|
650
|
+
<SearchTagsBar query={currentSearch} setQuery={updateCurrentSearch} />
|
|
652
651
|
<FilterTagsBar
|
|
653
652
|
filters={filterValues[currentStructuredData?.id || "all"]}
|
|
654
653
|
setFilters={setFiltersSelection}
|
|
@@ -712,7 +711,7 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
712
711
|
currentSiteErrorPages: state.sites.currentSiteErrorPages,
|
|
713
712
|
skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
|
|
714
713
|
contentFilters: state.structuredData.contentFilters,
|
|
715
|
-
|
|
714
|
+
currentSearch: state.structuredData.currentSearch,
|
|
716
715
|
});
|
|
717
716
|
|
|
718
717
|
const mapDispatchToProps = {
|
|
@@ -739,6 +738,7 @@ const mapDispatchToProps = {
|
|
|
739
738
|
resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
|
|
740
739
|
setContentFilters: structuredDataActions.setContentFilters,
|
|
741
740
|
checkUserSession: appActions.checkUserSession,
|
|
741
|
+
updateCurrentSearch: structuredDataActions.updateCurrentSearch,
|
|
742
742
|
};
|
|
743
743
|
|
|
744
744
|
interface IDispatchProps {
|
|
@@ -765,6 +765,7 @@ interface IDispatchProps {
|
|
|
765
765
|
resetCurrentSiteErrorPages: () => Promise<void>;
|
|
766
766
|
setContentFilters(contentFilters: Record<string, IStructuredDataQueryValues> | null): void;
|
|
767
767
|
checkUserSession(): Promise<void>;
|
|
768
|
+
updateCurrentSearch(query: string): Promise<void>;
|
|
768
769
|
}
|
|
769
770
|
|
|
770
771
|
interface ICategoriesProps {
|
|
@@ -783,7 +784,7 @@ interface ICategoriesProps {
|
|
|
783
784
|
currentSiteErrorPages: number[];
|
|
784
785
|
skipReviewOnPublish?: boolean;
|
|
785
786
|
contentFilters: Record<string, IStructuredDataQueryValues> | null;
|
|
786
|
-
|
|
787
|
+
currentSearch: string;
|
|
787
788
|
}
|
|
788
789
|
|
|
789
790
|
type IProps = ICategoriesProps & IDispatchProps;
|
package/src/types/index.tsx
CHANGED
|
File without changes
|
|
File without changes
|