diff --git a/src/modules/crud/api.ts b/src/modules/crud/api.ts index 1d917b8..12d4f0c 100644 --- a/src/modules/crud/api.ts +++ b/src/modules/crud/api.ts @@ -52,6 +52,11 @@ export interface Api { */ getConnectionPool(name: string): Promise<{ data?: ConnectionPoolType }>; + /** + * 获取自定义驱动列表 + */ + getSimpleDriverList(): Promise<{ data?: any[] }>; + /** * 获取连接状态 * @param name diff --git a/src/modules/crud/decision.api.ts b/src/modules/crud/decision.api.ts index a15cd14..7301526 100644 --- a/src/modules/crud/decision.api.ts +++ b/src/modules/crud/decision.api.ts @@ -52,6 +52,14 @@ export class DecisionApi implements Api { return requestGet(`pool/info?connectionName=${encodeURIComponent(name)}`, {}); } + getSimpleDriverList(): Promise<{ data: any[] }> { + return new Promise(resolve => { + Dec.reqGet('/v10/drivers/simple/list', '', re => { + resolve(re); + }); + }); + } + getConnectionStatus(name: string): Promise { return this.sendEditStatusEvent(name, editStatusEvent.OPEN) .then(re => { diff --git a/src/modules/pages/connection/connection.ts b/src/modules/pages/connection/connection.ts index 4682418..90f5ba1 100644 --- a/src/modules/pages/connection/connection.ts +++ b/src/modules/pages/connection/connection.ts @@ -79,7 +79,16 @@ export class Connection extends BI.Widget { right: [ { type: 'dec.connection.driver.entry', + invisible: !BI.Services.getService('dec.service.global').isAdmin(), from: '.dec-dcm', + listeners: [ + { + eventName: 'EVENT_CLOSE', + action: () => { + this.reset(); + }, + }, + ], }, ], }, diff --git a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts b/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts index 4dc6d0e..eff5383 100644 --- a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts +++ b/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts @@ -23,6 +23,7 @@ export class ConnectionJdbc extends BI.Widget { const connectionData = this.model.connectionSelectedOne.connectionData as ConnectionJDBC; const { driver, + driverSource, database, user, originalCharsetName, @@ -45,7 +46,7 @@ export class ConnectionJdbc extends BI.Widget { { type: FormItem.xtype, name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'), - value: driver, + value: BI.isKey(driverSource) ? `${driver} (${driverSource})` : driver, }, { type: FormItem.xtype, @@ -182,9 +183,9 @@ export class ConnectionJdbc extends BI.Widget { unit: BI.i18nText('BI-Basic_Seconds'), }, { type: FormItem.xtype, - invisible: BI.parseInt(fetchSize) < 0, + invisible: fetchSize < 0 && fetchSize !== -2, name: 'Fetchsize', - value: fetchSize, + value: fetchSize === -2 ? '' : fetchSize, }, ], }, diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.model.ts b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts new file mode 100644 index 0000000..384e4f4 --- /dev/null +++ b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts @@ -0,0 +1,126 @@ +import { model, Model } from '@core/core'; +import { ConnectionJDBC } from '../../../../crud/crud.typings'; +import { getJdbcDatabaseType } from '../../../../app.service'; +import { ApiFactory } from '../../../../crud/apiFactory'; + +const api = new ApiFactory().create(); + +@model() +export class DriverSelectorModel extends Model { + static xtype = 'dec.dcm.model.maintain.form.jdbc.driver_selector'; + + state = () => { + const defaultDrivers = this.getDrivers(); + const [driverSource, selectedDriver] = this.resolveSelectedDriverType(); + + return { + defaultDrivers, + driverSource, + selectedDriverType: driverSource === '' ? 'default' : 'custom', + customDrivers: [], + defaultDriver: { + driver: driverSource === '' ? selectedDriver : '', + }, + customDriver: { + driver: driverSource !== '' ? selectedDriver : '', + value: driverSource !== '' ? `${this.options.driver} (${driverSource})` : '', + }, + }; + }; + + computed = { + driverClassItems: () => this.model.customDrivers.map(driver => { + return { + text: `${driver.driverClass} (${driver.name})`, + value: `${driver.driverClass} (${driver.name})`, + driverClass: driver.driverClass, + }; + }), + + driverTypeComboValue: () => this.model.driverSource === '' ? 'default' : 'custom', + + driverManageEntryVisible: () => this.model.selectedDriverType === 'custom' && BI.Services.getService('dec.service.global').isAdmin(), + }; + + actions = { + initDriverClassList: cb => { + + api.getSimpleDriverList().then(res => { + this.model.customDrivers = res.data.filter(driver => { + return BI.isKey(driver.driverClass); + }); + cb(); + }); + }, + + changeDefaultDriver: driver => { + this.model.defaultDriver.driver = driver; + this.model.driverSource = ''; + }, + + changeCustomDriver: value => { + + const item = this.model.driverClassItems.find(item => { + return item.value === value; + }); + const driver = item.driverClass; + this.model.customDriver.driver = driver; + + this.model.customDrivers.some(customDriver => { + if (customDriver.driverClass === driver) { + this.model.driverSource = customDriver.name; + this.model.customDriver.value = `${driver} (${customDriver.name})`; + + return true; + } + + return false; + }); + }, + + changeSelectedDriverType: driverTypeComboValue => { + this.model.selectedDriverType = driverTypeComboValue; + this.model.driverSource = driverTypeComboValue === 'default' ? '' : this.model.driverSource; + }, + + changeDriverSource: driverTypeComboValue => { + this.model.driverSource = driverTypeComboValue === 'default' ? '' : this.model.driverSource; + }, + }; + + private resolveSelectedDriverType = () => { + if (BI.isNotEmptyString(this.options.driverSource)) { + return [this.options.driverSource, this.options.driver]; + } + + return [this.options.driverSource, this.options.driver]; + }; + + private getDrivers = () => { + const connectionData = this.options.connectionData as ConnectionJDBC; + const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); + const drivers = connectionType.drivers ? + connectionType.drivers.map(item => { + return { + text: item, + value: item, + }; + }) : + [{ + text: connectionType.driver, + value: connectionType.driver, + }]; + + if (!drivers.some(item => item.text === connectionData.driver)) { + return [ + { + text: connectionData.driver, + value: connectionData.driver, + }, + ...drivers, + ]; + } + + return drivers; + }; +} diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.ts b/src/modules/pages/maintain/components/driverselector/driverselector.ts new file mode 100644 index 0000000..896c157 --- /dev/null +++ b/src/modules/pages/maintain/components/driverselector/driverselector.ts @@ -0,0 +1,185 @@ +import { shortcut, store } from '@core/core'; + +import { + Button, + EditorIconCheckCombo, + SearchTextValueCombo, + TextValueCombo, +} from '@fui/core'; +import { ConnectionJDBC } from '../../../../crud/crud.typings'; +import { getJdbcDatabaseType } from '../../../../app.service'; +import { DriverSelectorModel } from './driverselector.model'; + + +@shortcut() +@store(DriverSelectorModel, { + props(this: DriverSelector) { + return this.options; + }, +}) +export class DriverSelector extends BI.Widget { + static xtype = 'dec.dcm.maintain.form.jdbc.driver_selector'; + + props = { + driver: '', + driverSource: '', + connectionData: {} as ConnectionJDBC, + }; + + defaultDrivers: EditorIconCheckCombo = null; + + customDrivers: SearchTextValueCombo = null; + + beforeRender(cb: Function) { + this.store.initDriverClassList(cb); + } + + watch = { + driverClassItems: items => { + this.customDrivers.populate(items); + this.customDrivers.setValue(this.model.customDriver.value); + }, + + driverManageEntryVisible: b => { + this.driverManageEntry.setVisible(b); + }, + }; + + private driverManageEntry = null; + + render() { + const { driver } = this.options.connectionData; + + return { + type: BI.VerticalAdaptLayout.xtype, + rgap: 10, + items: [ + { + el: { + type: BI.TextValueCombo.xtype, + width: 86, + value: this.model.selectedDriverType, + items: [ + { + text: BI.i18nText('Dec-Basic_Default'), + value: 'default', + }, { + text: BI.i18nText('Dec-Basic_Custom'), + value: 'custom', + }, + ], + listeners: [ + { + eventName: BI.TextValueCombo.EVENT_CHANGE, + action: value => { + this.store.changeSelectedDriverType(value); + if (value === 'default') { + this.defaultDrivers.setVisible(true); + this.customDrivers.setVisible(false); + this.fireEvent('EVENT_CHANGE'); + return; + } + + this.defaultDrivers.setVisible(false); + this.customDrivers.setVisible(true); + if (BI.isKey(this.customDrivers.getValue()[0])) { + this.fireEvent('EVENT_CHANGE'); + } + }, + }, + ], + }, + }, { + el: { + type: BI.EditorIconCheckCombo.xtype, + $testId: 'dec-editor-icon-check-combo', + $value: 'driver', + ref: _ref => { + this.defaultDrivers = _ref; + }, + invisible: this.model.driverSource !== '', + width: 204, + items: this.model.defaultDrivers, + value: this.model.defaultDriver.driver, + listeners: [ + { + eventName: BI.EditorIconCheckCombo.EVENT_CHANGE, + action: () => { + this.store.changeDefaultDriver(this.defaultDrivers.getValue()); + this.fireEvent('EVENT_CHANGE'); + }, + }, + ], + }, + }, { + el: { + type: BI.SearchTextValueCombo.xtype, + $testId: 'dec-editor-icon-check-combo', + $value: 'driver', + ref: _ref => { + this.customDrivers = _ref; + }, + invisible: this.model.driverSource === '', + width: 204, + watermark: BI.i18nText('Dec-Please_Input'), + items: this.model.driverClassItems, + value: this.model.customDriver.value, + text: () => this.model.customDriver.value || '', + defaultText: BI.i18nText('Dec-Please_Select'), + warningTitle: BI.i18nText('Dec-Dcm-Driver_Driver_File_Lost'), + listeners: [ + { + eventName: BI.SearchTextValueCombo.EVENT_CHANGE, + action: () => { + this.store.changeCustomDriver(this.customDrivers.getValue()[0]); + this.fireEvent('EVENT_CHANGE'); + }, + }, + ], + }, + }, { + el: { + type: 'dec.connection.driver.entry', + ref: (_ref: Button) => { + this.driverManageEntry = _ref; + }, + el: { + type: BI.Button.xtype, + level: 'ignore', + text: BI.i18nText('Dec-Dcm_Create_New_Driver'), + }, + from: '.dec-dcm', + invisible: !this.model.driverManageEntryVisible, + listeners: [ + { + eventName: 'EVENT_CLOSE', + action: () => { + this.store.initDriverClassList(BI.emptyFn); + }, + }, + ], + }, + }, + ], + }; + } + + validation(): boolean { + if (this.model.selectedDriverType === 'default' && BI.isKey(this.model.defaultDriver.driver)) { + return true; + } + if (this.model.selectedDriverType === 'custom' && BI.isKey(this.model.customDriver.driver)) { + return true; + } + BI.Msg.toast(BI.i18nText('Dec-Dcm_Driver_Class_Not_Allow_Empty'), { level: 'error' }); + + return false; + } + + getValue() { + return { + driverSource: this.model.driverSource, + driver: this.model.driverSource === '' ? this.model.defaultDriver.driver : this.model.customDriver.driver, + }; + } +} diff --git a/src/modules/pages/maintain/forms/components/form.jdbc.ts b/src/modules/pages/maintain/forms/components/form.jdbc.ts index a0c49d4..d9fe88c 100644 --- a/src/modules/pages/maintain/forms/components/form.jdbc.ts +++ b/src/modules/pages/maintain/forms/components/form.jdbc.ts @@ -16,6 +16,7 @@ import { TextValueCombo, VerticalLayout, } from '@fui/core'; +import { DriverSelector } from '../../components/driverselector/driverselector'; const api = new ApiFactory().create(); @@ -70,6 +71,7 @@ export class FormJdbc extends BI.Widget { const { connectionName, connectionData } = this.options.formData; const { driver, + driverSource, user, password, originalCharsetName, @@ -130,31 +132,34 @@ export class FormJdbc extends BI.Widget { { type: FormItem.xtype, name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'), - forms: [{ - type: BI.EditorIconCheckCombo.xtype, - $testId: 'dec-editor-icon-check-combo', - $value: 'driver', - width: 300, - value: driver, - ref: (_ref: EditorIconCheckCombo) => { - this.form.driver = _ref; - }, - items: this.getDrivers(), - listeners: [{ - eventName: BI.EditorIconCheckCombo.EVENT_CHANGE, - action: () => { - const value = this.form.driver.getValue(); - const connectionData = this.options.formData.connectionData as ConnectionJDBC; - const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); - const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; - this.form.url.setValue(url); - const urlInfo = resolveUrlInfo(url, connectionData.database); - this.form.host.setValue(urlInfo.host); - this.form.database.setValue(urlInfo.databaseName); - this.form.port.setValue(urlInfo.port); + forms: [ + { + type: DriverSelector.xtype, + ref: (_ref: DriverSelector) => { + this.form.driver = _ref; }, - }], - }], + driver, + driverSource, + connectionData, + listeners: [ + { + eventName: 'EVENT_CHANGE', + action: () => { + const value = this.form.driver.getValue(); + const connectionData = this.options.formData.connectionData as ConnectionJDBC; + const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); + // DEC-2020 + const url = (connectionType.urls && connectionType.urls[value.driver]) || connectionType.url; + this.form.url.setValue(url); + const urlInfo = resolveUrlInfo(url, connectionData.database); + this.form.host.setValue(urlInfo.host); + this.form.database.setValue(urlInfo.databaseName); + this.form.port.setValue(urlInfo.port); + }, + }, + ], + }, + ], }, { type: FormItem.xtype, @@ -708,7 +713,7 @@ export class FormJdbc extends BI.Widget { el: { type: BI.VerticalLayout.xtype, cls: 'bi-border-top', - invisible: BI.parseInt(fetchSize) < 0, + invisible: fetchSize < 0 && fetchSize !== -2, items: [ { el: { @@ -719,7 +724,7 @@ export class FormJdbc extends BI.Widget { $value: 'fetch-size', width: 300, allowBlank: true, - value: fetchSize, + value: fetchSize === -2 ? '' : fetchSize, watermark: 'Fetchsize', validationChecker: [{ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Fetch_Size_Range'), @@ -802,7 +807,7 @@ export class FormJdbc extends BI.Widget { private onHostPortChange(databaseType) { const { urls, url } = databaseType; const driver = this.form.driver.getValue(); - const selectUrl = BI.get(urls, driver) || url; + const selectUrl = BI.get(urls, driver.driver) || url; const host = this.form.host.getValue(); const port = this.form.port.getValue(); const database = this.form.database.getValue(); @@ -823,6 +828,10 @@ export class FormJdbc extends BI.Widget { } } + public validation(): boolean { + return this.form.driver.validation(); + } + public getSubmitValue(): Connection { const connectionData = this.options.formData.connectionData as ConnectionJDBC; const connectionPoolAttr = connectionData.connectionPoolAttr; @@ -836,7 +845,7 @@ export class FormJdbc extends BI.Widget { connectionData: BI.extend({}, connectionData, { database: connectionData.database, connectionName: this.form.connectionName.getValue(), - driver: this.form.driver.getValue(), + ...this.form.driver.getValue(), url: this.form.url.getValue(), user: this.form.user.getValue(), password: this.oldPassword === this.form.password.getValue() ? this.oldPassword : api.getCipher(this.form.password.getValue()), @@ -849,7 +858,7 @@ export class FormJdbc extends BI.Widget { creator: Dec ? Dec.personal.username : '', principal: this.form.principal.getValue(), keyPath: this.form.keyPath.getValue(), - fetchSize: BI.parseInt(this.form.fetchSize.getValue()), + fetchSize: BI.isEmptyString(this.form.fetchSize.getValue()) ? -2 : BI.parseInt(this.form.fetchSize.getValue()), connectionPoolAttr: { initialSize: this.form.initialSize.getValue(), maxActive: this.form.maxActive.getValue(), diff --git a/src/modules/pages/maintain/forms/form.ts b/src/modules/pages/maintain/forms/form.ts index ceb59cc..cb3b573 100644 --- a/src/modules/pages/maintain/forms/form.ts +++ b/src/modules/pages/maintain/forms/form.ts @@ -197,6 +197,10 @@ export class MaintainForm extends BI.Widget { return false; } + if (this.form.validation && !this.form.validation()) { + return false; + } + return true; } @@ -223,13 +227,18 @@ export class MaintainForm extends BI.Widget { if (!formValue.connectionName) { this.setFromError(BI.i18nText('Dec-Dcm_Connection_ConnectionName_Cannt_Null')); - return; + return false; } if (getChartLength(formValue.connectionName) > NAME_MAX_LENGTH) { this.setFromError(BI.i18nText('Dec-Dcm_Connection_Cannot_Too_Lang', NAME_MAX_LENGTH)); return false; } + + if (this.form.validation && !this.form.validation()) { + return false; + } + if (this.isEdit || this.model.isCopy) { formValue.connectionId = this.connectionName; }