import { customElement, property } from "lit/decorators.js"; import { ClientConsumer } from "../../ClientConsumer"; import { html, css, CSSResultGroup, nothing } from "lit"; import { FolderInfo } from "@labir/server"; import { t } from "i18next"; import { T } from "../../../../translations/Languages"; import { booleanConverter } from "../../../../utils/converters/booleanConverter"; @customElement("folder-upload-dialog") export class FolderUploadDialog extends ClientConsumer { @property( { type: Object} ) public folder!: FolderInfo; @property({ type: String }) public label: string = t(T.uploadafile); @property({ type: String }) public variant: string = "primary"; @property({ type: String }) private errorMessage: string = ""; @property({ type: String, converter: booleanConverter(false) }) private plain: boolean = false; @property({type: String}) public tooltip?: string; @property({ type: Object }) private selectedFiles: FileList | null = null; @property({ type: Function}) public onSuccess?: (files: File[]) => void; public static styles?: CSSResultGroup = css` .content { padding: var(--thermal-gap); } .form-group { margin-bottom: var(--thermal-gap); } label { display: block; margin-bottom: calc(var(--thermal-gap) * 0.5); font-weight: bold; } input[type="file"] { width: 100%; padding: calc(var(--thermal-gap) * 0.5); border: 1px solid var(--thermal-slate); border-radius: var(--thermal-radius); font-size: var(--thermal-fs); } .file-info { background: var(--thermal-slate-light); border-radius: var(--thermal-radius); padding: calc(var(--thermal-gap) * 0.5); margin-top: calc(var(--thermal-gap) * 0.5); } .file-item { font-size: calc(var(--thermal-fs) * 0.9); margin-bottom: calc(var(--thermal-gap) * 0.25); } .error { background: var(--thermal-danger-light, #fee); border: 1px solid var(--thermal-danger, #f00); border-radius: var(--thermal-radius); padding: calc(var(--thermal-gap) * 0.5); margin-top: var(--thermal-gap); color: var(--thermal-danger-dark, #800); font-size: calc(var(--thermal-fs) * 0.9); } `; protected async handleSubmit(): Promise { if (!this.selectedFiles || this.selectedFiles.length === 0) { this.errorMessage = "Vyberte alespoň jeden soubor"; return false; } // Clear previous error this.errorMessage = ""; try { const uploadPromises = Array.from(this.selectedFiles).map(async (file) => { const result = await this .client ?.routes .post .uploadFile(this.folder.path, file) .execute(); if (!result?.success) { throw new Error(`Nepodařilo se nahrát soubor ${file.name}: ${result?.message}`); } return file; }); const uploadedFiles = await Promise.all(uploadPromises); if (this.onSuccess) { this.onSuccess(uploadedFiles); } this.selectedFiles = null; return true; } catch (error) { this.errorMessage = error instanceof Error ? error.message : "Nepodařilo se nahrát soubory"; return false; } } private handleFileChange(event: Event) { const target = event.target as HTMLInputElement; this.selectedFiles = target.files; } protected render(): unknown { const label = this.label !== undefined ? this.label : t(T.uploadafile); if ( ! this.isLoggedIn || !this.folder.may_manage_files_in) { return nothing } return html` this.handleSubmit()} button=${t(T.uploadafile)} > ${label}
${this.selectedFiles && this.selectedFiles.length > 0 ? html`
Vybrané soubory (${this.selectedFiles.length}): ${Array.from(this.selectedFiles).map(file => html`
${file.name} (${(file.size / 1024 / 1024).toFixed(2)} MB)
`)}
` : ''} ${this.errorMessage ? html`
${this.errorMessage}
` : ''}
`; } }