diff --git a/webapp/packages/administration/src/AdministrationMenuService.ts b/webapp/packages/administration/src/AdministrationMenuService.ts index 650b843273..629be48fb4 100644 --- a/webapp/packages/administration/src/AdministrationMenuService.ts +++ b/webapp/packages/administration/src/AdministrationMenuService.ts @@ -6,33 +6,46 @@ * you may not use this file except in compliance with the License. */ -import { SettingsMenuService } from '@dbeaver/core/app'; -import { injectable } from '@dbeaver/core/di'; +import { SettingsMenuService, ScreenService, AppScreenService } from '@dbeaver/core/app'; +import { injectable, Bootstrap } from '@dbeaver/core/di'; import { PermissionsService } from '@dbeaver/core/root'; import { AdministrationScreenService } from './AdministrationScreen/AdministrationScreenService'; - -export const ADMINISTRATION_PERMISSION = 'admin'; +import { EAdminPermission } from './EAdminPermission'; @injectable() -export class AdministrationMenuService { - static administrationMenuToken = 'administrationMenu'; +export class AdministrationMenuService extends Bootstrap { constructor( private settingsMenuService: SettingsMenuService, private permissionsService: PermissionsService, + private screenService: ScreenService, private administrationScreenService: AdministrationScreenService, - ) { } + private appScreenService: AppScreenService + ) { + super(); + } - register() { + bootstrap() { this.settingsMenuService.addMenuItem( SettingsMenuService.settingsMenuToken, { - id: AdministrationMenuService.administrationMenuToken, + id: 'administrationMenuEnter', order: 0, - isHidden: () => !this.permissionsService.has(ADMINISTRATION_PERMISSION), + isHidden: () => !this.permissionsService.has(EAdminPermission.admin) + || this.screenService.isActive(AdministrationScreenService.screenName), title: 'administration_menu_enter', onClick: () => this.administrationScreenService.navigateToRoot(), } ); + this.settingsMenuService.addMenuItem( + SettingsMenuService.settingsMenuToken, + { + id: 'administrationMenuBack', + order: 0, + isHidden: () => !this.screenService.isActive(AdministrationScreenService.screenName), + title: 'administration_menu_back', + onClick: () => this.appScreenService.navigateToRoot(), + } + ); } } diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx index e8eb7f588f..6cf20e05bc 100644 --- a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreen.tsx @@ -6,6 +6,21 @@ * you may not use this file except in compliance with the License. */ -export function AdministrationScreen() { - return <>Hello; -} +import { observer } from 'mobx-react'; + +import { usePermission } from '@dbeaver/core/root'; + +import { EAdminPermission } from '../EAdminPermission'; +import { AdministrationTopAppBar } from './AdministrationTopAppBar/AdministrationTopAppBar'; + +export const AdministrationScreen = observer(function AdministrationScreen() { + if (!usePermission(EAdminPermission.admin)) { + return <>You has no permission; + } + + return ( + <> + + + ); +}); diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts index c5081f1f7c..de9a5997ac 100644 --- a/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationScreenService.ts @@ -6,26 +6,44 @@ * you may not use this file except in compliance with the License. */ -import { ScreenService, RouterService } from '@dbeaver/core/app'; -import { injectable } from '@dbeaver/core/di'; +import { ScreenService, RouterService, AppScreenService } from '@dbeaver/core/app'; +import { injectable, Bootstrap } from '@dbeaver/core/di'; +import { PermissionsService } from '@dbeaver/core/root'; +import { EAdminPermission } from '../EAdminPermission'; import { AdministrationScreen } from './AdministrationScreen'; @injectable() -export class AdministrationScreenService { +export class AdministrationScreenService extends Bootstrap { static screenName = 'administration' constructor( private screenService: ScreenService, private routerService: RouterService, - ) {} + private permissionsService: PermissionsService, + private appScreenService: AppScreenService + ) { + super(); + this.permissionsService.onUpdate.subscribe(this.handleActivate.bind(this)); + } navigateToRoot() { - return this.routerService.router.navigate(AdministrationScreenService.screenName); + this.routerService.router.navigate(AdministrationScreenService.screenName); } - register() { - this.screenService.add({ name: AdministrationScreenService.screenName, path: '/admin', component: AdministrationScreen }); + bootstrap() { + this.screenService.create({ + name: AdministrationScreenService.screenName, + path: '/admin', + component: AdministrationScreen, + onActivate: this.handleActivate.bind(this), + }); + } + + private handleActivate() { + if (!this.permissionsService.has(EAdminPermission.admin)) { + this.appScreenService.navigateToRoot(); + } } } diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBar.tsx b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBar.tsx new file mode 100644 index 0000000000..67f8db9820 --- /dev/null +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBar.tsx @@ -0,0 +1,22 @@ +/* + * 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 { Placeholder, TopAppBar } from '@dbeaver/core/blocks'; +import { useService } from '@dbeaver/core/di'; + +import { AdministrationTopAppBarService } from './AdministrationTopAppBarService'; + +export function AdministrationTopAppBar() { + const administrationTopAppBarService = useService(AdministrationTopAppBarService); + + return ( + + + + ); +} diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBarService.ts b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBarService.ts new file mode 100644 index 0000000000..bcd0ae00a8 --- /dev/null +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBarService.ts @@ -0,0 +1,24 @@ +/* + * 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 { SettingsMenu, Logo } from '@dbeaver/core/app'; +import { PlaceholderContainer } from '@dbeaver/core/blocks'; +import { injectable } from '@dbeaver/core/di'; + +import { Fill } from './Fill'; + +@injectable() +export class AdministrationTopAppBarService { + readonly placeholder = new PlaceholderContainer(); + + constructor() { + this.placeholder.add(Logo, 0); + this.placeholder.add(Fill, 3); + this.placeholder.add(SettingsMenu, 4); + } +} diff --git a/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/Fill.tsx b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/Fill.tsx new file mode 100644 index 0000000000..54bdf739be --- /dev/null +++ b/webapp/packages/administration/src/AdministrationScreen/AdministrationTopAppBar/Fill.tsx @@ -0,0 +1,19 @@ +/* + * 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 styled, { css } from 'reshadow'; + +const styles = css` + fill { + flex: 1; + } +`; + +export function Fill() { + return styled(styles)(); +} diff --git a/webapp/packages/administration/src/Bootstrap.ts b/webapp/packages/administration/src/Bootstrap.ts deleted file mode 100644 index d5f2a72de9..0000000000 --- a/webapp/packages/administration/src/Bootstrap.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 { injectable } from '@dbeaver/core/di'; - -import { AdministrationMenuService } from './AdministrationMenuService'; -import { AdministrationScreenService } from './AdministrationScreen/AdministrationScreenService'; - -@injectable() -export class Bootstrap { - constructor( - private administrationMenuService: AdministrationMenuService, - private administrationScreenService: AdministrationScreenService, - ) { } - - bootstrap() { - this.administrationScreenService.register(); - this.administrationMenuService.register(); - } -} diff --git a/webapp/packages/administration/src/EAdminPermission.ts b/webapp/packages/administration/src/EAdminPermission.ts new file mode 100644 index 0000000000..c1c7cddd49 --- /dev/null +++ b/webapp/packages/administration/src/EAdminPermission.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export enum EAdminPermission { + admin = 'admin' +} diff --git a/webapp/packages/administration/src/index.ts b/webapp/packages/administration/src/index.ts index 72c5cfecc9..41181aba8c 100644 --- a/webapp/packages/administration/src/index.ts +++ b/webapp/packages/administration/src/index.ts @@ -3,3 +3,5 @@ import { manifest } from './manifest'; export default manifest; export * from './AdministrationMenuService'; +export * from './AdministrationScreen/AdministrationScreenService'; +export * from './AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBarService'; diff --git a/webapp/packages/administration/src/manifest.ts b/webapp/packages/administration/src/manifest.ts index 4acf5d475d..955e91126d 100644 --- a/webapp/packages/administration/src/manifest.ts +++ b/webapp/packages/administration/src/manifest.ts @@ -10,7 +10,7 @@ import { IServiceInjector, PluginManifest } from '@dbeaver/core/di'; import { AdministrationMenuService } from './AdministrationMenuService'; import { AdministrationScreenService } from './AdministrationScreen/AdministrationScreenService'; -import { Bootstrap } from './Bootstrap'; +import { AdministrationTopAppBarService } from './AdministrationScreen/AdministrationTopAppBar/AdministrationTopAppBarService'; export const manifest: PluginManifest = { info: { @@ -20,11 +20,9 @@ export const manifest: PluginManifest = { providers: [ AdministrationMenuService, AdministrationScreenService, + AdministrationTopAppBarService, ], async initialize(services: IServiceInjector) { - services - .resolveServiceByClass(Bootstrap) - .bootstrap(); }, }; diff --git a/webapp/packages/authentication/package.json b/webapp/packages/authentication/package.json index dde951a9e1..bbb32ddcb6 100644 --- a/webapp/packages/authentication/package.json +++ b/webapp/packages/authentication/package.json @@ -12,10 +12,12 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "devDependencies": { - "@dbeaver/core": "^0.1.0", - "@dbeaver/builder": "^0.1.0" + "@dbeaver/administration": "^0.1.0", + "@dbeaver/builder": "^0.1.0", + "@dbeaver/core": "^0.1.0" }, "peerDependencies": { + "@dbeaver/administration": "^0.1.0", "@dbeaver/core": "^0.1.0" } } diff --git a/webapp/packages/authentication/src/AuthMenuService.ts b/webapp/packages/authentication/src/AuthMenuService.ts index 0ed1ee92a4..16c998f1ce 100644 --- a/webapp/packages/authentication/src/AuthMenuService.ts +++ b/webapp/packages/authentication/src/AuthMenuService.ts @@ -6,6 +6,7 @@ * you may not use this file except in compliance with the License. */ +import { AdministrationTopAppBarService } from '@dbeaver/administration'; import { SettingsMenuService, TopNavService } from '@dbeaver/core/app'; import { injectable } from '@dbeaver/core/di'; import { ServerService } from '@dbeaver/core/root'; @@ -24,6 +25,7 @@ export class AuthMenuService { private settingsMenuService: SettingsMenuService, private authenticationService: AuthenticationService, private topNavService: TopNavService, + private administrationTopAppBarService: AdministrationTopAppBarService, ) { } register() { @@ -50,6 +52,7 @@ export class AuthMenuService { ); this.topNavService.placeholder.add(UserInfo, 4); + this.administrationTopAppBarService.placeholder.add(UserInfo, 4); } private async logout() { diff --git a/webapp/packages/core/assets/locales/en.js b/webapp/packages/core/assets/locales/en.js index 740bb9c556..e47957ffb9 100644 --- a/webapp/packages/core/assets/locales/en.js +++ b/webapp/packages/core/assets/locales/en.js @@ -42,6 +42,7 @@ module.exports = { data_transfer_exporting_sql: 'SQL:', administration_menu_enter: 'Administration', + administration_menu_back: 'Back to app', authentication_login_dialog_title: 'Authentication', authentication_login: 'Login', diff --git a/webapp/packages/core/assets/locales/ru.js b/webapp/packages/core/assets/locales/ru.js index 4f5a6ed5db..b652c1dae6 100644 --- a/webapp/packages/core/assets/locales/ru.js +++ b/webapp/packages/core/assets/locales/ru.js @@ -41,6 +41,7 @@ module.exports = { data_transfer_exporting_sql: 'SQL:', administration_menu_enter: 'Администрирование', + administration_menu_back: 'Вернуться в приложение', authentication_login_dialog_title: 'Авторизация', authentication_login: 'Войти', diff --git a/webapp/packages/core/src/app/AppScreen/AppScreen.tsx b/webapp/packages/core/src/app/AppScreen/AppScreen.tsx index 702c3734c0..c8c2aac465 100644 --- a/webapp/packages/core/src/app/AppScreen/AppScreen.tsx +++ b/webapp/packages/core/src/app/AppScreen/AppScreen.tsx @@ -6,9 +6,6 @@ * you may not use this file except in compliance with the License. */ -import { DialogsPortal } from '@dbeaver/core/dialogs'; - -import { Notifications } from '../Notifications/Notifications'; import { TopNavBar } from '../TopNavBar/TopNavBar'; import { Main } from './Main'; @@ -18,8 +15,6 @@ export function AppScreen() { <>
- - ); } diff --git a/webapp/packages/core/src/app/AppScreen/AppScreenService.ts b/webapp/packages/core/src/app/AppScreen/AppScreenService.ts index c51fe18354..2169015209 100644 --- a/webapp/packages/core/src/app/AppScreen/AppScreenService.ts +++ b/webapp/packages/core/src/app/AppScreen/AppScreenService.ts @@ -8,17 +8,25 @@ import { injectable } from '@dbeaver/core/di'; +import { RouterService } from '../RouterService'; import { ScreenService } from '../Screen/ScreenService'; import { AppScreen } from './AppScreen'; @injectable() export class AppScreenService { + static screenName = 'app' + constructor( - private screenService: ScreenService + private screenService: ScreenService, + private routerService: RouterService, ) {} + navigateToRoot() { + this.routerService.router.navigate(AppScreenService.screenName); + } + register() { - this.screenService.add({ name: 'app', path: '/', component: AppScreen }); + this.screenService.create({ name: AppScreenService.screenName, path: '/', component: AppScreen }); } } diff --git a/webapp/packages/core/src/app/Body.tsx b/webapp/packages/core/src/app/Body.tsx index 19a5167704..e016f6b8e5 100644 --- a/webapp/packages/core/src/app/Body.tsx +++ b/webapp/packages/core/src/app/Body.tsx @@ -10,8 +10,10 @@ import { observer } from 'mobx-react'; import styled, { css } from 'reshadow'; import { useService } from '@dbeaver/core/di'; +import { DialogsPortal } from '@dbeaver/core/dialogs'; import { useStyles, useTheme } from '@dbeaver/core/theming'; +import { Notifications } from './Notifications/Notifications'; import { ScreenService } from './Screen/ScreenService'; const bodyStyles = css` @@ -31,6 +33,8 @@ export const Body = observer(function Body() { return styled(useStyles(bodyStyles))( {Screen && } + + ); }); diff --git a/webapp/packages/core/src/app/Screen/ScreenService.ts b/webapp/packages/core/src/app/Screen/ScreenService.ts index 998b0797ef..4b4b15827f 100644 --- a/webapp/packages/core/src/app/Screen/ScreenService.ts +++ b/webapp/packages/core/src/app/Screen/ScreenService.ts @@ -28,7 +28,7 @@ export class ScreenService { this.routerService.subscribe(this.onRouteChange.bind(this)); } - add(screen: IScreen) { + create(screen: IScreen) { if (this.screens.has(screen.name)) { return; } @@ -37,6 +37,14 @@ export class ScreenService { this.routerService.router.add({ name: screen.name, path: screen.path }); } + isActive(name: string, strict = false): boolean { + if (strict) { + return this.screen?.name === name; + } + + return this.screen?.name.startsWith(name) || false; + } + buildUrl(screen: string) { return this.routerService.router.buildUrl(screen); } diff --git a/webapp/packages/core/src/app/TopNavBar/Logo.tsx b/webapp/packages/core/src/app/TopNavBar/Logo.tsx index 4439d512e3..5f5fe8208e 100644 --- a/webapp/packages/core/src/app/TopNavBar/Logo.tsx +++ b/webapp/packages/core/src/app/TopNavBar/Logo.tsx @@ -7,37 +7,20 @@ */ import { observer } from 'mobx-react'; -import styled, { css } from 'reshadow'; -import { Icon } from '@dbeaver/core/blocks'; +import { AppLogo } from '@dbeaver/core/blocks'; import { useService } from '@dbeaver/core/di'; import { ServerService } from '@dbeaver/core/root'; +import { AppScreenService } from '../AppScreen/AppScreenService'; + declare const version: string; // declared in webpack DefinePlugin // todo move to enviroment? -const styles = css` - logo { - height: 100%; - display: flex; - align-items: center; - margin-right: 16px; - width: 250px; - } - - Icon { - height: 24px; - width: auto; - margin-bottom: 2px; - } -`; - export const Logo = observer(function Logo() { const serverService = useService(ServerService); + const appScreenService = useService(AppScreenService); + const title = `Frontend: ${version}\nBackend: ${serverService.config.data?.version}`; - return styled(styles)( - - - - ); + return appScreenService.navigateToRoot()}/>; }); diff --git a/webapp/packages/core/src/app/TopNavBar/TopNavBar.tsx b/webapp/packages/core/src/app/TopNavBar/TopNavBar.tsx index f1ac6baa5f..207f59faca 100644 --- a/webapp/packages/core/src/app/TopNavBar/TopNavBar.tsx +++ b/webapp/packages/core/src/app/TopNavBar/TopNavBar.tsx @@ -6,21 +6,17 @@ * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - -import { Placeholder } from '@dbeaver/core/blocks'; +import { Placeholder, TopAppBar } from '@dbeaver/core/blocks'; import { useService } from '@dbeaver/core/di'; -import { useStyles } from '@dbeaver/core/theming'; import { TopNavService } from './TopNavBarService'; -import { topNavBarStyles } from './topNavBarStyles'; export function TopNavBar() { const topNavBarService = useService(TopNavService); - return styled(useStyles(topNavBarStyles))( -
+ return ( + -
+ ); } diff --git a/webapp/packages/core/src/app/index.ts b/webapp/packages/core/src/app/index.ts index 5296588631..2c2c7e761f 100644 --- a/webapp/packages/core/src/app/index.ts +++ b/webapp/packages/core/src/app/index.ts @@ -44,6 +44,8 @@ export * from './shared/InlineEditor/InlineEditor'; // components export * from './Body'; export * from './Notifications/NotificationsItem/ErrorDetailsDialog/ErrorDetailsDialog'; +export * from './TopNavBar/SettingsMenu/SettingsMenu'; +export * from './TopNavBar/Logo'; // Interfaces export * from './shared/Navigation/INavigator'; diff --git a/webapp/packages/core/src/blocks/Placeholder/PlaceholderContainer.ts b/webapp/packages/core/src/blocks/Placeholder/PlaceholderContainer.ts index 52c589a657..cb3d48ebea 100644 --- a/webapp/packages/core/src/blocks/Placeholder/PlaceholderContainer.ts +++ b/webapp/packages/core/src/blocks/Placeholder/PlaceholderContainer.ts @@ -22,7 +22,7 @@ export type PlaceholderElement = { order?: number; } -export class PlaceholderContainer { +export class PlaceholderContainer { private placeholders = observable>([], { deep: false }); get() { diff --git a/webapp/packages/core/src/blocks/index.ts b/webapp/packages/core/src/blocks/index.ts index a688b5421a..dba7030142 100644 --- a/webapp/packages/core/src/blocks/index.ts +++ b/webapp/packages/core/src/blocks/index.ts @@ -1,22 +1,23 @@ -export * from './Icons'; -export * from './Split'; -export * from './StaticImage'; export * from './ComplexLoader'; -export * from './Loader/Loader'; -export * from './StaticImage'; -export * from './Tabs'; -export * from './Button'; -export * from './Radio'; -export * from './InputField'; -export * from './ShadowInput'; -export * from './ErrorMessage'; -export * from './IconOrImage'; -export * from './TextPlaceholder'; -export * from './useClipboard'; -export * from './SubmittingForm'; -export * from './SanitizedHTML/SanitizedHTML'; +export * from './Icons'; export * from './ItemList'; -export * from './PropertiesTable'; -export * from './IconButton'; +export * from './layout/AppLogo'; +export * from './layout/TopAppBar'; +export * from './Loader/Loader'; export * from './Placeholder/Placeholder'; export * from './Placeholder/PlaceholderContainer'; +export * from './PropertiesTable'; +export * from './SanitizedHTML/SanitizedHTML'; +export * from './Split'; +export * from './Tabs'; +export * from './Button'; +export * from './ErrorMessage'; +export * from './IconButton'; +export * from './IconOrImage'; +export * from './InputField'; +export * from './Radio'; +export * from './ShadowInput'; +export * from './StaticImage'; +export * from './SubmittingForm'; +export * from './TextPlaceholder'; +export * from './useClipboard'; diff --git a/webapp/packages/core/src/blocks/layout/AppLogo.tsx b/webapp/packages/core/src/blocks/layout/AppLogo.tsx new file mode 100644 index 0000000000..4b074003e5 --- /dev/null +++ b/webapp/packages/core/src/blocks/layout/AppLogo.tsx @@ -0,0 +1,41 @@ +/* + * 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 styled, { css } from 'reshadow'; + +import { Icon } from '../Icons/Icon'; + +const styles = css` + logo { + height: 100%; + display: flex; + align-items: center; + margin-right: 16px; + width: 250px; + cursor: pointer; + } + + Icon { + height: 24px; + width: auto; + margin-bottom: 2px; + } +`; + +type Props = { + title: string; + onClick?: () => void; +} + +export function AppLogo({ title, onClick }: Props) { + return styled(styles)( + + + + ); +} diff --git a/webapp/packages/core/src/app/TopNavBar/topNavBarStyles.ts b/webapp/packages/core/src/blocks/layout/TopAppBar.tsx similarity index 62% rename from webapp/packages/core/src/app/TopNavBar/topNavBarStyles.ts rename to webapp/packages/core/src/blocks/layout/TopAppBar.tsx index 18aa0f60e8..1d28fa0bb0 100644 --- a/webapp/packages/core/src/app/TopNavBar/topNavBarStyles.ts +++ b/webapp/packages/core/src/blocks/layout/TopAppBar.tsx @@ -6,11 +6,11 @@ * you may not use this file except in compliance with the License. */ -import { css } from 'reshadow'; +import styled, { css } from 'reshadow'; -import { composes } from '@dbeaver/core/theming'; +import { useStyles, composes } from '@dbeaver/core/theming'; -export const topNavBarStyles = composes( +export const topAppBarStyles = composes( css` header { composes: theme-background-primary theme-text-on-primary from global; @@ -27,3 +27,11 @@ export const topNavBarStyles = composes( } ` ); + +export function TopAppBar({ children }: React.PropsWithChildren<{}>) { + return styled(useStyles(topAppBarStyles))( +
+ {children} +
+ ); +} diff --git a/webapp/packages/core/src/bootstrap.ts b/webapp/packages/core/src/bootstrap.ts index 87e2a02fe6..1c824d7ad9 100644 --- a/webapp/packages/core/src/bootstrap.ts +++ b/webapp/packages/core/src/bootstrap.ts @@ -13,6 +13,7 @@ export async function bootstrap(plugins: PluginManifest[]) { try { await appBootstrap.init(); + await app.initializeServices(); await app.initializePlugins(); await appBootstrap.doAfterPluginsInit(); await app.load(); diff --git a/webapp/packages/core/src/di/App.ts b/webapp/packages/core/src/di/App.ts index 3e2deee34a..95ced75684 100644 --- a/webapp/packages/core/src/di/App.ts +++ b/webapp/packages/core/src/di/App.ts @@ -6,6 +6,7 @@ * you may not use this file except in compliance with the License. */ +import { Bootstrap } from './Bootstrap'; import { DIContainer } from './DIContainer'; import { RootContainerService } from './entities/RootContainerService'; import { IServiceCollection, IServiceInjector } from './IApp'; @@ -55,6 +56,18 @@ export class App { } } + async initializeServices() { + for (const plugin of this.plugins) { + for (const service of plugin.providers) { + if (service.prototype instanceof Bootstrap) { + const serviceInstance = this.diWrapper.injector.getServiceByClass(service); + + await serviceInstance.bootstrap(); + } + } + } + } + // second phase - run init scripts todo run it based on dependency tree async initializePlugins() { for (const plugin of this.plugins) { diff --git a/webapp/packages/core/src/di/Bootstrap.ts b/webapp/packages/core/src/di/Bootstrap.ts new file mode 100644 index 0000000000..6f7a37b6c2 --- /dev/null +++ b/webapp/packages/core/src/di/Bootstrap.ts @@ -0,0 +1,14 @@ +/* + * 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 { injectable } from './injectable'; + +@injectable() +export abstract class Bootstrap { + abstract bootstrap(): void | Promise; +} diff --git a/webapp/packages/core/src/di/index.ts b/webapp/packages/core/src/di/index.ts index e46b7ac9a6..af0b07fbd7 100644 --- a/webapp/packages/core/src/di/index.ts +++ b/webapp/packages/core/src/di/index.ts @@ -1,6 +1,7 @@ export * from './IApp'; export * from './App'; export * from './AppContext'; +export * from './Bootstrap'; export * from './injectable'; export * from './PluginManifest'; export * from './useService'; diff --git a/webapp/packages/core/src/theming/ThemeService.ts b/webapp/packages/core/src/theming/ThemeService.ts index 130a01e0a7..b927dffba1 100644 --- a/webapp/packages/core/src/theming/ThemeService.ts +++ b/webapp/packages/core/src/theming/ThemeService.ts @@ -60,11 +60,11 @@ export class ThemeService { constructor(private notificationService: NotificationService, private settingsService: SettingsService) { + this.loadAllThemes(); } async init() { this.settingsService.registerSettings(this.settings, THEME_SETTINGS_KEY); - await this.loadAllThemesAsync(); await this.changeThemeAsync(this.currentThemeId); } @@ -95,7 +95,7 @@ export class ThemeService { this.settings.currentThemeId = themeId; } - private async loadAllThemesAsync(): Promise { + private loadAllThemes(): void { for (const theme of themes) { this.themeMap.set(theme.id, theme); }