semantic-fe visual modeling pr (#21)

* [improvement][semantic-fe] Added an editing component to set filtering rules for Q&A. Now, the SQL editor will be accompanied by a list for display and control, to resolve ambiguity when using comma-separated values.
[improvement][semantic-fe] Improved validation logic and prompt copywriting for data source/dimension/metric editing and creation.
[improvement][semantic-fe] Improved user experience for visual modeling. Now, when using the legend to control the display/hide of data sources and their associated metric dimensions, the canvas will be re-layout based on the activated data source in the legend.

* [improvement][semantic-fe] Submitted a new version of the visual modeling tool.
[improvement][semantic-fe] Fixed an issue with the initialization of YoY and MoM metrics in Q&A settings.
[improvement][semantic-fe] Added a version field to the database settings.
[improvement][semantic-fe] 1. Added the ability to set YoY and MoM metrics in Q&A settings.2. Moved dimension value editing from the dimension editing window to the dimension list.

---------

Co-authored-by: tristanliu <tristanliu@tencent.com>
This commit is contained in:
tristanliu
2023-07-31 11:23:37 +08:00
committed by GitHub
parent e2b2d31429
commit 0ac652c5d9
50 changed files with 2375 additions and 1188 deletions

View File

@@ -1,5 +1,6 @@
import { ISemantic, IDataSource } from '../data';
import { ISemantic } from '../data';
import { SemanticNodeType } from '../enum';
import { TreeGraphData } from '@antv/g6-core';
export const typeConfigs = {
datasource: {
@@ -11,6 +12,7 @@ export const typeConfigs = {
export const getDimensionChildren = (
dimensions: ISemantic.IDimensionItem[],
dataSourceNodeId: string,
limit: number = 999,
) => {
const dimensionChildrenList = dimensions.reduce(
(dimensionChildren: any[], dimension: ISemantic.IDimensionItem) => {
@@ -19,7 +21,7 @@ export const getDimensionChildren = (
...dimension,
nodeType: SemanticNodeType.DIMENSION,
legendType: dataSourceNodeId,
id: `${SemanticNodeType.DIMENSION}-${id}`,
id: `${dataSourceNodeId}-${SemanticNodeType.DIMENSION}-${id}`,
uid: id,
style: {
lineWidth: 2,
@@ -31,10 +33,14 @@ export const getDimensionChildren = (
},
[],
);
return dimensionChildrenList;
return dimensionChildrenList.slice(0, limit);
};
export const getMetricChildren = (metrics: ISemantic.IMetricItem[], dataSourceNodeId: string) => {
export const getMetricChildren = (
metrics: ISemantic.IMetricItem[],
dataSourceNodeId: string,
limit: number = 999,
) => {
const metricsChildrenList = metrics.reduce(
(metricsChildren: any[], metric: ISemantic.IMetricItem) => {
const { id } = metric;
@@ -42,7 +48,7 @@ export const getMetricChildren = (metrics: ISemantic.IMetricItem[], dataSourceNo
...metric,
nodeType: SemanticNodeType.METRIC,
legendType: dataSourceNodeId,
id: `${SemanticNodeType.METRIC}-${id}`,
id: `${dataSourceNodeId}-${SemanticNodeType.METRIC}-${id}`,
uid: id,
style: {
lineWidth: 2,
@@ -54,40 +60,50 @@ export const getMetricChildren = (metrics: ISemantic.IMetricItem[], dataSourceNo
},
[],
);
return metricsChildrenList;
return metricsChildrenList.slice(0, limit);
};
export const formatterRelationData = (
dataSourceList: IDataSource.IDataSourceItem[],
type: SemanticNodeType = SemanticNodeType.DIMENSION,
) => {
const relationData = dataSourceList.reduce((relationList: any[], item: any) => {
const { datasource, dimensions, metrics } = item;
const { id } = datasource;
const dataSourceNodeId = `${SemanticNodeType.DATASOURCE}-${id}`;
let childrenList = [];
if (type === SemanticNodeType.METRIC) {
childrenList = getMetricChildren(metrics, dataSourceNodeId);
}
if (type === SemanticNodeType.DIMENSION) {
childrenList = getDimensionChildren(dimensions, dataSourceNodeId);
}
relationList.push({
...datasource,
legendType: dataSourceNodeId,
id: dataSourceNodeId,
uid: id,
nodeType: SemanticNodeType.DATASOURCE,
size: 40,
children: [...childrenList],
style: {
lineWidth: 2,
fill: '#BDEFDB',
stroke: '#5AD8A6',
},
});
return relationList;
}, []);
export const formatterRelationData = (params: {
dataSourceList: ISemantic.IDomainSchemaRelaList;
limit?: number;
type?: SemanticNodeType;
}): TreeGraphData[] => {
const { type, dataSourceList, limit } = params;
const relationData = dataSourceList.reduce(
(relationList: TreeGraphData[], item: ISemantic.IDomainSchemaRelaItem) => {
const { datasource, dimensions, metrics } = item;
const { id } = datasource;
const dataSourceNodeId = `${SemanticNodeType.DATASOURCE}-${id}`;
let childrenList = [];
if (type === SemanticNodeType.METRIC) {
childrenList = getMetricChildren(metrics, dataSourceNodeId, limit);
}
if (type === SemanticNodeType.DIMENSION) {
childrenList = getDimensionChildren(dimensions, dataSourceNodeId, limit);
}
if (!type) {
const dimensionList = getDimensionChildren(dimensions, dataSourceNodeId, limit);
const metricList = getMetricChildren(metrics, dataSourceNodeId, limit);
childrenList = [...dimensionList, ...metricList];
}
relationList.push({
...datasource,
legendType: dataSourceNodeId,
id: dataSourceNodeId,
uid: id,
nodeType: SemanticNodeType.DATASOURCE,
size: 40,
children: [...childrenList],
style: {
lineWidth: 2,
fill: '#BDEFDB',
stroke: '#5AD8A6',
},
});
return relationList;
},
[],
);
return relationData;
};
@@ -121,6 +137,11 @@ export const getNodeConfigByType = (nodeData: any, defaultConfig = {}) => {
case SemanticNodeType.METRIC:
return {
...defaultConfig,
style: {
lineWidth: 2,
fill: '#fffbe6',
stroke: '#ffe58f',
},
labelCfg: { position: 'right', ...labelCfg },
};
default:
@@ -137,3 +158,37 @@ export const flatGraphDataNode = (graphData: any[]) => {
return nodeList;
}, []);
};
interface Node {
label: string;
children?: Node[];
}
export const findNodesByLabel = (query: string, nodes: Node[]): Node[] => {
const result: Node[] = [];
for (const node of nodes) {
let match = false;
let children: Node[] = [];
// 如果节点的label包含查询字符串我们将其标记为匹配
if (node.label.includes(query)) {
match = true;
}
// 我们还需要在子节点中进行搜索
if (node.children) {
children = findNodesByLabel(query, node.children);
if (children.length > 0) {
match = true;
}
}
// 如果节点匹配或者其子节点匹配,我们将其添加到结果中
if (match) {
result.push({ ...node, children });
}
}
return result;
};