Skip to content

Commit 85a29a8

Browse files
Merge pull request #13674 from AlexVelezLl/refactor-undo-actions
Refactor undo actions + consistent go back and close confirmation guards
2 parents cbed7b3 + 353333d commit 85a29a8

File tree

22 files changed

+862
-688
lines changed

22 files changed

+862
-688
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { bulkUserManagementStrings } from 'kolibri-common/strings/bulkUserManagementStrings';
2+
import useSnackbar from 'kolibri/composables/useSnackbar';
3+
4+
/**
5+
*
6+
* @param {Object} options
7+
* @param {() => Promise<boolean>} options.action - Callback that executes the action to perform.
8+
* Should return a boolean promise indicating whether the action was successful. If the action
9+
* succeeds, the snackbar will display a success message and provide an undo option.
10+
*
11+
* @param {() => string} options.actionNotice$ - Function that returns the message to display on
12+
* the snackbar when the action is successful.
13+
*
14+
* @param {() => Promise<void>} options.undoAction - Callback that executes the undo action.
15+
* Be careful if this action is happening after the component that triggered the original action has
16+
* been unmounted (e.g. you cannot emit events from an unmounted component). If the undoAction fails
17+
* the function should throw an error, and a snackbar will be shown with a generic error message.
18+
*
19+
* @param {() => string} options.undoActionNotice$ - Function that returns the message to display on
20+
* the snackbar when the undo action is successful.
21+
*
22+
* @param {() => void} [options.onBlur] - Optional callback that executes when the undo button in
23+
* the snackbar loses focus.
24+
*
25+
* @typedef {Object} UseActionWithUndoObject
26+
* @property {() => Promise<void>} performAction - A method to manually trigger the main action
27+
* with all the undo machinery set up.
28+
*
29+
* @returns {UseActionWithUndoObject}
30+
*/
31+
export default function useActionWithUndo({
32+
action,
33+
actionNotice$,
34+
undoAction,
35+
undoActionNotice$,
36+
onBlur,
37+
}) {
38+
const { undoAction$, defaultErrorMessage$ } = bulkUserManagementStrings;
39+
const { createSnackbar, clearSnackbar } = useSnackbar();
40+
41+
const performUndoAction = async () => {
42+
clearSnackbar();
43+
try {
44+
await undoAction();
45+
createSnackbar(undoActionNotice$());
46+
} catch (error) {
47+
createSnackbar(defaultErrorMessage$());
48+
}
49+
};
50+
51+
const performAction = async () => {
52+
const success = await action();
53+
if (!success) {
54+
return;
55+
}
56+
57+
createSnackbar({
58+
text: actionNotice$(),
59+
autofocus: true,
60+
autoDismiss: true,
61+
duration: 6000,
62+
actionText: undoAction$(),
63+
onBlur,
64+
actionCallback: performUndoAction,
65+
});
66+
};
67+
68+
return {
69+
performAction,
70+
};
71+
}

kolibri/plugins/facility/assets/src/utils.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ export function getRootRouteName(route) {
4949
if (route.name?.endsWith('__NEW_USERS')) {
5050
return PageNames.NEW_USERS_PAGE;
5151
}
52+
if (route.name?.endsWith('__TRASH')) {
53+
return PageNames.USERS_TRASH_PAGE;
54+
}
5255
return PageNames.USER_MGMT_PAGE;
5356
}
5457

kolibri/plugins/facility/assets/src/views/FacilityAppBarPage.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<template>
22

33
<AppBarPage :title="title">
4-
<div style="max-width: 1000px; margin: 0 auto">
5-
<slot></slot>
6-
</div>
4+
<template #default="{ pageContentHeight }">
5+
<div style="max-width: 1000px; margin: 0 auto">
6+
<slot :pageContentHeight="pageContentHeight"></slot>
7+
</div>
8+
</template>
79
</AppBarPage>
810

911
</template>

0 commit comments

Comments
 (0)