mirror of
https://github.com/Dadido3/Scanyonero.git
synced 2025-06-06 17:30:00 +00:00
170 lines
5.1 KiB
JavaScript
170 lines
5.1 KiB
JavaScript
import { API } from '../api.js';
|
|
import { DocumentQueueEntry } from './document-queue-entry.js'
|
|
|
|
/** @typedef {{selectedIDs: number[], allIDs: number[]}} DocumentQueueEventChangeSelectionDetails */
|
|
/** @typedef {CustomEvent<DocumentQueueEventChangeSelectionDetails>} DocumentQueueEventChangeSelection */
|
|
|
|
// TODO: Use LitElement, and use repeat directive, which also keeps the DOM state when shuffling elements around
|
|
export class DocumentQueue extends HTMLElement {
|
|
/** @type {API|undefined} */
|
|
#api;
|
|
|
|
/** @param {API} api */
|
|
set api(api) {
|
|
this.#api = api;
|
|
|
|
this.#api.addEventListener("queuedeleteat", /** @param {import("model").APIEvents["queuedeleteat"]} event */(event) => {
|
|
this.queueDeleteAt(event.detail.indexA, event.detail.indexB);
|
|
});
|
|
this.#api.addEventListener("queueinsertat", /** @param {import("model").APIEvents["queueinsertat"]} event */(event) => {
|
|
this.queueInsertAt(event.detail.index, event.detail.documents);
|
|
});
|
|
this.#api.addEventListener("queueshiftat", /** @param {import("model").APIEvents["queueshiftat"]} event */(event) => {
|
|
this.queueShiftAt(event.detail.index, event.detail.offset);
|
|
});
|
|
this.#api.addEventListener("queuereplace", /** @param {import("model").APIEvents["queuereplace"]} event */(event) => {
|
|
this.queueReplace(event.detail.documents);
|
|
});
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.style.display = "flex";
|
|
this.style.gap = "8px";
|
|
this.style.flexDirection = "column";
|
|
this.style.padding = "8px";
|
|
}
|
|
|
|
selectionInfo() {
|
|
const children = Array.from(this.children);
|
|
|
|
const result = {};
|
|
result.selectedIDs = children.filter(/** @param {DocumentQueueEntry} value */ value => { return value.selected; }).map(/** @param {DocumentQueueEntry} value */(value) => { return value.queueEntry.id; });
|
|
result.allIDs = children.map(/** @param {DocumentQueueEntry} value */ value => { return value.queueEntry.id; });
|
|
|
|
return result;
|
|
}
|
|
|
|
updateSelection() {
|
|
/** @type {CustomEventInit<DocumentQueueEventChangeSelectionDetails>} */
|
|
const eventData = { detail: this.selectionInfo() };
|
|
this.dispatchEvent(new CustomEvent("changeselection", eventData));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {boolean} state
|
|
*/
|
|
selectAll(state) {
|
|
const children = Array.from(this.children);
|
|
|
|
children.forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.selected = state;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Deletes a range of documents.
|
|
* @param {number} indexA // Start index.
|
|
* @param {number} indexB // End index. (Not included in the range).
|
|
*/
|
|
queueDeleteAt(indexA, indexB) {
|
|
// Store positions.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.prepareFLIP();
|
|
});
|
|
|
|
if (this.hasChildNodes()) {
|
|
const children = this.children;
|
|
for (let i = indexA; i < indexB; i++) {
|
|
this.removeChild(children[i]);
|
|
}
|
|
}
|
|
|
|
// Start FLIP animation.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.doFLIP();
|
|
});
|
|
|
|
this.updateSelection();
|
|
}
|
|
|
|
/**
|
|
* Inserts a range of documents at the given index.
|
|
* @param {number} index
|
|
* @param {import('model').APIQueueEntry[]} documents
|
|
*/
|
|
queueInsertAt(index, documents) {
|
|
// Store positions.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.prepareFLIP();
|
|
});
|
|
|
|
documents.forEach(document => {
|
|
if (!this.hasChildNodes() || this.children.length === index) {
|
|
const newChild = this.appendChild(new DocumentQueueEntry());
|
|
newChild.api = this.#api;
|
|
newChild.queueEntry = document;
|
|
newChild.addEventListener("changeselection", e => this.updateSelection());
|
|
} else {
|
|
const newChild = this.insertBefore(new DocumentQueueEntry(), this.childNodes[index]);
|
|
newChild.api = this.#api;
|
|
newChild.queueEntry = document;
|
|
newChild.addEventListener("changeselection", e => this.updateSelection());
|
|
}
|
|
index++;
|
|
});
|
|
|
|
// Start FLIP animation.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.doFLIP();
|
|
});
|
|
|
|
this.updateSelection();
|
|
}
|
|
|
|
/**
|
|
* Replaces all documents currently in the list/queue.
|
|
* @param {import('model').APIQueueEntry[]} documents
|
|
*/
|
|
queueReplace(documents) {
|
|
this.innerHTML = "";
|
|
|
|
documents.forEach(document => {
|
|
const newChild = this.appendChild(new DocumentQueueEntry());
|
|
newChild.api = this.#api;
|
|
newChild.queueEntry = document;
|
|
newChild.addEventListener("changeselection", e => this.updateSelection());
|
|
});
|
|
|
|
this.updateSelection();
|
|
}
|
|
|
|
/**
|
|
* Shifts a single document entry by the given offset.
|
|
* @param {number} index
|
|
* @param {number} offset
|
|
*/
|
|
queueShiftAt(index, offset) {
|
|
// Store positions.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.prepareFLIP();
|
|
});
|
|
|
|
const child = this.children[index];
|
|
child.remove();
|
|
const newIndex = index + offset;
|
|
if (!this.hasChildNodes() || this.children.length === newIndex) {
|
|
this.appendChild(child);
|
|
} else {
|
|
this.insertBefore(child, this.children[newIndex]);
|
|
}
|
|
|
|
// Start FLIP animation.
|
|
Array.from(this.children).forEach(/** @param {DocumentQueueEntry} child */ child => {
|
|
child.doFLIP();
|
|
});
|
|
}
|
|
}
|
|
|
|
customElements.define("document-queue", DocumentQueue);
|