diff --git a/.eslintrc b/.eslintrc
index 0a25792..1541dc7 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -30,7 +30,8 @@
"no-use-before-define": [
"error",
{
- "functions": false
+ "functions": false,
+ "classes ": false
}
],
"new-cap": [
@@ -179,7 +180,7 @@
"array-bracket-spacing": ["error", "never"], // 数组紧贴括号部分不允许包含空格
"object-curly-spacing": ["error", "always"], // 对象紧贴花括号部分不允许包含空格
"no-regex-spaces": "error", // 禁止正则表达式字面量中出现多个空格
- "no-multi-spaces": "error", // 禁止出现多个空格而且不是用来作缩进的
+ // "no-multi-spaces": "error", // 禁止出现多个空格而且不是用来作缩进的
"block-spacing": ["error", "never"], // 单行代码块中紧贴括号部分不允许包含空格
"computed-property-spacing": ["error", "never"], // 禁止括号和其内部值之间的空格
"no-trailing-spaces": [
diff --git a/README.md b/README.md
index cca899a..ac03007 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
## 开始
安装依赖
```
-yarn
+yarn install
```
开始开发
@@ -15,8 +15,107 @@ yarn
yarn dev
```
+## 决策平台开发:
+
+### A.项目运行
+
+#### 1. 工程`decision-webui-dev`添加代理(可跳过)
+```js
+ webpack/webpack.config
+ "/plugin/dcm": {
+ pathRewrite: { "^/plugin/dcm": "" },
+ target: "http://localhost:10002",
+ },
+```
+#### 2. 工程`decision-webui-dev`引入
+ fr环境:`templates/bundle.report.html` bi环境:`templates/bundle.bi.html`
+
+```html
+ // css 文件:
+
+
+
+
+
+ // js 文件
+
+```
+ 若未设1,将`/plugin/dcm`替换成`http://localhost:10002`亦可
+#### 3. 启动工程[decision-webui-dev]以及数据连接[desicion-webui-dcm]工程
+
+#### 4. 此时工程`decision-webui-dev`的`http://localhost:9002/#management/connnection`数据连接模块已替换成该工程
+
+### B.插件形式添加数据连接-数据库
+
+#### 1. 以多版本的tdsql为例 单一版本数据库不需drivers,versions,hasSchemas
+
+```js
+BI.config("dec.connection.provider.datebase", function (provider) {
+ BI.isFunction(provider.registerJdbcDatabase) && provider.registerJdbcDatabase({
+ text: 'TDSQL', // 数据库名称
+ databaseType: 'tdsql', // 数据库key
+ driver: 'org.postgresql.Driver', // 默认驱动
+ drivers: {
+ "pgsql": ["org.postgresql.Driver"],
+ "mysql": ["com.mysql.jdbc.Driver"]
+ }, // 驱动可选项,version: array[driver],[0]为该版本的默认驱动
+ versions: ["pgsql", "mysql"], // array[version]
+ urls: {
+ "org.postgresql.Driver": "jdbc:postgresql://hostname:port/database?finedbType=tdsql-pgsql",
+ "com.mysql.jdbc.Driver": "jdbc:mysql://hostname:port/database?finedbType=tdsql-mysql"
+ }, // urlkey : url 一个驱动对应一个url
+ url: 'jdbc:postgresql://hostname:port/database?finedbType=tdsql-pgsql',
+ commonly: false,
+ internal: true,
+ type: 'jdbc', 数据库类型
+ hasSchema: true, // 默认是否支持模式
+ hasSchemas: {
+ "pgsql": true,
+ "mysql": false,
+ },是否支持模式 version: boolean
+ kerberos: false, // 是否添加kerberos认证方式
+ }, function (url) {
+ var result = url.match(/^jdbc:(mysql|postgresql):\/\/([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?\/([0-9a-zA-Z_\\.]+)(.*)finedbType=([^&]+)(|(&.*))/i); // 匹配正则
+ if (result) {
+ return {
+ host: result[2], //主机
+ port: result[4] === "port" ? "" : result[4], // 端口
+ databaseName: result[5], // 数据库名称
+ version: result[7].split('-')[1] ?? "pgsql", // 版本 单版本不要返回这个
+ };
+ }
+//适配原先tbase的url
+ result = url.match(/^jdbc:postgresql:\/\/([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?\/([0-9a-zA-Z_\\.]+)(.*)/i);
+ if (result) {
+ return {
+ host: result[1],
+ port: result[3] === "port" ? "" : result[3],
+ databaseName: result[4],
+ version: "pgsql",
+ };
+ }
+
+ });
+ });
+```
+
+### C 工程开发
+
+#### 1. 图片资源添加
+ 工程`decision-webui-dev`
+ decision-webui/dist/images/1x/icon/database
+ decision-webui/dist/images/2x/icon/database
+
+#### 2. 国际化添加
+ 工程`decision-webui-dev`
+ decision-i18n/decision-main-i18n/src/main/resources/com/fr/decision/web/i18n
+
+#### 3. 版本控制
+ 版本和平台保持一致
+
## 接口文档:
-### 增加数据连接类型
+### A 增加数据连接类型
+#### 1. 增加数据连接类型
使用`BI.config`,ConstantName名称为`dec.constant.database.conf.connect.types`,值为连接的名称
例如增加`Redis`的连接:
@@ -30,25 +129,25 @@ BI.config(ConstantPluginTyps, (datas: string[]) => [...datas, {
}]);
```
-### 数据连接填写页面
+#### 2. 数据连接填写页面
edit属性值为填写组件shortcut的名称
-### 数据连接展示页面
+#### 3. 数据连接展示页面
show属性值为组件shortcut的名称
-### 示例
-```
+#### 4. 示例
+```js
const DataBaseConfigProvider = 'dec.connection.provider.datebase';
const RedisShowName = 'dec.dcm.connection.plugin.redis.show';
const RedisEditName = 'dec.dcm.connection.plugin.redis.edit';
BI.config(DataBaseConfigProvider, function (provider) {
- provider.registerDatabaseType({
+ provider.registerDatabaseType([{
text: "Redis",
databaseType: "Redis",
edit: "dec.dcm.connection.plugin.demo.edit",
show: "dec.dcm.connection.plugin.demo.show",
- });
+ }]);
});
const RedisShow = BI.inherit(BI.Widget, {
@@ -116,7 +215,7 @@ const RedisShow = BI.inherit(BI.Widget, {
],
},
],
- };
+ },
},
});
BI.shortcut(RedisShowName, RedisShow);
@@ -211,7 +310,55 @@ const RedisEdit = BI.inherit(BI.Widget, {
password: this.password.getValue(),
};
},
+ //可以触发组件的数据save方法,不需要则可不写
+ async save() {
+ let result = false;
+ await Promise.resolve().then(() => {result = true});
+ //要求返回是否成功的boolean变量
+ return result;
+ },
});
BI.shortcut(RedisEditName, RedisEdit);
```
+### B 添加数据连接实例
+#### 1. 增加数据连接
+```js
+BI.config('dec.constant.connection.list', function (value) {
+ const result = [{
+ "connectionType": "Redis",//和databaseType一致
+ "connectionName": "CHART",//类似于id,唯一性
+ "pluginConnection": true,//表示是外来添加的插件
+ "connectionData": {
+ //表单保存数据
+ },
+ "connectionId": null,
+ }];
+ return value.concat(result);
+ })
+```
+### C 添加数据连接类型分类
+#### 1. 添加分类DEMO
+```js
+BI.config('dec.constant.database.filter.type', (value) => {
+ value.push({
+ text:"DEMO",
+ value:"DEMO_VALUE"
+ });
+ return value;
+ });
+```
+#### 2. 添加数据连接类型进DEMO
+```js
+ BI.config('dec.connection.provider.datebase', function (provider) {
+ text: "Redis",//必填
+ databaseType: "Redis",//唯一值
+ marker: 'DEMO_VALUE',//marker对标dec.constant.database.filter.type常量item的value,用于过滤
+ isHideConnection: true, //是否隐藏测试连接按钮
+ isNoSave: true,//是否不执行平台的保存逻辑
+ iconUrl:'https://work.fineres.com/secure/projectavatar?pid=10301&avatarId=10011',
+ driver: 'com.amazon.redshift.jdbc41.Driver',
+ drivers: ['com.amazon.redshift.jdbc4.Driver', 'com.amazon.redshift.jdbc41.Driver'],
+ url: 'jdbc:redshift://endpoint:port/database',
+ }
+```
diff --git a/babel.config.js b/babel.config.js
index 9085ac7..092e4d1 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,3 +1,13 @@
-module.exports = function (api) {
- return require("@fui/babel-preset-fineui").configs.base(api)
+module.exports = api => {
+ const { plugins, presets, sourceType } = require("@fui/babel-preset-fineui").configs.base(api);
+
+ return {
+ compact: false,
+ presets,
+ sourceType,
+ plugins: [
+ ...plugins,
+ "@babel/plugin-proposal-logical-assignment-operators",
+ ],
+ };
};
diff --git a/i18n/zh_cn.properties b/i18n/zh_cn.properties
index 30f185f..1cb2866 100644
--- a/i18n/zh_cn.properties
+++ b/i18n/zh_cn.properties
@@ -62,6 +62,11 @@ Dec-Dcm_Connection_Form_UserName= 用户名
Dec-Dcm_Connection_Form_Password= 密码
Dec-Dcm_Connection_Form_Principal= 客户端principal
Dec-Dcm_Connection_Form_KeyPath= keytab密钥路径
+Dec-Dcm_Connection_Form_Krb5File= krb5.conf文件
+Dec-Dcm_Connection_File_Upload_Success= 已成功上传并校验成功
+Dec-Dcm_Connection_File_Upload_Error= 检测异常
+Dec-Dcm_Connection_File_Upload_ErrorCode= 错误代码
+Dec-Dcm_Connection_File_Upload_ErrorMsg= 错误详情
Dec-Dcm_Connection_Form_Pool_Properties= 连接池属性
Dec-Dcm_Connection_Form_SQL_Validation_Query= SQL验证查询
Dec-Dcm_Connection_Form_Connection-Check= 获取连接前校验
@@ -80,10 +85,10 @@ Dec-Dcm_Connection_Form_Database_Max_Wait= 最大等待时间
Dec-Dcm_Connection_Form_Database_Validation_Query= SQL验证查询
Dec-Dcm_Connection_Form_Database_Test_On_Borrow= 获取连接前检验
Dec-Dcm_Connection_Form_Database_Test_On_Return= 归还连接前检验
-Dec-Dcm_Connection_Form_Database_Test_While_Idle= 开启空闲回收器检验
-Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis= 空闲连接回收器休眠时间
+Dec-Dcm_Connection_Form_Database_Test_While_Idle= 获取连接时空闲连接可用性校验
+Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis= 空闲连接回收器工作间隔
Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num= 空闲连接回收检查数
-Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis= 保持空闲最小时间值
+Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis= 空闲连接回收时间阈值
Dec-Dcm_Connection_Make_Sure_Delete= 确定删除该数据连接?
Dec-Dcm_Connection_ReConnect= 重新连接
Dec-Dcm_Connection_JNDI_Form_ConnectionName= JNDI的名字
@@ -96,7 +101,7 @@ Dec-Dcm_Connection_JNDI= JNDI数据连接
Dec-Dcm_Connection_JNDI_Warning= 注意:需要把包含INTIAL_CONTEXT_FACTORY类的.jar文件复制到软件安装目录下的/lib目录下
Dec-Dcm_Connection_Error= 接口访问错误
Dec-Dcm_Connection_Is_Using= 该连接正在被{R1}编辑,请稍后再试
-Dec-Dcm_Connection_Check_Integer= 请输入不小于0的整数
+Dec-Dcm_Connection_Check_Integer= 请输入不小于{}的整数
Dec-Dcm_Connection_Check_Number= 只允许为整数
Dec-Dcm_Connection_JDBC_Other=其他JDBC
Dec-Dcm_Connection_JDBC_Warning= 请确认已经将krb5.Conf文件添加到/webapps/webroot/WEB_INF/resources目录
@@ -303,4 +308,9 @@ BI-Basic_No_Select= 不选
BI-Basic_Now= 此刻
Dec-Dcm_Connection_Analytic_DB=阿里云AnalyticDB
Dec-Dcm_Connection_Value_Out_Range=数值超出范围
-Dec-Dcm_Socket_Unable_Connect_Tip=可能出现编辑冲突
\ No newline at end of file
+Dec-Dcm_Socket_Unable_Connect_Tip=可能出现编辑冲突
+Dec-Dcm_Connection_File_Upload_ErrorTip1= 参考
+Dec-Dcm_Connection_File_Upload_ErrorTip2= kerberos配置
+Dec-Dcm_Connection_File_Upload_ErrorTip3= 获取帮助或联系技术支持
+Dec-Dcm_Connection_Timeout_Detection=数据连接超时检测
+Dec-Dcm_Connection_Timeout_Millisecond=毫秒(ms)
\ No newline at end of file
diff --git a/package.json b/package.json
index d7f4eac..e59b383 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"author": "decision",
"license": "MIT",
"dependencies": {
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7",
"@types/jss": "9.5.8",
"autoprefixer": "^9.6.1",
"es6-promise": "4.2.6",
@@ -18,9 +19,9 @@
"devDependencies": {
"@fui/babel-preset-fineui": "^1.0.0",
"@types/jest": "24.0.11",
- "@typescript-eslint/eslint-plugin": "1.7.0",
- "@typescript-eslint/parser": "1.7.0",
- "axios": "0.18.0",
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
+ "@typescript-eslint/parser": "^5.0.0",
+ "axios": "^0.24.0",
"babel-loader": "8.0.6",
"body-parser": "1.18.3",
"chokidar": "2.1.5",
diff --git a/private/i18n.ts b/private/i18n.ts
index 8f00670..eaf7e10 100644
--- a/private/i18n.ts
+++ b/private/i18n.ts
@@ -61,6 +61,11 @@ export default {
'Dec-Dcm_Connection_Form_Password': '密码',
'Dec-Dcm_Connection_Form_Principal': '客户端principal',
'Dec-Dcm_Connection_Form_KeyPath': 'keytab密钥路径',
+ 'Dec-Dcm_Connection_Form_Krb5File': 'krb5.conf文件',
+ 'Dec-Dcm_Connection_File_Upload_Success': ' 已成功上传并校验成功',
+ 'Dec-Dcm_Connection_File_Upload_Error': '检测异常',
+ 'Dec-Dcm_Connection_File_Upload_ErrorCode': '错误代码',
+ 'Dec-Dcm_Connection_File_Upload_ErrorMsg': '错误详情',
'Dec-Dcm_Connection_Form_Pool_Properties': '连接池属性',
'Dec-Dcm_Connection_Form_SQL_Validation_Query': 'SQL验证查询',
'Dec-Dcm_Connection_Form_Connection-Check': '获取连接前校验',
@@ -79,10 +84,10 @@ export default {
'Dec-Dcm_Connection_Form_Database_Validation_Query': 'SQL验证查询',
'Dec-Dcm_Connection_Form_Database_Test_On_Borrow': '获取连接前检验',
'Dec-Dcm_Connection_Form_Database_Test_On_Return': '归还连接前检验',
- 'Dec-Dcm_Connection_Form_Database_Test_While_Idle': '开启空闲回收器检验',
- 'Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis': '空闲连接回收器休眠时间',
+ 'Dec-Dcm_Connection_Form_Database_Test_While_Idle': '获取连接时空闲连接可用性校验',
+ 'Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis': '空闲连接回收器工作间隔',
'Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num': '空闲连接回收检查数',
- 'Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis': '保持空闲最小时间值',
+ 'Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis': '空闲连接回收时间阈值',
'Dec-Dcm_Connection_Make_Sure_Delete': '确定删除该数据连接?',
'Dec-Dcm_Connection_ReConnect': '重新连接',
'Dec-Dcm_Connection_JNDI_Form_ConnectionName': 'JNDI的名字',
@@ -95,7 +100,7 @@ export default {
'Dec-Dcm_Connection_JNDI_Warning': '注意:需要把包含INTIAL_CONTEXT_FACTORY类的.jar文件复制到软件安装目录下的/lib目录下',
'Dec-Dcm_Connection_Error': '接口访问错误',
'Dec-Dcm_Connection_Is_Using': '该连接正在被{R1}编辑,请稍后再试',
- 'Dec-Dcm_Connection_Check_Integer': '请输入不小于0的整数',
+ 'Dec-Dcm_Connection_Check_Integer': '请输入不小于{}的整数',
'Dec-Dcm_Connection_Check_Number': '只允许为整数',
'Dec-Dcm_Connection_JDBC_Other': '其他JDBC',
'Dec-Dcm_Connection_JDBC_Warning': '请确认已经将krb5.Conf文件添加到/webapps/webroot/WEB_INF/resources目录',
@@ -306,4 +311,7 @@ export default {
'Dec-Connection_Lic_Limit_Approach_Tip': '当前数据连接数量超过注册lic限制({}个),所有数据连接都不可用,请删除多余的数据连接',
'Dec-Connection_Lic_Limit_Approach_Prevent_Tip': '当前数据连接数量已经达到注册lic限制({}个),无法新增',
'Dec-Dcm_Connection_Check_Fetch_Size_Range': '请输入0-1000000之间的值',
+ 'Dec-Dcm_Connection_File_Upload_ErrorTip1':'参考',
+ 'Dec-Dcm_Connection_File_Upload_ErrorTip2': 'kerberos配置',
+ 'Dec-Dcm_Connection_File_Upload_ErrorTip3': '取帮助或联系技术支持',
};
diff --git a/src/modules/app.model.ts b/src/modules/app.model.ts
index 200800c..01b74b5 100644
--- a/src/modules/app.model.ts
+++ b/src/modules/app.model.ts
@@ -7,7 +7,7 @@ import { getAllDatabaseTypes } from './app.service';
export class AppModel extends Model {
static xtype = 'dec.dcm.model.main';
- childContext = ['pageIndex', 'datebaseTypeSelected', 'datebaseTypeSelectedOne', 'filter', 'connections', 'connectionSelected', 'connectionSelectedOne', 'saveEvent', 'testEvent', 'isCopy', 'connectionLicInfo'];
+ childContext = ['pageIndex', 'datebaseTypeSelected', 'datebaseTypeSelectedOne', 'filter', 'connections', 'connectionSelected', 'connectionSelectedOne', 'saveEvent', 'testEvent', 'isCopy', 'connectionLicInfo', 'noTestConnection'];
state() {
return {
@@ -23,6 +23,7 @@ export class AppModel extends Model {
currentConnectionNum: 0,
maxConnectionNum: 0,
},
+ noTestConnection: false,
};
}
diff --git a/src/modules/app.provider.ts b/src/modules/app.provider.ts
index af2db61..3662b4a 100644
--- a/src/modules/app.provider.ts
+++ b/src/modules/app.provider.ts
@@ -1,11 +1,67 @@
import { CONSTANT_PLUGIN_TYPES } from './app.constant';
+import { DATA_BASE_TYPES } from '@constants/constant';
-BI.provider('dec.connection.provider.datebase', function() {
+BI.provider('dec.connection.provider.datebase', function () {
this.resolves = {};
+ function starRocksResolve(url: string) {
+ // 处理starRocks数据连接常规模式
+ let result = url.match(/^jdbc:mysql:\/\/([0-9a-zA-Z_\\.-]+):([0-9a-zA-Z_\\.-]+)\/([0-9a-zA-Z_\\.-]+)\.([^]+)(.*)/i);
+ if (result) {
+ return {
+ host: result[1],
+ port: result[2] === 'port' ? '' : result[2],
+ catalog: result[3],
+ databaseName: result[4],
+ urlInfo: result[0],
+ };
+ } else {
+ // 兼容老数据库里面没有catalog的情况
+ result = url.match(/^jdbc:mysql:\/\/([0-9a-zA-Z_\\.-]+):([0-9a-zA-Z_\\.-]+)\/([^]+)(.*)/i);
+ if (result) {
+ return {
+ host: result[1],
+ port: result[2] === 'port' ? '' : result[2],
+ catalog: '',
+ databaseName: result[3],
+ urlInfo: result[0],
+ };
+ }
+ }
+ // 处理starRocks数据连接负载均衡模式
+ let loadBalance = url.match(/^jdbc:mysql:loadbalance:\/\/[^/]+\/([^/]+)\.([^/]+)/i);
+ if (loadBalance) {
+ return {
+ host: '',
+ port: '',
+ catalog: loadBalance[1],
+ databaseName: loadBalance[2],
+ urlInfo: loadBalance[0],
+ }
+ } else {
+ // 兼容老数据库里面没有catalog的情况
+ loadBalance = url.match(/^jdbc:mysql:loadbalance:\/\/[^/]+\/([^/]+)([^/]+)/i);
+ if (loadBalance) {
+ return {
+ host: '',
+ port: '',
+ catalog: '',
+ databaseName: loadBalance[1],
+ urlInfo: loadBalance[0],
+ }
+ }
+ }
+ return {
+ host: '',
+ port: '',
+ databaseName: '',
+ urlInfo: '',
+ };
+ }
// 原service中resolveUrlInfo方法
- function jdbcResolve (url: string) {
+ function jdbcResolve(url: string) {
if (BI.isNull(url)) return {};
+
const oracleUlr = url.match(/^jdbc:(oracle):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/)([^]+)(.*)/i);
if (oracleUlr) {
return {
@@ -15,8 +71,8 @@ BI.provider('dec.connection.provider.datebase', function() {
urlInfo: oracleUlr[10],
};
}
-
- const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;)([^]+)(.*)/i);
+
+ const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)(.*)/i);
if (greenplumUrl) {
return {
host: greenplumUrl[4],
@@ -25,7 +81,7 @@ BI.provider('dec.connection.provider.datebase', function() {
urlInfo: greenplumUrl[9],
};
}
- const result = url.match(/^jdbc:(mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql|clickhouse):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)?(.*)/i);
+ const result = url.match(/^jdbc:(mysql|sqlserver|db2|dm|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql|clickhouse|trino|sybase:Tds):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)?(.*)/i);
if (result) {
return {
host: result[5],
@@ -34,13 +90,24 @@ BI.provider('dec.connection.provider.datebase', function() {
urlInfo: result[10],
};
}
-
+
+ // 处理SAP HANA数据连接url
+ const sapHanaUrl = url.match(/^jdbc:(sap):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\?databaseName=)?([^&]+)([^]+)?(.*)/i);
+ if (sapHanaUrl) {
+ return {
+ host: sapHanaUrl[5],
+ port: sapHanaUrl[7] === 'port' ? '' : sapHanaUrl[7],
+ databaseName: sapHanaUrl[9] || '',
+ urlInfo: sapHanaUrl[10],
+ };
+ }
+
// 处理oracle的RAC方式
if (/^jdbc:oracle:thin:([0-9a-zA-Z/]*)?@\(DESCRIPTION/i.test(url)) {
const host = url.match(/\(HOST\s*=\s*([0-9a-zA-Z_\\.-]+)\)/i);
const port = url.match(/\(PORT\s*=\s*([0-9]+)\)/i);
const databaseName = url.match(/\(SERVICE_NAME\s*=\s*([\s0-9a-zA-Z_\\.]+)\)/i);
-
+
return {
host: host ? host[1] : '',
port: port && port[1] !== 'port' ? port[1] : '',
@@ -48,7 +115,6 @@ BI.provider('dec.connection.provider.datebase', function() {
urlInfo: '',
};
}
-
return {
host: '',
port: '',
@@ -57,18 +123,55 @@ BI.provider('dec.connection.provider.datebase', function() {
};
}
+ function coverBaseDatabase(config) {
+ const baseDataBase = DATA_BASE_TYPES.find(item => item.text === config.text);
+ if (BI.isNotNull(baseDataBase)) {
+ // 覆盖基础配置
+ Object.assign(baseDataBase, config);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ function filterPluginDataTypeByPriority() {
+ const originTypes = [...BI.Constants.getConstant(CONSTANT_PLUGIN_TYPES)];
+ const sortDataTypes = BI.sortBy(originTypes, (index, value: any) => {
+ return value.priority || 0;
+ })
+ return BI.uniqWith(sortDataTypes, (current, other) => {
+ return current.text == other.text;
+ });
+ }
+
this.registerDatabaseType = (config: any) => {
+ if (coverBaseDatabase(config)) return;
+
BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, config));
};
-
+
this.registerJdbcDatabase = (config: any, resolve?: Function) => {
- BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, { ...config, type: 'jdbc' }));
-
+ config = {
+ ...config,
+ type: 'jdbc',
+ };
BI.isFunction(resolve) && (this.resolves[config.databaseType] = resolve);
+
+ if (coverBaseDatabase(config)) return;
+
+ BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, config));
};
this.$get = () => BI.inherit(BI.OB, {
- getJdbcResolveByType: (type: string) => this.resolves[type] || jdbcResolve,
+ getJdbcResolveByType: (type: string) => {
+ // starRocks特殊处理
+ // todo: 后面有专门的迭代系统处理,这里先临时解决下bug
+ if (type === "starrocks"){
+ return starRocksResolve
+ }
+ return this.resolves[type] || jdbcResolve
+ },
customDatabaseType: BI.Constants.getConstant(CONSTANT_PLUGIN_TYPES),
});
});
diff --git a/src/modules/app.service.ts b/src/modules/app.service.ts
index 145b807..b236bb2 100644
--- a/src/modules/app.service.ts
+++ b/src/modules/app.service.ts
@@ -1,7 +1,13 @@
-import { DATA_BASE_TYPES, DATA_BASE_TYPES_OTHER, DESIGN_DRIVER_TYPE, OTHER_JDBC } from '@constants/constant';
+import {
+ DATA_BASE_TYPES,
+ DATA_BASE_TYPES_OTHER,
+ DESIGN_DRIVER_TYPE,
+ OTHER_JDBC,
+ DATABASE_TYPE,
+} from '@constants/constant';
import { DatabaseType } from './app.typings';
import { Connection } from './crud/crud.typings';
-export function getAllDatabaseTypes():DatabaseType[] {
+export function getAllDatabaseTypes(): DatabaseType[] {
return [
...DATA_BASE_TYPES,
...BI.Providers.getProvider('dec.connection.provider.datebase').customDatabaseType.map(item => {
@@ -45,13 +51,13 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT
if (!databaseType) {
return DATA_BASE_TYPES_OTHER;
}
-
+
return databaseType;
}
-export function resolveUrlInfo (url: string, database?: string) {
+export function resolveUrlInfo(url: string, database?: string) {
if (BI.isNull(url)) return {};
-
+
return BI.Providers.getProvider('dec.connection.provider.datebase').getJdbcResolveByType(database)(url) || {
host: '',
port: '',
@@ -61,14 +67,40 @@ export function resolveUrlInfo (url: string, database?: string) {
}
// 拼接url
-export function splitUrl(host: string, port: string, database: string, baseUrl: string) {
+export function splitUrl(host: string, port: string, catalog: string, database: string, baseUrl: string, databaseType: string) {
if (baseUrl.startsWith('jdbc:sqlserver')) {
return baseUrl.replace('hostname', host).replace(':port', port ? `:${port}` : '')
.replace('=database', `=${database}`);
}
-
+
+ // https://work.fineres.com/browse/REPORT-72078
+ if (baseUrl.startsWith('jdbc:informix-sqli')) {
+ return baseUrl.replace('hostname', host)
+ .replace(':port', port ? `:${port}` : '')
+ .replace('database', database)
+ .replace(':INFORMIXSERVER={server}', '');
+ }
+
+ if (databaseType === DATABASE_TYPE.STAR_ROCKS) {
+ let databaseStr = '';
+ if (!catalog || !database) {
+ databaseStr = catalog + database;
+ } else {
+ databaseStr = catalog + '.' + database;
+ }
+ return baseUrl.replace('hostname', host).replace(':port', port ? `:${port}` : '')
+ .replace('default_catalog.database', databaseStr);
+ }
+
+ if (databaseType === DATABASE_TYPE.SAP_HANA) {
+ return baseUrl.replace('hostname', host)
+ .replace('port', port || '')
+ .replace('=database', `=${database}`);
+ }
+
return baseUrl.replace('hostname', host).replace(':port', port ? `:${port}` : '')
- .replace('database', database)
+ .replace('/database', `/${database}`)
+ .replace(':database', `:${database}`)
.replace('dbname', database);
}
@@ -77,13 +109,13 @@ export function connectionCanEdit(connection: Connection) {
// privilegeType === 4 代表编辑权限,privilegeValue === 2 代表有权限
return connection.privilegeDetailBeanList.some(item => item.privilegeType === 4 && item.privilegeValue === 2);
}
-
+
return true;
}
export function getTextByDatabaseType(databaseType: string) {
const database = getAllDatabaseTypes().find(item => item.databaseType === databaseType);
-
+
return database ? database.text : '';
}
diff --git a/src/modules/app.ts b/src/modules/app.ts
index c347927..46cd7b7 100644
--- a/src/modules/app.ts
+++ b/src/modules/app.ts
@@ -7,8 +7,10 @@ import { Tab } from '@fui/core';
import { Datebase } from './pages/database/database';
import { Maintain } from './pages/maintain/maintain';
import { ConnectionPool } from './pages/connection_pool/connection_pool';
+import { TimeOutSetting } from './pages/setting/setting';
import './app.provider';
import '../less/index.less';
+import "./pages/__point__/connect.point";
@shortcut()
@store(AppModel)
@@ -37,7 +39,12 @@ export class App extends BI.Widget {
{
el: {
type: Title.xtype,
- cls: 'bi-border-bottom',
+ listeners: [{
+ eventName: 'EVENT_CLICK_SETTING',
+ action:() => {
+ this._setting();
+ },
+ }]
},
height: 40,
},
@@ -75,13 +82,30 @@ export class App extends BI.Widget {
}
},
},
- left: 10,
- top: 10,
- right: 10,
- bottom: 10,
+ left: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
}],
},
],
};
}
+
+ private _setting() {
+ const settingLayerId = BI.UUID();
+ BI.Layers.create(settingLayerId, null, {
+ container: this,
+ render: {
+ type: TimeOutSetting.xtype,
+ listeners: [{
+ eventName: "EVENT_CHANGE",
+ action: function () {
+ BI.Layers.remove(settingLayerId);
+ },
+ }],
+ },
+ }, this);
+ BI.Layers.show(settingLayerId);
+ }
}
diff --git a/src/modules/app.typings.d.ts b/src/modules/app.typings.d.ts
index 67a5665..3eda6f3 100644
--- a/src/modules/app.typings.d.ts
+++ b/src/modules/app.typings.d.ts
@@ -8,9 +8,18 @@ export interface DatabaseType {
internal: boolean;
type: string;
hasSchema?: boolean;
+ hasSchemas?: {
+ [key: string]: boolean;
+ };
+ fetchSize: number;
+ versionConfig?: {
+ [key: string]: DatabaseType;
+ },
kerberos?: boolean;
iconUrl?: string;
+ versions?: string[];
urls?: {
[key: string]: string;
- }
+ };
+ marker?: string;
}
diff --git a/src/modules/components/collapse/collapse.ts b/src/modules/components/collapse/collapse.ts
index 58e8db1..de2c51d 100644
--- a/src/modules/components/collapse/collapse.ts
+++ b/src/modules/components/collapse/collapse.ts
@@ -12,6 +12,7 @@ export class Collapse extends BI.BasicButton {
name: '',
isCollapse: true,
$testId: 'dec-dcm-components-collapse',
+ el: {},
}
rightFont: IconLabel;
@@ -57,6 +58,7 @@ export class Collapse extends BI.BasicButton {
lgap: 2,
text: this.options.name,
},
+ this.options.el,
],
};
}
@@ -64,4 +66,8 @@ export class Collapse extends BI.BasicButton {
doClick() {
this.store.setCollapse(!this.model.isCollapse);
}
+
+ setCollapse(v: boolean) {
+ this.store.setCollapse(v);
+ }
}
diff --git a/src/modules/components/file_chooser/file_chooser.model.ts b/src/modules/components/file_chooser/file_chooser.model.ts
new file mode 100644
index 0000000..708bd0f
--- /dev/null
+++ b/src/modules/components/file_chooser/file_chooser.model.ts
@@ -0,0 +1,68 @@
+import { model, Model } from '@core/core';
+
+type RootInfo = {
+ url: string; // api url
+ prefix: string; // 路径前缀
+ root: string; // 根文件夹名称
+};
+
+export const ROOT_INFO_MAP: Record = {
+ // 证书 resources/certificates/
+ certificates: {
+ url: '/v10/certificates/all',
+ prefix: 'resources/',
+ root: 'certificates',
+ },
+};
+
+@model()
+export class FileChooserModel extends Model {
+ static xtype = 'dec.dcm.model.components.file_chooser';
+
+ private options: {
+ root: string;
+ };
+
+ state() {
+ return {
+ keyword: '', // 搜索关键字
+ items: [], // 文件项
+ };
+ }
+
+ actions = {
+ /**
+ * 请求获取items
+ * @param callback 回调
+ */
+ requestGetItems: (callback?: Function) => {
+ const { keyword } = this.model;
+ const { url, prefix, root } = ROOT_INFO_MAP[this.options.root];
+ const requestUrl = `${url}?keyword=${encodeURIComponent(keyword)}`;
+ Dec.reqGetHandle(requestUrl, '', (data) => {
+ this.model.items = data
+ .concat({
+ id: root,
+ text: prefix + root,
+ value: prefix + root,
+ isParent: true,
+ })
+ .map((item) => ({
+ ...item,
+ value: prefix + item.path,
+ open: item.id === root || BI.isKey(keyword),
+ }));
+ BI.isFunction(callback) && callback();
+ });
+ },
+
+ /**
+ * 设置keyword
+ * @param value
+ */
+ setKeyword: (value: string) => {
+ this.model.keyword = value;
+ this.requestGetItems();
+ },
+ };
+}
diff --git a/src/modules/components/file_chooser/file_chooser.ts b/src/modules/components/file_chooser/file_chooser.ts
new file mode 100644
index 0000000..dc430d1
--- /dev/null
+++ b/src/modules/components/file_chooser/file_chooser.ts
@@ -0,0 +1,183 @@
+import { EVENT_CHANGE } from './../collapse/collapse';
+import { shortcut, store } from '@core/core';
+import { SignEditor, MultiLayerSingleLevelTree, SearchEditor, Button, Editor } from '@fui/core';
+import { FileChooserModel } from './file_chooser.model';
+
+@shortcut()
+@store(FileChooserModel, {
+ props(this: FileChooser) {
+ return this.options;
+ },
+})
+export class FileChooser extends BI.Widget {
+ static xtype = 'dec.dcm.components.file_chooser';
+
+ props = {
+ width: 300,
+ root: '', // 含义见model中的RootInfo
+ watermark: '',
+ value: '',
+ };
+
+ model: FileChooserModel['model'];
+ store: FileChooserModel['store'];
+ watch = {
+ items: (value) => {
+ this.fileTree.populate(value);
+ },
+ };
+
+ textEditor: SignEditor;
+ keywordEditor: SearchEditor;
+ fileTree: MultiLayerSingleLevelTree;
+ sureButton: Button;
+
+ render() {
+ const { width, watermark, value } = this.options;
+
+ return {
+ type: BI.VerticalAdaptLayout.xtype,
+ height: 24,
+ items: [
+ {
+ type: BI.SignEditor.xtype,
+ cls: 'bi-border-bottom bi-focus-shadow',
+ width,
+ height: 22,
+ watermark,
+ title: value,
+ value,
+ ref: (_ref: SignEditor) => {
+ this.textEditor = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.SignEditor.EVENT_CHANGE,
+ action: () => {
+ const value = this.textEditor.getValue();
+ this.setValue(value);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.Button.xtype,
+
+ text: BI.i18nText('Dec-Basic_Choose_File'),
+ clear: true,
+ handler: () => {
+ this.openFileChoosePopover();
+ },
+ },
+ lgap: 10,
+ },
+ ],
+ };
+ }
+
+ getValue(): string {
+ return this.textEditor.getValue();
+ }
+
+ setValue(value: string) {
+ this.options.value = value;
+ this.textEditor.text.setTitle(value);
+ this.textEditor.setValue(value);
+ }
+
+ /**
+ * 打开文件选择弹窗
+ */
+ private openFileChoosePopover() {
+ // 重置搜索关键词
+ this.store.setKeyword('');
+ // 创建并显示窗口
+ const popoverName = BI.UUID();
+ BI.Popovers.create(
+ popoverName,
+ {
+ header: BI.i18nText('Dec-Data_Set_File_Select_Server_File'),
+ body: {
+ type: BI.VTapeLayout.xtype,
+ items: [
+ {
+ type: BI.SearchEditor.xtype,
+ ref: (ref: SearchEditor) => {
+ this.keywordEditor = ref;
+ },
+ height: 24,
+ value: this.model.keyword,
+ listeners: [
+ {
+ eventName: BI.SearchEditor.EVENT_CHANGE,
+ action: () => {
+ const value = this.keywordEditor.getValue();
+ this.store.setKeyword(value);
+ },
+ },
+ {
+ eventName: BI.SearchEditor.EVENT_CLEAR,
+ action: () => {
+ this.store.setKeyword('');
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.MultiLayerSingleLevelTree.xtype,
+ ref: (ref: MultiLayerSingleLevelTree) => {
+ this.fileTree = ref;
+ },
+ keywordGetter: () => this.model.keyword,
+ items: this.model.items,
+ listeners: [
+ {
+ eventName: BI.MultiLayerSingleLevelTree.EVENT_CHANGE,
+ action: () => {
+ this.sureButton.setEnable(true);
+ },
+ },
+ ],
+ },
+ tgap: 15,
+ },
+ {
+ type: BI.RightVerticalAdaptLayout.xtype,
+ height: 24,
+ vgap: 10,
+ items: [
+ {
+ type: BI.Button.xtype,
+ text: BI.i18nText('BI-Basic_Cancel'),
+ level: 'ignore',
+ handler: () => {
+ BI.Popovers.remove(popoverName);
+ },
+ },
+ {
+ el: {
+ type: BI.Button.xtype,
+ ref: (ref: Button) => {
+ this.sureButton = ref;
+ },
+ text: BI.i18nText('BI-Basic_OK'),
+ disabled: true,
+ handler: () => {
+ const value = this.fileTree.getValue()[0];
+ this.setValue(value);
+ BI.Popovers.remove(popoverName);
+ },
+ },
+ lgap: 10,
+ },
+ ],
+ },
+ ],
+ },
+ },
+ this
+ ).show(popoverName);
+ }
+}
diff --git a/src/modules/components/file_upload/file_upload.less b/src/modules/components/file_upload/file_upload.less
new file mode 100644
index 0000000..83c51ce
--- /dev/null
+++ b/src/modules/components/file_upload/file_upload.less
@@ -0,0 +1,13 @@
+.data-conf-file {
+ .x-icon{
+ width: 48px;
+ height: 48px;
+ }
+}
+
+.data-keytab-file {
+ .x-icon{
+ width: 48px;
+ height: 48px;
+ }
+}
diff --git a/src/modules/components/file_upload/file_upload.model.ts b/src/modules/components/file_upload/file_upload.model.ts
new file mode 100644
index 0000000..bf6d905
--- /dev/null
+++ b/src/modules/components/file_upload/file_upload.model.ts
@@ -0,0 +1,35 @@
+import { model, Model } from '@core/core';
+
+type UploadParam = {
+ keytabPath: string;
+ krb5ConfPath: string;
+ principal: string;
+}
+
+@model()
+export class FileUploadModel extends Model {
+ static xtype = 'dec.dcm.model.components.file_upload';
+
+ private options: {
+ inter: string;
+ }
+
+ state() {
+ return {
+ uploadUrl: '',
+ fileName: '',
+ };
+ }
+
+ actions = {
+ setFileInfo: (params: UploadParam) => {
+ const inter = this.options.inter;
+
+ this.model.uploadUrl = Dec.Utils.getEncodeURL(Dec.fineServletURL + inter, "", params);
+ },
+
+ setFileName:(v: string) => {
+ this.model.fileName = v;
+ }
+ }
+}
diff --git a/src/modules/components/file_upload/file_upload.ts b/src/modules/components/file_upload/file_upload.ts
new file mode 100644
index 0000000..9a4f62f
--- /dev/null
+++ b/src/modules/components/file_upload/file_upload.ts
@@ -0,0 +1,327 @@
+import { shortcut, store } from '@core/core';
+import { SignEditor, MultiLayerSingleLevelTree, SearchEditor, Button, Editor, Label } from '@fui/core';
+import { FileUploadModel } from './file_upload.model';
+import { ApiFactory } from 'src/modules/crud/apiFactory';
+import './file_upload.less';
+
+const api = new ApiFactory().create();
+
+@shortcut()
+@store(FileUploadModel, {
+ props(this: FileUpload) {
+ return this.options;
+ },
+})
+export class FileUpload extends BI.Widget {
+ public static xtype = "dec.dcm.components.file_upload";
+ public static EVENT_CHECK_SUCCESS = 'EVENT_CHECK_SUCCESS';
+ public static EVENT_CLEAR_FILE = 'EVENT_CLEAR_FILE';
+
+ public props = {
+ watermark: '',
+ value: '',
+ processId: '',
+ disabled: false,
+ inter: '',
+ access: '',
+ iconCls: ''
+ };
+
+ model: FileUploadModel['model'];
+ store: FileUploadModel['store'];
+ watch = {
+ uploadUrl: function () {
+ this.uploader.setUrl(this.model.uploadUrl);
+ },
+ };
+
+ public textEditor: SignEditor;
+ public keywordEditor: SearchEditor;
+ public fileTree: MultiLayerSingleLevelTree;
+ public sureButton: Button;
+ public infoLabel: Label;
+
+ public render() {
+ const { width, watermark, value, processId, inter } = this.options;
+ let self = this;
+ const processName = BI.concat("process-", processId);
+ const processClass = BI.concat(".process-", processId);
+ this.setFileInfo({
+ keytabPath: '',
+ principal:'',
+ krb5ConfPath: '',
+ });
+
+ return {
+ type: BI.VerticalLayout.xtype,
+ items:[{
+ type: BI.FloatLeftLayout.xtype,
+ items: [
+ {
+ type: BI.SignEditor.xtype,
+ cls: 'bi-border-bottom bi-focus-shadow',
+ width: 300,
+ height: 22,
+ watermark,
+ disabled: true,
+ value,
+ ref: (_ref: SignEditor) => {
+ this.textEditor = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.SignEditor.EVENT_CHANGE,
+ action: () => {
+ const value = this.textEditor.getValue();
+ this.setValue(value);
+ },
+ },
+ ],
+ }, {
+ type: BI.Button.xtype,
+ width: 100,
+ _lgap: 10,
+ iconCls: "upload-font",
+ level: "ignore",
+ ghost: true,
+ ref: (_ref: Button) => {
+ this.uploadButton = _ref;
+ },
+ text: BI.i18nText('Dec-Basic_Choose_File'),
+ handler: () => {
+ this.uploader.select();
+ },
+ },
+ ],
+ }, {
+ type: BI.FloatLeftLayout.xtype,
+ tgap: 8,
+ invisible: true,
+ ref: (_ref) => {
+ this.fileInfo = _ref;
+ },
+ items: [
+ {
+ type: BI.VerticalLayout.xtype,
+ cls: "bi-border",
+ items: [{
+ type: BI.HTapeLayout.xtype,
+ height: 68,
+ width: 300,
+ items: [{
+ el: {
+ type: BI.IconLabel.xtype,
+ cls: this.options.iconCls,
+ },
+ width: 48,
+ lgap: 8,
+ }, {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ items : [{
+ type: BI.Label.xtype,
+ width: 200,
+ height: 20,
+ textAlign: "left",
+ ref: (_ref: Label) => {
+ this.fileName = _ref;
+ },
+ },{
+ type: BI.VerticalAdaptLayout.xtype,
+ items: [{
+ type: BI.Label.xtype,
+ cls: "bi-tips",
+ height: 20,
+ rgap: 3,
+ ref: (_ref: Label) => {
+ this.fileSize = _ref;
+ },
+ }, {
+ type: BI.Label.xtype,
+ cls: "bi-tips",
+ height: 20,
+ ref: (_ref: Label) => {
+ this.fileModified = _ref;
+ },
+ }]
+
+ }],
+
+ },
+ tgap: 14,
+ lgap: 4,
+ }, {
+ el: {
+ type: BI.IconButton.xtype,
+ cls: "default-delete-font",
+ handler: function () {
+ NProgress.set(0.0);
+ self.xhr.abort();
+ self.store.setFileName('');
+ self.clearInfo();
+ self.fireEvent(FileUpload.EVENT_CLEAR_FILE);
+
+ },
+ },
+ rgap: 10,
+ }]
+ }, {
+ type: BI.VerticalLayout.xtype,
+ cls: processName,
+ width: 300,
+ height: 1,
+ }]
+
+ }, {
+ el :{
+ type: BI.VerticalLayout.xtype,
+ cls: "bi-error",
+ ref: (_ref: any) => {
+ this.errorInfo = _ref;
+ },
+ invisible: true,
+ items : [{
+ type: BI.Label.xtype,
+ height: 20,
+ textAlign: "left",
+ ref: (_ref: Label) => {
+ this.errorCode = _ref;
+ },
+ },{
+ type: BI.Label.xtype,
+ height: 20,
+ textAlign: "left",
+ ref: (_ref: Label) => {
+ this.errorMsg = _ref;
+ },
+ }, {
+ type: BI.VerticalAdaptLayout.xtype,
+ rgap: 5,
+ items: [
+ {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-Dcm_Connection_File_Upload_ErrorTip1'),
+ },{
+ type: BI.TextButton.xtype,
+ cls: "bi-high-light bi-high-light-border-bottom",
+ text: BI.i18nText('Dec-Dcm_Connection_File_Upload_ErrorTip2'),
+ handler: function () {
+ window.open(Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][DecCst.Hyperlink.KERBEROS_CONF_HELP]);
+ },
+ },{
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-Dcm_Connection_File_Upload_ErrorTip3'),
+ }
+ ],
+ },],
+ },
+ vgap: 4,
+ lgap: 8,
+ }
+ ],
+ }, {
+ type: BI.MultifileEditor.xtype,
+ ref: (ref:any) => {
+ self.uploader = ref;
+ },
+ url: this.model.uploadUrl,
+ accept: this.options.accept,
+ listeners: [
+ {
+ // 选择文件
+ eventName: BI.MultifileEditor.EVENT_CHANGE,
+ action: function (files) {
+ self.options.attachId = '';
+ const fileInfo = files.files[0];
+ self.setInfo(fileInfo);
+ self.store.setFileName(fileInfo.fileName);
+ this.upload();
+ NProgress.configure({ parent: processClass, minimum: 0.0 });
+ },
+ },
+ {
+ // 上传进度刷新
+ eventName: BI.MultifileEditor.EVENT_PROGRESS,
+ action: function (progress) {
+ let rate = progress.loaded/progress.total;
+ NProgress.set(rate);
+ },
+ },
+ {
+ // 开始上传文件
+ eventName: BI.MultifileEditor.EVENT_UPLOADSTART,
+ action: function (progressEvent, xhr) {
+ self.xhr = xhr;
+ },
+ },
+ {
+ // 上传文件完毕
+ eventName: BI.MultifileEditor.EVENT_UPLOADED,
+ action: function () {
+ const uploadedInfo = this.getValue();
+ const failed = BI.some(uploadedInfo, function (index, file) {
+ if (file.data.errorCode) {
+ BI.Msg.toast(uploadedInfo[0].filename + BI.i18nText('Dec-Dcm_Connection_File_Upload_Error'), {
+ level: "error",
+ });
+ self.setErrorInfo(file.data)
+ return true;
+ }
+ });
+ const key = self.options.processId +'Path';
+ !failed && self.setValue(uploadedInfo[0].data.kerberosInfo[key]);
+ !failed && self.fireEvent(FileUpload.EVENT_CHECK_SUCCESS, uploadedInfo[0].data);
+ !failed && BI.Msg.toast(uploadedInfo[0].filename + BI.i18nText('Dec-Dcm_Connection_File_Upload_Success'),{
+ level: "success"
+ });
+ NProgress.configure({ parent: 'body'});
+
+ },
+ },
+ ],
+ }]
+
+ };
+ }
+
+ public getValue(): string {
+ return this.options.value;
+ }
+
+ public setValue(value: string) {
+ this.options.value = value;
+ this.textEditor.text.setTitle(value);
+ this.textEditor.setValue(value);
+ }
+
+ public setInfo(info: any) {
+ this.uploadButton.setEnable(false);
+ this.fileInfo.setVisible(true);
+ this.textEditor.setValue(info.fileName);
+ this.fileName.setText(info.fileName);
+ this.fileSize.setText(Dec.Utils.getByteWidthUnit(info.size));
+ this.fileModified.setText(BI.getDate().print("%Y-%X-%d %H:%M:%S"))
+ }
+
+ public clearInfo() {
+ this.uploadButton.setEnable(true);
+ this.fileInfo.setVisible(false);
+ this.errorInfo.setVisible(false);
+ this.textEditor.setValue('');
+ this.options.attachId = '';
+ }
+
+ public setErrorInfo(errorInfo: any) {
+ this.errorInfo.setVisible(true);
+ this.errorCode.setText(BI.i18nText("Dec-Dcm_Connection_File_Upload_ErrorCode") + ":"+ errorInfo.errorCode);
+ this.errorMsg.setText(BI.i18nText("Dec-Dcm_Connection_File_Upload_ErrorMsg") + ":" + errorInfo.errorMessage);
+ }
+
+ public setEnable(v) {
+ this.uploadButton._setEnable(v);
+ }
+
+ public setFileInfo(params) {
+ this.store.setFileInfo(params);
+ }
+}
diff --git a/src/modules/components/test_status/test_status.ts b/src/modules/components/test_status/test_status.ts
index 0cfba82..a055e6e 100644
--- a/src/modules/components/test_status/test_status.ts
+++ b/src/modules/components/test_status/test_status.ts
@@ -29,6 +29,9 @@ export class TestStatus extends BI.Widget {
failDriverMessage: Label;
driverLink: FloatLeftLayout;
detail: VerticalLayout;
+ failMaskers: any;
+
+ extraContainer: VerticalLayout;
watch = {
status: (status: string) => {
@@ -37,6 +40,7 @@ export class TestStatus extends BI.Widget {
}
render() {
+ const LAYOUT_WIDTH = 400;
const { loadingCls, loadingText, successCls, successText, failCls, failText, retryText } = this.options;
return {
@@ -51,7 +55,7 @@ export class TestStatus extends BI.Widget {
cls: 'bi-card',
width: 450,
height: 250,
- single: true,
+ // single: true,
showIndex: this.model.status,
ref: (_ref: Tab) => {
this.tab = _ref;
@@ -70,6 +74,12 @@ export class TestStatus extends BI.Widget {
tipCls: failCls,
tipText: failText,
retryText,
+ ref: (_ref: TipFail) => {
+ this.failMaskers = _ref;
+ if (BI.isEmptyString(this.failMessage.getText())) {
+ this.failMaskers.populateFail(BI.i18nText('Dec-Conn-ect-Failed'), false);
+ }
+ },
listeners: [
{
eventName: TipFail.EVENT_RELOAD,
@@ -116,10 +126,17 @@ export class TestStatus extends BI.Widget {
scrolly: true,
height: 75,
items: [
+ {
+ type: BI.VerticalLayout.xtype,
+ width: LAYOUT_WIDTH,
+ ref: (_ref: VerticalLayout) => {
+ this.extraContainer = _ref;
+ }
+ },
{
type: BI.Label.xtype,
whiteSpace: 'normal',
- width: 400,
+ width: LAYOUT_WIDTH,
textAlign: 'left',
text: '',
ref: (_ref: Label) => {
@@ -168,7 +185,7 @@ export class TestStatus extends BI.Widget {
this.store.setStatus(TEST_STATUS.SUCCESS);
}
- setFail(message: string, driver = '', link = '') {
+ setFail(message: string = '', driver = '', link = '') {
this.store.setStatus(TEST_STATUS.FAIL);
this.failMessage.setText(message);
this.failDriverMessage.setVisible(!!driver);
@@ -182,4 +199,14 @@ export class TestStatus extends BI.Widget {
setLoading() {
this.store.setStatus(TEST_STATUS.LOADING);
}
+
+ /**
+ * 设置报错弹窗自定义展示内容
+ */
+ setExtraContainer(container: Obj) {
+ BI.createWidget({
+ ...container,
+ element: this.extraContainer,
+ });
+ }
}
diff --git a/src/modules/components/test_status/tip_icon/tip_fail.ts b/src/modules/components/test_status/tip_icon/tip_fail.ts
index 05ef93f..a12f157 100644
--- a/src/modules/components/test_status/tip_icon/tip_fail.ts
+++ b/src/modules/components/test_status/tip_icon/tip_fail.ts
@@ -1,5 +1,5 @@
import { shortcut, store } from '@core/core';
-import { Button } from '@fui/core';
+import { Button, Label } from '@fui/core';
import { TipFailModel } from './tip_fail.model';
@shortcut()
@@ -21,7 +21,7 @@ export class TipFail extends BI.Widget {
store: TipFailModel['store'];
detailButton: Button;
-
+ failText:Label;
watch = {
isCollapse: (isCollapse: boolean) => {
this.detailButton.setText(isCollapse ?
@@ -29,6 +29,10 @@ export class TipFail extends BI.Widget {
BI.i18nText('Dec-Dcm_Connection_Detailed_Information'));
},
}
+ populateFail(text:string,isVisible:boolean){
+ this.failText.setText(text);
+ this.detailButton.setVisible(isVisible);
+ }
render() {
const { tipCls, tipText, retryText } = this.options;
@@ -50,18 +54,20 @@ export class TipFail extends BI.Widget {
}],
}, {
type: BI.Label.xtype,
- height: 14,
- bgap: 10,
+ _bgap: 10,
text: tipText,
+ ref:(_ref:Label)=>{
+ this.failText=_ref;
+ }
},
{
type: BI.VerticalAdaptLayout.xtype,
- hgap: 5,
+ hgap: 12,
items: [
{
type: BI.Button.xtype,
text: BI.i18nText('Dec-Dcm_Connection_Detailed_Information'),
- level: 'ignore',
+ clear: true,
ref: (_ref: Button) => {
this.detailButton = _ref;
},
@@ -72,8 +78,8 @@ export class TipFail extends BI.Widget {
},
{
type: BI.Button.xtype,
+ light: true,
text: BI.i18nText('Dec-Dcm_Back'),
- level: 'ignore',
handler: () => {
this.fireEvent(TipFail.EVENT_CLOSE);
},
@@ -82,6 +88,7 @@ export class TipFail extends BI.Widget {
type: BI.Button.xtype,
text: retryText,
handler: () => {
+ this.store.setIsCollapse(false);
this.fireEvent(TipFail.EVENT_RELOAD);
},
},
diff --git a/src/modules/components/text_checker/text_checker.ts b/src/modules/components/text_checker/text_checker.ts
index c7984c0..339e1c2 100644
--- a/src/modules/components/text_checker/text_checker.ts
+++ b/src/modules/components/text_checker/text_checker.ts
@@ -3,87 +3,97 @@ import { Label, TextEditor } from '@fui/core';
@shortcut()
export class TextChecker extends BI.Widget {
- static xtype = 'dec.dcm.components.text_checker';
+ public static xtype = 'dec.dcm.components.text_checker';
- props = {
+ public props = {
width: 300,
allowBlank: true,
value: '',
watermark: '',
+ inputType: 'text',
+ autocomplete: '',
validationChecker: [] as {
errorText: string;
checker: (value: string) => boolean;
autoFix?: boolean;
}[],
$value: '',
- }
+ };
- textEditor: TextEditor;
- errorLabel: Label;
+ public textEditor: TextEditor;
+ public errorLabel: Label;
private isError: boolean;
private value: string;
private errorChecker: {
errorText: string;
checker: (value: string) => boolean;
autoFix?: boolean;
- }
+ };
- render() {
- const { width, allowBlank, value, watermark, validationChecker, $value } = this.options;
+ public render() {
+ const { width, allowBlank, value, watermark, inputType, autocomplete, validationChecker, $value } = this.options;
this.value = value;
-
+
return {
type: BI.AbsoluteLayout.xtype,
width,
height: 20,
- items: [{
- el: {
- type: BI.TextEditor.xtype,
- $value,
- width,
- allowBlank,
- value,
- watermark,
- ref: (_ref: TextEditor) => {
- this.textEditor = _ref;
- },
- listeners: [{
- eventName: BI.Editor.EVENT_CHANGE,
- action: () => {
- const value = this.getValue();
- if (value) {
- this.errorChecker = validationChecker.find(item => item.checker && !item.checker(value));
- this.errorLabel.setText(BI.get(this.errorChecker, 'errorText'));
- this.isError = !!BI.get(this.errorChecker, 'errorText');
- } else {
- this.errorLabel.setText('');
- this.isError = false;
- }
- if (!this.isError) {
- this.value = value;
- }
- this.fireEvent(BI.Editor.EVENT_CHANGE);
- },
- }, {
- eventName: BI.TextEditor.EVENT_BLUR,
- action: () => {
- if (BI.get(this.errorChecker, 'autoFix')) {
- this.setValue(this.value);
- this.errorLabel.setText('');
- }
+ items: [
+ {
+ el: {
+ type: BI.TextEditor.xtype,
+ $value,
+ width,
+ allowBlank,
+ value,
+ watermark,
+ inputType,
+ autocomplete,
+ ref: (_ref: TextEditor) => {
+ this.textEditor = _ref;
},
- }],
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ const value = this.getValue();
+ if (value) {
+ this.errorChecker = validationChecker.find((item) => item.checker && !item.checker(value));
+ this.errorLabel.setText(BI.get(this.errorChecker, 'errorText'));
+ this.isError = !!BI.get(this.errorChecker, 'errorText');
+ } else {
+ this.errorLabel.setText('');
+ this.isError = false;
+ }
+ if (!this.isError) {
+ this.value = value;
+ }
+ this.fireEvent(BI.Editor.EVENT_CHANGE);
+ },
+ },
+ {
+ eventName: BI.TextEditor.EVENT_BLUR,
+ action: () => {
+ if (BI.get(this.errorChecker, 'autoFix')) {
+ this.setValue(this.value);
+ this.errorLabel.setText('');
+ }
+ },
+ },
+ ],
+ },
},
- }, {
- el: {
- type: BI.Label.xtype,
- cls: 'bi-error',
- ref: (_ref: Label) => {
- this.errorLabel = _ref;
+ {
+ el: {
+ type: BI.Label.xtype,
+ cls: 'bi-error',
+ ref: (_ref: Label) => {
+ this.errorLabel = _ref;
+ },
},
+ top: -15,
},
- top: -15,
- }],
+ ],
};
}
@@ -98,4 +108,8 @@ export class TextChecker extends BI.Widget {
public setError(value: string) {
this.errorLabel.setText(value);
}
+
+ public setWatermark(value: string) {
+ this.textEditor.setWaterMark(value);
+ }
}
diff --git a/src/modules/components/tips_combo/tips_combo.ts b/src/modules/components/tips_combo/tips_combo.ts
new file mode 100644
index 0000000..c1b049a
--- /dev/null
+++ b/src/modules/components/tips_combo/tips_combo.ts
@@ -0,0 +1,41 @@
+import { shortcut } from '@core/core';
+import { BubbleCombo, BubblePopupView, IconButton } from '@fui/core';
+
+@shortcut()
+export class TipsCombo extends BI.Widget {
+ public static xtype = 'dec.dcm.tips.combo';
+
+ public props: BubblePopupView['props'] & IconButton['props'] = {
+ trigger: 'hover',
+ direction: 'top'
+ };
+
+ private bubbleCombo: BubbleCombo;
+
+ private bubbleComboPopup: BubblePopupView;
+
+ public render() {
+ const { direction, trigger, el } = this.options;
+
+ return {
+ type: BI.BubbleCombo.xtype,
+ trigger,
+ direction,
+ el: {
+ type: BI.IconButton.xtype,
+ cls: "detail-font",
+ },
+ popup: {
+ type: BI.BubblePopupView.xtype,
+ ref: (_ref: BubblePopupView) => {
+ this.bubbleComboPopup = _ref;
+ },
+ el,
+ },
+ listeners: [],
+ ref: (_ref: BubbleCombo) => {
+ this.bubbleCombo = _ref;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/modules/constants/constant.ts b/src/modules/constants/constant.ts
index 5bb3778..e36e16a 100644
--- a/src/modules/constants/constant.ts
+++ b/src/modules/constants/constant.ts
@@ -5,6 +5,11 @@ export const PAGE_INDEX = {
POOL: 'pool',
};
+export const DATABASE_TYPE = {
+ SAP_HANA: "sap-hana",
+ STAR_ROCKS :'starrocks',
+};
+
export const OTHER_JDBC = 'otherJDBC';
export const DEFAULT_HELP_LINK = 'databaseHelpLink';
@@ -279,7 +284,7 @@ export const DATA_BASE_TYPES = [
text: 'ClickHouse',
databaseType: 'clickhouse',
driver: 'ru.yandex.clickhouse.ClickHouseDriver',
- url: 'jdbc:clickhouse://hostname:port',
+ url: 'jdbc:clickhouse://hostname:port/database',
commonly: false,
internal: true,
type: 'jdbc',
@@ -459,6 +464,7 @@ export const DATA_BASE_TYPES = [
text: 'KINGBASE',
databaseType: 'kingbase',
driver: 'com.kingbase.Driver',
+ versions: ['KingbaseES 7.0'],
url: 'jdbc:kingbase://hostname:port/database',
commonly: false,
internal: true,
@@ -537,7 +543,7 @@ export const DATA_BASE_TYPES = [
kerberos: false,
urls: {
'org.postgresql.Driver': 'jdbc:postgresql://hostname:port/dbname',
- 'com.pivotal.jdbc.GreenplumDriver': 'jdbc:pivotal:greenplum://hostname:port;dbname',
+ 'com.pivotal.jdbc.GreenplumDriver': 'jdbc:pivotal:greenplum://hostname:port;DatabaseName=dbname',
},
}, {
text: 'Postgresql',
@@ -561,6 +567,39 @@ export const DATA_BASE_TYPES = [
type: 'jdbc',
hasSchema: false,
kerberos: false,
+ }, {
+ text: 'Doris',
+ databaseType: 'doris',
+ driver: 'com.mysql.jdbc.Driver',
+ drivers: ['com.mysql.jdbc.Driver'],
+ url: 'jdbc:mysql://hostname:port/database',
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: false,
+ kerberos: false,
+ }, {
+ text: BI.i18nText('Dec-Dcm_Connection_Database_DM'),
+ databaseType: 'dm',
+ driver: 'dm.jdbc.driver.DmDriver',
+ drivers: ['dm.jdbc.driver.DmDriver'],
+ url: 'jdbc:dm://hostname:port',
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: true,
+ kerberos: true,
+ }, {
+ text: 'dremio',
+ databaseType: 'dremio',
+ driver: 'com.dremio.jdbc.Driver',
+ drivers: ['com.dremio.jdbc.Driver'],
+ url: 'jdbc:dremio:direct=hostname:31010',
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: true,
+ kerberos: false,
}, {
text: 'Presto',
databaseType: 'presto',
@@ -575,7 +614,7 @@ export const DATA_BASE_TYPES = [
text: 'SAP HANA',
databaseType: 'sap-hana',
driver: 'com.sap.db.jdbc.Driver',
- url: 'jdbc:sap://hostname:port?reconnect=true',
+ url: 'jdbc:sap://hostname:port?databaseName=database&reconnect=true',
commonly: false,
internal: true,
type: 'jdbc',
@@ -659,6 +698,42 @@ export const DATA_BASE_TYPES = [
'org.sqlite.JDBC': 'jdbc:sqlite:[PATH_TO_DB_FILES]',
},
},
+ {
+ text: 'trino',
+ databaseType: 'trino',
+ driver: 'io.trino.jdbc.TrinoDriver',
+ url: 'jdbc:trino://hostname:port/database',
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: true,
+ kerberos: false,
+ },
+ {
+ text: 'TDSQL',
+ databaseType: 'tdsql',
+ driver: 'org.postgresql.Driver',
+ url: 'jdbc:postgresql://hostname:port/database',
+ versions: ['pgsql'],
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: true,
+ kerberos: false,
+ fetchSize: 10000,
+ },
+ {
+ text: BI.i18nText('StarRocks'),
+ databaseType: 'starrocks',
+ driver: 'com.mysql.jdbc.Driver',
+ drivers: ['com.mysql.jdbc.Driver'],
+ url: 'jdbc:mysql://hostname:port/default_catalog.database',
+ commonly: false,
+ internal: true,
+ type: 'jdbc',
+ hasSchema: false,
+ kerberos: false,
+ }
];
@@ -701,6 +776,28 @@ export const CONNECT_CHARSET = [
},
];
+export const CONNECT_SSH_TYPE = [
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ value: 'NORMAL',
+ privateKeyPathFormVisible: false,
+ secretFormName: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ },
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Form_PublicKey'),
+ value: 'KEY',
+ privateKeyPathFormVisible: true,
+ secretFormName: BI.i18nText('Dec-Dcm_Connection_Form_Passphrase'),
+ },
+];
+
+export const CONNECT_SSL_TYPE = [
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ value: 'NORMAL',
+ },
+];
+
export const TEST_STATUS = {
LOADING: 'loading',
SUCCESS: 'success',
@@ -737,15 +834,18 @@ export const DEFAULT_JDBC_POOL = {
minIdle: 0,
maxWait: 10000,
testOnBorrow: true,
+ keepAlive: true,
testOnReturn: false,
testWhileIdle: false,
- timeBetweenEvictionRunsMillis: -1,
+ timeBetweenEvictionRunsMillis: 60000,
numTestsPerEvictionRun: 3,
minEvictableIdleTimeMillis: 1800,
+ maxEvictableIdleTimeMillis: 25200,
+ keepAliveBetweenTimeMillis: 120000,
};
export const CONNECTION_LAYOUT = {
- hgap: 5,
+ hgap: 10,
vgap: 15,
labelHeight: 24,
};
@@ -776,3 +876,14 @@ export const JNDI_FACTORYS = [
export const PAGE_SIZE = 50;
export const INT_MAX_VALUE = 2147483647;
export const INT_MIN_VALUE = -2147483648;
+
+export const YES_OR_NO = [
+ {
+ text: BI.i18nText('Dec-Basic_Yes'),
+ value: 1,
+ },
+ {
+ text: BI.i18nText('Dec-Basic_No'),
+ value: 0,
+ }
+]
diff --git a/src/modules/core/checkIllegalStrings/checkIllegalStrings.ts b/src/modules/core/checkIllegalStrings/checkIllegalStrings.ts
new file mode 100644
index 0000000..ddc4f99
--- /dev/null
+++ b/src/modules/core/checkIllegalStrings/checkIllegalStrings.ts
@@ -0,0 +1,52 @@
+/*
+ https://work.fineres.com/browse/REPORT-91724 用于参数统一校验
+ */
+import { ILLEGAL_STRINGS } from "./constant";
+export type CheckResult = {
+ legal: boolean,
+ errorMsg: string,
+}
+export const CHECK_CORRECT: CheckResult = {
+ legal: true,
+ errorMsg: "",
+};
+
+/**
+ * 检测非法字符,返回错误提示
+ * @param value 要校验的字符串
+ */
+export function checkIllegalStrings(value: string): CheckResult {
+ // 后端传入的校验开关,如果没传,那也默认开启
+ const enabled = Dec.system.enableParameterVerify ?? true;
+ let result = CHECK_CORRECT;
+ if (enabled) {
+ // 关键字不区分大小写
+ ILLEGAL_STRINGS.every(s => {
+ const sIndex = value.toLowerCase().indexOf(s);
+ if (sIndex !== -1) {
+ result = {
+ legal: false,
+ errorMsg: `${BI.i18nText("Dec-Basic_Check_Illegal_Strings")}${value.substr(sIndex, s.length)}`,
+ };
+
+ return false;
+ }
+
+ return true;
+ });
+
+ return result;
+ }
+
+ return result;
+}
+
+export function checkIllegalStringsInWidgetAndShowError(widget: any) {
+ const value = widget.getValue();
+ const result = checkIllegalStrings(value);
+ if (!result.legal) {
+ widget.showError(result.errorMsg);
+ }
+
+ return result.legal;
+}
diff --git a/src/modules/core/checkIllegalStrings/constant.ts b/src/modules/core/checkIllegalStrings/constant.ts
new file mode 100644
index 0000000..351c185
--- /dev/null
+++ b/src/modules/core/checkIllegalStrings/constant.ts
@@ -0,0 +1,15 @@
+/**
+ * 参数检验的非法字符数组,由于不区分大小写,统一用小写
+ */
+export const ILLEGAL_STRINGS = [
+ "\"",
+ "<",
+ ">",
+ "&",
+ "/script",
+ "javascript:",
+ "onblur",
+ "getruntime",
+ "processbuilder",
+ "java.lang.processimpl",
+];
diff --git a/src/modules/core/index.ts b/src/modules/core/index.ts
new file mode 100644
index 0000000..efe056c
--- /dev/null
+++ b/src/modules/core/index.ts
@@ -0,0 +1 @@
+export { checkIllegalStringsInWidgetAndShowError, checkIllegalStrings } from "./checkIllegalStrings/checkIllegalStrings"
diff --git a/src/modules/crud/api.ts b/src/modules/crud/api.ts
index fa0f2d4..9c5b7ba 100644
--- a/src/modules/crud/api.ts
+++ b/src/modules/crud/api.ts
@@ -5,6 +5,7 @@ import {
ConnectionPoolType,
SocketResult,
ResultType,
+ checkDriverStatusParams,
} from './crud.typings';
export interface Api {
@@ -46,6 +47,17 @@ export interface Api {
*/
testConnection(data: Connection): Promise;
+ /**
+ * 获取驱动加载路径
+ */
+ getDriverLoadPath(data: Connection): Promise>;
+
+ /**
+ * 检测驱动冲突状态
+ * @param data 驱动路径
+ */
+ checkDriverStatus(data: checkDriverStatusParams): Promise>;
+
/**
* 获取连接池数据
* @param name
@@ -99,4 +111,9 @@ export interface Api {
* 获取外链
*/
getHyperlink(name: string): string;
+
+ /**
+ * 获取JNDI数据库类型可用状态
+ */
+ getJNDIDatabaseStatus(): Promise<{ data?: boolean }>;
}
diff --git a/src/modules/crud/crud.service.ts b/src/modules/crud/crud.service.ts
index 19297e7..71c9604 100644
--- a/src/modules/crud/crud.service.ts
+++ b/src/modules/crud/crud.service.ts
@@ -15,7 +15,7 @@ export function requestGet(url: string, data?: any): Promise {
export function requestPost(url: string, data = {}): Promise {
return new Promise(resolve => {
- Dec.reqPost(getFullUrl(url), data, re => {
+ Dec.reqByEncrypt("POST", getFullUrl(url), data, re => {
resolve(re);
});
});
@@ -23,7 +23,7 @@ export function requestPost(url: string, data = {}): Promise {
export function requestDelete(url: string, data = {}) {
return new Promise(resolve => {
- Dec.reqDelete(getFullUrl(url), data, re => {
+ Dec.reqByEncrypt("DELETE", getFullUrl(url), data, re => {
resolve(re);
});
});
@@ -31,7 +31,7 @@ export function requestDelete(url: string, data = {}) {
export function requestPut(url: string, data = {}) {
return new Promise(resolve => {
- Dec.reqPut(getFullUrl(url), data, re => {
+ Dec.reqByEncrypt("PUT", getFullUrl(url), data, re => {
resolve(re);
});
});
diff --git a/src/modules/crud/crud.typings.d.ts b/src/modules/crud/crud.typings.d.ts
index 9f0f69f..8bc01bd 100644
--- a/src/modules/crud/crud.typings.d.ts
+++ b/src/modules/crud/crud.typings.d.ts
@@ -1,3 +1,7 @@
+export interface CrudParams {
+ [key: string]: string | number | { [key: string]: any };
+}
+
export interface CrudReqOpts {
url?: string;
type?: 'GET' | 'POST' | 'DELETE' | 'PUT';
@@ -9,28 +13,116 @@ export interface CrudReqOpts {
params?: CrudParams;
}
-export interface CrudParams {
- [key: string]: string | number | { [key: string]: any };
+export interface ConnectionLicInfo {
+ currentConnectionNum: number;
+ maxConnectionNum: number;
}
-export interface Connection {
- connectionId: string;
- connectionType: string;
- connectionName: string;
- creator?: string;
- connectionData: ConnectionJDBC | ConnectionJNDI | ConnectionPlugin | string;
- privilegeDetailBeanList?: {
- privilegeType: number;
- privilegeValue: number;
- }[];
+export interface ConnectionPoolType {
+ maxActive: number;
+ maxIdle: number;
+ numActive: number;
+ numIdle: number;
}
-export interface ConnectionLicInfo {
- currentConnectionNum: number;
- maxConnectionNum: number;
+type ConnectionDataOfSSH = {
+ usingSsh: boolean; // 使用SSH通道
+ sshIp: string; // 主机
+ sshPort: number; // 端口
+ sshUser: string; // 用户名
+ redirectPort: number;
+ redirectIp: string;
+ sshTimeOut: number;
+ sshKeepAlive: number;
+} & (
+ | {
+ sshType: 'NORMAL'; // 验证方法:密码
+ sshPrivateKeyPath: ''; // 没啥意义,该验证方法下为空字符串
+ sshSecret: string; // 密码
+ }
+ | {
+ sshType: 'KEY'; // 验证方法:公钥
+ sshPrivateKeyPath: string; // 私钥
+ sshSecret: string; // 密码短语
+ }
+ );
+
+type ConnectionDataOfSSL = {
+ usingSsl: boolean; // 使用SSL通道
+ sslType: 'NORMAL'; // SSL类型,只有NORMAL一种
+ caCertificate: string; // CA证书
+ verifyCa: boolean; // 验证针对CA的服务器证书
+ sslClientPrivateKey: string; // 客户端密钥
+ sslClientCertificate: string; // 客户端证书
+};
+
+export interface ConnectionPoolJDBC {
+ /**
+ * 初始化连接数量
+ */
+ initialSize?: number;
+ /**
+ * 最大连接数
+ */
+ maxActive?: number;
+ /**
+ * 最大空闲数
+ */
+ maxIdle?: number;
+ /**
+ * 最小空闲数
+ */
+ minIdle?: number;
+ /**
+ * 最大等待时间
+ */
+ maxWait?: number;
+ /**
+ * sql查询
+ */
+ validationQuery?: string;
+
+ /**
+ * 连接前校验
+ */
+ testOnBorrow?: boolean;
+
+ /**
+ * 空闲连接可用性定期检查
+ */
+ keepAlive?: boolean;
+ /**
+ * 归还前校验
+ */
+ testOnReturn?: boolean;
+
+ /**
+ * 空闲校验
+ */
+ testWhileIdle?: boolean;
+ /**
+ * 在空闲连接回收器线程运行期间休眠的时间值,毫秒。
+ */
+ timeBetweenEvictionRunsMillis?: number;
+ /**
+ * 每次空闲连接回收器现成运行时检查的连接数量
+ */
+ numTestsPerEvictionRun?: number;
+ /**
+ * 连接在池中保持空闲而不被空闲连接回收器回收的最小时间,单位毫秒
+ */
+ minEvictableIdleTimeMillis?: number;
+ /**
+ * 连接在池中保持空闲而不被空闲连接回收器回收的最小时间,单位毫秒
+ */
+ maxEvictableIdleTimeMillis?: number;
+ /**
+ * 空闲连接可用性定期检查时间阈值
+ */
+ keepAliveBetweenTimeMillis?: number;
}
-export interface ConnectionJDBC {
+export type ConnectionJDBC = {
/**
* 数据库名称
*/
@@ -44,6 +136,10 @@ export interface ConnectionJDBC {
* 驱动
*/
driver: string;
+ /**
+ * 驱动来源
+ */
+ driverSource: 'default' | 'custom';
/**
* 数据库连接url
*/
@@ -108,6 +204,10 @@ export interface ConnectionJDBC {
* 秘钥路径
*/
keyPath?: string;
+ /**
+ * krb5.conf文件
+ */
+ krb5Path?: string;
/**
* fetchSize
*/
@@ -118,71 +218,45 @@ export interface ConnectionJDBC {
identity?: string;
connectionPoolAttr: ConnectionPoolJDBC;
-}
-
-export interface ConnectionPoolJDBC {
- /**
- * 初始化连接数量
- */
- initialSize?: number;
- /**
- * 最大连接数
- */
- maxActive?: number;
- /**
- * 最大空闲数
- */
- maxIdle?: number;
- /**
- * 最小空闲数
- */
- minIdle?: number;
/**
- * 最大等待时间
+ * 并行装载
*/
- maxWait?: number;
+ parallelLoad?: IParallelLoad;
/**
- * sql查询
+ * HDFS
*/
- validationQuery?: string;
-
- /**
- * 连接前校验
- */
- testOnBorrow?: boolean;
+ hdfs?: {
+ /**
+ * HDFS地址
+ */
+ hdfsAddress?: string;
+ };
+} & ConnectionDataOfSSH & ConnectionDataOfSSL;
+/**
+ * 并行装载
+ */
+export interface IParallelLoad {
/**
- * 归还前校验
+ * 服务器地址
*/
- testOnReturn?: boolean;
-
+ serverAddress?: string;
/**
- * 空闲校验
+ * 服务器地址选项
*/
- testWhileIdle?: boolean;
+ serverAddressItems?: string[];
/**
- * 在空闲连接回收器线程运行期间休眠的时间值,毫秒。
+ * 复用临时表
*/
- timeBetweenEvictionRunsMillis?: number;
+ reuseTemporaryTable?: string;
/**
- * 每次空闲连接回收器现成运行时检查的连接数量
+ * 临时文件条数限制
*/
- numTestsPerEvictionRun?: number;
+ filePiecesLimit?: string;
/**
- * 连接在池中保持空闲而不被空闲连接回收器回收的最小时间,单位毫秒
+ * 临时文件大小限制
*/
- minEvictableIdleTimeMillis?: number;
-}
-
-export interface ConnectionJNDI {
- jndiName: string;
- /**
- * 编码
- */
- originalCharsetName: string;
- newCharsetName: string;
- creator?: string;
- contextHashtable: ContextHashtable;
+ fileSizeLimit?: string
}
export interface ContextHashtable {
@@ -203,33 +277,54 @@ export interface ContextHashtable {
'java.naming.applet': string;
}
+export interface ConnectionJNDI {
+ jndiName: string;
+ /**
+ * 编码
+ */
+ originalCharsetName: string;
+ newCharsetName: string;
+ creator?: string;
+ contextHashtable: ContextHashtable;
+}
+
export interface ConnectionPlugin {
pluginType: 'json';
creator: '';
pluginData: any;
}
+export interface Connection {
+ connectionId: string;
+ connectionType: string;
+ connectionName: string;
+ creator?: string;
+ connectionData: ConnectionJDBC | ConnectionJNDI | ConnectionPlugin | string;
+ privilegeDetailBeanList?: {
+ privilegeType: number;
+ privilegeValue: number;
+ }[];
+}
+
export interface TestRequest {
data?: string[];
errorCode?: string;
errorMsg?: string;
}
-export interface ConnectionPoolType {
- maxActive: number;
- maxIdle: number;
- numActive: number;
- numIdle: number;
-}
-
export interface SocketResult {
data?: string;
errorCode?: string;
errorMsg?: string;
}
-export interface ResultType {
- data?: any;
+export interface ResultType {
+ data?: T;
errorCode?: string;
errorMsg?: string;
}
+
+export type checkDriverStatusParams = {
+ path: string;
+ driver: ConnectionJDBC['driver'];
+}
\ No newline at end of file
diff --git a/src/modules/crud/decision.api.ts b/src/modules/crud/decision.api.ts
index 7b8bc37..6207d6f 100644
--- a/src/modules/crud/decision.api.ts
+++ b/src/modules/crud/decision.api.ts
@@ -1,5 +1,5 @@
import { Api } from './api';
-import { Connection, TestRequest, ConnectionPoolType, SocketResult, ConnectionLicInfo } from './crud.typings';
+import { Connection, TestRequest, ConnectionPoolType, SocketResult, ConnectionLicInfo, ResultType, checkDriverStatusParams } from './crud.typings';
import { requestGet, requestDelete, requestPost, requestPut } from './crud.service';
import { editStatusEvent, errorCode } from '@constants/env';
@@ -48,6 +48,27 @@ export class DecisionApi implements Api {
return requestPost('test', form);
}
+ /**
+ * 获取驱动加载路径
+ * @returns
+ */
+ getDriverLoadPath(data: Connection): Promise> {
+ const form = {
+ ...data,
+ connectionData: JSON.stringify(data.connectionData),
+ };
+
+ return requestPost('driver/path', form);
+ }
+
+ /**
+ * 检测驱动冲突状态
+ * @param data 驱动路径
+ */
+ checkDriverStatus(data: checkDriverStatusParams): Promise> {
+ return requestGet(Dec.Utils.getEncodeURL('test/driver/conflict', '', data));
+ }
+
getConnectionPool(name: string): Promise<{ data?: ConnectionPoolType }> {
return requestGet(`pool/info?connectionName=${encodeURIComponent(name)}`, {});
}
@@ -118,18 +139,39 @@ export class DecisionApi implements Api {
getCipher(password: string) {
return BI.Providers.getProvider('dec.provider.cipher')
- .getCipher(password);
+ .getCompleteCipher(password);
}
getPlain(cipher: string) {
return BI.Providers.getProvider('dec.provider.cipher')
- .getPlain(cipher);
+ .getCompletePlain(cipher);
}
getHyperlink(name: string) {
return Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][name];
}
+ changePrincipal(value: any) {
+ return requestPost(`switch/principal`, value);
+ }
+
+ getPrincipals(keytab: string) {
+ return requestGet(`/principals?keytabPath=${keytab}`, {});
+ }
+
+ getTimeOut(): Promise<{ data?: any }> {
+ return requestGet('kdc/timeout', {});
+ }
+
+ putTimeOut(value: number) {
+ return requestPut(`kdc/timeout?timeout=${value}`, {})
+ }
+
+ // 获取当前lic是否可以使用JNDI数据库类型
+ getJNDIDatabaseStatus(): Promise<{ data?: boolean }> {
+ return requestGet('databasetype/limit', {});
+ }
+
private sendEditStatusEvent(name: string, type: string): Promise {
return new Promise(resolve => {
if (Dec?.socket?.connected) {
diff --git a/src/modules/crud/design.api.ts b/src/modules/crud/design.api.ts
index f010918..d629b16 100644
--- a/src/modules/crud/design.api.ts
+++ b/src/modules/crud/design.api.ts
@@ -1,5 +1,5 @@
import { Api } from './api';
-import { Connection, TestRequest, ConnectionPoolType, SocketResult, ConnectionLicInfo } from './crud.typings';
+import { Connection, TestRequest, ConnectionPoolType, SocketResult, ConnectionLicInfo, ResultType, ConnectionJDBC, checkDriverStatusParams } from './crud.typings';
import { requestGet } from './crud.service';
// TODO: 此页面的接口等待设计器提供相应的方法
@@ -39,6 +39,27 @@ export class DesignApi implements Api {
});
}
+ /**
+ * 获取驱动加载路径
+ * @param name
+ * @returns
+ */
+ getDriverLoadPath(data: Connection): Promise> {
+ return new Promise(resolve => {
+ resolve({ data: '' });
+ });
+ }
+
+ /**
+ * 检测驱动冲突状态
+ * @param data 驱动路径
+ */
+ checkDriverStatus(data: checkDriverStatusParams): Promise> {
+ return new Promise(resolve => {
+ resolve({ data: false });
+ });
+ }
+
getConnectionPool(name: string): Promise<{ data: ConnectionPoolType }> {
return new Promise(resolve => {
resolve({
@@ -88,4 +109,8 @@ export class DesignApi implements Api {
// 设计器获取超链
return '';
}
+
+ getJNDIDatabaseStatus() {
+ return Promise.resolve({ data: true });
+ }
}
diff --git a/src/modules/pages/__point__/connect.point.ts b/src/modules/pages/__point__/connect.point.ts
new file mode 100644
index 0000000..576f153
--- /dev/null
+++ b/src/modules/pages/__point__/connect.point.ts
@@ -0,0 +1,24 @@
+BI.point("dec.dcm.model.connection", "createNewConnection", () => {
+ Dec.Utils.saveFocusPoint({
+ id: "E73325",
+ title: "新建数据连接",
+ });
+});
+
+BI.point("dec.dcm.model.title_maintain", "setTestEvent", () => {
+ Dec.Utils.saveFocusPoint({
+ id: "E73328",
+ title: "测试数据连接",
+ });
+});
+
+BI.point("dec.dcm.model.maintain_form", "addConnection", function () {
+ Dec.Utils.saveFocusPoint({
+ id: "E8827",
+ title: "保存数据连接",
+ body: {
+ datebaseType: this.model.datebaseTypeSelected,
+ databaseName: this.model.connectionSelected,
+ },
+ });
+});
\ No newline at end of file
diff --git a/src/modules/pages/connection/connection.model.ts b/src/modules/pages/connection/connection.model.ts
index f037865..97daf69 100644
--- a/src/modules/pages/connection/connection.model.ts
+++ b/src/modules/pages/connection/connection.model.ts
@@ -13,13 +13,14 @@ export class ConnectionModel extends Model<{
connectionSelected: AppModel['TYPE']['connectionSelected'];
connectionSelectedOne: AppModel['TYPE']['connectionSelectedOne'];
datebaseTypeSelected: AppModel['TYPE']['datebaseTypeSelected'];
+ noTestConnection: AppModel['TYPE']['noTestConnection'];
},
childContext: ConnectionModel['childContext'];
context: ConnectionModel['context'];
}> {
static xtype = 'dec.dcm.model.connection';
- context = ['pageIndex', 'connectionSelected', 'connectionSelectedOne', 'datebaseTypeSelected', 'connectionLicInfo'];
+ context = ['pageIndex', 'connectionSelected', 'connectionSelectedOne', 'datebaseTypeSelected', 'connectionLicInfo', 'noTestConnection'];
actions = {
initConnectionLicInfo: (cb: Function) => {
@@ -53,8 +54,14 @@ export class ConnectionModel extends Model<{
this.model.connectionSelected = name;
},
getConnectionStatus() {
+ if (this.model.connectionSelectedOne.pluginConnection) {
+ return Promise.resolve();
+ }
return api.getConnectionStatus(this.model.connectionSelected);
},
+ setNoTestConnection(value: boolean) {
+ this.model.noTestConnection = value;
+ },
checkConnectionLic() {
return this.model.connectionLicInfo.currentConnectionNum > this.model.connectionLicInfo.maxConnectionNum;
},
diff --git a/src/modules/pages/connection/connection.ts b/src/modules/pages/connection/connection.ts
index f8d175c..1215974 100644
--- a/src/modules/pages/connection/connection.ts
+++ b/src/modules/pages/connection/connection.ts
@@ -24,24 +24,17 @@ export class Connection extends BI.Widget {
title: HTapeLayout;
watch = {
- connectionSelected: (name: string) => {
- if (name) {
- const canEdit = connectionCanEdit(this.model.connectionSelectedOne);
- const type = this.getSelectConnectionType();
- this.connectionTitleWidget.setText(`${name}(${getTextByDatabaseType(type)})`);
- this.connectionEditWidget.setVisible(canEdit);
- const hasRegistered = this.hasRegistered();
- this.title.setVisible(hasRegistered);
- if (!hasRegistered) {
- this.listView.populate(BI.createItems(this.renderNoRegistered()));
- } else {
- this.listView.populate(BI.createItems(this.renderItems()));
- }
- } else {
- this.listView.populate(BI.createItems(this.renderEmpty()));
- this.connectionTitleWidget.setText('');
- this.connectionEditWidget.setVisible(false);
- }
+ connectionSelectedOne: {
+ immediate: true,
+ handler: (v: Connection) => {
+ BI.nextTick(() => {
+ const connectionName = v.connectionName;
+
+ connectionName
+ ? this.renderConnectionListView(connectionName)
+ : this.renderEmptyListView();
+ });
+ },
},
};
@@ -50,8 +43,6 @@ export class Connection extends BI.Widget {
}
render() {
- this.store.setConnectionSelected('');
-
return {
type: BI.HTapeLayout.xtype,
hgap: 10,
@@ -71,6 +62,9 @@ export class Connection extends BI.Widget {
{
type: BI.Button.xtype,
text: BI.i18nText('Dec-Dcm_Connection_New'),
+ title: BI.i18nText('Dec-Dcm_Connection_New'),
+ minWidth: 0,
+ width: 98,
handler: () => {
this.store.createNewConnection();
},
@@ -79,7 +73,7 @@ export class Connection extends BI.Widget {
right: [
{
type: 'dec.connection.driver.entry',
- invisible: true,
+ invisible: !BI.Services.getService('dec.service.global').isAdmin(),
from: '.dec-dcm',
listeners: [
{
@@ -134,16 +128,17 @@ export class Connection extends BI.Widget {
},
handler: () => {
this.store.getConnectionStatus()
- .then(re => {
- this.store.setPageIndex(PAGE_INDEX.MAINTAIN);
- this.store.setDatebaseTypeSelected('');
+ .then(() => {
+ const databaseType = this.model.connectionSelectedOne.connectionType;
+ const database = BI.find(getAllDatabaseTypes(), (_index, value) => value.databaseType === databaseType);
+ this.setMaintainPage();
+ this.store.setNoTestConnection(database.isHideConnection);
})
.catch(() => {
});
},
}],
},
- width: 90,
},
],
},
@@ -210,12 +205,6 @@ export class Connection extends BI.Widget {
}];
}
- private renderEmpty() {
- return [{
- type: BI.Layout.xtype,
- }];
- }
-
private hasRegistered() {
const allDatabaseTypes = getAllDatabaseTypes();
switch (this.model.connectionSelectedOne.connectionType) {
@@ -237,4 +226,37 @@ export class Connection extends BI.Widget {
return databaseType;
}
+
+ private setMaintainPage() {
+ this.store.setPageIndex(PAGE_INDEX.MAINTAIN);
+ this.store.setDatebaseTypeSelected('');
+ }
+
+ private renderConnectionListView(name: string) {
+ const canEdit = connectionCanEdit(this.model.connectionSelectedOne),
+ type = this.getSelectConnectionType(),
+ hasRegistered = this.hasRegistered();
+
+ this.connectionTitleWidget.setText(`${name}(${getTextByDatabaseType(type)})`);
+ this.connectionEditWidget.setVisible(canEdit);
+
+ this.title.setVisible(hasRegistered);
+
+ hasRegistered
+ ? this.listView.populate(BI.createItems(this.renderItems()))
+ : this.listView.populate(BI.createItems(this.renderNoRegistered()));
+ }
+
+ private renderEmptyListView() {
+ this.listView.populate(
+ BI.createItems([
+ {
+ type: BI.Layout.xtype,
+ }
+ ])
+ );
+
+ this.connectionTitleWidget.setText('');
+ this.connectionEditWidget.setVisible(false);
+ }
}
diff --git a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts b/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts
index 6f97be8..893e960 100644
--- a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts
+++ b/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts
@@ -1,195 +1,405 @@
-import { shortcut, store } from '@core/core';
-import { FormItem } from '../components/form_item/form_item';
-import { Collapse, EVENT_CHANGE } from 'src/modules/components/collapse/collapse';
-import { ConnectionJdecModel } from './connection_jdbc.model';
-import { ConnectionJDBC } from 'src/modules/crud/crud.typings';
-import { getAllDatabaseTypes, getJdbcDatabaseType, resolveUrlInfo } from '../../../app.service';
-import { CONNECTION_LAYOUT } from '@constants/constant';
-import { VerticalLayout } from '@fui/core';
-import { ApiFactory } from '../../../crud/apiFactory';
-
-const api = new ApiFactory().create();
-
-@shortcut()
-@store(ConnectionJdecModel)
-export class ConnectionJdbc extends BI.Widget {
- static xtype = 'dec.dcm.connection_jdbc';
-
- advancedSet: any;
- model: ConnectionJdecModel['model'];
- allDatabaseTypes = getAllDatabaseTypes();
-
- render() {
- const connectionData = this.model.connectionSelectedOne.connectionData as ConnectionJDBC;
- const {
- driver,
- driverSource,
- database,
- user,
- originalCharsetName,
- schema,
- connectionPoolAttr,
- authType,
- principal,
- url,
- fetchSize,
- } = connectionData;
- const databaseType = getJdbcDatabaseType(database, driver);
- const { host, port, databaseName } = resolveUrlInfo(url, database);
- const { hgap, vgap } = CONNECTION_LAYOUT;
-
- return {
- type: BI.VerticalLayout.xtype,
- hgap,
- vgap,
- items: [
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'),
- value: BI.isKey(driverSource) ? `${driver} (${driverSource})` : driver,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
- value: databaseName,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
- value: host,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
- value: port,
- },
- authType ?
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_AuthType'),
- value: authType,
- } : {
- type: BI.Layout.xtype,
- },
- {
- type: FormItem.xtype,
- name: authType ? BI.i18nText('Dec-Dcm_Connection_Form_Principal') : BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
- value: authType ? principal : user,
- },
- {
- type: FormItem.xtype,
- name: authType ? BI.i18nText('Dec-Dcm_Connection_Form_KeyPath') : BI.i18nText('Dec-Dcm_Connection_Form_Password'),
- value: '******',
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_OriginalCharsetName'),
- value: originalCharsetName ? originalCharsetName : BI.i18nText('Dec-Dcm_Connection_Form_Default'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Pattern'),
- value: schema,
- invisible: !databaseType.hasSchema,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
- value: url,
- },
- {
- type: Collapse.xtype,
- width: 70,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Advanced_Setting'),
- listeners: [
- {
- eventName: EVENT_CHANGE,
- action: (isCollapse: boolean) => {
- this.advancedSet.setVisible(!isCollapse);
- },
- },
- ],
- },
- {
- type: BI.VerticalLayout.xtype,
- tgap: -15,
- vgap,
- invisible: true,
- ref: (_ref: VerticalLayout) => {
- this.advancedSet = _ref;
- },
- items: [
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
- value: connectionPoolAttr.initialSize,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
- value: connectionPoolAttr.maxActive,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Idle'),
- value: connectionPoolAttr.maxIdle,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
- value: connectionPoolAttr.minIdle,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
- value: connectionPoolAttr.maxWait,
- unit: BI.i18nText('Dec-Dcm_Millisecond'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Validation_Query'),
- value: api.getPlain(connectionPoolAttr.validationQuery || ''),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
- value: connectionPoolAttr.testOnBorrow ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
- value: connectionPoolAttr.testOnReturn ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
- value: connectionPoolAttr.testWhileIdle ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
- value: connectionPoolAttr.timeBetweenEvictionRunsMillis,
- unit: BI.i18nText('Dec-Dcm_Millisecond'),
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
- value: connectionPoolAttr.numTestsPerEvictionRun,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
- value: connectionPoolAttr.minEvictableIdleTimeMillis,
- unit: BI.i18nText('BI-Basic_Seconds'),
- }, {
- type: FormItem.xtype,
- invisible: fetchSize < 0 && fetchSize !== -2,
- name: 'Fetchsize',
- value: fetchSize === -2 ? '' : fetchSize,
- },
- ],
- },
- ],
- };
- }
-}
+import { shortcut, store } from '@core/core';
+import { FormItem } from '../components/form_item/form_item';
+import { Collapse, EVENT_CHANGE } from 'src/modules/components/collapse/collapse';
+import { ConnectionJdecModel } from './connection_jdbc.model';
+import { ConnectionJDBC } from 'src/modules/crud/crud.typings';
+import { getAllDatabaseTypes, getJdbcDatabaseType, resolveUrlInfo } from '../../../app.service';
+import { CONNECTION_LAYOUT, CONNECT_SSH_TYPE } from '@constants/constant';
+import { VerticalLayout } from '@fui/core';
+import { ApiFactory } from '../../../crud/apiFactory';
+
+const api = new ApiFactory().create();
+
+@shortcut()
+@store(ConnectionJdecModel)
+export class ConnectionJdbc extends BI.Widget {
+ static xtype = 'dec.dcm.connection_jdbc';
+
+ model: ConnectionJdecModel['model'];
+ allDatabaseTypes = getAllDatabaseTypes();
+
+ sshSet: VerticalLayout;
+ sslSet: VerticalLayout;
+ advancedSet: VerticalLayout;
+ parallelLoadSet: VerticalLayout;
+
+ render() {
+ const connectionData = this.model.connectionSelectedOne.connectionData as ConnectionJDBC;
+ const {
+ driver,
+ driverSource,
+ database,
+ user,
+ originalCharsetName,
+ schema,
+ connectionPoolAttr,
+ authType,
+ principal,
+ url,
+ fetchSize,
+ // ssh
+ usingSsh,
+ sshIp,
+ sshPort,
+ sshUser,
+ sshType,
+ sshSecret,
+ sshPrivateKeyPath,
+ // ssl
+ usingSsl,
+ caCertificate,
+ verifyCa,
+ sslClientPrivateKey,
+ sslClientCertificate,
+ // 并行装载
+ parallelLoad,
+ // HDFS
+ hdfs,
+ } = connectionData;
+ const databaseType = getJdbcDatabaseType(database, driver);
+ const { host, port, catalog, databaseName, version } = resolveUrlInfo(url, database);
+ this.version = !BI.isUndefined(databaseType.versions) ? (version ?? databaseType.versions[0]) : version;
+ const { hgap, vgap } = CONNECTION_LAYOUT;
+
+ return {
+ type: BI.VerticalLayout.xtype,
+ hgap,
+ vgap,
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Basic_Version'),
+ invisible: BI.isUndefined(this.version),
+ value: BI.i18nText('Dec-Migration_Database_Version', this.version),
+ },
+ {
+ type: FormItem.xtype,
+ _tgap: BI.isUndefined(this.version) ? vgap : 0,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'),
+ value: BI.isKey(driverSource) ? `${driver} (${driverSource})` : driver,
+ },
+ {
+ type: FormItem.xtype,
+ name: 'catalog',
+ invisible: database !== 'starrocks',
+ value: catalog,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
+ value: databaseName,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ value: host,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ value: port,
+ },
+ authType
+ ? {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_AuthType'),
+ value: authType,
+ }
+ : {
+ type: BI.Layout.xtype,
+ },
+ {
+ type: FormItem.xtype,
+ name: authType ? BI.i18nText('Dec-Dcm_Connection_Form_Principal') : BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ value: authType ? principal : user,
+ },
+ {
+ type: FormItem.xtype,
+ name: authType ? BI.i18nText('Dec-Dcm_Connection_Form_KeyPath') : BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ value: '******',
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_OriginalCharsetName'),
+ value: originalCharsetName ? originalCharsetName : BI.i18nText('Dec-Dcm_Connection_Form_Default'),
+ },
+ // HDFS设置
+ {
+ type: FormItem.xtype,
+ invisible: BI.isNull(hdfs),
+ name: BI.i18nText('Dec-Dcm_Connection_Address', 'HDFS'),
+ value: hdfs?.hdfsAddress,
+ },
+ // 并行装载设置
+ {
+ type: Collapse.xtype,
+ invisible: BI.isNull(parallelLoad),
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', BI.i18nText('Dec-Dcm_Connection_Parallel_Load')),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.parallelLoadSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ type: BI.VerticalLayout.xtype,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.parallelLoadSet = _ref;
+ },
+ items: [
+ {
+ type: FormItem.xtype,
+ _bgap: vgap,
+ name: `${BI.i18nText('Dec-Dcm_Connection_Server_Address')}-${BI.i18nText('Dec-Memory_Detection_Server_Cluster_Node', '1')}`,
+ value: parallelLoad?.serverAddress,
+ },
+ {
+ type: FormItem.xtype,
+ _bgap: vgap,
+ name: BI.i18nText('Dec-Dcm_Connection_Reuse_Temporary_Table'),
+ value: parallelLoad?.reuseTemporaryTable,
+ },
+ {
+ type: FormItem.xtype,
+ _bgap: vgap,
+ name: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Pieces_Limit'),
+ value: parallelLoad?.filePiecesLimit,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Size_Limit'),
+ value: parallelLoad?.fileSizeLimit,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Pattern'),
+ value: schema,
+ invisible: !databaseType.hasSchema,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
+ value: url,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
+ value: connectionPoolAttr.maxActive,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
+ value: connectionPoolAttr.testOnBorrow ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow'),
+ value: connectionPoolAttr.keepAlive ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_SQL_Validation_Query'),
+ value: api.getPlain(connectionPoolAttr.validationQuery || ''),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
+ value: connectionPoolAttr.maxWait,
+ unit: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ // ssh设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ invisible: !usingSsh,
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', 'SSH'),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.sshSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ bgap: vgap,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.sshSet = _ref;
+ },
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ value: sshIp,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ value: sshPort,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ value: sshUser,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_VerifyType'),
+ value: CONNECT_SSH_TYPE.find((SSH_TYPE) => sshType === SSH_TYPE.value).text,
+ },
+ {
+ type: FormItem.xtype,
+ invisible: sshType !== 'KEY',
+ name: BI.i18nText('Dec-Dcm_Connection_Form_PrivateKey'),
+ value: sshPrivateKeyPath,
+ },
+ {
+ type: FormItem.xtype,
+ name: CONNECT_SSH_TYPE.find((SSH_TYPE) => sshType === SSH_TYPE.value).secretFormName,
+ value: sshSecret,
+ },
+ ],
+ },
+ },
+ // ssl设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ invisible: !usingSsl,
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', 'SSL'),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.sslSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ bgap: vgap,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.sslSet = _ref;
+ },
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_CA_Certificate'),
+ value: caCertificate,
+ },
+ {
+ type: FormItem.xtype,
+ invisible: !caCertificate,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Verify_CA_Certificate'),
+ value: verifyCa ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_SecretKey'),
+ value: sslClientPrivateKey,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_Certificate'),
+ value: sslClientCertificate,
+ },
+ ],
+ },
+ },
+ // 更多设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_More_Setting'),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.advancedSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ bgap: vgap,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.advancedSet = _ref;
+ },
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
+ value: connectionPoolAttr.initialSize,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
+ value: connectionPoolAttr.minIdle,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
+ value: connectionPoolAttr.testOnReturn ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
+ value: connectionPoolAttr.testWhileIdle ? BI.i18nText('Dec-Dcm_Yes') : BI.i18nText('Dec-Dcm_No'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
+ value: connectionPoolAttr.timeBetweenEvictionRunsMillis,
+ unit: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
+ value: connectionPoolAttr.numTestsPerEvictionRun,
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
+ value: connectionPoolAttr.minEvictableIdleTimeMillis,
+ unit: BI.i18nText('BI-Basic_Seconds'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Evictable_Idle_Time_Millis'),
+ value: connectionPoolAttr.maxEvictableIdleTimeMillis,
+ unit: BI.i18nText('BI-Basic_Seconds'),
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow_Threshold'),
+ value: connectionPoolAttr.keepAliveBetweenTimeMillis,
+ unit: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ {
+ type: FormItem.xtype,
+ name: 'Fetchsize',
+ value: fetchSize,
+ },
+ ],
+ },
+ },
+ ],
+ };
+ }
+}
diff --git a/src/modules/pages/connection/list/list.constant.ts b/src/modules/pages/connection/list/list.constant.ts
new file mode 100644
index 0000000..fa5112c
--- /dev/null
+++ b/src/modules/pages/connection/list/list.constant.ts
@@ -0,0 +1 @@
+BI.constant('dec.constant.connection.list', []);
\ No newline at end of file
diff --git a/src/modules/pages/connection/list/list.model.ts b/src/modules/pages/connection/list/list.model.ts
index 5d650e9..b1bc9d2 100644
--- a/src/modules/pages/connection/list/list.model.ts
+++ b/src/modules/pages/connection/list/list.model.ts
@@ -1,10 +1,11 @@
import { model, Model } from '@core/core';
import { ApiFactory } from '../../..//crud/apiFactory';
import { AppModel } from '../../../app.model';
+import type { ConnectionJDBC } from '../../../crud/crud.typings';
const api = new ApiFactory().create();
@model()
export class ConnectionListModel extends Model<{
- types : {
+ types: {
connections: AppModel['TYPE']['connections'];
connectionSelected: AppModel['TYPE']['connectionSelected'];
},
@@ -19,21 +20,40 @@ export class ConnectionListModel extends Model<{
}
actions = {
- setConnections: ():Promise => api.getConnectionList().then(data => {
+ setConnections: (): Promise => api.getConnectionList().then(data => {
+ data.data.push(...BI.Constants.getConstant('dec.constant.connection.list'));
if (BI.size(data.data) > 0) {
this.model.connections = data.data;
+ let defaultDatabaseName,
+ defaultDatabaseId = BI.Services.getService("dec.service.global")
+ .getHashSearchParams("databaseId");
+
this.model.connections.forEach(item => {
- // 后端传过来的是字符串,转为对象
- item.connectionData = JSON.parse(item.connectionData as string);
+ // REPORT-111534 有些环境存在脏数据,补下容错
+ if (BI.isNull(item.connectionData)) return;
+
+ // 后端传过来的是字符串,转为对象
+ BI.isString(item.connectionData) && (item.connectionData = JSON.parse(item.connectionData as string));
+
+ // 目前只有jdbc存在identity,后期拓展
+ if ((item.connectionData as ConnectionJDBC).identity === defaultDatabaseId) {
+ defaultDatabaseName = item.connectionName;
+ }
});
- this.model.connectionSelected = data.data[0].connectionName;
- } else {
- this.model.connectionSelected = '';
+
+ // 仅首次进入时从url中读取参数,其他情况保留选中状态
+ defaultDatabaseName ||= data.data[0].connectionName;
+
+ this.setSelectedConnection(defaultDatabaseName);
}
return new Promise(resolve => {
resolve();
});
}),
+
+ setSelectedConnection(name: string) {
+ this.model.connectionSelected = name;
+ }
}
}
diff --git a/src/modules/pages/connection/list/list.ts b/src/modules/pages/connection/list/list.ts
index f674dab..8ffa81c 100644
--- a/src/modules/pages/connection/list/list.ts
+++ b/src/modules/pages/connection/list/list.ts
@@ -3,6 +3,7 @@ import { ListItem } from './list_item/list_item';
import { ConnectionListModel } from './list.model';
import { getDatabaseType } from './list.service';
import { Tab } from '@fui/core';
+import './list.constant'
@shortcut()
@store(ConnectionListModel)
@@ -91,6 +92,7 @@ export class ConnectionList extends BI.Pane {
creator: item.creator,
databaseType: getDatabaseType(item),
selected: this.model.connectionSelected ? this.model.connectionSelected === item.connectionName : index === 0,
+ pluginConnection: item.pluginConnection,
};
});
}
diff --git a/src/modules/pages/connection/list/list_item/list_item.model.ts b/src/modules/pages/connection/list/list_item/list_item.model.ts
index f23de66..fa43a36 100644
--- a/src/modules/pages/connection/list/list_item/list_item.model.ts
+++ b/src/modules/pages/connection/list/list_item/list_item.model.ts
@@ -139,8 +139,9 @@ export class ListItemModel extends Model<{
// 后端传过来的是字符串,转为对象
item.connectionData = JSON.parse(item.connectionData as string);
});
+
if (name === this.model.connectionSelected) {
- this.model.connectionSelected = BI.size(this.model.connections) > 0 ? this.model.connections[0].connectionName : '';
+ this.setConnectionSelected(this.model.connections?.[0]?.connectionName || '');
}
api.shutdownConnectionStatus(name);
});
diff --git a/src/modules/pages/connection/list/list_item/list_item.ts b/src/modules/pages/connection/list/list_item/list_item.ts
index 58537d7..2d1fc0f 100644
--- a/src/modules/pages/connection/list/list_item/list_item.ts
+++ b/src/modules/pages/connection/list/list_item/list_item.ts
@@ -6,6 +6,10 @@ import { hasRegistered } from '../list.service';
import { connectionCanEdit, getTextByDatabaseType, getChartLength } from '../../../../app.service';
import { testConnection } from '../../../maintain/forms/form.server';
import { DownListCombo, Label, SignEditor } from '@fui/core';
+import { ApiFactory } from '../../../../crud/apiFactory';
+import { checkIllegalStrings } from "@core/index";
+
+const api = new ApiFactory().create();
@shortcut()
@store(ListItemModel)
@@ -16,6 +20,7 @@ export class ListItem extends BI.BasicButton {
name: '',
creator: '',
databaseType: '',
+ pluginConnection: false,
height: 25,
baseCls: 'dec-dcm-connection-list-item bi-list-item-active2',
$testId: 'dec-dcm-connection-list-item',
@@ -39,7 +44,7 @@ export class ListItem extends BI.BasicButton {
};
render() {
- const { name, databaseType } = this.options;
+ const { name, databaseType, pluginConnection } = this.options;
return {
type: BI.HTapeLayout.xtype,
@@ -86,6 +91,17 @@ export class ListItem extends BI.BasicButton {
return;
}
+ const result = checkIllegalStrings(newName);
+ if (!result.legal) {
+ BI.Msg.toast(result.errorMsg, {
+ level: 'error',
+ });
+ this.store.setIsEdit(false, name);
+ this.nameLabel.setText(name);
+ this.nameEditor.setValue(name);
+
+ return;
+ }
this.store.changeName(name, newName).then(re => {
this.store.setIsEdit(false, name);
if (re.errorCode) {
@@ -103,7 +119,7 @@ export class ListItem extends BI.BasicButton {
},
],
}, {
- el: databaseType ? {
+ el: databaseType && !pluginConnection ? {
type: BI.DownListCombo.xtype,
cls: 'link-item-icon',
stopPropagation: true,
@@ -206,8 +222,17 @@ export class ListItem extends BI.BasicButton {
}
private testConnectionAction() {
- const { name } = this.options;
- testConnection(this.model.connections.find(item => item.connectionName === name));
+ // 接口返回的内容是对称加密的,前端要先解密再用新加密传回去
+ const connection = BI.cloneDeep(this.model.connections
+ .find(item => item.connectionName === this.options.name));
+
+ if (BI.isNull(connection)) return;
+
+ const validationQuery = connection?.connectionData?.connectionPoolAttr?.validationQuery || '';
+
+ BI.set(connection, 'connectionData.connectionPoolAttr.validationQuery', api.getCipher(api.getPlain(validationQuery)));
+
+ testConnection(connection);
}
private itemActionCalculate() {
diff --git a/src/modules/pages/database/database.constant.ts b/src/modules/pages/database/database.constant.ts
new file mode 100644
index 0000000..12f2af8
--- /dev/null
+++ b/src/modules/pages/database/database.constant.ts
@@ -0,0 +1,17 @@
+import { DATEBASE_FILTER_TYPE } from "@constants/constant";
+
+BI.constant('dec.constant.database.filter.type', [
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Commonly'),
+ value: DATEBASE_FILTER_TYPE.COMMONLY,
+ selected: true,
+ },
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_All'),
+ value: DATEBASE_FILTER_TYPE.ALL,
+ },
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Other'),
+ value: DATEBASE_FILTER_TYPE.OTHER,
+ },
+]);
\ No newline at end of file
diff --git a/src/modules/pages/database/database.model.ts b/src/modules/pages/database/database.model.ts
index 44109ea..0de45eb 100644
--- a/src/modules/pages/database/database.model.ts
+++ b/src/modules/pages/database/database.model.ts
@@ -2,10 +2,12 @@ import { model, Model } from '@core/core';
import { AppModel } from 'src/modules/app.model';
import { getAllDatabaseTypes } from '../../app.service';
import { DatabaseType } from '../../app.typings';
+import { connectionType } from '@constants/env';
+import { OTHER_JDBC } from '@constants/constant';
@model()
export class DatebaseModel extends Model<{
- types : {
+ types: {
filter: AppModel['TYPE']['filter'];
datebaseTypeSelected: AppModel['TYPE']['datebaseTypeSelected'];
},
@@ -20,20 +22,30 @@ export class DatebaseModel extends Model<{
isInternal: true,
isPlugin: true,
datebaseTypes: getAllDatabaseTypes().filter(item => item.commonly),
+ isJNDILimit: false,
};
}
+
+ computed = {
+ otherDatabases: () => {
+ return this.model.isJNDILimit
+ ? [OTHER_JDBC]
+ : [OTHER_JDBC, connectionType.JNDI];
+ }
+ }
+
actions = {
- setSearch:(search: string) => {
+ setSearch: (search: string) => {
this.model.search = search;
},
- setFilter:(filter: string) => {
+ setFilter: (filter: string) => {
this.model.filter = filter;
},
setDatebaseTypes: (datebaseTypes: DatabaseType[]) => {
this.model.datebaseTypes = datebaseTypes;
this.model.datebaseTypeSelected = '';
},
- setInternal:(isInternal: boolean) => {
+ setInternal: (isInternal: boolean) => {
this.model.isInternal = isInternal;
},
setPlugin: (isPlugin: boolean) => {
@@ -42,5 +54,8 @@ export class DatebaseModel extends Model<{
setDatebaseTypeSelected(datebaseType: string) {
this.model.datebaseTypeSelected = datebaseType;
},
+ setJNDILimit: (v: boolean) => {
+ this.model.isJNDILimit = v;
+ },
}
}
diff --git a/src/modules/pages/database/database.ts b/src/modules/pages/database/database.ts
index 93b32ae..85a4a3b 100644
--- a/src/modules/pages/database/database.ts
+++ b/src/modules/pages/database/database.ts
@@ -6,6 +6,11 @@ import { connectionType } from '@constants/env';
import { DatebaseType } from './database_type/database_type';
import { getAllDatabaseTypes } from '../../app.service';
import { ButtonGroup, MultiSelectItem, SearchEditor } from '@fui/core';
+import { ApiFactory } from 'src/modules/crud/apiFactory';
+import './database.constant'
+
+const api = new ApiFactory().create();
+
@shortcut()
@store(DatebaseModel)
export class Datebase extends BI.Widget {
@@ -65,6 +70,7 @@ export class Datebase extends BI.Widget {
mounted() {
this.store.setFilter(DATEBASE_FILTER_TYPE.COMMONLY);
this.store.setDatebaseTypeSelected('');
+ this.getDatabaseTypeLimit();
}
render() {
@@ -116,24 +122,12 @@ export class Datebase extends BI.Widget {
ref: (_ref: ButtonGroup) => {
this.filter = _ref;
},
- items: [
- {
+ items: () => BI.map(BI.Constants.getConstant('dec.constant.database.filter.type'), (_, value) => {
+ return {
type: Filter.xtype,
- text: BI.i18nText('Dec-Dcm_Connection_Commonly'),
- value: DATEBASE_FILTER_TYPE.COMMONLY,
- selected: true,
- },
- {
- type: Filter.xtype,
- text: BI.i18nText('Dec-Dcm_Connection_All'),
- value: DATEBASE_FILTER_TYPE.ALL,
- },
- {
- type: Filter.xtype,
- text: BI.i18nText('Dec-Dcm_Connection_Other'),
- value: DATEBASE_FILTER_TYPE.OTHER,
- },
- ],
+ ...value,
+ }
+ }),
},
width: 200,
},
@@ -142,20 +136,18 @@ export class Datebase extends BI.Widget {
items: [
{
el: {
- type: BI.HTapeLayout.xtype,
+ type: BI.VerticalAdaptLayout.xtype,
hgap: 20,
invisible: true,
items: [
{
type: BI.Label.xtype,
- width: 70,
textAlign: 'left',
text: BI.i18nText('Dec-Dcm_Connection_Type_Filter'),
title: BI.i18nText('Dec-Dcm_Connection_Type_Filter'),
},
{
type: BI.MultiSelectItem.xtype,
- width: 80,
selected: this.model.isInternal,
text: BI.i18nText('Dec-Dcm_Connection_Support_Inner'),
title: BI.i18nText('Dec-Dcm_Connection_Support_Inner'),
@@ -168,7 +160,6 @@ export class Datebase extends BI.Widget {
},
{
type: BI.MultiSelectItem.xtype,
- width: 80,
selected: this.model.isPlugin,
text: BI.i18nText('Dec-Dcm_Connection_Support_Plugin'),
title: BI.i18nText('Dec-Dcm_Connection_Support_Plugin'),
@@ -250,11 +241,20 @@ export class Datebase extends BI.Widget {
this.store.setDatebaseTypes(this.allDatabaseTypes.filter(item => item.commonly));
break;
case DATEBASE_FILTER_TYPE.OTHER:
- this.store.setDatebaseTypes(this.allDatabaseTypes.filter(item => item.type === connectionType.JNDI || item.type === OTHER_JDBC));
+ this.store.setDatebaseTypes(this.allDatabaseTypes.filter(item => this.model.otherDatabases.includes(item.type)));
break;
- default:
+ case DATEBASE_FILTER_TYPE.ALL:
this.store.setDatebaseTypes(this.allDatabaseTypes.filter(item => item.type !== connectionType.JNDI && item.type !== OTHER_JDBC));
break;
+ default:
+ this.store.setDatebaseTypes(this.allDatabaseTypes.filter(item => item.marker && (item.marker === filter)));
+ break;
}
}
+
+ // 获取JNDI
+ private async getDatabaseTypeLimit() {
+ const result = await api.getJNDIDatabaseStatus();
+ this.store.setJNDILimit(result.data);
+ }
}
diff --git a/src/modules/pages/database/database_type/database_type.model.ts b/src/modules/pages/database/database_type/database_type.model.ts
index cb51507..483b700 100644
--- a/src/modules/pages/database/database_type/database_type.model.ts
+++ b/src/modules/pages/database/database_type/database_type.model.ts
@@ -6,11 +6,13 @@ export class DatebaseTypeModel extends Model<
types: {
datebaseTypeSelected: AppModel['TYPE']['datebaseTypeSelected'];
pageIndex: AppModel['TYPE']['pageIndex'];
+ noTestConnection: AppModel['TYPE']['noTestConnection'];
+ datebaseTypeSelectedOne: AppModel['TYPE']['datebaseTypeSelectedOne'];
},
context: DatebaseTypeModel['context'];
}> {
static xtype = 'dec.dcm.model.datebase.type';
- context = ['datebaseTypeSelected', 'pageIndex'];
+ context = ['datebaseTypeSelected', 'pageIndex', 'noTestConnection', 'datebaseTypeSelectedOne'];
actions = {
setDatebaseTypeSelected: (datebaseTypeSelected: string) => {
@@ -19,5 +21,8 @@ export class DatebaseTypeModel extends Model<
setPageIndex: (index: string) => {
this.model.pageIndex = index;
},
+ setNoTestConnection: (value: boolean) => {
+ this.model.noTestConnection = value;
+ }
}
}
diff --git a/src/modules/pages/database/database_type/database_type.ts b/src/modules/pages/database/database_type/database_type.ts
index 6778564..2741408 100644
--- a/src/modules/pages/database/database_type/database_type.ts
+++ b/src/modules/pages/database/database_type/database_type.ts
@@ -70,6 +70,7 @@ export class DatebaseType extends BI.BasicButton {
const { value } = this.options;
this.store.setDatebaseTypeSelected(value);
this.store.setPageIndex(PAGE_INDEX.MAINTAIN);
+ this.store.setNoTestConnection(this.model.datebaseTypeSelectedOne.isHideConnection);
}
mounted() {
@@ -88,6 +89,9 @@ export class DatebaseType extends BI.BasicButton {
if (url.startsWith('/')) {
return `${PluginImgPrefix}${url}`;
}
+ if (url.startsWith('http')) {
+ return url;
+ }
return `${PluginImgPrefix}/${url}`;
}
diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.model.ts b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts
index 384e4f4..15b164e 100644
--- a/src/modules/pages/maintain/components/driverselector/driverselector.model.ts
+++ b/src/modules/pages/maintain/components/driverselector/driverselector.model.ts
@@ -67,7 +67,8 @@ export class DriverSelectorModel extends Model {
this.model.customDriver.driver = driver;
this.model.customDrivers.some(customDriver => {
- if (customDriver.driverClass === driver) {
+ // DEC-21469 存在driver值相同但driver名不同的场景,因此要用拼接名判断
+ if (`${customDriver.driverClass} (${customDriver.name})` === value) {
this.model.driverSource = customDriver.name;
this.model.customDriver.value = `${driver} (${customDriver.name})`;
@@ -86,6 +87,12 @@ export class DriverSelectorModel extends Model {
changeDriverSource: driverTypeComboValue => {
this.model.driverSource = driverTypeComboValue === 'default' ? '' : this.model.driverSource;
},
+
+ setDefaultDrivers: version => {
+ const defaultDrivers = this.getDrivers(version);
+ this.model.defaultDrivers = defaultDrivers;
+ this.changeDefaultDriver(defaultDrivers[0]?.value);
+ }
};
private resolveSelectedDriverType = () => {
@@ -96,11 +103,12 @@ export class DriverSelectorModel extends Model {
return [this.options.driverSource, this.options.driver];
};
- private getDrivers = () => {
+ private getDrivers = (version?: string) => {
const connectionData = this.options.connectionData as ConnectionJDBC;
const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver);
+ const selectedVersion = version ?? this.options.version;
const drivers = connectionType.drivers ?
- connectionType.drivers.map(item => {
+ (BI.isUndefined(connectionType.versions) ? connectionType.drivers : connectionType.drivers[selectedVersion]).map(item => {
return {
text: item,
value: item,
@@ -110,8 +118,7 @@ export class DriverSelectorModel extends Model {
text: connectionType.driver,
value: connectionType.driver,
}];
-
- if (!drivers.some(item => item.text === connectionData.driver)) {
+ if (BI.isUndefined(connectionType.versions) && !drivers.some(item => item.text === connectionData.driver)) {
return [
{
text: connectionData.driver,
diff --git a/src/modules/pages/maintain/components/driverselector/driverselector.ts b/src/modules/pages/maintain/components/driverselector/driverselector.ts
index ef6c351..8408e05 100644
--- a/src/modules/pages/maintain/components/driverselector/driverselector.ts
+++ b/src/modules/pages/maintain/components/driverselector/driverselector.ts
@@ -24,21 +24,32 @@ export class DriverSelector extends BI.Widget {
driver: '',
driverSource: '',
connectionData: {} as ConnectionJDBC,
+ version: '',
};
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);
+ this.customDrivers.populate(items);
+ this.customDrivers.setValue(this.model.customDriver.value);
},
driverManageEntryVisible: b => {
- this.driverManageEntry.setVisible(false);
+ this.driverManageEntry.setVisible(b);
},
+
+ defaultDrivers: items => {
+ this.defaultDrivers.populate(items);
+ this.defaultDrivers.setValue(this.model.defaultDriver.driver);
+ this.fireEvent('EVENT_CHANGE');
+ }
};
private driverManageEntry = null;
@@ -55,7 +66,6 @@ export class DriverSelector extends BI.Widget {
type: BI.TextValueCombo.xtype,
width: 86,
value: this.model.selectedDriverType,
- invisible: true,
items: [
{
text: BI.i18nText('Dec-Basic_Default'),
@@ -95,7 +105,7 @@ export class DriverSelector extends BI.Widget {
this.defaultDrivers = _ref;
},
invisible: this.model.driverSource !== '',
- width: 300,
+ width: 204,
items: this.model.defaultDrivers,
value: this.model.defaultDriver.driver,
listeners: [
@@ -116,13 +126,13 @@ export class DriverSelector extends BI.Widget {
ref: _ref => {
this.customDrivers = _ref;
},
- invisible: true,
+ 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'),
+ defaultText: BI.i18nText('Dec-Please_Select_One'),
warningTitle: BI.i18nText('Dec-Dcm-Driver_Driver_File_Lost'),
listeners: [
{
@@ -146,7 +156,7 @@ export class DriverSelector extends BI.Widget {
text: BI.i18nText('Dec-Dcm_Create_New_Driver'),
},
from: '.dec-dcm',
- invisible: true,
+ invisible: !this.model.driverManageEntryVisible,
listeners: [
{
eventName: 'EVENT_CLOSE',
@@ -175,8 +185,12 @@ export class DriverSelector extends BI.Widget {
getValue() {
return {
- // driverSource: this.model.driverSource,
+ driverSource: this.model.driverSource,
driver: this.model.driverSource === '' ? this.model.defaultDriver.driver : this.model.customDriver.driver,
};
}
+
+ setDefaultDrivers(version: string) {
+ this.store.setDefaultDrivers(version);
+ }
}
diff --git a/src/modules/pages/maintain/components/form_item/form_item.ts b/src/modules/pages/maintain/components/form_item/form_item.ts
index 00b6f1a..a0d54eb 100644
--- a/src/modules/pages/maintain/components/form_item/form_item.ts
+++ b/src/modules/pages/maintain/components/form_item/form_item.ts
@@ -1,4 +1,5 @@
import { shortcut } from '@core/core';
+import { Label } from '@fui/core';
import { CONNECTION_LAYOUT } from '@constants/constant';
@shortcut()
@@ -11,14 +12,19 @@ export class FormItem extends BI.Widget {
nameWidth: 140,
isBold: true,
$testId: 'dec-dcm-maintain-form-item',
- }
+ };
+
+ nameLabel: Label;
- render () {
+ render() {
return {
type: BI.FloatLeftLayout.xtype,
items: [
{
type: BI.Label.xtype,
+ ref: (ref: Label) => {
+ this.nameLabel = ref;
+ },
cls: this.options.isBold ? 'bi-font-bold' : '',
width: this.options.nameWidth,
textAlign: 'left',
@@ -29,4 +35,12 @@ export class FormItem extends BI.Widget {
],
};
}
+
+ /**
+ * 设置表单名称
+ * @param name
+ */
+ setName(name: string) {
+ this.nameLabel.setText(name);
+ }
}
diff --git a/src/modules/pages/maintain/forms/components/form.jdbc.ts b/src/modules/pages/maintain/forms/components/form.jdbc.ts
index d9fe88c..430a7aa 100644
--- a/src/modules/pages/maintain/forms/components/form.jdbc.ts
+++ b/src/modules/pages/maintain/forms/components/form.jdbc.ts
@@ -1,879 +1,1876 @@
-import { shortcut } from '@core/core';
-import { Collapse, EVENT_CHANGE } from 'src/modules/components/collapse/collapse';
-import { FormItem } from '../../components/form_item/form_item';
-import { Connection, ConnectionJDBC, ConnectionPoolJDBC } from 'src/modules/crud/crud.typings';
-import { connectionType } from '@constants/env';
-import { CONNECT_CHARSET, CONNECTION_LAYOUT, INT_MAX_VALUE, INT_MIN_VALUE } from '@constants/constant';
-import { getAllDatabaseTypes, getJdbcDatabaseType, resolveUrlInfo, splitUrl } from '../../../../app.service';
-import { TextChecker } from '../../../../components/text_checker/text_checker';
-import { ApiFactory } from 'src/modules/crud/apiFactory';
-import {
- Editor,
- EditorIconCheckCombo,
- Label,
- TextAreaEditor,
- TextEditor,
- TextValueCombo,
- VerticalLayout,
-} from '@fui/core';
-import { DriverSelector } from '../../components/driverselector/driverselector';
-
-const api = new ApiFactory().create();
-
-@shortcut()
-export class FormJdbc extends BI.Widget {
- static xtype = 'dec.dcm.maintain.form.jdbc';
-
- props = {
- formData: {} as Connection,
- };
-
- oldPassword = '';
- allDatabaseTypes = getAllDatabaseTypes();
-
- advancedSet: VerticalLayout;
- formUser: FormItem;
- formPassword: FormItem;
- formPrincipal: FormItem;
- formKeyPath: FormItem;
- labelTips: Label;
-
- form = {
- connectionName: null,
- driver: null,
- database: null,
- host: null,
- port: null,
- user: null,
- password: null,
- authType: null,
- principal: null,
- keyPath: null,
- originalCharsetName: null,
- schema: null,
- url: null,
- initialSize: null,
- maxActive: null,
- maxIdle: null,
- maxWait: null,
- validationQuery: null,
- testOnBorrow: null,
- testOnReturn: null,
- testWhileIdle: null,
- timeBetweenEvictionRunsMillis: null,
- numTestsPerEvictionRun: null,
- minIdle: null,
- minEvictableIdleTimeMillis: null,
- fetchSize: null,
- };
-
- render() {
- const { connectionName, connectionData } = this.options.formData;
- const {
- driver,
- driverSource,
- user,
- password,
- originalCharsetName,
- schema,
- url,
- connectionPoolAttr,
- database,
- authType,
- principal,
- keyPath,
- fetchSize,
- } = connectionData as ConnectionJDBC;
- const {
- initialSize,
- maxActive,
- maxIdle,
- maxWait,
- validationQuery,
- testOnBorrow,
- testOnReturn,
- testWhileIdle,
- timeBetweenEvictionRunsMillis,
- numTestsPerEvictionRun,
- minIdle,
- minEvictableIdleTimeMillis,
- } = connectionPoolAttr as ConnectionPoolJDBC;
- const databaseType = getJdbcDatabaseType(database, driver);
- this.oldPassword = password;
- const { host, port, databaseName } = resolveUrlInfo(url, database);
- const { hgap, vgap } = CONNECTION_LAYOUT;
-
- const valueRangeConfig = {
- errorText: BI.i18nText('Dec-Dcm_Connection_Value_Out_Range'),
- checker: (value: string) => this.checkValueRange(value),
- autoFix: true,
- };
-
- return {
- type: BI.VerticalLayout.xtype,
- hgap,
- vgap,
- items: [
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Name'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'connection-name',
- width: 300,
- value: connectionName,
- allowBlank: true,
- ref: (_ref: TextChecker) => {
- this.form.connectionName = _ref;
- },
- watermark: BI.i18nText('Dec-Dcm_Data_Connections'),
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'),
- 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,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
- forms: [{
- type: BI.TextEditor.xtype,
- $value: 'database-name',
- width: 300,
- allowBlank: true,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
- value: databaseName,
- ref: (_ref: any) => {
- this.form.database = _ref;
- },
- listeners: [{
- eventName: BI.Editor.EVENT_CHANGE,
- action: () => {
- this.onHostPortChange(databaseType);
- },
- }],
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
- forms: [{
- type: BI.TextEditor.xtype,
- $value: 'database-host',
- width: 300,
- allowBlank: true,
- value: host,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
- ref: (_ref: any) => {
- this.form.host = _ref;
- },
- listeners: [{
- eventName: BI.Editor.EVENT_CHANGE,
- action: () => {
- this.onHostPortChange(databaseType);
- },
- }],
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'database-port',
- width: 300,
- allowBlank: true,
- value: port,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.port = _ref;
- },
- listeners: [{
- eventName: BI.Editor.EVENT_CHANGE,
- action: () => {
- this.onHostPortChange(databaseType);
- },
- }],
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_AuthType'),
- invisible: !databaseType.kerberos,
- forms: [{
- type: BI.TextValueCombo.xtype,
- $value: 'auth-type',
- width: 300,
- value: authType,
- ref: (_ref: TextValueCombo) => {
- this.form.authType = _ref;
- },
- items: [
- {
- text: BI.i18nText('Dec-Dcm_Connection_Form_UserName_Password'),
- value: '',
- },
- {
- text: 'Kerberos',
- value: 'kerberos',
- },
- ],
- listeners: [
- {
- eventName: BI.Combo.EVENT_CHANGE,
- action: () => {
- const type = this.form.authType.getValue()[0];
- this.formPrincipal.setVisible(!!type);
- this.formKeyPath.setVisible(!!type);
- this.formUser.setVisible(!type);
- this.formPassword.setVisible(!type);
- this.labelTips.setVisible(!!type);
- },
- },
- ],
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
- invisible: !!authType,
- ref: (_ref: FormItem) => {
- this.formUser = _ref;
- },
- forms: [{
- type: BI.TextEditor.xtype,
- $value: 'username',
- width: 300,
- allowBlank: true,
- value: user,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
- ref: (_ref: TextEditor) => {
- this.form.user = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
- invisible: !!authType,
- ref: (_ref: FormItem) => {
- this.formPassword = _ref;
- },
- forms: [{
- type: BI.Editor.xtype,
- $value: 'password',
- cls: 'bi-border bi-border-radius',
- width: 300,
- height: 20,
- allowBlank: true,
- value: password,
- inputType: 'password',
- autocomplete: 'new-password',
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
- ref: (_ref: Editor) => {
- this.form.password = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Principal'),
- invisible: !authType,
- ref: (_ref: FormItem) => {
- this.formPrincipal = _ref;
- },
- forms: [{
- type: BI.TextEditor.xtype,
- $value: 'principal',
- width: 300,
- allowBlank: true,
- value: principal,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Principal'),
- ref: (_ref: TextEditor) => {
- this.form.principal = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_KeyPath'),
- invisible: !authType,
- ref: (_ref: FormItem) => {
- this.formKeyPath = _ref;
- },
- forms: [{
- type: BI.Editor.xtype,
- $value: 'key-path',
- cls: 'bi-border',
- width: 300,
- height: 20,
- allowBlank: true,
- value: keyPath,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_KeyPath'),
- ref: (_ref: Editor) => {
- this.form.keyPath = _ref;
- },
- }],
- },
- {
- type: BI.Label.xtype,
- cls: 'bi-tips',
- textAlign: 'left',
- invisible: true,
- text: BI.i18nText('Dec-Dcm_Connection_JDBC_Warning'),
- ref: (_ref: Label) => {
- this.labelTips = _ref;
- },
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_OriginalCharsetName'),
- forms: [{
- type: BI.TextValueCombo.xtype,
- $value: 'original-charset-name',
- width: 300,
- value: originalCharsetName ? originalCharsetName : '',
- items: CONNECT_CHARSET,
- ref: (_ref: TextValueCombo) => {
- this.form.originalCharsetName = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- invisible: !databaseType.hasSchema,
- height: 64,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Pattern'),
- forms: [{
- type: BI.VerticalLayout.xtype,
- items: [{
- type: BI.FloatLeftLayout.xtype,
- items: [{
- type: BI.TextButton.xtype,
- cls: 'bi-high-light',
- text: BI.i18nText('Dec-Dcm_Connection_Click_Connect_Database'),
- handler: () => {
- this.fireEvent('EVENT_TEST_CONNECTION');
- },
- }, {
- type: BI.Label.xtype,
- cls: 'bi-tips',
- lgap: 3,
- text: BI.i18nText('Dec-Dcm_Connection_Read_Mode_List'),
- }],
- }, {
- type: BI.TextValueCombo.xtype,
- $value: 'schema',
- width: 300,
- vgap: 15,
- disabled: true,
- value: schema,
- items: schema ? [{ text: schema, value: schema }] : [],
- ref: (_ref: TextValueCombo) => {
- this.form.schema = _ref;
- },
- }],
- }],
- },
- {
- type: BI.Layout.xtype,
- cls: 'bi-border-top',
- bgap: 8,
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
- forms: [{
- type: BI.TextEditor.xtype,
- $value: 'database-url',
- width: 300,
- allowBlank: true,
- value: url,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
- ref: (_ref: TextEditor) => {
- this.form.url = _ref;
- },
- listeners: [{
- eventName: 'EVENT_CHANGE',
- action: () => {
- const urlInfo = resolveUrlInfo(this.form.url.getValue(), database);
- this.form.host.setValue(urlInfo.host);
- this.form.database.setValue(urlInfo.databaseName);
- this.form.port.setValue(urlInfo.port);
- },
- }],
- }],
- },
- {
- type: Collapse.xtype,
- bgap: -15,
- width: 70,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Advanced_Setting'),
- listeners: [
- {
- eventName: EVENT_CHANGE,
- action: (isCollapse: boolean) => {
- this.advancedSet.setVisible(!isCollapse);
- },
- },
- ],
- },
- {
- type: BI.VerticalLayout.xtype,
- vgap,
- tgap: -15,
- invisible: true,
- ref: (_ref: VerticalLayout) => {
- this.advancedSet = _ref;
- },
- items: [
- {
- type: FormItem.xtype,
- tgap: 15,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'initial-size',
- width: 300,
- allowBlank: false,
- value: initialSize,
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
- ref: (_ref: TextChecker) => {
- this.form.initialSize = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'max-active',
- width: 300,
- allowBlank: false,
- value: maxActive,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.maxActive = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Idle'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'max-idle',
- width: 300,
- allowBlank: false,
- value: maxIdle,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Idle'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.maxIdle = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'min-idle',
- width: 300,
- allowBlank: false,
- value: minIdle,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.minIdle = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
- forms: [
- {
- type: TextChecker.xtype,
- $value: 'max-wait',
- width: 300,
- allowBlank: false,
- value: maxWait,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.maxWait = _ref;
- },
- },
- {
- type: BI.Label.xtype,
- lgap: 5,
- height: CONNECTION_LAYOUT.labelHeight,
- text: BI.i18nText('Dec-Dcm_Millisecond'),
- },
- ],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_SQL_Validation_Query'),
- forms: [{
- type: BI.TextAreaEditor.xtype,
- $value: 'validation-query',
- cls: 'bi-border',
- allowBlank: true,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Place_Input'),
- value: api.getPlain(validationQuery || ''),
- width: 300,
- height: 100,
- ref: (_ref: TextAreaEditor) => {
- this.form.validationQuery = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
- forms: [{
- type: BI.TextValueCombo.xtype,
- $value: 'check',
- width: 300,
- allowBlank: true,
- value: testOnBorrow,
- items: this.getBooleanItem(),
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
- ref: (_ref: TextValueCombo) => {
- this.form.testOnBorrow = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
- forms: [{
- type: BI.TextValueCombo.xtype,
- $value: 'test-on-return',
- width: 300,
- allowBlank: true,
- value: testOnReturn,
- items: this.getBooleanItem(),
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
- ref: (_ref: TextValueCombo) => {
- this.form.testOnReturn = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
- forms: [{
- type: BI.TextValueCombo.xtype,
- $value: 'test-while-idle',
- width: 300,
- allowBlank: true,
- value: testWhileIdle,
- items: this.getBooleanItem(),
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
- ref: (_ref: TextValueCombo) => {
- this.form.testWhileIdle = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
- forms: [
- {
- type: TextChecker.xtype,
- $value: 'test-between-evicition-millis',
- width: 300,
- allowBlank: false,
- value: timeBetweenEvictionRunsMillis,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Number'),
- checker: (value: string) => this.checkNumber(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.timeBetweenEvictionRunsMillis = _ref;
- },
- },
- {
- type: BI.Label.xtype,
- lgap: 5,
- height: CONNECTION_LAYOUT.labelHeight,
- text: BI.i18nText('Dec-Dcm_Millisecond'),
- },
- ],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
- forms: [{
- type: TextChecker.xtype,
- $value: 'test-pereviction-run-num',
- width: 300,
- allowBlank: false,
- value: numTestsPerEvictionRun,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.numTestsPerEvictionRun = _ref;
- },
- }],
- },
- {
- type: FormItem.xtype,
- name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
- forms: [
- {
- type: TextChecker.xtype,
- $value: 'min-evictable-idle-time-millis',
- width: 300,
- allowBlank: false,
- value: minEvictableIdleTimeMillis,
- watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer'),
- checker: (value: string) => this.checkInteger(value),
- autoFix: true,
- }, valueRangeConfig],
- ref: (_ref: TextChecker) => {
- this.form.minEvictableIdleTimeMillis = _ref;
- },
- },
- {
- type: BI.Label.xtype,
- lgap: 5,
- height: CONNECTION_LAYOUT.labelHeight,
- text: BI.i18nText('BI-Basic_Seconds'),
- },
- ],
- }, {
- el: {
- type: BI.VerticalLayout.xtype,
- cls: 'bi-border-top',
- invisible: fetchSize < 0 && fetchSize !== -2,
- items: [
- {
- el: {
- type: FormItem.xtype,
- name: 'Fetchsize',
- forms: [{
- type: TextChecker.xtype,
- $value: 'fetch-size',
- width: 300,
- allowBlank: true,
- value: fetchSize === -2 ? '' : fetchSize,
- watermark: 'Fetchsize',
- validationChecker: [{
- errorText: BI.i18nText('Dec-Dcm_Connection_Check_Fetch_Size_Range'),
- checker: (value: string) => BI.isInteger(value) && BI.parseInt(value) >= 0 && BI.parseInt(value) <= 1000000,
- autoFix: true,
- }],
- ref: (_ref: TextChecker) => {
- this.form.fetchSize = _ref;
- },
- }],
- },
- vgap: 15,
- },
- ],
- },
- },
- ],
- },
- ],
- };
- }
-
- public setError(value: string) {
- this.form.connectionName.setError(value);
- }
-
- private checkInteger(value: string) {
- return /^[\d]+$/.test(value);
- }
-
- private checkNumber(value: string) {
- return /^[(\-|\+)?\d]+$/.test(value);
- }
-
- private checkValueRange(value: string) {
- return parseInt(value, 0) <= INT_MAX_VALUE && parseInt(value, 0) >= INT_MIN_VALUE;
- }
-
- private getDrivers() {
- const connectionData = this.options.formData.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;
- }
-
- private getBooleanItem() {
- return [
- {
- text: BI.i18nText('Dec-Dcm_Yes'),
- value: true,
- },
- {
- text: BI.i18nText('Dec-Dcm_No'),
- value: false,
- },
- ];
- }
-
- private onHostPortChange(databaseType) {
- const { urls, url } = databaseType;
- const driver = this.form.driver.getValue();
- 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();
- this.form.url.setValue(splitUrl(host, port, database, selectUrl));
- }
-
- public setSchemas(schemas: string[]) {
- this.form.schema.setEnable(true);
- if (schemas.length > 0) {
- const value = this.form.schema.getValue()[0];
- this.form.schema.populate(schemas.map(item => {
- return {
- text: item,
- value: item,
- };
- }));
- this.form.schema.setValue(value && schemas.some(item => item === value) ? value : schemas[0]);
- }
- }
-
- public validation(): boolean {
- return this.form.driver.validation();
- }
-
- public getSubmitValue(): Connection {
- const connectionData = this.options.formData.connectionData as ConnectionJDBC;
- const connectionPoolAttr = connectionData.connectionPoolAttr;
- const originalCharsetName = this.form.originalCharsetName.getValue()[0] || '';
- // TODO 获取表单数据这里待优化
-
- return {
- connectionType: connectionType.JDBC,
- connectionId: this.form.connectionName.getValue(),
- connectionName: this.form.connectionName.getValue(),
- connectionData: BI.extend({}, connectionData, {
- database: connectionData.database,
- connectionName: this.form.connectionName.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()),
- queryType: '',
- newCharsetName: originalCharsetName ? 'gbk' : '', // 后台要求,originalCharsetName不为空时,newCharsetName为gbk
- originalCharsetName,
- schema: this.form.schema.getValue()[0],
- host: this.form.host.getValue(),
- authType: this.form.authType.getValue()[0] || '',
- creator: Dec ? Dec.personal.username : '',
- principal: this.form.principal.getValue(),
- keyPath: this.form.keyPath.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(),
- maxIdle: this.form.maxIdle.getValue(),
- minIdle: this.form.minIdle.getValue(),
- maxWait: this.form.maxWait.getValue(),
- validationQuery: api.getCipher(this.form.validationQuery.getValue()),
- testOnBorrow: BI.size(this.form.testOnBorrow.getValue()) > 0 ? this.form.testOnBorrow.getValue()[0] : connectionPoolAttr.testOnBorrow,
- testOnReturn: BI.size(this.form.testOnReturn.getValue()) > 0 ? this.form.testOnReturn.getValue()[0] : connectionPoolAttr.testOnReturn,
- testWhileIdle: BI.size(this.form.testWhileIdle.getValue()) > 0 ? this.form.testWhileIdle.getValue()[0] : connectionPoolAttr.testWhileIdle,
- timeBetweenEvictionRunsMillis: this.form.timeBetweenEvictionRunsMillis.getValue(),
- numTestsPerEvictionRun: this.form.numTestsPerEvictionRun.getValue(),
- minEvictableIdleTimeMillis: this.form.minEvictableIdleTimeMillis.getValue(),
- },
- }),
- };
- }
-}
+import { shortcut } from '@core/core';
+import { Collapse, EVENT_CHANGE } from 'src/modules/components/collapse/collapse';
+import { FormItem } from '../../components/form_item/form_item';
+import { Connection, ConnectionJDBC, ConnectionPoolJDBC } from 'src/modules/crud/crud.typings';
+import { connectionType } from '@constants/env';
+import { CONNECT_CHARSET, CONNECTION_LAYOUT, INT_MAX_VALUE, INT_MIN_VALUE, CONNECT_SSH_TYPE, CONNECT_SSL_TYPE, YES_OR_NO } from '@constants/constant';
+import { getAllDatabaseTypes, getJdbcDatabaseType, resolveUrlInfo, splitUrl } from '../../../../app.service';
+import { DatabaseType } from 'src/modules/app.typings';
+import { TextChecker } from '../../../../components/text_checker/text_checker';
+import { FileChooser } from '../../../../components/file_chooser/file_chooser';
+import { ApiFactory } from 'src/modules/crud/apiFactory';
+import { Editor, Label, TextAreaEditor, TextEditor, TextValueCombo, VerticalLayout, MultiSelectItem } from '@fui/core';
+import { DriverSelector } from '../../components/driverselector/driverselector';
+import { FileUpload } from '../../../../components/file_upload/file_upload';
+import { TipsCombo } from '../../../../components/tips_combo/tips_combo';
+
+const api = new ApiFactory().create();
+
+const EDITOR_WIDTH = 300, EDITOR_HEIGHT = 20;
+
+@shortcut()
+export class FormJdbc extends BI.Widget {
+ static xtype = 'dec.dcm.maintain.form.jdbc';
+
+ props = {
+ formData: {} as Connection,
+ };
+
+ oldPassword = '';
+ oldSshSecret = '';
+
+ databaseType: DatabaseType;
+ allDatabaseTypes = getAllDatabaseTypes();
+
+ parallelLoadSet: VerticalLayout;
+ hdfsSet: VerticalLayout;
+ sshSet: VerticalLayout;
+ sshForm: VerticalLayout;
+ sslSet: VerticalLayout;
+ sslForm: VerticalLayout;
+ advancedSet: VerticalLayout;
+ formUser: FormItem;
+ formPassword: FormItem;
+ formPrincipal: FormItem;
+ formKeyPath: FormItem;
+ formKrb5File: FormItem;
+ labelTips: Label;
+ schemaForm: FormItem;
+
+ form = {
+ connectionName: null,
+ version: null,
+ driver: null,
+ catalog: null,
+ database: null,
+ host: null,
+ port: null,
+ user: null,
+ password: null,
+ authType: null,
+ principal: null,
+ keyPath: null,
+ krb5Path: null,
+ originalCharsetName: null,
+ schema: null,
+ url: null,
+ initialSize: null,
+ maxActive: null,
+ maxWait: null,
+ // ssh
+ usingSsh: null,
+ sshIp: null,
+ sshPort: null,
+ sshUser: null,
+ sshType: null,
+ sshPrivateKeyPathForm: null,
+ sshPrivateKeyPath: null,
+ sshSecretForm: null,
+ sshSecret: null,
+ // ssl
+ usingSsl: null,
+ caCertificate: null,
+ verifyCa: null,
+ sslClientPrivateKey: null,
+ sslClientCertificate: null,
+ // more
+ validationQuery: null,
+ testOnBorrow: null,
+ keepAlive: null,
+ testOnReturn: null,
+ testWhileIdle: null,
+ timeBetweenEvictionRunsMillis: null,
+ numTestsPerEvictionRun: null,
+ minIdle: null,
+ minEvictableIdleTimeMillis: null,
+ maxEvictableIdleTimeMillis: null,
+ keepAliveBetweenTimeMillis: null,
+ fetchSize: null,
+ // 并行装载
+ parallelLoad: {
+ serverAddress: '',
+ isReuseTemporaryTable: 0,
+ filePiecesLimit: null,
+ fileSizeLimit: null,
+ },
+ // HDFS
+ hdfs: {
+ hdfsAddress: null,
+ }
+ };
+
+ render() {
+ const { connectionName, connectionData } = this.options.formData;
+ const {
+ driver,
+ driverSource,
+ user,
+ password,
+ originalCharsetName,
+ schema,
+ url,
+ connectionPoolAttr,
+ database,
+ authType,
+ principal,
+ keyPath,
+ krb5Path,
+ fetchSize,
+ // ssh
+ usingSsh = false,
+ sshIp, // sshIp默认值在表单那用||设置,因为在这可能是空字符串,解构默认值没用
+ sshPort = 22,
+ sshUser = '',
+ sshType = CONNECT_SSH_TYPE[0].value,
+ sshPrivateKeyPath = '',
+ sshSecret = '',
+ // ssl
+ usingSsl = false,
+ caCertificate = '',
+ verifyCa = false,
+ sslClientPrivateKey = '',
+ sslClientCertificate = '',
+ // 并行装载
+ parallelLoad,
+ // HDFS
+ hdfs,
+ } = connectionData as ConnectionJDBC;
+ this.oldPassword = password;
+ this.oldSshSecret = sshSecret;
+ !BI.isUndefined(principal) && this.initPrincipals(keyPath, principal);
+
+ const {
+ initialSize,
+ maxActive,
+ maxWait,
+ validationQuery,
+ testOnBorrow,
+ keepAlive,
+ testOnReturn,
+ testWhileIdle,
+ timeBetweenEvictionRunsMillis,
+ numTestsPerEvictionRun,
+ minIdle,
+ minEvictableIdleTimeMillis,
+ maxEvictableIdleTimeMillis,
+ keepAliveBetweenTimeMillis,
+ } = connectionPoolAttr as ConnectionPoolJDBC;
+ const databaseType = getJdbcDatabaseType(database, driver);
+ this.databaseType = databaseType;
+ const { host, port, catalog, databaseName, version } = resolveUrlInfo(url, database);
+ this.version = !BI.isUndefined(databaseType.versions) ? (version ?? databaseType.versions[0]) : version;
+ const { hgap, vgap } = CONNECTION_LAYOUT;
+
+ const valueRangeConfig = {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Value_Out_Range'),
+ checker: (value: string) => this.checkValueRange(value),
+ autoFix: true,
+ };
+
+ return {
+ type: BI.VerticalLayout.xtype,
+ hgap,
+ vgap,
+ items: [
+ // 数据连接名称
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Name'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'connection-name',
+ width: EDITOR_WIDTH,
+ value: connectionName,
+ allowBlank: true,
+ ref: (_ref: TextChecker) => {
+ this.form.connectionName = _ref;
+ },
+ watermark: BI.i18nText('Dec-Dcm_Data_Connections'),
+ },
+ ],
+ },
+ // 版本
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Basic_Version'),
+ invisible: BI.isUndefined(databaseType.versions),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ width: EDITOR_WIDTH,
+ value: this.version,
+ items: () => databaseType.versions.map(item => {
+ return {
+ text: BI.i18nText('Dec-Migration_Database_Version', item),
+ value: item,
+ }
+ }),
+ ref: (_ref: TextValueCombo) => {
+ this.form.version = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.TextValueCombo.EVENT_CHANGE,
+ action: () => {
+ const version = this.form.version.getValue()[0];
+ this.version = version;
+ this.sslCollapse.setCollapse(true);
+ this.sslCollapse.setVisible(this.getSslSetEnabled());
+ !BI.isUndefined(databaseType.hasSchemas) && this.schemaForm.setVisible(databaseType.hasSchemas[version]);
+ !BI.isUndefined(databaseType.versionConfig?.[version]?.fetchSize) && this.form.fetchSize.setValue(databaseType.versionConfig[version].fetchSize);
+ this.form.driver.setDefaultDrivers(version);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 驱动
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Driver'),
+ forms: [
+ {
+ type: DriverSelector.xtype,
+ ref: (_ref: DriverSelector) => {
+ this.form.driver = _ref;
+ },
+ driver,
+ driverSource,
+ connectionData,
+ version: this.version,
+ 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);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // catalog
+ {
+ type: FormItem.xtype,
+ name: 'catalog',
+ invisible: database !== 'starrocks',
+ forms: [
+ {
+ type: BI.TextEditor.xtype,
+ $value: 'database-catalog',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ watermark: 'catalog',
+ value: catalog,
+ ref: (_ref: any) => {
+ this.form.catalog = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.onHostPortChange(databaseType);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 数据库名称
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
+ forms: [
+ {
+ type: BI.TextEditor.xtype,
+ $value: 'database-name',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Name'),
+ value: databaseName,
+ ref: (_ref: any) => {
+ this.form.database = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.onHostPortChange(databaseType);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 主机
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ forms: [
+ {
+ type: BI.TextEditor.xtype,
+ $value: 'database-host',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: host,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ ref: (_ref: any) => {
+ this.form.host = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.onHostPortChange(databaseType);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 端口
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'database-port',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: port,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.port = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.onHostPortChange(databaseType);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 认证方式
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_AuthType'),
+ invisible: !databaseType.kerberos,
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'auth-type',
+ width: EDITOR_WIDTH,
+ value: authType,
+ ref: (_ref: TextValueCombo) => {
+ this.form.authType = _ref;
+ },
+ items: [
+ {
+ text: BI.i18nText('Dec-Dcm_Connection_Form_UserName_Password'),
+ value: '',
+ },
+ {
+ text: 'Kerberos',
+ value: 'kerberos',
+ },
+ ],
+ listeners: [
+ {
+ eventName: BI.Combo.EVENT_CHANGE,
+ action: () => {
+ const type = this.form.authType.getValue()[0];
+ this.formPrincipal.setVisible(!!type);
+ this.formKeyPath.setVisible(!!type);
+ this.formKrb5File.setVisible(!!type);
+ this.form.krb5Path.setEnable(!type);
+ this.formUser.setVisible(!type);
+ this.formPassword.setVisible(!type);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 用户名
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ invisible: !!authType,
+ ref: (_ref: FormItem) => {
+ this.formUser = _ref;
+ },
+ forms: [
+ {
+ type: BI.TextEditor.xtype,
+ $value: 'username',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: user,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ ref: (_ref: TextEditor) => {
+ this.form.user = _ref;
+ },
+ },
+ ],
+ },
+ // 密码
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ invisible: !!authType,
+ ref: (_ref: FormItem) => {
+ this.formPassword = _ref;
+ },
+ forms: [
+ {
+ type: BI.Editor.xtype,
+ $value: 'password',
+ cls: 'bi-border-bottom',
+ width: EDITOR_WIDTH,
+ height: EDITOR_HEIGHT,
+ allowBlank: true,
+ value: password,
+ inputType: 'password',
+ autocomplete: 'new-password',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Password'),
+ ref: (_ref: Editor) => {
+ this.form.password = _ref;
+ },
+ },
+ ],
+ },
+ // keytab密钥路径
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_KeyPath'),
+ invisible: !authType,
+ ref: (_ref: FormItem) => {
+ this.formKeyPath = _ref;
+ },
+ forms: [
+ {
+ type: FileUpload.xtype,
+ $value: 'key-path',
+ processId: "keytab",
+ allowBlank: true,
+ value: keyPath,
+ accept: '.keytab',
+ inter: '/v10/config/connection/upload/keytab?',
+ iconCls: "data-keytab-file",
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_KeyPath'),
+ ref: (_ref: FileUpload) => {
+ this.form.keyPath = _ref;
+ },
+ listeners: [
+ {
+ eventName: FileUpload.EVENT_CHECK_SUCCESS,
+ action: (value) => {
+ const principalsItems = BI.map(value.principals, function (index, item) {
+ return {
+ text: item,
+ value: item
+ }
+ })
+ this.form.principal.populate(principalsItems);
+ this.form.principal.setValue(principalsItems[0].value);
+ this.setKerberos();
+ this.form.krb5Path.setEnable(true);
+ },
+ }, {
+ eventName: FileUpload.EVENT_CLEAR_FILE,
+ action: () => {
+ this.form.krb5Path.setEnable(false);
+ this.form.principal.populate();
+ this.form.principal.setValue();
+ }
+ }
+ ]
+ },
+ ],
+ },
+ // 客户端principal
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Principal'),
+ invisible: !authType,
+ ref: (_ref: FormItem) => {
+ this.formPrincipal = _ref;
+ },
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'principal',
+ width: EDITOR_WIDTH,
+ value: principal,
+ ref: (_ref: TextEditor) => {
+ this.form.principal = _ref;
+ },
+ listeners: [
+ {
+ eventName: BI.Combo.EVENT_CHANGE,
+ action: () => {
+ this.changePrincipal();
+ this.setKerberos();
+ },
+ },
+ ],
+ }
+ ],
+ },
+ // krb5.conf文件
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Krb5File'),
+ invisible: !authType,
+ ref: (_ref: FormItem) => {
+ this.formKrb5File = _ref;
+ },
+ forms: [
+ {
+ type: FileUpload.xtype,
+ $value: 'krb5-file',
+ processId: "krb5Conf",
+ allowBlank: true,
+ value: krb5Path,
+ iconCls: "data-conf-file",
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Krb5File'),
+ ref: (_ref: FileUpload) => {
+ this.form.krb5Path = _ref;
+ },
+ inter: '/v10/config/connection/upload/krb5?',
+ accept: '.conf',
+ listeners: [
+ {
+ eventName: FileUpload.EVENT_CHECK_SUCCESS,
+ action: () => {
+ this.setKerberos();
+ },
+ }
+ ]
+ }
+ ]
+ },
+ // 编码
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_OriginalCharsetName'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'original-charset-name',
+ width: EDITOR_WIDTH,
+ value: originalCharsetName ? originalCharsetName : '',
+ items: CONNECT_CHARSET,
+ ref: (_ref: TextValueCombo) => {
+ this.form.originalCharsetName = _ref;
+ },
+ },
+ ],
+ },
+ // 模式
+ {
+ type: FormItem.xtype,
+ invisible: BI.isUndefined(databaseType.hasSchemas) ? !databaseType.hasSchema : !databaseType.hasSchemas[this.version],
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Pattern'),
+ forms: [
+ {
+ type: BI.VerticalLayout.xtype,
+ height: 55,
+ items: [
+ {
+ type: BI.FloatLeftLayout.xtype,
+ items: [
+ {
+ type: BI.TextButton.xtype,
+ cls: 'bi-high-light',
+ text: BI.i18nText('Dec-Dcm_Connection_Click_Connect_Database'),
+ handler: () => {
+ this.fireEvent('EVENT_TEST_CONNECTION');
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ cls: 'bi-tips',
+ lgap: 3,
+ text: BI.i18nText('Dec-Dcm_Connection_Read_Mode_List'),
+ },
+ ],
+ },
+ {
+ type: BI.TextValueCombo.xtype,
+ _tgap: 15,
+ $value: 'schema',
+ width: EDITOR_WIDTH,
+ disabled: true,
+ value: schema,
+ items: schema ? [{ text: schema, value: schema }] : [],
+ ref: (_ref: TextValueCombo) => {
+ this.form.schema = _ref;
+ },
+ },
+ ],
+ },
+ ],
+ ref: (_ref: FormItem) => {
+ this.schemaForm = _ref;
+ },
+ },
+ // 并行装载设置
+ {
+ type: Collapse.xtype,
+ invisible: BI.isNull(parallelLoad),
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', BI.i18nText('Dec-Dcm_Connection_Parallel_Load')),
+ el: {
+ type: TipsCombo.xtype,
+ _lgap: 6,
+ el: {
+ type: BI.CenterAdaptLayout.xtype,
+ innerHgap: 15,
+ innerVgap: 10,
+ items: [
+ {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-Dcm_Connection_Setting_Tips', BI.i18nText('Dec-Dcm_Connection_Parallel_Load')),
+ },
+ /**
+ * FIXME: 帮助链接待提供
+ */
+ {
+ type: BI.A.xtype,
+ href: '',
+ el: {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-BI_Help_Paper'),
+ }
+ }
+ ]
+ }
+ },
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.parallelLoadSet.setVisible(!isCollapse);
+ }
+ }
+ ]
+ },
+ {
+ type: BI.VerticalLayout.xtype,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.parallelLoadSet = _ref;
+ },
+ items: [
+ {
+ // 服务器地址-节点1
+ type: FormItem.xtype,
+ name: `${BI.i18nText('Dec-Dcm_Connection_Server_Address')}-${BI.i18nText('Dec-Memory_Detection_Server_Cluster_Node', '1')}`,
+ _bgap: vgap,
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'server-cluster-node',
+ width: EDITOR_WIDTH,
+ value: parallelLoad?.serverAddress ?? '',
+ items: parallelLoad?.serverAddressItems || [],
+ listeners: [
+ {
+ eventName: BI.TextValueCombo.EVENT_CHANGE,
+ action: (value: string) => {
+ this.form.parallelLoad.serverAddress = value;
+ }
+ }
+ ]
+ },
+ ],
+ },
+ {
+ // 复用临时表
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Reuse_Temporary_Table'),
+ _bgap: vgap,
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'reuse-temporary-table',
+ width: EDITOR_WIDTH,
+ value: parallelLoad?.reuseTemporaryTable ?? 0,
+ items: YES_OR_NO,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Reuse_Temporary_Table'),
+ listeners: [
+ {
+ eventName: BI.TextValueCombo.EVENT_CHANGE,
+ action: (value: number) => {
+ this.form.parallelLoad.isReuseTemporaryTable = value;
+ }
+ }
+ ]
+ },
+ ],
+ },
+ {
+ // 临时文件条数限制
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Pieces_Limit'),
+ _bgap: vgap,
+ forms: [
+ {
+ type: BI.Editor.xtype,
+ $value: 'temporary-file-pieces-limit',
+ cls: 'bi-border-bottom',
+ width: EDITOR_WIDTH,
+ height: EDITOR_HEIGHT,
+ allowBlank: true,
+ value: parallelLoad?.filePiecesLimit ?? '',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Pieces_Limit'),
+ ref: (_ref: Editor) => {
+ this.form.parallelLoad.filePiecesLimit = _ref;
+ },
+ },
+ ],
+ },
+ {
+ // 临时文件大小限制(MB)
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Size_Limit'),
+ forms: [
+ {
+ type: BI.Editor.xtype,
+ $value: 'temporary-file-size-limit',
+ cls: 'bi-border-bottom',
+ width: EDITOR_WIDTH,
+ height: EDITOR_HEIGHT,
+ allowBlank: true,
+ value: parallelLoad?.fileSizeLimit ?? '',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Temporary_File_Size_Limit'),
+ ref: (_ref: Editor) => {
+ this.form.parallelLoad.fileSizeLimit = _ref;
+ },
+ },
+ ],
+ },
+ ]
+ },
+ // HDFS设置
+ {
+ type: Collapse.xtype,
+ invisible: BI.isNull(hdfs),
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', 'HDFS'),
+ el: {
+ type: TipsCombo.xtype,
+ _lgap: 6,
+ el: {
+ type: BI.CenterAdaptLayout.xtype,
+ innerHgap: 15,
+ innerVgap: 10,
+ items: [
+ {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-Dcm_Connection_Setting_Tips', 'HDFS'),
+ },
+ {
+ type: BI.A.xtype,
+ href: '',
+ el: {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-BI_Help_Paper'),
+ }
+ }
+ ]
+ }
+ },
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.hdfsSet.setVisible(!isCollapse);
+ }
+ }
+ ]
+ },
+ {
+ type: BI.VerticalLayout.xtype,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.hdfsSet = _ref;
+ },
+ items: [
+ {
+ // HDFS地址
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Address', 'HDFS'),
+ forms: [
+ {
+ type: BI.Editor.xtype,
+ $value: 'hdfs-connection-address',
+ cls: 'bi-border-bottom',
+ width: EDITOR_WIDTH,
+ height: EDITOR_HEIGHT,
+ allowBlank: true,
+ value: hdfs?.hdfsAddress ?? '',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Address', 'HDFS'),
+ ref: (_ref: Editor) => {
+ this.form.hdfs.hdfsAddress = _ref;
+ },
+ },
+ ],
+ }
+ ]
+ },
+ // 分隔线
+ {
+ type: BI.Layout.xtype,
+ cls: 'bi-border-top',
+ bgap: 8,
+ },
+ // 数据连接URL
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
+ forms: [
+ {
+ type: BI.TextEditor.xtype,
+ $value: 'database-url',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: url,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_URL'),
+ ref: (_ref: TextEditor) => {
+ this.form.url = _ref;
+ },
+ listeners: [
+ {
+ eventName: 'EVENT_CHANGE',
+ action: () => {
+ const urlInfo = resolveUrlInfo(this.form.url.getValue(), database);
+ this.form.host.setValue(urlInfo.host);
+ this.form.catalog.setValue(urlInfo.catalog);
+ this.form.database.setValue(urlInfo.databaseName);
+ this.form.port.setValue(urlInfo.port);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 最大活动连接数
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'max-active',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: maxActive,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Active'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.maxActive = _ref;
+ },
+ },
+ ],
+ },
+ // 获取连接前检验
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'check',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: testOnBorrow,
+ items: this.getBooleanItem(),
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Borrow'),
+ ref: (_ref: TextValueCombo) => {
+ this.form.testOnBorrow = _ref;
+ },
+ },
+ ],
+ },
+ // 空闲连接可用性定期检查
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'keep-alive-check',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: keepAlive,
+ items: this.getBooleanItem(),
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow'),
+ ref: (_ref: TextValueCombo) => {
+ this.form.keepAlive = _ref;
+ },
+ },
+ ],
+ },
+ // 校验语句
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_SQL_Validation_Query'),
+ forms: [
+ {
+ type: BI.TextAreaEditor.xtype,
+ $value: 'validation-query',
+ cls: 'bi-border',
+ allowBlank: true,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_SQL_Validation_Query_Watermark'),
+ value: api.getPlain(validationQuery || ''),
+ width: EDITOR_WIDTH,
+ height: 100,
+ ref: (_ref: TextAreaEditor) => {
+ this.form.validationQuery = _ref;
+ },
+ },
+ ],
+ },
+ // 最大等待时间
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'max-wait',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: maxWait,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Wait'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.maxWait = _ref;
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ lgap: 5,
+ height: CONNECTION_LAYOUT.labelHeight,
+ text: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ ],
+ },
+ // SSH设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', 'SSH'),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.sshSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ ref: (_ref: VerticalLayout) => {
+ this.sshSet = _ref;
+ },
+ bgap: vgap,
+ invisible: true,
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Tunnel', 'SSH'),
+ forms: [
+ {
+ type: BI.MultiSelectItem.xtype,
+ ref: (_ref: MultiSelectItem) => {
+ this.form.usingSsh = _ref;
+ },
+ logic: { dynamic: true },
+ text: BI.i18nText('Dec-Basic_Use') + BI.i18nText('Dec-Dcm_Connection_Tunnel', 'SSH'),
+ selected: usingSsh,
+ listeners: [
+ {
+ eventName: BI.MultiSelectItem.EVENT_CHANGE,
+ action: () => {
+ const value = this.form.usingSsh.isSelected();
+ this.sshForm.setVisible(value);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ ref: (_ref: VerticalLayout) => {
+ this.sshForm = _ref;
+ },
+ bgap: vgap,
+ invisible: !usingSsh,
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ ref: (_ref: TextChecker) => {
+ this.form.sshIp = _ref;
+ },
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Host'),
+ value: sshIp,
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.form.sshSecret.setValue("");
+ }
+ }
+ ]
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ ref: (_ref: TextChecker) => {
+ this.form.sshPort = _ref;
+ },
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Port'),
+ allowBlank: false,
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ value: String(sshPort || 22),
+ listeners: [
+ {
+ eventName: BI.Editor.EVENT_CHANGE,
+ action: () => {
+ this.form.sshSecret.setValue("");
+ }
+ }
+ ]
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ ref: (_ref: TextChecker) => {
+ this.form.sshUser = _ref;
+ },
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_UserName'),
+ value: sshUser,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_VerifyType'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ ref: (_ref: TextValueCombo) => {
+ this.form.sshType = _ref;
+ },
+ width: EDITOR_WIDTH,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_VerifyType'),
+ items: CONNECT_SSH_TYPE,
+ value: sshType,
+ listeners: [
+ {
+ eventName: BI.TextValueCombo.EVENT_CHANGE,
+ action: () => {
+ const sshType = this.form.sshType.getValue()[0];
+ this.onSshTypeChange(sshType);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ ref: (_ref: FormItem) => {
+ this.form.sshPrivateKeyPathForm = _ref;
+ },
+ name: BI.i18nText('Dec-Dcm_Connection_Form_PrivateKey'),
+ forms: [
+ {
+ type: FileChooser.xtype,
+ ref: (_ref: TextChecker) => {
+ this.form.sshPrivateKeyPath = _ref;
+ },
+ root: 'certificates',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_PrivateKey'),
+ value: sshPrivateKeyPath,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ ref: (ref: FormItem) => {
+ this.form.sshSecretForm = ref;
+ },
+ name: BI.i18nText(''),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ ref: (_ref: TextChecker) => {
+ this.form.sshSecret = _ref;
+ },
+ watermark: BI.i18nText(''),
+ inputType: 'password',
+ autocomplete: 'new-password',
+ value: sshSecret,
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ // SSL设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ name: BI.i18nText('Dec-Dcm_Connection_Setting', 'SSL'),
+ invisible: !this.getSslSetEnabled(),
+ ref: (_ref: Collapse) => {
+ this.sslCollapse = _ref;
+ },
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.sslSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ ref: (_ref: VerticalLayout) => {
+ this.sslSet = _ref;
+ },
+ bgap: vgap,
+ invisible: true,
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Tunnel', 'SSL'),
+ forms: [
+ {
+ type: BI.MultiSelectItem.xtype,
+ ref: (_ref: MultiSelectItem) => {
+ this.form.usingSsl = _ref;
+ },
+ logic: { dynamic: true },
+ text: BI.i18nText('Dec-Basic_Use') + BI.i18nText('Dec-Dcm_Connection_Tunnel', 'SSL'),
+ selected: usingSsl,
+ listeners: [
+ {
+ eventName: BI.MultiSelectItem.EVENT_CHANGE,
+ action: () => {
+ const value = this.form.usingSsl.isSelected();
+ this.sslForm.setVisible(value);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ ref: (_ref: VerticalLayout) => {
+ this.sslForm = _ref;
+ },
+ bgap: vgap,
+ invisible: !usingSsl,
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_CA_Certificate'),
+ forms: [
+ {
+ type: FileChooser.xtype,
+ ref: (_ref: FileChooser) => {
+ this.form.caCertificate = _ref;
+ },
+ root: 'certificates',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_CA_Certificate'),
+ value: caCertificate,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Verify_CA_Certificate'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ ref: (_ref: TextValueCombo) => {
+ this.form.verifyCa = _ref;
+ },
+ width: EDITOR_WIDTH,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Verify_CA_Certificate'),
+ items: this.getBooleanItem(),
+ value: verifyCa,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_SecretKey'),
+ forms: [
+ {
+ type: FileChooser.xtype,
+ ref: (_ref: FileChooser) => {
+ this.form.sslClientPrivateKey = _ref;
+ },
+ root: 'certificates',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_SecretKey'),
+ value: sslClientPrivateKey,
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_Certificate'),
+ forms: [
+ {
+ type: FileChooser.xtype,
+ ref: (_ref: FileChooser) => {
+ this.form.sslClientCertificate = _ref;
+ },
+ root: 'certificates',
+ watermark: BI.i18nText('Dec-Dcm_Connection_Client') + BI.i18nText('Dec-Dcm_Connection_Form_Certificate'),
+ value: sslClientCertificate,
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ // 高级设置
+ {
+ type: Collapse.xtype,
+ width: 100,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_More_Setting'),
+ listeners: [
+ {
+ eventName: EVENT_CHANGE,
+ action: (isCollapse: boolean) => {
+ this.advancedSet.setVisible(!isCollapse);
+ },
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ vgap: vgap,
+ top: -15,
+ invisible: true,
+ ref: (_ref: VerticalLayout) => {
+ this.advancedSet = _ref;
+ },
+ items: [
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'initial-size',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: initialSize,
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Initial_Size'),
+ ref: (_ref: TextChecker) => {
+ this.form.initialSize = _ref;
+ },
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'min-idle',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: minIdle,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Idle'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.minIdle = _ref;
+ },
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'test-on-return',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: testOnReturn,
+ items: this.getBooleanItem(),
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_On_Return'),
+ ref: (_ref: TextValueCombo) => {
+ this.form.testOnReturn = _ref;
+ },
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
+ forms: [
+ {
+ type: BI.TextValueCombo.xtype,
+ $value: 'test-while-idle',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: testWhileIdle,
+ items: this.getBooleanItem(),
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_While_Idle'),
+ ref: (_ref: TextValueCombo) => {
+ this.form.testWhileIdle = _ref;
+ },
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'test-between-evicition-millis',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: timeBetweenEvictionRunsMillis,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Number'),
+ checker: (value: string) => this.checkNumber(value),
+ autoFix: true,
+ },
+ {
+ errorText: BI.i18nText('Dec-Util-Must_Less_Than', BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis'), BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow_Threshold')),
+ checker: (value: string) => this.checkNumber(value) && (parseInt(value) < parseInt(this.form.keepAliveBetweenTimeMillis.getValue())),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.timeBetweenEvictionRunsMillis = _ref;
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ lgap: 5,
+ height: CONNECTION_LAYOUT.labelHeight,
+ text: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'test-pereviction-run-num',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: numTestsPerEvictionRun,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Tests_PerEviction_Run_Num'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.numTestsPerEvictionRun = _ref;
+ },
+ },
+ ],
+ },
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'min-evictable-idle-time-millis',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: minEvictableIdleTimeMillis,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 30),
+ checker: (value: string) => this.checkNumber(value) && (parseInt(value) >= 30),
+ autoFix: true,
+ },
+ {
+ errorText: BI.i18nText('Dec-Util-Must_Less_Than', BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis'), BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Evictable_Idle_Time_Millis')),
+ checker: (value: string) => parseInt(value) < parseInt(this.form.maxEvictableIdleTimeMillis.getValue()),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.minEvictableIdleTimeMillis = _ref;
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ lgap: 5,
+ height: CONNECTION_LAYOUT.labelHeight,
+ text: BI.i18nText('BI-Basic_Seconds'),
+ },
+ ],
+ },
+
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Evictable_Idle_Time_Millis'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'max-evictable-idle-time-millis',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: maxEvictableIdleTimeMillis,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Evictable_Idle_Time_Millis'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 0),
+ checker: (value: string) => this.checkInteger(value),
+ autoFix: true,
+ },
+ {
+ errorText: BI.i18nText('Dec-Util-Must_More_Than', BI.i18nText('Dec-Dcm_Connection_Form_Database_Max_Evictable_Idle_Time_Millis'), BI.i18nText('Dec-Dcm_Connection_Form_Database_Min_Evictable_Idle_Time_Millis')),
+ checker: (value: string) => parseInt(value) > parseInt(this.form.minEvictableIdleTimeMillis.getValue()),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.maxEvictableIdleTimeMillis = _ref;
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ lgap: 5,
+ height: CONNECTION_LAYOUT.labelHeight,
+ text: BI.i18nText('BI-Basic_Seconds'),
+ },
+ ],
+ },
+
+ {
+ type: FormItem.xtype,
+ name: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow_Threshold'),
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'keep-live-between-time-millis',
+ width: EDITOR_WIDTH,
+ allowBlank: false,
+ value: keepAliveBetweenTimeMillis,
+ watermark: BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow_Threshold'),
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Integer', 30000),
+ checker: (value: string) => this.checkNumber(value) && (parseInt(value) > 30000),
+ autoFix: true,
+ },
+ {
+ errorText: BI.i18nText('Dec-Util-Must_More_Than', BI.i18nText('Dec-Dcm_Connection_Form_Database_Regular_Check_On_Borrow_Threshold'), BI.i18nText('Dec-Dcm_Connection_Form_Database_Test_Between_Eviction_Millis')),
+ checker: (value: string) => this.checkNumber(value) && (parseInt(value) > parseInt(this.form.timeBetweenEvictionRunsMillis.getValue())),
+ autoFix: true,
+ },
+ valueRangeConfig,
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.keepAliveBetweenTimeMillis = _ref;
+ },
+ },
+ {
+ type: BI.Label.xtype,
+ lgap: 5,
+ height: CONNECTION_LAYOUT.labelHeight,
+ text: BI.i18nText('Dec-Dcm_Millisecond'),
+ },
+ ],
+ },
+ {
+ el: {
+ type: BI.VerticalLayout.xtype,
+ cls: 'bi-border-top',
+ items: [
+ {
+ el: {
+ type: FormItem.xtype,
+ name: 'Fetchsize',
+ forms: [
+ {
+ type: TextChecker.xtype,
+ $value: 'fetch-size',
+ width: EDITOR_WIDTH,
+ allowBlank: true,
+ value: fetchSize,
+ watermark: 'Fetchsize',
+ validationChecker: [
+ {
+ errorText: BI.i18nText('Dec-Dcm_Connection_Check_Fetch_Size_Range'),
+ checker: (value: string) =>
+ BI.isInteger(value) && BI.parseInt(value) >= 0 && BI.parseInt(value) <= 1000000,
+ autoFix: true,
+ },
+ ],
+ ref: (_ref: TextChecker) => {
+ this.form.fetchSize = _ref;
+ },
+ },
+ ],
+ },
+ vgap: 15,
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ };
+ }
+
+ public mounted() {
+ const sshType = this.form.sshType.getValue()[0];
+ this.onSshTypeChange(sshType);
+ this.setKerberos();
+ }
+
+ public setError(value: string) {
+ this.form.connectionName.setError(value);
+ }
+
+ private checkInteger(value: string) {
+ return /^[\d]+$/.test(value);
+ }
+
+ private checkNumber(value: string) {
+ return /^[(\-|\+)?\d]+$/.test(value);
+ }
+
+ private checkValueRange(value: string) {
+ return parseInt(value, 0) <= INT_MAX_VALUE && parseInt(value, 0) >= INT_MIN_VALUE;
+ }
+
+ private getDrivers() {
+ const connectionData = this.options.formData.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;
+ }
+
+ private getBooleanItem() {
+ return [
+ {
+ text: BI.i18nText('Dec-Dcm_Yes'),
+ value: true,
+ },
+ {
+ text: BI.i18nText('Dec-Dcm_No'),
+ value: false,
+ },
+ ];
+ }
+
+ private onHostPortChange(database) {
+ const { urls, url, databaseType } = database;
+ const driver = this.form.driver.getValue();
+ const selectUrl = BI.get(urls, driver.driver) || url;
+ const host = this.form.host.getValue();
+ const port = this.form.port.getValue();
+ const catalog = this.form.catalog.getValue();
+ const databaseName = this.form.database.getValue();
+ this.form.url.setValue(splitUrl(host, port, catalog, databaseName, selectUrl, databaseType));
+ }
+
+ private onSshTypeChange(sshType) {
+ const { privateKeyPathFormVisible, secretFormName } = CONNECT_SSH_TYPE.find((SSH_TYPE) => sshType === SSH_TYPE.value);
+ this.form.sshPrivateKeyPathForm.setVisible(privateKeyPathFormVisible);
+ this.form.sshSecretForm.setName(secretFormName);
+ this.form.sshSecret.setWatermark(secretFormName);
+ }
+
+ private getSslSetEnabled(): boolean {
+ const { databaseType } = this.databaseType;
+ return databaseType === 'mysql' || this.version === 'mysql';
+ }
+
+ public setSchemas(schemas: string[]) {
+ this.form.schema.setEnable(true);
+ if (schemas.length > 0) {
+ const value = this.form.schema.getValue()[0];
+ this.form.schema.populate(
+ schemas.map((item) => {
+ return {
+ text: item,
+ value: item,
+ };
+ })
+ );
+ this.form.schema.setValue(value && schemas.some((item) => item === value) ? value : schemas[0]);
+ }
+ }
+
+ public setKerberos() {
+ const KerberosParams = BI.extend({}, {
+ keytabPath: this.form.keyPath.getValue(),
+ krb5ConfPath: this.form.krb5Path.getValue(),
+ principal: this.form.principal.getValue()[0]
+ });
+ this.form.krb5Path.setFileInfo(KerberosParams);
+ this.form.keyPath.setFileInfo(KerberosParams);
+ }
+
+ public initPrincipals(keyPath, principal) {
+ let self = this;
+ api.getPrincipals(keyPath).then(res => {
+ const principalsItems = BI.map(res.data, function (index, item) {
+ return {
+ text: item,
+ value: item
+ }
+ });
+ self.form.principal.populate(principalsItems);
+ self.form.principal.setValue(principal);
+ })
+ }
+
+ public changePrincipal() {
+ let self = this;
+ const KerberosParams = BI.extend({}, {
+ keytabPath: this.form.keyPath.getValue(),
+ krb5ConfPath: this.form.krb5Path.getValue(),
+ principal: this.form.principal.getValue()[0]
+ });
+ api.changePrincipal(KerberosParams).then(res => {
+ self.form.keyPath.setValue(res.data.keytabPath);
+ self.form.krb5Path.setValue(res.data.krb5ConfPath);
+ });
+
+ }
+
+ public validation(): boolean {
+ const driver = this.form.driver.validation();
+ const sshSet = !this.form.usingSsh.isSelected() || BI.isNotEmptyString(this.form.sshPort.getValue());
+
+ return driver && sshSet;
+ }
+
+ public getSubmitValue(): Connection {
+ const connectionData = this.options.formData.connectionData as ConnectionJDBC;
+ const connectionPoolAttr = connectionData.connectionPoolAttr;
+ const originalCharsetName = this.form.originalCharsetName.getValue()[0] || '';
+ // TODO 获取表单数据这里待优化
+ const { parallelLoad, hdfs } = this.form;
+
+ return {
+ connectionType: connectionType.JDBC,
+ connectionId: this.form.connectionName.getValue(),
+ connectionName: this.form.connectionName.getValue(),
+ connectionData: BI.extend({}, connectionData, {
+ database: connectionData.database,
+ connectionName: this.form.connectionName.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()),
+ queryType: '',
+ newCharsetName: originalCharsetName ? 'gbk' : '', // 后台要求,originalCharsetName不为空时,newCharsetName为gbk
+ originalCharsetName,
+ schema: this.form.schema.getValue()[0],
+ host: this.form.host.getValue(),
+ authType: this.form.authType.getValue()[0] || '',
+ creator: Dec ? Dec.personal.username : '',
+ principal: this.form.principal.getValue()[0],
+ keyPath: this.form.keyPath.getValue(),
+ krb5Path: this.form.krb5Path.getValue(),
+ fetchSize: BI.isEmptyString(this.form.fetchSize.getValue()) ? -1 : BI.parseInt(this.form.fetchSize.getValue()),
+ // ssh
+ usingSsh: this.form.usingSsh.isSelected(),
+ // redirectPort: 0,
+ // redirectIp: '',
+ // sshKeepAlive: 10000,
+ // sshTimeOut: 10000,
+ sshIp: this.form.sshIp.getValue(),
+ sshPort: Number(this.form.sshPort.getValue()),
+ sshUser: this.form.sshUser.getValue(),
+ sshType: this.form.sshType.getValue()[0],
+ sshPrivateKeyPath: this.form.sshPrivateKeyPath.getValue(),
+ sshSecret: this.oldSshSecret === this.form.sshSecret.getValue() ? this.oldSshSecret : api.getCipher(this.form.sshSecret.getValue()),
+ // ssl
+ usingSsl: this.getSslSetEnabled() && this.form.usingSsl.isSelected(),
+ caCertificate: this.form.caCertificate.getValue(),
+ verifyCa: this.form.verifyCa.getValue()[0],
+ sslType: CONNECT_SSL_TYPE[0].value,
+ sslClientPrivateKey: this.form.sslClientPrivateKey.getValue(),
+ sslClientCertificate: this.form.sslClientCertificate.getValue(),
+ // 连接池
+ connectionPoolAttr: {
+ initialSize: this.form.initialSize.getValue(),
+ maxActive: this.form.maxActive.getValue(),
+ minIdle: this.form.minIdle.getValue(),
+ maxWait: this.form.maxWait.getValue(),
+ validationQuery: api.getCipher(this.form.validationQuery.getValue()),
+ testOnBorrow: BI.size(this.form.testOnBorrow.getValue()) > 0 ? this.form.testOnBorrow.getValue()[0] : connectionPoolAttr.testOnBorrow,
+ keepAlive: BI.size(this.form.keepAlive.getValue()) > 0 ? this.form.keepAlive.getValue()[0] : connectionPoolAttr.keepAlive,
+ testOnReturn: BI.size(this.form.testOnReturn.getValue()) > 0 ? this.form.testOnReturn.getValue()[0] : connectionPoolAttr.testOnReturn,
+ testWhileIdle: BI.size(this.form.testWhileIdle.getValue()) > 0 ? this.form.testWhileIdle.getValue()[0] : connectionPoolAttr.testWhileIdle,
+ timeBetweenEvictionRunsMillis: this.form.timeBetweenEvictionRunsMillis.getValue(),
+ numTestsPerEvictionRun: this.form.numTestsPerEvictionRun.getValue(),
+ minEvictableIdleTimeMillis: this.form.minEvictableIdleTimeMillis.getValue(),
+ maxEvictableIdleTimeMillis: this.form.maxEvictableIdleTimeMillis.getValue(),
+ keepAliveBetweenTimeMillis: this.form.keepAliveBetweenTimeMillis.getValue(),
+ },
+ // 并行装载
+ parallelLoad: {
+ serverAddress: parallelLoad.serverAddress,
+ isReuseTemporaryTable: parallelLoad.isReuseTemporaryTable,
+ filePiecesLimit: parallelLoad.filePiecesLimit.getValue(),
+ fileSizeLimit: parallelLoad.fileSizeLimit.getValue(),
+ },
+ hdfs: {
+ hdfsAddress: hdfs.hdfsAddress.getValue(),
+ }
+ // HDFS
+ }),
+ };
+ }
+}
diff --git a/src/modules/pages/maintain/forms/components/form.plugin.ts b/src/modules/pages/maintain/forms/components/form.plugin.ts
index 6282203..881089a 100644
--- a/src/modules/pages/maintain/forms/components/form.plugin.ts
+++ b/src/modules/pages/maintain/forms/components/form.plugin.ts
@@ -37,4 +37,8 @@ export class FormPlugin extends BI.Widget {
connectionData: BI.extend({}, connectionData, this.plugin.getValue()),
};
}
+
+ public getSaveFn() {
+ return this.plugin.save;
+ }
}
diff --git a/src/modules/pages/maintain/forms/form.model.ts b/src/modules/pages/maintain/forms/form.model.ts
index 3bbc66e..7947b15 100644
--- a/src/modules/pages/maintain/forms/form.model.ts
+++ b/src/modules/pages/maintain/forms/form.model.ts
@@ -17,6 +17,7 @@ export class MaintainFormModel extends Model<{
pageIndex: AppModel['TYPE']['pageIndex'];
connections: AppModel['TYPE']['connections'];
isCopy: AppModel['TYPE']['isCopy'];
+ connectionSelected: AppModel['TYPE']['connectionSelected'];
},
context: MaintainFormModel['context'];
}> {
@@ -31,6 +32,7 @@ export class MaintainFormModel extends Model<{
'testEvent',
'connections',
'isCopy',
+ 'connectionSelected',
];
actions = {
@@ -51,5 +53,8 @@ export class MaintainFormModel extends Model<{
goFirstPage() {
this.model.pageIndex = PAGE_INDEX.CONNECTION;
},
+ setConnectionSelected(name: string) {
+ this.model.connectionSelected = name;
+ }
}
}
diff --git a/src/modules/pages/maintain/forms/form.server.ts b/src/modules/pages/maintain/forms/form.server.ts
index d378768..2098ac1 100644
--- a/src/modules/pages/maintain/forms/form.server.ts
+++ b/src/modules/pages/maintain/forms/form.server.ts
@@ -5,6 +5,7 @@ import { TestStatus } from '../../../components/test_status/test_status';
import { getJdbcDatabaseType } from '../../../app.service';
import { ApiFactory } from '../../../crud/apiFactory';
const api = new ApiFactory().create();
+
export function testConnection(value: Connection): Promise {
return new Promise(resolve => {
let testStatus = null;
@@ -15,12 +16,18 @@ export function testConnection(value: Connection): Promise {
return false;
}
+
const id = BI.UUID();
const testConnection = () => {
const formValue = value;
+
api.testConnection(formValue).then(re => {
if (re && re.errorCode) {
- // 判断是否是缺少驱动,如果缺少驱动则显示下载驱动的连接
+ if (re.errorCode === DecCst.ErrorCode.NO_IP_AUTHORIZED) {
+ testStatus.setFail();
+ return;
+ }
+ // 判断是否是缺少驱动,如果缺少驱动则显示下载驱动的连接
if (api.isDriverError(re.errorCode)) {
if (formValue.connectionType === connectionType.JDBC) {
const driver = (formValue.connectionData as ConnectionJDBC).driver;
@@ -40,7 +47,11 @@ export function testConnection(value: Connection): Promise {
} else if (re.errorCode === errorCode.DUPLICATE_NAMES) {
testStatus.setFail(BI.i18nText(re.errorMsg));
} else {
+ // 不缺少驱动,但连接失败,打印出当前驱动加载路径,并显示检测驱动按钮
testStatus.setFail(re.errorMsg);
+ api.getDriverLoadPath(formValue).then(res => {
+ testStatus.setExtraContainer(createDriverTestContainer(res.data));
+ })
}
} else if (re.data) {
testStatus.setSuccess();
@@ -55,7 +66,54 @@ export function testConnection(value: Connection): Promise {
BI.Maskers.remove(id);
}
});
+
+ /**
+ * 驱动及冲突检测内容,补充到报错弹窗里
+ */
+ function createDriverTestContainer(path: string) {
+ return {
+ type: BI.VerticalLayout.xtype,
+ vgap: 5,
+ items: [
+ {
+ type: BI.Label.xtype,
+ text: BI.i18nText('Dec-Connection_Driver_Current_Load_Path', path),
+ textAlign: 'left',
+ whiteSpace: 'normal',
+ },
+ {
+ type: BI.TextButton.xtype,
+ cls: 'bi-high-light',
+ text: BI.i18nText('Dec-Connection_Driver_Check'),
+ textAlign: 'left',
+ handler: () => {
+ api.checkDriverStatus({
+ driver: (formValue.connectionData as ConnectionJDBC).driver,
+ path,
+ }).then(res => {
+ const isDriverConflict = res.data;
+
+ testStatus.setExtraContainer({
+ type: BI.VerticalLayout.xtype,
+ items: [
+ {
+ type: BI.Label.xtype,
+ textAlign: 'left',
+ text: isDriverConflict
+ ? BI.i18nText('Dec-Connection_Driver_Has_Confilt_Tip')
+ : BI.i18nText('Dec-Connection_Driver_No_Confilt_Tip'),
+ cls: isDriverConflict ? 'bi-error' : '',
+ }
+ ]
+ })
+ });
+ }
+ }
+ ]
+ }
+ }
};
+
BI.Maskers.create(id, null, {
render: {
type: TestStatus.xtype,
diff --git a/src/modules/pages/maintain/forms/form.ts b/src/modules/pages/maintain/forms/form.ts
index cb3b573..2e6248b 100644
--- a/src/modules/pages/maintain/forms/form.ts
+++ b/src/modules/pages/maintain/forms/form.ts
@@ -6,13 +6,15 @@ import { FormPlugin } from './components/form.plugin';
import { connectionType, errorCode } from '@constants/env';
import { ConnectionJDBC, Connection, ResultType } from 'src/modules/crud/crud.typings';
import { DEFAULT_JNDI_DATA, DEFAULT_JDBC_POOL, DATEBASE_FILTER_TYPE } from '@constants/constant';
-import { getJdbcDatabaseType, getChartLength } from '../../../app.service';
+import { getJdbcDatabaseType, getChartLength, getAllDatabaseTypes } from '../../../app.service';
import { NAME_MAX_LENGTH } from '../../../app.constant';
+import { checkIllegalStrings } from "@core/index";
@shortcut()
@store(MaintainFormModel)
export class MaintainForm extends BI.Widget {
static xtype = 'dec.dcm.maintain.form';
+ static EVENT_TESTCONNECTION = 'EVENT_TEST_CONNECTION';
props = {
connectionType: '',
@@ -28,29 +30,37 @@ export class MaintainForm extends BI.Widget {
watch = {
saveEvent: () => {
- if (!this.testValue()) {
- return;
- }
- if (this.connectionName && !this.model.isCopy) {
- const value = this.form.getSubmitValue();
- (value.connectionData as ConnectionJDBC).creator = BI.get(this.getFormData(), 'creator');
- // DEC-10155 为了适配插件的数据连接,在外层也加一个creator字段
- value.creator = BI.get(this.getFormData(), 'creator');
- this.store.updateConnection(this.connectionName, value).then(result => {
- if (result.errorCode) {
- this.showError(result);
+ const sonSave = this.form.getSaveFn?.();
+ if (sonSave) {
+ sonSave().then((success: boolean) => {
+ if (success) {
+ this.store.goFirstPage();
+ BI.Msg.toast(BI.i18nText("Dec-Basic_Save_Success"), {
+ level: "success",
+ });
+ } else {
+ BI.Msg.toast(BI.i18nText("Dec-Basic_Save_Fail"), {
+ level: "error",
+ });
+ }
+ });
+
+ //只有外来插件才可以使用是否不执行平台的保存逻辑
+ if (this.model.datebaseTypeSelected) {
+ const isPluginDatabase = BI.some(BI.Providers.getProvider('dec.connection.provider.datebase').customDatabaseType, (_index, value) => value.databaseType === this.model.datebaseTypeSelected);
+ if (isPluginDatabase && this.model.datebaseTypeSelectedOne.isNoSave) {
return;
}
- this.store.goFirstPage();
- });
- } else {
- const form = this.form.getSubmitValue();
- form.connectionId = this.connectionName;
- // DEC-10155 为了适配插件的数据连接,在外层也加一个creator字段
- form.creator = Dec ? Dec.personal.username : '';
- this.addConnection(form);
+ } else {
+ const databaseType = this.model.connectionSelectedOne.connectionType;
+ const database = BI.find(getAllDatabaseTypes(), (_index, value) => value.databaseType === databaseType);
+ if (this.model.connectionSelectedOne.pluginConnection && database?.isNoSave) {
+ return;
+ }
+ }
}
+ this.save();
},
testEvent: () => {
this.testConnection();
@@ -71,7 +81,7 @@ export class MaintainForm extends BI.Widget {
this.form = _ref;
},
listeners: [{
- eventName: 'EVENT_TEST_CONNECTION',
+ eventName: MaintainForm.EVENT_TESTCONNECTION,
action: () => {
this.testConnection();
},
@@ -116,15 +126,16 @@ export class MaintainForm extends BI.Widget {
let editConnection: Connection;
let connectionData: ConnectionJDBC;
if (this.model.datebaseTypeSelected) {
+ const { databaseType: database, fetchSize } = this.model.datebaseTypeSelectedOne;
+
connectionData = {
- driver: this.model.datebaseTypeSelectedOne.driver,
- url: this.model.datebaseTypeSelectedOne.url,
- database: this.model.datebaseTypeSelectedOne.databaseType,
+ ...this.model.datebaseTypeSelectedOne,
+ database,
connectionName,
connectionPoolAttr: DEFAULT_JDBC_POOL,
port: '',
host: 'localhost',
- fetchSize: this.model.datebaseTypeSelectedOne.fetchSize ?? -1,
+ fetchSize: fetchSize ?? -1,
identity: BI.UUID(),
};
editConnection = {
@@ -139,9 +150,12 @@ export class MaintainForm extends BI.Widget {
this.isEdit = true;
this.connectionName = this.model.connectionSelectedOne.connectionName;
const connection = BI.clone(this.model.connectionSelectedOne);
- const { database, driver } = connection.connectionData as ConnectionJDBC;
- (connection.connectionData as ConnectionJDBC).database = getJdbcDatabaseType(database, driver).databaseType;
-
+ connectionData = connection.connectionData as ConnectionJDBC;
+ const { database, driver } = connectionData;
+ connectionData.database = getJdbcDatabaseType(database, driver).databaseType;
+ if (this.model.isCopy) {
+ connectionData.identity = BI.UUID();
+ }
return connection;
}
@@ -200,6 +214,12 @@ export class MaintainForm extends BI.Widget {
if (this.form.validation && !this.form.validation()) {
return false;
}
+ const result = checkIllegalStrings(value.connectionName);
+ if (!result.legal) {
+ this.setFromError(result.errorMsg);
+
+ return false;
+ }
return true;
}
@@ -250,6 +270,11 @@ export class MaintainForm extends BI.Widget {
private addConnection(form: Connection) {
this.store.addConnection(form).then(result => {
if (result.errorCode) {
+ if (result.errorCode === DecCst.ErrorCode.NO_IP_AUTHORIZED) {
+ BI.Msg.toast(BI.i18nText("Dec-Basic_Save_Fail"), {
+ level: "error",
+ });
+ }
if (result.errorCode === errorCode.DUPLICATE_NAMES) {
if (form.connectionType !== connectionType.JDBC && form.connectionType !== connectionType.JNDI) {
// 如果不是jdbc或jndi,即如果是插件,名称重复的时候需要修改名字重新提交给后台
@@ -270,8 +295,41 @@ export class MaintainForm extends BI.Widget {
return;
}
+ // 新增之后connections待更新,connectionSelected先置空
+ this.store.setConnectionSelected('');
this.store.goFirstPage();
this.store.setIsCopy(false);
});
}
+
+ private save() {
+ if (!this.testValue()) {
+ return;
+ }
+ if (this.connectionName && !this.model.isCopy) {
+ const value = this.form.getSubmitValue();
+ (value.connectionData as ConnectionJDBC).creator = BI.get(this.getFormData(), 'creator');
+ // DEC-10155 为了适配插件的数据连接,在外层也加一个creator字段
+ value.creator = BI.get(this.getFormData(), 'creator');
+ this.store.updateConnection(this.connectionName, value).then(result => {
+ if (result.errorCode) {
+ if (result.errorCode === DecCst.ErrorCode.NO_IP_AUTHORIZED) {
+ BI.Msg.toast(BI.i18nText("Dec-Basic_Save_Fail"), {
+ level: "error",
+ });
+ }
+ this.showError(result);
+
+ return;
+ }
+ this.store.goFirstPage();
+ });
+ } else {
+ const form = this.form.getSubmitValue();
+ form.connectionId = this.connectionName;
+ // DEC-10155 为了适配插件的数据连接,在外层也加一个creator字段
+ form.creator = Dec ? Dec.personal.username : '';
+ this.addConnection(form);
+ }
+ }
}
diff --git a/src/modules/pages/maintain/maintain.ts b/src/modules/pages/maintain/maintain.ts
index 137ccfe..4511666 100644
--- a/src/modules/pages/maintain/maintain.ts
+++ b/src/modules/pages/maintain/maintain.ts
@@ -9,7 +9,7 @@ import './maintain.less';
import { connectionType } from '@constants/env';
import { getJdbcDatabaseType, getTextByDatabaseType } from '../../app.service';
import { ConnectionJDBC } from 'src/modules/crud/crud.typings';
-import { ListView } from '@fui/core';
+import { ButtonGroup } from '@fui/core';
@shortcut()
@store(MaintainModel)
@@ -19,16 +19,16 @@ export class Maintain extends BI.Widget {
model: MaintainModel['model'];
store: MaintainModel['store'];
- listView: ListView;
+ buttonGroup: ButtonGroup;
socketTip: LinkButton;
render() {
const { isEdit, databaseType } = this.getEditConnection();
const titleText = getTextByDatabaseType(databaseType);
-
+
return {
type: BI.VTapeLayout.xtype,
- hgap: 5,
+ hgap: 16,
items: [
{
type: BI.VerticalAdaptLayout.xtype,
@@ -64,9 +64,9 @@ export class Maintain extends BI.Widget {
],
},
{
- type: BI.ListView.xtype,
- ref: (_ref: ListView) => {
- this.listView = _ref;
+ type: BI.ButtonGroup.xtype,
+ ref: (_ref: ButtonGroup) => {
+ this.buttonGroup = _ref;
},
items: this.renderItems(),
},
@@ -82,12 +82,13 @@ export class Maintain extends BI.Widget {
this.socketTip.setVisible(true);
}
- api.setEditedConnectionStatus(this.model.connectionSelectedOne.connectionName);
+ this.model.connectionSelectedOne
+ && api.setEditedConnectionStatus(this.model.connectionSelectedOne.connectionName);
}
private renderItems() {
const { type } = this.getEditConnection();
-
+
return [{
type: MaintainForm.xtype,
connectionType: type,
@@ -108,7 +109,7 @@ export class Maintain extends BI.Widget {
const connectionJDBC = this.model.connectionSelectedOne.connectionData as ConnectionJDBC;
databaseType = getJdbcDatabaseType(connectionJDBC.database, connectionJDBC.driver).databaseType;
}
-
+
return {
type: this.model.connectionSelectedOne.connectionType,
text: this.model.connectionSelectedOne.connectionName,
diff --git a/src/modules/pages/setting/setting.ts b/src/modules/pages/setting/setting.ts
new file mode 100644
index 0000000..d788cb5
--- /dev/null
+++ b/src/modules/pages/setting/setting.ts
@@ -0,0 +1,96 @@
+import { shortcut } from '@core/core';
+import { ApiFactory } from 'src/modules/crud/apiFactory';
+
+const api = new ApiFactory().create();
+
+@shortcut()
+export class TimeOutSetting extends BI.Widget {
+ public static xtype = 'dec.dcm.page.timeout.setting';
+
+ public props = {
+ value: 0,
+ };
+
+ beforeRender(cb: Function) {
+ const self = this;
+ api.getTimeOut().then(res => {
+ self.props.value = res.data.count;
+ cb();
+ });
+ }
+
+ public render() {
+ const { value } = this.props;
+ const self = this;
+
+ return {
+ type: 'bi.vtape',
+ cls: 'bi-background',
+ items: [{
+ type: 'dec.setting.header',
+ height: 40,
+ listeners: [{
+ eventName: 'EVENT_CANCEL',
+ action: function () {
+ self.fireEvent('EVENT_CHANGE');
+ },
+ }, {
+ eventName: 'EVENT_SAVE',
+ action: function () {
+ api.putTimeOut(Number(self.editor.getValue()));
+ self.fireEvent('EVENT_CHANGE');
+ },
+ }],
+ }, {
+ type: 'bi.vertical',
+ cls: 'bi-card',
+ vgap: 10,
+ items: [
+ {
+ el: {
+ type: 'bi.vertical_adapt',
+ cls: 'bi-border-bottom',
+ height: 40,
+ items: [{
+ type: 'bi.label',
+ textAlign: 'left',
+ width: 120,
+ cls: 'dec-font-weight-bold',
+ text: BI.i18nText('Dec-Dcm_Connection_Timeout_Detection'),
+ }]
+ }, tgap: -10, hgap: 16,
+ },
+ {
+ type: 'bi.vertical_adapt',
+ hgap: 16,
+ items: [{
+ type: 'dec.label.editor.item',
+ text: BI.i18nText('Dec-Over_Time'),
+ textWidth: 100,
+ editorWidth: 80,
+ allowBlank: false,
+ value: value,
+ validationChecker: function(v) {
+ return BI.isPositiveInteger(v);
+ },
+ errorText: BI.i18nText('BI-Please_Input_Positive_Integer'),
+ ref: function (_ref) {
+ self.editor = _ref;
+ },
+ }, {
+ el: {
+ type: 'bi.label',
+ text: BI.i18nText('Dec-Dcm_Connection_Timeout_Millisecond'),
+ },
+ lgap: 10,
+ }]
+
+ },
+ ]
+ }],
+ ref: function (_ref) {
+ self.setting = _ref;
+ },
+ };
+ }
+}
diff --git a/src/modules/title/title.ts b/src/modules/title/title.ts
index dc85b0f..28858fb 100644
--- a/src/modules/title/title.ts
+++ b/src/modules/title/title.ts
@@ -11,7 +11,7 @@ export class Title extends BI.Widget {
static xtype = 'dec.dcm.title';
props = {
- baseCls: 'bi-card',
+ baseCls: '',
}
tab: Tab;
linearSegment: LinearSegment;
@@ -31,6 +31,14 @@ export class Title extends BI.Widget {
type: BI.LeftRightVerticalAdaptLayout.xtype,
items: {
left: [
+ {
+ type: 'bi.icon_button',
+ cls: 'setting-font',
+ _lgap: 15,
+ handler: () => {
+ this.fireEvent('EVENT_CLICK_SETTING');
+ },
+ },
{
type: BI.LinearSegment.xtype,
cls: 'bi-font-bold',
@@ -70,6 +78,7 @@ export class Title extends BI.Widget {
type: BI.Tab.xtype,
height: 40,
showIndex: this.model.pageIndex,
+ width:200,
ref: (_ref: Tab) => {
this.tab = _ref;
},
diff --git a/src/modules/title/title_database/title_datebase.ts b/src/modules/title/title_database/title_datebase.ts
index 1441d75..6541237 100644
--- a/src/modules/title/title_database/title_datebase.ts
+++ b/src/modules/title/title_database/title_datebase.ts
@@ -25,13 +25,13 @@ export class TitleDatabase extends BI.Widget {
items: [{
type: BI.VerticalAdaptLayout.xtype,
height: 40,
- rgap: 5,
+ rgap: 16,
items: [
{
type: BI.Button.xtype,
$value: 'title-database-cancel',
text: BI.i18nText('BI-Basic_Cancel'),
- level: 'ignore',
+ light: true,
handler: () => {
this.store.setPageIndex(PAGE_INDEX.CONNECTION);
},
@@ -49,6 +49,7 @@ export class TitleDatabase extends BI.Widget {
},
},
],
+ _rgap: -16,
}],
};
}
diff --git a/src/modules/title/title_maintain/title_maintain.model.ts b/src/modules/title/title_maintain/title_maintain.model.ts
index 21fd87a..c3bc416 100644
--- a/src/modules/title/title_maintain/title_maintain.model.ts
+++ b/src/modules/title/title_maintain/title_maintain.model.ts
@@ -11,12 +11,13 @@ export class TitleMaintainModel extends Model<{
connectionSelected: AppModel['TYPE']['connectionSelected'];
testEvent: AppModel['TYPE']['testEvent'];
isCopy: AppModel['TYPE']['isCopy'];
+ noTestConnection: AppModel['TYPE']['noTestConnection'];
},
context: TitleMaintainModel['context'];
}> {
static xtype = 'dec.dcm.model.title_maintain';
- context = ['pageIndex', 'saveEvent', 'testEvent', 'connectionSelected', 'isCopy'];
+ context = ['pageIndex', 'saveEvent', 'testEvent', 'connectionSelected', 'isCopy', 'noTestConnection'];
actions = {
setPageIndex: (index: string) => {
diff --git a/src/modules/title/title_maintain/title_maintain.ts b/src/modules/title/title_maintain/title_maintain.ts
index 18fdc2c..2f3c48f 100644
--- a/src/modules/title/title_maintain/title_maintain.ts
+++ b/src/modules/title/title_maintain/title_maintain.ts
@@ -1,6 +1,7 @@
import { shortcut, store } from '@core/core';
import { TitleMaintainModel } from './title_maintain.model';
import { PAGE_INDEX } from '@constants/constant';
+import { Button } from '@fui/core';
@shortcut()
@store(TitleMaintainModel)
@@ -9,19 +10,20 @@ export class TitleMaintain extends BI.Widget {
store: TitleMaintainModel['store'];
model: TitleMaintainModel['model'];
+
render() {
return {
type: BI.FloatRightLayout.xtype,
items: [{
type: BI.VerticalAdaptLayout.xtype,
height: 40,
- rgap: 5,
items: [
{
type: BI.Button.xtype,
$value: 'title-maintain-cancel',
text: BI.i18nText('BI-Basic_Cancel'),
- level: 'ignore',
+ clear: true,
+ _rgap: 16,
handler: () => {
this.store.setIsCopy(false);
this.store.setPageIndex(PAGE_INDEX.CONNECTION);
@@ -30,15 +32,21 @@ export class TitleMaintain extends BI.Widget {
},
{
type: BI.Button.xtype,
+ ref: (_ref) => {
+ this.testConnectionBtn = _ref;
+ },
+ invisible: () => this.model.noTestConnection,
+ _rgap: 16,
$value: 'title-maintain-connection-test',
text: BI.i18nText('Dec-Dcm_Connection_Test'),
- level: 'ignore',
+ light: true,
handler: () => {
this.store.setTestEvent();
},
},
{
type: BI.Button.xtype,
+ _rgap: 16,
$value: 'title-maintain-save',
text: BI.i18nText('BI-Basic_Save'),
handler: () => {
diff --git a/tsconfig.json b/tsconfig.json
index 4e9e3db..bac5abb 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,8 +5,8 @@
"module": "es2015",
"moduleResolution": "node",
"lib": [
- "es2017",
- "dom"
+ "es2017",
+ "dom"
],
"declaration": true,
"experimentalDecorators": true,
@@ -19,13 +19,23 @@
// "noUnusedParameters": true,
// "noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
- "skipLibCheck": true,
+ "skipLibCheck": false,
"paths": {
- "ui": ["./src/ui"],
- "ReportCst": ["./private/constants"],
- "types": ["./types/index.d.ts"],
- "@core/*": ["./src/modules/core/*"],
- "@constants/*": ["./src/modules/constants/*"]
+ "ui": [
+ "./src/ui"
+ ],
+ "ReportCst": [
+ "./private/constants"
+ ],
+ "types": [
+ "./types/index.d.ts"
+ ],
+ "@core/*": [
+ "./src/modules/core/*"
+ ],
+ "@constants/*": [
+ "./src/modules/constants/*"
+ ]
}
},
"include": [
@@ -33,6 +43,6 @@
"src/**/*.ts",
"private/*.ts",
"private/**/*.ts",
- "types/globals.d.ts"
+ "types"
]
}
\ No newline at end of file
diff --git a/types/globals.d.ts b/types/globals.d.ts
index 09ede39..a00fd3b 100644
--- a/types/globals.d.ts
+++ b/types/globals.d.ts
@@ -2,6 +2,8 @@ interface Obj {
[key: string]: any;
}
+type RequestFunction = (url: string, data: any, callback: (re: any) => void) => void;
+
declare let BI: Obj & import('@fui/core').BI & import('@fui/materials').BI;
declare const Fix: Obj;
declare const DecCst: Obj;
@@ -14,15 +16,21 @@ declare const Dec: {
hasListeners: Function;
removeListener: Function;
};
- system: {
-
- };
+ system: {};
personal: {
username: string;
};
+ Utils: Obj;
+ reqByEncrypt: (method: AxiosType.X_Method, url: string, data?: any, config?: AxiosType.X_AxiosRequestConfig) => {},
socketEmit: (type: string, name: string, callback: (re: any) => void) => void;
- reqGet: (url: string, data: any, callback: (re: any) => void) => void;
- reqPost: (url: string, data: any, callback: (re: any) => void) => void;
- reqPut: (url: string, data: any, callback: (re: any) => void) => void;
- reqDelete: (url: string, data: any, callback: (re: any) => void) => void;
-};
\ No newline at end of file
+ // req
+ reqGet: RequestFunction;
+ reqPost: RequestFunction;
+ reqPut: RequestFunction;
+ reqDelete: RequestFunction;
+ // reqHandle
+ reqGetHandle: RequestFunction;
+ reqPostHandle: RequestFunction;
+ reqPutHandle: RequestFunction;
+ reqDeleteHandle: RequestFunction;
+};
diff --git a/types/request.d.ts b/types/request.d.ts
new file mode 100644
index 0000000..4042317
--- /dev/null
+++ b/types/request.d.ts
@@ -0,0 +1,9 @@
+import { Method, AxiosRequestConfig } from 'axios';
+
+declare namespace AxiosType {
+ type X_Method = Method
+ interface X_AxiosRequestConfig extends AxiosRequestConfig { }
+}
+
+export = AxiosType;
+export as namespace AxiosType;
\ No newline at end of file