feat(core): add placeholder

CB-63
This commit is contained in:
Wroud
2020-05-14 16:12:29 +03:00
parent b3f3511028
commit e4acc7710a
17 changed files with 3487 additions and 2867 deletions
@@ -6,13 +6,14 @@
* you may not use this file except in compliance with the License.
*/
import { SettingsMenuService, MainRightMenuService } from '@dbeaver/core/app';
import { SettingsMenuService, TopNavService } from '@dbeaver/core/app';
import { injectable } from '@dbeaver/core/di';
import { ServerService } from '@dbeaver/core/root';
import { AuthenticationService } from './AuthenticationService';
import { AuthInfoService } from './AuthInfoService';
import { AuthDialogService } from './Dialog/AuthDialogService';
import { UserInfo } from './UserInfo';
@injectable()
export class AuthMenuService {
@@ -22,7 +23,7 @@ export class AuthMenuService {
private authInfoService: AuthInfoService,
private settingsMenuService: SettingsMenuService,
private authenticationService: AuthenticationService,
private mainRightMenuService: MainRightMenuService,
private topNavService: TopNavService,
) { }
register() {
@@ -48,13 +49,7 @@ export class AuthMenuService {
}
);
this.mainRightMenuService.registerRootItem({
id: 'user',
order: 0,
isHidden: () => !this.authInfoService.userInfo,
icon: 'user',
title: 'User',
});
this.topNavService.placeholder.add(UserInfo, 4);
}
private async logout() {
@@ -0,0 +1,58 @@
/*
* 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 styled, { css } from 'reshadow';
import { IconOrImage } from '@dbeaver/core/blocks';
import { useService } from '@dbeaver/core/di';
import { composes, useStyles } from '@dbeaver/core/theming';
import { AuthInfoService } from './AuthInfoService';
const styles = composes(
css`
user {
composes: theme-ripple from global;
}
`,
css`
user {
height: 100%;
padding: 0 16px;
display: flex;
align-items: center;
}
IconOrImage {
display: block;
width: 24px;
}
user-name {
display: block;
line-height: initial;
margin-left: 8px;
}
`
);
export const UserInfo = observer(function UserInfo() {
const authInfoService = useService(AuthInfoService);
if (!authInfoService.userInfo) {
return null;
}
return styled(useStyles(styles))(
<user as='div'>
<user-icon as="div">
<IconOrImage icon='user' viewBox='0 0 28 28' />
</user-icon>
<user-name as='div'>{authInfoService.userInfo.userId}</user-name>
</user>
);
});
@@ -0,0 +1,8 @@
{
"name": "@dbeaver/core/placeholder",
"private": true,
"sideEffects": false,
"main": "../dist/placeholder",
"module": "../dist/placeholder",
"types": "../dist/types/placeholder"
}
+11 -10
View File
@@ -26,16 +26,17 @@ import { LocalizationService } from './localization';
@injectable()
export class AppBootstrap {
constructor(private exceptionsCatcherService: ExceptionsCatcherService,
private localizationService: LocalizationService,
private themeService: ThemeService,
private connectionDialogService: ConnectionDialogsService,
private logViewerMenuService: LogViewerMenuService,
private sessionExpireService: SessionExpireService,
private navigationTreeContextMenuService: NavigationTreeContextMenuService,
private navigationTabsService: NavigationTabsService,
private connectionSchemaManagerService: ConnectionSchemaManagerService) {
}
constructor(
private exceptionsCatcherService: ExceptionsCatcherService,
private localizationService: LocalizationService,
private themeService: ThemeService,
private connectionDialogService: ConnectionDialogsService,
private logViewerMenuService: LogViewerMenuService,
private sessionExpireService: SessionExpireService,
private navigationTreeContextMenuService: NavigationTreeContextMenuService,
private navigationTabsService: NavigationTabsService,
private connectionSchemaManagerService: ConnectionSchemaManagerService,
) { }
async init() {
this.exceptionsCatcherService.subscribe();
@@ -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)(<fill as='div' />);
}
@@ -0,0 +1,43 @@
/*
* 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 styled, { css } from 'reshadow';
import { Icon } from '@dbeaver/core/blocks';
import { useService } from '@dbeaver/core/di';
import { ServerService } from '@dbeaver/core/root';
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 title = `Frontend: ${version}\nBackend: ${serverService.config.data?.version}`;
return styled(styles)(
<logo as="div" title={title}>
<Icon name="logo" viewBox="0 0 361 73" />
</logo>
);
});
@@ -6,37 +6,21 @@
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react';
import styled from 'reshadow';
import { Icon } from '@dbeaver/core/blocks';
import { useService } from '@dbeaver/core/di';
import { ServerService } from '@dbeaver/core/root';
import { Placeholder } from '@dbeaver/core/placeholder';
import { useStyles } from '@dbeaver/core/theming';
import { ConnectionSelector } from './ConnectionSchemaManager/ConnectionSelector/ConnectionSelector';
import { MainMenu } from './MainMenu/MainMenu';
import { MainRightMenu } from './MainRightMenu/MainRightMenu';
import { SettingsMenu } from './SettingsMenu/SettingsMenu';
import { TopNavService } from './TopNavBarService';
import { topNavBarStyles } from './topNavBarStyles';
declare const version: string; // declared in webpack DefinePlugin // todo move to enviroment?
export const TopNavBar = observer(function TopNavBar() {
const serverService = useService(ServerService);
const title = `Frontend: ${version}\nBackend: ${serverService.config.data?.version}`;
export function TopNavBar() {
const topNavBarService = useService(TopNavService);
return styled(useStyles(topNavBarStyles))(
<header>
<logo as="div" title={title}>
<Icon name="logo" viewBox="0 0 361 73" />
</logo>
<MainMenu />
<ConnectionSelector/>
<fill as='div'/>
<MainRightMenu />
<SettingsMenu />
<Placeholder container={topNavBarService.placeholder} />
</header>
);
});
}
@@ -0,0 +1,29 @@
/*
* 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 { PlaceholderContainer } from '@dbeaver/core/placeholder';
import { ConnectionSelector } from './ConnectionSchemaManager/ConnectionSelector/ConnectionSelector';
import { Fill } from './Fill';
import { Logo } from './Logo';
import { MainMenu } from './MainMenu/MainMenu';
import { MainRightMenu } from './MainRightMenu/MainRightMenu';
@injectable()
export class TopNavService {
readonly placeholder = new PlaceholderContainer();
constructor() {
this.placeholder.add(Logo, 0);
this.placeholder.add(MainMenu, 1);
this.placeholder.add(ConnectionSelector, 2);
this.placeholder.add(Fill, 3);
this.placeholder.add(MainRightMenu, 4);
}
}
@@ -25,21 +25,5 @@ export const topNavBarStyles = composes(
padding: 0 16px;
z-index: 1;
}
logo {
height: 100%;
display: flex;
align-items: center;
margin-right: 16px;
width: 250px;
& Icon {
height: 24px;
width: auto;
margin-bottom: 2px;
}
}
fill {
flex: 1;
}
`
);
+1
View File
@@ -3,6 +3,7 @@ export * from './TopNavBar/MainMenu/MainMenuService';
export * from './TopNavBar/MainRightMenu/MainRightMenuService';
export * from './TopNavBar/ConnectionSchemaManager/ConnectionSchemaManagerService';
export * from './TopNavBar/SettingsMenu/SettingsMenuService';
export * from './TopNavBar/TopNavBarService';
export * from './shared/ConnectionsManager/ConnectionsManagerService';
export * from './shared/ConnectionsManager/ConnectionDialogsService';
export * from './shared/ConnectionsManager/extensions/IConnectionProvider';
+2 -1
View File
@@ -11,7 +11,7 @@ import {
MainMenuService, NavigationService, NavigationTreeService, NodesManagerService,
ConnectionSchemaManagerService, NavigationTabsService,
NavigationTreeContextMenuService,
SettingsMenuService, LogViewerService, LogViewerMenuService, MainRightMenuService,
SettingsMenuService, LogViewerService, LogViewerMenuService, MainRightMenuService, TopNavService,
} from '@dbeaver/core/app';
import { PluginManifest } from '@dbeaver/core/di';
import { CommonDialogService, ContextMenuService, SessionExpireService } from '@dbeaver/core/dialogs';
@@ -56,6 +56,7 @@ export const coreManifest: PluginManifest = {
LogViewerMenuService,
LogViewerService,
MainMenuService,
TopNavService,
NavigationService,
NavigationTabsService,
NavigationTreeContextMenuService,
@@ -0,0 +1,27 @@
/*
* 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 { PlaceholderContainer } from './PlaceholderContainer';
type Props<T = unknown> = T extends unknown ? {
container: PlaceholderContainer<T>;
context?: T;
} :{
container: PlaceholderContainer<T>;
context: T;
}
export const Placeholder = observer(function Placeholder<T = unknown>({ container, context }: Props<T>) {
return (
<>
{container.get().map(({ id, component: Component }) => <Component key={id} context={context!} />)}
</>
);
});
@@ -0,0 +1,58 @@
/*
* 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 { observable } from 'mobx';
import { uuid } from '@dbeaver/core/utils';
export type PlaceholderProps<T = unknown> = {
context: T;
}
export type PlaceholderComponent<T = unknown> = React.FunctionComponent<PlaceholderProps<T>>
export type PlaceholderElement<T = unknown> = {
id: string;
component: PlaceholderComponent<T>;
order?: number;
}
export class PlaceholderContainer<T = unknown> {
private placeholders = observable<PlaceholderElement<T>>([], { deep: false });
get() {
return this.placeholders;
}
add(component: PlaceholderComponent<T>, order?: number) {
const placeholder: PlaceholderElement<T> = {
id: uuid(),
component,
order,
};
if (!order) {
this.placeholders.push(placeholder);
} else {
const position = this.findPosition(order);
console.log(position);
this.placeholders.splice(position, 0, placeholder);
}
}
private findPosition(order: number) {
for (let i = 0; i < this.placeholders.length; i++) {
const placeholder = this.placeholders[i];
if (placeholder.order === undefined || order <= placeholder.order) {
return i;
}
}
return this.placeholders.length;
}
}
@@ -0,0 +1,2 @@
export * from './Placeholder';
export * from './PlaceholderContainer';
@@ -49,6 +49,7 @@ module.exports = (env, argv) => merge(commonConfig(env, argv), {
"@dbeaver/core/extensions": path.resolve(__dirname, "../../../core/src/extensions"),
"@dbeaver/core/product": path.resolve(__dirname, "../../../core/src/product"),
"@dbeaver/core/plugin": path.resolve(__dirname, "../../../core/src/plugin"),
"@dbeaver/core/placeholder": path.resolve(__dirname, "../../../core/src/placeholder"),
// rewrite imports for unnecessary work in `web/src/libs/sdk.ts`
'graphql-tag': path.join(__dirname, '../../fix-gql.js'),
+2 -1
View File
@@ -19,7 +19,8 @@
"@dbeaver/core/utils": ["packages/core/src/utils"],
"@dbeaver/core/extensions": ["packages/core/src/extensions"],
"@dbeaver/core/plugin": ["packages/core/src/plugin"],
"@dbeaver/core/product": ["packages/core/src/product"]
"@dbeaver/core/product": ["packages/core/src/product"],
"@dbeaver/core/placeholder": ["packages/core/src/placeholder"]
}
}
}
+3216 -2808
View File
File diff suppressed because it is too large Load Diff