Merge pull request #1249 from umbraco/feature/media-collection-repository
Feature: Media Collection Repository
This commit is contained in:
@@ -1 +1 @@
|
||||
export { UMB_MEDIA_COLLECTION_ALIAS } from './manifests.js';
|
||||
export const UMB_MEDIA_COLLECTION_ALIAS = 'Umb.Collection.Media';
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
export const UMB_MEDIA_COLLECTION_ALIAS = 'Umb.Collection.Media';
|
||||
import { UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS } from './repository/index.js';
|
||||
import { manifests as collectionRepositoryManifests } from './repository/manifests.js';
|
||||
import { UmbMediaCollectionContext } from './media-collection.context.js';
|
||||
import { UMB_MEDIA_COLLECTION_ALIAS } from './index.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const collectionManifest: ManifestTypes = {
|
||||
type: 'collection',
|
||||
alias: UMB_MEDIA_COLLECTION_ALIAS,
|
||||
name: 'Media Collection',
|
||||
api: UmbMediaCollectionContext,
|
||||
element: () => import('./media-collection.element.js'),
|
||||
meta: {
|
||||
repositoryAlias: UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS,
|
||||
},
|
||||
};
|
||||
|
||||
export const manifests = [
|
||||
// TODO: temp registration, missing collection repository
|
||||
{
|
||||
type: 'collection',
|
||||
kind: 'default',
|
||||
alias: UMB_MEDIA_COLLECTION_ALIAS,
|
||||
name: 'Media Collection',
|
||||
},
|
||||
collectionManifest,
|
||||
...collectionRepositoryManifests,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { UmbMediaCollectionFilterModel, UmbMediaCollectionItemModel } from './types.js';
|
||||
import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbMediaCollectionContext extends UmbDefaultCollectionContext<
|
||||
UmbMediaCollectionItemModel,
|
||||
UmbMediaCollectionFilterModel
|
||||
> {
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, 'Umb.CollectionView.MediaGrid');
|
||||
|
||||
this.selection.setSelectable(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
@customElement('umb-media-collection')
|
||||
export class UmbMediaCollectionElement extends UmbCollectionDefaultElement {
|
||||
constructor() {
|
||||
super();
|
||||
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);
|
||||
}
|
||||
|
||||
#onFileChange(event: Event) {
|
||||
console.log('#onFileChange', event);
|
||||
}
|
||||
|
||||
protected renderToolbar() {
|
||||
return html`
|
||||
<umb-collection-toolbar slot="header"></umb-collection-toolbar>
|
||||
<!-- TODO: Add the Media Upload dropzone component in here. [LK] -->
|
||||
<uui-file-dropzone
|
||||
id="dropzone"
|
||||
multiple
|
||||
@file-change=${this.#onFileChange}
|
||||
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: 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;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-media-collection': UmbMediaCollectionElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export { UmbMediaCollectionRepository } from './media-collection.repository.js';
|
||||
|
||||
export const UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS = 'Umb.Repository.MediaCollection';
|
||||
@@ -0,0 +1,12 @@
|
||||
import { UmbMediaCollectionRepository } from './media-collection.repository.js';
|
||||
import { UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS } from './index.js';
|
||||
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const collectionRepositoryManifest: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS,
|
||||
name: 'Media Collection Repository',
|
||||
api: UmbMediaCollectionRepository,
|
||||
};
|
||||
|
||||
export const manifests = [collectionRepositoryManifest];
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { UmbMediaCollectionFilterModel } from '../types.js';
|
||||
import { UmbMediaCollectionServerDataSource } from './media-collection.server.data-source.js';
|
||||
import type { UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbMediaCollectionRepository implements UmbCollectionRepository {
|
||||
#collectionSource: UmbMediaCollectionServerDataSource;
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
this.#collectionSource = new UmbMediaCollectionServerDataSource(host);
|
||||
}
|
||||
|
||||
async requestCollection(query: UmbMediaCollectionFilterModel) {
|
||||
return this.#collectionSource.getCollection(query);
|
||||
}
|
||||
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
export default UmbMediaCollectionRepository;
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { UmbMediaCollectionFilterModel, UmbMediaCollectionItemModel } from '../types.js';
|
||||
import { DirectionModel, MediaResource } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
import type { MediaCollectionResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbMediaCollectionServerDataSource implements UmbCollectionDataSource<UmbMediaCollectionItemModel> {
|
||||
#host: UmbControllerHost;
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
async getCollection(query: UmbMediaCollectionFilterModel) {
|
||||
// if (!query.dataTypeId) {
|
||||
// throw new Error('Data type ID is required to fetch a collection.');
|
||||
// }
|
||||
|
||||
const params = {
|
||||
id: query.unique ?? '',
|
||||
dataTypeId: query.dataTypeId,
|
||||
orderBy: query.orderBy ?? 'updateDate',
|
||||
orderDirection: query.orderDirection === 'asc' ? DirectionModel.ASCENDING : DirectionModel.DESCENDING,
|
||||
filter: query.filter,
|
||||
skip: query.skip ?? 0,
|
||||
take: query.take ?? 100,
|
||||
};
|
||||
|
||||
const { data, error } = await tryExecuteAndNotify(this.#host, MediaResource.getCollectionMedia(params));
|
||||
|
||||
if (data) {
|
||||
const items = data.items.map((item: MediaCollectionResponseModel) => {
|
||||
// TODO: [LK] Temp solution, review how to get the name from the corresponding variant.
|
||||
const variant = item.variants[0];
|
||||
|
||||
const model: UmbMediaCollectionItemModel = {
|
||||
unique: item.id,
|
||||
createDate: new Date(variant.createDate),
|
||||
creator: item.creator,
|
||||
icon: item.mediaType.icon,
|
||||
name: variant.name,
|
||||
updateDate: new Date(variant.updateDate),
|
||||
values: item.values.map((item) => {
|
||||
return { alias: item.alias, value: item.value };
|
||||
}),
|
||||
};
|
||||
return model;
|
||||
});
|
||||
|
||||
return { data: { items, total: data.total } };
|
||||
}
|
||||
|
||||
return { error };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
export interface UmbMediaCollectionFilterModel extends UmbCollectionFilterModel {
|
||||
unique?: string;
|
||||
dataTypeId?: string;
|
||||
orderBy?: string;
|
||||
orderDirection?: 'asc' | 'desc';
|
||||
userDefinedProperties: Array<{alias: string, header: string, isSystem: boolean}>;
|
||||
}
|
||||
|
||||
export interface UmbMediaCollectionItemModel {
|
||||
unique: string;
|
||||
createDate: Date;
|
||||
creator?: string | null;
|
||||
icon: string;
|
||||
name: string;
|
||||
updateDate: Date;
|
||||
values: Array<{ alias: string; value: string }>;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { manifests as collectionViewManifests } from './collection-view/manifests.js';
|
||||
import { manifests as collectionManifests } from './collection/manifests.js';
|
||||
import { manifests as entityActionsManifests } from './entity-actions/manifests.js';
|
||||
import { manifests as entityBulkActionsManifests } from './entity-bulk-actions/manifests.js';
|
||||
import { manifests as menuItemManifests } from './menu-item/manifests.js';
|
||||
@@ -10,6 +11,7 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
|
||||
export const manifests = [
|
||||
...collectionViewManifests,
|
||||
...collectionManifests,
|
||||
...entityActionsManifests,
|
||||
...entityBulkActionsManifests,
|
||||
...menuItemManifests,
|
||||
|
||||
Reference in New Issue
Block a user