Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: inline editing mode for Block List Editor #2215

Merged
merged 19 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { UMB_BLOCK_CATALOGUE_MODAL, UmbBlockEntriesContext } from '../../block/i
import {
UMB_BLOCK_GRID_ENTRY_CONTEXT,
UMB_BLOCK_GRID_WORKSPACE_MODAL,
type UmbBlockGridWorkspaceData,
type UmbBlockGridWorkspaceOriginData,
} from '../index.js';
import type { UmbBlockGridLayoutModel, UmbBlockGridTypeAreaType, UmbBlockGridTypeModel } from '../types.js';
import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from './block-grid-manager.context-token.js';
Expand All @@ -19,13 +19,17 @@ export class UmbBlockGridEntriesContext
typeof UMB_BLOCK_GRID_MANAGER_CONTEXT,
typeof UMB_BLOCK_GRID_MANAGER_CONTEXT.TYPE,
UmbBlockGridTypeModel,
UmbBlockGridLayoutModel
UmbBlockGridLayoutModel,
UmbBlockGridWorkspaceOriginData
>
implements UmbBlockGridScalableContainerContext
{
//
#catalogueModal: UmbModalRouteRegistrationController<typeof UMB_BLOCK_CATALOGUE_MODAL.DATA, undefined>;
#workspaceModal: UmbModalRouteRegistrationController;
#catalogueModal: UmbModalRouteRegistrationController<
typeof UMB_BLOCK_CATALOGUE_MODAL.DATA,
typeof UMB_BLOCK_CATALOGUE_MODAL.VALUE
>;
#workspaceModal;

#parentEntry?: typeof UMB_BLOCK_GRID_ENTRY_CONTEXT.TYPE;

Expand Down Expand Up @@ -128,7 +132,7 @@ export class UmbBlockGridEntriesContext
blocks: this.#allowedBlockTypes.getValue(),
blockGroups: this._manager?.getBlockGroups() ?? [],
openClipboard: routingInfo.view === 'clipboard',
blockOriginData: { index: index, areaKey: this.#areaKey, parentUnique: this.#parentUnique },
originData: { index: index, areaKey: this.#areaKey, parentUnique: this.#parentUnique },
},
};
})
Expand Down Expand Up @@ -312,10 +316,10 @@ export class UmbBlockGridEntriesContext
async create(
contentElementTypeKey: string,
partialLayoutEntry?: Omit<UmbBlockGridLayoutModel, 'contentUdi'>,
modalData?: UmbBlockGridWorkspaceData,
originData?: UmbBlockGridWorkspaceOriginData,
) {
await this._retrieveManager;
return this._manager?.create(contentElementTypeKey, partialLayoutEntry, modalData);
return this._manager?.create(contentElementTypeKey, partialLayoutEntry, originData);
}

// insert Block?
Expand All @@ -324,11 +328,11 @@ export class UmbBlockGridEntriesContext
layoutEntry: UmbBlockGridLayoutModel,
content: UmbBlockDataType,
settings: UmbBlockDataType | undefined,
modalData: UmbBlockGridWorkspaceData,
originData: UmbBlockGridWorkspaceOriginData,
) {
await this._retrieveManager;
// TODO: Insert layout entry at the right spot.
return this._manager?.insert(layoutEntry, content, settings, modalData) ?? false;
return this._manager?.insert(layoutEntry, content, settings, originData) ?? false;
}

