mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-30 04:54:25 +08:00
Compare commits
9 Commits
56cfddea60
...
v0.9.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7ce9480bb | ||
|
|
f8104687cc | ||
|
|
6eba693982 | ||
|
|
b871ae542a | ||
|
|
3ca48e1ca1 | ||
|
|
ea7238304d | ||
|
|
1746db53c1 | ||
|
|
90c2f8b374 | ||
|
|
bd64bf1f62 |
@@ -55,8 +55,8 @@ if "%command%"=="restart" (
|
||||
set "webDir=%baseDir%\webapp"
|
||||
set "logDir=%baseDir%\logs"
|
||||
set "classpath=%baseDir%;%webDir%;%libDir%\*;%confDir%"
|
||||
set "java-command=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile% -Xms1024m
|
||||
-Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||
set "property=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile%"
|
||||
set "java-command=%property% -Xms1024m -Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||
if not exist %logDir% mkdir %logDir%
|
||||
start /B java %java-command% >nul 2>&1
|
||||
timeout /t 10 >nul
|
||||
|
||||
@@ -3,11 +3,13 @@ package com.tencent.supersonic.common.pojo;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
||||
|
||||
@Data
|
||||
public class Order {
|
||||
public class Order implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotBlank(message = "Invalid order column")
|
||||
private String column;
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
# Use an official OpenJDK runtime as a parent image
|
||||
FROM openjdk:21-jdk-bullseye
|
||||
FROM supersonicbi/supersonic:0.9.10-SNAPSHOT
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Delete old supersonic installation directory and the symbolic link
|
||||
RUN rm -rf /usr/src/app/supersonic-standalone-0.9.10-SNAPSHOT
|
||||
RUN rm -f /usr/src/app/supersonic-standalone-latest
|
||||
|
||||
# Argument to pass in the supersonic version at build time
|
||||
ARG SUPERSONIC_VERSION
|
||||
|
||||
# Install necessary packages, including Postgres client
|
||||
RUN apt-get update && apt-get install -y postgresql-client
|
||||
|
||||
# Install the vim editor.
|
||||
RUN apt-get update && apt-get install -y vim && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Update the package list and install iputils-ping.
|
||||
RUN apt-get update && apt-get install -y iputils-ping
|
||||
|
||||
# 更新包列表并安装 dnsutils 包
|
||||
RUN apt-get update && apt-get install -y dnsutils
|
||||
|
||||
# Copy the supersonic standalone zip file into the container
|
||||
COPY assembly/build/supersonic-standalone-${SUPERSONIC_VERSION}.zip .
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
- 8.8.4.4
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "sh -c 'pg_isready -U supersonic_user -d postgres'"]
|
||||
interval: 30s
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
|
||||
|
||||
@@ -133,6 +133,10 @@
|
||||
<groupId>io.trino</groupId>
|
||||
<artifactId>trino-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.tencent.supersonic.headless.core.translator.parser.calcite;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.tencent.supersonic.common.calcite.Configuration;
|
||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
||||
@@ -9,17 +10,26 @@ import com.tencent.supersonic.headless.api.pojo.response.DatabaseResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DimSchemaResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.MetricSchemaResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.ModelResp;
|
||||
import com.tencent.supersonic.headless.core.pojo.*;
|
||||
import com.tencent.supersonic.headless.core.pojo.JoinRelation;
|
||||
import com.tencent.supersonic.headless.core.pojo.Ontology;
|
||||
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||
import com.tencent.supersonic.headless.core.pojo.QueryStatement;
|
||||
import com.tencent.supersonic.headless.core.translator.parser.Constants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.calcite.sql.*;
|
||||
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
|
||||
import org.apache.calcite.sql.parser.SqlParseException;
|
||||
import org.apache.calcite.sql.parser.SqlParser;
|
||||
import org.apache.calcite.sql.parser.SqlParserPos;
|
||||
import org.apache.calcite.sql.validate.SqlValidatorScope;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.GraphPath;
|
||||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.graph.DefaultUndirectedGraph;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -37,6 +47,8 @@ public class SqlBuilder {
|
||||
|
||||
public String buildOntologySql(QueryStatement queryStatement) throws Exception {
|
||||
OntologyQuery ontologyQuery = queryStatement.getOntologyQuery();
|
||||
Ontology ontology = queryStatement.getOntology();
|
||||
|
||||
if (ontologyQuery.getLimit() == null) {
|
||||
ontologyQuery.setLimit(0L);
|
||||
}
|
||||
@@ -46,7 +58,14 @@ public class SqlBuilder {
|
||||
throw new Exception("data model not found");
|
||||
}
|
||||
|
||||
TableView tableView = render(ontologyQuery, new ArrayList<>(dataModels), scope, schema);
|
||||
TableView tableView;
|
||||
if (!CollectionUtils.isEmpty(ontology.getJoinRelations()) && dataModels.size() > 1) {
|
||||
Set<ModelResp> models = probeRelatedModels(dataModels, queryStatement.getOntology());
|
||||
tableView = render(ontologyQuery, models, scope, schema);
|
||||
} else {
|
||||
tableView = render(ontologyQuery, dataModels, scope, schema);
|
||||
}
|
||||
|
||||
SqlNode parserNode = tableView.build();
|
||||
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
||||
EngineType engineType = EngineType.fromString(database.getType());
|
||||
@@ -54,7 +73,61 @@ public class SqlBuilder {
|
||||
return SemanticNode.getSql(parserNode, engineType);
|
||||
}
|
||||
|
||||
private SqlNode optimizeParseNode(SqlNode parserNode, EngineType engineType) {
|
||||
private Set<ModelResp> probeRelatedModels(Set<ModelResp> dataModels, Ontology ontology) {
|
||||
List<JoinRelation> joinRelations = ontology.getJoinRelations();
|
||||
Graph<String, DefaultEdge> graph = buildGraph(joinRelations);
|
||||
DijkstraShortestPath<String, DefaultEdge> dijkstraAlg = new DijkstraShortestPath<>(graph);
|
||||
Set<String> queryModels =
|
||||
dataModels.stream().map(ModelResp::getName).collect(Collectors.toSet());
|
||||
GraphPath<String, DefaultEdge> selectedGraphPath = null;
|
||||
for (String fromModel : queryModels) {
|
||||
for (String toModel : queryModels) {
|
||||
if (fromModel != toModel) {
|
||||
GraphPath<String, DefaultEdge> path = dijkstraAlg.getPath(fromModel, toModel);
|
||||
if (isGraphPathContainsAll(path, queryModels)) {
|
||||
selectedGraphPath = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectedGraphPath == null) {
|
||||
return dataModels;
|
||||
}
|
||||
Set<String> modelNames = Sets.newHashSet();
|
||||
for (DefaultEdge edge : selectedGraphPath.getEdgeList()) {
|
||||
modelNames.add(selectedGraphPath.getGraph().getEdgeSource(edge));
|
||||
modelNames.add(selectedGraphPath.getGraph().getEdgeTarget(edge));
|
||||
}
|
||||
return modelNames.stream().map(m -> ontology.getModelMap().get(m))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean isGraphPathContainsAll(GraphPath<String, DefaultEdge> graphPath,
|
||||
Set<String> vertex) {
|
||||
Set<String> allVertex = Sets.newHashSet();
|
||||
for (DefaultEdge edge : graphPath.getEdgeList()) {
|
||||
allVertex.add(graphPath.getGraph().getEdgeSource(edge));
|
||||
allVertex.add(graphPath.getGraph().getEdgeTarget(edge));
|
||||
}
|
||||
Collection<String> intersect =
|
||||
org.apache.commons.collections.CollectionUtils.intersection(vertex, allVertex);
|
||||
|
||||
return intersect.size() == vertex.size() ? true : false;
|
||||
}
|
||||
|
||||
private Graph<String, DefaultEdge> buildGraph(List<JoinRelation> joinRelations) {
|
||||
Graph<String, DefaultEdge> directedGraph = new DefaultUndirectedGraph<>(DefaultEdge.class);
|
||||
for (JoinRelation joinRelation : joinRelations) {
|
||||
directedGraph.addVertex(joinRelation.getLeft());
|
||||
directedGraph.addVertex(joinRelation.getRight());
|
||||
directedGraph.addEdge(joinRelation.getLeft(), joinRelation.getRight());
|
||||
}
|
||||
return directedGraph;
|
||||
}
|
||||
|
||||
private SqlNode optimizeParseNode(SqlNode parserNode, EngineType engineType)
|
||||
throws SqlParseException {
|
||||
if (Objects.isNull(schema.getRuntimeOptions())
|
||||
|| Objects.isNull(schema.getRuntimeOptions().getEnableOptimize())
|
||||
|| !schema.getRuntimeOptions().getEnableOptimize()) {
|
||||
@@ -62,14 +135,10 @@ public class SqlBuilder {
|
||||
}
|
||||
|
||||
SqlNode optimizeNode = null;
|
||||
try {
|
||||
SqlNode sqlNode = SqlParser.create(SemanticNode.getSql(parserNode, engineType),
|
||||
Configuration.getParserConfig(engineType)).parseStmt();
|
||||
if (Objects.nonNull(sqlNode)) {
|
||||
optimizeNode = SemanticNode.optimize(scope, schema, sqlNode, engineType);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("optimize error {}", e);
|
||||
SqlNode sqlNode = SqlParser.create(SemanticNode.getSql(parserNode, engineType),
|
||||
Configuration.getParserConfig(engineType)).parseStmt();
|
||||
if (Objects.nonNull(sqlNode)) {
|
||||
optimizeNode = SemanticNode.optimize(scope, schema, sqlNode, engineType);
|
||||
}
|
||||
|
||||
if (Objects.nonNull(optimizeNode)) {
|
||||
@@ -79,7 +148,7 @@ public class SqlBuilder {
|
||||
return parserNode;
|
||||
}
|
||||
|
||||
private TableView render(OntologyQuery ontologyQuery, List<ModelResp> dataModels,
|
||||
private TableView render(OntologyQuery ontologyQuery, Set<ModelResp> dataModels,
|
||||
SqlValidatorScope scope, S2CalciteSchema schema) throws Exception {
|
||||
SqlNode left = null;
|
||||
TableView leftTable = null;
|
||||
@@ -88,8 +157,7 @@ public class SqlBuilder {
|
||||
Map<String, String> beforeModels = new HashMap<>();
|
||||
EngineType engineType = EngineType.fromString(schema.getOntology().getDatabase().getType());
|
||||
|
||||
for (int i = 0; i < dataModels.size(); i++) {
|
||||
final ModelResp dataModel = dataModels.get(i);
|
||||
for (ModelResp dataModel : dataModels) {
|
||||
final Set<DimSchemaResp> queryDimensions =
|
||||
ontologyQuery.getDimensionsByModel(dataModel.getName());
|
||||
final Set<MetricSchemaResp> queryMetrics =
|
||||
@@ -141,7 +209,8 @@ public class SqlBuilder {
|
||||
SqlLiteral sqlLiteral = SemanticNode.getJoinSqlLiteral("");
|
||||
JoinRelation matchJoinRelation = getMatchJoinRelation(before, rightTable, schema);
|
||||
SqlNode joinRelationCondition;
|
||||
if (!CollectionUtils.isEmpty(matchJoinRelation.getJoinCondition())) {
|
||||
if (!org.apache.commons.collections.CollectionUtils
|
||||
.isEmpty(matchJoinRelation.getJoinCondition())) {
|
||||
sqlLiteral = SemanticNode.getJoinSqlLiteral(matchJoinRelation.getJoinType());
|
||||
joinRelationCondition = getCondition(matchJoinRelation, scope, engineType);
|
||||
condition = joinRelationCondition;
|
||||
@@ -170,12 +239,19 @@ public class SqlBuilder {
|
||||
} else if (joinRelation.getLeft()
|
||||
.equalsIgnoreCase(tableView.getDataModel().getName())
|
||||
&& before.containsKey(joinRelation.getRight())) {
|
||||
matchJoinRelation.setJoinCondition(joinRelation.getJoinCondition().stream()
|
||||
List<Triple<String, String, String>> candidateJoinCon = joinRelation
|
||||
.getJoinCondition().stream()
|
||||
.map(r -> Triple.of(
|
||||
before.get(joinRelation.getRight()) + "." + r.getRight(),
|
||||
r.getMiddle(), tableView.getAlias() + "." + r.getLeft()))
|
||||
.collect(Collectors.toList()));
|
||||
matchJoinRelation.setJoinType(joinRelation.getJoinType());
|
||||
.collect(Collectors.toList());
|
||||
// added by jerryjzhang on 20250214
|
||||
// use the one with the most conditions to join left and right tables
|
||||
if (matchJoinRelation.getJoinCondition() == null || candidateJoinCon
|
||||
.size() > matchJoinRelation.getJoinCondition().size()) {
|
||||
matchJoinRelation.setJoinCondition(candidateJoinCon);
|
||||
matchJoinRelation.setJoinType(joinRelation.getJoinType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ spring:
|
||||
url: jdbc:postgresql://${DB_HOST}:${DB_PORT:5432}/${DB_NAME}?stringtype=unspecified
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
|
||||
sql:
|
||||
init:
|
||||
continue-on-error: true
|
||||
mode: always
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
|
||||
@@ -5,21 +5,21 @@ CREATE TABLE IF NOT EXISTS `s2_agent` (
|
||||
`examples` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`status` tinyint DEFAULT NULL,
|
||||
`model` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`tool_config` varchar(6000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`llm_config` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`tool_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`llm_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`chat_model_config` text COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`visual_config` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`visual_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`enable_search` tinyint DEFAULT 1,
|
||||
`enable_feedback` tinyint DEFAULT 1,
|
||||
`created_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`admin` varchar(3000) DEFAULT NULL COMMENT '管理员',
|
||||
`admin_org` varchar(3000) DEFAULT NULL COMMENT '管理员组织',
|
||||
`admin` varchar(1000) DEFAULT NULL COMMENT '管理员',
|
||||
`admin_org` varchar(1000) DEFAULT NULL COMMENT '管理员组织',
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||
`viewer` varchar(3000) DEFAULT NULL COMMENT '可用用户',
|
||||
`view_org` varchar(3000) DEFAULT NULL COMMENT '可用组织',
|
||||
`viewer` varchar(1000) DEFAULT NULL COMMENT '可用用户',
|
||||
`view_org` varchar(1000) DEFAULT NULL COMMENT '可用组织',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -26,7 +26,7 @@
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<revision>0.9.10-SNAPSHOT</revision>
|
||||
<revision>0.9.10</revision>
|
||||
<java.source.version>21</java.source.version>
|
||||
<java.target.version>21</java.target.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
@@ -82,6 +82,7 @@
|
||||
<spotless.skip>false</spotless.skip>
|
||||
<stax2.version>4.2.1</stax2.version>
|
||||
<aws-java-sdk.version>1.12.780</aws-java-sdk.version>
|
||||
<jgrapht.version>1.5.2</jgrapht.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -236,6 +237,11 @@
|
||||
<artifactId>aws-java-sdk</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-core</artifactId>
|
||||
<version>${jgrapht.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@@ -155,29 +155,8 @@ export default defineConfig({
|
||||
|
||||
//================ pro 插件配置 =================
|
||||
presets: ['umi-presets-pro'],
|
||||
/**
|
||||
* @name openAPI 插件的配置
|
||||
* @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码
|
||||
* @doc https://pro.ant.design/zh-cn/docs/openapi/
|
||||
*/
|
||||
// openAPI: [
|
||||
// {
|
||||
// requestLibPath: "import { request } from '@umijs/max'",
|
||||
// // 或者使用在线的版本
|
||||
// // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
|
||||
// schemaPath: join(__dirname, 'oneapi.json'),
|
||||
// mock: false,
|
||||
// },
|
||||
// {
|
||||
// requestLibPath: "import { request } from '@umijs/max'",
|
||||
// schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
|
||||
// projectName: 'swagger',
|
||||
// },
|
||||
// ],
|
||||
// 将insights-flow相关包排除出mfsu编译,在pnpm link 模式下保持热更新
|
||||
mfsu: {
|
||||
strategy: 'normal',
|
||||
// exclude: ['supersonic-insights-flow-components', 'supersonic-insights-flow-core'],
|
||||
},
|
||||
requestRecord: {},
|
||||
exportStatic: {},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -147,8 +147,8 @@ export const layout: RunTimeLayoutConfig = (params) => {
|
||||
height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined,
|
||||
}}
|
||||
>
|
||||
<AppPage dom={dom} />
|
||||
{/* {dom} */}
|
||||
{/* <AppPage dom={dom} /> */}
|
||||
{dom}
|
||||
{history.location.pathname !== '/chat' && !isMobile && (
|
||||
<Copilot token={getToken() || ''} isDeveloper />
|
||||
)}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd';
|
||||
import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu, MenuProps } from 'antd';
|
||||
import type { DataNode } from 'antd/lib/tree';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { useModel } from '@umijs/max';
|
||||
import { useModel, history } from '@umijs/max';
|
||||
import { createDomain, updateDomain, deleteDomain } from '../service';
|
||||
import DomainInfoForm from './DomainInfoForm';
|
||||
import styles from './style.less';
|
||||
@@ -71,6 +71,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
message.success('编辑分类成功');
|
||||
setProjectInfoModalVisible(false);
|
||||
onTreeDataUpdate?.();
|
||||
window.location.reload();
|
||||
} else {
|
||||
message.error(res.msg);
|
||||
}
|
||||
@@ -78,10 +79,13 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
|
||||
const domainSubmit = async (values: any) => {
|
||||
if (values.modelType === 'add') {
|
||||
const { code, data } = await createDomain(values);
|
||||
// if (code === 200 && values.type === 'top') {
|
||||
// await createDefaultModelSet(data.id);
|
||||
// }
|
||||
const { code, data, msg } = await createDomain(values);
|
||||
if (code === 200) {
|
||||
history.push(`/model/domain/${data.id}`);
|
||||
window.location.reload();
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
} else if (values.modelType === 'edit') {
|
||||
await editProject(values);
|
||||
}
|
||||
@@ -95,6 +99,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
message.success('删除成功');
|
||||
setProjectInfoModalVisible(false);
|
||||
onTreeDataUpdate?.();
|
||||
window.location.reload();
|
||||
} else {
|
||||
message.error(res.msg);
|
||||
}
|
||||
@@ -104,12 +109,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
const { id, name, path, hasEditPermission, parentId, hasModel } = node as any;
|
||||
const type = parentId === 0 ? 'top' : 'normal';
|
||||
return (
|
||||
<div
|
||||
className={styles.projectItem}
|
||||
// onClick={() => {
|
||||
// handleSelect(id);
|
||||
// }}
|
||||
>
|
||||
<div className={styles.projectItem}>
|
||||
<span className={styles.projectItemTitle}>{name}</span>
|
||||
{createDomainBtnVisible && hasEditPermission && (
|
||||
<span className={`${styles.operation} ${styles.rowHover} `}>
|
||||
@@ -175,13 +175,12 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
return {
|
||||
key: domain.id,
|
||||
label: titleRender(domain),
|
||||
// icon: <AppstoreOutlined />,
|
||||
};
|
||||
});
|
||||
|
||||
const getLevelKeys = (items1: LevelKeysProps[]) => {
|
||||
const getLevelKeys = (items1: any[]) => {
|
||||
const key: Record<string, number> = {};
|
||||
const func = (items2: LevelKeysProps[], level = 1) => {
|
||||
const func = (items2: any[], level = 1) => {
|
||||
items2.forEach((item) => {
|
||||
if (item.key) {
|
||||
key[item.key] = level;
|
||||
@@ -194,7 +193,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
func(items1);
|
||||
return key;
|
||||
};
|
||||
const levelKeys = getLevelKeys(items as LevelKeysProps[]);
|
||||
const levelKeys = getLevelKeys(items as any[]);
|
||||
const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']);
|
||||
|
||||
const onOpenChange: MenuProps['onOpenChange'] = (openKeys) => {
|
||||
|
||||
@@ -82,6 +82,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
||||
});
|
||||
if (code === 200) {
|
||||
onModelChange?.();
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
@@ -198,6 +199,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
||||
const { code, msg } = await deleteModel(record.id);
|
||||
if (code === 200) {
|
||||
onModelChange?.();
|
||||
window.location.reload();
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
@@ -292,6 +294,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
||||
onModelChange?.();
|
||||
setIsEditing(false);
|
||||
setCreateDataSourceModalOpen(false);
|
||||
window.location.reload();
|
||||
}}
|
||||
onCancel={() => {
|
||||
setIsEditing(false);
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { history, useParams, useModel, Outlet } from '@umijs/max';
|
||||
import DomainListTree from './components/DomainList';
|
||||
import styles from './components/style.less';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useParams, useModel, Outlet } from '@umijs/max';
|
||||
import { ISemantic } from './data';
|
||||
import { getDomainList, getDataSetList, getModelDetail } from './service';
|
||||
import { getDomainList, getModelDetail } from './service';
|
||||
import PageBreadcrumb from './PageBreadcrumb';
|
||||
|
||||
type Props = {};
|
||||
@@ -17,20 +14,10 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const databaseModel = useModel('SemanticModel.databaseData');
|
||||
const metricModel = useModel('SemanticModel.metricData');
|
||||
const { setSelectDomain, setDomainList, selectDomainId } = domainModel;
|
||||
const { selectModel, setSelectModel, setModelTableHistoryParams, MrefreshModelList } = modelModel;
|
||||
const { setSelectDomain, setDomainList } = domainModel;
|
||||
const { selectModel, setSelectModel } = modelModel;
|
||||
const { MrefreshDatabaseList } = databaseModel;
|
||||
|
||||
const { selectMetric, setSelectMetric } = metricModel;
|
||||
|
||||
// useEffect(() => {
|
||||
|
||||
// return () => {
|
||||
// setSelectMetric(undefined);
|
||||
// }
|
||||
// }, [])
|
||||
|
||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||
const targetNode = domainList.filter((item: any) => {
|
||||
return `${item.id}` === domainId;
|
||||
@@ -40,9 +27,7 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
||||
return item.parentId === 0;
|
||||
})[0];
|
||||
if (firstRootNode) {
|
||||
const { id } = firstRootNode;
|
||||
setSelectDomain(firstRootNode);
|
||||
// pushUrlMenu(id, menuKey);
|
||||
}
|
||||
} else {
|
||||
setSelectDomain(targetNode);
|
||||
@@ -87,7 +72,6 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
||||
</div>
|
||||
<div>
|
||||
<Outlet />
|
||||
{/* <OverviewContainer /> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
|
||||
import { useModel } from '@umijs/max';
|
||||
|
||||
export default function Domain() {
|
||||
const [selectDomain, setSelectDomain] = useState<ISemantic.IDomainItem>(
|
||||
const [selectDomain, setSelectDomain] = useState<ISemantic.IDomainItem | undefined>(
|
||||
{} as ISemantic.IDomainItem,
|
||||
);
|
||||
const [selectDataSet, setSelectDataSet] = useState<ISemantic.IDatasetItem>();
|
||||
|
||||
Reference in New Issue
Block a user