mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2026-02-04 02:25:30 +00:00
+Image ordering
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/tools/router"
|
"github.com/pocketbase/pocketbase/tools/router"
|
||||||
|
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -317,6 +318,8 @@ func (p *AlmanachContentsEditPage) POSTSave(engine *templating.Engine, app core.
|
|||||||
|
|
||||||
uploadedScans, _ := e.FindUploadedFiles(dbmodels.SCAN_FIELD)
|
uploadedScans, _ := e.FindUploadedFiles(dbmodels.SCAN_FIELD)
|
||||||
deleteScans := valuesForKey(e.Request.PostForm, "scans_delete")
|
deleteScans := valuesForKey(e.Request.PostForm, "scans_delete")
|
||||||
|
scansOrder := valuesForKey(e.Request.PostForm, "scans_order")
|
||||||
|
pendingScanIDs := valuesForKey(e.Request.PostForm, "scans_pending_ids")
|
||||||
targetContentID := contentID
|
targetContentID := contentID
|
||||||
if targetContentID == "" && len(contentInputs) == 1 {
|
if targetContentID == "" && len(contentInputs) == 1 {
|
||||||
for id := range contentInputs {
|
for id := range contentInputs {
|
||||||
@@ -403,7 +406,7 @@ func (p *AlmanachContentsEditPage) POSTSave(engine *templating.Engine, app core.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if targetContentID != "" && (len(uploadedScans) > 0 || len(deleteScans) > 0) {
|
if targetContentID != "" && (len(uploadedScans) > 0 || len(deleteScans) > 0 || len(scansOrder) > 0) {
|
||||||
record, err := tx.FindRecordById(dbmodels.CONTENTS_TABLE, targetContentID)
|
record, err := tx.FindRecordById(dbmodels.CONTENTS_TABLE, targetContentID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -412,16 +415,74 @@ func (p *AlmanachContentsEditPage) POSTSave(engine *templating.Engine, app core.
|
|||||||
if content.Entry() != entry.Id {
|
if content.Entry() != entry.Id {
|
||||||
return fmt.Errorf("Beitrag gehört zu einem anderen Band.")
|
return fmt.Errorf("Beitrag gehört zu einem anderen Band.")
|
||||||
}
|
}
|
||||||
if len(uploadedScans) > 0 {
|
deleteSet := map[string]struct{}{}
|
||||||
content.Set(dbmodels.SCAN_FIELD+"+", uploadedScans)
|
for _, scan := range deleteScans {
|
||||||
|
scan = strings.TrimSpace(scan)
|
||||||
|
if scan == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deleteSet[scan] = struct{}{}
|
||||||
}
|
}
|
||||||
if len(deleteScans) > 0 {
|
if len(scansOrder) > 0 || len(pendingScanIDs) > 0 {
|
||||||
for _, scan := range deleteScans {
|
pendingMap := map[string]*filesystem.File{}
|
||||||
scan = strings.TrimSpace(scan)
|
for idx, id := range pendingScanIDs {
|
||||||
if scan == "" {
|
if idx >= len(uploadedScans) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
id = strings.TrimSpace(id)
|
||||||
|
if id == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
content.Set(dbmodels.SCAN_FIELD+"-", scan)
|
pendingMap[id] = uploadedScans[idx]
|
||||||
|
}
|
||||||
|
ordered := make([]any, 0, len(scansOrder)+len(uploadedScans))
|
||||||
|
seenExisting := map[string]struct{}{}
|
||||||
|
for _, token := range scansOrder {
|
||||||
|
token = strings.TrimSpace(token)
|
||||||
|
if token == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(token, "pending:") {
|
||||||
|
id := strings.TrimPrefix(token, "pending:")
|
||||||
|
if file, ok := pendingMap[id]; ok {
|
||||||
|
ordered = append(ordered, file)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(token, "existing:") {
|
||||||
|
name := strings.TrimPrefix(token, "existing:")
|
||||||
|
if name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, deleted := deleteSet[name]; deleted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ordered = append(ordered, name)
|
||||||
|
seenExisting[name] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, name := range content.Scans() {
|
||||||
|
if _, deleted := deleteSet[name]; deleted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, seen := seenExisting[name]; seen {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ordered = append(ordered, name)
|
||||||
|
}
|
||||||
|
content.Set(dbmodels.SCAN_FIELD, ordered)
|
||||||
|
} else {
|
||||||
|
if len(uploadedScans) > 0 {
|
||||||
|
content.Set(dbmodels.SCAN_FIELD+"+", uploadedScans)
|
||||||
|
}
|
||||||
|
if len(deleteScans) > 0 {
|
||||||
|
for _, scan := range deleteScans {
|
||||||
|
scan = strings.TrimSpace(scan)
|
||||||
|
if scan == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
content.Set(dbmodels.SCAN_FIELD+"-", scan)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -373,9 +373,20 @@
|
|||||||
}
|
}
|
||||||
const imagesComponent = document.querySelector("content-images");
|
const imagesComponent = document.querySelector("content-images");
|
||||||
if (imagesComponent && typeof imagesComponent.getPendingFiles === "function") {
|
if (imagesComponent && typeof imagesComponent.getPendingFiles === "function") {
|
||||||
imagesComponent.getPendingFiles().forEach((file) => {
|
const pendingFiles = imagesComponent.getPendingFiles();
|
||||||
|
const pendingIds = typeof imagesComponent.getPendingIds === "function" ? imagesComponent.getPendingIds() : [];
|
||||||
|
const scanOrder = typeof imagesComponent.getScanOrder === "function" ? imagesComponent.getScanOrder() : [];
|
||||||
|
pendingFiles.forEach((file, index) => {
|
||||||
payload.append("scans", file);
|
payload.append("scans", file);
|
||||||
|
if (pendingIds[index]) {
|
||||||
|
payload.append("scans_pending_ids[]", pendingIds[index]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
if (Array.isArray(scanOrder) && scanOrder.length > 0) {
|
||||||
|
scanOrder.forEach((token) => {
|
||||||
|
payload.append("scans_order[]", token);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (typeof imagesComponent.getPendingDeletes === "function") {
|
if (typeof imagesComponent.getPendingDeletes === "function") {
|
||||||
imagesComponent.getPendingDeletes().forEach((fileName) => {
|
imagesComponent.getPendingDeletes().forEach((fileName) => {
|
||||||
payload.append("scans_delete[]", fileName);
|
payload.append("scans_delete[]", fileName);
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ export class ContentImages extends HTMLElement {
|
|||||||
this._pendingFiles = [];
|
this._pendingFiles = [];
|
||||||
this._pendingUrls = [];
|
this._pendingUrls = [];
|
||||||
this._pendingDeletes = new Set();
|
this._pendingDeletes = new Set();
|
||||||
|
this._pendingIds = [];
|
||||||
|
this._pendingIdCounter = 0;
|
||||||
|
this._scanOrder = [];
|
||||||
|
|
||||||
this._wireUpload();
|
this._wireUpload();
|
||||||
|
|
||||||
@@ -98,9 +101,31 @@ export class ContentImages extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setPendingFiles(files) {
|
_setPendingFiles(files) {
|
||||||
this._clearPendingPreviews();
|
const incoming = Array.isArray(files) ? files : [];
|
||||||
this._pendingFiles = Array.isArray(files) ? files : [];
|
if (incoming.length === 0) {
|
||||||
this._pendingUrls = this._pendingFiles.map((file) => URL.createObjectURL(file));
|
return;
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this._pendingFiles)) {
|
||||||
|
this._pendingFiles = [];
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this._pendingUrls)) {
|
||||||
|
this._pendingUrls = [];
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this._pendingIds)) {
|
||||||
|
this._pendingIds = [];
|
||||||
|
}
|
||||||
|
const newIds = [];
|
||||||
|
incoming.forEach((file) => {
|
||||||
|
this._pendingFiles.push(file);
|
||||||
|
this._pendingUrls.push(URL.createObjectURL(file));
|
||||||
|
const id = `p${Date.now()}_${this._pendingIdCounter++}`;
|
||||||
|
this._pendingIds.push(id);
|
||||||
|
newIds.push(id);
|
||||||
|
});
|
||||||
|
if (!Array.isArray(this._scanOrder)) {
|
||||||
|
this._scanOrder = [];
|
||||||
|
}
|
||||||
|
this._scanOrder = this._scanOrder.concat(newIds.map((id) => `pending:${id}`));
|
||||||
this._render(this._currentImages || []);
|
this._render(this._currentImages || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,10 +148,91 @@ export class ContentImages extends HTMLElement {
|
|||||||
const csrfToken = this.getAttribute("data-csrf-token") || "";
|
const csrfToken = this.getAttribute("data-csrf-token") || "";
|
||||||
const canDelete = deleteEndpoint && contentId && csrfToken;
|
const canDelete = deleteEndpoint && contentId && csrfToken;
|
||||||
|
|
||||||
images.forEach((image, index) => {
|
const imagesByName = new Map();
|
||||||
|
images.forEach((image) => {
|
||||||
|
if (image && image.name) {
|
||||||
|
imagesByName.set(image.name, image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!Array.isArray(this._scanOrder) || this._scanOrder.length === 0) {
|
||||||
|
this._scanOrder = images.map((image) => `existing:${image.name}`);
|
||||||
|
this._scanOrder = this._scanOrder.concat(this._pendingIds.map((id) => `pending:${id}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingById = new Map();
|
||||||
|
this._pendingIds.forEach((id, index) => {
|
||||||
|
pendingById.set(id, { url: this._pendingUrls[index] });
|
||||||
|
});
|
||||||
|
|
||||||
|
const order = [];
|
||||||
|
this._scanOrder.forEach((token) => {
|
||||||
|
if (token.startsWith("existing:")) {
|
||||||
|
const name = token.slice("existing:".length);
|
||||||
|
if (imagesByName.has(name)) {
|
||||||
|
order.push({ type: "existing", name, image: imagesByName.get(name) });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (token.startsWith("pending:")) {
|
||||||
|
const id = token.slice("pending:".length);
|
||||||
|
if (pendingById.has(id)) {
|
||||||
|
order.push({ type: "pending", id, url: pendingById.get(id).url });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
order.forEach((item, index) => {
|
||||||
|
if (item.type === "pending") {
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
wrapper.className = "group relative";
|
||||||
|
wrapper.dataset.role = "content-images-pending";
|
||||||
|
wrapper.dataset.scanKey = `pending:${item.id}`;
|
||||||
|
wrapper.draggable = true;
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.type = "button";
|
||||||
|
button.className = [
|
||||||
|
"rounded",
|
||||||
|
"border",
|
||||||
|
"border-dashed",
|
||||||
|
"border-slate-300",
|
||||||
|
"bg-stone-50",
|
||||||
|
"p-1",
|
||||||
|
"shadow-sm",
|
||||||
|
].join(" ");
|
||||||
|
button.dataset.imageUrl = item.url;
|
||||||
|
button.dataset.imageIndex = `pending-${index}`;
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = item.url;
|
||||||
|
img.alt = "Digitalisat (neu)";
|
||||||
|
img.loading = "lazy";
|
||||||
|
img.className = "h-28 w-28 object-cover opacity-70";
|
||||||
|
button.appendChild(img);
|
||||||
|
const badge = document.createElement("span");
|
||||||
|
badge.className = "absolute left-1 top-1 rounded bg-amber-200 px-1.5 py-0.5 text-[10px] font-semibold text-amber-900";
|
||||||
|
badge.textContent = "Neu";
|
||||||
|
wrapper.appendChild(button);
|
||||||
|
wrapper.appendChild(badge);
|
||||||
|
const removeButton = document.createElement("button");
|
||||||
|
removeButton.type = "button";
|
||||||
|
removeButton.className = "absolute right-1 top-1 hidden rounded-full border border-red-200 bg-white/90 px-2 py-1 text-xs font-semibold text-red-700 shadow-sm transition group-hover:flex hover:text-red-900 hover:border-red-300";
|
||||||
|
removeButton.innerHTML = '<i class="ri-close-line mr-1"></i>Entfernen';
|
||||||
|
removeButton.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this._removePendingFileById(item.id);
|
||||||
|
});
|
||||||
|
wrapper.appendChild(removeButton);
|
||||||
|
list.appendChild(wrapper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = item.image;
|
||||||
const wrapper = document.createElement("div");
|
const wrapper = document.createElement("div");
|
||||||
wrapper.className = "group relative";
|
wrapper.className = "group relative";
|
||||||
wrapper.dataset.role = "content-images-item";
|
wrapper.dataset.role = "content-images-item";
|
||||||
|
wrapper.dataset.scanKey = `existing:${item.name}`;
|
||||||
|
wrapper.draggable = true;
|
||||||
const isPendingDelete = this._pendingDeletes.has(image.name);
|
const isPendingDelete = this._pendingDeletes.has(image.name);
|
||||||
if (isPendingDelete) {
|
if (isPendingDelete) {
|
||||||
wrapper.classList.add("content-image-pending");
|
wrapper.classList.add("content-image-pending");
|
||||||
@@ -203,47 +309,6 @@ export class ContentImages extends HTMLElement {
|
|||||||
list.appendChild(wrapper);
|
list.appendChild(wrapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._pendingUrls.forEach((url, index) => {
|
|
||||||
const wrapper = document.createElement("div");
|
|
||||||
wrapper.className = "group relative";
|
|
||||||
wrapper.dataset.role = "content-images-pending";
|
|
||||||
const button = document.createElement("button");
|
|
||||||
button.type = "button";
|
|
||||||
button.className = [
|
|
||||||
"rounded",
|
|
||||||
"border",
|
|
||||||
"border-dashed",
|
|
||||||
"border-slate-300",
|
|
||||||
"bg-stone-50",
|
|
||||||
"p-1",
|
|
||||||
"shadow-sm",
|
|
||||||
].join(" ");
|
|
||||||
button.dataset.imageUrl = url;
|
|
||||||
button.dataset.imageIndex = `pending-${index}`;
|
|
||||||
const img = document.createElement("img");
|
|
||||||
img.src = url;
|
|
||||||
img.alt = "Digitalisat (neu)";
|
|
||||||
img.loading = "lazy";
|
|
||||||
img.className = "h-28 w-28 object-cover opacity-70";
|
|
||||||
button.appendChild(img);
|
|
||||||
const badge = document.createElement("span");
|
|
||||||
badge.className = "absolute left-1 top-1 rounded bg-amber-200 px-1.5 py-0.5 text-[10px] font-semibold text-amber-900";
|
|
||||||
badge.textContent = "Neu";
|
|
||||||
wrapper.appendChild(button);
|
|
||||||
wrapper.appendChild(badge);
|
|
||||||
const removeButton = document.createElement("button");
|
|
||||||
removeButton.type = "button";
|
|
||||||
removeButton.className = "absolute right-1 top-1 hidden rounded-full border border-red-200 bg-white/90 px-2 py-1 text-xs font-semibold text-red-700 shadow-sm transition group-hover:flex hover:text-red-900 hover:border-red-300";
|
|
||||||
removeButton.innerHTML = '<i class="ri-close-line mr-1"></i>Entfernen';
|
|
||||||
removeButton.addEventListener("click", (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
this._removePendingFile(index);
|
|
||||||
});
|
|
||||||
wrapper.appendChild(removeButton);
|
|
||||||
list.appendChild(wrapper);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (uploadProxy && uploadProxy.parentElement !== list) {
|
if (uploadProxy && uploadProxy.parentElement !== list) {
|
||||||
list.appendChild(uploadProxy);
|
list.appendChild(uploadProxy);
|
||||||
}
|
}
|
||||||
@@ -266,6 +331,8 @@ export class ContentImages extends HTMLElement {
|
|||||||
dialog.setAttribute("open", "true");
|
dialog.setAttribute("open", "true");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._wireDrag(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ensureList() {
|
_ensureList() {
|
||||||
@@ -281,18 +348,6 @@ export class ContentImages extends HTMLElement {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
_findUploadTile() {
|
|
||||||
const panel = this.closest("[data-role='content-images-panel']");
|
|
||||||
if (!panel) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const upload = panel.querySelector("[data-role='content-images-upload']");
|
|
||||||
if (!upload) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return upload;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ensureUploadProxy() {
|
_ensureUploadProxy() {
|
||||||
const panel = this.closest("[data-role='content-images-panel']");
|
const panel = this.closest("[data-role='content-images-panel']");
|
||||||
if (!panel) {
|
if (!panel) {
|
||||||
@@ -329,8 +384,9 @@ export class ContentImages extends HTMLElement {
|
|||||||
this._render(this._currentImages || []);
|
this._render(this._currentImages || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
_removePendingFile(index) {
|
_removePendingFileById(id) {
|
||||||
if (index < 0 || index >= this._pendingFiles.length) {
|
const index = this._pendingIds.indexOf(id);
|
||||||
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const url = this._pendingUrls[index];
|
const url = this._pendingUrls[index];
|
||||||
@@ -339,6 +395,8 @@ export class ContentImages extends HTMLElement {
|
|||||||
}
|
}
|
||||||
this._pendingFiles.splice(index, 1);
|
this._pendingFiles.splice(index, 1);
|
||||||
this._pendingUrls.splice(index, 1);
|
this._pendingUrls.splice(index, 1);
|
||||||
|
this._pendingIds.splice(index, 1);
|
||||||
|
this._scanOrder = this._scanOrder.filter((token) => token !== `pending:${id}`);
|
||||||
this._render(this._currentImages || []);
|
this._render(this._currentImages || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,10 +404,21 @@ export class ContentImages extends HTMLElement {
|
|||||||
return Array.isArray(this._pendingFiles) ? this._pendingFiles : [];
|
return Array.isArray(this._pendingFiles) ? this._pendingFiles : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPendingIds() {
|
||||||
|
return Array.isArray(this._pendingIds) ? this._pendingIds : [];
|
||||||
|
}
|
||||||
|
|
||||||
getPendingDeletes() {
|
getPendingDeletes() {
|
||||||
return Array.from(this._pendingDeletes || []);
|
return Array.from(this._pendingDeletes || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScanOrder() {
|
||||||
|
if (!Array.isArray(this._scanOrder)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this._scanOrder.slice();
|
||||||
|
}
|
||||||
|
|
||||||
_clearPendingPreviews() {
|
_clearPendingPreviews() {
|
||||||
if (Array.isArray(this._pendingUrls)) {
|
if (Array.isArray(this._pendingUrls)) {
|
||||||
this._pendingUrls.forEach((url) => URL.revokeObjectURL(url));
|
this._pendingUrls.forEach((url) => URL.revokeObjectURL(url));
|
||||||
@@ -361,6 +430,63 @@ export class ContentImages extends HTMLElement {
|
|||||||
this._clearPendingPreviews();
|
this._clearPendingPreviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_wireDrag(list) {
|
||||||
|
if (!list || list.dataset.dragInit === "true") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list.dataset.dragInit = "true";
|
||||||
|
let draggingKey = null;
|
||||||
|
|
||||||
|
list.addEventListener("dragstart", (event) => {
|
||||||
|
const item = event.target.closest("[data-role='content-images-item'], [data-role='content-images-pending']");
|
||||||
|
if (!item) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
draggingKey = item.dataset.scanKey || null;
|
||||||
|
item.classList.add("opacity-60");
|
||||||
|
event.dataTransfer.effectAllowed = "move";
|
||||||
|
event.dataTransfer.setData("text/plain", "move");
|
||||||
|
});
|
||||||
|
|
||||||
|
list.addEventListener("dragover", (event) => {
|
||||||
|
if (!draggingKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
const target = event.target.closest("[data-role='content-images-item'], [data-role='content-images-pending']");
|
||||||
|
if (!target || target.dataset.scanKey === draggingKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rect = target.getBoundingClientRect();
|
||||||
|
const before = event.clientY - rect.top < rect.height / 2;
|
||||||
|
const dragged = list.querySelector(`[data-scan-key="${CSS.escape(draggingKey)}"]`);
|
||||||
|
if (!dragged) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (before) {
|
||||||
|
target.before(dragged);
|
||||||
|
} else {
|
||||||
|
target.after(dragged);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
list.addEventListener("dragend", () => {
|
||||||
|
const dragged = draggingKey ? list.querySelector(`[data-scan-key="${CSS.escape(draggingKey)}"]`) : null;
|
||||||
|
if (dragged) {
|
||||||
|
dragged.classList.remove("opacity-60");
|
||||||
|
}
|
||||||
|
draggingKey = null;
|
||||||
|
const newOrder = [];
|
||||||
|
list.querySelectorAll("[data-role='content-images-item'], [data-role='content-images-pending']").forEach((item) => {
|
||||||
|
if (item.dataset.scanKey) {
|
||||||
|
newOrder.push(item.dataset.scanKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._scanOrder = newOrder;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_ensureDialog() {
|
_ensureDialog() {
|
||||||
let dialog = this.querySelector(`[data-role='${CONTENT_IMAGES_DIALOG_ROLE}']`);
|
let dialog = this.querySelector(`[data-role='${CONTENT_IMAGES_DIALOG_ROLE}']`);
|
||||||
if (dialog) {
|
if (dialog) {
|
||||||
|
|||||||
Reference in New Issue
Block a user