@griddo/ax 12.6.0 → 12.6.1

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.
Files changed (86) hide show
  1. package/config/griddo-config/index.js +1 -0
  2. package/package.json +3 -4
  3. package/src/GlobalStore.tsx +91 -35
  4. package/src/__tests__/modules/ActivityLog/ActivityLog.uc.test.tsx +132 -0
  5. package/src/__tests__/modules/Analytics/Analytics.uc.test.tsx +168 -0
  6. package/src/__tests__/modules/GlobalSettings/Robots/Robots.test.tsx +110 -0
  7. package/src/__tests__/modules/GlobalSettings/Robots/Robots.uc.test.tsx +125 -0
  8. package/src/__tests__/modules/Redirects/Redirects.uc.test.tsx +164 -0
  9. package/src/__tests__/modules/Settings/Languages/Languages.uc.test.tsx +213 -0
  10. package/src/__tests__/modules/Settings/Social/Social.uc.test.tsx +171 -0
  11. package/src/__tests__/store/activityLog.test.ts +301 -0
  12. package/src/__tests__/store/analytics.test.ts +134 -0
  13. package/src/__tests__/store/domains.test.ts +107 -0
  14. package/src/__tests__/store/languages.test.ts +129 -0
  15. package/src/__tests__/store/persist.test.ts +47 -0
  16. package/src/__tests__/store/redirects.test.ts +313 -0
  17. package/src/__tests__/store/social.test.ts +165 -0
  18. package/src/components/MainWrapper/index.tsx +14 -2
  19. package/src/containers/ActivityLog/index.tsx +16 -3
  20. package/src/containers/ActivityLog/slice.ts +45 -0
  21. package/src/containers/ActivityLog/{actions.tsx → thunks.ts} +104 -89
  22. package/src/containers/Analytics/index.tsx +14 -3
  23. package/src/containers/Analytics/slice.ts +48 -0
  24. package/src/containers/Analytics/thunks.ts +103 -0
  25. package/src/containers/Domains/index.tsx +12 -3
  26. package/src/containers/Domains/slice.ts +37 -0
  27. package/src/containers/Domains/thunks.ts +60 -0
  28. package/src/containers/Redirects/constants.tsx +1 -17
  29. package/src/containers/Redirects/index.tsx +14 -3
  30. package/src/containers/Redirects/slice.ts +60 -0
  31. package/src/containers/Redirects/thunks.ts +196 -0
  32. package/src/containers/Settings/Languages/index.tsx +15 -3
  33. package/src/containers/Settings/Languages/slice.ts +48 -0
  34. package/src/containers/Settings/Languages/thunks.ts +83 -0
  35. package/src/containers/Settings/Social/index.tsx +11 -3
  36. package/src/containers/Settings/Social/slice.ts +40 -0
  37. package/src/containers/Settings/Social/thunks.ts +68 -0
  38. package/src/containers/Sites/actions.tsx +6 -2
  39. package/src/index.tsx +7 -6
  40. package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +13 -27
  41. package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +13 -27
  42. package/src/modules/ActivityLog/index.tsx +22 -51
  43. package/src/modules/Analytics/index.tsx +33 -42
  44. package/src/modules/App/Routing/index.tsx +5 -4
  45. package/src/modules/FileDrive/index.tsx +1 -1
  46. package/src/modules/GlobalSettings/Robots/index.tsx +24 -47
  47. package/src/modules/MediaGallery/index.tsx +1 -1
  48. package/src/modules/Redirects/RedirectItem/index.tsx +9 -22
  49. package/src/modules/Redirects/RedirectPanel/index.tsx +13 -14
  50. package/src/modules/Redirects/index.tsx +26 -69
  51. package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +4 -3
  52. package/src/modules/Settings/Languages/LanguagePanel/Form/ConnectedField/index.tsx +11 -18
  53. package/src/modules/Settings/Languages/LanguagePanel/Form/index.tsx +7 -9
  54. package/src/modules/Settings/Languages/LanguagePanel/index.tsx +38 -44
  55. package/src/modules/Settings/Languages/Table/Header/index.tsx +12 -19
  56. package/src/modules/Settings/Languages/Table/Item/index.tsx +21 -36
  57. package/src/modules/Settings/Languages/Table/index.tsx +6 -14
  58. package/src/modules/Settings/Languages/index.tsx +18 -30
  59. package/src/modules/Settings/SeoAnalyticsSettings/Analytics/index.tsx +42 -52
  60. package/src/modules/Settings/Social/index.tsx +17 -12
  61. package/src/modules/StructuredData/StructuredDataList/index.tsx +3 -2
  62. package/src/store/hooks.ts +37 -0
  63. package/src/store/index.ts +2 -0
  64. package/src/types/index.tsx +5 -6
  65. package/tsconfig.paths.json +1 -0
  66. package/src/containers/ActivityLog/constants.tsx +0 -6
  67. package/src/containers/ActivityLog/interfaces.tsx +0 -12
  68. package/src/containers/ActivityLog/reducer.tsx +0 -24
  69. package/src/containers/Analytics/actions.tsx +0 -109
  70. package/src/containers/Analytics/constants.tsx +0 -5
  71. package/src/containers/Analytics/interfaces.tsx +0 -9
  72. package/src/containers/Analytics/reducer.tsx +0 -28
  73. package/src/containers/Domains/actions.tsx +0 -58
  74. package/src/containers/Domains/constants.tsx +0 -5
  75. package/src/containers/Domains/interfaces.tsx +0 -9
  76. package/src/containers/Domains/reducer.tsx +0 -22
  77. package/src/containers/Redirects/actions.tsx +0 -190
  78. package/src/containers/Redirects/interfaces.tsx +0 -23
  79. package/src/containers/Redirects/reducer.tsx +0 -35
  80. package/src/containers/Settings/Languages/actions.tsx +0 -88
  81. package/src/containers/Settings/Languages/constants.tsx +0 -6
  82. package/src/containers/Settings/Languages/reducer.tsx +0 -31
  83. package/src/containers/Settings/Social/actions.tsx +0 -63
  84. package/src/containers/Settings/Social/constants.tsx +0 -3
  85. package/src/containers/Settings/Social/interfaces.tsx +0 -9
  86. package/src/containers/Settings/Social/reducer.tsx +0 -18
