Skip to content

Commit

Permalink
JNG-4838 wire in post call operation hooks, fix dialog close lifecycle
Browse files Browse the repository at this point in the history
  • Loading branch information
noherczeg committed Nov 22, 2023
1 parent b1ad530 commit 2facb85
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,79 @@ import { useRef, createContext, useContext, useState } from 'react';
import Dialog from '@mui/material/Dialog';
import type { DialogProps } from '@mui/material';
import { SlideUpTransition } from '~/theme/animations';
import { dialogStackCloseDelay } from '~/config';

export type DialogOption = Omit<DialogProps, 'open'>;

type ProviderContext = readonly [(option: DialogOption) => void, () => void, () => void];
type ProviderContext = readonly [(option: DialogOption) => void, () => Promise<void>, () => Promise<void>];

const EMPTY_FUNC = () => {};
const DialogContext = createContext<ProviderContext>([
EMPTY_FUNC,
EMPTY_FUNC,
EMPTY_FUNC,
]);
const EMPTY_FUNC = () => undefined;
const EMPTY_ASYNC_FUNC = () => Promise.resolve();
const DialogContext = createContext<ProviderContext>([EMPTY_FUNC, EMPTY_ASYNC_FUNC, EMPTY_ASYNC_FUNC]);

export const useDialog = () => useContext(DialogContext);

