Merge pull request #1621 from umbraco/bugfix/content-type-design-editor-fixes-20240416

Fix: Content Type Design Editor fixes
This commit is contained in:
Niels Lyngsø
2024-04-16 15:40:50 +02:00
committed by GitHub
7 changed files with 123 additions and 98 deletions

View File

@@ -12,21 +12,21 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
#init;
#initResolver?: (value: unknown) => void;
_containerId?: string | null;
_childType?: UmbPropertyContainerTypes = 'Group';
#containerId?: string | null;
#childType?: UmbPropertyContainerTypes = 'Group';
#structure?: UmbContentTypeStructureManager<T>;
// State containing the all containers defined in the data:
#containers = new UmbArrayState<UmbPropertyTypeContainerModel>([], (x) => x.id);
readonly containers = this.#containers.asObservable();
#childContainers = new UmbArrayState<UmbPropertyTypeContainerModel>([], (x) => x.id);
readonly containers = this.#childContainers.asObservable();
// State containing the merged containers (only one pr. name):
#mergedContainers = new UmbArrayState<UmbPropertyTypeContainerModel>([], (x) => x.id);
readonly mergedContainers = this.#mergedContainers.asObservable();
#mergedChildContainers = new UmbArrayState<UmbPropertyTypeContainerModel>([], (x) => x.id);
readonly mergedContainers = this.#mergedChildContainers.asObservable();
// Owner containers are containers owned by the owner Content Type (The specific one up for editing)
private _ownerContainers: UmbPropertyTypeContainerModel[] = [];
#ownerChildContainers: UmbPropertyTypeContainerModel[] = [];
#hasProperties = new UmbBooleanState(false);
readonly hasProperties = this.#hasProperties.asObservable();
@@ -37,7 +37,7 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
this.#initResolver = resolve;
});
this.#mergedContainers.sortBy((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
this.#mergedChildContainers.sortBy((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
this.observe(this.containers, this.#performContainerMerge, null);
}
@@ -64,73 +64,73 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
}
}
public getIsRoot() {
return this._containerId === null;
return this.#containerId === null;
}
public setContainerId(value: string | null | undefined) {
if (this._containerId === value) return;
this._containerId = value;
if (this.#containerId === value) return;
this.#containerId = value;
this.#observeContainers();
}
public getContainerId() {
return this._containerId;
return this.#containerId;
}
public setContainerChildType(value?: UmbPropertyContainerTypes) {
if (this._childType === value) return;
this._childType = value;
if (this.#childType === value) return;
this.#childType = value;
this.#observeContainers();
}
public getContainerChildType() {
return this._childType;
return this.#childType;
}
private _containerName?: string;
private _containerType?: UmbPropertyContainerTypes;
private _parentName?: string | null;
private _parentType?: UmbPropertyContainerTypes;
#containerName?: string;
#containerType?: UmbPropertyContainerTypes;
#parentName?: string | null;
#parentType?: UmbPropertyContainerTypes;
#observeContainers() {
if (!this.#structure || this._containerId === undefined) return;
if (!this.#structure || this.#containerId === undefined) return;
if (this._containerId === null) {
if (this.#containerId === null) {
this.#observeHasPropertiesOf(null);
this.#observeRootContainers();
this.removeUmbControllerByAlias('_observeContainers');
} else {
this.observe(
this.#structure.containerById(this._containerId),
this.#structure.containerById(this.#containerId),
(container) => {
if (container) {
this._containerName = container.name ?? '';
this._containerType = container.type;
this.#containerName = container.name ?? '';
this.#containerType = container.type;
if (container.parent) {
// We have a parent for our main container, so lets observe that one as well:
this.observe(
this.#structure!.containerById(container.parent.id),
(parent) => {
if (parent) {
this._parentName = parent.name ?? '';
this._parentType = parent.type;
this.#parentName = parent.name ?? '';
this.#parentType = parent.type;
this.#observeSimilarContainers();
} else {
this.removeUmbControllerByAlias('_observeContainers');
this._parentName = undefined;
this._parentType = undefined;
this.#parentName = undefined;
this.#parentType = undefined;
}
},
'_observeMainParentContainer',
);
} else {
this.removeUmbControllerByAlias('_observeMainParentContainer');
this._parentName = null; //In this way we want to look for one without a parent. [NL]
this._parentType = undefined;
this.#parentName = null; //In this way we want to look for one without a parent. [NL]
this.#parentType = undefined;
this.#observeSimilarContainers();
}
} else {
this.removeUmbControllerByAlias('_observeContainers');
this._containerName = undefined;
this._containerType = undefined;
this.#containerName = undefined;
this.#containerType = undefined;
// TODO: reset has Properties.
this.#hasProperties.setValue(false);
}
@@ -141,30 +141,37 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
}
#observeSimilarContainers() {
if (!this._containerName || !this._containerType || this._parentName === undefined) return;
if (!this.#containerName || !this.#containerType || this.#parentName === undefined) return;
this.observe(
this.#structure!.containersByNameAndTypeAndParent(
this._containerName,
this._containerType,
this._parentName,
this._parentType,
this.#containerName,
this.#containerType,
this.#parentName,
this.#parentType,
),
(containers) => {
// We want to remove hasProperties of groups that does not exist anymore.:
// this.#removeHasPropertiesOfGroup()
this.#hasProperties.setValue(false);
this.#containers.setValue([]);
this.#childContainers.setValue([]);
containers.forEach((container) => {
this.#observeHasPropertiesOf(container.id);
this.observe(
this.#structure!.containersOfParentId(container.id, this._childType!),
this.#structure!.containersOfParentId(container.id, this.#childType!),
(containers) => {
// Remove existing containers that are not the parent of the new containers:
this.#containers.filter((x) => x.parent?.id !== container.id || containers.some((y) => y.id === x.id));
// get the direct owner containers of this container id:
this.#ownerChildContainers =
this.#structure!.getOwnerContainers(this.#childType!, this.#containerId!) ?? [];
// TODO: Maybe check for dif before setting it? Cause currently we are setting it every time one of the containers change. [NL]
this.#containers.append(containers);
// Remove existing containers that are not the parent of the new containers:
this.#childContainers.filter(
(x) => x.parent?.id !== container.id || containers.some((y) => y.id === x.id),
);
this.#childContainers.append(containers);
},
'_observeGroupsOf_' + container.id,
);
@@ -175,16 +182,16 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
}
#observeRootContainers() {
if (!this.#structure || !this._childType || !this._containerId === undefined) return;
if (!this.#structure || !this.#childType || !this.#containerId === undefined) return;
this.observe(
this.#structure.rootContainers(this._childType),
this.#structure.rootContainers(this.#childType),
(rootContainers) => {
// Here (When getting root containers) we get containers from all ContentTypes. It also means we need to do an extra filtering to ensure we only get one of each containers. [NL]
// For that we get the owner containers first (We do not need to observe as this observation will be triggered if one of the owner containers change) [NL]
this._ownerContainers = this.#structure!.getOwnerContainers(this._childType!, this._containerId!) ?? [];
this.#containers.setValue(rootContainers);
this.#ownerChildContainers = this.#structure!.getOwnerContainers(this.#childType!, this.#containerId!) ?? [];
this.#childContainers.setValue(rootContainers);
},
'_observeRootContainers',
);
@@ -204,10 +211,10 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
}
#filterNonOwnerContainers(containers: Array<UmbPropertyTypeContainerModel>) {
return this._ownerContainers.length > 0
return this.#ownerChildContainers.length > 0
? containers.filter(
(anyCon) =>
!this._ownerContainers.some(
!this.#ownerChildContainers.some(
(ownerCon) =>
// Then if this is not the owner container but matches one by name & type, then we do not want it.
ownerCon.id !== anyCon.id && ownerCon.name === anyCon.name && ownerCon.type === anyCon.type,
@@ -222,7 +229,7 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
// Remove containers of same name and type:
// This only works cause we are dealing with a single level of containers in this Helper, if we had more levels we would need to be more clever about the parent as well. [NL]
merged = merged.filter((x, i, cons) => i === cons.findIndex((y) => y.name === x.name && y.type === x.type));
this.#mergedContainers.setValue(merged);
this.#mergedChildContainers.setValue(merged);
};
/**
@@ -230,11 +237,11 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
*/
isOwnerChildContainer(containerId?: string) {
if (!this.#structure || !containerId) return;
return this._ownerContainers.some((x) => x.id === containerId);
return this.#ownerChildContainers.some((x) => x.id === containerId);
}
containersByNameAndType(name: string, type: UmbPropertyContainerTypes) {
return this.#containers.asObservablePart((cons) => cons.filter((x) => x.name === name && x.type === type));
return this.#childContainers.asObservablePart((cons) => cons.filter((x) => x.name === name && x.type === type));
}
/** Manipulate methods: */
@@ -252,7 +259,7 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
async addContainer(parentContainerId?: string | null, sortOrder?: number) {
if (!this.#structure) return;
await this.#structure.createContainer(null, parentContainerId, this._childType, sortOrder);
await this.#structure.createContainer(null, parentContainerId, this.#childType, sortOrder);
}
async removeContainer(groupId: string) {

View File

@@ -159,7 +159,7 @@ export class UmbContentTypePropertyStructureHelper<T extends UmbContentTypeModel
// Lets append the properties that does not exists already:
properties?.forEach((property) => {
if (!_propertyStructure.find((x) => x.alias === property.alias)) {
if (!_propertyStructure.find((x) => x.id === property.id)) {
_propertyStructure.push(property);
}
});

View File

@@ -386,14 +386,20 @@ export class UmbContentTypeStructureManager<
await this.#init;
contentTypeUnique = contentTypeUnique ?? this.#ownerContentTypeUnique!;
const frozenContainers =
this.#contentTypes.getValue().find((x) => x.unique === contentTypeUnique)?.containers ?? [];
const containers = frozenContainers.filter((x) => x.id !== containerId);
const contentType = this.#contentTypes.getValue().find((x) => x.unique === contentTypeUnique);
if (!contentType) {
throw new Error('Could not find the Content Type to remove container from');
}
const frozenContainers = contentType.containers ?? [];
const containers = frozenContainers.filter((x) => x.id !== containerId || x.parent?.id !== containerId);
const frozenProperties = contentType.properties ?? [];
const properties = frozenProperties.filter((x) => x.container?.id !== containerId);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// TODO: fix TS partial complaint
this.#contentTypes.updateOne(contentTypeUnique, { containers });
this.#contentTypes.updateOne(contentTypeUnique, { containers, properties });
}
createPropertyScaffold(containerId: string | null = null) {
@@ -424,7 +430,7 @@ export class UmbContentTypeStructureManager<
await this.#init;
contentTypeUnique = contentTypeUnique ?? this.#ownerContentTypeUnique!;
// If we have a container, we need to ensure it exists, and then update the container with the new parent id.
// If we have a container, we need to ensure it exists, and then update the container with the new parent id. [NL]
if (containerId) {
const container = await this.ensureContainerOf(containerId, contentTypeUnique);
if (!container) {
@@ -455,7 +461,7 @@ export class UmbContentTypeStructureManager<
await this.#init;
contentTypeUnique = contentTypeUnique ?? this.#ownerContentTypeUnique!;
// If we have a container, we need to ensure it exists, and then update the container with the new parent id.
// If we have a container, we need to ensure it exists, and then update the container with the new parent id. [NL]
if (property.container) {
const container = await this.ensureContainerOf(property.container.id, contentTypeUnique);
if (!container) {
@@ -501,7 +507,6 @@ export class UmbContentTypeStructureManager<
const frozenProperties =
this.#contentTypes.getValue().find((x) => x.unique === contentTypeUnique)?.properties ?? [];
const properties = partialUpdateFrozenArray(frozenProperties, partialUpdate, (x) => x.id === propertyId);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment

View File

@@ -59,8 +59,13 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
);
const pureOwnerContainer = hasAOwnerContainer && containers.length === 1;
// TODO: Check if requstUpdate is needed here, I do not think it is when i added it, but I just wanted to be safe when debugging [NL]
const oldHasOwnerContainer = this._hasOwnerContainer;
const oldInherited = this._inherited;
this._hasOwnerContainer = hasAOwnerContainer;
this._inherited = !pureOwnerContainer;
this.requestUpdate('_hasOwnerContainer', oldHasOwnerContainer);
this.requestUpdate('_inherited', oldInherited);
},
'observeGroupContainers',
);

View File

@@ -91,8 +91,8 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
return this._containerId;
}
public set containerId(value: string | null | undefined) {
if (value === this._containerId) return;
const oldValue = this._containerId;
if (value === oldValue) return;
this._containerId = value;
this.#propertyStructureHelper.setContainerId(value);
this.#addPropertyModal.setUniquePathValue('container-id', value === null ? 'root' : value);

View File

@@ -23,8 +23,8 @@ import {
export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
//
#dataTypeDetailRepository = new UmbDataTypeDetailRepository(this);
#settingsModal;
#dataTypeUnique?: string;
@property({ attribute: false })
public set propertyStructureHelper(value: UmbContentTypePropertyStructureHelper<UmbContentTypeModel> | undefined) {
@@ -49,10 +49,11 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
}
public set property(value: UmbPropertyTypeModel | UmbPropertyTypeScaffoldModel | undefined) {
const oldValue = this._property;
if (value === oldValue) return;
this._property = value;
this.#checkInherited();
this.#settingsModal.setUniquePathValue('propertyId', value?.id);
this.setDataType(this._property?.dataType?.unique);
this.#setDataType(this._property?.dataType?.unique);
this.requestUpdate('property', oldValue);
}
private _property?: UmbPropertyTypeModel | UmbPropertyTypeScaffoldModel | undefined;
@@ -102,7 +103,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
return { data: { contentTypeId: id }, value: propertyData };
})
.onSubmit((result) => {
this._partialUpdate(result as UmbPropertyTypeModel);
this.#partialUpdate(result as UmbPropertyTypeModel);
})
.observeRouteBuilder((routeBuilder) => {
this._modalRoute = routeBuilder(null);
@@ -122,12 +123,12 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
}
}
_partialUpdate(partialObject: UmbPropertyTypeModel) {
#partialUpdate(partialObject: UmbPropertyTypeModel) {
if (!this._property || !this._propertyStructureHelper) return;
this._propertyStructureHelper.partialUpdateProperty(this._property.id, partialObject);
}
_singleValueUpdate<PropertyNameType extends keyof UmbPropertyTypeModel>(
#singleValueUpdate<PropertyNameType extends keyof UmbPropertyTypeModel>(
propertyName: PropertyNameType,
value: UmbPropertyTypeModel[PropertyNameType],
) {
@@ -141,9 +142,15 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
this._aliasLocked = !this._aliasLocked;
}
async setDataType(dataTypeId: string | undefined) {
if (!dataTypeId) return;
this.#dataTypeDetailRepository.requestByUnique(dataTypeId).then((x) => (this._dataTypeName = x?.data?.name));
async #setDataType(dataTypeUnique: string | undefined) {
if (!dataTypeUnique) {
this._dataTypeName = undefined;
this.#dataTypeUnique = undefined;
return;
}
if (dataTypeUnique === this.#dataTypeUnique) return;
this.#dataTypeUnique = dataTypeUnique;
this.#dataTypeDetailRepository.requestByUnique(dataTypeUnique).then((x) => (this._dataTypeName = x?.data?.name));
}
async #requestRemove(e: Event) {
@@ -167,7 +174,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
this._propertyStructureHelper?.removeProperty(this._property.id);
}
#onNameChange(event: UUIInputEvent) {
#onNameChanged(event: UUIInputEvent) {
if (event instanceof UUIInputEvent) {
const target = event.composedPath()[0] as UUIInputElement;
@@ -179,10 +186,10 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
const expectedOldAlias = generateAlias(oldName ?? '');
// Only update the alias if the alias matches a generated alias of the old name (otherwise the alias is considered one written by the user.)
if (expectedOldAlias === oldAlias) {
this._singleValueUpdate('alias', generateAlias(newName ?? ''));
this.#singleValueUpdate('alias', generateAlias(newName ?? ''));
}
}
this._singleValueUpdate('name', newName);
this.#singleValueUpdate('name', newName);
}
}
}
@@ -234,7 +241,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
placeholder=${this.localize.term('placeholders_label')}
label="label"
.value=${this.property.name}
@input=${this.#onNameChange}></uui-input>
@input=${this.#onNameChanged}></uui-input>
${this.renderPropertyAlias()}
<slot name="action-menu"></slot>
<p>
@@ -245,7 +252,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
placeholder=${this.localize.term('placeholders_enterDescription')}
.value=${this.property.description}
@input=${(e: CustomEvent) => {
if (e.target) this._singleValueUpdate('description', (e.target as HTMLInputElement).value);
if (e.target) this.#singleValueUpdate('description', (e.target as HTMLInputElement).value);
}}></uui-textarea>
</p>
</div>
@@ -276,7 +283,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
?readonly=${this.inherited}
label="sort order"
@change=${(e: UUIInputEvent) =>
this._partialUpdate({ sortOrder: parseInt(e.target.value as string) ?? 0 } as UmbPropertyTypeModel)}
this.#partialUpdate({ sortOrder: parseInt(e.target.value as string) ?? 0 } as UmbPropertyTypeModel)}
.value=${this.property.sortOrder ?? 0}></uui-input>
`;
}
@@ -291,7 +298,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
.value=${this.property.alias}
?disabled=${this._aliasLocked}
@input=${(e: CustomEvent) => {
if (e.target) this._singleValueUpdate('alias', (e.target as HTMLInputElement).value);
if (e.target) this.#singleValueUpdate('alias', (e.target as HTMLInputElement).value);
}}>
<!-- TODO: should use UUI-LOCK-INPUT, but that does not fire an event when its locked/unlocked -->
<!-- TODO: validation for bad characters -->

View File

@@ -25,7 +25,7 @@ import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
@customElement('umb-content-type-design-editor')
export class UmbContentTypeDesignEditorElement extends UmbLitElement implements UmbWorkspaceViewElement {
#sorter = new UmbSorterController<UmbPropertyTypeContainerModel, UUITabElement>(this, {
getUniqueOfElement: (element) => element.getAttribute('data-umb-tabs-id'),
getUniqueOfElement: (element) => element.getAttribute('data-umb-tab-id'),
getUniqueOfModel: (tab) => tab.id,
identifier: 'content-type-tabs-sorter',
itemSelector: 'uui-tab',
@@ -167,7 +167,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
if (!this.#workspaceContext || !this._tabs || this._hasRootGroups === undefined) return;
const routes: UmbRoute[] = [];
// We gather the activeTab name to check for rename, this is a bit hacky way to redirect the user without noticing to the new name [NL]
// We gather the activeTab name to check for rename, this is a bit hacky way to redirect the user without noticing the url changes to the new name [NL]
let activeTabName: string | undefined = undefined;
if (this._tabs.length > 0) {
@@ -180,8 +180,6 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
path: `tab/${encodeFolderName(tabName).toString()}`,
component: () => import('./content-type-design-editor-tab.element.js'),
setup: (component) => {
// Or just cache the current view here, and use it if the same is begin requested?. [NL]
//(component as UmbContentTypeDesignEditorTabElement).tabName = tabName;
(component as UmbContentTypeDesignEditorTabElement).containerId = tab.id;
},
});
@@ -192,7 +190,6 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
path: 'root',
component: () => import('./content-type-design-editor-tab.element.js'),
setup: (component) => {
//(component as UmbContentTypeDesignEditorTabElement).noTabName = true;
(component as UmbContentTypeDesignEditorTabElement).containerId = null;
},
});
@@ -220,7 +217,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
if (oldPath !== newPath) {
// Lets cheat a bit and update the activePath already, in this way our input does not loose focus [NL]
this._activePath = this._routerPath + newPath;
// Update the current URL, so we are still on this specific tab:
// Update the current URL, so we are still on this specific tab: [NL]
window.history.replaceState(null, '', this._activePath);
// TODO: We have some flickering when renaming, this could potentially be fixed if we cache the view and re-use it if the same is requested [NL]
// Or maybe its just about we just send the updated tabName to the view, and let it handle the update itself [NL]
@@ -247,7 +244,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
color: 'danger',
};
// TODO: If this tab is composed of other tabs, then notify that it will only delete the local tab.
// TODO: If this tab is composed of other tabs, then notify that it will only delete the local tab. [NL]
await umbConfirmModal(this, modalData);
@@ -256,13 +253,13 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
#remove(tabId?: string) {
if (!tabId) return;
this.#workspaceContext?.structure.removeContainer(null, tabId);
// TODO: We should only navigate away if it was the last tab and if it was the active one...
// TODO: We should only navigate away if it was the last tab and if it was the active one... [NL]
this._tabsStructureHelper?.isOwnerChildContainer(tabId)
? window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root'))
: '';
}
async #addTab() {
// If there is already a Tab with no name, then focus it instead of adding a new one:
// If there is already a Tab with no name, then focus it instead of adding a new one: [NL]
// TODO: Optimize this so it looks at the data instead of the DOM [NL]
const inputEl = this.shadowRoot?.querySelector('uui-tab[active] uui-input') as UUIInputElement;
if (inputEl?.value === '') {
@@ -373,7 +370,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
renderAddButton() {
// TODO: Localize this:
if (this._sortModeActive) return;
return html`<uui-button id="add-tab" @click="${this.#addTab}" label="Add tab" compact>
return html`<uui-button id="add-tab" @click="${this.#addTab}" label="Add tab">
<uui-icon name="icon-add"></uui-icon>
Add tab
</uui-button>`;
@@ -439,7 +436,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
label=${tab.name ?? 'unnamed'}
.active=${tabActive}
href=${path}
data-umb-tabs-id=${ifDefined(tab.id)}>
data-umb-tab-id=${ifDefined(tab.id)}>
${this.renderTabInner(tab, tabActive, ownedTab)}
</uui-tab>`;
}
@@ -447,7 +444,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
renderTabInner(tab: UmbPropertyTypeContainerModel, tabActive: boolean, ownedTab: boolean) {
// TODO: Localize this:
if (this._sortModeActive) {
return html`<div class="no-edit">
return html`<div class="not-active">
${ownedTab
? html`<uui-icon name="icon-navigation" class="drag-${tab.id}"> </uui-icon>${tab.name!}
<uui-input
@@ -456,7 +453,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
value=${ifDefined(tab.sortOrder)}
style="width:50px"
@change=${(e: UUIInputEvent) => this.#changeOrderNumber(tab, e)}></uui-input>`
: html`<uui-icon class="external" name="icon-merge"></uui-icon>${tab.name!}`}
: html`<uui-icon name="icon-merge"></uui-icon>${tab.name!}`}
</div>`;
}
@@ -471,16 +468,16 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
auto-width
@change=${(e: InputEvent) => this.#tabNameChanged(e, tab)}
@input=${(e: InputEvent) => this.#tabNameChanged(e, tab)}
@blur=${(e: InputEvent) => this.#tabNameBlur()}>
@blur=${() => this.#tabNameBlur()}>
${this.renderDeleteFor(tab)}
</uui-input>
</div>`;
}
if (ownedTab) {
return html`<div class="no-edit">${tab.name!} ${this.renderDeleteFor(tab)}</div>`;
return html`<div class="not-active">${tab.name!} ${this.renderDeleteFor(tab)}</div>`;
} else {
return html`<div class="no-edit"><uui-icon name="icon-merge"></uui-icon>${tab.name!}</div>`;
return html`<div class="not-active"><uui-icon name="icon-merge"></uui-icon>${tab.name!}</div>`;
}
}
@@ -495,7 +492,11 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
label=${this.localize.term('actions_remove')}
class="trash"
slot="append"
@click=${() => this.#requestRemoveTab(tab)}
@click=${(e: MouseEvent) => {
e.stopPropagation();
e.preventDefault();
this.#requestRemoveTab(tab);
}}
compact>
<uui-icon name="icon-trash"></uui-icon>
</uui-button>`;
@@ -546,7 +547,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
flex-wrap: nowrap;
}
.content-tab-is-empty {
uui-tab.content-tab-is-empty {
align-self: center;
border-radius: 3px;
--uui-tab-text: var(--uui-color-text-alt);
@@ -559,11 +560,11 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
border-right: 1px solid var(--uui-color-border);
}
.no-edit uui-input {
.not-active uui-button {
pointer-events: auto;
}
.no-edit {
.not-active {
pointer-events: none;
display: inline-flex;
padding-left: var(--uui-size-space-3);
@@ -574,12 +575,12 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
.trash {
opacity: 1;
transition: opacity 120ms;
transition: opacity 100ms;
}
uui-tab:not(:hover, :focus) .trash {
opacity: 0;
transition: opacity 120ms;
transition: opacity 100ms;
}
uui-input:not(:focus, :hover) {