fixing types
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { UmbVariantStructureItemModel } from './types.js';
|
||||
import type { UmbTreeRepository, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
|
||||
import type { UmbTreeItemModel, UmbTreeRepository, UmbTreeRootModel } from '@umbraco-cms/backoffice/tree';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UMB_VARIANT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
@@ -46,7 +46,7 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um
|
||||
const unique = (await this.observe(uniqueObservable, () => {})?.asPromise()) as string;
|
||||
if (!unique) throw new Error('Unique is not available');
|
||||
|
||||
const treeRepository = await createExtensionApiByAlias<UmbTreeRepository<any, UmbUniqueTreeRootModel>>(
|
||||
const treeRepository = await createExtensionApiByAlias<UmbTreeRepository<UmbTreeItemModel, UmbTreeRootModel>>(
|
||||
this,
|
||||
this.#args.treeRepositoryAlias,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbRequestReloadTreeItemChildrenEvent } from '../reload-tree-item-children/index.js';
|
||||
import type { UmbTreeItemModelBase, UmbTreeStartNode } from '../types.js';
|
||||
import type { UmbTreeItemModel, UmbTreeItemModelBase, UmbTreeRootModel, UmbTreeStartNode } from '../types.js';
|
||||
import type { UmbTreeRepository } from '../data/tree-repository.interface.js';
|
||||
import type { UmbTreeContext } from '../tree-context.interface.js';
|
||||
import { type UmbActionEventContext, UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
|
||||
@@ -17,11 +17,11 @@ import { UmbArrayState, UmbBooleanState, UmbObjectState } from '@umbraco-cms/bac
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
|
||||
export class UmbDefaultTreeContext<TreeItemType extends UmbTreeItemModelBase>
|
||||
extends UmbContextBase<UmbDefaultTreeContext<TreeItemType>>
|
||||
export class UmbDefaultTreeContext<TreeItemType extends UmbTreeItemModel, TreeRootType extends UmbTreeRootModel>
|
||||
extends UmbContextBase<UmbDefaultTreeContext<TreeItemType, TreeRootType>>
|
||||
implements UmbTreeContext
|
||||
{
|
||||
#treeRoot = new UmbObjectState<TreeItemType | undefined>(undefined);
|
||||
#treeRoot = new UmbObjectState<TreeRootType | undefined>(undefined);
|
||||
treeRoot = this.#treeRoot.asObservable();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
@@ -41,7 +41,7 @@ export class UmbDefaultTreeContext<TreeItemType extends UmbTreeItemModelBase>
|
||||
startNode = this.#startNode.asObservable();
|
||||
|
||||
#manifest?: ManifestTree;
|
||||
#repository?: UmbTreeRepository<TreeItemType>;
|
||||
#repository?: UmbTreeRepository<TreeItemType, TreeRootType>;
|
||||
#actionEventContext?: UmbActionEventContext;
|
||||
|
||||
#paging = {
|
||||
@@ -173,7 +173,10 @@ export class UmbDefaultTreeContext<TreeItemType extends UmbTreeItemModelBase>
|
||||
|
||||
const { data } = startNode?.unique
|
||||
? await this.#repository!.requestTreeItemsOf({
|
||||
parentUnique: startNode.unique,
|
||||
parent: {
|
||||
unique: startNode.unique,
|
||||
entityType: startNode.entityType,
|
||||
},
|
||||
skip,
|
||||
take,
|
||||
})
|
||||
@@ -299,4 +302,6 @@ export class UmbDefaultTreeContext<TreeItemType extends UmbTreeItemModelBase>
|
||||
|
||||
export default UmbDefaultTreeContext;
|
||||
|
||||
export const UMB_DEFAULT_TREE_CONTEXT = new UmbContextToken<UmbDefaultTreeContext<any>>('UmbTreeContext');
|
||||
export const UMB_DEFAULT_TREE_CONTEXT = new UmbContextToken<UmbDefaultTreeContext<UmbTreeItemModel, UmbTreeRootModel>>(
|
||||
'UmbTreeContext',
|
||||
);
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { UmbTreeItemModelBase, UmbTreeSelectionConfiguration, UmbTreeStartNode } from '../types.js';
|
||||
import type {
|
||||
UmbTreeItemModel,
|
||||
UmbTreeItemModelBase,
|
||||
UmbTreeRootModel,
|
||||
UmbTreeSelectionConfiguration,
|
||||
UmbTreeStartNode,
|
||||
} from '../types.js';
|
||||
import type { UmbDefaultTreeContext } from './default-tree.context.js';
|
||||
import { UMB_DEFAULT_TREE_CONTEXT } from './default-tree.context.js';
|
||||
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
@@ -32,10 +38,10 @@ export class UmbDefaultTreeElement extends UmbLitElement {
|
||||
filter: (item: UmbTreeItemModelBase) => boolean = () => true;
|
||||
|
||||
@state()
|
||||
private _rootItems: UmbTreeItemModelBase[] = [];
|
||||
private _rootItems: UmbTreeItemModel[] = [];
|
||||
|
||||
@state()
|
||||
private _treeRoot?: UmbTreeItemModelBase;
|
||||
private _treeRoot?: UmbTreeRootModel;
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
@@ -43,7 +49,7 @@ export class UmbDefaultTreeElement extends UmbLitElement {
|
||||
@state()
|
||||
private _totalPages = 1;
|
||||
|
||||
#treeContext?: UmbDefaultTreeContext<UmbTreeItemModelBase>;
|
||||
#treeContext?: UmbDefaultTreeContext<UmbTreeItemModel, UmbTreeRootModel>;
|
||||
#init: Promise<unknown>;
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { UmbTreeItemContext } from '../tree-item-context.interface.js';
|
||||
import { UMB_DEFAULT_TREE_CONTEXT, type UmbDefaultTreeContext } from '../../default/default-tree.context.js';
|
||||
import type { UmbTreeItemModel } from '../../types.js';
|
||||
import type { UmbTreeItemModel, UmbTreeRootModel } from '../../types.js';
|
||||
import { UmbRequestReloadTreeItemChildrenEvent } from '../../reload-tree-item-children/index.js';
|
||||
import { map } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import { UMB_SECTION_CONTEXT, UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section';
|
||||
@@ -17,7 +17,10 @@ import type { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action
|
||||
import { UmbPaginationManager, debounce } from '@umbraco-cms/backoffice/utils';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
|
||||
export abstract class UmbTreeItemContextBase<TreeItemType extends UmbTreeItemModel>
|
||||
export abstract class UmbTreeItemContextBase<
|
||||
TreeItemType extends UmbTreeItemModel,
|
||||
TreeRootType extends UmbTreeRootModel,
|
||||
>
|
||||
extends UmbContextBase<UmbTreeItemContext<TreeItemType>>
|
||||
implements UmbTreeItemContext<TreeItemType>
|
||||
{
|
||||
@@ -59,7 +62,7 @@ export abstract class UmbTreeItemContextBase<TreeItemType extends UmbTreeItemMod
|
||||
#path = new UmbStringState('');
|
||||
readonly path = this.#path.asObservable();
|
||||
|
||||
treeContext?: UmbDefaultTreeContext<TreeItemType>;
|
||||
treeContext?: UmbDefaultTreeContext<TreeItemType, TreeRootType>;
|
||||
#sectionContext?: UmbSectionContext;
|
||||
#sectionSidebarContext?: UmbSectionSidebarContext;
|
||||
#actionEventContext?: UmbActionEventContext;
|
||||
@@ -226,7 +229,7 @@ export abstract class UmbTreeItemContextBase<TreeItemType extends UmbTreeItemMod
|
||||
this.#sectionSidebarContext = instance;
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_DEFAULT_TREE_CONTEXT, (treeContext: UmbDefaultTreeContext<TreeItemType>) => {
|
||||
this.consumeContext(UMB_DEFAULT_TREE_CONTEXT, (treeContext) => {
|
||||
this.treeContext = treeContext;
|
||||
this.#observeIsSelectable();
|
||||
this.#observeIsSelected();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { UmbTreeItemContextBase } from '../tree-item-base/index.js';
|
||||
import type { UmbTreeItemModel } from '../../types.js';
|
||||
import type { UmbTreeItemModel, UmbTreeRootModel } from '../../types.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbDefaultTreeItemContext<
|
||||
TreeItemModelType extends UmbTreeItemModel,
|
||||
> extends UmbTreeItemContextBase<TreeItemModelType> {
|
||||
TreeItemType extends UmbTreeItemModel,
|
||||
TreeRootType extends UmbTreeRootModel,
|
||||
> extends UmbTreeItemContextBase<TreeItemType, TreeRootType> {
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import type { UmbDocumentTreeItemModel } from '../types.js';
|
||||
import type { UmbDocumentTreeItemModel, UmbDocumentTreeRootModel } from '../types.js';
|
||||
import { UmbDefaultTreeItemContext } from '@umbraco-cms/backoffice/tree';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin';
|
||||
|
||||
export class UmbDocumentTreeItemContext extends UmbDefaultTreeItemContext<UmbDocumentTreeItemModel> {
|
||||
export class UmbDocumentTreeItemContext extends UmbDefaultTreeItemContext<
|
||||
UmbDocumentTreeItemModel,
|
||||
UmbDocumentTreeRootModel
|
||||
> {
|
||||
// TODO: Provide this together with the EntityContext, ideally this takes part via a extension-type [NL]
|
||||
#isTrashedContext = new UmbIsTrashedEntityContext(this);
|
||||
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
import type { UmbMediaPathModel } from '../types.js';
|
||||
import type { UmbMediaDetailModel } from '../../../types.js';
|
||||
import { UmbMediaDetailRepository } from '../../../repository/index.js';
|
||||
import { UmbMediaTreeRepository } from '../../../tree/media-tree.repository.js';
|
||||
import { UmbMediaTreeRepository } from '../../../tree/index.js';
|
||||
import { UMB_MEDIA_ROOT_ENTITY_TYPE } from '../../../entity.js';
|
||||
import { css, html, customElement, state, repeat, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbId } from '@umbraco-cms/backoffice/id';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { getUmbracoFolderUnique } from '@umbraco-cms/backoffice/media-type';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
const root = { name: 'Media', unique: null };
|
||||
// TODO: get root from tree repository
|
||||
const root = { name: 'Media', unique: null, entityType: UMB_MEDIA_ROOT_ENTITY_TYPE };
|
||||
|
||||
@customElement('umb-media-picker-folder-path')
|
||||
export class UmbMediaPickerFolderPathElement extends UmbLitElement {
|
||||
#mediaTreeRepository = new UmbMediaTreeRepository(this); // used to get file structure
|
||||
#mediaDetailRepository = new UmbMediaDetailRepository(this); // used to create folders
|
||||
|
||||
@property()
|
||||
public set currentPath(value: string | null) {
|
||||
if (value !== this._currentPath) {
|
||||
this._currentPath = value;
|
||||
@property({ type: Object, attribute: false })
|
||||
public set currentMedia(value: UmbEntityModel | undefined) {
|
||||
if (value !== this._currentMedia) {
|
||||
this._currentMedia = value;
|
||||
this.#loadPath();
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
}
|
||||
}
|
||||
public get currentPath() {
|
||||
return this._currentPath;
|
||||
|
||||
public get currentMedia() {
|
||||
return this._currentMedia;
|
||||
}
|
||||
|
||||
@state()
|
||||
private _currentPath: string | null = null;
|
||||
private _currentMedia: UmbEntityModel | undefined;
|
||||
|
||||
@state()
|
||||
private _paths: Array<UmbMediaPathModel> = [root];
|
||||
@@ -43,21 +45,32 @@ export class UmbMediaPickerFolderPathElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
async #loadPath() {
|
||||
if (this.currentPath) {
|
||||
const unique = this._currentMedia?.unique;
|
||||
const entityType = this._currentMedia?.entityType;
|
||||
|
||||
if (unique && entityType) {
|
||||
const { data } = await this.#mediaTreeRepository.requestTreeItemAncestors({
|
||||
descendantUnique: this.currentPath,
|
||||
treeItem: {
|
||||
unique,
|
||||
entityType,
|
||||
},
|
||||
});
|
||||
|
||||
if (data) {
|
||||
this._paths = [root, ...data.map((item) => ({ name: item.name, unique: item.unique }))];
|
||||
} else {
|
||||
this._paths = [root];
|
||||
this._paths = [
|
||||
root,
|
||||
...data.map((item) => ({ name: item.name, unique: item.unique, entityType: item.entityType })),
|
||||
];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._paths = [root];
|
||||
}
|
||||
|
||||
#goToFolder(unique: string | null) {
|
||||
this._paths = [...this._paths].slice(0, this._paths.findIndex((path) => path.unique === unique) + 1);
|
||||
this.currentPath = unique;
|
||||
#goToFolder(entity: UmbEntityModel) {
|
||||
this._paths = [...this._paths].slice(0, this._paths.findIndex((path) => path.unique === entity.unique) + 1);
|
||||
this.currentMedia = entity;
|
||||
}
|
||||
|
||||
#focusFolderInput() {
|
||||
@@ -102,9 +115,10 @@ export class UmbMediaPickerFolderPathElement extends UmbLitElement {
|
||||
|
||||
const name = data.variants[0].name;
|
||||
const unique = data.unique;
|
||||
const entityType = data.entityType;
|
||||
|
||||
this._paths = [...this._paths, { name, unique }];
|
||||
this.currentPath = unique;
|
||||
this._paths = [...this._paths, { name, unique, entityType }];
|
||||
this.currentMedia = { unique, entityType };
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -116,8 +130,8 @@ export class UmbMediaPickerFolderPathElement extends UmbLitElement {
|
||||
html`<uui-button
|
||||
compact
|
||||
.label=${path.name}
|
||||
?disabled=${this.currentPath == path.unique}
|
||||
@click=${() => this.#goToFolder(path.unique)}></uui-button
|
||||
?disabled=${this.currentMedia?.unique === path.unique}
|
||||
@click=${() => this.#goToFolder({ unique: path.unique, entityType: path.entityType })}></uui-button
|
||||
>/`,
|
||||
)}${this._typingNewFolder
|
||||
? html`<uui-input
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { type UmbMediaItemModel, UmbMediaItemRepository, UmbMediaUrlRepository } from '../../repository/index.js';
|
||||
import { UmbMediaTreeRepository } from '../../tree/media-tree.repository.js';
|
||||
import { UMB_MEDIA_ROOT_ENTITY_TYPE } from '../../entity.js';
|
||||
import type { UmbMediaCardItemModel } from './types.js';
|
||||
import type { UmbMediaPickerFolderPathElement } from './components/media-picker-folder-path.element.js';
|
||||
import type { UmbMediaPickerModalData, UmbMediaPickerModalValue } from './media-picker-modal.token.js';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
@customElement('umb-media-picker-modal')
|
||||
export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPickerModalData, UmbMediaPickerModalValue> {
|
||||
@@ -25,17 +27,27 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
private _searchQuery = '';
|
||||
|
||||
@state()
|
||||
private _currentNode: string | null = null;
|
||||
|
||||
connectedCallback(): void {
|
||||
private _currentMediaEntity: UmbEntityModel = { unique: null, entityType: UMB_MEDIA_ROOT_ENTITY_TYPE };
|
||||
async connectedCallback(): Promise<void> {
|
||||
super.connectedCallback();
|
||||
this._currentNode = this.data?.startNode ?? null;
|
||||
|
||||
if (this.data?.startNode) {
|
||||
const { data } = await this.#mediaItemRepository.requestItems([this.data.startNode]);
|
||||
|
||||
if (data?.length) {
|
||||
this._currentMediaEntity = { unique: data[0].unique, entityType: data[0].entityType };
|
||||
}
|
||||
}
|
||||
|
||||
this.#loadMediaFolder();
|
||||
}
|
||||
|
||||
async #loadMediaFolder() {
|
||||
const { data } = await this.#mediaTreeRepository.requestTreeItemsOf({
|
||||
parentUnique: this._currentNode,
|
||||
parent: {
|
||||
unique: this._currentMediaEntity.unique,
|
||||
entityType: this._currentMediaEntity.entityType,
|
||||
},
|
||||
skip: 0,
|
||||
take: 100,
|
||||
});
|
||||
@@ -53,13 +65,15 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
const url = data?.find((media) => media.unique === item.unique)?.url;
|
||||
const extension = url?.split('.').pop();
|
||||
//TODO Eventually we will get a renderable img from the server. Use this for the url. [LI]
|
||||
|
||||
return { name: item.name, unique: item.unique, url, extension };
|
||||
return { name: item.name, unique: item.unique, url, extension, entityType: item.entityType };
|
||||
});
|
||||
}
|
||||
|
||||
#onOpen(item: UmbMediaCardItemModel) {
|
||||
this._currentNode = item.unique!;
|
||||
this._currentMediaEntity = {
|
||||
unique: item.unique,
|
||||
entityType: UMB_MEDIA_ROOT_ENTITY_TYPE,
|
||||
};
|
||||
this.#loadMediaFolder();
|
||||
}
|
||||
|
||||
@@ -107,7 +121,10 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
}
|
||||
|
||||
#onPathChange(e: CustomEvent) {
|
||||
this._currentNode = (e.target as UmbMediaPickerFolderPathElement).currentPath;
|
||||
this._currentMediaEntity = (e.target as UmbMediaPickerFolderPathElement).currentMedia || {
|
||||
unique: null,
|
||||
entityType: UMB_MEDIA_ROOT_ENTITY_TYPE,
|
||||
};
|
||||
this.#loadMediaFolder();
|
||||
}
|
||||
|
||||
@@ -129,7 +146,7 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
|
||||
#renderBody() {
|
||||
return html`${this.#renderToolbar()}
|
||||
<umb-dropzone id="dropzone" @change=${() => this.#loadMediaFolder()} .parentUnique=${this._currentNode}></umb-dropzone>
|
||||
<umb-dropzone id="dropzone" @change=${() => this.#loadMediaFolder()} .parentUnique=${this._currentMediaEntity.unique}></umb-dropzone>
|
||||
${
|
||||
!this._mediaFilteredList.length
|
||||
? html`<div class="container"><p>${this.localize.term('content_listViewNoItems')}</p></div>`
|
||||
@@ -146,7 +163,7 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
|
||||
#renderToolbar() {
|
||||
return html`<div id="toolbar">
|
||||
<umb-media-picker-create-item .node=${this._currentNode}></umb-media-picker-create-item>
|
||||
<umb-media-picker-create-item .node=${this._currentMediaEntity.unique}></umb-media-picker-create-item>
|
||||
<div id="search">
|
||||
<uui-input
|
||||
label=${this.localize.term('general_search')}
|
||||
@@ -182,7 +199,7 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement<UmbMediaPick
|
||||
#renderPath() {
|
||||
return html`<umb-media-picker-folder-path
|
||||
slot="footer-info"
|
||||
.currentPath=${this._currentNode}
|
||||
.currentPath=${this._currentMediaEntity.unique}
|
||||
@change=${this.#onPathChange}></umb-media-picker-folder-path>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import type { UmbMediaEntityType } from '../../entity.js';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
export interface UmbMediaCardItemModel {
|
||||
name: string;
|
||||
unique: string;
|
||||
entityType: UmbMediaEntityType;
|
||||
url?: string;
|
||||
extension?: string;
|
||||
}
|
||||
|
||||
export interface UmbMediaPathModel {
|
||||
export interface UmbMediaPathModel extends UmbEntityModel {
|
||||
name: string;
|
||||
unique: string | null;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { UmbMediaTreeItemModel } from '../types.js';
|
||||
import type { UmbMediaTreeItemModel, UmbMediaTreeRootModel } from '../types.js';
|
||||
import { UmbDefaultTreeItemContext } from '@umbraco-cms/backoffice/tree';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin';
|
||||
|
||||
export class UmbMediaTreeItemContext extends UmbDefaultTreeItemContext<UmbMediaTreeItemModel> {
|
||||
export class UmbMediaTreeItemContext extends UmbDefaultTreeItemContext<UmbMediaTreeItemModel, UmbMediaTreeRootModel> {
|
||||
#isTrashedContext = new UmbIsTrashedEntityContext(this);
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
|
||||
Reference in New Issue
Block a user