export function StackableDialogProvider({ children }: { children: ReactNode }) {
const [dialogs, setDialogs] = useState<DialogProps[]>([]);
const createDialog = (option: DialogOption) => {
const dialog = { ...option, open: true };
setDialogs((d) => [...d, dialog]);
};
const closeDialog = () => {
setDialogs((d) => {
// const tmp = d[d.length - 1];
//
// if (tmp && tmp.disableBackdropClick && reason === 'backdropClick') {
// return d;
// }
const [dialogs, setDialogs] = useState<DialogProps[]>([]);
const createDialog = (option: DialogOption) => {
const dialog = { ...option, open: true };
setDialogs((d) => [...d, dialog]);
};
const closeDialog: () => Promise<void> = async () => {
return new Promise((resolve, reject) => {
setDialogs((d) => {
// const tmp = d[d.length - 1];
//
// if (tmp && tmp.disableBackdropClick && reason === 'backdropClick') {
// return d;
// }

const latestDialog = d.pop();
if (!latestDialog) return d;
// if (latestDialog.onClose) latestDialog.onClose({}, undefined);
latestDialog.open = false
return [...d];
// return [...d].concat({ ...latestDialog, open: false });
});
};
const closeAllDialogs = () => {
setDialogs((d) => {
for (const dialog of d) {
dialog.open = false;
}
return [];
});
};
const contextValue = useRef([createDialog, closeDialog, closeAllDialogs] as const);
const latestDialog = d.pop();
if (!latestDialog) return d;
// if (latestDialog.onClose) latestDialog.onClose({}, undefined);
latestDialog.open = false
return [...d];
// return [...d].concat({ ...latestDialog, open: false });
});
window.setTimeout(() => {
resolve(undefined);
}, dialogStackCloseDelay);
});
};
const closeAllDialogs: () => Promise<void> = async () => {
return new Promise((resolve, reject) => {
setDialogs((d) => {
for (const dialog of d) {
dialog.open = false;
}
return [];
});
window.setTimeout(() => {
resolve(undefined);
}, dialogStackCloseDelay);
});
};
const contextValue = useRef([createDialog, closeDialog, closeAllDialogs] as const);

return (
<DialogContext.Provider value={contextValue.current}>
{children}
{dialogs.map((dialog, i) => {
const { ...dialogParams } = dialog;
// const handleKill = () => {
// if (dialog.onExited) dialog.onExited();
// setDialogs((dialogs) => dialogs.slice(0, dialogs.length - 1));
// };
return (
<DialogContext.Provider value={contextValue.current}>
{children}
{dialogs.map((dialog, i) => {
const { ...dialogParams } = dialog;
// const handleKill = () => {
// if (dialog.onExited) dialog.onExited();
// setDialogs((dialogs) => dialogs.slice(0, dialogs.length - 1));
// };

return (
<Dialog
TransitionComponent={SlideUpTransition}
key={i}
// onKill={handleKill}
{...dialogParams}
/>
);
})}
</DialogContext.Provider>
);
return (
<Dialog
TransitionComponent={SlideUpTransition}
key={i}
// onKill={handleKill}
{...dialogParams}
/>
);
})}
</DialogContext.Provider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ export const debounceInputs: number = 500;
export const animationDuration: number = 0.8;

export const delayDuration: number = 0.2;

export const dialogStackCloseDelay: number = 50;
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { useConfirmDialog } from '~/components/dialog';
export interface {{ containerComponentName container }}DialogProps {
ownerData: any;
title: string;
onClose: () => void;
onClose: () => Promise<void>;
{{# unless (containerIsEmptyDashboard container) }}
actions: {{ containerComponentName container }}DialogActions;
isLoading: boolean;
Expand Down
24 changes: 13 additions & 11 deletions judo-ui-react/src/main/resources/actor/src/dialogs/index.tsx.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,18 @@ import { useCallback, useEffect, useRef, useState, lazy, Suspense } from 'react'
{{/ unless }}

{{# unless (containerIsEmptyDashboard page.container) }}
export const {{ camelCaseNameToInterfaceKey (pageName page) }}_ACTIONS_HOOK_INTERFACE_KEY = '{{ containerComponentName page.container }}ActionsHook';
export type {{ containerComponentName page.container }}DialogActionsExtended = {{ containerComponentName page.container }}DialogActions & {
{{# each (getAllCallOperationActions page) as |action| }}
post{{ firstToUpper (simpleActionDefinitionName action.actionDefinition) }}?: (
{{# if action.actionDefinition.targetType }}target: {{ classDataName action.actionDefinition.targetType 'Stored' }},{{/ if }}
{{# if action.actionDefinition.operation.output }}output: {{ classDataName action.actionDefinition.operation.output.target '' }},{{/ if }}
{{# if page.container.form }}onSubmit: (result?: {{# if (pageHasOutputTarget page) }}{{ classDataName (getPageOutputTarget page) 'Stored' }}{{ else }}{{ dialogDataType page }}{{# if page.container.table }}[]{{/ if }}{{/ if }}) => void{{/ if }}
{{# if page.container.form }}onSubmit: (result?: {{# if (pageHasOutputTarget page) }}{{ classDataName (getPageOutputTarget page) 'Stored' }}{{ else }}{{ dialogDataType page }}{{# if page.container.table }}[]{{/ if }}{{/ if }}) => Promise<void>,{{/ if }}
onClose: () => Promise<void>
) => Promise<void>;
{{/ each }}
};

export const {{ camelCaseNameToInterfaceKey (pageName page) }}_ACTIONS_HOOK_INTERFACE_KEY = '{{ containerComponentName page.container }}ActionsHook';
export type {{ containerComponentName page.container }}ActionsHook = (
ownerData: any,
data: {{ dialogDataType page }}{{# if page.container.table }}[]{{/ if }},
Expand All @@ -77,9 +79,9 @@ import { useCallback, useEffect, useRef, useState, lazy, Suspense } from 'react'
fullWidth: true,
maxWidth: '{{ toLower page.dialogSize.name }}',
{{/ if }}
onClose: (event: object, reason: string) => {
onClose: async (event: object, reason: string) => {
if (reason !== 'backdropClick') {
closeDialog();
await closeDialog();
resolve({
result: 'close',
});
Expand All @@ -91,14 +93,14 @@ import { useCallback, useEffect, useRef, useState, lazy, Suspense } from 'react'
{{# if page.container.isRelationSelector}}
alreadySelected={alreadySelected}
{{/ if }}
onClose={() => {
closeDialog();
onClose={async () => {
await closeDialog();
resolve({
result: 'close',
});
}}
onSubmit={({{# if (dialogHasResult page) }}result{{/ if }}) => {
closeDialog();
onSubmit={async ({{# if (dialogHasResult page) }}result{{/ if }}) => {
await closeDialog();
resolve({
result: 'submit',
{{# if (dialogHasResult page) }}
Expand All @@ -123,11 +125,11 @@ import { useCallback, useEffect, useRef, useState, lazy, Suspense } from 'react'
export interface {{ pageName page }}Props {
ownerData: any;
{{# if page.container.isRelationSelector }}alreadySelected: {{ classDataName (getReferenceClassType page) 'Stored' }}[]{{/ if }}
onClose: () => void;
onClose: () => Promise<void>;
{{# if (pageHasOutputTarget page) }}
onSubmit: (result?: {{ classDataName (getPageOutputTarget page) 'Stored' }}) => void;
onSubmit: (result?: {{ classDataName (getPageOutputTarget page) 'Stored' }}) => Promise<void>;
{{ else }}
onSubmit: (result?: {{ dialogDataType page }}{{# if page.container.table }}[]{{/ if }}) => void;
onSubmit: (result?: {{ dialogDataType page }}{{# if page.container.table }}[]{{/ if }}) => Promise<void>;
{{/ if }}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ const {{ simpleActionDefinitionName action.actionDefinition }} = async ({{# if a
await customActions.post{{ firstToUpper (simpleActionDefinitionName action.actionDefinition) }}(
{{# if action.actionDefinition.targetType }}target!,{{/ if }}
{{# if operation.output }}result,{{/ if }}
{{# if page.container.form }}onSubmit{{/ if }}
{{# if page.container.form }}onSubmit,{{/ if }}
{{# if page.openInDialog }}onClose{{/ if }}
);
} else {
enqueueSnackbar(t('judo.action.operation.success', { defaultValue: 'Operation executed successfully' }) as string, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ const {{ simpleActionDefinitionName action.actionDefinition }} = async ({{# if a
const { result, data: returnedData } = await open{{ pageName action.targetPageDefinition }}({{# if action.actionDefinition.targetType }}target{{ else }}data{{/ if }});
{{# with (getRefreshActionDefinitionForContainer page.container) as |actionDefinition| }}
{{# if page.container.view }}
if (!editMode) {
if (result === 'submit' && !editMode) {
await actions.{{ simpleActionDefinitionName actionDefinition }}!(processQueryCustomizer(pageQueryCustomizer));
}
{{/ if }}
{{# if page.container.table }}
setRefreshCounter((prev) => prev + 1);
if (result === 'submit') {
setRefreshCounter((prev) => prev + 1);
}
{{/ if }}
{{/ with }}
};
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ import { useCallback, useEffect, useRef, useState, lazy, Suspense } from 'react'
{{/ unless }}

{{# unless (containerIsEmptyDashboard page.container) }}
export const {{ camelCaseNameToInterfaceKey (pageName page) }}_ACTIONS_HOOK_INTERFACE_KEY = '{{ containerComponentName page.container }}ActionsHook';
export type {{ containerComponentName page.container }}PageActionsExtended = {{ containerComponentName page.container }}PageActions & {
{{# each (getAllCallOperationActions page) as |action| }}
post{{ firstToUpper (simpleActionDefinitionName action.actionDefinition) }}?: ({{# if action.actionDefinition.targetType }}target: {{ classDataName action.actionDefinition.targetType 'Stored' }}{{/ if }}{{# if action.actionDefinition.operation.output }}{{# if action.actionDefinition.targetType }},{{/ if }}output: {{ classDataName action.actionDefinition.operation.output.target '' }}{{/ if }}) => Promise<void>;
{{/ each }}
};

export const {{ camelCaseNameToInterfaceKey (pageName page) }}_ACTIONS_HOOK_INTERFACE_KEY = '{{ containerComponentName page.container }}ActionsHook';
export type {{ containerComponentName page.container }}ActionsHook = (
data: {{ classDataName (getReferenceClassType page) 'Stored' }}{{# if page.container.table }}[]{{/ if }},
editMode: boolean,
Expand Down

0 comments on commit 2facb85

Please sign in to comment.