@griddo/ax 11.2.3 → 11.2.4-rc.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "11.2.3",
4
+ "version": "11.2.4-rc.0",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Carlos Torres <carlos.torres@secuoyas.com>",
@@ -225,5 +225,5 @@
225
225
  "publishConfig": {
226
226
  "access": "public"
227
227
  },
228
- "gitHead": "be3ccf7d5452e6527b4406f25363f64200ff9b7d"
228
+ "gitHead": "50e917b87710678093a5ccdb473513a3147fbdba"
229
229
  }
@@ -24,9 +24,14 @@ const SERVICES: { [key: string]: IServiceConfig } = {
24
24
  endpoint: ["/metrics/groups/site/", "/bulk"],
25
25
  method: "POST",
26
26
  },
27
+ DELETE_SCRIPT_CODE: {
28
+ ...template,
29
+ endpoint: ["/site/", "/metrics/code"],
30
+ method: "DELETE",
31
+ },
27
32
  };
28
33
 
29
- const getAnalytics = async (siteId: number | string): Promise<AxiosResponse> => {
34
+ const getAnalytics = async (siteId: number | "global"): Promise<AxiosResponse> => {
30
35
  const {
31
36
  host,
32
37
  endpoint: [prefix, suffix],
@@ -37,7 +42,7 @@ const getAnalytics = async (siteId: number | string): Promise<AxiosResponse> =>
37
42
  return sendRequest(SERVICES.GET_ANALYTICS);
38
43
  };
39
44
 
40
- const updateScriptCode = async (siteId: number | string, data: { scriptCode: string }): Promise<AxiosResponse> => {
45
+ const updateScriptCode = async (siteId: number | "global", data: { scriptCode: string }): Promise<AxiosResponse> => {
41
46
  const {
42
47
  host,
43
48
  endpoint: [prefix, suffix],
@@ -48,7 +53,10 @@ const updateScriptCode = async (siteId: number | string, data: { scriptCode: str
48
53
  return sendRequest(SERVICES.UPDATE_SCRIPT_CODE, { ...data });
49
54
  };
50
55
 
51
- const createDimensions = async (siteId: number | string, data: { dimensions: IDimension[] }): Promise<AxiosResponse> => {
56
+ const createDimensions = async (
57
+ siteId: number | "global",
58
+ data: { dimensions: IDimension[] }
59
+ ): Promise<AxiosResponse> => {
52
60
  const {
53
61
  host,
54
62
  endpoint: [prefix, suffix],
@@ -59,7 +67,10 @@ const createDimensions = async (siteId: number | string, data: { dimensions: IDi
59
67
  return sendRequest(SERVICES.CREATE_DIMENSIONS, { ...data });
60
68
  };
61
69
 
62
- const createDimensionsGroups = async (siteId: number | string, data: { groups: IDimensionsGroup[] }): Promise<AxiosResponse> => {
70
+ const createDimensionsGroups = async (
71
+ siteId: number | "global",
72
+ data: { groups: IDimensionsGroup[] }
73
+ ): Promise<AxiosResponse> => {
63
74
  const {
64
75
  host,
65
76
  endpoint: [prefix, suffix],
@@ -70,9 +81,21 @@ const createDimensionsGroups = async (siteId: number | string, data: { groups: I
70
81
  return sendRequest(SERVICES.CREATE_DIMENSIONS_GROUPS, { ...data });
71
82
  };
72
83
 
84
+ const deleteScriptCode = async (siteId: number | "global"): Promise<AxiosResponse> => {
85
+ const {
86
+ host,
87
+ endpoint: [prefix, suffix],
88
+ } = SERVICES.DELETE_SCRIPT_CODE;
89
+
90
+ SERVICES.DELETE_SCRIPT_CODE.dynamicUrl = `${host}${prefix}${siteId}${suffix}`;
91
+
92
+ return sendRequest(SERVICES.DELETE_SCRIPT_CODE);
93
+ };
94
+
73
95
  export default {
74
96
  getAnalytics,
75
97
  updateScriptCode,
76
98
  createDimensions,
77
- createDimensionsGroups
99
+ createDimensionsGroups,
100
+ deleteScriptCode,
78
101
  };
@@ -365,7 +365,7 @@ const AutoPanel = (props: IProps): JSX.Element => {
365
365
  <S.ConfigWrapper>
366
366
  <S.SubConfigContent hasMargin={true}>
367
367
  <S.OptionDescription isOpen={configState.isCustomLangOpen}>
368
- By default, content is shown in the page's language. Activate this option to{" "}
368
+ By default, content is shown in the page`&apos;`s language. Activate this option to{" "}
369
369
  <strong>specifically set a different language</strong> for the content shown in this
370
370
  distributor.
371
371
  </S.OptionDescription>
@@ -2,6 +2,7 @@ import { analytics } from "@ax/api";
2
2
  import { appActions } from "@ax/containers/App";
3
3
  import { handleRequest } from "@ax/helpers";
4
4
  import { IAnalytics } from "@ax/types";
5
+ import { Dispatch } from "redux";
5
6
  import { SET_ANALYTICS } from "./constants";
6
7
  import { ISetAnalytics } from "./interfaces";
7
8
 
@@ -9,10 +10,10 @@ function setAnalytics(analytics: IAnalytics): ISetAnalytics {
9
10
  return { type: SET_ANALYTICS, payload: analytics };
10
11
  }
11
12
 
12
- function getAnalytics(siteId: number | string = "global"): (dispatch: any) => Promise<void> {
13
+ function getAnalytics(siteId?: number | null): (dispatch: Dispatch) => Promise<void> {
13
14
  return async (dispatch) => {
14
15
  try {
15
- const callback = async () => analytics.getAnalytics(siteId);
16
+ const callback = async () => analytics.getAnalytics(siteId || "global");
16
17
 
17
18
  const responseActions = {
18
19
  handleSuccess: (response: any) => {
@@ -28,24 +29,22 @@ function getAnalytics(siteId: number | string = "global"): (dispatch: any) => Pr
28
29
  };
29
30
  }
30
31
 
31
- function updateAnalytics(
32
- analyticsState: IAnalytics,
33
- siteId: number | string = "global"
34
- ): (dispatch: any) => Promise<boolean> {
32
+ function updateAnalytics(analyticsState: IAnalytics, siteId?: number | null): (dispatch: Dispatch) => Promise<boolean> {
35
33
  return async (dispatch) => {
36
34
  try {
37
35
  const { scriptCode, dimensions, groups } = analyticsState;
38
36
  const callback = async () => {
39
37
  const promises = [];
40
- promises.push(analytics.updateScriptCode(siteId, { scriptCode }));
41
- promises.push(analytics.createDimensions(siteId, { dimensions }));
42
- promises.push(analytics.createDimensionsGroups(siteId, { groups }));
38
+ const site = siteId || "global";
39
+ promises.push(analytics.updateScriptCode(site, { scriptCode }));
40
+ promises.push(analytics.createDimensions(site, { dimensions }));
41
+ promises.push(analytics.createDimensionsGroups(site, { groups }));
43
42
  return Promise.all(promises);
44
43
  };
45
44
 
46
45
  const responseActions = {
47
46
  handleSuccess: () => {
48
- dispatch(getAnalytics());
47
+ getAnalytics(siteId)(dispatch);
49
48
  },
50
49
  handleError: (response: any) => {
51
50
  const {
@@ -65,16 +64,16 @@ function updateAnalytics(
65
64
  };
66
65
  }
67
66
 
68
- function updateScriptCode(scriptCode: string, siteId: number): (dispatch: any) => Promise<boolean> {
67
+ function updateScriptCode(scriptCode: string, siteId?: number | null): (dispatch: Dispatch) => Promise<boolean> {
69
68
  return async (dispatch) => {
70
69
  try {
71
70
  const callback = async () => {
72
- return analytics.updateScriptCode(siteId, { scriptCode });
71
+ return analytics.updateScriptCode(siteId || "global", { scriptCode });
73
72
  };
74
73
 
75
74
  const responseActions = {
76
75
  handleSuccess: () => {
77
- dispatch(getAnalytics(siteId));
76
+ getAnalytics(siteId)(dispatch);
78
77
  },
79
78
  handleError: (response: any) => appActions.handleError(response)(dispatch),
80
79
  };
@@ -87,4 +86,24 @@ function updateScriptCode(scriptCode: string, siteId: number): (dispatch: any) =
87
86
  };
88
87
  }
89
88
 
90
- export { setAnalytics, getAnalytics, updateAnalytics, updateScriptCode };
89
+ function deleteScriptCode(siteId?: number | null): (dispatch: Dispatch) => Promise<boolean> {
90
+ return async (dispatch) => {
91
+ try {
92
+ const callback = async () => analytics.deleteScriptCode(siteId || "global");
93
+
94
+ const responseActions = {
95
+ handleSuccess: () => {
96
+ getAnalytics(siteId)(dispatch);
97
+ },
98
+ handleError: (response: any) => appActions.handleError(response)(dispatch),
99
+ };
100
+
101
+ return await handleRequest(callback, responseActions, [])(dispatch);
102
+ } catch (e) {
103
+ console.log(e);
104
+ return false;
105
+ }
106
+ };
107
+ }
108
+
109
+ export { setAnalytics, getAnalytics, updateAnalytics, updateScriptCode, deleteScriptCode };
@@ -30,7 +30,8 @@ const Analytics = (props: IProps): JSX.Element => {
30
30
  const changeGroups = (groups: IDimensionsGroup[]) => setAnalyticsState((state) => ({ ...state, groups }));
31
31
 
32
32
  useEffect(() => {
33
- getAnalytics();
33
+ const handleGetAnalytics = async () => await getAnalytics();
34
+ handleGetAnalytics();
34
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
35
36
  }, []);
36
37
 
@@ -205,9 +206,9 @@ interface IAnalyticsProps {
205
206
  }
206
207
 
207
208
  interface IDispatchProps {
208
- getAnalytics(siteId?: number): void;
209
+ getAnalytics(siteId?: number | null): Promise<void>;
209
210
  setHistoryPush(path: string, isEditor?: boolean): void;
210
- updateAnalytics(analyticsState: IAnalytics, siteId?: number): Promise<boolean>;
211
+ updateAnalytics(analyticsState: IAnalytics, siteId?: number | null): Promise<boolean>;
211
212
  }
212
213
 
213
214
  type IProps = IAnalyticsProps & IDispatchProps;
@@ -177,8 +177,10 @@ const Content = (props: IProps): JSX.Element => {
177
177
  const dataIds = currentDataContent && currentDataContent.map((data: any) => data.id);
178
178
  const contentIds = isStructuredData ? dataIds : pagesIds;
179
179
  const currentSitePagesTemplatesIds = allSitePages && allSitePages.map((page: any) => page.templateId);
180
- const currentSitesByLang = sitesByLang?.filter((site: ISite) =>
181
- user?.roles.find((siteRole: ISiteRoles) => siteRole.siteId === site.id || siteRole.siteId === "all")
180
+ const currentSitesByLang = sitesByLang?.filter(
181
+ (site: ISite) =>
182
+ user?.isSuperAdmin ||
183
+ user?.roles.find((siteRole: ISiteRoles) => siteRole.siteId === site.id || siteRole.siteId === "all")
182
184
  );
183
185
  const categoryColumns: ISchemaField[] =
184
186
  currentStructuredData && currentStructuredData.schema
@@ -1,9 +1,9 @@
1
1
  import React from "react";
2
2
  import { Link } from "react-router-dom";
3
3
 
4
- import { Button } from "@ax/components";
4
+ import { Button, Modal } from "@ax/components";
5
5
  import { FieldsBehavior } from "@ax/components";
6
- import { IDimension, IDimensionsGroup } from "@ax/types";
6
+ import { IDimension, IDimensionsGroup, IModal } from "@ax/types";
7
7
  import { splitAndTrim, splitAndJoin } from "@ax/helpers";
8
8
 
9
9
  import * as S from "./style";
@@ -124,6 +124,29 @@ const Groups = (props: IGroups): JSX.Element => {
124
124
  );
125
125
  };
126
126
 
127
+ const ResetModal = (props: IModal): JSX.Element => {
128
+ const { isOpen, toggleModal, mainModalAction } = props;
129
+
130
+ const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
131
+
132
+ return (
133
+ <Modal
134
+ isOpen={isOpen}
135
+ hide={toggleModal}
136
+ title="Reset to global defaults"
137
+ secondaryAction={secondaryModalAction}
138
+ mainAction={mainModalAction}
139
+ size="S"
140
+ height={240}
141
+ >
142
+ <S.ModalContent>
143
+ The Analytics script for this site will be removed and reconnected to the global Analytics. Please be aware of
144
+ this change.
145
+ </S.ModalContent>
146
+ </Modal>
147
+ );
148
+ };
149
+
127
150
  interface IWarning {
128
151
  setShowWarning: React.Dispatch<React.SetStateAction<boolean>>;
129
152
  }
@@ -141,4 +164,4 @@ interface IGroups {
141
164
  groups: IDimensionsGroup[];
142
165
  }
143
166
 
144
- export { Warning, ScriptCode, Dimensions, Groups };
167
+ export { Warning, ScriptCode, Dimensions, Groups, ResetModal };
@@ -1,14 +1,14 @@
1
1
  import React, { useEffect, useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { IAnalytics, INavItem, IRootState } from "@ax/types";
4
+ import { IAnalytics, INavItem, IRootState, ISite } from "@ax/types";
5
5
  import { appActions } from "@ax/containers/App";
6
6
  import { analyticsActions } from "@ax/containers/Analytics";
7
7
  import { MainWrapper, Loading, Nav } from "@ax/components";
8
- import { useIsDirty } from "@ax/hooks";
8
+ import { useIsDirty, useModal } from "@ax/hooks";
9
9
  import { RouteLeavingGuard } from "@ax/guards";
10
10
 
11
- import { Dimensions, Groups, ScriptCode, Warning } from "./atoms";
11
+ import { Dimensions, Groups, ResetModal, ScriptCode, Warning } from "./atoms";
12
12
  import * as S from "./style";
13
13
 
14
14
  const Analytics = (props: IProps): JSX.Element => {
@@ -22,34 +22,41 @@ const Analytics = (props: IProps): JSX.Element => {
22
22
  setHistoryPush,
23
23
  site,
24
24
  updateScriptCode,
25
+ deleteScriptCode,
25
26
  } = props;
27
+
26
28
  const [showWarning, setShowWarning] = useState(false);
27
29
  const [scriptCode, setScriptCode] = useState(analytics.scriptCode);
28
- const { isDirty, setIsDirty } = useIsDirty(scriptCode);
30
+ const { isDirty, setIsDirty, resetDirty } = useIsDirty(scriptCode);
31
+ const { isOpen, toggleModal } = useModal();
29
32
 
30
33
  useEffect(() => {
31
- site?.id && getAnalytics(site.id);
34
+ const handleGetAnalytics = async () => await getAnalytics(site?.id);
35
+ handleGetAnalytics();
32
36
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
- }, [site?.id]);
37
+ }, []);
34
38
 
35
39
  useEffect(() => {
36
40
  setScriptCode(analytics.scriptCode);
37
41
  setShowWarning(!analytics.siteScriptCodeExists);
42
+ if (!analytics.siteScriptCodeExists) {
43
+ resetDirty();
44
+ }
38
45
  // eslint-disable-next-line react-hooks/exhaustive-deps
39
46
  }, [analytics]);
40
47
 
41
48
  const handleSave = async () => {
42
- const isSaved = await updateScriptCode(scriptCode, site.id);
49
+ const isSaved = !!site && (await updateScriptCode(scriptCode, site.id));
43
50
  if (isSaved) setIsDirty(false);
44
51
  };
45
52
 
46
- const rightButtonProps = {
47
- label: isSaving ? "Saving" : isDirty ? "Save" : "Saved",
48
- disabled: isSaving || !isDirty,
49
- action: () => handleSave(),
53
+ const setRoute = (path: string) => setHistoryPush(path);
54
+
55
+ const handleReset = async () => {
56
+ await deleteScriptCode(site?.id);
57
+ isOpen && toggleModal();
50
58
  };
51
59
 
52
- const setRoute = (path: string) => setHistoryPush(path);
53
60
  const modalText = (
54
61
  <>
55
62
  Analytics Script Code <strong>is not saved</strong>.{" "}
@@ -70,15 +77,39 @@ const Analytics = (props: IProps): JSX.Element => {
70
77
  </>
71
78
  );
72
79
 
80
+ const rightButtonProps = {
81
+ label: isSaving ? "Saving" : isDirty ? "Save" : "Saved",
82
+ disabled: isSaving || !isDirty,
83
+ action: handleSave,
84
+ };
85
+
86
+ const secondaryButtonProps = !showWarning
87
+ ? {
88
+ label: "Reset to Global Defaults",
89
+ action: toggleModal,
90
+ }
91
+ : undefined;
92
+
93
+ const mainResetModalAction = {
94
+ title: "Reset to Global",
95
+ onClick: handleReset,
96
+ };
97
+
73
98
  return (
74
99
  <>
75
100
  <RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
76
- <MainWrapper backLink={false} title="Analytics Settings" rightButton={rightButtonProps}>
101
+ <MainWrapper
102
+ backLink={false}
103
+ title="Analytics Settings"
104
+ rightButton={rightButtonProps}
105
+ rightLineButton={secondaryButtonProps}
106
+ >
77
107
  <S.Wrapper>
78
108
  <Nav current={currentNavItem} items={navItems} onClick={setRoute} />
79
109
  <S.ContentWrapper>{isLoading ? <Loading /> : analyticsSettings}</S.ContentWrapper>
80
110
  </S.Wrapper>
81
111
  </MainWrapper>
112
+ <ResetModal isOpen={isOpen} toggleModal={toggleModal} mainModalAction={mainResetModalAction} />
82
113
  </>
83
114
  );
84
115
  };
@@ -94,6 +125,7 @@ const mapDispatchToProps = {
94
125
  setHistoryPush: appActions.setHistoryPush,
95
126
  getAnalytics: analyticsActions.getAnalytics,
96
127
  updateScriptCode: analyticsActions.updateScriptCode,
128
+ deleteScriptCode: analyticsActions.deleteScriptCode,
97
129
  };
98
130
 
99
131
  interface IAnalyticsProps {
@@ -102,13 +134,14 @@ interface IAnalyticsProps {
102
134
  isSaving: boolean;
103
135
  isLoading: boolean;
104
136
  analytics: IAnalytics;
105
- site: any;
137
+ site: ISite | null;
106
138
  }
107
139
 
108
140
  interface IDispatchProps {
109
- getAnalytics(siteId?: number): void;
141
+ getAnalytics(siteId?: number | null): Promise<void>;
110
142
  setHistoryPush(path: string, isEditor?: boolean): void;
111
- updateScriptCode(scriptCode: string, siteId: number): Promise<boolean>;
143
+ updateScriptCode(scriptCode: string, siteId?: number | null): Promise<boolean>;
144
+ deleteScriptCode(siteId?: number | null): Promise<boolean>;
112
145
  }
113
146
 
114
147
  type IProps = IAnalyticsProps & IDispatchProps;
@@ -101,6 +101,14 @@ const ContentType = styled.div`
101
101
  }
102
102
  `;
103
103
 
104
+ const ModalContent = styled.div`
105
+ padding: ${(p) => p.theme.spacing.m};
106
+
107
+ p {
108
+ margin-bottom: ${(p) => p.theme.spacing.m};
109
+ }
110
+ `;
111
+
104
112
  export {
105
113
  Wrapper,
106
114
  Heading,
@@ -115,4 +123,5 @@ export {
115
123
  ComponentValues,
116
124
  AnalyticsWrapper,
117
125
  ContentType,
126
+ ModalContent,
118
127
  };
@@ -792,7 +792,7 @@ interface IDispatchProps {
792
792
  deleteBulk(ids: number[]): Promise<boolean>;
793
793
  restorePage(id: number | number[]): Promise<boolean>;
794
794
  resetPageEditor(): Promise<void>;
795
- getAnalytics(): void;
795
+ getAnalytics(siteId?: number | null): Promise<void>;
796
796
  setCurrentDataID(id: number | null): void;
797
797
  resetCurrentSiteErrorPages: () => Promise<void>;
798
798
  setContentFilters(contentFilters: Record<string, IStructuredDataQueryValues> | null): void;