@@ -1,61 +1,76 @@
1
- import { useEffect, useState } from "react";
2
- import { connect } from "react-redux";
1
+ import { memo, useEffect, useState } from "react";
3
2
 
4
3
  import { Loading, MainWrapper, Nav } from "@ax/components";
5
4
  import { analyticsActions } from "@ax/containers/Analytics";
6
5
  import { appActions } from "@ax/containers/App";
7
6
  import { RouteLeavingGuard } from "@ax/guards";
8
7
  import { useModal } from "@ax/hooks";
9
- import type { IAnalytics, INavItem, IRootState, ISite } from "@ax/types";
8
+ import { useAppDispatch, useAppSelector } from "@ax/store";
9
+ import type { INavItem } from "@ax/types";
10
10
 
11
11
  import { Dimensions, Groups, ResetModal, ScriptCode, Warning } from "./atoms";
12
12
 
13
13
  import * as S from "./style";
14
14
 
15
15
  const Analytics = (props: IProps): JSX.Element => {
16
- const {
17
- navItems,
18
- currentNavItem,
19
- isSaving,
20
- isLoading,
21
- analytics,
22
- getAnalytics,
23
- setHistoryPush,
24
- site,
25
- updateScriptCode,
26
- deleteScriptCode,
27
- } = props;
16
+ const { navItems, currentNavItem } = props;
17
+
18
+ const dispatch = useAppDispatch();
19
+ const isSaving = useAppSelector((state) => state.app.isSaving);
20
+ const isLoading = useAppSelector((state) => state.app.isLoading);
21
+ const analytics = useAppSelector((state) => state.analytics);
22
+ const site = useAppSelector((state) => state.sites.currentSiteInfo);
28
23
 
29
24
  const [showWarning, setShowWarning] = useState(false);
30
25
  const [scriptCode, setScriptCode] = useState(analytics.scriptCode);
31
26
  const [isDirty, setIsDirty] = useState(false);
27
+ const [hasLoaded, setHasLoaded] = useState(false);
32
28
  const { isOpen, toggleModal } = useModal();
33
29
 
34
- // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
30
+ // biome-ignore lint/correctness/useExhaustiveDependencies: only on mount, as before
35
31
  useEffect(() => {
36
- const handleGetAnalytics = async () => await getAnalytics(site?.id);
37
- handleGetAnalytics();
32
+ const load = async () => {
33
+ try {
34
+ setHasLoaded(await dispatch(analyticsActions.getAnalytics(site?.id ?? null)).unwrap());
35
+ } catch {
36
+ setHasLoaded(false);
37
+ }
38
+ };
39
+ load();
38
40
  }, []);
39
41
 
42
+ // The Warning ("this site has no script code of its own, edit the global one") is a
43
+ // claim about the server, and `siteScriptCodeExists` is `false` both when the site has
44
+ // no override and when nothing has been fetched yet. Making the claim before the GET
45
+ // answers told a site that HAS its own script that it had none — and `getAnalytics`
46
+ // sets no loading flag, so nothing covered the gap. Hence the guard: until the GET
47
+ // succeeds the editor is the neutral state, and on failure the error modal is already up.
40
48
  useEffect(() => {
41
- setScriptCode(analytics.scriptCode);
49
+ if (!hasLoaded) return;
42
50
  setShowWarning(!analytics.siteScriptCodeExists);
51
+ }, [hasLoaded, analytics.siteScriptCodeExists]);
52
+
53
+ useEffect(() => {
54
+ setScriptCode(analytics.scriptCode);
43
55
  setIsDirty(false);
44
- }, [analytics.scriptCode, analytics.siteScriptCodeExists]);
56
+ }, [analytics.scriptCode]);
45
57
 
