@griddo/ax 1.59.10 → 1.60.2
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/webpackSchemas.config.js +7 -0
- package/package.json +3 -2
- package/src/GlobalStore.tsx +3 -0
- package/src/api/index.tsx +2 -0
- package/src/api/redirects.tsx +71 -0
- package/src/api/sites.tsx +11 -25
- package/src/components/Fields/TextArea/index.tsx +3 -1
- package/src/components/Fields/TextArea/style.tsx +11 -11
- package/src/components/FloatingPanel/style.tsx +7 -2
- package/src/components/TableFilters/SiteFilter/index.tsx +7 -6
- package/src/components/TableFilters/SiteFilter/style.tsx +2 -2
- package/src/containers/Redirects/actions.tsx +129 -0
- package/src/containers/Redirects/constants.tsx +18 -0
- package/src/containers/Redirects/index.tsx +4 -0
- package/src/containers/Redirects/interfaces.tsx +13 -0
- package/src/containers/Redirects/reducer.tsx +24 -0
- package/src/containers/Settings/DataPacks/constants.tsx +11 -11
- package/src/containers/Sites/actions.tsx +1 -25
- package/src/helpers/thumbnails.tsx +3 -3
- package/src/modules/Content/PageItem/index.tsx +5 -8
- package/src/modules/Content/index.tsx +25 -35
- package/src/modules/GlobalSettings/Robots/Item/index.tsx +1 -1
- package/src/modules/GlobalSettings/Robots/index.tsx +5 -2
- package/src/modules/GlobalSettings/index.tsx +6 -0
- package/src/modules/Redirects/BulkHeader/TableHeader/index.tsx +44 -0
- package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +31 -0
- package/src/modules/Redirects/BulkHeader/index.tsx +59 -0
- package/src/modules/Redirects/RedirectItem/index.tsx +139 -0
- package/src/modules/Redirects/RedirectItem/style.tsx +50 -0
- package/src/modules/Redirects/RedirectPanel/index.tsx +117 -0
- package/src/modules/Redirects/RedirectPanel/style.tsx +13 -0
- package/src/modules/Redirects/index.tsx +310 -0
- package/src/modules/Redirects/style.tsx +52 -0
- package/src/modules/Settings/SeoSettings/index.tsx +25 -0
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +3 -3
- package/src/modules/StructuredData/StructuredDataList/index.tsx +1 -0
- package/src/modules/StructuredData/StructuredDataList/utils.tsx +1 -1
- package/src/routes/multisite.tsx +6 -0
- package/src/routes/site.tsx +6 -0
- package/src/types/index.tsx +13 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import { INavItem, IRedirect, IRootState } from "@ax/types";
|
|
5
|
+
import { appActions } from "@ax/containers/App";
|
|
6
|
+
import { redirectsActions } from "@ax/containers/Redirects";
|
|
7
|
+
import { MainWrapper, ErrorToast, Nav, TableList, EmptyState, Modal, Toast } from "@ax/components";
|
|
8
|
+
import { useBulkSelection, useModal, useToast } from "@ax/hooks";
|
|
9
|
+
import BulkHeader from "./BulkHeader";
|
|
10
|
+
import RedirectItem from "./RedirectItem";
|
|
11
|
+
import RedirectPanel from "./RedirectPanel";
|
|
12
|
+
|
|
13
|
+
import * as S from "./style";
|
|
14
|
+
|
|
15
|
+
const Redirects = (props: IProps): JSX.Element => {
|
|
16
|
+
const {
|
|
17
|
+
navItems,
|
|
18
|
+
currentNavItem,
|
|
19
|
+
setHistoryPush,
|
|
20
|
+
getRedirects,
|
|
21
|
+
redirects,
|
|
22
|
+
totalItems,
|
|
23
|
+
deleteRedirect,
|
|
24
|
+
addRedirect,
|
|
25
|
+
currentSiteID,
|
|
26
|
+
} = props;
|
|
27
|
+
|
|
28
|
+
const itemsPerPage = 50;
|
|
29
|
+
const [page, setPage] = useState(1);
|
|
30
|
+
const [isScrolling, setIsScrolling] = useState(false);
|
|
31
|
+
const [isOpenedSecond, setIsOpenedSecond] = useState(false);
|
|
32
|
+
const { isOpen, toggleModal } = useModal();
|
|
33
|
+
const { isOpen: isOpenDelete, toggleModal: toggleModalDelete } = useModal();
|
|
34
|
+
const tableRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
const [currentFilterQuery, setCurrentFilterQuery] = useState("");
|
|
36
|
+
const [filterValues, setFilterValues] = useState({ sites: "all" });
|
|
37
|
+
const { isVisible, toggleToast, setIsVisible } = useToast();
|
|
38
|
+
const { isOpen: isOpenOverwrite, toggleModal: toggleOverwriteModal } = useModal();
|
|
39
|
+
|
|
40
|
+
const initState = {
|
|
41
|
+
from: "",
|
|
42
|
+
to: {
|
|
43
|
+
pageId: undefined,
|
|
44
|
+
url: "",
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const [formValues, setFormValues] = useState<IRedirect>(initState);
|
|
49
|
+
|
|
50
|
+
const redIds = redirects && redirects.map((red: any) => red.id);
|
|
51
|
+
const isEmpty = redirects && redirects.length === 0;
|
|
52
|
+
|
|
53
|
+
const getParams = useCallback(() => {
|
|
54
|
+
const params = {
|
|
55
|
+
page,
|
|
56
|
+
itemsPerPage,
|
|
57
|
+
pagination: true,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return params;
|
|
61
|
+
}, [page]);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const params = getParams();
|
|
65
|
+
const siteFilterQuery = currentSiteID ? `&sites=${currentSiteID}` : currentFilterQuery;
|
|
66
|
+
getRedirects(params, siteFilterQuery);
|
|
67
|
+
if (tableRef.current) {
|
|
68
|
+
tableRef.current.scrollTo(0, 0);
|
|
69
|
+
}
|
|
70
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
|
+
}, [page, currentFilterQuery]);
|
|
72
|
+
|
|
73
|
+
const {
|
|
74
|
+
resetBulkSelection,
|
|
75
|
+
selectedItems,
|
|
76
|
+
isSelected,
|
|
77
|
+
areItemsSelected,
|
|
78
|
+
checkState,
|
|
79
|
+
addToBulkSelection,
|
|
80
|
+
selectAllItems,
|
|
81
|
+
} = useBulkSelection(redIds);
|
|
82
|
+
|
|
83
|
+
const bulkDelete = async () => {
|
|
84
|
+
const deleted = await deleteRedirect(selectedItems.all);
|
|
85
|
+
if (deleted) {
|
|
86
|
+
toggleToast();
|
|
87
|
+
}
|
|
88
|
+
toggleModalDelete();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const unselectAllItems = () => resetBulkSelection();
|
|
92
|
+
|
|
93
|
+
const selectItems = () => (checkState.isAllSelected ? unselectAllItems() : handleSelectAll());
|
|
94
|
+
|
|
95
|
+
const handleSelectAll = () => selectAllItems();
|
|
96
|
+
|
|
97
|
+
const filterItems = async (filterPointer: string, filtersSelected: string) => {
|
|
98
|
+
let filterQuery = "";
|
|
99
|
+
if (filtersSelected !== "all") {
|
|
100
|
+
filterQuery = `&${filterPointer}=${filtersSelected}`;
|
|
101
|
+
}
|
|
102
|
+
setFilterValues({ sites: filtersSelected });
|
|
103
|
+
setCurrentFilterQuery(filterQuery);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const TableHeader = (
|
|
107
|
+
<BulkHeader
|
|
108
|
+
showBulk={areItemsSelected(redIds)}
|
|
109
|
+
bulkDelete={toggleModalDelete}
|
|
110
|
+
selectAllItems={handleSelectAll}
|
|
111
|
+
totalItems={totalItems}
|
|
112
|
+
selectItems={selectItems}
|
|
113
|
+
checkState={checkState}
|
|
114
|
+
isScrolling={isScrolling}
|
|
115
|
+
filterItems={filterItems}
|
|
116
|
+
filterValues={filterValues}
|
|
117
|
+
isSiteItem={!!currentSiteID}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const onScroll = (e: any) => setIsScrolling(e.target.scrollTop > 0);
|
|
122
|
+
|
|
123
|
+
const toggleSecondaryPanel = () => setIsOpenedSecond(!isOpenedSecond);
|
|
124
|
+
|
|
125
|
+
const rightButtonProps = {
|
|
126
|
+
label: "New Redirect",
|
|
127
|
+
action: () => handleModal(),
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const handleMenuClick = (path: string) => {
|
|
131
|
+
setHistoryPush(path);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleModal = () => {
|
|
135
|
+
setFormValues(initState);
|
|
136
|
+
setIsOpenedSecond(false);
|
|
137
|
+
toggleModal();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const handleAddRedirect = async (force?: boolean) => {
|
|
141
|
+
const toPage = formValues.to.pageId ? formValues.to.pageId : formValues.to.url;
|
|
142
|
+
await addRedirect({ from: formValues.from, to: toPage }, toggleOverwriteModal, force, currentFilterQuery);
|
|
143
|
+
isOpen && toggleModal();
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const addItemActionForce = () => {
|
|
147
|
+
handleAddRedirect(true);
|
|
148
|
+
toggleOverwriteModal();
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const emptyStateProps = {
|
|
152
|
+
message: "To have a redirects on your site, create as many redirects as you want.",
|
|
153
|
+
button: "Create New redirect",
|
|
154
|
+
action: handleModal,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const pagination = {
|
|
158
|
+
setPage,
|
|
159
|
+
itemsPerPage,
|
|
160
|
+
totalItems,
|
|
161
|
+
currPage: page,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const toastProps = {
|
|
165
|
+
setIsVisible,
|
|
166
|
+
message: "Redirect deleted",
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const mainDeleteModalAction = {
|
|
170
|
+
title: "Delete redirects",
|
|
171
|
+
onClick: bulkDelete,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleModalDelete };
|
|
175
|
+
|
|
176
|
+
const mainOverwriteModalAction = {
|
|
177
|
+
title: "Overwrite redirect",
|
|
178
|
+
onClick: addItemActionForce,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const secondaryOverwriteModalAction = { title: "Cancel", onClick: toggleOverwriteModal };
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<>
|
|
185
|
+
<MainWrapper backLink={false} title="SEO Settings" rightButton={rightButtonProps}>
|
|
186
|
+
<S.Wrapper>
|
|
187
|
+
<Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
|
|
188
|
+
<S.ContentWrapper>
|
|
189
|
+
<ErrorToast />
|
|
190
|
+
<S.TitleWrapper>
|
|
191
|
+
<S.Title>URL Redirects Manager</S.Title>
|
|
192
|
+
<S.Description>
|
|
193
|
+
You can create 301 redirects to direct users and search engines from an old URL to a new one.
|
|
194
|
+
</S.Description>
|
|
195
|
+
</S.TitleWrapper>
|
|
196
|
+
<S.TableWrapper>
|
|
197
|
+
<TableList
|
|
198
|
+
tableHeader={TableHeader}
|
|
199
|
+
pagination={pagination}
|
|
200
|
+
onScroll={onScroll}
|
|
201
|
+
hasFixedHeader={true}
|
|
202
|
+
tableRef={tableRef}
|
|
203
|
+
>
|
|
204
|
+
{isEmpty ? (
|
|
205
|
+
<S.EmptyWrapper>
|
|
206
|
+
<EmptyState {...emptyStateProps} />
|
|
207
|
+
</S.EmptyWrapper>
|
|
208
|
+
) : (
|
|
209
|
+
redirects.map((redirect: any) => {
|
|
210
|
+
const isItemSelected = isSelected(redirect.id);
|
|
211
|
+
return (
|
|
212
|
+
<RedirectItem
|
|
213
|
+
key={redirect.id}
|
|
214
|
+
redirect={redirect}
|
|
215
|
+
isSelected={isItemSelected}
|
|
216
|
+
onChange={addToBulkSelection}
|
|
217
|
+
toggleToast={toggleToast}
|
|
218
|
+
setFormValues={setFormValues}
|
|
219
|
+
formValues={formValues}
|
|
220
|
+
addRedirect={handleAddRedirect}
|
|
221
|
+
currentFilter={currentFilterQuery}
|
|
222
|
+
isSiteItem={!!currentSiteID}
|
|
223
|
+
/>
|
|
224
|
+
);
|
|
225
|
+
})
|
|
226
|
+
)}
|
|
227
|
+
</TableList>
|
|
228
|
+
</S.TableWrapper>
|
|
229
|
+
{isVisible && <Toast {...toastProps} />}
|
|
230
|
+
</S.ContentWrapper>
|
|
231
|
+
</S.Wrapper>
|
|
232
|
+
{isOpen && (
|
|
233
|
+
<RedirectPanel
|
|
234
|
+
isOpen={isOpen}
|
|
235
|
+
isOpenedSecond={isOpenedSecond}
|
|
236
|
+
toggleModal={toggleModal}
|
|
237
|
+
toggleSecondaryPanel={toggleSecondaryPanel}
|
|
238
|
+
formValues={formValues}
|
|
239
|
+
setFormValues={setFormValues}
|
|
240
|
+
addRedirect={handleAddRedirect}
|
|
241
|
+
currentFilter={currentFilterQuery}
|
|
242
|
+
/>
|
|
243
|
+
)}
|
|
244
|
+
<Modal
|
|
245
|
+
isOpen={isOpenDelete}
|
|
246
|
+
hide={toggleModalDelete}
|
|
247
|
+
title="Delete Redirects"
|
|
248
|
+
secondaryAction={secondaryDeleteModalAction}
|
|
249
|
+
mainAction={mainDeleteModalAction}
|
|
250
|
+
size="S"
|
|
251
|
+
>
|
|
252
|
+
<S.ModalContent>
|
|
253
|
+
Are you sure you want to delete the selected <strong>redirects</strong>? This action{" "}
|
|
254
|
+
<strong>cannot be undone</strong>.
|
|
255
|
+
</S.ModalContent>
|
|
256
|
+
</Modal>
|
|
257
|
+
<Modal
|
|
258
|
+
isOpen={isOpenOverwrite}
|
|
259
|
+
hide={toggleOverwriteModal}
|
|
260
|
+
title="Overwrite Redirect"
|
|
261
|
+
secondaryAction={secondaryOverwriteModalAction}
|
|
262
|
+
mainAction={mainOverwriteModalAction}
|
|
263
|
+
size="S"
|
|
264
|
+
>
|
|
265
|
+
<S.ModalContent>
|
|
266
|
+
This Redirect is already created. It will overwrite.
|
|
267
|
+
<br />
|
|
268
|
+
This action <strong>cannot be undone</strong>.
|
|
269
|
+
</S.ModalContent>
|
|
270
|
+
</Modal>
|
|
271
|
+
</MainWrapper>
|
|
272
|
+
</>
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
277
|
+
redirects: state.redirects.redirects,
|
|
278
|
+
totalItems: state.redirects.totalItems,
|
|
279
|
+
currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const mapDispatchToProps = {
|
|
283
|
+
setHistoryPush: appActions.setHistoryPush,
|
|
284
|
+
getRedirects: redirectsActions.getRedirects,
|
|
285
|
+
deleteRedirect: redirectsActions.deleteRedirect,
|
|
286
|
+
addRedirect: redirectsActions.addRedirect,
|
|
287
|
+
};
|
|
288
|
+
interface IRedirectsProps {
|
|
289
|
+
navItems: INavItem[];
|
|
290
|
+
currentNavItem: INavItem;
|
|
291
|
+
redirects: IRedirect[];
|
|
292
|
+
totalItems: number;
|
|
293
|
+
currentSiteID: number | null;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
interface IDispatchProps {
|
|
297
|
+
setHistoryPush(path: string, isEditor?: boolean): void;
|
|
298
|
+
getRedirects(params: any, filters: string): void;
|
|
299
|
+
deleteRedirect(redirectID: number[]): Promise<boolean>;
|
|
300
|
+
addRedirect(
|
|
301
|
+
redirect: { from: string; to: string | number },
|
|
302
|
+
errorAction: () => void,
|
|
303
|
+
force?: boolean,
|
|
304
|
+
filter?: string
|
|
305
|
+
): Promise<void>;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
type IProps = IRedirectsProps & IDispatchProps;
|
|
309
|
+
|
|
310
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Redirects);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
height: 100%;
|
|
6
|
+
`;
|
|
7
|
+
|
|
8
|
+
const ContentWrapper = styled.div`
|
|
9
|
+
display: flex;
|
|
10
|
+
overflow: auto;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
width: 100%;
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const TitleWrapper = styled.div`
|
|
16
|
+
padding: ${(p) => p.theme.spacing.m};
|
|
17
|
+
border-bottom: ${(p) => `1px solid ${p.theme.color.uiLine}`};
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const Title = styled.div`
|
|
21
|
+
${(p) => p.theme.textStyle.headingXS};
|
|
22
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const Description = styled.div`
|
|
26
|
+
${(p) => p.theme.textStyle.uiM};
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const TableWrapper = styled.div`
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
width: 100%;
|
|
33
|
+
position: relative;
|
|
34
|
+
height: calc(100vh - ${(p) => p.theme.spacing.xl});
|
|
35
|
+
overflow: auto;
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const EmptyWrapper = styled.div`
|
|
39
|
+
height: ${(p) => `calc(100vh - (${p.theme.spacing.xl} * 3))`};
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const ModalContent = styled.div`
|
|
45
|
+
padding: ${(p) => p.theme.spacing.m};
|
|
46
|
+
|
|
47
|
+
p {
|
|
48
|
+
margin-bottom: ${(p) => p.theme.spacing.m};
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
export { Wrapper, ContentWrapper, TitleWrapper, Title, Description, TableWrapper, EmptyWrapper, ModalContent };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Switch, Route } from "react-router-dom";
|
|
3
|
+
import Redirects from "../../Redirects";
|
|
4
|
+
|
|
5
|
+
const navItems = [
|
|
6
|
+
{
|
|
7
|
+
title: "SEO",
|
|
8
|
+
path: "/sites/settings/seo-settings",
|
|
9
|
+
component: Redirects,
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const SeoSettings = (): JSX.Element => {
|
|
14
|
+
return (
|
|
15
|
+
<Switch>
|
|
16
|
+
{navItems.map((item, index) => (
|
|
17
|
+
<Route exact path={item.path} key={index}>
|
|
18
|
+
{React.createElement(item.component, { navItems, currentNavItem: item }, null)}
|
|
19
|
+
</Route>
|
|
20
|
+
))}
|
|
21
|
+
</Switch>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default SeoSettings;
|
|
@@ -77,7 +77,7 @@ const TableHeader = (props: IProps): JSX.Element => {
|
|
|
77
77
|
)}
|
|
78
78
|
{!isAllPages && activeColumns.includes("site") && (
|
|
79
79
|
<S.HeaderWrapper>
|
|
80
|
-
<SiteFilter filterItems={filterItems} value={filterValues
|
|
80
|
+
<SiteFilter filterItems={filterItems} value={filterValues} pointer="filterSites" />
|
|
81
81
|
</S.HeaderWrapper>
|
|
82
82
|
)}
|
|
83
83
|
{activeColumns.includes("live") && (
|
|
@@ -51,7 +51,7 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
51
51
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
52
52
|
|
|
53
53
|
const { locale } = lang;
|
|
54
|
-
const { title, pageLanguages, metaDescription, metaTitle, isIndexed, availableSites, structuredData } = globalPage;
|
|
54
|
+
const { title, pageLanguages, metaDescription, metaTitle, isIndexed, availableSites, structuredData, structuredDataContent } = globalPage;
|
|
55
55
|
|
|
56
56
|
const publishedTooltip: Record<string, string> = {
|
|
57
57
|
active: "Live",
|
|
@@ -305,8 +305,8 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
305
305
|
const mainUnpublishAction = { title: "Ok", onClick: toggleUnpublishModal };
|
|
306
306
|
|
|
307
307
|
const CategoryColumns = categoryColumns.map((col: any) => {
|
|
308
|
-
const type =
|
|
309
|
-
const categories = type && type.map((cat: any) => cat.title);
|
|
308
|
+
const type = structuredDataContent[col.from];
|
|
309
|
+
const categories = type && type.map((cat: any) => cat.label || cat.title);
|
|
310
310
|
return (
|
|
311
311
|
activeColumns.includes(col.key) && (
|
|
312
312
|
<CategoryCell
|
|
@@ -49,7 +49,7 @@ const getOptionValues = (options: { global: IStructuredData[]; site: IStructured
|
|
|
49
49
|
const type =
|
|
50
50
|
!!currSchema.type && currSchema.type.value && currSchema.type.value && currSchema.type.value.toLowerCase();
|
|
51
51
|
|
|
52
|
-
const isDetailTemplate =
|
|
52
|
+
const isDetailTemplate = currSchema.type.mode === "detail";
|
|
53
53
|
|
|
54
54
|
!!currSchema.type &&
|
|
55
55
|
isDetailTemplate &&
|
package/src/routes/multisite.tsx
CHANGED
package/src/routes/site.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import ContentTypes from "./../modules/Settings/ContentTypes";
|
|
|
7
7
|
import Settings from "./../modules/Settings";
|
|
8
8
|
import CategoriesList from "./../modules/Categories/CategoriesList";
|
|
9
9
|
import StructuredData from "./../modules/StructuredData";
|
|
10
|
+
import SeoSettings from "./../modules/Settings/SeoSettings";
|
|
10
11
|
|
|
11
12
|
const BASE_PATH = "/sites";
|
|
12
13
|
|
|
@@ -78,6 +79,11 @@ export default [
|
|
|
78
79
|
component: ContentTypes,
|
|
79
80
|
name: "Content types",
|
|
80
81
|
},
|
|
82
|
+
{
|
|
83
|
+
path: `${BASE_PATH}/settings/seo-settings`,
|
|
84
|
+
component: SeoSettings,
|
|
85
|
+
name: "SEO Settings",
|
|
86
|
+
},
|
|
81
87
|
],
|
|
82
88
|
},
|
|
83
89
|
],
|
package/src/types/index.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { IDataPacksState } from "@ax/containers/Settings/DataPacks/reducer";
|
|
|
9
9
|
import { IUsersState } from "@ax/containers/Users/reducer";
|
|
10
10
|
import { IGalleryState } from "@ax/containers/Gallery/reducer";
|
|
11
11
|
import { IDomainsState } from "@ax/containers/Domains/reducer";
|
|
12
|
+
import { IRedirectsState } from "@ax/containers/Redirects/reducer";
|
|
12
13
|
|
|
13
14
|
export interface IBreadcrumbItem {
|
|
14
15
|
editorID: number;
|
|
@@ -86,6 +87,8 @@ export interface IAPIPage {
|
|
|
86
87
|
haveDraftPage: number | null;
|
|
87
88
|
draftFromPage: number | null;
|
|
88
89
|
liveChanged: boolean;
|
|
90
|
+
templateId: string;
|
|
91
|
+
structuredDataContent: Record<string, []>
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
export interface IPage extends IAPIPage {
|
|
@@ -181,6 +184,7 @@ export interface IRootState {
|
|
|
181
184
|
users: IUsersState;
|
|
182
185
|
gallery: IGalleryState;
|
|
183
186
|
domains: IDomainsState;
|
|
187
|
+
redirects: IRedirectsState;
|
|
184
188
|
}
|
|
185
189
|
|
|
186
190
|
export interface IStyledProps {
|
|
@@ -267,6 +271,7 @@ export interface IGetSitePagesParams {
|
|
|
267
271
|
query?: string;
|
|
268
272
|
lang?: number;
|
|
269
273
|
filterStructuredData?: string;
|
|
274
|
+
format?: string;
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
export interface IGetGlobalPagesParams {
|
|
@@ -279,6 +284,7 @@ export interface IGetGlobalPagesParams {
|
|
|
279
284
|
filterStructuredData?: boolean | string;
|
|
280
285
|
excludeSite?: number;
|
|
281
286
|
liveStatus?: string;
|
|
287
|
+
format?: string;
|
|
282
288
|
}
|
|
283
289
|
|
|
284
290
|
export interface IGetStructuredDataParams {
|
|
@@ -673,6 +679,13 @@ export interface IDomainRobot {
|
|
|
673
679
|
content: string;
|
|
674
680
|
}
|
|
675
681
|
|
|
682
|
+
export interface IRedirect {
|
|
683
|
+
id?: number;
|
|
684
|
+
from: string;
|
|
685
|
+
to: { pageId?: number; url: string; linkTo?: number; href?: string };
|
|
686
|
+
site?: { siteId: number | null; siteName: string | null };
|
|
687
|
+
}
|
|
688
|
+
|
|
676
689
|
export type Field =
|
|
677
690
|
| "AsyncCheckGroup"
|
|
678
691
|
| "AsyncSelect"
|