Merge branch 'main' into feature/tree-item-ancestors
This commit is contained in:
@@ -83,6 +83,7 @@
|
||||
"./user-permission": "./dist-cms/packages/user/user-permission/index.js",
|
||||
"./user": "./dist-cms/packages/user/user/index.js",
|
||||
"./utils": "./dist-cms/packages/core/utils/index.js",
|
||||
"./validation": "./dist-cms/packages/core/validation/index.js",
|
||||
"./variant": "./dist-cms/packages/core/variant/index.js",
|
||||
"./webhook": "./dist-cms/packages/webhook/index.js",
|
||||
"./workspace": "./dist-cms/packages/core/workspace/index.js",
|
||||
|
||||
@@ -55,7 +55,7 @@ export class UmbBackofficeElement extends UmbLitElement {
|
||||
new UmbBackofficeContext(this);
|
||||
new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
|
||||
new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry);
|
||||
new UmbServerExtensionRegistrator(this, umbExtensionsRegistry);
|
||||
new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerAllExtensions();
|
||||
|
||||
// So far local packages are this simple to registerer, so no need for a manager to do that:
|
||||
CORE_PACKAGES.forEach(async (packageImport) => {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { PackageResource, OpenAPI } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import {
|
||||
PackageResource,
|
||||
OpenAPI,
|
||||
type PackageManifestResponseModel,
|
||||
} from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import type { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
@@ -14,56 +18,66 @@ export class UmbServerExtensionRegistrator extends UmbControllerBase {
|
||||
constructor(host: UmbControllerHost, extensionRegistry: UmbBackofficeExtensionRegistry) {
|
||||
super(host, UmbServerExtensionRegistrator.name);
|
||||
this.#extensionRegistry = extensionRegistry;
|
||||
this.#loadServerPackages();
|
||||
}
|
||||
|
||||
async #loadServerPackages() {
|
||||
/* TODO: we need a new endpoint here, to remove the dependency on the package repository, to get the modules available for the backoffice scope
|
||||
/ we will need a similar endpoint for the login, installer etc at some point.
|
||||
We should expose more information about the packages when not authorized so the end point should only return a list of modules from the manifest with
|
||||
with the correct scope.
|
||||
|
||||
This code is copy pasted from the package repository. We probably don't need this is the package repository anymore.
|
||||
*/
|
||||
/**
|
||||
* Registers all extensions from the server.
|
||||
* This is used to register all extensions that are available to the user (including private extensions).
|
||||
* @remark Users must have the BACKOFFICE_ACCESS permission to access this method.
|
||||
*/
|
||||
public async registerAllExtensions() {
|
||||
const { data: packages } = await tryExecuteAndNotify(this, PackageResource.getPackageManifest());
|
||||
|
||||
if (packages) {
|
||||
// Append packages to the store but only if they have a name
|
||||
//store.appendItems(packages.filter((p) => p.name?.length));
|
||||
const extensions: ManifestBase[] = [];
|
||||
|
||||
packages.forEach((p) => {
|
||||
p.extensions?.forEach((e) => {
|
||||
// Crudely validate that the extension at least follows a basic manifest structure
|
||||
// Idea: Use `Zod` to validate the manifest
|
||||
if (isManifestBaseType(e)) {
|
||||
/**
|
||||
* Crude check to see if extension is of type "js" since it is safe to assume we do not
|
||||
* need to load any other types of extensions in the backoffice (we need a js file to load)
|
||||
*/
|
||||
|
||||
// TODO: add helper to check for relative paths
|
||||
// Add base url if the js path is relative
|
||||
if ('js' in e && typeof e.js === 'string' && !e.js.startsWith('http')) {
|
||||
e.js = `${this.#apiBaseUrl}${e.js}`;
|
||||
}
|
||||
|
||||
// Add base url if the element path is relative
|
||||
if ('element' in e && typeof e.element === 'string' && !e.element.startsWith('http')) {
|
||||
e.element = `${this.#apiBaseUrl}${e.element}`;
|
||||
}
|
||||
|
||||
// Add base url if the element path api relative
|
||||
if ('api' in e && typeof e.api === 'string' && !e.api.startsWith('http')) {
|
||||
e.api = `${this.#apiBaseUrl}${e.api}`;
|
||||
}
|
||||
|
||||
extensions.push(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.#extensionRegistry.registerMany(extensions);
|
||||
await this.#loadServerPackages(packages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all public extensions from the server.
|
||||
* This is used to register all extensions that are available to the user (excluding private extensions) such as login extensions.
|
||||
* @remark Any user can access this method without any permissions.
|
||||
*/
|
||||
public async registerPublicExtensions() {
|
||||
const { data: packages } = await tryExecuteAndNotify(this, PackageResource.getPackageManifestPublic());
|
||||
if (packages) {
|
||||
await this.#loadServerPackages(packages);
|
||||
}
|
||||
}
|
||||
|
||||
async #loadServerPackages(packages: PackageManifestResponseModel[]) {
|
||||
const extensions: ManifestBase[] = [];
|
||||
|
||||
packages.forEach((p) => {
|
||||
p.extensions?.forEach((e) => {
|
||||
// Crudely validate that the extension at least follows a basic manifest structure
|
||||
// Idea: Use `Zod` to validate the manifest
|
||||
if (isManifestBaseType(e)) {
|
||||
/**
|
||||
* Crude check to see if extension is of type "js" since it is safe to assume we do not
|
||||
* need to load any other types of extensions in the backoffice (we need a js file to load)
|
||||
*/
|
||||
|
||||
// TODO: add helper to check for relative paths
|
||||
// Add base url if the js path is relative
|
||||
if ('js' in e && typeof e.js === 'string' && !e.js.startsWith('http')) {
|
||||
e.js = `${this.#apiBaseUrl}${e.js}`;
|
||||
}
|
||||
|
||||
// Add base url if the element path is relative
|
||||
if ('element' in e && typeof e.element === 'string' && !e.element.startsWith('http')) {
|
||||
e.element = `${this.#apiBaseUrl}${e.element}`;
|
||||
}
|
||||
|
||||
// Add base url if the element path api relative
|
||||
if ('api' in e && typeof e.api === 'string' && !e.api.startsWith('http')) {
|
||||
e.api = `${this.#apiBaseUrl}${e.api}`;
|
||||
}
|
||||
|
||||
extensions.push(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.#extensionRegistry.registerMany(extensions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import type { UmbBlockGridTypeAreaType } from '../../../types.js';
|
||||
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type {
|
||||
UmbInvariantableWorkspaceContextInterface,
|
||||
UmbWorkspaceContextInterface,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbInvariantDatasetWorkspaceContext, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
UmbInvariantWorkspacePropertyDatasetContext,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api';
|
||||
@@ -15,8 +12,8 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { ManifestWorkspace, PropertyEditorSettingsProperty } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export class UmbBlockGridAreaTypeWorkspaceContext
|
||||
extends UmbEditableWorkspaceContextBase<UmbBlockGridTypeAreaType>
|
||||
implements UmbInvariantableWorkspaceContextInterface
|
||||
extends UmbSaveableWorkspaceContextBase<UmbBlockGridTypeAreaType>
|
||||
implements UmbInvariantDatasetWorkspaceContext
|
||||
{
|
||||
// Just for context token safety:
|
||||
public readonly IS_BLOCK_GRID_AREA_TYPE_WORKSPACE_CONTEXT = true;
|
||||
@@ -132,7 +129,7 @@ export class UmbBlockGridAreaTypeWorkspaceContext
|
||||
export default UmbBlockGridAreaTypeWorkspaceContext;
|
||||
|
||||
export const UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbWorkspaceContext,
|
||||
UmbBlockGridAreaTypeWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import type { UmbBlockTypeWorkspaceContext } from './block-type-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_BLOCK_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbBlockTypeWorkspaceContext
|
||||
>(
|
||||
export const UMB_BLOCK_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbBlockTypeWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbBlockTypeWorkspaceContext => (context as any).IS_BLOCK_TYPE_WORKSPACE_CONTEXT,
|
||||
|
||||
@@ -3,11 +3,11 @@ import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-edito
|
||||
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type {
|
||||
UmbInvariantableWorkspaceContextInterface,
|
||||
UmbInvariantDatasetWorkspaceContext,
|
||||
UmbRoutableWorkspaceContext,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
UmbInvariantWorkspacePropertyDatasetContext,
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
UmbWorkspaceRouteManager,
|
||||
@@ -17,8 +17,8 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import type { ManifestWorkspace, PropertyEditorSettingsProperty } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeWithGroupKey = UmbBlockTypeWithGroupKey>
|
||||
extends UmbEditableWorkspaceContextBase<BlockTypeData>
|
||||
implements UmbInvariantableWorkspaceContextInterface, UmbRoutableWorkspaceContext
|
||||
extends UmbSaveableWorkspaceContextBase<BlockTypeData>
|
||||
implements UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext
|
||||
{
|
||||
// Just for context token safety:
|
||||
public readonly IS_BLOCK_TYPE_WORKSPACE_CONTEXT = true;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { UmbBlockWorkspaceContext } from './block-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_BLOCK_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContextInterface, UmbBlockWorkspaceContext>(
|
||||
export const UMB_BLOCK_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbBlockWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbBlockWorkspaceContext => (context as any).IS_BLOCK_WORKSPACE_CONTEXT,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '../types.js';
|
||||
import { UmbBlockElementManager } from './block-element-manager.js';
|
||||
import { UmbBlockWorkspaceEditorElement } from './block-workspace-editor.element.js';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
UmbWorkspaceRouteManager,
|
||||
type UmbRoutableWorkspaceContext,
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
@@ -20,7 +20,7 @@ import { decodeFilePath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export type UmbBlockWorkspaceElementManagerNames = 'content' | 'settings';
|
||||
export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel>
|
||||
extends UmbEditableWorkspaceContextBase<LayoutDataType>
|
||||
extends UmbSaveableWorkspaceContextBase<LayoutDataType>
|
||||
implements UmbRoutableWorkspaceContext
|
||||
{
|
||||
// Just for context token safety:
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { html, nothing, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { map } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbEntityAction } from '@umbraco-cms/backoffice/entity-action';
|
||||
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { html, nothing, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section';
|
||||
import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { ManifestEntityActionDefaultKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
@customElement('umb-entity-actions-bundle')
|
||||
export class UmbEntityActionsBundleElement extends UmbLitElement {
|
||||
private _entityType?: string;
|
||||
@property({ type: String, attribute: 'entity-type' })
|
||||
public get entityType() {
|
||||
return this._entityType;
|
||||
}
|
||||
public set entityType(value: string | undefined) {
|
||||
const oldValue = this._entityType;
|
||||
if (oldValue === value) return;
|
||||
|
||||
this._entityType = value;
|
||||
this.#observeEntityActions();
|
||||
this.requestUpdate('entityType', oldValue);
|
||||
}
|
||||
entityType?: string;
|
||||
|
||||
@property({ type: String })
|
||||
unique?: string | null;
|
||||
@@ -28,7 +20,13 @@ export class UmbEntityActionsBundleElement extends UmbLitElement {
|
||||
public label?: string;
|
||||
|
||||
@state()
|
||||
private _hasActions = false;
|
||||
private _numberOfActions = 0;
|
||||
|
||||
@state()
|
||||
private _firstActionManifest?: ManifestEntityActionDefaultKind;
|
||||
|
||||
@state()
|
||||
private _firstActionApi?: UmbEntityAction<unknown>;
|
||||
|
||||
#sectionSidebarContext?: UmbSectionSidebarContext;
|
||||
|
||||
@@ -40,36 +38,59 @@ export class UmbEntityActionsBundleElement extends UmbLitElement {
|
||||
});
|
||||
}
|
||||
|
||||
protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
if (_changedProperties.has('entityType') && _changedProperties.has('unique')) {
|
||||
this.#observeEntityActions();
|
||||
}
|
||||
}
|
||||
|
||||
#observeEntityActions() {
|
||||
this.observe(
|
||||
umbExtensionsRegistry
|
||||
.byType('entityAction')
|
||||
.pipe(map((actions) => actions.some((action) => action.forEntityTypes.includes(this.entityType!)))),
|
||||
(hasActions) => {
|
||||
this._hasActions = hasActions;
|
||||
umbExtensionsRegistry.byType('entityAction'),
|
||||
async (manifests) => {
|
||||
const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!));
|
||||
this._numberOfActions = actions.length;
|
||||
this._firstActionManifest =
|
||||
this._numberOfActions > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined;
|
||||
if (!this._firstActionManifest) return;
|
||||
this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [
|
||||
{ unique: this.unique, entityType: this.entityType },
|
||||
]);
|
||||
},
|
||||
'umbEntityActionsObserver',
|
||||
);
|
||||
}
|
||||
|
||||
private _openActions() {
|
||||
#openContextMenu() {
|
||||
if (!this.entityType) throw new Error('Entity type is not defined');
|
||||
if (this.unique === undefined) throw new Error('Unique is not defined');
|
||||
this.#sectionSidebarContext?.toggleContextMenu(this.entityType, this.unique, this.label);
|
||||
}
|
||||
|
||||
async #onFirstActionClick(event: PointerEvent) {
|
||||
event.stopPropagation();
|
||||
await this._firstActionApi?.execute();
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this._hasActions
|
||||
? html`
|
||||
<uui-action-bar slot="actions">
|
||||
<uui-button @click=${this._openActions} label="Open actions menu">
|
||||
<uui-symbol-more></uui-symbol-more>
|
||||
</uui-button>
|
||||
</uui-action-bar>
|
||||
`
|
||||
: nothing}
|
||||
`;
|
||||
if (this._numberOfActions === 0) return nothing;
|
||||
return html`<uui-action-bar slot="actions"> ${this.#renderFirstAction()} ${this.#renderMore()} </uui-action-bar>`;
|
||||
}
|
||||
|
||||
#renderMore() {
|
||||
if (this._numberOfActions === 1) return nothing;
|
||||
return html`<uui-button @click=${this.#openContextMenu} label="Open actions menu">
|
||||
<uui-symbol-more></uui-symbol-more>
|
||||
</uui-button>`;
|
||||
}
|
||||
|
||||
#renderFirstAction() {
|
||||
if (!this._firstActionApi) return nothing;
|
||||
return html`<uui-button
|
||||
label=${ifDefined(this._firstActionManifest?.meta.label)}
|
||||
@click=${this.#onFirstActionClick}>
|
||||
<uui-icon name=${ifDefined(this._firstActionManifest?.meta.icon)}></uui-icon>
|
||||
</uui-button>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
|
||||
import { html, customElement, property, state, type PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
|
||||
function getNumberOrUndefined(value: string) {
|
||||
@@ -8,7 +8,7 @@ function getNumberOrUndefined(value: string) {
|
||||
}
|
||||
|
||||
@customElement('umb-input-number-range')
|
||||
export class UmbInputNumberRangeElement extends FormControlMixin(UmbLitElement) {
|
||||
export class UmbInputNumberRangeElement extends UmbFormControlMixin(UmbLitElement, undefined) {
|
||||
@property({ type: String, attribute: 'min-label' })
|
||||
minLabel = 'Low value';
|
||||
|
||||
@@ -40,7 +40,8 @@ export class UmbInputNumberRangeElement extends FormControlMixin(UmbLitElement)
|
||||
}
|
||||
|
||||
private updateValue() {
|
||||
const newValue = this._minValue || this._maxValue ? (this._minValue || '') + ',' + (this._maxValue || '') : '';
|
||||
const newValue =
|
||||
this._minValue || this._maxValue ? (this._minValue ?? '') + ',' + (this._maxValue ?? '') : undefined;
|
||||
if (super.value !== newValue) {
|
||||
super.value = newValue;
|
||||
}
|
||||
@@ -48,7 +49,7 @@ export class UmbInputNumberRangeElement extends FormControlMixin(UmbLitElement)
|
||||
|
||||
@property()
|
||||
public set value(valueString: string) {
|
||||
if (valueString !== this._value) {
|
||||
if (valueString !== this.value) {
|
||||
const splittedValue = valueString.split(/[ ,]+/);
|
||||
this.minValue = getNumberOrUndefined(splittedValue[0]);
|
||||
this.maxValue = getNumberOrUndefined(splittedValue[1]);
|
||||
@@ -62,19 +63,27 @@ export class UmbInputNumberRangeElement extends FormControlMixin(UmbLitElement)
|
||||
return this;
|
||||
}
|
||||
|
||||
protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.shadowRoot
|
||||
?.querySelectorAll('uui-input')
|
||||
.forEach((x) => this.addFormControlElement(x as unknown as HTMLInputElement));
|
||||
}
|
||||
|
||||
private _onMinInput(e: InputEvent) {
|
||||
this.minValue = Number((e.target as HTMLInputElement).value);
|
||||
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }));
|
||||
this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
|
||||
}
|
||||
|
||||
private _onMaxInput(e: InputEvent) {
|
||||
this.maxValue = Number((e.target as HTMLInputElement).value);
|
||||
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }));
|
||||
this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<uui-input
|
||||
type="number"
|
||||
required
|
||||
.value=${this._minValue}
|
||||
@input=${this._onMinInput}
|
||||
label=${this.minLabel}></uui-input>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
@@ -10,7 +10,7 @@ export const UMB_PROPERTY_TYPE_WORKSPACE_ALIAS = 'Umb.Workspace.PropertyType';
|
||||
*/
|
||||
export class UmbPropertyTypeWorkspaceContext
|
||||
extends UmbContextBase<UmbPropertyTypeWorkspaceContext>
|
||||
implements UmbWorkspaceContextInterface
|
||||
implements UmbWorkspaceContext
|
||||
{
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT);
|
||||
@@ -32,7 +32,7 @@ export class UmbPropertyTypeWorkspaceContext
|
||||
export default UmbPropertyTypeWorkspaceContext;
|
||||
|
||||
export const UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbWorkspaceContext,
|
||||
UmbPropertyTypeWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { UmbContentTypeCompositionModel, UmbContentTypeModel, UmbContentTypeSortModel } from '../types.js';
|
||||
import type { UmbContentTypeStructureManager } from '../structure/index.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbSaveableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export interface UmbContentTypeWorkspaceContext<ContentTypeType extends UmbContentTypeModel = UmbContentTypeModel>
|
||||
extends UmbSaveableWorkspaceContextInterface {
|
||||
extends UmbSaveableWorkspaceContext {
|
||||
readonly IS_CONTENT_TYPE_WORKSPACE_CONTEXT: true;
|
||||
|
||||
readonly name: Observable<string | undefined>;
|
||||
|
||||
@@ -3,13 +3,13 @@ import type { ManifestMenuItem } from '@umbraco-cms/backoffice/extension-registr
|
||||
const menuItem: ManifestMenuItem = {
|
||||
type: 'menuItem',
|
||||
alias: 'Umb.MenuItem.Extensions',
|
||||
name: 'Extensions Menu Item',
|
||||
weight: 0,
|
||||
name: 'Extension Insights Menu Item',
|
||||
weight: 200,
|
||||
meta: {
|
||||
label: 'Extensions',
|
||||
label: 'Extension Insights',
|
||||
icon: 'icon-wand',
|
||||
entityType: 'extension-root',
|
||||
menus: ['Umb.Menu.Settings'],
|
||||
menus: ['Umb.Menu.AdvancedSettings'],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbRoutableWorkspaceContext } from '../../workspace/contexts/routable-workspace-context.interface.js';
|
||||
import type { UmbWorkspaceContextInterface } from '../../workspace/contexts/workspace-context.interface.js';
|
||||
import type { UmbRoutableWorkspaceContext } from '../../workspace/contexts/tokens/routable-workspace-context.interface.js';
|
||||
import type { UmbWorkspaceContext } from '../../workspace/contexts/tokens/workspace-context.interface.js';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import type { ManifestElementAndApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { ManifestElementAndApi } from '@umbraco-cms/backoffice/extension-ap
|
||||
export interface ManifestWorkspace<
|
||||
MetaType extends MetaWorkspace = MetaWorkspace,
|
||||
ElementType extends UmbControllerHostElement = UmbControllerHostElement,
|
||||
ApiType extends UmbWorkspaceContextInterface = UmbWorkspaceContextInterface,
|
||||
ApiType extends UmbWorkspaceContext = UmbWorkspaceContext,
|
||||
> extends ManifestElementAndApi<ElementType, ApiType> {
|
||||
type: 'workspace';
|
||||
meta: MetaType;
|
||||
|
||||
@@ -27,6 +27,12 @@ export interface UmbracoPackage {
|
||||
*/
|
||||
allowTelemetry?: boolean;
|
||||
|
||||
/**
|
||||
* @title Decides if the package is allowed to be accessed by the public, e.g. on the login screen
|
||||
* @default false
|
||||
*/
|
||||
allowPublicAccess?: boolean;
|
||||
|
||||
/**
|
||||
* @title An array of Umbraco package manifest types that will be installed
|
||||
* @required
|
||||
|
||||
@@ -7,7 +7,10 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
export class UmbExtensionRootWorkspaceElement extends UmbLitElement {
|
||||
render() {
|
||||
return html`
|
||||
<umb-workspace-editor headline="Extensions" alias=${UMB_EXTENSION_ROOT_WORKSPACE_ALIAS} .enforceNoFooter=${true}>
|
||||
<umb-workspace-editor
|
||||
headline="Extension Insights"
|
||||
alias=${UMB_EXTENSION_ROOT_WORKSPACE_ALIAS}
|
||||
.enforceNoFooter=${true}>
|
||||
<umb-collection alias=${UMB_EXTENSION_COLLECTION_ALIAS}></umb-collection>
|
||||
</umb-workspace-editor>
|
||||
`;
|
||||
|
||||
@@ -13,20 +13,20 @@ export class UmbLocalizeDateElement extends UmbLitElement {
|
||||
* @attr
|
||||
* @example date="Sep 22 2023"
|
||||
*/
|
||||
@property()
|
||||
date!: string | Date;
|
||||
@property({ type: String })
|
||||
date?: string | Date;
|
||||
|
||||
/**
|
||||
* Formatting options
|
||||
* @attr
|
||||
* @example options={ dateStyle: 'full', timeStyle: 'long', timeZone: 'Australia/Sydney' }
|
||||
*/
|
||||
@property()
|
||||
@property({ type: Object })
|
||||
options?: Intl.DateTimeFormatOptions;
|
||||
|
||||
@state()
|
||||
protected get text(): string {
|
||||
return this.localize.date(this.date, this.options);
|
||||
return this.localize.date(this.date!, this.options);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export type UmbEntityUnique = string | null;
|
||||
|
||||
/** Tried to find a common base of our entities — used by Entity Workspace Context */
|
||||
export type UmbEntityBase = {
|
||||
id?: string;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { html, customElement, property, state } from '@umbraco-cms/backoffice/ex
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_DOCUMENT_COLLECTION_ALIAS } from '@umbraco-cms/backoffice/document';
|
||||
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_WORKSPACE_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UMB_COLLECTION_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type {
|
||||
UmbCollectionBulkActionPermissions,
|
||||
@@ -31,7 +31,7 @@ export class UmbPropertyEditorUICollectionViewElement extends UmbLitElement impl
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_COLLECTION_CONTEXT, (workspaceContext) => {
|
||||
this.consumeContext(UMB_COLLECTION_WORKSPACE_CONTEXT, (workspaceContext) => {
|
||||
this._collectionAlias = workspaceContext.getCollectionAlias();
|
||||
|
||||
this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => {
|
||||
@@ -39,8 +39,9 @@ export class UmbPropertyEditorUICollectionViewElement extends UmbLitElement impl
|
||||
if (propertyAlias) {
|
||||
// Gets the Data Type ID for the current property.
|
||||
const property = await workspaceContext.structure.getPropertyStructureByAlias(propertyAlias);
|
||||
if (property && this._config) {
|
||||
this._config.unique = workspaceContext.getUnique();
|
||||
const unique = workspaceContext.getUnique();
|
||||
if (unique && property && this._config) {
|
||||
this._config.unique = unique;
|
||||
this._config.dataTypeId = property.dataType.unique;
|
||||
this.requestUpdate('_config');
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { html, customElement, property, state } from '@umbraco-cms/backoffice/ex
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbDynamicRootRepository } from '@umbraco-cms/backoffice/dynamic-root';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type { UmbInputTreeElement } from '@umbraco-cms/backoffice/tree';
|
||||
@@ -69,7 +69,7 @@ export class UmbPropertyEditorUITreePickerElement extends UmbLitElement implemen
|
||||
|
||||
// TODO: Awaiting the workspace context to have a parent entity ID value. [LK]
|
||||
// e.g. const parentEntityId = this.#workspaceContext?.getParentEntityId();
|
||||
const workspaceContext = await this.getContext(UMB_WORKSPACE_CONTEXT);
|
||||
const workspaceContext = await this.getContext(UMB_ENTITY_WORKSPACE_CONTEXT);
|
||||
const unique = workspaceContext.getUnique();
|
||||
if (unique && this.#dynamicRoot) {
|
||||
const result = await this.#dynamicRootRepository.postDynamicRootQuery(this.#dynamicRoot, unique);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { UmbVariantId } from '../../variant/variant-id.class.js';
|
||||
import type { UmbContext } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/models';
|
||||
|
||||
/**
|
||||
* A property dataset context, represents the data of a set of properties.
|
||||
@@ -18,7 +19,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
*/
|
||||
export interface UmbPropertyDatasetContext extends UmbContext {
|
||||
getEntityType(): string;
|
||||
getUnique(): string | undefined;
|
||||
getUnique(): UmbEntityUnique | undefined;
|
||||
getVariantId: () => UmbVariantId;
|
||||
|
||||
getName(): string | undefined;
|
||||
|
||||
@@ -21,21 +21,62 @@ export const manifests = [
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
alias: 'Umb.Menu.Settings',
|
||||
alias: 'Umb.Menu.StructureSettings',
|
||||
name: 'Settings Menu',
|
||||
meta: {
|
||||
label: 'Settings',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'sectionSidebarApp',
|
||||
kind: 'menu',
|
||||
alias: 'Umb.SectionSidebarMenu.Settings',
|
||||
name: 'Settings Section Sidebar Menu',
|
||||
weight: 200,
|
||||
name: 'Structure Settings Sidebar Menu',
|
||||
weight: 300,
|
||||
meta: {
|
||||
label: 'Settings',
|
||||
menu: 'Umb.Menu.Settings',
|
||||
label: 'Structure',
|
||||
menu: 'Umb.Menu.StructureSettings',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: 'Umb.Condition.SectionAlias',
|
||||
match: UMB_SETTINGS_SECTION_ALIAS,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
alias: 'Umb.Menu.AdvancedSettings',
|
||||
name: 'Advanced Settings Menu',
|
||||
},
|
||||
{
|
||||
type: 'sectionSidebarApp',
|
||||
kind: 'menu',
|
||||
alias: 'Umb.SectionSidebarMenu.AdvancedSettings',
|
||||
name: 'Advanced Settings Sidebar Menu',
|
||||
weight: 100,
|
||||
meta: {
|
||||
label: 'Advanced',
|
||||
menu: 'Umb.Menu.AdvancedSettings',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: 'Umb.Condition.SectionAlias',
|
||||
match: UMB_SETTINGS_SECTION_ALIAS,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
alias: 'Umb.Menu.AdvancedSettings',
|
||||
name: 'Advanced Settings Menu',
|
||||
},
|
||||
{
|
||||
type: 'sectionSidebarApp',
|
||||
kind: 'menu',
|
||||
alias: 'Umb.SectionSidebarMenu.AdvancedSettings',
|
||||
name: 'Advanced Settings Section Sidebar Menu',
|
||||
weight: 100,
|
||||
meta: {
|
||||
label: 'Advanced',
|
||||
menu: 'Umb.Menu.AdvancedSettings',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './validation.context.js';
|
||||
export * from './validation.context-token.js';
|
||||
@@ -0,0 +1,4 @@
|
||||
import type { UmbValidationContext } from './validation.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_VALIDATION_CONTEXT = new UmbContextToken<UmbValidationContext>('UmbValidationContext');
|
||||
@@ -0,0 +1,9 @@
|
||||
import { UMB_VALIDATION_CONTEXT } from './validation.context-token.js';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbValidationContext extends UmbContextBase<UmbValidationContext> {
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, UMB_VALIDATION_CONTEXT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './validation-valid.event.js';
|
||||
export * from './validation-invalid.event.js';
|
||||
@@ -0,0 +1,9 @@
|
||||
import { UmbValidationEvent } from './validation.event.js';
|
||||
|
||||
export class UmbValidationInvalidEvent extends UmbValidationEvent {
|
||||
static readonly TYPE = 'invalid';
|
||||
|
||||
public constructor() {
|
||||
super(UmbValidationInvalidEvent.TYPE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { UmbValidationEvent } from './validation.event.js';
|
||||
|
||||
export class UmbValidationValidEvent extends UmbValidationEvent {
|
||||
static readonly TYPE = 'valid';
|
||||
|
||||
constructor() {
|
||||
super(UmbValidationValidEvent.TYPE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export class UmbValidationEvent extends Event {
|
||||
public constructor(type: string) {
|
||||
super(type, { bubbles: true, composed: true, cancelable: false });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './events/index.js';
|
||||
export * from './mixins/index.js';
|
||||
export * from './context/index.js';
|
||||
@@ -0,0 +1,306 @@
|
||||
import { UmbValidationInvalidEvent } from '../events/validation-invalid.event.js';
|
||||
import { UmbValidationValidEvent } from '../events/validation-valid.event.js';
|
||||
import { UmbValidityState } from './validity-state.class.js';
|
||||
import { property, type LitElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
type NativeFormControlElement = HTMLInputElement | HTMLTextAreaElement; // Eventually use a specific interface or list multiple options like appending these types: ... | HTMLTextAreaElement | HTMLSelectElement
|
||||
|
||||
/* FlagTypes type options originate from:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
|
||||
* */
|
||||
type FlagTypes =
|
||||
| 'badInput'
|
||||
| 'customError'
|
||||
| 'patternMismatch'
|
||||
| 'rangeOverflow'
|
||||
| 'rangeUnderflow'
|
||||
| 'stepMismatch'
|
||||
| 'tooLong'
|
||||
| 'tooShort'
|
||||
| 'typeMismatch'
|
||||
| 'valueMissing'
|
||||
| 'badInput'
|
||||
| 'valid';
|
||||
|
||||
// Acceptable as an internal interface/type, BUT if exposed externally this should be turned into a public class in a separate file.
|
||||
interface Validator {
|
||||
flagKey: FlagTypes;
|
||||
getMessageMethod: () => string;
|
||||
checkMethod: () => boolean;
|
||||
}
|
||||
|
||||
export interface UmbFormControlMixinInterface<ValueType, DefaultValueType> extends HTMLElement {
|
||||
formAssociated: boolean;
|
||||
get value(): ValueType | DefaultValueType;
|
||||
set value(newValue: ValueType | DefaultValueType);
|
||||
formResetCallback(): void;
|
||||
checkValidity(): boolean;
|
||||
get validationMessage(): string;
|
||||
get validity(): ValidityState;
|
||||
setCustomValidity(error: string): void;
|
||||
submit(): void;
|
||||
pristine: boolean;
|
||||
required: boolean;
|
||||
requiredMessage: string;
|
||||
error: boolean;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
||||
export declare abstract class UmbFormControlMixinElement<ValueType, DefaultValueType>
|
||||
extends LitElement
|
||||
implements UmbFormControlMixinInterface<ValueType, DefaultValueType>
|
||||
{
|
||||
protected _internals: ElementInternals;
|
||||
protected _runValidators(): void;
|
||||
protected abstract getFormElement(): HTMLElement | undefined;
|
||||
protected addValidator: (flagKey: FlagTypes, getMessageMethod: () => string, checkMethod: () => boolean) => void;
|
||||
protected addFormControlElement(element: NativeFormControlElement): void;
|
||||
|
||||
formAssociated: boolean;
|
||||
get value(): ValueType | DefaultValueType;
|
||||
set value(newValue: ValueType | DefaultValueType);
|
||||
formResetCallback(): void;
|
||||
checkValidity(): boolean;
|
||||
get validationMessage(): string;
|
||||
get validity(): ValidityState;
|
||||
setCustomValidity(error: string): void;
|
||||
submit(): void;
|
||||
pristine: boolean;
|
||||
required: boolean;
|
||||
requiredMessage: string;
|
||||
error: boolean;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The mixin allows a custom element to participate in HTML forms.
|
||||
*
|
||||
* @param {Object} superClass - superclass to be extended.
|
||||
* @mixin
|
||||
*/
|
||||
export const UmbFormControlMixin = <
|
||||
ValueType = FormDataEntryValue | FormData,
|
||||
T extends HTMLElementConstructor<LitElement> = HTMLElementConstructor<LitElement>,
|
||||
DefaultValueType = unknown,
|
||||
>(
|
||||
superClass: T,
|
||||
defaultValue: DefaultValueType,
|
||||
) => {
|
||||
abstract class UmbFormControlMixinClass extends superClass {
|
||||
/**
|
||||
* This is a static class field indicating that the element is can be used inside a native form and participate in its events.
|
||||
* It may require a polyfill, check support here https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals.
|
||||
* Read more about form controls here https://web.dev/more-capable-form-controls/
|
||||
* @type {boolean}
|
||||
*/
|
||||
static readonly formAssociated = true;
|
||||
|
||||
/**
|
||||
* Value of this form control.
|
||||
* If you dont want the setFormValue to be called on the ElementInternals, then prevent calling this method, by not calling super.value = newValue in your implementation of the value setter method.
|
||||
* @type {string}
|
||||
* @attr value
|
||||
* @default ''
|
||||
*/
|
||||
@property({ reflect: false }) // Do not 'reflect' as the attribute is used as fallback.
|
||||
get value(): ValueType | DefaultValueType {
|
||||
return this.#value;
|
||||
}
|
||||
set value(newValue: ValueType | DefaultValueType) {
|
||||
this.#value = newValue;
|
||||
this._runValidators();
|
||||
}
|
||||
|
||||
// Validation
|
||||
private _validityState = new UmbValidityState();
|
||||
|
||||
/**
|
||||
* Determines wether the form control has been touched or interacted with, this determines wether the validation-status of this form control should be made visible.
|
||||
* @type {boolean}
|
||||
* @attr
|
||||
* @default false
|
||||
*/
|
||||
@property({ type: Boolean, reflect: true })
|
||||
pristine: boolean = true;
|
||||
|
||||
#value: ValueType | DefaultValueType = defaultValue;
|
||||
protected _internals: ElementInternals;
|
||||
#form: HTMLFormElement | null = null;
|
||||
#validators: Validator[] = [];
|
||||
#formCtrlElements: NativeFormControlElement[] = [];
|
||||
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
this._internals = this.attachInternals();
|
||||
|
||||
this.addEventListener('blur', () => {
|
||||
this.pristine = false;
|
||||
this.checkValidity();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get internal form element.
|
||||
* This has to be implemented to provide a FormControl Element of choice for the given context. The element is used as anchor for validation-messages.
|
||||
* @abstract
|
||||
* @method getFormElement
|
||||
* @returns {HTMLElement | undefined}
|
||||
*/
|
||||
protected abstract getFormElement(): HTMLElement | undefined;
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this.#removeFormListeners();
|
||||
}
|
||||
#removeFormListeners() {
|
||||
if (this.#form) {
|
||||
this.#form.removeEventListener('submit', this.#onFormSubmit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add validator, to validate this Form Control.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/ValidityState for available Validator FlagTypes.
|
||||
*
|
||||
* @example
|
||||
* this.addValidator(
|
||||
* 'tooLong',
|
||||
* () => 'This input contains too many characters',
|
||||
* () => this._value.length > 10
|
||||
* );
|
||||
* @method addValidator
|
||||
* @param {FlagTypes} flagKey the type of validation.
|
||||
* @param {method} getMessageMethod method to retrieve relevant message. Is executed every time the validator is re-executed.
|
||||
* @param {method} checkMethod method to determine if this validator should invalidate this form control. Return true if this should prevent submission.
|
||||
*/
|
||||
protected addValidator(flagKey: FlagTypes, getMessageMethod: () => string, checkMethod: () => boolean): Validator {
|
||||
const obj = {
|
||||
flagKey: flagKey,
|
||||
getMessageMethod: getMessageMethod,
|
||||
checkMethod: checkMethod,
|
||||
};
|
||||
this.#validators.push(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected removeValidator(validator: Validator) {
|
||||
const index = this.#validators.indexOf(validator);
|
||||
if (index !== -1) {
|
||||
this.#validators.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method addFormControlElement
|
||||
* @description Important notice if adding a native form control then ensure that its value and thereby validity is updated when value is changed from the outside.
|
||||
* @param element {NativeFormControlElement} - element to validate and include as part of this form association.
|
||||
*/
|
||||
protected addFormControlElement(element: NativeFormControlElement) {
|
||||
this.#formCtrlElements.push(element);
|
||||
element.addEventListener(UmbValidationInvalidEvent.TYPE, () => {
|
||||
this._runValidators();
|
||||
});
|
||||
element.addEventListener(UmbValidationValidEvent.TYPE, () => {
|
||||
this._runValidators();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @method _runValidators
|
||||
* @description Run all validators and set the validityState of this form control.
|
||||
* Run this method when you want to re-run all validators.
|
||||
* This can be relevant if you have a validators that is using values that is not triggering the Lit Updated Callback.
|
||||
* Such are mainly properties that are not declared as a Lit state and or Lit property.
|
||||
*/
|
||||
protected _runValidators() {
|
||||
this._validityState = new UmbValidityState();
|
||||
|
||||
// Loop through inner native form controls to adapt their validityState.
|
||||
this.#formCtrlElements.forEach((formCtrlEl) => {
|
||||
let key: keyof ValidityState;
|
||||
for (key in formCtrlEl.validity) {
|
||||
if (key !== 'valid' && formCtrlEl.validity[key]) {
|
||||
this._validityState[key] = true;
|
||||
this._internals.setValidity(this._validityState, formCtrlEl.validationMessage, formCtrlEl);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Loop through custom validators, currently its intentional to have them overwritten native validity. but might need to be reconsidered (This current way enables to overwrite with custom messages) [NL]
|
||||
this.#validators.forEach((validator) => {
|
||||
if (validator.checkMethod()) {
|
||||
this._validityState[validator.flagKey] = true;
|
||||
this._internals.setValidity(this._validityState, validator.getMessageMethod(), this.getFormElement());
|
||||
}
|
||||
});
|
||||
|
||||
const hasError = Object.values(this._validityState).includes(true);
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState#valid
|
||||
this._validityState.valid = !hasError;
|
||||
|
||||
if (hasError) {
|
||||
this.dispatchEvent(new UmbValidationInvalidEvent());
|
||||
} else {
|
||||
this._internals.setValidity({});
|
||||
this.dispatchEvent(new UmbValidationValidEvent());
|
||||
}
|
||||
}
|
||||
|
||||
updated(changedProperties: Map<string | number | symbol, unknown>) {
|
||||
super.updated(changedProperties);
|
||||
this._runValidators();
|
||||
}
|
||||
|
||||
#onFormSubmit = () => {
|
||||
this.pristine = false;
|
||||
};
|
||||
|
||||
public formAssociatedCallback() {
|
||||
this.#removeFormListeners();
|
||||
this.#form = this._internals.form;
|
||||
if (this.#form) {
|
||||
// This relies on the form begin a 'uui-form': [NL]
|
||||
if (this.#form.hasAttribute('submit-invalid')) {
|
||||
this.pristine = false;
|
||||
}
|
||||
this.#form.addEventListener('submit', this.#onFormSubmit);
|
||||
}
|
||||
}
|
||||
public formResetCallback() {
|
||||
this.pristine = true;
|
||||
this.value = this.getInitialValue() ?? this.getDefaultValue();
|
||||
}
|
||||
|
||||
protected getDefaultValue(): DefaultValueType {
|
||||
return defaultValue;
|
||||
}
|
||||
protected getInitialValue(): ValueType | DefaultValueType {
|
||||
return this.getAttribute('value') as ValueType | DefaultValueType;
|
||||
}
|
||||
|
||||
public checkValidity() {
|
||||
for (const key in this.#formCtrlElements) {
|
||||
if (this.#formCtrlElements[key].checkValidity() === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this._internals?.checkValidity();
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
|
||||
public get validity(): ValidityState {
|
||||
return this._validityState;
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._internals?.validationMessage;
|
||||
}
|
||||
}
|
||||
return UmbFormControlMixinClass as unknown as HTMLElementConstructor<
|
||||
UmbFormControlMixinElement<ValueType, DefaultValueType>
|
||||
> &
|
||||
T;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './form-control.mixin.js';
|
||||
@@ -0,0 +1,15 @@
|
||||
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
|
||||
|
||||
export class UmbValidityState implements Writeable<ValidityState> {
|
||||
badInput: boolean = false;
|
||||
customError: boolean = false;
|
||||
patternMismatch: boolean = false;
|
||||
rangeOverflow: boolean = false;
|
||||
rangeUnderflow: boolean = false;
|
||||
stepMismatch: boolean = false;
|
||||
tooLong: boolean = false;
|
||||
tooShort: boolean = false;
|
||||
typeMismatch: boolean = false;
|
||||
valid: boolean = false;
|
||||
valueMissing: boolean = false;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
||||
async #observeActiveVariants() {
|
||||
if (!this.#splitViewContext) return;
|
||||
|
||||
const workspaceContext = this.#splitViewContext.getWorkspaceContext();
|
||||
const workspaceContext = this.#splitViewContext.getWorkspaceContext() as UmbDocumentWorkspaceContext;
|
||||
if (workspaceContext) {
|
||||
this.observe(
|
||||
workspaceContext.splitView.activeVariantsInfo,
|
||||
@@ -223,9 +223,9 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
||||
<uui-button slot="append" compact id="variant-close" @click=${this.#closeSplitView}>
|
||||
<uui-icon name="remove"></uui-icon>
|
||||
</uui-button>
|
||||
`
|
||||
`
|
||||
: ''}
|
||||
`
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
</uui-input>
|
||||
@@ -264,7 +264,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
||||
@click=${() => this.#openSplitView(variant)}>
|
||||
Split view
|
||||
</uui-button>
|
||||
`}
|
||||
`}
|
||||
</li>
|
||||
`,
|
||||
)}
|
||||
@@ -272,7 +272,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
||||
</uui-scroll-container>
|
||||
</div>
|
||||
</uui-popover-container>
|
||||
`
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { UmbSaveableWorkspaceContextInterface } from '../../../../contexts/saveable-workspace-context.interface.js';
|
||||
import type { UmbSaveableWorkspaceContext } from '../../../../contexts/tokens/saveable-workspace-context.interface.js';
|
||||
import { UmbWorkspaceActionBase } from '../../workspace-action-base.controller.js';
|
||||
import { UMB_SAVEABLE_WORKSPACE_CONTEXT, type UmbWorkspaceActionArgs } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbSaveWorkspaceAction extends UmbWorkspaceActionBase<UmbSaveableWorkspaceContextInterface> {
|
||||
constructor(host: UmbControllerHost, args: UmbWorkspaceActionArgs<UmbSaveableWorkspaceContextInterface>) {
|
||||
export class UmbSaveWorkspaceAction extends UmbWorkspaceActionBase<UmbSaveableWorkspaceContext> {
|
||||
constructor(host: UmbControllerHost, args: UmbWorkspaceActionArgs<UmbSaveableWorkspaceContext>) {
|
||||
super(host, args);
|
||||
|
||||
// TODO: Could we make change label depending on the state?
|
||||
|
||||
@@ -2,14 +2,14 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, customElement, state, nothing, query } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UMB_ENTITY_WORKSPACE_CONTEXT, type UmbWorkspaceUniqueType } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
@customElement('umb-workspace-entity-action-menu')
|
||||
export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement {
|
||||
private _workspaceContext?: typeof UMB_WORKSPACE_CONTEXT.TYPE;
|
||||
private _workspaceContext?: typeof UMB_ENTITY_WORKSPACE_CONTEXT.TYPE;
|
||||
|
||||
@state()
|
||||
private _unique?: string;
|
||||
private _unique?: UmbWorkspaceUniqueType;
|
||||
|
||||
@state()
|
||||
private _entityType?: string;
|
||||
@@ -23,7 +23,7 @@ export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => {
|
||||
this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (context) => {
|
||||
this._workspaceContext = context;
|
||||
this._observeInfo();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UMB_SAVEABLE_WORKSPACE_CONTEXT } from '../../contexts/saveable-workspace.context-token.js';
|
||||
import { UMB_SAVEABLE_WORKSPACE_CONTEXT } from '../../contexts/tokens/saveable-workspace.context-token.js';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UMB_WORKSPACE_CONTEXT, type UmbWorkspaceContextInterface } from '../contexts/index.js';
|
||||
import { UMB_WORKSPACE_CONTEXT, type UmbWorkspaceContext } from '../contexts/index.js';
|
||||
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
@@ -15,12 +15,11 @@ export class UmbWorkspaceAliasCondition
|
||||
constructor(host: UmbControllerHost, args: UmbConditionControllerArguments<WorkspaceAliasConditionConfig>) {
|
||||
super(host, args);
|
||||
|
||||
let permissionCheck: ((context: UmbWorkspaceContextInterface) => boolean) | undefined = undefined;
|
||||
let permissionCheck: ((context: UmbWorkspaceContext) => boolean) | undefined = undefined;
|
||||
if (this.config.match) {
|
||||
permissionCheck = (context: UmbWorkspaceContextInterface) => context.workspaceAlias === this.config.match;
|
||||
permissionCheck = (context: UmbWorkspaceContext) => context.workspaceAlias === this.config.match;
|
||||
} else if (this.config.oneOf) {
|
||||
permissionCheck = (context: UmbWorkspaceContextInterface) =>
|
||||
this.config.oneOf!.indexOf(context.workspaceAlias) !== -1;
|
||||
permissionCheck = (context: UmbWorkspaceContext) => this.config.oneOf!.indexOf(context.workspaceAlias) !== -1;
|
||||
}
|
||||
|
||||
if (permissionCheck !== undefined) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UMB_WORKSPACE_COLLECTION_CONTEXT } from '../contexts/workspace-collection-context.token.js';
|
||||
import { UMB_COLLECTION_WORKSPACE_CONTEXT } from '../contexts/tokens/collection-workspace.context-token.js';
|
||||
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type {
|
||||
ManifestCondition,
|
||||
@@ -15,7 +15,7 @@ export class UmbWorkspaceHasCollectionCondition
|
||||
constructor(host: UmbControllerHost, args: UmbConditionControllerArguments<WorkspaceHasCollectionConditionConfig>) {
|
||||
super(host, args);
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_COLLECTION_CONTEXT, (context) => {
|
||||
this.consumeContext(UMB_COLLECTION_WORKSPACE_CONTEXT, (context) => {
|
||||
this.observe(
|
||||
context.contentTypeHasCollection,
|
||||
(hasCollection) => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { UMB_WORKSPACE_CONTEXT } from './workspace-context.token.js';
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import { UMB_WORKSPACE_CONTEXT } from './tokens/workspace.context-token.js';
|
||||
import type { UmbWorkspaceContext } from './tokens/workspace-context.interface.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export abstract class UmbDefaultWorkspaceContext
|
||||
extends UmbContextBase<UmbDefaultWorkspaceContext>
|
||||
implements UmbWorkspaceContextInterface
|
||||
implements UmbWorkspaceContext
|
||||
{
|
||||
public workspaceAlias!: string;
|
||||
#entityType!: string;
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
export * from './default-workspace.context.js';
|
||||
export * from './editable-workspace-context-base.js';
|
||||
export * from './property-structure-workspace-context.interface.js';
|
||||
export * from './publishable-workspace-context.interface.js';
|
||||
export * from './publishable-workspace.context-token.js';
|
||||
export * from './routable-workspace-context.interface.js';
|
||||
export * from './saveable-workspace-context.interface.js';
|
||||
export * from './saveable-workspace.context-token.js';
|
||||
export * from './variant-workspace-context.token.js';
|
||||
export * from './workspace-collection-context.interface.js';
|
||||
export * from './workspace-collection-context.token.js';
|
||||
export * from './workspace-context.interface.js';
|
||||
export * from './workspace-context.token.js';
|
||||
export * from './workspace-invariantable-context.interface.js';
|
||||
export * from './workspace-variantable-context.interface.js';
|
||||
export * from './saveable-workspace-context-base.js';
|
||||
export * from './tokens/index.js';
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace-context.interface.js';
|
||||
|
||||
export interface UmbPublishableWorkspaceContextInterface extends UmbSaveableWorkspaceContextInterface {
|
||||
saveAndPublish(): Promise<void>;
|
||||
publish(): Promise<void>;
|
||||
unpublish(): Promise<void>;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type {
|
||||
UmbPublishableWorkspaceContextInterface,
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_PUBLISHABLE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbPublishableWorkspaceContextInterface
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbPublishableWorkspaceContextInterface => (context as any).publish !== undefined,
|
||||
);
|
||||
@@ -1,6 +0,0 @@
|
||||
import type { UmbWorkspaceRouteManager } from '../index.js';
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
|
||||
export interface UmbRoutableWorkspaceContext extends UmbWorkspaceContextInterface {
|
||||
readonly routes: UmbWorkspaceRouteManager;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UMB_WORKSPACE_CONTEXT } from './workspace-context.token.js';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace-context.interface.js';
|
||||
import { UmbWorkspaceRouteManager } from '../controllers/workspace-route-manager.controller.js';
|
||||
import { UMB_WORKSPACE_CONTEXT } from './tokens/workspace.context-token.js';
|
||||
import type { UmbSaveableWorkspaceContext } from './tokens/saveable-workspace-context.interface.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
|
||||
@@ -7,18 +8,22 @@ import type { UmbModalContext } from '@umbraco-cms/backoffice/modal';
|
||||
import { UMB_MODAL_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export abstract class UmbEditableWorkspaceContextBase<WorkspaceDataModelType>
|
||||
extends UmbContextBase<UmbEditableWorkspaceContextBase<WorkspaceDataModelType>>
|
||||
implements UmbSaveableWorkspaceContextInterface
|
||||
export abstract class UmbSaveableWorkspaceContextBase<WorkspaceDataModelType>
|
||||
extends UmbContextBase<UmbSaveableWorkspaceContextBase<WorkspaceDataModelType>>
|
||||
implements UmbSaveableWorkspaceContext
|
||||
{
|
||||
public readonly workspaceAlias: string;
|
||||
|
||||
// TODO: We could make a base type for workspace modal data, and use this here: As well as a base for the result, to make sure we always include the unique (instead of the object type)
|
||||
public readonly modalContext?: UmbModalContext<{ preset: object }>;
|
||||
|
||||
abstract readonly unique: Observable<string | null | undefined>;
|
||||
|
||||
#isNew = new UmbBooleanState(undefined);
|
||||
isNew = this.#isNew.asObservable();
|
||||
|
||||
readonly routes = new UmbWorkspaceRouteManager(this);
|
||||
|
||||
/*
|
||||
Concept notes: [NL]
|
||||
Considerations are, if we bring a dirty state (observable) we need to maintain it all the time.
|
||||
@@ -63,3 +68,11 @@ export abstract class UmbEditableWorkspaceContextBase<WorkspaceDataModelType>
|
||||
abstract save(): Promise<void>;
|
||||
abstract unique: Observable<string | undefined>;
|
||||
}
|
||||
|
||||
/*
|
||||
* @deprecated Use UmbSaveableWorkspaceContextBase instead — Will be removed before RC.
|
||||
* TODO: Delete before RC.
|
||||
*/
|
||||
export abstract class UmbEditableWorkspaceContextBase<
|
||||
WorkspaceDataModelType,
|
||||
> extends UmbSaveableWorkspaceContextBase<WorkspaceDataModelType> {}
|
||||
@@ -1,11 +0,0 @@
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export interface UmbSaveableWorkspaceContextInterface extends UmbWorkspaceContextInterface {
|
||||
unique: Observable<string | undefined>;
|
||||
isNew: Observable<boolean | undefined>;
|
||||
getIsNew(): boolean | undefined;
|
||||
save(): Promise<void>;
|
||||
setValidationErrors?(errorMap: any): void; // TODO: temp solution to bubble validation errors to the UI
|
||||
destroy(): void;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbWorkspaceContextInterface, UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_SAVEABLE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbSaveableWorkspaceContextInterface
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbSaveableWorkspaceContextInterface =>
|
||||
(context as UmbSaveableWorkspaceContextInterface).getIsNew !== undefined,
|
||||
);
|
||||
@@ -1,10 +1,16 @@
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import type { UmbEntityWorkspaceContext } from './entity-workspace-context.interface.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbContentTypeModel, UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type';
|
||||
|
||||
export interface UmbWorkspaceCollectionContextInterface<T extends UmbContentTypeModel>
|
||||
extends UmbWorkspaceContextInterface {
|
||||
export interface UmbCollectionWorkspaceContext<T extends UmbContentTypeModel> extends UmbEntityWorkspaceContext {
|
||||
contentTypeHasCollection: Observable<boolean>;
|
||||
getCollectionAlias(): string;
|
||||
structure: UmbContentTypeStructureManager<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use UmbCollectionWorkspaceContextInterface instead — Will be removed before RC.
|
||||
* TODO: Delete before RC.
|
||||
*/
|
||||
export interface UmbWorkspaceCollectionContextInterface<T extends UmbContentTypeModel>
|
||||
extends UmbCollectionWorkspaceContext<T> {}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type';
|
||||
import type { UmbWorkspaceContext, UmbCollectionWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_COLLECTION_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContext,
|
||||
UmbCollectionWorkspaceContext<UmbContentTypeModel>
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbCollectionWorkspaceContext<UmbContentTypeModel> =>
|
||||
(context as UmbCollectionWorkspaceContext<UmbContentTypeModel>).contentTypeHasCollection !== undefined,
|
||||
);
|
||||
|
||||
/**
|
||||
* @deprecated Use `UMB_COLLECTION_WORKSPACE_CONTEXT` instead. This token will be removed in the RC version.
|
||||
* TODO: Remove in RC
|
||||
*/
|
||||
export const UMB_WORKSPACE_COLLECTION_CONTEXT = UMB_COLLECTION_WORKSPACE_CONTEXT;
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import type { UmbWorkspaceUniqueType } from './../../types.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export interface UmbEntityWorkspaceContext extends UmbWorkspaceContext {
|
||||
unique: Observable<UmbWorkspaceUniqueType | undefined>;
|
||||
getUnique(): UmbWorkspaceUniqueType | undefined;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import type { UmbEntityWorkspaceContext } from './entity-workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_ENTITY_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbEntityWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbEntityWorkspaceContext => (context as any).getUnique !== undefined,
|
||||
);
|
||||
@@ -0,0 +1,16 @@
|
||||
export * from './collection-workspace.context-token.js';
|
||||
export * from './entity-workspace.context-token.js';
|
||||
export * from './publishable-workspace.context-token.js';
|
||||
export * from './routable-workspace.context-token.js';
|
||||
export * from './saveable-workspace.context-token.js';
|
||||
export * from './variant-workspace.context-token.js';
|
||||
export * from './workspace.context-token.js';
|
||||
export type * from './collection-workspace-context.interface.js';
|
||||
export type * from './entity-workspace-context.interface.js';
|
||||
export type * from './invariant-dataset-workspace-context.interface.js';
|
||||
export type * from './property-structure-workspace-context.interface.js';
|
||||
export type * from './publishable-workspace-context.interface.js';
|
||||
export type * from './routable-workspace-context.interface.js';
|
||||
export type * from './saveable-workspace-context.interface.js';
|
||||
export type * from './variant-dataset-workspace-context.interface.js';
|
||||
export type * from './workspace-context.interface.js';
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { UmbVariantId } from '../../variant/variant-id.class.js';
|
||||
import type { UmbPropertyDatasetContext } from '../../property/property-dataset/property-dataset-context.interface.js';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace-context.interface.js';
|
||||
import type { UmbVariantId } from '../../../variant/variant-id.class.js';
|
||||
import type { UmbPropertyDatasetContext } from '../../../property/property-dataset/property-dataset-context.interface.js';
|
||||
import type { UmbSaveableWorkspaceContext } from './saveable-workspace-context.interface.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export interface UmbInvariantableWorkspaceContextInterface extends UmbSaveableWorkspaceContextInterface {
|
||||
export interface UmbInvariantDatasetWorkspaceContext extends UmbSaveableWorkspaceContext {
|
||||
// Name:
|
||||
name: Observable<string | undefined>;
|
||||
getName(): string | undefined;
|
||||
@@ -17,3 +17,9 @@ export interface UmbInvariantableWorkspaceContextInterface extends UmbSaveableWo
|
||||
|
||||
createPropertyDatasetContext(host: UmbControllerHost, variantId?: UmbVariantId): UmbPropertyDatasetContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use UmbInvariantWorkspaceContextInterface instead — Will be removed before RC.
|
||||
* TODO: Delete before RC.
|
||||
*/
|
||||
export interface UmbInvariantableWorkspaceContextInterface extends UmbInvariantDatasetWorkspaceContext {}
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import type { UmbEntityWorkspaceContext } from './entity-workspace-context.interface.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { ValueModelBaseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
|
||||
export interface UmbPropertyStructureWorkspaceContextInterface extends UmbWorkspaceContextInterface {
|
||||
export interface UmbPropertyStructureWorkspaceContext extends UmbEntityWorkspaceContext {
|
||||
propertyStructureById(id: string): Promise<Observable<ValueModelBaseModel | undefined>>;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import type { UmbPropertyStructureWorkspaceContext } from './property-structure-workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContext,
|
||||
UmbPropertyStructureWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbPropertyStructureWorkspaceContext => 'propertyStructureById' in context,
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { UmbSaveableWorkspaceContext } from './saveable-workspace-context.interface.js';
|
||||
|
||||
export interface UmbPublishableWorkspaceContext extends UmbSaveableWorkspaceContext {
|
||||
saveAndPublish(): Promise<void>;
|
||||
publish(): Promise<void>;
|
||||
unpublish(): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbPublishableWorkspaceContext, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_PUBLISHABLE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContext,
|
||||
UmbPublishableWorkspaceContext
|
||||
>('UmbWorkspaceContext', undefined, (context): context is UmbPublishableWorkspaceContext => 'publish' in context);
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { UmbWorkspaceRouteManager } from '../../index.js';
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
|
||||
export interface UmbRoutableWorkspaceContext extends UmbWorkspaceContext {
|
||||
readonly routes: UmbWorkspaceRouteManager;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { UmbRoutableWorkspaceContext } from './routable-workspace-context.interface.js';
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_ROUTABLE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbRoutableWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbRoutableWorkspaceContext => 'routes' in context,
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { UmbEntityWorkspaceContext } from './entity-workspace-context.interface.js';
|
||||
import type { UmbRoutableWorkspaceContext } from './routable-workspace-context.interface.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export interface UmbSaveableWorkspaceContext extends UmbEntityWorkspaceContext, UmbRoutableWorkspaceContext {
|
||||
isNew: Observable<boolean | undefined>;
|
||||
getIsNew(): boolean | undefined;
|
||||
save(): Promise<void>;
|
||||
destroy(): void;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `UmbSaveableWorkspaceContext` instead. This token will be removed in the RC version.
|
||||
* TODO: Remove in RC
|
||||
*/
|
||||
export interface UmbSaveableWorkspaceContextInterface extends UmbSaveableWorkspaceContext {}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbWorkspaceContext, UmbSaveableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_SAVEABLE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbSaveableWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbSaveableWorkspaceContext => 'getIsNew' in context,
|
||||
);
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { UmbWorkspaceSplitViewManager } from '../controllers/workspace-split-view-manager.controller.js';
|
||||
import type { UmbPropertyDatasetContext } from '../../property/property-dataset/property-dataset-context.interface.js';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace-context.interface.js';
|
||||
import type { UmbWorkspaceSplitViewManager } from '../../controllers/workspace-split-view-manager.controller.js';
|
||||
import type { UmbPropertyDatasetContext } from '../../../property/property-dataset/property-dataset-context.interface.js';
|
||||
import type { UmbSaveableWorkspaceContext } from './saveable-workspace-context.interface.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbVariantId, UmbVariantModel, UmbVariantOptionModel } from '@umbraco-cms/backoffice/variant';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export interface UmbVariantableWorkspaceContextInterface<VariantType extends UmbVariantModel = UmbVariantModel>
|
||||
extends UmbSaveableWorkspaceContextInterface {
|
||||
export interface UmbVariantDatasetWorkspaceContext<VariantType extends UmbVariantModel = UmbVariantModel>
|
||||
extends UmbSaveableWorkspaceContext {
|
||||
// Name:
|
||||
getName(variantId?: UmbVariantId): string | undefined;
|
||||
setName(name: string, variantId?: UmbVariantId): void;
|
||||
@@ -19,14 +19,19 @@ export interface UmbVariantableWorkspaceContextInterface<VariantType extends Umb
|
||||
getVariant(variantId: UmbVariantId): UmbVariantModel | undefined;
|
||||
|
||||
// Property:
|
||||
// This one is async cause it needs to structure to provide this data:
|
||||
// This one is async cause it needs to structure to provide this data: [NL]
|
||||
propertyValueByAlias<ReturnValue = unknown>(
|
||||
alias: string,
|
||||
variantId?: UmbVariantId,
|
||||
): Promise<Observable<ReturnValue | undefined> | undefined>;
|
||||
getPropertyValue<ReturnValue = unknown>(alias: string, variantId?: UmbVariantId): ReturnValue | undefined;
|
||||
setPropertyValue(alias: string, value: unknown, variantId?: UmbVariantId): Promise<void>;
|
||||
//propertyDataByAlias(alias: string, variantId?: UmbVariantId): Observable<ValueModelBaseModel | undefined>;
|
||||
|
||||
createPropertyDatasetContext(host: UmbControllerHost, variantId?: UmbVariantId): UmbPropertyDatasetContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use UmbVariantWorkspaceContextInterface instead — Will be removed before RC.
|
||||
* TODO: Delete before RC.
|
||||
*/
|
||||
export interface UmbVariantableWorkspaceContextInterface extends UmbVariantDatasetWorkspaceContext {}
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import type { UmbVariantDatasetWorkspaceContext } from './variant-dataset-workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_VARIANT_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContext,
|
||||
UmbVariantDatasetWorkspaceContext
|
||||
>('UmbWorkspaceContext', undefined, (context): context is UmbVariantDatasetWorkspaceContext => 'variants' in context);
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface UmbWorkspaceContext extends UmbApi {
|
||||
readonly workspaceAlias: string;
|
||||
getEntityType(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use UmbWorkspaceContext instead — Will be removed before RC.
|
||||
* Notice if you have complains on missing `getUnique()` then you need to use UmbEntityWorkspaceContext instead.
|
||||
* TODO: Delete before RC.
|
||||
*/
|
||||
export interface UmbWorkspaceContextInterface extends UmbWorkspaceContext {}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import type { UmbWorkspaceContext } from './workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContextInterface>('UmbWorkspaceContext');
|
||||
export const UMB_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext>('UmbWorkspaceContext');
|
||||
@@ -1,12 +0,0 @@
|
||||
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
|
||||
import type { UmbVariantableWorkspaceContextInterface } from './workspace-variantable-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_VARIANT_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbVariantableWorkspaceContextInterface
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context,
|
||||
);
|
||||
@@ -1,16 +0,0 @@
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type';
|
||||
import type {
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbWorkspaceCollectionContextInterface,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_WORKSPACE_COLLECTION_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbWorkspaceCollectionContextInterface<UmbContentTypeModel>
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbWorkspaceCollectionContextInterface<UmbContentTypeModel> =>
|
||||
(context as UmbWorkspaceCollectionContextInterface<UmbContentTypeModel>).contentTypeHasCollection !== undefined,
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface UmbWorkspaceContextInterface extends UmbApi {
|
||||
readonly workspaceAlias: string;
|
||||
getEntityType(): string;
|
||||
getUnique(): string | undefined;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbEditableWorkspaceContextBase } from '../contexts/index.js';
|
||||
import type { UmbSaveableWorkspaceContextBase } from '../contexts/index.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { createRoutePathBuilder, type UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
|
||||
@@ -16,7 +16,7 @@ import { ensurePathEndsWithSlash } from '@umbraco-cms/backoffice/utils';
|
||||
export class UmbWorkspaceIsNewRedirectController extends UmbControllerBase {
|
||||
constructor(
|
||||
host: UmbControllerHost,
|
||||
workspaceContext: UmbEditableWorkspaceContextBase<unknown>,
|
||||
workspaceContext: UmbSaveableWorkspaceContextBase<unknown>,
|
||||
router: UmbRouterSlotElement,
|
||||
) {
|
||||
super(host, 'isNewRedirectController');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export * from './components/index.js';
|
||||
export * from './contexts/index.js';
|
||||
export * from './controllers/index.js';
|
||||
export type * from './conditions/index.js';
|
||||
export * from './modals/index.js';
|
||||
export * from './workspace-property-dataset/index.js';
|
||||
export type * from './conditions/index.js';
|
||||
export type * from './types.js';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { UmbSaveableWorkspaceContext } from '../../contexts/tokens/saveable-workspace-context.interface.js';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
|
||||
import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
@customElement('umb-editable-workspace')
|
||||
export class UmbEditableWorkspaceElement extends UmbLitElement {
|
||||
@state()
|
||||
_routes: UmbRoute[] = [];
|
||||
|
||||
public set api(api: UmbSaveableWorkspaceContext) {
|
||||
this.observe(api.routes.routes, (routes) => (this._routes = routes));
|
||||
|
||||
new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [api]);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<uui-form>
|
||||
<form>
|
||||
<umb-router-slot .routes="${this._routes}"></umb-router-slot>
|
||||
</form>
|
||||
</uui-form>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbEditableWorkspaceElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-editable-workspace': UmbEditableWorkspaceElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifest: UmbBackofficeManifestKind = {
|
||||
type: 'kind',
|
||||
alias: 'Umb.Kind.Workspace.Editable',
|
||||
matchKind: 'editable',
|
||||
matchType: 'workspace',
|
||||
manifest: {
|
||||
type: 'workspace',
|
||||
kind: 'editable',
|
||||
element: () => import('./editable-workspace.element.js'),
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
import { UmbEditableWorkspaceElement } from './editable-workspace.element.js';
|
||||
import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
||||
|
||||
describe('UmbEditableWorkspaceElement', () => {
|
||||
let element: UmbEditableWorkspaceElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
element = await fixture(html`<umb-editable-workspace></umb-editable-workspace>`);
|
||||
});
|
||||
|
||||
it('is defined with its own instance', () => {
|
||||
expect(element).to.be.instanceOf(UmbEditableWorkspaceElement);
|
||||
});
|
||||
|
||||
if ((window as UmbTestRunnerWindow).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||
it('passes the a11y audit', async () => {
|
||||
// TODO: should we use shadowDom here?
|
||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,3 +1,3 @@
|
||||
import { manifest as routableKindManifest } from './routable-workspace.kind.js';
|
||||
import { manifest as routableKindManifest } from './routable/routable-workspace.kind.js';
|
||||
|
||||
export const manifests = [routableKindManifest];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbRoutableWorkspaceContext } from '../contexts/routable-workspace-context.interface.js';
|
||||
import type { UmbRoutableWorkspaceContext } from '../../contexts/tokens/routable-workspace-context.interface.js';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
@@ -0,0 +1 @@
|
||||
export type UmbWorkspaceUniqueType = string | null;
|
||||
@@ -3,13 +3,13 @@ import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
import type { UmbInvariantableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbInvariantDatasetWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
/**
|
||||
* A property dataset context that hooks directly into the workspace context.
|
||||
*/
|
||||
export class UmbInvariantWorkspacePropertyDatasetContext<
|
||||
WorkspaceType extends UmbInvariantableWorkspaceContextInterface = UmbInvariantableWorkspaceContextInterface,
|
||||
WorkspaceType extends UmbInvariantDatasetWorkspaceContext = UmbInvariantDatasetWorkspaceContext,
|
||||
>
|
||||
extends UmbContextBase<UmbPropertyDatasetContext>
|
||||
implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext
|
||||
|
||||
@@ -5,6 +5,7 @@ import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection';
|
||||
import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
/**
|
||||
* A data source that fetches the data-type collection data from the server.
|
||||
@@ -14,6 +15,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
*/
|
||||
export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataSource<UmbDataTypeItemModel> {
|
||||
#host: UmbControllerHost;
|
||||
#manifestPropertyEditorUis: Array<ManifestPropertyEditorUi> = [];
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDataTypeCollectionServerDataSource.
|
||||
@@ -22,6 +24,12 @@ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataS
|
||||
*/
|
||||
constructor(host: UmbControllerHost) {
|
||||
this.#host = host;
|
||||
umbExtensionsRegistry
|
||||
.byType('propertyEditorUi')
|
||||
.subscribe((manifestPropertyEditorUIs) => {
|
||||
this.#manifestPropertyEditorUis = manifestPropertyEditorUIs;
|
||||
})
|
||||
.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +56,7 @@ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataS
|
||||
unique: item.id,
|
||||
name: item.name,
|
||||
propertyEditorUiAlias: item.editorUiAlias!,
|
||||
icon: this.#manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias!)?.meta.icon,
|
||||
};
|
||||
|
||||
return dataTypeDetail;
|
||||
|
||||
@@ -78,8 +78,6 @@ export class UmbInputDataTypeElement extends FormControlMixin(UmbLitElement) {
|
||||
this.#editDataTypeModal?.open({}, 'edit/' + this._ids![0]);
|
||||
}}
|
||||
standalone>
|
||||
<!-- TODO: Get the icon from property editor UI -->
|
||||
<uui-icon name="${'document'}" slot="icon"></uui-icon>
|
||||
<uui-action-bar slot="actions">
|
||||
<uui-button label="Change" .href=${this._createRoute}></uui-button>
|
||||
</uui-action-bar>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { UmbDataTypeDetailRepository } from '../../repository/detail/data-type-detail.repository.js';
|
||||
import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UUIIconRequestEvent, UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
/**
|
||||
* @element umb-ref-data-type
|
||||
@@ -10,8 +11,10 @@ import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
*/
|
||||
@customElement('umb-ref-data-type')
|
||||
export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) {
|
||||
@state()
|
||||
protected fallbackIcon =
|
||||
'<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M142.212 397.267l106.052-48.024L398.479 199.03l-26.405-26.442-90.519 90.517-15.843-15.891 90.484-90.486-16.204-16.217-150.246 150.243-47.534 106.513zm74.904-100.739l23.285-23.283 3.353 22.221 22.008 3.124-23.283 23.313-46.176 20.991 20.813-46.366zm257.6-173.71L416.188 64.3l-49.755 49.785 58.504 58.503 49.779-49.77zM357.357 300.227h82.826v116.445H68.929V300.227h88.719v-30.648H38.288v177.733h432.537V269.578H357.357v30.649z"></path></svg>';
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M255.981 440.734c-4.422 0-8.895-.159-13.293-.471l1.682-23.62c15.395 1.095 31.076-.014 46.053-3.277l5.039 23.137a185.943 185.943 0 0 1-39.481 4.231zm-43.253-5.094a183.61 183.61 0 0 1-49.174-19.657l11.864-20.49a159.927 159.927 0 0 0 42.833 17.123l-5.523 23.024zm111.734-8.02l-8.781-21.991a160.553 160.553 0 0 0 39.949-23.097l14.666 18.593a184.376 184.376 0 0 1-45.834 26.495zm-185.815-28.926a185.575 185.575 0 0 1-35.652-39.114l19.596-13.293a161.956 161.956 0 0 0 31.105 34.125l-15.049 18.282zm253.834-18.216l-17.492-15.96a161.321 161.321 0 0 0 25.924-38.192l21.297 10.353a184.986 184.986 0 0 1-29.729 43.799zM88.097 333.183a183.381 183.381 0 0 1-14.977-50.791l23.438-3.355a159.869 159.869 0 0 0 13.047 44.243l-21.508 9.903zm345.082-24.798l-22.711-6.705c4.355-14.761 6.566-30.131 6.566-45.679h23.678c0 17.818-2.533 35.444-7.533 52.384zM94.96 252.634l-23.672-.483c.365-17.809 3.266-35.378 8.625-52.224l22.566 7.181c-4.671 14.677-7.203 29.996-7.519 45.526zm320.881-16.346a159.854 159.854 0 0 0-12.115-44.503l21.713-9.45a183.696 183.696 0 0 1 13.908 51.088l-23.506 2.865zM112.546 182.67l-21.072-10.798a184.915 184.915 0 0 1 30.633-43.168l17.154 16.319a161.599 161.599 0 0 0-26.715 37.647zm278.68-14.155a161.801 161.801 0 0 0-30.389-34.763l15.426-17.966a185.512 185.512 0 0 1 34.832 39.846l-19.869 12.883zm-232.239-41.101l-14.273-18.894a184.318 184.318 0 0 1 46.375-25.533l8.322 22.169a160.705 160.705 0 0 0-40.424 22.258zm180.444-9.19a160.053 160.053 0 0 0-42.466-18.02l6.009-22.903a183.633 183.633 0 0 1 48.748 20.684l-12.291 20.239zM224.825 97.956l-4.553-23.239a186.147 186.147 0 0 1 35.705-3.45h.004c5.711 0 11.473.266 17.129.786l-2.174 23.58c-15.306-1.414-31.072-.624-46.111 2.323z"/></svg>`;
|
||||
//icon-circle-dotted.svg
|
||||
|
||||
@property({ type: String, attribute: 'data-type-id' })
|
||||
public get dataTypeId(): string | undefined {
|
||||
@@ -28,8 +31,11 @@ export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) {
|
||||
(dataType) => {
|
||||
if (dataType) {
|
||||
this.name = dataType.name ?? '';
|
||||
this.propertyEditorUiAlias = dataType.editorUiAlias ?? '';
|
||||
this.propertyEditorSchemaAlias = dataType.editorAlias ?? '';
|
||||
if (dataType.editorUiAlias ?? '' !== this.propertyEditorUiAlias) {
|
||||
this.propertyEditorUiAlias = dataType.editorUiAlias ?? '';
|
||||
this.#getIconFromUiAlias();
|
||||
}
|
||||
}
|
||||
},
|
||||
'dataType',
|
||||
@@ -53,6 +59,37 @@ export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) {
|
||||
@state()
|
||||
propertyEditorSchemaAlias = '';
|
||||
|
||||
async #getIconFromUiAlias() {
|
||||
if (!this.propertyEditorUiAlias) return;
|
||||
this.observe(
|
||||
umbExtensionsRegistry.byTypeAndAlias('propertyEditorUi', this.propertyEditorUiAlias),
|
||||
async (manifestPropertyEditorUi) => {
|
||||
const icon = manifestPropertyEditorUi?.meta.icon;
|
||||
/** [LI] We have the icon name now, but because this element extends from uui-ref-node, it wants the icon via the icon slot.
|
||||
* From what I can see, this is not possible via this file, but this is the file that have the datatype data....
|
||||
* Instead, overwriting the fallbackIcon property which requires a SVG... */
|
||||
if (icon) {
|
||||
this.#requestIconSVG(icon);
|
||||
}
|
||||
},
|
||||
),
|
||||
'_observeIcon';
|
||||
}
|
||||
|
||||
#requestIconSVG(iconName: string) {
|
||||
if (iconName !== '' && iconName !== null) {
|
||||
const event = new UUIIconRequestEvent(UUIIconRequestEvent.ICON_REQUEST, {
|
||||
detail: { iconName: iconName },
|
||||
});
|
||||
this.dispatchEvent(event);
|
||||
if (event.icon !== null) {
|
||||
event.icon.then((iconSvg: string) => {
|
||||
this.fallbackIcon = iconSvg;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected renderDetail() {
|
||||
const details: string[] = [];
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ export class UmbDataTypePickerFlowDataTypePickerModalElement extends UmbModalBas
|
||||
? html` <li class="item">
|
||||
<uui-button label="dataType.name" type="button" @click="${() => this._handleClick(dataType)}">
|
||||
<div class="item-content">
|
||||
<uui-icon name="${'icon-bug'}" class="icon"></uui-icon>
|
||||
<umb-icon name=${dataType.icon ?? 'icon-circle-dotted'} class="icon"></umb-icon>
|
||||
${dataType.name}
|
||||
</div>
|
||||
</uui-button>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { UmbDataTypeTreeRepository } from '../../tree/data-type-tree.repository.js';
|
||||
import { UMB_DATATYPE_WORKSPACE_MODAL } from '../../workspace/data-type-workspace.modal-token.js';
|
||||
import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js';
|
||||
import { UmbDataTypeCollectionRepository } from '../../collection/index.js';
|
||||
@@ -275,10 +274,10 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement<
|
||||
dataTypes,
|
||||
(dataType) => dataType.unique,
|
||||
(dataType) =>
|
||||
html`<li class="item" ?selected=${this.value.selection.includes(dataType.unique)}>
|
||||
html` <li class="item" ?selected=${this.value.selection.includes(dataType.unique)}>
|
||||
<uui-button .label=${dataType.name} type="button" @click="${() => this._handleDataTypeClick(dataType)}">
|
||||
<div class="item-content">
|
||||
<uui-icon name="${'icon-bug'}" class="icon"></uui-icon>
|
||||
<umb-icon name=${dataType.icon ?? 'icon-circle-dotted'} class="icon"></umb-icon>
|
||||
${dataType.name}
|
||||
</div>
|
||||
</uui-button>
|
||||
|
||||
@@ -3,6 +3,9 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
|
||||
import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
let manifestPropertyEditorUis: Array<ManifestPropertyEditorUi> = [];
|
||||
|
||||
/**
|
||||
* A server data source for Data Type items
|
||||
@@ -19,11 +22,19 @@ export class UmbDataTypeItemServerDataSource extends UmbItemServerDataSourceBase
|
||||
* @param {UmbControllerHost} host
|
||||
* @memberof UmbDataTypeItemServerDataSource
|
||||
*/
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, {
|
||||
getItems,
|
||||
mapper,
|
||||
});
|
||||
|
||||
umbExtensionsRegistry
|
||||
.byType('propertyEditorUi')
|
||||
.subscribe((manifestPropertyEditorUIs) => {
|
||||
manifestPropertyEditorUis = manifestPropertyEditorUIs;
|
||||
})
|
||||
.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +46,6 @@ const mapper = (item: DataTypeItemResponseModel): UmbDataTypeItemModel => {
|
||||
unique: item.id,
|
||||
name: item.name,
|
||||
propertyEditorUiAlias: item.editorUiAlias || '', // TODO: why can this be undefined or null on the server?
|
||||
icon: manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias)?.meta.icon,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,5 @@ export interface UmbDataTypeItemModel {
|
||||
unique: string;
|
||||
name: string;
|
||||
propertyEditorUiAlias: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
|
||||
import type { DataTypeTreeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
let manifestPropertyEditorUis: Array<ManifestPropertyEditorUi> = [];
|
||||
|
||||
/**
|
||||
* A data source for a data type tree that fetches data from the server
|
||||
@@ -31,12 +34,19 @@ export class UmbDataTypeTreeServerDataSource extends UmbTreeServerDataSourceBase
|
||||
getAncestorsOf,
|
||||
mapper,
|
||||
});
|
||||
umbExtensionsRegistry
|
||||
.byType('propertyEditorUi')
|
||||
.subscribe((manifestPropertyEditorUIs) => {
|
||||
manifestPropertyEditorUis = manifestPropertyEditorUIs;
|
||||
})
|
||||
.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
const getRootItems = (args: UmbTreeRootItemsRequestArgs) =>
|
||||
const getRootItems = async (args: UmbTreeRootItemsRequestArgs) => {
|
||||
// eslint-disable-next-line local-rules/no-direct-api-import
|
||||
DataTypeResource.getTreeDataTypeRoot({ skip: args.skip, take: args.take });
|
||||
return DataTypeResource.getTreeDataTypeRoot({ skip: args.skip, take: args.take });
|
||||
};
|
||||
|
||||
const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => {
|
||||
if (args.parentUnique === null) {
|
||||
@@ -59,6 +69,7 @@ const mapper = (item: DataTypeTreeItemResponseModel): UmbDataTypeTreeItemModel =
|
||||
return {
|
||||
unique: item.id,
|
||||
parentUnique: item.parent?.id || null,
|
||||
icon: manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias)?.meta.icon,
|
||||
name: item.name,
|
||||
entityType: item.isFolder ? 'data-type-folder' : 'data-type',
|
||||
isFolder: item.isFolder,
|
||||
|
||||
@@ -23,7 +23,7 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement {
|
||||
|
||||
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => {
|
||||
this.#workspaceContext = workspaceContext;
|
||||
this.#workspaceContext?.createPropertyDatasetContext(this);
|
||||
this.#workspaceContext.createPropertyDatasetContext(this);
|
||||
this.#observeIsNew();
|
||||
this.#observeName();
|
||||
});
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import type { UmbDataTypeWorkspaceContext } from './data-type-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbDataTypeWorkspaceContext
|
||||
>(
|
||||
export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbDataTypeWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type',
|
||||
|
||||
@@ -3,11 +3,11 @@ import type { UmbDataTypeDetailModel } from '../types.js';
|
||||
import { UmbDataTypeWorkspaceEditorElement } from './data-type-workspace-editor.element.js';
|
||||
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import type {
|
||||
UmbInvariantableWorkspaceContextInterface,
|
||||
UmbInvariantDatasetWorkspaceContext,
|
||||
UmbRoutableWorkspaceContext,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
UmbInvariantWorkspacePropertyDatasetContext,
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
UmbWorkspaceRouteManager,
|
||||
@@ -32,8 +32,8 @@ import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice
|
||||
|
||||
type EntityType = UmbDataTypeDetailModel;
|
||||
export class UmbDataTypeWorkspaceContext
|
||||
extends UmbEditableWorkspaceContextBase<EntityType>
|
||||
implements UmbInvariantableWorkspaceContextInterface, UmbRoutableWorkspaceContext
|
||||
extends UmbSaveableWorkspaceContextBase<EntityType>
|
||||
implements UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext
|
||||
{
|
||||
//
|
||||
public readonly repository: UmbDataTypeDetailRepository = new UmbDataTypeDetailRepository(this);
|
||||
@@ -348,6 +348,11 @@ export class UmbDataTypeWorkspaceContext
|
||||
this.workspaceComplete(this.#currentData.value);
|
||||
}
|
||||
|
||||
protected workspaceComplete(data: EntityType | undefined) {
|
||||
this.dispatchEvent(new CustomEvent('workspace-complete'));
|
||||
super.workspaceComplete(data);
|
||||
}
|
||||
|
||||
async delete(unique: string) {
|
||||
await this.repository.delete(unique);
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ export const manifests = [
|
||||
type: 'menu',
|
||||
alias: UMB_DICTIONARY_MENU_ALIAS,
|
||||
name: 'Dictionary Menu',
|
||||
meta: {
|
||||
label: 'Dictionary',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'menuItem',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { UmbDictionaryWorkspaceContext } from './dictionary-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbSaveableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbSaveableWorkspaceContext,
|
||||
UmbDictionaryWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
|
||||
@@ -2,8 +2,8 @@ import { UmbDictionaryDetailRepository } from '../repository/index.js';
|
||||
import type { UmbDictionaryDetailModel } from '../types.js';
|
||||
import { UmbDictionaryWorkspaceEditorElement } from './dictionary-workspace-editor.element.js';
|
||||
import {
|
||||
type UmbSaveableWorkspaceContextInterface,
|
||||
UmbEditableWorkspaceContextBase,
|
||||
type UmbSaveableWorkspaceContext,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
UmbWorkspaceRouteManager,
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
type UmbRoutableWorkspaceContext,
|
||||
@@ -15,8 +15,8 @@ import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
|
||||
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
|
||||
|
||||
export class UmbDictionaryWorkspaceContext
|
||||
extends UmbEditableWorkspaceContextBase<UmbDictionaryDetailModel>
|
||||
implements UmbSaveableWorkspaceContextInterface, UmbRoutableWorkspaceContext
|
||||
extends UmbSaveableWorkspaceContextBase<UmbDictionaryDetailModel>
|
||||
implements UmbSaveableWorkspaceContext, UmbRoutableWorkspaceContext
|
||||
{
|
||||
//
|
||||
public readonly detailRepository = new UmbDictionaryDetailRepository(this);
|
||||
@@ -26,6 +26,7 @@ export class UmbDictionaryWorkspaceContext
|
||||
|
||||
#data = new UmbObjectState<UmbDictionaryDetailModel | undefined>(undefined);
|
||||
readonly data = this.#data.asObservable();
|
||||
|
||||
readonly unique = this.#data.asObservablePart((data) => data?.unique);
|
||||
readonly name = this.#data.asObservablePart((data) => data?.name);
|
||||
readonly dictionary = this.#data.asObservablePart((data) => data);
|
||||
|
||||
@@ -9,7 +9,7 @@ const menuItem: ManifestMenuItem = {
|
||||
label: 'Document Blueprints',
|
||||
icon: 'icon-blueprint',
|
||||
entityType: 'document-blueprint-root',
|
||||
menus: ['Umb.Menu.Settings'],
|
||||
menus: ['Umb.Menu.StructureSettings'],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { UmbDocumentTypeWorkspaceContext } from './document-type-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbSaveableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbSaveableWorkspaceContext,
|
||||
UmbDocumentTypeWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { UmbDocumentTypeDetailModel } from '../types.js';
|
||||
import { UmbDocumentTypeWorkspaceEditorElement } from './document-type-workspace-editor.element.js';
|
||||
import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbSaveableWorkspaceContextBase,
|
||||
type UmbRoutableWorkspaceContext,
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
UmbWorkspaceRouteManager,
|
||||
@@ -23,7 +23,7 @@ import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice
|
||||
|
||||
type EntityType = UmbDocumentTypeDetailModel;
|
||||
export class UmbDocumentTypeWorkspaceContext
|
||||
extends UmbEditableWorkspaceContextBase<EntityType>
|
||||
extends UmbSaveableWorkspaceContextBase<EntityType>
|
||||
implements UmbContentTypeWorkspaceContext<EntityType>, UmbRoutableWorkspaceContext
|
||||
{
|
||||
readonly IS_CONTENT_TYPE_WORKSPACE_CONTEXT = true;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import type { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js';
|
||||
import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from '../../document-type-workspace.context-token.js';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import type { UUIToggleElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@customElement('umb-document-type-workspace-view-settings')
|
||||
export class UmbDocumentTypeWorkspaceViewSettingsElement extends UmbLitElement implements UmbWorkspaceViewElement {
|
||||
#workspaceContext?: UmbDocumentTypeWorkspaceContext;
|
||||
#workspaceContext?: typeof UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT.TYPE;
|
||||
|
||||
@state()
|
||||
private _variesByCulture?: boolean;
|
||||
@@ -21,8 +20,8 @@ export class UmbDocumentTypeWorkspaceViewSettingsElement extends UmbLitElement i
|
||||
super();
|
||||
|
||||
// TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.#workspaceContext = documentTypeContext as UmbDocumentTypeWorkspaceContext;
|
||||
this.consumeContext(UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.#workspaceContext = documentTypeContext;
|
||||
this._observeDocumentType();
|
||||
});
|
||||
}
|
||||
@@ -47,7 +46,7 @@ export class UmbDocumentTypeWorkspaceViewSettingsElement extends UmbLitElement i
|
||||
<div slot="description">Allow editors to create content of different languages.</div>
|
||||
<div slot="editor">
|
||||
<uui-toggle
|
||||
.checked=${this._variesByCulture}
|
||||
?checked=${this._variesByCulture}
|
||||
@change=${(e: CustomEvent) => {
|
||||
this.#workspaceContext?.setVariesByCulture((e.target as UUIToggleElement).checked);
|
||||
}}
|
||||
@@ -58,7 +57,7 @@ export class UmbDocumentTypeWorkspaceViewSettingsElement extends UmbLitElement i
|
||||
<div slot="description">Allow editors to segment their content.</div>
|
||||
<div slot="editor">
|
||||
<uui-toggle
|
||||
.checked=${this._variesBySegment}
|
||||
?checked=${this._variesBySegment}
|
||||
@change=${(e: CustomEvent) => {
|
||||
this.#workspaceContext?.setVariesBySegment((e.target as UUIToggleElement).checked);
|
||||
}}
|
||||
@@ -71,7 +70,7 @@ export class UmbDocumentTypeWorkspaceViewSettingsElement extends UmbLitElement i
|
||||
</div>
|
||||
<div slot="editor">
|
||||
<uui-toggle
|
||||
.checked=${this._isElement}
|
||||
?checked=${this._isElement}
|
||||
@change=${(e: CustomEvent) => {
|
||||
this.#workspaceContext?.setIsElement((e.target as UUIToggleElement).checked);
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js';
|
||||
import type { UmbInputDocumentTypeElement } from '../../../components/input-document-type/input-document-type.element.js';
|
||||
import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from '../../document-type-workspace.context-token.js';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbContentTypeSortModel } from '@umbraco-cms/backoffice/content-type';
|
||||
import type { UmbInputCollectionConfigurationElement } from '@umbraco-cms/backoffice/components';
|
||||
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
@@ -26,7 +26,7 @@ export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement
|
||||
super();
|
||||
|
||||
// TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.consumeContext(UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.#workspaceContext = documentTypeContext as UmbDocumentTypeWorkspaceContext;
|
||||
this._observeDocumentType();
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js';
|
||||
import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from '../../document-type-workspace.context-token.js';
|
||||
import type { UmbInputTemplateElement } from '@umbraco-cms/backoffice/template';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
import '@umbraco-cms/backoffice/template'; // TODO: This is needed to register the <umb-input-template> element, but it should be done in a better way without importing the whole module.
|
||||
@@ -20,7 +20,7 @@ export class UmbDocumentTypeWorkspaceViewTemplatesElement extends UmbLitElement
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.consumeContext(UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT, (documentTypeContext) => {
|
||||
this.#workspaceContext = documentTypeContext as UmbDocumentTypeWorkspaceContext;
|
||||
this._observeDocumentType();
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
|
||||
import type { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbSaveableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbSaveableWorkspaceContext,
|
||||
UmbDocumentWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user