[improvement][semantic-fe] Refactor database settings functionality.

This commit is contained in:
tristanliu
2023-09-04 12:29:07 +08:00
parent d5c5c63a75
commit f5a7068d5e
34 changed files with 1222 additions and 441 deletions

View File

@@ -2,30 +2,27 @@ import React, { useEffect, useState } from 'react';
import { Form, Input, Spin, Select, message } from 'antd';
import type { FormInstance } from 'antd/lib/form';
import { getDbNames, getTables } from '../../service';
import { ISemantic } from '../../data';
const FormItem = Form.Item;
const { TextArea } = Input;
type Props = {
isEdit?: boolean;
dataBaseConfig: any;
databaseConfigList: ISemantic.IDatabaseItemList;
form: FormInstance<any>;
tableLoading?: boolean;
mode?: 'normal' | 'fast';
};
const DataSourceBasicForm: React.FC<Props> = ({
isEdit,
dataBaseConfig,
tableLoading = false,
mode = 'normal',
}) => {
const DataSourceBasicForm: React.FC<Props> = ({ isEdit, databaseConfigList, mode = 'normal' }) => {
const [currentDbLinkConfigId, setCurrentDbLinkConfigId] = useState<number>();
const [dbNameList, setDbNameList] = useState<any[]>([]);
const [tableNameList, setTableNameList] = useState<any[]>([]);
const [currentDbName, setCurrentDbName] = useState<string>('');
const [currentTableName, setCurrentTableName] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const queryDbNameList = async (databaseId: number) => {
setLoading(true);
const { code, data, msg } = await getDbNames(databaseId);
setLoading(false);
if (code === 200) {
const list = data?.resultList || [];
setDbNameList(list);
@@ -34,7 +31,12 @@ const DataSourceBasicForm: React.FC<Props> = ({
}
};
const queryTableNameList = async (databaseName: string) => {
const { code, data, msg } = await getTables(dataBaseConfig.id, databaseName);
if (!currentDbLinkConfigId) {
return;
}
setLoading(true);
const { code, data, msg } = await getTables(currentDbLinkConfigId, databaseName);
setLoading(false);
if (code === 200) {
const list = data?.resultList || [];
setTableNameList(list);
@@ -42,16 +44,32 @@ const DataSourceBasicForm: React.FC<Props> = ({
message.error(msg);
}
};
useEffect(() => {
if (dataBaseConfig?.id) {
queryDbNameList(dataBaseConfig.id);
}
}, [dataBaseConfig]);
return (
<Spin spinning={tableLoading}>
<Spin spinning={loading}>
{mode === 'fast' && (
<>
<FormItem
name="databaseId"
label="数据库连接"
rules={[{ required: true, message: '请选择数据库连接' }]}
>
<Select
showSearch
placeholder="请选择数据库连接"
disabled={isEdit}
onChange={(dbLinkConfigId: number) => {
queryDbNameList(dbLinkConfigId);
setCurrentDbLinkConfigId(dbLinkConfigId);
}}
>
{databaseConfigList.map((item) => (
<Select.Option key={item.id} value={item.id} disabled={!item.hasUsePermission}>
{item.name}
</Select.Option>
))}
</Select>
</FormItem>
<FormItem
name="dbName"
label="数据库名"
@@ -59,11 +77,10 @@ const DataSourceBasicForm: React.FC<Props> = ({
>
<Select
showSearch
placeholder="请选择数据库/表"
placeholder="请选择一个数据库连接"
disabled={isEdit}
onChange={(dbName: string) => {
queryTableNameList(dbName);
setCurrentDbName(dbName);
}}
>
{dbNameList.map((item) => (
@@ -78,15 +95,7 @@ const DataSourceBasicForm: React.FC<Props> = ({
label="数据表名"
rules={[{ required: true, message: '请选择数据库/表' }]}
>
<Select
placeholder="请选择数据库/表"
disabled={isEdit}
showSearch
onChange={(tableName: string) => {
// queryTableNameList(tableName);
setCurrentTableName(tableName);
}}
>
<Select placeholder="请选择数据库/表" disabled={isEdit} showSearch>
{tableNameList.map((item) => (
<Select.Option key={item.name} value={item.name}>
{item.name}

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { Form, Button, Modal, Steps, message } from 'antd';
import BasicInfoForm from './DataSourceBasicForm';
import DataSourceBasicForm from './DataSourceBasicForm';
import FieldForm from './DataSourceFieldForm';
import { formLayout } from '@/components/FormHelper/utils';
import { EnumDataSourceType } from '../constants';
@@ -46,9 +46,10 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
const [currentStep, setCurrentStep] = useState(0);
const [saveLoading, setSaveLoading] = useState(false);
const [hasEmptyNameField, setHasEmptyNameField] = useState<boolean>(false);
const [formDatabaseId, setFormDatabaseId] = useState<number>();
const formValRef = useRef(initFormVal as any);
const [form] = Form.useForm();
const { dataBaseConfig, selectModelId: modelId } = domainManger;
const { databaseConfigList, selectModelId: modelId } = domainManger;
const updateFormVal = (val: any) => {
formValRef.current = val;
};
@@ -82,11 +83,13 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
bizName,
timeGranularity,
agg,
isCreateDimension,
isCreateDimension: createDimension,
name,
isCreateMetric,
isCreateMetric: createMetric,
dateFormat,
} = item;
const isCreateDimension = createDimension ? 1 : 0;
const isCreateMetric = createMetric ? 1 : 0;
switch (type) {
case EnumDataSourceType.CATEGORICAL:
fieldsClassify.dimensions.push({
@@ -157,7 +160,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
const queryParams = {
...submitForm,
sqlQuery: sql,
databaseId: dataSourceItem?.databaseId || dataBaseConfig.id,
databaseId: dataSourceItem?.databaseId || formDatabaseId,
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
modelId,
@@ -217,7 +220,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
if (queryType === 'table_query') {
const tableQueryString = tableQuery || '';
const [dbName, tableName] = tableQueryString.split('.');
columns = await queryTableColumnList(dbName, tableName);
columns = await queryTableColumnList(dataSourceItem.databaseId, dbName, tableName);
tableQueryInitValue = {
dbName,
tableName,
@@ -227,13 +230,14 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
};
const formatterInitData = (columns: any[], extendParams: Record<string, any> = {}) => {
const { id, name, bizName, description, datasourceDetail } = dataSourceItem as any;
const { id, name, bizName, description, datasourceDetail, databaseId } = dataSourceItem as any;
const { dimensions, identifiers, measures } = datasourceDetail;
const initValue = {
id,
name,
bizName,
description,
databaseId,
...extendParams,
// ...tableQueryInitValue,
};
@@ -274,11 +278,8 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
setFields(result);
};
const queryTableColumnList = async (dbName: string, tableName: string) => {
if (!dataBaseConfig?.id) {
return;
}
const { code, data, msg } = await getColumns(dataBaseConfig.id, dbName, tableName);
const queryTableColumnList = async (databaseId: number, dbName: string, tableName: string) => {
const { code, data, msg } = await getColumns(databaseId, dbName, tableName);
if (code === 200) {
const list = data?.resultList || [];
// setTableNameList(list);
@@ -299,16 +300,20 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
};
const renderContent = () => {
if (currentStep === 1) {
return <FieldForm fields={fields} onFieldChange={handleFieldChange} />;
}
return (
<BasicInfoForm
form={form}
isEdit={isEdit}
mode={basicInfoFormMode}
dataBaseConfig={dataBaseConfig}
/>
<>
<div style={{ display: currentStep === 1 ? 'block' : 'none' }}>
<FieldForm fields={fields} onFieldChange={handleFieldChange} />;
</div>
<div style={{ display: currentStep !== 1 ? 'block' : 'none' }}>
<DataSourceBasicForm
form={form}
isEdit={isEdit}
mode={basicInfoFormMode}
databaseConfigList={databaseConfigList}
/>
</div>
</>
);
};
@@ -365,9 +370,10 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
}}
onValuesChange={(value, values) => {
const { tableName } = value;
const { dbName } = values;
const { dbName, databaseId } = values;
setFormDatabaseId(databaseId);
if (tableName) {
queryTableColumnList(dbName, tableName);
queryTableColumnList(databaseId, dbName, tableName);
}
}}
className={styles.form}

View File

@@ -230,9 +230,12 @@ const FieldForm: React.FC<Props> = ({ fields, onFieldChange }) => {
style={{ marginBottom: '10px' }}
banner
message={
<Marquee pauseOnHover gradient={false}>
//
</Marquee>
<div>
//
</div>
// <Marquee pauseOnHover gradient={false}>
// 为了保障同一个主题域下维度/指标列表唯一,消除歧义,若本主题域下的多个数据源存在相同的字段名并且都勾选了快速创建,系统默认这些相同字段的指标维度是同一个,同时列表中将只显示最后一次创建的指标/维度。
// </Marquee>
}
/>
<Table<FieldItem>

View File

@@ -27,11 +27,12 @@ import 'ace-builds/src-min-noconflict/ext-searchbox';
import 'ace-builds/src-min-noconflict/theme-sqlserver';
import 'ace-builds/src-min-noconflict/theme-monokai';
import 'ace-builds/src-min-noconflict/mode-sql';
import { IDataSource, ISemantic } from '../../data';
type IProps = {
domainManger: StateType;
dispatch: Dispatch;
dataSourceItem: DataInstanceItem;
dataSourceItem: IDataSource.IDataSourceItem;
onUpdateSql?: (sql: string) => void;
sql?: string;
onSubmitSuccess?: (dataSourceInfo: any) => void;
@@ -61,7 +62,7 @@ const SqlDetail: React.FC<IProps> = ({
onUpdateSql,
onJdbcSourceChange,
}) => {
const { dataBaseConfig, selectModelId: modelId } = domainManger;
const { databaseConfigList, selectModelId: modelId } = domainManger;
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
const [resultTableLoading, setResultTableLoading] = useState(false);
const [resultCols, setResultCols] = useState<ResultColItem[]>([]);
@@ -71,6 +72,7 @@ const SqlDetail: React.FC<IProps> = ({
total: 0,
});
const [jdbcSourceItems, setJdbcSourceItems] = useState<JdbcSourceItems[]>([]);
const [currentJdbcSourceItem, setCurrentJdbcSourceItem] = useState<JdbcSourceItems>();
const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false);
const [tableScroll, setTableScroll] = useState({
@@ -99,15 +101,40 @@ const SqlDetail: React.FC<IProps> = ({
const [scriptColumns, setScriptColumns] = useState<any[]>([]);
// useEffect(() => {
// const list = databaseConfigList.map((item: ISemantic.IDatabaseItem) => {
// return {
// label: item.name,
// key: item.id,
// disabled: !item.hasUsePermission,
// };
// });
// setJdbcSourceItems(list);
// const config = list[0];
// setCurrentJdbcSourceItem(config);
// onJdbcSourceChange?.(config?.key && Number(config?.key));
// }, [databaseConfigList]);
useEffect(() => {
setJdbcSourceItems([
{
label: dataBaseConfig?.name,
key: dataBaseConfig?.id,
},
]);
onJdbcSourceChange?.(dataBaseConfig?.id && Number(dataBaseConfig?.id));
}, [dataBaseConfig]);
const list = databaseConfigList.map((item: ISemantic.IDatabaseItem) => {
return {
label: item.name,
key: item.id,
disabled: !item.hasUsePermission,
};
});
setJdbcSourceItems(list);
let targetDataBase = list[0];
if (dataSourceItem?.id) {
const { databaseId } = dataSourceItem;
const target = list.find((item) => item.key === databaseId);
if (target) {
targetDataBase = target;
}
}
setCurrentJdbcSourceItem(targetDataBase);
// onJdbcSourceChange?.(targetDataBase?.key && Number(targetDataBase?.key));
}, [dataSourceItem, databaseConfigList]);
function creatCalcItem(key: string, data: string) {
const line = document.createElement('div'); // 需要每条数据一行,这样避免数据换行的时候获得的宽度不准确
@@ -209,10 +236,14 @@ const SqlDetail: React.FC<IProps> = ({
};
const separateSql = async (value: string) => {
if (!currentJdbcSourceItem?.key) {
return;
}
setResultTableLoading(true);
const { code, data, msg } = await excuteSql({
sql: value,
modelId,
// modelId,
id: currentJdbcSourceItem.key,
});
setResultTableLoading(false);
if (code === 200) {
@@ -378,6 +409,7 @@ const SqlDetail: React.FC<IProps> = ({
})[0];
if (target) {
// setJdbcSourceName(target.label);
setCurrentJdbcSourceItem(target);
onJdbcSourceChange?.(Number(value));
}
},
@@ -387,7 +419,7 @@ const SqlDetail: React.FC<IProps> = ({
<Button style={{ marginRight: '15px', minWidth: '140px' }}>
<Space>
<CloudServerOutlined className={styles.sqlOprIcon} style={{ marginRight: 0 }} />
<span>{jdbcSourceItems[0]?.label}</span>
<span>{currentJdbcSourceItem?.label}</span>
</Space>
</Button>
</Dropdown>

View File

@@ -29,10 +29,10 @@ export const TYPE_OPTIONS = [
label: '主键',
value: EnumDataSourceType.PRIMARY,
},
{
label: '外键',
value: EnumDataSourceType.FOREIGN,
},
// {
// label: '外键',
// value: EnumDataSourceType.FOREIGN,
// },
];
export const AGG_OPTIONS = [

View File

@@ -1,11 +1,3 @@
// 数据类型
export type DataInstanceItem = {
sourceInstanceId: number; // 数据实例id
sourceInstanceName: string; // 数据实例名
defaultSourceId: number; // 查询表需要的默认datasource id
bindSourceId: number;
};
// 任务查询结果列
export type TaskResultColumn = {
name: string;