chore: Automatically display errors as toast if uncaught in actions (#6482)
Reduces plumbing
This commit is contained in:
@@ -86,19 +86,14 @@ export const clearIndexedDB = createAction({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const createTestUsers = createAction({
|
export const createTestUsers = createAction({
|
||||||
name: "Create test users",
|
name: "Create 10 test users",
|
||||||
icon: <UserIcon />,
|
icon: <UserIcon />,
|
||||||
section: DeveloperSection,
|
section: DeveloperSection,
|
||||||
visible: () => env.ENVIRONMENT === "development",
|
visible: () => env.ENVIRONMENT === "development",
|
||||||
perform: async () => {
|
perform: async () => {
|
||||||
const count = 10;
|
const count = 10;
|
||||||
|
|
||||||
try {
|
|
||||||
await client.post("/developer.create_test_users", { count });
|
await client.post("/developer.create_test_users", { count });
|
||||||
toast.message(`${count} test users created`);
|
toast.message(`${count} test users created`);
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -251,7 +251,6 @@ export const unpublishDocument = createAction({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await document.unpublish();
|
await document.unpublish();
|
||||||
|
|
||||||
toast.success(
|
toast.success(
|
||||||
@@ -259,9 +258,6 @@ export const unpublishDocument = createAction({
|
|||||||
documentName: document.noun,
|
documentName: document.noun,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -288,9 +284,7 @@ export const subscribeDocument = createAction({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const document = stores.documents.get(activeDocumentId);
|
const document = stores.documents.get(activeDocumentId);
|
||||||
|
|
||||||
await document?.subscribe();
|
await document?.subscribe();
|
||||||
|
|
||||||
toast.success(t("Subscribed to document notifications"));
|
toast.success(t("Subscribed to document notifications"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -540,7 +534,6 @@ export const pinDocumentToCollection = createAction({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const document = stores.documents.get(activeDocumentId);
|
const document = stores.documents.get(activeDocumentId);
|
||||||
await document?.pin(document.collectionId);
|
await document?.pin(document.collectionId);
|
||||||
|
|
||||||
@@ -549,9 +542,6 @@ export const pinDocumentToCollection = createAction({
|
|||||||
if (!collection || !location.pathname.startsWith(collection?.url)) {
|
if (!collection || !location.pathname.startsWith(collection?.url)) {
|
||||||
toast.success(t("Pinned to collection"));
|
toast.success(t("Pinned to collection"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -583,15 +573,11 @@ export const pinDocumentToHome = createAction({
|
|||||||
}
|
}
|
||||||
const document = stores.documents.get(activeDocumentId);
|
const document = stores.documents.get(activeDocumentId);
|
||||||
|
|
||||||
try {
|
|
||||||
await document?.pin();
|
await document?.pin();
|
||||||
|
|
||||||
if (location.pathname !== homePath()) {
|
if (location.pathname !== homePath()) {
|
||||||
toast.success(t("Pinned to home"));
|
toast.success(t("Pinned to home"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -641,7 +627,6 @@ export const importDocument = createAction({
|
|||||||
input.onchange = async (ev) => {
|
input.onchange = async (ev) => {
|
||||||
const files = getEventFiles(ev);
|
const files = getEventFiles(ev);
|
||||||
|
|
||||||
try {
|
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
const document = await documents.import(
|
const document = await documents.import(
|
||||||
file,
|
file,
|
||||||
@@ -652,10 +637,6 @@ export const importDocument = createAction({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
history.push(document.url);
|
history.push(document.url);
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
input.click();
|
input.click();
|
||||||
|
|||||||
@@ -74,13 +74,7 @@ export function actionToMenuItem(
|
|||||||
icon,
|
icon,
|
||||||
visible,
|
visible,
|
||||||
dangerous: action.dangerous,
|
dangerous: action.dangerous,
|
||||||
onClick: () => {
|
onClick: () => performAction(action, context),
|
||||||
try {
|
|
||||||
action.perform?.(context);
|
|
||||||
} catch (err) {
|
|
||||||
toast.error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selected: action.selected?.(context),
|
selected: action.selected?.(context),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -114,10 +108,18 @@ export function actionToKBar(
|
|||||||
keywords: action.keywords ?? "",
|
keywords: action.keywords ?? "",
|
||||||
shortcut: action.shortcut || [],
|
shortcut: action.shortcut || [],
|
||||||
icon: resolvedIcon,
|
icon: resolvedIcon,
|
||||||
perform: action.perform ? () => action.perform?.(context) : undefined,
|
perform: action.perform
|
||||||
|
? () => performAction(action, context)
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
].concat(
|
].concat(
|
||||||
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
|
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
|
||||||
children.map((child) => ({ ...child, parent: child.parent ?? action.id }))
|
children.map((child) => ({ ...child, parent: child.parent ?? action.id }))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function performAction(action: Action, context: ActionContext) {
|
||||||
|
return action.perform?.(context).catch((err: Error) => {
|
||||||
|
toast.error(err.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Tooltip, { Props as TooltipProps } from "~/components/Tooltip";
|
import Tooltip, { Props as TooltipProps } from "~/components/Tooltip";
|
||||||
|
import { performAction } from "~/actions";
|
||||||
import { Action, ActionContext } from "~/types";
|
import { Action, ActionContext } from "~/types";
|
||||||
|
|
||||||
export type Props = React.HTMLAttributes<HTMLButtonElement> & {
|
export type Props = React.HTMLAttributes<HTMLButtonElement> & {
|
||||||
@@ -60,10 +61,10 @@ const ActionButton = React.forwardRef<HTMLButtonElement, Props>(
|
|||||||
? (ev) => {
|
? (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
const response = action.perform?.(actionContext);
|
const response = performAction(action, actionContext);
|
||||||
if (response?.finally) {
|
if (response?.finally) {
|
||||||
setExecuting(true);
|
setExecuting(true);
|
||||||
response.finally(() => setExecuting(false));
|
void response.finally(() => setExecuting(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: rest.onClick
|
: rest.onClick
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ export type Action = {
|
|||||||
placeholder?: ((context: ActionContext) => string) | string;
|
placeholder?: ((context: ActionContext) => string) | string;
|
||||||
selected?: (context: ActionContext) => boolean;
|
selected?: (context: ActionContext) => boolean;
|
||||||
visible?: (context: ActionContext) => boolean;
|
visible?: (context: ActionContext) => boolean;
|
||||||
|
/**
|
||||||
|
* Perform the action – note this should generally not be called directly, use `performAction`
|
||||||
|
* instead. Errors will be caught and displayed to the user as a toast message.
|
||||||
|
*/
|
||||||
perform?: (context: ActionContext) => Promise<any> | any;
|
perform?: (context: ActionContext) => Promise<any> | any;
|
||||||
children?: ((context: ActionContext) => Action[]) | Action[];
|
children?: ((context: ActionContext) => Action[]) | Action[];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user