better data binding + inline mode
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { createObservablePart, type MappingFunction, type MemoizationFunction } from '../index.js';
|
||||
import { UmbBasicState } from './basic-state.js';
|
||||
|
||||
/**
|
||||
@@ -10,4 +11,11 @@ export class UmbStringState<T> extends UmbBasicState<T | string> {
|
||||
constructor(initialData: T | string) {
|
||||
super(initialData);
|
||||
}
|
||||
|
||||
asObservablePart<ReturnType>(
|
||||
mappingFunction: MappingFunction<T | string, ReturnType>,
|
||||
memoizationFunction?: MemoizationFunction<ReturnType>,
|
||||
) {
|
||||
return createObservablePart(this._subject, mappingFunction, memoizationFunction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +500,6 @@ export const data: Array<DataTypeResponseModel | FolderTreeItemResponseModel> =
|
||||
editorSize: 'medium',
|
||||
icon: 'icon-coffee',
|
||||
},
|
||||
|
||||
{
|
||||
label: 'Headline',
|
||||
contentElementTypeKey: 'headline-umbraco-demo-block-id',
|
||||
@@ -528,6 +527,14 @@ export const data: Array<DataTypeResponseModel | FolderTreeItemResponseModel> =
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
alias: 'useInlineEditingAsDefault',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
alias: 'useLiveEditing',
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { UmbBlockListContext } from '../../context/block-list.context.js';
|
||||
import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { type UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/block';
|
||||
import '../ref-list-block/index.js';
|
||||
import { UmbBlockContext } from '@umbraco-cms/backoffice/block';
|
||||
import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal';
|
||||
import { encodeFilePath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
@@ -23,7 +23,7 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl
|
||||
}
|
||||
private _layout?: UmbBlockLayoutBaseModel | undefined;
|
||||
|
||||
#context = new UmbBlockContext(this);
|
||||
#context = new UmbBlockListContext(this);
|
||||
|
||||
@state()
|
||||
_contentUdi?: string;
|
||||
@@ -32,13 +32,16 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl
|
||||
_label = '';
|
||||
|
||||
@state()
|
||||
_workspacePath?: string;
|
||||
_workspaceEditPath?: string;
|
||||
|
||||
@state()
|
||||
_inlineEditingMode?: boolean;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.observe(this.#context.workspacePath, (workspacePath) => {
|
||||
this._workspacePath = workspacePath;
|
||||
this.observe(this.#context.workspaceEditPath, (workspaceEditPath) => {
|
||||
this._workspaceEditPath = workspaceEditPath;
|
||||
});
|
||||
this.observe(this.#context.contentUdi, (contentUdi) => {
|
||||
this._contentUdi = contentUdi;
|
||||
@@ -46,9 +49,9 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl
|
||||
this.observe(this.#context.label, (label) => {
|
||||
this._label = label;
|
||||
});
|
||||
/*this.observe(this.#context.layout, (layout) => {
|
||||
console.log('layout', layout);
|
||||
});*/
|
||||
this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => {
|
||||
this._inlineEditingMode = inlineEditingMode;
|
||||
});
|
||||
}
|
||||
|
||||
#requestDelete() {
|
||||
@@ -67,22 +70,19 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl
|
||||
}
|
||||
|
||||
#renderRefBlock() {
|
||||
return html`<umb-ref-list-block .name=${this._label}> </umb-ref-list-block>`;
|
||||
return html`<umb-ref-list-block .name=${this._label}></umb-ref-list-block>`;
|
||||
}
|
||||
|
||||
/*#renderInlineBlock() {
|
||||
return html`<umb-inline-list-block name="block" }}></umb-inline-list-block>`;
|
||||
}*/
|
||||
#renderInlineBlock() {
|
||||
return html`<umb-inline-list-block .name=${this._label}></umb-inline-list-block>`;
|
||||
}
|
||||
|
||||
#renderBlock() {
|
||||
return html`
|
||||
${this.#renderRefBlock()}
|
||||
${this._inlineEditingMode ? this.#renderInlineBlock() : this.#renderRefBlock()}
|
||||
<uui-action-bar>
|
||||
${this._workspacePath
|
||||
? html`<uui-button
|
||||
label="edit"
|
||||
compact
|
||||
href=${this._workspacePath + 'edit/' + encodeFilePath(this._contentUdi!)}>
|
||||
${this._workspaceEditPath
|
||||
? html`<uui-button label="edit" compact href=${this._workspaceEditPath}>
|
||||
<uui-icon name="icon-edit"></uui-icon>
|
||||
</uui-button>`
|
||||
: ''}
|
||||
|
||||
@@ -1,15 +1,37 @@
|
||||
import { css, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UMB_BLOCK_LIST_CONTEXT } from '../../context/block-list.context-token.js';
|
||||
import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
|
||||
/**
|
||||
* @element umb-ref-list-block
|
||||
*/
|
||||
@customElement('umb-ref-list-block')
|
||||
export class UmbRefListBlockElement extends UUIRefNodeElement {
|
||||
export class UmbRefListBlockElement extends UmbLitElement {
|
||||
//
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.setAttribute('border', '');
|
||||
@property({ type: String })
|
||||
name?: string;
|
||||
|
||||
@state()
|
||||
_workspaceEditPath?: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_BLOCK_LIST_CONTEXT, (context) => {
|
||||
this.observe(
|
||||
context.workspaceEditPath,
|
||||
(workspaceEditPath) => {
|
||||
this._workspaceEditPath = workspaceEditPath;
|
||||
},
|
||||
'observeWorkspaceEditPath',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
// href=${this._workspaceEditPath ?? '#'}
|
||||
return html`<uui-ref-node border .name=${this.name ?? ''}></uui-ref-node>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import type { UmbBlockListContext } from './block-list.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_BLOCK_LIST_CONTEXT = new UmbContextToken<UmbBlockListContext>('UmbBlockContext');
|
||||
@@ -0,0 +1,30 @@
|
||||
import { UMB_BLOCK_LIST_MANAGER_CONTEXT } from '../manager/block-list-manager.context.js';
|
||||
import { UmbBlockContext } from '@umbraco-cms/backoffice/block';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
|
||||
export class UmbBlockListContext extends UmbBlockContext<
|
||||
typeof UMB_BLOCK_LIST_MANAGER_CONTEXT,
|
||||
typeof UMB_BLOCK_LIST_MANAGER_CONTEXT.TYPE
|
||||
> {
|
||||
#inlineEditingMode = new UmbBooleanState(undefined);
|
||||
inlineEditingMode = this.#inlineEditingMode.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, UMB_BLOCK_LIST_MANAGER_CONTEXT);
|
||||
}
|
||||
|
||||
_gotManager() {
|
||||
super._gotManager();
|
||||
if (this._manager) {
|
||||
this.observe(
|
||||
this._manager.inlineEditingMode,
|
||||
(inlineEditingMode) => {
|
||||
this.#inlineEditingMode.setValue(inlineEditingMode);
|
||||
},
|
||||
'observeInlineEditingMode',
|
||||
);
|
||||
} else {
|
||||
this.removeControllerByAlias('observeInlineEditingMode');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * from './workspace/index.js';
|
||||
export * from './context/block-list.context-token.js';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { UmbBlockListLayoutModel, UmbBlockListTypeModel } from '../types.js';
|
||||
import { UmbBlockManagerContext } from '@umbraco-cms/backoffice/block';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
/**
|
||||
* A implementation of the Block Manager specifically for the Block List.
|
||||
@@ -8,6 +9,14 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
export class UmbBlockListManagerContext<
|
||||
BlockLayoutType extends UmbBlockListLayoutModel = UmbBlockListLayoutModel,
|
||||
> extends UmbBlockManagerContext<UmbBlockListTypeModel, BlockLayoutType> {
|
||||
//
|
||||
#inlineEditingMode = new UmbBooleanState(undefined);
|
||||
inlineEditingMode = this.#inlineEditingMode.asObservable();
|
||||
|
||||
setInlineEditingMode(inlineEditingMode: boolean | undefined) {
|
||||
this.#inlineEditingMode.setValue(inlineEditingMode ?? false);
|
||||
}
|
||||
|
||||
createBlock(layoutEntry: Omit<BlockLayoutType, 'contentUdi'>, contentElementTypeKey: string) {
|
||||
// Here is room to append some extra layout properties if needed for this type.
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement
|
||||
|
||||
const blocks = config.getValueByAlias<Array<UmbBlockTypeBaseModel>>('blocks') ?? [];
|
||||
this.#context.setBlockTypes(blocks);
|
||||
|
||||
const useInlineEditingAsDefault = config.getValueByAlias<boolean>('useInlineEditingAsDefault');
|
||||
this.#context.setInlineEditingMode(useInlineEditingAsDefault);
|
||||
//config.useSingleBlockMode
|
||||
//config.useLiveEditing
|
||||
//config.useInlineEditingAsDefault
|
||||
|
||||
@@ -4,8 +4,8 @@ export interface UmbBlockTypeBaseModel {
|
||||
contentElementTypeKey: string;
|
||||
settingsElementTypeKey?: string;
|
||||
label?: string;
|
||||
view?: string;
|
||||
stylesheet?: string;
|
||||
view?: string; // TODO: remove/replace with custom element manifest type for block list.
|
||||
stylesheet?: string; // TODO: remove/replace with custom element manifest type for block list.
|
||||
iconColor?: string;
|
||||
backgroundColor?: string;
|
||||
editorSize?: UUIModalSidebarSize;
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../../block-type/types.js';
|
||||
import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '../types.js';
|
||||
import { UMB_BLOCK_MANAGER_CONTEXT } from '../manager/index.js';
|
||||
import { UMB_BLOCK_MANAGER_CONTEXT, type UmbBlockManagerContext } from '../manager/index.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import { encodeFilePath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export class UmbBlockContext<
|
||||
export abstract class UmbBlockContext<
|
||||
BlockManagerContextTokenType extends UmbContextToken<BlockManagerContextType, BlockManagerContextType>,
|
||||
BlockManagerContextType extends UmbBlockManagerContext<BlockType, BlockLayoutType>,
|
||||
BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel,
|
||||
BlockLayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel,
|
||||
> extends UmbContextBase<UmbBlockContext> {
|
||||
> extends UmbContextBase<
|
||||
UmbBlockContext<BlockManagerContextTokenType, BlockManagerContextType, BlockType, BlockLayoutType>
|
||||
> {
|
||||
//
|
||||
#manager?: typeof UMB_BLOCK_MANAGER_CONTEXT.TYPE;
|
||||
_manager?: BlockManagerContextType;
|
||||
|
||||
#blockTypeName = new UmbStringState(undefined);
|
||||
public readonly blockTypeName = this.#blockTypeName.asObservable();
|
||||
@@ -21,11 +26,17 @@ export class UmbBlockContext<
|
||||
|
||||
#workspacePath = new UmbStringState(undefined);
|
||||
public readonly workspacePath = this.#workspacePath.asObservable();
|
||||
public readonly workspaceEditPath = this.#workspacePath.asObservablePart(
|
||||
(path) => path + 'edit/' + encodeFilePath(this.getContentUdi() ?? ''),
|
||||
);
|
||||
public readonly workspaceEditSettingsPath = this.#workspacePath.asObservablePart(
|
||||
(path) => path + 'edit/' + encodeFilePath(this.getContentUdi() ?? '') + '/view/settings',
|
||||
);
|
||||
|
||||
#blockType = new UmbObjectState<BlockType | undefined>(undefined);
|
||||
public readonly blockType = this.#blockType.asObservable();
|
||||
public readonly blockTypeContentElementTypeKey = this.#blockType.asObservablePart((x) => x?.contentElementTypeKey);
|
||||
public readonly blockTypeSettingsElementTypeKey = this.#blockType.asObservablePart((x) => x?.settingsElementTypeKey);
|
||||
_blockType = new UmbObjectState<BlockType | undefined>(undefined);
|
||||
public readonly blockType = this._blockType.asObservable();
|
||||
public readonly blockTypeContentElementTypeKey = this._blockType.asObservablePart((x) => x?.contentElementTypeKey);
|
||||
public readonly blockTypeSettingsElementTypeKey = this._blockType.asObservablePart((x) => x?.settingsElementTypeKey);
|
||||
|
||||
#layout = new UmbObjectState<BlockLayoutType | undefined>(undefined);
|
||||
public readonly layout = this.#layout.asObservable();
|
||||
@@ -48,21 +59,13 @@ export class UmbBlockContext<
|
||||
this.#layout.setValue(layout);
|
||||
}
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
constructor(host: UmbControllerHost, blockManagerContextToken: BlockManagerContextTokenType) {
|
||||
super(host, UMB_BLOCK_CONTEXT);
|
||||
|
||||
// Consume block manager:
|
||||
this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (manager) => {
|
||||
this.#manager = manager;
|
||||
this.observe(
|
||||
manager.workspacePath,
|
||||
(workspacePath) => {
|
||||
this.#workspacePath.setValue(workspacePath);
|
||||
},
|
||||
'observeWorkspacePath',
|
||||
);
|
||||
this.#observeBlockType();
|
||||
this.#observeData();
|
||||
this.consumeContext(blockManagerContextToken, (manager) => {
|
||||
this._manager = manager;
|
||||
this._gotManager();
|
||||
});
|
||||
|
||||
// Observe UDI:
|
||||
@@ -85,14 +88,34 @@ export class UmbBlockContext<
|
||||
});
|
||||
}
|
||||
|
||||
getContentUdi() {
|
||||
return this.#layout.value?.contentUdi;
|
||||
}
|
||||
|
||||
_gotManager() {
|
||||
if (this._manager) {
|
||||
this.observe(
|
||||
this._manager.workspacePath,
|
||||
(workspacePath) => {
|
||||
this.#workspacePath.setValue(workspacePath);
|
||||
},
|
||||
'observeWorkspacePath',
|
||||
);
|
||||
} else {
|
||||
this.removeControllerByAlias('observeWorkspacePath');
|
||||
}
|
||||
this.#observeBlockType();
|
||||
this.#observeData();
|
||||
}
|
||||
|
||||
#observeData() {
|
||||
if (!this.#manager) return;
|
||||
if (!this._manager) return;
|
||||
const contentUdi = this.#layout.value?.contentUdi;
|
||||
if (!contentUdi) return;
|
||||
|
||||
// observe content:
|
||||
this.observe(
|
||||
this.#manager.contentOf(contentUdi),
|
||||
this._manager.contentOf(contentUdi),
|
||||
(content) => {
|
||||
this.#content.setValue(content);
|
||||
},
|
||||
@@ -103,7 +126,7 @@ export class UmbBlockContext<
|
||||
const settingsUdi = this.#layout.value?.settingsUdi;
|
||||
if (settingsUdi) {
|
||||
this.observe(
|
||||
this.#manager.contentOf(settingsUdi),
|
||||
this._manager.contentOf(settingsUdi),
|
||||
(content) => {
|
||||
this.#settings.setValue(content);
|
||||
},
|
||||
@@ -113,28 +136,28 @@ export class UmbBlockContext<
|
||||
}
|
||||
|
||||
#observeBlockType() {
|
||||
if (!this.#manager) return;
|
||||
if (!this._manager) return;
|
||||
const contentTypeKey = this.#content.value?.contentTypeKey;
|
||||
if (!contentTypeKey) return;
|
||||
|
||||
// observe blockType:
|
||||
this.observe(
|
||||
this.#manager.blockTypeOf(contentTypeKey),
|
||||
this._manager.blockTypeOf(contentTypeKey),
|
||||
(blockType) => {
|
||||
this.#blockType.setValue(blockType as BlockType);
|
||||
this._blockType.setValue(blockType as BlockType);
|
||||
},
|
||||
'observeBlockType',
|
||||
);
|
||||
}
|
||||
|
||||
#observeBlockTypeContentElementName() {
|
||||
if (!this.#manager) return;
|
||||
const contentElementTypeKey = this.#blockType.value?.contentElementTypeKey;
|
||||
if (!this._manager) return;
|
||||
const contentElementTypeKey = this._blockType.value?.contentElementTypeKey;
|
||||
if (!contentElementTypeKey) return;
|
||||
|
||||
// observe blockType:
|
||||
this.observe(
|
||||
this.#manager.contentTypeNameOf(contentElementTypeKey),
|
||||
this._manager.contentTypeNameOf(contentElementTypeKey),
|
||||
(contentTypeName) => {
|
||||
this.#blockTypeName.setValue(contentTypeName);
|
||||
},
|
||||
@@ -143,8 +166,8 @@ export class UmbBlockContext<
|
||||
}
|
||||
|
||||
#observeBlockTypeLabel() {
|
||||
if (!this.#manager) return;
|
||||
const blockType = this.#blockType.value;
|
||||
if (!this._manager) return;
|
||||
const blockType = this._blockType.value;
|
||||
if (!blockType) return;
|
||||
|
||||
if (blockType.label) {
|
||||
@@ -168,11 +191,13 @@ export class UmbBlockContext<
|
||||
// Public methods:
|
||||
|
||||
public delete() {
|
||||
if (!this.#manager) return;
|
||||
if (!this._manager) return;
|
||||
const contentUdi = this.#layout.value?.contentUdi;
|
||||
if (!contentUdi) return;
|
||||
this.#manager.deleteBlock(contentUdi);
|
||||
this._manager.deleteBlock(contentUdi);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_BLOCK_CONTEXT = new UmbContextToken<UmbBlockContext, UmbBlockContext>('UmbBlockContext');
|
||||
export const UMB_BLOCK_CONTEXT = new UmbContextToken<
|
||||
UmbBlockContext<typeof UMB_BLOCK_MANAGER_CONTEXT, typeof UMB_BLOCK_MANAGER_CONTEXT.TYPE>
|
||||
>('UmbBlockContext');
|
||||
|
||||
Reference in New Issue
Block a user