From 9aacfff6619e192dee5855bc281771a5c8b17bb2 Mon Sep 17 00:00:00 2001 From: Wroud Date: Thu, 25 Aug 2022 14:50:25 +0300 Subject: [PATCH] feat(plugin-connections): CB-2405 project selection for connection form --- .../core-connections/src/locales/en.ts | 1 + .../core-connections/src/locales/it.ts | 2 +- .../core-connections/src/locales/ru.ts | 1 + .../core-connections/src/locales/zh.ts | 1 + .../src/ConnectionForm/ConnectionFormState.ts | 8 ++++- .../ConnectionForm/IConnectionFormProps.ts | 1 + .../Options/ConnectionOptionsTabService.ts | 13 +++++-- .../src/ConnectionForm/Options/Options.tsx | 34 +++++++++++++++++-- .../plugin-connections/src/locales/en.ts | 3 ++ .../plugin-connections/src/locales/it.ts | 3 ++ .../plugin-connections/src/locales/ru.ts | 3 ++ .../plugin-connections/src/locales/zh.ts | 3 ++ 12 files changed, 67 insertions(+), 6 deletions(-) diff --git a/webapp/packages/core-connections/src/locales/en.ts b/webapp/packages/core-connections/src/locales/en.ts index a0184a1ddb..345d2d9669 100644 --- a/webapp/packages/core-connections/src/locales/en.ts +++ b/webapp/packages/core-connections/src/locales/en.ts @@ -39,6 +39,7 @@ export default [ ['connections_connection_access_filter_placeholder', 'Search for user or role name'], ['connections_connection_access_admin_info', 'Administrators see all connections.'], ['connections_connection_description', 'Description'], + ['connections_connection_project', 'Project'], ['connections_connection_driver', 'Driver'], ['connections_connection_configuration', 'Configuration'], ['connections_connection_host', 'Host'], diff --git a/webapp/packages/core-connections/src/locales/it.ts b/webapp/packages/core-connections/src/locales/it.ts index e5e162ae56..8d9b78b876 100644 --- a/webapp/packages/core-connections/src/locales/it.ts +++ b/webapp/packages/core-connections/src/locales/it.ts @@ -41,7 +41,7 @@ export default [ ['connections_connection_access_filter_placeholder', 'Cerca per utente o ruolo'], ['connections_connection_access_admin_info', 'Gli amministratori vedono tutte le connessioni.'], ['connections_connection_description', 'Descrizione'], - ['connections_connection_driver', 'Driver'], + ['connections_connection_project', 'Project'], ['connections_connection_configuration', 'Configuration'], ['connections_connection_host', 'Host'], ['connections_connection_port', 'Porta'], diff --git a/webapp/packages/core-connections/src/locales/ru.ts b/webapp/packages/core-connections/src/locales/ru.ts index 56f153f42d..95aba0ed5b 100644 --- a/webapp/packages/core-connections/src/locales/ru.ts +++ b/webapp/packages/core-connections/src/locales/ru.ts @@ -36,6 +36,7 @@ export default [ ['connections_connection_access_filter_placeholder', 'Поиск по имени пользователя или роли'], ['connections_connection_access_admin_info', 'Администраторы видят все подключения.'], ['connections_connection_description', 'Описание'], + ['connections_connection_project', 'Проект'], ['connections_connection_driver', 'Драйвер'], ['connections_connection_configuration', 'Конфигурация'], ['connections_connection_host', 'Хост'], diff --git a/webapp/packages/core-connections/src/locales/zh.ts b/webapp/packages/core-connections/src/locales/zh.ts index 1be926f601..bbba3eb1b5 100644 --- a/webapp/packages/core-connections/src/locales/zh.ts +++ b/webapp/packages/core-connections/src/locales/zh.ts @@ -39,6 +39,7 @@ export default [ ['connections_connection_access_filter_placeholder', '搜索用户或角色名称'], ['connections_connection_access_admin_info', '管理员查看所有连接。'], ['connections_connection_description', '描述'], + ['connections_connection_project', 'Project'], ['connections_connection_driver', '驱动'], ['connections_connection_configuration', 'Configuration'], ['connections_connection_host', '主机'], diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts index 6be41db8f9..e3abcbcc2a 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts @@ -152,6 +152,7 @@ export class ConnectionFormState implements IConnectionFormState { .next(this.formStateTask); makeObservable(this, { + projectId: observable, mode: observable, type: observable, config: observable, @@ -208,12 +209,17 @@ export class ConnectionFormState implements IConnectionFormState { } setConfig(projectId: string, config: ConnectionConfig): this { - this.projectId = projectId; + this.setProject(projectId); this.config = config; this.reset(); return this; } + setProject(projectId: string): this { + this.projectId = projectId; + return this; + } + setAvailableDrivers(drivers: string[]): this { this._availableDrivers = drivers; this.reset(); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts b/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts index 7d2d79df06..f96456c19c 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts @@ -46,6 +46,7 @@ export interface IConnectionFormState { type: ConnectionFormType ) => this; readonly setConfig: (projectId: string, config: ConnectionConfig) => this; + readonly setProject: (projectId: string) => this; readonly setAvailableDrivers: (drivers: string[]) => this; readonly save: () => Promise; readonly test: () => Promise; diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts index 622e14d02a..0efae411cb 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts @@ -11,6 +11,7 @@ import { action, makeObservable, runInAction, toJS } from 'mobx'; import { createConnectionParam, DatabaseAuthModelsResource, DatabaseConnection, DBDriverResource } from '@cloudbeaver/core-connections'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import type { IExecutionContextProvider } from '@cloudbeaver/core-executor'; +import { ProjectsResource } from '@cloudbeaver/core-projects'; import { CachedMapAllKey, DriverConfigurationType, isObjectPropertyInfoStateEqual, ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; import { getUniqueName, isValuesEqual } from '@cloudbeaver/core-utils'; @@ -25,6 +26,7 @@ import { Options } from './Options'; @injectable() export class ConnectionOptionsTabService extends Bootstrap { constructor( + private readonly projectsResource: ProjectsResource, private readonly connectionFormService: ConnectionFormService, private readonly dbDriverResource: DBDriverResource, private readonly databaseAuthModelsResource: DatabaseAuthModelsResource, @@ -120,14 +122,21 @@ export class ConnectionOptionsTabService extends Bootstrap { const validation = contexts.getContext(this.connectionFormService.connectionValidationContext); if (!state.config.name?.length) { - validation.error("Field 'name' can't be empty"); + validation.error('plugin_connections_connection_form_name_invalid'); } if (state.config.driverId && state.config.configurationType) { const driver = await this.dbDriverResource.load(state.config.driverId, ['includeProviderProperties']); if (!driver.configurationTypes.includes(state.config.configurationType)) { - validation.error('Configuration is not supported'); + validation.error('plugin_connections_connection_form_host_configuration_invalid'); + } + } + + if (state.projectId !== null) { + const project = this.projectsResource.get(state.projectId); + if (!project?.canCreateConnections) { + validation.error('plugin_connections_connection_form_project_invalid'); } } diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx index 3f0ae0b60e..ba10f04288 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx @@ -34,9 +34,9 @@ import { import { DatabaseAuthModelsResource, DBDriverResource, isLocalConnection } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { useTranslate } from '@cloudbeaver/core-localization'; -import { PROJECT_GLOBAL_ID } from '@cloudbeaver/core-projects'; +import { Project, ProjectsResource, PROJECT_GLOBAL_ID } from '@cloudbeaver/core-projects'; import { usePermission } from '@cloudbeaver/core-root'; -import { CachedMapEmptyKey, DriverConfigurationType, resourceKeyList } from '@cloudbeaver/core-sdk'; +import { CachedMapAllKey, CachedMapEmptyKey, DriverConfigurationType, resourceKeyList } from '@cloudbeaver/core-sdk'; import { useStyles } from '@cloudbeaver/core-theming'; import type { TabContainerPanelComponent } from '@cloudbeaver/core-ui'; import { useAuthenticationAction } from '@cloudbeaver/core-ui'; @@ -116,6 +116,17 @@ export const Options: TabContainerPanelComponent = observe optionsHook.setAuthModel(model); }, []); + const projectsLoader = useMapResource(Options, ProjectsResource, CachedMapAllKey); + const projects = projectsLoader.data as Project[]; + + function handleProjectSelect(projectId: string) { + const project = projectsLoader.resource.get(projectId); + + if (project?.canCreateConnections) { + state.setProject(projectId); + } + } + const driverMap = useMapResource( Options, DBDriverResource, @@ -293,6 +304,24 @@ export const Options: TabContainerPanelComponent = observe > {translate('connections_connection_name')} + project.id} + valueSelector={project => project.name} + titleSelector={project => project.description} + isDisabled={project => !project.canCreateConnections} + searchable={projects.length > 10} + readOnly={readonly || edit || projects.length < 2} + disabled={disabled} + loading={projectsLoader.isLoading()} + tiny + fill + onSelect={handleProjectSelect} + > + {translate('connections_connection_project')} + {!config.template && ( = observe disabled={disabled} autoComplete={`section-${config.driverId || 'driver'} section-folder`} mod='surface' + autoHide readOnly tiny fill diff --git a/webapp/packages/plugin-connections/src/locales/en.ts b/webapp/packages/plugin-connections/src/locales/en.ts index 7586edd8c0..3ef11a8065 100644 --- a/webapp/packages/plugin-connections/src/locales/en.ts +++ b/webapp/packages/plugin-connections/src/locales/en.ts @@ -6,5 +6,8 @@ export default [ ['connections_public_connection_edit_reconnect_message', 'Connection has been updated. Do you want to reconnect?'], ['connections_public_connection_edit_reconnect_failed', 'Failed to reconnect'], ['connections_public_connection_folder_move_failed', 'Failed to move to folder'], + ['plugin_connections_connection_form_project_invalid', 'You have no access to create connections in selected project'], + ['plugin_connections_connection_form_host_configuration_invalid', 'Host configuration is not supported'], + ['plugin_connections_connection_form_name_invalid', 'Field \'name\' can\'t be empty'], ['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'], ]; diff --git a/webapp/packages/plugin-connections/src/locales/it.ts b/webapp/packages/plugin-connections/src/locales/it.ts index fc4b70d326..fa9dc30a32 100644 --- a/webapp/packages/plugin-connections/src/locales/it.ts +++ b/webapp/packages/plugin-connections/src/locales/it.ts @@ -6,5 +6,8 @@ export default [ ['connections_public_connection_edit_reconnect_message', 'Connection has been updated. Do you want to reconnect?'], ['connections_public_connection_edit_reconnect_failed', 'Failed to reconnect'], ['connections_public_connection_folder_move_failed', 'Failed to move to folder'], + ['plugin_connections_connection_form_project_invalid', 'You have no access to create connections in selected project'], + ['plugin_connections_connection_form_host_configuration_invalid', 'Host configuration is not supported'], + ['plugin_connections_connection_form_name_invalid', 'Field \'name\' can\'t be empty'], ['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'], ]; diff --git a/webapp/packages/plugin-connections/src/locales/ru.ts b/webapp/packages/plugin-connections/src/locales/ru.ts index 1976281521..c662698d4a 100644 --- a/webapp/packages/plugin-connections/src/locales/ru.ts +++ b/webapp/packages/plugin-connections/src/locales/ru.ts @@ -6,5 +6,8 @@ export default [ ['connections_public_connection_edit_reconnect_message', 'Подключение было обновлено. Вы хотите переподключиться?'], ['connections_public_connection_edit_reconnect_failed', 'Не удалось переподключиться'], ['connections_public_connection_folder_move_failed', 'Ошибка перемещения в папку'], + ['plugin_connections_connection_form_project_invalid', 'У вас нет разрешения создавать коннекшены в выбранном проекте'], + ['plugin_connections_connection_form_host_configuration_invalid', 'Конфигурация хоста не поддерживается'], + ['plugin_connections_connection_form_name_invalid', 'Поле \'Название\' не может быть пустым'], ['connections_public_connection_folder_delete_confirmation', 'Вы удаляете "{args.name}". Подключения не будут удалены. Вы уверены?'], ]; diff --git a/webapp/packages/plugin-connections/src/locales/zh.ts b/webapp/packages/plugin-connections/src/locales/zh.ts index 5576999d6b..a137e60271 100644 --- a/webapp/packages/plugin-connections/src/locales/zh.ts +++ b/webapp/packages/plugin-connections/src/locales/zh.ts @@ -6,5 +6,8 @@ export default [ ['connections_public_connection_edit_reconnect_message', '连接已更新。您想重新连接吗?'], ['connections_public_connection_edit_reconnect_failed', '重新连接失败'], ['connections_public_connection_folder_move_failed', 'Failed to move to folder'], + ['plugin_connections_connection_form_project_invalid', 'You have no access to create connections in selected project'], + ['plugin_connections_connection_form_host_configuration_invalid', 'Host configuration is not supported'], + ['plugin_connections_connection_form_name_invalid', 'Field \'name\' can\'t be empty'], ['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'], ];