@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.
Files changed (49) hide show
  1. package/app/LayoutProvider.js +4 -1
  2. package/command/types.d.ts +1 -1
  3. package/dataform/DataFormProvider/UnsavedChangesInfoSetter.d.ts +2 -0
  4. package/dataform/DataFormProvider/UnsavedChangesInfoSetter.js +25 -0
  5. package/dataform/hooks/useFormSave.js +4 -2
  6. package/dataform/utils/defaultParameters.js +10 -1
  7. package/datagrid/hooks/useOpenRecord.d.ts +1 -1
  8. package/datagrid/hooks/useOpenRecord.js +2 -2
  9. package/dialog/hooks/useCloseDialog.d.ts +3 -0
  10. package/dialog/hooks/useCloseDialog.js +3 -0
  11. package/dialog/hooks/useOpenConfirmDialog.d.ts +3 -0
  12. package/dialog/hooks/useOpenConfirmDialog.js +3 -0
  13. package/dialog/hooks/useOpenDialog.d.ts +3 -0
  14. package/dialog/hooks/useOpenDialog.js +3 -0
  15. package/mutable/context.d.ts +3 -0
  16. package/mutable/context.js +3 -0
  17. package/navigation/hooks/useOpenForm.d.ts +1 -1
  18. package/navigation/hooks/useOpenForm.js +3 -3
  19. package/navigation/unsaved-changes/UnsavedChangesRouteGuard.d.ts +1 -0
  20. package/navigation/unsaved-changes/UnsavedChangesRouteGuard.js +9 -0
  21. package/navigation/unsaved-changes/index.d.ts +3 -0
  22. package/navigation/unsaved-changes/index.js +10 -0
  23. package/navigation/unsaved-changes/unsavedChangesInfo.d.ts +6 -0
  24. package/navigation/unsaved-changes/unsavedChangesInfo.js +11 -0
  25. package/navigation/unsaved-changes/useUnsavedChangesRouteGuard.d.ts +1 -0
  26. package/navigation/unsaved-changes/useUnsavedChangesRouteGuard.js +48 -0
  27. package/package.json +2 -2
  28. package/providers/PageEntityFormProvider/index.js +2 -1
  29. package/quickcreate/QuickCreateProvider.d.ts +5 -0
  30. package/quickcreate/QuickCreateProvider.js +13 -0
  31. package/quickcreate/context.d.ts +16 -0
  32. package/quickcreate/context.js +5 -0
  33. package/quickcreate/hooks/index.d.ts +5 -0
  34. package/quickcreate/hooks/index.js +13 -0
  35. package/quickcreate/hooks/useFormSave.d.ts +2 -0
  36. package/quickcreate/hooks/useFormSave.js +64 -0
  37. package/quickcreate/hooks/useIsQuickCreateSupported.d.ts +1 -0
  38. package/quickcreate/hooks/useIsQuickCreateSupported.js +16 -0
  39. package/quickcreate/hooks/useOpenQuickCreate.d.ts +3 -0
  40. package/quickcreate/hooks/useOpenQuickCreate.js +58 -0
  41. package/quickcreate/hooks/useQuickCreateItem.d.ts +1 -0
  42. package/quickcreate/hooks/useQuickCreateItem.js +8 -0
  43. package/quickcreate/hooks/useQuickCreateItems.d.ts +1 -0
  44. package/quickcreate/hooks/useQuickCreateItems.js +8 -0
  45. package/quickcreate/index.d.ts +1 -0
  46. package/quickcreate/index.js +5 -0
  47. package/route/context.d.ts +7 -4
  48. package/store/SchemaExperienceStore.d.ts +5 -2
  49. package/store/SchemaExperienceStore.js +19 -0
@@ -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.jsx)(AuthWrapper_1.AuthWrapper, { Placeholder: authPlaceholder, children: children }) }) })] }) }) }) }) }) }) }) }) }));
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;
@@ -39,7 +39,7 @@ interface BaseCommandState {
39
39
  appearance?: 'subtle' | 'colored';
40
40
  }
41
41
  interface ActionableCommandState {
42
- onClick?: () => void;
42
+ onClick?: () => void | Promise<void>;
43
43
  disabled?: boolean;
44
44
  hidden?: boolean;
45
45
  }
@@ -0,0 +1,2 @@
1
+ import { FC } from 'react';
2
+ export declare const UnsavedChangesInfoSetter: FC;
@@ -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
- defaultValue = new Date().toISOString();
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
  ? {
@@ -1 +1,4 @@
1
+ /**
2
+ * @zero-deps
3
+ */
1
4
  export declare function useCloseDialog(): (id: string) => void;
@@ -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) => {
@@ -1,4 +1,7 @@
1
1
  import { DialogOptions } from '@headless-adminapp/core/experience/dialog';
2
+ /**
3
+ * @zero-deps
4
+ */
2
5
  export declare function useOpenDialog(): (options: DialogOptions) => {
3
6
  id: string;
4
7
  close: () => void;
@@ -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)();
@@ -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;
@@ -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,3 @@
1
+ export { getUnsavedChangesInfo, setUnsavedChangesInfo, } from './unsavedChangesInfo';
2
+ export { useUnsavedChangesRouteGuard } from './useUnsavedChangesRouteGuard';
3
+ export { UnsavedChangesRouteGuard } from './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,6 @@
1
+ export interface UnsavedChangesInfo {
2
+ title: string;
3
+ message: string;
4
+ }
5
+ export declare function getUnsavedChangesInfo(): UnsavedChangesInfo | null;
6
+ export declare function setUnsavedChangesInfo(info: UnsavedChangesInfo | null): void;
@@ -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.20",
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": "be1677e04dcd2ac91082078c0b59f81b0799d469"
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.jsx)(DataFormProvider_1.DataFormProvider, { schema: schema, form: form, recordId: recordId, commands: commands, retriveRecordFn: retriveRecordFn, saveRecordFn: saveRecordFn, children: children }));
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,5 @@
1
+ import { FC, PropsWithChildren } from 'react';
2
+ interface QuickCreateProviderProps {
3
+ }
4
+ export declare const QuickCreateProvider: FC<PropsWithChildren<QuickCreateProviderProps>>;
5
+ export {};
@@ -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
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QuickCreateContext = void 0;
4
+ const mutable_1 = require("../mutable");
5
+ exports.QuickCreateContext = (0, mutable_1.createContext)();
@@ -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,2 @@
1
+ import { DataLookup, Id } from '@headless-adminapp/core/attributes';
2
+ export declare function useFormSave(): () => Promise<DataLookup<Id> | null>;
@@ -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,3 @@
1
+ import { DataLookup, Id } from '@headless-adminapp/core/attributes';
2
+ import { QuickCreateOptions } from '../context';
3
+ export declare function useOpenQuickCreate(): (options: Omit<QuickCreateOptions, "onCreate" | "onCancel">) => Promise<DataLookup<Id> | null>;
@@ -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; } });
@@ -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
- getForm<S extends SchemaAttributes = SchemaAttributes>(logicalName: string, formId: string): Promise<Form<S>>;
25
- getQuickCreateForm<S extends SchemaAttributes = SchemaAttributes>(logicalName: string, formId: string): Promise<QuickCreateForm<S>>;
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`);