Add batch upload configure modal and settings mapping utilities.

Users configure share mode, expiry, and max views before upload; batch summary confirms choices above the queue.
This commit is contained in:
2026-10-22 03:14:02 +02:00
parent 3bb3258686
commit 805665745b
23 changed files with 637 additions and 7 deletions
+52 -6
View File
@@ -9,16 +9,36 @@
</p>
</div>
<UploadDropzone
ref="dropzoneRef"
:disabled="loadingMetadata"
:selection-error="selectionError"
@pick="onFilesPicked"
/>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<UploadDropzone ref="dropzoneRef" :disabled="loadingMetadata" @pick="onFilesPicked" />
<button
type="button"
class="inline-flex shrink-0 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60 sm:self-center"
:disabled="!canOpenConfigure"
@click="configureModalOpen = true"
>
Configure & upload
</button>
</div>
<p v-if="selectionError" class="text-sm text-destructive">{{ selectionError }}</p>
</div>
<p v-if="confirmedBatchSummary" class="text-center text-xs text-muted-foreground" aria-live="polite">
{{ confirmedBatchSummary }}
</p>
<UploadQueueList :rows="queueRows" :selected-file="selectedFile" @select="selectedFile = $event" />
<MetadataInspector :file-name="selectedFile?.name ?? null" :entry="selectedPreview" />
<UploadConfigureModal
v-model:open="configureModalOpen"
v-model:settings="batchSettings"
@upload="onBatchUpload"
/>
</main>
</template>
@@ -28,8 +48,10 @@ import type UploadDropzone from '@/components/upload/UploadDropzone.vue';
import { config } from '@/config';
import { useExiftoolStore } from '@/stores/exiftool';
import { useMetadataStore } from '@/stores/metadata';
import type { UploadBatchSettingsForm } from '@/types/upload/UploadBatchSettingsForm';
import { analyzePickedUploadFiles } from '@/utils/upload/analyzePickedUploadFiles';
import { buildPickedUploadWarning } from '@/utils/upload/buildPickedUploadWarning';
import { formatUploadBatchSettingsSummary } from '@/utils/upload/formatUploadBatchSettingsSummary';
import prettyBytes from 'pretty-bytes';
const { maxQueueSize, maxImageBytes } = config.validation.upload;
@@ -45,6 +67,15 @@ const selectedFile = ref<File | null>(null);
const selectionError = ref<string | null>(null);
const loadingMetadata = ref(false);
const dropzoneRef = ref<InstanceType<typeof UploadDropzone> | null>(null);
const batchSettings = ref<UploadBatchSettingsForm>({
mode: 'zk',
expiryPreset: 'never',
maxViewsPreset: 'unlimited',
passwordEnabled: false,
password: ''
});
const configureModalOpen = ref(false);
const confirmedBatchSummary = ref<string | null>(null);
onBeforeMount(async () => {
try {
@@ -66,6 +97,14 @@ const queueRows = computed(() =>
const selectedPreview = computed(() => getPreview(selectedFile.value));
const canOpenConfigure = computed(() => {
if (queuedFiles.value.length === 0 || loadingMetadata.value) {
return false;
}
return !queuedFiles.value.some(file => getPreview(file).status === 'error');
});
const onFilesPicked = async (picked: File[]): Promise<void> => {
if (loadingMetadata.value) {
return;
@@ -120,5 +159,12 @@ const resetUploadSelection = (): void => {
queuedFiles.value = [];
selectedFile.value = null;
dropzoneRef.value?.clearInput();
configureModalOpen.value = false;
confirmedBatchSummary.value = null;
};
const onBatchUpload = (): void => {
confirmedBatchSummary.value = formatUploadBatchSettingsSummary(batchSettings.value);
configureModalOpen.value = false;
};
</script>