Scanyonero/static/js/api.js
David Vogel 853a1bb58d Rework into FTP scanning server
- Rename to Scanyonero
- Add FTP server that ingests TIFF, PNG, JPEG or PDF files
- Add web interface to check and modify ingested files
- Rework how ocrmypdf is invoked

Basics are working, but the program is not in a usable state.
2025-05-14 12:08:38 +02:00

128 lines
3.3 KiB
JavaScript

export class API extends EventTarget {
constructor() {
super();
this.#socketOpen();
}
/** @type {WebSocket} */
#socket;
/**
* Opens a new websocket connection, and adds all necessary listeners.
*/
#socketOpen() {
this.#socket = new WebSocket("ws://" + location.host + "/ws");
this.#socket.onopen = event => {
console.log(`Websocket connection opened.`)
}
this.#socket.onmessage = event => {
/** @type {{type: string, payload: any}} */
const data = JSON.parse(event.data);
switch (data.type) {
case "QueueDeleteAt": {
/** @type {CustomEventInit<import("./model").APIPacketQueueDeleteAt>} */
const eventData = { detail: data.payload };
this.dispatchEvent(new CustomEvent("queuedeleteat", eventData));
break;
}
case "QueueInsertAt": {
/** @type {CustomEventInit<import("./model").APIPacketQueueInsertAt>} */
const eventData = { detail: data.payload };
this.dispatchEvent(new CustomEvent("queueinsertat", eventData));
break;
}
case "QueueReplace": {
/** @type {CustomEventInit<import("./model").APIPacketQueueReplace>} */
const eventData = { detail: data.payload };
this.dispatchEvent(new CustomEvent("queuereplace", eventData));
break;
}
case "QueueShiftAt": {
/** @type {CustomEventInit<import("./model").APIPacketQueueShift>} */
const eventData = { detail: data.payload };
this.dispatchEvent(new CustomEvent("queueshiftat", eventData));
break;
}
default:
console.error(`Unknown websocket data type "${data.type}"`);
break;
}
}
this.#socket.onclose = event => {
console.log(`Socket is closed. Reconnect will be attempted in 1 second. Code: ${event.code} Reason: ${event.reason} WasClean: ${event.wasClean}.`);
setTimeout(() => {
this.#socketOpen();
}, 1000);
};
this.#socket.onerror = event => {
console.error(`Socket encountered error: ${event}. Closing socket.`);
this.#socket.close();
};
}
/**
* Sends a document queue delete request to the server.
* @param {...number} ids Document ids.
*/
queueDelete(...ids) {
if (this.#socket.readyState !== WebSocket.OPEN) {
return
}
/** @type {{type: string, payload: import("./model").APIPacketQueueDelete}} */
const message = { type: "QueueDelete", payload: { ids: ids } };
this.#socket.send(JSON.stringify(message));
}
/**
* Sends a document queue shift request to the server.
* @param {number} offset
* @param {...number} ids Document ids.
*/
queueShift(offset, ...ids) {
if (this.#socket.readyState !== WebSocket.OPEN) {
return
}
/** @type {{type: string, payload: import("./model").APIPacketQueueShift}} */
const message = { type: "QueueShift", payload: { offset: offset, ids: ids } };
this.#socket.send(JSON.stringify(message));
}
/**
*
* @param {"GET"|"POST"|"DELETE"|"UPDATE"} method
* @param {string} url
*/
#ajaxRequest(method, url) {
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(this.response);
} else {
reject({
status: this.status,
statusText: this.statusText,
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: this.statusText,
});
};
xhr.send();
});
}
}