mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat(plugin-connections): CB-2405 project selection for connection form
This commit is contained in:
@@ -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'],
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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', 'Хост'],
|
||||
|
||||
@@ -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', '主机'],
|
||||
|
||||
@@ -152,6 +152,7 @@ export class ConnectionFormState implements IConnectionFormState {
|
||||
.next(this.formStateTask);
|
||||
|
||||
makeObservable<IConnectionFormState, '_availableDrivers' | 'stateInfo' | 'updateFormState'>(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();
|
||||
|
||||
@@ -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<void>;
|
||||
readonly test: () => Promise<void>;
|
||||
|
||||
+11
-2
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<IConnectionFormProps> = 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<IConnectionFormProps> = observe
|
||||
>
|
||||
{translate('connections_connection_name')}
|
||||
</InputField>
|
||||
<Combobox
|
||||
name='projectId'
|
||||
value={state.projectId ?? PROJECT_GLOBAL_ID}
|
||||
items={projects}
|
||||
keySelector={project => 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')}
|
||||
</Combobox>
|
||||
{!config.template && (
|
||||
<InputField
|
||||
type="text"
|
||||
@@ -301,6 +330,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
disabled={disabled}
|
||||
autoComplete={`section-${config.driverId || 'driver'} section-folder`}
|
||||
mod='surface'
|
||||
autoHide
|
||||
readOnly
|
||||
tiny
|
||||
fill
|
||||
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
@@ -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}". Подключения не будут удалены. Вы уверены?'],
|
||||
];
|
||||
|
||||
@@ -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?'],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user