Merge remote-tracking branch 'origin/main' into feature/workspace-action-menu
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
"tinymce",
|
||||
"umbraco",
|
||||
"Uncategorized",
|
||||
"uninitialize",
|
||||
"variantable"
|
||||
],
|
||||
"exportall.config.folderListener": [],
|
||||
|
||||
@@ -124,6 +124,8 @@
|
||||
"check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist",
|
||||
"compile": "tsc",
|
||||
"dev": "vite",
|
||||
"dev:server": "VITE_UMBRACO_USE_MSW=off vite",
|
||||
"dev:mock": "VITE_UMBRACO_USE_MSW=on vite",
|
||||
"example": "node ./devops/example-runner/index.js",
|
||||
"format:fix": "npm run format -- --write",
|
||||
"format": "prettier 'src/**/*.ts' -- check",
|
||||
|
||||
@@ -197,6 +197,8 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
|
||||
|
||||
#scrollElement?: Element | null;
|
||||
|
||||
#enabled = true;
|
||||
|
||||
#dragX = 0;
|
||||
#dragY = 0;
|
||||
|
||||
@@ -234,7 +236,18 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
|
||||
});
|
||||
}
|
||||
|
||||
setModel(model: Array<T>) {
|
||||
enable(): void {
|
||||
if (this.#enabled) return;
|
||||
this.#enabled = true;
|
||||
this.#initialize();
|
||||
}
|
||||
disable(): void {
|
||||
if (!this.#enabled) return;
|
||||
this.#enabled = false;
|
||||
this.#uninitialize();
|
||||
}
|
||||
|
||||
setModel(model: Array<T>): void {
|
||||
if (this.#model) {
|
||||
// TODO: Some updates might need to be done, as the modal is about to changed? Do make the changes after setting the model?..
|
||||
}
|
||||
@@ -250,9 +263,16 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
requestAnimationFrame(this._onFirstRender);
|
||||
if (this.#enabled) {
|
||||
requestAnimationFrame(this.#initialize);
|
||||
}
|
||||
}
|
||||
private _onFirstRender = () => {
|
||||
hostDisconnected() {
|
||||
if (this.#enabled) {
|
||||
this.#uninitialize();
|
||||
}
|
||||
}
|
||||
#initialize = () => {
|
||||
const containerEl =
|
||||
(this.#config.containerSelector
|
||||
? this.#host.shadowRoot!.querySelector(this.#config.containerSelector)
|
||||
@@ -281,7 +301,7 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
|
||||
subtree: false,
|
||||
});
|
||||
};
|
||||
hostDisconnected() {
|
||||
#uninitialize() {
|
||||
// TODO: Is there more clean up to do??
|
||||
this.#observer.disconnect();
|
||||
if (this.#containerElement) {
|
||||
@@ -427,7 +447,7 @@ export class UmbSorterController<T, ElementType extends HTMLElement = HTMLElemen
|
||||
UmbSorterController.originalIndex = this.#model.indexOf(UmbSorterController.activeItem);
|
||||
|
||||
if (!UmbSorterController.activeItem) {
|
||||
console.error('Could not find item related to this element.');
|
||||
console.error('Could not find item related to this element.', UmbSorterController.activeElement);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,23 +22,20 @@ export class UmbWorkspaceIsNewRedirectController extends UmbBaseController {
|
||||
super(host, 'isNewRedirectController');
|
||||
|
||||
// Navigate to edit route when language is created:
|
||||
this.observe(
|
||||
workspaceContext.isNew,
|
||||
(isNew) => {
|
||||
if (isNew === false) {
|
||||
const unique = workspaceContext.getUnique();
|
||||
if (router && unique) {
|
||||
const routerPath = router.absoluteRouterPath;
|
||||
if (routerPath) {
|
||||
const newPath = createRoutePathBuilder(ensurePathEndsWithSlash(routerPath) + 'edit/:id')({ id: unique });
|
||||
window.history.pushState({}, '', newPath);
|
||||
|
||||
this.destroy();
|
||||
}
|
||||
this.observe(workspaceContext.isNew, (isNew) => {
|
||||
if (isNew === false) {
|
||||
const unique = workspaceContext.getUnique();
|
||||
if (router && unique) {
|
||||
const routerPath = router.absoluteRouterPath;
|
||||
if (routerPath) {
|
||||
const newPath: string = createRoutePathBuilder(ensurePathEndsWithSlash(routerPath) + 'edit/:id')({
|
||||
id: unique,
|
||||
});
|
||||
this.destroy();
|
||||
window.history.pushState({}, '', newPath);
|
||||
}
|
||||
}
|
||||
},
|
||||
'_observeIsNew',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement {
|
||||
(this.shadowRoot!.querySelector('#nameInput') as HTMLElement).focus();
|
||||
});
|
||||
}
|
||||
this.removeControllerByAlias('_observeIsNew');
|
||||
this.removeControllerByAlias('isNewRedirectController');
|
||||
},
|
||||
'_observeIsNew',
|
||||
);
|
||||
|
||||
@@ -54,7 +54,7 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement {
|
||||
// TODO: Would be good with a more general way to bring focus to the name input.
|
||||
(this.shadowRoot?.querySelector('#name') as HTMLElement)?.focus();
|
||||
}
|
||||
this.removeControllerByAlias('_observeIsNew');
|
||||
this.removeControllerByAlias('isNewRedirectController');
|
||||
},
|
||||
'_observeIsNew',
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ export class UmbDocumentTypeWorkspaceElement extends UmbLitElement {
|
||||
path: 'edit/:id',
|
||||
component: this.#createElement,
|
||||
setup: (_component, info) => {
|
||||
this.removeControllerByAlias('_observeIsNew');
|
||||
this.removeControllerByAlias('isNewRedirectController');
|
||||
const id = info.match.params.id;
|
||||
this.#workspaceContext.load(id);
|
||||
},
|
||||
|
||||
@@ -13,7 +13,6 @@ import { UMB_PROPERTY_SETTINGS_MODAL, UmbModalRouteRegistrationController } from
|
||||
|
||||
@customElement('umb-document-type-workspace-view-edit-properties')
|
||||
export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitElement {
|
||||
#model: Array<UmbPropertyTypeModel> = [];
|
||||
#sorter = new UmbSorterController<UmbPropertyTypeModel, UmbDocumentTypeWorkspacePropertyElement>(this, {
|
||||
getUniqueOfElement: (element) => {
|
||||
return element.getAttribute('data-umb-property-id');
|
||||
@@ -29,8 +28,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
// Or maybe we do, but we still need to check if the group exists locally, if not, then it needs to be created before we move a property into it.
|
||||
// TODO: Fix bug where a local property turn into an inherited when moved to a new group container.
|
||||
containerSelector: '#property-list',
|
||||
onChange: ({ item, model }) => {
|
||||
this.#model = model;
|
||||
onChange: ({ model }) => {
|
||||
this._propertyStructure = model;
|
||||
},
|
||||
onEnd: ({ item }) => {
|
||||
@@ -38,7 +36,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
* If it's not the first in list, we will compare to the item in before it, and check the following item to see if it caused overlapping sortOrder, then update
|
||||
* the overlap if true, which may cause another overlap, so we loop through them till no more overlaps...
|
||||
*/
|
||||
const model = this.#model;
|
||||
const model = this._propertyStructure;
|
||||
const newIndex = model.findIndex((entry) => entry.id === item.id);
|
||||
|
||||
// Doesn't exist in model
|
||||
@@ -123,6 +121,8 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.#sorter.disable();
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, async (workspaceContext) => {
|
||||
this._propertyStructureHelper.setStructureManager(
|
||||
(workspaceContext as UmbDocumentTypeWorkspaceContext).structure,
|
||||
@@ -132,9 +132,9 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
(isSorting) => {
|
||||
this._sortModeActive = isSorting;
|
||||
if (isSorting) {
|
||||
this.#sorter.setModel(this._propertyStructure);
|
||||
this.#sorter.enable();
|
||||
} else {
|
||||
this.#sorter.setModel([]);
|
||||
this.#sorter.disable();
|
||||
}
|
||||
},
|
||||
'_observeIsSorting',
|
||||
@@ -151,11 +151,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
});
|
||||
this.observe(this._propertyStructureHelper.propertyStructure, (propertyStructure) => {
|
||||
this._propertyStructure = propertyStructure;
|
||||
if (this._sortModeActive) {
|
||||
this.#sorter.setModel(this._propertyStructure);
|
||||
} else {
|
||||
this.#sorter.setModel([]);
|
||||
}
|
||||
this.#sorter.setModel(this._propertyStructure);
|
||||
});
|
||||
|
||||
// Note: Route for adding a new property
|
||||
@@ -171,9 +167,6 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
|
||||
return { data: { documentTypeId }, value: propertyData };
|
||||
})
|
||||
.onSubmit((value) => {
|
||||
if (!value.dataType) {
|
||||
throw new Error('No data type selected');
|
||||
}
|
||||
this.#addProperty(value as UmbPropertyTypeModel);
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
|
||||
@@ -93,9 +93,6 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
|
||||
return { data: { documentTypeId }, value: propertyData };
|
||||
})
|
||||
.onSubmit((result) => {
|
||||
if (!result.dataType) {
|
||||
throw new Error('No dataType found on property');
|
||||
}
|
||||
this._partialUpdate(result as UmbPropertyTypeModel);
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
|
||||
@@ -16,7 +16,6 @@ import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
|
||||
@customElement('umb-document-type-workspace-view-edit-tab')
|
||||
export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
#model: Array<UmbPropertyTypeContainerModel> = [];
|
||||
#sorter = new UmbSorterController<UmbPropertyTypeContainerModel, UmbDocumentTypeWorkspaceViewEditPropertiesElement>(
|
||||
this,
|
||||
{
|
||||
@@ -28,14 +27,13 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
containerSelector: '.container-list',
|
||||
onChange: ({ model }) => {
|
||||
this._groups = model;
|
||||
this.#model = model;
|
||||
},
|
||||
onEnd: ({ item }) => {
|
||||
/** Explanation: If the item is the first in list, we compare it to the item behind it to set a sortOrder.
|
||||
* If it's not the first in list, we will compare to the item in before it, and check the following item to see if it caused overlapping sortOrder, then update
|
||||
* the overlap if true, which may cause another overlap, so we loop through them till no more overlaps...
|
||||
*/
|
||||
const model = this.#model;
|
||||
const model = this._groups;
|
||||
const newIndex = model.findIndex((entry) => entry.id === item.id);
|
||||
|
||||
// Doesn't exist in model
|
||||
@@ -43,7 +41,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
// First in list
|
||||
if (newIndex === 0 && model.length > 1) {
|
||||
this._groupStructureHelper.partialUpdateContainer(item.id, { sortOrder: model[1].sortOrder - 1 });
|
||||
this.#groupStructureHelper.partialUpdateContainer(item.id, { sortOrder: model[1].sortOrder - 1 });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,14 +50,14 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
const prevItemSortOrder = model[newIndex - 1].sortOrder;
|
||||
|
||||
let weight = 1;
|
||||
this._groupStructureHelper.partialUpdateContainer(item.id, { sortOrder: prevItemSortOrder + weight });
|
||||
this.#groupStructureHelper.partialUpdateContainer(item.id, { sortOrder: prevItemSortOrder + weight });
|
||||
|
||||
// Check for overlaps
|
||||
model.some((entry, index) => {
|
||||
if (index <= newIndex) return;
|
||||
if (entry.sortOrder === prevItemSortOrder + weight) {
|
||||
weight++;
|
||||
this._groupStructureHelper.partialUpdateContainer(entry.id, { sortOrder: prevItemSortOrder + weight });
|
||||
this.#groupStructureHelper.partialUpdateContainer(entry.id, { sortOrder: prevItemSortOrder + weight });
|
||||
}
|
||||
// Break the loop
|
||||
return true;
|
||||
@@ -80,7 +78,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
if (value === this._ownerTabId) return;
|
||||
const oldValue = this._ownerTabId;
|
||||
this._ownerTabId = value;
|
||||
this._groupStructureHelper.setOwnerId(value);
|
||||
this.#groupStructureHelper.setOwnerId(value);
|
||||
this.requestUpdate('ownerTabId', oldValue);
|
||||
}
|
||||
|
||||
@@ -88,13 +86,13 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
@property({ type: String })
|
||||
public get tabName(): string | undefined {
|
||||
return this._groupStructureHelper.getName();
|
||||
return this.#groupStructureHelper.getName();
|
||||
}
|
||||
public set tabName(value: string | undefined) {
|
||||
if (value === this._tabName) return;
|
||||
const oldValue = this._tabName;
|
||||
this._tabName = value;
|
||||
this._groupStructureHelper.setName(value);
|
||||
this.#groupStructureHelper.setName(value);
|
||||
this.requestUpdate('tabName', oldValue);
|
||||
}
|
||||
|
||||
@@ -103,15 +101,13 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
@property({ type: Boolean })
|
||||
public get noTabName(): boolean {
|
||||
return this._groupStructureHelper.getIsRoot();
|
||||
return this.#groupStructureHelper.getIsRoot();
|
||||
}
|
||||
public set noTabName(value: boolean) {
|
||||
this._noTabName = value;
|
||||
this._groupStructureHelper.setIsRoot(value);
|
||||
this.#groupStructureHelper.setIsRoot(value);
|
||||
}
|
||||
|
||||
_groupStructureHelper = new UmbContentTypeContainerStructureHelper<UmbDocumentTypeDetailModel>(this);
|
||||
|
||||
@state()
|
||||
_groups: Array<UmbPropertyTypeContainerModel> = [];
|
||||
|
||||
@@ -121,35 +117,32 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
@state()
|
||||
_sortModeActive?: boolean;
|
||||
|
||||
#groupStructureHelper = new UmbContentTypeContainerStructureHelper<UmbDocumentTypeDetailModel>(this);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => {
|
||||
this._groupStructureHelper.setStructureManager((context as UmbDocumentTypeWorkspaceContext).structure);
|
||||
this.#groupStructureHelper.setStructureManager((context as UmbDocumentTypeWorkspaceContext).structure);
|
||||
this.observe(
|
||||
(context as UmbDocumentTypeWorkspaceContext).isSorting,
|
||||
(isSorting) => {
|
||||
this._sortModeActive = isSorting;
|
||||
|
||||
if (isSorting) {
|
||||
this.#sorter.setModel(this._groups);
|
||||
this.#sorter.enable();
|
||||
} else {
|
||||
this.#sorter.setModel([]);
|
||||
this.#sorter.disable();
|
||||
}
|
||||
},
|
||||
'_observeIsSorting',
|
||||
);
|
||||
});
|
||||
this.observe(this._groupStructureHelper.containers, (groups) => {
|
||||
this.observe(this.#groupStructureHelper.containers, (groups) => {
|
||||
this._groups = groups;
|
||||
if (this._sortModeActive) {
|
||||
this.#sorter.setModel(this._groups);
|
||||
} else {
|
||||
this.#sorter.setModel([]);
|
||||
}
|
||||
this.#sorter.setModel(this._groups);
|
||||
this.requestUpdate('_groups');
|
||||
});
|
||||
this.observe(this._groupStructureHelper.hasProperties, (hasProperties) => {
|
||||
this.observe(this.#groupStructureHelper.hasProperties, (hasProperties) => {
|
||||
this._hasProperties = hasProperties;
|
||||
this.requestUpdate('_hasProperties');
|
||||
});
|
||||
@@ -157,7 +150,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
#onAddGroup = () => {
|
||||
// Idea, maybe we can gather the sortOrder from the last group rendered and add 1 to it?
|
||||
this._groupStructureHelper.addContainer(this._ownerTabId);
|
||||
this.#groupStructureHelper.addContainer(this._ownerTabId);
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -186,7 +179,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
<div class="container-list" ?sort-mode-active=${this._sortModeActive}>
|
||||
${repeat(
|
||||
this._groups,
|
||||
(group) => group.id + '' + group.name + group.sortOrder,
|
||||
(group) => group.id,
|
||||
(group) =>
|
||||
html`<uui-box class="container-handle">
|
||||
${this.#renderHeader(group)}
|
||||
@@ -203,7 +196,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#renderHeader(group: UmbPropertyTypeContainerModel) {
|
||||
const inherited = !this._groupStructureHelper.isOwnerChildContainer(group.id!);
|
||||
const inherited = !this.#groupStructureHelper.isOwnerChildContainer(group.id!);
|
||||
|
||||
if (this._sortModeActive) {
|
||||
return html`<div slot="header">
|
||||
@@ -215,7 +208,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
type="number"
|
||||
label=${this.localize.term('sort_sortOrder')}
|
||||
@change=${(e: UUIInputEvent) =>
|
||||
this._groupStructureHelper.partialUpdateContainer(group.id!, {
|
||||
this.#groupStructureHelper.partialUpdateContainer(group.id!, {
|
||||
sortOrder: parseInt(e.target.value as string) || 0,
|
||||
})}
|
||||
.value=${group.sortOrder || 0}
|
||||
@@ -235,7 +228,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
.value=${group.name}
|
||||
@change=${(e: InputEvent) => {
|
||||
const newName = (e.target as HTMLInputElement).value;
|
||||
this._groupStructureHelper.updateContainerName(group.id!, group.parent?.id ?? null, newName);
|
||||
this.#groupStructureHelper.updateContainerName(group.id!, group.parent?.id ?? null, newName);
|
||||
}}></uui-input>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export class UmbLanguageWorkspaceElement extends UmbLitElement {
|
||||
path: 'edit/:unique',
|
||||
component: this.#createElement,
|
||||
setup: (_component, info) => {
|
||||
this.removeControllerByAlias('_observeIsNew');
|
||||
this.removeControllerByAlias('isNewRedirectController');
|
||||
this.#languageWorkspaceContext.load(info.match.params.unique);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -55,7 +55,7 @@ export class UmbMediaTypeWorkspaceEditorElement extends UmbLitElement {
|
||||
// TODO: Would be good with a more general way to bring focus to the name input.
|
||||
(this.shadowRoot?.querySelector('#name') as HTMLElement)?.focus();
|
||||
}
|
||||
this.removeControllerByAlias('_observeIsNew');
|
||||
this.removeControllerByAlias('isNewRedirectController');
|
||||
},
|
||||
'_observeIsNew',
|
||||
);
|
||||
|
||||
@@ -94,9 +94,6 @@ export class UmbMediaTypeWorkspacePropertyElement extends UmbLitElement {
|
||||
return { data: { documentTypeId: mediaTypeId }, value: propertyData }; //TODO: Should we have a separate modal for mediaTypes?
|
||||
})
|
||||
.onSubmit((result) => {
|
||||
if (!result.dataType) {
|
||||
throw new Error('No dataType found on property');
|
||||
}
|
||||
this._partialUpdate(result as UmbPropertyTypeModel);
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
|
||||
Reference in New Issue
Block a user