@griddo/ax 11.10.23 → 11.10.24

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 (58) hide show
  1. package/config/griddo-config/index.js +1 -0
  2. package/package.json +2 -2
  3. package/src/Style/index.tsx +10 -8
  4. package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +10 -8
  5. package/src/__tests__/components/ConfigPanel/Form/ConnectedField/PageConnectedField/PageConnectedField.test.tsx +86 -8
  6. package/src/__tests__/components/SideModal/SideModal.test.tsx +64 -0
  7. package/src/__tests__/hooks/useSchemas.test.tsx +224 -0
  8. package/src/__tests__/services/SchemasService.test.ts +135 -0
  9. package/src/api/schemas.tsx +11 -1
  10. package/src/components/ConfigPanel/GlobalPageForm/index.tsx +11 -17
  11. package/src/components/Fields/Wysiwyg/helpers.tsx +14 -4
  12. package/src/components/Loader/components/Dots.js +4 -5
  13. package/src/components/PageFinder/index.tsx +15 -9
  14. package/src/components/ResizePanel/index.tsx +13 -3
  15. package/src/components/ResizePanel/style.tsx +2 -9
  16. package/src/containers/App/actions.tsx +96 -24
  17. package/src/containers/App/constants.tsx +7 -0
  18. package/src/containers/App/interfaces.tsx +26 -8
  19. package/src/containers/App/reducer.tsx +24 -9
  20. package/src/containers/Sites/actions.tsx +49 -49
  21. package/src/forms/editor.tsx +4 -3
  22. package/src/helpers/index.tsx +76 -94
  23. package/src/helpers/schemas.tsx +144 -36
  24. package/src/helpers/structuredData.tsx +36 -7
  25. package/src/helpers/themes.tsx +26 -8
  26. package/src/hooks/index.tsx +5 -0
  27. package/src/hooks/useSchemas.ts +151 -0
  28. package/src/locales/en-US.ts +1 -0
  29. package/src/locales/es-ES.ts +1 -0
  30. package/src/modules/Analytics/GroupPanel/index.tsx +9 -6
  31. package/src/modules/Analytics/GroupPanel/utils.tsx +12 -28
  32. package/src/modules/Content/PageItem/index.tsx +33 -36
  33. package/src/modules/Content/index.tsx +34 -30
  34. package/src/modules/Content/utils.tsx +16 -12
  35. package/src/modules/Forms/FormEditor/index.tsx +13 -14
  36. package/src/modules/FramePreview/index.tsx +8 -8
  37. package/src/modules/GlobalEditor/index.tsx +57 -42
  38. package/src/modules/MediaGallery/ImageModal/index.tsx +15 -9
  39. package/src/modules/MediaGallery/ImageModal/style.tsx +16 -1
  40. package/src/modules/PublicPreview/index.tsx +4 -3
  41. package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/index.tsx +4 -5
  42. package/src/modules/Settings/Globals/index.tsx +10 -11
  43. package/src/modules/Sites/index.tsx +13 -5
  44. package/src/modules/StructuredData/Form/index.tsx +25 -29
  45. package/src/modules/StructuredData/StructuredDataList/OptionTable/index.tsx +15 -6
  46. package/src/modules/StructuredData/StructuredDataList/index.tsx +22 -14
  47. package/src/modules/StructuredData/StructuredDataList/utils.tsx +12 -11
  48. package/src/schemas/index.tsx +5 -4
  49. package/src/schemas/pages/Page.ts +308 -0
  50. package/src/schemas/pages/index.ts +9 -0
  51. package/src/services/SchemasService.ts +240 -0
  52. package/src/services/index.ts +9 -0
  53. package/src/types/index.tsx +48 -39
  54. package/tsconfig.paths.json +1 -0
  55. package/src/schemas/pages/Page.tsx +0 -301
  56. package/src/schemas/pages/index.tsx +0 -5
  57. /package/src/schemas/pages/{FormPage.tsx → FormPage.ts} +0 -0
  58. /package/src/schemas/pages/{GlobalPage.tsx → GlobalPage.ts} +0 -0
@@ -1,16 +1,11 @@
1
- import React from "react";
2
- import { config } from "components";
3
-
4
1
  import { Icon, NoteField, Tabs } from "@ax/components";
