Merge branch 'main' into chore/uui-1.5.0-rc.0

This commit is contained in:
Jacob Overgaard
2023-10-18 09:54:05 +02:00
committed by GitHub
5 changed files with 157 additions and 174 deletions

View File

@@ -1,8 +1,6 @@
import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
import {
PropertyEditorConfigProperty,
} from '@umbraco-cms/backoffice/extension-registry';
import { html, customElement, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_DATA_TYPE_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/data-type';
@@ -14,53 +12,46 @@ import { UMB_DATA_TYPE_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/data-type
*/
@customElement('umb-property-editor-config')
export class UmbPropertyEditorConfigElement extends UmbLitElement {
// TODO: Make this element generic, so its not bound to DATA-TYPEs. This will require moving some functionality of Data-Type-Context to this. and this might need to self provide a variant Context for its inner property editor UIs.
#variantContext?: typeof UMB_DATA_TYPE_VARIANT_CONTEXT.TYPE;
/**
* Data. The element will render configuration editors with values from this data.
* If a value is not found in this data, the element will use the default value from the configuration.
* @type {Array<{ alias: string; value: unknown }>}
* @attr
* @default []
*/
@property({ type: Array })
public data: Array<{ alias: string; value: unknown }> = [];
@state()
private _properties: Array<PropertyEditorConfigProperty> = [];
constructor() {
super();
this.consumeContext(UMB_DATA_TYPE_VARIANT_CONTEXT, (instance) => {
this.#variantContext = instance;
this.observe(this.#variantContext.properties, (properties) => {
this._properties = properties as Array<PropertyEditorConfigProperty>;
}, 'observeProperties');
this.#observeProperties();
});
}
#observeProperties() {
if (!this.#variantContext) return;
this.observe(
this.#variantContext.properties,
(properties) => {
this._properties = properties as Array<PropertyEditorConfigProperty>;
},
'observeProperties',
);
}
render() {
return html`
${this._properties.length > 0
? html`
${this._properties?.map(
(property) => html`
<umb-workspace-property
label="${property.label}"
description="${ifDefined(property.description)}"
alias="${property.alias}"
property-editor-ui-alias="${property.propertyEditorUiAlias}"
.config=${property.config}></umb-workspace-property>
`
)}
`
: html`<div>No configuration</div>`}
`;
return this._properties.length > 0
? repeat(
this._properties,
(property) => property.alias,
(property) =>
html`<umb-workspace-property
label="${property.label}"
description="${ifDefined(property.description)}"
alias="${property.alias}"
property-editor-ui-alias="${property.propertyEditorUiAlias}"
.config=${property.config}></umb-workspace-property>`,
)
: html`<div>No configuration</div>`;
}
static styles = [UmbTextStyles];

View File

@@ -3,7 +3,7 @@ import type { ManifestPropertyEditorSchema } from '@umbraco-cms/backoffice/exten
export const manifest: ManifestPropertyEditorSchema = {
type: 'propertyEditorSchema',
name: 'Checkbox List',
alias: 'Umbraco.CheckboxList',
alias: 'Umbraco.CheckBoxList',
meta: {
defaultPropertyEditorUiAlias: 'Umb.PropertyEditorUi.CheckboxList',
},

View File

@@ -1,12 +1,25 @@
import { UmbDataTypeRepository } from '../repository/data-type.repository.js';
import { UmbDataTypeVariantContext } from '../variant-context/data-type-variant-context.js';
import { UmbInvariantableWorkspaceContextInterface, UmbWorkspaceContext, UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
import {
UmbInvariantableWorkspaceContextInterface,
UmbWorkspaceContext,
UmbWorkspaceContextInterface,
} from '@umbraco-cms/backoffice/workspace';
import type { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { appendToFrozenArray, UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import {
appendToFrozenArray,
UmbArrayState,
UmbObjectState,
UmbStringState,
} from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHost, UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { Observable, combineLatest, map } from '@umbraco-cms/backoffice/external/rxjs';
import { PropertyEditorConfigDefaultData, PropertyEditorConfigProperty, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import {
PropertyEditorConfigDefaultData,
PropertyEditorConfigProperty,
umbExtensionsRegistry,
} from '@umbraco-cms/backoffice/extension-registry';
import { UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT } from '@umbraco-cms/backoffice/property-editor';
export class UmbDataTypeWorkspaceContext
@@ -30,64 +43,99 @@ export class UmbDataTypeWorkspaceContext
private _propertyEditorSchemaConfigDefaultData: Array<PropertyEditorConfigDefaultData> = [];
private _propertyEditorUISettingsDefaultData: Array<PropertyEditorConfigDefaultData> = [];
private _propertyEditorSchemaConfigProperties?: Array<PropertyEditorConfigProperty>;
private _propertyEditorUISettingsProperties?: Array<PropertyEditorConfigProperty>;
private _propertyEditorSchemaConfigProperties: Array<PropertyEditorConfigProperty> = [];
private _propertyEditorUISettingsProperties: Array<PropertyEditorConfigProperty> = [];
private _propertyEditorSchemaConfigDefaultUIAlias: string | null = null;
private _configDefaultData?: Array<PropertyEditorConfigDefaultData>;
private _propertyEditorUISettingsSchemaAlias?: string;
#defaults = new UmbArrayState<PropertyEditorConfigDefaultData>([], (entry) => entry.alias);
defaults = this.#defaults.asObservable();
#propertyEditorUiIcon = new UmbStringState<string | null>(null);
propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable();
#propertyEditorUiName = new UmbStringState<string | null>(null);
propertyEditorUiName = this.#propertyEditorUiName.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.DataType', new UmbDataTypeRepository(host));
this.#observePropertyEditorUIAlias();
}
this.observe(this.propertyEditorUiAlias, (propertyEditorUiAlias) => {
if (!propertyEditorUiAlias) {
// No property editor ui alias, so we clean up and reset the properties.
this.removeControllerByAlias('propertyEditorUiAlias');
this._propertyEditorUISettingsProperties = [];
this._propertyEditorUISettingsDefaultData = [];
this._mergeConfigProperties();
this._mergeConfigDefaultData();
return;
#observePropertyEditorUIAlias() {
this.observe(this.propertyEditorUiAlias, async (propertyEditorUiAlias) => {
// we only want to react on the change if the alias is set or null. When it is undefined something is still loading
if (propertyEditorUiAlias === undefined) return;
// if the property editor ui alias is not set, we use the default alias from the schema
if (propertyEditorUiAlias === null) {
await this.#observePropertyEditorSchemaAlias();
this.setPropertyEditorUiAlias(this._propertyEditorSchemaConfigDefaultUIAlias!);
} else {
await this.#setPropertyEditorUIConfig(propertyEditorUiAlias);
this.setPropertyEditorSchemaAlias(this._propertyEditorUISettingsSchemaAlias!);
await this.#observePropertyEditorSchemaAlias();
}
this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUi', propertyEditorUiAlias),
(manifest) => {
this._observePropertyEditorSchemaConfig(
manifest?.meta.propertyEditorSchemaAlias || UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT
);
this._propertyEditorUISettingsProperties = manifest?.meta.settings?.properties || [];
this._propertyEditorUISettingsDefaultData = manifest?.meta.settings?.defaultData || [];
this._mergeConfigProperties();
this._mergeConfigDefaultData();
}
, 'observePropertyEditorUiAlias'
);
this._mergeConfigProperties();
this._mergeConfigDefaultData();
});
}
private _observePropertyEditorSchemaConfig(propertyEditorSchemaAlias: string) {
this.observe(
#observePropertyEditorSchemaAlias() {
return this.observe(this.propertyEditorSchemaAlias, async (propertyEditorSchemaAlias) => {
if (!propertyEditorSchemaAlias) {
this.setPropertyEditorSchemaAlias(UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT);
return;
}
await this.#setPropertyEditorSchemaConfig(propertyEditorSchemaAlias);
}).asPromise();
}
#setPropertyEditorSchemaConfig(propertyEditorSchemaAlias: string) {
return this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorSchema', propertyEditorSchemaAlias),
(manifest) => {
this._propertyEditorSchemaConfigProperties = manifest?.meta.settings?.properties || [];
this._propertyEditorSchemaConfigDefaultData = manifest?.meta.settings?.defaultData || [];
this._mergeConfigProperties();
this._mergeConfigDefaultData();
}
);
this._propertyEditorSchemaConfigDefaultUIAlias = manifest?.meta.defaultPropertyEditorUiAlias || null;
},
).asPromise();
}
#setPropertyEditorUIConfig(propertyEditorUIAlias: string) {
return this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUi', propertyEditorUIAlias),
(manifest) => {
this.#propertyEditorUiIcon.next(manifest?.meta.icon || null);
this.#propertyEditorUiName.next(manifest?.name || null);
this._propertyEditorUISettingsSchemaAlias = manifest?.meta.propertyEditorSchemaAlias;
this._propertyEditorUISettingsProperties = manifest?.meta.settings?.properties || [];
this._propertyEditorUISettingsDefaultData = manifest?.meta.settings?.defaultData || [];
},
).asPromise();
}
private _mergeConfigProperties() {
if(this._propertyEditorSchemaConfigProperties && this._propertyEditorUISettingsProperties) {
this.#properties.next([...this._propertyEditorSchemaConfigProperties, ...this._propertyEditorUISettingsProperties]);
console.log('schema properties', this._propertyEditorSchemaConfigProperties);
console.log('ui properties', this._propertyEditorUISettingsProperties);
if (this._propertyEditorSchemaConfigProperties && this._propertyEditorUISettingsProperties) {
this.#properties.next([
...this._propertyEditorSchemaConfigProperties,
...this._propertyEditorUISettingsProperties,
]);
}
}
private _mergeConfigDefaultData() {
if(!this._propertyEditorSchemaConfigDefaultData || !this._propertyEditorUISettingsDefaultData) return;
if (!this._propertyEditorSchemaConfigDefaultData || !this._propertyEditorUISettingsDefaultData) return;
this._configDefaultData = [
...this._propertyEditorSchemaConfigDefaultData,
@@ -159,17 +207,22 @@ export class UmbDataTypeWorkspaceContext
return combineLatest([
this.#data.asObservablePart((data) => data?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType),
this.#defaults.asObservablePart((defaults) => defaults?.find((x) => x.alias === propertyAlias)?.value as ReturnType),
this.#defaults.asObservablePart(
(defaults) => defaults?.find((x) => x.alias === propertyAlias)?.value as ReturnType,
),
]).pipe(
map(([value, defaultValue]) => {
return (value ?? defaultValue);
})
return value ?? defaultValue;
}),
);
//return this.#data.asObservablePart((data) => data?.values?.find((x) => x.alias === propertyAlias)?.value ?? this.getPropertyDefaultValue(propertyAlias) as ReturnType);
}
getPropertyValue<ReturnType = unknown>(propertyAlias: string) {
return this.#data.getValue()?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType ?? this.getPropertyDefaultValue(propertyAlias) as ReturnType;
return (
(this.#data.getValue()?.values?.find((x) => x.alias === propertyAlias)?.value as ReturnType) ??
(this.getPropertyDefaultValue(propertyAlias) as ReturnType)
);
}
// TODO: its not called a property in the model, but we do consider this way in our front-end
@@ -207,7 +260,10 @@ export class UmbDataTypeWorkspaceContext
}
}
export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContextInterface, UmbDataTypeWorkspaceContext>(
export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbWorkspaceContextInterface,
UmbDataTypeWorkspaceContext
>(
'UmbWorkspaceContext',
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type'
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type',
);

View File

@@ -1,5 +1,5 @@
import { UmbDataTypeWorkspaceContext } from './data-type-workspace.context.js';
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@@ -24,7 +24,7 @@ export class UmbDataTypeWorkspaceElement extends UmbLitElement {
new UmbWorkspaceIsNewRedirectController(
this,
this.#workspaceContext,
this.shadowRoot!.querySelector('umb-router-slot')!
this.shadowRoot!.querySelector('umb-router-slot')!,
);
},
},

