Merge pull request #1621 from umbraco/bugfix/content-type-design-editor-fixes-20240416
Fix: Content Type Design Editor fixes
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user