5
- import { INotification, ISchema } from "@ax/types";
6
- import { useGlobalPermission } from "@ax/hooks";
2
+ import { useGlobalPermission, useThemes } from "@ax/hooks";
3
+ import type { INotification, ISchema } from "@ax/types";
7
4
 
8
5
  import ConnectedField from "../Form/ConnectedField";
9
6
 
10
7
  import * as S from "./style";
11
8
 
12
- const themes = config.schemas.config.themes;
13
-
14
9
  const noteText = "This is Global content and you cannot edit it here. To do so, you must go to the Global page";
15
10
  const noteTitle = "Global content";
16
11
  const errorText = "You don't have the permissions to edit the original content.";
@@ -19,6 +14,7 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
19
14
  const { selectedTab, setSelectedTab, schema, pageTitle, setHistoryPush, actions, header, footer } = props;
20
15
  const tabs = ["content", "config"];
21
16
 
17
+ const { themes } = useThemes();
22
18
  const isAllowedToEditGlobalData = useGlobalPermission("global.globalData.editAllGlobalData");
23
19
 
24
20
  const handleGetGlobalPage = async () => {
@@ -30,7 +26,7 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
30
26
  if (isAllowedToEditGlobalData) {
31
27
  await handleGetGlobalPage();
32
28
  const path = "/data/pages/editor";
33
- setHistoryPush && setHistoryPush(path, true);
29
+ setHistoryPush?.(path, true);
34
30
  } else {
35
31
  actions.setNotificationAction({
36
32
  type: "error",
@@ -47,6 +43,8 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
47
43
  options: { excludeDetailPages: true },
48
44
  };
49
45
 
46
+ const themeOptions = themes ?? [];
47
+
50
48
  const themeField = {
51
49
  title: "Page Options",
52
50
  type: "FieldGroup",
@@ -57,7 +55,7 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
57
55
  title: "Theme",
58
56
  type: "Select",
59
57
  key: "theme",
60
- options: themes,
58
+ options: themeOptions,
61
59
  helptext: "It affects the whole page: Header, Content, and footer.",
62
60
  },
63
61
  {
@@ -83,14 +81,14 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
83
81
  title: "Header Theme",
84
82
  type: "Select",
85
83
  key: "headerTheme",
86
- options: themes,
84
+ options: themeOptions,
87
85
  condition: true,
88
86
  },
89
87
  {
90
88
  title: "Footer Theme",
91
89
  type: "Select",
92
90
  key: "footerTheme",
93
- options: themes,
91
+ options: themeOptions,
94
92
  condition: true,
95
93
  },
96
94
  ],
@@ -98,12 +96,8 @@ const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
98
96
  ],
99
97
  };
100
98
 