View File

@@ -1,5 +1,5 @@
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../data-type-workspace.context.js';
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import {
UmbModalManagerContext,
@@ -8,10 +8,7 @@ import {
} from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import {
UmbWorkspaceEditorViewExtensionElement,
umbExtensionsRegistry,
} from '@umbraco-cms/backoffice/extension-registry';
import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-data-type-details-workspace-view')
export class UmbDataTypeDetailsWorkspaceViewEditElement
@@ -22,19 +19,16 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement
_dataType?: DataTypeResponseModel;
@state()
private _propertyEditorUiIcon?: string;
private _propertyEditorUiIcon?: string | null = null;
@state()
private _propertyEditorUiName?: string;
private _propertyEditorUiName?: string | null = null;
@state()
private _propertyEditorUiAlias?: string;
private _propertyEditorUiAlias?: string | null = null;
@state()
private _propertyEditorSchemaAlias?: string;
@state()
private _data: Array<any> = [];
private _propertyEditorSchemaAlias?: string | null = null;
private _workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE;
private _modalContext?: UmbModalManagerContext;
@@ -58,95 +52,45 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement
}
this.observe(this._workspaceContext.data, (dataType) => {
if (!dataType) return;
// TODO: handle if model is not of the type wanted.
this._dataType = dataType;
});
if (!this._dataType.propertyEditorUiAlias) {
if (this._dataType.propertyEditorAlias) {
// Get the property editor UI alias from the property editor alias:
this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorSchema', this._dataType.propertyEditorAlias),
(propertyEditorSchema) => {
// TODO: show error. We have stored a propertyEditorSchemaAlias and can't find the PropertyEditorSchema in the registry.
if (!propertyEditorSchema) return;
this._setPropertyEditorUiAlias(propertyEditorSchema.meta.defaultPropertyEditorUiAlias ?? undefined);
},
'_observePropertyEditorSchemaForDefaultUI'
);
} else {
this._setPropertyEditorUiAlias(undefined);
}
} else {
this._setPropertyEditorUiAlias(this._dataType.propertyEditorUiAlias);
}
this.observe(this._workspaceContext.propertyEditorUiAlias, (value) => {
this._propertyEditorUiAlias = value;
});
if (this._dataType.values && this._dataType.values !== this._data) {
this._data = this._dataType.values;
}
this.observe(this._workspaceContext.propertyEditorSchemaAlias, (value) => {
this._propertyEditorSchemaAlias = value;
});
this.observe(this._workspaceContext.propertyEditorUiName, (value) => {
this._propertyEditorUiName = value;
});
this.observe(this._workspaceContext.propertyEditorUiIcon, (value) => {
this._propertyEditorUiIcon = value;
});
}
private _setPropertyEditorUiAlias(value: string | undefined) {
const oldValue = this._propertyEditorUiAlias;
if (oldValue !== value) {
this._propertyEditorUiAlias = value;
this._observePropertyEditorUI(value || undefined);
}
}
private _observePropertyEditorUI(propertyEditorUiAlias?: string) {
if (!propertyEditorUiAlias) {
this._propertyEditorUiName = this._propertyEditorUiIcon = this._propertyEditorUiAlias = undefined;
this.removeControllerByAlias('_observePropertyEditorUI');
return;
}
// remove the '_observePropertyEditorSchemaForDefaultUI' controller, as we do not want to observe for default value anymore:
this.removeControllerByAlias('_observePropertyEditorSchemaForDefaultUI');
this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUi', propertyEditorUiAlias),
(propertyEditorUI) => {
// TODO: show error. We have stored a PropertyEditorUIAlias and can't find the PropertyEditorUI in the registry.
if (!propertyEditorUI) return;
this._propertyEditorUiName = propertyEditorUI?.meta.label ?? propertyEditorUI?.name ?? '';
this._propertyEditorUiAlias = propertyEditorUI?.alias ?? '';
this._propertyEditorUiIcon = propertyEditorUI?.meta.icon ?? '';
this._propertyEditorSchemaAlias = propertyEditorUI?.meta.propertyEditorSchemaAlias ?? '';
this._workspaceContext?.setPropertyEditorSchemaAlias(this._propertyEditorSchemaAlias);
},
'_observePropertyEditorUI'
);
}
private _openPropertyEditorUIPicker() {
if (!this._dataType) return;
const modalContext = this._modalContext?.open(UMB_PROPERTY_EDITOR_UI_PICKER_MODAL, {
selection: this._propertyEditorUiAlias ? [this._propertyEditorUiAlias] : [],
});
modalContext?.onSubmit().then(({ selection }) => {
this._selectPropertyEditorUI(selection[0]);
this._workspaceContext?.setPropertyEditorUiAlias(selection[0]);
});
}
private _selectPropertyEditorUI(propertyEditorUiAlias: string | undefined) {
this._workspaceContext?.setPropertyEditorUiAlias(propertyEditorUiAlias);
}
render() {
return html`
<uui-box> ${this._renderPropertyEditorUI()} </uui-box>
${this._renderConfig()} </uui-box>
<uui-box> ${this.#renderPropertyEditorReference()} </uui-box>
${this.#renderPropertyEditorConfig()} </uui-box>
`;
}
private _renderPropertyEditorUI() {
#renderPropertyEditorReference() {
console.log(this._dataType);
return html`
<umb-workspace-property-layout label="Property Editor" description="Select a property editor">
${this._propertyEditorUiAlias && this._propertyEditorSchemaAlias
@@ -178,18 +122,10 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement
`;
}
private _renderConfig() {
return html`
${this._propertyEditorSchemaAlias && this._propertyEditorUiAlias
? html`
<uui-box headline="Settings">
<umb-property-editor-config
property-editor-ui-alias="${this._propertyEditorUiAlias}"
.data="${this._data}"></umb-property-editor-config>
</uui-box>
`
: nothing}
`;
#renderPropertyEditorConfig() {
return html`<uui-box headline="Settings">
<umb-property-editor-config></umb-property-editor-config>
</uui-box> `;
}
static styles = [