From fbcb69d18fe32c7c546f0cb5f08ff973da7bcad6 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:03:16 +0100 Subject: [PATCH] dropzone upload --- .../src/packages/media/media-types/index.ts | 2 + .../packages/media/media-types/utils/index.ts | 28 +++++++ .../collection/media-collection.element.ts | 80 ++++++++++++++++--- 3 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/utils/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts index 4a54461e21..60142d5186 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts @@ -6,3 +6,5 @@ export * from './workspace/index.js'; export * from './repository/index.js'; export * from './tree/types.js'; export * from './types.js'; + +export * from './utils/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/utils/index.ts new file mode 100644 index 0000000000..b67055a38e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/utils/index.ts @@ -0,0 +1,28 @@ +export enum UmbMediaTypeFileType { + SVG = 'Vector Graphics (SVG)', + IMAGE = 'Image', + AUDIO = 'Audio', + VIDEO = 'Video', + ARTICLE = 'Article', + FILE = 'File', +} + +export function getMediaTypeByFileExtension(extension: string) { + if (extension === 'svg') return UmbMediaTypeFileType.SVG; + if (['jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff', 'tif', 'webp'].includes(extension)) + return UmbMediaTypeFileType.IMAGE; + if (['mp3', 'weba', 'oga', 'opus'].includes(extension)) return UmbMediaTypeFileType.AUDIO; + if (['mp4', 'webm', 'ogv'].includes(extension)) return UmbMediaTypeFileType.VIDEO; + if (['pdf', 'docx', 'doc'].includes(extension)) return UmbMediaTypeFileType.ARTICLE; + return UmbMediaTypeFileType.FILE; +} + +export function getMediaTypeByFileMimeType(mimetype: string) { + if (mimetype === 'image/svg+xml') return UmbMediaTypeFileType.SVG; + const [type, extension] = mimetype.split('/'); + if (type === 'image') return UmbMediaTypeFileType.IMAGE; + if (type === 'audio') return UmbMediaTypeFileType.AUDIO; + if (type === 'video') return UmbMediaTypeFileType.VIDEO; + if (['pdf', 'docx', 'doc'].includes(extension)) return UmbMediaTypeFileType.ARTICLE; + return UmbMediaTypeFileType.FILE; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts index ac33ba4e8e..feab96f6c5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts @@ -1,16 +1,34 @@ +import type { UmbMediaDetailModel } from '../types.js'; +import { type UmbMediaTreeStore, UMB_MEDIA_TREE_STORE_CONTEXT } from '../tree/media-tree.store.js'; +import type { UmbMediaCollectionContext } from './media-collection.context.js'; import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; -import { UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection'; +import { UMB_DEFAULT_COLLECTION_CONTEXT, UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection'; import './media-collection-toolbar.element.js'; import type { UUIFileDropzoneEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbTemporaryFileManager, type UmbTemporaryFileQueueModel } from '@umbraco-cms/backoffice/temporary-file'; +import { UMB_MEDIA_ENTITY_TYPE, UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media'; +import { UmbTemporaryFileManager } from '@umbraco-cms/backoffice/temporary-file'; import { UmbId } from '@umbraco-cms/backoffice/id'; +import { getMediaTypeByFileMimeType, UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type'; + @customElement('umb-media-collection') export class UmbMediaCollectionElement extends UmbCollectionDefaultElement { #fileManager = new UmbTemporaryFileManager(this); + #mediaTypeStructure = new UmbMediaTypeStructureRepository(this); + #mediaDetailRepository = new UmbMediaDetailRepository(this); + + #mediaCollection?: UmbMediaCollectionContext; + #mediaTreeStore?: UmbMediaTreeStore; constructor() { super(); + this.consumeContext(UMB_DEFAULT_COLLECTION_CONTEXT, (instance) => { + this.#mediaCollection = instance as UmbMediaCollectionContext; + }); + this.consumeContext(UMB_MEDIA_TREE_STORE_CONTEXT, (instance) => { + this.#mediaTreeStore = instance; + console.log('instance is here', instance); + }); document.addEventListener('dragenter', this.#handleDragEnter.bind(this)); document.addEventListener('dragleave', this.#handleDragLeave.bind(this)); document.addEventListener('drop', this.#handleDrop.bind(this)); @@ -38,26 +56,66 @@ export class UmbMediaCollectionElement extends UmbCollectionDefaultElement { } async #onFileUpload(event: UUIFileDropzoneEvent) { - const files: Array = event.detail.files.map((file) => ({ file, unique: UmbId.new() })); + /** TODO: Move dropzone and logic into its own component, so that we can reuse it in more places... */ + const files: Array = event.detail.files; if (!files.length) return; - const items = await this.#fileManager.upload(files); - if (!items.length) return; + const { data } = await this.#mediaTypeStructure.requestAllowedChildrenOf(null); + if (!data) return; - console.log('uploadComplete', items); + for (const file of files) { + const mediaTypeDetailUnique = UmbId.new(); + + const mediaTypeName = getMediaTypeByFileMimeType(file.type); + const mediaType = data.items.find((type) => type.name === mediaTypeName)!; + + const mediaTempFileUnique = UmbId.new(); + + const uploaded = await this.#fileManager.uploadOne({ file, unique: mediaTempFileUnique }); + if (uploaded.find((item) => item.status === 'error')) return; + + const model: UmbMediaDetailModel = { + unique: mediaTypeDetailUnique, + mediaType: { + unique: mediaType.unique, + collection: null, + }, + entityType: UMB_MEDIA_ENTITY_TYPE, + isTrashed: false, + urls: [], + values: [ + { + alias: 'umbracoFile', + value: { src: mediaTempFileUnique }, + culture: null, + segment: null, + }, + ], + variants: [ + { + culture: null, + segment: null, + name: file.name, + createDate: '', + updateDate: '', + }, + ], + }; + + await this.#mediaDetailRepository.create(model, null); + + this.#mediaCollection?.requestCollection(); + } } protected renderToolbar() { - return html` - - + return html` - `; + accept="">`; } static styles = [