diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/collection.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/collection.context.ts new file mode 100644 index 0000000000..8b865085f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/collection.context.ts @@ -0,0 +1,43 @@ +import { BehaviorSubject, Observable } from 'rxjs'; + +export interface UmbCollectionContext { + readonly selectable: Observable; + readonly selection: Observable>; + readonly entityKey: string; + setSelectable(value: boolean): void; + setSelection(value: Array): void; + select(key: string): void; +} + +export class UmbCollectionContextBase implements UmbCollectionContext { + private _selectable: BehaviorSubject = new BehaviorSubject(false); + public readonly selectable: Observable = this._selectable.asObservable(); + + private _selection: BehaviorSubject> = new BehaviorSubject(>[]); + public readonly selection: Observable> = this._selection.asObservable(); + + public entityKey = ''; + + constructor(entityKey: string) { + this.entityKey = entityKey; + } + + public setSelectable(value: boolean) { + this._selectable.next(value); + } + + public setSelection(value: Array) { + if (!value) return; + this._selection.next(value); + } + + public select(key: string) { + const selection = [...this._selection.getValue(), key]; + this._selection.next(selection); + } + + public deselect(key: string) { + const selection = this._selection.getValue(); + this._selection.next(selection.filter((x) => x !== key)); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/layouts/collection-layout-media-grid.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/layouts/collection-layout-media-grid.element.ts index 87522f8c82..4b86be1b27 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/layouts/collection-layout-media-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/collection/layouts/collection-layout-media-grid.element.ts @@ -2,6 +2,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; +import { UmbCollectionContext } from '../collection.context'; import type { MediaDetails } from '@umbraco-cms/models'; import { UmbMediaStore } from '@umbraco-cms/stores/media/media.store'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; @@ -68,6 +69,8 @@ export class UmbCollectionLayoutMediaGridElement extends UmbContextConsumerMixin @state() private _mediaItems: Array = []; + private _collectionContext?: UmbCollectionContext; + private _mediaStore?: UmbMediaStore; constructor() { super(); @@ -81,19 +84,23 @@ export class UmbCollectionLayoutMediaGridElement extends UmbContextConsumerMixin e.preventDefault(); this.toggleAttribute('dragging', false); }); - this.consumeContext('umbMediaStore', (store: UmbMediaStore) => { - this._mediaStore = store; + this.consumeAllContexts(['umbMediaStore', 'umbCollectionContext'], (instance) => { + this._mediaStore = instance['umbMediaStore']; + this._collectionContext = instance['umbCollectionContext']; this._observeMediaItems(); }); } private _observeMediaItems() { - if (!this._mediaStore) return; + if (!this._mediaStore || !this._collectionContext) return; - this.observe>(this._mediaStore?.getTreeRoot(), (items) => { - this._mediaItems = items; - console.log('media store', this._mediaStore); - }); + this.observe>( + this._mediaStore?.getTreeItemChildren(this._collectionContext.entityKey), + (items) => { + this._mediaItems = items; + console.log('media store', this._mediaStore); + } + ); } private _handleOpenItem(key: string) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/media-management/dashboard-media-management.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/media-management/dashboard-media-management.element.ts index 2a33d39c19..43fd24d538 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/media-management/dashboard-media-management.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/media-management/dashboard-media-management.element.ts @@ -1,6 +1,6 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, LitElement } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import '../../components/collection/collection-toolbar.element'; import '../../components/collection/collection-selection-actions.element'; import '../../components/collection/collection-view.element'; @@ -11,6 +11,7 @@ import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/c import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { createExtensionElement } from '@umbraco-cms/extensions-api'; +import { UmbCollectionContextBase } from '@umbraco-cms/components/collection/collection.context'; @customElement('umb-dashboard-media-management') export class UmbDashboardMediaManagementElement extends UmbContextProviderMixin( @@ -33,6 +34,20 @@ export class UmbDashboardMediaManagementElement extends UmbContextProviderMixin( @state() private _routes: Array = []; + private _entityKey = ''; + + @property() + public get entityKey() { + return this._entityKey; + } + public set entityKey(value: string) { + const oldValue = this._entityKey; + if (oldValue === value) return; + this._entityKey = value; + this.requestUpdate('entityKey', oldValue); + this.provideContext('umbCollectionContext', new UmbCollectionContextBase(this.entityKey)); + } + @state() private _collectionLayouts: Array = []; @@ -41,7 +56,6 @@ export class UmbDashboardMediaManagementElement extends UmbContextProviderMixin( constructor() { super(); - this.provideContext('umbMediaContext', this); this._observeCollectionLayouts(); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/media/workspace-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/media/workspace-media.element.ts index d676c61f20..dedd2037c3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/media/workspace-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/media/workspace-media.element.ts @@ -36,6 +36,19 @@ export class UmbWorkspaceMediaElement extends UmbContextConsumerMixin(UmbContext private _registerWorkspaceViews() { const dashboards: Array = [ + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.Media.Collection', + name: 'Media Workspace Collection View', + loader: () => import('../shared/workspace-content/views/collection/workspace-view-content-collection.element'), + weight: 300, + meta: { + workspaces: ['Umb.Workspace.Media'], + label: 'Media', + pathname: 'collection', + icon: 'umb:grid', + }, + }, { type: 'workspaceView', alias: 'Umb.WorkspaceView.Media.Edit', @@ -71,7 +84,9 @@ export class UmbWorkspaceMediaElement extends UmbContextConsumerMixin(UmbContext } render() { - return html``; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/shared/workspace-content/views/collection/workspace-view-content-collection.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/shared/workspace-content/views/collection/workspace-view-content-collection.element.ts new file mode 100644 index 0000000000..e518ca6d80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/workspaces/shared/workspace-content/views/collection/workspace-view-content-collection.element.ts @@ -0,0 +1,67 @@ +import { css, html, LitElement, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import { distinctUntilChanged } from 'rxjs'; +import { UmbNodeContext } from '../../node.context'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import type { ContentProperty, ContentPropertyData, DocumentDetails, MediaDetails } from '@umbraco-cms/models'; + +import '../../../../../components/content-property/content-property.element'; +import 'src/backoffice/dashboards/media-management/dashboard-media-management.element'; + +@customElement('umb-workspace-view-content-collection') +export class UmbWorkspaceViewContentCollectionElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + margin: var(--uui-size-layout-1); + } + `, + ]; + + @state() + _properties: ContentProperty[] = []; + + @state() + _data: ContentPropertyData[] = []; + + @state() + private _key = ''; + + private _nodeContext?: UmbNodeContext; + + constructor() { + super(); + + this.consumeContext('umbNodeContext', (nodeContext) => { + this._nodeContext = nodeContext; + this._observeContent(); + }); + } + + private _observeContent() { + if (!this._nodeContext) return; + + this.observe(this._nodeContext.data.pipe(distinctUntilChanged()), (content) => { + this._properties = content.properties; + this._data = content.data; + this._key = content.key; + }); + } + + render() { + if (!this._key) return nothing; + return html``; + } +} + +export default UmbWorkspaceViewContentCollectionElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-workspace-view-content-collection': UmbWorkspaceViewContentCollectionElement; + } +}