death-notifier/src/main/js/API.ts

151 lines
4.7 KiB
TypeScript

// @ts-ignore
const {$} = window.fwdekker;
import {clearMessages, showError} from "./Message";
/**
* The CSRF token to be used for the next API request.
*/
export let csrfToken: string | null = null;
/**
* A shared element to place global messages in.
*/
export const sharedMessageElement: HTMLFormElement = $("#sharedValidationInfo");
/**
* A response sent by the server after a request has been sent to it.
*/
export type ServerResponse = {
/**
* The message or payload, depending on the type of request that is being responded to.
*/
payload: any;
/**
* `true` if and only if the request was completed successfully.
*/
satisfied: boolean;
/**
* The CSRF token to use for the next request.
*/
token: string;
};
/**
* Does nothing.
*
* Exists because auto-format adds that annoying line in an empty function.
*/
const emptyFunction = () => {
};
/**
* Sends a GET request to the API.
*
* @param params the GET parameters to send
* @param form the form to display validation info in
* @param onSatisfied the callback to execute if the request returns successfully
* @param onUnsatisfied the callback to execute if the request returns unsuccessfully
* @param onError the callback to execute if there was an HTTP error
* @param onAlways the callback to execute regardless of output
*/
export function getApi(
params: Record<string, string>,
form: HTMLFormElement,
onSatisfied: (response: ServerResponse) => void = emptyFunction,
onUnsatisfied: (response: ServerResponse) => void = emptyFunction,
onError: (error: any) => void = emptyFunction,
onAlways: () => void = emptyFunction
): void {
interactWithApi(
"api.php?" + new URLSearchParams(params), undefined, form,
onSatisfied, onUnsatisfied, onError, onAlways
);
}
/**
* Sends a POST request to the API.
*
* @param params the POST parameters to send
* @param form the form to display validation info in
* @param onSatisfied the callback to execute if the request returns successfully
* @param onUnsatisfied the callback to execute if the request returns unsuccessfully
* @param onError the callback to execute if there was an HTTP error
* @param onAlways the callback to execute regardless of output
*/
export function postApi(
params: object,
form: HTMLFormElement,
onSatisfied: (response: ServerResponse) => void = emptyFunction,
onUnsatisfied: (response: ServerResponse) => void = emptyFunction,
onError: (error: any) => void = emptyFunction,
onAlways: () => void = emptyFunction
): void {
interactWithApi("api.php",
{
method: "post",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(params)
},
form,
onSatisfied, onUnsatisfied, onError, onAlways
);
}
/**
* Sends a request to the API.
*
* @param url the URL to send the request to
* @param options the options to send with the request
* @param form the form to display validation info in
* @param onSatisfied the callback to execute if the request returns successfully
* @param onUnsatisfied the callback to execute if the request returns unsuccessfully
* @param onError the callback to execute if there was an HTTP error
* @param onAlways the callback to execute regardless of output
*/
function interactWithApi(
url: string,
options: object | undefined,
form: HTMLFormElement,
onSatisfied: (response: ServerResponse) => void = emptyFunction,
onUnsatisfied: (response: ServerResponse) => void = emptyFunction,
onError: (error: any) => void = emptyFunction,
onAlways: () => void = emptyFunction
): void {
clearMessages(form);
const topErrorElement = $(".formValidationInfo", form) ?? sharedMessageElement;
fetch(url, options)
.then(it => it.json())
.then(it => {
csrfToken = it.token;
if (!it.satisfied) {
if (it.payload.message !== null) {
if (it.payload.target === null) {
showError(topErrorElement, it.payload.message);
} else {
const target = form?.querySelector(`input[name=${it.payload.target}]`)?.parentElement;
showError(target ?? topErrorElement, it.payload.message);
target?.focus();
}
}
onUnsatisfied(it);
} else {
onSatisfied(it);
}
onAlways();
})
.catch((error) => {
showError(topErrorElement, "Unexpected error. Please try again later.");
onError(error);
onAlways();
});
}