Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
2ca4272
remove use of modals in collections
nielslyngsoe Sep 29, 2025
307ffdd
add parent path to support absolute path generation
nielslyngsoe Sep 29, 2025
9518eba
Merge branch 'v16/bugfix/media-workspace-path-absolute-argument' into…
nielslyngsoe Sep 29, 2025
53a0beb
Merge branch 'v17/dev' into v17/feature/stop-opening-modals-in-collec…
nielslyngsoe Sep 29, 2025
bc84db8
add note
nielslyngsoe Oct 1, 2025
62aef67
make tree load more minimalistic
nielslyngsoe Oct 5, 2025
a21172f
set type and expand inherited styles
nielslyngsoe Oct 5, 2025
90ddb02
Merge branch 'v17/dev' into v17/feature/minimalistic-tree-load-more
nielslyngsoe Oct 6, 2025
9cc8ad5
also set title
nielslyngsoe Oct 6, 2025
298844f
Merge branch 'v17/dev' into v17/feature/stop-opening-modals-in-collec…
nielslyngsoe Oct 6, 2025
4ac3ec3
Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/col…
nielslyngsoe Oct 6, 2025
53461ff
create actions should not open as modal
nielslyngsoe Oct 6, 2025
052da8f
remove unused import
nielslyngsoe Oct 6, 2025
b89d8d2
Merge branch 'v17/feature/minimalistic-tree-load-more' into v17/featu…
nielslyngsoe Oct 6, 2025
4767314
fix router getActivePath
nielslyngsoe Oct 6, 2025
d4f4835
make expand open the collection
nielslyngsoe Oct 6, 2025
13435cb
setTargetTakeSize to low when Collection parent
nielslyngsoe Oct 6, 2025
8e386fa
expose typeUnique
nielslyngsoe Oct 7, 2025
0b02ea9
fix opening collection
nielslyngsoe Oct 7, 2025
d84d289
remove log
nielslyngsoe Oct 7, 2025
c454261
active manager
nielslyngsoe Oct 7, 2025
65acc73
export
nielslyngsoe Oct 7, 2025
e581295
impl active manager
nielslyngsoe Oct 7, 2025
b8a564a
prepare for search param redirects
nielslyngsoe Oct 7, 2025
810cc55
fixed collapse feature
nielslyngsoe Oct 7, 2025
77263e3
set routes to undefined
nielslyngsoe Oct 7, 2025
e081cca
preserveQuery
nielslyngsoe Oct 7, 2025
2fefcc6
ensureSlash
nielslyngsoe Oct 7, 2025
a53a7ee
make a hard redirect for collections
nielslyngsoe Oct 7, 2025
f6df50f
Merge branch 'v17/dev' into v17/feature/hide-expand-children-of-colle…
nielslyngsoe Oct 7, 2025
40db76b
only if anscenstors are present in data.
nielslyngsoe Oct 7, 2025
fc5ef70
not full match anyway
nielslyngsoe Oct 7, 2025
60e8003
only forceShow on hasCollection
nielslyngsoe Oct 7, 2025
a9d5dbb
remove umb-section-sidebar-context-menu
nielslyngsoe Oct 7, 2025
83129b8
rename to isMenu
nielslyngsoe Oct 7, 2025
1873968
Merge branch 'v17/dev' into v17/feature/hide-expand-children-of-colle…
nielslyngsoe Oct 7, 2025
efc7cde
Merge branch 'v17/dev' into v17/feature/hide-expand-children-of-colle…
nielslyngsoe Oct 8, 2025
4ecf5f9
Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/wor…
nielslyngsoe Oct 8, 2025
ecb868f
Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/tre…
nielslyngsoe Oct 8, 2025
7e16832
Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/ite…
nielslyngsoe Oct 8, 2025
9557ff8
Fixed TS linting errors
leekelleher Oct 8, 2025
81a8d74
Fixed TS linting errors
leekelleher Oct 8, 2025
c18952a
Merge branch 'v17/dev' into v17/feature/hide-expand-children-of-colle…
leekelleher Oct 8, 2025
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 @@ -115,7 +115,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
private _hasRootGroups = false;

@state()
private _routes: UmbRoute[] = [];
private _routes?: UmbRoute[];

@state()
private _tabs?: Array<UmbPropertyTypeContainerMergedModel>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class UmbRouteContext extends UmbContextBase {
return this.#basePath.getValue();
}
getActivePath() {
return this.getBasePath() + '/' + this.#activeLocalPath;
return this.getBasePath() + '/' + this.#activeLocalPath.getValue();
}

