Trying to render a umb-property-editor-ui-block-list on a custom workspace panel

Im trying to place a umb-property-editor-ui-block-list editor on a workplace panel in a custom section.

I can get the Add button to display (only by going back to content and a page that hase a BlockList omponent on it. Then returning to my section panel).

This is what I have

`// Start with an empty BlockEditorModel
value = {
    layout: [],
    contentData: [],
    settingsData: []
};`

`` connectedCallback() {
super.connectedCallback();

    // Wait for first render so the workspace shell exists
    this.loadBlockListConfig();
}



/* -------------------------------------------------------------
   LOAD BLOCK LIST CONFIG (datatype definition)
   ------------------------------------------------------------- */
private async loadBlockListConfig() {
    const response = await umbHttpClient.get({
        url: `/umbraco/management/api/v1/data-type/55e53032-de54-49ae-9232-c79fcfa91c4e`,
        security: [{ scheme: "bearer", type: "http" }]
    });

    this.config = (response.data as any).values;
    console.log("🔵 BlockList Config:", this.config);
} ``

then I render it

`` render() {
    return html`
        <h2>Calendar Group</h2>
        <umb-property-editor-ui-block-list
            .value=${this.value}
            .config=${this.config}
            @umb-property-value-change=${this.onValueChange}>
        </umb-property-editor-ui-block-list>
    `;
} ``

like I said I can get the add button to render but it comes with errors

