temp file rename unique

This commit is contained in:
Lone Iversen
2023-11-29 10:17:13 +01:00
parent bcbd680806
commit e23b0c22ed
2 changed files with 40 additions and 35 deletions

View File

@@ -25,12 +25,13 @@ export class UmbInputUploadFieldElement extends FormControlMixin(UmbLitElement)
* @type {Array<String>}
* @default []
*/
@property({ type: Array<string> })
@property({ type: Array })
public set keys(fileKeys: Array<string>) {
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<String>}
* @default undefined
*/
@property({ type: Array<string> })
@property({ type: Array })
fileExtensions?: Array<string>;
/**
@@ -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`<div id="wrapper">${this.#renderFilesWithPath()} ${this.#renderFilesUploaded()}</div>
${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`<div id="wrapper">
return html`
${repeat(
this._currentFiles,
(item) => item.id + item.status,
(item) => item.unique + item.status,
(item) =>
html`<div style="position:relative;">
<umb-input-upload-field-file .file=${item.file as any}></umb-input-upload-field-file>
${item.status === 'waiting' ? html`<umb-temporary-file-badge></umb-temporary-file-badge>` : nothing}
</div>`,
</div> `,
)}
</div>`;
}
@@ -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 */
}
`,
];
}

View File

@@ -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<TemporaryFileQueueItem>([], (item) => item.id);
public readonly items = this.#items.asObservable();
#queue = new UmbArrayState<TemporaryFileQueueItem>([], (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<TemporaryFileQueueItem>) {
this.#items.append(items);
upload(queueItems: Array<TemporaryFileQueueItem>) {
this.#queue.append(queueItems);
this.handleQueue();
}
removeOne(id: string) {
this.#items.removeOne(id);
removeOne(unique: string) {
this.#queue.removeOne(unique);
}
remove(ids: Array<string>) {
this.#items.remove(ids);
remove(uniques: Array<string>) {
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();
}
}