@griddo/ax 1.75.224 → 1.75.225
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/ConfigPanel/Form/ConnectedField/NavConnectedField/index.tsx +10 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +1 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +15 -11
- package/src/components/ConfigPanel/Form/index.tsx +22 -2
- package/src/components/ConfigPanel/index.tsx +3 -0
- package/src/components/ErrorCenter/index.tsx +2 -2
- package/src/components/Fields/AnalyticsField/PageAnalytics/atoms.tsx +19 -9
- package/src/components/Fields/AnalyticsField/PageAnalytics/index.tsx +6 -3
- package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/atoms.tsx +11 -5
- package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/index.tsx +4 -3
- package/src/components/Fields/AnalyticsField/index.tsx +1 -0
- package/src/components/Fields/ConditionalField/index.tsx +3 -2
- package/src/components/Fields/MultiCheckSelect/index.tsx +30 -5
- package/src/components/Fields/MultiCheckSelect/style.tsx +9 -3
- package/src/components/Fields/MultiCheckSelectGroup/index.tsx +6 -1
- package/src/components/FieldsBehavior/index.tsx +1 -1
- package/src/components/MainWrapper/AppBar/atoms.tsx +3 -1
- package/src/components/MainWrapper/AppBar/index.tsx +6 -1
- package/src/components/MainWrapper/AppBar/style.tsx +2 -1
- package/src/containers/Sites/actions.tsx +3 -4
- package/src/forms/fields.tsx +5 -3
- package/src/forms/validators.tsx +30 -3
- package/src/modules/Content/PageItem/index.tsx +2 -2
- package/src/modules/Content/hooks.tsx +1 -1
- package/src/modules/Content/index.tsx +4 -1
- package/src/modules/Content/utils.tsx +0 -1
- package/src/modules/GlobalEditor/Editor/index.tsx +4 -1
- package/src/modules/GlobalEditor/index.tsx +35 -35
- package/src/modules/PageEditor/Editor/index.tsx +8 -1
- package/src/modules/PageEditor/index.tsx +34 -34
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +2 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "1.75.
|
|
4
|
+
"version": "1.75.225",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -235,5 +235,5 @@
|
|
|
235
235
|
"publishConfig": {
|
|
236
236
|
"access": "public"
|
|
237
237
|
},
|
|
238
|
-
"gitHead": "
|
|
238
|
+
"gitHead": "a6b6a2ed7e0944aae31e4d35a07d74ad195a70c2"
|
|
239
239
|
}
|
|
@@ -24,6 +24,7 @@ const NavConnectedField = (props: any) => {
|
|
|
24
24
|
activatedTemplates,
|
|
25
25
|
menus,
|
|
26
26
|
theme,
|
|
27
|
+
disabled,
|
|
27
28
|
moduleCopy,
|
|
28
29
|
} = props;
|
|
29
30
|
|
|
@@ -56,7 +57,15 @@ const NavConnectedField = (props: any) => {
|
|
|
56
57
|
|
|
57
58
|
if (isConditional) {
|
|
58
59
|
const innerActions = { ...actions, updateValue, goTo };
|
|
59
|
-
innerFields = getInnerFields(
|
|
60
|
+
innerFields = getInnerFields(
|
|
61
|
+
field.fields,
|
|
62
|
+
innerActions,
|
|
63
|
+
selectedContent,
|
|
64
|
+
isTemplateActivated,
|
|
65
|
+
theme,
|
|
66
|
+
disabled,
|
|
67
|
+
site
|
|
68
|
+
);
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
return (
|
|
@@ -37,6 +37,7 @@ const PageConnectedField = (props: any) => {
|
|
|
37
37
|
availableDataPacks,
|
|
38
38
|
template,
|
|
39
39
|
setHistoryPush,
|
|
40
|
+
isReadOnly,
|
|
40
41
|
} = props;
|
|
41
42
|
|
|
42
43
|
const isTemplate = field.type === "template";
|
|
@@ -55,22 +56,25 @@ const PageConnectedField = (props: any) => {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
const parentIsReadOnly =
|
|
58
|
-
componentType === "page" &&
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
(componentType === "page" &&
|
|
60
|
+
objKey === "parent" &&
|
|
61
|
+
isTemplateActivated &&
|
|
62
|
+
templateConfig &&
|
|
63
|
+
templateConfig.modifiableOnPage === false) ||
|
|
64
|
+
isReadOnly;
|
|
65
|
+
|
|
63
66
|
const defaultParent =
|
|
64
67
|
isTemplateActivated && templateConfig && templateConfig.defaultParent ? templateConfig.defaultParent : null;
|
|
68
|
+
|
|
65
69
|
const hasDefaultIndex = isTemplateActivated && templateConfig && templateConfig.indexDefault !== undefined;
|
|
66
70
|
|
|
67
|
-
const
|
|
71
|
+
const isFieldReadOnly =
|
|
68
72
|
(["parent", "slug"].includes(objKey) && (selectedContent.setAsHome || isPageHome)) || parentIsReadOnly;
|
|
73
|
+
|
|
69
74
|
const isDisabled =
|
|
70
|
-
!isGlobal &&
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
!isTemplateActivated);
|
|
75
|
+
(!isGlobal &&
|
|
76
|
+
(isModuleDisabled(selectedContent.component, componentType, activatedModules) || !isTemplateActivated)) ||
|
|
77
|
+
isFieldReadOnly;
|
|
74
78
|
|
|
75
79
|
const isMetaTitleModified = selectedContent.metaTitle && selectedContent.metaTitle !== selectedContent.title;
|
|
76
80
|
|
|
@@ -176,7 +180,7 @@ const PageConnectedField = (props: any) => {
|
|
|
176
180
|
site={site}
|
|
177
181
|
lang={lang}
|
|
178
182
|
disabled={isDisabled}
|
|
179
|
-
readonly={
|
|
183
|
+
readonly={isFieldReadOnly}
|
|
180
184
|
activatedModules={activatedModules}
|
|
181
185
|
isTemplateActivated={isTemplateActivated}
|
|
182
186
|
error={error}
|
|
@@ -8,8 +8,20 @@ import ConnectedField from "./ConnectedField";
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
10
10
|
export const Form = (props: IFormProps): JSX.Element => {
|
|
11
|
-
const {
|
|
12
|
-
|
|
11
|
+
const {
|
|
12
|
+
schema,
|
|
13
|
+
selectedTab,
|
|
14
|
+
setSelectedTab,
|
|
15
|
+
actions,
|
|
16
|
+
isPage,
|
|
17
|
+
isGlobal,
|
|
18
|
+
theme,
|
|
19
|
+
setHistoryPush,
|
|
20
|
+
header,
|
|
21
|
+
footer,
|
|
22
|
+
isEditLive,
|
|
23
|
+
} = props;
|
|
24
|
+
|
|
13
25
|
const tabContent = schema.configTabs.find((tab: ISchemaTab) => tab.title === selectedTab);
|
|
14
26
|
const setTab = (tab: string) => setSelectedTab(tab);
|
|
15
27
|
|
|
@@ -33,6 +45,7 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
33
45
|
isGlobal={isGlobal}
|
|
34
46
|
theme={theme}
|
|
35
47
|
setHistoryPush={setHistoryPush}
|
|
48
|
+
isReadOnly={isEditLive}
|
|
36
49
|
/>
|
|
37
50
|
);
|
|
38
51
|
};
|
|
@@ -65,6 +78,12 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
65
78
|
return (
|
|
66
79
|
<section data-testid="form-section">
|
|
67
80
|
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={setTab} />
|
|
81
|
+
{selectedTab === "content" && isEditLive && (
|
|
82
|
+
<S.FieldWrapper>
|
|
83
|
+
There are some changes in the <strong>draft associated</strong> with this page. Before making changes to the
|
|
84
|
+
published version, you should <strong>discard or publish your draft</strong>.
|
|
85
|
+
</S.FieldWrapper>
|
|
86
|
+
)}
|
|
68
87
|
{selectedTab === "content" && !isGlobal && header === 0 && (
|
|
69
88
|
<S.FieldWrapper>
|
|
70
89
|
This page doesn't have a header. Click{" "}
|
|
@@ -100,6 +119,7 @@ export interface IFormProps {
|
|
|
100
119
|
setHistoryPush?: (path: string, isEditor: boolean) => void;
|
|
101
120
|
header?: number | null;
|
|
102
121
|
footer?: number | null;
|
|
122
|
+
isEditLive?: boolean;
|
|
103
123
|
}
|
|
104
124
|
|
|
105
125
|
export default Form;
|
|
@@ -35,6 +35,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
35
35
|
lastElementAddedId,
|
|
36
36
|
header,
|
|
37
37
|
footer,
|
|
38
|
+
isEditLive,
|
|
38
39
|
} = props;
|
|
39
40
|
|
|
40
41
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
@@ -84,6 +85,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
84
85
|
setHistoryPush={setHistoryPush}
|
|
85
86
|
header={header}
|
|
86
87
|
footer={footer}
|
|
88
|
+
isEditLive={isEditLive}
|
|
87
89
|
/>
|
|
88
90
|
);
|
|
89
91
|
}
|
|
@@ -125,6 +127,7 @@ export interface IStateProps {
|
|
|
125
127
|
lastElementAddedId?: null | number;
|
|
126
128
|
header?: number | null;
|
|
127
129
|
footer?: number | null;
|
|
130
|
+
isEditLive?: boolean;
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
export default ConfigPanel;
|
|
@@ -8,7 +8,7 @@ const ErrorCenter = (props: IErrorCenterProps): JSX.Element => {
|
|
|
8
8
|
const { errors, actions } = props;
|
|
9
9
|
|
|
10
10
|
const goToElement = (key: string) => {
|
|
11
|
-
const element = document.getElementById(key);
|
|
11
|
+
const element = document.getElementById(`gdd_${key}`);
|
|
12
12
|
|
|
13
13
|
if (element) {
|
|
14
14
|
const pos = element.style.position;
|
|
@@ -28,7 +28,7 @@ const ErrorCenter = (props: IErrorCenterProps): JSX.Element => {
|
|
|
28
28
|
if (item.hasDeactivatedPackage) {
|
|
29
29
|
actions?.goToPackage();
|
|
30
30
|
} else {
|
|
31
|
-
item.editorID && actions?.goToError(item.editorID, item.tab, item.template);
|
|
31
|
+
item.editorID !== null && actions?.goToError(item.editorID, item.tab, item.template);
|
|
32
32
|
goToElement(item.key);
|
|
33
33
|
}
|
|
34
34
|
};
|
|
@@ -11,8 +11,9 @@ const DimensionsGroup = (props: {
|
|
|
11
11
|
analytics: IAnalytics;
|
|
12
12
|
state: IState;
|
|
13
13
|
setDimension: (value: Record<string, string>) => void;
|
|
14
|
+
disabled?: boolean;
|
|
14
15
|
}): JSX.Element => {
|
|
15
|
-
const { analytics, state, setDimension } = props;
|
|
16
|
+
const { analytics, state, setDimension, disabled } = props;
|
|
16
17
|
const { groupSelect, values } = state;
|
|
17
18
|
const selectedGroup = analytics.groups.find((g) => g.name === groupSelect);
|
|
18
19
|
const dimensionNames = splitAndTrim(selectedGroup?.dimensions, ";");
|
|
@@ -26,7 +27,8 @@ const DimensionsGroup = (props: {
|
|
|
26
27
|
<S.FieldsDivider />
|
|
27
28
|
{groupDimensions &&
|
|
28
29
|
groupDimensions.map(
|
|
29
|
-
(dimension, idx) =>
|
|
30
|
+
(dimension, idx) =>
|
|
31
|
+
dimension && <DimensionValue key={idx} {...{ dimension, setDimension, values, disabled }} />
|
|
30
32
|
)}
|
|
31
33
|
</>
|
|
32
34
|
);
|
|
@@ -36,8 +38,9 @@ const DimensionsSelection = (props: {
|
|
|
36
38
|
analytics: IAnalytics;
|
|
37
39
|
state: IState;
|
|
38
40
|
setDimension: (value: Record<string, string>) => void;
|
|
41
|
+
disabled?: boolean;
|
|
39
42
|
}): JSX.Element => {
|
|
40
|
-
const { analytics, state, setDimension } = props;
|
|
43
|
+
const { analytics, state, setDimension, disabled } = props;
|
|
41
44
|
const { dimensionsSelect, values } = state;
|
|
42
45
|
const selectedDimensions = analytics.dimensions?.filter((d) => dimensionsSelect.includes(d.name));
|
|
43
46
|
|
|
@@ -46,19 +49,24 @@ const DimensionsSelection = (props: {
|
|
|
46
49
|
{selectedDimensions?.length ? <S.FieldsDivider /> : <></>}
|
|
47
50
|
{selectedDimensions &&
|
|
48
51
|
selectedDimensions.map((dimension, idx) => (
|
|
49
|
-
<DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
52
|
+
<DimensionValue key={idx} {...{ dimension, setDimension, values, disabled }} />
|
|
50
53
|
))}
|
|
51
54
|
</>
|
|
52
55
|
);
|
|
53
56
|
};
|
|
54
57
|
|
|
55
|
-
const DimensionValue = (props: {
|
|
56
|
-
|
|
58
|
+
const DimensionValue = (props: {
|
|
59
|
+
dimension: IDimension;
|
|
60
|
+
setDimension: (value: Record<string, string>) => void;
|
|
61
|
+
values: Record<string, string>;
|
|
62
|
+
disabled?: boolean;
|
|
63
|
+
}) => {
|
|
64
|
+
const { dimension, setDimension, values, disabled } = props;
|
|
57
65
|
const dimensionValues = splitAndTrim(dimension?.values, ";");
|
|
58
66
|
const options = dimensionValues.map((option) => ({ label: option, value: option }));
|
|
59
67
|
const handleOnChange = (value: string) => {
|
|
60
68
|
dimension && setDimension({ [dimension.name]: value });
|
|
61
|
-
}
|
|
69
|
+
};
|
|
62
70
|
|
|
63
71
|
const isNullValue = dimensionValues.includes("null");
|
|
64
72
|
const fieldValue = values && dimension ? values[dimension.name] : "";
|
|
@@ -70,6 +78,7 @@ const DimensionValue = (props: { dimension: IDimension, setDimension: (value: Re
|
|
|
70
78
|
value={fieldValue}
|
|
71
79
|
onChange={handleOnChange}
|
|
72
80
|
placeholder="Type a variable"
|
|
81
|
+
disabled={disabled}
|
|
73
82
|
/>
|
|
74
83
|
) : (
|
|
75
84
|
<FieldsBehavior
|
|
@@ -79,8 +88,9 @@ const DimensionValue = (props: { dimension: IDimension, setDimension: (value: Re
|
|
|
79
88
|
value={fieldValue}
|
|
80
89
|
onChange={handleOnChange}
|
|
81
90
|
placeholder="Select variable"
|
|
91
|
+
disabled={disabled}
|
|
82
92
|
/>
|
|
83
|
-
)
|
|
84
|
-
}
|
|
93
|
+
);
|
|
94
|
+
};
|
|
85
95
|
|
|
86
96
|
export { DimensionsGroup, DimensionsSelection };
|
|
@@ -7,7 +7,7 @@ import { DimensionsGroup, DimensionsSelection } from "./atoms";
|
|
|
7
7
|
import * as S from "../style";
|
|
8
8
|
|
|
9
9
|
const PageAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
10
|
-
const { value, onChange, analytics } = props;
|
|
10
|
+
const { value, onChange, analytics, disabled } = props;
|
|
11
11
|
|
|
12
12
|
const initialState = {
|
|
13
13
|
contentSelect: "",
|
|
@@ -103,6 +103,7 @@ const PageAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
|
103
103
|
value={state.contentSelect}
|
|
104
104
|
onChange={handleContentSelect}
|
|
105
105
|
placeholder="Select Dimensions Options"
|
|
106
|
+
disabled={disabled}
|
|
106
107
|
/>
|
|
107
108
|
</S.FieldWrapper>
|
|
108
109
|
{isGroup && (
|
|
@@ -114,8 +115,9 @@ const PageAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
|
114
115
|
value={state.groupSelect}
|
|
115
116
|
onChange={handleGroupSelect}
|
|
116
117
|
placeholder="Select Group"
|
|
118
|
+
disabled={disabled}
|
|
117
119
|
/>
|
|
118
|
-
{!!state.groupSelect && <DimensionsGroup {...{ analytics, state, setDimension }} />}
|
|
120
|
+
{!!state.groupSelect && <DimensionsGroup {...{ analytics, state, setDimension, disabled }} />}
|
|
119
121
|
</>
|
|
120
122
|
)}
|
|
121
123
|
{isIndividual && (
|
|
@@ -128,9 +130,10 @@ const PageAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
|
128
130
|
onChange={handleDimensionsSelect}
|
|
129
131
|
selectAllOption="all"
|
|
130
132
|
placeholder="Select Dimensions"
|
|
133
|
+
disabled={disabled}
|
|
131
134
|
floating
|
|
132
135
|
/>
|
|
133
|
-
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension }} />}
|
|
136
|
+
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension, disabled }} />}
|
|
134
137
|
</>
|
|
135
138
|
)}
|
|
136
139
|
</>
|
|
@@ -7,7 +7,7 @@ import { IAnalytics, IDimension } from "@ax/types";
|
|
|
7
7
|
import { IState } from "..";
|
|
8
8
|
|
|
9
9
|
const TemplateDimensions = (props: ITemplateDimensions): JSX.Element => {
|
|
10
|
-
const { analytics, state, setDimension, dimensionNames } = props;
|
|
10
|
+
const { analytics, state, setDimension, dimensionNames, disabled } = props;
|
|
11
11
|
const { values } = state;
|
|
12
12
|
const groupDimensions = dimensionNames.map((dimensionName) => {
|
|
13
13
|
const dimension = analytics.dimensions?.find((dimension) => dimension.name === dimensionName);
|
|
@@ -18,7 +18,8 @@ const TemplateDimensions = (props: ITemplateDimensions): JSX.Element => {
|
|
|
18
18
|
<>
|
|
19
19
|
{groupDimensions &&
|
|
20
20
|
groupDimensions.map(
|
|
21
|
-
(dimension, idx) =>
|
|
21
|
+
(dimension, idx) =>
|
|
22
|
+
dimension && <DimensionValue key={idx} {...{ dimension, setDimension, values, disabled }} />
|
|
22
23
|
)}
|
|
23
24
|
</>
|
|
24
25
|
);
|
|
@@ -28,8 +29,9 @@ const DimensionsSelection = (props: {
|
|
|
28
29
|
analytics: IAnalytics;
|
|
29
30
|
state: IState;
|
|
30
31
|
setDimension: (value: Record<string, string>) => void;
|
|
32
|
+
disabled?: boolean;
|
|
31
33
|
}): JSX.Element => {
|
|
32
|
-
const { analytics, state, setDimension } = props;
|
|
34
|
+
const { analytics, state, setDimension, disabled } = props;
|
|
33
35
|
const { dimensionsSelect, values } = state;
|
|
34
36
|
const selectedDimensions = analytics.dimensions?.filter((d) => dimensionsSelect.includes(d.name));
|
|
35
37
|
|
|
@@ -37,7 +39,7 @@ const DimensionsSelection = (props: {
|
|
|
37
39
|
<>
|
|
38
40
|
{selectedDimensions &&
|
|
39
41
|
selectedDimensions.map((dimension, idx) => (
|
|
40
|
-
<DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
42
|
+
<DimensionValue key={idx} {...{ dimension, setDimension, values, disabled }} />
|
|
41
43
|
))}
|
|
42
44
|
</>
|
|
43
45
|
);
|
|
@@ -47,8 +49,9 @@ const DimensionValue = (props: {
|
|
|
47
49
|
dimension: IDimension;
|
|
48
50
|
setDimension: (value: Record<string, string>) => void;
|
|
49
51
|
values: Record<string, string>;
|
|
52
|
+
disabled?: boolean;
|
|
50
53
|
}) => {
|
|
51
|
-
const { dimension, setDimension, values } = props;
|
|
54
|
+
const { dimension, setDimension, values, disabled } = props;
|
|
52
55
|
const dimensionValues = splitAndTrim(dimension?.values, ";");
|
|
53
56
|
|
|
54
57
|
const options = dimensionValues.map((option) => ({ label: option, value: option }));
|
|
@@ -66,6 +69,7 @@ const DimensionValue = (props: {
|
|
|
66
69
|
value={fieldValue}
|
|
67
70
|
onChange={handleOnChange}
|
|
68
71
|
placeholder="Type a variable"
|
|
72
|
+
disabled={disabled}
|
|
69
73
|
/>
|
|
70
74
|
) : (
|
|
71
75
|
<FieldsBehavior
|
|
@@ -75,6 +79,7 @@ const DimensionValue = (props: {
|
|
|
75
79
|
value={fieldValue}
|
|
76
80
|
onChange={handleOnChange}
|
|
77
81
|
placeholder="Select variable"
|
|
82
|
+
disabled={disabled}
|
|
78
83
|
/>
|
|
79
84
|
);
|
|
80
85
|
};
|
|
@@ -84,6 +89,7 @@ interface ITemplateDimensions {
|
|
|
84
89
|
state: IState;
|
|
85
90
|
setDimension: (value: Record<string, string>) => void;
|
|
86
91
|
dimensionNames: string[];
|
|
92
|
+
disabled?: boolean;
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
export { TemplateDimensions, DimensionsSelection };
|
|
@@ -8,7 +8,7 @@ import { TemplateDimensions, DimensionsSelection } from "./atoms";
|
|
|
8
8
|
import * as S from "../style";
|
|
9
9
|
|
|
10
10
|
const StructuredDataAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
11
|
-
const { value, onChange, analytics, template } = props;
|
|
11
|
+
const { value, onChange, analytics, template, disabled } = props;
|
|
12
12
|
|
|
13
13
|
const initialState = {
|
|
14
14
|
dimensionsSelect: [],
|
|
@@ -61,7 +61,7 @@ const StructuredDataAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
63
|
<>
|
|
64
|
-
<TemplateDimensions dimensionNames={templateDimensions} {...{ analytics, state, setDimension }} />
|
|
64
|
+
<TemplateDimensions dimensionNames={templateDimensions} {...{ analytics, state, setDimension, disabled }} />
|
|
65
65
|
{dimensionOptions.length > 1 && (
|
|
66
66
|
<>
|
|
67
67
|
<S.FieldsDivider />
|
|
@@ -73,9 +73,10 @@ const StructuredDataAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
|
73
73
|
onChange={handleDimensionsSelect}
|
|
74
74
|
selectAllOption="all"
|
|
75
75
|
placeholder="Select Dimensions"
|
|
76
|
+
disabled={disabled}
|
|
76
77
|
floating
|
|
77
78
|
/>
|
|
78
|
-
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension }} />}
|
|
79
|
+
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension, disabled }} />}
|
|
79
80
|
</>
|
|
80
81
|
)}
|
|
81
82
|
</>
|
|
@@ -4,7 +4,7 @@ import { RadioGroup } from "@ax/components";
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const ConditionalField = (props: IConditionalFieldProps) => {
|
|
7
|
-
const { value, options, innerFields, onChange, defaultValue } = props;
|
|
7
|
+
const { value, options, innerFields, onChange, defaultValue, disabled } = props;
|
|
8
8
|
|
|
9
9
|
const safeValue = value === undefined ? defaultValue : value;
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ const ConditionalField = (props: IConditionalFieldProps) => {
|
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<S.Wrapper>
|
|
15
|
-
<RadioGroup name="radio" value={safeValue} options={options} onChange={handleChange} />
|
|
15
|
+
<RadioGroup name="radio" value={safeValue} options={options} onChange={handleChange} disabled={disabled} />
|
|
16
16
|
<S.Content data-testid="conditionalFieldContent">
|
|
17
17
|
{innerFields &&
|
|
18
18
|
innerFields.map((item: any) => {
|
|
@@ -31,4 +31,5 @@ interface IConditionalFieldProps {
|
|
|
31
31
|
innerFields: any;
|
|
32
32
|
onChange: (value: any) => void;
|
|
33
33
|
defaultValue?: string | boolean;
|
|
34
|
+
disabled?: boolean;
|
|
34
35
|
}
|
|
@@ -7,8 +7,19 @@ import CheckGroup from "@ax/components/Fields/CheckGroup";
|
|
|
7
7
|
import * as S from "./style";
|
|
8
8
|
|
|
9
9
|
const MultiCheckSelect = (props: IMultiCheckSelectProps) => {
|
|
10
|
-
const {
|
|
11
|
-
|
|
10
|
+
const {
|
|
11
|
+
placeholder,
|
|
12
|
+
source,
|
|
13
|
+
value,
|
|
14
|
+
onChange,
|
|
15
|
+
site,
|
|
16
|
+
className,
|
|
17
|
+
mandatory,
|
|
18
|
+
options,
|
|
19
|
+
selectAllOption,
|
|
20
|
+
floating,
|
|
21
|
+
disabled,
|
|
22
|
+
} = props;
|
|
12
23
|
|
|
13
24
|
const [isOpen, setIsOpen] = useState(false);
|
|
14
25
|
|
|
@@ -18,16 +29,29 @@ const MultiCheckSelect = (props: IMultiCheckSelectProps) => {
|
|
|
18
29
|
|
|
19
30
|
return (
|
|
20
31
|
<S.Wrapper className={className} data-testid="multi-check-select-wrapper">
|
|
21
|
-
<S.Field isOpen={isOpen} onClick={handleClick} data-testid="field">
|
|
32
|
+
<S.Field isOpen={isOpen} onClick={handleClick} disabled={disabled} data-testid="field">
|
|
22
33
|
{placeholder} <Asterisk />
|
|
23
34
|
</S.Field>
|
|
24
35
|
{isOpen && (
|
|
25
36
|
<S.DropDown floating={floating}>
|
|
26
37
|
{options && (
|
|
27
|
-
<CheckGroup
|
|
38
|
+
<CheckGroup
|
|
39
|
+
options={options}
|
|
40
|
+
value={value}
|
|
41
|
+
onChange={onChange}
|
|
42
|
+
selectAllOption={selectAllOption}
|
|
43
|
+
disabled={disabled}
|
|
44
|
+
/>
|
|
28
45
|
)}
|
|
29
46
|
{source && (
|
|
30
|
-
<AsyncCheckGroup
|
|
47
|
+
<AsyncCheckGroup
|
|
48
|
+
source={source}
|
|
49
|
+
site={site}
|
|
50
|
+
value={value}
|
|
51
|
+
onChange={onChange}
|
|
52
|
+
fullHeight={true}
|
|
53
|
+
disabled={disabled}
|
|
54
|
+
/>
|
|
31
55
|
)}
|
|
32
56
|
</S.DropDown>
|
|
33
57
|
)}
|
|
@@ -46,6 +70,7 @@ export interface IMultiCheckSelectProps {
|
|
|
46
70
|
options?: { name: string; value: string; title: string }[];
|
|
47
71
|
selectAllOption?: string;
|
|
48
72
|
floating?: boolean;
|
|
73
|
+
disabled?: boolean;
|
|
49
74
|
}
|
|
50
75
|
|
|
51
76
|
export default memo(MultiCheckSelect);
|
|
@@ -7,15 +7,21 @@ const Wrapper = styled.div`
|
|
|
7
7
|
z-index: 2;
|
|
8
8
|
`;
|
|
9
9
|
|
|
10
|
-
const Field = styled.div<{ isOpen: boolean }>`
|
|
10
|
+
const Field = styled.div<{ isOpen: boolean; disabled?: boolean }>`
|
|
11
11
|
position: relative;
|
|
12
12
|
${(p) => p.theme.textStyle?.fieldContent};
|
|
13
|
-
color: ${(p) => p.theme.color?.textHighEmphasis};
|
|
13
|
+
color: ${(p) => (p.disabled ? p.theme.color?.interactiveDisabled : p.theme.color?.textHighEmphasis)};
|
|
14
14
|
display: flex;
|
|
15
15
|
width: 100%;
|
|
16
16
|
height: ${(p) => p.theme.spacing?.l};
|
|
17
17
|
background-color: ${(p) => p.theme.color?.interactiveBackground};
|
|
18
|
-
border: 1px solid
|
|
18
|
+
border: 1px solid
|
|
19
|
+
${(p) =>
|
|
20
|
+
p.isOpen
|
|
21
|
+
? p.theme.color?.interactive01
|
|
22
|
+
: p.disabled
|
|
23
|
+
? p.theme.color?.interactiveDisabled
|
|
24
|
+
: p.theme.color?.uiLine};
|
|
19
25
|
border-radius: ${(p) => p.theme.radii?.s};
|
|
20
26
|
align-items: center;
|
|
21
27
|
cursor: pointer;
|
|
@@ -5,7 +5,7 @@ import { ISite } from "@ax/types";
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
7
|
const MultiCheckSelectGroup = (props: IMultiCheckSelectGroupProps) => {
|
|
8
|
-
const { value, onChange, site, elements, note } = props;
|
|
8
|
+
const { value, onChange, site, elements, note, disabled, error, handleValidation } = props;
|
|
9
9
|
|
|
10
10
|
const completedValue = value ? value : {};
|
|
11
11
|
|
|
@@ -25,6 +25,7 @@ const MultiCheckSelectGroup = (props: IMultiCheckSelectGroupProps) => {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
onChange(newValue);
|
|
28
|
+
error && handleValidation && handleValidation(newValue);
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
const val = completedValue[key] ? completedValue[key] : [];
|
|
@@ -39,6 +40,7 @@ const MultiCheckSelectGroup = (props: IMultiCheckSelectGroupProps) => {
|
|
|
39
40
|
site={fromSite}
|
|
40
41
|
placeholder={placeholder}
|
|
41
42
|
source={source}
|
|
43
|
+
disabled={disabled}
|
|
42
44
|
/>
|
|
43
45
|
);
|
|
44
46
|
})}
|
|
@@ -52,6 +54,9 @@ export interface IMultiCheckSelectGroupProps {
|
|
|
52
54
|
onChange: (value: Record<string, any[]> | Record<string, never>) => void;
|
|
53
55
|
site?: ISite;
|
|
54
56
|
note?: string;
|
|
57
|
+
error?: boolean;
|
|
58
|
+
handleValidation?: (value: Record<string, unknown>, validators?: Record<string, unknown>) => void;
|
|
59
|
+
disabled?: boolean;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
export default memo(MultiCheckSelectGroup);
|
|
@@ -79,7 +79,7 @@ const FieldsBehavior = (props: any): JSX.Element => {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
return (
|
|
82
|
-
<S.Wrapper className={wrapperClass} showTitle={showTitle} id={objKey}>
|
|
82
|
+
<S.Wrapper className={wrapperClass} showTitle={showTitle} id={`gdd_${objKey}`}>
|
|
83
83
|
<S.Content error={errorField} data-testid="fields-behavior-wrapper">
|
|
84
84
|
<Field
|
|
85
85
|
{...props}
|
|
@@ -52,7 +52,9 @@ const ActionSimpleMenu = (props: any) => {
|
|
|
52
52
|
return (
|
|
53
53
|
menu &&
|
|
54
54
|
menu.options && (
|
|
55
|
-
<S.ActionMenu data-testid="action-simple-menu">
|
|
55
|
+
<S.ActionMenu data-testid="action-simple-menu">
|
|
56
|
+
{menu.options.map((item: any, i: number) => ActionMenuItem(item, true))}
|
|
57
|
+
</S.ActionMenu>
|
|
56
58
|
)
|
|
57
59
|
);
|
|
58
60
|
};
|
|
@@ -130,7 +130,12 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
130
130
|
</S.ErrorWrapper>
|
|
131
131
|
);
|
|
132
132
|
|
|
133
|
-
const StatusBtn = () =>
|
|
133
|
+
const StatusBtn = () =>
|
|
134
|
+
pageStatus && (
|
|
135
|
+
<S.StatusBtn data-testid="status-button">
|
|
136
|
+
<Icon name={pageStatus} size="24" />
|
|
137
|
+
</S.StatusBtn>
|
|
138
|
+
);
|
|
134
139
|
|
|
135
140
|
const statusMenu = {
|
|
136
141
|
options: pageStatusActions,
|
|
@@ -82,6 +82,7 @@ const ActionMenuTitle = styled.li`
|
|
|
82
82
|
const ButtonWrapper = styled.div`
|
|
83
83
|
padding: ${(p) => `0 ${p.theme.spacing.s} ${p.theme.spacing.xs} ${p.theme.spacing.s}`};
|
|
84
84
|
margin-left: 0;
|
|
85
|
+
white-space: nowrap;
|
|
85
86
|
|
|
86
87
|
button {
|
|
87
88
|
width: 100%;
|
|
@@ -204,5 +205,5 @@ export {
|
|
|
204
205
|
WrapperEnd,
|
|
205
206
|
WrapperTitle,
|
|
206
207
|
TabsContent,
|
|
207
|
-
StatusBtn
|
|
208
|
+
StatusBtn,
|
|
208
209
|
};
|
|
@@ -578,7 +578,7 @@ function deleteAndRemoveFromSiteBulk(
|
|
|
578
578
|
sites: { currentSiteInfo },
|
|
579
579
|
} = getState();
|
|
580
580
|
|
|
581
|
-
let responseErrorPages: any = { data: { code: null, message:
|
|
581
|
+
let responseErrorPages: any = { data: { code: null, message: null } };
|
|
582
582
|
|
|
583
583
|
const responsePageActions = {
|
|
584
584
|
handleSuccess: () => true,
|
|
@@ -604,13 +604,12 @@ function deleteAndRemoveFromSiteBulk(
|
|
|
604
604
|
}
|
|
605
605
|
},
|
|
606
606
|
handleError: (response: any) => {
|
|
607
|
+
const errorMessages = responseErrorPages.data?.message ? responseErrorPages.data.message : [];
|
|
607
608
|
responseErrorPages = {
|
|
608
609
|
...responseErrorPages,
|
|
609
610
|
data: {
|
|
610
611
|
code: responseErrorPages.data?.code || response.data?.code,
|
|
611
|
-
message: response.data
|
|
612
|
-
? [...responseErrorPages.data.message, ...response.data.message]
|
|
613
|
-
: responseErrorPages.data?.message,
|
|
612
|
+
message: response.data ? [...errorMessages, ...response.data.message] : errorMessages,
|
|
614
613
|
},
|
|
615
614
|
};
|
|
616
615
|
|
package/src/forms/fields.tsx
CHANGED
|
@@ -8,9 +8,10 @@ const getInnerFields = (
|
|
|
8
8
|
selectedContent: IPage,
|
|
9
9
|
isTemplateActivated: boolean,
|
|
10
10
|
theme: string,
|
|
11
|
+
parentDisabled?: boolean,
|
|
11
12
|
site?: ISite,
|
|
12
13
|
errors?: IErrorItem[],
|
|
13
|
-
deleteError?: (error: IErrorItem) => void
|
|
14
|
+
deleteError?: (error: IErrorItem) => void
|
|
14
15
|
) => {
|
|
15
16
|
let fieldArr: any[] = [];
|
|
16
17
|
|
|
@@ -27,9 +28,10 @@ const getInnerFields = (
|
|
|
27
28
|
selectedContent,
|
|
28
29
|
isTemplateActivated,
|
|
29
30
|
theme,
|
|
31
|
+
parentDisabled,
|
|
30
32
|
site,
|
|
31
33
|
errors,
|
|
32
|
-
deleteError
|
|
34
|
+
deleteError
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -45,7 +47,7 @@ const getInnerFields = (
|
|
|
45
47
|
goTo={innerActions.goTo}
|
|
46
48
|
site={site}
|
|
47
49
|
{...singleFieldProps}
|
|
48
|
-
disabled={!isTemplateActivated || singleFieldProps.disabled}
|
|
50
|
+
disabled={!isTemplateActivated || singleFieldProps.disabled || parentDisabled}
|
|
49
51
|
error={error}
|
|
50
52
|
deleteError={deleteError}
|
|
51
53
|
theme={theme}
|
package/src/forms/validators.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
isValidDate,
|
|
13
13
|
isValidDateRange,
|
|
14
14
|
stringToDate,
|
|
15
|
+
isEmptyObj,
|
|
15
16
|
} from "@ax/helpers";
|
|
16
17
|
|
|
17
18
|
import { findByEditorID } from "@ax/forms";
|
|
@@ -177,6 +178,7 @@ const isEmptyField = (value: any, fieldType: string, multiple: boolean) => {
|
|
|
177
178
|
case "AsyncCheckGroup":
|
|
178
179
|
case "CheckGroup":
|
|
179
180
|
case "ComponentArray":
|
|
181
|
+
case "MultiCheckSelect":
|
|
180
182
|
return (
|
|
181
183
|
!value || (Array.isArray(value) && !value.length) || (value.component === "Section" && !value.modules.length)
|
|
182
184
|
);
|
|
@@ -190,6 +192,8 @@ const isEmptyField = (value: any, fieldType: string, multiple: boolean) => {
|
|
|
190
192
|
}
|
|
191
193
|
case "NumberField":
|
|
192
194
|
return value === null || Number.isNaN(value);
|
|
195
|
+
case "MultiCheckSelectGroup":
|
|
196
|
+
return !value || isEmptyObj(value);
|
|
193
197
|
default:
|
|
194
198
|
return typeof value === "string" && value.trim().length === 0;
|
|
195
199
|
}
|
|
@@ -238,7 +242,7 @@ const getValidationErrors = (
|
|
|
238
242
|
type: "error",
|
|
239
243
|
message: getErrorMessage("ERR015", null),
|
|
240
244
|
validator: { mandatory: true },
|
|
241
|
-
editorID: current && current.editorID ? current.editorID :
|
|
245
|
+
editorID: current && current.editorID ? current.editorID : 0,
|
|
242
246
|
component: current && current.component ? current.component : null,
|
|
243
247
|
name: name ? name : field.title,
|
|
244
248
|
key: field.key,
|
|
@@ -261,7 +265,7 @@ const getValidationErrors = (
|
|
|
261
265
|
type: "error",
|
|
262
266
|
message: getErrorMessage("ERR016", null),
|
|
263
267
|
validator: { isMockup: { type: field.type, defaultValue } },
|
|
264
|
-
editorID: current.editorID ? current.editorID :
|
|
268
|
+
editorID: current.editorID ? current.editorID : 0,
|
|
265
269
|
component: current.component ? current.component : null,
|
|
266
270
|
name: name ? name : field.title,
|
|
267
271
|
key: field.key,
|
|
@@ -285,7 +289,7 @@ const getValidationErrors = (
|
|
|
285
289
|
type: "error",
|
|
286
290
|
message: errorText,
|
|
287
291
|
validator: allValidators,
|
|
288
|
-
editorID: current.editorID ? current.editorID :
|
|
292
|
+
editorID: current.editorID ? current.editorID : 0,
|
|
289
293
|
component: current.component ? current.component : null,
|
|
290
294
|
name: name ? name : field.title,
|
|
291
295
|
key: field.key,
|
|
@@ -320,6 +324,29 @@ const getValidationErrors = (
|
|
|
320
324
|
errors = [...errors, ...innerErrors];
|
|
321
325
|
});
|
|
322
326
|
}
|
|
327
|
+
|
|
328
|
+
if (field.type === "MultiCheckSelectGroup") {
|
|
329
|
+
const multiCheckError = field.elements.some((item: any) =>
|
|
330
|
+
item.mandatory &&
|
|
331
|
+
(!current || !current[field.key] || !current[field.key][item.key] || !current[field.key][item.key].length)
|
|
332
|
+
? true
|
|
333
|
+
: false
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
if (multiCheckError) {
|
|
337
|
+
errors.push({
|
|
338
|
+
type: "error",
|
|
339
|
+
message: getErrorMessage("ERR015", null),
|
|
340
|
+
validator: { mandatory: true },
|
|
341
|
+
editorID: current && current.editorID ? current.editorID : 0,
|
|
342
|
+
component: current && current.component ? current.component : null,
|
|
343
|
+
name: name ? name : field.title,
|
|
344
|
+
key: field.key,
|
|
345
|
+
tab,
|
|
346
|
+
template,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
323
350
|
});
|
|
324
351
|
|
|
325
352
|
return errors;
|
|
@@ -380,7 +380,7 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
380
380
|
const viewPage = () => window.open(page.fullUrl || `${API_URL}/page/go/${page.id}`, "_blank");
|
|
381
381
|
|
|
382
382
|
const viewOption = {
|
|
383
|
-
label: "View
|
|
383
|
+
label: "View online",
|
|
384
384
|
icon: "View",
|
|
385
385
|
action: viewPage,
|
|
386
386
|
};
|
|
@@ -397,7 +397,7 @@ const PageItem = (props: IPageItemProps): JSX.Element => {
|
|
|
397
397
|
color: true,
|
|
398
398
|
},
|
|
399
399
|
{
|
|
400
|
-
label: "
|
|
400
|
+
label: "View live",
|
|
401
401
|
icon: "active",
|
|
402
402
|
action: editLivePage,
|
|
403
403
|
color: true,
|
|
@@ -317,7 +317,10 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
317
317
|
addToBulkSelection(item, bulkFilter);
|
|
318
318
|
};
|
|
319
319
|
|
|
320
|
-
const handleSelectAll = () =>
|
|
320
|
+
const handleSelectAll = () => {
|
|
321
|
+
selectAllItems(bulkFilter);
|
|
322
|
+
setPagesSelected(isStructuredData ? currentDataContent : currentSitePages);
|
|
323
|
+
};
|
|
321
324
|
|
|
322
325
|
const unselectAllItems = () => {
|
|
323
326
|
resetBulkSelection();
|
|
@@ -112,7 +112,6 @@ const filterByStatus = (bulkSelection: number[], currentSitePages: IPage[]): Rec
|
|
|
112
112
|
case pageStatus.OFFLINE_PENDING:
|
|
113
113
|
case pageStatus.OFFLINE:
|
|
114
114
|
case pageStatus.UPLOAD_PENDING:
|
|
115
|
-
notPublishedItems.push(id);
|
|
116
115
|
haveDraftPage ? draftItems.push(id) : notPublishedItems.push(id);
|
|
117
116
|
break;
|
|
118
117
|
case pageStatus.PUBLISHED:
|
|
@@ -31,6 +31,7 @@ const Editor = (props: IProps) => {
|
|
|
31
31
|
theme,
|
|
32
32
|
browserRef,
|
|
33
33
|
setNotification,
|
|
34
|
+
isEditLive,
|
|
34
35
|
} = props;
|
|
35
36
|
|
|
36
37
|
const actions = {
|
|
@@ -48,7 +49,7 @@ const Editor = (props: IProps) => {
|
|
|
48
49
|
|
|
49
50
|
return (
|
|
50
51
|
<ResizePanel
|
|
51
|
-
leftPanel={<PageBrowser isReadOnly={isReadOnly} theme={theme} browserRef={browserRef} />}
|
|
52
|
+
leftPanel={<PageBrowser isReadOnly={isReadOnly || isEditLive} theme={theme} browserRef={browserRef} />}
|
|
52
53
|
rightPanel={
|
|
53
54
|
<ConfigPanel
|
|
54
55
|
schema={schema}
|
|
@@ -66,6 +67,7 @@ const Editor = (props: IProps) => {
|
|
|
66
67
|
isReadOnly={isReadOnly}
|
|
67
68
|
userEditing={userEditing}
|
|
68
69
|
theme={theme}
|
|
70
|
+
isEditLive={isEditLive}
|
|
69
71
|
/>
|
|
70
72
|
}
|
|
71
73
|
/>
|
|
@@ -101,6 +103,7 @@ interface IPageBrowserDispatchProps {
|
|
|
101
103
|
isReadOnly: boolean;
|
|
102
104
|
theme: string;
|
|
103
105
|
browserRef: any;
|
|
106
|
+
isEditLive: boolean;
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -55,9 +55,10 @@ const GlobalEditor = (props: IProps) => {
|
|
|
55
55
|
|
|
56
56
|
const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
|
|
57
57
|
const isDraft = props.pageStatus === pageStatus.MODIFIED;
|
|
58
|
-
const hasDraft = editorContent && editorContent.haveDraftPage;
|
|
58
|
+
const hasDraft: boolean = editorContent && !!editorContent.haveDraftPage;
|
|
59
59
|
const isLivePageChanged = editorContent && editorContent.liveChanged;
|
|
60
60
|
const structuredData = editorContent ? editorContent.structuredData : "";
|
|
61
|
+
const isEditLive: boolean = isPublished && hasDraft;
|
|
61
62
|
|
|
62
63
|
const errorNotificationText =
|
|
63
64
|
"There are some errors on the page so you can not publish yet. Please review them in the error panel.";
|
|
@@ -173,12 +174,6 @@ const GlobalEditor = (props: IProps) => {
|
|
|
173
174
|
updatePageStatus([pageID], pageStatus.OFFLINE_PENDING);
|
|
174
175
|
};
|
|
175
176
|
|
|
176
|
-
const cancelPublishPage = () => {
|
|
177
|
-
const { updatePageStatus, pageID } = props;
|
|
178
|
-
|
|
179
|
-
updatePageStatus([pageID], pageStatus.OFFLINE);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
177
|
const reviewPage = async () => {
|
|
183
178
|
const { validatePage } = props;
|
|
184
179
|
const validated = await validatePage(false);
|
|
@@ -214,6 +209,13 @@ const GlobalEditor = (props: IProps) => {
|
|
|
214
209
|
getPage(pageID, true);
|
|
215
210
|
};
|
|
216
211
|
|
|
212
|
+
const handleCreateDraft = async () => {
|
|
213
|
+
const { savePage } = props;
|
|
214
|
+
|
|
215
|
+
const isSaved = await savePage(true);
|
|
216
|
+
if (isSaved) resetDirty();
|
|
217
|
+
};
|
|
218
|
+
|
|
217
219
|
const getPublishButton = (status: string) => {
|
|
218
220
|
switch (status) {
|
|
219
221
|
case pageStatus.OFFLINE:
|
|
@@ -222,20 +224,16 @@ const GlobalEditor = (props: IProps) => {
|
|
|
222
224
|
label: "Publish",
|
|
223
225
|
action: publishPage,
|
|
224
226
|
};
|
|
225
|
-
case pageStatus.UPLOAD_PENDING:
|
|
226
|
-
return {
|
|
227
|
-
label: "Cancel Publication",
|
|
228
|
-
action: cancelPublishPage,
|
|
229
|
-
};
|
|
230
227
|
case pageStatus.PUBLISHED:
|
|
231
|
-
|
|
228
|
+
case pageStatus.UPLOAD_PENDING:
|
|
229
|
+
return !hasDraft && isDirty
|
|
232
230
|
? {
|
|
233
|
-
label: "
|
|
234
|
-
action:
|
|
231
|
+
label: "Create new draft",
|
|
232
|
+
action: handleCreateDraft,
|
|
235
233
|
}
|
|
236
234
|
: {
|
|
237
235
|
label: "Unpublish",
|
|
238
|
-
action: unpublishPage,
|
|
236
|
+
action: hasDraft ? toggleUnpublishModal : unpublishPage,
|
|
239
237
|
};
|
|
240
238
|
case pageStatus.MODIFIED:
|
|
241
239
|
return {
|
|
@@ -259,7 +257,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
259
257
|
};
|
|
260
258
|
|
|
261
259
|
const unpublishOption =
|
|
262
|
-
props.pageStatus === pageStatus.PUBLISHED && !hasDraft
|
|
260
|
+
props.pageStatus === pageStatus.PUBLISHED && !hasDraft && isDirty
|
|
263
261
|
? {
|
|
264
262
|
label: "Unpublish",
|
|
265
263
|
icon: "offline",
|
|
@@ -276,6 +274,14 @@ const GlobalEditor = (props: IProps) => {
|
|
|
276
274
|
}
|
|
277
275
|
: undefined;
|
|
278
276
|
|
|
277
|
+
const deleteOption = !isDraft
|
|
278
|
+
? {
|
|
279
|
+
label: "Delete",
|
|
280
|
+
icon: "delete",
|
|
281
|
+
action: removePage,
|
|
282
|
+
}
|
|
283
|
+
: undefined;
|
|
284
|
+
|
|
279
285
|
const downArrowMenu = {
|
|
280
286
|
displayed: !isReadOnly,
|
|
281
287
|
button: getPublishButton(props.pageStatus),
|
|
@@ -287,11 +293,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
287
293
|
},
|
|
288
294
|
unpublishOption,
|
|
289
295
|
discardOption,
|
|
290
|
-
|
|
291
|
-
label: "Delete",
|
|
292
|
-
icon: "delete",
|
|
293
|
-
action: removePage,
|
|
294
|
-
},
|
|
296
|
+
deleteOption,
|
|
295
297
|
],
|
|
296
298
|
};
|
|
297
299
|
|
|
@@ -300,14 +302,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
300
302
|
const handleSavePage = async () => {
|
|
301
303
|
const { savePage } = props;
|
|
302
304
|
|
|
303
|
-
const
|
|
304
|
-
status: pageStatus.UPLOAD_PENDING,
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
const createDraft = isPublished && !hasDraft;
|
|
308
|
-
const status = props.pageStatus === pageStatus.PUBLISHED && !createDraft ? publishPage : undefined;
|
|
309
|
-
|
|
310
|
-
const isSaved = await savePage(createDraft, status);
|
|
305
|
+
const isSaved = await savePage(false);
|
|
311
306
|
if (isSaved) resetDirty();
|
|
312
307
|
};
|
|
313
308
|
|
|
@@ -331,16 +326,20 @@ const GlobalEditor = (props: IProps) => {
|
|
|
331
326
|
switch (props.pageStatus) {
|
|
332
327
|
case pageStatus.PUBLISHED:
|
|
333
328
|
case pageStatus.UPLOAD_PENDING:
|
|
334
|
-
return !isDirty && !isNewTranslation ? "Saved" : isPublished && hasDraft ? "Save & publish" : "
|
|
329
|
+
return !isDirty && !isNewTranslation ? "Saved" : isPublished && hasDraft ? "Save & publish" : "Publish changes";
|
|
335
330
|
default:
|
|
336
|
-
return !
|
|
331
|
+
return !pageID || isNewTranslation || (isDirty && props.pageStatus !== pageStatus.MODIFIED)
|
|
332
|
+
? "Save"
|
|
333
|
+
: isDirty && props.pageStatus === pageStatus.MODIFIED
|
|
334
|
+
? "Save draft"
|
|
335
|
+
: "Saved";
|
|
337
336
|
}
|
|
338
337
|
};
|
|
339
338
|
|
|
340
339
|
const rightButtonProps = {
|
|
341
340
|
label: isSaving ? "Saving" : getSaveLabel(),
|
|
342
341
|
disabled: (!isDirty && pageID !== null && !isNewTranslation) || isSaving || isReadOnly,
|
|
343
|
-
action: handleSavePage,
|
|
342
|
+
action: isPublished ? publishChanges : handleSavePage,
|
|
344
343
|
};
|
|
345
344
|
|
|
346
345
|
const goToLivePage = () => {
|
|
@@ -361,7 +360,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
361
360
|
props.pageStatus === pageStatus.PUBLISHED || isDraft
|
|
362
361
|
? [
|
|
363
362
|
{
|
|
364
|
-
label: "
|
|
363
|
+
label: "Go to live page",
|
|
365
364
|
icon: "view",
|
|
366
365
|
action: goToLivePage,
|
|
367
366
|
},
|
|
@@ -372,7 +371,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
372
371
|
isDraft || hasDraft
|
|
373
372
|
? [
|
|
374
373
|
{
|
|
375
|
-
label: isDraft ? "
|
|
374
|
+
label: isDraft ? "View live" : "Edit draft",
|
|
376
375
|
icon: isDraft ? "active" : "modified",
|
|
377
376
|
action: toggleDraftPage,
|
|
378
377
|
},
|
|
@@ -477,6 +476,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
477
476
|
theme={theme}
|
|
478
477
|
browserRef={browserRef}
|
|
479
478
|
setNotification={setNotification}
|
|
479
|
+
isEditLive={isEditLive}
|
|
480
480
|
/>
|
|
481
481
|
</S.Content>
|
|
482
482
|
</>
|
|
@@ -42,6 +42,7 @@ const Editor = (props: IProps) => {
|
|
|
42
42
|
setNotification,
|
|
43
43
|
restorePageNavigation,
|
|
44
44
|
content,
|
|
45
|
+
isEditLive,
|
|
45
46
|
} = props;
|
|
46
47
|
|
|
47
48
|
const { header, footer, theme: pageTheme } = content;
|
|
@@ -66,7 +67,11 @@ const Editor = (props: IProps) => {
|
|
|
66
67
|
return (
|
|
67
68
|
<ResizePanel
|
|
68
69
|
leftPanel={
|
|
69
|
-
<PageBrowser
|
|
70
|
+
<PageBrowser
|
|
71
|
+
isTemplateActivated={isTemplateActivated}
|
|
72
|
+
isReadOnly={isReadOnly || isEditLive}
|
|
73
|
+
browserRef={browserRef}
|
|
74
|
+
/>
|
|
70
75
|
}
|
|
71
76
|
rightPanel={
|
|
72
77
|
<ConfigPanel
|
|
@@ -90,6 +95,7 @@ const Editor = (props: IProps) => {
|
|
|
90
95
|
lastElementAddedId={lastElementAddedId}
|
|
91
96
|
header={header}
|
|
92
97
|
footer={footer}
|
|
98
|
+
isEditLive={isEditLive}
|
|
93
99
|
/>
|
|
94
100
|
}
|
|
95
101
|
/>
|
|
@@ -133,6 +139,7 @@ interface IPageBrowserDispatchProps {
|
|
|
133
139
|
pageTitle: string;
|
|
134
140
|
isReadOnly: boolean;
|
|
135
141
|
browserRef: any;
|
|
142
|
+
isEditLive: boolean;
|
|
136
143
|
}
|
|
137
144
|
|
|
138
145
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -66,6 +66,7 @@ const PageEditor = (props: IProps) => {
|
|
|
66
66
|
const isLivePageChanged = editorContent && editorContent.liveChanged;
|
|
67
67
|
const isTranslated = pageLanguages.length > 1;
|
|
68
68
|
const structuredData = editorContent ? editorContent.structuredData : "";
|
|
69
|
+
const isEditLive = isPublished && hasDraft;
|
|
69
70
|
|
|
70
71
|
const errorNotificationText =
|
|
71
72
|
"There are some errors on the page so you can not publish yet. Please review them in the error panel.";
|
|
@@ -189,12 +190,6 @@ const PageEditor = (props: IProps) => {
|
|
|
189
190
|
updatePageStatus([pageID], pageStatus.OFFLINE_PENDING);
|
|
190
191
|
};
|
|
191
192
|
|
|
192
|
-
const cancelPublishPage = () => {
|
|
193
|
-
const { updatePageStatus, pageID } = props;
|
|
194
|
-
|
|
195
|
-
updatePageStatus([pageID], pageStatus.OFFLINE);
|
|
196
|
-
};
|
|
197
|
-
|
|
198
193
|
const reviewPage = async () => {
|
|
199
194
|
const { validatePage } = props;
|
|
200
195
|
const validated = await validatePage(false);
|
|
@@ -231,6 +226,13 @@ const PageEditor = (props: IProps) => {
|
|
|
231
226
|
getPage(pageID);
|
|
232
227
|
};
|
|
233
228
|
|
|
229
|
+
const handleCreateDraft = async () => {
|
|
230
|
+
const { savePage } = props;
|
|
231
|
+
|
|
232
|
+
const isSaved = await savePage(true);
|
|
233
|
+
if (isSaved) resetDirty();
|
|
234
|
+
};
|
|
235
|
+
|
|
234
236
|
const getPublishButton = (status: string) => {
|
|
235
237
|
switch (status) {
|
|
236
238
|
case pageStatus.OFFLINE:
|
|
@@ -239,20 +241,16 @@ const PageEditor = (props: IProps) => {
|
|
|
239
241
|
label: "Publish",
|
|
240
242
|
action: publishPage,
|
|
241
243
|
};
|
|
242
|
-
case pageStatus.UPLOAD_PENDING:
|
|
243
|
-
return {
|
|
244
|
-
label: "Cancel Publication",
|
|
245
|
-
action: cancelPublishPage,
|
|
246
|
-
};
|
|
247
244
|
case pageStatus.PUBLISHED:
|
|
248
|
-
|
|
245
|
+
case pageStatus.UPLOAD_PENDING:
|
|
246
|
+
return !isGlobal && !hasDraft && isDirty
|
|
249
247
|
? {
|
|
250
|
-
label: "
|
|
251
|
-
action:
|
|
248
|
+
label: "Create new draft",
|
|
249
|
+
action: handleCreateDraft,
|
|
252
250
|
}
|
|
253
251
|
: {
|
|
254
252
|
label: "Unpublish",
|
|
255
|
-
action: unpublishPage,
|
|
253
|
+
action: hasDraft ? toggleUnpublishModal : unpublishPage,
|
|
256
254
|
};
|
|
257
255
|
case pageStatus.MODIFIED:
|
|
258
256
|
return {
|
|
@@ -276,7 +274,7 @@ const PageEditor = (props: IProps) => {
|
|
|
276
274
|
};
|
|
277
275
|
|
|
278
276
|
const unpublishOption =
|
|
279
|
-
props.pageStatus === pageStatus.PUBLISHED && !hasDraft
|
|
277
|
+
props.pageStatus === pageStatus.PUBLISHED && !hasDraft && isDirty
|
|
280
278
|
? {
|
|
281
279
|
label: "Unpublish",
|
|
282
280
|
icon: "offline",
|
|
@@ -293,6 +291,14 @@ const PageEditor = (props: IProps) => {
|
|
|
293
291
|
}
|
|
294
292
|
: undefined;
|
|
295
293
|
|
|
294
|
+
const deleteOption = !isDraft
|
|
295
|
+
? {
|
|
296
|
+
label: "Delete",
|
|
297
|
+
icon: "delete",
|
|
298
|
+
action: toggleDeleteModal,
|
|
299
|
+
}
|
|
300
|
+
: undefined;
|
|
301
|
+
|
|
296
302
|
const menuOptions = !isGlobal
|
|
297
303
|
? [
|
|
298
304
|
{
|
|
@@ -302,11 +308,7 @@ const PageEditor = (props: IProps) => {
|
|
|
302
308
|
},
|
|
303
309
|
unpublishOption,
|
|
304
310
|
discardOption,
|
|
305
|
-
|
|
306
|
-
label: "Delete",
|
|
307
|
-
icon: "delete",
|
|
308
|
-
action: toggleDeleteModal,
|
|
309
|
-
},
|
|
311
|
+
deleteOption,
|
|
310
312
|
]
|
|
311
313
|
: [];
|
|
312
314
|
|
|
@@ -319,14 +321,7 @@ const PageEditor = (props: IProps) => {
|
|
|
319
321
|
const handleSavePage = async () => {
|
|
320
322
|
const { savePage } = props;
|
|
321
323
|
|
|
322
|
-
const
|
|
323
|
-
status: pageStatus.UPLOAD_PENDING,
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
const createDraft = isPublished && !hasDraft && !isGlobal;
|
|
327
|
-
const status = props.pageStatus === pageStatus.PUBLISHED && !createDraft ? publishPage : undefined;
|
|
328
|
-
|
|
329
|
-
const isSaved = await savePage(createDraft, status);
|
|
324
|
+
const isSaved = await savePage(false);
|
|
330
325
|
if (isSaved) resetDirty();
|
|
331
326
|
};
|
|
332
327
|
|
|
@@ -381,9 +376,13 @@ const PageEditor = (props: IProps) => {
|
|
|
381
376
|
? "Saved"
|
|
382
377
|
: isGlobal || (isPublished && hasDraft)
|
|
383
378
|
? "Save & publish"
|
|
384
|
-
: "
|
|
379
|
+
: "Publish changes";
|
|
385
380
|
default:
|
|
386
|
-
return !pageID || isNewTranslation
|
|
381
|
+
return !pageID || isNewTranslation || (isDirty && props.pageStatus !== pageStatus.MODIFIED)
|
|
382
|
+
? "Save"
|
|
383
|
+
: isDirty && props.pageStatus === pageStatus.MODIFIED
|
|
384
|
+
? "Save draft"
|
|
385
|
+
: "Saved";
|
|
387
386
|
}
|
|
388
387
|
};
|
|
389
388
|
|
|
@@ -394,7 +393,7 @@ const PageEditor = (props: IProps) => {
|
|
|
394
393
|
isSaving ||
|
|
395
394
|
isReadOnly ||
|
|
396
395
|
(!isTemplateActivated && !isGlobal),
|
|
397
|
-
action: handleSavePage,
|
|
396
|
+
action: isPublished ? publishChanges : handleSavePage,
|
|
398
397
|
};
|
|
399
398
|
|
|
400
399
|
const goToLivePage = () => {
|
|
@@ -415,7 +414,7 @@ const PageEditor = (props: IProps) => {
|
|
|
415
414
|
props.pageStatus === pageStatus.PUBLISHED || isDraft
|
|
416
415
|
? [
|
|
417
416
|
{
|
|
418
|
-
label: "
|
|
417
|
+
label: "Go to live page",
|
|
419
418
|
icon: "view",
|
|
420
419
|
action: goToLivePage,
|
|
421
420
|
},
|
|
@@ -426,7 +425,7 @@ const PageEditor = (props: IProps) => {
|
|
|
426
425
|
isDraft || hasDraft
|
|
427
426
|
? [
|
|
428
427
|
{
|
|
429
|
-
label: isDraft ? "
|
|
428
|
+
label: isDraft ? "View live" : "Edit draft",
|
|
430
429
|
icon: isDraft ? "active" : "modified",
|
|
431
430
|
action: toggleDraftPage,
|
|
432
431
|
},
|
|
@@ -543,6 +542,7 @@ const PageEditor = (props: IProps) => {
|
|
|
543
542
|
isReadOnly={isReadOnly}
|
|
544
543
|
browserRef={browserRef}
|
|
545
544
|
setNotification={setNotification}
|
|
545
|
+
isEditLive={isEditLive}
|
|
546
546
|
/>
|
|
547
547
|
</S.Content>
|
|
548
548
|
</>
|
|
@@ -225,7 +225,7 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
225
225
|
const viewPage = () => window.open(globalPage.fullUrl || `${API_URL}/page/go/${globalPage.id}`, "_blank");
|
|
226
226
|
|
|
227
227
|
const viewOption = {
|
|
228
|
-
label: "View
|
|
228
|
+
label: "View online",
|
|
229
229
|
icon: "View",
|
|
230
230
|
action: viewPage,
|
|
231
231
|
};
|
|
@@ -238,7 +238,7 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
238
238
|
color: true,
|
|
239
239
|
},
|
|
240
240
|
{
|
|
241
|
-
label: "
|
|
241
|
+
label: "View live",
|
|
242
242
|
icon: "active",
|
|
243
243
|
action: handleEditLivePage,
|
|
244
244
|
color: true,
|