property-editor-ui-block-list.element.ts:105 Uncaught (in promise) TypeError: t.getValueByAlias is not a function
at set config (property-editor-ui-block-list.element.ts:105:34)
at Nt.j (lit-html.js:6:6006)
at Nt.$AI (lit-html.js:6:5815)
at Rt.p (lit-html.js:6:3601)
at U.$ (lit-html.js:6:4600)
at U.
$AI (lit-html.js:6:4152)
at Dt (lit-html.js:6:7083)
at _GenesisCalendarGroupsWorkspace.update (lit-element.js:6:356)
at _GenesisCalendarGroupsWorkspace.performUpdate (reactive-element.js:6:5255)
at _GenesisCalendarGroupsWorkspace.scheduleUpdate (reactive-element.js:6:4775)
config @ property-editor-ui-block-list.element.ts:105
j @ lit-html.js:6
_$AI @ lit-html.js:6
p @ lit-html.js:6
$ @ lit-html.js:6
_$AI @ lit-html.js:6
(anonymous) @ lit-html.js:6
update @ lit-element.js:6
performUpdate @ reactive-element.js:6
scheduleUpdate @ reactive-element.js:6
_$EP @ reactive-element.js:6
await in _$EP
requestUpdate @ reactive-element.js:6
set @ reactive-element.js:6
loadBlockListConfig @ Genesis-Calendar.esm.js:2298
await in loadBlockListConfig
connectedCallback @ Genesis-Calendar.esm.js:2288
O @ lit-html.js:6
T @ lit-html.js:6
_$AI @ lit-html.js:6
(anonymous) @ lit-html.js:6
update @ lit-element.js:6
performUpdate @ reactive-element.js:6
scheduleUpdate @ reactive-element.js:6
_$EP @ reactive-element.js:6
await in _$EP
requestUpdate @ reactive-element.js:6
set @ reactive-element.js:6
(anonymous) @ workspace.element.ts:46
(anonymous) @ base-extensions-initializer.controller.ts:186
requestAnimationFrame
(anonymous) @ base-extensions-initializer.controller.ts:146
(anonymous) @ base-extension-initializer.controller.ts:329
await in (anonymous)
#gotManifest @ base-extension-initializer.controller.ts:169
(anonymous) @ base-extension-initializer.controller.ts:83
(anonymous) @ Subscriber.js:96
(anonymous) @ Subscriber.js:63
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ switchMap.js:14
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ innerFrom.js:51
(anonymous) @ Observable.js:38
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ switchMap.js:14
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ BehaviorSubject.js:19
(anonymous) @ Observable.js:38
(anonymous) @ Subject.js:95
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ Observable.js:66
(anonymous) @ Observable.js:30
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ switchMap.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
constructor @ observer.ts:16
constructor @ observer.controller.ts:19
observe @ class.mixin.ts:70
_init @ base-extension-initializer.controller.ts:72
constructor @ extension-element-and-api-initializer.controller.ts:115
_createController @ extensions-element-and-api-initializer.controller.ts:80
(anonymous) @ base-extensions-initializer.controller.ts:120
(anonymous) @ base-extensions-initializer.controller.ts:117
(anonymous) @ Subscriber.js:96
(anonymous) @ Subscriber.js:63
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ combineLatest.js:47
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ BehaviorSubject.js:19
(anonymous) @ Observable.js:38
(anonymous) @ Subject.js:95
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ Observable.js:66
(anonymous) @ Observable.js:30
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ combineLatest.js:40
maybeSchedule @ combineLatest.js:67
(anonymous) @ combineLatest.js:37
(anonymous) @ combineLatest.js:57
maybeSchedule @ combineLatest.js:67
(anonymous) @ combineLatest.js:31
(anonymous) @ Observable.js:38
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
constructor @ observer.ts:16
constructor @ observer.controller.ts:19
observe @ class.mixin.ts:70
_init @ base-extensions-initializer.controller.ts:86
constructor @ extensions-element-and-api-initializer.controller.ts:76
(anonymous) @ workspace.element.ts:39
entityType @ workspace.element.ts:31
set @ reactive-element.js:6
setup @ workspace-section-route.route-entry.ts:12
(anonymous) @ default-section.element.ts:85
resolvePageComponent @ router.ts:165
await in resolvePageComponent
renderPath @ router-slot.ts:441
render @ router-slot.ts:257
(anonymous) @ router-slot.ts:170
requestAnimationFrame
connectedCallback @ router-slot.ts:168
O @ lit-html.js:6
T @ lit-html.js:6
$ @ lit-html.js:6
_$AI @ lit-html.js:6
(anonymous) @ lit-html.js:6
update @ lit-element.js:6
performUpdate @ reactive-element.js:6
scheduleUpdate @ reactive-element.js:6
_$EP @ reactive-element.js:6
await in _$EP
requestUpdate @ reactive-element.js:6
_$Ev @ reactive-element.js:6
constructor @ reactive-element.js:6
constructor @ lit-element.js:6
(anonymous) @ controller-host.mixin.ts:19
(anonymous) @ controller-host-element.mixin.ts:13
(anonymous) @ element.mixin.ts:13
constructor @ lit-element.element.ts:10
constructor @ router-slot.element.ts:83
u @ lit-html.js:6
$ @ lit-html.js:6
_$AI @ lit-html.js:6
p @ lit-html.js:6
$ @ lit-html.js:6
_$AI @ lit-html.js:6
(anonymous) @ lit-html.js:6
update @ lit-element.js:6
performUpdate @ reactive-element.js:6
scheduleUpdate @ reactive-element.js:6
_$EP @ reactive-element.js:6
await in _$EP
requestUpdate @ reactive-element.js:6
set @ reactive-element.js:6
(anonymous) @ default-section.element.ts:98
(anonymous) @ default-section.element.ts:91
await in (anonymous)
(anonymous) @ base-extensions-initializer.controller.ts:186
requestAnimationFrame
(anonymous) @ base-extensions-initializer.controller.ts:146
(anonymous) @ base-extension-initializer.controller.ts:329
await in (anonymous)
#gotManifest @ base-extension-initializer.controller.ts:169
(anonymous) @ base-extension-initializer.controller.ts:83
(anonymous) @ Subscriber.js:96
(anonymous) @ Subscriber.js:63
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ switchMap.js:14
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ innerFrom.js:51
(anonymous) @ Observable.js:38
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ switchMap.js:14
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ BehaviorSubject.js:19
(anonymous) @ Observable.js:38
(anonymous) @ Subject.js:95
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ Observable.js:66
(anonymous) @ Observable.js:30
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ switchMap.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
constructor @ observer.ts:16
constructor @ observer.controller.ts:19
observe @ class.mixin.ts:70
_init @ base-extension-initializer.controller.ts:72
constructor @ extension-manifest-initializer.controller.ts:26
_createController @ extensions-manifest-initializer.controller.ts:48
(anonymous) @ base-extensions-initializer.controller.ts:120
(anonymous) @ base-extensions-initializer.controller.ts:117
(anonymous) @ Subscriber.js:96
(anonymous) @ Subscriber.js:63
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ combineLatest.js:47
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ distinctUntilChanged.js:15
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ map.js:7
(anonymous) @ OperatorSubscriber.js:15
(anonymous) @ Subscriber.js:34
(anonymous) @ BehaviorSubject.js:19
(anonymous) @ Observable.js:38
(anonymous) @ Subject.js:95
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ Observable.js:66
(anonymous) @ Observable.js:30
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ combineLatest.js:40
maybeSchedule @ combineLatest.js:67
(anonymous) @ combineLatest.js:37
(anonymous) @ combineLatest.js:57
maybeSchedule @ combineLatest.js:67
(anonymous) @ combineLatest.js:31
(anonymous) @ Observable.js:38
(anonymous) @ Observable.js:32
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ map.js:6
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
(anonymous) @ distinctUntilChanged.js:10
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:27
errorContext @ errorContext.js:19
(anonymous) @ Observable.js:23
constructor @ observer.ts:16
constructor @ observer.controller.ts:19
observe @ class.mixin.ts:70
_init @ base-extensions-initializer.controller.ts:86
constructor @ extensions-manifest-initializer.controller.ts:44
(anonymous) @ default-section.element.ts:57
constructor @ default-section.element.ts:48
createExtensionElement @ create-extension-element.function.ts:32
component @ backoffice-main.element.js:37
resolvePageComponent @ router.ts:136
renderPath @ router-slot.ts:441
render @ router-slot.ts:257
dispatchRouteChangeEvent @ events.ts:10
(anonymous) @ router-slot.ts:317
requestAnimationFrame
notifyChildRouters @ router-slot.ts:316
renderPath @ router-slot.ts:472
render @ router-slot.ts:257
dispatchGlobalRouterEvent @ events.ts:19
(anonymous) @ history.ts:64
#onSectionClick @ backoffice-header-sections.element.js:68
(anonymous) @ backoffice-header-sections.element.js:90
handleEvent @ lit-html.js:6
router-slot.ts:258 Uncaught (in promise) Context could not be found. (Context Alias: UmbPropertyContext with API Alias: UmbClipboardPropertyContext). Controller is hosted on #document-fragment > UMB-PROPERTY-EDITOR-UI-BLOCK-LIST

