From e23b0c22ed7501d84127f2df82b821153e8e8c76 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:17:13 +0100 Subject: [PATCH] temp file rename unique --- .../input-upload-field.element.ts | 31 +++++++------ .../temporary-file-manager.class.ts | 44 +++++++++---------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-upload-field/input-upload-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-upload-field/input-upload-field.element.ts index e316b90d4d..a2bcb6591a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-upload-field/input-upload-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-upload-field/input-upload-field.element.ts @@ -25,12 +25,13 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) * @type {Array} * @default [] */ - @property({ type: Array }) + @property({ type: Array }) public set keys(fileKeys: Array) { this._keys = fileKeys; super.value = this._keys.join(','); fileKeys.forEach((key) => { if (!UmbId.validate(key)) { + //TODO push when its a path this._filePaths.push(key); } }); @@ -44,7 +45,7 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) * @type {Array} * @default undefined */ - @property({ type: Array }) + @property({ type: Array }) fileExtensions?: Array; /** @@ -79,7 +80,7 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) this.#manager = new UmbTemporaryFileManager(this); this.observe(this.#manager.isReady, (value) => (this.error = !value)); - this.observe(this.#manager.items, (value) => (this._currentFiles = value)); + this.observe(this.#manager.queue, (value) => (this._currentFiles = value)); } connectedCallback(): void { @@ -107,14 +108,14 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) #setFiles(files: File[]) { const items = files.map( (file): TemporaryFileQueueItem => ({ - id: UmbId.new(), + unique: UmbId.new(), file, status: 'waiting', }), ); this.#manager.upload(items); - this.keys = items.map((item) => item.id); + this.keys = items.map((item) => item.unique); this.value = this.keys.join(','); this.dispatchEvent(new CustomEvent('change', { bubbles: true })); @@ -126,12 +127,12 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) } render() { - return html`${this.#renderFilesWithPath()} ${this.#renderFilesUploaded()} - ${this.#renderDropzone()}${this.#renderButtonRemove()}`; + return html`
${this.#renderFilesWithPath()} ${this.#renderFilesUploaded()}
+ ${this.#renderDropzone()}${this.#renderButtonRemove()}`; } //TODO When the property editor gets saved, it seems that the property editor gets the file path from the server rather than key/id. - // Image/files needs to be displayed from a previous save (not just when it just got uploaded). + // This however does not work when there is multiple files. Can the server not handle multiple files uploaded into one property editor? #renderDropzone() { if (!this.multiple && (this._currentFiles.length || this._filePaths.length)) return nothing; return html` @@ -155,15 +156,15 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) #renderFilesUploaded() { if (!this._currentFiles.length) return nothing; - return html`
+ return html` ${repeat( this._currentFiles, - (item) => item.id + item.status, + (item) => item.unique + item.status, (item) => html`
${item.status === 'waiting' ? html`` : nothing} -
`, +
`, )} `; } @@ -177,8 +178,8 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) #handleRemove() { this._filePaths = []; - const ids = this._currentFiles.map((item) => item.id) as string[]; - this.#manager.remove(ids); + const uniques = this._currentFiles.map((item) => item.unique) as string[]; + this.#manager.remove(uniques); this.dispatchEvent(new CustomEvent('change', { bubbles: true })); } @@ -206,6 +207,10 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement) grid-template-columns: repeat(auto-fit, 200px); gap: var(--uui-size-space-4); } + + uui-file-dropzone { + padding: 3px; /** Dropzone background is blurry and covers slightly into other elements. Hack to avoid this */ + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts index 5e39ef14f7..5037f8fecc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts @@ -1,74 +1,74 @@ import { UmbTemporaryFileRepository } from './temporary-file.repository.js'; import { UmbArrayState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; export type TemporaryFileStatus = 'complete' | 'waiting' | 'error'; export interface TemporaryFileQueueItem { - id: string; + unique: string; file: File; status?: TemporaryFileStatus; - //type?: string; } -export class UmbTemporaryFileManager { +export class UmbTemporaryFileManager extends UmbBaseController { #temporaryFileRepository; - #items = new UmbArrayState([], (item) => item.id); - public readonly items = this.#items.asObservable(); + #queue = new UmbArrayState([], (item) => item.unique); + public readonly queue = this.#queue.asObservable(); #isReady = new UmbBooleanState(true); public readonly isReady = this.#isReady.asObservable(); constructor(host: UmbControllerHostElement) { + super(host); this.#temporaryFileRepository = new UmbTemporaryFileRepository(host); - //this.items.subscribe(() => this.handleQueue()); } - uploadOne(id: string, file: File, status: TemporaryFileStatus = 'waiting') { - this.#items.appendOne({ id, file, status }); + uploadOne(unique: string, file: File, status: TemporaryFileStatus = 'waiting') { + this.#queue.appendOne({ unique, file, status }); this.handleQueue(); } - upload(items: Array) { - this.#items.append(items); + upload(queueItems: Array) { + this.#queue.append(queueItems); this.handleQueue(); } - removeOne(id: string) { - this.#items.removeOne(id); + removeOne(unique: string) { + this.#queue.removeOne(unique); } - remove(ids: Array) { - this.#items.remove(ids); + remove(uniques: Array) { + this.#queue.remove(uniques); } private async handleQueue() { - const items = this.#items.getValue(); + const queue = this.#queue.getValue(); - if (!items.length && this.getIsReady()) return; + if (!queue.length && this.getIsReady()) return; this.#isReady.next(false); - items.forEach(async (item) => { + queue.forEach(async (item) => { if (item.status !== 'waiting') return; - const { error } = await this.#temporaryFileRepository.upload(item.id, item.file); + const { error } = await this.#temporaryFileRepository.upload(item.unique, item.file); await new Promise((resolve) => setTimeout(resolve, (Math.random() + 0.5) * 1000)); // simulate small delay so that the upload badge is properly shown if (error) { - this.#items.updateOne(item.id, { ...item, status: 'error' }); + this.#queue.updateOne(item.unique, { ...item, status: 'error' }); } else { - this.#items.updateOne(item.id, { ...item, status: 'complete' }); + this.#queue.updateOne(item.unique, { ...item, status: 'complete' }); } }); - if (!items.find((item) => item.status === 'waiting') && !this.getIsReady()) { + if (!queue.find((item) => item.status === 'waiting') && !this.getIsReady()) { this.#isReady.next(true); } } getIsReady() { - return this.#items.getValue(); + return this.#queue.getValue(); } }