mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-22 12:03:25 -04:00
120 lines
4.0 KiB
TypeScript
120 lines
4.0 KiB
TypeScript
import { useNuxtApp } from 'nuxt/app';
|
|
import type { FetchOptions } from 'ofetch';
|
|
import { getCurrentInstance, h, render } from 'vue';
|
|
|
|
import DialogueBox from '../components/DialogueBox.vue';
|
|
import type { DialogueMessage } from '../components/DialogueBox.vue';
|
|
import type { Color, ModalSize } from '../src/bootstrap.ts';
|
|
|
|
export default (to: string = 'body') => {
|
|
const { $translator: translator } = useNuxtApp();
|
|
|
|
const self = getCurrentInstance()!;
|
|
|
|
const show = (
|
|
choice: boolean,
|
|
message: string | DialogueMessage,
|
|
colour: Color,
|
|
value: string | string[] | undefined,
|
|
size: ModalSize,
|
|
): Promise<string | string[] | undefined> => {
|
|
return new Promise((resolve, reject) => {
|
|
if (typeof message === 'string') {
|
|
message = { message };
|
|
}
|
|
|
|
const vnode = h(DialogueBox, {
|
|
choice,
|
|
icon: message.icon || (choice ? 'map-marker-question' : undefined),
|
|
header: message.header,
|
|
message: message.message || (choice ? translator.translate('confirm.header') : undefined),
|
|
margin: message.margin ?? true,
|
|
colour,
|
|
value,
|
|
size: message.size ?? size,
|
|
onConfirm: (value) => {
|
|
hide();
|
|
resolve(value);
|
|
},
|
|
onCancel: () => {
|
|
hide();
|
|
reject();
|
|
},
|
|
});
|
|
vnode.key = Math.random();
|
|
vnode.appContext = self.appContext;
|
|
render(vnode, document.querySelector(to)!);
|
|
});
|
|
};
|
|
|
|
const hide = () => {
|
|
render(null, document.querySelector(to)!);
|
|
};
|
|
|
|
const alert = (
|
|
message: string | DialogueMessage,
|
|
color: Color = 'primary',
|
|
): Promise<void> => {
|
|
return show(false, message, color, undefined, undefined).then(() => undefined);
|
|
};
|
|
|
|
const confirm = (
|
|
message: string | DialogueMessage = '',
|
|
colour: Color = 'primary',
|
|
): Promise<void> => {
|
|
return show(true, message, colour, undefined, undefined).then(() => undefined);
|
|
};
|
|
|
|
const editor = (
|
|
value: string | string[],
|
|
message: string | DialogueMessage = '',
|
|
color: Color = 'primary',
|
|
): Promise<string | string[] | undefined> => {
|
|
return show(false, message, color, value, 'lg');
|
|
};
|
|
|
|
const alertRaw = (
|
|
message: string | DialogueMessage,
|
|
color: Color = 'primary',
|
|
): Promise<void> => {
|
|
return show(false, `<pre class="text-start"><code>${message}</code></pre>`, color, undefined, 'lg').then(() => undefined);
|
|
};
|
|
|
|
const postWithAlertOnError = async <T = unknown>(
|
|
url: string,
|
|
data: BodyInit | Record<string, unknown> | null | undefined = undefined,
|
|
options: Omit<FetchOptions, 'method' | 'data' | 'timeout'> = {},
|
|
timeout = 30000,
|
|
): Promise<T> => {
|
|
return $fetch<T>(url, {
|
|
method: 'POST',
|
|
body: data,
|
|
timeout,
|
|
...options,
|
|
})
|
|
.catch(async (error) => {
|
|
let errorMessage = translator.translate('error.generic');
|
|
if (typeof error.data?.message === 'string') {
|
|
errorMessage = error.data.message;
|
|
}
|
|
if (typeof error.data?.error === 'string') {
|
|
errorMessage = translator.translate(error.data?.error);
|
|
// in case no translatable key was provided
|
|
if (errorMessage === undefined) {
|
|
errorMessage = error.data?.error;
|
|
}
|
|
}
|
|
await alert(errorMessage, 'danger');
|
|
throw new Error(`POST to ${url} failed: ${error.data?.error || 'unknown error'}`);
|
|
});
|
|
};
|
|
|
|
return {
|
|
alert,
|
|
confirm,
|
|
editor,
|
|
alertRaw,
|
|
postWithAlertOnError,
|
|
};
|
|
};
|