101
- const handleRestoreHeader = () =>
102
- actions.restorePageNavigationAction && actions.restorePageNavigationAction("header");
103
-
104
- const handleRestoreFooter = () =>
105
- actions.restorePageNavigationAction && actions.restorePageNavigationAction("footer");
106
-
99
+ const handleRestoreHeader = () => actions.restorePageNavigationAction?.("header");
100
+ const handleRestoreFooter = () => actions.restorePageNavigationAction?.("footer");
107
101
  return (
108
102
  <section data-testid="global-page-section">
109
103
  <Tabs tabs={tabs} active={selectedTab} setSelectedTab={setSelectedTab} />
@@ -1,14 +1,24 @@
1
1
  /** biome-ignore-all lint/a11y/useValidAnchor: TODO: fix this */
2
- import React from "react";
2
+
3
+ import { schemasService } from "@ax/services";
4
+
3
5
  import { renderToString } from "react-dom/server";
4
- import { config } from "components";
5
6
 
7
+ /**
8
+ * NOTA DE MIGRACIÓN: Antes, la configuración de rich text (`richTextConfig`)
9
+ * venía de un archivo estático (import de "components"). Ahora, se obtiene de
10
+ * forma centralizada usando el singleton `schemasService`.
11
+ */
6
12
  const getRichTextConfig = (): IRichTextConfig | null => {
7
- return config.schemas.config.richTextConfig || null;
13
+ if (!schemasService.isLoaded()) {
14
+ return null;
15
+ }
16
+ return (schemasService.getSchemas().config.richTextConfig as IRichTextConfig) || null;
8
17
  };
9
18
 
10
19
  const parseClassNames = (styles: { label: string; className: string }[]) =>
11
20
  styles.reduce(
21
+ // biome-ignore lint/performance/noAccumulatingSpread: TODO: fix this
12
22
  (acc, current: { label: string; className: string }) => ({ ...acc, [current.className]: current.label }),
13
23
  {},
14
24
  );
@@ -85,4 +95,4 @@ const getLanguageMenuHtml = (languages: { name: string; iso: string; featured?:
85
95
  );
86
96
  };
87
97
 
88
- export { getRichTextConfig, parseClassNames, getLanguageMenuHtml };
98
+ export { getRichTextConfig, parseClassNames, getLanguageMenuHtml, type IRichTextConfig };
@@ -1,15 +1,14 @@
1
- import * as React from "react";
2
-
1
+ /** biome-ignore-all lint/a11y/noSvgWithoutTitle: not necessary */
3
2
  function SvgDots(props) {
4
3
  return (
5
4
  <svg data-testid="dots-svg" viewBox="0 0 100 100" {...props}>
6
- <circle fill="#5057FF" cx={6} cy={50} r={6}>
5
+ <circle fill="#5057FF" cx={30} cy={50} r={6}>
7
6
  <animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin={0.1} />
8
7
  </circle>
9
- <circle fill="#5057FF" cx={26} cy={50} r={6}>
8
+ <circle fill="#5057FF" cx={50} cy={50} r={6}>
10
9
  <animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin={0.2} />
11
10
  </circle>
12
- <circle fill="#5057FF" cx={46} cy={50} r={6}>
11
+ <circle fill="#5057FF" cx={70} cy={50} r={6}>
13
12
  <animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin={0.3} />
14
13
  </circle>
15
14
  </svg>
@@ -1,10 +1,12 @@
1
- import React, { useState, useEffect } from "react";
1
+ import { useEffect, useState } from "react";
2
2
  import { connect } from "react-redux";
3
3
 
4
- import { IContentType, IGetSitePagesParams, IGlobalLanguage, IPage, IRootState, ISite } from "@ax/types";
5
- import { getStructuredDataTitle, isReqOk } from "@ax/helpers";
6
4
  import { sites, structuredData } from "@ax/api";
7
- import { Loader, Pagination, Select, Button, AsyncSelect, SearchField } from "@ax/components";
5
+ import { AsyncSelect, Button, Loader, Pagination, SearchField, Select } from "@ax/components";
6
+ import { getStructuredDataTitle, isReqOk } from "@ax/helpers";
7
+ import { LOCALE } from "@ax/locales";
8
+ import type { IContentType, IGetSitePagesParams, IGlobalLanguage, IPage, IRootState, ISite } from "@ax/types";
9
+
8
10
  import SelectionListItem from "./SelectionListItem";
9
11
 
10
12
  import * as S from "./style";
@@ -150,7 +152,12 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
150
152
  const { value, isChecked } = item;
151
153
 
152
154
  let newSelection: IPage[] = [...selectedPages];
153
- isChecked ? newSelection.push(value) : (newSelection = newSelection.filter((page: IPage) => page.id !== value.id));
155
+ if (isChecked) {
156
+ newSelection.push(value);
157
+ } else {
158
+ newSelection = newSelection.filter((page: IPage) => page.id !== value.id);
159
+ }
160
+
154
161
  const newSelectionIDs = newSelection.map((page: IPage) => page.id);
155
162
 
156
163
  setSelectedPages(newSelection);
@@ -171,8 +178,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
171
178
  };
172
179
 
173
180
  const getPageList = (items: IPage[]) =>
174
- items &&
175
- items.map((page: IPage) => (
181
+ items?.map((page: IPage) => (
176
182
  <SelectionListItem
177
183
  option={page}
178
184
  key={page.id}
@@ -221,7 +227,7 @@ const PageFinder = (props: IPageFinderProps): JSX.Element => {
221
227
  )}
222
228
  </S.LanguageSiteFilters>
223
229
  <S.ContentTypeFilter>
224
- <S.Text>Content type</S.Text>
230
+ <S.Text>{LOCALE.common.filterByPageType}</S.Text>
225
231
  <Select
226
232
  name="select"
227
233
  options={contentTypeOptions}
@@ -293,7 +299,7 @@ interface IPageFinderProps {
293
299
  }
294
300
 
295
301
  const mapStateToProps = (state: IRootState) => ({
296
- currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
302
+ currentSiteID: state.sites.currentSiteInfo?.id || null,
297
303
  allSites: state.sites.sites,
298
304
  lang: state.app.lang,
299
305
  globalLangs: state.app.globalLangs,
@@ -1,4 +1,5 @@
1
- import React, { useState, useEffect, useRef } from "react";
1
+ import { useEffect, useRef, useState } from "react";
2
+
2
3
  import ResizeHandle from "./ResizeHandle";
3
4
 
4
5
  import * as S from "./style";
@@ -11,6 +12,11 @@ const ResizePanel = (props: IResizePanelProps): JSX.Element => {
11
12
  const [rwidth, setRwidth] = useState(MIN_WIDTH);
12
13
  const rightPanelRef = useRef<HTMLDivElement>(null);
13
14
 
15
+ const calculateFixedPanelMinWidth = (currentWidth: number) => {
16
+ const minWidth = 1280 - currentWidth - 32;
17
+ return minWidth < 500 ? "500px" : `${minWidth}px`;
18
+ };
19
+
14
20
  useEffect(() => {
15
21
  requestAnimationFrame(() => {
16
22
  if (rightPanelRef.current) {
@@ -27,7 +33,11 @@ const ResizePanel = (props: IResizePanelProps): JSX.Element => {
27
33
  <>
28
34
  <S.LeftPanel data-testid="left-panel">
29
35
  {fixed ? (
30
- <S.FixedPanel width={rwidth} full={full} data-testid="fixed-panel">
36
+ <S.FixedPanel
37
+ full={full}
38
+ data-testid="fixed-panel"
39
+ style={{ minWidth: rwidth ? calculateFixedPanelMinWidth(rwidth) : "auto" }}
40
+ >
31
41
  {leftPanel}
32
42
  </S.FixedPanel>
33
43
  ) : (
@@ -35,7 +45,7 @@ const ResizePanel = (props: IResizePanelProps): JSX.Element => {
35
45
  )}
36
46
  </S.LeftPanel>
37
47
  <ResizeHandle onMouseMove={resize} />
38
- <S.RightPanel width={rwidth} ref={rightPanelRef} data-testid="right-panel">
48
+ <S.RightPanel ref={rightPanelRef} data-testid="right-panel" style={{ width: rwidth ? `${rwidth}px` : "auto" }}>
39
49
  {rightPanel}
40
50
  </S.RightPanel>
41
51
  </>
@@ -1,35 +1,28 @@
1
1
  import styled from "styled-components";
2
2
 
3
- const getWidth = (width: number, space: string) => {
4
- const minWidth = 1280 - width - parseInt(space) * 2;
5
- return minWidth < 500 ? `500px` : `${minWidth}px`;
6
- };
7
-
8
3
  const LeftPanel = styled.section`
9
4
  position: relative;
10
5
  flex-grow: 1;
11
6
  min-width: 500px;
12
7
  `;
13
8
 
14
- const RightPanel = styled.section<{ width: number }>`
9
+ const RightPanel = styled.section`
15
10
  display: flex;
16
11
  position: relative;
17
12
  padding: ${(p) => `0 ${p.theme.spacing.m} ${p.theme.spacing.m} ${p.theme.spacing.m}`};
18
13
  flex-shrink: 0;
19
- width: ${(p) => p.width}px;
20
14
  min-width: 344px;
21
15
  max-width: ${(p) => `calc(100% - 500px - ${p.theme.spacing.m})`};
22
16
  flex-direction: column;
23
17
  `;
24
18
 
25
- const FixedPanel = styled.div<{ width: number; full: boolean }>`
19
+ const FixedPanel = styled.div<{ full: boolean }>`
26
20
  position: sticky;
27
21
  top: ${(p) => (p.full ? p.theme.spacing.xl : `calc(${p.theme.spacing.xl} + ${p.theme.spacing.m})`)};
28
22
  height: ${(p) =>
29
23
  p.full
30
24
  ? `calc(100vh - ${p.theme.spacing.xl})`
31
25
  : `calc(100vh - (${p.theme.spacing.xl} + (${p.theme.spacing.m} * 2)) - (${p.theme.spacing.m} + (${p.theme.spacing.xs} * 2)))`};
32
- min-width: ${(p) => getWidth(p.width, p.theme.spacing.m)};
33
26
  margin-left: ${(p) => (p.full ? "0" : p.theme.spacing.m)};
34
27
  `;
35
28
 
@@ -1,42 +1,47 @@
1
- import { Dispatch } from "redux";
2
- import differenceInSeconds from "date-fns/differenceInSeconds";
3
-
1
+ import { global, languages, schemas as schemasApi } from "@ax/api";
4
2
  import { isReqOk } from "@ax/helpers";
5
- import { languages, global } from "@ax/api";
6
- import { IRootState } from "@ax/types";
3
+ import { schemasService } from "@ax/services";
4
+ import type { IRootState } from "@ax/types";
7
5
 
8
- import history from "../../routes/history";
6
+ import differenceInSeconds from "date-fns/differenceInSeconds";
7
+ import type { Dispatch } from "redux";
9
8
 
9
+ import history from "../../routes/history";
10
10
  import {
11
- SET_ERROR,
12
- SET_IS_LOADING,
13
- SET_IS_SAVING,
14
11
  IS_LOGGING_IN,
15
- SET_TOKEN,
12
+ LOAD_SCHEMAS_ERROR,
13
+ LOAD_SCHEMAS_START,
14
+ LOAD_SCHEMAS_SUCCESS,
16
15
  LOGOUT,
17
- SET_LANGUAGE,
16
+ SET_ERROR,
18
17
  SET_GLOBAL_LANGUAGES,
19
18
  SET_GLOBAL_SETTINGS,
20
- SET_USER,
21
- SET_SESSION_STARTED_AT,
22
19
  SET_HAS_ANIMATION,
20
+ SET_IS_LOADING,
21
+ SET_IS_SAVING,
22
+ SET_LANGUAGE,
23
+ SET_SESSION_STARTED_AT,
24
+ SET_TOKEN,
25
+ SET_USER,
23
26
  } from "./constants";
24
-
25
- import {
26
- ISetIsLoading,
27
- ISetIsSaving,
28
- ISetErrorAction,
27
+ import type {
29
28
  IIsLoggingInAction,
30
- ISetTokenAction,
29
+ ILoadSchemasErrorAction,
30
+ ILoadSchemasStartAction,
31
+ ILoadSchemasSuccessAction,
31
32
  ILogoutAction,
32
- ISetLanguageAction,
33
+ ISetErrorAction,
33
34
  ISetGlobalLanguages,
34
35
  ISetGlobalSettings,
35
- ISetUserAction,
36
- ISetSessionStartedAtAction,
37
36
  ISetHasAnimation,
37
+ ISetIsLoading,
38
+ ISetIsSaving,
39
+ ISetLanguageAction,
40
+ ISetSessionStartedAtAction,
41
+ ISetTokenAction,
42
+ ISetUserAction,
38
43
  } from "./interfaces";
39
- import { IError, IUser } from "./reducer";
44
+ import type { IError, IUser } from "./reducer";
40
45
 
41
46
  function setIsLoading(isLoading: boolean): ISetIsLoading {
42
47
  return { type: SET_IS_LOADING, payload: { isLoading } };
@@ -210,7 +215,7 @@ function loginSSO(): (dispatch: Dispatch) => Promise<string | null> {
210
215
  } else {
211
216
  return null;
212
217
  }
213
- } catch (e) {
218
+ } catch (_error) {
214
219
  return null;
215
220
  }
216
221
  };
@@ -248,6 +253,72 @@ function checkUserSession(): (dispatch: Dispatch, getState: () => IRootState) =>
248
253
  };
249
254
  }
250
255
 
256
+ function loadSchemasStart(): ILoadSchemasStartAction {
257
+ return { type: LOAD_SCHEMAS_START };
258
+ }
259
+
260
+ function loadSchemasSuccess(): ILoadSchemasSuccessAction {
261
+ return { type: LOAD_SCHEMAS_SUCCESS };
262
+ }
263
+
264
+ function loadSchemasError(schemasError: string): ILoadSchemasErrorAction {
265
+ return { type: LOAD_SCHEMAS_ERROR, payload: { schemasError } };
266
+ }
267
+
268
+ /**
269
+ * Carga los schemas de la instancia desde la API.
270
+ *
271
+ * Esta función thunk comprueba primero si ya se está realizando una carga (`schemasLoading`)
272
+ * o si el servicio Singleton `schemasService` ya tiene schemas cargados para evitar peticiones duplicadas.
273
+ *
274
+ * - Si ya está cargando (loading), retorna `false`.
275
+ * - Si ya están cargados (loaded), retorna `true`.
276
+ * - Si no, realiza la petición al API y almacena los schemas globales en el servicio (singleton) SchemasService.
277
+ * - En caso de error, despacha la acción de error correspondiente y retorna `false`.
278
+ *
279
+ * @function
280
+ * @returns {Function} Thunk Redux que recibe `dispatch` y `getState` y retorna una Promesa<boolean>:
281
+ * - `true` si los schemas ya estaban cargados o se han cargado exitosamente.
282
+ * - `false` si la carga está en curso o ha fallado.
283
+ */
284
+ function loadSchemas(): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
285
+ return async (dispatch, getState) => {
286
+ const {
287
+ app: { schemasLoading },
288
+ } = getState();
289
+
290
+ // Avoid duplicate requests
291
+ if (schemasLoading) {
292
+ return false;
293
+ }
294
+
295
+ // Skip if already loaded
296
+ if (schemasService.isLoaded()) {
297
+ return true;
298
+ }
299
+
300
+ dispatch(loadSchemasStart());
301
+
302
+ try {
303
+ const response = await schemasApi.getSchemas();
304
+
305
+ if (isReqOk(response?.status)) {
306
+ schemasService.setSchemas(response.data);
307
+ dispatch(loadSchemasSuccess());
308
+ return true;
309
+ } else {
310
+ const errorMsg = response?.data?.message || "Failed to load schemas";
311
+ dispatch(loadSchemasError(errorMsg));
312
+ return false;
313
+ }
314
+ } catch (error) {
315
+ const errorMsg = error instanceof Error ? error.message : "Failed to load schemas";
316
+ dispatch(loadSchemasError(errorMsg));
317
+ return false;
318
+ }
319
+ };
320
+ }
321
+
251
322
  export {
252
323
  setError,
253
324
  resetError,
@@ -267,4 +338,5 @@ export {
267
338
  checkUserSession,
268
339
  setHasAnimation,
269
340
  loginSSO,
341
+ loadSchemas,
270
342
  };
@@ -13,6 +13,10 @@ const SET_USER = `${NAME}/SET_USER`;
13
13
  const SET_SESSION_STARTED_AT = `${NAME}/SET_SESSION_STARTED_AT`;
14
14
  const SET_HAS_ANIMATION = `${NAME}/SET_HAS_ANIMATION`;
15
15
 
16
+ const LOAD_SCHEMAS_START = `${NAME}/LOAD_SCHEMAS_START`;
17
+ const LOAD_SCHEMAS_SUCCESS = `${NAME}/LOAD_SCHEMAS_SUCCESS`;
18
+ const LOAD_SCHEMAS_ERROR = `${NAME}/LOAD_SCHEMAS_ERROR`;
19
+
16
20
  export {
17
21
  SET_ERROR,
18
22
  SET_IS_LOADING,
@@ -26,4 +30,7 @@ export {
26
30
  SET_USER,
27
31
  SET_SESSION_STARTED_AT,
28
32
  SET_HAS_ANIMATION,
33
+ LOAD_SCHEMAS_START,
34
+ LOAD_SCHEMAS_SUCCESS,
35
+ LOAD_SCHEMAS_ERROR,
29
36
  };
@@ -1,18 +1,21 @@
1
- import {
2
- SET_TOKEN,
1
+ import type {
2
+ IS_LOGGING_IN,
3
+ LOAD_SCHEMAS_ERROR,
4
+ LOAD_SCHEMAS_START,
5
+ LOAD_SCHEMAS_SUCCESS,
3
6
  LOGOUT,
4
7
  SET_ERROR,
5
- IS_LOGGING_IN,
8
+ SET_GLOBAL_LANGUAGES,
9
+ SET_GLOBAL_SETTINGS,
10
+ SET_HAS_ANIMATION,
6
11
  SET_IS_LOADING,
7
12
  SET_IS_SAVING,
8
13
  SET_LANGUAGE,
9
- SET_GLOBAL_LANGUAGES,
10
- SET_GLOBAL_SETTINGS,
11
- SET_USER,
12
14
  SET_SESSION_STARTED_AT,
13
- SET_HAS_ANIMATION,
15
+ SET_TOKEN,
16
+ SET_USER,
14
17
  } from "./constants";
15
- import { IUser } from "./reducer";
18
+ import type { IUser } from "./reducer";
16
19
 
17
20
  export interface ISetTokenAction {
18
21
  type: typeof SET_TOKEN;
@@ -76,6 +79,21 @@ export interface ISetHasAnimation {
76
79
  payload: { hasAnimation: boolean };
77
80
  }
78
81
 
82
+ export interface ILoadSchemasStartAction {
83
+ type: typeof LOAD_SCHEMAS_START;
84
+ }
85
+
86
+ export interface ILoadSchemasSuccessAction {
87
+ type: typeof LOAD_SCHEMAS_SUCCESS;
88
+ }
89
+
90
+ export interface ILoadSchemasErrorAction {
91
+ type: typeof LOAD_SCHEMAS_ERROR;
92
+ payload: { schemasError: string };
93
+ }
94
+
95
+ export type SchemasActionsCreators = ILoadSchemasStartAction | ILoadSchemasSuccessAction | ILoadSchemasErrorAction;
96
+
79
97
  export type AppActionsCreators = ISetIsLoading & ISetIsSaving;
80
98
 
81
99
  export type AuthActionsCreators = ISetTokenAction &
@@ -1,19 +1,24 @@
1
+ import type { ILanguage } from "@ax/types";
2
+
1
3
  import { REHYDRATE } from "redux-persist/lib/constants";
4
+
2
5
  import {
3
- SET_ERROR,
4
- SET_IS_LOADING,
5
- SET_IS_SAVING,
6
- SET_TOKEN,
7
6
  IS_LOGGING_IN,
7
+ LOAD_SCHEMAS_ERROR,
8
+ LOAD_SCHEMAS_START,
9
+ LOAD_SCHEMAS_SUCCESS,
8
10
  LOGOUT,
9
- SET_LANGUAGE,
11
+ SET_ERROR,
10
12
  SET_GLOBAL_LANGUAGES,
11
13
  SET_GLOBAL_SETTINGS,
12
- SET_USER,
13
- SET_SESSION_STARTED_AT,
14
14
  SET_HAS_ANIMATION,
15
+ SET_IS_LOADING,
16
+ SET_IS_SAVING,
17
+ SET_LANGUAGE,
18
+ SET_SESSION_STARTED_AT,
19
+ SET_TOKEN,
20
+ SET_USER,
15
21
  } from "./constants";
16
- import { ILanguage } from "@ax/types";
17
22
 
18
23
  export interface IAppState {
19
24
  isRehydrated: boolean;
@@ -28,6 +33,8 @@ export interface IAppState {
28
33
  globalSettings: IGlobalSettings;
29
34
  sessionStartedAt: null | Date;
30
35
  hasAnimation: boolean;
36
+ schemasLoading: boolean;
37
+ schemasError: string | null;
31
38
  }
32
39
  export interface IError {
33
40
  code?: number;
@@ -92,12 +99,14 @@ export const initialState = {
92
99
  },
93
100
  sessionStartedAt: null,
94
101
  hasAnimation: false,
102
+ schemasLoading: false,
103
+ schemasError: null,
95
104
  };
96
105
 
97
106
  export function reducer(state = initialState, action: any): IAppState {
98
107
  switch (action.type) {
99
108
  case REHYDRATE:
100
- return { ...state, isRehydrated: true };
109
+ return { ...state, isRehydrated: true, schemasLoading: false, schemasError: null };
101
110
  case SET_TOKEN:
102
111
  case SET_IS_LOADING:
103
112
  case SET_IS_SAVING:
@@ -112,6 +121,12 @@ export function reducer(state = initialState, action: any): IAppState {
112
121
  return { ...state, ...action.payload };
113
122
  case SET_ERROR:
114
123
  return { ...state, error: { ...action.payload } };
124
+ case LOAD_SCHEMAS_START:
125
+ return { ...state, schemasLoading: true, schemasError: null };
126
+ case LOAD_SCHEMAS_SUCCESS:
127
+ return { ...state, schemasLoading: false, schemasError: null };
128
+ case LOAD_SCHEMAS_ERROR:
129
+ return { ...state, schemasLoading: false, schemasError: action.payload.schemasError };
115
130
  default:
116
131
  return state;
117
132
  }