// create Block?
Expand Down
24 changes: 12 additions & 12 deletions src/packages/block/block-grid/context/block-grid-manager.context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { UmbBlockGridLayoutModel, UmbBlockGridTypeModel } from '../types.js';
import type { UmbBlockGridWorkspaceData } from '../index.js';
import type { UmbBlockGridWorkspaceOriginData } from '../index.js';
import { UmbArrayState, appendToFrozenArray, pushAtToUniqueArray } from '@umbraco-cms/backoffice/observable-api';
import { removeLastSlashFromPath, transformServerPathToClientPath } from '@umbraco-cms/backoffice/utils';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
Expand All @@ -16,7 +16,7 @@ export const UMB_BLOCK_GRID_DEFAULT_LAYOUT_STYLESHEET = '/umbraco/backoffice/css
*/
export class UmbBlockGridManagerContext<
BlockLayoutType extends UmbBlockGridLayoutModel = UmbBlockGridLayoutModel,
> extends UmbBlockManagerContext<UmbBlockGridTypeModel, UmbBlockGridLayoutModel> {
> extends UmbBlockManagerContext<UmbBlockGridTypeModel, UmbBlockGridLayoutModel, UmbBlockGridWorkspaceOriginData> {
//
#initAppUrl: Promise<void>;
#appUrl?: string;
Expand Down Expand Up @@ -74,9 +74,9 @@ export class UmbBlockGridManagerContext<
create(
contentElementTypeKey: string,
partialLayoutEntry?: Omit<BlockLayoutType, 'contentUdi'>,
// TODO: [v15] Ignore unused parameter to avoid breaking changes
// This property is used by some implementations, but not used in this.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
modalData?: UmbBlockGridWorkspaceData,
originData?: UmbBlockGridWorkspaceOriginData,
) {
return super.createBlockData(contentElementTypeKey, partialLayoutEntry);
}
Expand Down Expand Up @@ -165,24 +165,24 @@ export class UmbBlockGridManagerContext<
layoutEntry: BlockLayoutType,
content: UmbBlockDataType,
settings: UmbBlockDataType | undefined,
modalData: UmbBlockGridWorkspaceData,
originData: UmbBlockGridWorkspaceOriginData,
) {
this.setOneLayout(layoutEntry, modalData);
this.insertBlockData(layoutEntry, content, settings, modalData);
this.setOneLayout(layoutEntry, originData);
this.insertBlockData(layoutEntry, content, settings, originData);

return true;
}

override setOneLayout(layoutEntry: BlockLayoutType, modalData?: UmbBlockGridWorkspaceData) {
const index = modalData?.originData.index ?? -1;
override setOneLayout(layoutEntry: BlockLayoutType, originData?: UmbBlockGridWorkspaceOriginData) {
const index = originData?.index ?? -1;

if (modalData?.originData.parentUnique && modalData?.originData.areaKey) {
if (originData?.parentUnique && originData?.areaKey) {
// Find layout entry based on parentUnique, recursively, as it needs to check layout of areas as well:
const layoutEntries = this.#appendLayoutEntryToArea(
layoutEntry,
this._layouts.getValue(),
modalData.originData.parentUnique,
modalData.originData.areaKey,
originData?.parentUnique,
originData?.areaKey,
index,
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block';
import type { UmbBlockWorkspaceData, UmbBlockWorkspaceOriginData } from '@umbraco-cms/backoffice/block';
import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal';
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';

export interface UmbBlockGridWorkspaceOriginData {
export interface UmbBlockGridWorkspaceOriginData extends UmbBlockWorkspaceOriginData {
index: number;
parentUnique: string | null;
areaKey?: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js';
import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit';
import type {
ManifestBlockEditorCustomView,
UmbBlockEditorCustomViewProperties,
Expand All @@ -8,8 +10,6 @@ import type {
import '../ref-list-block/index.js';
import '../inline-list-block/index.js';
import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils';
import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js';
import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js';
import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation';
import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block';

Expand Down Expand Up @@ -234,11 +234,11 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
};

#renderRefBlock() {
return html`<umb-ref-list-block .label=${this._label}></umb-ref-list-block>`;
return html`<umb-ref-list-block .label=${this._label} .icon=${this._icon}></umb-ref-list-block>`;
}

#renderInlineBlock() {
return html`<umb-inline-list-block .label=${this._label}></umb-inline-list-block>`;
return html`<umb-inline-list-block .label=${this._label} .icon=${this._icon}></umb-inline-list-block>`;
}

#renderBlock() {
Expand All @@ -259,10 +259,10 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
href=${this._workspaceEditContentPath}>
<uui-icon name="icon-edit"></uui-icon>
${this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid settings">!</uui-badge>`
: ''}
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
: nothing}
</uui-button>`
: ''}
: nothing}
${this._hasSettings && this._workspaceEditSettingsPath
? html`<uui-button
label="Edit settings"
Expand All @@ -272,13 +272,16 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
<uui-icon name="icon-settings"></uui-icon>
${this._settingsInvalid
? html`<uui-badge attention color="danger" label="Invalid settings">!</uui-badge>`
: ''}
: nothing}
</uui-button>`
: ''}
: nothing}
<uui-button label="delete" look="secondary" @click=${() => this.#context.requestDelete()}>
<uui-icon name="icon-remove"></uui-icon>
</uui-button>
</uui-action-bar>
${!this._showContentEdit && this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
: nothing}
`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ export class UmbInlineListBlockElement extends UmbLitElement {
#workspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE;
#contentUdi?: string;

@property({ type: String })
@property({ type: String, reflect: false })
label?: string;

@property({ type: String, reflect: false })
icon?: string;

@state()
_isOpen = false;

Expand All @@ -42,6 +45,7 @@ export class UmbInlineListBlockElement extends UmbLitElement {
createExtensionApi(this, manifest, [{ manifest: manifest }]).then((context) => {
if (context) {
this.#workspaceContext = context as typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE;
this.#workspaceContext.establishLiveSync();
this.#load();

new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [
Expand All @@ -60,35 +64,141 @@ export class UmbInlineListBlockElement extends UmbLitElement {
}

override render() {
return html` <uui-box>
<button
slot="header"
id="accordion-button"
@click=${() => {
this._isOpen = !this._isOpen;
}}>
<uui-icon name="icon-document"></uui-icon>
<uui-symbol-expand .open=${this._isOpen}></uui-symbol-expand>
<span>${this.label}</span>
</button>
${this._isOpen === true
? html`<umb-block-workspace-view-edit-content-no-router></umb-block-workspace-view-edit-content-no-router>`
: ''}
</uui-box>`;
return html`
<div id="host">
<button
slot="header"
id="open-part"
tabindex="0"
@keydown=${(e: KeyboardEvent) => {
if (e.key !== ' ' && e.key !== 'Enter') return;
e.preventDefault();
e.stopPropagation();
this._isOpen = !this._isOpen;
}}
@click=${() => {
this._isOpen = !this._isOpen;
}}>
<uui-symbol-expand .open=${this._isOpen}></uui-symbol-expand>
${this.#renderContent()}
<slot></slot>
<slot name="tag"></slot>
</button>
${this._isOpen === true
? html`<umb-block-workspace-view-edit-content-no-router></umb-block-workspace-view-edit-content-no-router>`
: ''}
</div>
`;
}

#renderContent() {
return html`
<span id="content">
<span id="icon">
<umb-icon .name=${this.icon}></umb-icon>
</span>
<div id="info">
<div id="name">${this.label}</div>
</div>
</span>
`;
}

static override styles = [
UmbTextStyles,
css`
#accordion-button {
#host {
position: relative;
display: block;
width: 100%;

box-sizing: border-box;
border-radius: var(--uui-border-radius);
background-color: var(--uui-color-surface);

border: 1px solid var(--uui-color-border);
transition: border-color 80ms;

min-width: 250px;
}
#open-part + * {
border-top: 1px solid var(--uui-color-border);
}
:host([disabled]) #open-part {
cursor: default;
transition: border-color 80ms;
}
:host(:not([disabled])) #host:has(#open-part:hover) {
border-color: var(--uui-color-border-emphasis);
}
:host(:not([disabled])) #open-part:hover + * {
border-color: var(--uui-color-border-emphasis);
}
:host([disabled]) #host {
border-color: var(--uui-color-disabled-standalone);
}

slot[name='tag'] {
flex-grow: 1;

display: flex;
justify-content: flex-end;
align-items: center;
}

button {
font-size: inherit;
font-family: inherit;
border: 0;
padding: 0;
background-color: transparent;
text-align: left;
color: var(--uui-color-text);
}

#content {
align-self: stretch;
line-height: normal;
display: flex;
position: relative;
align-items: center;
}

#open-part {
color: inherit;
text-decoration: none;
cursor: pointer;

display: flex;
text-align: left;
align-items: center;
justify-content: flex-start;
width: 100%;
border: none;
background: none;
padding: 0;

min-height: var(--uui-size-16);
padding: calc(var(--uui-size-2) + 1px);
}

#icon {
font-size: 1.2em;
margin-left: var(--uui-size-2);
margin-right: var(--uui-size-1);
}

:host(:not([disabled])) #open-part:hover #icon {
color: var(--uui-color-interactive-emphasis);
}
:host(:not([disabled])) #open-part:hover #name {
color: var(--uui-color-interactive-emphasis);
}

:host([disabled]) #icon {
color: var(--uui-color-disabled-contrast);
}
:host([disabled]) #name {
color: var(--uui-color-disabled-contrast);
}
`,
];
Expand Down
Loading
Loading