Merge pull request #701 from umbraco/feature/selection

Feature: Selection Manager
This commit is contained in:
Jacob Overgaard
2023-05-09 11:38:49 +02:00
committed by GitHub
13 changed files with 213 additions and 252 deletions

View File

@@ -3,12 +3,12 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
export interface UmbLanguagePickerModalData {
multiple?: boolean;
selection?: Array<string>;
selection?: Array<string | null>;
filter?: (language: LanguageResponseModel) => boolean;
}
export interface UmbLanguagePickerModalResult {
selection: Array<string>;
selection: Array<string | null>;
}
export const UMB_LANGUAGE_PICKER_MODAL = new UmbModalToken<UmbLanguagePickerModalData, UmbLanguagePickerModalResult>(

View File

@@ -2,10 +2,17 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
export interface UmbSectionPickerModalData {
multiple: boolean;
selection: string[];
selection: Array<string | null>;
}
export const UMB_SECTION_PICKER_MODAL = new UmbModalToken<UmbSectionPickerModalData>('Umb.Modal.SectionPicker', {
type: 'sidebar',
size: 'small',
});
export interface UmbSectionPickerModalResult {
selection: Array<string | null>;
}
export const UMB_SECTION_PICKER_MODAL = new UmbModalToken<UmbSectionPickerModalData, UmbSectionPickerModalResult>(
'Umb.Modal.SectionPicker',
{
type: 'sidebar',
size: 'small',
}
);

View File

@@ -4,7 +4,7 @@ import { UserResponseModel } from '@umbraco-cms/backoffice/backend-api';
export type UmbUserPickerModalData = UmbPickerModalData<UserResponseModel>;
export interface UmbUserPickerModalResult {
selection: Array<string>;
selection: Array<string | null>;
}
export const UMB_USER_PICKER_MODAL = new UmbModalToken<UmbUserPickerModalData, UmbUserPickerModalResult>(

View File

@@ -1,19 +1,23 @@
import { Observable, map } from 'rxjs';
import { UmbPagedData, UmbTreeRepository } from '@umbraco-cms/backoffice/repository';
import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry';
import { UmbBooleanState, UmbArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import { UmbBooleanState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
import { createExtensionClass, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api';
import { ProblemDetailsModel, TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api';
import { UmbSelectionManagerBase } from '@umbraco-cms/backoffice/utils';
// TODO: update interface
export interface UmbTreeContext<TreeItemType extends TreeItemPresentationModel> {
readonly selectable: Observable<boolean>;
readonly selection: Observable<Array<string | null>>;
setSelectable(value: boolean): void;
getSelectable(): boolean;
setMultiple(value: boolean): void;
getMultiple(): boolean;
setSelection(value: Array<string | null>): void;
getSelection(): Array<string | null>;
select(unique: string | null): void;
deselect(unique: string | null): void;
requestChildrenOf: (parentUnique: string | null) => Promise<{
@@ -28,18 +32,16 @@ export class UmbTreeContextBase<TreeItemType extends TreeItemPresentationModel>
{
public host: UmbControllerHostElement;
#selectionManager = new UmbSelectionManagerBase();
#selectable = new UmbBooleanState(false);
public readonly selectable = this.#selectable.asObservable();
#multiple = new UmbBooleanState(false);
public readonly multiple = this.#multiple.asObservable();
#selection = new UmbArrayState(<Array<string | null>>[]);
public readonly selection = this.#selection.asObservable();
public readonly multiple = this.#selectionManager.multiple;
public readonly selection = this.#selectionManager.selection;
#treeAlias?: string;
repository?: UmbTreeRepository<TreeItemType>;
#treeManifestObserver?: UmbObserverController<any>;
#initResolver?: () => void;
@@ -84,32 +86,29 @@ export class UmbTreeContextBase<TreeItemType extends TreeItemPresentationModel>
}
public setMultiple(value: boolean) {
this.#multiple.next(value);
this.#selectionManager.setMultiple(value);
}
public getMultiple() {
return this.#multiple.getValue();
return this.#selectionManager.getMultiple();
}
public setSelection(value: Array<string | null>) {
if (!value) return;
this.#selection.next(value);
this.#selectionManager.setSelection(value);
}
public getSelection() {
return this.#selection.getValue();
return this.#selectionManager.getSelection();
}
public select(unique: string | null) {
if (!this.getSelectable()) return;
const newSelection = this.getMultiple() ? [...this.getSelection(), unique] : [unique];
this.#selection.next(newSelection);
this.#selectionManager.select(unique);
this.host.dispatchEvent(new CustomEvent('selected'));
}
public deselect(unique: string | null) {
const newSelection = this.getSelection().filter((x) => x !== unique);
this.#selection.next(newSelection);
this.#selectionManager.deselect(unique);
this.host.dispatchEvent(new CustomEvent('selected'));
}

View File

@@ -1,2 +1,3 @@
export * from './umbraco-path';
export * from './udi-service';
export * from './selection-manager';

View File

@@ -0,0 +1,61 @@
import { Observable } from 'rxjs';
import { UmbArrayState, UmbBooleanState } from '../observable-api';
export interface UmbSelectionManager {
selection: Observable<Array<string | null>>;
multiple: Observable<boolean>;
getSelection(): Array<string | null>;
setSelection(value: Array<string | null>): void;
getMultiple(): boolean;
setMultiple(value: boolean): void;
toggleSelect(unique: string | null): void;
select(unique: string | null): void;
deselect(unique: string | null): void;
isSelected(unique: string | null): boolean;
}
export class UmbSelectionManagerBase implements UmbSelectionManager {
#selection = new UmbArrayState(<Array<string | null>>[]);
public readonly selection = this.#selection.asObservable();
#multiple = new UmbBooleanState(false);
public readonly multiple = this.#multiple.asObservable();
public getSelection() {
return this.#selection.getValue();
}
public setSelection(value: Array<string | null>) {
if (value === undefined) throw new Error('Value cannot be undefined');
this.#selection.next(value);
}
public getMultiple() {
return this.#multiple.getValue();
}
public setMultiple(value: boolean) {
this.#multiple.next(value);
}
public toggleSelect(unique: string | null) {
this.isSelected(unique) ? this.deselect(unique) : this.select(unique);
}
public select(unique: string | null) {
const newSelection = this.getMultiple() ? [...this.getSelection(), unique] : [unique];
this.#selection.next(newSelection);
}
public deselect(unique: string | null) {
const newSelection = this.getSelection().filter((x) => x !== unique);
this.#selection.next(newSelection);
}
public isSelected(unique: string | null) {
return this.getSelection().includes(unique);
}
}