[improvement][headless-fe] Term management interface transformation & Unified model management and canvas functionality entry (#1009)

* [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

* [improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component.

* [improvement][semantic-fe] Adding the ability to filter dimensions based on whether they are tags or not.

* [improvement][semantic-fe] Adding the ability to edit relationships between models in the canvas.

* [improvement][semantic-fe] Updating the datePicker component to use dayjs instead.

* [improvement][semantic-fe] Fixing the issue with passing the model ID for dimensions in the indicator market.

* [improvement][semantic-fe] Fixing the abnormal state of the popup when creating a model.

* [improvement][semantic-fe] Adding permission logic for bulk operations in the indicator market.

* [improvement][semantic-fe] Adding the ability to download and transpose data.

* [improvement][semantic-fe] Fixing the initialization issue with the date selection component in the indicator details page when switching time granularity.

* [improvement][semantic-fe] Fixing the logic error in the dimension value setting.

* [improvement][semantic-fe] Fixing the synchronization issue with the question and answer settings information.

* [improvement][semantic-fe] Optimizing the canvas functionality for better performance and user experience.

* [improvement][semantic-fe] Optimizing the update process for drawing model relationship edges in the canvas.

* [improvement][semantic-fe] Changing the line type for canvas connections.

* [improvement][semantic-fe] Replacing the initialization variable from "semantic" to "headless".

* [improvement][semantic-fe] Fixing the missing migration issue for default drill-down dimension configuration in model editing. Additionally, optimizing the data retrieval method for initializing fields in the model.

* [improvement][semantic-fe] Updating the logic for the fieldName.

* [improvement][semantic-fe] Adjusting the position of the metrics tab.

* [improvement][semantic-fe] Changing the 字段名称 to 英文名称.

* [improvement][semantic-fe] Fix metric measurement deletion.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI adjustment for metric details page.

* [improvement][semantic-fe] The granularity field in the time type of model editing now supports setting it as empty.

* [improvement][semantic-fe] Added field type and metric type to the metric creation options.

* [improvement][semantic-fe] The organization structure selection feature has been added to the permission management.

* [improvement][semantic-fe] Improved user experience for the metric list.

* [improvement][semantic-fe] fix update the metric list.

* [improvement][headless-fe] Added view management functionality.

* [improvement][headless-fe] The view management functionality has been added. This feature allows users to create, edit, and manage different views within the system.

* [improvement][headless-fe] Added model editing side effect detection.

* [improvement][headless-fe] Fixed the logic error in view editing.

* [improvement][headless-fe] Fixed the issue with initializing dimension associations in metric settings.

* [improvement][headless-fe] Added the ability to hide the Q&A settings entry point.

* [improvement][headless-fe] Fixed the issue with selecting search results in metric field creation.

* [improvement][headless-fe] Added search functionality to the field list in model editing.

* [improvement][headless-fe] fix the field list in model editing

* [improvement][headless-fe] Restructured the data for the dimension value settings interface.

* [improvement][headless-fe] Added dynamic variable functionality to model creation based on SQL scripts.

* [improvement][headless-fe] Added support for passing dynamic variables as parameters in the executeSql function.

* [improvement][headless-fe] Resolved the issue where users were unable to select all options for dimensions, metrics, and fields in the metric generation process.

* [improvement][headless-fe] Replaced the term "view" with "dataset"

* [improvement][headless-fe] Added the ability to export metrics and dimensions to a specific target.

* [improvement][headless-fe] Enhanced dataset creation to support the tag mode.

* [improvement][headless-fe] Added tag value setting.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Updated the data initialization for model editing to use API requests instead.

* [improvement][headless-fe] Added search functionality to model management.

* [improvement][headless-fe] Removed field null validation during model editing.

* [improvement][headless-fe] Updated the batch operation button component.

* [improvement][headless-fe] Optimized the logic for initializing indicators in dimension value settings.

* [improvement][headless-fe] Adjusted the length of the input field for model editing names.

* [improvement][headless-fe]  Lock the version of the @ant-design/pro-table component and replace it with @ant-design/pro-components.

* [improvement][headless-fe] Optimized the style of the metrics market and tags market.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] Fixed the issue where the conditions for metric measurement creation were not being saved correctly.

* [improvement][headless-fe] Default value setting for hiding dimensions.

* [improvement][headless-fe] Updated the file imports in the project.

* [improvement][headless-fe] Adjusted the logic for displaying the tab in the theme domain.

* [improvement][headless-fe] Added term management functionality.

* [improvement][headless-fe] When creating a model, the current metric operator now allows for clearance.

* [improvement][headless-fe] Term management interface transformation
This commit is contained in:
tristanliu
2024-05-20 12:03:30 +08:00
committed by GitHub
parent 542121210e
commit 2d8c5c379c
12 changed files with 156 additions and 93 deletions

View File

@@ -67,7 +67,13 @@ const MetricAddClass: React.FC<Props> = ({ ids = [], createModalVisible, onCance
>
</Button>
<Button type="primary" loading={saveLoading} onClick={handleSubmit}>
<Button
type="primary"
loading={saveLoading}
onClick={() => {
handleSubmit();
}}
>
</Button>
</>

View File

@@ -64,6 +64,12 @@ const MetricBasicInformation: React.FC<Props> = ({ metircData }) => {
dataIndex: 'agg',
title: '聚合函数',
width: 80,
render: (_: string) => {
if (!_) {
return '--';
}
return _;
},
},
];

View File

@@ -189,9 +189,9 @@ const TrendChart: React.FC<Props> = ({
(item: any) =>
`<div style="margin-top: 3px;">${
item.marker
} <span style="display: inline-block; width: 70px; margin-right: 5px;">${
} <span style="display: inline-block; width: 100px; margin-right: 5px;">${
item.seriesName
}</span><span style="display: inline-block; width: 90px; text-align: right; font-weight: 500;">${
}</span><span style="display: inline-block; width: 120px; text-align: right; font-weight: 500;">${
item.value === ''
? '-'
: isPer

View File

@@ -13,7 +13,7 @@ import { ColumnConfig } from '../data';
import dayjs from 'dayjs';
import { ISemantic } from '../../data';
import { DateFieldMap } from '@/pages/SemanticModel/constant';
import { ProCard } from '@ant-design/pro-components';
import { ProCard } from '@ant-design/pro-components';
import styles from '../style.less';
@@ -100,7 +100,7 @@ const MetricTrendSection: React.FC<Props> = ({
setMetricTrendLoading(false);
if (code === 200) {
const { resultList, columns, queryAuthorization } = data;
setMetricTrendData(resultList);
setTableColumnConfig(columns);
const message = queryAuthorization?.message;
if (message) {
@@ -112,6 +112,22 @@ const MetricTrendSection: React.FC<Props> = ({
if (targetConfig) {
setMetricColumnConfig(targetConfig);
}
const dateConfig = columns.find((item: ISemantic.IMetricTrendColumn) => {
return item.type === 'DATE';
});
if (dateConfig) {
const sortDateField = dateConfig.nameEn;
setMetricTrendData(
[...resultList].sort((a, b) => {
return a[sortDateField].localeCompare(b[sortDateField]);
}),
);
} else {
setMetricTrendData(resultList);
}
setDownloadBtnDisabledState(false);
if (dimensionGroup[dimensionGroup.length - 1]) {
setGroupByDimensionFieldName(dimensionGroup[dimensionGroup.length - 1]);

View File

@@ -67,7 +67,6 @@ const DatabaseSettingModal: React.FC<CreateFormProps> = ({
<DatabaseCreateForm
hideSubmitBtn={true}
ref={createFormRef}
// dataBaseConfig={databaseItem}
databaseId={databaseItem?.id}
onSubmit={() => {
onSubmit?.();

View File

@@ -4,17 +4,16 @@ import styles from './style.less';
import { useMounted } from '@/hooks/useMounted';
import { message } from 'antd';
import { formLayout } from '@/components/FormHelper/utils';
import { EnumTransModelType } from '@/enum';
const FormItem = Form.Item;
export type ProjectInfoFormProps = {
export type Props = {
basicInfo: any;
onCancel: () => void;
onSubmit: (values: any) => Promise<any>;
};
const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
const DomaintInfoForm: React.FC<Props> = (props) => {
const { basicInfo, onSubmit: handleUpdate, onCancel } = props;
const { type, modelType } = basicInfo;
@@ -48,23 +47,13 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
</>
);
const titleRender = () => {
let str = EnumTransModelType[modelType];
if (type === 'top') {
str += '顶级';
} else if (modelType === 'add') {
str += '子';
}
str += '主题域';
return str;
};
const infoName = type === 'top' ? '主题域' : '模型集';
return (
<Modal
width={640}
styles={{ padding: '32px 40px 48px' }}
destroyOnClose
title={titleRender()}
title={`${modelType === 'add' ? '新增' : '编辑'}${infoName}`}
open={true}
footer={footer}
onCancel={onCancel}
@@ -78,26 +67,26 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
className={styles.form}
>
{type !== 'top' && modelType === 'add' && (
<FormItem name="parentName" label="主题域名称">
<Input disabled placeholder="主题域名称" />
<FormItem name="parentName" label="主题域名称">
<Input disabled placeholder="主题域名称" />
</FormItem>
)}
<FormItem
name="name"
label="主题域名称"
rules={[{ required: true, message: '请输入主题域名称!' }]}
label={`${infoName}名称`}
rules={[{ required: true, message: `请输入${infoName}名称!` }]}
>
<Input placeholder="主题域名称不可重复" />
</FormItem>
<FormItem
name="bizName"
label="主题域英文名称"
rules={[{ required: true, message: '请输入主题域英文名称!' }]}
label={`${infoName}英文名称`}
rules={[{ required: true, message: `请输入${infoName}英文名称!` }]}
>
<Input placeholder="请输入主题域英文名称" />
<Input placeholder={`请输入${infoName}英文名称`} />
</FormItem>
<FormItem name="description" label="主题域描述" hidden={true}>
<Input.TextArea placeholder="主题域描述" />
<FormItem name="description" label={`${infoName}描述`} hidden={true}>
<Input.TextArea placeholder={`${infoName}描述`} />
</FormItem>
<FormItem name="isUnique" label="是否唯一" hidden={true}>
<Switch size="small" checked={true} />
@@ -107,4 +96,4 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
);
};
export default ProjectInfoForm;
export default DomaintInfoForm;

View File

@@ -8,7 +8,7 @@ import type { Dispatch } from 'umi';
import type { StateType } from '../model';
import { createDomain, updateDomain, deleteDomain } from '../service';
import { treeParentKeyLists } from '../utils';
import ProjectInfoFormProps from './ProjectInfoForm';
import DomainInfoForm from './DomainInfoForm';
import { constructorClassTreeFromList, addPathInTreeData } from '../utils';
import styles from './style.less';
@@ -49,11 +49,10 @@ const DomainListTree: FC<DomainListProps> = ({
onCreateDomainBtnClick,
onTreeSelected,
onTreeDataUpdate,
dispatch,
}) => {
const [projectTree, setProjectTree] = useState<DataNode[]>([]);
const [projectInfoModalVisible, setProjectInfoModalVisible] = useState<boolean>(false);
const [projectInfoParams, setProjectInfoParams] = useState<any>({});
const [domainInfoParams, setDomainInfoParams] = useState<any>({});
const [filterValue, setFliterValue] = useState<string>('');
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
const [classList, setClassList] = useState<ISemantic.IDomainItem[]>([]);
@@ -91,9 +90,26 @@ const DomainListTree: FC<DomainListProps> = ({
}
};
const projectSubmit = async (values: any) => {
const createDefaultModelSet = async (domainId: number) => {
const { code, msg } = await createDomain({
modelType: 'add',
type: 'normal',
parentId: domainId,
name: '默认模型集',
bizName: 'defaultModelSet',
isUnique: 1,
});
if (code !== 200) {
message.error(msg);
}
};
const domainSubmit = async (values: any) => {
if (values.modelType === 'add') {
await createDomain(values);
const { code, data } = await createDomain(values);
if (code === 200 && values.type === 'top') {
await createDefaultModelSet(data.id);
}
} else if (values.modelType === 'edit') {
await editProject(values);
}
@@ -101,11 +117,10 @@ const DomainListTree: FC<DomainListProps> = ({
setProjectInfoModalVisible(false);
};
// 删除项目
const confirmDelete = async (projectId: string) => {
const res = await deleteDomain(projectId);
const confirmDelete = async (domainId: string) => {
const res = await deleteDomain(domainId);
if (res.code === 200) {
message.success('编辑项目成功');
message.success('删除成功');
setProjectInfoModalVisible(false);
onTreeDataUpdate?.();
} else {
@@ -131,7 +146,7 @@ const DomainListTree: FC<DomainListProps> = ({
<PlusOutlined
className={styles.icon}
onClick={() => {
setProjectInfoParams({
setDomainInfoParams({
modelType: 'add',
type: 'normal',
parentId: id,
@@ -145,7 +160,7 @@ const DomainListTree: FC<DomainListProps> = ({
<EditOutlined
className={styles.icon}
onClick={() => {
setProjectInfoParams({
setDomainInfoParams({
modelType: 'edit',
type: 'normal',
...node,
@@ -190,13 +205,13 @@ const DomainListTree: FC<DomainListProps> = ({
</Col>
{createDomainBtnVisible && (
<Col flex="0 0 45px" style={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="新增顶级域">
<Tooltip title="新增主题域">
<Button
type="primary"
icon={<PlusOutlined />}
size="small"
onClick={() => {
setProjectInfoParams({ type: 'top', modelType: 'add' });
setDomainInfoParams({ type: 'top', modelType: 'add' });
setProjectInfoModalVisible(true);
onCreateDomainBtnClick?.();
}}
@@ -218,9 +233,9 @@ const DomainListTree: FC<DomainListProps> = ({
titleRender={titleRender}
/>
{projectInfoModalVisible && (
<ProjectInfoFormProps
basicInfo={projectInfoParams}
onSubmit={projectSubmit}
<DomainInfoForm
basicInfo={domainInfoParams}
onSubmit={domainSubmit}
onCancel={() => {
setProjectInfoModalVisible(false);
}}

View File

@@ -1,5 +1,5 @@
import { Tabs, Breadcrumb, Space } from 'antd';
import React, { useRef, useEffect } from 'react';
import { Tabs, Breadcrumb, Space, Radio } from 'antd';
import React, { useRef, useEffect, useState } from 'react';
import { connect, history } from 'umi';
import ClassDimensionTable from './ClassDimensionTable';
@@ -55,6 +55,8 @@ const DomainManagerTab: React.FC<Props> = ({
initState.current = false;
}, [selectModelId]);
const [showModelType, setShowModelType] = useState<string>('list');
const domainListParentIdList: number[] = Array.isArray(domainList)
? Array.from(new Set(domainList.map((item) => item.parentId)))
: [];
@@ -64,15 +66,21 @@ const DomainManagerTab: React.FC<Props> = ({
label: '模型管理',
key: 'overview',
hidden: domainData && domainListParentIdList.includes(domainData.id),
children: (
<OverView
key={selectDomainId}
modelList={modelList}
onModelChange={(model) => {
handleModelChange(model);
}}
/>
),
children:
showModelType === 'list' ? (
<OverView
key={selectDomainId}
modelList={modelList}
onModelChange={(model) => {
handleModelChange(model);
}}
/>
) : (
<div style={{ width: '100%' }}>
<SemanticGraphCanvas />
{/* <HeadlessFlows /> */}
</div>
),
},
{
label: '数据集管理',
@@ -99,17 +107,17 @@ const DomainManagerTab: React.FC<Props> = ({
hidden: !!domainData?.parentId,
children: <TermTable />,
},
{
label: '画布',
key: 'xflow',
hidden: domainData && domainListParentIdList.includes(domainData.id),
children: (
<div style={{ width: '100%' }}>
<SemanticGraphCanvas />
{/* <HeadlessFlows /> */}
</div>
),
},
// {
// label: '画布',
// key: 'xflow',
// hidden: domainData && domainListParentIdList.includes(domainData.id),
// children: (
// <div style={{ width: '100%' }}>
// <SemanticGraphCanvas />
// {/* <HeadlessFlows /> */}
// </div>
// ),
// },
{
label: '权限管理',
key: 'permissonSetting',
@@ -212,6 +220,24 @@ const DomainManagerTab: React.FC<Props> = ({
className={styles.tab}
items={!isModel ? tabItem : isModelItem}
activeKey={getActiveKey()}
tabBarExtraContent={{
right:
getActiveKey() === 'overview' ? (
<Radio.Group
defaultValue="list"
buttonStyle="solid"
size="small"
style={{ marginRight: 25 }}
onChange={(e) => {
const showType = e.target.value;
setShowModelType(showType);
}}
>
<Radio.Button value="list"></Radio.Button>
<Radio.Button value="canvas"></Radio.Button>
</Radio.Group>
) : undefined,
}}
destroyInactiveTabPane
size="large"
onChange={(menuKey: string) => {

View File

@@ -1,9 +1,7 @@
import React, { useEffect, useRef } from 'react';
import { Form, Button, Modal, Input, Select } from 'antd';
import { formLayout } from '@/components/FormHelper/utils';
import styles from '../style.less';
import { ISemantic } from '../../data';
export type CreateFormProps = {
@@ -62,11 +60,7 @@ const TermCreateForm: React.FC<CreateFormProps> = ({
<FormItem name="name" label="名称" rules={[{ required: true, message: '请输入名称' }]}>
<Input placeholder="名称不可重复" />
</FormItem>
<FormItem
name="similarTerms"
label={'近义词'}
rules={[{ required: true, message: '请输入业务口径' }]}
>
<FormItem name="alias" label={'近义词'}>
<Select
mode="tags"
placeholder="输入近义词后回车确认,多近义词输入、复制粘贴支持英文逗号自动分隔"
@@ -74,7 +68,11 @@ const TermCreateForm: React.FC<CreateFormProps> = ({
maxTagCount={9}
/>
</FormItem>
<FormItem name="description" label={'描述'}>
<FormItem
name="description"
label={'描述'}
rules={[{ required: true, message: '请输入描述' }]}
>
<TextArea placeholder="请输入描述" />
</FormItem>
</>

View File

@@ -4,7 +4,7 @@ import { message, Button, Space, Popconfirm, Typography } from 'antd';
import React, { useRef, useState, useEffect } from 'react';
import { connect } from 'umi';
import type { StateType } from '../../model';
import { getTermList, saveOrUpdate } from '../../service';
import { getTermList, saveOrUpdate, deleteTerm } from '../../service';
import styles from '../style.less';
import { ISemantic } from '../../data';
@@ -36,21 +36,21 @@ const TermTable: React.FC<Props> = ({ domainManger }) => {
const { code, data, msg } = await getTermList(selectDomainId);
setLoading(false);
if (code === 200) {
setTableData(data?.terms || []);
setTableData(data || []);
} else {
message.error(msg);
setTableData([]);
}
};
const queryTermConfig = async (terms: ISemantic.ITermItem[]) => {
const queryTermConfig = async (terms: ISemantic.ITermItem) => {
const { code, msg } = await saveOrUpdate({
domainId: selectDomainId,
terms,
...terms,
});
setLoading(false);
if (code === 200) {
setTableData(terms);
queryTagList();
} else {
message.error(msg);
}
@@ -75,9 +75,13 @@ const TermTable: React.FC<Props> = ({ domainManger }) => {
queryTermConfig(terms);
};
const deleteTermConfig = (termItem: ISemantic.ITermItem) => {
const terms = tableData.filter((item) => item.name !== termItem.name);
queryTermConfig(terms);
const deleteTermConfig = async (termItem: ISemantic.ITermItem) => {
const { code, msg } = await deleteTerm(termItem.id);
if (code === 200) {
queryTagList();
} else {
message.error(msg);
}
};
const columnsConfig = ColumnsConfig();
@@ -89,17 +93,14 @@ const TermTable: React.FC<Props> = ({ domainManger }) => {
search: false,
},
{
dataIndex: 'similarTerms',
dataIndex: 'alias',
title: '近义词',
search: false,
render: (_: string[]) => {
const similarTerms = Array.isArray(_) ? _.join(',') : '-';
const alias = Array.isArray(_) ? _.join(',') : '-';
return (
<Paragraph
ellipsis={{ tooltip: similarTerms, rows: 3 }}
style={{ width: 350, marginBottom: 0 }}
>
{similarTerms}
<Paragraph ellipsis={{ tooltip: alias, rows: 3 }} style={{ width: 350, marginBottom: 0 }}>
{alias}
</Paragraph>
);
},
@@ -182,7 +183,7 @@ const TermTable: React.FC<Props> = ({ domainManger }) => {
createModalVisible={createModalVisible}
termItem={termItem}
onSubmit={(termData) => {
saveTermConfig(termData);
queryTermConfig(termData);
setCreateModalVisible(false);
}}
onCancel={() => {

View File

@@ -436,6 +436,7 @@ export declare namespace ISemantic {
}
interface ITermItem {
id: number;
name: string;
description: string;
similarTerms: string[];

View File

@@ -741,3 +741,9 @@ export function saveOrUpdate(data: any): Promise<any> {
data: { ...data },
});
}
export function deleteTerm(id: number): Promise<any> {
return request(`${process.env.API_BASE_URL}term/${id}`, {
method: 'DELETE',
});
}