Block Workspace: dynamic headline & browser title (#20424)

* get content type name method

* use local virtual render for the workspace headline and browser title
This commit is contained in:
Niels Lyngsø
2025-10-08 17:40:42 +02:00
committed by GitHub
parent a676dc4bad
commit 7ecc6ece7e
3 changed files with 58 additions and 21 deletions

View File

@@ -11,10 +11,7 @@ export class UmbBlockWorkspaceEditorElement extends UmbLitElement {
this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => {
if (context) {
this.observe(
observeMultiple([
context.isNew,
context.content.structure.ownerContentTypeObservablePart((contentType) => contentType?.name),
]),
observeMultiple([context.isNew, context.name]),
([isNew, name]) => {
this._headline =
this.localize.term(isNew ? 'general_add' : 'general_edit') + ' ' + this.localize.string(name);

View File

@@ -1,5 +1,5 @@
import type { UmbBlockDataModel, UmbBlockLayoutBaseModel } from '../types.js';
import { UMB_BLOCK_ENTRIES_CONTEXT, UMB_BLOCK_ENTRY_CONTEXT, UMB_BLOCK_MANAGER_CONTEXT } from '../context/index.js';
import type { UmbBlockDataModel, UmbBlockDataValueModel, UmbBlockLayoutBaseModel } from '../types.js';
import { UMB_BLOCK_ENTRIES_CONTEXT, UMB_BLOCK_MANAGER_CONTEXT } from '../context/index.js';
import { UmbBlockWorkspaceEditorElement } from './block-workspace-editor.element.js';
import { UmbBlockElementManager } from './block-element-manager.js';
import type { UmbBlockWorkspaceOriginData } from './block-workspace.modal-token.js';
@@ -24,6 +24,7 @@ import { decodeFilePath, UmbReadOnlyVariantGuardManager } from '@umbraco-cms/bac
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
import { UmbUfmVirtualRenderController } from '@umbraco-cms/backoffice/ufm';
export type UmbBlockWorkspaceElementManagerNames = 'content' | 'settings';
@@ -66,6 +67,8 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
#name = new UmbStringState<string | undefined>(undefined);
readonly name = this.#name.asObservable();
#labelRender = new UmbUfmVirtualRenderController(this);
#variantId = new UmbClassState<UmbVariantId | undefined>(undefined);
readonly variantId = this.#variantId.asObservable();
@@ -99,14 +102,22 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
this.#blockEntries = context;
}).asPromise({ preventTimeout: true });
this.consumeContext(UMB_BLOCK_ENTRY_CONTEXT, (context) => {
this.#name.setValue(context?.getName());
});
this.observe(
this.variantId,
(variantId) => {
this.content.setVariantId(variantId);
this.settings.setVariantId(variantId);
},
null,
);
this.observe(this.variantId, (variantId) => {
this.content.setVariantId(variantId);
this.settings.setVariantId(variantId);
});
this.observe(
observeMultiple([this.content.values, this.settings.values]),
async ([contentValues]) => {
this.#renderLabel(contentValues);
},
'observeContentForLabelRender',
);
this.routes.setRoutes([
{
@@ -210,15 +221,17 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
(contentTypeId) => {
this.observe(
contentTypeId ? manager.blockTypeOf(contentTypeId) : undefined,
(blockType) => {
if (!blockType?.editorSize) return;
const editorConfig = manager.getEditorConfiguration();
const useInlineEditing = editorConfig?.find((x) => x.alias === 'useInlineEditingAsDefault')?.value;
if (!useInlineEditing) {
this.setEditorSize(blockType.editorSize);
async (blockType) => {
if (blockType?.editorSize) {
const editorConfig = manager.getEditorConfiguration();
const useInlineEditing = editorConfig?.find((x) => x.alias === 'useInlineEditingAsDefault')?.value;
if (!useInlineEditing) {
this.setEditorSize(blockType.editorSize);
}
}
await this.content.structure.whenLoaded();
this.#gotLabel(blockType?.label ?? this.content.structure.getOwnerContentTypeName());
},
'observeBlockType',
);
@@ -227,6 +240,29 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
);
}
#gotLabel(label: string | undefined) {
if (label) {
this.#labelRender.markdown = label;
this.#renderLabel(this.content.getValues());
}
}
async #renderLabel(contentValues: Array<UmbBlockDataValueModel> | undefined) {
const valueObject = {} as Record<string, unknown>;
if (contentValues) {
for (const property of contentValues) {
valueObject[property.alias] = property.value;
}
}
this.#labelRender.value = valueObject;
// Await one animation frame:
await new Promise((resolve) => requestAnimationFrame(() => resolve(true)));
const result = this.#labelRender.toString();
this.#name.setValue(result);
this.view.setTitle(result);
}
#allowNavigateAway = false;
#onWillNavigate = async (e: CustomEvent) => {
const newUrl = e.detail.url;

View File

@@ -314,6 +314,10 @@ export class UmbContentTypeStructureManager<
return this.#contentTypes.getValue().find((y) => y.unique === this.#ownerContentTypeUnique);
}
getOwnerContentTypeName() {
return this.getOwnerContentType()?.name;
}
getOwnerContentTypeUnique() {
return this.#ownerContentTypeUnique;
}