@headless-adminapp/app 1.4.20 → 1.4.22
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/app/LayoutProvider.js +4 -1
- package/command/types.d.ts +1 -1
- package/dataform/DataFormProvider/UnsavedChangesInfoSetter.d.ts +2 -0
- package/dataform/DataFormProvider/UnsavedChangesInfoSetter.js +25 -0
- package/dataform/hooks/useFormSave.js +4 -2
- package/dataform/utils/defaultParameters.js +10 -1
- package/datagrid/hooks/useOpenRecord.d.ts +1 -1
- package/datagrid/hooks/useOpenRecord.js +2 -2
- package/dialog/hooks/useCloseDialog.d.ts +3 -0
- package/dialog/hooks/useCloseDialog.js +3 -0
- package/dialog/hooks/useOpenConfirmDialog.d.ts +3 -0
- package/dialog/hooks/useOpenConfirmDialog.js +3 -0
- package/dialog/hooks/useOpenDialog.d.ts +3 -0
- package/dialog/hooks/useOpenDialog.js +3 -0
- package/mutable/context.d.ts +3 -0
- package/mutable/context.js +3 -0
- package/navigation/hooks/useOpenForm.d.ts +1 -1
- package/navigation/hooks/useOpenForm.js +3 -3
- package/navigation/unsaved-changes/UnsavedChangesRouteGuard.d.ts +1 -0
- package/navigation/unsaved-changes/UnsavedChangesRouteGuard.js +9 -0
- package/navigation/unsaved-changes/index.d.ts +3 -0
- package/navigation/unsaved-changes/index.js +10 -0
- package/navigation/unsaved-changes/unsavedChangesInfo.d.ts +6 -0
- package/navigation/unsaved-changes/unsavedChangesInfo.js +11 -0
- package/navigation/unsaved-changes/useUnsavedChangesRouteGuard.d.ts +1 -0
- package/navigation/unsaved-changes/useUnsavedChangesRouteGuard.js +48 -0
- package/package.json +2 -2
- package/providers/PageEntityFormProvider/index.js +2 -1
- package/quickcreate/QuickCreateProvider.d.ts +5 -0
- package/quickcreate/QuickCreateProvider.js +13 -0
- package/quickcreate/context.d.ts +16 -0
- package/quickcreate/context.js +5 -0
- package/quickcreate/hooks/index.d.ts +5 -0
- package/quickcreate/hooks/index.js +13 -0
- package/quickcreate/hooks/useFormSave.d.ts +2 -0
- package/quickcreate/hooks/useFormSave.js +64 -0
- package/quickcreate/hooks/useIsQuickCreateSupported.d.ts +1 -0
- package/quickcreate/hooks/useIsQuickCreateSupported.js +16 -0
- package/quickcreate/hooks/useOpenQuickCreate.d.ts +3 -0
- package/quickcreate/hooks/useOpenQuickCreate.js +58 -0
- package/quickcreate/hooks/useQuickCreateItem.d.ts +1 -0
- package/quickcreate/hooks/useQuickCreateItem.js +8 -0
- package/quickcreate/hooks/useQuickCreateItems.d.ts +1 -0
- package/quickcreate/hooks/useQuickCreateItems.js +8 -0
- package/quickcreate/index.d.ts +1 -0
- package/quickcreate/index.js +5 -0
- package/route/context.d.ts +7 -4
- package/store/SchemaExperienceStore.d.ts +5 -2
- package/store/SchemaExperienceStore.js +19 -0
package/app/LayoutProvider.js
CHANGED
|
@@ -9,11 +9,14 @@ const dialog_1 = require("../dialog");
|
|
|
9
9
|
const header_1 = require("../header");
|
|
10
10
|
const locale_1 = require("../locale");
|
|
11
11
|
const metadata_1 = require("../metadata");
|
|
12
|
+
const unsaved_changes_1 = require("../navigation/unsaved-changes");
|
|
12
13
|
const progress_indicator_1 = require("../progress-indicator");
|
|
14
|
+
const quickcreate_1 = require("../quickcreate");
|
|
13
15
|
const route_1 = require("../route");
|
|
14
16
|
const toast_notification_1 = require("../toast-notification");
|
|
15
17
|
const transport_1 = require("../transport");
|
|
16
18
|
const context_1 = require("../transport/context");
|
|
19
|
+
const AppProvider_1 = require("./AppProvider");
|
|
17
20
|
const AuthWrapper_1 = require("./AuthWrapper");
|
|
18
21
|
const dataServiceNotProvidedError = new Error('No data service provided');
|
|
19
22
|
const defaultDataService = {
|
|
@@ -40,6 +43,6 @@ const defaultDataService = {
|
|
|
40
43
|
},
|
|
41
44
|
};
|
|
42
45
|
const LayoutProvider = ({ authPlaceholder, authProps, dataService = defaultDataService, fileService, localeProps, metadataProps, queryClient = defaults_1.queryClient, routeProps, children, containers: { DialogContainer, ProgressIndicatorContainer, ToastNotificationContainer, }, }) => {
|
|
43
|
-
return ((0, jsx_runtime_1.jsx)(route_1.RouteProvider, { ...routeProps, children: (0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: (0, jsx_runtime_1.jsx)(locale_1.LocaleProvider, { ...localeProps, children: (0, jsx_runtime_1.jsx)(metadata_1.MetadataProvider, { ...metadataProps, children: (0, jsx_runtime_1.jsx)(transport_1.DataServiceContext.Provider, { value: dataService, children: (0, jsx_runtime_1.jsx)(context_1.FileServiceContext.Provider, { value: fileService ?? null, children: (0, jsx_runtime_1.jsx)(dialog_1.DialogProvider, { children: (0, jsx_runtime_1.jsx)(progress_indicator_1.ProgressIndicatorProvider, { children: (0, jsx_runtime_1.jsxs)(toast_notification_1.ToastNotificationProvider, { children: [(0, jsx_runtime_1.jsx)(DialogContainer, {}), (0, jsx_runtime_1.jsx)(ProgressIndicatorContainer, {}), (0, jsx_runtime_1.jsx)(ToastNotificationContainer, {}), (0, jsx_runtime_1.jsx)(auth_1.AuthProvider, { ...authProps, children: (0, jsx_runtime_1.jsx)(header_1.HeaderProvider, { children: (0, jsx_runtime_1.
|
|
46
|
+
return ((0, jsx_runtime_1.jsx)(route_1.RouteProvider, { ...routeProps, children: (0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: (0, jsx_runtime_1.jsx)(locale_1.LocaleProvider, { ...localeProps, children: (0, jsx_runtime_1.jsx)(metadata_1.MetadataProvider, { ...metadataProps, children: (0, jsx_runtime_1.jsx)(transport_1.DataServiceContext.Provider, { value: dataService, children: (0, jsx_runtime_1.jsx)(context_1.FileServiceContext.Provider, { value: fileService ?? null, children: (0, jsx_runtime_1.jsx)(dialog_1.DialogProvider, { children: (0, jsx_runtime_1.jsx)(progress_indicator_1.ProgressIndicatorProvider, { children: (0, jsx_runtime_1.jsxs)(toast_notification_1.ToastNotificationProvider, { children: [(0, jsx_runtime_1.jsx)(DialogContainer, {}), (0, jsx_runtime_1.jsx)(ProgressIndicatorContainer, {}), (0, jsx_runtime_1.jsx)(ToastNotificationContainer, {}), (0, jsx_runtime_1.jsx)(auth_1.AuthProvider, { ...authProps, children: (0, jsx_runtime_1.jsx)(header_1.HeaderProvider, { children: (0, jsx_runtime_1.jsxs)(AuthWrapper_1.AuthWrapper, { Placeholder: authPlaceholder, children: [(0, jsx_runtime_1.jsx)(unsaved_changes_1.UnsavedChangesRouteGuard, {}), (0, jsx_runtime_1.jsx)(AppProvider_1.AppProvider, { children: (0, jsx_runtime_1.jsx)(quickcreate_1.QuickCreateProvider, { children: children }) })] }) }) })] }) }) }) }) }) }) }) }) }));
|
|
44
47
|
};
|
|
45
48
|
exports.LayoutProvider = LayoutProvider;
|
package/command/types.d.ts
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsavedChangesInfoSetter = void 0;
|
|
4
|
+
const unsaved_changes_1 = require("@headless-adminapp/app/navigation/unsaved-changes");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const hooks_1 = require("../hooks");
|
|
7
|
+
const UnsavedChangesInfoSetter = () => {
|
|
8
|
+
const form = (0, hooks_1.useFormInstance)();
|
|
9
|
+
(0, react_1.useEffect)(() => {
|
|
10
|
+
if (!form.formState.isDirty) {
|
|
11
|
+
(0, unsaved_changes_1.setUnsavedChangesInfo)(null);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
(0, unsaved_changes_1.setUnsavedChangesInfo)({
|
|
15
|
+
title: 'Unsaved Changes',
|
|
16
|
+
message: 'You have unsaved changes. Are you sure you want to leave without saving?',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return () => {
|
|
20
|
+
(0, unsaved_changes_1.setUnsavedChangesInfo)(null);
|
|
21
|
+
};
|
|
22
|
+
}, [form.formState.isDirty]);
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
exports.UnsavedChangesInfoSetter = UnsavedChangesInfoSetter;
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.useFormSave = useFormSave;
|
|
11
11
|
// Wrapper - Loader, response message
|
|
12
12
|
// Core - Extract modified fields, prepare operations, perform operations
|
|
13
|
+
const unsaved_changes_1 = require("@headless-adminapp/app/navigation/unsaved-changes");
|
|
13
14
|
const route_1 = require("@headless-adminapp/app/route");
|
|
14
15
|
const app_1 = require("@headless-adminapp/core/experience/app");
|
|
15
16
|
const react_query_1 = require("@tanstack/react-query");
|
|
@@ -85,12 +86,13 @@ function useFormSave() {
|
|
|
85
86
|
});
|
|
86
87
|
return;
|
|
87
88
|
}
|
|
89
|
+
(0, unsaved_changes_1.setUnsavedChangesInfo)(null);
|
|
88
90
|
if (mode === 'save') {
|
|
89
91
|
if (record) {
|
|
90
92
|
await refresh();
|
|
91
93
|
}
|
|
92
94
|
else {
|
|
93
|
-
router.replace(routeResolver({
|
|
95
|
+
await router.replace(routeResolver({
|
|
94
96
|
type: app_1.PageType.EntityForm,
|
|
95
97
|
logicalName: schema.logicalName,
|
|
96
98
|
id: result.recordId,
|
|
@@ -102,7 +104,7 @@ function useFormSave() {
|
|
|
102
104
|
queryKey: ['data', 'retriveRecord'],
|
|
103
105
|
});
|
|
104
106
|
if (mode === 'saveandclose') {
|
|
105
|
-
router.back();
|
|
107
|
+
await router.back();
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
await client.invalidateQueries({
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getFormDefaultParameters = getFormDefaultParameters;
|
|
7
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
4
8
|
function getFormDefaultParameters(schema, formExperience, router) {
|
|
5
9
|
const _values = router.getState('defaultParameters')?.values;
|
|
6
10
|
const _logicalName = router.getState('defaultParameters')?.logicalName;
|
|
@@ -14,7 +18,12 @@ function getFormDefaultParameters(schema, formExperience, router) {
|
|
|
14
18
|
defaultValue = defaultValue.toISOString();
|
|
15
19
|
}
|
|
16
20
|
else if (attribute.type === 'date' && defaultValue === '@now') {
|
|
17
|
-
|
|
21
|
+
if (attribute.format === 'date') {
|
|
22
|
+
defaultValue = (0, dayjs_1.default)().format('YYYY-MM-DD');
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
defaultValue = new Date().toISOString();
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
return {
|
|
20
29
|
...acc,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function useOpenRecord(): (id: string, logicalName: string) => void
|
|
1
|
+
export declare function useOpenRecord(): (id: string, logicalName: string) => Promise<void>;
|
|
@@ -13,13 +13,13 @@ function useOpenRecord() {
|
|
|
13
13
|
const router = (0, route_1.useRouter)();
|
|
14
14
|
const dataRef = (0, react_1.useRef)(data);
|
|
15
15
|
dataRef.current = data;
|
|
16
|
-
return (0, react_1.useCallback)((id, logicalName) => {
|
|
16
|
+
return (0, react_1.useCallback)(async (id, logicalName) => {
|
|
17
17
|
const path = routeResolver({
|
|
18
18
|
logicalName: logicalName,
|
|
19
19
|
type: app_1.PageType.EntityForm,
|
|
20
20
|
id,
|
|
21
21
|
});
|
|
22
|
-
router.push(path, {
|
|
22
|
+
await router.push(path, {
|
|
23
23
|
state: {
|
|
24
24
|
navigator: logicalName === schema.logicalName
|
|
25
25
|
? {
|
|
@@ -15,6 +15,9 @@ function markDialogAsClosed(items, id) {
|
|
|
15
15
|
function excludeDialogItemById(items, id) {
|
|
16
16
|
return items.filter((item) => item.id !== id);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* @zero-deps
|
|
20
|
+
*/
|
|
18
21
|
function useCloseDialog() {
|
|
19
22
|
const setValue = (0, context_1.useContextSetValue)(context_2.DialogContext);
|
|
20
23
|
const closeDialog = (0, react_1.useCallback)((id) => {
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { ConfirmDialogOptions, ConfirmResult } from '@headless-adminapp/core/experience/dialog';
|
|
2
|
+
/**
|
|
3
|
+
* @zero-deps
|
|
4
|
+
*/
|
|
2
5
|
export declare function useOpenConfirmDialog(): (options: Omit<ConfirmDialogOptions, "type" | "onConfirm" | "onDismiss" | "onCancel">) => Promise<ConfirmResult | null>;
|
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.useOpenConfirmDialog = useOpenConfirmDialog;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const useOpenDialog_1 = require("./useOpenDialog");
|
|
6
|
+
/**
|
|
7
|
+
* @zero-deps
|
|
8
|
+
*/
|
|
6
9
|
function useOpenConfirmDialog() {
|
|
7
10
|
const openDialog = (0, useOpenDialog_1.useOpenDialog)();
|
|
8
11
|
const openConfirmDialog = (0, react_1.useCallback)((options) => {
|
|
@@ -6,6 +6,9 @@ const uuid_1 = require("uuid");
|
|
|
6
6
|
const context_1 = require("../../mutable/context");
|
|
7
7
|
const context_2 = require("../context");
|
|
8
8
|
const useCloseDialog_1 = require("./useCloseDialog");
|
|
9
|
+
/**
|
|
10
|
+
* @zero-deps
|
|
11
|
+
*/
|
|
9
12
|
function useOpenDialog() {
|
|
10
13
|
const setValue = (0, context_1.useContextSetValue)(context_2.DialogContext);
|
|
11
14
|
const closeDialog = (0, useCloseDialog_1.useCloseDialog)();
|
package/mutable/context.d.ts
CHANGED
|
@@ -8,6 +8,9 @@ export declare function useContextValue<T>(context: React.Context<ContextValue<T
|
|
|
8
8
|
current: T;
|
|
9
9
|
};
|
|
10
10
|
export declare function useContextSelector<T, R>(context: React.Context<ContextValue<T>>, selector: (state: T) => R): R;
|
|
11
|
+
/**
|
|
12
|
+
* @zero-deps
|
|
13
|
+
*/
|
|
11
14
|
export declare function useContextSetValue<T>(context: React.Context<ContextValue<T>>): (value: Partial<T> | ((state: T) => Partial<T>)) => void;
|
|
12
15
|
type Setter<T, U extends unknown[]> = (setValue: ContextValue<T>['setValue']) => (...args: U) => void;
|
|
13
16
|
export declare function useContextValueSetter<T, U extends unknown[]>(context: React.Context<ContextValue<T>>, setter: Setter<T, U>): (...args: U) => void;
|
package/mutable/context.js
CHANGED
|
@@ -33,6 +33,9 @@ function useContextSelector(context, selector) {
|
|
|
33
33
|
}
|
|
34
34
|
return (0, exports.useContextSelectorInternal)(contextValue, selector);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @zero-deps
|
|
38
|
+
*/
|
|
36
39
|
function useContextSetValue(context) {
|
|
37
40
|
const contextValue = (0, react_1.useContext)(context);
|
|
38
41
|
if (!contextValue) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { OpenFormOptions } from '@headless-adminapp/core/experience/command';
|
|
2
|
-
export declare function useOpenForm(): (options: OpenFormOptions) => void
|
|
2
|
+
export declare function useOpenForm(): (options: OpenFormOptions) => Promise<void>;
|
|
@@ -8,7 +8,7 @@ const useRouteResolver_1 = require("../../route/hooks/useRouteResolver");
|
|
|
8
8
|
function useOpenForm() {
|
|
9
9
|
const routeResolver = (0, useRouteResolver_1.useRouteResolver)();
|
|
10
10
|
const router = (0, hooks_1.useRouter)();
|
|
11
|
-
return (0, react_1.useCallback)((options) => {
|
|
11
|
+
return (0, react_1.useCallback)(async (options) => {
|
|
12
12
|
const path = routeResolver({
|
|
13
13
|
logicalName: options.logicalName,
|
|
14
14
|
type: app_1.PageType.EntityForm,
|
|
@@ -29,7 +29,7 @@ function useOpenForm() {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
if (options.replace) {
|
|
32
|
-
router.replace(path, {
|
|
32
|
+
await router.replace(path, {
|
|
33
33
|
state: {
|
|
34
34
|
...router.getState(),
|
|
35
35
|
...state,
|
|
@@ -37,7 +37,7 @@ function useOpenForm() {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
|
-
router.push(path, {
|
|
40
|
+
await router.push(path, {
|
|
41
41
|
state,
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const UnsavedChangesRouteGuard: () => null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsavedChangesRouteGuard = void 0;
|
|
4
|
+
const useUnsavedChangesRouteGuard_1 = require("./useUnsavedChangesRouteGuard");
|
|
5
|
+
const UnsavedChangesRouteGuard = () => {
|
|
6
|
+
(0, useUnsavedChangesRouteGuard_1.useUnsavedChangesRouteGuard)();
|
|
7
|
+
return null;
|
|
8
|
+
};
|
|
9
|
+
exports.UnsavedChangesRouteGuard = UnsavedChangesRouteGuard;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsavedChangesRouteGuard = exports.useUnsavedChangesRouteGuard = exports.setUnsavedChangesInfo = exports.getUnsavedChangesInfo = void 0;
|
|
4
|
+
var unsavedChangesInfo_1 = require("./unsavedChangesInfo");
|
|
5
|
+
Object.defineProperty(exports, "getUnsavedChangesInfo", { enumerable: true, get: function () { return unsavedChangesInfo_1.getUnsavedChangesInfo; } });
|
|
6
|
+
Object.defineProperty(exports, "setUnsavedChangesInfo", { enumerable: true, get: function () { return unsavedChangesInfo_1.setUnsavedChangesInfo; } });
|
|
7
|
+
var useUnsavedChangesRouteGuard_1 = require("./useUnsavedChangesRouteGuard");
|
|
8
|
+
Object.defineProperty(exports, "useUnsavedChangesRouteGuard", { enumerable: true, get: function () { return useUnsavedChangesRouteGuard_1.useUnsavedChangesRouteGuard; } });
|
|
9
|
+
var UnsavedChangesRouteGuard_1 = require("./UnsavedChangesRouteGuard");
|
|
10
|
+
Object.defineProperty(exports, "UnsavedChangesRouteGuard", { enumerable: true, get: function () { return UnsavedChangesRouteGuard_1.UnsavedChangesRouteGuard; } });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUnsavedChangesInfo = getUnsavedChangesInfo;
|
|
4
|
+
exports.setUnsavedChangesInfo = setUnsavedChangesInfo;
|
|
5
|
+
let unsavedChangesInfo = null;
|
|
6
|
+
function getUnsavedChangesInfo() {
|
|
7
|
+
return unsavedChangesInfo;
|
|
8
|
+
}
|
|
9
|
+
function setUnsavedChangesInfo(info) {
|
|
10
|
+
unsavedChangesInfo = info;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useUnsavedChangesRouteGuard(): null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useUnsavedChangesRouteGuard = useUnsavedChangesRouteGuard;
|
|
4
|
+
const dialog_1 = require("@headless-adminapp/app/dialog");
|
|
5
|
+
const route_1 = require("@headless-adminapp/app/route");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const unsavedChangesInfo_1 = require("./unsavedChangesInfo");
|
|
8
|
+
function useUnsavedChangesRouteGuard() {
|
|
9
|
+
const router = (0, route_1.useRouter)();
|
|
10
|
+
const openConfirmDialog = (0, dialog_1.useOpenConfirmDialog)();
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
const guard = async () => {
|
|
13
|
+
const unsavedChangesInfo = (0, unsavedChangesInfo_1.getUnsavedChangesInfo)();
|
|
14
|
+
if (!unsavedChangesInfo) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const confirmResult = await openConfirmDialog({
|
|
18
|
+
title: unsavedChangesInfo.title,
|
|
19
|
+
text: unsavedChangesInfo.message,
|
|
20
|
+
confirmButtonLabel: 'Leave',
|
|
21
|
+
cancelButtonLabel: 'Stay',
|
|
22
|
+
});
|
|
23
|
+
if (!confirmResult?.confirmed) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
(0, unsavedChangesInfo_1.setUnsavedChangesInfo)(null);
|
|
27
|
+
return true;
|
|
28
|
+
};
|
|
29
|
+
router.registerGuard(guard);
|
|
30
|
+
return () => {
|
|
31
|
+
router.unregisterGuard(guard);
|
|
32
|
+
};
|
|
33
|
+
}, [router, openConfirmDialog]);
|
|
34
|
+
(0, react_1.useEffect)(() => {
|
|
35
|
+
function handleBeforeUnload(event) {
|
|
36
|
+
const unsavedChangesInfo = (0, unsavedChangesInfo_1.getUnsavedChangesInfo)();
|
|
37
|
+
if (unsavedChangesInfo) {
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
event.returnValue = unsavedChangesInfo.message;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
43
|
+
return () => {
|
|
44
|
+
window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-adminapp/app",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.22",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"uuid": "11.0.3",
|
|
39
39
|
"yup": "^1.4.0"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "8f687a2b8c3151c30c57f43105ac47c5d8c3ee79"
|
|
42
42
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PageEntityFormProvider = PageEntityFormProvider;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const DataFormProvider_1 = require("../../dataform/DataFormProvider");
|
|
6
|
+
const UnsavedChangesInfoSetter_1 = require("../../dataform/DataFormProvider/UnsavedChangesInfoSetter");
|
|
6
7
|
function PageEntityFormProvider({ schema, form, recordId, children, commands, retriveRecordFn, saveRecordFn, }) {
|
|
7
|
-
return ((0, jsx_runtime_1.
|
|
8
|
+
return ((0, jsx_runtime_1.jsxs)(DataFormProvider_1.DataFormProvider, { schema: schema, form: form, recordId: recordId, commands: commands, retriveRecordFn: retriveRecordFn, saveRecordFn: saveRecordFn, children: [(0, jsx_runtime_1.jsx)(UnsavedChangesInfoSetter_1.UnsavedChangesInfoSetter, {}), children] }));
|
|
8
9
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuickCreateProvider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const context_1 = require("../mutable/context");
|
|
6
|
+
const context_2 = require("./context");
|
|
7
|
+
const QuickCreateProvider = ({ children }) => {
|
|
8
|
+
const contextState = (0, context_1.useCreateContextStore)({
|
|
9
|
+
items: [],
|
|
10
|
+
});
|
|
11
|
+
return ((0, jsx_runtime_1.jsx)(context_2.QuickCreateContext.Provider, { value: contextState, children: children }));
|
|
12
|
+
};
|
|
13
|
+
exports.QuickCreateProvider = QuickCreateProvider;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Id } from '@headless-adminapp/core';
|
|
2
|
+
import { DataLookup } from '@headless-adminapp/core/attributes';
|
|
3
|
+
export interface QuickCreateOptions {
|
|
4
|
+
logicalName: string;
|
|
5
|
+
formId?: string;
|
|
6
|
+
onCreate?: (value: DataLookup<Id>) => void;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export type QuickCreateItemState = QuickCreateOptions & {
|
|
10
|
+
id: string;
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
};
|
|
13
|
+
export interface QuickCreateContextState {
|
|
14
|
+
items: QuickCreateItemState[];
|
|
15
|
+
}
|
|
16
|
+
export declare const QuickCreateContext: import("react").Context<import("../mutable").ContextValue<QuickCreateContextState>>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useOpenQuickCreate } from './useOpenQuickCreate';
|
|
2
|
+
export { useQuickCreateItem } from './useQuickCreateItem';
|
|
3
|
+
export { useQuickCreateItems } from './useQuickCreateItems';
|
|
4
|
+
export { useFormSave } from './useFormSave';
|
|
5
|
+
export { useIsQuickCreateSupported } from './useIsQuickCreateSupported';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useIsQuickCreateSupported = exports.useFormSave = exports.useQuickCreateItems = exports.useQuickCreateItem = exports.useOpenQuickCreate = void 0;
|
|
4
|
+
var useOpenQuickCreate_1 = require("./useOpenQuickCreate");
|
|
5
|
+
Object.defineProperty(exports, "useOpenQuickCreate", { enumerable: true, get: function () { return useOpenQuickCreate_1.useOpenQuickCreate; } });
|
|
6
|
+
var useQuickCreateItem_1 = require("./useQuickCreateItem");
|
|
7
|
+
Object.defineProperty(exports, "useQuickCreateItem", { enumerable: true, get: function () { return useQuickCreateItem_1.useQuickCreateItem; } });
|
|
8
|
+
var useQuickCreateItems_1 = require("./useQuickCreateItems");
|
|
9
|
+
Object.defineProperty(exports, "useQuickCreateItems", { enumerable: true, get: function () { return useQuickCreateItems_1.useQuickCreateItems; } });
|
|
10
|
+
var useFormSave_1 = require("./useFormSave");
|
|
11
|
+
Object.defineProperty(exports, "useFormSave", { enumerable: true, get: function () { return useFormSave_1.useFormSave; } });
|
|
12
|
+
var useIsQuickCreateSupported_1 = require("./useIsQuickCreateSupported");
|
|
13
|
+
Object.defineProperty(exports, "useIsQuickCreateSupported", { enumerable: true, get: function () { return useIsQuickCreateSupported_1.useIsQuickCreateSupported; } });
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFormSave = useFormSave;
|
|
4
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
7
|
+
const dataform_1 = require("../../dataform");
|
|
8
|
+
const useMetadata_1 = require("../../metadata/hooks/useMetadata");
|
|
9
|
+
const context_1 = require("../../mutable/context");
|
|
10
|
+
const useOpenToastNotification_1 = require("../../toast-notification/hooks/useOpenToastNotification");
|
|
11
|
+
const transport_1 = require("../../transport");
|
|
12
|
+
function useFormSave() {
|
|
13
|
+
const form = (0, dataform_1.useSelectedForm)();
|
|
14
|
+
const formInstance = (0, react_hook_form_1.useFormContext)();
|
|
15
|
+
const { schemaStore } = (0, useMetadata_1.useMetadata)();
|
|
16
|
+
const schema = (0, dataform_1.useDataFormSchema)();
|
|
17
|
+
const initialValues = (0, context_1.useContextSelector)(dataform_1.DataFormContext, (state) => state.initialValues);
|
|
18
|
+
const dataService = (0, transport_1.useDataService)();
|
|
19
|
+
const openToastNotification = (0, useOpenToastNotification_1.useOpenToastNotification)();
|
|
20
|
+
const saveRecord = (0, context_1.useContextSelector)(dataform_1.DataFormContext, (state) => state.saveRecordFn);
|
|
21
|
+
const client = (0, react_query_1.useQueryClient)();
|
|
22
|
+
const _save = async () => {
|
|
23
|
+
let saveResult = null;
|
|
24
|
+
await formInstance.handleSubmit(async (values) => {
|
|
25
|
+
const result = await saveRecord({
|
|
26
|
+
values,
|
|
27
|
+
form: form,
|
|
28
|
+
record: undefined,
|
|
29
|
+
initialValues: initialValues,
|
|
30
|
+
dataService,
|
|
31
|
+
schema: schema,
|
|
32
|
+
schemaStore,
|
|
33
|
+
});
|
|
34
|
+
if (!result.success) {
|
|
35
|
+
openToastNotification({
|
|
36
|
+
type: result.isError ? 'error' : 'info',
|
|
37
|
+
title: 'Error',
|
|
38
|
+
text: result.message,
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
await client.invalidateQueries({
|
|
43
|
+
queryKey: ['data', 'retriveRecords', schema.logicalName],
|
|
44
|
+
});
|
|
45
|
+
const record = await dataService.retriveRecord(schema.logicalName, result.recordId, [
|
|
46
|
+
schema.idAttribute,
|
|
47
|
+
schema.primaryAttribute,
|
|
48
|
+
schema.avatarAttribute,
|
|
49
|
+
].filter(Boolean));
|
|
50
|
+
saveResult = {
|
|
51
|
+
id: record[schema.idAttribute],
|
|
52
|
+
name: record[schema.primaryAttribute],
|
|
53
|
+
avatar: schema.avatarAttribute
|
|
54
|
+
? record[schema.avatarAttribute]
|
|
55
|
+
: undefined,
|
|
56
|
+
};
|
|
57
|
+
})();
|
|
58
|
+
return saveResult;
|
|
59
|
+
};
|
|
60
|
+
const _saveRef = (0, react_1.useRef)(_save);
|
|
61
|
+
_saveRef.current = _save;
|
|
62
|
+
const save = (0, react_1.useCallback)(() => _saveRef.current(), [_saveRef]);
|
|
63
|
+
return save;
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useIsQuickCreateSupported(logicalName: string): boolean | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useIsQuickCreateSupported = useIsQuickCreateSupported;
|
|
4
|
+
const metadata_1 = require("@headless-adminapp/app/metadata");
|
|
5
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
6
|
+
function useIsQuickCreateSupported(logicalName) {
|
|
7
|
+
const experienceStore = (0, metadata_1.useExperienceStore)();
|
|
8
|
+
const { data: isSupported } = (0, react_query_1.useQuery)({
|
|
9
|
+
queryKey: ['experience-schema-quick-create-form-supported', logicalName],
|
|
10
|
+
queryFn: async () => {
|
|
11
|
+
return experienceStore.getIsQuickCreateSupported(logicalName);
|
|
12
|
+
},
|
|
13
|
+
staleTime: 1000 * 60 * 5, // 5 minutes
|
|
14
|
+
});
|
|
15
|
+
return isSupported;
|
|
16
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useOpenQuickCreate = useOpenQuickCreate;
|
|
4
|
+
const mutable_1 = require("@headless-adminapp/app/mutable");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const uuid_1 = require("uuid");
|
|
7
|
+
const context_1 = require("../context");
|
|
8
|
+
function markAsClosed(items, id) {
|
|
9
|
+
return items.map((item) => {
|
|
10
|
+
if (item.id === id) {
|
|
11
|
+
return { ...item, isOpen: false };
|
|
12
|
+
}
|
|
13
|
+
return item;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function excludeItemById(items, id) {
|
|
17
|
+
return items.filter((item) => item.id !== id);
|
|
18
|
+
}
|
|
19
|
+
function useOpenQuickCreate() {
|
|
20
|
+
const setValue = (0, mutable_1.useContextSetValue)(context_1.QuickCreateContext);
|
|
21
|
+
const openQuickCreate = (0, react_1.useCallback)((options) => {
|
|
22
|
+
const id = (0, uuid_1.v4)();
|
|
23
|
+
const close = (id) => {
|
|
24
|
+
setValue((state) => ({
|
|
25
|
+
items: markAsClosed(state.items, id),
|
|
26
|
+
}));
|
|
27
|
+
// Simulate a delay to show the dialog closing animation
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
setValue((state) => ({
|
|
30
|
+
items: excludeItemById(state.items, id),
|
|
31
|
+
}));
|
|
32
|
+
}, 1000);
|
|
33
|
+
};
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
setValue((state) => {
|
|
36
|
+
return {
|
|
37
|
+
items: [
|
|
38
|
+
...state.items,
|
|
39
|
+
{
|
|
40
|
+
...options,
|
|
41
|
+
id,
|
|
42
|
+
isOpen: true,
|
|
43
|
+
onCancel: () => {
|
|
44
|
+
close(id);
|
|
45
|
+
resolve(null);
|
|
46
|
+
},
|
|
47
|
+
onCreate: (value) => {
|
|
48
|
+
close(id);
|
|
49
|
+
resolve(value);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}, [setValue]);
|
|
57
|
+
return openQuickCreate;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useQuickCreateItem(id: string): import("../context").QuickCreateItemState | undefined;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useQuickCreateItem = useQuickCreateItem;
|
|
4
|
+
const context_1 = require("../../mutable/context");
|
|
5
|
+
const context_2 = require("../context");
|
|
6
|
+
function useQuickCreateItem(id) {
|
|
7
|
+
return (0, context_1.useContextSelector)(context_2.QuickCreateContext, (state) => state.items.find((item) => item.id === id));
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useQuickCreateItems(): import("../context").QuickCreateItemState[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useQuickCreateItems = useQuickCreateItems;
|
|
4
|
+
const context_1 = require("../../mutable/context");
|
|
5
|
+
const context_2 = require("../context");
|
|
6
|
+
function useQuickCreateItems() {
|
|
7
|
+
return (0, context_1.useContextSelector)(context_2.QuickCreateContext, (state) => state.items);
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { QuickCreateProvider } from './QuickCreateProvider';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuickCreateProvider = void 0;
|
|
4
|
+
var QuickCreateProvider_1 = require("./QuickCreateProvider");
|
|
5
|
+
Object.defineProperty(exports, "QuickCreateProvider", { enumerable: true, get: function () { return QuickCreateProvider_1.QuickCreateProvider; } });
|
package/route/context.d.ts
CHANGED
|
@@ -5,16 +5,19 @@ export type InternalIsRouteActive = (path: string, item: NavPageItem) => boolean
|
|
|
5
5
|
interface NavigateOptions {
|
|
6
6
|
state?: any;
|
|
7
7
|
}
|
|
8
|
+
export type GuardFn = () => boolean | Promise<boolean>;
|
|
8
9
|
export interface RouterInstance {
|
|
9
|
-
back: () => void
|
|
10
|
-
forward: () => void
|
|
11
|
-
push(href: string, options?: NavigateOptions): void
|
|
12
|
-
replace(href: string, options?: NavigateOptions): void
|
|
10
|
+
back: () => Promise<void>;
|
|
11
|
+
forward: () => Promise<void>;
|
|
12
|
+
push(href: string, options?: NavigateOptions): Promise<void>;
|
|
13
|
+
replace(href: string, options?: NavigateOptions): Promise<void>;
|
|
13
14
|
prefetch(href: string): void;
|
|
14
15
|
setState(state: any): void;
|
|
15
16
|
setState(key: string, state: any): void;
|
|
16
17
|
getState<T = any>(): T;
|
|
17
18
|
getState<T = any>(key: string): T | undefined;
|
|
19
|
+
registerGuard(fn: GuardFn): void;
|
|
20
|
+
unregisterGuard(fn: GuardFn): void;
|
|
18
21
|
}
|
|
19
22
|
export declare const RouterContext: import("react").Context<RouterInstance>;
|
|
20
23
|
export declare const RouterPathnameContext: import("react").Context<string>;
|
|
@@ -21,8 +21,11 @@ export declare class SchemaExperienceStore implements ISchemaExperienceStore {
|
|
|
21
21
|
getViewLookupV2<S extends SchemaAttributes = SchemaAttributes>(logicalName: string, viewId?: string): Promise<View<S>>;
|
|
22
22
|
getDefaultViewId(logicalName: string): Promise<string>;
|
|
23
23
|
getDefaultViewLookupId(logicalName: string): Promise<string>;
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
getDefaultFormId(logicalName: string): Promise<string>;
|
|
25
|
+
getDefaultQuickCreateFormId(logicalName: string): Promise<string | null>;
|
|
26
|
+
getIsQuickCreateSupported(logicalName: string): Promise<boolean>;
|
|
27
|
+
getForm<S extends SchemaAttributes = SchemaAttributes>(logicalName: string, formId?: string): Promise<Form<S>>;
|
|
28
|
+
getQuickCreateForm<S extends SchemaAttributes = SchemaAttributes>(logicalName: string, formId?: string): Promise<QuickCreateForm<S>>;
|
|
26
29
|
getViewCommands(logicalName: string): Promise<EntityMainGridCommandItemExperience[][] | undefined>;
|
|
27
30
|
getFormCommands(logicalName: string): Promise<EntityMainFormCommandItemExperience[][] | undefined>;
|
|
28
31
|
getSubgridCommands(logicalName: string): Promise<SubGridCommandItemExperience[][] | undefined>;
|
|
@@ -151,6 +151,19 @@ class SchemaExperienceStore {
|
|
|
151
151
|
const experience = await this.getExperience(logicalName);
|
|
152
152
|
return experience.defaultLookupId;
|
|
153
153
|
}
|
|
154
|
+
async getDefaultFormId(logicalName) {
|
|
155
|
+
const experience = await this.getExperience(logicalName);
|
|
156
|
+
return experience.defaultFormId;
|
|
157
|
+
}
|
|
158
|
+
async getDefaultQuickCreateFormId(logicalName) {
|
|
159
|
+
const experience = await this.getExperience(logicalName);
|
|
160
|
+
return experience.defaultQuickCreateFormId ?? null;
|
|
161
|
+
}
|
|
162
|
+
async getIsQuickCreateSupported(logicalName) {
|
|
163
|
+
const experience = await this.getExperience(logicalName);
|
|
164
|
+
return (!!experience.defaultQuickCreateFormId &&
|
|
165
|
+
experience.quickCreateForms.length > 0);
|
|
166
|
+
}
|
|
154
167
|
async getForm(logicalName, formId) {
|
|
155
168
|
const experience = await this.getExperience(logicalName);
|
|
156
169
|
if (!formId) {
|
|
@@ -173,6 +186,12 @@ class SchemaExperienceStore {
|
|
|
173
186
|
}
|
|
174
187
|
async getQuickCreateForm(logicalName, formId) {
|
|
175
188
|
const experience = await this.getExperience(logicalName);
|
|
189
|
+
if (!formId) {
|
|
190
|
+
if (!experience.defaultQuickCreateFormId) {
|
|
191
|
+
throw new Error(`No quick create form ID provided and no default quick create form ID found for ${logicalName}`);
|
|
192
|
+
}
|
|
193
|
+
formId = experience.defaultQuickCreateFormId;
|
|
194
|
+
}
|
|
176
195
|
const form = experience.quickCreateForms.find((f) => f.id === formId);
|
|
177
196
|
if (!form) {
|
|
178
197
|
throw new Error(`Quick create form ${formId} not found`);
|