Scanyonero/static/js/api.js
David Vogel b5ecf95a7b Add split function
- Add ServerWebsocketPacketQueueSplit
- Add Split method to Queue
- Correct automatic separator insertion for newly ingested documents
- Rework UI so that entries have their own set of buttons
- Refactor occurrences of "document" to "queueEntry"
2025-05-19 12:03:40 +02:00

142 lines
3.7 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));
}
/**
* Sends a document queue split request to the server.
* @param {...number} ids Document ids.
*/
queueSplit(...ids) {
if (this.#socket.readyState !== WebSocket.OPEN) {
return
}
/** @type {{type: string, payload: import("./model").APIPacketQueueSplit}} */
const message = { type: "QueueSplit", payload: { 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();
});
}
}