diff --git a/webapp/packages/supersonic-fe/src/enum/index.ts b/webapp/packages/supersonic-fe/src/enum/index.ts index be75e95ce..389953605 100644 --- a/webapp/packages/supersonic-fe/src/enum/index.ts +++ b/webapp/packages/supersonic-fe/src/enum/index.ts @@ -1,22 +1,4 @@ export * from './models/base'; -type ObjToArrayParams = Record; - -const keyTypeTran = { - string: String, - number: Number, -}; -/** - * obj转成value,label的数组 - * @param _obj - */ -export const objToArray = (_obj: ObjToArrayParams, keyType: string = 'string') => { - return Object.keys(_obj).map((key) => { - return { - value: keyTypeTran[keyType](key), - label: _obj[key], - }; - }); -}; type EnumToArrayItem = { value: number; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSetting.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSetting.tsx deleted file mode 100644 index 28a378997..000000000 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSetting.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import { connect } from 'umi'; -import type { StateType } from '../model'; -import OverviewContainer from '../OverviewContainer'; -import type { Dispatch } from 'umi'; - -type Props = { - domainManger: StateType; - dispatch: Dispatch; -}; -const ChatSetting: React.FC = () => { - return ( - <> - - - ); -}; - -export default connect(({ domainManger }: { domainManger: StateType }) => ({ - domainManger, -}))(ChatSetting); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingSection.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingSection.tsx deleted file mode 100644 index 8e38dd6be..000000000 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingSection.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useRef } from 'react'; -import { connect } from 'umi'; -import type { StateType } from '../model'; -import ProCard from '@ant-design/pro-card'; -import EntitySection from '../components/Entity/EntitySection'; -import { ChatConfigType } from '../enum'; -import type { Dispatch } from 'umi'; - -type Props = { - domainManger: StateType; - dispatch: Dispatch; -}; - -const ChatSettingSection: React.FC = () => { - const metricRef = useRef(); - const tagRef = useRef(); - return ( -
- - { - tagRef.current.refreshConfigData(); - }} - /> - - - { - metricRef.current.refreshConfigData(); - }} - /> - -
- ); -}; - -export default connect(({ domainManger }: { domainManger: StateType }) => ({ - domainManger, -}))(ChatSettingSection); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingTab.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingTab.tsx deleted file mode 100644 index e5913a5e0..000000000 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ChatSetting/ChatSettingTab.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { Tabs, Button } from 'antd'; -import React from 'react'; -import { connect } from 'umi'; - -import styles from '../components/style.less'; -import type { StateType } from '../model'; -import { LeftOutlined } from '@ant-design/icons'; -import EntitySection from '../components/Entity/EntitySection'; -import RecommendedQuestionsSection from '../components/Entity/RecommendedQuestionsSection'; -import { ISemantic } from '../data'; - -import OverView from '../components/OverView'; -import { ChatConfigType } from '../enum'; -import type { Dispatch } from 'umi'; - -type Props = { - isModel: boolean; - activeKey: string; - modelList: ISemantic.IModelItem[]; - handleModelChange: (model?: ISemantic.IModelItem) => void; - onBackDomainBtnClick?: () => void; - onMenuChange?: (menuKey: string) => void; - domainManger: StateType; - dispatch: Dispatch; -}; - -const ChatSetting: React.FC = ({ - isModel, - activeKey, - modelList, - handleModelChange, - onBackDomainBtnClick, - onMenuChange, -}) => { - const defaultTabKey = 'metric'; - - const isModelItem = [ - { - label: '指标模式', - key: 'metric', - children: , - }, - { - label: '标签模式', - key: 'dimenstion', - children: , - }, - { - label: '推荐问题', - key: 'recommendedQuestions', - children: , - }, - ]; - - const tabItem = [ - { - label: '模型', - key: 'overview', - children: ( - { - handleModelChange(model); - }} - /> - ), - }, - ]; - - return ( - <> - } - onClick={() => { - onBackDomainBtnClick?.(); - }} - style={{ marginRight: 10 }} - > - 返回主题域 - - ) : undefined - } - onChange={(menuKey: string) => { - onMenuChange?.(menuKey); - }} - /> - - ); -}; - -export default connect(({ domainManger }: { domainManger: StateType }) => ({ - domainManger, -}))(ChatSetting); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlDetail.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlDetail.tsx index 8b5ba83c5..665a31a78 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlDetail.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlDetail.tsx @@ -12,17 +12,17 @@ import { SwapOutlined, PlayCircleOutlined, CloudServerOutlined, + ApiOutlined, } from '@ant-design/icons'; import { isFunction } from 'lodash'; import FullScreen from '@/components/FullScreen'; import SqlEditor from '@/components/SqlEditor'; import type { TaskResultItem, TaskResultColumn } from '../data'; import { excuteSql } from '@/pages/SemanticModel/service'; -// import DataSourceCreateForm from './DataSourceCreateForm'; import type { Dispatch } from 'umi'; import type { StateType } from '../../model'; +import SqlParams from './SqlParams'; import styles from '../style.less'; - import 'ace-builds/src-min-noconflict/ext-searchbox'; import 'ace-builds/src-min-noconflict/theme-sqlserver'; import 'ace-builds/src-min-noconflict/theme-monokai'; @@ -77,7 +77,6 @@ const SqlDetail: React.FC = ({ }); const [dataBaseItems, setDataBaseItems] = useState([]); const [currentDatabaseItem, setCurrentDatabaseItem] = useState(); - // const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false); const [tableScroll, setTableScroll] = useState({ scrollToFirstRowOnChange: true, @@ -88,7 +87,7 @@ const SqlDetail: React.FC = ({ const [runState, setRunState] = useState(); const [taskLog, setTaskLog] = useState(''); - const [isSqlExcLocked, setIsSqlExcLocked] = useState(false); + const [isSqlExcLocked, setIsSqlExcLocked] = useState(false); const [screenSize, setScreenSize] = useState('middle'); const [isSqlIdeFullScreen, setIsSqlIdeFullScreen] = useState(false); @@ -100,8 +99,11 @@ const SqlDetail: React.FC = ({ const DEFAULT_FULLSCREEN_TOP = 0; const [partialSql, setPartialSql] = useState(''); - const [isPartial, setIsPartial] = useState(false); - const [isRight, setIsRight] = useState(false); + const [isPartial, setIsPartial] = useState(false); + const [isRight, setIsRight] = useState(false); + + const [variableCollapsed, setVariableCollapsed] = useState(true); + const [sqlParams, setSqlParams] = useState([]); const [scriptColumns, setScriptColumns] = useState([]); @@ -125,6 +127,10 @@ const SqlDetail: React.FC = ({ setCurrentDatabaseItem(targetDataBase); }, [dataSourceItem, databaseConfigList]); + useEffect(() => { + setSqlParams(dataSourceItem?.modelDetail?.sqlVariables || []); + }, [dataSourceItem]); + useEffect(() => { setRunState(undefined); }, [currentDatabaseItem, sql]); @@ -138,6 +144,11 @@ const SqlDetail: React.FC = ({ return line; } + const handleVariable = () => { + const collapsedValue = !variableCollapsed; + setVariableCollapsed(collapsedValue); + }; + // 计算每列的宽度,通过容器插入文档中动态得到该列数据(包括表头)的最长宽度,设为列宽度,保证每列的数据都能一行展示完 function getKeyWidthMap(list: TaskResultItem[]): TaskResultItem { const widthMap = {}; @@ -417,6 +428,9 @@ const SqlDetail: React.FC = ({ + {/* + + */} @@ -463,6 +477,12 @@ const SqlDetail: React.FC = ({ onSelect={onSelect} /> +
+ +
diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParams.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParams.tsx new file mode 100644 index 000000000..bde912c90 --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParams.tsx @@ -0,0 +1,112 @@ +import { useState } from 'react'; +import type { FC } from 'react'; +import type { SqlParamsItem, OprType } from '../data'; + +import styles from '../style.less'; +import { AppstoreAddOutlined, DeleteTwoTone, EditTwoTone } from '@ant-design/icons'; +import SqlParamsDetailModal from './SqlParamsDetailModal'; +import { List } from 'antd'; + +type Props = { + value?: SqlParamsItem[]; + onChange?: (e: SqlParamsItem[]) => void; +}; + +const defalutItem: SqlParamsItem = { + name: '', + type: 'query', + defaultValues: [], + valueType: 'string', + udf: false, +}; + +const SqlParams: FC = ({ value, onChange }) => { + const [oprType, setOprType] = useState('add'); + const [visible, setVisible] = useState(false); + const [initValue, setInitValue] = useState(); + const paramsChange = (params: SqlParamsItem[]) => { + if (onChange) { + onChange(params); + } + }; + const handleAdd = () => { + setOprType('add'); + setVisible(true); + setInitValue(defalutItem); + }; + const handleSave = async (values: SqlParamsItem) => { + const newValue = value ? [...value] : []; + const { index, ...rest } = values; + if (index || index === 0) { + newValue[index] = rest; + } else { + newValue.push(rest); + } + setVisible(false); + setInitValue(undefined); + paramsChange(newValue); + }; + + const handleDelete = (index: number) => { + const newValue = value ? [...value] : []; + newValue.splice(index, 1); + paramsChange(newValue); + }; + const handleEdit = (index: number) => { + const paramsItem = value ? value[index] : defalutItem; + setInitValue({ ...paramsItem, index }); + setOprType('edit'); + setVisible(true); + }; + return ( + <> +
+
+ 变量 + +
+ ( + + { + handleEdit(index); + }} + /> + { + handleDelete(index); + }} + /> + , + ]} + > +
{item.name}
+
+ )} + /> +
+ item.name)} + oprType={oprType} + modalVisible={visible} + onSave={handleSave} + onCancel={() => { + setVisible(false); + }} + initValue={initValue} + /> + + ); +}; + +export default SqlParams; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParamsDetailModal.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParamsDetailModal.tsx new file mode 100644 index 000000000..264a8f3c5 --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Datasource/components/SqlParamsDetailModal.tsx @@ -0,0 +1,195 @@ +import { useEffect, useState } from 'react'; +import type { FC } from 'react'; +import { Modal, Form, Input, Select, Checkbox } from 'antd'; +import { isFunction } from 'lodash'; +import { objToArray } from '@/utils/utils'; +import type { ParamsItemProps, OprType } from '../data'; +import { IDataSource } from '../../data'; +import TextArea from 'antd/lib/input/TextArea'; +import ParamsSqlEditor from './SqlParamsSqlEditor'; + +const EnumSqlParamsType = { + auth: '权限变量', + query: '查询变量', +}; + +const EnumSqlValueType = { + string: '字符串', + sql: 'SQL表达式', + date: '日期', + boolean: '布尔', + number: '数字', +}; + +const { Option } = Select; + +const ParamsTextArea: FC = ({ value, onChange }) => { + return ( +