mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-14 13:47:09 +00:00
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:
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user