[improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality (#383)

* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab.
[improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions.
[improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager.

* [improvement][semantic-fe] Add time granularity setting in the data source configuration.

* [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility

* [improvement][semantic-fe] Modification of data source creation prompt wording"

* [improvement][semantic-fe] metric market experience optimization

* [improvement][semantic-fe] enhance the analysis of metric trends

* [improvement][semantic-fe] optimize the presentation of metric trend permissions

* [improvement][semantic-fe] add metric trend download functionality

* [improvement][semantic-fe] fix the dimension initialization issue in metric correlation

* [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source.

* [improvement][semantic-fe] Optimizing pagination logic and some CSS styles

* [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum"

* [improvement][semantic-fe] Fixing the default value setting for the indicator list

* [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models

* [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API

* [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators

* [improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality
This commit is contained in:
tristanliu
2023-11-14 06:01:23 -06:00
committed by GitHub
parent d4374f7074
commit 400d8b34fd
35 changed files with 1075 additions and 946 deletions

View File

@@ -1,10 +1,9 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { ReactNode, useEffect, useRef, useState } from 'react';
import { Form, Button, Modal, Steps, message } from 'antd';
import DataSourceBasicForm from './DataSourceBasicForm';
import FieldForm from './DataSourceFieldForm';
import { formLayout } from '@/components/FormHelper/utils';
import { EnumDataSourceType } from '../constants';
// import type { DataInstanceItem } from '../data';
import styles from '../style.less';
import { createDatasource, updateDatasource, getColumns } from '../../service';
import type { Dispatch } from 'umi';
@@ -17,13 +16,15 @@ export type CreateFormProps = {
dispatch: Dispatch;
createModalVisible: boolean;
sql?: string;
databaseItem?: any;
databaseId?: number;
dataSourceItem: IDataSource.IDataSourceItem;
onCancel?: () => void;
onSubmit?: (dataSourceInfo: any) => void;
scriptColumns?: any[] | undefined;
basicInfoFormMode?: 'normal' | 'fast';
onDataBaseTableChange?: (tableName: string) => void;
onDataSourceBtnClick?: () => void;
// modalSolt: ReactNode;
};
const { Step } = Steps;
@@ -41,8 +42,10 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
sql = '',
onSubmit,
dataSourceItem,
databaseItem,
databaseId,
basicInfoFormMode,
onDataSourceBtnClick,
children,
}) => {
const isEdit = !!dataSourceItem?.id;
const [fields, setFields] = useState<any[]>([]);
@@ -145,7 +148,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
);
return classify;
};
const handleNext = async () => {
const handleNext = async (saveState: boolean = false) => {
const fieldsValue = await form.validateFields();
const fieldsClassify = getFieldsClassify(fields);
@@ -155,7 +158,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
...fieldsClassify,
};
updateFormVal(submitForm);
if (currentStep < 1) {
if (!saveState && currentStep < 1) {
forward();
} else {
setSaveLoading(true);
@@ -163,7 +166,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
const queryParams = {
...submitForm,
sqlQuery: sql,
databaseId: databaseItem?.key || dataSourceItem?.databaseId || formDatabaseId,
databaseId: databaseId || dataSourceItem?.databaseId || formDatabaseId,
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
modelId: isEdit ? dataSourceItem.modelId : modelId,
@@ -191,7 +194,6 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
return {
...oldItem,
bizName: nameEn,
// name,
sqlType: type,
};
});
@@ -264,7 +266,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
} else {
initFields([], fieldColumns);
}
}, [dataSourceItem]);
}, [dataSourceItem, fieldColumns]);
const handleFieldChange = (fieldName: string, data: any) => {
const result = fields.map((field) => {
@@ -285,7 +287,6 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
const { code, data, msg } = await getColumns(databaseId, dbName, tableName);
if (code === 200) {
const list = data?.resultList || [];
// setTableNameList(list);
const columns = list.map((item: any) => {
const { dataType, name } = item;
return {
@@ -293,7 +294,6 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
type: dataType,
};
});
// setFields(columns);
initFields([], columns);
setFieldColumns(columns);
return columns;
@@ -327,14 +327,25 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
<Button style={{ float: 'left' }} onClick={backward}>
</Button>
<Button onClick={onCancel}></Button>
<Button onClick={onCancel}> </Button>
<Button
type="primary"
onClick={() => {
onDataSourceBtnClick?.();
}}
>
</Button>
<Button
type="primary"
loading={saveLoading}
onClick={handleNext}
onClick={() => {
handleNext(true);
}}
disabled={hasEmptyNameField}
>
</Button>
</>
);
@@ -342,9 +353,26 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
return (
<>
<Button onClick={onCancel}></Button>
<Button type="primary" onClick={handleNext}>
<Button
type="primary"
onClick={() => {
handleNext();
}}
>
</Button>
{isEdit && (
<Button
type="primary"
loading={saveLoading}
onClick={() => {
handleNext(true);
}}
// disabled={hasEmptyNameField}
>
</Button>
)}
</>
);
};
@@ -383,6 +411,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
>
{renderContent()}
</Form>
{children}
</Modal>
);
};

View File

@@ -18,7 +18,7 @@ import FullScreen from '@/components/FullScreen';
import SqlEditor from '@/components/SqlEditor';
import type { TaskResultItem, TaskResultColumn } from '../data';
import { excuteSql } from '@/pages/SemanticModel/service';
import DataSourceCreateForm from './DataSourceCreateForm';
// import DataSourceCreateForm from './DataSourceCreateForm';
import type { Dispatch } from 'umi';
import type { StateType } from '../../model';
import styles from '../style.less';
@@ -29,13 +29,19 @@ import 'ace-builds/src-min-noconflict/theme-monokai';
import 'ace-builds/src-min-noconflict/mode-sql';
import { IDataSource, ISemantic } from '../../data';
export type DataSourceSubmitData = {
sql: string;
databaseId: number;
columns: any[];
};
type IProps = {
domainManger: StateType;
dispatch: Dispatch;
dataSourceItem: IDataSource.IDataSourceItem;
onUpdateSql?: (sql: string) => void;
sql?: string;
onSubmitSuccess?: (dataSourceInfo: any) => void;
onSubmitSuccess?: (dataSourceInfo: DataSourceSubmitData) => void;
};
type ResultTableItem = Record<string, any>;
@@ -48,7 +54,7 @@ type ResultColItem = {
type ScreenSize = 'small' | 'middle' | 'large';
type JdbcSourceItems = {
type DatabaseItem = {
label: string;
key: number;
};
@@ -60,7 +66,7 @@ const SqlDetail: React.FC<IProps> = ({
sql = '',
onUpdateSql,
}) => {
const { databaseConfigList, selectModelId: modelId } = domainManger;
const { databaseConfigList } = domainManger;
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
const [resultTableLoading, setResultTableLoading] = useState(false);
const [resultCols, setResultCols] = useState<ResultColItem[]>([]);
@@ -69,9 +75,9 @@ const SqlDetail: React.FC<IProps> = ({
pageSize: 20,
total: 0,
});
const [jdbcSourceItems, setJdbcSourceItems] = useState<JdbcSourceItems[]>([]);
const [currentJdbcSourceItem, setCurrentJdbcSourceItem] = useState<JdbcSourceItems>();
const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false);
const [dataBaseItems, setDataBaseItems] = useState<DatabaseItem[]>([]);
const [currentDatabaseItem, setCurrentDatabaseItem] = useState<DatabaseItem>();
// const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false);
const [tableScroll, setTableScroll] = useState({
scrollToFirstRowOnChange: true,
@@ -107,7 +113,7 @@ const SqlDetail: React.FC<IProps> = ({
disabled: !item.hasUsePermission,
};
});
setJdbcSourceItems(list);
setDataBaseItems(list);
let targetDataBase = list[0];
if (dataSourceItem?.id) {
const { databaseId } = dataSourceItem;
@@ -116,12 +122,12 @@ const SqlDetail: React.FC<IProps> = ({
targetDataBase = target;
}
}
setCurrentJdbcSourceItem(targetDataBase);
setCurrentDatabaseItem(targetDataBase);
}, [dataSourceItem, databaseConfigList]);
useEffect(() => {
setRunState(undefined);
}, [currentJdbcSourceItem]);
}, [currentDatabaseItem, sql]);
function creatCalcItem(key: string, data: string) {
const line = document.createElement('div'); // 需要每条数据一行,这样避免数据换行的时候获得的宽度不准确
@@ -223,18 +229,16 @@ const SqlDetail: React.FC<IProps> = ({
};
const separateSql = async (value: string) => {
if (!currentJdbcSourceItem?.key) {
if (!currentDatabaseItem?.key) {
return;
}
setResultTableLoading(true);
const { code, data, msg } = await excuteSql({
sql: value,
// modelId,
id: currentJdbcSourceItem.key,
id: currentDatabaseItem.key,
});
setResultTableLoading(false);
if (code === 200) {
// setDataSourceResult(data);
fetchTaskResult(data);
setRunState(true);
} else {
@@ -268,13 +272,13 @@ const SqlDetail: React.FC<IProps> = ({
return isPartial ? separateSql(partialSql) : separateSql(sql);
};
const showDataSetModal = () => {
setDataSourceModalVisible(true);
};
// const showDataSetModal = () => {
// setDataSourceModalVisible(true);
// };
const startCreatDataSource = async () => {
showDataSetModal();
};
// const startCreatDataSource = async () => {
// showDataSetModal();
// };
const updateNormalResScroll = () => {
const node = resultInnerWrap?.current;
@@ -386,14 +390,14 @@ const SqlDetail: React.FC<IProps> = ({
<Tooltip title="数据类型">
<Dropdown
menu={{
items: jdbcSourceItems,
items: dataBaseItems,
onClick: (e) => {
const value = e.key;
const target: any = jdbcSourceItems.filter((item: any) => {
const target: any = dataBaseItems.filter((item: any) => {
return item.key === Number(value);
})[0];
if (target) {
setCurrentJdbcSourceItem(target);
setCurrentDatabaseItem(target);
}
},
}}
@@ -402,7 +406,7 @@ const SqlDetail: React.FC<IProps> = ({
<Button style={{ marginRight: '15px', minWidth: '140px' }}>
<Space>
<CloudServerOutlined className={styles.sqlOprIcon} style={{ marginRight: 0 }} />
<span>{currentJdbcSourceItem?.label}</span>
<span>{currentDatabaseItem?.label}</span>
</Space>
</Button>
</Dropdown>
@@ -464,7 +468,7 @@ const SqlDetail: React.FC<IProps> = ({
<div className={`${styles.sqlBottmWrap} ${screenSize}`}>
<div className={styles.sqlResultWrap}>
<div className={styles.sqlToolBar}>
{
{/* {
<Button
className={styles.sqlToolBtn}
type="primary"
@@ -473,7 +477,21 @@ const SqlDetail: React.FC<IProps> = ({
>
生成数据源
</Button>
}
} */}
<Button
className={styles.sqlToolBtn}
type="primary"
onClick={() => {
onSubmitSuccess?.({
columns: scriptColumns,
databaseId: currentDatabaseItem?.key || 0,
sql,
});
}}
disabled={!runState}
>
</Button>
<Button
className={styles.sqlToolBtn}
type="primary"
@@ -498,23 +516,6 @@ const SqlDetail: React.FC<IProps> = ({
</div>
</div>
</SplitPane>
{dataSourceModalVisible && (
<DataSourceCreateForm
sql={sql}
databaseItem={currentJdbcSourceItem}
dataSourceItem={dataSourceItem}
scriptColumns={scriptColumns}
onCancel={() => {
setDataSourceModalVisible(false);
}}
onSubmit={(dataSourceInfo: any) => {
setDataSourceModalVisible(false);
onSubmitSuccess?.(dataSourceInfo);
}}
createModalVisible={dataSourceModalVisible}
/>
)}
</>
);
};

View File

@@ -1,6 +1,6 @@
import React, { useState, useRef, useEffect } from 'react';
import { Tabs } from 'antd';
import SqlDetail from './SqlDetail';
import SqlDetail, { DataSourceSubmitData } from './SqlDetail';
import styles from '../style.less';
@@ -22,7 +22,7 @@ type TableRef = {
type Props = {
initialValues: any;
onSubmitSuccess?: (dataSourceInfo: any) => void;
onSubmitSuccess?: (dataSourceInfo: DataSourceSubmitData) => void;
};
const { TabPane } = Tabs;
@@ -105,7 +105,6 @@ const SqlSide: React.FC<Props> = ({ initialValues, onSubmitSuccess }) => {
})}
</Tabs>
</div>
{/* </SplitPane> */}
</>
);
};

View File

@@ -4,10 +4,11 @@ import SqlSide from './components/SqlSide';
import Pane from 'react-split-pane/lib/Pane';
import styles from './style.less';
import { RightOutlined, LeftOutlined } from '@ant-design/icons';
import { DataSourceSubmitData } from './components/SqlDetail';
type Props = {
initialValues: any;
onSubmitSuccess?: (dataSourceInfo: any) => void;
onSubmitSuccess?: (dataSourceInfo: DataSourceSubmitData) => void;
};
const DEFAULT_RIGHT_SIZE = '300px';