@griddo/ax 12.6.1 → 12.6.2
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 +0 -1
- package/package.json +4 -3
- package/src/GlobalStore.tsx +35 -91
- package/src/__tests__/hooks/heartbeat.test.tsx +88 -0
- package/src/components/MainWrapper/index.tsx +2 -14
- package/src/containers/ActivityLog/{thunks.ts → actions.tsx} +89 -104
- package/src/containers/ActivityLog/constants.tsx +6 -0
- package/src/containers/ActivityLog/index.tsx +3 -16
- package/src/containers/ActivityLog/interfaces.tsx +12 -0
- package/src/containers/ActivityLog/reducer.tsx +24 -0
- package/src/containers/Analytics/actions.tsx +109 -0
- package/src/containers/Analytics/constants.tsx +5 -0
- package/src/containers/Analytics/index.tsx +3 -14
- package/src/containers/Analytics/interfaces.tsx +9 -0
- package/src/containers/Analytics/reducer.tsx +28 -0
- package/src/containers/Domains/actions.tsx +58 -0
- package/src/containers/Domains/constants.tsx +5 -0
- package/src/containers/Domains/index.tsx +3 -12
- package/src/containers/Domains/interfaces.tsx +9 -0
- package/src/containers/Domains/reducer.tsx +22 -0
- package/src/containers/Redirects/actions.tsx +190 -0
- package/src/containers/Redirects/constants.tsx +17 -1
- package/src/containers/Redirects/index.tsx +3 -14
- package/src/containers/Redirects/interfaces.tsx +23 -0
- package/src/containers/Redirects/reducer.tsx +35 -0
- package/src/containers/Settings/Languages/actions.tsx +88 -0
- package/src/containers/Settings/Languages/constants.tsx +6 -0
- package/src/containers/Settings/Languages/index.tsx +3 -15
- package/src/containers/Settings/Languages/reducer.tsx +31 -0
- package/src/containers/Settings/Social/actions.tsx +63 -0
- package/src/containers/Settings/Social/constants.tsx +3 -0
- package/src/containers/Settings/Social/index.tsx +3 -11
- package/src/containers/Settings/Social/interfaces.tsx +9 -0
- package/src/containers/Settings/Social/reducer.tsx +18 -0
- package/src/containers/Sites/actions.tsx +2 -6
- package/src/hooks/heartbeat.ts +32 -0
- package/src/hooks/index.tsx +2 -0
- package/src/index.tsx +6 -7
- package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +27 -13
- package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +27 -13
- package/src/modules/ActivityLog/index.tsx +51 -22
- package/src/modules/Analytics/index.tsx +42 -33
- package/src/modules/App/Routing/index.tsx +4 -5
- package/src/modules/FileDrive/index.tsx +1 -1
- package/src/modules/GlobalEditor/index.tsx +6 -8
- package/src/modules/GlobalSettings/Robots/index.tsx +47 -24
- package/src/modules/MediaGallery/index.tsx +1 -1
- package/src/modules/PageEditor/index.tsx +5 -9
- package/src/modules/Redirects/RedirectItem/index.tsx +22 -9
- package/src/modules/Redirects/RedirectPanel/index.tsx +14 -13
- package/src/modules/Redirects/index.tsx +69 -26
- package/src/modules/Settings/ContentTypes/DataPacks/index.tsx +3 -4
- package/src/modules/Settings/Languages/LanguagePanel/Form/ConnectedField/index.tsx +18 -11
- package/src/modules/Settings/Languages/LanguagePanel/Form/index.tsx +9 -7
- package/src/modules/Settings/Languages/LanguagePanel/index.tsx +44 -38
- package/src/modules/Settings/Languages/Table/Header/index.tsx +19 -12
- package/src/modules/Settings/Languages/Table/Item/index.tsx +36 -21
- package/src/modules/Settings/Languages/Table/index.tsx +14 -6
- package/src/modules/Settings/Languages/index.tsx +30 -18
- package/src/modules/Settings/SeoAnalyticsSettings/Analytics/index.tsx +52 -42
- package/src/modules/Settings/Social/index.tsx +12 -17
- package/src/modules/StructuredData/StructuredDataList/index.tsx +2 -3
- package/src/types/index.tsx +6 -5
- package/tsconfig.paths.json +0 -1
- package/src/__tests__/modules/ActivityLog/ActivityLog.uc.test.tsx +0 -132
- package/src/__tests__/modules/Analytics/Analytics.uc.test.tsx +0 -168
- package/src/__tests__/modules/GlobalSettings/Robots/Robots.test.tsx +0 -110
- package/src/__tests__/modules/GlobalSettings/Robots/Robots.uc.test.tsx +0 -125
- package/src/__tests__/modules/Redirects/Redirects.uc.test.tsx +0 -164
- package/src/__tests__/modules/Settings/Languages/Languages.uc.test.tsx +0 -213
- package/src/__tests__/modules/Settings/Social/Social.uc.test.tsx +0 -171
- package/src/__tests__/store/activityLog.test.ts +0 -301
- package/src/__tests__/store/analytics.test.ts +0 -134
- package/src/__tests__/store/domains.test.ts +0 -107
- package/src/__tests__/store/languages.test.ts +0 -129
- package/src/__tests__/store/persist.test.ts +0 -47
- package/src/__tests__/store/redirects.test.ts +0 -313
- package/src/__tests__/store/social.test.ts +0 -165
- package/src/containers/ActivityLog/slice.ts +0 -45
- package/src/containers/Analytics/slice.ts +0 -48
- package/src/containers/Analytics/thunks.ts +0 -103
- package/src/containers/Domains/slice.ts +0 -37
- package/src/containers/Domains/thunks.ts +0 -60
- package/src/containers/Redirects/slice.ts +0 -60
- package/src/containers/Redirects/thunks.ts +0 -196
- package/src/containers/Settings/Languages/slice.ts +0 -48
- package/src/containers/Settings/Languages/thunks.ts +0 -83
- package/src/containers/Settings/Social/slice.ts +0 -40
- package/src/containers/Settings/Social/thunks.ts +0 -68
- package/src/store/hooks.ts +0 -37
- package/src/store/index.ts +0 -2
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
-
import { analyticsActions } from "@ax/containers/Analytics";
|
|
4
|
+
import type { IAnalytics, IDimension, IDimensionsGroup, IRootState } from "@ax/types";
|
|
5
5
|
import { appActions } from "@ax/containers/App";
|
|
6
|
+
import { analyticsActions } from "@ax/containers/Analytics";
|
|
7
|
+
import { MainWrapper, ErrorToast, Loading, FieldsBehavior } from "@ax/components";
|
|
6
8
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
7
|
-
import { useIsDirty
|
|
8
|
-
import {
|
|
9
|
-
import type { IDimension, IDimensionsGroup } from "@ax/types";
|
|
9
|
+
import { useIsDirty } from "@ax/hooks";
|
|
10
|
+
import { useModal } from "@ax/hooks";
|
|
10
11
|
|
|
11
12
|
import DimensionItem from "./DimensionItem";
|
|
12
13
|
import DimensionPanel from "./DimensionPanel";
|
|
13
14
|
import GroupItem from "./GroupItem";
|
|
14
15
|
import GroupPanel from "./GroupPanel";
|
|
15
|
-
|
|
16
16
|
import * as S from "./style";
|
|
17
17
|
|
|
18
|
-
const Analytics = (): JSX.Element => {
|
|
19
|
-
const
|
|
20
|
-
const isSaving = useAppSelector((state) => state.app.isSaving);
|
|
21
|
-
const isLoading = useAppSelector((state) => state.app.isLoading);
|
|
22
|
-
const analytics = useAppSelector((state) => state.analytics);
|
|
18
|
+
const Analytics = (props: IProps): JSX.Element => {
|
|
19
|
+
const { isSaving, isLoading, analytics, getAnalytics, setHistoryPush, updateAnalytics } = props;
|
|
23
20
|
|
|
24
21
|
const [analyticsState, setAnalyticsState] = useState(analytics);
|
|
25
22
|
const { isDirty, resetDirty } = useIsDirty(analyticsState);
|
|
@@ -34,27 +31,16 @@ const Analytics = (): JSX.Element => {
|
|
|
34
31
|
|
|
35
32
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
36
33
|
useEffect(() => {
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
const handleGetAnalytics = async () => await getAnalytics();
|
|
35
|
+
handleGetAnalytics();
|
|
39
36
|
}, []);
|
|
40
37
|
|
|
41
|
-
// `resetDirty()`, not `setIsDirty(false)`: it also moves useIsDirty's baseline to the
|
|
42
|
-
// state being hydrated here. useIsDirty snapshots its baseline during render, so on
|
|
43
|
-
// the first visit — nothing persisted for this scope — the store is still the initial
|
|
44
|
-
// state and the empty→loaded hop reads as an edit: Save enabled and the leave guard
|
|
45
|
-
// armed before the user touches anything, against this screen's own AC6. Same mine as
|
|
46
|
-
// Settings/Social (docs/RTK-MIGRATION.md §5).
|
|
47
38
|
useEffect(() => {
|
|
48
39
|
setAnalyticsState(analytics);
|
|
49
|
-
|
|
50
|
-
}, [analytics, resetDirty]);
|
|
40
|
+
}, [analytics]);
|
|
51
41
|
|
|
52
42
|
const handleSave = async () => {
|
|
53
|
-
|
|
54
|
-
// resolves to the fulfilled action, which would be truthy even on failure.
|
|
55
|
-
const isSaved = await dispatch(
|
|
56
|
-
analyticsActions.updateAnalytics({ analytics: analyticsState, siteId: null }),
|
|
57
|
-
).unwrap();
|
|
43
|
+
const isSaved = await updateAnalytics(analyticsState);
|
|
58
44
|
if (isSaved) resetDirty();
|
|
59
45
|
};
|
|
60
46
|
|
|
@@ -123,7 +109,7 @@ const Analytics = (): JSX.Element => {
|
|
|
123
109
|
changeGroups(updatedGroups);
|
|
124
110
|
};
|
|
125
111
|
|
|
126
|
-
const setRoute = (path: string) =>
|
|
112
|
+
const setRoute = (path: string) => setHistoryPush(path);
|
|
127
113
|
const modalText = (
|
|
128
114
|
<>
|
|
129
115
|
Some analytics <strong>are not saved</strong>.{" "}
|
|
@@ -137,7 +123,7 @@ const Analytics = (): JSX.Element => {
|
|
|
137
123
|
return (
|
|
138
124
|
<>
|
|
139
125
|
<RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
|
|
140
|
-
<MainWrapper backLink={false} title="Analytics Settings" rightButton={rightButtonProps}
|
|
126
|
+
<MainWrapper backLink={false} title="Analytics Settings" rightButton={rightButtonProps}>
|
|
141
127
|
<ErrorToast />
|
|
142
128
|
<S.Wrapper>
|
|
143
129
|
<S.FormWrapper>
|
|
@@ -200,7 +186,30 @@ const Analytics = (): JSX.Element => {
|
|
|
200
186
|
);
|
|
201
187
|
};
|
|
202
188
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
189
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
190
|
+
isSaving: state.app.isSaving,
|
|
191
|
+
isLoading: state.app.isLoading,
|
|
192
|
+
analytics: state.analytics,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const mapDispatchToProps = {
|
|
196
|
+
setHistoryPush: appActions.setHistoryPush,
|
|
197
|
+
getAnalytics: analyticsActions.getAnalytics,
|
|
198
|
+
updateAnalytics: analyticsActions.updateAnalytics,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
interface IAnalyticsProps {
|
|
202
|
+
isSaving: boolean;
|
|
203
|
+
isLoading: boolean;
|
|
204
|
+
analytics: IAnalytics;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface IDispatchProps {
|
|
208
|
+
getAnalytics(siteId?: number | null): Promise<void>;
|
|
209
|
+
setHistoryPush(path: string, isEditor?: boolean): void;
|
|
210
|
+
updateAnalytics(analyticsState: IAnalytics, siteId?: number | null): Promise<boolean>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
type IProps = IAnalyticsProps & IDispatchProps;
|
|
214
|
+
|
|
215
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Analytics);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
|
-
import { Switch, Route, matchPath
|
|
3
|
+
import { Switch, Route, matchPath } from "react-router-dom";
|
|
4
4
|
|
|
5
5
|
import { ErrorGuard } from "@ax/guards";
|
|
6
6
|
import type { IRootState, IUser } from "@ax/types";
|
|
@@ -17,10 +17,7 @@ import Logout from "./Logout";
|
|
|
17
17
|
import * as S from "./style";
|
|
18
18
|
|
|
19
19
|
const Routing = (props: IProps) => {
|
|
20
|
-
const { token, currentUser, globalSettings, setHistoryPush, logout } = props;
|
|
21
|
-
|
|
22
|
-
// Was `state.router.location.pathname` from connected-react-router's router slice.
|
|
23
|
-
const { pathname: path } = useLocation();
|
|
20
|
+
const { path, token, currentUser, globalSettings, setHistoryPush, logout } = props;
|
|
24
21
|
|
|
25
22
|
const { useForms } = globalSettings;
|
|
26
23
|
|
|
@@ -115,6 +112,7 @@ const Routing = (props: IProps) => {
|
|
|
115
112
|
};
|
|
116
113
|
|
|
117
114
|
const mapStateToProps = (state: IRootState) => ({
|
|
115
|
+
path: state.router.location.pathname,
|
|
118
116
|
token: state.app.token,
|
|
119
117
|
currentUser: state.users.currentUser,
|
|
120
118
|
globalSettings: state.app.globalSettings,
|
|
@@ -126,6 +124,7 @@ interface IDispatchProps {
|
|
|
126
124
|
}
|
|
127
125
|
|
|
128
126
|
interface IStateProps {
|
|
127
|
+
path?: string;
|
|
129
128
|
token: string;
|
|
130
129
|
currentUser: IUser | null;
|
|
131
130
|
globalSettings: IGlobalSettings;
|
|
@@ -605,7 +605,7 @@ const FileDrive = (props: IProps) => {
|
|
|
605
605
|
);
|
|
606
606
|
|
|
607
607
|
return (
|
|
608
|
-
<MainWrapper backLink={false} title="File Drive Manager" rightButton={rightButtonProps}
|
|
608
|
+
<MainWrapper backLink={false} title="File Drive Manager" rightButton={rightButtonProps}>
|
|
609
609
|
<S.Wrapper ref={wrapperRef}>
|
|
610
610
|
<S.FolderPanel
|
|
611
611
|
isOpen={isPanelOpen}
|
|
@@ -26,7 +26,7 @@ import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
|
26
26
|
import { usersActions } from "@ax/containers/Users";
|
|
27
27
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
28
28
|
import { dateToString, getDefaultTheme } from "@ax/helpers";
|
|
29
|
-
import { useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
29
|
+
import { useEditingHeartbeat, useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
30
30
|
import type {
|
|
31
31
|
HeadingFilter,
|
|
32
32
|
IErrorItem,
|
|
@@ -77,6 +77,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
77
77
|
schemaVersion,
|
|
78
78
|
updatePageAccessGrants,
|
|
79
79
|
accessGrants,
|
|
80
|
+
sendPagePing,
|
|
80
81
|
} = props;
|
|
81
82
|
|
|
82
83
|
const isAllowedTo = usePermissionsForPage(
|
|
@@ -153,7 +154,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
153
154
|
|
|
154
155
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
155
156
|
useEffect(() => {
|
|
156
|
-
const {
|
|
157
|
+
const { setStructuredDataFilter } = props;
|
|
157
158
|
|
|
158
159
|
editorContent?.structuredData && setStructuredDataFilter(editorContent.structuredData);
|
|
159
160
|
const handleGetPage = async () => await getPage(pageID, true);
|
|
@@ -163,13 +164,10 @@ const GlobalEditor = (props: IProps) => {
|
|
|
163
164
|
if (!pageID) {
|
|
164
165
|
setIsDirty(false);
|
|
165
166
|
}
|
|
166
|
-
|
|
167
|
-
const interval = setInterval(() => {
|
|
168
|
-
pageID && sendPagePing(pageID);
|
|
169
|
-
}, 30000);
|
|
170
|
-
return () => clearInterval(interval);
|
|
171
167
|
}, []);
|
|
172
168
|
|
|
169
|
+
useEditingHeartbeat(pageID, sendPagePing);
|
|
170
|
+
|
|
173
171
|
useEffect(() => {
|
|
174
172
|
setSelectedTab(defaultTab);
|
|
175
173
|
}, [defaultTab]);
|
|
@@ -181,7 +179,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
181
179
|
|
|
182
180
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
183
181
|
useEffect(() => {
|
|
184
|
-
const {
|
|
182
|
+
const { currentUserID } = props;
|
|
185
183
|
if (userEditing && userEditing.id !== currentUserID) {
|
|
186
184
|
setIsReadOnly(true);
|
|
187
185
|
!isOpen("userEditing") && toggleModal("userEditing");
|
|
@@ -1,31 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
4
|
import { ErrorToast, Loading, MainWrapper, Nav } from "@ax/components";
|
|
4
5
|
import { appActions } from "@ax/containers/App";
|
|
5
6
|
import { domainsActions } from "@ax/containers/Domains";
|
|
6
7
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
7
8
|
import { useIsDirty } from "@ax/hooks";
|
|
8
|
-
import {
|
|
9
|
-
import type { IDomainRobot, INavItem } from "@ax/types";
|
|
9
|
+
import type { IDomainRobot, INavItem, IRootState } from "@ax/types";
|
|
10
10
|
|
|
11
11
|
import Item from "./Item";
|
|
12
12
|
|
|
13
13
|
import * as S from "./style";
|
|
14
14
|
|
|
15
15
|
const Robots = (props: IProps): JSX.Element => {
|
|
16
|
-
const {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
const {
|
|
17
|
+
isSaving,
|
|
18
|
+
isLoading,
|
|
19
|
+
navItems,
|
|
20
|
+
currentNavItem,
|
|
21
|
+
robots,
|
|
22
|
+
getDomainsRobots,
|
|
23
|
+
setHistoryPush,
|
|
24
|
+
updateDomainRobots,
|
|
25
|
+
} = props;
|
|
22
26
|
|
|
23
27
|
const [robotItems, setRobotItems] = useState(robots);
|
|
24
28
|
const { isDirty, setIsDirty, resetDirty } = useIsDirty(robotItems);
|
|
25
29
|
|
|
26
30
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
27
31
|
useEffect(() => {
|
|
28
|
-
|
|
32
|
+
getDomainsRobots();
|
|
29
33
|
resetDirty();
|
|
30
34
|
}, []);
|
|
31
35
|
|
|
@@ -34,7 +38,7 @@ const Robots = (props: IProps): JSX.Element => {
|
|
|
34
38
|
}, [robots]);
|
|
35
39
|
|
|
36
40
|
const handleSave = async () => {
|
|
37
|
-
const isSaved = await
|
|
41
|
+
const isSaved = await updateDomainRobots(robotItems);
|
|
38
42
|
if (isSaved) {
|
|
39
43
|
setIsDirty(false);
|
|
40
44
|
}
|
|
@@ -47,23 +51,22 @@ const Robots = (props: IProps): JSX.Element => {
|
|
|
47
51
|
};
|
|
48
52
|
|
|
49
53
|
const handleMenuClick = (path: string) => {
|
|
50
|
-
|
|
54
|
+
setHistoryPush(path);
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
const mapItemList = (items: IDomainRobot[]) =>
|
|
54
58
|
Array.isArray(items) &&
|
|
55
59
|
items.map((item: IDomainRobot, i: number) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
setRobotItems((current) => current.map((it, index) => (index === i ? { ...it, content: newContent } : it)));
|
|
60
|
+
const handleSetItem = (newContent: string) => {
|
|
61
|
+
const newItems = [...robotItems];
|
|
62
|
+
newItems[i].content = newContent;
|
|
63
|
+
setRobotItems(newItems);
|
|
64
|
+
};
|
|
62
65
|
|
|
63
66
|
return <Item key={`${item.path}${i}`} item={item} setItemContent={handleSetItem} />;
|
|
64
67
|
});
|
|
65
68
|
|
|
66
|
-
const setRoute = (path: string) =>
|
|
69
|
+
const setRoute = (path: string) => setHistoryPush(path);
|
|
67
70
|
const modalText = (
|
|
68
71
|
<>
|
|
69
72
|
Some robots <strong>are not saved</strong>.{" "}
|
|
@@ -73,7 +76,7 @@ const Robots = (props: IProps): JSX.Element => {
|
|
|
73
76
|
return (
|
|
74
77
|
<>
|
|
75
78
|
<RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
|
|
76
|
-
<MainWrapper backLink={false} title="SEO Settings" rightButton={rightButtonProps}
|
|
79
|
+
<MainWrapper backLink={false} title="SEO Settings" rightButton={rightButtonProps}>
|
|
77
80
|
<S.Wrapper>
|
|
78
81
|
<Nav current={currentNavItem} items={navItems} onClick={handleMenuClick} />
|
|
79
82
|
<S.ContentWrapper>
|
|
@@ -90,11 +93,31 @@ const Robots = (props: IProps): JSX.Element => {
|
|
|
90
93
|
);
|
|
91
94
|
};
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
97
|
+
isSaving: state.app.isSaving,
|
|
98
|
+
isLoading: state.app.isLoading,
|
|
99
|
+
robots: state.domains.robots,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const mapDispatchToProps = {
|
|
103
|
+
setHistoryPush: appActions.setHistoryPush,
|
|
104
|
+
getDomainsRobots: domainsActions.getDomainsRobots,
|
|
105
|
+
updateDomainRobots: domainsActions.updateDomainsRobots,
|
|
106
|
+
};
|
|
107
|
+
interface IRobotsProps {
|
|
108
|
+
isSaving: boolean;
|
|
109
|
+
isLoading: boolean;
|
|
94
110
|
navItems: INavItem[];
|
|
95
111
|
currentNavItem: INavItem;
|
|
112
|
+
robots: IDomainRobot[];
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
interface IDispatchProps {
|
|
116
|
+
getDomainsRobots(): void;
|
|
117
|
+
setHistoryPush(path: string, isEditor?: boolean): void;
|
|
118
|
+
updateDomainRobots(robots: IDomainRobot[]): Promise<boolean>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
type IProps = IRobotsProps & IDispatchProps;
|
|
122
|
+
|
|
123
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Robots);
|
|
@@ -623,7 +623,7 @@ const MediaGallery = (props: IProps) => {
|
|
|
623
623
|
);
|
|
624
624
|
|
|
625
625
|
return (
|
|
626
|
-
<MainWrapper backLink={false} title="Media Gallery" rightButton={rightButtonProps}
|
|
626
|
+
<MainWrapper backLink={false} title="Media Gallery" rightButton={rightButtonProps}>
|
|
627
627
|
<S.Wrapper ref={wrapperRef}>
|
|
628
628
|
<S.FolderPanel
|
|
629
629
|
isOpen={isPanelOpen}
|
|
@@ -24,7 +24,7 @@ import { pageStatus } from "@ax/containers/PageEditor/interfaces";
|
|
|
24
24
|
import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
|
|
25
25
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
26
26
|
import { dateToString, getDeactivatedModules, isModuleDisabled } from "@ax/helpers";
|
|
27
|
-
import { useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
27
|
+
import { useEditingHeartbeat, useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
28
28
|
import type {
|
|
29
29
|
HeadingFilter,
|
|
30
30
|
IErrorItem,
|
|
@@ -80,6 +80,7 @@ const PageEditor = (props: IProps) => {
|
|
|
80
80
|
currentSiteInfo,
|
|
81
81
|
updatePageAccessGrants,
|
|
82
82
|
accessGrants,
|
|
83
|
+
sendPagePing,
|
|
83
84
|
} = props;
|
|
84
85
|
|
|
85
86
|
const isAllowedTo = usePermissionsForPage(
|
|
@@ -158,8 +159,6 @@ const PageEditor = (props: IProps) => {
|
|
|
158
159
|
|
|
159
160
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
160
161
|
useEffect(() => {
|
|
161
|
-
const { pageID, getPage, sendPagePing } = props;
|
|
162
|
-
|
|
163
162
|
const handleGetPage = async () => {
|
|
164
163
|
if (isNewTranslation) {
|
|
165
164
|
await getDefaults();
|
|
@@ -175,20 +174,17 @@ const PageEditor = (props: IProps) => {
|
|
|
175
174
|
if (!pageID) {
|
|
176
175
|
setIsDirty(false);
|
|
177
176
|
}
|
|
178
|
-
|
|
179
|
-
const interval = setInterval(() => {
|
|
180
|
-
pageID && sendPagePing(pageID);
|
|
181
|
-
}, 30000);
|
|
182
|
-
return () => clearInterval(interval);
|
|
183
177
|
}, []);
|
|
184
178
|
|
|
179
|
+
useEditingHeartbeat(pageID, sendPagePing);
|
|
180
|
+
|
|
185
181
|
useEffect(() => {
|
|
186
182
|
setSelectedTab(defaultTab);
|
|
187
183
|
}, [defaultTab]);
|
|
188
184
|
|
|
189
185
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
190
186
|
useEffect(() => {
|
|
191
|
-
const {
|
|
187
|
+
const { currentUserID } = props;
|
|
192
188
|
if (userEditing && userEditing.id !== currentUserID) {
|
|
193
189
|
setIsReadOnly(true);
|
|
194
190
|
!isOpen("userEditing") && toggleModal("userEditing");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
4
|
import { CheckField, ContextMenu, ElementsTooltip } from "@ax/components";
|
|
4
5
|
import { redirectsActions } from "@ax/containers/Redirects";
|
|
5
6
|
import { useContextMenu, useModals } from "@ax/hooks";
|
|
6
|
-
import {
|
|
7
|
-
import type { ICheck, IRedirect } from "@ax/types";
|
|
7
|
+
import type { ICheck, IRedirect, IRootState } from "@ax/types";
|
|
8
8
|
|
|
9
9
|
import { format } from "date-fns";
|
|
10
10
|
|
|
@@ -13,11 +13,12 @@ import RedirectPanel from "../RedirectPanel";
|
|
|
13
13
|
|
|
14
14
|
import * as S from "./style";
|
|
15
15
|
|
|
16
|
-
const RedirectItem = (props:
|
|
16
|
+
const RedirectItem = (props: IRedirectItemProps): JSX.Element => {
|
|
17
17
|
const {
|
|
18
18
|
redirect,
|
|
19
19
|
isSelected,
|
|
20
20
|
onChange,
|
|
21
|
+
deleteRedirect,
|
|
21
22
|
toggleToast,
|
|
22
23
|
setFormValues,
|
|
23
24
|
formValues,
|
|
@@ -25,10 +26,9 @@ const RedirectItem = (props: IProps): JSX.Element => {
|
|
|
25
26
|
currentFilter,
|
|
26
27
|
isSiteItem,
|
|
27
28
|
hoverCheck,
|
|
29
|
+
isSaving,
|
|
28
30
|
} = props;
|
|
29
31
|
|
|
30
|
-
const dispatch = useAppDispatch();
|
|
31
|
-
const isSaving = useAppSelector((state) => state.app.isSaving);
|
|
32
32
|
const { isOpen, toggleModal } = useModals(["edit", "delete"]);
|
|
33
33
|
const { contextMenu, handleContextMenu, closeContextMenu } = useContextMenu();
|
|
34
34
|
const [isOpenedSecond, setIsOpenedSecond] = useState(false);
|
|
@@ -47,9 +47,7 @@ const RedirectItem = (props: IProps): JSX.Element => {
|
|
|
47
47
|
const removeItem = async () => {
|
|
48
48
|
try {
|
|
49
49
|
if (redirect.id) {
|
|
50
|
-
const deleted = await
|
|
51
|
-
redirectsActions.deleteRedirect({ redirectID: redirect.id, filter: currentFilter }),
|
|
52
|
-
).unwrap();
|
|
50
|
+
const deleted = await deleteRedirect(redirect.id, currentFilter);
|
|
53
51
|
if (deleted) {
|
|
54
52
|
toggleToast();
|
|
55
53
|
}
|
|
@@ -150,6 +148,21 @@ interface IProps {
|
|
|
150
148
|
currentFilter: string;
|
|
151
149
|
isSiteItem: boolean;
|
|
152
150
|
hoverCheck: boolean;
|
|
151
|
+
isSaving: boolean;
|
|
153
152
|
}
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
interface IDispatchProps {
|
|
155
|
+
deleteRedirect(redirectID: number, filter?: string): Promise<boolean>;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
type IRedirectItemProps = IProps & IDispatchProps;
|
|
159
|
+
|
|
160
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
161
|
+
isSaving: state.app.isSaving,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const mapDispatchToProps = {
|
|
165
|
+
deleteRedirect: redirectsActions.deleteRedirect,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export default connect(mapStateToProps, mapDispatchToProps)(RedirectItem);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
4
|
import type { IRedirect } from "@ax/types";
|
|
4
5
|
import { Button, FieldsBehavior, FloatingPanel } from "@ax/components";
|
|
5
6
|
import { redirectsActions } from "@ax/containers/Redirects";
|
|
6
|
-
import { useAppDispatch } from "@ax/store";
|
|
7
7
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
@@ -15,13 +15,12 @@ const RedirectPanel = (props: IProps): JSX.Element => {
|
|
|
15
15
|
isOpenedSecond,
|
|
16
16
|
toggleSecondaryPanel,
|
|
17
17
|
addRedirect,
|
|
18
|
+
updateRedirect,
|
|
18
19
|
formValues,
|
|
19
20
|
setFormValues,
|
|
20
21
|
currentFilter,
|
|
21
22
|
} = props;
|
|
22
23
|
|
|
23
|
-
const dispatch = useAppDispatch();
|
|
24
|
-
|
|
25
24
|
const handleOldUrl = (newValue: string) => setFormValues({ ...formValues, from: newValue });
|
|
26
25
|
|
|
27
26
|
const handleNewUrl = (newValue: any) => {
|
|
@@ -35,14 +34,7 @@ const RedirectPanel = (props: IProps): JSX.Element => {
|
|
|
35
34
|
|
|
36
35
|
const editItemAction = async () => {
|
|
37
36
|
const toPage = formValues.to.pageId ? formValues.to.pageId : formValues.to.url;
|
|
38
|
-
formValues.id &&
|
|
39
|
-
(await dispatch(
|
|
40
|
-
redirectsActions.updateRedirect({
|
|
41
|
-
redirect: { from: formValues.from, to: toPage },
|
|
42
|
-
redirectID: formValues.id,
|
|
43
|
-
filter: currentFilter,
|
|
44
|
-
}),
|
|
45
|
-
));
|
|
37
|
+
formValues.id && (await updateRedirect({ from: formValues.from, to: toPage }, formValues.id, currentFilter));
|
|
46
38
|
toggleModal();
|
|
47
39
|
};
|
|
48
40
|
|
|
@@ -105,7 +97,10 @@ const RedirectPanel = (props: IProps): JSX.Element => {
|
|
|
105
97
|
);
|
|
106
98
|
};
|
|
107
99
|
|
|
108
|
-
|
|
100
|
+
const mapDispatchToProps = {
|
|
101
|
+
updateRedirect: redirectsActions.updateRedirect,
|
|
102
|
+
};
|
|
103
|
+
interface ICategoryPanelProps {
|
|
109
104
|
isOpen: boolean;
|
|
110
105
|
isOpenedSecond: boolean;
|
|
111
106
|
toggleSecondaryPanel(): any;
|
|
@@ -114,7 +109,13 @@ interface IProps {
|
|
|
114
109
|
formValues: IRedirect;
|
|
115
110
|
setFormValues(redirect: IRedirect): void;
|
|
116
111
|
currentFilter: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface IDispatchProps {
|
|
117
115
|
addRedirect(force?: boolean): void;
|
|
116
|
+
updateRedirect(redirect: { from: string; to: string | number }, redirectID: number, filter?: string): Promise<void>;
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
|
|
119
|
+
type IProps = ICategoryPanelProps & IDispatchProps;
|
|
120
|
+
|
|
121
|
+
export default connect(null, mapDispatchToProps)(RedirectPanel);
|