Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/packages/media/media/collection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { UMB_MEDIA_COLLECTION_ALIAS } from './manifests.js';
export const UMB_MEDIA_COLLECTION_ALIAS = 'Umb.Collection.Media';
26 changes: 18 additions & 8 deletions src/packages/media/media/collection/manifests.ts
Original file line number Diff line number Diff line change
@@ -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';

export const manifests = [
// TODO: temp registration, missing collection repository
{
type: 'collection',
kind: 'default',
alias: UMB_MEDIA_COLLECTION_ALIAS,
name: 'Media Collection',
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 = [
collectionManifest,
...collectionRepositoryManifests,
];
14 changes: 14 additions & 0 deletions src/packages/media/media/collection/media-collection.context.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
91 changes: 91 additions & 0 deletions src/packages/media/media/collection/media-collection.element.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
3 changes: 3 additions & 0 deletions src/packages/media/media/collection/repository/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { UmbMediaCollectionRepository } from './media-collection.repository.js';

export const UMB_MEDIA_COLLECTION_REPOSITORY_ALIAS = 'Umb.Repository.MediaCollection';
12 changes: 12 additions & 0 deletions src/packages/media/media/collection/repository/manifests.ts
Original file line number Diff line number Diff line change
@@ -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];
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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 };
}
}
19 changes: 19 additions & 0 deletions src/packages/media/media/collection/types.ts
Original file line number Diff line number Diff line change
@@ -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 }>;
}
2 changes: 2 additions & 0 deletions src/packages/media/media/manifests.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -10,6 +11,7 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';

export const manifests = [
...collectionViewManifests,
...collectionManifests,
...entityActionsManifests,
...entityBulkActionsManifests,
...menuItemManifests,
Expand Down