own component
This commit is contained in:
@@ -1,155 +1,23 @@
|
||||
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 { 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 { 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));
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
document.removeEventListener('dragenter', this.#handleDragEnter.bind(this));
|
||||
document.removeEventListener('dragleave', this.#handleDragLeave.bind(this));
|
||||
document.removeEventListener('drop', this.#handleDrop.bind(this));
|
||||
}
|
||||
|
||||
#handleDragEnter() {
|
||||
this.toggleAttribute('dragging', true);
|
||||
}
|
||||
|
||||
#handleDragLeave() {
|
||||
this.toggleAttribute('dragging', false);
|
||||
}
|
||||
|
||||
#handleDrop(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
console.log('#handleDrop', event);
|
||||
this.toggleAttribute('dragging', false);
|
||||
}
|
||||
|
||||
async #onFileUpload(event: UUIFileDropzoneEvent) {
|
||||
/** TODO: Move dropzone and logic into its own component, so that we can reuse it in more places... */
|
||||
const files: Array<File> = event.detail.files;
|
||||
if (!files.length) return;
|
||||
|
||||
const { data } = await this.#mediaTypeStructure.requestAllowedChildrenOf(null);
|
||||
if (!data) return;
|
||||
|
||||
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` <umb-media-collection-toolbar slot="header"></umb-media-collection-toolbar>
|
||||
<uui-file-dropzone
|
||||
id="dropzone"
|
||||
multiple
|
||||
@change=${this.#onFileUpload}
|
||||
label="${this.localize.term('media_dragAndDropYourFilesIntoTheArea')}"
|
||||
accept=""></uui-file-dropzone>`;
|
||||
<umb-dropzone-media @change=${() => this.#mediaCollection?.requestCollection()}></umb-dropzone-media>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host([dragging]) #dropzone {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
[dropzone] {
|
||||
opacity: 0;
|
||||
}
|
||||
#dropzone {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset: 0px;
|
||||
z-index: 100;
|
||||
backdrop-filter: opacity(1); /* Removes the built in blur effect */
|
||||
border-radius: var(--uui-border-radius);
|
||||
overflow: clip;
|
||||
border: 1px solid var(--uui-color-focus);
|
||||
}
|
||||
#dropzone:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: var(--uui-border-radius);
|
||||
background-color: var(--uui-color-focus);
|
||||
opacity: 0.2;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbMediaCollectionElement;
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
import { UmbMediaDetailRepository } from '../../repository/index.js';
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js';
|
||||
import type { UmbMediaDetailModel } from '../../types.js';
|
||||
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UUIFileDropzoneEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbId } from '@umbraco-cms/backoffice/id';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import {
|
||||
type UmbAllowedMediaTypeModel,
|
||||
UmbMediaTypeStructureRepository,
|
||||
getMediaTypeByFileMimeType,
|
||||
} from '@umbraco-cms/backoffice/media-type';
|
||||
import { UmbTemporaryFileManager } from '@umbraco-cms/backoffice/temporary-file';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
|
||||
@customElement('umb-dropzone-media')
|
||||
export class UmbDropzoneMediaElement extends UmbLitElement {
|
||||
#fileManager = new UmbTemporaryFileManager(this);
|
||||
#mediaTypeStructure = new UmbMediaTypeStructureRepository(this);
|
||||
#allowedMediaTypes: Array<UmbAllowedMediaTypeModel> = [];
|
||||
#mediaDetailRepository = new UmbMediaDetailRepository(this);
|
||||
|
||||
@property()
|
||||
collectionUnique: string | null = null;
|
||||
|
||||
@property()
|
||||
parentUnique: string | null = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#getAllowedMediaTypes();
|
||||
document.addEventListener('dragenter', this.#handleDragEnter.bind(this));
|
||||
document.addEventListener('dragleave', this.#handleDragLeave.bind(this));
|
||||
document.addEventListener('drop', this.#handleDrop.bind(this));
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
document.removeEventListener('dragenter', this.#handleDragEnter.bind(this));
|
||||
document.removeEventListener('dragleave', this.#handleDragLeave.bind(this));
|
||||
document.removeEventListener('drop', this.#handleDrop.bind(this));
|
||||
}
|
||||
|
||||
#handleDragEnter() {
|
||||
this.toggleAttribute('dragging', true);
|
||||
}
|
||||
|
||||
#handleDragLeave() {
|
||||
this.toggleAttribute('dragging', false);
|
||||
}
|
||||
|
||||
#handleDrop(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
this.toggleAttribute('dragging', false);
|
||||
}
|
||||
|
||||
async #getAllowedMediaTypes() {
|
||||
const { data } = await this.#mediaTypeStructure.requestAllowedChildrenOf(null);
|
||||
if (!data) return;
|
||||
this.#allowedMediaTypes = data.items;
|
||||
}
|
||||
|
||||
#getMediaTypeFromMime(mimetype: string): UmbAllowedMediaTypeModel {
|
||||
const mediaTypeName = getMediaTypeByFileMimeType(mimetype);
|
||||
return this.#allowedMediaTypes.find((type) => type.name === mediaTypeName)!;
|
||||
}
|
||||
|
||||
async #uploadHandler(file: File) {
|
||||
const unique = UmbId.new();
|
||||
const uploaded = await this.#fileManager.uploadOne({ file, unique });
|
||||
if (uploaded[0].status === 'error') {
|
||||
throw new Error('Error uploading file');
|
||||
}
|
||||
return uploaded[0];
|
||||
}
|
||||
|
||||
async #onFileUpload(event: UUIFileDropzoneEvent) {
|
||||
const files: Array<File> = event.detail.files;
|
||||
if (!files.length) return;
|
||||
|
||||
for (const file of files) {
|
||||
const mediaTypeDetailUnique = UmbId.new();
|
||||
|
||||
const mediaType = this.#getMediaTypeFromMime(file.type);
|
||||
const uploaded = await this.#uploadHandler(file);
|
||||
|
||||
const model: UmbMediaDetailModel = {
|
||||
unique: mediaTypeDetailUnique,
|
||||
mediaType: {
|
||||
unique: mediaType.unique,
|
||||
collection: this.collectionUnique ? { unique: this.collectionUnique } : null,
|
||||
},
|
||||
entityType: UMB_MEDIA_ENTITY_TYPE,
|
||||
isTrashed: false,
|
||||
urls: [],
|
||||
values: [
|
||||
{
|
||||
alias: 'umbracoFile',
|
||||
value: { src: uploaded.unique },
|
||||
culture: null,
|
||||
segment: null,
|
||||
},
|
||||
],
|
||||
variants: [
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
name: file.name,
|
||||
createDate: '',
|
||||
updateDate: '',
|
||||
},
|
||||
],
|
||||
};
|
||||
await this.#mediaDetailRepository.create(model, null);
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<uui-file-dropzone
|
||||
id="dropzone"
|
||||
multiple
|
||||
@change=${this.#onFileUpload}
|
||||
label="${this.localize.term('media_dragAndDropYourFilesIntoTheArea')}"
|
||||
accept=""></uui-file-dropzone>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host([dragging]) #dropzone {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
[dropzone] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#dropzone {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
inset: 0px;
|
||||
z-index: 100;
|
||||
backdrop-filter: opacity(1); /* Removes the built in blur effect */
|
||||
border-radius: var(--uui-border-radius);
|
||||
overflow: clip;
|
||||
border: 1px solid var(--uui-color-focus);
|
||||
}
|
||||
#dropzone:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: var(--uui-border-radius);
|
||||
background-color: var(--uui-color-focus);
|
||||
opacity: 0.2;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbDropzoneMediaElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-dropzone-media': UmbDropzoneMediaElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './dropzone-media.element.js';
|
||||
@@ -1,4 +1,5 @@
|
||||
import './input-media/index.js';
|
||||
|
||||
export * from './dropzone-media/index.js';
|
||||
export * from './input-media/index.js';
|
||||
export * from './input-image-cropper/index.js';
|
||||
|
||||
Reference in New Issue
Block a user