mirror of
https://github.com/Dadido3/Scanyonero.git
synced 2025-06-06 01:10:00 +00:00
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"
This commit is contained in:
parent
1bd8be6abf
commit
b5ecf95a7b
7
main.go
7
main.go
@ -58,7 +58,12 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
server.Documents.Lock()
|
||||
|
||||
var entries []QueueEntry
|
||||
if len(server.Documents.Documents) > 0 {
|
||||
entries = append(entries, QueueEntry{ID: NewQueueEntryID(), QueueEntryData: QueueEntryDataSeparator{}})
|
||||
}
|
||||
for _, page := range docPages {
|
||||
entries = append(entries, QueueEntry{
|
||||
ID: NewQueueEntryID(),
|
||||
@ -66,9 +71,7 @@ func main() {
|
||||
QueueEntryData: QueueEntryDataPage{Page: &page},
|
||||
})
|
||||
}
|
||||
entries = append(entries, QueueEntry{ID: NewQueueEntryID(), QueueEntryData: QueueEntryDataSeparator{}})
|
||||
|
||||
server.Documents.Lock()
|
||||
server.Documents.Append(entries...)
|
||||
server.Documents.Unlock()
|
||||
}
|
||||
|
33
queue.go
33
queue.go
@ -171,15 +171,38 @@ func (d *Queue) Shift(offset int, ids ...QueueEntryID) {
|
||||
}
|
||||
}
|
||||
|
||||
// Split will add a separator behind every queue entry with the given IDs.
|
||||
//
|
||||
// The Queue must be locked when calling this.
|
||||
func (d *Queue) Split(ids ...QueueEntryID) {
|
||||
for _, id := range ids {
|
||||
if i := slices.IndexFunc(d.Documents, func(e QueueEntry) bool { return e.ID == id }); i >= 0 && i < len(d.Documents)-1 {
|
||||
doc := &d.Documents[i]
|
||||
|
||||
switch d.Documents[i+1].QueueEntryData.(type) {
|
||||
case QueueEntryDataPage:
|
||||
default:
|
||||
// If the next entry is not a page, we will not put a separator here.
|
||||
continue
|
||||
}
|
||||
|
||||
switch doc.QueueEntryData.(type) {
|
||||
case QueueEntryDataPage:
|
||||
d.InsertAt(i+1, QueueEntry{
|
||||
ID: NewQueueEntryID(),
|
||||
QueueEntryData: QueueEntryDataSeparator{},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// QueueEntryByID returns the QueueEntry with the given ID.
|
||||
//
|
||||
// The Queue must be locked when calling this.
|
||||
func (d *Queue) QueueEntryByID(id QueueEntryID) *QueueEntry {
|
||||
for i := range d.Documents {
|
||||
document := &d.Documents[i]
|
||||
if document.ID == id {
|
||||
return document
|
||||
}
|
||||
if i := slices.IndexFunc(d.Documents, func(e QueueEntry) bool { return e.ID == id }); i >= 0 {
|
||||
return &d.Documents[i]
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -51,7 +51,7 @@ func init() { ServerWebsocketPacketRegister(&ServerWebsocketPacketQueueShiftAt{}
|
||||
|
||||
// ServerWebsocketPacketQueueShift represents a shift operation on a document queue list.
|
||||
type ServerWebsocketPacketQueueShift struct {
|
||||
IDs []QueueEntryID `json:"ids"` // IDs of the documents.
|
||||
IDs []QueueEntryID `json:"ids"` // IDs of the entries.
|
||||
Offset int `json:"offset"` // Shift offset.
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@ func (s *ServerWebsocketPacketQueueShift) Type() string { return "QueueShift" }
|
||||
|
||||
func init() { ServerWebsocketPacketRegister(&ServerWebsocketPacketQueueShift{}) }
|
||||
|
||||
// ServerWebsocketPacketQueueUpdate represents an update operation of documents in a queue list.
|
||||
// The receiver should update any of the received documents in their local queue list.
|
||||
// ServerWebsocketPacketQueueUpdate represents an update operation of entries in a queue list.
|
||||
// The receiver should update any of the received entries in their local queue list.
|
||||
type ServerWebsocketPacketQueueUpdate struct {
|
||||
Documents []QueueEntry `json:"documents"`
|
||||
}
|
||||
@ -68,3 +68,13 @@ type ServerWebsocketPacketQueueUpdate struct {
|
||||
func (s *ServerWebsocketPacketQueueUpdate) Type() string { return "QueueUpdate" }
|
||||
|
||||
func init() { ServerWebsocketPacketRegister(&ServerWebsocketPacketQueueUpdate{}) }
|
||||
|
||||
// ServerWebsocketPacketQueueSplit represents a "add separator" operation in a queue list.
|
||||
// The split is added behind the given entry IDs.
|
||||
type ServerWebsocketPacketQueueSplit struct {
|
||||
IDs []QueueEntryID `json:"ids"` // IDs of the entries.
|
||||
}
|
||||
|
||||
func (s *ServerWebsocketPacketQueueSplit) Type() string { return "QueueSplit" }
|
||||
|
||||
func init() { ServerWebsocketPacketRegister(&ServerWebsocketPacketQueueSplit{}) }
|
||||
|
@ -92,6 +92,10 @@ func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||
s.Documents.Lock()
|
||||
s.Documents.Shift(packet.Offset, packet.IDs...)
|
||||
s.Documents.Unlock()
|
||||
case *ServerWebsocketPacketQueueSplit:
|
||||
s.Documents.Lock()
|
||||
s.Documents.Split(packet.IDs...)
|
||||
s.Documents.Unlock()
|
||||
default:
|
||||
log.Printf("Websocket client %q sent unsupported packet type %T.", conn.LocalAddr(), prototype)
|
||||
return
|
||||
|
@ -96,6 +96,20 @@ export class API extends EventTarget {
|
||||
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
|
||||
|
@ -14,20 +14,46 @@ export class DocumentQueueEntryPage extends LitElement {
|
||||
/** @type {API} */
|
||||
this.api;
|
||||
/** @type {import('model').APIQueueEntry} */
|
||||
this.document;
|
||||
this.queueEntry;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 128px;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
// @ts-ignore
|
||||
render() {
|
||||
return html`
|
||||
<img id="image" src=${`/api/queue-entry-page/${this.document.id}/preview`}></img>
|
||||
<span>This is a document</span>
|
||||
<img id="image" src=${`/api/queue-entry-page/${this.queueEntry.id}/preview`}></img>
|
||||
<div style="flex-grow: 1;">
|
||||
<span>This is a document</span>
|
||||
</div>
|
||||
<div id="buttons">
|
||||
<button @click=${e => this.api.queueShift(-1, this.queueEntry.id)}>▲</button>
|
||||
<button @click=${e => this.api.queueDelete(this.queueEntry.id)}>Delete</button>
|
||||
<button @click=${e => this.api.queueSplit(this.queueEntry.id)}>Split</button>
|
||||
<button @click=${e => this.api.queueShift(1, this.queueEntry.id)}>▼</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -14,20 +14,38 @@ export class DocumentQueueEntrySeparator extends LitElement {
|
||||
/** @type {API} */
|
||||
this.api;
|
||||
/** @type {import('model').APIQueueEntry} */
|
||||
this.document;
|
||||
this.queueEntry;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: 100%;
|
||||
background: black;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
// @ts-ignore
|
||||
render() {
|
||||
return html`
|
||||
|
||||
<div style="flex-grow: 1; align-self: center;">
|
||||
<hr>
|
||||
</div>
|
||||
<div id="buttons">
|
||||
<button @click=${e => this.api.queueDelete(this.queueEntry.id)}>Delete</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,9 @@ export class DocumentQueueEntry extends LitElement {
|
||||
let embeddedElement;
|
||||
switch (this.queueEntry.type) {
|
||||
case "Page":
|
||||
embeddedElement = html`<document-queue-entry-page .document=${this.queueEntry} .api=${this.api}></document-queue-entry-page>`; break;
|
||||
embeddedElement = html`<document-queue-entry-page .queueEntry=${this.queueEntry} .api=${this.api}></document-queue-entry-page>`; break;
|
||||
case "Separator":
|
||||
embeddedElement = html`<document-queue-entry-separator .document=${this.queueEntry} .api=${this.api}></document-queue-entry-separator>`; break;
|
||||
embeddedElement = html`<document-queue-entry-separator .queueEntry=${this.queueEntry} .api=${this.api}></document-queue-entry-separator>`; break;
|
||||
default:
|
||||
embeddedElement = html`<span>Unsupported entry type!</span>`
|
||||
}
|
||||
@ -71,7 +71,6 @@ export class DocumentQueueEntry extends LitElement {
|
||||
return html`
|
||||
<div id="left-bar">
|
||||
<input id="checkbox-selected" type="checkbox" .checked=${this.selected} @change=${this.onCheckboxChange}></input>
|
||||
<button id="button-swap" @click=${e => this.api.queueShift(1, this.queueEntry.id)}>⇵</button>
|
||||
</div>
|
||||
|
||||
${embeddedElement}
|
||||
|
4
static/js/model.d.ts
vendored
4
static/js/model.d.ts
vendored
@ -33,6 +33,10 @@ export type APIPacketQueueShift = {
|
||||
offset: number;
|
||||
}
|
||||
|
||||
export type APIPacketQueueSplit = {
|
||||
ids: number[];
|
||||
}
|
||||
|
||||
export type APIEvents = {
|
||||
queuedeleteat: CustomEvent<APIPacketQueueDeleteAt>;
|
||||
queueinsertat: CustomEvent<APIPacketQueueInsertAt>;
|
||||
|
Loading…
Reference in New Issue
Block a user