[#2445] added support for multiple files sort in the Admin UI

This commit is contained in:
Gani Georgiev
2023-05-17 22:41:42 +03:00
parent 24ab233376
commit 04e0ad9b21
37 changed files with 380 additions and 318 deletions
+21 -5
View File
@@ -5,13 +5,14 @@
export let index;
export let list = [];
export let group = "default";
export let disabled = false;
let dragging = false;
let dragover = false;
function onDrag(event, i) {
if (!event && !disabled) {
if (!event || disabled) {
return;
}
@@ -19,11 +20,17 @@
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.dropEffect = "move";
event.dataTransfer.setData("text/plain", i);
event.dataTransfer.setData(
"text/plain",
JSON.stringify({
index: i,
group: group,
})
);
}
function onDrop(event, target) {
if (!event && !disabled) {
if (!event || disabled) {
return;
}
@@ -32,7 +39,16 @@
event.dataTransfer.dropEffect = "move";
const start = parseInt(event.dataTransfer.getData("text/plain"));
let dragData = {};
try {
dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
} catch (_) {}
if (dragData.group != group) {
return; // different draggable group
}
const start = dragData.index << 0;
if (start < target) {
list.splice(target + 1, 0, list[start]);
@@ -49,7 +65,7 @@
</script>
<div
draggable={true}
draggable={!disabled}
class="draggable"
class:dragging
class:dragover
@@ -11,22 +11,23 @@
$: previewUrl = "";
function loadPreviewUrl() {
previewUrl = "";
if (CommonHelper.hasImageExtension(file?.name)) {
CommonHelper.generateThumb(file, size, size)
.then((url) => {
previewUrl = url;
})
.catch((err) => {
previewUrl = "";
console.warn("Unable to generate thumb: ", err);
});
} else {
previewUrl = "";
}
}
</script>
{#if previewUrl}
<img src={previewUrl} width={size} height={size} alt={file.name} />
<img draggable={false} src={previewUrl} width={size} height={size} alt={file.name} />
{:else}
<i class="ri-file-line" alt={file.name} />
{/if}
@@ -46,6 +46,7 @@
<div class="thumb {size ? `thumb-${size}` : ''}" />
{:else}
<a
draggable={false}
class="thumb {size ? `thumb-${size}` : ''}"
href={originalUrl}
target="_blank"
@@ -59,7 +60,13 @@
}}
>
{#if type === "image"}
<img src={thumbUrl} alt={filename} title="Preview {filename}" on:error={onError} />
<img
draggable={false}
src={thumbUrl}
alt={filename}
title="Preview {filename}"
on:error={onError}
/>
{:else if type === "video" || type === "audio"}
<i class="ri-video-line" />
{:else}
@@ -4,6 +4,7 @@
import CommonHelper from "@/utils/CommonHelper";
import tooltip from "@/actions/tooltip";
import Field from "@/components/base/Field.svelte";
import Draggable from "@/components/base/Draggable.svelte";
import UploadedFilePreview from "@/components/base/UploadedFilePreview.svelte";
import RecordFileThumb from "@/components/records/RecordFileThumb.svelte";
import { onMount } from "svelte";
@@ -79,7 +80,7 @@
const files = e.dataTransfer?.files || [];
if (maxReached || !files.length) {
if (maxReached || !files.length || e.dataTransfer?.effectAllowed != "copy") {
return;
}
@@ -103,7 +104,10 @@
<div
class="block"
on:dragover|preventDefault={() => {
on:dragover|preventDefault={(e) => {
if (e.dataTransfer.effectAllowed != "copy") {
return; // not a file drag
}
isDragOver = true;
}}
on:dragleave={() => {
@@ -128,64 +132,85 @@
<div bind:this={filesListElem} class="list">
{#each valueAsArray as filename, i (filename + record.id)}
{@const isDeleted = deletedFileIndexes.includes(i)}
<div class="list-item">
<div class:fade={deletedFileIndexes.includes(i)}>
<RecordFileThumb {record} {filename} />
</div>
<Draggable
bind:list={value}
group={field.name + "_uploaded"}
index={i}
disabled={!isMultiple}
let:dragging
let:dragover
>
<div class="list-item" class:dragging class:dragover>
<div class:fade={deletedFileIndexes.includes(i)}>
<RecordFileThumb {record} {filename} />
</div>
<div class="content">
<a
href={ApiClient.files.getUrl(record, filename, { token: fileToken })}
class="txt-ellipsis {isDeleted ? 'txt-strikethrough txt-hint' : 'link-primary'}"
title="Download"
target="_blank"
rel="noopener noreferrer"
>
{filename}
</a>
</div>
<div class="content">
<a
draggable={false}
href={ApiClient.files.getUrl(record, filename, { token: fileToken })}
class="txt-ellipsis {isDeleted
? 'txt-strikethrough txt-hint'
: 'link-primary'}"
title="Download"
target="_blank"
rel="noopener noreferrer"
>
{filename}
</a>
</div>
<div class="actions">
{#if deletedFileIndexes.includes(i)}
<button
type="button"
class="btn btn-sm btn-danger btn-transparent"
on:click={() => restoreExistingFile(i)}
>
<span class="txt">Restore</span>
</button>
{:else}
<button
type="button"
class="btn btn-transparent btn-hint btn-sm btn-circle btn-remove"
use:tooltip={"Remove file"}
on:click={() => removeExistingFile(i)}
>
<i class="ri-close-line" />
</button>
{/if}
<div class="actions">
{#if deletedFileIndexes.includes(i)}
<button
type="button"
class="btn btn-sm btn-danger btn-transparent"
on:click={() => restoreExistingFile(i)}
>
<span class="txt">Restore</span>
</button>
{:else}
<button
type="button"
class="btn btn-transparent btn-hint btn-sm btn-circle btn-remove"
use:tooltip={"Remove file"}
on:click={() => removeExistingFile(i)}
>
<i class="ri-close-line" />
</button>
{/if}
</div>
</div>
</div>
</Draggable>
{/each}
{#each uploadedFiles as file, i}
<div class="list-item">
<figure class="thumb">
<UploadedFilePreview {file} />
</figure>
<div class="filename m-r-auto" title={file.name}>
<small class="label label-success m-r-5">New</small>
<span class="txt">{file.name}</span>
<Draggable
bind:list={uploadedFiles}
group={field.name + "_new"}
index={i}
disabled={!isMultiple}
let:dragging
let:dragover
>
<div class="list-item" class:dragging class:dragover>
<figure class="thumb">
<UploadedFilePreview {file} />
</figure>
<div class="filename m-r-auto" title={file.name}>
<small class="label label-success m-r-5">New</small>
<span class="txt">{file.name}</span>
</div>
<button
type="button"
class="btn btn-transparent btn-hint btn-sm btn-circle btn-remove"
use:tooltip={"Remove file"}
on:click={() => removeNewFile(i)}
>
<i class="ri-close-line" />
</button>
</div>
<button
type="button"
class="btn btn-transparent btn-hint btn-sm btn-circle btn-remove"
use:tooltip={"Remove file"}
on:click={() => removeNewFile(i)}
>
<i class="ri-close-line" />
</button>
</div>
</Draggable>
{/each}
<div class="list-item list-item-btn">
+9
View File
@@ -1112,6 +1112,8 @@ select {
.list-item {
border-top: 1px solid var(--baseAlt2Color);
&:hover,
&:focus,
&:focus-within,
&:focus-visible,
&:active {
background: none;
@@ -1128,6 +1130,13 @@ select {
background: var(--baseAlt3Color);
}
}
&.dragging {
z-index: 9;
box-shadow: inset 0 0 0 1px var(--baseAlt3Color);
}
&.dragover {
background: var(--baseAlt2Color);
}
}
}
&:focus-within {