Merge remote-tracking branch 'origin/devel' into devel

This commit is contained in:
Serge Rider
2021-12-29 11:22:00 +03:00
51 changed files with 941 additions and 281 deletions
@@ -10,7 +10,6 @@ import { AdministrationTopAppBarService, WizardTopAppBarService } from '@cloudbe
import { injectable, Bootstrap } from '@cloudbeaver/core-di';
import { Logo } from './Logo';
import { SettingsMenu } from './SettingsMenu/SettingsMenu';
@injectable()
export class AdministrationTopAppBarBootstrapService extends Bootstrap {
@@ -23,9 +22,8 @@ export class AdministrationTopAppBarBootstrapService extends Bootstrap {
register(): void | Promise<void> {
this.administrationTopAppBarService.placeholder.add(Logo, 0);
this.administrationTopAppBarService.placeholder.add(SettingsMenu, 4);
this.wizardTopAppBarService.placeholder.add(Logo, 0);
}
load(): void | Promise<void> {}
}
load(): void | Promise<void> { }
}
@@ -1,101 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { IComputedMenuItemOptions, IMenuPanel, StaticMenu } from '@cloudbeaver/core-dialogs';
import { LocalizationService } from '@cloudbeaver/core-localization';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import { ThemeService } from '@cloudbeaver/core-theming';
@injectable()
export class SettingsMenuService extends Bootstrap {
static settingsMenuToken = 'settingsMenu';
private menu = new StaticMenu();
private langMenuToken = 'langMenu';
private themeMenuToken = 'themeMenu';
constructor(
private localizationService: LocalizationService,
private themeService: ThemeService,
private serverConfigResource: ServerConfigResource,
) {
super();
}
register(): void | Promise<void> {
this.menu.addRootPanel(SettingsMenuService.settingsMenuToken);
}
async load(): Promise<void> {
this.addThemes();
await this.addLocales();
}
getMenu(): IMenuPanel {
return this.menu.getMenu(SettingsMenuService.settingsMenuToken);
}
addMenuItem(panelId: string, options: IComputedMenuItemOptions): void {
this.menu.addMenuItem(panelId, options);
}
private addThemes() {
this.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: this.themeMenuToken,
order: 1,
title: 'app_shared_settingsMenu_theme',
isPanel: true,
}
);
this.themeService.themes.forEach(theme => {
this.addMenuItem(
this.themeMenuToken,
{
id: theme.id,
title: theme.name,
isDisabled: () => theme.id === this.themeService.currentThemeId,
onClick: () => this.themeService.changeThemeAsync(theme.id),
}
);
});
}
private async addLocales() {
const config = await this.serverConfigResource.load();
if (!config) {
return;
}
this.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: this.langMenuToken,
order: 2,
title: 'app_shared_settingsMenu_lang',
isPanel: true,
}
);
config.supportedLanguages.forEach(lang => {
this.addMenuItem(
this.langMenuToken,
{
id: lang.isoCode,
title: lang.nativeName,
isDisabled: () => lang.isoCode === this.localizationService.getCurrentLanguage(),
onClick: () => this.localizationService.changeLocaleAsync(lang.isoCode),
}
);
});
}
}
@@ -11,7 +11,7 @@ import { useService } from '@cloudbeaver/core-di';
import { TopNavService } from './TopNavBarService';
export function TopNavBar() {
export const TopNavBar = function TopNavBar() {
const topNavBarService = useService(TopNavService);
return (
@@ -19,4 +19,4 @@ export function TopNavBar() {
<Placeholder container={topNavBarService.placeholder} />
</TopAppBar>
);
}
};
@@ -13,7 +13,6 @@ import { ConnectionSelector } from './ConnectionSchemaManager/ConnectionSelector
import { Fill } from './Fill';
import { Logo } from './Logo';
import { MainMenu } from './MainMenu/MainMenu';
import { SettingsMenu } from './SettingsMenu/SettingsMenu';
@injectable()
export class TopNavService {
@@ -24,6 +23,5 @@ export class TopNavService {
this.placeholder.add(MainMenu, 1);
this.placeholder.add(ConnectionSelector, 2);
this.placeholder.add(Fill, 3);
this.placeholder.add(SettingsMenu, 4);
}
}
-2
View File
@@ -2,7 +2,6 @@
export * from './CoreSettingsService';
export * from './AppScreen/AppScreenService';
export * from './TopNavBar/MainMenu/MainMenuService';
export * from './TopNavBar/SettingsMenu/SettingsMenuService';
export * from './TopNavBar/ConnectionSchemaManager/ConnectionSchemaManagerService';
export * from './TopNavBar/TopNavBarService';
export * from './TopNavBar/AdministrationTopAppBarBootstrapService';
@@ -59,7 +58,6 @@ export * from './useAppVersion';
// components
export * from './Body';
export * from './TopNavBar/SettingsMenu/SettingsMenu';
export * from './TopNavBar/Logo';
// Interfaces
@@ -31,7 +31,6 @@ import {
ConnectionSchemaManagerService,
NavigationTabsService,
NavNodeContextMenuService,
SettingsMenuService,
LogViewerService,
LogViewerBootstrap,
TopNavService,
@@ -156,7 +155,6 @@ export const coreManifests: PluginManifest[] = [
DBObjectResource,
NotificationService,
SessionService,
SettingsMenuService,
SettingsService,
ThemeSettingsService,
ThemeService,
@@ -10,7 +10,7 @@ import { action, observable, makeObservable } from 'mobx';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { ServerService, SessionResource } from '@cloudbeaver/core-root';
import { ServerConfigResource, SessionResource } from '@cloudbeaver/core-root';
import type { ServerLanguage } from '@cloudbeaver/core-sdk';
import { SettingsService } from '@cloudbeaver/core-settings';
@@ -38,10 +38,10 @@ export class LocalizationService extends Bootstrap {
private localeProviders: ILocaleProvider[] = [];
constructor(
private notificationService: NotificationService,
private sessionResource: SessionResource,
private serverService: ServerService,
private settingsService: SettingsService
private readonly notificationService: NotificationService,
private readonly sessionResource: SessionResource,
private readonly serverConfigResource: ServerConfigResource,
private readonly settingsService: SettingsService
) {
super();
@@ -133,7 +133,7 @@ export class LocalizationService extends Bootstrap {
}
private async setLocale(key: string) {
const config = await this.serverService.config.load();
const config = await this.serverConfigResource.load();
if (!config) {
throw new Error('Can\'t get server settings');
@@ -59,6 +59,7 @@ export const defaultENLocale = [
['ui_changes_will_be_lost', 'Your changes will be lost'],
['ui_continue', 'Continue'],
['ui_authentication', 'Authentication'],
['ui_settings', 'Settings'],
['root_permission_denied', "You don't have permissions"],
['root_permission_no_permission', "You don't have permission for this action"],
@@ -38,6 +38,7 @@ export const defaultITLocale = [
['ui_no_items_placeholder', 'Non ci sono ancora elementi.'],
['ui_search_no_result_placeholder', 'Nessun risultato trovato.'],
['ui_save_reminder', 'Ci sono modifiche non salvate.'],
['ui_settings', 'Settings'],
['root_permission_denied', 'Non hai i permessi'],
['app_root_session_expire_warning_title', 'La sessione sta per scadere'],
@@ -57,6 +57,7 @@ export const defaultRULocale = [
['ui_changes_will_be_lost', 'Ваши изменения будут потеряны'],
['ui_continue', 'Продолжить'],
['ui_authentication', 'Аутентификация'],
['ui_settings', 'Настройки'],
['root_permission_denied', 'Отказано в доступе'],
['root_permission_no_permission', 'У вас нет разрешения на это действие'],
@@ -1,73 +1,74 @@
export const defaultZHLocale = [
['name', 'zh'],
['ui_tag_new', '新建'],
['ui_light_theme', '明亮'],
['ui_dark_theme', '黑暗'],
['ui_stepper_back', '返回'],
['ui_stepper_next', '下一步'],
['ui_stepper_finish', '完成'],
['ui_processing_loading', '加载中...'],
['ui_processing_cancel', '取消'],
['ui_processing_canceling', '取消中...'],
['ui_processing_retry', '重试'],
['ui_processing_ok', '好'],
['ui_processing_create', '创建'],
['ui_processing_save', '保存'],
['ui_configure', '配置'],
['ui_apply', '应用'],
['ui_error_message', '错误:'],
['ui_error_close', '关闭'],
['ui_close', '关闭'],
['ui_errors_details', '详情'],
['ui_search', '搜索...'],
['ui_delete', '删除'],
['ui_add', '添加'],
['ui_refresh', '刷新'],
['ui_data_saving_error', '保存出错'],
['ui_data_delete_confirmation', '删除确认'],
['ui_no_matches_placeholder', '您的搜索没有返回匹配项。'],
['ui_information', '信息'],
['ui_clipboard', '剪贴板'],
['ui_copy_to_clipboard', '复制'],
['ui_copy_to_clipboard_copied', '已复制'],
['ui_copy_to_clipboard_failed_to_copy', '复制失败'],
['ui_clipboard_access_denied_title', '剪贴板访问被拒绝'],
['ui_clipboard_access_denied_message', '您需要授予对剪贴板的访问权限才能使用某些应用功能'],
['ui_reveal_password', '展示或隐藏密码'],
['ui_page_not_found', '找不到页面'],
['ui_revoke', '撤销'],
['ui_grant', '授予'],
['ui_edit', '编辑'],
['ui_open_in_tab', '在选项卡中打开'],
['ui_rename', '重命名'],
['ui_rename_processing', '重命名中...'],
['ui_name', '名称'],
['ui_cant_delete_item', "此项目不能删除"],
['ui_no_items_placeholder', '还没有项目'],
['ui_search_no_result_placeholder', '没有找到结果'],
['ui_save_reminder', '您有未保存的更改'],
['ui_yes', '是'],
['ui_no', '否'],
['ui_select_all', '选择所有'],
['ui_reconnect', '重新连接'],
['ui_forget', '忘记'],
['ui_set', '设置'],
['ui_are_you_sure', '您确定吗?'],
['ui_options', '选项'],
['ui_changes_might_be_lost', '您的更改可能会丢失'],
['ui_file', '文件'],
['ui_changes_will_be_lost', '您的更改将丢失'],
['ui_continue', '继续'],
['ui_authentication', '认证'],
['name', 'zh'],
['ui_tag_new', '新建'],
['ui_light_theme', '明亮'],
['ui_dark_theme', '黑暗'],
['ui_stepper_back', '返回'],
['ui_stepper_next', '下一步'],
['ui_stepper_finish', '完成'],
['ui_processing_loading', '加载中...'],
['ui_processing_cancel', '取消'],
['ui_processing_canceling', '取消中...'],
['ui_processing_retry', '重试'],
['ui_processing_ok', '好'],
['ui_processing_create', '创建'],
['ui_processing_save', '保存'],
['ui_configure', '配置'],
['ui_apply', '应用'],
['ui_error_message', '错误:'],
['ui_error_close', '关闭'],
['ui_close', '关闭'],
['ui_errors_details', '详情'],
['ui_search', '搜索...'],
['ui_delete', '删除'],
['ui_add', '添加'],
['ui_refresh', '刷新'],
['ui_data_saving_error', '保存出错'],
['ui_data_delete_confirmation', '删除确认'],
['ui_no_matches_placeholder', '您的搜索没有返回匹配项。'],
['ui_information', '信息'],
['ui_clipboard', '剪贴板'],
['ui_copy_to_clipboard', '复制'],
['ui_copy_to_clipboard_copied', '已复制'],
['ui_copy_to_clipboard_failed_to_copy', '复制失败'],
['ui_clipboard_access_denied_title', '剪贴板访问被拒绝'],
['ui_clipboard_access_denied_message', '您需要授予对剪贴板的访问权限才能使用某些应用功能'],
['ui_reveal_password', '展示或隐藏密码'],
['ui_page_not_found', '找不到页面'],
['ui_revoke', '撤销'],
['ui_grant', '授予'],
['ui_edit', '编辑'],
['ui_open_in_tab', '在选项卡中打开'],
['ui_rename', '重命名'],
['ui_rename_processing', '重命名中...'],
['ui_name', '名称'],
['ui_cant_delete_item', "此项目不能删除"],
['ui_no_items_placeholder', '还没有项目'],
['ui_search_no_result_placeholder', '没有找到结果'],
['ui_save_reminder', '您有未保存的更改'],
['ui_yes', '是'],
['ui_no', '否'],
['ui_select_all', '选择所有'],
['ui_reconnect', '重新连接'],
['ui_forget', '忘记'],
['ui_set', '设置'],
['ui_are_you_sure', '您确定吗?'],
['ui_options', '选项'],
['ui_changes_might_be_lost', '您的更改可能会丢失'],
['ui_file', '文件'],
['ui_changes_will_be_lost', '您的更改将丢失'],
['ui_continue', '继续'],
['ui_authentication', '认证'],
['ui_settings', 'Settings'],
['root_permission_denied', "您没有权限"],
['root_permission_no_permission', "您没有权限执行此操作"],
['app_root_session_expire_warning_title', '会话即将过期'],
['app_root_session_expire_warning_message', '您的会话将在5分钟内到期。要继续工作,请关闭此弹出窗口。'],
['app_root_session_expire_warning_button', '我在'],
['app_root_session_expired_title', '会话已过期'],
['app_root_session_expired_message', '会话已过期。您想重新加载吗?'],
['app_root_session_expired_reload', '重新加载'],
['app_root_quota_exceeded', '超出配额'],
['core_eventsLog_dbeaverErrorDetails', '错误详情'],
];
['root_permission_denied', "您没有权限"],
['root_permission_no_permission', "您没有权限执行此操作"],
['app_root_session_expire_warning_title', '会话即将过期'],
['app_root_session_expire_warning_message', '您的会话将在5分钟内到期。要继续工作,请关闭此弹出窗口。'],
['app_root_session_expire_warning_button', '我在'],
['app_root_session_expired_title', '会话已过期'],
['app_root_session_expired_message', '会话已过期。您想重新加载吗?'],
['app_root_session_expired_reload', '重新加载'],
['app_root_quota_exceeded', '超出配额'],
['core_eventsLog_dbeaverErrorDetails', '错误详情'],
];
@@ -18,8 +18,7 @@ import { DbeaverError, NotificationService } from '@cloudbeaver/core-events';
import { SettingsService } from '@cloudbeaver/core-settings';
import { themes } from './themes';
import { defaultThemeSettings } from './ThemeSettingsService';
import { ThemeSettingsService } from './ThemeSettingsService';
import { defaultThemeSettings, ThemeSettingsService } from './ThemeSettingsService';
import type { ClassCollection } from './themeUtils';
const COMMON_STYLES: any[] = [];
@@ -82,11 +81,10 @@ export class ThemeService extends Bootstrap {
});
}
register(): void {
this.loadAllThemes();
}
register(): void { }
async load(): Promise<void> {
this.loadAllThemes();
this.setCurrentThemeId(this.defaultThemeId);
this.settingsService.registerSettings(this.settings, THEME_SETTINGS_KEY);
await this.changeThemeAsync(this.currentThemeId);
@@ -8,21 +8,29 @@
import { observer } from 'mobx-react-lite';
import { useCallback } from 'react';
import { MenuSeparator } from 'reakit';
import { MenuInitialState, MenuSeparator } from 'reakit';
import styled, { use } from 'reshadow';
import { useService } from '@cloudbeaver/core-di';
import { useStyles, ComponentStyle } from '@cloudbeaver/core-theming';
import { IMenuActionItem, IMenuData, IMenuItem, MenuActionItem, MenuBaseItem, MenuSeparatorItem } from '@cloudbeaver/core-view';
import { DATA_CONTEXT_MENU_NESTED, IMenuActionItem, IMenuData, IMenuItem, MenuActionItem, MenuBaseItem, MenuSeparatorItem, MenuService, MenuSubMenuItem, useMenu } from '@cloudbeaver/core-view';
import { ContextMenu } from '../MenuTrigger';
import { MenuBarItem } from './MenuBarItem';
interface INestedMenuSettings extends MenuInitialState {
onVisibleSwitch?: (visible: boolean) => void;
}
interface IMenuBarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> {
menu: IMenuData;
nestedMenuSettings?: INestedMenuSettings;
style?: ComponentStyle;
}
export const MenuBar = observer<IMenuBarProps, HTMLDivElement>(function MenuBar({
menu,
nestedMenuSettings,
style,
...props
}, ref) {
@@ -40,6 +48,7 @@ export const MenuBar = observer<IMenuBarProps, HTMLDivElement>(function MenuBar(
key={item.id}
item={item}
menuData={menu}
nestedMenuSettings={nestedMenuSettings}
style={style}
/>
))}
@@ -50,16 +59,33 @@ export const MenuBar = observer<IMenuBarProps, HTMLDivElement>(function MenuBar(
interface IMenuBarElementProps {
item: IMenuItem;
menuData: IMenuData;
nestedMenuSettings?: INestedMenuSettings;
style?: ComponentStyle;
}
const MenuBarElement = observer<IMenuBarElementProps>(function MenuBarElement({ item, style }) {
const MenuBarElement = observer<IMenuBarElementProps>(function MenuBarElement({
item,
menuData,
nestedMenuSettings,
style
}) {
const styles = useStyles(style);
const onClick = useCallback(() => {
item.events?.onSelect?.();
}, [item]);
if (item instanceof MenuSubMenuItem) {
return styled(styles)(
<SubMenuItem
item={item}
menuData={menuData}
style={style}
nestedMenuSettings={nestedMenuSettings}
/>
);
}
if (item instanceof MenuSeparatorItem) {
return styled(styles)(
<MenuSeparator />
@@ -127,3 +153,48 @@ const MenuBarAction = observer<IMenuBarActionProps>(function MenuBarAction({ ite
/>
);
});
interface ISubMenuItemProps {
item: MenuSubMenuItem;
menuData: IMenuData;
nestedMenuSettings?: INestedMenuSettings;
style?: ComponentStyle;
}
const SubMenuItem = observer<ISubMenuItemProps>(function SubmenuItem({
item,
menuData,
nestedMenuSettings,
style
}) {
const styles = useStyles(style);
const menuService = useService(MenuService);
const subMenuData = useMenu(item.menu, menuData.context);
const handler = menuService.getHandler(menuData.context);
const loading = handler?.isLoading?.(menuData.context);
const disabled = handler?.isDisabled?.(menuData.context);
subMenuData.context.set(DATA_CONTEXT_MENU_NESTED, true);
return styled(styles)(
<ContextMenu
menu={subMenuData}
style={style}
disclosure
{...nestedMenuSettings}
>
<MenuBarItem
id={item.id}
aria-label={item.menu.label}
label={item.menu.label}
icon={item.menu.icon}
title={item.menu.tooltip || item.menu.label}
loading={loading}
disabled={disabled}
style={style}
{...use({ hidden: item.hidden })}
/>
</ContextMenu>
);
});
@@ -22,22 +22,23 @@ interface Props extends Omit<React.DetailedHTMLProps<ButtonHTMLAttributes<HTMLBu
style?: ComponentStyle;
}
export const MenuBarItem = observer<Props>(function MenuBarItem({
export const MenuBarItem = observer<Props, HTMLButtonElement>(function MenuBarItem({
label,
loading = false,
icon,
viewBox = '0 0 24 24',
style = [],
...rest
}) {
}, ref) {
const translate = useTranslate();
loading = useStateDelay(loading, 100);
const title = translate(rest.title);
return styled(useStyles(style))(
<menu-bar-item as='button' {...rest} title={translate(rest.title)}>
<menu-bar-item as='button' ref={ref} {...rest} title={title} aria-label={title}>
{loading && <Loader small fullSize />}
{!loading && icon && <IconOrImage icon={icon} viewBox={viewBox} />}
{label && <item-label><Translate token={label} /></item-label>}
</menu-bar-item>
);
});
}, { forwardRef: true });
@@ -40,7 +40,7 @@ export const MenuPanelItem = observer<MenuPanelItemProps>(function MenuPanelItem
loading = useStateDelay(loading, 100);
return styled(useStyles(menuPanelStyles, style))(
<menu-panel-item title={tooltip}>
<menu-panel-item title={tooltip ? translate(tooltip) : title}>
<menu-item-content>
{typeof icon === 'string' ? <IconOrImage icon={icon} /> : icon}
</menu-item-content>
@@ -11,20 +11,27 @@ import type { IMenuItemEvents } from './IMenuItem';
import { MenuItem } from './MenuItem';
export class MenuBaseItem extends MenuItem implements IMenuBaseItem {
private readonly isDisabled?: () => boolean;
readonly label: string;
readonly icon?: string;
readonly tooltip?: string;
readonly hidden?: boolean;
readonly disabled?: boolean;
get disabled(): boolean {
return this.isDisabled?.() ?? false;
}
constructor(
id: string,
label: string,
tooltip?: string,
events?: IMenuItemEvents
events?: IMenuItemEvents,
isDisabled?: () => boolean
) {
super(id, events);
this.label = label;
this.tooltip = tooltip;
this.isDisabled = isDisabled;
}
}
@@ -7,45 +7,67 @@
*/
import { EAdminPermission, AdministrationScreenService } from '@cloudbeaver/core-administration';
import { SettingsMenuService } from '@cloudbeaver/core-app';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { PermissionsService } from '@cloudbeaver/core-root';
import { ScreenService } from '@cloudbeaver/core-routing';
import { DATA_CONTEXT_MENU, MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
import { TOP_NAV_BAR_SETTINGS_MENU } from '@cloudbeaver/plugin-settings-menu';
@injectable()
export class PluginBootstrap extends Bootstrap {
constructor(
private settingsMenuService: SettingsMenuService,
private permissionsService: PermissionsService,
private screenService: ScreenService,
private administrationScreenService: AdministrationScreenService,
private readonly permissionsService: PermissionsService,
private readonly screenService: ScreenService,
private readonly administrationScreenService: AdministrationScreenService,
private readonly menuService: MenuService
) {
super();
}
register(): void {
this.settingsMenuService.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: 'administrationMenuEnter',
order: 0,
isHidden: () => !this.permissionsService.has(EAdminPermission.admin)
|| this.screenService.isActive(AdministrationScreenService.screenName),
title: 'administration_menu_enter',
onClick: () => this.administrationScreenService.navigateToRoot(),
this.menuService.addCreator({
isApplicable: (context) => context.get(DATA_CONTEXT_MENU) === TOP_NAV_BAR_SETTINGS_MENU,
getItems: (context, items) => {
const administrationScreen = this.screenService.isActive(AdministrationScreenService.screenName);
if (this.permissionsService.has(EAdminPermission.admin) && !administrationScreen) {
return [
...items,
new MenuBaseItem(
'administrationMenuEnter',
'administration_menu_enter',
'administration_menu_enter',
{ onSelect: () => this.administrationScreenService.navigateToRoot() }
)
]
}
if (administrationScreen) {
return [
...items,
new MenuBaseItem(
'administrationMenuBack',
'administration_menu_back',
'administration_menu_back',
{ onSelect: () => this.screenService.navigateToRoot() }
)
]
}
return items;
},
orderItems: (context, items) => {
const index = items.findIndex(item => item.id === 'administrationMenuBack' || item.id === 'administrationMenuEnter');
if (index > -1) {
const item = items.splice(index, 1);
items.unshift(item[0]);
}
return items;
}
);
this.settingsMenuService.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: 'administrationMenuBack',
order: 0,
isHidden: () => !this.screenService.isActive(AdministrationScreenService.screenName),
title: 'administration_menu_back',
onClick: () => this.screenService.navigateToRoot(),
}
);
});
}
load(): void {}
load(): void { }
}
@@ -6,10 +6,11 @@
* you may not use this file except in compliance with the License.
*/
import { SettingsMenuService } from '@cloudbeaver/core-app';
import { AuthInfoService } from '@cloudbeaver/core-authentication';
import { injectable, Bootstrap } from '@cloudbeaver/core-di';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import { DATA_CONTEXT_MENU, MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
import { TOP_NAV_BAR_SETTINGS_MENU } from '@cloudbeaver/plugin-settings-menu';
import { AuthenticationService } from './AuthenticationService';
import { AuthDialogService } from './Dialog/AuthDialogService';
@@ -21,33 +22,52 @@ export class PluginBootstrap extends Bootstrap {
private readonly authDialogService: AuthDialogService,
private readonly authenticationService: AuthenticationService,
private readonly authInfoService: AuthInfoService,
private readonly settingsMenuService: SettingsMenuService,
private readonly menuService: MenuService,
) {
super();
}
register(): void {
this.settingsMenuService.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: 'login',
order: 0,
isHidden: () => this.serverConfigResource.enabledAuthProviders.length === 0 || !!this.authInfoService.userInfo,
title: 'authentication_login',
onClick: () => this.authDialogService.showLoginForm(false, null, true),
}
);
this.menuService.addCreator({
isApplicable: (context) => context.get(DATA_CONTEXT_MENU) === TOP_NAV_BAR_SETTINGS_MENU,
getItems: (context, items) => {
if (this.serverConfigResource.enabledAuthProviders.length > 0 && !this.authInfoService.userInfo) {
return [
...items,
new MenuBaseItem(
'login',
'authentication_login',
'authentication_login',
{ onSelect: () => this.authDialogService.showLoginForm(false, null, true) }
)
]
};
this.settingsMenuService.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: 'logout',
order: Number.MAX_SAFE_INTEGER,
isHidden: () => !this.authInfoService.userInfo,
title: 'authentication_logout',
onClick: this.authenticationService.logout.bind(this.authenticationService),
if (this.authInfoService.userInfo) {
return [
...items,
new MenuBaseItem(
'logout',
'authentication_logout',
'authentication_logout',
{ onSelect: this.authenticationService.logout.bind(this.authenticationService) }
)
]
}
return items;
},
orderItems: (context, items) => {
const index = items.findIndex(item => item.id === 'logout' || item.id === 'login')
if (index > -1) {
const item = items.splice(index, 1);
items.push(item[0]);
}
return items;
}
);
});
}
load(): void | Promise<void> { }
@@ -0,0 +1,17 @@
# dependencies
/node_modules
# testing
/coverage
# production
/lib
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
@@ -0,0 +1,46 @@
{
"name": "@cloudbeaver/plugin-localization",
"sideEffects": false,
"version": "0.1.0",
"description": "",
"license": "Apache-2.0",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "src/index.ts",
"scripts": {
"prebuild": "rimraf lib/*",
"build": "webpack --config ../../configs/webpack.plugin.config.js",
"postbuild": "tsc",
"lint": "eslint ./src/ --ext .ts,.tsx",
"lint-fix": "eslint ./src/ --ext .ts,.tsx --fix"
},
"peerDependencies": {
"@cloudbeaver/core-administration": "^0.1.0",
"@cloudbeaver/core-app": "^0.1.0",
"@cloudbeaver/core-authentication": "^0.1.0",
"@cloudbeaver/core-blocks": "^0.1.0",
"@cloudbeaver/core-connections": "^0.1.0",
"@cloudbeaver/core-di": "^0.1.0",
"@cloudbeaver/core-dialogs": "^0.1.0",
"@cloudbeaver/core-events": "^0.1.0",
"@cloudbeaver/core-executor": "^0.1.0",
"@cloudbeaver/core-extensions": "^0.1.0",
"@cloudbeaver/core-localization": "^0.1.0",
"@cloudbeaver/core-notifications": "^0.1.0",
"@cloudbeaver/core-plugin": "^0.1.0",
"@cloudbeaver/core-product": "^0.1.0",
"@cloudbeaver/core-root": "^0.1.0",
"@cloudbeaver/core-routing": "^0.1.0",
"@cloudbeaver/core-sdk": "^0.1.0",
"@cloudbeaver/core-settings": "^0.1.0",
"@cloudbeaver/core-theming": "^0.1.0",
"@cloudbeaver/core-ui": "^0.1.0",
"@cloudbeaver/core-utils": "^0.1.0",
"@cloudbeaver/core-view": "^0.1.0",
"@cloudbeaver/plugin-settings-menu": "^0.1.0",
"react": "^17.x.x",
"mobx": "^6.x.x",
"mobx-react-lite": "^3.x.x",
"reshadow": "^0.x.x"
}
}
@@ -0,0 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { createMenu } from '@cloudbeaver/core-view';
export const LOCALIZATION_MENU = createMenu('localization-menu', 'app_shared_settingsMenu_lang');
@@ -0,0 +1,77 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import { LocalizationService } from '@cloudbeaver/core-localization';
import { DATA_CONTEXT_MENU, MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
import { TOP_NAV_BAR_SETTINGS_MENU } from '@cloudbeaver/plugin-settings-menu';
import { LOCALIZATION_MENU } from './LOCALIZATION_MENU';
@injectable()
export class PluginBootstrap extends Bootstrap {
constructor(
private readonly localizationService: LocalizationService,
private readonly menuService: MenuService,
private readonly serverConfigResource: ServerConfigResource
) {
super();
}
register(): void | Promise<void> {
this.menuService.setHandler({
id: 'localization-menu',
isApplicable: (context) => context.get(DATA_CONTEXT_MENU) === LOCALIZATION_MENU,
isLoading: () => this.serverConfigResource.isLoading(),
handler: () => this.serverConfigResource.load(),
})
this.menuService.addCreator({
isApplicable: context => {
return context.get(DATA_CONTEXT_MENU) === TOP_NAV_BAR_SETTINGS_MENU && !!this.serverConfigResource.data?.supportedLanguages.length
},
getItems(context, items) {
return [
...items,
LOCALIZATION_MENU
]
},
});
this.menuService.addCreator({
isApplicable: context => context.get(DATA_CONTEXT_MENU) === LOCALIZATION_MENU,
getItems: (context, items) => {
const supportedLanguages = this.serverConfigResource.data?.supportedLanguages;
if (!supportedLanguages?.length) {
return items;
}
const languages = supportedLanguages.map(lang => {
const label = lang.nativeName || lang.isoCode;
return new MenuBaseItem(
lang.isoCode,
label,
label,
{ onSelect: () => this.localizationService.changeLocaleAsync(lang.isoCode) },
() => this.localizationService.getCurrentLanguage() === lang.isoCode
)
})
return [
...items,
...languages
]
},
});
}
load(): void | Promise<void> { }
}
@@ -0,0 +1,5 @@
import { localizationPlugin } from './manifest';
export default localizationPlugin;
export * from './LOCALIZATION_MENU';
@@ -0,0 +1,17 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 type { PluginManifest } from '@cloudbeaver/core-di';
import { PluginBootstrap } from './PluginBootstrap';
export const localizationPlugin: PluginManifest = {
info: { name: 'Localization plugin' },
providers: [
PluginBootstrap,
],
};
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"composite": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules",
"**/.*/"
],
}
@@ -54,6 +54,12 @@ const itemStyles = css`
menu-icon {
padding-right: 8px;
}
menu-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 500px;
}
TableColumnValue:not(:hover):not([|menuOpened]) {
& Icon {
opacity: 0;
@@ -185,7 +191,7 @@ const ItemName = observer<IItemNameProps>(function ItemName({
<menu-icon><Icon name="snack" viewBox="0 0 16 10" /></menu-icon>
</ContextMenu>
)}
<menu-name>{name}</menu-name>
<menu-name title={name}>{name}</menu-name>
</menu-box>
</TableColumnValue>
);
@@ -6,36 +6,40 @@
* you may not use this file except in compliance with the License.
*/
import { SettingsMenuService } from '@cloudbeaver/core-app';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
import { DATA_CONTEXT_MENU, MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import { TOP_NAV_BAR_SETTINGS_MENU } from '@cloudbeaver/plugin-settings-menu';
import { ProductInfoDialog } from './ProductInfoDialog';
@injectable()
export class ProductBootstrap extends Bootstrap {
private productInfoMenuToken = 'productInfoMenu';
constructor(
private settingsMenuService: SettingsMenuService,
private serverConfigResource: ServerConfigResource,
private commonDialogService: CommonDialogService
private readonly serverConfigResource: ServerConfigResource,
private readonly commonDialogService: CommonDialogService,
private readonly menuService: MenuService,
) {
super();
}
register(): void | Promise<void> {
this.settingsMenuService.addMenuItem(
SettingsMenuService.settingsMenuToken,
{
id: this.productInfoMenuToken,
order: 3,
title: 'app_product_info',
isHidden: () => !this.serverConfigResource.data?.productInfo,
onClick: async () => await this.commonDialogService.open(ProductInfoDialog, null),
}
);
this.menuService.addCreator({
isApplicable: (context) => {
return context.get(DATA_CONTEXT_MENU) === TOP_NAV_BAR_SETTINGS_MENU && !!this.serverConfigResource.data?.productInfo
},
getItems: (context, items) => [
...items,
new MenuBaseItem(
'productInfo',
'app_product_info',
'app_product_info',
{ onSelect: () => this.commonDialogService.open(ProductInfoDialog, null) }
)
]
});
}
load(): void | Promise<void> { }
@@ -0,0 +1,17 @@
# dependencies
/node_modules
# testing
/coverage
# production
/lib
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
@@ -0,0 +1,46 @@
{
"name": "@cloudbeaver/plugin-settings-menu-administration",
"sideEffects": false,
"version": "0.1.0",
"description": "",
"license": "Apache-2.0",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "src/index.ts",
"scripts": {
"prebuild": "rimraf lib/*",
"build": "webpack --config ../../configs/webpack.plugin.config.js",
"postbuild": "tsc",
"lint": "eslint ./src/ --ext .ts,.tsx",
"lint-fix": "eslint ./src/ --ext .ts,.tsx --fix"
},
"peerDependencies": {
"@cloudbeaver/core-administration": "^0.1.0",
"@cloudbeaver/core-app": "^0.1.0",
"@cloudbeaver/core-authentication": "^0.1.0",
"@cloudbeaver/core-blocks": "^0.1.0",
"@cloudbeaver/core-connections": "^0.1.0",
"@cloudbeaver/core-di": "^0.1.0",
"@cloudbeaver/core-dialogs": "^0.1.0",
"@cloudbeaver/core-events": "^0.1.0",
"@cloudbeaver/core-executor": "^0.1.0",
"@cloudbeaver/core-extensions": "^0.1.0",
"@cloudbeaver/core-localization": "^0.1.0",
"@cloudbeaver/core-notifications": "^0.1.0",
"@cloudbeaver/core-plugin": "^0.1.0",
"@cloudbeaver/core-product": "^0.1.0",
"@cloudbeaver/core-root": "^0.1.0",
"@cloudbeaver/core-routing": "^0.1.0",
"@cloudbeaver/core-sdk": "^0.1.0",
"@cloudbeaver/core-settings": "^0.1.0",
"@cloudbeaver/core-theming": "^0.1.0",
"@cloudbeaver/core-ui": "^0.1.0",
"@cloudbeaver/core-utils": "^0.1.0",
"@cloudbeaver/core-view": "^0.1.0",
"@cloudbeaver/plugin-settings-menu": "^0.1.0",
"react": "^17.x.x",
"mobx": "^6.x.x",
"mobx-react-lite": "^3.x.x",
"reshadow": "^0.x.x"
}
}
@@ -0,0 +1,26 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { AdministrationTopAppBarService } from '@cloudbeaver/core-administration';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { SettingsMenu } from '@cloudbeaver/plugin-settings-menu';
@injectable()
export class PluginBootstrap extends Bootstrap {
constructor(
private readonly administrationTopAppBarService: AdministrationTopAppBarService
) {
super();
}
register(): void | Promise<void> {
this.administrationTopAppBarService.placeholder.add(SettingsMenu, 5);
}
load(): void | Promise<void> { }
}
@@ -0,0 +1,3 @@
import { settingsMenuAdministrationPlugin } from './manifest';
export default settingsMenuAdministrationPlugin;
@@ -0,0 +1,17 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 type { PluginManifest } from '@cloudbeaver/core-di';
import { PluginBootstrap } from './PluginBootstrap';
export const settingsMenuAdministrationPlugin: PluginManifest = {
info: { name: 'Settings menu administration plugin' },
providers: [
PluginBootstrap,
],
};
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"composite": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules",
"**/.*/"
],
}
@@ -0,0 +1,17 @@
# dependencies
/node_modules
# testing
/coverage
# production
/lib
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
@@ -0,0 +1,45 @@
{
"name": "@cloudbeaver/plugin-settings-menu",
"sideEffects": false,
"version": "0.1.0",
"description": "",
"license": "Apache-2.0",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "src/index.ts",
"scripts": {
"prebuild": "rimraf lib/*",
"build": "webpack --config ../../configs/webpack.plugin.config.js",
"postbuild": "tsc",
"lint": "eslint ./src/ --ext .ts,.tsx",
"lint-fix": "eslint ./src/ --ext .ts,.tsx --fix"
},
"peerDependencies": {
"@cloudbeaver/core-administration": "^0.1.0",
"@cloudbeaver/core-app": "^0.1.0",
"@cloudbeaver/core-authentication": "^0.1.0",
"@cloudbeaver/core-blocks": "^0.1.0",
"@cloudbeaver/core-connections": "^0.1.0",
"@cloudbeaver/core-di": "^0.1.0",
"@cloudbeaver/core-dialogs": "^0.1.0",
"@cloudbeaver/core-events": "^0.1.0",
"@cloudbeaver/core-executor": "^0.1.0",
"@cloudbeaver/core-extensions": "^0.1.0",
"@cloudbeaver/core-localization": "^0.1.0",
"@cloudbeaver/core-notifications": "^0.1.0",
"@cloudbeaver/core-plugin": "^0.1.0",
"@cloudbeaver/core-product": "^0.1.0",
"@cloudbeaver/core-root": "^0.1.0",
"@cloudbeaver/core-routing": "^0.1.0",
"@cloudbeaver/core-sdk": "^0.1.0",
"@cloudbeaver/core-settings": "^0.1.0",
"@cloudbeaver/core-theming": "^0.1.0",
"@cloudbeaver/core-ui": "^0.1.0",
"@cloudbeaver/core-utils": "^0.1.0",
"@cloudbeaver/core-view": "^0.1.0",
"react": "^17.x.x",
"mobx": "^6.x.x",
"mobx-react-lite": "^3.x.x",
"reshadow": "^0.x.x"
}
}
@@ -0,0 +1,26 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { TopNavService } from '@cloudbeaver/core-app';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { SettingsMenu } from './SettingsMenu/SettingsMenu';
@injectable()
export class PluginBootstrap extends Bootstrap {
constructor(
private readonly topNavService: TopNavService
) {
super();
}
register(): void | Promise<void> {
this.topNavService.placeholder.add(SettingsMenu, 5);
}
load(): void | Promise<void> { }
}
@@ -9,21 +9,27 @@
import { observer } from 'mobx-react-lite';
import styled from 'reshadow';
import { Icon } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { MenuTrigger } from '@cloudbeaver/core-dialogs';
import { useStyles } from '@cloudbeaver/core-theming';
import { ContextMenu } from '@cloudbeaver/core-ui';
import { useMenu } from '@cloudbeaver/core-view';
import { Icon } from '@cloudbeaver/core-blocks';
import { topMenuStyles } from '@cloudbeaver/core-app';
import { topMenuStyles } from '../shared/topMenuStyles';
import { SettingsMenuService } from './SettingsMenuService';
import { settingsMenuStyles } from './settingsMenuStyles';
import { TOP_NAV_BAR_SETTINGS_MENU } from './TOP_NAV_BAR_SETTINGS_MENU';
export const SettingsMenu = observer(function SettingsMenu() {
const settingsMenuService = useService(SettingsMenuService);
const menu = useMenu(TOP_NAV_BAR_SETTINGS_MENU);
return styled(useStyles(settingsMenuStyles))(
<MenuTrigger panel={settingsMenuService.getMenu()} style={[topMenuStyles, settingsMenuStyles]} placement='bottom-end' modal rtl>
<ContextMenu
menu={menu}
style={[topMenuStyles, settingsMenuStyles]}
placement='bottom-end'
modal
rtl
>
<Icon name="settings" viewBox="0 0 28 28" />
</MenuTrigger>
</ContextMenu>
);
});
});
@@ -0,0 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { createMenu } from '@cloudbeaver/core-view';
export const TOP_NAV_BAR_SETTINGS_MENU = createMenu('top-nav-bar-settings', 'ui_settings', 'settings', 'ui_settings');
@@ -9,7 +9,7 @@
import { css } from 'reshadow';
export const settingsMenuStyles = css`
MenuTrigger {
ContextMenu {
padding: 0 16px !important;
height: 48px;
cursor: pointer;
@@ -33,4 +33,4 @@ export const settingsMenuStyles = css`
transform: rotate(90deg);
}
}
`;
`;
@@ -0,0 +1,6 @@
import { settingsMenuPlugin } from './manifest';
export default settingsMenuPlugin;
export * from './SettingsMenu/SettingsMenu';
export * from './SettingsMenu/TOP_NAV_BAR_SETTINGS_MENU';
@@ -0,0 +1,17 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 type { PluginManifest } from '@cloudbeaver/core-di';
import { PluginBootstrap } from './PluginBootstrap';
export const settingsMenuPlugin: PluginManifest = {
info: { name: 'Settings menu plugin' },
providers: [
PluginBootstrap,
],
};
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"composite": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules",
"**/.*/"
],
}
+17
View File
@@ -0,0 +1,17 @@
# dependencies
/node_modules
# testing
/coverage
# production
/lib
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+46
View File
@@ -0,0 +1,46 @@
{
"name": "@cloudbeaver/plugin-theme",
"sideEffects": false,
"version": "0.1.0",
"description": "",
"license": "Apache-2.0",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "src/index.ts",
"scripts": {
"prebuild": "rimraf lib/*",
"build": "webpack --config ../../configs/webpack.plugin.config.js",
"postbuild": "tsc",
"lint": "eslint ./src/ --ext .ts,.tsx",
"lint-fix": "eslint ./src/ --ext .ts,.tsx --fix"
},
"peerDependencies": {
"@cloudbeaver/core-administration": "^0.1.0",
"@cloudbeaver/core-app": "^0.1.0",
"@cloudbeaver/core-authentication": "^0.1.0",
"@cloudbeaver/core-blocks": "^0.1.0",
"@cloudbeaver/core-connections": "^0.1.0",
"@cloudbeaver/core-di": "^0.1.0",
"@cloudbeaver/core-dialogs": "^0.1.0",
"@cloudbeaver/core-events": "^0.1.0",
"@cloudbeaver/core-executor": "^0.1.0",
"@cloudbeaver/core-extensions": "^0.1.0",
"@cloudbeaver/core-localization": "^0.1.0",
"@cloudbeaver/core-notifications": "^0.1.0",
"@cloudbeaver/core-plugin": "^0.1.0",
"@cloudbeaver/core-product": "^0.1.0",
"@cloudbeaver/core-root": "^0.1.0",
"@cloudbeaver/core-routing": "^0.1.0",
"@cloudbeaver/core-sdk": "^0.1.0",
"@cloudbeaver/core-settings": "^0.1.0",
"@cloudbeaver/core-theming": "^0.1.0",
"@cloudbeaver/core-ui": "^0.1.0",
"@cloudbeaver/core-utils": "^0.1.0",
"@cloudbeaver/core-view": "^0.1.0",
"@cloudbeaver/plugin-settings-menu": "^0.1.0",
"react": "^17.x.x",
"mobx": "^6.x.x",
"mobx-react-lite": "^3.x.x",
"reshadow": "^0.x.x"
}
}
@@ -0,0 +1,62 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { ThemeService } from '@cloudbeaver/core-theming';
import { DATA_CONTEXT_MENU, MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
import { TOP_NAV_BAR_SETTINGS_MENU } from '@cloudbeaver/plugin-settings-menu';
import { THEME_MENU } from './THEME_MENU';
@injectable()
export class PluginBootstrap extends Bootstrap {
constructor(
private readonly menuService: MenuService,
private readonly themeService: ThemeService
) {
super();
}
register(): void | Promise<void> {
this.menuService.addCreator({
isApplicable: (context) => {
return context.get(DATA_CONTEXT_MENU) === TOP_NAV_BAR_SETTINGS_MENU && this.themeService.themes.length > 0;
},
getItems(context, items) {
return [
...items,
THEME_MENU
]
},
});
this.menuService.addCreator({
isApplicable(context) {
return context.get(DATA_CONTEXT_MENU) === THEME_MENU
},
getItems: (context, items) => {
const themes = this.themeService.themes.map(theme => new MenuBaseItem(
theme.id,
theme.name,
theme.name,
{
onSelect: () => this.themeService.changeThemeAsync(theme.id)
},
() => this.themeService.currentThemeId === theme.id,
))
return [
...items,
...themes
]
},
});
}
load(): void | Promise<void> { }
}
@@ -0,0 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { createMenu } from '@cloudbeaver/core-view';
export const THEME_MENU = createMenu('theme-menu', 'app_shared_settingsMenu_theme');
@@ -0,0 +1,5 @@
import { themePlugin } from './manifest';
export default themePlugin;
export * from './THEME_MENU';
@@ -0,0 +1,17 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 type { PluginManifest } from '@cloudbeaver/core-di';
import { PluginBootstrap } from './PluginBootstrap';
export const themePlugin: PluginManifest = {
info: { name: 'Theme plugin' },
providers: [
PluginBootstrap,
],
};
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"composite": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules",
"**/.*/"
],
}
+5 -1
View File
@@ -22,6 +22,8 @@
"@cloudbeaver/core-bootstrap": "0.1.0",
"@cloudbeaver/core-di": "0.1.0",
"@cloudbeaver/core-product": "0.1.0",
"@cloudbeaver/plugin-theme": "0.1.0",
"@cloudbeaver/plugin-localization": "0.1.0",
"@cloudbeaver/plugin-administration": "0.1.0",
"@cloudbeaver/plugin-authentication": "0.1.0",
"@cloudbeaver/plugin-authentication-administration": "0.1.0",
@@ -35,7 +37,9 @@
"@cloudbeaver/plugin-sql-editor": "0.1.0",
"@cloudbeaver/plugin-sql-editor-navigation-tab": "0.1.0",
"@cloudbeaver/plugin-sql-editor-screen": "0.1.0",
"@cloudbeaver/plugin-version-update-administration": "0.1.0"
"@cloudbeaver/plugin-version-update-administration": "0.1.0",
"@cloudbeaver/plugin-settings-menu": "0.1.0",
"@cloudbeaver/plugin-settings-menu-administration": "0.1.0"
},
"product": {
"name": "CloudBeaver Community"
@@ -5,6 +5,8 @@ import type { PluginManifest } from '@cloudbeaver/core-di';
import administration from '@cloudbeaver/plugin-administration';
import authentication from '@cloudbeaver/plugin-authentication';
import authenticationAdministration from '@cloudbeaver/plugin-authentication-administration';
import theme from '@cloudbeaver/plugin-theme';
import localization from '@cloudbeaver/plugin-localization';
import connectionCustom from '@cloudbeaver/plugin-connection-custom';
import connectionTemplate from '@cloudbeaver/plugin-connection-template';
import connectionPlugin from '@cloudbeaver/plugin-connections';
@@ -22,6 +24,8 @@ import sqlEditorScreen from '@cloudbeaver/plugin-sql-editor-screen';
import userProfile from '@cloudbeaver/plugin-user-profile';
import userProfileAdministration from '@cloudbeaver/plugin-user-profile-administration';
import versionUpdate from '@cloudbeaver/plugin-version-update-administration';
import settingsMenu from '@cloudbeaver/plugin-settings-menu';
import settingsMenuAdministration from '@cloudbeaver/plugin-settings-menu-administration';
import { defaultProductManifest } from './manifest';
@@ -30,6 +34,8 @@ const PLUGINS: PluginManifest[] = [
spreadsheetNew,
authentication,
authenticationAdministration,
theme,
localization,
connectionCustom,
connectionTemplate,
dataExport,
@@ -47,6 +53,8 @@ const PLUGINS: PluginManifest[] = [
connectionAdministration,
versionUpdate,
productPlugin,
settingsMenu,
settingsMenuAdministration,
];
bootstrap(PLUGINS);