mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 19:51:00 +00:00
[improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab. (#63)
[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.
This commit is contained in:
@@ -34,17 +34,11 @@ const ROUTES = [
|
||||
component: './Agent',
|
||||
envEnableList: [ENV_KEY.CHAT],
|
||||
},
|
||||
{
|
||||
{
|
||||
path: '/model',
|
||||
name: 'semanticModel',
|
||||
component: './SemanticModel/DomainManager',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
routes: [
|
||||
{
|
||||
path: '/model',
|
||||
redirect: '/model/:domainId?/:modelId?/:menuKey?',
|
||||
},
|
||||
|
||||
{
|
||||
path: '/model/:domainId?/:modelId?/:menuKey?',
|
||||
component: './SemanticModel/DomainManager',
|
||||
@@ -59,6 +53,7 @@ const ROUTES = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: '/database',
|
||||
name: 'database',
|
||||
@@ -66,7 +61,6 @@ const ROUTES = [
|
||||
component: './SemanticModel/components/Database/DatabaseTable',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
|
||||
{
|
||||
path: '/metric',
|
||||
name: 'metric',
|
||||
|
||||
@@ -18,7 +18,7 @@ const GlobalHeaderRight: React.FC = () => {
|
||||
const { navTheme, layout } = initialState.settings;
|
||||
let className = styles.right;
|
||||
|
||||
if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
|
||||
if (layout === 'top' || layout === 'mix') {
|
||||
className = cx(styles.right, styles.dark);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,19 +4,21 @@ import DataSourceBasicForm from './DataSourceBasicForm';
|
||||
import FieldForm from './DataSourceFieldForm';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import { EnumDataSourceType } from '../constants';
|
||||
import type { DataInstanceItem } from '../data';
|
||||
// import type { DataInstanceItem } from '../data';
|
||||
import styles from '../style.less';
|
||||
import { createDatasource, updateDatasource, getColumns } from '../../service';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { connect } from 'umi';
|
||||
import { IDataSource } from '../../data';
|
||||
|
||||
export type CreateFormProps = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
createModalVisible: boolean;
|
||||
sql?: string;
|
||||
dataSourceItem: DataInstanceItem | any;
|
||||
databaseItem?: any;
|
||||
dataSourceItem: IDataSource.IDataSourceItem;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (dataSourceInfo: any) => void;
|
||||
scriptColumns?: any[] | undefined;
|
||||
@@ -39,6 +41,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
sql = '',
|
||||
onSubmit,
|
||||
dataSourceItem,
|
||||
databaseItem,
|
||||
basicInfoFormMode,
|
||||
}) => {
|
||||
const isEdit = !!dataSourceItem?.id;
|
||||
@@ -160,10 +163,10 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
const queryParams = {
|
||||
...submitForm,
|
||||
sqlQuery: sql,
|
||||
databaseId: dataSourceItem?.databaseId || formDatabaseId,
|
||||
databaseId: dataSourceItem?.databaseId || formDatabaseId || databaseItem?.key,
|
||||
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
|
||||
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
|
||||
modelId,
|
||||
modelId: isEdit ? dataSourceItem.modelId : modelId,
|
||||
};
|
||||
const queryDatasource = isEdit ? updateDatasource : createDatasource;
|
||||
const { code, msg, data } = await queryDatasource(queryParams);
|
||||
@@ -303,7 +306,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: currentStep === 1 ? 'block' : 'none' }}>
|
||||
<FieldForm fields={fields} onFieldChange={handleFieldChange} />;
|
||||
<FieldForm fields={fields} onFieldChange={handleFieldChange} />
|
||||
</div>
|
||||
<div style={{ display: currentStep !== 1 ? 'block' : 'none' }}>
|
||||
<DataSourceBasicForm
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { isFunction } from 'lodash';
|
||||
import FullScreen from '@/components/FullScreen';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import type { TaskResultItem, DataInstanceItem, TaskResultColumn } from '../data';
|
||||
import type { TaskResultItem, TaskResultColumn } from '../data';
|
||||
import { excuteSql } from '@/pages/SemanticModel/service';
|
||||
import DataSourceCreateForm from './DataSourceCreateForm';
|
||||
import type { Dispatch } from 'umi';
|
||||
@@ -36,7 +36,6 @@ type IProps = {
|
||||
onUpdateSql?: (sql: string) => void;
|
||||
sql?: string;
|
||||
onSubmitSuccess?: (dataSourceInfo: any) => void;
|
||||
onJdbcSourceChange?: (jdbcId: number) => void;
|
||||
};
|
||||
|
||||
type ResultTableItem = Record<string, any>;
|
||||
@@ -60,7 +59,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
onSubmitSuccess,
|
||||
sql = '',
|
||||
onUpdateSql,
|
||||
onJdbcSourceChange,
|
||||
}) => {
|
||||
const { databaseConfigList, selectModelId: modelId } = domainManger;
|
||||
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
|
||||
@@ -101,20 +99,6 @@ 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(() => {
|
||||
const list = databaseConfigList.map((item: ISemantic.IDatabaseItem) => {
|
||||
return {
|
||||
@@ -133,9 +117,12 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
}
|
||||
}
|
||||
setCurrentJdbcSourceItem(targetDataBase);
|
||||
// onJdbcSourceChange?.(targetDataBase?.key && Number(targetDataBase?.key));
|
||||
}, [dataSourceItem, databaseConfigList]);
|
||||
|
||||
useEffect(() => {
|
||||
setRunState(undefined);
|
||||
}, [currentJdbcSourceItem]);
|
||||
|
||||
function creatCalcItem(key: string, data: string) {
|
||||
const line = document.createElement('div'); // 需要每条数据一行,这样避免数据换行的时候获得的宽度不准确
|
||||
const child = document.createElement('span');
|
||||
@@ -408,9 +395,7 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
return item.key === Number(value);
|
||||
})[0];
|
||||
if (target) {
|
||||
// setJdbcSourceName(target.label);
|
||||
setCurrentJdbcSourceItem(target);
|
||||
onJdbcSourceChange?.(Number(value));
|
||||
}
|
||||
},
|
||||
}}
|
||||
@@ -520,6 +505,7 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
{dataSourceModalVisible && (
|
||||
<DataSourceCreateForm
|
||||
sql={sql}
|
||||
databaseItem={currentJdbcSourceItem}
|
||||
dataSourceItem={dataSourceItem}
|
||||
scriptColumns={scriptColumns}
|
||||
onCancel={() => {
|
||||
|
||||
@@ -43,8 +43,6 @@ const SqlSide: React.FC<Props> = ({ initialValues, onSubmitSuccess }) => {
|
||||
const tableRef: TableRef = useRef();
|
||||
const panesRef = useRef<Panes[]>(defaultPanes);
|
||||
|
||||
const [dataSourceItem, setDataSourceItem] = useState<any>(initialValues || {});
|
||||
|
||||
const updatePane = (list: Panes[]) => {
|
||||
setPanes(list);
|
||||
panesRef.current = list;
|
||||
@@ -96,16 +94,10 @@ const SqlSide: React.FC<Props> = ({ initialValues, onSubmitSuccess }) => {
|
||||
>
|
||||
<SqlDetail
|
||||
onSubmitSuccess={onSubmitSuccess}
|
||||
dataSourceItem={dataSourceItem}
|
||||
dataSourceItem={initialValues}
|
||||
onUpdateSql={(sql: string) => {
|
||||
updateTabSql(sql, pane.key);
|
||||
}}
|
||||
onJdbcSourceChange={(databaseId) => {
|
||||
setDataSourceItem({
|
||||
...dataSourceItem,
|
||||
databaseId,
|
||||
});
|
||||
}}
|
||||
sql={pane.sql}
|
||||
/>
|
||||
</TabPane>
|
||||
|
||||
@@ -101,7 +101,6 @@ const XflowJsonSchemaFormDrawerForm: React.FC<CreateFormProps> = (props) => {
|
||||
{dataSourceModalVisible && (
|
||||
<DataSourceCreateForm
|
||||
basicInfoFormMode="fast"
|
||||
domainId={Number(selectDomainId)}
|
||||
dataSourceItem={dataSourceItem}
|
||||
onCancel={() => {
|
||||
setDataSourceModalVisible(false);
|
||||
|
||||
@@ -113,15 +113,15 @@ const NodeInfoDrawer: React.FC<Props> = ({
|
||||
{
|
||||
title: '应用信息',
|
||||
children: [
|
||||
{
|
||||
label: '全路径',
|
||||
value: fullPath,
|
||||
content: (
|
||||
<Paragraph style={{ width: 275, margin: 0 }} ellipsis={{ tooltip: fullPath }}>
|
||||
{fullPath}
|
||||
</Paragraph>
|
||||
),
|
||||
},
|
||||
// {
|
||||
// label: '全路径',
|
||||
// value: fullPath,
|
||||
// content: (
|
||||
// <Paragraph style={{ width: 275, margin: 0 }} ellipsis={{ tooltip: fullPath }}>
|
||||
// {fullPath}
|
||||
// </Paragraph>
|
||||
// ),
|
||||
// },
|
||||
{
|
||||
label: '敏感度',
|
||||
value: SENSITIVE_LEVEL_ENUM[sensitiveLevel],
|
||||
|
||||
@@ -124,7 +124,6 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
<DataSourceCreateForm
|
||||
sql={fastModeSql}
|
||||
basicInfoFormMode="fast"
|
||||
domainId={Number(selectDomainId)}
|
||||
dataSourceItem={dataSourceItem}
|
||||
onCancel={() => {
|
||||
setDataSourceModalVisible(false);
|
||||
|
||||
@@ -57,7 +57,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
|
||||
const saveDimension = async (fieldsValue: any, isSilenceSubmit = false) => {
|
||||
const queryParams = {
|
||||
modelId,
|
||||
modelId: isEdit ? dimensionItem.modelId : modelId,
|
||||
type: 'categorical',
|
||||
...fieldsValue,
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
};
|
||||
|
||||
const titleRender = (node: any) => {
|
||||
const { id, name, path } = node as any;
|
||||
const { id, name, path, hasEditPermission } = node as any;
|
||||
return (
|
||||
<div className={styles.projectItem}>
|
||||
<span
|
||||
@@ -126,7 +126,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
{createDomainBtnVisible && (
|
||||
{createDomainBtnVisible && hasEditPermission && (
|
||||
<span className={styles.operation}>
|
||||
{Array.isArray(path) && path.length < 2 && (
|
||||
<PlusOutlined
|
||||
|
||||
@@ -33,12 +33,13 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
isModel,
|
||||
activeKey,
|
||||
modelList,
|
||||
domainManger,
|
||||
handleModelChange,
|
||||
onBackDomainBtnClick,
|
||||
onMenuChange,
|
||||
}) => {
|
||||
const defaultTabKey = 'xflow';
|
||||
|
||||
const { selectDomainId, domainList } = domainManger;
|
||||
const tabItem = [
|
||||
{
|
||||
label: '模型',
|
||||
@@ -62,7 +63,13 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection permissionTarget={'domain'} />,
|
||||
},
|
||||
];
|
||||
].filter((item) => {
|
||||
const target = domainList.find((domain) => domain.id === selectDomainId);
|
||||
if (target?.hasEditPermission) {
|
||||
return true;
|
||||
}
|
||||
return item.key !== 'permissonSetting';
|
||||
});
|
||||
|
||||
const isModelItem = [
|
||||
{
|
||||
|
||||
@@ -28,11 +28,10 @@ const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
{ metricList, dimensionList, domainId, entityData, chatConfigKey, chatConfigType, onSubmit },
|
||||
{ metricList, dimensionList, entityData, chatConfigKey, chatConfigType, onSubmit },
|
||||
ref,
|
||||
) => {
|
||||
const [form] = Form.useForm();
|
||||
const [metricListOptions, setMetricListOptions] = useState<any>([]);
|
||||
const [dataItemListOptions, setDataItemListOptions] = useState<any>([]);
|
||||
const formatEntityData = formatRichEntityDataListToIds(entityData);
|
||||
const getFormValidateFields = async () => {
|
||||
@@ -74,16 +73,6 @@ const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const metricOption = metricList.map((item: any) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
};
|
||||
});
|
||||
setMetricListOptions(metricOption);
|
||||
}, [metricList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(dimensionList) && Array.isArray(metricList)) {
|
||||
const dimensionEnum = dimensionList.map((item: ISemantic.IDimensionItem) => {
|
||||
@@ -141,9 +130,10 @@ const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
...formatEntityData,
|
||||
chatDefaultConfig: { ...values, ...dimensionConfig },
|
||||
};
|
||||
const { modelId } = entityData;
|
||||
const { code, msg, data } = await saveDomainExtendQuery({
|
||||
[chatConfigKey]: params,
|
||||
// domainId,
|
||||
modelId,
|
||||
id,
|
||||
});
|
||||
if (code === 200) {
|
||||
|
||||
@@ -81,7 +81,7 @@ const DimensionAndMetricVisibleModal: React.FC<Props> = ({
|
||||
if (globalKnowledgeConfigFormFields) {
|
||||
globalKnowledgeConfig = globalKnowledgeConfigFormFields;
|
||||
}
|
||||
const { id } = entityData;
|
||||
const { id, modelId } = entityData;
|
||||
let saveDomainExtendQuery = addDomainExtend;
|
||||
if (id) {
|
||||
saveDomainExtendQuery = editDomainExtend;
|
||||
@@ -126,8 +126,8 @@ const DimensionAndMetricVisibleModal: React.FC<Props> = ({
|
||||
|
||||
const { code, msg } = await saveDomainExtendQuery({
|
||||
[chatConfigKey]: params,
|
||||
// domainId,
|
||||
id,
|
||||
modelId,
|
||||
});
|
||||
if (code === 200) {
|
||||
if (!isSilenceSubmit) {
|
||||
|
||||
@@ -8,7 +8,7 @@ type Props = {
|
||||
const FormLabelRequire: React.FC<Props> = ({ title, labelStyles = {} }) => {
|
||||
return (
|
||||
<>
|
||||
<div className="ant-col ant-form-item-label">
|
||||
<div className="ant-col ant-form-item-label" style={{ padding: 0 }}>
|
||||
<label
|
||||
htmlFor="description"
|
||||
className="ant-form-item-required"
|
||||
|
||||
@@ -136,7 +136,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
sensitiveLevel,
|
||||
description,
|
||||
// isPercent,
|
||||
dataFormatType,
|
||||
dataFormatType: dataFormatType || '',
|
||||
alias: alias && alias.trim() ? alias.split(',') : [],
|
||||
dataFormat: dataFormat || {
|
||||
decimalPlaces: 2,
|
||||
@@ -163,7 +163,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
|
||||
const saveMetric = async (fieldsValue: any) => {
|
||||
const queryParams = {
|
||||
modelId,
|
||||
modelId: isEdit ? metricItem.modelId : modelId,
|
||||
...fieldsValue,
|
||||
};
|
||||
const { typeParams, alias, dataFormatType } = queryParams;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Form, Button, Modal, Input, Switch } from 'antd';
|
||||
import { Form, Button, Modal, Input, Switch, Select } from 'antd';
|
||||
import styles from './style.less';
|
||||
import { message } from 'antd';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
@@ -22,13 +22,20 @@ const ModelCreateFormModal: React.FC<ModelCreateFormModalProps> = (props) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue(basicInfo);
|
||||
form.setFieldsValue({
|
||||
...basicInfo,
|
||||
alias: basicInfo?.alias && basicInfo.alias.trim() ? basicInfo.alias.split(',') : [],
|
||||
});
|
||||
}, [basicInfo]);
|
||||
|
||||
const handleConfirm = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
const columnsValue = { ...fieldsValue, isUnique: 1, domainId };
|
||||
const submitData = { ...formVals, ...columnsValue };
|
||||
const submitData = {
|
||||
...formVals,
|
||||
...columnsValue,
|
||||
alias: Array.isArray(fieldsValue.alias) ? fieldsValue.alias.join(',') : '',
|
||||
};
|
||||
setFormVals(submitData);
|
||||
setSaveLoading(true);
|
||||
const { code, msg } = await (!submitData.id ? createModel : updateModel)(submitData);
|
||||
@@ -81,6 +88,14 @@ const ModelCreateFormModal: React.FC<ModelCreateFormModalProps> = (props) => {
|
||||
>
|
||||
<Input placeholder="请输入模型英文名称" />
|
||||
</FormItem>
|
||||
<FormItem name="alias" label="别名">
|
||||
<Select
|
||||
mode="tags"
|
||||
placeholder="输入别名后回车确认,多别名输入、复制粘贴支持英文逗号自动分隔"
|
||||
tokenSeparators={[',']}
|
||||
maxTagCount={9}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="description" label="模型描述">
|
||||
<Input.TextArea placeholder="模型描述" />
|
||||
</FormItem>
|
||||
|
||||
@@ -141,24 +141,28 @@ const PermissionCreateDrawer: React.FC<Props> = ({
|
||||
<DimensionMetricVisibleTransfer
|
||||
titles={['未授权维度/指标', '已授权维度/指标']}
|
||||
sourceList={[
|
||||
...dimensionList.map((item) => {
|
||||
const transType = TransType.DIMENSION;
|
||||
const { id } = item;
|
||||
return {
|
||||
...item,
|
||||
transType,
|
||||
key: wrapperTransTypeAndId(transType, id),
|
||||
};
|
||||
}),
|
||||
...metricList.map((item) => {
|
||||
const transType = TransType.METRIC;
|
||||
const { id } = item;
|
||||
return {
|
||||
...item,
|
||||
transType,
|
||||
key: wrapperTransTypeAndId(transType, id),
|
||||
};
|
||||
}),
|
||||
...dimensionList
|
||||
.map((item) => {
|
||||
const transType = TransType.DIMENSION;
|
||||
const { id } = item;
|
||||
return {
|
||||
...item,
|
||||
transType,
|
||||
key: wrapperTransTypeAndId(transType, id),
|
||||
};
|
||||
})
|
||||
.filter((item) => item.sensitiveLevel === 2),
|
||||
...metricList
|
||||
.map((item) => {
|
||||
const transType = TransType.METRIC;
|
||||
const { id } = item;
|
||||
return {
|
||||
...item,
|
||||
transType,
|
||||
key: wrapperTransTypeAndId(transType, id),
|
||||
};
|
||||
})
|
||||
.filter((item) => item.sensitiveLevel === 2),
|
||||
]}
|
||||
targetList={selectedKeyList}
|
||||
onChange={(newTargetKeys: string[]) => {
|
||||
|
||||
@@ -60,6 +60,7 @@ export declare namespace IDataSource {
|
||||
name: string;
|
||||
bizName: string;
|
||||
description: string;
|
||||
modelId: number;
|
||||
status: number | null;
|
||||
sensitiveLevel: SensitiveLevel;
|
||||
domainId: number;
|
||||
@@ -79,6 +80,7 @@ export declare namespace ISemantic {
|
||||
name: string;
|
||||
bizName: string;
|
||||
description: any;
|
||||
hasEditPermission: boolean;
|
||||
status?: number;
|
||||
typeEnum?: any;
|
||||
sensitiveLevel?: number;
|
||||
@@ -135,6 +137,7 @@ export declare namespace ISemantic {
|
||||
expr: string;
|
||||
fullPath: string;
|
||||
datasourceId: number;
|
||||
modelId: number;
|
||||
datasourceName: string;
|
||||
datasourceBizName: string;
|
||||
semanticType: string;
|
||||
@@ -178,6 +181,7 @@ export declare namespace ISemantic {
|
||||
sensitiveLevel: number;
|
||||
domainId: number;
|
||||
domainName: string;
|
||||
modelId: number;
|
||||
type: string;
|
||||
typeParams: ITypeParams;
|
||||
fullPath: string;
|
||||
|
||||
Reference in New Issue
Block a user