Merge remote-tracking branch 'origin/main' into feature/static-file-management
This commit is contained in:
@@ -13,7 +13,9 @@ describe('UmbLogin', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbLoginElement);
|
expect(element).to.be.instanceOf(UmbLoginElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Property Dataset Dashboard Example
|
||||||
|
|
||||||
|
This example demonstrates the essence of the Property Dataset.
|
||||||
|
|
||||||
|
This dashboard implements such, to display a few selected Property Editors and bind the data back to the Dashboard.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
|
import { css, html, customElement, LitElement } from '@umbraco-cms/backoffice/external/lit';
|
||||||
|
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||||
|
import { UmbPropertyValueData, type UmbPropertyDatasetElement } from '@umbraco-cms/backoffice/property';
|
||||||
|
|
||||||
|
@customElement('example-dataset-dashboard')
|
||||||
|
export class ExampleDatasetDashboard extends UmbElementMixin(LitElement) {
|
||||||
|
data: UmbPropertyValueData[] = [
|
||||||
|
{
|
||||||
|
alias: 'textProperty',
|
||||||
|
value: 'Hello',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
#onDataChange(e: Event) {
|
||||||
|
const oldValue = this.data;
|
||||||
|
this.data = (e.target as UmbPropertyDatasetElement).value;
|
||||||
|
this.requestUpdate('data', oldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<uui-box class="uui-text">
|
||||||
|
<h1 class="uui-h2" style="margin-top: var(--uui-size-layout-1);">Dataset Example</h1>
|
||||||
|
<umb-property-dataset .value=${this.data} @change=${this.#onDataChange}>
|
||||||
|
<umb-property
|
||||||
|
label="Textual input"
|
||||||
|
description="Example of text editor"
|
||||||
|
alias="textProperty"
|
||||||
|
property-editor-ui-alias="Umb.PropertyEditorUi.TextBox"></umb-property>
|
||||||
|
<umb-property
|
||||||
|
label="List of options"
|
||||||
|
description="Example of dropdown editor"
|
||||||
|
alias="listProperty"
|
||||||
|
.config=${[
|
||||||
|
{
|
||||||
|
alias: 'multiple',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: 'items',
|
||||||
|
value: {
|
||||||
|
0: { sortOrder: 1, value: 'First Option' },
|
||||||
|
1: { sortOrder: 2, value: 'Second Option' },
|
||||||
|
2: { sortOrder: 3, value: 'Third Option' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
property-editor-ui-alias="Umb.PropertyEditorUi.Dropdown"></umb-property>
|
||||||
|
</umb-property-dataset>
|
||||||
|
|
||||||
|
<h5 class="uui-h3" style="margin-top: var(--uui-size-layout-1);">Output of dashboard data:</h5>
|
||||||
|
<code> ${JSON.stringify(this.data, null, 2)} </code>
|
||||||
|
</uui-box>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = [
|
||||||
|
UmbTextStyles,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
padding: var(--uui-size-layout-1);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExampleDatasetDashboard;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'example-dataset-dashboard': ExampleDatasetDashboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||||
|
|
||||||
|
export const manifests: Array<ManifestTypes> = [
|
||||||
|
{
|
||||||
|
type: 'dashboard',
|
||||||
|
name: 'Example Dataset Workspace View',
|
||||||
|
alias: 'example.dashboard.dataset',
|
||||||
|
element: () => import('./dataset-dashboard.js'),
|
||||||
|
weight: 900,
|
||||||
|
meta: {
|
||||||
|
label: 'Dataset example',
|
||||||
|
pathname: 'dataset-example',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
"./modal": "./dist-cms/packages/core/modal/index.js",
|
"./modal": "./dist-cms/packages/core/modal/index.js",
|
||||||
"./notification": "./dist-cms/packages/core/notification/index.js",
|
"./notification": "./dist-cms/packages/core/notification/index.js",
|
||||||
"./picker-input": "./dist-cms/packages/core/picker-input/index.js",
|
"./picker-input": "./dist-cms/packages/core/picker-input/index.js",
|
||||||
|
"./property": "./dist-cms/packages/core/property/index.js",
|
||||||
"./property-action": "./dist-cms/packages/core/property-action/index.js",
|
"./property-action": "./dist-cms/packages/core/property-action/index.js",
|
||||||
"./property-editor": "./dist-cms/packages/core/property-editor/index.js",
|
"./property-editor": "./dist-cms/packages/core/property-editor/index.js",
|
||||||
"./section": "./dist-cms/packages/core/section/index.js",
|
"./section": "./dist-cms/packages/core/section/index.js",
|
||||||
@@ -121,6 +122,8 @@
|
|||||||
"storybook:build": "npm run wc-analyze && storybook build",
|
"storybook:build": "npm run wc-analyze && storybook build",
|
||||||
"storybook": "npm run wc-analyze && storybook dev -p 6006",
|
"storybook": "npm run wc-analyze && storybook dev -p 6006",
|
||||||
"test:e2e": "npm run auth:test:e2e && npm run backoffice:test:e2e",
|
"test:e2e": "npm run auth:test:e2e && npm run backoffice:test:e2e",
|
||||||
|
"test:dev": "web-test-runner --config ./web-test-runner.dev.config.mjs",
|
||||||
|
"test:dev-watch": "web-test-runner --watch --config ./web-test-runner.dev.config.mjs",
|
||||||
"test:watch": "web-test-runner --watch",
|
"test:watch": "web-test-runner --watch",
|
||||||
"test": "web-test-runner --coverage",
|
"test": "web-test-runner --coverage",
|
||||||
"wc-analyze:vscode": "wca **/*.element.ts --format vscode --outFile dist-cms/vscode-html-custom-data.json",
|
"wc-analyze:vscode": "wca **/*.element.ts --format vscode --outFile dist-cms/vscode-html-custom-data.json",
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ export class UmbAppContext extends UmbBaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UMB_APP_CONTEXT = new UmbContextToken<UmbAppContext>('UMB_APP');
|
export const UMB_APP_CONTEXT = new UmbContextToken<UmbAppContext>('UmbAppContext');
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerConsentElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerConsentElement);
|
expect(element).to.be.instanceOf(UmbInstallerConsentElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerDatabaseElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerDatabaseElement);
|
expect(element).to.be.instanceOf(UmbInstallerDatabaseElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerErrorElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerErrorElement);
|
expect(element).to.be.instanceOf(UmbInstallerErrorElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerElement);
|
expect(element).to.be.instanceOf(UmbInstallerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerInstallingElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerInstallingElement);
|
expect(element).to.be.instanceOf(UmbInstallerInstallingElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerLayoutElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerLayoutElement);
|
expect(element).to.be.instanceOf(UmbInstallerLayoutElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbInstallerUserElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInstallerUserElement);
|
expect(element).to.be.instanceOf(UmbInstallerUserElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ describe('UmbUpgraderView', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbUpgraderViewElement);
|
expect(element).to.be.instanceOf(UmbUpgraderViewElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,8 +38,11 @@ describe('UmbControllerHostTestElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbControllerHostProviderElement);
|
expect(element).to.be.instanceOf(UmbControllerHostProviderElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('provides the context', () => {
|
it('provides the context', async () => {
|
||||||
|
await Promise.resolve();
|
||||||
// Potentially we need to wait a bit here, cause the value might not be set already? as of the context consumption...
|
// Potentially we need to wait a bit here, cause the value might not be set already? as of the context consumption...
|
||||||
|
expect(consumer).to.be.instanceOf(UmbTestControllerHostInitializerConsumerElement);
|
||||||
|
expect(consumer.value).to.not.be.null;
|
||||||
expect(consumer.value).to.equal(contextValue);
|
expect(consumer.value).to.equal(contextValue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,9 +27,11 @@ describe('UmbExtensionSlotElement', () => {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
// This test fails offen on FireFox, there is no real need for this test. So i have chosen to skip it.
|
// This test fails offen on FireFox, there is no real need for this test. So i have chosen to skip it.
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
describe('properties', () => {
|
describe('properties', () => {
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ describe('UmbInputColorElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInputColorElement);
|
expect(element).to.be.instanceOf(UmbInputColorElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ describe('UmbInputDateElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInputDateElement);
|
expect(element).to.be.instanceOf(UmbInputDateElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ describe('UmbInputDateElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInputDropdownListElement);
|
expect(element).to.be.instanceOf(UmbInputDropdownListElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ describe('UmbInputEyeDropperElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInputEyeDropperElement);
|
expect(element).to.be.instanceOf(UmbInputEyeDropperElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ describe('UmbPropertyEditorUINumberRangeElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbInputNumberRangeElement);
|
expect(element).to.be.instanceOf(UmbInputNumberRangeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import { expect, fixture, html } from '@open-wc/testing';
|
|||||||
// expect(element).to.be.instanceOf(UmbPickerSectionElement);
|
// expect(element).to.be.instanceOf(UmbPickerSectionElement);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
// if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
// it('passes the a11y audit', async () => {
|
// it('passes the a11y audit', async () => {
|
||||||
// await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
// await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
// });
|
// });
|
||||||
|
// }
|
||||||
// });
|
// });
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`<umb-workspace-property
|
return html`<umb-property
|
||||||
alias=${ifDefined(this._property?.alias)}
|
alias=${ifDefined(this._property?.alias)}
|
||||||
label=${ifDefined(this._property?.name)}
|
label=${ifDefined(this._property?.name)}
|
||||||
description=${ifDefined(this._property?.description || undefined)}
|
description=${ifDefined(this._property?.description || undefined)}
|
||||||
property-editor-ui-alias=${ifDefined(this._propertyEditorUiAlias)}
|
property-editor-ui-alias=${ifDefined(this._propertyEditorUiAlias)}
|
||||||
.config=${this._dataTypeData}></umb-workspace-property>`;
|
.config=${this._dataTypeData}></umb-property>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { UMB_PROPERTY_DATASET_CONTEXT, isNameablePropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||||
import { UmbVariantId } from '../../variant/variant-id.class.js';
|
import { UmbVariantId } from '../../variant/variant-id.class.js';
|
||||||
import { UUIInputElement, UUIInputEvent, UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui';
|
import { UUIInputElement, UUIInputEvent, UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui';
|
||||||
import {
|
import {
|
||||||
@@ -13,9 +14,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
UmbWorkspaceSplitViewContext,
|
UmbWorkspaceSplitViewContext,
|
||||||
UMB_WORKSPACE_SPLIT_VIEW_CONTEXT,
|
UMB_WORKSPACE_SPLIT_VIEW_CONTEXT,
|
||||||
UMB_VARIANT_CONTEXT,
|
|
||||||
ActiveVariant,
|
ActiveVariant,
|
||||||
isNameablePropertySetContext,
|
|
||||||
} from '@umbraco-cms/backoffice/workspace';
|
} from '@umbraco-cms/backoffice/workspace';
|
||||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
import { DocumentVariantResponseModel, ContentStateModel } from '@umbraco-cms/backoffice/backend-api';
|
import { DocumentVariantResponseModel, ContentStateModel } from '@umbraco-cms/backoffice/backend-api';
|
||||||
@@ -38,7 +37,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#splitViewContext?: UmbWorkspaceSplitViewContext;
|
#splitViewContext?: UmbWorkspaceSplitViewContext;
|
||||||
#variantContext?: typeof UMB_VARIANT_CONTEXT.TYPE;
|
#variantContext?: typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private _name?: string;
|
private _name?: string;
|
||||||
@@ -66,7 +65,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
|||||||
this._observeVariants();
|
this._observeVariants();
|
||||||
this._observeActiveVariants();
|
this._observeActiveVariants();
|
||||||
});
|
});
|
||||||
this.consumeContext(UMB_VARIANT_CONTEXT, (instance) => {
|
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (instance) => {
|
||||||
this.#variantContext = instance;
|
this.#variantContext = instance;
|
||||||
this._observeVariantContext();
|
this._observeVariantContext();
|
||||||
});
|
});
|
||||||
@@ -140,7 +139,7 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
|||||||
if (
|
if (
|
||||||
typeof target?.value === 'string' &&
|
typeof target?.value === 'string' &&
|
||||||
this.#variantContext &&
|
this.#variantContext &&
|
||||||
isNameablePropertySetContext(this.#variantContext)
|
isNameablePropertyDatasetContext(this.#variantContext)
|
||||||
) {
|
) {
|
||||||
this.#variantContext.setName(target.value);
|
this.#variantContext.setName(target.value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { html, customElement, state, ifDefined, repeat, nothing } from '@umbraco-cms/backoffice/external/lit';
|
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../workspace/data-type-workspace.context.js';
|
||||||
|
import { html, customElement, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
import { PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry';
|
import { PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry';
|
||||||
|
|
||||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
import { UMB_DATA_TYPE_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/data-type';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @element umb-property-editor-config
|
* @element umb-property-editor-config
|
||||||
@@ -13,7 +13,7 @@ import { UMB_DATA_TYPE_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/data-type
|
|||||||
@customElement('umb-property-editor-config')
|
@customElement('umb-property-editor-config')
|
||||||
export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
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.
|
// 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;
|
#workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private _properties: Array<PropertyEditorConfigProperty> = [];
|
private _properties: Array<PropertyEditorConfigProperty> = [];
|
||||||
@@ -21,16 +21,17 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.consumeContext(UMB_DATA_TYPE_VARIANT_CONTEXT, (instance) => {
|
// This now connects to the workspace, as the variant does not know about the layout details.
|
||||||
this.#variantContext = instance;
|
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (instance) => {
|
||||||
|
this.#workspaceContext = instance;
|
||||||
this.#observeProperties();
|
this.#observeProperties();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#observeProperties() {
|
#observeProperties() {
|
||||||
if (!this.#variantContext) return;
|
if (!this.#workspaceContext) return;
|
||||||
this.observe(
|
this.observe(
|
||||||
this.#variantContext.properties,
|
this.#workspaceContext.properties,
|
||||||
(properties) => {
|
(properties) => {
|
||||||
this._properties = properties as Array<PropertyEditorConfigProperty>;
|
this._properties = properties as Array<PropertyEditorConfigProperty>;
|
||||||
},
|
},
|
||||||
@@ -44,12 +45,12 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
|||||||
this._properties,
|
this._properties,
|
||||||
(property) => property.alias,
|
(property) => property.alias,
|
||||||
(property) =>
|
(property) =>
|
||||||
html`<umb-workspace-property
|
html`<umb-property
|
||||||
label="${property.label}"
|
label="${property.label}"
|
||||||
description="${ifDefined(property.description)}"
|
description="${ifDefined(property.description)}"
|
||||||
alias="${property.alias}"
|
alias="${property.alias}"
|
||||||
property-editor-ui-alias="${property.propertyEditorUiAlias}"
|
property-editor-ui-alias="${property.propertyEditorUiAlias}"
|
||||||
.config=${property.config}></umb-workspace-property>`,
|
.config=${property.config}></umb-property>`,
|
||||||
)
|
)
|
||||||
: html`<div>No configuration</div>`;
|
: html`<div>No configuration</div>`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,5 @@ import './components/index.js';
|
|||||||
|
|
||||||
export * from './entity.js';
|
export * from './entity.js';
|
||||||
export * from './repository/index.js';
|
export * from './repository/index.js';
|
||||||
export * from './variant-context/index.js';
|
|
||||||
|
|
||||||
export type { UmbDataTypeDetailModel } from './types.js';
|
export type { UmbDataTypeDetailModel } from './types.js';
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { UmbDataTypeVariantContext } from './data-type-variant-context.js';
|
|
||||||
import { UmbVariantContext } from '@umbraco-cms/backoffice/workspace';
|
|
||||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
|
||||||
|
|
||||||
export const isDataTypeVariantContext = (context: UmbVariantContext): context is UmbDataTypeVariantContext =>
|
|
||||||
'properties' in context && context.getType() === 'data-type';
|
|
||||||
|
|
||||||
export const UMB_DATA_TYPE_VARIANT_CONTEXT = new UmbContextToken<UmbVariantContext, UmbDataTypeVariantContext>(
|
|
||||||
'UmbVariantContext',
|
|
||||||
undefined,
|
|
||||||
isDataTypeVariantContext,
|
|
||||||
);
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { UmbDataTypeWorkspaceContext } from '../workspace/data-type-workspace.context.js';
|
|
||||||
import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
|
||||||
import { UmbInvariantWorkspaceVariantContext } from '@umbraco-cms/backoffice/workspace';
|
|
||||||
|
|
||||||
export class UmbDataTypeVariantContext extends UmbInvariantWorkspaceVariantContext<UmbDataTypeWorkspaceContext> {
|
|
||||||
properties = this._workspace.properties;
|
|
||||||
|
|
||||||
constructor(host: UmbControllerHost, workspace: UmbDataTypeWorkspaceContext) {
|
|
||||||
super(host, workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './data-type-variant-context.token.js';
|
|
||||||
export * from './data-type-variant-context.js';
|
|
||||||
@@ -22,7 +22,7 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement {
|
|||||||
|
|
||||||
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => {
|
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => {
|
||||||
this.#workspaceContext = workspaceContext;
|
this.#workspaceContext = workspaceContext;
|
||||||
this.#workspaceContext?.createVariantContext(this);
|
this.#workspaceContext?.createPropertyDatasetContext(this);
|
||||||
this.#observeIsNew();
|
this.#observeIsNew();
|
||||||
this.#observeName();
|
this.#observeName();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||||
import { UmbDataTypeDetailRepository } from '../repository/detail/data-type-detail.repository.js';
|
import { UmbDataTypeDetailRepository } from '../repository/detail/data-type-detail.repository.js';
|
||||||
import { UmbDataTypeVariantContext } from '../variant-context/data-type-variant-context.js';
|
|
||||||
import type { UmbDataTypeDetailModel } from '../types.js';
|
import type { UmbDataTypeDetailModel } from '../types.js';
|
||||||
import {
|
import {
|
||||||
UmbInvariantableWorkspaceContextInterface,
|
UmbInvariantableWorkspaceContextInterface,
|
||||||
UmbEditableWorkspaceContextBase,
|
UmbEditableWorkspaceContextBase,
|
||||||
UmbWorkspaceContextInterface,
|
UmbWorkspaceContextInterface,
|
||||||
|
UmbInvariantWorkspacePropertyDatasetContext,
|
||||||
} from '@umbraco-cms/backoffice/workspace';
|
} from '@umbraco-cms/backoffice/workspace';
|
||||||
import {
|
import {
|
||||||
appendToFrozenArray,
|
appendToFrozenArray,
|
||||||
@@ -26,7 +27,6 @@ export class UmbDataTypeWorkspaceContext
|
|||||||
extends UmbEditableWorkspaceContextBase<UmbDataTypeDetailRepository, UmbDataTypeDetailModel>
|
extends UmbEditableWorkspaceContextBase<UmbDataTypeDetailRepository, UmbDataTypeDetailModel>
|
||||||
implements UmbInvariantableWorkspaceContextInterface<UmbDataTypeDetailModel | undefined>
|
implements UmbInvariantableWorkspaceContextInterface<UmbDataTypeDetailModel | undefined>
|
||||||
{
|
{
|
||||||
// TODO: revisit. temp solution because the create and response models are different.
|
|
||||||
#data = new UmbObjectState<UmbDataTypeDetailModel | undefined>(undefined);
|
#data = new UmbObjectState<UmbDataTypeDetailModel | undefined>(undefined);
|
||||||
readonly data = this.#data.asObservable();
|
readonly data = this.#data.asObservable();
|
||||||
#getDataPromise?: Promise<any>;
|
#getDataPromise?: Promise<any>;
|
||||||
@@ -146,8 +146,49 @@ export class UmbDataTypeWorkspaceContext
|
|||||||
return this._configDefaultData?.find((x) => x.alias === alias)?.value;
|
return this._configDefaultData?.find((x) => x.alias === alias)?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
createVariantContext(host: UmbControllerHost): UmbDataTypeVariantContext {
|
createPropertyDatasetContext(host: UmbControllerHost): UmbPropertyDatasetContext {
|
||||||
return new UmbDataTypeVariantContext(host, this);
|
return new UmbInvariantWorkspacePropertyDatasetContext(host, this);
|
||||||
|
/*
|
||||||
|
// Example of how this could have been done with the PropertyDatasetBaseContext:
|
||||||
|
const context = new UmbPropertyDatasetBaseContext(host);
|
||||||
|
|
||||||
|
// Observe workspace name:
|
||||||
|
this.observe(this.name, (name) => {
|
||||||
|
context.setName(name ?? '');
|
||||||
|
});
|
||||||
|
// Observe the variant name:
|
||||||
|
this.observe(context.name, (name) => {
|
||||||
|
this.setName(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.observe(
|
||||||
|
this.properties,
|
||||||
|
(properties) => {
|
||||||
|
if (properties) {
|
||||||
|
properties.forEach(async (property) => {
|
||||||
|
// Observe value of workspace:
|
||||||
|
this.observe(
|
||||||
|
await this.propertyValueByAlias(property.alias),
|
||||||
|
(value) => {
|
||||||
|
context.setPropertyValue(property.alias, value);
|
||||||
|
},
|
||||||
|
'observeWorkspacePropertyOf_' + property.alias,
|
||||||
|
);
|
||||||
|
// Observe value of variant:
|
||||||
|
this.observe(
|
||||||
|
await context.propertyValueByAlias(property.alias),
|
||||||
|
(value) => {
|
||||||
|
this.setPropertyValue(property.alias, value);
|
||||||
|
},
|
||||||
|
'observeVariantPropertyOf_' + property.alias,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'observePropertyValues',
|
||||||
|
);
|
||||||
|
return context;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(unique: string) {
|
async load(unique: string) {
|
||||||
@@ -187,7 +228,7 @@ export class UmbDataTypeWorkspaceContext
|
|||||||
getName() {
|
getName() {
|
||||||
return this.#data.getValue()?.name;
|
return this.#data.getValue()?.name;
|
||||||
}
|
}
|
||||||
setName(name: string) {
|
setName(name: string | undefined) {
|
||||||
this.#data.update({ name });
|
this.#data.update({ name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement extends UmbLitElement im
|
|||||||
|
|
||||||
#renderPropertyEditorReference() {
|
#renderPropertyEditorReference() {
|
||||||
return html`
|
return html`
|
||||||
<umb-workspace-property-layout label="Property Editor" description="Select a property editor">
|
<umb-property-layout label="Property Editor" description="Select a property editor">
|
||||||
${this._propertyEditorUiAlias && this._propertyEditorSchemaAlias
|
${this._propertyEditorUiAlias && this._propertyEditorSchemaAlias
|
||||||
? html`
|
? html`
|
||||||
<!-- TODO: border is a bit weird attribute name. Maybe single or standalone would be better? -->
|
<!-- TODO: border is a bit weird attribute name. Maybe single or standalone would be better? -->
|
||||||
@@ -117,7 +117,7 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement extends UmbLitElement im
|
|||||||
color="default"
|
color="default"
|
||||||
@click=${this._openPropertyEditorUIPicker}></uui-button>
|
@click=${this._openPropertyEditorUIPicker}></uui-button>
|
||||||
`}
|
`}
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement implement
|
|||||||
private _renderGeneralInfo() {
|
private _renderGeneralInfo() {
|
||||||
return html`
|
return html`
|
||||||
<uui-box headline="General" style="margin-bottom: 20px;">
|
<uui-box headline="General" style="margin-bottom: 20px;">
|
||||||
<umb-workspace-property-layout label="Id">
|
<umb-property-layout label="Id">
|
||||||
<div slot="editor">${this._dataType?.unique}</div>
|
<div slot="editor">${this._dataType?.unique}</div>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
<umb-workspace-property-layout label="Property Editor Alias">
|
<umb-property-layout label="Property Editor Alias">
|
||||||
<div slot="editor">${this._dataType?.propertyEditorAlias}</div>
|
<div slot="editor">${this._dataType?.propertyEditorAlias}</div>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
|
|
||||||
<umb-workspace-property-layout label="Property Editor UI Alias">
|
<umb-property-layout label="Property Editor UI Alias">
|
||||||
<div slot="editor">${this._dataType?.propertyEditorUiAlias}</div>
|
<div slot="editor">${this._dataType?.propertyEditorUiAlias}</div>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
</uui-box>
|
</uui-box>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ export class UmbEmbeddedMediaModalElement extends UmbModalBaseElement<
|
|||||||
return html`
|
return html`
|
||||||
<umb-body-layout headline="Embed">
|
<umb-body-layout headline="Embed">
|
||||||
<uui-box>
|
<uui-box>
|
||||||
<umb-workspace-property-layout label="URL" orientation="vertical">
|
<umb-property-layout label="URL" orientation="vertical">
|
||||||
<div slot="editor">
|
<div slot="editor">
|
||||||
<uui-input .value=${this._model.url} type="text" @change=${this.#onUrlChange} required="true">
|
<uui-input .value=${this._model.url} type="text" @change=${this.#onUrlChange} required="true">
|
||||||
<uui-button
|
<uui-button
|
||||||
@@ -176,12 +176,12 @@ export class UmbEmbeddedMediaModalElement extends UmbModalBaseElement<
|
|||||||
label="Retrieve"></uui-button>
|
label="Retrieve"></uui-button>
|
||||||
</uui-input>
|
</uui-input>
|
||||||
</div>
|
</div>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
|
|
||||||
${when(
|
${when(
|
||||||
this.#embedResult?.oEmbedStatus === OEmbedStatus.Success || this._model.a11yInfo,
|
this.#embedResult?.oEmbedStatus === OEmbedStatus.Success || this._model.a11yInfo,
|
||||||
() =>
|
() =>
|
||||||
html` <umb-workspace-property-layout label="Preview" orientation="vertical">
|
html` <umb-property-layout label="Preview" orientation="vertical">
|
||||||
<div slot="editor">
|
<div slot="editor">
|
||||||
${when(this.#loading, () => html`<uui-loader-circle></uui-loader-circle>`)}
|
${when(this.#loading, () => html`<uui-loader-circle></uui-loader-circle>`)}
|
||||||
${when(this.#embedResult?.markup, () => html`${unsafeHTML(this.#embedResult.markup)}`)}
|
${when(this.#embedResult?.markup, () => html`${unsafeHTML(this.#embedResult.markup)}`)}
|
||||||
@@ -191,34 +191,34 @@ export class UmbEmbeddedMediaModalElement extends UmbModalBaseElement<
|
|||||||
() => html` <p class="sr-only" role="alert">${this._model.a11yInfo}</p>`,
|
() => html` <p class="sr-only" role="alert">${this._model.a11yInfo}</p>`,
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</umb-workspace-property-layout>`,
|
</umb-property-layout>`,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<umb-workspace-property-layout label="Width" orientation="vertical">
|
<umb-property-layout label="Width" orientation="vertical">
|
||||||
<uui-input
|
<uui-input
|
||||||
slot="editor"
|
slot="editor"
|
||||||
.value=${this._model.width}
|
.value=${this._model.width}
|
||||||
type="number"
|
type="number"
|
||||||
?disabled=${this.#dimensionControlsDisabled()}
|
?disabled=${this.#dimensionControlsDisabled()}
|
||||||
@change=${this.#onWidthChange}></uui-input>
|
@change=${this.#onWidthChange}></uui-input>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
|
|
||||||
<umb-workspace-property-layout label="Height" orientation="vertical">
|
<umb-property-layout label="Height" orientation="vertical">
|
||||||
<uui-input
|
<uui-input
|
||||||
slot="editor"
|
slot="editor"
|
||||||
.value=${this._model.height}
|
.value=${this._model.height}
|
||||||
type="number"
|
type="number"
|
||||||
?disabled=${this.#dimensionControlsDisabled()}
|
?disabled=${this.#dimensionControlsDisabled()}
|
||||||
@change=${this.#onHeightChange}></uui-input>
|
@change=${this.#onHeightChange}></uui-input>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
|
|
||||||
<umb-workspace-property-layout label="Constrain" orientation="vertical">
|
<umb-property-layout label="Constrain" orientation="vertical">
|
||||||
<uui-toggle
|
<uui-toggle
|
||||||
slot="editor"
|
slot="editor"
|
||||||
@change=${this.#onConstrainChange}
|
@change=${this.#onConstrainChange}
|
||||||
?disabled=${this.#dimensionControlsDisabled()}
|
?disabled=${this.#dimensionControlsDisabled()}
|
||||||
.checked=${this._model.constrain}></uui-toggle>
|
.checked=${this._model.constrain}></uui-toggle>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
</uui-box>
|
</uui-box>
|
||||||
|
|
||||||
<uui-button slot="actions" id="cancel" label="Cancel" @click=${this.#handleCancel}>Cancel</uui-button>
|
<uui-button slot="actions" id="cancel" label="Cancel" @click=${this.#handleCancel}>Cancel</uui-button>
|
||||||
@@ -257,11 +257,11 @@ export class UmbEmbeddedMediaModalElement extends UmbModalBaseElement<
|
|||||||
width: 1px;
|
width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
umb-workspace-property-layout:first-child {
|
umb-property-layout:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
umb-workspace-property-layout:last-child {
|
umb-property-layout:last-child {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
// expect(element).to.be.instanceOf(UmbIconPickerModalElement);
|
// expect(element).to.be.instanceOf(UmbIconPickerModalElement);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
// if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
// // TODO: Reinstate this test when the a11y audit is fixed on uui-color-picker
|
// // TODO: Reinstate this test when the a11y audit is fixed on uui-color-picker
|
||||||
// // it('passes the a11y audit', async () => {
|
// // it('passes the a11y audit', async () => {
|
||||||
// // await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
// // await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
// // });
|
// // });
|
||||||
|
// }
|
||||||
// });
|
// });
|
||||||
|
|||||||
@@ -31,9 +31,11 @@ describe('UmbNotificationLayoutDefault', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbNotificationLayoutDefaultElement);
|
expect(element).to.be.instanceOf(UmbNotificationLayoutDefaultElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).to.be.accessible();
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).to.be.accessible();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe('Public API', () => {
|
describe('Public API', () => {
|
||||||
describe('properties', () => {
|
describe('properties', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { UmbPropertyContext, UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||||
import type { UmbPropertyAction } from '../../shared/property-action/property-action.interface.js';
|
import type { UmbPropertyAction } from '../../shared/property-action/property-action.interface.js';
|
||||||
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { UmbWorkspacePropertyContext, UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/workspace';
|
|
||||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
|
|
||||||
@customElement('umb-property-action-clear')
|
@customElement('umb-property-action-clear')
|
||||||
@@ -10,7 +10,7 @@ export class UmbPropertyActionClearElement extends UmbLitElement implements UmbP
|
|||||||
|
|
||||||
// THESE OUT COMMENTED CODE IS USED FOR THE EXAMPLE BELOW, TODO: Should be transferred to some documentation.
|
// THESE OUT COMMENTED CODE IS USED FOR THE EXAMPLE BELOW, TODO: Should be transferred to some documentation.
|
||||||
//private _propertyActionMenuContext?: UmbPropertyActionMenuContext;
|
//private _propertyActionMenuContext?: UmbPropertyActionMenuContext;
|
||||||
private _propertyContext?: UmbWorkspacePropertyContext;
|
private _propertyContext?: UmbPropertyContext;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@@ -20,7 +20,7 @@ export class UmbPropertyActionClearElement extends UmbLitElement implements UmbP
|
|||||||
this._propertyActionMenuContext = propertyActionsContext;
|
this._propertyActionMenuContext = propertyActionsContext;
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
this.consumeContext(UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN, (propertyContext: UmbWorkspacePropertyContext) => {
|
this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext: UmbPropertyContext) => {
|
||||||
this._propertyContext = propertyContext;
|
this._propertyContext = propertyContext;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIBlockGridBlockConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridBlockConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridBlockConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIBlockGridGroupConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridGroupConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridGroupConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIBlockGridStylesheetPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridStylesheetPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridStylesheetPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN } from '../../../workspace/workspace-property/workspace-property.context.js';
|
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||||
@@ -33,7 +33,7 @@ export class UmbPropertyEditorUIBlockGridElement extends UmbLitElement implement
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.consumeContext(UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN, (context) => {
|
this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
|
||||||
this.observe(context?.variantId, (propertyVariantId) => {
|
this.observe(context?.variantId, (propertyVariantId) => {
|
||||||
this._variantId = propertyVariantId;
|
this._variantId = propertyVariantId;
|
||||||
this.setupRoutes();
|
this.setupRoutes();
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIBlockGridElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockGridElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement
|
|||||||
public config?: UmbPropertyEditorConfigCollection;
|
public config?: UmbPropertyEditorConfigCollection;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`<div>umb-property-editor-ui-block-list-block-configuration</div>`;
|
return html` <div>umb-property-editor-ui-block-list-block-configuration</div> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [UmbTextStyles];
|
static styles = [UmbTextStyles];
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIBlockListBlockConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockListBlockConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockListBlockConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIBlockListElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockListElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIBlockListElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUICheckboxListElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICheckboxListElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICheckboxListElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUICollectionViewBulkActionPermissionsElement', () =>
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewBulkActionPermissionsElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewBulkActionPermissionsElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUICollectionViewColumnConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewColumnConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewColumnConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUICollectionViewLayoutConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewLayoutConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewLayoutConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUICollectionViewOrderByElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewOrderByElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewOrderByElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUICollectionViewElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUICollectionViewElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIColorPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIColorPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIColorPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ describe('UmbPropertyEditorUIDatePickerElement', () => {
|
|||||||
expect(inputElement.type).to.equal('time');
|
expect(inputElement.type).to.equal('time');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIDropdownElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIDropdownElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIDropdownElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIEyeDropperElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIEyeDropperElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIEyeDropperElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIIconPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIIconPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIIconPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIImageCropperElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropperElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropperElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { expect, fixture, html } from '@open-wc/testing';
|
import { expect, fixture, html } from '@open-wc/testing';
|
||||||
import { UmbPropertyEditorUIImageCropsConfigurationElement } from './property-editor-ui-image-crops-configuration.element.js';
|
import { UmbPropertyEditorUIImageCropsConfigurationElement } from './property-editor-ui-image-crops-configuration.element.js';
|
||||||
import { defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
//import { defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
||||||
|
|
||||||
describe('UmbPropertyEditorUIImageCropsConfigurationElement', () => {
|
describe('UmbPropertyEditorUIImageCropsConfigurationElement', () => {
|
||||||
let element: UmbPropertyEditorUIImageCropsConfigurationElement;
|
let element: UmbPropertyEditorUIImageCropsConfigurationElement;
|
||||||
@@ -15,8 +15,10 @@ describe('UmbPropertyEditorUIImageCropsConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropsConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropsConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
//TODO: This test is broken. It fails at forms because of missing labels even if you have them.
|
it('passes the a11y audit', async () => {
|
||||||
// await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
//TODO: This test is broken. It fails at forms because of missing labels even if you have them.
|
||||||
});
|
// await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUILabelElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUILabelElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUILabelElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIMarkdownEditorElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMarkdownEditorElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMarkdownEditorElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIMediaPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMediaPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMediaPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIMemberGroupPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMemberGroupPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMemberGroupPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIMemberPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMemberPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMemberPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
|
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
|
||||||
import { UmbInputMultiUrlElement } from '@umbraco-cms/backoffice/components';
|
import { UmbInputMultiUrlElement } from '@umbraco-cms/backoffice/components';
|
||||||
import { UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/workspace';
|
|
||||||
import { UmbLinkPickerLink } from '@umbraco-cms/backoffice/modal';
|
import { UmbLinkPickerLink } from '@umbraco-cms/backoffice/modal';
|
||||||
import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
@@ -49,7 +49,7 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement impl
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.consumeContext(UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN, (context) => {
|
this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
|
||||||
this.observe(context.alias, (alias) => {
|
this.observe(context.alias, (alias) => {
|
||||||
this._alias = alias;
|
this._alias = alias;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIMultiUrlPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMultiUrlPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMultiUrlPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIMultipleTextStringElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIMultipleTextStringElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIMultipleTextStringElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUINumberRangeElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUINumberRangeElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUINumberRangeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { expect, fixture, html } from '@open-wc/testing';
|
import { expect, fixture, html } from '@open-wc/testing';
|
||||||
import { UmbPropertyEditorUIOrderDirectionElement } from './property-editor-ui-order-direction.element.js';
|
import { UmbPropertyEditorUIOrderDirectionElement } from './property-editor-ui-order-direction.element.js';
|
||||||
//import { defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
import { defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
||||||
|
|
||||||
describe('UmbPropertyEditorUIOrderDirectionElement', () => {
|
describe('UmbPropertyEditorUIOrderDirectionElement', () => {
|
||||||
let element: UmbPropertyEditorUIOrderDirectionElement;
|
let element: UmbPropertyEditorUIOrderDirectionElement;
|
||||||
@@ -12,9 +12,10 @@ describe('UmbPropertyEditorUIOrderDirectionElement', () => {
|
|||||||
it('is defined with its own instance', () => {
|
it('is defined with its own instance', () => {
|
||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIOrderDirectionElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIOrderDirectionElement);
|
||||||
});
|
});
|
||||||
/*
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
*/
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIOverlaySizeElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIOverlaySizeElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIOverlaySizeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUIRadioButtonListElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIRadioButtonListElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIRadioButtonListElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUISliderElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUISliderElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUISliderElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ export class UmbPropertyEditorUITextBoxElement extends UmbLitElement implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onChange(e: Event) {
|
private onChange(e: Event) {
|
||||||
this.value = (e.target as HTMLInputElement).value;
|
const newValue = (e.target as HTMLInputElement).value;
|
||||||
|
if (newValue === this.value) return;
|
||||||
|
this.value = newValue;
|
||||||
this.dispatchEvent(new CustomEvent('property-value-change'));
|
this.dispatchEvent(new CustomEvent('property-value-change'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ export class UmbPropertyEditorUITextBoxElement extends UmbLitElement implements
|
|||||||
.type=${this._type}
|
.type=${this._type}
|
||||||
inputMode=${ifDefined(this._inputMode)}
|
inputMode=${ifDefined(this._inputMode)}
|
||||||
maxlength=${ifDefined(this._maxChars)}
|
maxlength=${ifDefined(this._maxChars)}
|
||||||
@change=${this.onChange}></uui-input>`;
|
@input=${this.onChange}></uui-input>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUITinyMceDimensionsConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceDimensionsConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceDimensionsConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUITinyMceMaxImSizeConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceMaxImageSizeConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceMaxImageSizeConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUITinyMceStylesheetsConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceStylesheetsConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceStylesheetsConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUITinyMceToolbarConfigurationElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceToolbarConfigurationElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceToolbarConfigurationElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUITinyMceElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITinyMceElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIToggleElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIToggleElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIToggleElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe('UmbPropertyEditorUITreePickerStartNodeElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITreePickerStartNodeElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITreePickerStartNodeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUITreePickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUITreePickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUITreePickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIUploadFieldElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIUploadFieldElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIUploadFieldElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIUserPickerElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIUserPickerElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIUserPickerElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ describe('UmbPropertyEditorUIValueTypeElement', () => {
|
|||||||
expect(element).to.be.instanceOf(UmbPropertyEditorUIValueTypeElement);
|
expect(element).to.be.instanceOf(UmbPropertyEditorUIValueTypeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the a11y audit', async () => {
|
if ((window as any).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
it('passes the a11y audit', async () => {
|
||||||
});
|
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './property/index.js';
|
||||||
|
export * from './property-dataset/index.js';
|
||||||
|
export * from './property-layout/index.js';
|
||||||
|
export * from './types/index.js';
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export * from './nameable-property-dataset-context.interface.js';
|
||||||
|
export * from './nameable-property-dataset-context.token.js';
|
||||||
|
export * from './property-dataset-base-context.js';
|
||||||
|
export * from './property-dataset-context.interface.js';
|
||||||
|
export * from './property-dataset-context.token.js';
|
||||||
|
export * from './property-dataset.element.js';
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { UmbPropertyDatasetContext } from './property-dataset-context.interface.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant context with ability to set the name of it.
|
||||||
|
*/
|
||||||
|
export interface UmbNameablePropertyDatasetContext extends UmbPropertyDatasetContext {
|
||||||
|
setName(name: string): void;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { type UmbPropertyDatasetContext } from './property-dataset-context.interface.js';
|
||||||
|
import { UmbNameablePropertyDatasetContext } from './nameable-property-dataset-context.interface.js';
|
||||||
|
import { UMB_PROPERTY_DATASET_CONTEXT } from './property-dataset-context.token.js';
|
||||||
|
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||||
|
|
||||||
|
export const isNameablePropertyDatasetContext = (
|
||||||
|
context: UmbPropertyDatasetContext,
|
||||||
|
): context is UmbNameablePropertyDatasetContext => 'setName' in context;
|
||||||
|
|
||||||
|
export const UMB_NAMEABLE_PROPERTY_DATASET_CONTEXT = new UmbContextToken<
|
||||||
|
UmbPropertyDatasetContext,
|
||||||
|
UmbNameablePropertyDatasetContext
|
||||||
|
>(UMB_PROPERTY_DATASET_CONTEXT.toString(), undefined, isNameablePropertyDatasetContext);
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
UMB_PROPERTY_DATASET_CONTEXT,
|
||||||
|
type UmbNameablePropertyDatasetContext,
|
||||||
|
type UmbPropertyDatasetContext,
|
||||||
|
} from '@umbraco-cms/backoffice/property';
|
||||||
|
import type { UmbPropertyValueData } from '../types/property-value-data.type.js';
|
||||||
|
import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||||
|
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||||
|
import { UmbArrayState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
|
||||||
|
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base property dataset context implementation.
|
||||||
|
* @class UmbPropertyDatasetBaseContext
|
||||||
|
* @extends {UmbContextBase}
|
||||||
|
*/
|
||||||
|
export class UmbPropertyDatasetBaseContext
|
||||||
|
extends UmbContextBase<typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE>
|
||||||
|
implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext
|
||||||
|
{
|
||||||
|
#name = new UmbStringState(undefined);
|
||||||
|
name = this.#name.asObservable();
|
||||||
|
|
||||||
|
#values = new UmbArrayState<UmbPropertyValueData>([], (x) => x.alias);
|
||||||
|
public readonly values = this.#values.asObservable();
|
||||||
|
private _entityType!: string;
|
||||||
|
private _unique!: string;
|
||||||
|
|
||||||
|
getEntityType() {
|
||||||
|
return this._entityType;
|
||||||
|
}
|
||||||
|
getUnique() {
|
||||||
|
return this._unique;
|
||||||
|
}
|
||||||
|
getName() {
|
||||||
|
return this.#name.getValue();
|
||||||
|
}
|
||||||
|
setName(name: string | undefined) {
|
||||||
|
this.#name.next(name);
|
||||||
|
}
|
||||||
|
getVariantId() {
|
||||||
|
return UmbVariantId.CreateInvariant();
|
||||||
|
}
|
||||||
|
// variant id for a specific property?
|
||||||
|
|
||||||
|
constructor(host: UmbControllerHost) {
|
||||||
|
// The controller alias, is a very generic name cause we want only one of these for this controller host.
|
||||||
|
super(host, UMB_PROPERTY_DATASET_CONTEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write proper JSDocs here.
|
||||||
|
*/
|
||||||
|
async propertyValueByAlias<ReturnType = unknown>(propertyAlias: string) {
|
||||||
|
return this.#values.asObservablePart((values) => {
|
||||||
|
const valueObj = values.find((x) => x.alias === propertyAlias);
|
||||||
|
return valueObj ? (valueObj.value as ReturnType) : undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write proper JSDocs here.
|
||||||
|
*/
|
||||||
|
setPropertyValue(alias: string, value: unknown) {
|
||||||
|
this.#values.appendOne({ alias, value });
|
||||||
|
}
|
||||||
|
|
||||||
|
getValues() {
|
||||||
|
return this.#values.getValue();
|
||||||
|
}
|
||||||
|
setValues(map: Array<UmbPropertyValueData>) {
|
||||||
|
this.#values.next(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,31 +2,34 @@ import type { UmbVariantId } from '../../variant/variant-id.class.js';
|
|||||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variant context, represents a set of properties.
|
* A property dataset context, represents the data of a set of properties.
|
||||||
* This can take form as many, so to list a few:
|
* This can take form as many, so to list a few:
|
||||||
* - A specific variant of content
|
* - A specific variant of content.
|
||||||
* - Content that does not vary
|
* - Content that does not vary.
|
||||||
* - A block.
|
* - A block.
|
||||||
* - A DataType configuration.
|
* - A DataType configuration.
|
||||||
|
* - A property editor that hosts a set of properties.
|
||||||
*
|
*
|
||||||
* The base type of this holds a Name and some Properties.
|
* The base type of this holds a Name and some Properties.
|
||||||
* Some might be enriches with Variant Info, like culture and segment.
|
* Some might be enriches with Variant Info, like culture and segment.
|
||||||
* Others might have saved publishing status.
|
* Others might have saved publishing status.
|
||||||
* Also setting the name is an additional feature.
|
* Also setting the name is an additional feature.
|
||||||
*/
|
*/
|
||||||
export interface UmbVariantContext {
|
export interface UmbPropertyDatasetContext {
|
||||||
getType(): string;
|
getEntityType(): string;
|
||||||
getUnique(): string | undefined;
|
getUnique(): string | undefined;
|
||||||
//getUniqueName(): string;
|
|
||||||
getVariantId: () => UmbVariantId;
|
getVariantId: () => UmbVariantId;
|
||||||
|
|
||||||
getName(): string | undefined;
|
getName(): string | undefined;
|
||||||
readonly name: Observable<string | undefined>;
|
readonly name: Observable<string | undefined>;
|
||||||
|
|
||||||
|
// Should it be possible to get the properties as a list of property aliases?
|
||||||
|
//readonly properties: Observable<Array<string>>;
|
||||||
|
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
|
|
||||||
// Property methods:
|
// Property methods:
|
||||||
propertyVariantId?: (propertyAlias: string) => Promise<Observable<UmbVariantId | undefined>>;
|
propertyVariantId?: (propertyAlias: string) => Promise<Observable<UmbVariantId | undefined>>;
|
||||||
propertyValueByAlias<ReturnType = unknown>(propertyAlias: string): Promise<Observable<ReturnType | undefined>>;
|
propertyValueByAlias<ReturnType = unknown>(propertyAlias: string): Promise<Observable<ReturnType | undefined>>;
|
||||||
setPropertyValue(propertyAlias: string, value: unknown): Promise<void>;
|
setPropertyValue(propertyAlias: string, value: unknown): void;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { type UmbPropertyDatasetContext } from './property-dataset-context.interface.js';
|
||||||
|
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||||
|
|
||||||
|
export const UMB_PROPERTY_DATASET_CONTEXT = new UmbContextToken<UmbPropertyDatasetContext>('UmbPropertyDatasetContext');
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
import { expect, fixture, oneEvent } from '@open-wc/testing';
|
||||||
|
import type { UmbPropertyValueData } from '../types/property-value-data.type.js';
|
||||||
|
import { UMB_PROPERTY_DATASET_CONTEXT } from './property-dataset-context.token.js';
|
||||||
|
import { UmbPropertyDatasetElement } from './property-dataset.element.js';
|
||||||
|
import { customElement, html, property, state, LitElement } from '@umbraco-cms/backoffice/external/lit';
|
||||||
|
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||||
|
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||||
|
|
||||||
|
@customElement('test-property-editor')
|
||||||
|
export class UmbTestPropertyEditorElement extends UmbElementMixin(LitElement) {
|
||||||
|
//
|
||||||
|
_datasetContext?: typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE;
|
||||||
|
|
||||||
|
@property()
|
||||||
|
public get alias() {
|
||||||
|
return this._alias;
|
||||||
|
}
|
||||||
|
public set alias(value) {
|
||||||
|
this._alias = value;
|
||||||
|
this._observeProperty();
|
||||||
|
}
|
||||||
|
_alias?: string;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
_value?: string;
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
setValue(value: string) {
|
||||||
|
if (this._alias) {
|
||||||
|
this._datasetContext?.setPropertyValue(this._alias, value);
|
||||||
|
this.dispatchEvent(new UmbChangeEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _observeProperty() {
|
||||||
|
if (!this._datasetContext || !this._alias) return;
|
||||||
|
this.observe(
|
||||||
|
await this._datasetContext.propertyValueByAlias(this._alias),
|
||||||
|
(value) => {
|
||||||
|
this._value = value as string;
|
||||||
|
},
|
||||||
|
'observeValue',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (variantContext) => {
|
||||||
|
this._datasetContext = variantContext;
|
||||||
|
this._observeProperty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapter property editor, which tests what happens if a editor sets values of other editors.
|
||||||
|
@customElement('test-adapter-property-editor')
|
||||||
|
export class UmbTestAdapterPropertyEditorElement extends UmbTestPropertyEditorElement {
|
||||||
|
protected async _observeProperty() {
|
||||||
|
super._observeProperty();
|
||||||
|
if (!this._datasetContext || !this._alias) return;
|
||||||
|
this.observe(
|
||||||
|
await this._datasetContext.propertyValueByAlias(this._alias),
|
||||||
|
(value) => {
|
||||||
|
this._datasetContext?.setPropertyValue('testAlias', 'setByAdapter_' + value);
|
||||||
|
},
|
||||||
|
'observeValue',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataSet: Array<UmbPropertyValueData> = [
|
||||||
|
{
|
||||||
|
alias: 'testAlias',
|
||||||
|
value: 'testValue',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('UmbBasicVariantElement', () => {
|
||||||
|
describe('Public API', () => {
|
||||||
|
let datasetElement: UmbPropertyDatasetElement;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
datasetElement = await fixture(
|
||||||
|
html`<umb-property-dataset .name=${'hi'} .value=${dataSet}> </umb-property-dataset>`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('properties', () => {
|
||||||
|
it('has a value property', () => {
|
||||||
|
expect(datasetElement).to.have.property('value').to.be.an.a('array');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has a name property', () => {
|
||||||
|
expect(datasetElement).to.have.property('name').to.be.an.a('string');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Data bindings', () => {
|
||||||
|
let datasetElement: UmbPropertyDatasetElement;
|
||||||
|
let propertyEditor: UmbTestPropertyEditorElement;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
datasetElement = await fixture(
|
||||||
|
html`<umb-property-dataset .value=${dataSet}>
|
||||||
|
<test-property-editor alias="testAlias"></test-property-editor>
|
||||||
|
</umb-property-dataset>`,
|
||||||
|
);
|
||||||
|
|
||||||
|
propertyEditor = datasetElement.querySelector('test-property-editor') as UmbTestPropertyEditorElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defines with its own instance', () => {
|
||||||
|
expect(datasetElement).to.be.instanceOf(UmbPropertyDatasetElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('provides the value for the property editor to get', () => {
|
||||||
|
expect(propertyEditor.alias).to.equal('testAlias');
|
||||||
|
expect(propertyEditor.getValue()).to.equal('testValue');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('property editor sets value on it self', () => {
|
||||||
|
propertyEditor.setValue('testValue2');
|
||||||
|
expect(propertyEditor.getValue()).to.equal('testValue2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('retrieves value set by child', () => {
|
||||||
|
propertyEditor.setValue('testValue2');
|
||||||
|
expect(datasetElement.context.getValues()[0].alias).to.equal('testAlias');
|
||||||
|
expect(datasetElement.context.getValues()[0].value).to.equal('testValue2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fires change event', async () => {
|
||||||
|
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE);
|
||||||
|
|
||||||
|
expect(propertyEditor.alias).to.eq('testAlias');
|
||||||
|
propertyEditor.setValue('testValue3');
|
||||||
|
|
||||||
|
const event = (await listener) as unknown as UmbChangeEvent;
|
||||||
|
expect(event).to.exist;
|
||||||
|
expect(event.type).to.eq(UmbChangeEvent.TYPE);
|
||||||
|
expect(event.target).to.equal(datasetElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does respond to changes triggered internally', async () => {
|
||||||
|
const adapterPropertyEditor = document.createElement(
|
||||||
|
'test-adapter-property-editor',
|
||||||
|
) as UmbTestAdapterPropertyEditorElement;
|
||||||
|
|
||||||
|
// We actually do not use the alias of the adapter property editor, but we need to set this to start observing the property value:
|
||||||
|
adapterPropertyEditor.alias = 'testAdapterAlias';
|
||||||
|
datasetElement.appendChild(adapterPropertyEditor);
|
||||||
|
|
||||||
|
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE);
|
||||||
|
|
||||||
|
// The alias of the original property editor must be 'testAlias' for the adapter to set the value of it.
|
||||||
|
expect(propertyEditor.alias).to.eq('testAlias');
|
||||||
|
expect(adapterPropertyEditor.alias).to.eq('testAdapterAlias');
|
||||||
|
adapterPropertyEditor.setValue('testValue4');
|
||||||
|
|
||||||
|
const event = (await listener) as unknown as UmbChangeEvent;
|
||||||
|
expect(event).to.exist;
|
||||||
|
expect(event.type).to.eq(UmbChangeEvent.TYPE);
|
||||||
|
expect(event.target).to.equal(datasetElement);
|
||||||
|
expect(adapterPropertyEditor.getValue()).to.equal('testValue4');
|
||||||
|
expect(propertyEditor.getValue()).to.equal('setByAdapter_testValue4');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import type { UmbPropertyValueData } from '../types/property-value-data.type.js';
|
||||||
|
import { UmbPropertyDatasetBaseContext } from './property-dataset-base-context.js';
|
||||||
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
|
import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
|
||||||
|
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @element umb-property-dataset
|
||||||
|
* @description - Element for hosting a property dataset. This is needed for umb-property to work.
|
||||||
|
* @slot default - Slot for rendering content within.
|
||||||
|
*/
|
||||||
|
@customElement('umb-property-dataset')
|
||||||
|
export class UmbPropertyDatasetElement extends UmbLitElement {
|
||||||
|
// Determine wether state change should fire an event when the value is changed.
|
||||||
|
#allowChangeEvent = false;
|
||||||
|
|
||||||
|
public readonly context: UmbPropertyDatasetBaseContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the dataset.
|
||||||
|
* @returns {Array<UmbPropertyValueData>}
|
||||||
|
* @memberof UmbBasicVariantElement
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const dataSet = [
|
||||||
|
* {
|
||||||
|
* alias: 'testAlias',
|
||||||
|
* value: 'value as a string',
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* alias: 'anotherAlias',
|
||||||
|
* value: 123,
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* html`
|
||||||
|
* <umb-property-dataset .value="${dataSet}">
|
||||||
|
* <umb-property
|
||||||
|
* label="My label for this property"
|
||||||
|
* description="The description to show on the property"
|
||||||
|
* alias="testAlias"
|
||||||
|
* property-editor-ui-alias="Umb.PropertyEditorUi.TextBox"
|
||||||
|
* .config=${...}>
|
||||||
|
* </umb-property>
|
||||||
|
* </umb-property-dataset>
|
||||||
|
* `
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@property({ attribute: false })
|
||||||
|
public get value(): Array<UmbPropertyValueData> {
|
||||||
|
return this.context.getValues();
|
||||||
|
}
|
||||||
|
public set value(value: Array<UmbPropertyValueData>) {
|
||||||
|
this.#allowChangeEvent = false;
|
||||||
|
this.context.setValues(value);
|
||||||
|
// Above might not trigger a observer callback (if no change), so set the allow change event to true:
|
||||||
|
this.#allowChangeEvent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the dataset, this name varies depending on the use-case. But this is either
|
||||||
|
* @type {string}
|
||||||
|
* @returns {string}
|
||||||
|
* @memberof UmbBasicVariantElement
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* html`
|
||||||
|
* <umb-property-dataset name="My variant name">
|
||||||
|
* ...
|
||||||
|
* </umb-property-dataset>
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
@property({ attribute: false })
|
||||||
|
public get name(): string | undefined {
|
||||||
|
return this.context.getName();
|
||||||
|
}
|
||||||
|
public set name(value: string | undefined) {
|
||||||
|
this.#allowChangeEvent = false;
|
||||||
|
this.context.setName(value);
|
||||||
|
// Above might not trigger a observer callback (if no change), so set the allow change event to true:
|
||||||
|
this.#allowChangeEvent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Prevent any child events escaping this element.
|
||||||
|
this.addEventListener('change', (e) => {
|
||||||
|
if (e.target !== this) {
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.context = new UmbPropertyDatasetBaseContext(this);
|
||||||
|
// prevent the first change event from firing:
|
||||||
|
this.#allowChangeEvent = false;
|
||||||
|
this.observe(this.context.name, this.#observerCallback);
|
||||||
|
// prevent the first change event from firing:
|
||||||
|
this.#allowChangeEvent = false;
|
||||||
|
this.observe(this.context.values, this.#observerCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#observerCallback = () => {
|
||||||
|
if (this.#allowChangeEvent) {
|
||||||
|
this.dispatchEvent(new UmbChangeEvent());
|
||||||
|
} else {
|
||||||
|
// Set allow change event to true.
|
||||||
|
this.#allowChangeEvent = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`<slot></slot>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UmbPropertyDatasetElement;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'umb-property-dataset': UmbPropertyDatasetElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './property-layout.element.js';
|
||||||
@@ -2,14 +2,14 @@ import { css, html, LitElement, customElement, property } from '@umbraco-cms/bac
|
|||||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @element umb-workspace-property-layout
|
* @element umb-property-layout
|
||||||
* @description - Element for displaying a property in an workspace.
|
* @description - Element for displaying a property in an workspace.
|
||||||
* @slot editor - Slot for rendering the Property Editor
|
* @slot editor - Slot for rendering the Property Editor
|
||||||
* @slot description - Slot for rendering things below the label.
|
* @slot description - Slot for rendering things below the label.
|
||||||
* @slot property-action-menu - Slot for rendering the Property Action Menu
|
* @slot action-menu - Slot for rendering the Property Action Menu
|
||||||
*/
|
*/
|
||||||
@customElement('umb-workspace-property-layout')
|
@customElement('umb-property-layout')
|
||||||
export class UmbWorkspacePropertyLayoutElement extends LitElement {
|
export class UmbPropertyLayoutElement extends LitElement {
|
||||||
/**
|
/**
|
||||||
* Alias. The technical name of the property.
|
* Alias. The technical name of the property.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -52,7 +52,7 @@ export class UmbWorkspacePropertyLayoutElement extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div id="headerColumn">
|
<div id="headerColumn">
|
||||||
<uui-label title=${this.alias}>${this.label}</uui-label>
|
<uui-label title=${this.alias}>${this.label}</uui-label>
|
||||||
<slot name="property-action-menu"></slot>
|
<slot name="action-menu"></slot>
|
||||||
<div id="description">${this.description}</div>
|
<div id="description">${this.description}</div>
|
||||||
<slot name="description"></slot>
|
<slot name="description"></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,6 +117,6 @@ export class UmbWorkspacePropertyLayoutElement extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
'umb-workspace-property-layout': UmbWorkspacePropertyLayoutElement;
|
'umb-property-layout': UmbPropertyLayoutElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Meta, Story } from '@storybook/web-components';
|
||||||
|
import type { UmbPropertyLayoutElement } from './property-layout.element.js';
|
||||||
|
import { html } from '@umbraco-cms/backoffice/external/lit';
|
||||||
|
|
||||||
|
import './property-layout.element.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Workspaces/Property Layout',
|
||||||
|
component: 'umb-property-layout',
|
||||||
|
id: 'umb-property-layout',
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
export const AAAOverview: Story<UmbPropertyLayoutElement> = () =>
|
||||||
|
html` <umb-property-layout label="Label" description="Description">
|
||||||
|
<div slot="action-menu"><uui-button color="" look="placeholder">Action Menu</uui-button></div>
|
||||||
|
|
||||||
|
<div slot="editor"><uui-button color="" look="placeholder">Editor</uui-button></div>
|
||||||
|
</umb-property-layout>`;
|
||||||
|
AAAOverview.storyName = 'Overview';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './property.context.js';
|
||||||
|
export * from './property.element.js';
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
|
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||||
import { UmbPropertyEditorUiElement } from '../../extension-registry/interfaces/property-editor-ui-element.interface.js';
|
import { UmbPropertyEditorUiElement } from '../../extension-registry/interfaces/property-editor-ui-element.interface.js';
|
||||||
import { type WorkspacePropertyData } from '../types/workspace-property-data.type.js';
|
import { type WorkspacePropertyData } from '../../workspace/types/workspace-property-data.type.js';
|
||||||
import { UMB_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
|
||||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||||
import { type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
import { type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||||
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
|
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
|
||||||
import {
|
import {
|
||||||
|
UmbBasicState,
|
||||||
UmbClassState,
|
UmbClassState,
|
||||||
UmbObjectState,
|
UmbObjectState,
|
||||||
UmbStringState,
|
|
||||||
UmbObserverController,
|
UmbObserverController,
|
||||||
UmbBasicState,
|
UmbStringState,
|
||||||
} from '@umbraco-cms/backoffice/observable-api';
|
} from '@umbraco-cms/backoffice/observable-api';
|
||||||
import { UmbContextProviderController, UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
import { UmbContextProviderController, UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||||
import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||||
|
|
||||||
export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseController {
|
export class UmbPropertyContext<ValueType = any> extends UmbBaseController {
|
||||||
private _providerController: UmbContextProviderController;
|
private _providerController: UmbContextProviderController;
|
||||||
|
|
||||||
#data = new UmbObjectState<WorkspacePropertyData<ValueType>>({});
|
#data = new UmbObjectState<WorkspacePropertyData<ValueType>>({});
|
||||||
@@ -44,13 +44,13 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
private _variantDifference = new UmbStringState(undefined);
|
private _variantDifference = new UmbStringState(undefined);
|
||||||
public readonly variantDifference = this._variantDifference.asObservable();
|
public readonly variantDifference = this._variantDifference.asObservable();
|
||||||
|
|
||||||
#variantContext?: typeof UMB_VARIANT_CONTEXT.TYPE;
|
#datasetContext?: typeof UMB_PROPERTY_DATASET_CONTEXT.TYPE;
|
||||||
|
|
||||||
constructor(host: UmbControllerHostElement) {
|
constructor(host: UmbControllerHostElement) {
|
||||||
super(host);
|
super(host);
|
||||||
|
|
||||||
this.consumeContext(UMB_VARIANT_CONTEXT, (variantContext) => {
|
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (variantContext) => {
|
||||||
this.#variantContext = variantContext;
|
this.#datasetContext = variantContext;
|
||||||
this._generateVariantDifferenceString();
|
this._generateVariantDifferenceString();
|
||||||
this._observeProperty();
|
this._observeProperty();
|
||||||
});
|
});
|
||||||
@@ -59,7 +59,7 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
this._observeProperty();
|
this._observeProperty();
|
||||||
});
|
});
|
||||||
|
|
||||||
this._providerController = new UmbContextProviderController(host, UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN, this);
|
this._providerController = new UmbContextProviderController(host, UMB_PROPERTY_CONTEXT, this);
|
||||||
|
|
||||||
this.observe(this.configValues, (configValues) => {
|
this.observe(this.configValues, (configValues) => {
|
||||||
this.#configCollection.next(configValues ? new UmbPropertyEditorConfigCollection(configValues) : undefined);
|
this.#configCollection.next(configValues ? new UmbPropertyEditorConfigCollection(configValues) : undefined);
|
||||||
@@ -74,9 +74,9 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
private _observePropertyValue?: UmbObserverController<ValueType | undefined>;
|
private _observePropertyValue?: UmbObserverController<ValueType | undefined>;
|
||||||
private async _observeProperty() {
|
private async _observeProperty() {
|
||||||
const alias = this.#data.getValue().alias;
|
const alias = this.#data.getValue().alias;
|
||||||
if (!this.#variantContext || !alias) return;
|
if (!this.#datasetContext || !alias) return;
|
||||||
|
|
||||||
const variantIdSubject = (await this.#variantContext.propertyVariantId?.(alias)) ?? undefined;
|
const variantIdSubject = (await this.#datasetContext.propertyVariantId?.(alias)) ?? undefined;
|
||||||
this._observePropertyVariant?.destroy();
|
this._observePropertyVariant?.destroy();
|
||||||
if (variantIdSubject) {
|
if (variantIdSubject) {
|
||||||
this._observePropertyVariant = this.observe(variantIdSubject, (variantId) => {
|
this._observePropertyVariant = this.observe(variantIdSubject, (variantId) => {
|
||||||
@@ -85,7 +85,7 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Verify if we need to optimize runtime by parsing the propertyVariantID, cause this method retrieves it again:
|
// TODO: Verify if we need to optimize runtime by parsing the propertyVariantID, cause this method retrieves it again:
|
||||||
const subject = await this.#variantContext.propertyValueByAlias<ValueType>(alias);
|
const subject = await this.#datasetContext.propertyValueByAlias<ValueType>(alias);
|
||||||
|
|
||||||
this._observePropertyValue?.destroy();
|
this._observePropertyValue?.destroy();
|
||||||
if (subject) {
|
if (subject) {
|
||||||
@@ -97,8 +97,8 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _generateVariantDifferenceString() {
|
private _generateVariantDifferenceString() {
|
||||||
if (!this.#variantContext) return;
|
if (!this.#datasetContext) return;
|
||||||
const contextVariantId = this.#variantContext.getVariantId?.() ?? undefined;
|
const contextVariantId = this.#datasetContext.getVariantId?.() ?? undefined;
|
||||||
this._variantDifference.next(
|
this._variantDifference.next(
|
||||||
contextVariantId ? this.#variantId.getValue()?.toDifferencesString(contextVariantId) : '',
|
contextVariantId ? this.#variantId.getValue()?.toDifferencesString(contextVariantId) : '',
|
||||||
);
|
);
|
||||||
@@ -115,9 +115,8 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
}
|
}
|
||||||
public setValue(value: WorkspacePropertyData<ValueType>['value']) {
|
public setValue(value: WorkspacePropertyData<ValueType>['value']) {
|
||||||
const alias = this.#data.getValue().alias;
|
const alias = this.#data.getValue().alias;
|
||||||
if (!this.#variantContext || !alias) return;
|
if (!this.#datasetContext || !alias) return;
|
||||||
|
this.#datasetContext?.setPropertyValue(alias, value);
|
||||||
this.#variantContext?.setPropertyValue(alias, value);
|
|
||||||
}
|
}
|
||||||
public setConfig(config: WorkspacePropertyData<ValueType>['config'] | undefined) {
|
public setConfig(config: WorkspacePropertyData<ValueType>['config'] | undefined) {
|
||||||
this.#data.update({ config });
|
this.#data.update({ config });
|
||||||
@@ -139,6 +138,4 @@ export class UmbWorkspacePropertyContext<ValueType = any> extends UmbBaseControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UMB_WORKSPACE_PROPERTY_CONTEXT_TOKEN = new UmbContextToken<UmbWorkspacePropertyContext>(
|
export const UMB_PROPERTY_CONTEXT = new UmbContextToken<UmbPropertyContext>('UmbPropertyContext');
|
||||||
'UmbWorkspacePropertyContext',
|
|
||||||
);
|
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
import { type UmbPropertyEditorConfig } from '../../property-editor/index.js';
|
import { UmbPropertyContext } from './property.context.js';
|
||||||
import { UmbWorkspacePropertyContext } from './workspace-property.context.js';
|
|
||||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||||
import { css, html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
import { css, html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
|
import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
|
||||||
import { ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
import { ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||||
import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
|
import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
|
||||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||||
import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
import {
|
||||||
|
UmbPropertyEditorConfigCollection,
|
||||||
|
type UmbPropertyEditorConfig,
|
||||||
|
} from '@umbraco-cms/backoffice/property-editor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @element umb-workspace-property
|
* @element umb-property
|
||||||
* @description - Component for displaying a entity property. The Element will render a Property Editor based on the Property Editor UI alias passed to the element.
|
* @description Component for displaying a property with editor from extension registry.
|
||||||
* The element will also render all Property Actions related to the Property Editor.
|
* The Element will render a Property Editor based on the Property Editor UI alias passed to the element.
|
||||||
|
* This will also render all Property Actions related to the Property Editor UI Alias.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@customElement('umb-workspace-property')
|
@customElement('umb-property')
|
||||||
export class UmbWorkspacePropertyElement extends UmbLitElement {
|
export class UmbPropertyElement extends UmbLitElement {
|
||||||
/**
|
/**
|
||||||
* Label. Name of the property
|
* Label. Name of the property
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@@ -24,7 +27,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
public set label(label: string) {
|
public set label(label: string) {
|
||||||
this._propertyContext.setLabel(label);
|
this.#propertyContext.setLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,7 +38,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
public set description(description: string) {
|
public set description(description: string) {
|
||||||
this._propertyContext.setDescription(description);
|
this.#propertyContext.setDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,7 +50,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
public set alias(alias: string) {
|
public set alias(alias: string) {
|
||||||
this._propertyContext.setAlias(alias);
|
this.#propertyContext.setAlias(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,13 +60,13 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
* @attr
|
* @attr
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
private _propertyEditorUiAlias = '';
|
|
||||||
@property({ type: String, attribute: 'property-editor-ui-alias' })
|
@property({ type: String, attribute: 'property-editor-ui-alias' })
|
||||||
public set propertyEditorUiAlias(value: string) {
|
public set propertyEditorUiAlias(value: string) {
|
||||||
if (this._propertyEditorUiAlias === value) return;
|
if (this._propertyEditorUiAlias === value) return;
|
||||||
this._propertyEditorUiAlias = value;
|
this._propertyEditorUiAlias = value;
|
||||||
this._observePropertyEditorUI();
|
this._observePropertyEditorUI();
|
||||||
}
|
}
|
||||||
|
private _propertyEditorUiAlias = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config. Configuration to pass to the Property Editor UI. This is also the configuration data stored on the Data Type.
|
* Config. Configuration to pass to the Property Editor UI. This is also the configuration data stored on the Data Type.
|
||||||
@@ -74,7 +77,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: Array, attribute: false })
|
@property({ type: Array, attribute: false })
|
||||||
public set config(value: UmbPropertyEditorConfig | undefined) {
|
public set config(value: UmbPropertyEditorConfig | undefined) {
|
||||||
this._propertyContext.setConfig(value);
|
this.#propertyContext.setConfig(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
@@ -95,24 +98,24 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
@state()
|
@state()
|
||||||
private _description?: string;
|
private _description?: string;
|
||||||
|
|
||||||
private _propertyContext = new UmbWorkspacePropertyContext(this);
|
#propertyContext = new UmbPropertyContext(this);
|
||||||
|
|
||||||
private _valueObserver?: UmbObserverController<unknown>;
|
#valueObserver?: UmbObserverController<unknown>;
|
||||||
private _configObserver?: UmbObserverController<UmbPropertyEditorConfigCollection | undefined>;
|
#configObserver?: UmbObserverController<UmbPropertyEditorConfigCollection | undefined>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.observe(this._propertyContext.alias, (alias) => {
|
this.observe(this.#propertyContext.alias, (alias) => {
|
||||||
this._alias = alias;
|
this._alias = alias;
|
||||||
});
|
});
|
||||||
this.observe(this._propertyContext.label, (label) => {
|
this.observe(this.#propertyContext.label, (label) => {
|
||||||
this._label = label;
|
this._label = label;
|
||||||
});
|
});
|
||||||
this.observe(this._propertyContext.description, (description) => {
|
this.observe(this.#propertyContext.description, (description) => {
|
||||||
this._description = description;
|
this._description = description;
|
||||||
});
|
});
|
||||||
this.observe(this._propertyContext.variantDifference, (variantDifference) => {
|
this.observe(this.#propertyContext.variantDifference, (variantDifference) => {
|
||||||
this._variantDifference = variantDifference;
|
this._variantDifference = variantDifference;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -121,7 +124,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
const target = e.composedPath()[0] as any;
|
const target = e.composedPath()[0] as any;
|
||||||
|
|
||||||
//this.value = target.value; // Sets value in context.
|
//this.value = target.value; // Sets value in context.
|
||||||
this._propertyContext.setValue(target.value);
|
this.#propertyContext.setValue(target.value);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -136,7 +139,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _gotEditorUI(manifest?: ManifestPropertyEditorUi | null) {
|
private async _gotEditorUI(manifest?: ManifestPropertyEditorUi | null) {
|
||||||
this._propertyContext.setEditor(undefined);
|
this.#propertyContext.setEditor(undefined);
|
||||||
|
|
||||||
if (!manifest) {
|
if (!manifest) {
|
||||||
// TODO: if propertyEditorUiAlias didn't exist in store, we should do some nice fail UI.
|
// TODO: if propertyEditorUiAlias didn't exist in store, we should do some nice fail UI.
|
||||||
@@ -144,49 +147,44 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const el = await createExtensionElement(manifest);
|
const el = await createExtensionElement(manifest);
|
||||||
if (el) {
|
|
||||||
const oldValue = this._element;
|
|
||||||
|
|
||||||
oldValue?.removeEventListener('change', this._onPropertyEditorChange as any as EventListener);
|
if (el) {
|
||||||
|
const oldElement = this._element;
|
||||||
|
|
||||||
|
// cleanup:
|
||||||
|
this.#valueObserver?.destroy();
|
||||||
|
this.#configObserver?.destroy();
|
||||||
|
oldElement?.removeEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener);
|
||||||
|
|
||||||
this._element = el as ManifestPropertyEditorUi['ELEMENT_TYPE'];
|
this._element = el as ManifestPropertyEditorUi['ELEMENT_TYPE'];
|
||||||
|
|
||||||
this._propertyContext.setEditor(this._element);
|
this.#propertyContext.setEditor(this._element);
|
||||||
|
|
||||||
this._valueObserver?.destroy();
|
|
||||||
this._configObserver?.destroy();
|
|
||||||
|
|
||||||
if (this._element) {
|
if (this._element) {
|
||||||
|
// TODO: Could this be changed to change event? (or additionally support change?)
|
||||||
this._element.addEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener);
|
this._element.addEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener);
|
||||||
|
|
||||||
this._valueObserver = this.observe(
|
// No need for a controller alias, as the clean is handled via the observer prop:
|
||||||
this._propertyContext.value,
|
this.#valueObserver = this.observe(this.#propertyContext.value, (value) => {
|
||||||
(value) => {
|
this._value = value;
|
||||||
this._value = value;
|
if (this._element) {
|
||||||
if (this._element) {
|
this._element.value = value;
|
||||||
this._element.value = value;
|
}
|
||||||
}
|
});
|
||||||
},
|
this.#configObserver = this.observe(this.#propertyContext.config, (config) => {
|
||||||
'_observePropertyValue',
|
if (this._element && config) {
|
||||||
);
|
this._element.config = config;
|
||||||
this._configObserver = this.observe(
|
}
|
||||||
this._propertyContext.config,
|
});
|
||||||
(config) => {
|
|
||||||
if (this._element && config) {
|
|
||||||
this._element.config = config;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'_observePropertyConfig',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.requestUpdate('element', oldValue);
|
this.requestUpdate('element', oldElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<umb-workspace-property-layout
|
<umb-property-layout
|
||||||
id="layout"
|
id="layout"
|
||||||
alias="${ifDefined(this._alias)}"
|
alias="${ifDefined(this._alias)}"
|
||||||
label="${ifDefined(this._label)}"
|
label="${ifDefined(this._label)}"
|
||||||
@@ -196,15 +194,15 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
? html`<uui-tag look="secondary" slot="description">${this._variantDifference}</uui-tag>`
|
? html`<uui-tag look="secondary" slot="description">${this._variantDifference}</uui-tag>`
|
||||||
: ''}
|
: ''}
|
||||||
<div slot="editor">${this._element}</div>
|
<div slot="editor">${this._element}</div>
|
||||||
</umb-workspace-property-layout>
|
</umb-property-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderPropertyActionMenu() {
|
private _renderPropertyActionMenu() {
|
||||||
return html`${this._propertyEditorUiAlias
|
return html`${this._propertyEditorUiAlias
|
||||||
? html`<umb-property-action-menu
|
? html`<umb-property-action-menu
|
||||||
slot="property-action-menu"
|
slot="action-menu"
|
||||||
id="property-action-menu"
|
id="action-menu"
|
||||||
.propertyEditorUiAlias=${this._propertyEditorUiAlias}
|
.propertyEditorUiAlias=${this._propertyEditorUiAlias}
|
||||||
.value=${this._value}></umb-property-action-menu>`
|
.value=${this._value}></umb-property-action-menu>`
|
||||||
: ''}`;
|
: ''}`;
|
||||||
@@ -221,13 +219,13 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
color: var(--uui-color-text-alt);
|
color: var(--uui-color-text-alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#property-action-menu {
|
#action-menu {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#layout:focus-within #property-action-menu,
|
#layout:focus-within #action-menu,
|
||||||
#layout:hover #property-action-menu,
|
#layout:hover #action-menu,
|
||||||
#property-action-menu[open] {
|
#action-menu[open] {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,6 +238,6 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
'umb-workspace-property': UmbWorkspacePropertyElement;
|
'umb-property': UmbPropertyElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Meta, Story } from '@storybook/web-components';
|
||||||
|
import type { UmbPropertyElement } from './property.element.js';
|
||||||
|
import { html } from '@umbraco-cms/backoffice/external/lit';
|
||||||
|
|
||||||
|
import './property.element.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/Property',
|
||||||
|
component: 'umb-property',
|
||||||
|
id: 'umb-property',
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
export const AAAOverview: Story<UmbPropertyElement> = () =>
|
||||||
|
html` <umb-property
|
||||||
|
label="Property"
|
||||||
|
description="Description"
|
||||||
|
alias="textProperty"
|
||||||
|
property-editor-ui-alias="Umb.PropertyEditorUi.TextBox"
|
||||||
|
.value="${'Hello'}"></umb-property>`;
|
||||||
|
AAAOverview.storyName = 'Overview';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './property-value-data.type.js';
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user