@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.
- package/config/griddo-config/index.js +1 -0
- package/package.json +3 -4
- package/src/GlobalStore.tsx +91 -35
- package/src/__tests__/modules/ActivityLog/ActivityLog.uc.test.tsx +132 -0
- package/src/__tests__/modules/Analytics/Analytics.uc.test.tsx +168 -0
- package/src/__tests__/modules/GlobalSettings/Robots/Robots.test.tsx +110 -0
- package/src/__tests__/modules/GlobalSettings/Robots/Robots.uc.test.tsx +125 -0
- package/src/__tests__/modules/Redirects/Redirects.uc.test.tsx +164 -0
- package/src/__tests__/modules/Settings/Languages/Languages.uc.test.tsx +213 -0
- package/src/__tests__/modules/Settings/Social/Social.uc.test.tsx +171 -0
- package/src/__tests__/store/activityLog.test.ts +301 -0
- package/src/__tests__/store/analytics.test.ts +134 -0
- package/src/__tests__/store/domains.test.ts +107 -0
- package/src/__tests__/store/languages.test.ts +129 -0
- package/src/__tests__/store/persist.test.ts +47 -0
- package/src/__tests__/store/redirects.test.ts +313 -0
- package/src/__tests__/store/social.test.ts +165 -0
- package/src/components/MainWrapper/index.tsx +14 -2
- package/src/containers/ActivityLog/index.tsx +16 -3
- package/src/containers/ActivityLog/slice.ts +45 -0
- package/src/containers/ActivityLog/{actions.tsx → thunks.ts} +104 -89
- package/src/containers/Analytics/index.tsx +14 -3
- package/src/containers/Analytics/slice.ts +48 -0
- package/src/containers/Analytics/thunks.ts +103 -0
- package/src/containers/Domains/index.tsx +12 -3
- package/src/containers/Domains/slice.ts +37 -0
- package/src/containers/Domains/thunks.ts +60 -0
- package/src/containers/Redirects/constants.tsx +1 -17
- package/src/containers/Redirects/index.tsx +14 -3
- package/src/containers/Redirects/slice.ts +60 -0
- package/src/containers/Redirects/thunks.ts +196 -0
- package/src/containers/Settings/Languages/index.tsx +15 -3
- package/src/containers/Settings/Languages/slice.ts +48 -0
- package/src/containers/Settings/Languages/thunks.ts +83 -0
- package/src/containers/Settings/Social/index.tsx +11 -3
- package/src/containers/Settings/Social/slice.ts +40 -0
- package/src/containers/Settings/Social/thunks.ts +68 -0
- package/src/containers/Sites/actions.tsx +6 -2
- package/src/index.tsx +7 -6
- package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +13 -27
- package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +13 -27
- package/src/modules/ActivityLog/index.tsx +22 -51
- package/src/modules/Analytics/index.tsx +33 -42
- package/src/modules/App/Routing/index.tsx +5 -4
- package/src/modules/FileDrive/index.tsx +1 -1
- package/src/modules/GlobalSettings/Robots/index.tsx +24 -47
- package/src/modules/MediaGallery/index.tsx +1 -1
- package/src/modules/Redirects/RedirectItem/index.tsx +9 -22
- package/src/modules/Redirects/RedirectPanel/index.tsx +13 -14
- package/src/modules/Redirects/index.tsx +26 -69
- package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +4 -3
- package/src/modules/Settings/Languages/LanguagePanel/Form/ConnectedField/index.tsx +11 -18
- package/src/modules/Settings/Languages/LanguagePanel/Form/index.tsx +7 -9
- package/src/modules/Settings/Languages/LanguagePanel/index.tsx +38 -44
- package/src/modules/Settings/Languages/Table/Header/index.tsx +12 -19
- package/src/modules/Settings/Languages/Table/Item/index.tsx +21 -36
- package/src/modules/Settings/Languages/Table/index.tsx +6 -14
- package/src/modules/Settings/Languages/index.tsx +18 -30
- package/src/modules/Settings/SeoAnalyticsSettings/Analytics/index.tsx +42 -52
- package/src/modules/Settings/Social/index.tsx +17 -12
- package/src/modules/StructuredData/StructuredDataList/index.tsx +3 -2
- package/src/store/hooks.ts +37 -0
- package/src/store/index.ts +2 -0
- package/src/types/index.tsx +5 -6
- package/tsconfig.paths.json +1 -0
- package/src/containers/ActivityLog/constants.tsx +0 -6
- package/src/containers/ActivityLog/interfaces.tsx +0 -12
- package/src/containers/ActivityLog/reducer.tsx +0 -24
- package/src/containers/Analytics/actions.tsx +0 -109
- package/src/containers/Analytics/constants.tsx +0 -5
- package/src/containers/Analytics/interfaces.tsx +0 -9
- package/src/containers/Analytics/reducer.tsx +0 -28
- package/src/containers/Domains/actions.tsx +0 -58
- package/src/containers/Domains/constants.tsx +0 -5
- package/src/containers/Domains/interfaces.tsx +0 -9
- package/src/containers/Domains/reducer.tsx +0 -22
- package/src/containers/Redirects/actions.tsx +0 -190
- package/src/containers/Redirects/interfaces.tsx +0 -23
- package/src/containers/Redirects/reducer.tsx +0 -35
- package/src/containers/Settings/Languages/actions.tsx +0 -88
- package/src/containers/Settings/Languages/constants.tsx +0 -6
- package/src/containers/Settings/Languages/reducer.tsx +0 -31
- package/src/containers/Settings/Social/actions.tsx +0 -63
- package/src/containers/Settings/Social/constants.tsx +0 -3
- package/src/containers/Settings/Social/interfaces.tsx +0 -9
- 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
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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:
|
|
30
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: only on mount, as before
|
|
35
31
|
useEffect(() => {
|
|
36
|
-
const
|
|
37
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
146
|
-
|
|
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
|
|
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 =
|
|
68
|
-
const isSaving =
|
|
69
|
-
const socialInfo =
|
|
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
|
|
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
|
-
|
|
95
|
-
}, [socialInfo,
|
|
97
|
+
resetDirty();
|
|
98
|
+
}, [socialInfo, resetDirty]);
|
|
96
99
|
|
|
97
100
|
const saveForm = async () => {
|
|
98
|
-
|
|
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
|
-
|
|
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
|
|
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;
|
package/src/types/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { IActivityLogState } from "@ax/containers/ActivityLog/
|
|
2
|
-
import type { IAnalyticsState } from "@ax/containers/Analytics/
|
|
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/
|
|
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/
|
|
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/
|
|
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;
|
package/tsconfig.paths.json
CHANGED
|
@@ -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,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,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,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 };
|