46
58
  useEffect(() => {
47
59
  setIsDirty(scriptCode !== analytics.scriptCode);
48
60
  }, [scriptCode, analytics.scriptCode]);
49
61
 
50
62
  const handleSave = async () => {
51
- const isSaved = !!site && (await updateScriptCode(scriptCode, site.id));
63
+ // `.unwrap()` is what hands over handleRequest's boolean: the dispatch itself
64
+ // resolves to the fulfilled action, which would be truthy even on failure.
65
+ const isSaved =
66
+ !!site && (await dispatch(analyticsActions.updateScriptCode({ scriptCode, siteId: site.id })).unwrap());
52
67
  if (isSaved) setIsDirty(false);
53
68
  };
54
69
 
55
- const setRoute = (path: string) => setHistoryPush(path);
70
+ const setRoute = (path: string) => dispatch(appActions.setHistoryPush(path));
56
71
 
57
72
  const handleReset = async () => {
58
- await deleteScriptCode(site?.id);
73
+ await dispatch(analyticsActions.deleteScriptCode(site?.id ?? null));
59
74
  isOpen && toggleModal();
60
75
  setShowWarning(true);
61
76
  setScriptCode(analytics.scriptCode);
@@ -106,6 +121,7 @@ const Analytics = (props: IProps): JSX.Element => {
106
121
  <MainWrapper
107
122
  backLink={false}
108
123
  title="Analytics Settings"
124
+ screen="analytics-site"
109
125
  rightButton={rightButtonProps}
110
126
  rightLineButton={secondaryButtonProps}
111
127
  >
@@ -119,36 +135,10 @@ const Analytics = (props: IProps): JSX.Element => {
119
135
  );
120
136
  };
121
137
 
122
- const mapStateToProps = (state: IRootState) => ({
123
- isSaving: state.app.isSaving,
124
- isLoading: state.app.isLoading,
125
- analytics: state.analytics,
126
- site: state.sites.currentSiteInfo,
127
- });
128
-
129
- const mapDispatchToProps = {
130
- setHistoryPush: appActions.setHistoryPush,
131
- getAnalytics: analyticsActions.getAnalytics,
132
- updateScriptCode: analyticsActions.updateScriptCode,
133
- deleteScriptCode: analyticsActions.deleteScriptCode,
134
- };
135
-
136
- interface IAnalyticsProps {
138
+ interface IProps {
137
139
  navItems: INavItem[];
138
140
  currentNavItem: INavItem;
139
- isSaving: boolean;
140
- isLoading: boolean;
141
- analytics: IAnalytics;
142
- site: ISite | null;
143
141
  }
144
142
 
145
- interface IDispatchProps {
146
- getAnalytics(siteId?: number | null): Promise<void>;
147
- setHistoryPush(path: string, isEditor?: boolean): void;
148
- updateScriptCode(scriptCode: string, siteId?: number | null): Promise<boolean>;
149
- deleteScriptCode(siteId?: number | null): Promise<boolean>;
150
- }
151
-
152
- type IProps = IAnalyticsProps & IDispatchProps;
153
-
154
- export default connect(mapStateToProps, mapDispatchToProps)(Analytics);
143
+ // `connect` memoised this screen implicitly; `memo` keeps that now it is gone.
144
+ export default memo(Analytics);
@@ -27,7 +27,6 @@
27
27
  //
28
28
 
29
29
  import { useEffect, useState } from "react";
30
- import { useDispatch, useSelector } from "react-redux";
31
30
 
32
31
  import { ErrorToast, FieldsBehavior, MainWrapper, Nav } from "@ax/components";
33
32
  import { appActions } from "@ax/containers/App";
@@ -35,11 +34,10 @@ import { socialActions } from "@ax/containers/Settings/Social";
35
34
  import { RouteLeavingGuard } from "@ax/guards";
36
35
  import { capitalize } from "@ax/helpers";
37
36
  import { useIsDirty } from "@ax/hooks";
38
- import type { INavItem, IRootState } from "@ax/types";
37
+ import { useAppDispatch, useAppSelector } from "@ax/store";
38
+ import type { INavItem } from "@ax/types";
39
39
 
40
40
  import { config } from "components";
41
- import type { AnyAction } from "redux";
42
- import type { ThunkDispatch } from "redux-thunk";
43
41
 
44
42
  import * as S from "./style";
45
43
 
@@ -64,12 +62,12 @@ const hardcodedSocials = [
64
62
 
65
63
  const Social = (props: IProps): JSX.Element => {
66
64
  const { navItems, currentNavItem } = props;
67
- const dispatch = useDispatch<ThunkDispatch<IRootState, undefined, AnyAction>>();
68
- const isSaving = useSelector((state: IRootState) => state.app.isSaving);
69
- const socialInfo = useSelector((state: IRootState) => state.social);
65
+ const dispatch = useAppDispatch();
66
+ const isSaving = useAppSelector((state) => state.app.isSaving);
67
+ const socialInfo = useAppSelector((state) => state.social);
70
68
  const [socialForm, setSocialForm] = useState<Record<string, string>>({});
71
69
  const [serverFields, setServerFields] = useState<Set<string>>(new Set());
72
- const { isDirty, resetDirty, setIsDirty } = useIsDirty(socialForm);
70
+ const { isDirty, resetDirty } = useIsDirty(socialForm);
73
71
 
74
72
  const socialFields = [
75
73
  ...instanceSocials.map((name) => ({ name, title: `${capitalize(name)} URL` })),
@@ -88,14 +86,21 @@ const Social = (props: IProps): JSX.Element => {
88
86
  resetDirty();
89
87
  }, [dispatch]);
90
88
 
89
+ // `resetDirty()`, not `setIsDirty(false)`: it also moves useIsDirty's baseline to the
90
+ // form being hydrated here. Leaving the redux-persist (ADR 0002) means `social` is
91
+ // empty on the first render and arrives with the GET, and useIsDirty snapshots the
92
+ // baseline during render — so the empty→loaded hop read as an edit and the screen
93
+ // landed dirty, arming the leave guard before the user touched anything.
91
94
  useEffect(() => {
92
95
  setSocialForm({ ...socialInfo });
93
96
  setServerFields(new Set(Object.keys(socialInfo).filter((k) => !!socialInfo[k])));
94
- setIsDirty(false);
95
- }, [socialInfo, setIsDirty]);
97
+ resetDirty();
98
+ }, [socialInfo, resetDirty]);
96
99
 
97
100
  const saveForm = async () => {
98
- const isSaved = await dispatch(socialActions.saveSocial(socialForm));
101
+ // `.unwrap()` is what hands over handleRequest's boolean: the dispatch itself
102
+ // resolves to the fulfilled action, which would be truthy even on failure.
103
+ const isSaved = await dispatch(socialActions.saveSocial(socialForm)).unwrap();
99
104
  if (isSaved) resetDirty();
100
105
  };
101
106
 
@@ -122,7 +127,7 @@ const Social = (props: IProps): JSX.Element => {
122
127
  return (
123
128
  <>
124
129
  <RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
125
- <MainWrapper backLink={false} title="Social" rightButton={rightButtonProps}>
130
+ <MainWrapper backLink={false} title="Social" rightButton={rightButtonProps} screen="social">
126
131
  <S.Wrapper>
127
132
  <Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
128
133
  <S.ContentWrapper>
@@ -315,7 +315,8 @@ const StructuredDataList = (props: IProps): JSX.Element => {
315
315
  // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
316
316
  useEffect(() => {
317
317
  checkUserSession();
318
- getAnalytics();
318
+ // `null` is the global scope: the RTK thunk takes exactly one argument.
319
+ getAnalytics(null);
319
320
  }, []);
320
321
 
321
322
  // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
@@ -811,7 +812,7 @@ interface IDispatchProps {
811
812
  deleteBulk(ids: number[]): Promise<boolean>;
812
813
  restorePage(id: number | number[]): Promise<boolean>;
813
814
  resetPageEditor(): Promise<void>;
814
- getAnalytics(siteId?: number | null): Promise<void>;
815
+ getAnalytics(siteId: number | null): unknown;
815
816
  setCurrentDataID(id: number | null): void;
816
817
  resetCurrentSiteErrorPages: () => Promise<void>;
817
818
  setContentFilters(contentFilters: Record<string, Record<string, IQueryValue[]>> | null): void;
@@ -0,0 +1,37 @@
1
+ import type { TypedUseSelectorHook } from "react-redux";
2
+ import { useDispatch, useSelector } from "react-redux";
3
+
4
+ import type { IRootState } from "@ax/types";
5
+
6
+ import type { ThunkDispatch } from "@reduxjs/toolkit";
7
+ import type { AnyAction } from "redux";
8
+
9
+ /**
10
+ * Typed hooks — the replacement for `connect` during the RTK migration.
11
+ *
12
+ * `RootState` is `IRootState` (the hand-written shape the 145 legacy `connect`
13
+ * call-sites already use) rather than `ReturnType<store.getState>`: the root
14
+ * reducer is still declared as `Reducer<any>`, so deriving the type from the
15
+ * store would silently collapse to `any`. Once every area owns a slice, the
16
+ * derivation becomes the source of truth and `IRootState` can go.
17
+ *
18
+ * `AppDispatch` is spelled out as a thunk dispatch for the same reason — it is
19
+ * what `configureStore`'s default middleware actually gives us, and writing it
20
+ * explicitly keeps `dispatch` from degrading to `any`.
21
+ *
22
+ * The stack stays on react-redux 7.2.9 + redux 4.2.1 on purpose — RTK 2.9 accepts
23
+ * both as peers, so nothing here needs them bumped. Both bumps were tried and
24
+ * backed out, each for a measured reason (see docs/RTK-MIGRATION.md §8.3):
25
+ * - redux 5 retypes `Dispatch` to `UnknownAction`, which the 15 legacy
26
+ * `containers/*\/actions.tsx` action interfaces are not assignable to (361 type
27
+ * errors) — and three of those files are ones `main` has already changed.
28
+ * - react-redux 8 subscribes via `useSyncExternalStore`, which surfaces a
29
+ * pre-existing render loop in `components/TableFilters/CheckGroupFilter`
30
+ * (unconditional `setSelectedValue` in an effect keyed on fresh references).
31
+ * Hence `AnyAction` rather than redux 5's `UnknownAction`.
32
+ */
33
+ export type RootState = IRootState;
34
+ export type AppDispatch = ThunkDispatch<IRootState, undefined, AnyAction>;
35
+
36
+ export const useAppDispatch = () => useDispatch<AppDispatch>();
37
+ export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
@@ -0,0 +1,2 @@
1
+ export type { AppDispatch, RootState } from "./hooks";
2
+ export { useAppDispatch, useAppSelector } from "./hooks";
@@ -1,7 +1,7 @@
1
- import type { IActivityLogState } from "@ax/containers/ActivityLog/reducer";
2
- import type { IAnalyticsState } from "@ax/containers/Analytics/reducer";
1
+ import type { IActivityLogState } from "@ax/containers/ActivityLog/slice";
2
+ import type { IAnalyticsState } from "@ax/containers/Analytics/slice";
3
3
  import type { IAppState } from "@ax/containers/App/reducer";
4
- import type { IDomainsState } from "@ax/containers/Domains/reducer";
4
+ import type { IDomainsState } from "@ax/containers/Domains/slice";
5
5
  import type { IFileDriveState } from "@ax/containers/FileDrive/reducer";
6
6
  import type { IFormsState } from "@ax/containers/Forms/reducer";
7
7
  import type { IGalleryState } from "@ax/containers/Gallery/reducer";
@@ -9,9 +9,9 @@ import type { IIntegrationsState } from "@ax/containers/Integrations/reducer";
9
9
  import type { INavigationState } from "@ax/containers/Navigation/Defaults/reducer";
10
10
  import type { IMenuState } from "@ax/containers/Navigation/Menu/reducer";
11
11
  import type { IPageEditorState } from "@ax/containers/PageEditor/reducer";
12
- import type { IRedirectsState } from "@ax/containers/Redirects/reducer";
12
+ import type { IRedirectsState } from "@ax/containers/Redirects/slice";
13
13
  import type { IDataPacksState } from "@ax/containers/Settings/DataPacks/reducer";
14
- import type { ILanguageState } from "@ax/containers/Settings/Languages/reducer";
14
+ import type { ILanguageState } from "@ax/containers/Settings/Languages/slice";
15
15
  import type { ISitesState } from "@ax/containers/Sites/reducer";
16
16
  import type { IStructuredDataState } from "@ax/containers/StructuredData/reducer";
17
17
  import type { IUsersState } from "@ax/containers/Users/reducer";
@@ -261,7 +261,6 @@ export interface IHeadingField {
261
261
  }
262
262
 
263
263
  export interface IRootState {
264
- router: any;
265
264
  app: IAppState;
266
265
  sites: ISitesState;
267
266
  pageEditor: IPageEditorState;
@@ -17,6 +17,7 @@
17
17
  "@ax/routes/*": ["./src/routes/*"],
18
18
  "@ax/types": ["./src/types"],
19
19
  "@ax/schemas": ["./src/schemas"],
20
+ "@ax/store": ["./src/store"],
20
21
  "@ax/themes/*": ["./src/themes/*"],
21
22
  "@ax/constants": ["./src/constants"],
22
23
  "@ax/constants/*": ["./src/constants/*"]
@@ -1,6 +0,0 @@
1
- const NAME = "activityLog";
2
-
3
- const SET_ACTIVITY_LOG = `${NAME}/SET_ACTIVITY_LOG`;
4
- const SET_LIST_MODE = `${NAME}/SET_LIST_MODE`;
5
-
6
- export { SET_ACTIVITY_LOG, SET_LIST_MODE };
@@ -1,12 +0,0 @@
1
- import type { ILogItemsByDay, ILogItemsByUser } from "@ax/types";
2
- import type { SET_ACTIVITY_LOG, SET_LIST_MODE } from "./constants";
3
-
4
- export interface ISetActivityLog {
5
- type: typeof SET_ACTIVITY_LOG;
6
- payload: { activityLog: ILogItemsByDay | ILogItemsByUser };
7
- }
8
-
9
- export interface ISetListMode {
10
- type: typeof SET_LIST_MODE;
11
- payload: { listMode: string };
12
- }
@@ -1,24 +0,0 @@
1
- import type { ILogItemsByDay, ILogItemsByUser } from "@ax/types";
2
- import { SET_ACTIVITY_LOG, SET_LIST_MODE } from "./constants";
3
-
4
- export interface IActivityLogState {
5
- activityLog: ILogItemsByDay | ILogItemsByUser;
6
- listMode: string;
7
- }
8
-
9
- export const initialState: IActivityLogState = {
10
- activityLog: { totalItems: 0, items: [] },
11
- listMode: "default",
12
- };
13
-
14
- export function reducer(state = initialState, action: any): IActivityLogState {
15
- switch (action.type) {
16
- case SET_ACTIVITY_LOG:
17
- case SET_LIST_MODE:
18
- return { ...state, ...action.payload };
19
- default:
20
- return state;
21
- }
22
- }
23
-
24
- export { initialState as activityLogInitialState, reducer as activityLogReducer };
@@ -1,109 +0,0 @@
1
- import { analytics } from "@ax/api";
2
- import { appActions } from "@ax/containers/App";
3
- import { handleRequest } from "@ax/helpers";
4
- import type { IAnalytics } from "@ax/types";
5
- import type { Dispatch } from "redux";
6
- import { SET_ANALYTICS } from "./constants";
7
- import type { ISetAnalytics } from "./interfaces";
8
-
9
- function setAnalytics(analytics: IAnalytics): ISetAnalytics {
10
- return { type: SET_ANALYTICS, payload: analytics };
11
- }
12
-
13
- function getAnalytics(siteId?: number | null): (dispatch: Dispatch) => Promise<void> {
14
- return async (dispatch) => {
15
- try {
16
- const callback = async () => analytics.getAnalytics(siteId || "global");
17
-
18
- const responseActions = {
19
- handleSuccess: (response: any) => {
20
- dispatch(setAnalytics(response));
21
- },
22
- handleError: (response: any) => appActions.handleError(response)(dispatch),
23
- };
24
-
25
- await handleRequest(callback, responseActions, [])(dispatch);
26
- } catch (e) {
27
- console.log(e);
28
- }
29
- };
30
- }
31
-
32
- function updateAnalytics(analyticsState: IAnalytics, siteId?: number | null): (dispatch: Dispatch) => Promise<boolean> {
33
- return async (dispatch) => {
34
- try {
35
- const { scriptCode, dimensions, groups } = analyticsState;
36
- const callback = async () => {
37
- const promises = [];
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 }));
42
- return Promise.all(promises);
43
- };
44
-
45
- const responseActions = {
46
- handleSuccess: () => {
47
- getAnalytics(siteId)(dispatch);
48
- },
49
- handleError: (response: any) => {
50
- const {
51
- data: { message },
52
- } = response;
53
- const isMultiple = Array.isArray(message) && message.length > 1;
54
- const msg = isMultiple ? `The action failed due to ${message.length} errors.` : undefined;
55
- appActions.handleError(response, isMultiple, msg)(dispatch);
56
- },
57
- };
58
-
59
- return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
60
- } catch (e) {
61
- console.log(e);
62
- return false;
63
- }
64
- };
65
- }
66
-
67
- function updateScriptCode(scriptCode: string, siteId?: number | null): (dispatch: Dispatch) => Promise<boolean> {
68
- return async (dispatch) => {
69
- try {
70
- const callback = async () => {
71
- return analytics.updateScriptCode(siteId || "global", { scriptCode });
72
- };
73
-
74
- const responseActions = {
75
- handleSuccess: () => {
76
- getAnalytics(siteId)(dispatch);
77
- },
78
- handleError: (response: any) => appActions.handleError(response)(dispatch),
79
- };
80
-
81
- return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
82
- } catch (e) {
83
- console.log(e);
84
- return false;
85
- }
86
- };
87
- }
88
-
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 };
@@ -1,5 +0,0 @@
1
- const NAME = "analytics";
2
-
3
- const SET_ANALYTICS = `${NAME}/SET_ANALYTICS`;
4
-
5
- export { NAME, SET_ANALYTICS };
@@ -1,9 +0,0 @@
1
- import type { IAnalytics } from "@ax/types";
2
- import type { SET_ANALYTICS } from "./constants";
3
-
4
- export interface ISetAnalytics {
5
- type: typeof SET_ANALYTICS;
6
- payload: IAnalytics;
7
- }
8
-
9
- export type AnalyticsActionsCreators = ISetAnalytics;
@@ -1,28 +0,0 @@
1
- import type { IDimension, IDimensionsGroup } from "@ax/types";
2
- import { SET_ANALYTICS } from "./constants";
3
- import type { AnalyticsActionsCreators } from "./interfaces";
4
-
5
- export interface IAnalyticsState {
6
- scriptCode: string;
7
- siteScriptCodeExists: boolean;
8
- dimensions: IDimension[];
9
- groups: IDimensionsGroup[];
10
- }
11
-
12
- export const initialState = {
13
- scriptCode: "",
14
- siteScriptCodeExists: false,
15
- dimensions: [],
16
- groups: [],
17
- };
18
-
19
- export function reducer(state = initialState, action: AnalyticsActionsCreators): IAnalyticsState {
20
- switch (action.type) {
21
- case SET_ANALYTICS:
22
- return { ...state, ...action.payload };
23
- default:
24
- return state;
25
- }
26
- }
27
-
28
- export { initialState as analyticsInitialState, reducer as analyticsReducer };
@@ -1,58 +0,0 @@
1
- import { domains } from "@ax/api";
2
- import { appActions } from "@ax/containers/App";
3
- import { handleRequest } from "@ax/helpers";
4
- import type { IDomainRobot } from "@ax/types";
5
- import { SET_DOMAINS_ROBOTS } from "./constants";
6
- import type { ISetDomainsRobots } from "./interfaces";
7
-
8
- function setDomainsRobots(robots: IDomainRobot[]): ISetDomainsRobots {
9
- return { type: SET_DOMAINS_ROBOTS, payload: { robots } };
10
- }
11
-
12
- function getDomainsRobots(): (dispatch: any) => Promise<void> {
13
- return async (dispatch) => {
14
- try {
15
- const callback = async () => domains.getDomainsRobots();
16
-
17
- const responseActions = {
18
- handleSuccess: (response: any) => {
19
- dispatch(setDomainsRobots(response));
20
- },
21
- handleError: (response: any) => appActions.handleError(response)(dispatch),
22
- };
23
-
24
- await handleRequest(callback, responseActions, [appActions.setIsLoading])(dispatch);
25
- } catch (e) {
26
- console.log(e);
27
- }
28
- };
29
- }
30
-
31
- function updateDomainsRobots(robots: IDomainRobot[]): (dispatch: any) => Promise<boolean> {
32
- return async (dispatch) => {
33
- try {
34
- const callback = async () => domains.updateDomainsRobots(robots);
35
-
36
- const responseActions = {
37
- handleSuccess: () => {
38
- dispatch(getDomainsRobots());
39
- },
40
- handleError: (response: any) => {
41
- const {
42
- data: { message },
43
- } = response;
44
- const isMultiple = Array.isArray(message) && message.length > 1;
45
- const msg = isMultiple ? `The action failed due to ${message.length} errors.` : undefined;
46
- appActions.handleError(response, isMultiple, msg)(dispatch);
47
- },
48
- };
49
-
50
- return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
51
- } catch (e) {
52
- console.log(e);
53
- return false;
54
- }
55
- };
56
- }
57
-
58
- export { getDomainsRobots, updateDomainsRobots };
@@ -1,5 +0,0 @@
1
- const NAME = "domains";
2
-
3
- const SET_DOMAINS_ROBOTS = `${NAME}/SET_DOMAINS_ROBOTS`;
4
-
5
- export { NAME, SET_DOMAINS_ROBOTS };
@@ -1,9 +0,0 @@
1
- import type { IDomainRobot } from "@ax/types";
2
- import type { SET_DOMAINS_ROBOTS } from "./constants";
3
-
4
- export interface ISetDomainsRobots {
5
- type: typeof SET_DOMAINS_ROBOTS;
6
- payload: { robots: IDomainRobot[] };
7
- }
8
-
9
- export type DomainsActionsCreators = ISetDomainsRobots;
@@ -1,22 +0,0 @@
1
- import type { IDomainRobot } from "@ax/types";
2
- import { SET_DOMAINS_ROBOTS } from "./constants";
3
- import type { DomainsActionsCreators } from "./interfaces";
4
-
5
- export interface IDomainsState {
6
- robots: IDomainRobot[];
7
- }
8
-
9
- export const initialState = {
10
- robots: [],
11
- };
12
-
13
- export function reducer(state = initialState, action: DomainsActionsCreators): IDomainsState {
14
- switch (action.type) {
15
- case SET_DOMAINS_ROBOTS:
16
- return { ...state, ...action.payload };
17
- default:
18
- return state;
19
- }
20
- }
21
-
22
- export { initialState as domainsInitialState, reducer as domainsReducer };