Skip to content

Commit

Permalink
Refactor RouterPromptHandler to store saveAction as part of the r…
Browse files Browse the repository at this point in the history
…egistered message instead of creating a separate record (#1440)
  • Loading branch information
nsams authored Nov 29, 2023
1 parent 0a8bafa commit bccb21c
Showing 1 changed file with 11 additions and 20 deletions.
31 changes: 11 additions & 20 deletions packages/admin/admin/src/router/PromptHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ export interface PromptHandlerApi {
}
function InnerPromptHandler({
registeredMessages,
saveActions,
apiRef,
}: {
registeredMessages: React.MutableRefObject<PromptMessages>;
saveActions: React.MutableRefObject<SaveActions>;
apiRef: React.MutableRefObject<PromptHandlerApi | undefined>;
}) {
const [state, setState] = React.useState<PromptHandlerState>({
Expand Down Expand Up @@ -55,8 +53,11 @@ function InnerPromptHandler({

const handleClose = async (action: PromptAction) => {
let allowTransition: boolean;
if (Object.keys(saveActions.current).length > 0 && action === PromptAction.Save) {
const results: Array<SaveActionSuccess> = await Promise.all(Object.keys(saveActions.current).map((id) => saveActions.current[id]()));
const saveActions = Object.values(registeredMessages.current)
.filter((registeredMessage) => !!registeredMessage.saveAction)
.map((registeredMessage) => registeredMessage.saveAction);
if (saveActions.length > 0 && action === PromptAction.Save) {
const results: Array<SaveActionSuccess> = await Promise.all(saveActions.map((saveAction) => saveAction!()));
allowTransition = results.every((saveActionSuccess) => saveActionSuccess);
} else {
allowTransition = action === PromptAction.Discard;
Expand All @@ -77,7 +78,7 @@ function InnerPromptHandler({
isOpen={state.showConfirmationDialog}
message={state.message}
handleClose={handleClose}
showSaveButton={Object.keys(saveActions.current).length > 0}
showSaveButton={Object.values(registeredMessages.current).some((registeredMessage) => !!registeredMessage.saveAction)}
/>
<Prompt when={true} message={promptMessage} />
</>
Expand All @@ -89,6 +90,7 @@ interface PromptMessages {
message: (location: History.Location, action: History.Action) => boolean | string;
path: string;
subRoutePath?: string;
saveAction?: SaveAction;
};
}
interface Props {
Expand All @@ -98,13 +100,8 @@ interface Props {
export type SaveActionSuccess = boolean;
export type SaveAction = (() => Promise<SaveActionSuccess>) | (() => SaveActionSuccess);

interface SaveActions {
[id: string]: SaveAction;
}

export const RouterPromptHandler: React.FunctionComponent<Props> = ({ children, apiRef }) => {
const registeredMessages = React.useRef<PromptMessages>({});
const saveActions = React.useRef<SaveActions>({});

const register = ({
id,
Expand All @@ -115,18 +112,13 @@ export const RouterPromptHandler: React.FunctionComponent<Props> = ({ children,
}: {
id: string;
message: (location: History.Location, action: History.Action) => string | boolean;
saveAction: SaveAction;
saveAction?: SaveAction;
path: string;
subRoutePath?: string;
}) => {
registeredMessages.current[id] = { message, path, subRoutePath };
if (saveAction) {
saveActions.current[id] = saveAction;
}
registeredMessages.current[id] = { message, path, subRoutePath, saveAction };
// If saveAction is passed it has to be passed for all registered components
const countSaveActions = Object.keys(saveActions.current).length;
const countRegisteredMessages = Object.keys(registeredMessages.current).length;
if (countSaveActions > 0 && countSaveActions !== countRegisteredMessages) {
if (saveAction && Object.values(registeredMessages.current).some((registeredMessage) => !registeredMessage.saveAction)) {
// eslint-disable-next-line no-console
console.error(
"A component (e.g. RouterPrompt) is missing a saveAction-prop. If you fail to do so, the Save-Button in the Dirty-Dialog won't save the changes",
Expand All @@ -136,7 +128,6 @@ export const RouterPromptHandler: React.FunctionComponent<Props> = ({ children,

const unregister = (id: string) => {
delete registeredMessages.current[id];
if (saveActions.current[id] !== undefined) delete saveActions.current[id];
};

return (
Expand All @@ -147,7 +138,7 @@ export const RouterPromptHandler: React.FunctionComponent<Props> = ({ children,
}}
>
{/* inner component not wrapping children contains local state to avoid rerender on state change */}
<InnerPromptHandler registeredMessages={registeredMessages} saveActions={saveActions} apiRef={apiRef} />
<InnerPromptHandler registeredMessages={registeredMessages} apiRef={apiRef} />
{children}
</RouterContext.Provider>
);
Expand Down

0 comments on commit bccb21c

Please sign in to comment.