procode-lowcode-core 1.0.18 → 1.0.19
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/dist/index.esm.js +54 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -1
- package/dist/types/Action/helpers/hasLastApiCallFailed.d.ts +2 -0
- package/dist/types/ApplicationStart/Core.d.ts +2 -0
- package/dist/types/ApplicationStart/HOC/ApiResultDispatcher.d.ts +13 -0
- package/dist/types/BasicTypes/index.d.ts +2 -0
- package/dist/types/Store/Slices/appSlice.d.ts +5 -0
- package/package.json +1 -1
- package/src/Action/StandardActions/handleCreateAndNavigate.ts +6 -0
- package/src/Action/StandardActions/handleUpdateAndNavigate.ts +6 -0
- package/src/Action/helpers/hasLastApiCallFailed.ts +16 -0
- package/src/ApplicationStart/Core.tsx +2 -0
- package/src/ApplicationStart/HOC/ApiResultDispatcher.ts +23 -0
- package/src/ApplicationStart/helper/setupStoreAction.ts +10 -0
- package/src/ApplicationStart/useCoreInitialization.ts +1 -0
- package/src/BasicTypes/index.ts +3 -0
- package/src/Services/CentralService.ts +10 -0
- package/src/Store/Slices/appSlice.ts +4 -0
|
@@ -8,6 +8,7 @@ import { RequestType } from "../Services/helpers/ErrorMessageProvider";
|
|
|
8
8
|
import IValidationFactory from "../Validation/IValidationFactory";
|
|
9
9
|
import { IStorage } from "../StorageManager/IStorage";
|
|
10
10
|
import { ResponseFormat } from "../Services/helpers/coreResponseFormatter";
|
|
11
|
+
import { FieldErrorMapper } from "../Services/helpers/defaultFieldErrorMapper";
|
|
11
12
|
export type CoreProps = {
|
|
12
13
|
LoaderElement?: prcElement;
|
|
13
14
|
NotificationElement?: any;
|
|
@@ -28,6 +29,7 @@ export type CoreProps = {
|
|
|
28
29
|
getSchemaBySlugService?: any;
|
|
29
30
|
requestHeaders?: Record<string, string>;
|
|
30
31
|
responseFormatter?: ((data: any, status: number) => ResponseFormat) | undefined;
|
|
32
|
+
fieldErrorMapper?: FieldErrorMapper;
|
|
31
33
|
customStorages?: Record<string, IStorage>;
|
|
32
34
|
customRoute?: {
|
|
33
35
|
parentSimblingRoutes: CustomRoute[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AlertType } from "../../UIElement/UIElementDefinations/ApiConfig";
|
|
2
|
+
type ApiResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
alertType: AlertType;
|
|
5
|
+
};
|
|
6
|
+
type Handler = (result: ApiResult) => void;
|
|
7
|
+
declare class ApiResultDispatcher {
|
|
8
|
+
private static handler?;
|
|
9
|
+
static registerHandler(handler: Handler): void;
|
|
10
|
+
static dispatch(result: ApiResult): void;
|
|
11
|
+
}
|
|
12
|
+
export default ApiResultDispatcher;
|
|
13
|
+
export type { ApiResult };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import type { ApiResult } from "../ApplicationStart/HOC/ApiResultDispatcher";
|
|
2
3
|
type prcElement = JSX.Element;
|
|
3
4
|
type AppState = {
|
|
4
5
|
inProgressCount: number;
|
|
5
6
|
viewModel: any;
|
|
6
7
|
validation: Record<string, string[]>;
|
|
8
|
+
lastApiResult: ApiResult | null;
|
|
7
9
|
};
|
|
8
10
|
type MetaDataState = {
|
|
9
11
|
uiSchema: any;
|
|
@@ -8,6 +8,7 @@ export declare const appActions: import("@reduxjs/toolkit").CaseReducerActions<{
|
|
|
8
8
|
inProgressCount: number;
|
|
9
9
|
viewModel: any;
|
|
10
10
|
validation: Record<string, string[]>;
|
|
11
|
+
lastApiResult: import("../../ApplicationStart/HOC/ApiResultDispatcher").ApiResult | null;
|
|
11
12
|
};
|
|
12
13
|
loadViewModel: (state: import("immer/dist/internal").WritableDraft<AppState>, action: {
|
|
13
14
|
payload: any;
|
|
@@ -29,6 +30,10 @@ export declare const appActions: import("@reduxjs/toolkit").CaseReducerActions<{
|
|
|
29
30
|
payload: any;
|
|
30
31
|
type: string;
|
|
31
32
|
}) => void;
|
|
33
|
+
setLastApiResult: (state: import("immer/dist/internal").WritableDraft<AppState>, action: {
|
|
34
|
+
payload: any;
|
|
35
|
+
type: string;
|
|
36
|
+
}) => void;
|
|
32
37
|
}, "appState">;
|
|
33
38
|
declare const _default: import("redux").Reducer<AppState, import("redux").AnyAction>;
|
|
34
39
|
export default _default;
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { ActionInvokerProperties } from "../Types";
|
|
|
6
6
|
import handleNavigation from "./handleNavigation";
|
|
7
7
|
import { appActions } from "../../Store/Slices/appSlice";
|
|
8
8
|
import { hasFieldValidationErrors } from "../helpers/hasFieldValidationErrors";
|
|
9
|
+
import { hasLastApiCallFailed } from "../helpers/hasLastApiCallFailed";
|
|
9
10
|
|
|
10
11
|
const handleCreateAndNavigate = async (
|
|
11
12
|
actionInvokerProps: ActionInvokerProperties,
|
|
@@ -53,6 +54,11 @@ const handleCreateAndNavigate = async (
|
|
|
53
54
|
// from a form the user still has to fix.
|
|
54
55
|
if (hasFieldValidationErrors(eventService)) return;
|
|
55
56
|
|
|
57
|
+
// TOAST-alert failures don't populate state.validation, so check the
|
|
58
|
+
// last API call's success flag too — a toast-only error should still
|
|
59
|
+
// keep the user on the current screen.
|
|
60
|
+
if (hasLastApiCallFailed(eventService)) return;
|
|
61
|
+
|
|
56
62
|
handleNavigation(actionInvokerProps);
|
|
57
63
|
};
|
|
58
64
|
export default handleCreateAndNavigate;
|
|
@@ -6,6 +6,7 @@ import { ActionInvokerProperties } from "../Types";
|
|
|
6
6
|
import handleNavigation from "./handleNavigation";
|
|
7
7
|
import { appActions } from "../../Store/Slices/appSlice";
|
|
8
8
|
import { hasFieldValidationErrors } from "../helpers/hasFieldValidationErrors";
|
|
9
|
+
import { hasLastApiCallFailed } from "../helpers/hasLastApiCallFailed";
|
|
9
10
|
|
|
10
11
|
const handleUpdateAndNavigate = async (
|
|
11
12
|
actionInvokerProps: ActionInvokerProperties
|
|
@@ -53,6 +54,11 @@ const handleUpdateAndNavigate = async (
|
|
|
53
54
|
// from a form the user still has to fix.
|
|
54
55
|
if (hasFieldValidationErrors(eventService)) return;
|
|
55
56
|
|
|
57
|
+
// TOAST-alert failures don't populate state.validation, so check the
|
|
58
|
+
// last API call's success flag too — a toast-only error should still
|
|
59
|
+
// keep the user on the current screen.
|
|
60
|
+
if (hasLastApiCallFailed(eventService)) return;
|
|
61
|
+
|
|
56
62
|
handleNavigation(actionInvokerProps);
|
|
57
63
|
};
|
|
58
64
|
export default handleUpdateAndNavigate;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { eventServiceType } from "../../Constant";
|
|
2
|
+
import { EventService } from "../../Services/EventService";
|
|
3
|
+
import { ApiResult } from "../../ApplicationStart/HOC/ApiResultDispatcher";
|
|
4
|
+
|
|
5
|
+
// Reads `state.app.lastApiResult` written by CentralService's response
|
|
6
|
+
// interceptor and returns true if the most recent request failed. Used by
|
|
7
|
+
// save/update actions to skip navigation when the server reported a
|
|
8
|
+
// non-success status under any alertType (FIELDVALIDATION already populates
|
|
9
|
+
// state.validation, but TOAST leaves no trace there).
|
|
10
|
+
export const hasLastApiCallFailed = (
|
|
11
|
+
eventService: EventService | undefined,
|
|
12
|
+
): boolean => {
|
|
13
|
+
const appState = eventService?.emit(eventServiceType.APP_STATE);
|
|
14
|
+
const lastApiResult = appState?.lastApiResult as ApiResult | null | undefined;
|
|
15
|
+
return lastApiResult ? lastApiResult.success === false : false;
|
|
16
|
+
};
|
|
@@ -11,6 +11,7 @@ import { RequestType } from "../Services/helpers/ErrorMessageProvider";
|
|
|
11
11
|
import IValidationFactory from "../Validation/IValidationFactory";
|
|
12
12
|
import { IStorage } from "../StorageManager/IStorage";
|
|
13
13
|
import { ResponseFormat } from "../Services/helpers/coreResponseFormatter";
|
|
14
|
+
import { FieldErrorMapper } from "../Services/helpers/defaultFieldErrorMapper";
|
|
14
15
|
import LoaderElement from "../Renderer/LoadingRenderer";
|
|
15
16
|
import Skeleton from "../Renderer/SkelitonRenderer";
|
|
16
17
|
import { SkeletonType } from "../Renderer/SkelitonRenderer/constant";
|
|
@@ -48,6 +49,7 @@ export type CoreProps = {
|
|
|
48
49
|
responseFormatter?:
|
|
49
50
|
| ((data: any, status: number) => ResponseFormat)
|
|
50
51
|
| undefined;
|
|
52
|
+
fieldErrorMapper?: FieldErrorMapper;
|
|
51
53
|
|
|
52
54
|
customStorages?: Record<string, IStorage>;
|
|
53
55
|
customRoute?: {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AlertType } from "../../UIElement/UIElementDefinations/ApiConfig";
|
|
2
|
+
|
|
3
|
+
type ApiResult = { success: boolean; alertType: AlertType };
|
|
4
|
+
type Handler = (result: ApiResult) => void;
|
|
5
|
+
|
|
6
|
+
class ApiResultDispatcher {
|
|
7
|
+
private static handler?: Handler;
|
|
8
|
+
|
|
9
|
+
static registerHandler(handler: Handler) {
|
|
10
|
+
ApiResultDispatcher.handler = handler;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static dispatch(result: ApiResult) {
|
|
14
|
+
if (ApiResultDispatcher.handler) {
|
|
15
|
+
ApiResultDispatcher.handler(result);
|
|
16
|
+
} else {
|
|
17
|
+
console.warn("Api result dispatcher handler not registered.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default ApiResultDispatcher;
|
|
23
|
+
export type { ApiResult };
|
|
@@ -5,6 +5,9 @@ import { commonDataActions } from "../../Store/Slices/commonDataSlice";
|
|
|
5
5
|
import FieldValidationDispatcher, {
|
|
6
6
|
FieldErrors,
|
|
7
7
|
} from "../HOC/FieldValidationDispatcher";
|
|
8
|
+
import ApiResultDispatcher, {
|
|
9
|
+
ApiResult,
|
|
10
|
+
} from "../HOC/ApiResultDispatcher";
|
|
8
11
|
|
|
9
12
|
let globalEventService: any = null;
|
|
10
13
|
|
|
@@ -30,6 +33,13 @@ const setupStoreAction = (dispatch: any, eventService: any, store: any) => {
|
|
|
30
33
|
dispatch(appActions.loadValidation(errors));
|
|
31
34
|
});
|
|
32
35
|
|
|
36
|
+
// Record the latest server response's success/alertType so flow-control
|
|
37
|
+
// helpers (e.g. hasLastApiCallFailed) can decide whether to continue with
|
|
38
|
+
// post-request actions like navigation.
|
|
39
|
+
ApiResultDispatcher.registerHandler((result: ApiResult) => {
|
|
40
|
+
dispatch(appActions.setLastApiResult(result));
|
|
41
|
+
});
|
|
42
|
+
|
|
33
43
|
// Register loader handlers for external services
|
|
34
44
|
eventService?.subscribe(eventServiceType.REQUEST_START, () => () => {
|
|
35
45
|
dispatch(commonDataActions.updatePendingRequests(LoadingStatus.INPROCESS));
|
|
@@ -22,6 +22,7 @@ export const useCoreInitialization = (coreProps: CoreProps) => {
|
|
|
22
22
|
requestHeaders: coreProps.requestHeaders,
|
|
23
23
|
getSchemaBySlugService: coreProps.getSchemaBySlugService,
|
|
24
24
|
responseFormatter: coreProps.responseFormatter,
|
|
25
|
+
fieldErrorMapper: coreProps.fieldErrorMapper,
|
|
25
26
|
});
|
|
26
27
|
};
|
|
27
28
|
|
package/src/BasicTypes/index.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import type { ApiResult } from "../ApplicationStart/HOC/ApiResultDispatcher";
|
|
2
|
+
|
|
1
3
|
type prcElement = JSX.Element;
|
|
2
4
|
|
|
3
5
|
type AppState = {
|
|
4
6
|
inProgressCount: number;
|
|
5
7
|
viewModel: any;
|
|
6
8
|
validation: Record<string, string[]>;
|
|
9
|
+
lastApiResult: ApiResult | null;
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
type MetaDataState = {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "../UIElement/UIElementDefinations/ApiConfig";
|
|
11
11
|
import NotificationService from "../ApplicationStart/HOC/NotificationService";
|
|
12
12
|
import FieldValidationDispatcher from "../ApplicationStart/HOC/FieldValidationDispatcher";
|
|
13
|
+
import ApiResultDispatcher from "../ApplicationStart/HOC/ApiResultDispatcher";
|
|
13
14
|
import { getStatusBaseNotifiType } from "./helpers/getStatusBaseNotifiType";
|
|
14
15
|
|
|
15
16
|
export interface CustomAxiosRequestConfig extends AxiosRequestConfig {
|
|
@@ -74,6 +75,15 @@ export class CentralService {
|
|
|
74
75
|
const alertType = statusRelatedConfig?.alertType || AlertType.TOAST;
|
|
75
76
|
response.data.alertType = alertType;
|
|
76
77
|
|
|
78
|
+
// Record the response outcome so post-request flow (e.g. navigation)
|
|
79
|
+
// can short-circuit when the server reported failure regardless of
|
|
80
|
+
// alertType. Success is derived from the HTTP-ish status set by the
|
|
81
|
+
// response formatter (2xx = success).
|
|
82
|
+
ApiResultDispatcher.dispatch({
|
|
83
|
+
success: status >= 200 && status < 300,
|
|
84
|
+
alertType,
|
|
85
|
+
});
|
|
86
|
+
|
|
77
87
|
if (alertType === AlertType.FIELDVALIDATION) {
|
|
78
88
|
// Structured payload (default convention {propertyName, message}, or
|
|
79
89
|
// whatever shape the registered fieldErrorMapper recognizes): route to
|
|
@@ -11,6 +11,7 @@ const initialState: AppState = {
|
|
|
11
11
|
viewModel: { supportiveData: null, screenData: null },
|
|
12
12
|
inProgressCount: 0,
|
|
13
13
|
validation: {},
|
|
14
|
+
lastApiResult: null,
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
const appSlice = createSlice({
|
|
@@ -54,6 +55,9 @@ const appSlice = createSlice({
|
|
|
54
55
|
[fieldName]: invalidMessages || [],
|
|
55
56
|
};
|
|
56
57
|
},
|
|
58
|
+
setLastApiResult: (state, action) => {
|
|
59
|
+
state.lastApiResult = action.payload;
|
|
60
|
+
},
|
|
57
61
|
},
|
|
58
62
|
});
|
|
59
63
|
export const appActions = appSlice.actions;
|