@griddo/ax 1.61.4 → 1.61.7
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/helpers/index.tsx +2 -0
- package/src/helpers/structuredData.tsx +3 -0
- package/src/hooks/forms.tsx +2 -1
- package/src/modules/Content/OptionTable/index.tsx +11 -12
- package/src/modules/Content/PageItem/index.tsx +13 -4
- package/src/modules/Content/index.tsx +6 -4
- package/src/modules/Content/utils.tsx +6 -5
- package/src/modules/GlobalEditor/index.tsx +3 -3
- package/src/modules/PageEditor/index.tsx +11 -3
- package/src/modules/StructuredData/StructuredDataList/OptionTable/index.tsx +3 -5
- package/src/modules/StructuredData/StructuredDataList/utils.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "1.61.
|
|
4
|
+
"version": "1.61.7",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -244,5 +244,5 @@
|
|
|
244
244
|
"publishConfig": {
|
|
245
245
|
"access": "public"
|
|
246
246
|
},
|
|
247
|
-
"gitHead": "
|
|
247
|
+
"gitHead": "9b014749b0e843961331bd3c95724e2449f67a8d"
|
|
248
248
|
}
|
package/src/helpers/index.tsx
CHANGED
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
getFilteredStructuredData,
|
|
56
56
|
getStructuredDataTitle,
|
|
57
57
|
isStructuredDataFromPage,
|
|
58
|
+
isGlobalStructuredData,
|
|
58
59
|
getGlobalPageTypes,
|
|
59
60
|
} from "./structuredData";
|
|
60
61
|
|
|
@@ -149,6 +150,7 @@ export {
|
|
|
149
150
|
decodeEntities,
|
|
150
151
|
getStructuredDataTitle,
|
|
151
152
|
isStructuredDataFromPage,
|
|
153
|
+
isGlobalStructuredData,
|
|
152
154
|
getGlobalPageTypes,
|
|
153
155
|
isNumber,
|
|
154
156
|
getFileExtension,
|
|
@@ -28,6 +28,8 @@ const getStructuredDataTitle = (name: string): string => schemas.structuredData[
|
|
|
28
28
|
|
|
29
29
|
const isStructuredDataFromPage = (name: string): boolean => schemas.structuredData[name].fromPage;
|
|
30
30
|
|
|
31
|
+
const isGlobalStructuredData = (name: string): boolean => !schemas.structuredData[name].local;
|
|
32
|
+
|
|
31
33
|
const getGlobalPageTypes = (): Record<string, string>[] => {
|
|
32
34
|
const { structuredData } = schemas;
|
|
33
35
|
const keys = Object.keys(structuredData);
|
|
@@ -44,6 +46,7 @@ export {
|
|
|
44
46
|
getCurrentPageStructuredData,
|
|
45
47
|
getFilteredStructuredData,
|
|
46
48
|
getStructuredDataTitle,
|
|
49
|
+
isGlobalStructuredData,
|
|
47
50
|
isStructuredDataFromPage,
|
|
48
51
|
getGlobalPageTypes,
|
|
49
52
|
};
|
package/src/hooks/forms.tsx
CHANGED
|
@@ -89,6 +89,7 @@ const useIsDirty = (
|
|
|
89
89
|
const [isResetting, setIsResetting] = useState(false);
|
|
90
90
|
|
|
91
91
|
const prevContent = usePrevious(updatedValues, isSaved);
|
|
92
|
+
const isTranslatedVersion: boolean = prevContent?.language !== updatedValues?.language;
|
|
92
93
|
|
|
93
94
|
const hasChanged = () => {
|
|
94
95
|
if (prevContent && updatedValues) {
|
|
@@ -97,7 +98,7 @@ const useIsDirty = (
|
|
|
97
98
|
|
|
98
99
|
const { cleanUpdatedValues, cleanOriginalValues } = cleanPageValues(updatedValuesCloned, originalValuesCloned);
|
|
99
100
|
|
|
100
|
-
const hasChanged = !isEqual(cleanUpdatedValues, cleanOriginalValues);
|
|
101
|
+
const hasChanged = !isTranslatedVersion && !isEqual(cleanUpdatedValues, cleanOriginalValues);
|
|
101
102
|
|
|
102
103
|
return hasChanged;
|
|
103
104
|
}
|
|
@@ -2,7 +2,7 @@ import React, { useReducer, useEffect, useLayoutEffect } from "react";
|
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
5
|
-
import { getStructuredDataTitle, getThumbnailProps,
|
|
5
|
+
import { getStructuredDataTitle, getThumbnailProps, isGlobalStructuredData } from "@ax/helpers";
|
|
6
6
|
import { MenuItem, RadioGroup } from "@ax/components";
|
|
7
7
|
|
|
8
8
|
import { reducer, IOptionTableStore, setColumnValues, setShowThumbnail, setSelectedType, setOption } from "./store";
|
|
@@ -31,9 +31,10 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
31
31
|
|
|
32
32
|
const optionObj = availableOptions.find((item: any) => item.value === option);
|
|
33
33
|
setSelectedOption(option);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (optionObj) {
|
|
35
|
+
const { isData } = optionObj;
|
|
36
|
+
setValue(option, !!isData);
|
|
37
|
+
}
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
let filteredByTypeOptions = filterOptions(state.selectedType, "type");
|
|
@@ -44,7 +45,7 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
44
45
|
}, []);
|
|
45
46
|
|
|
46
47
|
useEffect(() => {
|
|
47
|
-
const firstOption = filteredByTypeOptions[0].value;
|
|
48
|
+
const firstOption = filteredByTypeOptions[0] && filteredByTypeOptions[0].value;
|
|
48
49
|
selectOption(firstOption, filteredByTypeOptions);
|
|
49
50
|
// eslint-disable-next-line
|
|
50
51
|
}, []);
|
|
@@ -72,20 +73,20 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
72
73
|
setType(value);
|
|
73
74
|
filteredByTypeOptions = filterOptions(value, "type");
|
|
74
75
|
|
|
75
|
-
const isGlobal = value !== "static" &&
|
|
76
|
+
const isGlobal = value !== "static" && isGlobalStructuredData(value.toUpperCase());
|
|
76
77
|
if (isGlobal) {
|
|
77
78
|
filteredByTypeOptions = filteredByTypeOptions.map((option: any) => {
|
|
78
|
-
if (
|
|
79
|
+
if (option.mode !== "detail") return option;
|
|
79
80
|
const title = `Get ${getStructuredDataTitle(value.toUpperCase())} from Global`;
|
|
80
81
|
return { ...option, title };
|
|
81
82
|
});
|
|
82
|
-
const globalOptionIdx = filteredByTypeOptions.findIndex((option: any) => option.
|
|
83
|
+
const globalOptionIdx = filteredByTypeOptions.findIndex((option: any) => option.mode === "detail");
|
|
83
84
|
const globalOption = filteredByTypeOptions.splice(globalOptionIdx, 1);
|
|
84
85
|
filteredByTypeOptions.push(...globalOption);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
setValues(filteredByTypeOptions);
|
|
88
|
-
const firstOption = filteredByTypeOptions[0].value;
|
|
89
|
+
const firstOption = filteredByTypeOptions[0] && filteredByTypeOptions[0].value;
|
|
89
90
|
selectOption(firstOption, filteredByTypeOptions);
|
|
90
91
|
|
|
91
92
|
const optionList = filterOptions(state.selectedOption, "value");
|
|
@@ -106,9 +107,7 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
106
107
|
return (
|
|
107
108
|
<MenuItem key={`${item.type}${i}`}>
|
|
108
109
|
<S.NavLink onClick={displayFilteredOptions} className={selectedClass}>
|
|
109
|
-
<S.Link active={isSelected}>
|
|
110
|
-
{item.label}
|
|
111
|
-
</S.Link>
|
|
110
|
+
<S.Link active={isSelected}>{item.label}</S.Link>
|
|
112
111
|
</S.NavLink>
|
|
113
112
|
</MenuItem>
|
|
114
113
|
);
|
|
@@ -47,7 +47,16 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
47
47
|
removePageFromSite,
|
|
48
48
|
} = functions;
|
|
49
49
|
const { locale } = lang;
|
|
50
|
-
const {
|
|
50
|
+
const {
|
|
51
|
+
pageLanguages,
|
|
52
|
+
isHome,
|
|
53
|
+
fullPath,
|
|
54
|
+
canBeUnpublished,
|
|
55
|
+
origin,
|
|
56
|
+
manuallyImported,
|
|
57
|
+
templateId,
|
|
58
|
+
structuredDataContent,
|
|
59
|
+
} = page;
|
|
51
60
|
const displayName = getTemplateDisplayName(templateId);
|
|
52
61
|
|
|
53
62
|
const initValue = { title: "", slug: "" };
|
|
@@ -261,8 +270,8 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
261
270
|
isGlobal && !manuallyImported
|
|
262
271
|
? "This page has been provided by subscription. You cannot remove it."
|
|
263
272
|
: canBeUnpublished === false
|
|
264
|
-
|
|
265
|
-
|
|
273
|
+
? "This is the canonical site of the page. You cannot remove it."
|
|
274
|
+
: null;
|
|
266
275
|
|
|
267
276
|
let menuOptions: IPageOption[] = [
|
|
268
277
|
{
|
|
@@ -394,7 +403,7 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
394
403
|
{page.title}
|
|
395
404
|
{isHome && <Icon name="home" />}
|
|
396
405
|
</S.Title>
|
|
397
|
-
<S.Slug>{fullPath.page}</S.Slug>
|
|
406
|
+
<S.Slug>{fullPath && fullPath.page}</S.Slug>
|
|
398
407
|
</S.NameCell>
|
|
399
408
|
{CategoryColumns}
|
|
400
409
|
{activeColumns.includes("type") && (
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
IColumn,
|
|
16
16
|
} from "@ax/types";
|
|
17
17
|
import { MainWrapper, Modal, TableList, ErrorToast, Toast, EmptyState } from "@ax/components";
|
|
18
|
-
import { getFilteredStructuredData, isStructuredDataFromPage } from "@ax/helpers";
|
|
18
|
+
import { getFilteredStructuredData, isGlobalStructuredData, isStructuredDataFromPage } from "@ax/helpers";
|
|
19
19
|
|
|
20
20
|
import { appActions } from "@ax/containers/App";
|
|
21
21
|
import { sitesActions } from "@ax/containers/Sites";
|
|
@@ -535,9 +535,11 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
535
535
|
|
|
536
536
|
const onScroll = (e: any) => setIsScrolling(e.target.scrollTop > 0);
|
|
537
537
|
|
|
538
|
-
const
|
|
539
|
-
const
|
|
540
|
-
const
|
|
538
|
+
const selectedOptionObject = options.values.find((option) => option.value === selectedOption);
|
|
539
|
+
const selectedOptionType = selectedOptionObject.type.toUpperCase();
|
|
540
|
+
const isOptionGlobal = selectedOptionType !== "STATIC" && isGlobalStructuredData(selectedOptionType);
|
|
541
|
+
const isOptionImportable =
|
|
542
|
+
isOptionGlobal && isStructuredDataFromPage(selectedOptionType) && selectedOptionObject.mode === "detail";
|
|
541
543
|
|
|
542
544
|
const handleImport = () => {
|
|
543
545
|
toggleNewModal();
|
|
@@ -3,11 +3,10 @@ import { filterDuplicatedValues, getActivatedDataPacksIds } from "@ax/helpers";
|
|
|
3
3
|
import { pageStatus } from "@ax/containers/PageEditor/interfaces";
|
|
4
4
|
import { IPage } from "@ax/types";
|
|
5
5
|
|
|
6
|
-
const { templates } = schemas;
|
|
7
|
-
|
|
8
6
|
const getTemplatesFilters = (activatedDataPacks: any) => {
|
|
9
7
|
const types: any[] = [];
|
|
10
8
|
const activatedDataPacksIds = getActivatedDataPacksIds(activatedDataPacks);
|
|
9
|
+
const { templates } = schemas;
|
|
11
10
|
|
|
12
11
|
Object.keys(templates).forEach((schema: any) => {
|
|
13
12
|
const { type, dataPacks } = templates[schema];
|
|
@@ -39,12 +38,13 @@ const mapStructuredOptions = (options: any[]) => {
|
|
|
39
38
|
|
|
40
39
|
const getOptionValues = (options: any) => {
|
|
41
40
|
const templatesOptionsValues: any = [];
|
|
41
|
+
const { templates } = schemas;
|
|
42
42
|
|
|
43
43
|
Object.keys(templates).forEach((schema: any) => {
|
|
44
44
|
const currSchema = templates[schema];
|
|
45
45
|
const { component, displayName } = currSchema;
|
|
46
|
-
const type =
|
|
47
|
-
|
|
46
|
+
const type = currSchema.type && currSchema.type.value && currSchema.type.value.toLowerCase();
|
|
47
|
+
const mode = currSchema.type && currSchema.type.mode;
|
|
48
48
|
|
|
49
49
|
!!currSchema.type &&
|
|
50
50
|
templatesOptionsValues.push({
|
|
@@ -52,6 +52,7 @@ const getOptionValues = (options: any) => {
|
|
|
52
52
|
title: displayName,
|
|
53
53
|
type,
|
|
54
54
|
value: component,
|
|
55
|
+
mode,
|
|
55
56
|
});
|
|
56
57
|
});
|
|
57
58
|
|
|
@@ -64,7 +65,7 @@ const getOptionFilters = (options: any, activatedDataPacks: any) => {
|
|
|
64
65
|
|
|
65
66
|
const mappedOptions = pureOptions.map((option: any) => ({
|
|
66
67
|
label: option.title,
|
|
67
|
-
value: option.
|
|
68
|
+
value: option.id.toLowerCase(),
|
|
68
69
|
}));
|
|
69
70
|
|
|
70
71
|
const filters = [...templateFilters, ...mappedOptions];
|
|
@@ -273,15 +273,15 @@ const GlobalEditor = (props: IProps) => {
|
|
|
273
273
|
switch (props.pageStatus) {
|
|
274
274
|
case pageStatus.PUBLISHED:
|
|
275
275
|
case pageStatus.UPLOAD_PENDING:
|
|
276
|
-
return !isDirty ? "Saved" : isPublished && hasDraft ? "Save & publish" : "Save draft";
|
|
276
|
+
return !isDirty && !isNewTranslation ? "Saved" : isPublished && hasDraft ? "Save & publish" : "Save draft";
|
|
277
277
|
default:
|
|
278
|
-
return !isDirty ? "Saved" : "Save";
|
|
278
|
+
return !isDirty && !isNewTranslation ? "Saved" : "Save";
|
|
279
279
|
}
|
|
280
280
|
};
|
|
281
281
|
|
|
282
282
|
const rightButtonProps = {
|
|
283
283
|
label: isSaving ? "Saving" : getSaveLabel(),
|
|
284
|
-
disabled:
|
|
284
|
+
disabled: (!isDirty && pageID !== null && !isNewTranslation) || isSaving || isPreviewMode,
|
|
285
285
|
action: handleSavePage,
|
|
286
286
|
};
|
|
287
287
|
|
|
@@ -301,15 +301,23 @@ const PageEditor = (props: IProps) => {
|
|
|
301
301
|
switch (props.pageStatus) {
|
|
302
302
|
case pageStatus.PUBLISHED:
|
|
303
303
|
case pageStatus.UPLOAD_PENDING:
|
|
304
|
-
return !isDirty
|
|
304
|
+
return !isDirty && !isNewTranslation
|
|
305
|
+
? "Saved"
|
|
306
|
+
: isGlobal || (isPublished && hasDraft)
|
|
307
|
+
? "Save & publish"
|
|
308
|
+
: "Save draft";
|
|
305
309
|
default:
|
|
306
|
-
return !
|
|
310
|
+
return !pageID || isNewTranslation ? "Save" : isDirty ? "Save" : "Saved";
|
|
307
311
|
}
|
|
308
312
|
};
|
|
309
313
|
|
|
310
314
|
const rightButtonProps = {
|
|
311
315
|
label: isSaving ? "Saving" : getSaveLabel(),
|
|
312
|
-
disabled:
|
|
316
|
+
disabled:
|
|
317
|
+
(!isDirty && pageID !== null && !isNewTranslation) ||
|
|
318
|
+
isSaving ||
|
|
319
|
+
isPreviewMode ||
|
|
320
|
+
(!isTemplateActivated && !isGlobal),
|
|
313
321
|
action: handleSavePage,
|
|
314
322
|
};
|
|
315
323
|
|
|
@@ -56,11 +56,11 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
56
56
|
setType(value);
|
|
57
57
|
filteredByTypeOptions = filterOptions(value, "type");
|
|
58
58
|
setValues(filteredByTypeOptions);
|
|
59
|
-
const firstOption = filteredByTypeOptions[0].value;
|
|
59
|
+
const firstOption = filteredByTypeOptions[0] && filteredByTypeOptions[0].value;
|
|
60
60
|
selectOption(firstOption);
|
|
61
61
|
|
|
62
62
|
const optionList = filterOptions(state.selectedOption, "value");
|
|
63
|
-
const displayThumbnail = optionList[0].type !== value;
|
|
63
|
+
const displayThumbnail = optionList[0] && optionList[0].type !== value;
|
|
64
64
|
|
|
65
65
|
showThumbnail(displayThumbnail);
|
|
66
66
|
};
|
|
@@ -77,9 +77,7 @@ const OptionTable = (props: IOptionTableProps): JSX.Element => {
|
|
|
77
77
|
return (
|
|
78
78
|
<MenuItem key={`${item.value}${i}`}>
|
|
79
79
|
<S.NavLink onClick={displayFilteredOptions} className={selectedClass}>
|
|
80
|
-
<S.Link active={isSelected}>
|
|
81
|
-
{item.label}
|
|
82
|
-
</S.Link>
|
|
80
|
+
<S.Link active={isSelected}>{item.label}</S.Link>
|
|
83
81
|
</S.NavLink>
|
|
84
82
|
</MenuItem>
|
|
85
83
|
);
|
|
@@ -9,7 +9,7 @@ const getOptionFilters = (options: { global: IStructuredData[]; site: IStructure
|
|
|
9
9
|
|
|
10
10
|
const filters = pageOptions.map((option: IStructuredData) => ({
|
|
11
11
|
label: option.title,
|
|
12
|
-
value: option.
|
|
12
|
+
value: option.id.toLowerCase(),
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
15
|
const uniqueFilters = [...new Map(filters.map((item: IStructuredDataFilter) => [item.value, item])).values()];
|