diff --git a/webapp/packages/administration/src/Administration/Administration.tsx b/webapp/packages/administration/src/Administration/Administration.tsx index 1d931b0abe..52ee816541 100644 --- a/webapp/packages/administration/src/Administration/Administration.tsx +++ b/webapp/packages/administration/src/Administration/Administration.tsx @@ -64,10 +64,14 @@ const administrationStyles = composes( type Props = { activeItem: string | null; + activeItemSub: string | null; + activeItemSubParam: string | null; onItemSelect(name: string): void; } -export const Administration = observer(function Administration({ activeItem, onItemSelect }: Props) { +export const Administration = observer(function Administration({ + activeItem, activeItemSub, activeItemSubParam, onItemSelect, +}: Props) { const controller = useController(AdministrationController); return styled(useStyles(verticalTabStyles, administrationStyles, tabsStyles))( @@ -81,7 +85,11 @@ export const Administration = observer(function Administration({ activeItem, onI - + diff --git a/webapp/packages/administration/src/Administration/ItemContent.tsx b/webapp/packages/administration/src/Administration/ItemContent.tsx index 6aa8e52069..94b699b61b 100644 --- a/webapp/packages/administration/src/Administration/ItemContent.tsx +++ b/webapp/packages/administration/src/Administration/ItemContent.tsx @@ -14,9 +14,11 @@ import { AdministrationItemService } from '../AdministrationItem/AdministrationI type Props = { activeItemName: string | null; + activeItemSub: string | null; + activeItemSubParam: string | null; } -export const ItemContent = observer(function ItemContent({ activeItemName }: Props) { +export const ItemContent = observer(function ItemContent({ activeItemName, activeItemSub, activeItemSubParam }: Props) { const administrationItemService = useService(AdministrationItemService); if (!activeItemName) { @@ -29,6 +31,15 @@ export const ItemContent = observer(function ItemContent({ activeItemName }: Pro return null; } + if (activeItemSub) { + const sub = administrationItemService.getItemSub(item, activeItemSub); + if (sub) { + const Component = sub.getComponent(); + + return ; + } + } + const Component = item.getContentComponent(); return ; diff --git a/webapp/packages/administration/src/AdministrationItem/AdministrationItemService.ts b/webapp/packages/administration/src/AdministrationItem/AdministrationItemService.ts index e2988ddec6..0a4e295f3f 100644 --- a/webapp/packages/administration/src/AdministrationItem/AdministrationItemService.ts +++ b/webapp/packages/administration/src/AdministrationItem/AdministrationItemService.ts @@ -10,7 +10,7 @@ import { observable } from 'mobx'; import { injectable } from '@dbeaver/core/di'; -import { IAdministrationItem, IAdministrationItemOptions } from './IAdministrationItem'; +import { IAdministrationItem, IAdministrationItemOptions, IAdministrationItemSubItem } from './IAdministrationItem'; @injectable() export class AdministrationItemService { @@ -33,6 +33,15 @@ export class AdministrationItemService { return item; } + getItemSub(item: IAdministrationItem, subItem: string): IAdministrationItemSubItem | null { + const sub = item.sub.find(sub => sub.name === subItem); + if (!sub) { + return null; + } + + return sub; + } + create(options: IAdministrationItemOptions) { if (this.items.some(item => item.name === options.name)) { throw new Error(`Administration item "${options.name}" already exists`); @@ -40,15 +49,27 @@ export class AdministrationItemService { const item: IAdministrationItem = { ...options, + sub: options.sub || [], order: options.order || Number.MAX_SAFE_INTEGER, }; this.items.push(item); } - async activate(name: string) { + async activate(name: string, itemSub: string | null, param: string | null) { const item = this.getItem(name); - if (item && item.onActivate) { + if (!item) { + return; + } + + if (item.onActivate) { await item.onActivate(); } + + if (itemSub) { + const sub = this.getItemSub(item, itemSub); + if (sub && sub.onActivate) { + await sub.onActivate(param); + } + } } } diff --git a/webapp/packages/administration/src/AdministrationItem/IAdministrationItem.ts b/webapp/packages/administration/src/AdministrationItem/IAdministrationItem.ts index f0065deba6..707ee5a71c 100644 --- a/webapp/packages/administration/src/AdministrationItem/IAdministrationItem.ts +++ b/webapp/packages/administration/src/AdministrationItem/IAdministrationItem.ts @@ -20,11 +20,26 @@ export type AdministrationItemContentProps = { } export type AdministrationItemContentComponent = React.FunctionComponent +export type AdministrationItemSubContentProps = { + item: IAdministrationItem; + sub: IAdministrationItemSubItem; + param: string | null; +} +export type AdministrationItemSubContentComponent = React.FunctionComponent + export type AdministrationItemEvent = () => Promise | void +export type AdministrationItemSubEvent = (param: string | null) => Promise | void + +export interface IAdministrationItemSubItem { + name: string; + getComponent(): AdministrationItemSubContentComponent; + onActivate?: AdministrationItemSubEvent; +} export interface IAdministrationItemOptions { name: string; order?: number; + sub?: IAdministrationItemSubItem[]; getDrawerComponent(): AdministrationItemDrawerComponent; getContentComponent(): AdministrationItemContentComponent; onActivate?: AdministrationItemEvent; @@ -32,4 +47,5 @@ export interface IAdministrationItemOptions { export interface IAdministrationItem extends IAdministrationItemOptions { order: number; + sub: IAdministrationItemSubItem[]; } diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx index 07d7224b65..6bc5dd8c4e 100644 --- a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx @@ -32,7 +32,12 @@ export const AdministrationScreen = observer(function AdministrationScreen() { return ( <> - + ); }); diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts index f51b31194e..ad2bf813f6 100644 --- a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts @@ -21,6 +21,8 @@ export class AdministrationScreenService extends Bootstrap { static screenName = 'administration' static itemRouteName = 'administration.item' + static itemSubRouteName = 'administration.item.sub' + static itemSubParamRouteName = 'administration.item.sub.param' @computed get activeItem(): string | null { if (!this.screenService.isActive(AdministrationScreenService.screenName)) { @@ -29,6 +31,20 @@ export class AdministrationScreenService extends Bootstrap { return this.routerService.params.item || this.administrationItemService.getDefaultItem(); } + @computed get activeItemSub(): string | null { + if (!this.screenService.isActive(AdministrationScreenService.screenName)) { + return null; + } + return this.routerService.params.sub || null; + } + + @computed get activeItemSubParam(): string | null { + if (!this.screenService.isActive(AdministrationScreenService.screenName)) { + return null; + } + return this.routerService.params.param || null; + } + constructor( private screenService: ScreenService, private routerService: RouterService, @@ -48,6 +64,14 @@ export class AdministrationScreenService extends Bootstrap { this.routerService.router.navigate(AdministrationScreenService.itemRouteName, { item }); } + navigateToItemSub(item: string, sub: string, param?: string) { + if (!param) { + this.routerService.router.navigate(AdministrationScreenService.itemSubRouteName, { item, sub }); + return; + } + this.routerService.router.navigate(AdministrationScreenService.itemSubParamRouteName, { item, sub, param }); + } + bootstrap() { this.screenService.create({ name: AdministrationScreenService.screenName, @@ -60,6 +84,14 @@ export class AdministrationScreenService extends Bootstrap { name: AdministrationScreenService.itemRouteName, path: '/:item', }, + { + name: AdministrationScreenService.itemSubRouteName, + path: '/:sub', + }, + { + name: AdministrationScreenService.itemSubParamRouteName, + path: '/:param', + }, ], component: AdministrationScreen, onActivate: this.handleActivate.bind(this), @@ -73,7 +105,7 @@ export class AdministrationScreenService extends Bootstrap { } if (this.activeItem) { - await this.administrationItemService.activate(this.activeItem); + await this.administrationItemService.activate(this.activeItem, this.activeItemSub, this.activeItemSubParam); } } }