151 lines
4.7 KiB
TypeScript
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();
|
|
});
|
|
}
|