@griddo/ax 1.60.9 → 1.61.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/package.json +4 -2
- package/public/fonts/fonts.css +48 -660
- package/public/index.html +19 -16
- package/public/templates/template-redirects.csv +2 -0
- package/src/GlobalStore.tsx +3 -0
- package/src/Style/fonts.tsx +98 -72
- package/src/api/analytics.tsx +78 -0
- package/src/api/index.tsx +2 -0
- package/src/api/redirects.tsx +30 -2
- package/src/components/Button/style.tsx +1 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +1 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx +4 -3
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +6 -1
- package/src/components/FieldContainer/index.tsx +2 -2
- package/src/components/Fields/AnalyticsField/PageAnalytics/atoms.tsx +75 -0
- package/src/components/Fields/AnalyticsField/PageAnalytics/index.tsx +139 -0
- package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/atoms.tsx +77 -0
- package/src/components/Fields/AnalyticsField/StructuredDataAnalytics/index.tsx +89 -0
- package/src/components/Fields/AnalyticsField/index.tsx +38 -0
- package/src/components/Fields/AnalyticsField/style.tsx +13 -0
- package/src/components/Fields/AnalyticsField/utils.tsx +13 -0
- package/src/components/Fields/FieldGroup/style.tsx +1 -1
- package/src/components/Fields/ImageField/index.tsx +1 -1
- package/src/components/Fields/MultiCheckSelect/index.tsx +23 -6
- package/src/components/Fields/MultiCheckSelect/style.tsx +1 -0
- package/src/components/Fields/NoteField/index.tsx +1 -1
- package/src/components/Fields/RadioGroup/index.tsx +4 -3
- package/src/components/Fields/RadioGroup/style.tsx +8 -3
- package/src/components/Fields/RichText/index.tsx +13 -8
- package/src/components/Fields/TextArea/index.tsx +1 -3
- package/src/components/Fields/TextArea/style.tsx +3 -3
- package/src/components/Fields/UrlField/style.tsx +1 -0
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/Modal/index.tsx +1 -1
- package/src/components/Modal/style.tsx +5 -1
- package/src/components/Notification/style.tsx +2 -5
- package/src/components/TableFilters/LiveFilter/index.tsx +4 -0
- package/src/components/TableFilters/NameFilter/style.tsx +1 -0
- package/src/components/TableFilters/TypeFilter/index.tsx +7 -2
- package/src/containers/Analytics/actions.tsx +58 -0
- package/src/containers/Analytics/constants.tsx +5 -0
- package/src/containers/Analytics/index.tsx +4 -0
- package/src/containers/Analytics/interfaces.tsx +9 -0
- package/src/containers/Analytics/reducer.tsx +26 -0
- package/src/containers/PageEditor/actions.tsx +1 -0
- package/src/containers/Redirects/actions.tsx +49 -3
- package/src/containers/Redirects/constants.tsx +12 -1
- package/src/containers/Redirects/interfaces.tsx +11 -1
- package/src/containers/Redirects/reducer.tsx +12 -1
- package/src/containers/Sites/actions.tsx +3 -0
- package/src/global.d.ts +2 -0
- package/src/helpers/index.tsx +4 -0
- package/src/helpers/requests.tsx +12 -7
- package/src/helpers/strings.tsx +13 -0
- package/src/hooks/forms.tsx +1 -1
- package/src/modules/Analytics/DimensionItem/index.tsx +71 -0
- package/src/modules/Analytics/DimensionItem/style.tsx +59 -0
- package/src/modules/Analytics/DimensionPanel/index.tsx +110 -0
- package/src/modules/Analytics/DimensionPanel/style.tsx +14 -0
- package/src/modules/Analytics/GroupItem/index.tsx +75 -0
- package/src/modules/Analytics/GroupItem/style.tsx +80 -0
- package/src/modules/Analytics/GroupPanel/index.tsx +178 -0
- package/src/modules/Analytics/GroupPanel/style.tsx +67 -0
- package/src/modules/Analytics/GroupPanel/utils.tsx +29 -0
- package/src/modules/Analytics/index.tsx +207 -0
- package/src/modules/Analytics/style.tsx +68 -0
- package/src/modules/Content/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/modules/Content/PageItem/index.tsx +3 -3
- package/src/modules/Content/PageItem/style.tsx +1 -1
- package/src/modules/Content/hooks.tsx +2 -2
- package/src/modules/Content/index.tsx +22 -20
- package/src/modules/GlobalEditor/index.tsx +1 -1
- package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +2 -2
- package/src/modules/PageEditor/index.tsx +1 -1
- package/src/modules/Redirects/RedirectItem/index.tsx +6 -2
- package/src/modules/Redirects/RedirectPanel/index.tsx +2 -0
- package/src/modules/Redirects/atoms.tsx +212 -0
- package/src/modules/Redirects/index.tsx +85 -27
- package/src/modules/Redirects/style.tsx +124 -3
- package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +1 -1
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +12 -3
- package/src/modules/StructuredData/StructuredDataList/index.tsx +17 -2
- package/src/routes/multisite.tsx +20 -2
- package/src/schemas/pages/GlobalPage.tsx +75 -64
- package/src/schemas/pages/Page.tsx +79 -67
- package/src/types/index.tsx +25 -3
- package/public/fonts/Source_Sans_Pro-200-cyrillic-ext107.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-cyrillic-ext149.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-cyrillic108.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-cyrillic150.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-greek-ext109.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-greek-ext151.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-greek110.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-greek152.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-vietnamese111.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-200-vietnamese153.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-cyrillic-ext114.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-cyrillic-ext156.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-cyrillic115.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-cyrillic157.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-greek-ext116.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-greek-ext158.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-greek117.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-greek159.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-vietnamese118.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-300-vietnamese160.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-cyrillic-ext121.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-cyrillic-ext163.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-cyrillic122.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-cyrillic164.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-greek-ext123.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-greek-ext165.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-greek124.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-greek166.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-vietnamese125.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-400-vietnamese167.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-cyrillic-ext128.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-cyrillic-ext170.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-cyrillic129.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-cyrillic171.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-greek-ext130.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-greek-ext172.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-greek131.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-greek173.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-vietnamese132.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-600-vietnamese174.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-cyrillic-ext135.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-cyrillic-ext177.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-cyrillic136.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-cyrillic178.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-greek-ext137.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-greek-ext179.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-greek138.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-greek180.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-vietnamese139.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-700-vietnamese181.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-cyrillic-ext142.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-cyrillic-ext184.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-cyrillic143.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-cyrillic185.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-greek-ext144.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-greek-ext186.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-greek145.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-greek187.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-vietnamese146.woff2 +0 -0
- package/public/fonts/Source_Sans_Pro-900-vietnamese188.woff2 +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { IDimension, IDimensionsGroup } from "@ax/types";
|
|
2
|
+
import { AxiosResponse } from "axios";
|
|
3
|
+
import { template } from "./config";
|
|
4
|
+
import { IServiceConfig, sendRequest } from "./utils";
|
|
5
|
+
|
|
6
|
+
const SERVICES: { [key: string]: IServiceConfig } = {
|
|
7
|
+
GET_ANALYTICS: {
|
|
8
|
+
...template,
|
|
9
|
+
endpoint: ["/site/", "/analytics"],
|
|
10
|
+
method: "GET",
|
|
11
|
+
},
|
|
12
|
+
UPDATE_SCRIPT_CODE: {
|
|
13
|
+
...template,
|
|
14
|
+
endpoint: ["/site/", "/analytics/script"],
|
|
15
|
+
method: "PUT",
|
|
16
|
+
},
|
|
17
|
+
CREATE_DIMENSIONS: {
|
|
18
|
+
...template,
|
|
19
|
+
endpoint: ["/analytics/dimensions/site/", "/bulk"],
|
|
20
|
+
method: "POST",
|
|
21
|
+
},
|
|
22
|
+
CREATE_DIMENSIONS_GROUPS: {
|
|
23
|
+
...template,
|
|
24
|
+
endpoint: ["/analytics/groups/site/", "/bulk"],
|
|
25
|
+
method: "POST",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const getAnalytics = async (siteId: number | string): Promise<AxiosResponse> => {
|
|
30
|
+
const {
|
|
31
|
+
host,
|
|
32
|
+
endpoint: [prefix, suffix],
|
|
33
|
+
} = SERVICES.GET_ANALYTICS;
|
|
34
|
+
|
|
35
|
+
SERVICES.GET_ANALYTICS.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
|
|
36
|
+
|
|
37
|
+
return sendRequest(SERVICES.GET_ANALYTICS);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const updateScriptCode = async (siteId: number | string, data: { scriptCode: string }): Promise<AxiosResponse> => {
|
|
41
|
+
const {
|
|
42
|
+
host,
|
|
43
|
+
endpoint: [prefix, suffix],
|
|
44
|
+
} = SERVICES.UPDATE_SCRIPT_CODE;
|
|
45
|
+
|
|
46
|
+
SERVICES.UPDATE_SCRIPT_CODE.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
|
|
47
|
+
|
|
48
|
+
return sendRequest(SERVICES.UPDATE_SCRIPT_CODE, { ...data });
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const createDimensions = async (siteId: number | string, data: { dimensions: IDimension[] }): Promise<AxiosResponse> => {
|
|
52
|
+
const {
|
|
53
|
+
host,
|
|
54
|
+
endpoint: [prefix, suffix],
|
|
55
|
+
} = SERVICES.CREATE_DIMENSIONS;
|
|
56
|
+
|
|
57
|
+
SERVICES.CREATE_DIMENSIONS.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
|
|
58
|
+
|
|
59
|
+
return sendRequest(SERVICES.CREATE_DIMENSIONS, { ...data });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const createDimensionsGroups = async (siteId: number | string, data: { groups: IDimensionsGroup[] }): Promise<AxiosResponse> => {
|
|
63
|
+
const {
|
|
64
|
+
host,
|
|
65
|
+
endpoint: [prefix, suffix],
|
|
66
|
+
} = SERVICES.CREATE_DIMENSIONS_GROUPS;
|
|
67
|
+
|
|
68
|
+
SERVICES.CREATE_DIMENSIONS_GROUPS.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
|
|
69
|
+
|
|
70
|
+
return sendRequest(SERVICES.CREATE_DIMENSIONS_GROUPS, { ...data });
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default {
|
|
74
|
+
getAnalytics,
|
|
75
|
+
updateScriptCode,
|
|
76
|
+
createDimensions,
|
|
77
|
+
createDimensionsGroups
|
|
78
|
+
};
|
package/src/api/index.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import files from "./files";
|
|
|
15
15
|
import users from "./users";
|
|
16
16
|
import domains from "./domains";
|
|
17
17
|
import redirects from "./redirects";
|
|
18
|
+
import analytics from "./analytics";
|
|
18
19
|
|
|
19
20
|
export {
|
|
20
21
|
sites,
|
|
@@ -34,4 +35,5 @@ export {
|
|
|
34
35
|
users,
|
|
35
36
|
domains,
|
|
36
37
|
redirects,
|
|
38
|
+
analytics
|
|
37
39
|
};
|
package/src/api/redirects.tsx
CHANGED
|
@@ -27,6 +27,16 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
27
27
|
endpoint: "/redirects/bulk",
|
|
28
28
|
method: "DELETE",
|
|
29
29
|
},
|
|
30
|
+
CREATE_REDIRECT_BULK_CHECK: {
|
|
31
|
+
...template,
|
|
32
|
+
endpoint: "/redirect/bulk/check",
|
|
33
|
+
method: "POST",
|
|
34
|
+
},
|
|
35
|
+
CREATE_REDIRECT_BULK: {
|
|
36
|
+
...template,
|
|
37
|
+
endpoint: "/redirect/bulk",
|
|
38
|
+
method: "POST",
|
|
39
|
+
},
|
|
30
40
|
};
|
|
31
41
|
|
|
32
42
|
const getRedirects = async (params: any, filters?: string) => {
|
|
@@ -34,7 +44,9 @@ const getRedirects = async (params: any, filters?: string) => {
|
|
|
34
44
|
|
|
35
45
|
const { host, endpoint } = SERVICES.GET_REDIRECTS;
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
const filterString = filters || "";
|
|
48
|
+
|
|
49
|
+
SERVICES.GET_REDIRECTS.dynamicUrl = `${host}${endpoint}?page=${page}&itemsPerPage=${itemsPerPage}&pagination=${pagination}${filterString}`;
|
|
38
50
|
|
|
39
51
|
return sendRequest(SERVICES.GET_REDIRECTS);
|
|
40
52
|
};
|
|
@@ -68,4 +80,20 @@ const deleteRedirectsBulk = async (ids: number[]) => {
|
|
|
68
80
|
return sendRequest(SERVICES.DELETE_REDIRECT_BULK, { ids });
|
|
69
81
|
};
|
|
70
82
|
|
|
71
|
-
|
|
83
|
+
const createRedirectsBulkCheck = async (redirects: any[]) => {
|
|
84
|
+
return sendRequest(SERVICES.CREATE_REDIRECT_BULK_CHECK, { redirects });
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const createRedirectsBulk = async (redirects: any[]) => {
|
|
88
|
+
return sendRequest(SERVICES.CREATE_REDIRECT_BULK, { redirects });
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default {
|
|
92
|
+
getRedirects,
|
|
93
|
+
createRedirect,
|
|
94
|
+
updateRedirect,
|
|
95
|
+
deleteRedirect,
|
|
96
|
+
deleteRedirectsBulk,
|
|
97
|
+
createRedirectsBulk,
|
|
98
|
+
createRedirectsBulkCheck,
|
|
99
|
+
};
|
|
@@ -4,6 +4,7 @@ export const Button = styled.button`
|
|
|
4
4
|
${(p) => p.theme.textStyle.uiButton};
|
|
5
5
|
background-color: ${(p) => p.theme.color.interactive01};
|
|
6
6
|
border-radius: 4px;
|
|
7
|
+
z-index: 0;
|
|
7
8
|
border: none;
|
|
8
9
|
color: ${p => p.theme.colors.uiBackground02};
|
|
9
10
|
min-height: calc(${(p) => p.theme.spacing.s} * 2);
|
|
@@ -77,7 +77,7 @@ interface IProps {
|
|
|
77
77
|
readonly?: boolean;
|
|
78
78
|
activatedModules?: string[];
|
|
79
79
|
isTemplateActivated: boolean;
|
|
80
|
-
updateValue: any;
|
|
80
|
+
updateValue: (key: string, value: any, templateID?: number, slugTo?: string) => void;
|
|
81
81
|
categories?: any;
|
|
82
82
|
error?: IErrorItem;
|
|
83
83
|
deleteError(error: IErrorItem): void;
|
package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/TemplateManager/index.tsx
CHANGED
|
@@ -32,12 +32,13 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
32
32
|
const modulesDataPacks = activatedPacks.map((pack: IDataPack) => pack.modules).flat();
|
|
33
33
|
|
|
34
34
|
const getFieldProps = (field: any) => {
|
|
35
|
-
const { key, type, whiteList = [] } = field;
|
|
35
|
+
const { key, type, whiteList = [], slugTo } = field;
|
|
36
36
|
const isArr = type === "ComponentArray";
|
|
37
37
|
const currentContent = isArr ? templateContent[key] : templateContent;
|
|
38
38
|
const fieldObjKey = !isArr ? `${key}` : `modules`;
|
|
39
39
|
const mappedField = !isArr ? { ...field, key: fieldObjKey } : field;
|
|
40
|
-
const handleUpdate = (fieldKey: string, value: any) =>
|
|
40
|
+
const handleUpdate = (fieldKey: string, value: any) =>
|
|
41
|
+
updateValue(fieldKey, value, templateContent.editorID, slugTo);
|
|
41
42
|
const error = errors.find((err: any) => err.editorID === templateContent.editorID && err.key === key);
|
|
42
43
|
|
|
43
44
|
const addedModules = modulesDataPacks
|
|
@@ -98,7 +99,7 @@ export const TemplateManager = (props: IProps): JSX.Element => {
|
|
|
98
99
|
|
|
99
100
|
interface IProps {
|
|
100
101
|
template: any;
|
|
101
|
-
updateValue: (key: string, value: any, templateID?: number) => void;
|
|
102
|
+
updateValue: (key: string, value: any, templateID?: number, slugTo?: string) => void;
|
|
102
103
|
goTo: any;
|
|
103
104
|
objKey: string;
|
|
104
105
|
pages: any;
|
|
@@ -84,7 +84,7 @@ const PageConnectedField = (props: any) => {
|
|
|
84
84
|
// eslint-disable-next-line
|
|
85
85
|
}, [isPageHome]);
|
|
86
86
|
|
|
87
|
-
let updateValue = (key: string, value: any, templateID?: number) => {
|
|
87
|
+
let updateValue = (key: string, value: any, templateID?: number, slugTo?: string) => {
|
|
88
88
|
if (key === "parent") {
|
|
89
89
|
getPageBreadcrumb(value);
|
|
90
90
|
}
|
|
@@ -95,6 +95,11 @@ const PageConnectedField = (props: any) => {
|
|
|
95
95
|
updateEditorContent(selectedEditorID, "isHome", value);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
if (slugTo) {
|
|
99
|
+
const slugValue = typeof value === "object" && value.content ? value.content : value;
|
|
100
|
+
updateEditorContent(selectedEditorID, slugTo, slugify(slugValue));
|
|
101
|
+
}
|
|
102
|
+
|
|
98
103
|
const editorID = templateID ? templateID : selectedEditorID;
|
|
99
104
|
|
|
100
105
|
updateEditorContent(editorID, key, value);
|
|
@@ -8,7 +8,7 @@ import { FieldsBehavior, HiddenField } from "@ax/components";
|
|
|
8
8
|
const FieldContainer = (props: IProps) => {
|
|
9
9
|
const { selectedContent, updateValue, field, goTo, objKey, lang } = props;
|
|
10
10
|
|
|
11
|
-
const { type, key, title, hideable } = field;
|
|
11
|
+
const { type, key, title, hideable, slugTo } = field;
|
|
12
12
|
const isContainer = field.type === "ComponentContainer";
|
|
13
13
|
|
|
14
14
|
const hideField = () => updateValue(key, nullValue);
|
|
@@ -19,7 +19,7 @@ const FieldContainer = (props: IProps) => {
|
|
|
19
19
|
fieldType: type,
|
|
20
20
|
value: containerValue,
|
|
21
21
|
hideField,
|
|
22
|
-
onChange: (e: any) => updateValue(key, e),
|
|
22
|
+
onChange: (e: any) => updateValue(key, e, undefined, slugTo),
|
|
23
23
|
goTo,
|
|
24
24
|
editorID: selectedContent.editorID,
|
|
25
25
|
lang,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldsBehavior } from "@ax/components";
|
|
4
|
+
import { splitAndTrim } from "@ax/helpers";
|
|
5
|
+
import { IAnalytics, IDimension } from "@ax/types";
|
|
6
|
+
|
|
7
|
+
import { IState } from "..";
|
|
8
|
+
import * as S from "../style";
|
|
9
|
+
|
|
10
|
+
const DimensionsGroup = (props: { analytics: IAnalytics, state: IState, setDimension: (value: Record<string, string>) => void }): JSX.Element => {
|
|
11
|
+
const { analytics, state, setDimension } = props;
|
|
12
|
+
const { groupSelect, values } = state;
|
|
13
|
+
const selectedGroup = analytics.groups.find((g) => g.name === groupSelect);
|
|
14
|
+
const dimensionNames = splitAndTrim(selectedGroup?.dimensions, ";");
|
|
15
|
+
const groupDimensions = dimensionNames.map((dimensionName) => {
|
|
16
|
+
const dimension = analytics.dimensions.find((dimension) => dimension.name === dimensionName);
|
|
17
|
+
return dimension;
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<S.FieldsDivider />
|
|
23
|
+
{groupDimensions && groupDimensions.map((dimension, idx) => (
|
|
24
|
+
dimension && <DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
25
|
+
))}
|
|
26
|
+
</>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const DimensionsSelection = (props: { analytics: IAnalytics, state: IState, setDimension: (value: Record<string, string>) => void }): JSX.Element => {
|
|
31
|
+
const { analytics, state, setDimension } = props;
|
|
32
|
+
const { dimensionsSelect, values } = state;
|
|
33
|
+
const selectedDimensions = analytics.dimensions.filter((d) => dimensionsSelect.includes(d.name));
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{selectedDimensions.length ? <S.FieldsDivider /> : <></>}
|
|
38
|
+
{selectedDimensions && selectedDimensions.map((dimension, idx) => (
|
|
39
|
+
<DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
40
|
+
))}
|
|
41
|
+
</>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const DimensionValue = (props: { dimension: IDimension, setDimension: (value: Record<string, string>) => void, values: Record<string, string> }) => {
|
|
46
|
+
const { dimension, setDimension, values } = props;
|
|
47
|
+
const dimensionValues = splitAndTrim(dimension?.values, ";");
|
|
48
|
+
const options = dimensionValues.map((option) => ({ label: option, value: option }));
|
|
49
|
+
const handleOnChange = (value: string) => {
|
|
50
|
+
dimension && setDimension({ [dimension.name]: value });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isNullValue = dimensionValues.includes("null");
|
|
54
|
+
|
|
55
|
+
return isNullValue ? (
|
|
56
|
+
<FieldsBehavior
|
|
57
|
+
title={dimension?.name}
|
|
58
|
+
fieldType="TextField"
|
|
59
|
+
value={dimension ? values[dimension.name] : ""}
|
|
60
|
+
onChange={handleOnChange}
|
|
61
|
+
placeholder="Type a variable"
|
|
62
|
+
/>
|
|
63
|
+
) : (
|
|
64
|
+
<FieldsBehavior
|
|
65
|
+
title={dimension?.name}
|
|
66
|
+
fieldType="Select"
|
|
67
|
+
options={options}
|
|
68
|
+
value={dimension ? values[dimension.name] : ""}
|
|
69
|
+
onChange={handleOnChange}
|
|
70
|
+
placeholder="Select variable"
|
|
71
|
+
/>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { DimensionsGroup, DimensionsSelection };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { NoteField, FieldsBehavior, FieldGroup } from "@ax/components";
|
|
4
|
+
|
|
5
|
+
import { IAnalyticsFieldProps, IState } from "..";
|
|
6
|
+
import { DimensionsGroup, DimensionsSelection } from "./atoms";
|
|
7
|
+
import * as S from "../style";
|
|
8
|
+
|
|
9
|
+
const PageAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
10
|
+
const {
|
|
11
|
+
value,
|
|
12
|
+
onChange,
|
|
13
|
+
analytics,
|
|
14
|
+
} = props;
|
|
15
|
+
|
|
16
|
+
const initialState = {
|
|
17
|
+
contentSelect: "",
|
|
18
|
+
groupSelect: "",
|
|
19
|
+
dimensionsSelect: [],
|
|
20
|
+
values: {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const [state, setState] = useState<IState>(value || initialState);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
onChange && onChange(state);
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, [state]);
|
|
29
|
+
|
|
30
|
+
const handleContentSelect = (contentSelect: string) => {
|
|
31
|
+
setState({ ...initialState, contentSelect });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const handleGroupSelect = (groupSelect: string) => {
|
|
35
|
+
setState((state: IState) => ({ ...state, groupSelect, values: {} }));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const handleDimensionsSelect = (selection: string[]) => {
|
|
39
|
+
const values: Record<string, string> = {};
|
|
40
|
+
let dimensionsSelect = selection;
|
|
41
|
+
|
|
42
|
+
if (selection.includes("all")) {
|
|
43
|
+
dimensionsSelect = analytics.dimensions.map((dimension) => dimension.name);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
dimensionsSelect.forEach((dimension) => values[dimension] = state.values[dimension]);
|
|
47
|
+
setState((state: IState) => ({ ...state, dimensionsSelect, values }));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const setDimension = (value: Record<string, string>) => {
|
|
51
|
+
setState((state: IState) => ({ ...state, values: { ...state.values, ...value } }));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const contentOptions = [
|
|
55
|
+
{
|
|
56
|
+
label: "Dimensions Group",
|
|
57
|
+
value: "group"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: "Individual Dimensions",
|
|
61
|
+
value: "individual"
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
const groupOptions: { label: string, value: string }[] = [];
|
|
66
|
+
analytics.groups?.forEach((group) => {
|
|
67
|
+
groupOptions.push({ label: group.name, value: group.name })
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const noteText = (
|
|
71
|
+
<>
|
|
72
|
+
Select <strong>Dimension Group</strong> if you want to select one of the groups you created in the global settings (based on the page content).<br /><br />Select <strong>Individual Dimensions</strong> if you want to select the dimensions to track manually.
|
|
73
|
+
</>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const isGroup = state.contentSelect === "group";
|
|
77
|
+
const isIndividual = state.contentSelect === "individual";
|
|
78
|
+
|
|
79
|
+
const dimensionOptions = [
|
|
80
|
+
{
|
|
81
|
+
name: "all",
|
|
82
|
+
value: "all",
|
|
83
|
+
title: "Select All",
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
analytics.dimensions.forEach((dimension) => {
|
|
87
|
+
const option = {
|
|
88
|
+
name: dimension.name,
|
|
89
|
+
value: dimension.name,
|
|
90
|
+
title: dimension.name,
|
|
91
|
+
}
|
|
92
|
+
dimensionOptions.push(option);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<FieldGroup title="Analytics Data Layer">
|
|
97
|
+
<NoteField value={{ text: noteText }} />
|
|
98
|
+
<S.FieldWrapper>
|
|
99
|
+
<FieldsBehavior
|
|
100
|
+
title="Content Dimension"
|
|
101
|
+
fieldType="Select"
|
|
102
|
+
options={contentOptions}
|
|
103
|
+
value={state.contentSelect}
|
|
104
|
+
onChange={handleContentSelect}
|
|
105
|
+
placeholder="Select Dimensions Options"
|
|
106
|
+
/>
|
|
107
|
+
</S.FieldWrapper>
|
|
108
|
+
{isGroup && (
|
|
109
|
+
<>
|
|
110
|
+
<FieldsBehavior
|
|
111
|
+
title="Select Group"
|
|
112
|
+
fieldType="Select"
|
|
113
|
+
options={groupOptions}
|
|
114
|
+
value={state.groupSelect}
|
|
115
|
+
onChange={handleGroupSelect}
|
|
116
|
+
placeholder="Select Group"
|
|
117
|
+
/>
|
|
118
|
+
{!!state.groupSelect && <DimensionsGroup {...{ analytics, state, setDimension }} />}
|
|
119
|
+
</>
|
|
120
|
+
)}
|
|
121
|
+
{isIndividual && (
|
|
122
|
+
<>
|
|
123
|
+
<FieldsBehavior
|
|
124
|
+
title="Select Dimensions"
|
|
125
|
+
fieldType="MultiCheckSelect"
|
|
126
|
+
options={dimensionOptions}
|
|
127
|
+
value={state.dimensionsSelect}
|
|
128
|
+
onChange={handleDimensionsSelect}
|
|
129
|
+
selectAllOption="all"
|
|
130
|
+
placeholder="Select Dimensions"
|
|
131
|
+
/>
|
|
132
|
+
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension }} />}
|
|
133
|
+
</>
|
|
134
|
+
)}
|
|
135
|
+
</FieldGroup>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export default PageAnalytics;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldsBehavior } from "@ax/components";
|
|
4
|
+
import { splitAndTrim } from "@ax/helpers";
|
|
5
|
+
import { IAnalytics, IDimension } from "@ax/types";
|
|
6
|
+
|
|
7
|
+
import { IState } from "..";
|
|
8
|
+
|
|
9
|
+
const TemplateDimensions = (props: ITemplateDimensions): JSX.Element => {
|
|
10
|
+
const { analytics, state, setDimension, dimensionNames } = props;
|
|
11
|
+
const { values } = state;
|
|
12
|
+
const groupDimensions = dimensionNames.map((dimensionName) => {
|
|
13
|
+
const dimension = analytics.dimensions.find((dimension) => dimension.name === dimensionName);
|
|
14
|
+
return dimension;
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
{groupDimensions && groupDimensions.map((dimension, idx) => (
|
|
20
|
+
dimension && <DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
21
|
+
))}
|
|
22
|
+
</>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const DimensionsSelection = (props: { analytics: IAnalytics, state: IState, setDimension: (value: Record<string, string>) => void }): JSX.Element => {
|
|
27
|
+
const { analytics, state, setDimension } = props;
|
|
28
|
+
const { dimensionsSelect, values } = state;
|
|
29
|
+
const selectedDimensions = analytics.dimensions.filter((d) => dimensionsSelect.includes(d.name));
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
{selectedDimensions && selectedDimensions.map((dimension, idx) => (
|
|
34
|
+
<DimensionValue key={idx} {...{ dimension, setDimension, values }} />
|
|
35
|
+
))}
|
|
36
|
+
</>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const DimensionValue = (props: { dimension: IDimension, setDimension: (value: Record<string, string>) => void, values: Record<string, string> }) => {
|
|
41
|
+
const { dimension, setDimension, values } = props;
|
|
42
|
+
const dimensionValues = splitAndTrim(dimension?.values, ";");
|
|
43
|
+
const options = dimensionValues.map((option) => ({ label: option, value: option }));
|
|
44
|
+
const handleOnChange = (value: string) => {
|
|
45
|
+
dimension && setDimension({ [dimension.name]: value });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const isNullValue = dimensionValues.includes("null");
|
|
49
|
+
|
|
50
|
+
return isNullValue ? (
|
|
51
|
+
<FieldsBehavior
|
|
52
|
+
title={dimension?.name}
|
|
53
|
+
fieldType="TextField"
|
|
54
|
+
value={dimension ? values[dimension.name] : ""}
|
|
55
|
+
onChange={handleOnChange}
|
|
56
|
+
placeholder="Type a variable"
|
|
57
|
+
/>
|
|
58
|
+
) : (
|
|
59
|
+
<FieldsBehavior
|
|
60
|
+
title={dimension?.name}
|
|
61
|
+
fieldType="Select"
|
|
62
|
+
options={options}
|
|
63
|
+
value={dimension ? values[dimension.name] : ""}
|
|
64
|
+
onChange={handleOnChange}
|
|
65
|
+
placeholder="Select variable"
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface ITemplateDimensions {
|
|
71
|
+
analytics: IAnalytics;
|
|
72
|
+
state: IState;
|
|
73
|
+
setDimension: (value: Record<string, string>) => void;
|
|
74
|
+
dimensionNames: string[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { TemplateDimensions, DimensionsSelection };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldsBehavior, FieldGroup } from "@ax/components";
|
|
4
|
+
|
|
5
|
+
import { IAnalyticsFieldProps, IState } from "..";
|
|
6
|
+
import { getTemplateDimensions } from "../utils";
|
|
7
|
+
import { TemplateDimensions, DimensionsSelection } from "./atoms";
|
|
8
|
+
import * as S from "../style";
|
|
9
|
+
|
|
10
|
+
const StructuredDataAnalytics = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
11
|
+
const {
|
|
12
|
+
value,
|
|
13
|
+
onChange,
|
|
14
|
+
analytics,
|
|
15
|
+
template,
|
|
16
|
+
} = props;
|
|
17
|
+
|
|
18
|
+
const initialState = {
|
|
19
|
+
dimensionsSelect: [],
|
|
20
|
+
values: {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const [state, setState] = useState<IState>({ ...initialState, ...value });
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
onChange && onChange(state);
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, [state]);
|
|
29
|
+
|
|
30
|
+
const templateDimensions = getTemplateDimensions(analytics.groups, template);
|
|
31
|
+
|
|
32
|
+
const handleDimensionsSelect = (selection: string[]) => {
|
|
33
|
+
const values: Record<string, string> = {};
|
|
34
|
+
templateDimensions.forEach((dimension) => values[dimension] = state.values[dimension]);
|
|
35
|
+
let dimensionsSelect = selection;
|
|
36
|
+
|
|
37
|
+
if (selection.includes("all")) {
|
|
38
|
+
dimensionsSelect = dimensionOptions.map((dimension) => dimension.name);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
dimensionsSelect.forEach((dimension) => values[dimension] = state.values[dimension]);
|
|
42
|
+
setState((state: IState) => ({ ...state, dimensionsSelect, values }));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const setDimension = (value: Record<string, string>) => {
|
|
46
|
+
setState((state: IState) => ({ ...state, values: { ...state.values, ...value } }));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const dimensionOptions = [
|
|
50
|
+
{
|
|
51
|
+
name: "all",
|
|
52
|
+
value: "all",
|
|
53
|
+
title: "Select All",
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
analytics.dimensions.forEach((dimension) => {
|
|
57
|
+
if (!templateDimensions.includes(dimension.name)) {
|
|
58
|
+
const option = {
|
|
59
|
+
name: dimension.name,
|
|
60
|
+
value: dimension.name,
|
|
61
|
+
title: dimension.name,
|
|
62
|
+
}
|
|
63
|
+
dimensionOptions.push(option);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<FieldGroup title="Analytics Data Layer">
|
|
69
|
+
<TemplateDimensions dimensionNames={templateDimensions} {...{ analytics, state, setDimension }} />
|
|
70
|
+
{dimensionOptions.length > 1 && (
|
|
71
|
+
<>
|
|
72
|
+
<S.FieldsDivider />
|
|
73
|
+
<FieldsBehavior
|
|
74
|
+
title="Add More Dimensions (Optional)"
|
|
75
|
+
fieldType="MultiCheckSelect"
|
|
76
|
+
options={dimensionOptions}
|
|
77
|
+
value={state.dimensionsSelect}
|
|
78
|
+
onChange={handleDimensionsSelect}
|
|
79
|
+
selectAllOption="all"
|
|
80
|
+
placeholder="Select Dimensions"
|
|
81
|
+
/>
|
|
82
|
+
{!!state.dimensionsSelect && <DimensionsSelection {...{ analytics, state, setDimension }} />}
|
|
83
|
+
</>
|
|
84
|
+
)}
|
|
85
|
+
</FieldGroup>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default StructuredDataAnalytics;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import { IAnalytics, IRootState } from "@ax/types";
|
|
5
|
+
import { isEmptyArray } from "@ax/helpers";
|
|
6
|
+
|
|
7
|
+
import PageAnalytics from "./PageAnalytics";
|
|
8
|
+
import StructuredDataAnalytics from "./StructuredDataAnalytics";
|
|
9
|
+
import { getTemplateDimensions } from "./utils";
|
|
10
|
+
|
|
11
|
+
const AnalyticsField = (props: IAnalyticsFieldProps): JSX.Element => {
|
|
12
|
+
const { analytics, template } = props;
|
|
13
|
+
|
|
14
|
+
const templateDimensions = getTemplateDimensions(analytics.groups, template);
|
|
15
|
+
|
|
16
|
+
return isEmptyArray(templateDimensions) ? <PageAnalytics {...props} /> : <StructuredDataAnalytics {...props} />;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
20
|
+
analytics: state.analytics,
|
|
21
|
+
template: state.pageEditor.template,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export interface IAnalyticsFieldProps {
|
|
25
|
+
value: IState;
|
|
26
|
+
onChange: (value: IState) => void;
|
|
27
|
+
analytics: IAnalytics;
|
|
28
|
+
template: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface IState {
|
|
32
|
+
contentSelect: string;
|
|
33
|
+
groupSelect: string;
|
|
34
|
+
dimensionsSelect: string[];
|
|
35
|
+
values: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default connect(mapStateToProps, null)(AnalyticsField);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const FieldWrapper = styled.div`
|
|
4
|
+
margin-top: ${(p) => p.theme.spacing.s};
|
|
5
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
6
|
+
`;
|
|
7
|
+
|
|
8
|
+
const FieldsDivider = styled.div`
|
|
9
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
10
|
+
border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
export { FieldWrapper, FieldsDivider };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IDimensionsGroup } from "@ax/types";
|
|
2
|
+
import { splitAndTrim } from "@ax/helpers";
|
|
3
|
+
|
|
4
|
+
const getTemplateDimensions = (groups: IDimensionsGroup[], template: string): string[] => {
|
|
5
|
+
const templateDimensionsGroups = groups.filter((group) => group.templates?.includes(template));
|
|
6
|
+
const templateDimensions = templateDimensionsGroups.reduce((dimensions: string[], group: IDimensionsGroup) => {
|
|
7
|
+
return [...dimensions, ...splitAndTrim(group.dimensions, ";")];
|
|
8
|
+
}, []);
|
|
9
|
+
const uniqueTemplateDimensions = [...new Set(templateDimensions)];
|
|
10
|
+
return uniqueTemplateDimensions;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { getTemplateDimensions }
|
|
@@ -26,7 +26,7 @@ export const Label = styled.div<{ isOpen: boolean }>`
|
|
|
26
26
|
`;
|
|
27
27
|
|
|
28
28
|
export const Content = styled.div<{ isOpen: boolean }>`
|
|
29
|
-
overflow-y: hidden;
|
|
29
|
+
overflow-y: ${(p) => (p.isOpen ? "visible" : "hidden")};
|
|
30
30
|
max-height: ${(p) => (p.isOpen ? `auto` : 0)};
|
|
31
31
|
transition: all 0.5s ease-in-out;
|
|
32
32
|
`;
|