move routing logic into the view manager

This commit is contained in:
Mads Rasmussen
2023-11-29 11:33:37 +01:00
parent cc417e2ffe
commit 8df817dbde
4 changed files with 51 additions and 54 deletions

View File

@@ -1,8 +1,13 @@
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api';
import { UmbExtensionsManifestInitializer, createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
import { ManifestCollectionView, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbArrayState, UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
import { UmbRoute } from '@umbraco-cms/backoffice/router';
export interface UmbCollectionViewManagerConfig {
defaultViewAlias: string;
}
export class UmbCollectionViewManager extends UmbBaseController {
#views = new UmbArrayState<ManifestCollectionView>([], (x) => x.alias);
@@ -11,12 +16,18 @@ export class UmbCollectionViewManager extends UmbBaseController {
#currentView = new UmbObjectState<ManifestCollectionView | undefined>(undefined);
public readonly currentView = this.#currentView.asObservable();
#routes = new UmbArrayState<UmbRoute>([], (x) => x.path);
public readonly routes = this.#routes.asObservable();
#rootPathname = new UmbStringState('');
public readonly rootPathname = this.#rootPathname.asObservable();
constructor(host: UmbControllerHost) {
#defaultViewAlias?: string;
constructor(host: UmbControllerHost, config: UmbCollectionViewManagerConfig) {
super(host);
this.#defaultViewAlias = config.defaultViewAlias;
this.#observeViews();
// TODO: hack - we need to figure out how to get the "parent path" from the router
@@ -47,25 +58,36 @@ export class UmbCollectionViewManager extends UmbBaseController {
#observeViews() {
return new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'collectionView', null, (views) => {
this.#views.next(views.map((view) => view.manifest));
this.#initCurrentView();
const manifests = views.map((view) => view.manifest);
this.#views.next(manifests);
this.#createRoutes(manifests);
});
}
#initCurrentView() {
// if we already have a current view, don't set it again
if (this.#currentView.getValue()) return;
#createRoutes(views: ManifestCollectionView[] | null) {
let routes: Array<UmbRoute> = [];
const currentUrl = new URL(window.location.href);
const lastPathSegment = currentUrl.pathname.split('/').pop();
const views = this.#views.getValue();
const viewMatch = views.find((view) => view.meta.pathName === lastPathSegment);
if (views) {
// find the default view from the config. If it doesn't exist, use the first view
const defaultView = views.find((view) => view.alias === this.#defaultViewAlias);
const fallbackView = defaultView?.meta.pathName || views[0].meta.pathName;
/* TODO: Find a way to figure out which layout it starts with and set _currentLayout to that instead of [0]. eg. '/table'
For document, media and members this will come as part of a data type configuration, but in other cases "users" we should find another way.
This should only happen if the current layout is not set in the URL.
*/
const currentView = viewMatch || views[0];
this.setCurrentView(currentView);
routes = views.map((view) => {
return {
path: `${view.meta.pathName}`,
component: () => createExtensionElement(view),
setup: () => {
this.setCurrentView(view);
},
};
});
routes.push({
path: '',
redirectTo: fallbackView,
});
}
this.#routes.next(routes);
}
}

View File

@@ -41,16 +41,17 @@ export class UmbDefaultCollectionContext<ItemType = any, FilterModelType extends
public readonly pagination = new UmbPaginationManager();
public readonly selection = new UmbSelectionManager();
public readonly view = new UmbCollectionViewManager(this);
public readonly view;
constructor(host: UmbControllerHostElement, config: UmbCollectionConfiguration = { pageSize: 50 }) {
super(host);
this.view = new UmbCollectionViewManager(this, { defaultViewAlias: config.defaultViewAlias });
this.#configure(config);
// listen for page changes on the pagination manager
this.pagination.addEventListener(UmbChangeEvent.TYPE, this.#onPageChange);
this.#configure(config);
this.provideContext(UMB_COLLECTION_CONTEXT, this);
}

View File

@@ -1,12 +1,7 @@
import { UMB_COLLECTION_CONTEXT, UmbDefaultCollectionContext } from './collection-default.context.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
import {
umbExtensionsRegistry,
type ManifestCollectionView,
UmbBackofficeManifestKind,
} from '@umbraco-cms/backoffice/extension-registry';
import { umbExtensionsRegistry, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
@@ -33,41 +28,19 @@ export class UmbCollectionDefaultElement extends UmbLitElement {
constructor() {
super();
this.#observeCollectionViews();
this.consumeContext(UMB_COLLECTION_CONTEXT, (instance) => {
this.#collectionContext = instance;
this.#observeCollectionViews();
this.#observeCollectionRoutes();
});
}
#observeCollectionViews() {
#observeCollectionRoutes() {
if (!this.#collectionContext) return;
this.observe(this.#collectionContext.view.views, (views) => {
this.#createRoutes(views);
this.observe(this.#collectionContext.view.routes, (routes) => {
this._routes = routes;
}),
'umbCollectionViewsObserver';
}
#createRoutes(views: ManifestCollectionView[] | null) {
this._routes = [];
if (views) {
this._routes = views.map((view) => {
return {
path: `${view.meta.pathName}`,
component: () => createExtensionElement(view),
};
});
}
this._routes.push({
path: '',
redirectTo: views?.[0]?.meta.pathName ?? '/',
});
this.requestUpdate();
'umbCollectionRoutesObserver';
}
render() {

View File

@@ -1,4 +1,5 @@
import { UmbUserCollectionFilterModel, UmbUserDetailModel } from '../types.js';
import { UMB_COLLECTION_VIEW_USER_GRID } from './views/index.js';
import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
import { UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
@@ -8,7 +9,7 @@ export class UmbUserCollectionContext extends UmbDefaultCollectionContext<
UmbUserCollectionFilterModel
> {
constructor(host: UmbControllerHostElement) {
super(host, { pageSize: 50 });
super(host, { pageSize: 50, defaultViewAlias: UMB_COLLECTION_VIEW_USER_GRID });
}
/**