@griddo/ax 1.73.28 → 1.74.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/config/griddo-config/index.js +24 -3
- package/config/webpackSchemas.config.js +3 -5
- package/package.json +3 -2
- package/scripts/griddo-sync-schemas.js +4 -3
- package/src/__mocks__/axios/SitesList.ts +84 -0
- package/src/__mocks__/store/SitesList.ts +714 -0
- package/src/__tests__/components/Avatar/Avatar.test.tsx +119 -0
- package/src/__tests__/components/Avatar/__snapshots__/Avatar.test.tsx.snap +61 -0
- package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +10 -10
- package/src/__tests__/components/LanguageMenu/LanguageMenu.test.tsx +221 -0
- package/src/__tests__/components/Loading/Loading.test.tsx +23 -0
- package/src/__tests__/components/Login/Login.test.tsx +247 -0
- package/src/__tests__/components/Login/RecoveryModal/RecoveryModal.test.tsx +185 -0
- package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +6 -6
- package/src/__tests__/modules/Sites/Sites.test.tsx +259 -0
- package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +51 -0
- package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +896 -0
- package/src/api/sites.tsx +43 -4
- package/src/components/ActionMenu/index.tsx +1 -1
- package/src/components/Avatar/index.tsx +4 -4
- package/src/components/Browser/index.tsx +27 -20
- package/src/components/BrowserContent/index.tsx +6 -0
- package/src/components/Fields/AsyncSelect/style.tsx +6 -3
- package/src/components/Fields/CheckField/index.tsx +1 -0
- package/src/components/Fields/DateField/style.tsx +3 -1
- package/src/components/Fields/HeadingField/index.tsx +14 -5
- package/src/components/Fields/ImageField/index.tsx +3 -0
- package/src/components/Fields/ImageField/style.tsx +2 -2
- package/src/components/Fields/Select/style.tsx +2 -0
- package/src/components/Fields/SliderField/index.tsx +2 -1
- package/src/components/Fields/TextField/index.tsx +1 -0
- package/src/components/Icon/components/BulletList.js +16 -0
- package/src/components/Icon/components/Grid2.js +16 -0
- package/src/components/Icon/svgs/Bullet-list.svg +3 -0
- package/src/components/Icon/svgs/Grid-2.svg +3 -0
- package/src/components/IconAction/index.tsx +4 -2
- package/src/components/IconAction/style.tsx +8 -2
- package/src/components/LanguageMenu/index.tsx +13 -6
- package/src/components/Login/RecoveryModal/index.tsx +5 -4
- package/src/components/Login/index.tsx +13 -3
- package/src/components/Login/style.tsx +12 -25
- package/src/components/Pagination/style.tsx +1 -1
- package/src/components/SearchField/index.tsx +9 -1
- package/src/components/SideModal/style.tsx +8 -8
- package/src/components/TableFilters/LastAccessFilter/index.tsx +52 -0
- package/src/components/TableFilters/LastAccessFilter/style.tsx +31 -0
- package/src/components/TableFilters/LiveFilter/index.tsx +7 -5
- package/src/components/TableFilters/NameFilter/index.tsx +4 -3
- package/src/components/TableFilters/index.tsx +2 -0
- package/src/components/TableList/index.tsx +2 -1
- package/src/components/TableList/style.tsx +2 -2
- package/src/components/index.tsx +2 -0
- package/src/containers/App/actions.tsx +5 -0
- package/src/containers/App/interfaces.tsx +1 -1
- package/src/containers/App/reducer.tsx +1 -1
- package/src/containers/Navigation/Defaults/actions.tsx +3 -1
- package/src/containers/PageEditor/actions.tsx +6 -3
- package/src/containers/Sites/actions.tsx +76 -11
- package/src/containers/Sites/constants.tsx +2 -0
- package/src/containers/Sites/interfaces.tsx +12 -0
- package/src/containers/Sites/reducer.tsx +8 -0
- package/src/helpers/schemas.tsx +27 -1
- package/src/hooks/iframe.ts +56 -0
- package/src/hooks/index.tsx +3 -0
- package/src/modules/Content/index.tsx +4 -3
- package/src/modules/FramePreview/index.tsx +25 -39
- package/src/modules/GlobalEditor/Editor/index.tsx +2 -2
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +11 -7
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -3
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +1 -0
- package/src/modules/PageEditor/Editor/index.tsx +2 -2
- package/src/modules/PageEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/PageEditor/index.tsx +8 -7
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/index.tsx +12 -11
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +3 -17
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/style.tsx +2 -10
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/index.tsx +72 -0
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/style.tsx +32 -0
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/index.tsx +17 -27
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/style.tsx +14 -25
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +64 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/style.tsx +50 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +75 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/style.tsx +8 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +200 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/style.tsx +112 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/index.tsx +50 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/style.tsx +28 -0
- package/src/modules/Sites/SitesList/SiteModal/index.tsx +4 -3
- package/src/modules/Sites/SitesList/atoms.tsx +47 -0
- package/src/modules/Sites/SitesList/hooks.tsx +102 -0
- package/src/modules/Sites/SitesList/index.tsx +272 -19
- package/src/modules/Sites/SitesList/style.tsx +157 -4
- package/src/modules/Sites/SitesList/utils.tsx +33 -0
- package/src/modules/Sites/index.tsx +6 -11
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/types/index.tsx +25 -2
|
@@ -1,39 +1,112 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { appActions } from "@ax/containers/App";
|
|
5
5
|
import { sitesActions } from "@ax/containers/Sites";
|
|
6
|
-
import { IRootState, ISettingsForm, ISite, IUser } from "@ax/types";
|
|
7
|
-
import { useModal } from "@ax/hooks";
|
|
8
|
-
import { MainWrapper, Modal, ErrorToast } from "@ax/components";
|
|
6
|
+
import { ICheck, IGetSitesParams, IRootState, ISettingsForm, ISite, IUser } from "@ax/types";
|
|
7
|
+
import { useBulkSelection, useModal } from "@ax/hooks";
|
|
8
|
+
import { MainWrapper, Modal, ErrorToast, Icon, IconAction, TableList, EmptyState } from "@ax/components";
|
|
9
|
+
|
|
10
|
+
import { useFilterQuery, useSortedListStatus, useIsMount } from "./hooks";
|
|
11
|
+
import { filterByStatus, getSortedListStatus } from "./utils";
|
|
9
12
|
|
|
10
13
|
import SiteModal from "./SiteModal";
|
|
11
|
-
import
|
|
14
|
+
import RecentSiteItem from "./RecentSiteItem";
|
|
15
|
+
import GridHeaderFilter from "./GridView/GridHeaderFilter";
|
|
16
|
+
import GridSiteItem from "./GridView/GridSiteItem";
|
|
17
|
+
import BulkHeader from "./ListView/BulkHeader";
|
|
18
|
+
import ListSiteItem from "./ListView/ListSiteItem";
|
|
12
19
|
|
|
13
20
|
import * as S from "./style";
|
|
14
21
|
|
|
15
|
-
const SitesList = (props:
|
|
16
|
-
const {
|
|
22
|
+
const SitesList = (props: ISitesListProps): JSX.Element => {
|
|
23
|
+
const {
|
|
24
|
+
token,
|
|
25
|
+
sites,
|
|
26
|
+
recentSites,
|
|
27
|
+
totalItems,
|
|
28
|
+
saveSettings,
|
|
29
|
+
setHistoryPush,
|
|
30
|
+
currentUser,
|
|
31
|
+
getSites,
|
|
32
|
+
publishSitesBulk,
|
|
33
|
+
unpublishSitesBulk,
|
|
34
|
+
} = props;
|
|
17
35
|
|
|
36
|
+
const isMount = useIsMount();
|
|
18
37
|
const initialState = {
|
|
19
38
|
name: "",
|
|
20
39
|
defaultLanguage: null,
|
|
21
40
|
path: "",
|
|
22
41
|
domain: null,
|
|
23
42
|
};
|
|
43
|
+
|
|
44
|
+
const itemsPerPage = 30;
|
|
45
|
+
const firstPage = 1;
|
|
46
|
+
const [sitesIds, setsitesIds] = useState<any[]>([]);
|
|
47
|
+
|
|
48
|
+
const [page, setPage] = useState(firstPage);
|
|
24
49
|
const [form, setForm] = useState(initialState);
|
|
50
|
+
const [isRecentSitesListDisplayed, setIsRecentSitesListDisplayed] = useState<boolean>(true);
|
|
51
|
+
const [displayMode, setDisplayMode] = useState<"list" | "grid">("grid");
|
|
52
|
+
const [searchQuery, setSearchQuery] = useState<string | null>("");
|
|
53
|
+
const [currentFilterQuery, setCurrentFilterQuery] = useState("&order=lastAccess-desc");
|
|
25
54
|
|
|
26
|
-
const
|
|
55
|
+
const tableRef = useRef<HTMLDivElement>(null);
|
|
27
56
|
|
|
28
|
-
const
|
|
29
|
-
|
|
57
|
+
const pagination = {
|
|
58
|
+
setPage,
|
|
59
|
+
itemsPerPage,
|
|
60
|
+
totalItems,
|
|
61
|
+
currPage: page,
|
|
30
62
|
};
|
|
31
63
|
|
|
64
|
+
const { isOpen, toggleModal } = useModal();
|
|
65
|
+
|
|
66
|
+
const openModal = () => toggleModal();
|
|
32
67
|
const rightButtonProps = {
|
|
33
68
|
label: "New",
|
|
34
69
|
action: openModal,
|
|
35
70
|
};
|
|
36
71
|
|
|
72
|
+
const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
|
|
73
|
+
const { setFiltersSelection, setFilterQuery, filterValues } = useFilterQuery();
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (token) {
|
|
77
|
+
const query = searchQuery ? `&query=${searchQuery}` : "";
|
|
78
|
+
const params = {
|
|
79
|
+
pagination: true,
|
|
80
|
+
language: undefined,
|
|
81
|
+
recentSitesNumber: 7,
|
|
82
|
+
page,
|
|
83
|
+
itemsPerPage,
|
|
84
|
+
filterQuery: currentFilterQuery,
|
|
85
|
+
searchQuery: query,
|
|
86
|
+
};
|
|
87
|
+
if (isMount) {
|
|
88
|
+
getSites({ ...params, token });
|
|
89
|
+
} else {
|
|
90
|
+
getSites(params);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
94
|
+
}, [token, currentFilterQuery, searchQuery, page]);
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (sites.length > 0) {
|
|
98
|
+
const currentSitesId = sites?.map((site: any) => site.id);
|
|
99
|
+
setsitesIds(currentSitesId);
|
|
100
|
+
}
|
|
101
|
+
}, [sites]);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (tableRef.current) {
|
|
105
|
+
tableRef.current.scrollTo(0, 0);
|
|
106
|
+
}
|
|
107
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
108
|
+
}, [page, searchQuery, filterValues]);
|
|
109
|
+
|
|
37
110
|
const saveSiteSettings = async () => {
|
|
38
111
|
const result = await saveSettings(form);
|
|
39
112
|
if (result) {
|
|
@@ -51,17 +124,184 @@ const SitesList = (props: IProps): JSX.Element => {
|
|
|
51
124
|
const secondaryAction = { title: "Cancel", onClick: toggleModal };
|
|
52
125
|
|
|
53
126
|
const userHasSite = (siteID: number) => currentUser.sites.includes("all") || currentUser.sites.includes(siteID);
|
|
127
|
+
const toggleRecentSites = () => setIsRecentSitesListDisplayed(!isRecentSitesListDisplayed);
|
|
54
128
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
129
|
+
const sortItems = (orderPointer: string, isAscending: boolean) => {
|
|
130
|
+
setIsRecentSitesListDisplayed(false);
|
|
131
|
+
setPage(firstPage);
|
|
132
|
+
const orderMethod = isAscending ? "asc" : "desc";
|
|
133
|
+
const sortedState = getSortedListStatus(orderPointer, isAscending);
|
|
134
|
+
setSortedListStatus(sortedState);
|
|
135
|
+
const pointer = orderPointer === "title" ? "name" : orderPointer;
|
|
136
|
+
const filtersSelection = setFiltersSelection("order", pointer, orderMethod);
|
|
137
|
+
const filterQuery = setFilterQuery(filtersSelection);
|
|
138
|
+
|
|
139
|
+
setCurrentFilterQuery(filterQuery);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const filterItems = async (filterPointer: string, filtersSelected: string) => {
|
|
143
|
+
setIsRecentSitesListDisplayed(false);
|
|
144
|
+
setPage(firstPage);
|
|
145
|
+
const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
|
|
146
|
+
const filterQuery = setFilterQuery(filtersSelection);
|
|
147
|
+
setCurrentFilterQuery(filterQuery);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const RecentSitesHeader = () => (
|
|
151
|
+
<S.SectionHeader data-testid="recent-sites-header" isRecentSites={true}>
|
|
152
|
+
<S.Title data-testid="recent-sites-title" isActive={isRecentSitesListDisplayed}>
|
|
153
|
+
Recent sites
|
|
154
|
+
</S.Title>
|
|
155
|
+
<S.CollapseButton data-testid="recent-sites-collapse-button" onClick={toggleRecentSites}>
|
|
156
|
+
{isRecentSitesListDisplayed ? (
|
|
157
|
+
<>
|
|
158
|
+
<S.Label data-testid="recent-sites-hide-label">Hide recent sites </S.Label> <Icon name="UpArrow" />
|
|
159
|
+
</>
|
|
160
|
+
) : (
|
|
161
|
+
<>
|
|
162
|
+
<S.Label data-testid="recent-sites-show-label">Show recent sites </S.Label> <Icon name="DownArrow" />
|
|
163
|
+
</>
|
|
164
|
+
)}
|
|
165
|
+
</S.CollapseButton>
|
|
166
|
+
</S.SectionHeader>
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const RecentSitesList = () => (
|
|
170
|
+
<S.RecentSites data-testid="recent-sites-list">
|
|
171
|
+
<RecentSitesHeader />
|
|
172
|
+
<S.RecentSitesItemsWrapper data-testid="recent-sites-items-wrapper" isHidden={!isRecentSitesListDisplayed}>
|
|
173
|
+
{recentSites
|
|
60
174
|
.filter((site: ISite) => userHasSite(site.id))
|
|
61
|
-
.map((site: ISite) => (
|
|
62
|
-
<
|
|
175
|
+
.map((site: ISite, i: number) => (
|
|
176
|
+
<RecentSiteItem key={i} site={site} />
|
|
63
177
|
))}
|
|
64
|
-
</S.
|
|
178
|
+
</S.RecentSitesItemsWrapper>
|
|
179
|
+
</S.RecentSites>
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const AllSitesHeader = () => (
|
|
183
|
+
<S.SectionHeader data-testid="all-sites-header">
|
|
184
|
+
<S.Title isActive={true} data-testid="all-sites-title">
|
|
185
|
+
All sites
|
|
186
|
+
</S.Title>
|
|
187
|
+
<S.HeaderIconsWrapper data-testid="all-sites-header-icons">
|
|
188
|
+
{displayMode === "grid" ? (
|
|
189
|
+
<S.FilterSelect data-testid="all-sites-grid-filter">
|
|
190
|
+
<S.FilterSelectLabel data-testid="all-sites-grid-filter-label">Sort by:</S.FilterSelectLabel>{" "}
|
|
191
|
+
<GridHeaderFilter sortItems={sortItems} sortedState={sortedListStatus} />{" "}
|
|
192
|
+
</S.FilterSelect>
|
|
193
|
+
) : null}
|
|
194
|
+
<IconAction icon="Grid2" onClick={() => setDisplayMode("grid")} active={displayMode === "grid"} />
|
|
195
|
+
<IconAction icon="BulletList" onClick={() => setDisplayMode("list")} active={displayMode === "list"} />
|
|
196
|
+
</S.HeaderIconsWrapper>
|
|
197
|
+
</S.SectionHeader>
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const {
|
|
201
|
+
resetBulkSelection,
|
|
202
|
+
selectedItems,
|
|
203
|
+
isSelected,
|
|
204
|
+
areItemsSelected,
|
|
205
|
+
checkState,
|
|
206
|
+
addToBulkSelection,
|
|
207
|
+
selectAllItems,
|
|
208
|
+
} = useBulkSelection(sitesIds);
|
|
209
|
+
|
|
210
|
+
const bulkFilter = (bulkSelection: number[]) => filterByStatus(bulkSelection, sites);
|
|
211
|
+
|
|
212
|
+
const handleAddToBulk = (item: ICheck) => addToBulkSelection(item, bulkFilter);
|
|
213
|
+
|
|
214
|
+
const handleSelectAll = () => selectAllItems(bulkFilter);
|
|
215
|
+
|
|
216
|
+
const unselectAllItems = () => resetBulkSelection();
|
|
217
|
+
|
|
218
|
+
const selectItems = () => (checkState.isAllSelected ? unselectAllItems() : handleSelectAll());
|
|
219
|
+
|
|
220
|
+
const bulkPublishAction = async (isPublish: boolean) => {
|
|
221
|
+
const { notPublished, published } = selectedItems;
|
|
222
|
+
if (notPublished.length > 0 && isPublish) {
|
|
223
|
+
publishSitesBulk(notPublished);
|
|
224
|
+
}
|
|
225
|
+
if (published.length > 0 && !isPublish) {
|
|
226
|
+
unpublishSitesBulk(published);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const query = searchQuery ? `&query=${searchQuery}` : "";
|
|
230
|
+
const params = {
|
|
231
|
+
pagination: true,
|
|
232
|
+
language: undefined,
|
|
233
|
+
recentSitesNumber: 7,
|
|
234
|
+
page,
|
|
235
|
+
itemsPerPage,
|
|
236
|
+
filterQuery: currentFilterQuery,
|
|
237
|
+
searchQuery: query,
|
|
238
|
+
};
|
|
239
|
+
getSites(params);
|
|
240
|
+
unselectAllItems();
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const bulkPublish = () => bulkPublishAction(true);
|
|
244
|
+
const bulkUnpublish = () => bulkPublishAction(false);
|
|
245
|
+
|
|
246
|
+
const Header = (
|
|
247
|
+
<BulkHeader
|
|
248
|
+
showBulk={areItemsSelected(sitesIds)}
|
|
249
|
+
bulkPublish={bulkPublish}
|
|
250
|
+
bulkUnpublish={bulkUnpublish}
|
|
251
|
+
checkState={checkState}
|
|
252
|
+
selectAllItems={handleSelectAll}
|
|
253
|
+
totalItems={totalItems}
|
|
254
|
+
selectItems={selectItems}
|
|
255
|
+
sortItems={sortItems}
|
|
256
|
+
sortedListStatus={sortedListStatus}
|
|
257
|
+
filterItems={filterItems}
|
|
258
|
+
filterValues={filterValues}
|
|
259
|
+
/>
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
const mappedSites =
|
|
263
|
+
sites.length > 0 ? (
|
|
264
|
+
sites
|
|
265
|
+
.filter((site: ISite) => userHasSite(site.id))
|
|
266
|
+
.map((site: ISite) => {
|
|
267
|
+
const isItemSelected = isSelected(site.id);
|
|
268
|
+
return displayMode === "grid" ? (
|
|
269
|
+
<GridSiteItem key={site.id} site={site} />
|
|
270
|
+
) : (
|
|
271
|
+
<ListSiteItem key={site.id} site={site} isSelected={isItemSelected} onCheck={handleAddToBulk} />
|
|
272
|
+
);
|
|
273
|
+
})
|
|
274
|
+
) : (
|
|
275
|
+
<S.EmptyStateWrapper data-testid="empty-state">
|
|
276
|
+
<EmptyState icon="search" message="We couldn't find what you are looking for. Please, try another search." />
|
|
277
|
+
</S.EmptyStateWrapper>
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const GridList = () => (
|
|
281
|
+
<S.GridList data-testid="sites-grid-list" isEmpty={sites.length === 0}>
|
|
282
|
+
{mappedSites}
|
|
283
|
+
</S.GridList>
|
|
284
|
+
);
|
|
285
|
+
const ListTable = () => (
|
|
286
|
+
<TableList
|
|
287
|
+
tableHeader={Header}
|
|
288
|
+
pagination={pagination}
|
|
289
|
+
hasFixedHeader={true}
|
|
290
|
+
tableRef={tableRef}
|
|
291
|
+
overflow="visible"
|
|
292
|
+
>
|
|
293
|
+
{mappedSites}
|
|
294
|
+
</TableList>
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
const AllSitesList = () => (displayMode === "grid" ? <GridList /> : <ListTable />);
|
|
298
|
+
|
|
299
|
+
return (
|
|
300
|
+
<MainWrapper title="Sites" rightButton={rightButtonProps} searchAction={setSearchQuery}>
|
|
301
|
+
<ErrorToast />
|
|
302
|
+
{recentSites?.length > 0 ? <RecentSitesList /> : null}
|
|
303
|
+
<AllSitesHeader />
|
|
304
|
+
<AllSitesList />
|
|
65
305
|
<Modal
|
|
66
306
|
isOpen={isOpen}
|
|
67
307
|
hide={toggleModal}
|
|
@@ -78,23 +318,36 @@ const SitesList = (props: IProps): JSX.Element => {
|
|
|
78
318
|
|
|
79
319
|
interface ISitesProps {
|
|
80
320
|
sites: ISite[];
|
|
321
|
+
recentSites: ISite[];
|
|
81
322
|
currentUser: IUser;
|
|
323
|
+
totalItems: number;
|
|
324
|
+
token: string;
|
|
82
325
|
}
|
|
83
326
|
|
|
84
327
|
const mapStateToProps = (state: IRootState) => ({
|
|
85
328
|
currentUser: state.users.currentUser,
|
|
329
|
+
totalItems: state.sites.sitesTotalItems,
|
|
330
|
+
token: state.app.token,
|
|
331
|
+
sites: state.sites.sites,
|
|
332
|
+
recentSites: state.sites.recentSites,
|
|
86
333
|
});
|
|
87
334
|
|
|
88
335
|
interface IDispatchProps {
|
|
89
336
|
setHistoryPush(path: string, isEditor?: boolean): void;
|
|
90
337
|
saveSettings(form: ISettingsForm): Promise<boolean>;
|
|
338
|
+
getSites(params: IGetSitesParams): void;
|
|
339
|
+
publishSitesBulk(ids: number[]): void;
|
|
340
|
+
unpublishSitesBulk(ids: number[]): void;
|
|
91
341
|
}
|
|
92
342
|
|
|
93
343
|
const mapDispatchToProps = {
|
|
94
344
|
setHistoryPush: appActions.setHistoryPush,
|
|
95
345
|
saveSettings: sitesActions.saveSettings,
|
|
346
|
+
getSites: sitesActions.getSites,
|
|
347
|
+
publishSitesBulk: sitesActions.publishSitesBulk,
|
|
348
|
+
unpublishSitesBulk: sitesActions.unpublishSitesBulk,
|
|
96
349
|
};
|
|
97
350
|
|
|
98
|
-
type
|
|
351
|
+
export type ISitesListProps = ISitesProps & IDispatchProps;
|
|
99
352
|
|
|
100
353
|
export default connect(mapStateToProps, mapDispatchToProps)(SitesList);
|
|
@@ -1,8 +1,161 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const SectionHeader = styled.div<{ isRecentSites?: boolean }>`
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: space-between;
|
|
6
|
+
margin: 0 ${(p) => (p.isRecentSites ? p.theme.spacing.s : p.theme.spacing.m)};
|
|
7
|
+
margin-top: ${(p) => p.theme.spacing.m};
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
const Label = styled.span`
|
|
11
|
+
margin-right: 14px;
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
const Title = styled.h1<{ isActive?: boolean }>`
|
|
15
|
+
margin: 0;
|
|
16
|
+
margin-right: ${(p) => p.theme.spacing.m};
|
|
17
|
+
${(p) => p.theme.textStyle.headingM};
|
|
18
|
+
color: ${(p) => (p.isActive ? p.theme.colors.textHighEmphasis : p.theme.colors.textMediumEmphasis)};
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const HeaderIconsWrapper = styled.div`
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const FilterSelectLabel = styled.span`
|
|
27
|
+
color: ${(p) => p.theme.color.interactive01};
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const FilterSelect = styled.div`
|
|
31
|
+
${(p) => p.theme.textStyle.uiS};
|
|
32
|
+
line-height: 32px;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
position: relative;
|
|
36
|
+
color: ${(p) => p.theme.color.textLowEmphasis};
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const CollapseButton = styled.div`
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
${(p) => p.theme.textStyle.uiS};
|
|
43
|
+
color: ${(p) => p.theme.colors.textMediumEmphasis};
|
|
44
|
+
padding: 0;
|
|
45
|
+
margin: 0;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const RecentSites = styled.div`
|
|
50
|
+
padding-bottom: ${(p) => p.theme.spacing.s};
|
|
51
|
+
border-radius: ${(p) => p.theme.radii.s};
|
|
52
|
+
background: ${(p) => p.theme.color.uiBackground02};
|
|
53
|
+
min-height: 56px;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
margin: ${(p) => p.theme.spacing.m};
|
|
56
|
+
margin-bottom: 0;
|
|
57
|
+
|
|
58
|
+
h1 {
|
|
59
|
+
padding-left: 0;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
const RecentSitesItemsWrapper = styled.div<{ isHidden: boolean }>`
|
|
4
64
|
display: grid;
|
|
5
|
-
grid-
|
|
65
|
+
grid-auto-flow: column;
|
|
66
|
+
overflow: auto;
|
|
6
67
|
grid-gap: ${(p) => p.theme.spacing.m};
|
|
7
|
-
padding: ${(p) => p.theme.spacing.
|
|
68
|
+
padding: ${(p) => p.theme.spacing.s} ${(p) => p.theme.spacing.s} 0px ${(p) => p.theme.spacing.s};
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
|
|
71
|
+
div {
|
|
72
|
+
min-width: 100%;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
${(props) =>
|
|
76
|
+
props.isHidden &&
|
|
77
|
+
css`
|
|
78
|
+
height: 0;
|
|
79
|
+
padding: 0;
|
|
80
|
+
padding-left: ${(p) => p.theme.spacing.s};
|
|
81
|
+
padding-top: ${(p) => p.theme.spacing.xs};
|
|
82
|
+
`};
|
|
83
|
+
|
|
84
|
+
@media (min-width: 1200px) {
|
|
85
|
+
div:nth-child(6),
|
|
86
|
+
div:nth-child(7) {
|
|
87
|
+
display: none;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@media (min-width: 1600px) {
|
|
92
|
+
div:nth-child(6) {
|
|
93
|
+
display: block;
|
|
94
|
+
}
|
|
95
|
+
div:nth-child(7) {
|
|
96
|
+
display: none;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@media (min-width: 1700px) {
|
|
101
|
+
div:nth-child(6),
|
|
102
|
+
div:nth-child(7) {
|
|
103
|
+
display: block;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
const GridList = styled.div<{ isEmpty: boolean }>`
|
|
109
|
+
padding-top: ${(p) => p.theme.spacing.s};
|
|
110
|
+
padding-bottom: ${(p) => p.theme.spacing.m};
|
|
111
|
+
margin: 0 ${(p) => p.theme.spacing.m};
|
|
112
|
+
|
|
113
|
+
${({ isEmpty, theme }) =>
|
|
114
|
+
isEmpty
|
|
115
|
+
? `
|
|
116
|
+
display: flex;
|
|
117
|
+
justify-content: center;
|
|
118
|
+
`
|
|
119
|
+
: `display: grid;
|
|
120
|
+
grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
|
|
121
|
+
grid-gap: ${theme.spacing.m};
|
|
122
|
+
`}
|
|
8
123
|
`;
|
|
124
|
+
|
|
125
|
+
const EmptyStateWrapper = styled.div`
|
|
126
|
+
text-align: center;
|
|
127
|
+
`;
|
|
128
|
+
|
|
129
|
+
const ImageWrapper = styled.div<{ borderRadius?: boolean }>`
|
|
130
|
+
img {
|
|
131
|
+
border-radius: ${(p) => (p.borderRadius ? p.theme.spacing.xs : 0)};
|
|
132
|
+
object-fit: cover;
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
const Thumbnail = styled.div<{ backgroundUrl: string; height: number; width: number; borderRadius?: boolean }>`
|
|
137
|
+
background: url(${(p) => p.backgroundUrl}) no-repeat center;
|
|
138
|
+
background-size: cover;
|
|
139
|
+
height: ${(p) => p.height}px;
|
|
140
|
+
width: ${(p) => p.width}px;
|
|
141
|
+
border-radius: ${(p) => (p.borderRadius ? p.theme.spacing.xs : 0)};
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
const ItemName = styled.span``;
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
SectionHeader,
|
|
148
|
+
CollapseButton,
|
|
149
|
+
Label,
|
|
150
|
+
Title,
|
|
151
|
+
HeaderIconsWrapper,
|
|
152
|
+
FilterSelect,
|
|
153
|
+
FilterSelectLabel,
|
|
154
|
+
RecentSites,
|
|
155
|
+
RecentSitesItemsWrapper,
|
|
156
|
+
GridList,
|
|
157
|
+
EmptyStateWrapper,
|
|
158
|
+
ImageWrapper,
|
|
159
|
+
Thumbnail,
|
|
160
|
+
ItemName,
|
|
161
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ISite } from "@ax/types";
|
|
2
|
+
|
|
3
|
+
const getSortedListStatus = (orderPointer: string, isAscending: boolean): any => {
|
|
4
|
+
const sortedListStatus = {
|
|
5
|
+
isAscending,
|
|
6
|
+
sortedByTitle: orderPointer === "name",
|
|
7
|
+
sortedByLastAccess: orderPointer === "lastAccess",
|
|
8
|
+
sortedByDateCreated: orderPointer === "dateCreated",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return sortedListStatus;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const filterByStatus = (bulkSelection: number[], sites: ISite[]): Record<string, number[]> => {
|
|
15
|
+
const notPublishedItems: number[] = [];
|
|
16
|
+
const publishedItems: number[] = [];
|
|
17
|
+
|
|
18
|
+
sites.forEach((site: ISite) => {
|
|
19
|
+
const { id, isPublished } = site;
|
|
20
|
+
if (bulkSelection.includes(id)) {
|
|
21
|
+
isPublished ? publishedItems.push(id) : notPublishedItems.push(id);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const filteredItems = {
|
|
26
|
+
all: bulkSelection,
|
|
27
|
+
notPublished: notPublishedItems,
|
|
28
|
+
published: publishedItems,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return filteredItems;
|
|
32
|
+
};
|
|
33
|
+
export { getSortedListStatus, filterByStatus };
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
|
+
|
|
2
3
|
import { connect } from "react-redux";
|
|
3
4
|
import { withRouter, RouteComponentProps } from "react-router-dom";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { IRootState } from "@ax/types";
|
|
6
7
|
import { Loading } from "@ax/components";
|
|
7
8
|
import { appActions } from "@ax/containers/App";
|
|
8
9
|
import { sitesActions } from "@ax/containers/Sites";
|
|
9
10
|
import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
|
|
10
11
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
11
12
|
import { usersActions } from "@ax/containers/Users";
|
|
13
|
+
|
|
12
14
|
import SitesList from "./SitesList";
|
|
13
15
|
|
|
14
|
-
const Sites = (props:
|
|
16
|
+
const Sites = (props: ISitesProps): JSX.Element => {
|
|
15
17
|
const {
|
|
16
18
|
isLoading,
|
|
17
|
-
sites,
|
|
18
19
|
token,
|
|
19
20
|
setCurrentSiteInfo,
|
|
20
|
-
getSites,
|
|
21
21
|
getStructuredData,
|
|
22
22
|
setLanguage,
|
|
23
23
|
getAllDataPacks,
|
|
@@ -28,7 +28,6 @@ const Sites = (props: IProps): JSX.Element => {
|
|
|
28
28
|
const fetchInitialData = async () => {
|
|
29
29
|
setCurrentSiteInfo(null);
|
|
30
30
|
await getStructuredData(token);
|
|
31
|
-
await getSites();
|
|
32
31
|
await getAllDataPacks();
|
|
33
32
|
await getUser("me");
|
|
34
33
|
|
|
@@ -49,37 +48,33 @@ const Sites = (props: IProps): JSX.Element => {
|
|
|
49
48
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
49
|
}, [token]);
|
|
51
50
|
|
|
52
|
-
return isLoading
|
|
51
|
+
return isLoading ? <Loading /> : <SitesList />;
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
const mapStateToProps = (state: IRootState) => ({
|
|
56
55
|
isLoading: state.app.isLoading,
|
|
57
|
-
sites: state.sites.sites,
|
|
58
56
|
token: state.app.token,
|
|
59
57
|
globalLangs: state.app.globalLangs,
|
|
60
58
|
});
|
|
61
59
|
|
|
62
60
|
interface IStateProps {
|
|
63
61
|
isLoading: boolean;
|
|
64
|
-
sites: ISite[];
|
|
65
62
|
token: string;
|
|
66
63
|
globalLangs: any[];
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
interface IDispatchProps {
|
|
70
67
|
setCurrentSiteInfo(currentSiteInfo: any): void;
|
|
71
|
-
getSites(): Promise<void>;
|
|
72
68
|
getStructuredData(token: string, siteId?: number): Promise<void>;
|
|
73
69
|
setLanguage(lang: { locale: string; id: number | null }): void;
|
|
74
70
|
getAllDataPacks: () => Promise<void>;
|
|
75
71
|
getUser: (id: string) => Promise<void>;
|
|
76
72
|
}
|
|
77
73
|
|
|
78
|
-
type
|
|
74
|
+
export type ISitesProps = IStateProps & IDispatchProps & RouteComponentProps;
|
|
79
75
|
|
|
80
76
|
const mapDispatchToProps = {
|
|
81
77
|
setCurrentSiteInfo: sitesActions.setCurrentSiteInfo,
|
|
82
|
-
getSites: sitesActions.getSites,
|
|
83
78
|
getStructuredData: structuredDataActions.getStructuredData,
|
|
84
79
|
setLanguage: appActions.setLanguage,
|
|
85
80
|
getAllDataPacks: dataPacksActions.getAllDataPacks,
|
|
@@ -105,7 +105,7 @@ const TableHeader = (props: IProps): JSX.Element => {
|
|
|
105
105
|
</S.NameWrapper>
|
|
106
106
|
{activeColumns.includes("live") && (
|
|
107
107
|
<S.HeaderWrapper>
|
|
108
|
-
<LiveFilter filterItems={filterItems} value={filterValues.liveStatus}
|
|
108
|
+
<LiveFilter filterItems={filterItems} value={filterValues.liveStatus} hasBasicStatus={true} />
|
|
109
109
|
</S.HeaderWrapper>
|
|
110
110
|
)}
|
|
111
111
|
{CategoryColumns}
|
package/src/types/index.tsx
CHANGED
|
@@ -97,10 +97,22 @@ export interface IPage extends IAPIPage {
|
|
|
97
97
|
isGlobal?: boolean;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export interface IGetSitesParams {
|
|
101
|
+
token?: string;
|
|
102
|
+
language?: number;
|
|
103
|
+
recentSitesNumber?: number;
|
|
104
|
+
pagination?: boolean;
|
|
105
|
+
page?: number;
|
|
106
|
+
itemsPerPage?: number;
|
|
107
|
+
searchQuery?: string;
|
|
108
|
+
filterQuery?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
export interface ISite {
|
|
101
112
|
author: string;
|
|
102
113
|
id: number;
|
|
103
114
|
name: string;
|
|
115
|
+
home?: string;
|
|
104
116
|
pages: IPage[];
|
|
105
117
|
published: string;
|
|
106
118
|
isPublished: boolean;
|
|
@@ -114,6 +126,12 @@ export interface ISite {
|
|
|
114
126
|
bigAvatar: string;
|
|
115
127
|
thumbnail: string;
|
|
116
128
|
domain: number | null;
|
|
129
|
+
lastAccess?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface IRecentSite {
|
|
133
|
+
lastAccess: string;
|
|
134
|
+
siteId: number;
|
|
117
135
|
}
|
|
118
136
|
|
|
119
137
|
export interface ISchema {
|
|
@@ -169,8 +187,8 @@ export interface IUrlField {
|
|
|
169
187
|
}
|
|
170
188
|
|
|
171
189
|
export interface IHeadingField {
|
|
172
|
-
content
|
|
173
|
-
tag
|
|
190
|
+
content?: string;
|
|
191
|
+
tag?: string;
|
|
174
192
|
}
|
|
175
193
|
|
|
176
194
|
export interface IRootState {
|
|
@@ -625,6 +643,11 @@ export interface IUsersQueryValues {
|
|
|
625
643
|
filterSites: string;
|
|
626
644
|
}
|
|
627
645
|
|
|
646
|
+
export interface ISitesQueryValues {
|
|
647
|
+
order: string;
|
|
648
|
+
liveStatus: string;
|
|
649
|
+
}
|
|
650
|
+
|
|
628
651
|
export interface IDataPackConfigImportCategory {
|
|
629
652
|
id: number;
|
|
630
653
|
title: string;
|