From 0627f55148715b60b87960286b4c8189ad8c6504 Mon Sep 17 00:00:00 2001 From: Naumov Alexey Date: Thu, 4 Feb 2021 17:58:11 +0300 Subject: [PATCH 1/2] feat(core-connections): CB-692 add new custom properties --- .../src/FormControls/Checkboxes/Checkbox.tsx | 13 ++++++- .../Checkboxes/CheckboxMarkup.tsx | 6 ++-- .../ObjectPropertyInfoForm.tsx | 21 +++++++++-- .../ConnectionFormController.ts | 13 +++++-- .../ConnectionForm/Options/Options.tsx | 14 +++++++- .../Options/OptionsController.ts | 7 +++- .../ConnectionForm/OriginInfo/OriginInfo.tsx | 4 +-- .../src/Administration/ConnectionsResource.ts | 1 + .../core-connections/src/DBDriverResource.ts | 31 ++++++++-------- .../DatabaseAuthDialog/DatabaseAuthDialog.tsx | 2 +- .../core-connections/src/locales/en.ts | 1 + .../core-connections/src/locales/ru.ts | 1 + .../src/queries/connections/driverList.gql | 14 +++++++- .../src/queries/fragments/AdminConnection.gql | 1 + webapp/packages/core-sdk/src/sdk.ts | 36 +++++++++++++++++-- .../Users/UserForm/OriginInfo.tsx | 2 +- .../ConnectionForm/ConnectionForm.tsx | 2 +- .../src/ConnectionDialog/ConnectionDialog.tsx | 2 +- 18 files changed, 136 insertions(+), 35 deletions(-) diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx index 7e5194fe7cc..a683c9757be 100644 --- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx @@ -17,6 +17,7 @@ import { CheckboxMarkup } from './CheckboxMarkup'; export type CheckboxBaseProps = Omit, 'onChange' | 'type' | 'value' | 'checked'> & { value?: string; checkboxLabel?: string; + title?: string; mod?: 'surface'; long?: boolean; }; @@ -52,6 +53,7 @@ export const Checkbox: CheckboxType = observer(function Checkbox({ value, state, checkboxLabel, + title, checked: checkedControlled, children, className, @@ -89,7 +91,15 @@ export const Checkbox: CheckboxType = observer(function Checkbox({ return null; } - let checked = state ? state[name] : checkedControlled; + let checked = checkedControlled; + + if (state) { + if (typeof state[name] === 'string') { + checked = state[name] === 'true'; + } else { + checked = state[name]; + } + } if (Array.isArray(checked)) { checked = checked.includes(value); @@ -102,6 +112,7 @@ export const Checkbox: CheckboxType = observer(function Checkbox({ id={value || name} checked={checked} label={checkboxLabel} + title={title} className={className} onChange={handleChange} {...use({ mod })} diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/CheckboxMarkup.tsx b/webapp/packages/core-blocks/src/FormControls/Checkboxes/CheckboxMarkup.tsx index 89976b56d8d..2e099a231d7 100644 --- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/CheckboxMarkup.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/CheckboxMarkup.tsx @@ -78,10 +78,12 @@ interface ICheckboxMarkupProps extends React.InputHTMLAttributes = function CheckboxMarkup({ label, className, ...rest }) { +export const CheckboxMarkup: React.FC = function CheckboxMarkup({ + label, className, title, ...rest +}) { return styled(useStyles(checkboxStyles, checkboxMod.primary, rest.disabled && checkboxState.disabled, rest.checked && checkboxState.checked))( - + diff --git a/webapp/packages/core-blocks/src/ObjectPropertyInfoForm/ObjectPropertyInfoForm.tsx b/webapp/packages/core-blocks/src/ObjectPropertyInfoForm/ObjectPropertyInfoForm.tsx index 27d3a34fa04..971ab34f699 100644 --- a/webapp/packages/core-blocks/src/ObjectPropertyInfoForm/ObjectPropertyInfoForm.tsx +++ b/webapp/packages/core-blocks/src/ObjectPropertyInfoForm/ObjectPropertyInfoForm.tsx @@ -14,6 +14,7 @@ import { InputField } from '@cloudbeaver/core-blocks'; import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; import { useStyles } from '@cloudbeaver/core-theming'; +import { FieldCheckbox } from '../FormControls/Checkboxes/FieldCheckbox'; import { FormFieldDescription } from '../FormControls/FormFieldDescription'; import { FormGroup } from '../FormControls/FormGroup'; import { isControlPresented } from '../FormControls/isControlPresented'; @@ -48,6 +49,7 @@ const RenderField: React.FC = observer(function RenderField({ }) { const href = property.features.includes('href'); const password = property.features.includes('password'); + const checkbox = property.dataType === 'Boolean'; let description: string | undefined; if (href) { @@ -73,6 +75,19 @@ const RenderField: React.FC = observer(function RenderField({ description = 'Password saved'; } + if (checkbox) { + return ( + + ); + } + return ( = observer(function RenderField({ interface ObjectPropertyFormProps { properties: ObjectPropertyInfo[] | undefined; - credentials: Record; + state: Record; editable?: boolean; autofillToken?: string; className?: string; @@ -106,7 +121,7 @@ interface ObjectPropertyFormProps { export const ObjectPropertyInfoForm: React.FC = observer(function ObjectPropertyInfoForm({ properties, - credentials, + state, editable = true, autofillToken = '', className, @@ -134,7 +149,7 @@ export const ObjectPropertyInfoForm: React.FC = observe ; @@ -80,7 +80,10 @@ implements IInitializableController { const connectionConfig = this.getConnectionConfig(); const validation = this.validate(connectionConfig); if (!validation.status) { - this.notificationService.logError({ title: this.model.editing ? 'connections_administration_connection_save_error' : 'connections_administration_connection_create_error', message: validation.errorMessage }); + this.notificationService.logError({ + title: this.model.editing ? 'connections_administration_connection_save_error' : 'connections_administration_connection_create_error', + message: validation.errorMessage, + }); return; } @@ -133,7 +136,7 @@ implements IInitializableController { if (!config.name?.length) { validationStatus.errorMessage = "Field 'name' can't be empty"; } else if (this.model.editing && this.isConnectionNameAlreadyExists(config.name)) { - validationStatus.errorMessage = 'Connection with this name already exists'; + validationStatus.errorMessage = `Connection with ${config.name} name already exists`; } validationStatus.status = !validationStatus.errorMessage; @@ -173,6 +176,10 @@ implements IInitializableController { } config.networkHandlersConfig = this.model.networkHandlersState; + if (Object.keys(this.model.connection.providerProperties).length > 0) { + config.providerProperties = this.model.connection.providerProperties; + } + return config; } diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/Options.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/Options.tsx index 39b37ca05c1..d27e354225b 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/Options.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/Options.tsx @@ -140,7 +140,7 @@ export const Options = observer(function Options({ @@ -157,6 +157,18 @@ export const Options = observer(function Options({ )} + {controller.providerProperties && controller.providerProperties.length > 0 && ( + + + {translate('connections_connection_edit_settings')} + + + + )} ); diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/OptionsController.ts b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/OptionsController.ts index 75f3647aa64..bcb009a71d2 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/OptionsController.ts +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/Options/OptionsController.ts @@ -18,7 +18,7 @@ import type { IConnectionFormModel } from '../IConnectionFormModel'; @injectable() export class OptionsController -implements IInitializableController { + implements IInitializableController { get drivers(): DBDriver[] { return Array.from(this.dbDriverResource.data.values()) .filter(({ id }) => this.model.availableDrivers.includes(id)); @@ -46,6 +46,10 @@ implements IInitializableController { return this.authModel?.properties; } + get providerProperties(): ObjectPropertyInfo[] | undefined { + return this.dbDriverResource.get(this.model.connection.driverId)?.providerProperties; + } + private model!: IConnectionFormModel; /** we want to save prev generated connection name to detect if user changed "name" field to turn off autofill */ private prevGeneratedName: string | null = null; @@ -87,6 +91,7 @@ implements IInitializableController { this.setDefaultParameters(prevDriverId); this.cleanCredentials(); this.model.connection.properties = {}; + this.model.connection.providerProperties = {}; this.model.connection.authModel = this.driver?.defaultAuthModel; } diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/OriginInfo/OriginInfo.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/OriginInfo/OriginInfo.tsx index f8334ed9a3f..d1b7cad1083 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/OriginInfo/OriginInfo.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionForm/OriginInfo/OriginInfo.tsx @@ -8,7 +8,7 @@ import { observer } from 'mobx-react-lite'; -import { TextPlaceholder, useTab, ObjectPropertyInfoForm, FormBox, FormBoxElement, FormGroup, InputGroup, Loader, useTabState, ExceptionMessage } from '@cloudbeaver/core-blocks'; +import { TextPlaceholder, useTab, ObjectPropertyInfoForm, FormBox, FormBoxElement, FormGroup, Loader, useTabState, ExceptionMessage } from '@cloudbeaver/core-blocks'; import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { useTranslate } from '@cloudbeaver/core-localization'; @@ -94,7 +94,7 @@ export const OriginInfo: TabContainerPanelComponent = obse
diff --git a/webapp/packages/core-connections/src/Administration/ConnectionsResource.ts b/webapp/packages/core-connections/src/Administration/ConnectionsResource.ts index 1128a1d396f..0d4474df9f0 100644 --- a/webapp/packages/core-connections/src/Administration/ConnectionsResource.ts +++ b/webapp/packages/core-connections/src/Administration/ConnectionsResource.ts @@ -71,6 +71,7 @@ export class ConnectionsResource extends CachedMapResource; @injectable() diff --git a/webapp/packages/core-connections/src/DatabaseAuthDialog/DatabaseAuthDialog.tsx b/webapp/packages/core-connections/src/DatabaseAuthDialog/DatabaseAuthDialog.tsx index 84baa30a994..eb76bfd2b01 100644 --- a/webapp/packages/core-connections/src/DatabaseAuthDialog/DatabaseAuthDialog.tsx +++ b/webapp/packages/core-connections/src/DatabaseAuthDialog/DatabaseAuthDialog.tsx @@ -101,7 +101,7 @@ export const DatabaseAuthDialog = observer(function DatabaseAuthDialog({ diff --git a/webapp/packages/core-connections/src/locales/en.ts b/webapp/packages/core-connections/src/locales/en.ts index 2e4f1a2e6a3..4b56ea518db 100644 --- a/webapp/packages/core-connections/src/locales/en.ts +++ b/webapp/packages/core-connections/src/locales/en.ts @@ -16,6 +16,7 @@ export default [ ['connections_connection_create_search_database', 'Search'], ['connections_connection_edit_save_credentials', 'Save credentials'], ['connections_connection_edit_authentication', 'Authentication'], + ['connections_connection_edit_settings', 'Settings'], ['connections_connection_edit_access', 'Access'], ['connections_connection_edit_access_load_failed', 'Fail to get connection access'], ['connections_connection_edit_access_role', 'Role'], diff --git a/webapp/packages/core-connections/src/locales/ru.ts b/webapp/packages/core-connections/src/locales/ru.ts index 21a486c6b92..c7989d69c79 100644 --- a/webapp/packages/core-connections/src/locales/ru.ts +++ b/webapp/packages/core-connections/src/locales/ru.ts @@ -15,6 +15,7 @@ export default [ ['connections_connection_create_search_database', 'Найти'], ['connections_connection_edit_save_credentials', ' Запомнить данные'], ['connections_connection_edit_authentication', 'Авторизация'], + ['connections_connection_edit_settings', 'Настройки'], ['connections_connection_edit_access', 'Доступ'], ['connections_connection_edit_access_load_failed', 'Не удалось загрузить информацию доступа'], ['connections_connection_edit_access_role', 'Роль'], diff --git a/webapp/packages/core-sdk/src/queries/connections/driverList.gql b/webapp/packages/core-sdk/src/queries/connections/driverList.gql index db52518e431..6586da95497 100644 --- a/webapp/packages/core-sdk/src/queries/connections/driverList.gql +++ b/webapp/packages/core-sdk/src/queries/connections/driverList.gql @@ -15,6 +15,18 @@ query driverList { defaultAuthModel # applicableAuthModel + + providerProperties { + id + displayName + description + category + dataType + defaultValue + validValues + features + order + } applicableNetworkHandlers } -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/AdminConnection.gql b/webapp/packages/core-sdk/src/queries/fragments/AdminConnection.gql index 5edf54eec14..9774a0947e0 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/AdminConnection.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/AdminConnection.gql @@ -15,6 +15,7 @@ fragment AdminConnection on ConnectionInfo { databaseName url properties + providerProperties features diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index 2fb09d54d90..fe7ef5d88ca 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -268,6 +268,7 @@ export interface Mutation { sqlContextSetDefaults: Scalars['Boolean']; sqlResultClose: Scalars['Boolean']; testConnection: ConnectionInfo; + testNetworkHandler: NetworkEndpointInfo; touchSession?: Maybe; updateResultsData?: Maybe; updateResultsDataBatch?: Maybe; @@ -374,6 +375,10 @@ export interface MutationTestConnectionArgs { config: ConnectionConfig; } +export interface MutationTestNetworkHandlerArgs { + config: NetworkHandlerConfigInput; +} + export interface MutationUpdateResultsDataArgs { connectionId: Scalars['ID']; contextId: Scalars['ID']; @@ -448,6 +453,8 @@ export interface ServerConfig { supportsCustomConnections?: Maybe; supportsConnectionBrowser?: Maybe; supportsWorkspaces?: Maybe; + publicCredentialsSaveEnabled?: Maybe; + adminCredentialsSaveEnabled?: Maybe; sessionExpireTime?: Maybe; localHostAddress?: Maybe; configurationMode?: Maybe; @@ -569,6 +576,12 @@ export interface ConnectionInfo { supportedDataFormats: ResultDataFormat[]; } +export interface NetworkEndpointInfo { + message?: Maybe; + clientVersion?: Maybe; + serverVersion?: Maybe; +} + export interface ObjectOrigin { type: Scalars['ID']; subType?: Maybe; @@ -844,6 +857,8 @@ export interface ServerConfigInput { anonymousAccessEnabled?: Maybe; authenticationEnabled?: Maybe; customConnectionsEnabled?: Maybe; + publicCredentialsSaveEnabled?: Maybe; + adminCredentialsSaveEnabled?: Maybe; sessionExpireTime?: Maybe; } @@ -1097,7 +1112,12 @@ export type DeleteConnectionMutation = Pick; export type DriverListQueryVariables = Exact<{ [key: string]: never }>; -export interface DriverListQuery { driverList: Array> } +export interface DriverListQuery { + driverList: Array<( + Pick + & { providerProperties: Array> } + )>; +} export type DriverPropertiesQueryVariables = Exact<{ driverId: Scalars['ID']; @@ -1216,7 +1236,7 @@ export type NavGetStructContainersQueryVariables = Exact<{ export interface NavGetStructContainersQuery { navGetStructContainers: { catalogList: Array>; schemaList: Array> } } export type AdminConnectionFragment = ( - Pick + Pick & { origin: ObjectOriginInfoFragment; authProperties: UserConnectionAuthPropertiesFragment[]; networkHandlersConfig: Array> } ); @@ -1540,6 +1560,7 @@ export const AdminConnectionFragmentDoc = ` databaseName url properties + providerProperties features origin { ...ObjectOriginInfo @@ -1907,6 +1928,17 @@ export const DriverListDocument = ` anonymousAccess promotedScore defaultAuthModel + providerProperties { + id + displayName + description + category + dataType + defaultValue + validValues + features + order + } applicableNetworkHandlers } } diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/OriginInfo.tsx b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/OriginInfo.tsx index ba83f157239..6240bf3a794 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/OriginInfo.tsx +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UserForm/OriginInfo.tsx @@ -98,7 +98,7 @@ export const OriginInfo: TabContainerPanelComponent = observer(f
diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/ConnectionForm/ConnectionForm.tsx b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/ConnectionForm/ConnectionForm.tsx index a0501672cde..4f28e4530de 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/ConnectionForm/ConnectionForm.tsx +++ b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/ConnectionForm/ConnectionForm.tsx @@ -89,7 +89,7 @@ export const ConnectionForm = observer(function ConnectionForm({ diff --git a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx index aa20964734b..473f83a9368 100644 --- a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx +++ b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx @@ -85,7 +85,7 @@ export const ConnectionDialog = observer(function ConnectionDialog({ From a72c70dae74931e33d5c48a6c923b945f88f5a19 Mon Sep 17 00:00:00 2001 From: Naumov Alexey Date: Thu, 4 Feb 2021 18:36:50 +0300 Subject: [PATCH 2/2] feat(core-connections): CB-692 remove unnecessary type 'title' from checkbox component --- .../core-blocks/src/FormControls/Checkboxes/Checkbox.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx index a683c9757be..e54f6535790 100644 --- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Checkbox.tsx @@ -17,7 +17,6 @@ import { CheckboxMarkup } from './CheckboxMarkup'; export type CheckboxBaseProps = Omit, 'onChange' | 'type' | 'value' | 'checked'> & { value?: string; checkboxLabel?: string; - title?: string; mod?: 'surface'; long?: boolean; }; @@ -53,7 +52,6 @@ export const Checkbox: CheckboxType = observer(function Checkbox({ value, state, checkboxLabel, - title, checked: checkedControlled, children, className, @@ -112,7 +110,6 @@ export const Checkbox: CheckboxType = observer(function Checkbox({ id={value || name} checked={checked} label={checkboxLabel} - title={title} className={className} onChange={handleChange} {...use({ mod })}