Merge branch 'main' into feature/global-search
This commit is contained in:
@@ -13,8 +13,11 @@ import type { Guard, UmbRoute } from '@umbraco-cms/backoffice/router';
|
||||
import { pathWithoutBasePath } from '@umbraco-cms/backoffice/router';
|
||||
import { OpenAPI, RuntimeLevelModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbContextDebugController } from '@umbraco-cms/backoffice/debug';
|
||||
import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbBundleExtensionInitializer, UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
|
||||
import {
|
||||
UmbAppEntryPointExtensionInitializer,
|
||||
umbExtensionsRegistry,
|
||||
} from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@customElement('umb-app')
|
||||
export class UmbAppElement extends UmbLitElement {
|
||||
@@ -79,6 +82,9 @@ export class UmbAppElement extends UmbLitElement {
|
||||
|
||||
OpenAPI.BASE = window.location.origin;
|
||||
|
||||
new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
|
||||
new UmbAppEntryPointExtensionInitializer(this, umbExtensionsRegistry);
|
||||
|
||||
new UmbIconRegistry().attach(this);
|
||||
new UUIIconRegistryEssential().attach(this);
|
||||
|
||||
@@ -99,7 +105,7 @@ export class UmbAppElement extends UmbLitElement {
|
||||
// Register Core extensions (this is specifically done here because we need these extensions to be registered before the application is initialized)
|
||||
onInit(this, umbExtensionsRegistry);
|
||||
|
||||
// Register public extensions
|
||||
// Register public extensions (login extensions)
|
||||
await new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerPublicExtensions();
|
||||
|
||||
// Try to initialise the auth flow and get the runtime status
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UmbBackofficeContext } from './backoffice.context.js';
|
||||
import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import {
|
||||
UmbBundleExtensionInitializer,
|
||||
UmbBackofficeEntryPointExtensionInitializer,
|
||||
UmbEntryPointExtensionInitializer,
|
||||
UmbServerExtensionRegistrator,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
umbExtensionsRegistry,
|
||||
} from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
|
||||
import './components/index.js';
|
||||
@@ -52,7 +52,7 @@ export class UmbBackofficeElement extends UmbLitElement {
|
||||
|
||||
new UmbBackofficeContext(this);
|
||||
|
||||
new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
|
||||
new UmbBackofficeEntryPointExtensionInitializer(this, umbExtensionsRegistry);
|
||||
new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry);
|
||||
|
||||
new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerPrivateExtensions();
|
||||
|
||||
@@ -1948,8 +1948,8 @@ export default {
|
||||
stateInactive: 'Inactive',
|
||||
sortNameAscending: 'Name (A-Z)',
|
||||
sortNameDescending: 'Name (Z-A)',
|
||||
sortCreateDateAscending: 'Newest',
|
||||
sortCreateDateDescending: 'Oldest',
|
||||
sortCreateDateDescending: 'Newest',
|
||||
sortCreateDateAscending: 'Oldest',
|
||||
sortLastLoginDateDescending: 'Last login',
|
||||
noUserGroupsAdded: 'No user groups have been added',
|
||||
'2faDisableText':
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { UmbEntryPointModule } from '../models/entry-point.interface.js';
|
||||
|
||||
/**
|
||||
* Validate if an ESModule has exported a function called `onUnload`
|
||||
*/
|
||||
export function hasOnUnloadExport(obj: unknown): obj is Pick<UmbEntryPointModule, 'onUnload'> {
|
||||
return obj !== null && typeof obj === 'object' && 'onUnload' in obj;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ export * from './create-extension-api.function.js';
|
||||
export * from './create-extension-element-with-api.function.js';
|
||||
export * from './create-extension-element.function.js';
|
||||
export * from './has-init-export.function.js';
|
||||
export * from './has-on-unload-export.function.js';
|
||||
export * from './load-manifest-api.function.js';
|
||||
export * from './load-manifest-element.function.js';
|
||||
export * from './load-manifest-plain-css.function.js';
|
||||
|
||||
@@ -2,7 +2,7 @@ export * from './condition/index.js';
|
||||
export * from './controller/index.js';
|
||||
export * from './functions/index.js';
|
||||
export * from './initializers/index.js';
|
||||
export type * from './models/index.js';
|
||||
export * from './registry/extension.registry.js';
|
||||
export * from './type-guards/index.js';
|
||||
export type * from './models/index.js';
|
||||
export type * from './types/index.js';
|
||||
|
||||
@@ -1,35 +1,18 @@
|
||||
import type { ManifestBase, ManifestBundle } from '../types/index.js';
|
||||
import type { UmbExtensionRegistry } from '../registry/extension.registry.js';
|
||||
import { loadManifestPlainJs } from '../functions/load-manifest-plain-js.function.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbExtensionInitializerBase } from './extension-initializer-base.js';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
|
||||
export class UmbBundleExtensionInitializer extends UmbControllerBase {
|
||||
#extensionRegistry;
|
||||
#bundleMap = new Map();
|
||||
|
||||
constructor(host: UmbControllerHost, extensionRegistry: UmbExtensionRegistry<ManifestBundle>) {
|
||||
super(host);
|
||||
this.#extensionRegistry = extensionRegistry;
|
||||
this.observe(extensionRegistry.byType('bundle'), (bundles) => {
|
||||
// Unregister removed bundles:
|
||||
this.#bundleMap.forEach((existingBundle) => {
|
||||
if (!bundles.find((b) => b.alias === existingBundle.alias)) {
|
||||
this.unregisterBundle(existingBundle);
|
||||
this.#bundleMap.delete(existingBundle.alias);
|
||||
}
|
||||
});
|
||||
|
||||
// Register new bundles:
|
||||
bundles.forEach((bundle) => {
|
||||
if (this.#bundleMap.has(bundle.alias)) return;
|
||||
this.#bundleMap.set(bundle.alias, bundle);
|
||||
this.instantiateBundle(bundle);
|
||||
});
|
||||
});
|
||||
/**
|
||||
* Extension initializer for the `bundle` extension type
|
||||
*/
|
||||
export class UmbBundleExtensionInitializer extends UmbExtensionInitializerBase<'bundle', ManifestBundle> {
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestBundle>) {
|
||||
super(host, extensionRegistry, 'bundle');
|
||||
}
|
||||
|
||||
async instantiateBundle(manifest: ManifestBundle) {
|
||||
async instantiateExtension(manifest: ManifestBundle): Promise<void> {
|
||||
if (manifest.js) {
|
||||
const js = await loadManifestPlainJs(manifest.js);
|
||||
|
||||
@@ -38,16 +21,16 @@ export class UmbBundleExtensionInitializer extends UmbControllerBase {
|
||||
const value = js[key];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
this.#extensionRegistry.registerMany(value);
|
||||
this.extensionRegistry.registerMany(value);
|
||||
} else if (typeof value === 'object') {
|
||||
this.#extensionRegistry.register(value);
|
||||
this.extensionRegistry.register(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async unregisterBundle(manifest: ManifestBundle) {
|
||||
async unloadExtension(manifest: ManifestBundle): Promise<void> {
|
||||
if (manifest.js) {
|
||||
const js = await loadManifestPlainJs(manifest.js);
|
||||
|
||||
@@ -56,9 +39,9 @@ export class UmbBundleExtensionInitializer extends UmbControllerBase {
|
||||
const value = js[key];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
this.#extensionRegistry.unregisterMany(value.map((v) => v.alias));
|
||||
this.extensionRegistry.unregisterMany(value.map((v) => v.alias));
|
||||
} else if (typeof value === 'object') {
|
||||
this.#extensionRegistry.unregister((value as ManifestBase).alias);
|
||||
this.extensionRegistry.unregister((value as ManifestBase).alias);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import type { ManifestEntryPoint } from '../types/index.js';
|
||||
import type { UmbExtensionRegistry } from '../registry/extension.registry.js';
|
||||
import { hasInitExport, loadManifestPlainJs } from '../functions/index.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
|
||||
export class UmbEntryPointExtensionInitializer extends UmbControllerBase {
|
||||
#host;
|
||||
#extensionRegistry;
|
||||
#entryPointMap = new Map();
|
||||
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestEntryPoint>) {
|
||||
super(host);
|
||||
this.#host = host;
|
||||
this.#extensionRegistry = extensionRegistry;
|
||||
this.observe(extensionRegistry.byType('entryPoint'), (entryPoints) => {
|
||||
entryPoints.forEach((entryPoint) => {
|
||||
if (this.#entryPointMap.has(entryPoint.alias)) return;
|
||||
this.#entryPointMap.set(entryPoint.alias, entryPoint);
|
||||
// TODO: Should we unInit a entry point if is removed?
|
||||
this.instantiateEntryPoint(entryPoint);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async instantiateEntryPoint(manifest: ManifestEntryPoint) {
|
||||
if (manifest.js) {
|
||||
const js = await loadManifestPlainJs(manifest.js);
|
||||
// If the extension has an onInit export, be sure to run that or else let the module handle itself
|
||||
if (hasInitExport(js)) {
|
||||
js.onInit(this.#host, this.#extensionRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { ManifestBase } from '../types/index.js';
|
||||
import type { UmbExtensionRegistry } from '../registry/extension.registry.js';
|
||||
import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
/**
|
||||
* Base class for extension initializers, which are responsible for loading and unloading extensions.
|
||||
*/
|
||||
export abstract class UmbExtensionInitializerBase<
|
||||
Key extends string,
|
||||
T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>,
|
||||
> extends UmbControllerBase {
|
||||
protected host;
|
||||
protected extensionRegistry;
|
||||
#extensionMap = new Map();
|
||||
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<T>, manifestType: Key) {
|
||||
super(host);
|
||||
this.host = host;
|
||||
this.extensionRegistry = extensionRegistry;
|
||||
this.observe(extensionRegistry.byType<Key, T>(manifestType), (extensions) => {
|
||||
this.#extensionMap.forEach((existingExt) => {
|
||||
if (!extensions.find((b) => b.alias === existingExt.alias)) {
|
||||
this.unloadExtension(existingExt);
|
||||
this.#extensionMap.delete(existingExt.alias);
|
||||
}
|
||||
});
|
||||
|
||||
extensions.forEach((extension) => {
|
||||
if (this.#extensionMap.has(extension.alias)) return;
|
||||
this.#extensionMap.set(extension.alias, extension);
|
||||
this.instantiateExtension(extension);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any logic required to instantiate the extension.
|
||||
*/
|
||||
abstract instantiateExtension(manifest: T): Promise<void> | void;
|
||||
|
||||
/**
|
||||
* Perform any logic required to unload the extension.
|
||||
*/
|
||||
abstract unloadExtension(manifest: T): Promise<void> | void;
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './bundle-extension-initializer.js';
|
||||
export * from './entry-point-extension-initializer.js';
|
||||
export * from './extension-initializer-base.js';
|
||||
|
||||
@@ -4,9 +4,22 @@ import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
|
||||
export type UmbEntryPointOnInit = (host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestBase>) => void;
|
||||
|
||||
export type UmbEntryPointOnUnload = (host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestBase>) => void;
|
||||
|
||||
/**
|
||||
* Interface containing supported life-cycle functions for ESModule entry points
|
||||
*/
|
||||
export interface UmbEntryPointModule {
|
||||
/**
|
||||
* Function that will be called when the host element is initialized and/or the extension is loaded for the first time.
|
||||
* @optional
|
||||
*/
|
||||
onInit: UmbEntryPointOnInit;
|
||||
|
||||
/**
|
||||
* Function that will be called when the extension is unregistered.
|
||||
* @remark This does not mean the host element is destroyed, only that the extension is no longer available. You should listen to the host element's `destroy` event if you need to clean up after the host element.
|
||||
* @optional
|
||||
*/
|
||||
onUnload: UmbEntryPointOnUnload;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,5 @@ export * from './condition.types.js';
|
||||
export * from './manifest-base.interface.js';
|
||||
export * from './manifest-bundle.interface.js';
|
||||
export * from './manifest-condition.interface.js';
|
||||
export * from './manifest-entrypoint.interface.js';
|
||||
export * from './manifest-kind.interface.js';
|
||||
export * from './utils.js';
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { UmbEntryPointModule } from '../models/index.js';
|
||||
import type { ManifestPlainJs } from './base.types.js';
|
||||
|
||||
/**
|
||||
* This type of extension gives full control and will simply load the specified JS file
|
||||
* You could have custom logic to decide which extensions to load/register by using extensionRegistry
|
||||
*/
|
||||
export interface ManifestEntryPoint extends ManifestPlainJs<UmbEntryPointModule> {
|
||||
type: 'entryPoint';
|
||||
}
|
||||
@@ -56,7 +56,7 @@ export const manifestDevelopmentHandlers = [
|
||||
name: 'Package with an entry point',
|
||||
extensions: [
|
||||
{
|
||||
type: 'entryPoint',
|
||||
type: 'backofficeEntryPoint',
|
||||
name: 'My Custom Entry Point',
|
||||
alias: 'My.Entrypoint.Custom',
|
||||
js: '/App_Plugins/custom-entrypoint.js',
|
||||
|
||||
@@ -110,11 +110,6 @@ export class UmbCollectionViewBundleElement extends UmbLitElement {
|
||||
|
||||
#onClick(view: UmbCollectionViewLayout) {
|
||||
this.#collectionContext?.setLastSelectedView(this._entityUnique, view.alias);
|
||||
|
||||
// TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
this._popover?.hidePopover();
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -123,7 +118,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement {
|
||||
|
||||
return html`
|
||||
<uui-button compact popovertarget="collection-view-bundle-popover" label="status">
|
||||
${this.#renderItemDisplay(this._currentView)}
|
||||
<umb-icon name=${this._currentView.icon}></umb-icon>
|
||||
</uui-button>
|
||||
<uui-popover-container id="collection-view-bundle-popover" placement="bottom-end">
|
||||
<umb-popover-layout>
|
||||
@@ -141,31 +136,27 @@ export class UmbCollectionViewBundleElement extends UmbLitElement {
|
||||
|
||||
#renderItem(view: UmbCollectionViewLayout) {
|
||||
return html`
|
||||
<uui-button compact href="${this._collectionRootPathName}/${view.pathName}" @click=${() => this.#onClick(view)}>
|
||||
${this.#renderItemDisplay(view)}
|
||||
<span class="label">${view.label}</span>
|
||||
</uui-button>
|
||||
<uui-menu-item
|
||||
label=${view.label}
|
||||
href="${this._collectionRootPathName}/${view.pathName}"
|
||||
@click-label=${() => this.#onClick(view)}
|
||||
?active=${view.alias === this._currentView?.alias}>
|
||||
<umb-icon slot="icon" name=${view.icon}></umb-icon>
|
||||
</uui-menu-item>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItemDisplay(view: UmbCollectionViewLayout) {
|
||||
return html`<umb-icon name=${view.icon}></umb-icon>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
--uui-button-content-align: left;
|
||||
}
|
||||
.label {
|
||||
margin-left: var(--uui-size-space-1);
|
||||
}
|
||||
|
||||
.filter-dropdown {
|
||||
display: flex;
|
||||
gap: var(--uui-size-space-1);
|
||||
flex-direction: column;
|
||||
padding: var(--uui-size-space-3);
|
||||
}
|
||||
|
||||
umb-icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ export class UmbDefaultCollectionContext<
|
||||
public readonly view = new UmbCollectionViewManager(this);
|
||||
|
||||
#defaultViewAlias: string;
|
||||
#defaultFilter: Partial<FilterModelType>;
|
||||
|
||||
#initResolver?: () => void;
|
||||
#initialized = false;
|
||||
@@ -59,10 +60,11 @@ export class UmbDefaultCollectionContext<
|
||||
this.#initialized ? resolve() : (this.#initResolver = resolve);
|
||||
});
|
||||
|
||||
constructor(host: UmbControllerHost, defaultViewAlias: string) {
|
||||
constructor(host: UmbControllerHost, defaultViewAlias: string, defaultFilter: Partial<FilterModelType> = {}) {
|
||||
super(host, UMB_DEFAULT_COLLECTION_CONTEXT);
|
||||
|
||||
this.#defaultViewAlias = defaultViewAlias;
|
||||
this.#defaultFilter = defaultFilter;
|
||||
|
||||
this.pagination.addEventListener(UmbChangeEvent.TYPE, this.#onPageChange);
|
||||
}
|
||||
@@ -79,6 +81,7 @@ export class UmbDefaultCollectionContext<
|
||||
}
|
||||
|
||||
this.#filter.setValue({
|
||||
...this.#defaultFilter,
|
||||
...this.#config,
|
||||
...this.#filter.getValue(),
|
||||
skip: 0,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export * from './conditions/index.js';
|
||||
export type * from './interfaces/index.js';
|
||||
export type * from './models/index.js';
|
||||
export * from './initializers/index.js';
|
||||
export * from './registry.js';
|
||||
export * from './utils/index.js';
|
||||
export type * from './interfaces/index.js';
|
||||
export type * from './models/index.js';
|
||||
|
||||
export { UmbExtensionElementAndApiSlotElementBase } from './extension-element-and-api-slot-element-base.js';
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { ManifestAppEntryPoint } from '../models/app-entry-point.model.js';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
import {
|
||||
type UmbEntryPointModule,
|
||||
UmbExtensionInitializerBase,
|
||||
type UmbExtensionRegistry,
|
||||
loadManifestPlainJs,
|
||||
hasInitExport,
|
||||
hasOnUnloadExport,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Extension initializer for the `appEntryPoint` extension type
|
||||
*/
|
||||
export class UmbAppEntryPointExtensionInitializer extends UmbExtensionInitializerBase<
|
||||
'appEntryPoint',
|
||||
ManifestAppEntryPoint
|
||||
> {
|
||||
#instanceMap = new Map<string, UmbEntryPointModule>();
|
||||
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestAppEntryPoint>) {
|
||||
super(host, extensionRegistry, 'appEntryPoint' satisfies ManifestAppEntryPoint['type']);
|
||||
}
|
||||
|
||||
async instantiateExtension(manifest: ManifestAppEntryPoint) {
|
||||
if (manifest.js) {
|
||||
const moduleInstance = await loadManifestPlainJs(manifest.js);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
this.#instanceMap.set(manifest.alias, moduleInstance);
|
||||
|
||||
// If the extension has known exports, be sure to run those
|
||||
if (hasInitExport(moduleInstance)) {
|
||||
moduleInstance.onInit(this.host, this.extensionRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async unloadExtension(manifest: ManifestAppEntryPoint): Promise<void> {
|
||||
const moduleInstance = this.#instanceMap.get(manifest.alias);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
if (hasOnUnloadExport(moduleInstance)) {
|
||||
moduleInstance.onUnload(this.host, this.extensionRegistry);
|
||||
}
|
||||
|
||||
this.#instanceMap.delete(manifest.alias);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { ManifestBackofficeEntryPoint } from '../models/backoffice-entry-point.model.js';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
import {
|
||||
type UmbEntryPointModule,
|
||||
UmbExtensionInitializerBase,
|
||||
type UmbExtensionRegistry,
|
||||
loadManifestPlainJs,
|
||||
hasInitExport,
|
||||
hasOnUnloadExport,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Extension initializer for the `backofficeEntryPoint` extension type
|
||||
*/
|
||||
export class UmbBackofficeEntryPointExtensionInitializer extends UmbExtensionInitializerBase<
|
||||
'backofficeEntryPoint',
|
||||
ManifestBackofficeEntryPoint
|
||||
> {
|
||||
#instanceMap = new Map<string, UmbEntryPointModule>();
|
||||
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestBackofficeEntryPoint>) {
|
||||
super(host, extensionRegistry, 'backofficeEntryPoint' satisfies ManifestBackofficeEntryPoint['type']);
|
||||
}
|
||||
|
||||
async instantiateExtension(manifest: ManifestBackofficeEntryPoint) {
|
||||
if (manifest.js) {
|
||||
const moduleInstance = await loadManifestPlainJs(manifest.js);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
this.#instanceMap.set(manifest.alias, moduleInstance);
|
||||
|
||||
// If the extension has known exports, be sure to run those
|
||||
if (hasInitExport(moduleInstance)) {
|
||||
moduleInstance.onInit(this.host, this.extensionRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async unloadExtension(manifest: ManifestBackofficeEntryPoint): Promise<void> {
|
||||
const moduleInstance = this.#instanceMap.get(manifest.alias);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
if (hasOnUnloadExport(moduleInstance)) {
|
||||
moduleInstance.onUnload(this.host, this.extensionRegistry);
|
||||
}
|
||||
|
||||
this.#instanceMap.delete(manifest.alias);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { ManifestEntryPoint } from '../models/entry-point.model.js';
|
||||
import type { UmbElement } from '@umbraco-cms/backoffice/element-api';
|
||||
import {
|
||||
type UmbEntryPointModule,
|
||||
UmbExtensionInitializerBase,
|
||||
type UmbExtensionRegistry,
|
||||
loadManifestPlainJs,
|
||||
hasInitExport,
|
||||
hasOnUnloadExport,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Extension initializer for the `entryPoint` extension type
|
||||
*/
|
||||
export class UmbEntryPointExtensionInitializer extends UmbExtensionInitializerBase<'entryPoint', ManifestEntryPoint> {
|
||||
#instanceMap = new Map<string, UmbEntryPointModule>();
|
||||
|
||||
constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestEntryPoint>) {
|
||||
super(host, extensionRegistry, 'entryPoint' satisfies ManifestEntryPoint['type']);
|
||||
}
|
||||
|
||||
async instantiateExtension(manifest: ManifestEntryPoint) {
|
||||
if (manifest.js) {
|
||||
const moduleInstance = await loadManifestPlainJs(manifest.js);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
this.#instanceMap.set(manifest.alias, moduleInstance);
|
||||
|
||||
// If the extension has known exports, be sure to run those
|
||||
if (hasInitExport(moduleInstance)) {
|
||||
moduleInstance.onInit(this.host, this.extensionRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async unloadExtension(manifest: ManifestEntryPoint): Promise<void> {
|
||||
const moduleInstance = this.#instanceMap.get(manifest.alias);
|
||||
|
||||
if (!moduleInstance) return;
|
||||
|
||||
if (hasOnUnloadExport(moduleInstance)) {
|
||||
moduleInstance.onUnload(this.host, this.extensionRegistry);
|
||||
}
|
||||
|
||||
this.#instanceMap.delete(manifest.alias);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './app-entry-point-extension-initializer.js';
|
||||
export * from './backoffice-entry-point-extension-initializer.js';
|
||||
export * from './entry-point-extension-initializer.js';
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ManifestPlainJs, UmbEntryPointModule } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Manifest for an `appEntryPoint`, which is loaded up front when the app starts.
|
||||
*
|
||||
* This type of extension gives full control and will simply load the specified JS file.
|
||||
* You could have custom logic to decide which extensions to load/register by using extensionRegistry.
|
||||
* This is useful for extensions that need to be loaded up front, like an `authProvider`.
|
||||
*/
|
||||
export interface ManifestAppEntryPoint extends ManifestPlainJs<UmbEntryPointModule> {
|
||||
type: 'appEntryPoint';
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { ManifestPlainJs, UmbEntryPointModule } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Manifest for an `backofficeEntryPoint`, which is loaded after the Backoffice has been loaded and authentication has been done.
|
||||
*
|
||||
* This type of extension gives full control and will simply load the specified JS file.
|
||||
* You could have custom logic to decide which extensions to load/register by using extensionRegistry.
|
||||
*/
|
||||
export interface ManifestBackofficeEntryPoint extends ManifestPlainJs<UmbEntryPointModule> {
|
||||
type: 'backofficeEntryPoint';
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { ManifestPlainJs, UmbEntryPointModule } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Manifest for an `entryPoint`, which is loaded after the Backoffice has been loaded and authentication has been done.
|
||||
*
|
||||
* This type of extension gives full control and will simply load the specified JS file.
|
||||
* You could have custom logic to decide which extensions to load/register by using extensionRegistry.
|
||||
*
|
||||
* @deprecated Use `ManifestBackofficeEntryPoint` instead.
|
||||
*/
|
||||
export interface ManifestEntryPoint extends ManifestPlainJs<UmbEntryPointModule> {
|
||||
type: 'entryPoint';
|
||||
}
|
||||
@@ -63,14 +63,13 @@ import type { ManifestCollectionAction } from './collection-action.model.js';
|
||||
import type { ManifestMfaLoginProvider } from './mfa-login-provider.model.js';
|
||||
import type { ManifestSearchProvider } from './search-provider.model.js';
|
||||
import type { ManifestSearchResultItem } from './search-result-item.model.js';
|
||||
import type {
|
||||
ManifestBase,
|
||||
ManifestBundle,
|
||||
ManifestCondition,
|
||||
ManifestEntryPoint,
|
||||
} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestAppEntryPoint } from './app-entry-point.model.js';
|
||||
import type { ManifestBackofficeEntryPoint } from './backoffice-entry-point.model.js';
|
||||
import type { ManifestEntryPoint } from './entry-point.model.js';
|
||||
import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export type * from './auth-provider.model.js';
|
||||
export type * from './backoffice-entry-point.model.js';
|
||||
export type * from './block-editor-custom-view.model.js';
|
||||
export type * from './collection-action.model.js';
|
||||
export type * from './collection-view.model.js';
|
||||
@@ -82,6 +81,7 @@ export type * from './dynamic-root.model.js';
|
||||
export type * from './entity-action.model.js';
|
||||
export type * from './entity-bulk-action.model.js';
|
||||
export type * from './entity-user-permission.model.js';
|
||||
export type * from './entry-point.model.js';
|
||||
export type * from './external-login-provider.model.js';
|
||||
export type * from './global-context.model.js';
|
||||
export type * from './header-app.model.js';
|
||||
@@ -113,6 +113,7 @@ export type * from './workspace-context.model.js';
|
||||
export type * from './workspace-footer-app.model.js';
|
||||
export type * from './workspace-view.model.js';
|
||||
export type * from './workspace.model.js';
|
||||
export type * from './app-entry-point.model.js';
|
||||
|
||||
export type ManifestEntityActions =
|
||||
| ManifestEntityAction
|
||||
@@ -143,7 +144,9 @@ export type ManifestWorkspaces = ManifestWorkspace | ManifestWorkspaceRoutableKi
|
||||
export type ManifestWorkspaceViews = ManifestWorkspaceView | ManifestWorkspaceViewContentTypeDesignEditorKind;
|
||||
|
||||
export type ManifestTypes =
|
||||
| ManifestAppEntryPoint
|
||||
| ManifestAuthProvider
|
||||
| ManifestBackofficeEntryPoint
|
||||
| ManifestBlockEditorCustomView
|
||||
| ManifestBundle<ManifestTypes>
|
||||
| ManifestCollection
|
||||
|
||||
@@ -17,7 +17,7 @@ export const manifest: ManifestPropertyEditorSchema = {
|
||||
{
|
||||
alias: 'max',
|
||||
label: 'Maximum',
|
||||
description: 'Enter the minimum amount of number to be entered',
|
||||
description: 'Enter the maximum amount of number to be entered',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUi.Decimal',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ export const manifest: ManifestPropertyEditorSchema = {
|
||||
{
|
||||
alias: 'max',
|
||||
label: 'Maximum',
|
||||
description: 'Enter the minimum amount of number to be entered',
|
||||
description: 'Enter the maximum amount of number to be entered',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUi.Number',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,66 +1,46 @@
|
||||
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
|
||||
import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models';
|
||||
import type { UmbInputMemberGroupElement } from '@umbraco-cms/backoffice/member-group';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-member-group-picker
|
||||
*/
|
||||
@customElement('umb-property-editor-ui-member-group-picker')
|
||||
export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement {
|
||||
// private _value: Array<string> = [];
|
||||
|
||||
// @property({ type: Array })
|
||||
// public set value(value: Array<string>) {
|
||||
// this._value = Array.isArray(value) ? value : value ? [value] : [];
|
||||
// }
|
||||
// public get value(): Array<string> {
|
||||
// return this._value;
|
||||
// }
|
||||
|
||||
@property({ type: String })
|
||||
public value: string = '';
|
||||
@property()
|
||||
public value?: string;
|
||||
|
||||
public set config(config: UmbPropertyEditorConfigCollection | undefined) {
|
||||
const validationLimit = config?.find((x) => x.alias === 'validationLimit');
|
||||
if (!config) return;
|
||||
|
||||
this._limitMin = (validationLimit?.value as any)?.min;
|
||||
this._limitMax = (validationLimit?.value as any)?.max;
|
||||
const minMax = config?.getValueByAlias<NumberRangeValueType>('validationLimit');
|
||||
this.min = minMax?.min ?? 0;
|
||||
this.max = minMax?.max ?? Infinity;
|
||||
}
|
||||
|
||||
@state()
|
||||
_items: Array<string> = [];
|
||||
min = 0;
|
||||
|
||||
@state()
|
||||
private _limitMin?: number;
|
||||
@state()
|
||||
private _limitMax?: number;
|
||||
max = Infinity;
|
||||
|
||||
protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
super.updated(_changedProperties);
|
||||
if (_changedProperties.has('value')) {
|
||||
this._items = this.value ? this.value.split(',') : [];
|
||||
}
|
||||
}
|
||||
|
||||
private _onChange(event: CustomEvent) {
|
||||
//TODO: This is a hack, something changed so now we need to convert the array to a comma separated string to make it work with the server.
|
||||
const toCommaSeparatedString = (event.target as UmbInputMemberGroupElement).selection.join(',');
|
||||
// this.value = (event.target as UmbInputMemberGroupElement).selection;
|
||||
this.value = toCommaSeparatedString;
|
||||
this.dispatchEvent(new CustomEvent('property-value-change'));
|
||||
#onChange(event: CustomEvent & { target: UmbInputMemberGroupElement }) {
|
||||
this.value = event.target.value;
|
||||
this.dispatchEvent(new UmbPropertyValueChangeEvent());
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<umb-input-member-group
|
||||
@change=${this._onChange}
|
||||
.selection=${this._items}
|
||||
.min=${this._limitMin ?? 0}
|
||||
.max=${this._limitMax ?? Infinity}>
|
||||
</umb-input-member-group>
|
||||
.min=${this.min}
|
||||
.max=${this.max}
|
||||
.value=${this.value ?? ''}
|
||||
?showOpenButton=${true}
|
||||
@change=${this.#onChange}></umb-input-member-group>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export type UmbDirectionType = 'Ascending' | 'Descending';
|
||||
|
||||
export const UmbDirection = Object.freeze({
|
||||
ASCENDING: 'Ascending',
|
||||
DESCENDING: 'Descending',
|
||||
});
|
||||
@@ -1,3 +1,6 @@
|
||||
export * from './debounce/debounce.function.js';
|
||||
export * from './direction/index.js';
|
||||
export * from './download/blob-download.function.js';
|
||||
export * from './get-processed-image-url.function.js';
|
||||
export * from './math/math.js';
|
||||
export * from './pagination-manager/pagination.manager.js';
|
||||
@@ -7,11 +10,9 @@ export * from './path/path-encode.function.js';
|
||||
export * from './path/path-folder-name.function.js';
|
||||
export * from './path/umbraco-path.function.js';
|
||||
export * from './selection-manager/selection.manager.js';
|
||||
export * from './string/from-camel-case.function.js';
|
||||
export * from './string/generate-umbraco-alias.function.js';
|
||||
export * from './string/increment-string.function.js';
|
||||
export * from './string/split-string-to-array.js';
|
||||
export * from './type/diff.type.js';
|
||||
export * from './string/to-camel-case/to-camel-case.function.js';
|
||||
export * from './string/from-camel-case.function.js';
|
||||
export * from './debounce/debounce.function.js';
|
||||
export * from './download/blob-download.function.js';
|
||||
export * from './type/diff.type.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbDataTypeDetailModel } from '../../types.js';
|
||||
import { UmbDataTypeServerDataSource } from './data-type-detail.server.data-source.js';
|
||||
import type { UmbDataTypeDetailStore } from './data-type-detail.store.js';
|
||||
@@ -24,3 +25,5 @@ export class UmbDataTypeDetailRepository extends UmbDetailRepositoryBase<UmbData
|
||||
return this.#detailStore!.withPropertyEditorUiAlias(propertyEditorUiAlias);
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDataTypeDetailRepository as api };
|
||||
|
||||
@@ -25,3 +25,5 @@ export class UmbDataTypeDetailStore extends UmbDetailStoreBase<UmbDataTypeDetail
|
||||
}
|
||||
|
||||
export const UMB_DATA_TYPE_DETAIL_STORE_CONTEXT = new UmbContextToken<UmbDataTypeDetailStore>('UmbDataTypeDetailStore');
|
||||
|
||||
export { UmbDataTypeDetailStore as api };
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { UmbDataTypeDetailRepository } from './data-type-detail.repository.js';
|
||||
import { UmbDataTypeDetailStore } from './data-type-detail.store.js';
|
||||
import type { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Detail';
|
||||
@@ -8,7 +6,7 @@ const repository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Detail Repository',
|
||||
api: UmbDataTypeDetailRepository,
|
||||
api: () => import('./data-type-detail.repository.js'),
|
||||
};
|
||||
|
||||
export const UMB_DATA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DataType.Detail';
|
||||
@@ -17,7 +15,7 @@ const store: ManifestStore = {
|
||||
type: 'store',
|
||||
alias: UMB_DATA_TYPE_DETAIL_STORE_ALIAS,
|
||||
name: 'Data Type Detail Store',
|
||||
api: UmbDataTypeDetailStore,
|
||||
api: () => import('./data-type-detail.store.js'),
|
||||
};
|
||||
|
||||
export const manifests = [repository, store];
|
||||
|
||||
@@ -9,3 +9,5 @@ export class UmbDataTypeItemRepository extends UmbItemRepositoryBase<UmbDataType
|
||||
super(host, UmbDataTypeItemServerDataSource, UMB_DATA_TYPE_ITEM_STORE_CONTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDataTypeItemRepository as api };
|
||||
|
||||
@@ -22,3 +22,5 @@ export class UmbDataTypeItemStore extends UmbItemStoreBase<UmbDataTypeItemModel>
|
||||
}
|
||||
|
||||
export const UMB_DATA_TYPE_ITEM_STORE_CONTEXT = new UmbContextToken<UmbDataTypeItemStore>('UmbDataTypeItemStore');
|
||||
|
||||
export { UmbDataTypeItemStore as api };
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { UmbDataTypeItemStore } from './data-type-item.store.js';
|
||||
import { UmbDataTypeItemRepository } from './data-type-item.repository.js';
|
||||
import type { ManifestRepository, ManifestItemStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Item';
|
||||
@@ -9,14 +7,14 @@ const itemRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Item Repository',
|
||||
api: UmbDataTypeItemRepository,
|
||||
api: () => import('./data-type-item.repository.js'),
|
||||
};
|
||||
|
||||
const itemStore: ManifestItemStore = {
|
||||
type: 'itemStore',
|
||||
alias: UMB_DATA_TYPE_STORE_ALIAS,
|
||||
name: 'Data Type Item Store',
|
||||
api: UmbDataTypeItemStore,
|
||||
api: () => import('./data-type-item.store.js'),
|
||||
};
|
||||
|
||||
export const manifests = [itemRepository, itemStore];
|
||||
|
||||
@@ -29,3 +29,5 @@ export class UmbDataTypeTreeRepository
|
||||
return { data };
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDataTypeTreeRepository as api };
|
||||
|
||||
@@ -20,3 +20,5 @@ export class UmbDataTypeTreeStore extends UmbUniqueTreeStore {
|
||||
}
|
||||
|
||||
export const UMB_DATA_TYPE_TREE_STORE_CONTEXT = new UmbContextToken<UmbDataTypeTreeStore>('UmbDataTypeTreeStore');
|
||||
|
||||
export { UmbDataTypeTreeStore as api };
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { manifests as folderManifests } from './folder/manifests.js';
|
||||
import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js';
|
||||
import { UmbDataTypeTreeRepository } from './data-type-tree.repository.js';
|
||||
import { UmbDataTypeTreeStore } from './data-type-tree.store.js';
|
||||
import {
|
||||
UMB_DATA_TYPE_TREE_ALIAS,
|
||||
UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
@@ -18,14 +16,14 @@ const treeRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Tree Repository',
|
||||
api: UmbDataTypeTreeRepository,
|
||||
api: () => import('./data-type-tree.repository.js'),
|
||||
};
|
||||
|
||||
const treeStore: ManifestTreeStore = {
|
||||
type: 'treeStore',
|
||||
alias: UMB_DATA_TYPE_TREE_STORE_ALIAS,
|
||||
name: 'Data Type Tree Store',
|
||||
api: UmbDataTypeTreeStore,
|
||||
api: () => import('./data-type-tree.store.js'),
|
||||
};
|
||||
|
||||
const tree: ManifestTree = {
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
import type { UmbMemberGroupItemModel } from '../../repository/index.js';
|
||||
import { UmbMemberPickerContext } from './input-member-group.context.js';
|
||||
import { css, html, customElement, property, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { MemberItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
|
||||
import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
|
||||
import { type UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
|
||||
const SORTER_CONFIG: UmbSorterConfig<string> = {
|
||||
getUniqueOfElement: (element) => {
|
||||
return element.getAttribute('detail');
|
||||
},
|
||||
getUniqueOfModel: (modelEntry) => {
|
||||
return modelEntry;
|
||||
},
|
||||
identifier: 'Umb.SorterIdentifier.InputMemberGroup',
|
||||
itemSelector: 'uui-ref-node',
|
||||
containerSelector: 'uui-ref-list',
|
||||
};
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
import { UmbModalRouteRegistrationController, UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
|
||||
@customElement('umb-input-member-group')
|
||||
export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElement, '') {
|
||||
#sorter = new UmbSorterController(this, {
|
||||
...SORTER_CONFIG,
|
||||
#sorter = new UmbSorterController<string>(this, {
|
||||
getUniqueOfElement: (element) => {
|
||||
return element.id;
|
||||
},
|
||||
getUniqueOfModel: (modelEntry) => {
|
||||
return modelEntry;
|
||||
},
|
||||
identifier: 'Umb.SorterIdentifier.InputMemberGroup',
|
||||
itemSelector: 'uui-ref-node',
|
||||
containerSelector: 'uui-ref-list',
|
||||
onChange: ({ model }) => {
|
||||
this.selection = model;
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
},
|
||||
});
|
||||
|
||||
@@ -91,7 +88,6 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
|
||||
@property()
|
||||
public set value(idsString: string) {
|
||||
// Its with full purpose we don't call super.value, as thats being handled by the observation of the context selection.
|
||||
this.selection = splitStringToArray(idsString);
|
||||
}
|
||||
public get value(): string {
|
||||
@@ -112,7 +108,6 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// TODO: This would have to be more specific if used in a property editor context... [NL]
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath('member-group')
|
||||
.onSetup(() => {
|
||||
@@ -122,10 +117,8 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
this._editMemberGroupPath = routeBuilder({});
|
||||
});
|
||||
|
||||
this.observe(this.#pickerContext.selection, (selection) => (this.value = selection.join(',')));
|
||||
this.observe(this.#pickerContext.selectedItems, (selectedItems) => {
|
||||
this._items = selectedItems;
|
||||
});
|
||||
this.observe(this.#pickerContext.selection, (selection) => (this.value = selection.join(',')), '_observeSelection');
|
||||
this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems), '_observeItems');
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
@@ -144,16 +137,6 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
);
|
||||
}
|
||||
|
||||
protected _openPicker() {
|
||||
this.#pickerContext.openPicker({
|
||||
hideTreeRoot: true,
|
||||
});
|
||||
}
|
||||
|
||||
protected _requestRemoveItem(item: UmbMemberGroupItemModel) {
|
||||
this.#pickerContext.requestRemoveItem(item.unique!);
|
||||
}
|
||||
|
||||
protected getFormElement() {
|
||||
return undefined;
|
||||
}
|
||||
@@ -164,29 +147,31 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
});
|
||||
}
|
||||
|
||||
#requestRemoveItem(item: MemberItemResponseModel) {
|
||||
this.#pickerContext.requestRemoveItem(item.id!);
|
||||
#removeItem(item: UmbMemberGroupItemModel) {
|
||||
this.#pickerContext.requestRemoveItem(item.unique);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` ${this.#renderItems()} ${this.#renderAddButton()} `;
|
||||
return html`${this.#renderItems()} ${this.#renderAddButton()}`;
|
||||
}
|
||||
|
||||
#renderItems() {
|
||||
if (!this._items) return;
|
||||
return html`<uui-ref-list>
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.unique,
|
||||
(item) => this.#renderItem(item),
|
||||
)}
|
||||
</uui-ref-list>`;
|
||||
return html`
|
||||
<uui-ref-list>
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.unique,
|
||||
(item) => this.#renderItem(item),
|
||||
)}
|
||||
</uui-ref-list>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderAddButton() {
|
||||
if (this.max === 1 && this.selection.length >= this.max) return;
|
||||
return html`<uui-button
|
||||
id="add-button"
|
||||
id="btn-add"
|
||||
look="placeholder"
|
||||
@click=${this.#openPicker}
|
||||
label=${this.localize.term('general_choose')}></uui-button>`;
|
||||
@@ -194,17 +179,11 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
|
||||
#renderItem(item: UmbMemberGroupItemModel) {
|
||||
if (!item.unique) return;
|
||||
// TODO: get the correct variant name
|
||||
const name = item.name;
|
||||
return html`
|
||||
<uui-ref-node name=${ifDefined(item.name)} detail=${ifDefined(item.unique)}>
|
||||
<uui-ref-node name=${item.name} id=${item.unique}>
|
||||
<uui-action-bar slot="actions">
|
||||
${this.#renderOpenButton(item)}
|
||||
<uui-button
|
||||
@click=${() => this._requestRemoveItem(item)}
|
||||
label="${this.localize.term('general_remove')} ${name}">
|
||||
${this.localize.term('general_remove')}
|
||||
</uui-button>
|
||||
<uui-button @click=${() => this.#removeItem(item)} label=${this.localize.term('general_remove')}></uui-button>
|
||||
</uui-action-bar>
|
||||
</uui-ref-node>
|
||||
`;
|
||||
@@ -212,21 +191,18 @@ export class UmbInputMemberGroupElement extends UUIFormControlMixin(UmbLitElemen
|
||||
|
||||
#renderOpenButton(item: UmbMemberGroupItemModel) {
|
||||
if (!this.showOpenButton) return;
|
||||
// TODO: get the correct variant name
|
||||
const name = item.name;
|
||||
return html`
|
||||
<uui-button
|
||||
compact
|
||||
href="${this._editMemberGroupPath}edit/${item.unique}"
|
||||
label=${this.localize.term('general_edit') + ` ${name}`}>
|
||||
<uui-icon name="icon-edit"></uui-icon>
|
||||
label="${this.localize.term('general_open')} ${item.name}">
|
||||
${this.localize.term('general_open')}
|
||||
</uui-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
#add-button {
|
||||
#btn-add {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,12 @@ import type { UmbUserDetailModel } from '../../types.js';
|
||||
import { UMB_USER_ENTITY_TYPE } from '../../entity.js';
|
||||
import type { UmbUserCollectionFilterModel } from '../types.js';
|
||||
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection';
|
||||
import type { UserResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type {
|
||||
DirectionModel,
|
||||
UserOrderModel,
|
||||
UserResponseModel,
|
||||
UserStateModel,
|
||||
} from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UserService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
@@ -32,7 +37,18 @@ export class UmbUserCollectionServerDataSource implements UmbCollectionDataSourc
|
||||
* @memberof UmbUserCollectionServerDataSource
|
||||
*/
|
||||
async getCollection(filter: UmbUserCollectionFilterModel) {
|
||||
const { data, error } = await tryExecuteAndNotify(this.#host, UserService.getFilterUser(filter));
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this.#host,
|
||||
UserService.getFilterUser({
|
||||
filter: filter.filter,
|
||||
orderBy: filter.orderBy as unknown as UserOrderModel, // TODO: This is a temporary workaround to avoid a type error.
|
||||
orderDirection: filter.orderDirection as unknown as DirectionModel, // TODO: This is a temporary workaround to avoid a type error.
|
||||
skip: filter.skip,
|
||||
take: filter.take,
|
||||
userGroupIds: filter.userGroupIds,
|
||||
userStates: filter.userStates as unknown as Array<UserStateModel>, // TODO: This is a temporary workaround to avoid a type error.
|
||||
}),
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const { items, total } = data;
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import type { DirectionModel, UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbUserOrderByType, UmbUserStateFilterType } from './utils/index.js';
|
||||
import type { UmbDirectionType } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export interface UmbUserCollectionFilterModel {
|
||||
skip?: number;
|
||||
take?: number;
|
||||
orderBy?: UserOrderModel;
|
||||
orderDirection?: DirectionModel;
|
||||
orderBy?: UmbUserOrderByType;
|
||||
orderDirection?: UmbDirectionType;
|
||||
userGroupIds?: string[];
|
||||
userStates?: UserStateModel[];
|
||||
userStates?: UmbUserStateFilterType[];
|
||||
filter?: string;
|
||||
}
|
||||
|
||||
export interface UmbUserOrderByOption {
|
||||
unique: string;
|
||||
label: string;
|
||||
config: {
|
||||
orderBy: UmbUserOrderByType;
|
||||
orderDirection: UmbDirectionType;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import type { UmbUserCollectionContext } from './user-collection.context.js';
|
||||
import type {
|
||||
UUIBooleanInputEvent,
|
||||
UUICheckboxElement,
|
||||
UUIRadioGroupElement,
|
||||
UUIRadioGroupEvent,
|
||||
} from '@umbraco-cms/backoffice/external/uui';
|
||||
import type { UmbUserOrderByOption } from './types.js';
|
||||
import type { UmbUserStateFilterType } from './utils/index.js';
|
||||
import { UmbUserStateFilter } from './utils/index.js';
|
||||
import type { UUIBooleanInputEvent, UUICheckboxElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
|
||||
import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
|
||||
import type { UserOrderModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group';
|
||||
import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group';
|
||||
import { observeMultiple } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
@customElement('umb-user-collection-header')
|
||||
export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
@state()
|
||||
private _stateFilterOptions: Array<UserStateModel> = Object.values(UserStateModel);
|
||||
private _stateFilterOptions: Array<UmbUserStateFilterType> = Object.values(UmbUserStateFilter);
|
||||
|
||||
@state()
|
||||
private _stateFilterSelection: Array<UserStateModel> = [];
|
||||
|
||||
@state()
|
||||
private _orderBy?: UserOrderModel;
|
||||
private _stateFilterSelection: Array<UmbUserStateFilterType> = [];
|
||||
|
||||
@state()
|
||||
private _userGroups: Array<UmbUserGroupDetailModel> = [];
|
||||
@@ -31,7 +24,12 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
@state()
|
||||
private _userGroupFilterSelection: Array<UmbUserGroupDetailModel> = [];
|
||||
|
||||
#modalContext?: UmbModalManagerContext;
|
||||
@state()
|
||||
private _orderByOptions: Array<UmbUserOrderByOption> = [];
|
||||
|
||||
@state()
|
||||
_activeOrderByOption?: UmbUserOrderByOption;
|
||||
|
||||
#collectionContext?: UmbUserCollectionContext;
|
||||
#inputTimer?: NodeJS.Timeout;
|
||||
#inputTimerAmount = 500;
|
||||
@@ -43,9 +41,28 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
|
||||
this.consumeContext(UMB_DEFAULT_COLLECTION_CONTEXT, (instance) => {
|
||||
this.#collectionContext = instance as UmbUserCollectionContext;
|
||||
this.#observeOrderByOptions();
|
||||
});
|
||||
}
|
||||
|
||||
#observeOrderByOptions() {
|
||||
if (!this.#collectionContext) return;
|
||||
this.observe(
|
||||
observeMultiple([this.#collectionContext.orderByOptions, this.#collectionContext.activeOrderByOption]),
|
||||
([options, activeOption]) => {
|
||||
// the options are hardcoded in the context, so we can just compare the length
|
||||
if (this._orderByOptions.length !== options.length) {
|
||||
this._orderByOptions = options;
|
||||
}
|
||||
|
||||
if (activeOption && activeOption !== this._activeOrderByOption?.unique) {
|
||||
this._activeOrderByOption = this._orderByOptions.find((option) => option.unique === activeOption);
|
||||
}
|
||||
},
|
||||
'_umbObserveUserOrderByOptions',
|
||||
);
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
this.#requestUserGroups();
|
||||
}
|
||||
@@ -68,7 +85,7 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
#onStateFilterChange(event: UUIBooleanInputEvent) {
|
||||
event.stopPropagation();
|
||||
const target = event.currentTarget as UUICheckboxElement;
|
||||
const value = target.value as UserStateModel;
|
||||
const value = target.value as UmbUserStateFilterType;
|
||||
const isChecked = target.checked;
|
||||
|
||||
this._stateFilterSelection = isChecked
|
||||
@@ -78,34 +95,6 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
this.#collectionContext?.setStateFilter(this._stateFilterSelection);
|
||||
}
|
||||
|
||||
#onOrderByChange(event: UUIRadioGroupEvent) {
|
||||
event.stopPropagation();
|
||||
const target = event.currentTarget as UUIRadioGroupElement | null;
|
||||
|
||||
if (target) {
|
||||
this._orderBy = target.value as UserOrderModel;
|
||||
this.#collectionContext?.setOrderByFilter(this._orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<umb-collection-action-bundle></umb-collection-action-bundle>
|
||||
${this.#renderSearch()}
|
||||
<div>${this.#renderFilters()} ${this.#renderCollectionViews()}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderSearch() {
|
||||
return html`
|
||||
<uui-input
|
||||
@input=${this._updateSearch}
|
||||
label=${this.localize.term('visuallyHiddenTexts_userSearchLabel')}
|
||||
placeholder=${this.localize.term('visuallyHiddenTexts_userSearchLabel')}
|
||||
id="input-search"></uui-input>
|
||||
`;
|
||||
}
|
||||
|
||||
#onUserGroupFilterChange(event: UUIBooleanInputEvent) {
|
||||
const target = event.currentTarget as UUICheckboxElement;
|
||||
const item = this._userGroups.find((group) => group.unique === target.value);
|
||||
@@ -122,6 +111,10 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
this.#collectionContext?.setUserGroupFilter(uniques);
|
||||
}
|
||||
|
||||
#onOrderByChange(option: UmbUserOrderByOption) {
|
||||
this.#collectionContext?.setActiveOrderByOption(option.unique);
|
||||
}
|
||||
|
||||
#getUserGroupFilterLabel() {
|
||||
const length = this._userGroupFilterSelection.length;
|
||||
const max = 2;
|
||||
@@ -146,8 +139,26 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
.join(', ') + (length > max ? ' + ' + (length - max) : '');
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<umb-collection-action-bundle></umb-collection-action-bundle>
|
||||
${this.#renderSearch()}
|
||||
<div>${this.#renderFilters()} ${this.#renderCollectionViews()}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderSearch() {
|
||||
return html`
|
||||
<uui-input
|
||||
@input=${this._updateSearch}
|
||||
label=${this.localize.term('visuallyHiddenTexts_userSearchLabel')}
|
||||
placeholder=${this.localize.term('visuallyHiddenTexts_userSearchLabel')}
|
||||
id="input-search"></uui-input>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderFilters() {
|
||||
return html` ${this.#renderStatusFilter()} ${this.#renderUserGroupFilter()} `;
|
||||
return html` ${this.#renderStatusFilter()} ${this.#renderUserGroupFilter()} ${this.#renderOrderBy()} `;
|
||||
}
|
||||
|
||||
#renderStatusFilter() {
|
||||
@@ -196,6 +207,29 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
#renderOrderBy() {
|
||||
return html`
|
||||
<uui-button popovertarget="popover-order-by-filter" label="order by">
|
||||
<umb-localize key="general_orderBy"></umb-localize>:
|
||||
<b> ${this._activeOrderByOption ? this.localize.string(this._activeOrderByOption.label) : ''}</b>
|
||||
</uui-button>
|
||||
<uui-popover-container id="popover-order-by-filter" placement="bottom">
|
||||
<umb-popover-layout>
|
||||
<div class="filter-dropdown">
|
||||
${this._orderByOptions.map(
|
||||
(option) => html`
|
||||
<uui-menu-item
|
||||
label=${this.localize.string(option.label)}
|
||||
@click-label=${() => this.#onOrderByChange(option)}
|
||||
?active=${this._activeOrderByOption?.unique === option.unique}></uui-menu-item>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
</umb-popover-layout>
|
||||
</uui-popover-container>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderCollectionViews() {
|
||||
return html` <umb-collection-view-bundle></umb-collection-view-bundle> `;
|
||||
}
|
||||
@@ -224,6 +258,7 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
|
||||
display: flex;
|
||||
gap: var(--uui-size-space-3);
|
||||
flex-direction: column;
|
||||
padding: var(--uui-size-space-3);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -1,33 +1,105 @@
|
||||
import type { UmbUserDetailModel } from '../types.js';
|
||||
import { UMB_COLLECTION_VIEW_USER_GRID } from './views/index.js';
|
||||
import type { UmbUserCollectionFilterModel } from './types.js';
|
||||
import type { UmbUserCollectionFilterModel, UmbUserOrderByOption } from './types.js';
|
||||
import type { UmbUserOrderByType, UmbUserStateFilterType } from './utils/index.js';
|
||||
import { UmbUserOrderBy } from './utils/index.js';
|
||||
import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
|
||||
import type { UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbArrayState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import type { UmbDirectionType } from '@umbraco-cms/backoffice/utils';
|
||||
import { UmbDirection } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
const orderByOptions: Array<UmbUserOrderByOption> = [
|
||||
{
|
||||
unique: 'nameAscending',
|
||||
label: '#user_sortNameAscending',
|
||||
config: {
|
||||
orderBy: UmbUserOrderBy.NAME,
|
||||
orderDirection: UmbDirection.ASCENDING,
|
||||
},
|
||||
},
|
||||
{
|
||||
unique: 'nameDescending',
|
||||
label: '#user_sortNameDescending',
|
||||
config: {
|
||||
orderBy: UmbUserOrderBy.NAME,
|
||||
orderDirection: UmbDirection.DESCENDING,
|
||||
},
|
||||
},
|
||||
{
|
||||
unique: 'createDateDescending',
|
||||
label: '#user_sortCreateDateDescending',
|
||||
config: {
|
||||
orderBy: UmbUserOrderBy.CREATE_DATE,
|
||||
orderDirection: UmbDirection.DESCENDING,
|
||||
},
|
||||
},
|
||||
{
|
||||
unique: 'createDateAscending',
|
||||
label: '#user_sortCreateDateAscending',
|
||||
config: {
|
||||
orderBy: UmbUserOrderBy.CREATE_DATE,
|
||||
orderDirection: UmbDirection.ASCENDING,
|
||||
},
|
||||
},
|
||||
{
|
||||
unique: 'lastLoginDateDescending',
|
||||
label: '#user_sortLastLoginDateDescending',
|
||||
config: {
|
||||
orderBy: UmbUserOrderBy.LAST_LOGIN_DATE,
|
||||
orderDirection: UmbDirection.DESCENDING,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export class UmbUserCollectionContext extends UmbDefaultCollectionContext<
|
||||
UmbUserDetailModel,
|
||||
UmbUserCollectionFilterModel
|
||||
> {
|
||||
#orderByOptions = new UmbArrayState<UmbUserOrderByOption>([], (x) => x.label);
|
||||
orderByOptions = this.#orderByOptions.asObservable();
|
||||
|
||||
#activeOrderByOption = new UmbStringState<string | undefined>(undefined);
|
||||
activeOrderByOption = this.#activeOrderByOption.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, UMB_COLLECTION_VIEW_USER_GRID);
|
||||
const firstOption: UmbUserOrderByOption = orderByOptions[0];
|
||||
|
||||
super(host, UMB_COLLECTION_VIEW_USER_GRID, {
|
||||
orderBy: firstOption.config.orderBy,
|
||||
orderDirection: firstOption.config.orderDirection,
|
||||
});
|
||||
|
||||
this.#orderByOptions.setValue(orderByOptions);
|
||||
this.#activeOrderByOption.setValue(firstOption.unique);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active order by option for the collection and refreshes the collection.
|
||||
* @param {string} unique
|
||||
* @memberof UmbUserCollectionContext
|
||||
*/
|
||||
setActiveOrderByOption(unique: string) {
|
||||
const option = this.#orderByOptions.getValue().find((x) => x.unique === unique);
|
||||
this.#activeOrderByOption.setValue(unique);
|
||||
this.setFilter({ orderBy: option?.config.orderBy, orderDirection: option?.config.orderDirection });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state filter for the collection and refreshes the collection.
|
||||
* @param {Array<UserStateModel>} selection
|
||||
* @param {Array<UmbUserStateFilterModel>} selection
|
||||
* @memberof UmbUserCollectionContext
|
||||
*/
|
||||
setStateFilter(selection: Array<UserStateModel>) {
|
||||
setStateFilter(selection: Array<UmbUserStateFilterType>) {
|
||||
this.setFilter({ userStates: selection });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order by filter for the collection and refreshes the collection.
|
||||
* @param {UserOrderModel} orderBy
|
||||
* @param {UmbUserOrderByModel} orderBy
|
||||
* @memberof UmbUserCollectionContext
|
||||
*/
|
||||
setOrderByFilter(orderBy: UserOrderModel) {
|
||||
setOrderByFilter(orderBy: UmbUserOrderByType) {
|
||||
this.setFilter({ orderBy });
|
||||
}
|
||||
|
||||
@@ -39,6 +111,15 @@ export class UmbUserCollectionContext extends UmbDefaultCollectionContext<
|
||||
setUserGroupFilter(selection: Array<string>) {
|
||||
this.setFilter({ userGroupIds: selection });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order direction filter for the collection and refreshes the collection.
|
||||
* @param {any} orderDirection
|
||||
* @memberof UmbUserCollectionContext
|
||||
*/
|
||||
setOrderDirectionFilter(orderDirection: UmbDirectionType) {
|
||||
this.setFilter({ orderDirection });
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbUserCollectionContext;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export type UmbUserOrderByType = 'Name' | 'CreateDate' | 'LastLoginDate';
|
||||
|
||||
export const UmbUserOrderBy = Object.freeze({
|
||||
NAME: 'Name',
|
||||
CREATE_DATE: 'CreateDate',
|
||||
LAST_LOGIN_DATE: 'LastLoginDate',
|
||||
});
|
||||
|
||||
export type UmbUserStateFilterType = 'Active' | 'Disabled' | 'LockedOut' | 'Invited' | 'Inactive' | 'All';
|
||||
|
||||
export const UmbUserStateFilter = Object.freeze({
|
||||
ACTIVE: 'Active',
|
||||
DISABLED: 'Disabled',
|
||||
LOCKED_OUT: 'LockedOut',
|
||||
INVITED: 'Invited',
|
||||
INACTIVE: 'Inactive',
|
||||
ALL: 'All',
|
||||
});
|
||||
Reference in New Issue
Block a user