@griddo/ax 1.75.0 → 1.75.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/package.json +2 -2
- package/src/__tests__/components/Fields/ToggleField/ToggleField.test.tsx +2 -2
- package/src/components/Fields/NumberField/index.tsx +13 -10
- package/src/components/Fields/SliderField/index.tsx +3 -3
- package/src/components/Fields/ToggleField/index.tsx +4 -5
- package/src/containers/App/actions.tsx +31 -4
- package/src/containers/App/constants.tsx +15 -13
- package/src/containers/App/interfaces.tsx +13 -2
- package/src/containers/App/reducer.tsx +4 -0
- package/src/modules/Content/index.tsx +4 -0
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +0 -1
- package/src/modules/StructuredData/StructuredDataList/index.tsx +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "1.75.
|
|
4
|
+
"version": "1.75.2",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -229,5 +229,5 @@
|
|
|
229
229
|
"publishConfig": {
|
|
230
230
|
"access": "public"
|
|
231
231
|
},
|
|
232
|
-
"gitHead": "
|
|
232
|
+
"gitHead": "f2d7e58bd884b6fb5472d1127975fd806f936e17"
|
|
233
233
|
}
|
|
@@ -23,7 +23,7 @@ describe("ToggleField component rendering", () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
it("should render input as checked", () => {
|
|
26
|
-
defaultProps.
|
|
26
|
+
defaultProps.value = true;
|
|
27
27
|
|
|
28
28
|
render(
|
|
29
29
|
<ThemeProvider theme={parseTheme(globalTheme)}>
|
|
@@ -64,7 +64,7 @@ describe("ToggleField component rendering", () => {
|
|
|
64
64
|
|
|
65
65
|
describe("onClick events", () => {
|
|
66
66
|
it("should call onChange function with value true", () => {
|
|
67
|
-
defaultProps.
|
|
67
|
+
defaultProps.value = false;
|
|
68
68
|
defaultProps.onChange = jest.fn();
|
|
69
69
|
|
|
70
70
|
render(
|
|
@@ -4,9 +4,11 @@ import { Icon } from "@ax/components";
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const NumberField = (props: INumberFieldProps): JSX.Element => {
|
|
7
|
-
const { name, value, error, onChange, onBlur, maxValue, minValue, disabled, handleValidation } = props;
|
|
7
|
+
const { name, value, error, onChange, onBlur, maxValue, minValue, disabled, handleValidation, min, max } = props;
|
|
8
8
|
|
|
9
9
|
const strValue = value ? value.toString() : "0";
|
|
10
|
+
const safeMax = typeof max !== "undefined" ? max : maxValue;
|
|
11
|
+
const safeMin = typeof min !== "undefined" ? min : minValue;
|
|
10
12
|
|
|
11
13
|
const [inputValue, setInputValue] = useState(strValue);
|
|
12
14
|
|
|
@@ -25,9 +27,8 @@ const NumberField = (props: INumberFieldProps): JSX.Element => {
|
|
|
25
27
|
const currentValue = parseFloat(inputValue);
|
|
26
28
|
|
|
27
29
|
let updatedValue = currentValue ? currentValue : 0;
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
const isMax = updatedValue === maxValue;
|
|
30
|
+
const isMin = updatedValue === safeMin;
|
|
31
|
+
const isMax = updatedValue === safeMax;
|
|
31
32
|
|
|
32
33
|
if (pressedKey === "ArrowUp" && !isMax) {
|
|
33
34
|
updatedValue++;
|
|
@@ -40,8 +41,8 @@ const NumberField = (props: INumberFieldProps): JSX.Element => {
|
|
|
40
41
|
handleValidation && handleValidation(updatedValue.toString(), validators);
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
let validators: Record<string, unknown> =
|
|
44
|
-
validators =
|
|
44
|
+
let validators: Record<string, unknown> = safeMax ? { maxValue: safeMax } : {};
|
|
45
|
+
validators = safeMin ? { ...validators, minValue: safeMin } : validators;
|
|
45
46
|
|
|
46
47
|
const handleOnBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
47
48
|
setValue(e.target.value, e.type);
|
|
@@ -65,8 +66,8 @@ const NumberField = (props: INumberFieldProps): JSX.Element => {
|
|
|
65
66
|
onChange={handleChange}
|
|
66
67
|
onBlur={handleOnBlur}
|
|
67
68
|
error={error}
|
|
68
|
-
min={
|
|
69
|
-
max={
|
|
69
|
+
min={safeMin}
|
|
70
|
+
max={safeMax}
|
|
70
71
|
disabled={disabled}
|
|
71
72
|
data-testid="input"
|
|
72
73
|
/>
|
|
@@ -87,8 +88,10 @@ export interface INumberFieldProps {
|
|
|
87
88
|
onChange: (value: number) => void;
|
|
88
89
|
name?: string;
|
|
89
90
|
error?: boolean;
|
|
90
|
-
minValue?: number;
|
|
91
|
-
maxValue?: number;
|
|
91
|
+
minValue?: number; // to deprecate
|
|
92
|
+
maxValue?: number; // to deprecate
|
|
93
|
+
min?: number;
|
|
94
|
+
max?: number;
|
|
92
95
|
onClickIcon?: () => void;
|
|
93
96
|
onBlur?: (value: number) => void;
|
|
94
97
|
disabled?: boolean;
|
|
@@ -6,7 +6,7 @@ const SliderField = (props: ITextFieldProps): JSX.Element => {
|
|
|
6
6
|
const { value, min = 0, max = 100, defaultValue = min, step, prefix, suffix, onChange } = props;
|
|
7
7
|
const bubbleRef = useRef<HTMLOutputElement>(null);
|
|
8
8
|
|
|
9
|
-
const val = typeof value === "undefined" ? defaultValue : value;
|
|
9
|
+
const val = typeof value === "undefined" || value === null ? defaultValue : value;
|
|
10
10
|
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
onChange(Number(val));
|
|
@@ -37,14 +37,14 @@ const SliderField = (props: ITextFieldProps): JSX.Element => {
|
|
|
37
37
|
{val}
|
|
38
38
|
{suffix && ` ${suffix}`}
|
|
39
39
|
</S.Bubble>
|
|
40
|
-
<S.Input data-testid="inputComponent" value={
|
|
40
|
+
<S.Input data-testid="inputComponent" value={val} min={min} max={max} step={step} onChange={handleChange} />
|
|
41
41
|
</S.Slider>
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
export interface ITextFieldProps {
|
|
46
46
|
title: string;
|
|
47
|
-
value: number;
|
|
47
|
+
value: number | undefined | null;
|
|
48
48
|
defaultValue?: number;
|
|
49
49
|
min: number;
|
|
50
50
|
max: number;
|
|
@@ -3,7 +3,7 @@ import React from "react";
|
|
|
3
3
|
import * as S from "./style";
|
|
4
4
|
|
|
5
5
|
const ToggleField = (props: IToggleFieldProps): JSX.Element => {
|
|
6
|
-
const { name, value, disabled,
|
|
6
|
+
const { name, value, disabled, onChange } = props;
|
|
7
7
|
|
|
8
8
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
9
9
|
const isChecked = e.target.checked;
|
|
@@ -15,16 +15,16 @@ const ToggleField = (props: IToggleFieldProps): JSX.Element => {
|
|
|
15
15
|
return (
|
|
16
16
|
<S.Wrapper data-testid="toggle-field-wrapper">
|
|
17
17
|
<S.Input
|
|
18
|
-
id=
|
|
18
|
+
id={`toggle-${name}`}
|
|
19
19
|
type="checkbox"
|
|
20
20
|
name={name}
|
|
21
21
|
value={value || false}
|
|
22
|
-
checked={
|
|
22
|
+
checked={value || false}
|
|
23
23
|
disabled={disabled}
|
|
24
24
|
onChange={handleChange}
|
|
25
25
|
data-testid="toggle-field-input"
|
|
26
26
|
/>
|
|
27
|
-
<S.Label htmlFor=
|
|
27
|
+
<S.Label htmlFor={`toggle-${name}`} />
|
|
28
28
|
</S.Wrapper>
|
|
29
29
|
);
|
|
30
30
|
};
|
|
@@ -32,7 +32,6 @@ const ToggleField = (props: IToggleFieldProps): JSX.Element => {
|
|
|
32
32
|
export interface IToggleFieldProps {
|
|
33
33
|
name: string;
|
|
34
34
|
value: any;
|
|
35
|
-
checked?: boolean;
|
|
36
35
|
disabled?: boolean;
|
|
37
36
|
onChange?: (value: boolean) => void;
|
|
38
37
|
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Dispatch } from "redux";
|
|
2
|
+
import differenceInSeconds from "date-fns/differenceInSeconds";
|
|
3
|
+
|
|
4
|
+
import { isReqOk } from "@ax/helpers";
|
|
5
|
+
import { languages, global } from "@ax/api";
|
|
6
|
+
import { IRootState } from "@ax/types";
|
|
7
|
+
|
|
8
|
+
import history from "../../routes/history";
|
|
2
9
|
|
|
3
10
|
import {
|
|
4
11
|
SET_ERROR,
|
|
@@ -12,12 +19,9 @@ import {
|
|
|
12
19
|
SET_GLOBAL_LANGUAGES,
|
|
13
20
|
SET_GLOBAL_SETTINGS,
|
|
14
21
|
SET_USER,
|
|
22
|
+
SET_SESSION_STARTED_AT,
|
|
15
23
|
} from "./constants";
|
|
16
24
|
|
|
17
|
-
import { isReqOk } from "@ax/helpers";
|
|
18
|
-
import { languages, global } from "@ax/api";
|
|
19
|
-
|
|
20
|
-
import history from "../../routes/history";
|
|
21
25
|
import {
|
|
22
26
|
ISetIsLoading,
|
|
23
27
|
ISetIsSaving,
|
|
@@ -29,6 +33,7 @@ import {
|
|
|
29
33
|
ISetGlobalLanguages,
|
|
30
34
|
ISetGlobalSettings,
|
|
31
35
|
ISetUserAction,
|
|
36
|
+
ISetSessionStartedAtAction,
|
|
32
37
|
} from "./interfaces";
|
|
33
38
|
import { IError, IUser } from "./reducer";
|
|
34
39
|
|
|
@@ -97,6 +102,10 @@ function resetError(): ISetErrorAction {
|
|
|
97
102
|
return { type: RESET_ERROR, payload: { code: undefined, text: "" } };
|
|
98
103
|
}
|
|
99
104
|
|
|
105
|
+
function setSessionStartedAt(sessionStartedAt: Date): ISetSessionStartedAtAction {
|
|
106
|
+
return { type: SET_SESSION_STARTED_AT, payload: { sessionStartedAt } };
|
|
107
|
+
}
|
|
108
|
+
|
|
100
109
|
function handleError(response: any, isMultiple = false, msg?: string): (dispatch: Dispatch) => Promise<void> {
|
|
101
110
|
return async (dispatch) => {
|
|
102
111
|
if (typeof response === "string") {
|
|
@@ -139,6 +148,7 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
|
|
|
139
148
|
const langResponse: { status: number; data: any } = await languages.getLanguages(token);
|
|
140
149
|
isReqOk(langResponse.status) && dispatch(setGlobalLanguages(langResponse.data.items));
|
|
141
150
|
dispatch(setToken(loginResponse.data.token));
|
|
151
|
+
dispatch(setSessionStartedAt(new Date()));
|
|
142
152
|
setHistoryPush(welcomePageURI)(dispatch);
|
|
143
153
|
if (rememberMe) {
|
|
144
154
|
const user: any = { token: loginResponse.data.token };
|
|
@@ -178,6 +188,22 @@ function getGlobalSettings(): (dispatch: Dispatch) => Promise<void> {
|
|
|
178
188
|
};
|
|
179
189
|
}
|
|
180
190
|
|
|
191
|
+
function checkUserSession(): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
|
|
192
|
+
return async (dispatch, getState) => {
|
|
193
|
+
const {
|
|
194
|
+
app: { sessionStartedAt },
|
|
195
|
+
} = getState();
|
|
196
|
+
|
|
197
|
+
const timeSinceSessionStart = !!sessionStartedAt && differenceInSeconds(new Date(), new Date(sessionStartedAt));
|
|
198
|
+
const eightHoursInSeconds = 8 * 60 * 60;
|
|
199
|
+
const isSessionFinished = !!timeSinceSessionStart && timeSinceSessionStart > eightHoursInSeconds;
|
|
200
|
+
if (!timeSinceSessionStart || isSessionFinished) {
|
|
201
|
+
localStorage.removeItem("persist:root");
|
|
202
|
+
dispatch(setSessionStartedAt(new Date()));
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
181
207
|
export {
|
|
182
208
|
setError,
|
|
183
209
|
resetError,
|
|
@@ -194,4 +220,5 @@ export {
|
|
|
194
220
|
login,
|
|
195
221
|
getGlobalSettings,
|
|
196
222
|
setUser,
|
|
223
|
+
checkUserSession,
|
|
197
224
|
};
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
const NAME
|
|
1
|
+
const NAME = "app";
|
|
2
2
|
|
|
3
|
-
const SET_ERROR
|
|
4
|
-
const RESET_ERROR
|
|
5
|
-
const SET_IS_LOADING
|
|
6
|
-
const SET_IS_SAVING
|
|
7
|
-
const SET_TOKEN
|
|
8
|
-
const LOGOUT
|
|
9
|
-
const IS_LOGGING_IN
|
|
10
|
-
const SET_LANGUAGE
|
|
11
|
-
const SET_GLOBAL_LANGUAGES
|
|
12
|
-
const SET_GLOBAL_SETTINGS
|
|
13
|
-
const SET_USER
|
|
3
|
+
const SET_ERROR = `${NAME}/SET_ERROR`;
|
|
4
|
+
const RESET_ERROR = `${NAME}/RESET_ERROR`;
|
|
5
|
+
const SET_IS_LOADING = `${NAME}/SET_IS_LOADING`;
|
|
6
|
+
const SET_IS_SAVING = `${NAME}/SET_IS_SAVING`;
|
|
7
|
+
const SET_TOKEN = `${NAME}/SET_TOKEN`;
|
|
8
|
+
const LOGOUT = `${NAME}/LOGOUT`;
|
|
9
|
+
const IS_LOGGING_IN = `${NAME}/IS_LOGGING_IN`;
|
|
10
|
+
const SET_LANGUAGE = `${NAME}/SET_LANGUAGE`;
|
|
11
|
+
const SET_GLOBAL_LANGUAGES = `${NAME}/SET_GLOBAL_LANGUAGES`;
|
|
12
|
+
const SET_GLOBAL_SETTINGS = `${NAME}/SET_GLOBAL_SETTINGS`;
|
|
13
|
+
const SET_USER = `${NAME}/SET_USER`;
|
|
14
|
+
const SET_SESSION_STARTED_AT = `${NAME}/SET_SESSION_STARTED_AT`;
|
|
14
15
|
|
|
15
16
|
export {
|
|
16
17
|
SET_ERROR,
|
|
@@ -23,5 +24,6 @@ export {
|
|
|
23
24
|
SET_LANGUAGE,
|
|
24
25
|
SET_GLOBAL_LANGUAGES,
|
|
25
26
|
SET_GLOBAL_SETTINGS,
|
|
26
|
-
SET_USER
|
|
27
|
+
SET_USER,
|
|
28
|
+
SET_SESSION_STARTED_AT,
|
|
27
29
|
};
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
SET_LANGUAGE,
|
|
9
9
|
SET_GLOBAL_LANGUAGES,
|
|
10
10
|
SET_GLOBAL_SETTINGS,
|
|
11
|
-
SET_USER
|
|
11
|
+
SET_USER,
|
|
12
|
+
SET_SESSION_STARTED_AT,
|
|
12
13
|
} from "./constants";
|
|
13
14
|
import { IUser } from "./reducer";
|
|
14
15
|
|
|
@@ -64,6 +65,16 @@ export interface ISetUserAction {
|
|
|
64
65
|
payload: { user: IUser };
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
export interface ISetSessionStartedAtAction {
|
|
69
|
+
type: typeof SET_SESSION_STARTED_AT;
|
|
70
|
+
payload: { sessionStartedAt: null | Date };
|
|
71
|
+
}
|
|
72
|
+
|
|
67
73
|
export type AppActionsCreators = ISetIsLoading & ISetIsSaving;
|
|
68
74
|
|
|
69
|
-
export type AuthActionsCreators = ISetTokenAction &
|
|
75
|
+
export type AuthActionsCreators = ISetTokenAction &
|
|
76
|
+
ILogoutAction &
|
|
77
|
+
ISetErrorAction &
|
|
78
|
+
IIsLoggingInAction &
|
|
79
|
+
ISetUserAction &
|
|
80
|
+
ISetSessionStartedAtAction;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
SET_GLOBAL_LANGUAGES,
|
|
12
12
|
SET_GLOBAL_SETTINGS,
|
|
13
13
|
SET_USER,
|
|
14
|
+
SET_SESSION_STARTED_AT,
|
|
14
15
|
} from "./constants";
|
|
15
16
|
|
|
16
17
|
export interface IAppState {
|
|
@@ -24,6 +25,7 @@ export interface IAppState {
|
|
|
24
25
|
lang: { locale: string; id: any };
|
|
25
26
|
globalLangs: any;
|
|
26
27
|
globalSettings: IGlobalSettings;
|
|
28
|
+
sessionStartedAt: null | Date;
|
|
27
29
|
}
|
|
28
30
|
export interface IError {
|
|
29
31
|
code?: any;
|
|
@@ -75,6 +77,7 @@ export const initialState = {
|
|
|
75
77
|
welcomeText1: "",
|
|
76
78
|
welcomeText2: "",
|
|
77
79
|
},
|
|
80
|
+
sessionStartedAt: null,
|
|
78
81
|
};
|
|
79
82
|
|
|
80
83
|
export function reducer(state = initialState, action: any): IAppState {
|
|
@@ -90,6 +93,7 @@ export function reducer(state = initialState, action: any): IAppState {
|
|
|
90
93
|
case SET_GLOBAL_LANGUAGES:
|
|
91
94
|
case SET_GLOBAL_SETTINGS:
|
|
92
95
|
case SET_USER:
|
|
96
|
+
case SET_SESSION_STARTED_AT:
|
|
93
97
|
return { ...state, ...action.payload };
|
|
94
98
|
case SET_ERROR:
|
|
95
99
|
case RESET_ERROR:
|
|
@@ -101,6 +101,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
101
101
|
setContentFilters,
|
|
102
102
|
contentFilters,
|
|
103
103
|
deleteAndRemoveFromSiteBulk,
|
|
104
|
+
checkUserSession,
|
|
104
105
|
} = props;
|
|
105
106
|
|
|
106
107
|
const itemsPerPage = 50;
|
|
@@ -260,6 +261,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
260
261
|
const fetchSitesByLang = async () => await getSitesByLang(params);
|
|
261
262
|
|
|
262
263
|
useEffect(() => {
|
|
264
|
+
checkUserSession();
|
|
263
265
|
if (!locationState || locationState.isFromEditor !== true) {
|
|
264
266
|
setFilter("unique-pages");
|
|
265
267
|
}
|
|
@@ -823,6 +825,7 @@ interface IDispatchProps {
|
|
|
823
825
|
getSitesByLang(params: IGetSitesParams): Promise<void>;
|
|
824
826
|
setContentFilters(contentFilters: Record<string, string> | null): void;
|
|
825
827
|
deleteAndRemoveFromSiteBulk(pageIds: number[], globalPageIds: number[]): Promise<boolean>;
|
|
828
|
+
checkUserSession(): Promise<void>;
|
|
826
829
|
}
|
|
827
830
|
|
|
828
831
|
const mapDispatchToProps = {
|
|
@@ -857,6 +860,7 @@ const mapDispatchToProps = {
|
|
|
857
860
|
getSitesByLang: sitesActions.getSitesByLang,
|
|
858
861
|
setContentFilters: sitesActions.setContentFilters,
|
|
859
862
|
deleteAndRemoveFromSiteBulk: sitesActions.deleteAndRemoveFromSiteBulk,
|
|
863
|
+
checkUserSession: appActions.checkUserSession,
|
|
860
864
|
};
|
|
861
865
|
|
|
862
866
|
interface IPagesProps {
|
|
@@ -167,7 +167,6 @@ const Form = (props: IProps): JSX.Element => {
|
|
|
167
167
|
name="defaultParent"
|
|
168
168
|
fieldType="ToggleField"
|
|
169
169
|
value={(configFormData && configFormData.modifiableOnPage) || false}
|
|
170
|
-
checked={(configFormData && configFormData.modifiableOnPage) || false}
|
|
171
170
|
onChange={setModifiableOnPage}
|
|
172
171
|
/>
|
|
173
172
|
<FieldsBehavior
|
|
@@ -89,6 +89,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
89
89
|
skipReviewOnPublish,
|
|
90
90
|
setContentFilters,
|
|
91
91
|
contentFilters,
|
|
92
|
+
checkUserSession,
|
|
92
93
|
} = props;
|
|
93
94
|
|
|
94
95
|
const itemsPerPage = 50;
|
|
@@ -297,6 +298,7 @@ const StructuredDataList = (props: IProps): JSX.Element => {
|
|
|
297
298
|
}, [isLoading, currentSitePages, currentDataContent]);
|
|
298
299
|
|
|
299
300
|
useEffect(() => {
|
|
301
|
+
checkUserSession();
|
|
300
302
|
getAnalytics();
|
|
301
303
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
302
304
|
}, []);
|
|
@@ -669,6 +671,7 @@ const mapDispatchToProps = {
|
|
|
669
671
|
setCurrentDataID: structuredDataActions.setCurrentDataID,
|
|
670
672
|
resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
|
|
671
673
|
setContentFilters: structuredDataActions.setContentFilters,
|
|
674
|
+
checkUserSession: appActions.checkUserSession,
|
|
672
675
|
};
|
|
673
676
|
|
|
674
677
|
interface IDispatchProps {
|
|
@@ -694,6 +697,7 @@ interface IDispatchProps {
|
|
|
694
697
|
setCurrentDataID(id: number | null): void;
|
|
695
698
|
resetCurrentSiteErrorPages: () => Promise<void>;
|
|
696
699
|
setContentFilters(contentFilters: Record<string, IStructuredDataQueryValues> | null): void;
|
|
700
|
+
checkUserSession(): Promise<void>;
|
|
697
701
|
}
|
|
698
702
|
|
|
699
703
|
interface ICategoriesProps {
|