diff --git a/webapp/packages/core-app/src/ProductInfoDialog.tsx b/webapp/packages/core-app/src/ProductInfoDialog.tsx new file mode 100644 index 0000000000..c9e7e7e54d --- /dev/null +++ b/webapp/packages/core-app/src/ProductInfoDialog.tsx @@ -0,0 +1,102 @@ +/* + * 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 { observer } from 'mobx-react-lite'; +import styled, { css } from 'reshadow'; + +import { BASE_CONTAINERS_STYLES, Button, ColoredContainer, FormFieldDescriptionNew, Group, IconOrImage } from '@cloudbeaver/core-blocks'; +import { Link } from '@cloudbeaver/core-blocks'; +import { CommonDialogWrapper, DialogComponentProps } from '@cloudbeaver/core-dialogs'; +import { useTranslate } from '@cloudbeaver/core-localization'; +import type { ServerConfig } from '@cloudbeaver/core-sdk'; +import { composes, useStyles } from '@cloudbeaver/core-theming'; + +import { useAppVersion } from './useAppVersion'; + +const productInfoDialogStyles = composes( + css` + IconOrImage { + composes: theme-background-primary from global; + } + `, + css` + CommonDialogWrapper { + min-width: 600px; + min-height: 90vh; + } + controls { + display: flex; + flex: 1; + height: 100%; + align-items: center; + justify-content: flex-end; + } + contacts-info { + display: flex; + white-space: pre-wrap; + } + IconOrImage { + padding: 10px; + border-radius: 2px; + } +`); + +export const ProductInfoDialog: React.FC> = observer( + function ProductInfoDialog(props) { + const translate = useTranslate(); + const styles = useStyles(BASE_CONTAINERS_STYLES, productInfoDialogStyles); + const version = useAppVersion(); + + const productInfo = props.payload.productInfo; + + return styled(styles)( + + + + )} + onReject={props.rejectDialog} + > + + + + + {productInfo.name} + + + {productInfo.description} + + + {productInfo.licenseInfo} + + + {productInfo.buildTime} + + + {productInfo.version} + + + {version.frontendVersion} + + + You can contact us via our + Site + or + Github + + + + + + ); + } +); diff --git a/webapp/packages/core-app/src/TopNavBar/SettingsMenu/SettingsMenuService.ts b/webapp/packages/core-app/src/TopNavBar/SettingsMenu/SettingsMenuService.ts index e6110ba50e..ceccab080f 100644 --- a/webapp/packages/core-app/src/TopNavBar/SettingsMenu/SettingsMenuService.ts +++ b/webapp/packages/core-app/src/TopNavBar/SettingsMenu/SettingsMenuService.ts @@ -8,12 +8,14 @@ import { EAdminPermission, AdministrationScreenService } from '@cloudbeaver/core-administration'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; -import { IComputedMenuItemOptions, IMenuPanel, StaticMenu } from '@cloudbeaver/core-dialogs'; +import { CommonDialogService, IComputedMenuItemOptions, IMenuPanel, StaticMenu } from '@cloudbeaver/core-dialogs'; import { LocalizationService } from '@cloudbeaver/core-localization'; import { ServerConfigResource, PermissionsService } from '@cloudbeaver/core-root'; import { ScreenService } from '@cloudbeaver/core-routing'; import { ThemeService } from '@cloudbeaver/core-theming'; +import { ProductInfoDialog } from '../../ProductInfoDialog'; + @injectable() export class SettingsMenuService extends Bootstrap { static settingsMenuToken = 'settingsMenu'; @@ -21,6 +23,7 @@ export class SettingsMenuService extends Bootstrap { private menu = new StaticMenu(); private langMenuToken = 'langMenu'; private themeMenuToken = 'themeMenu'; + private productInfoMenuToken = 'productInfoMenuToken'; constructor( private localizationService: LocalizationService, @@ -28,7 +31,8 @@ export class SettingsMenuService extends Bootstrap { private permissionsService: PermissionsService, private serverConfigResource: ServerConfigResource, private screenService: ScreenService, - private administrationScreenService: AdministrationScreenService + private administrationScreenService: AdministrationScreenService, + private commonDialogService: CommonDialogService ) { super(); } @@ -41,6 +45,7 @@ export class SettingsMenuService extends Bootstrap { this.addAdministration(); this.addThemes(); await this.addLocales(); + await this.addProductInfo(); } getMenu(): IMenuPanel { @@ -128,4 +133,22 @@ export class SettingsMenuService extends Bootstrap { ); }); } + + private async addProductInfo() { + const config = await this.serverConfigResource.load(); + + if (!config) { + return; + } + + this.addMenuItem( + SettingsMenuService.settingsMenuToken, + { + id: this.productInfoMenuToken, + order: 3, + title: 'app_product_info', + onClick: async () => await this.commonDialogService.open(ProductInfoDialog, config), + } + ); + } } diff --git a/webapp/packages/core-app/src/locales/en.ts b/webapp/packages/core-app/src/locales/en.ts index 35a9f0eb99..4a00ff35db 100644 --- a/webapp/packages/core-app/src/locales/en.ts +++ b/webapp/packages/core-app/src/locales/en.ts @@ -22,6 +22,12 @@ export default [ 'app_shared_navigationTabsBar_placeholder', 'There are no objects to show. Double click on an object in the navigation tree to open it.', ], + ['app_product_info', 'Product information'], + ['app_product_info_name', 'Product name'], + ['app_product_info_description', 'Product description'], + ['app_product_info_license_info', 'License information'], + ['app_product_info_build_time', 'Build time'], + ['app_product_info_contacts', 'Contacts'], ['app_log_view_clear_log', 'Clear logs'], ['app_log_view_entry_type', 'Type'], ['app_log_view_entry_timestamp', 'Timestamp'], diff --git a/webapp/packages/core-app/src/locales/ru.ts b/webapp/packages/core-app/src/locales/ru.ts index 9ab94a9074..8a9ce613bb 100644 --- a/webapp/packages/core-app/src/locales/ru.ts +++ b/webapp/packages/core-app/src/locales/ru.ts @@ -21,6 +21,12 @@ export default [ ['app_shared_inlineEditor_dialog_title', 'Редактирование'], ['app_shared_inlineEditor_dialog_apply', 'Применить'], ['app_shared_inlineEditor_dialog_cancel', 'Отменить'], + ['app_product_info', 'Информация о продукте'], + ['app_product_info_name', 'Название продукта'], + ['app_product_info_description', 'Описание продукта'], + ['app_product_info_license_info', 'Информация о лицензии'], + ['app_product_info_build_time', 'Время последней сборки'], + ['app_product_info_contacts', 'Контакты'], ['app_log_view_clear_log', 'Очистить лог'], ['app_log_view_entry_type', 'Тип'], ['app_log_view_entry_timestamp', 'Время'], diff --git a/webapp/packages/core-app/src/useAppVersion.tsx b/webapp/packages/core-app/src/useAppVersion.tsx index 4f55b34ef4..2b9d42809a 100644 --- a/webapp/packages/core-app/src/useAppVersion.tsx +++ b/webapp/packages/core-app/src/useAppVersion.tsx @@ -1,3 +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 { useService } from '@cloudbeaver/core-di'; import { ServerService } from '@cloudbeaver/core-root'; diff --git a/webapp/packages/core-blocks/src/index.ts b/webapp/packages/core-blocks/src/index.ts index fef608dccc..1861ea4e07 100644 --- a/webapp/packages/core-blocks/src/index.ts +++ b/webapp/packages/core-blocks/src/index.ts @@ -61,6 +61,7 @@ export * from './FormControls/Switch'; export * from './FormControls/SwitchNew'; export * from './FormControls/Textarea'; export * from './FormControls/TextareaNew'; +export * from './Link'; export * from './ErrorMessage'; export * from './ExceptionMessage'; export * from './IconButton'; diff --git a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql index 6cc3ab32ab..6fe22573f6 100644 --- a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql +++ b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql @@ -29,5 +29,14 @@ query serverConfig { defaultNavigatorSettings { ...AllNavigatorSettings } + productInfo { + id + version + name + description + buildTime + releaseTime + licenseInfo + } } } diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index f6b68c660c..831c7e5685 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -1540,7 +1540,7 @@ export type ServerConfigQueryVariables = Exact<{ [key: string]: never }>; export interface ServerConfigQuery { serverConfig: ( Pick - & { supportedLanguages: Array>; defaultNavigatorSettings: AllNavigatorSettingsFragment } + & { supportedLanguages: Array>; defaultNavigatorSettings: AllNavigatorSettingsFragment; productInfo: Pick } ); } @@ -2475,6 +2475,15 @@ export const ServerConfigDocument = ` defaultNavigatorSettings { ...AllNavigatorSettings } + productInfo { + id + version + name + description + buildTime + releaseTime + licenseInfo + } } } ${AllNavigatorSettingsFragmentDoc}`;