and if I click it I would expect the add Block panel to show. but I get an other error

router-slot.ts:258 Uncaught (in promise) Context could not be found. (Context Alias: UmbPropertyContext with API Alias: UmbClipboardPropertyContext). Controller is hosted on #document-fragment > UMB-PROPERTY-EDITOR-UI-BLOCK-LIST

For the record block config is

BlockList Config: 

(2) [{…}, {…}]

0: 

alias: "blocks"

value: Array(1)

0: 

backgroundColor: "#0c5f4a"

contentElementTypeKey: "266221db-e0ed-40c3-83e1-129e3a6bd9b5"

label: "Calendar Group"

settingsElementTypeKey: "87b4feb3-5f76-4ade-a172-6509505dadf0"

[[Prototype]]: Object

length: 1

[[Prototype]]: Array(0)

[[Prototype]]: Object

1: 

alias: "maxPropertyWidth"

value: "600px"

[[Prototype]]: Object

length: 2

[[Prototype]]: Array(0)

hey hello @DanielRogers-Intelli

thanks for sharing detailed code, i think the .config prop expects a UmbPropertyEditorConfigCollection instance (which has the getValueByAlias() method on it), not a plain array. Wrap your raw values before passing it in:

ts

import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
this.config = new UmbPropertyEditorConfigCollection(rawValues);

The UmbPropertyContext / UmbClipboardPropertyContext errors are because those contexts are normally provided by the property editor host further up the DOM they don’t exist in a custom workspace panel. The “Add button only appearing after visiting a content page” symptom is the same root cause; it’s picking up leaked context from the editor you just left.

The officially supported way to embed a property editor outside of content editing is using <umb-property-dataset> wrapping an <umb-property> — the dataset component provides all the required context for you:

html