public registerModal(registration: UmbModalRouteRegistration) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './tree-active-manager.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { expect } from '@open-wc/testing';
import { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import { customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controller-api';
import { UmbTreeItemActiveManager } from './tree-active-manager';

@customElement('test-my-controller-host')
class UmbTestControllerHostElement extends UmbControllerHostElementMixin(HTMLElement) {}

describe('UmbTreeItemActiveManager', () => {
let manager: UmbTreeItemActiveManager;
const item = { entityType: 'test', unique: '123' };
const item2 = { entityType: 'test', unique: '456' };

beforeEach(() => {
const hostElement = new UmbTestControllerHostElement();
manager = new UmbTreeItemActiveManager(hostElement);
});

describe('Public API', () => {
describe('properties', () => {
it('has an active property', () => {
expect(manager).to.have.property('active').to.be.an.instanceOf(Observable);
});
});

describe('methods', () => {
it('has an isActive method', () => {
expect(manager).to.have.property('isActive').that.is.a('function');
});
});
});

describe('isActive', () => {
it('checks if an item is active', (done) => {
manager.setActive([item]);
const isActive = manager.isActive(item);
expect(isActive).to.be.an.instanceOf(Observable);
manager.isActive(item).subscribe((value) => {
expect(value).to.be.true;
done();
});
});
});

describe('setActive & getActive', () => {
it('sets and gets the active state', () => {
const active = [item];
manager.setActive(active);
expect(manager.getActive()).to.deep.equal(active);
});
});

describe('removeActiveIfMatch', () => {
it('removes the active state', () => {
const active = [item];
manager.setActive(active);
manager.removeActiveIfMatch(active);
expect(manager.getActive()).to.deep.equal([]);
});
it('does not remove the active state if it does not match', () => {
const active = [item];
manager.setActive(active);
manager.removeActiveIfMatch([item2]);
expect(manager.getActive()).to.deep.equal([item]);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { UmbArrayState, type Observable } from '@umbraco-cms/backoffice/observable-api';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';

/**
* Manages the expansion state of a tree
* @exports
* @class UmbTreeItemActiveManager
* @augments {UmbControllerBase}
*/
export class UmbTreeItemActiveManager extends UmbControllerBase {
#active = new UmbArrayState<UmbEntityModel>([], (x) => x.entityType + x.unique);
readonly active = this.#active.asObservable();

/**
* Checks if an entity is active
* @param {UmbEntityModel} entity The entity to check
* @returns {Observable<boolean>} True if the entity is active
* @memberof UmbTreeItemActiveManager
*/
isActive(entity: UmbEntityModel): Observable<boolean> {
return this.#active.asObservablePart((entities) => {
const index = entities.findIndex((e) => e.entityType === entity.entityType && e.unique === entity.unique);
return index === entities.length;
});
}

/**
* Checks if an descendant entity is active
* @param {UmbEntityModel} entity The entity to check
* @returns {Observable<boolean>} True if a descendant entity is active
* @memberof UmbTreeItemActiveManager
*/
hasActiveDescendants(entity: UmbEntityModel): Observable<boolean> {
return this.#active.asObservablePart((entities) => {
const index = entities.findIndex((e) => e.entityType === entity.entityType && e.unique === entity.unique);
return index > -1 && index < entities.length - 1;
});
}
/**
* Checks if an descendant entity is active
* @param {UmbEntityModel} entity The entity to check
* @returns {boolean} True if a descendant entity is active
* @memberof UmbTreeItemActiveManager
*/
getHasActiveDescendants(entity: UmbEntityModel): boolean {
return this.#active.getValue().some((e) => e.entityType === entity.entityType && e.unique === entity.unique);
}

/**
* Sets the active chain state
* @param {Array<UmbEntityModel>} activeChain The active entries.
* @memberof UmbTreeItemActiveManager
* @returns {void}
*/
setActive(activeChain: Array<UmbEntityModel>): void {
this.#active.setValue(activeChain);
}

/**
* Sets the active chain state
* @param {Array<UmbEntityModel>} activeChain The active entries.
* @memberof UmbTreeItemActiveManager
* @returns {void}
*/
removeActiveIfMatch(activeChain: Array<UmbEntityModel>): void {
const currentChain = this.#active.getValue();
// test if new chain and current chain matches:
// Test length for a start:
if (activeChain.length !== currentChain.length) return;
// test content next:
for (let i = 0; i < activeChain.length; i++) {
if (
activeChain[i].entityType !== currentChain[i].entityType ||
activeChain[i].unique !== currentChain[i].unique
) {
return;
}
}
// TODO: Problem!!!! we are removing the active state, but something is loading that wants to add it...
// then we can remove it all:
this.#active.setValue([]);
}

/**
* Gets the expansion state
* @memberof UmbTreeItemActiveManager
* @returns {Array<UmbEntityModel>} The expansion state
*/
getActive(): Array<UmbEntityModel> {
return this.#active.getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { UmbDeprecation, UmbSelectionManager, debounce } from '@umbraco-cms/back
import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbTreeItemActiveManager } from '../active-manager/tree-active-manager.js';

export class UmbDefaultTreeContext<
TreeItemType extends UmbTreeItemModel,
Expand Down Expand Up @@ -53,6 +54,8 @@ export class UmbDefaultTreeContext<
targetPaginationManager: this.targetPagination,
});

readonly activeManager = new UmbTreeItemActiveManager(this);

#manifest?: ManifestTree;
#repository?: UmbTreeRepository<TreeItemType, TreeRootType>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export class UmbDefaultTreeElement extends UmbLitElement {
@property({ type: Boolean, attribute: false })
foldersOnly?: boolean = false;

@property({ type: Boolean, attribute: false })
isMenu?: boolean = false;

@property({ attribute: false })
selectableFilter: (item: UmbTreeItemModelBase) => boolean = () => true;

Expand Down Expand Up @@ -165,7 +168,11 @@ export class UmbDefaultTreeElement extends UmbLitElement {
return html`
<umb-tree-item
.entityType=${this._treeRoot.entityType}
.props=${{ hideActions: this.hideTreeItemActions, item: this._treeRoot }}></umb-tree-item>
.props=${{
hideActions: this.hideTreeItemActions,
item: this._treeRoot,
isMenu: this.isMenu,
}}></umb-tree-item>
`;
}

Expand All @@ -180,7 +187,7 @@ export class UmbDefaultTreeElement extends UmbLitElement {
(item) => html`
<umb-tree-item
.entityType=${item.entityType}
.props=${{ hideActions: this.hideTreeItemActions, item }}></umb-tree-item>
.props=${{ hideActions: this.hideTreeItemActions, item, isMenu: this.isMenu }}></umb-tree-item>
`,
)}
${this.#renderLoadNextButton()}
Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './active-manager/index.js';
export * from './components/index.js';
export * from './constants.js';
export * from './data/index.js';
Expand Down
Loading
Loading