mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat(core-administration): configuration wizard pages API
CB-243
This commit is contained in:
@@ -66,6 +66,7 @@ const administrationStyles = composes(
|
||||
);
|
||||
|
||||
type Props = {
|
||||
configurationWizard: boolean;
|
||||
activeItem: string | null;
|
||||
activeItemSub: string | null;
|
||||
activeItemSubParam: string | null;
|
||||
@@ -73,17 +74,24 @@ type Props = {
|
||||
}
|
||||
|
||||
export const Administration = observer(function Administration({
|
||||
activeItem, activeItemSub, activeItemSubParam, onItemSelect,
|
||||
configurationWizard, activeItem, activeItemSub, activeItemSubParam, onItemSelect,
|
||||
}: Props) {
|
||||
const controller = useController(AdministrationController);
|
||||
const items = controller.getItems(configurationWizard);
|
||||
|
||||
return styled(useStyles(verticalTabStyles, administrationStyles, tabsStyles))(
|
||||
<container as='div'>
|
||||
<TabsState currentTabId={activeItem} orientation='vertical'>
|
||||
<drawer as='div'>
|
||||
<TabList aria-label="Administration items">
|
||||
{controller.items.map(item => (
|
||||
<DrawerItem key={item.name} item={item} onSelect={onItemSelect} style={[verticalTabStyles, tabsStyles]} />
|
||||
{items.map(item => (
|
||||
<DrawerItem
|
||||
key={item.name}
|
||||
item={item}
|
||||
onSelect={onItemSelect}
|
||||
configurationWizard={configurationWizard}
|
||||
style={[verticalTabStyles, tabsStyles]}
|
||||
/>
|
||||
))}
|
||||
</TabList>
|
||||
</drawer>
|
||||
@@ -92,6 +100,7 @@ export const Administration = observer(function Administration({
|
||||
activeItemName={activeItem}
|
||||
activeItemSub={activeItemSub}
|
||||
activeItemSubParam={activeItemSubParam}
|
||||
configurationWizard={configurationWizard}
|
||||
/>
|
||||
</content>
|
||||
</TabsState>
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
|
||||
import { AdministrationItemService } from '../AdministrationItem/AdministrationItemService';
|
||||
import { filterConfigurationWizard } from '../AdministrationItem/filterConfigurationWizard';
|
||||
import { orderAdministrationItems } from '../AdministrationItem/orderAdministrationItems';
|
||||
|
||||
@injectable()
|
||||
export class AdministrationController {
|
||||
@computed get items() {
|
||||
getItems(configurationWizard: boolean) {
|
||||
return this.administrationItemService
|
||||
.items
|
||||
.concat()
|
||||
.sort((a, b) => a.order - b.order);
|
||||
.filter(filterConfigurationWizard(configurationWizard))
|
||||
.sort(orderAdministrationItems);
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -10,8 +10,10 @@ import { observer } from 'mobx-react';
|
||||
|
||||
import { AdministrationItemDrawerProps } from '../AdministrationItem/IAdministrationItem';
|
||||
|
||||
export const DrawerItem = observer(function DrawerItem({ item, onSelect, style }: AdministrationItemDrawerProps) {
|
||||
export const DrawerItem = observer(function DrawerItem({
|
||||
item, onSelect, style, configurationWizard,
|
||||
}: AdministrationItemDrawerProps) {
|
||||
const Component = item.getDrawerComponent();
|
||||
|
||||
return <Component item={item} onSelect={onSelect} style={style}/>;
|
||||
return <Component item={item} onSelect={onSelect} configurationWizard={configurationWizard} style={style}/>;
|
||||
});
|
||||
|
||||
@@ -16,16 +16,22 @@ type Props = {
|
||||
activeItemName: string | null;
|
||||
activeItemSub: string | null;
|
||||
activeItemSubParam: string | null;
|
||||
configurationWizard: boolean;
|
||||
}
|
||||
|
||||
export const ItemContent = observer(function ItemContent({ activeItemName, activeItemSub, activeItemSubParam }: Props) {
|
||||
export const ItemContent = observer(function ItemContent({
|
||||
activeItemName,
|
||||
activeItemSub,
|
||||
activeItemSubParam,
|
||||
configurationWizard,
|
||||
}: Props) {
|
||||
const administrationItemService = useService(AdministrationItemService);
|
||||
|
||||
if (!activeItemName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const item = administrationItemService.getItem(activeItemName);
|
||||
const item = administrationItemService.getItem(activeItemName, configurationWizard);
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
@@ -36,11 +42,11 @@ export const ItemContent = observer(function ItemContent({ activeItemName, activ
|
||||
if (sub) {
|
||||
const Component = sub.getComponent();
|
||||
|
||||
return <Component item={item} sub={sub} param={activeItemSubParam} />;
|
||||
return <Component item={item} sub={sub} param={activeItemSubParam} configurationWizard={configurationWizard} />;
|
||||
}
|
||||
}
|
||||
|
||||
const Component = item.getContentComponent();
|
||||
|
||||
return <Component item={item} />;
|
||||
return <Component item={item} configurationWizard={configurationWizard} />;
|
||||
});
|
||||
|
||||
+30
-14
@@ -10,23 +10,32 @@ import { observable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
|
||||
import { IAdministrationItem, IAdministrationItemOptions, IAdministrationItemSubItem } from './IAdministrationItem';
|
||||
import { filterConfigurationWizard } from './filterConfigurationWizard';
|
||||
import {
|
||||
IAdministrationItem, IAdministrationItemOptions, IAdministrationItemSubItem, AdministrationItemType
|
||||
} from './IAdministrationItem';
|
||||
import { orderAdministrationItems } from './orderAdministrationItems';
|
||||
|
||||
@injectable()
|
||||
export class AdministrationItemService {
|
||||
@observable items: IAdministrationItem[] = []
|
||||
|
||||
getDefaultItem() {
|
||||
if (this.items.length === 0) {
|
||||
getDefaultItem(configurationWizard: boolean) {
|
||||
const items = this.items.filter(filterConfigurationWizard(configurationWizard));
|
||||
|
||||
console.log(configurationWizard, items);
|
||||
|
||||
if (items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return this.items
|
||||
.concat()
|
||||
.sort((a, b) => a.order - b.order)[0].name;
|
||||
return items.sort(orderAdministrationItems)[0].name;
|
||||
}
|
||||
|
||||
getItem(name: string): IAdministrationItem | null {
|
||||
const item = this.items.find(item => item.name === name);
|
||||
getItem(name: string, configurationWizard: boolean): IAdministrationItem | null {
|
||||
const item = this.items.find(item => (
|
||||
filterConfigurationWizard(configurationWizard)(item)
|
||||
&& item.name === name
|
||||
));
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
@@ -44,32 +53,39 @@ export class AdministrationItemService {
|
||||
}
|
||||
|
||||
create(options: IAdministrationItemOptions) {
|
||||
if (this.items.some(item => item.name === options.name)) {
|
||||
throw new Error(`Administration item "${options.name}" already exists`);
|
||||
const type = options.type === undefined ? AdministrationItemType.Administration : options.type;
|
||||
|
||||
if (this.items.some(item => item.name === options.name && (
|
||||
item.type === type
|
||||
|| item.type === AdministrationItemType.Default
|
||||
|| type === AdministrationItemType.Default
|
||||
))) {
|
||||
throw new Error(`Administration item "${options.name}" already exists in the same visibility scope`);
|
||||
}
|
||||
|
||||
const item: IAdministrationItem = {
|
||||
...options,
|
||||
type,
|
||||
sub: options.sub || [],
|
||||
order: options.order || Number.MAX_SAFE_INTEGER,
|
||||
};
|
||||
this.items.push(item);
|
||||
}
|
||||
|
||||
async activate(name: string, itemSub: string | null, param: string | null) {
|
||||
const item = this.getItem(name);
|
||||
async activate(name: string, itemSub: string | null, param: string | null, configurationWizard: boolean) {
|
||||
const item = this.getItem(name, configurationWizard);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.onActivate) {
|
||||
await item.onActivate();
|
||||
await item.onActivate(configurationWizard);
|
||||
}
|
||||
|
||||
if (itemSub) {
|
||||
const sub = this.getItemSub(item, itemSub);
|
||||
if (sub && sub.onActivate) {
|
||||
await sub.onActivate(param);
|
||||
await sub.onActivate(param, configurationWizard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,15 @@
|
||||
|
||||
import { Style } from '@cloudbeaver/core-theming';
|
||||
|
||||
export enum AdministrationItemType {
|
||||
Default,
|
||||
Administration,
|
||||
ConfigurationWizard
|
||||
}
|
||||
|
||||
export type AdministrationItemDrawerProps = {
|
||||
item: IAdministrationItem;
|
||||
configurationWizard: boolean;
|
||||
onSelect(id: string): void;
|
||||
style: Style[];
|
||||
}
|
||||
@@ -17,18 +24,20 @@ export type AdministrationItemDrawerComponent = React.FunctionComponent<Administ
|
||||
|
||||
export type AdministrationItemContentProps = {
|
||||
item: IAdministrationItem;
|
||||
configurationWizard: boolean;
|
||||
}
|
||||
export type AdministrationItemContentComponent = React.FunctionComponent<AdministrationItemContentProps>
|
||||
|
||||
export type AdministrationItemSubContentProps = {
|
||||
item: IAdministrationItem;
|
||||
sub: IAdministrationItemSubItem;
|
||||
configurationWizard: boolean;
|
||||
param: string | null;
|
||||
}
|
||||
export type AdministrationItemSubContentComponent = React.FunctionComponent<AdministrationItemSubContentProps>
|
||||
|
||||
export type AdministrationItemEvent = () => Promise<void> | void
|
||||
export type AdministrationItemSubEvent = (param: string | null) => Promise<void> | void
|
||||
export type AdministrationItemEvent = (configurationWizard: boolean) => Promise<void> | void
|
||||
export type AdministrationItemSubEvent = (param: string | null, configurationWizard: boolean) => Promise<void> | void
|
||||
|
||||
export interface IAdministrationItemSubItem {
|
||||
name: string;
|
||||
@@ -38,6 +47,8 @@ export interface IAdministrationItemSubItem {
|
||||
|
||||
export interface IAdministrationItemOptions {
|
||||
name: string;
|
||||
/** By default will be set to AdministrationItemType.Administration */
|
||||
type?: AdministrationItemType;
|
||||
order?: number;
|
||||
sub?: IAdministrationItemSubItem[];
|
||||
getDrawerComponent(): AdministrationItemDrawerComponent;
|
||||
@@ -46,6 +57,7 @@ export interface IAdministrationItemOptions {
|
||||
}
|
||||
|
||||
export interface IAdministrationItem extends IAdministrationItemOptions {
|
||||
type: AdministrationItemType;
|
||||
order: number;
|
||||
sub: IAdministrationItemSubItem[];
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { AdministrationItemType, IAdministrationItem } from './IAdministrationItem';
|
||||
|
||||
export function filterConfigurationWizard(configurationWizard: boolean) {
|
||||
return (item: IAdministrationItem) => (configurationWizard
|
||||
? item.type !== AdministrationItemType.Administration
|
||||
: item.type !== AdministrationItemType.ConfigurationWizard);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { IAdministrationItem } from './IAdministrationItem';
|
||||
|
||||
export function orderAdministrationItems(itemA: IAdministrationItem, itemB: IAdministrationItem) {
|
||||
return itemA.order - itemB.order;
|
||||
}
|
||||
@@ -33,6 +33,7 @@ export const AdministrationScreen = observer(function AdministrationScreen() {
|
||||
<>
|
||||
<AdministrationTopAppBar />
|
||||
<Administration
|
||||
configurationWizard={false}
|
||||
activeItem={administrationScreenService.activeItem}
|
||||
activeItemSub={administrationScreenService.activeItemSub}
|
||||
activeItemSubParam={administrationScreenService.activeItemSubParam}
|
||||
|
||||
+73
-10
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed } from 'mobx';
|
||||
import { computed, observable } from 'mobx';
|
||||
|
||||
import { injectable, Bootstrap } from '@cloudbeaver/core-di';
|
||||
import { PermissionsService } from '@cloudbeaver/core-root';
|
||||
@@ -15,6 +15,7 @@ import { ScreenService, RouterService } from '@cloudbeaver/core-routing';
|
||||
import { AdministrationItemService } from '../AdministrationItem/AdministrationItemService';
|
||||
import { EAdminPermission } from '../EAdminPermission';
|
||||
import { AdministrationScreen } from './AdministrationScreen';
|
||||
import { ConfigurationWizardScreen } from './ConfigurationWizardScreen';
|
||||
|
||||
@injectable()
|
||||
export class AdministrationScreenService extends Bootstrap {
|
||||
@@ -24,22 +25,29 @@ export class AdministrationScreenService extends Bootstrap {
|
||||
static itemSubRouteName = 'administration.item.sub'
|
||||
static itemSubParamRouteName = 'administration.item.sub.param'
|
||||
|
||||
static setupName = 'setup'
|
||||
static setupItemRouteName = 'setup.item'
|
||||
static setupItemSubRouteName = 'setup.item.sub'
|
||||
static setupItemSubParamRouteName = 'setup.item.sub.param'
|
||||
|
||||
@observable configurationWizard = false;
|
||||
|
||||
@computed get activeItem(): string | null {
|
||||
if (!this.screenService.isActive(AdministrationScreenService.screenName)) {
|
||||
if (!this.isAdministrationRouteActive()) {
|
||||
return null;
|
||||
}
|
||||
return this.routerService.params.item || this.administrationItemService.getDefaultItem();
|
||||
return this.routerService.params.item || this.administrationItemService.getDefaultItem(this.configurationWizard);
|
||||
}
|
||||
|
||||
@computed get activeItemSub(): string | null {
|
||||
if (!this.screenService.isActive(AdministrationScreenService.screenName)) {
|
||||
if (!this.isAdministrationRouteActive()) {
|
||||
return null;
|
||||
}
|
||||
return this.routerService.params.sub || null;
|
||||
}
|
||||
|
||||
@computed get activeItemSubParam(): string | null {
|
||||
if (!this.screenService.isActive(AdministrationScreenService.screenName)) {
|
||||
if (!this.isAdministrationRouteActive()) {
|
||||
return null;
|
||||
}
|
||||
return this.routerService.params.param || null;
|
||||
@@ -56,19 +64,35 @@ export class AdministrationScreenService extends Bootstrap {
|
||||
}
|
||||
|
||||
navigateToRoot() {
|
||||
this.routerService.router.navigate(AdministrationScreenService.screenName);
|
||||
if (this.configurationWizard) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.setupName);
|
||||
} else {
|
||||
this.routerService.router.navigate(AdministrationScreenService.screenName);
|
||||
}
|
||||
}
|
||||
|
||||
navigateToItem(item: string) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemRouteName, { item });
|
||||
if (this.configurationWizard) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.setupItemRouteName, { item });
|
||||
} else {
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemRouteName, { item });
|
||||
}
|
||||
}
|
||||
|
||||
navigateToItemSub(item: string, sub: string, param?: string) {
|
||||
if (!param) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemSubRouteName, { item, sub });
|
||||
if (this.configurationWizard) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.setupItemSubRouteName, { item, sub });
|
||||
} else {
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemSubRouteName, { item, sub });
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemSubParamRouteName, { item, sub, param });
|
||||
if (this.configurationWizard) {
|
||||
this.routerService.router.navigate(AdministrationScreenService.setupItemSubParamRouteName, { item, sub, param });
|
||||
} else {
|
||||
this.routerService.router.navigate(AdministrationScreenService.itemSubParamRouteName, { item, sub, param });
|
||||
}
|
||||
}
|
||||
|
||||
register() {
|
||||
@@ -95,6 +119,30 @@ export class AdministrationScreenService extends Bootstrap {
|
||||
component: AdministrationScreen,
|
||||
onActivate: this.handleActivate.bind(this),
|
||||
});
|
||||
|
||||
this.screenService.create({
|
||||
name: AdministrationScreenService.setupName,
|
||||
routes: [
|
||||
{
|
||||
name: AdministrationScreenService.setupName,
|
||||
path: '/setup',
|
||||
},
|
||||
{
|
||||
name: AdministrationScreenService.setupItemRouteName,
|
||||
path: '/:item',
|
||||
},
|
||||
{
|
||||
name: AdministrationScreenService.setupItemSubRouteName,
|
||||
path: '/:sub',
|
||||
},
|
||||
{
|
||||
name: AdministrationScreenService.setupItemSubParamRouteName,
|
||||
path: '/:param',
|
||||
},
|
||||
],
|
||||
component: ConfigurationWizardScreen,
|
||||
onActivate: this.handleActivate.bind(this),
|
||||
});
|
||||
}
|
||||
|
||||
load(): void | Promise<void> { }
|
||||
@@ -105,8 +153,23 @@ export class AdministrationScreenService extends Bootstrap {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: for development purposes only, must be removed
|
||||
if (this.screenService.isActive(AdministrationScreenService.setupName)) {
|
||||
this.configurationWizard = true;
|
||||
}
|
||||
|
||||
if (this.activeItem) {
|
||||
await this.administrationItemService.activate(this.activeItem, this.activeItemSub, this.activeItemSubParam);
|
||||
await this.administrationItemService.activate(
|
||||
this.activeItem,
|
||||
this.activeItemSub,
|
||||
this.activeItemSubParam,
|
||||
this.configurationWizard
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private isAdministrationRouteActive() {
|
||||
return this.screenService.isActive(AdministrationScreenService.screenName)
|
||||
|| this.screenService.isActive(AdministrationScreenService.setupName);
|
||||
}
|
||||
}
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { Translate } from '@cloudbeaver/core-localization';
|
||||
import { usePermission } from '@cloudbeaver/core-root';
|
||||
|
||||
import { Administration } from '../Administration/Administration';
|
||||
import { EAdminPermission } from '../EAdminPermission';
|
||||
import { AdministrationScreenService } from './AdministrationScreenService';
|
||||
import { AdministrationTopAppBar } from './AdministrationTopAppBar/AdministrationTopAppBar';
|
||||
|
||||
export const ConfigurationWizardScreen = observer(function ConfigurationWizardScreen() {
|
||||
const administrationScreenService = useService(AdministrationScreenService);
|
||||
if (!usePermission(EAdminPermission.admin)) {
|
||||
return <Translate token='root_permission_denied'/>;
|
||||
}
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(item: string) => administrationScreenService.navigateToItem(item),
|
||||
[administrationScreenService]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AdministrationTopAppBar />
|
||||
<Administration
|
||||
configurationWizard={true}
|
||||
activeItem={administrationScreenService.activeItem}
|
||||
activeItemSub={administrationScreenService.activeItemSub}
|
||||
activeItemSubParam={administrationScreenService.activeItemSubParam}
|
||||
onItemSelect={handleSelect}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
+2
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { AdministrationItemService, AdministrationScreenService } from '@cloudbeaver/core-administration';
|
||||
import { AdministrationItemService, AdministrationScreenService, AdministrationItemType } from '@cloudbeaver/core-administration';
|
||||
import { injectable, Bootstrap } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
|
||||
@@ -30,6 +30,7 @@ export class ConnectionsAdministrationService extends Bootstrap {
|
||||
register() {
|
||||
this.administrationItemService.create({
|
||||
name: 'connections',
|
||||
type: AdministrationItemType.Default,
|
||||
order: 2,
|
||||
sub: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user