<umb-property-dataset .value=${this.data} @change=${this.#onDataChange}>
    <umb-property
        label="Calendar Group"
        alias="calendarGroupBlocks"
        property-editor-ui-alias="Umb.PropertyEditorUi.BlockList"
        .config=${this.rawConfig}>
    </umb-property>
</umb-property-dataset>

See the docs here: https://docs.umbraco.com/umbraco-cms/customizing/property-editors/integrate-property-editors

i think theres also a github for example code umbraco Core i used to check with it and do it so pls have a check with that

Hi Bishal thanks for that. This has got me a long way further. I have now got a blocklist editor where I can add blocks/edit blocks/deleteblocks.

Note: I are not saving anything tey. So everytime I loaded it its an empty array.

However I still have a few errors and cant get a value for the array of blocks.

import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element"; import { html, css } from '@umbraco-cms/backoffice/external/lit'; import { umbHttpClient } from "@umbraco-cms/backoffice/http-client"; import '@umbraco-cms/backoffice/property-editor'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';

export class GenesisCalendarGroupsWorkspace extends UmbElementMixin(UmbLitElement) {
static properties = { blockListConfig: { type: Object }, config: {type: Object }, value: { type: Object } };

private data = [ { alias: "calendarGroupBlocks", value: { layout: [], contentData: [], settingsData: [] } } ];

config: any;
value: any | null = [];

connectedCallback() {
super.connectedCallback();
this.loadBlockListConfig();
}

`private async loadBlockListConfig() {
const response = await umbHttpClient.get({
url: ‘/umbraco/management/api/v1/data-type/55e53032-de54-49ae-9232-c79fcfa91c4e’,
security: [{ scheme: ‘bearer’, type: ‘http’ }],
});

const data = response.data as { values?: DataTypePropertyValue[] };

this.config = new UmbPropertyEditorConfigCollection(
    (data.values ?? []).map((item) => ({
        alias: item.alias,
        value: item.value,
    }))
);

this.requestUpdate();

}`

private onValueChange = (e: CustomEvent) => {
console.log('Property Dataset Changed', e.detail);
};

`` render() {
if (!this.config) return html<p>Loading...</p>;

    return html`
        <umb-property-dataset
            .value=${this.data} 
            @change=${this.onValueChange}>
          <umb-property
            alias="calendarGroupBlocks"
            label="Calendar Group"
            property-editor-ui-alias="Umb.PropertyEditorUi.BlockList"
            .config=${this.config}>
          </umb-property>
        </umb-property-dataset>
      `;
} ``

}
customElements.define("genesis-calendar-groups-workspace", GenesisCalendarGroupsWorkspace);

onValueChange always returns indefined.

if I change it to

private onValueChange = (e: any) => {
console.log('Property Dataset Changed', e);
};

I do get a result but there is nothing in it that seems useful. The key is @changechange is triggering but returning the wrong information.

The second obeservation is: On displaying the to the workspace I get x3 stops at this code (this.#promiseRejecter(
`Context request was cancelled, host was disconnected. (Context Alias: ${this.#contextAlias} with API Alias: ${this.#apiAlias}). Controller is hosted on ${hostElement?.parentNode?.nodeName ?? ‘Not attached node’} > ${hostElement?.nodeName}`,
);)

`` #handleDisconnect() {
	this.#disconnectAC = undefined;
	this.#unprovide();
	if (this.#promiseRejecter) {
		const hostElement = this._retrieveHost();
		this.#promiseRejecter(
			`Context request was cancelled, host was disconnected. (Context Alias: ${this.#contextAlias} with API Alias: ${this.#apiAlias}). Controller is hosted on ${hostElement?.parentNode?.nodeName ?? 'Not attached node'} > ${hostElement?.nodeName}`,
		);
	}
	this.#promise = undefined;
	this.#promiseOptions = undefined;
	this.#promiseResolver = undefined;
	this.#promiseRejecter = undefined;
} ``

After this I can add /edt/delete blocks

Third Observation: is I get this error

genesisCalendar.configuration.groups:1 Uncaught (in promise) Context request was cancelled, host was disconnected. (Context Alias: UmbPropertyDatasetContext with API Alias: default). Controller is hosted on Not attached node > UMB-PROPERTY-ACTION

I have tried adding

import { UMB_PROPERTY_CONTEXT } from "@umbraco-cms/backoffice/property"; import { UmbPropertyContext } from "@umbraco-cms/backoffice/property";
….
private propertyContext = new UmbPropertyContext(this);

` connectedCallback() {
super.connectedCallback();

    this.provideContext(UMB_PROPERTY_CONTEXT, this.propertyContext);

    // Wait for first render so the workspace shell exists
    this.loadBlockListConfig();
}`

`` render() {
if (!this.config) return html<p>Loading...</p>;

    return html`
        <umb-property-dataset
            .value=${this.data} 
            .propertyContext=${this.propertyContext}
            @change=${this.onValueChange}>
          <umb-property
            alias="calendarGroupBlocks"
            label="Calendar Group"
            property-editor-ui-alias="Umb.PropertyEditorUi.BlockList"
            .config=${this.config}>
          </umb-property>
        </umb-property-dataset>
      `;
} ``

But didnt have any obvious results.

I have also tried gettin@change the @change off of umb-property as expected never triggers anything.

For contect this is the manifest snipit that relates to the worspace

const configurationGroupsMenuItem: ManifestMenuItem = { type: 'menuItem', alias: 'GenesisCalendar.Menu.Configuration.Groups', name: 'Groups', meta: { label: 'Groups', icon: 'icon-thumbnails-small', menus: ['genesis-calendar.Menu'], entityType: 'genesisCalendar.configuration.groups' } };

const configurationGroupsWorkspace: ManifestWorkspace = { type: 'workspace', alias: 'GenesisCalendar.Workspace.Configuration.Groups', name: 'Calendar Groups Workspace', elementName: 'genesis-calendar-groups-workspace', meta: { entityType: 'genesisCalendar.configuration.groups' } };