refactoring
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import type { UmbCollectionContext } from './collection.context';
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import type { MediaDetails } from '@umbraco-cms/models';
|
||||
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
|
||||
import type { UmbDashboardMediaManagementElement } from 'src/backoffice/dashboards/media-management/dashboard-media-management.element';
|
||||
|
||||
@customElement('umb-collection-selection-actions')
|
||||
export class UmbCollectionSelectionActionsElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
|
||||
@@ -28,18 +28,18 @@ export class UmbCollectionSelectionActionsElement extends UmbContextConsumerMixi
|
||||
public entityType = 'media';
|
||||
|
||||
@state()
|
||||
private _mediaItems: Array<MediaDetails> = [];
|
||||
private _nodesLength = 0;
|
||||
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
private _selectionLength = 0;
|
||||
|
||||
private _mediaContext?: UmbDashboardMediaManagementElement;
|
||||
private _collectionContext?: UmbCollectionContext<MediaDetails>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeAllContexts(['umbMediaContext'], (instance) => {
|
||||
this._mediaContext = instance['umbMediaContext'];
|
||||
this._observeMediaContext();
|
||||
this.consumeContext('umbCollectionContext', (instance) => {
|
||||
this._collectionContext = instance;
|
||||
this._observeCollectionContext();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -50,27 +50,28 @@ export class UmbCollectionSelectionActionsElement extends UmbContextConsumerMixi
|
||||
}
|
||||
|
||||
private _handleClearSelection() {
|
||||
this._mediaContext?.setSelection([]);
|
||||
this._collectionContext?.setSelection([]);
|
||||
}
|
||||
|
||||
private _observeMediaContext() {
|
||||
if (!this._mediaContext) return;
|
||||
private _observeCollectionContext() {
|
||||
if (!this._collectionContext) return;
|
||||
|
||||
this.observe<Array<MediaDetails>>(this._mediaContext.mediaItems, (mediaItems) => {
|
||||
this._mediaItems = mediaItems;
|
||||
// TODO: Make sure it only updates on length change.
|
||||
this.observe<Array<MediaDetails>>(this._collectionContext.data, (mediaItems) => {
|
||||
this._nodesLength = mediaItems.length;
|
||||
});
|
||||
|
||||
this.observe<Array<string>>(this._mediaContext.selection, (selection) => {
|
||||
this._selection = selection;
|
||||
this.observe<Array<string>>(this._collectionContext.selection, (selection) => {
|
||||
this._selectionLength = selection.length;
|
||||
});
|
||||
}
|
||||
|
||||
private _renderSelectionCount() {
|
||||
return html`<div>${this._selection.length} of ${this._mediaItems.length} selected</div>`;
|
||||
return html`<div>${this._selectionLength} of ${this._nodesLength} selected</div>`;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this._selection.length === 0) return nothing;
|
||||
if (this._selectionLength === 0) return nothing;
|
||||
|
||||
return html`<uui-button
|
||||
@click=${this._handleClearSelection}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import { BehaviorSubject, Observable, Subscription } from "rxjs";
|
||||
import { ContentTreeItem } from "@umbraco-cms/backend-api";
|
||||
import { UmbContextConsumer } from "@umbraco-cms/context-api";
|
||||
import { UmbTreeDataStore } from "@umbraco-cms/stores/store";
|
||||
|
||||
export class UmbCollectionContext<DataType extends ContentTreeItem, StoreType extends UmbTreeDataStore<DataType> = UmbTreeDataStore<DataType>> {
|
||||
|
||||
|
||||
private _target: HTMLElement;
|
||||
private _entityKey:string;
|
||||
|
||||
|
||||
protected _storeConsumer!:UmbContextConsumer;
|
||||
private _store?: StoreType;
|
||||
|
||||
private _data: BehaviorSubject<Array<DataType>> = new BehaviorSubject(<Array<DataType>>[]);
|
||||
public readonly data: Observable<Array<DataType>> = this._data.asObservable();
|
||||
protected _dataObserver?:Subscription;
|
||||
|
||||
|
||||
private _selection: BehaviorSubject<Array<string>> = new BehaviorSubject(<Array<string>>[]);
|
||||
public readonly selection: Observable<Array<string>> = this._selection.asObservable();
|
||||
|
||||
/*
|
||||
TODO:
|
||||
private _search: BehaviorSubject<string> = new BehaviorSubject('');
|
||||
public readonly search: Observable<string> = this._search.asObservable();
|
||||
*/
|
||||
|
||||
constructor(target:HTMLElement, entityKey: string, storeAlias:string) {
|
||||
this._target = target;
|
||||
this._entityKey = entityKey;
|
||||
|
||||
this._storeConsumer = new UmbContextConsumer(this._target, storeAlias, (_instance: StoreType) => {
|
||||
this._store = _instance;
|
||||
if(!this._store) {
|
||||
// TODO: if we keep the type assumption of _store existing, then we should here make sure to break the application in a good way.
|
||||
return;
|
||||
}
|
||||
this._onStoreSubscription();
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this._storeConsumer.attach();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this._storeConsumer.detach();
|
||||
}
|
||||
|
||||
|
||||
public getData() {
|
||||
return this._data.getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
public update(data: Partial<DataType>) {
|
||||
this._data.next({ ...this.getData(), ...data });
|
||||
}
|
||||
*/
|
||||
|
||||
protected _onStoreSubscription(): void {
|
||||
if(!this._store) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._entityKey) {
|
||||
this._dataObserver = this._store.getTreeItemChildren(this._entityKey).subscribe((nodes) => {
|
||||
this._data.next(nodes);
|
||||
});
|
||||
} else {
|
||||
this._dataObserver = this._store.getTreeRoot().subscribe((nodes) => {
|
||||
this._data.next(nodes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
TODO:
|
||||
public setSearch(value: string) {
|
||||
if (!value) value = '';
|
||||
|
||||
this._search.next(value);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public setSelection(value: Array<string>) {
|
||||
if (!value) return;
|
||||
this._selection.next(value);
|
||||
}
|
||||
|
||||
public clearSelection() {
|
||||
this._selection.next([]);
|
||||
}
|
||||
|
||||
public select(key: string) {
|
||||
const selection = this._selection.getValue();
|
||||
this._selection.next([...selection, key]);
|
||||
}
|
||||
|
||||
public deselect(key: string) {
|
||||
const selection = this._selection.getValue();
|
||||
this._selection.next(selection.filter((k) => k !== key));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: how can we make sure to call this.
|
||||
public destroy(): void {
|
||||
this._data.unsubscribe();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { customElement, state, property } from 'lit/decorators.js';
|
||||
import { map } from 'rxjs';
|
||||
import './collection-selection-actions.element';
|
||||
import './collection-toolbar.element';
|
||||
import type { UmbCollectionContext } from './collection.context';
|
||||
import { createExtensionElement } from '@umbraco-cms/extensions-api';
|
||||
import type { ManifestCollectionView } from '@umbraco-cms/models';
|
||||
import type { ManifestCollectionView, MediaDetails } from '@umbraco-cms/models';
|
||||
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry';
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import type { UmbDashboardMediaManagementElement } from 'src/backoffice/dashboards/media-management/dashboard-media-management.element';
|
||||
|
||||
@customElement('umb-collection')
|
||||
export class UmbCollectionElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
|
||||
@@ -32,7 +32,7 @@ export class UmbCollectionElement extends UmbContextConsumerMixin(UmbObserverMix
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
|
||||
private _mediaContext?: UmbDashboardMediaManagementElement;
|
||||
private _collectionContext?: UmbCollectionContext<MediaDetails>;
|
||||
|
||||
|
||||
private _entityType!: string;
|
||||
@@ -51,16 +51,16 @@ export class UmbCollectionElement extends UmbContextConsumerMixin(UmbObserverMix
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeAllContexts(['umbMediaContext'], (instance) => {
|
||||
this._mediaContext = instance['umbMediaContext'];
|
||||
this._observeMediaContext();
|
||||
this.consumeContext('umbCollectionContext', (instance) => {
|
||||
this._collectionContext = instance;
|
||||
this._observeCollectionContext();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeMediaContext() {
|
||||
if (!this._mediaContext) return;
|
||||
private _observeCollectionContext() {
|
||||
if (!this._collectionContext) return;
|
||||
|
||||
this.observe<Array<string>>(this._mediaContext.selection, (selection) => {
|
||||
this.observe<Array<string>>(this._collectionContext.selection, (selection) => {
|
||||
this._selection = selection;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ 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 type { UmbCollectionContext } from '../collection.context';
|
||||
import type { MediaDetails } from '@umbraco-cms/models';
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
|
||||
import type { UmbDashboardMediaManagementElement } from 'src/backoffice/dashboards/media-management/dashboard-media-management.element';
|
||||
|
||||
@customElement('umb-collection-view-media-grid')
|
||||
export class UmbCollectionViewsMediaGridElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
|
||||
@@ -71,7 +71,7 @@ export class UmbCollectionViewsMediaGridElement extends UmbContextConsumerMixin(
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
|
||||
private _mediaContext?: UmbDashboardMediaManagementElement;
|
||||
private _collectionContext?: UmbCollectionContext<MediaDetails>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -85,20 +85,20 @@ export class UmbCollectionViewsMediaGridElement extends UmbContextConsumerMixin(
|
||||
e.preventDefault();
|
||||
this.toggleAttribute('dragging', false);
|
||||
});
|
||||
this.consumeAllContexts(['umbMediaContext'], (instance) => {
|
||||
this._mediaContext = instance['umbMediaContext'];
|
||||
this._observeMediaContext();
|
||||
this.consumeContext('umbCollectionContext', (instance) => {
|
||||
this._collectionContext = instance;
|
||||
this._observeCollectionContext();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeMediaContext() {
|
||||
if (!this._mediaContext) return;
|
||||
private _observeCollectionContext() {
|
||||
if (!this._collectionContext) return;
|
||||
|
||||
this.observe<Array<MediaDetails>>(this._mediaContext.mediaItems, (mediaItems) => {
|
||||
this.observe<Array<MediaDetails>>(this._collectionContext.data, (mediaItems) => {
|
||||
this._mediaItems = mediaItems;
|
||||
});
|
||||
|
||||
this.observe<Array<string>>(this._mediaContext.selection, (selection) => {
|
||||
this.observe<Array<string>>(this._collectionContext.selection, (selection) => {
|
||||
this._selection = selection;
|
||||
});
|
||||
}
|
||||
@@ -109,11 +109,11 @@ export class UmbCollectionViewsMediaGridElement extends UmbContextConsumerMixin(
|
||||
}
|
||||
|
||||
private _handleSelect(mediaItem: MediaDetails) {
|
||||
this._mediaContext?.select(mediaItem.key);
|
||||
this._collectionContext?.select(mediaItem.key);
|
||||
}
|
||||
|
||||
private _handleDeselect(mediaItem: MediaDetails) {
|
||||
this._mediaContext?.deselect(mediaItem.key);
|
||||
this._collectionContext?.deselect(mediaItem.key);
|
||||
}
|
||||
|
||||
private _isSelected(mediaItem: MediaDetails) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import type { UmbCollectionContext } from '../collection.context';
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import type { MediaDetails } from '@umbraco-cms/models';
|
||||
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
|
||||
import type { UmbDashboardMediaManagementElement } from 'src/backoffice/dashboards/media-management/dashboard-media-management.element';
|
||||
|
||||
@customElement('umb-collection-view-media-table')
|
||||
export class UmbCollectionViewMediaTableElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
|
||||
@@ -16,24 +16,24 @@ export class UmbCollectionViewMediaTableElement extends UmbContextConsumerMixin(
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
|
||||
private _mediaContext?: UmbDashboardMediaManagementElement;
|
||||
private _collectionContext?: UmbCollectionContext<MediaDetails>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeAllContexts(['umbMediaContext'], (instance) => {
|
||||
this._mediaContext = instance['umbMediaContext'];
|
||||
this._observeMediaContext();
|
||||
this.consumeContext('umbCollectionContext', (instance) => {
|
||||
this._collectionContext = instance;
|
||||
this._observeCollectionContext();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeMediaContext() {
|
||||
if (!this._mediaContext) return;
|
||||
private _observeCollectionContext() {
|
||||
if (!this._collectionContext) return;
|
||||
|
||||
this.observe<Array<MediaDetails>>(this._mediaContext.mediaItems, (mediaItems) => {
|
||||
this._mediaItems = mediaItems;
|
||||
this.observe<Array<MediaDetails>>(this._collectionContext.data, (nodes) => {
|
||||
this._mediaItems = nodes;
|
||||
});
|
||||
|
||||
this.observe<Array<string>>(this._mediaContext.selection, (selection) => {
|
||||
this.observe<Array<string>>(this._collectionContext.selection, (selection) => {
|
||||
this._selection = selection;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import '../../components/collection/collection.element';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import type { MediaDetails } from '@umbraco-cms/models';
|
||||
import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api';
|
||||
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
|
||||
import { UmbMediaStore } from '@umbraco-cms/stores/media/media.store';
|
||||
import { UmbMediaStore, UmbMediaStoreItemType } from '@umbraco-cms/stores/media/media.store';
|
||||
import { UmbCollectionContext } from '@umbraco-cms/components/collection/collection.context';
|
||||
|
||||
@customElement('umb-dashboard-media-management')
|
||||
export class UmbDashboardMediaManagementElement extends UmbContextProviderMixin(
|
||||
@@ -25,68 +24,47 @@ export class UmbDashboardMediaManagementElement extends UmbContextProviderMixin(
|
||||
`,
|
||||
];
|
||||
|
||||
|
||||
private _collectionContext?:UmbCollectionContext<UmbMediaStoreItemType, UmbMediaStore>;
|
||||
|
||||
private _entityKey!: string;
|
||||
@property()
|
||||
public entityKey = '';
|
||||
public get entityKey(): string {
|
||||
return this._entityKey;
|
||||
}
|
||||
public set entityKey(value: string) {
|
||||
this._entityKey = value;
|
||||
this._provideWorkspace();
|
||||
}
|
||||
|
||||
private _mediaStore?: UmbMediaStore;
|
||||
|
||||
private _selection: BehaviorSubject<Array<string>> = new BehaviorSubject(<Array<string>>[]);
|
||||
public readonly selection: Observable<Array<string>> = this._selection.asObservable();
|
||||
|
||||
private _mediaItems: BehaviorSubject<Array<MediaDetails>> = new BehaviorSubject(<Array<MediaDetails>>[]);
|
||||
public readonly mediaItems: Observable<Array<MediaDetails>> = this._mediaItems.asObservable();
|
||||
|
||||
private _search: BehaviorSubject<string> = new BehaviorSubject('');
|
||||
public readonly search: Observable<string> = this._search.asObservable();
|
||||
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.provideContext('umbMediaContext', this);
|
||||
this.consumeAllContexts(['umbMediaStore'], (instance) => {
|
||||
this._mediaStore = instance['umbMediaStore'];
|
||||
this._observeMediaItems();
|
||||
});
|
||||
// TODO: subscribe selection.
|
||||
}
|
||||
|
||||
private _observeMediaItems() {
|
||||
if (!this._mediaStore) return;
|
||||
|
||||
if (this.entityKey) {
|
||||
this.observe<Array<MediaDetails>>(this._mediaStore?.getTreeItemChildren(this.entityKey), (items) => {
|
||||
this._mediaItems.next(items);
|
||||
});
|
||||
} else {
|
||||
this.observe<Array<MediaDetails>>(this._mediaStore?.getTreeRoot(), (items) => {
|
||||
this._mediaItems.next(items);
|
||||
});
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
// TODO: avoid this connection, our own approach on Lit-Controller could be handling this case.
|
||||
this._collectionContext?.connectedCallback();
|
||||
}
|
||||
disconnectedCallback(): void {
|
||||
super.connectedCallback()
|
||||
// TODO: avoid this connection, our own approach on Lit-Controller could be handling this case.
|
||||
this._collectionContext?.disconnectedCallback();
|
||||
}
|
||||
|
||||
|
||||
protected _provideWorkspace() {
|
||||
if(this._entityKey) {
|
||||
this._collectionContext = new UmbCollectionContext(this, this._entityKey, 'umbMediaStore');
|
||||
this.provideContext('umbCollectionContext', this._collectionContext);
|
||||
}
|
||||
}
|
||||
|
||||
public setSearch(value: string) {
|
||||
if (!value) value = '';
|
||||
|
||||
this._search.next(value);
|
||||
this._observeMediaItems();
|
||||
this.requestUpdate('search');
|
||||
}
|
||||
|
||||
public setSelection(value: Array<string>) {
|
||||
if (!value) return;
|
||||
this._selection.next(value);
|
||||
this.requestUpdate('selection');
|
||||
}
|
||||
|
||||
public select(key: string) {
|
||||
const selection = this._selection.getValue();
|
||||
this._selection.next([...selection, key]);
|
||||
this.requestUpdate('selection');
|
||||
}
|
||||
|
||||
public deselect(key: string) {
|
||||
const selection = this._selection.getValue();
|
||||
this._selection.next(selection.filter((k) => k !== key));
|
||||
this.requestUpdate('selection');
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return html`<umb-collection entityType="media"></umb-collection>`;
|
||||
|
||||
@@ -8,8 +8,11 @@ export interface UmbDataStoreIdentifiers {
|
||||
export interface UmbDataStore<T> {
|
||||
readonly items: Observable<Array<T>>;
|
||||
updateItems(items: Array<T>): void;
|
||||
getTreeRoot?(): Observable<Array<T>>;
|
||||
getTreeItemChildren?(key: string): Observable<Array<T>>;
|
||||
}
|
||||
|
||||
export interface UmbTreeDataStore<T> extends UmbDataStore<T> {
|
||||
getTreeRoot(): Observable<Array<T>>;
|
||||
getTreeItemChildren(key: string): Observable<Array<T>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,4 +90,4 @@ export abstract class UmbNodeStoreBase<T extends UmbDataStoreIdentifiers> extend
|
||||
* @memberof UmbNodeStoreBase
|
||||
*/
|
||||
abstract save(data: T[]): Promise<void>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user