Skip to content

Commit 0d7b2cf

Browse files
authored
Merge pull request #351 from devforth/AdminForth/688
feat: add possibility to add buttons in adminforth.alert method
2 parents 2f182c4 + 99be1e8 commit 0d7b2cf

File tree

4 files changed

+69
-11
lines changed

4 files changed

+69
-11
lines changed

adminforth/spa/src/adminforth.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,24 @@ class FrontendAPI implements FrontendAPIInterface {
9797
})
9898
}
9999

100-
alert(params: AlertParams): void {
101-
this.toastStore.addToast({
100+
alert(params: AlertParams): void | Promise<string> | string {
101+
const toats = {
102102
message: params.message,
103103
messageHtml: params.messageHtml,
104104
variant: params.variant,
105-
timeout: params.timeout
106-
})
105+
timeout: params.timeout,
106+
buttons: params.buttons,
107+
}
108+
if (params.buttons && params.buttons.length > 0) {
109+
return new Promise<string>((resolve) => {
110+
this.toastStore.addToast({
111+
...toats,
112+
onResolve: (value?: any) => resolve(String(value ?? '')),
113+
})
114+
})
115+
} else {
116+
this.toastStore.addToast({...toats})
117+
}
107118
}
108119

109120
listFilterValidation(filter: FilterParams): boolean {

adminforth/spa/src/components/Toast.vue

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,18 @@
3030
</div>
3131

3232
<div class="ms-3 text-sm font-normal max-w-xs pr-2" v-if="toast.messageHtml" v-html="toast.messageHtml"></div>
33-
<div class="ms-3 text-sm font-normal max-w-xs pr-2" v-else>{{toast.message}}</div>
33+
<div class="ms-3 text-sm font-normal max-w-xs pr-2" v-else>
34+
<div class="flex flex-col items-center justify-center">
35+
{{toast.message}}
36+
<div class="flex justify-center mt-2 gap-2">
37+
<div v-for="button in toast.buttons" class="rounded-md bg-lightButtonsBackground hover:bg-lightButtonsHover text-lightButtonsText dark:bg-darkPrimary dark:hover:bg-darkButtonsBackground dark:text-darkButtonsText">
38+
<button @click="onButtonClick(button.value)" class="px-2 py-1 rounded hover:bg-black/5 dark:hover:bg-white/10">
39+
{{ button.label }}
40+
</button>
41+
</div>
42+
</div>
43+
</div>
44+
</div>
3445
<button @click="closeToast" type="button" class="ms-auto -mx-1.5 -my-1.5 bg-lightToastCloseIconBackground text-lightToastCloseIcon hover:text-lightToastCloseIconHover rounded-lg focus:ring-2 focus:ring-lightToastCloseIconFocusRing p-1.5 hover:bg-lightToastCloseIconBackgroundHover inline-flex items-center justify-center h-8 w-8 dark:text-darkToastCloseIcon dark:hover:text-darkToastCloseIconHover dark:bg-darkToastCloseIconBackground dark:hover:bg-darkToastCloseIconBackgroundHover dark:focus:ring-darkToastCloseIconFocusRing" >
3546
<svg class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
3647
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
@@ -53,16 +64,28 @@ const props = defineProps<{
5364
variant: string;
5465
id: string;
5566
timeout?: number|'unlimited';
67+
buttons?: { value: any; label: string }[];
5668
}
5769
}>();
5870
function closeToast() {
71+
// resolve with undefined on close (X button)
72+
toastStore.resolveToast(props.toast.id);
73+
emit('close');
74+
}
75+
76+
function onButtonClick(value: any) {
77+
toastStore.resolveToast(props.toast.id, value);
5978
emit('close');
6079
}
6180
6281
onMounted(() => {
6382
if (props.toast.timeout === 'unlimited') return;
6483
else {
65-
setTimeout(() => {emit('close');}, (props.toast.timeout || 10) * 1e3 );
84+
setTimeout(() => {
85+
// resolve with undefined on auto-timeout
86+
toastStore.resolveToast(props.toast.id);
87+
emit('close');
88+
}, (props.toast.timeout || 10) * 1e3 );
6689
}
6790
});
6891

adminforth/spa/src/stores/toast.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,38 @@ export const useToastStore = defineStore('toast', () => {
1212
watch(route, () => {
1313
// on route change clear all toasts older then 5 seconds
1414
const now = +new Date();
15-
toasts.value = toasts.value.filter((t) => now - t.createdAt < 5000);
15+
toasts.value = toasts.value.filter((t) => t?.timeout === 'unlimited' || now - t.createdAt < 5000);
1616
});
1717

18-
const addToast = (toast: { message: string; variant: string }) => {
18+
const addToast = (toast: {
19+
message?: string;
20+
messageHtml?: string;
21+
variant: string;
22+
timeout?: number | 'unlimited';
23+
buttons?: { value: any; label: string }[];
24+
onResolve?: (value?: any) => void;
25+
}): string => {
1926
const toastId = uuid();
2027
toasts.value.push({
2128
...toast,
2229
id: toastId,
2330
createdAt: +new Date(),
2431
});
32+
return toastId;
2533
};
2634
const removeToast = (toast: { id: string }) => {
2735
toasts.value = toasts.value.filter((t) => t.id !== toast.id);
2836
};
29-
return { toasts, addToast, removeToast };
37+
38+
const resolveToast = (toastId: string, value?: any) => {
39+
const t = toasts.value.find((x) => x.id === toastId);
40+
try {
41+
t?.onResolve?.(value);
42+
} catch {
43+
// no-op
44+
}
45+
toasts.value = toasts.value.filter((x) => x.id !== toastId);
46+
};
47+
48+
return { toasts, addToast, removeToast, resolveToast };
3049
});

adminforth/types/FrontendAPI.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface FrontendAPIInterface {
5555
*
5656
* @param params - The parameters of the alert
5757
*/
58-
alert(params:AlertParams): void;
58+
alert(params:AlertParams): void | Promise<string> | string;
5959

6060

6161
list: {
@@ -179,7 +179,12 @@ export type AlertParams = {
179179
* Default is 10 seconds;
180180
*/
181181
timeout?: number | 'unlimited';
182-
182+
183+
/**
184+
* Optional buttons to display in the alert
185+
*/
186+
buttons?: {value: any, label: string}[];
187+
183188
}
184189

185190

0 commit comments

Comments
 (0)