diff --git a/dinky-web/config/routes.ts b/dinky-web/config/routes.ts index 6cbced7d19..b8898552b2 100644 --- a/dinky-web/config/routes.ts +++ b/dinky-web/config/routes.ts @@ -62,13 +62,6 @@ export default [ name: 'datastudio', icon: 'CodeOutlined', footerRender: false, - component: './DataStudio' - }, - { - path: '/datastudio-new', - name: 'datastudio', - icon: 'CodeOutlined', - footerRender: false, component: './DataStudioNew' }, { diff --git a/dinky-web/src/components/CallBackButton/CircleBtn.tsx b/dinky-web/src/components/CallBackButton/CircleBtn.tsx index 68d16d9f2b..a483de8126 100644 --- a/dinky-web/src/components/CallBackButton/CircleBtn.tsx +++ b/dinky-web/src/components/CallBackButton/CircleBtn.tsx @@ -17,8 +17,6 @@ * */ -import { TabsItemType, TaskDataType } from '@/pages/DataStudio/model'; -import { Tab } from '@/pages/DataStudio/route'; import { Button } from 'antd'; import React from 'react'; @@ -30,26 +28,6 @@ export type CircleButtonProps = { key?: string; href?: string; }; -export type CircleBottomButtonProps = { - icon: React.ReactNode; - loading?: boolean; - onClick?: ( - tabs: Tab[], - key: string, - data: TaskDataType | undefined, - refresh: any - ) => Promise; - title?: string; - key?: string; -}; -export type CircleDataStudioButtonProps = { - icon: React.ReactNode; - loading?: boolean; - onClick?: (panes: TabsItemType[], activeKey: string) => void; - title?: string; - key?: string; - isShow?: boolean; -}; export const CircleBtn: React.FC = (props) => { const { onClick, title, icon, loading, href } = props; diff --git a/dinky-web/src/components/Icons/CodeLanguageIcon.tsx b/dinky-web/src/components/Icons/CodeLanguageIcon.tsx index 508c34db67..9ccb43ce3e 100644 --- a/dinky-web/src/components/Icons/CodeLanguageIcon.tsx +++ b/dinky-web/src/components/Icons/CodeLanguageIcon.tsx @@ -66,17 +66,19 @@ export const FileIcon = () => { * @returns {JSX.Element} * @constructor */ -export const JavaSvg = () => { +export const JavaSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { * @returns {JSX.Element} * @constructor */ -export const YAMLSvg = () => { +export const YAMLSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { * @returns {JSX.Element} * @constructor */ -export const ShellSvg = () => { +export const ShellSvg = (props: { size?: number }) => { + const { size = 16 } = props; + return ( <> ( { /** * xml icon - * @returns {JSX.Element} * @constructor */ -export const XMLSvg = () => { +export const XMLSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { * @returns {JSX.Element} * @constructor */ -export const MarkDownSvg = () => { +export const MarkDownSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { ); }; -export const FlinkSQLSvg = () => ( - ( - // - // - // - // - - - - - )} - /> -); -export const FlinkSQLEnvSvg = () => ( - ( - - - - - - )} - /> -); +export const FlinkSQLSvg = (props: { size?: number }) => { + const { size = 16 } = props; -export const FlinkJarSvg = () => ( - ( - - - - - )} - /> -); + return ( + ( + // + // + // + // + + + + + )} + /> + ); +}; +export const FlinkSQLEnvSvg = (props: { size?: number }) => { + const { size = 16 } = props; + return ( + ( + + + + + + )} + /> + ); +}; + +export const FlinkJarSvg = (props: { size?: number }) => { + const { size = 16 } = props; + + return ( + ( + + + + + )} + /> + ); +}; -export const LogSvg = () => { +export const LogSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> { viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' + width={size} + height={size} > { ); }; -export const ScalaSvg = () => { +export const ScalaSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { ); }; -export const PythonSvg = () => { +export const PythonSvg = (props: { size?: number }) => { + const { size = 16 } = props; return ( <> ( { - const size = props.size || defaultSvgSize; + const { size = 16 } = props; return ( <> { }; export const SQLIcons = (props: any) => { - const size = props.size || defaultSvgSize; + const { size = 16 } = props; + return ( <> { - const keys: Key[] = []; - keys.push(node.key); - if (node?.children?.length > 0) { - node.children.forEach((item: ProcessStep) => { - keys.push(...buildExpandKeys(item)); - }); - } - return keys; -}; - -const ConsoleContent = (props: ConsoleProps) => { - const { tab } = props; - const refObject = useRef(null); - - const [selectNode, setSelectNode] = useState(); - const [processNode, setProcessNode] = useState(); - const [expandedKeys, setExpandedKeys] = useState([]); - - const [showCacheData, setShowCacheData] = useState(false); - - const process = `FlinkSubmit/${tab.params.taskId}`; - const { subscribeTopic } = useModel('UseWebSocketModel', (model: any) => ({ - subscribeTopic: model?.subscribeTopic - })); - - const { wsState } = useModel('UseWebSocketModel', (model: any) => ({ - wsState: model?.wsState - })); - - const onUpdate = (data: ProcessStep) => { - setProcessNode((prevState: any) => { - //如果key不一致代表重新提交了任务,清空旧状态 - if ((prevState && prevState?.key != data?.key) || !data) { - setSelectNode(undefined); - } - return data; - }); - setSelectNode((prevState: any) => { - if (prevState && data?.lastUpdateStep && prevState?.key === data?.lastUpdateStep?.key) { - //更新当前节点 - return data?.lastUpdateStep; - } else if (!prevState || prevState?.key === data?.key) { - //未选择节点状态下选择根节点 - return data; - } - return prevState; - }); - }; - - const killProcess = useRequest( - { url: API_CONSTANTS.KILL_PROCESS, params: { processName: process } }, - { onSuccess: async (res) => onUpdate(res) } - ); - - const refreshProcess = () => { - subscribeTopic(Topic.PROCESS_CONSOLE, [process], (data: SseData) => - onUpdate(data?.data[process]) - ); - }; - - useEffect(refreshProcess, []); - const onSelect = ( - _selectedKeys: Key[], - info: { - node: ProcessStep; - } - ) => setSelectNode(info.node); - - const renderTitle = (node: any) => { - const startDate = new Date(node.startTime); - const endDate = new Date(); - const duration = node.time ? node.time : endDate.getTime() - startDate.getTime(); - return ( - - {node.status === JobStatus.RUNNING && } - {node.status === JobStatus.FINISHED && ( - - )} - {node.status === JobStatus.FAILED && ( - - )} - {node.title} - - {parseMilliSecondStr(duration)} - - - ); - }; - - useEffect(() => { - if (processNode) { - setExpandedKeys(buildExpandKeys(processNode)); - } - }, [processNode]); - - const handleExpand = (expandedKeys: Key[]) => { - setExpandedKeys(expandedKeys); - }; - - if (!wsState?.wsOnReady && !showCacheData) { - return ( - setShowCacheData(true)}> - {l('devops.jobinfo.recently.job.status')} - - } - /> - ); - } - - return ( -
- - - {processNode ? ( - - ) : ( - - )} - - - - { - const boolean = await handleDeleteOperation( - API_CONSTANTS.PROCESS_LOG_CLEAR, - { processName: process }, - l('rc.ds.detail.tag.console.clear.log') - ); - if (boolean) refreshProcess(); - }} - btnExtraContent={ - await killProcess.run()} - icon={ - - } - /> - } - /> - - -
- ); -}; - -export default connect(({ Studio }: { Studio: StateType }) => ({ - height: Studio.bottomContainer.height, - console: Studio.bottomContainerContent.console -}))(ConsoleContent); diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/Console/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/Console/index.tsx deleted file mode 100644 index b23a606bf5..0000000000 --- a/dinky-web/src/pages/DataStudio/BottomContainer/Console/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import ConsoleContent from '@/pages/DataStudio/BottomContainer/Console/ConsoleContent'; -import { StateType, TabsItemType } from '@/pages/DataStudio/model'; -import { connect } from '@@/exports'; -import { Tabs } from 'antd'; -import React, { useEffect } from 'react'; - -const Console: React.FC = (props: any) => { - const { - tabs: { panes, activeKey } - } = props; - useEffect(() => {}, []); - - const tabItems = panes.map((item: TabsItemType) => ({ - key: item.key, - label: {item.label}, - children: - })); - - return ( - - ); -}; - -export default connect(({ Studio }: { Studio: StateType }) => ({ - tabs: Studio.tabs, - height: Studio.bottomContainer.height, - console: Studio.bottomContainerContent.console -}))(Console); diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/JobExecHistory/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/JobExecHistory/index.tsx deleted file mode 100644 index b6b4fcb5ab..0000000000 --- a/dinky-web/src/pages/DataStudio/BottomContainer/JobExecHistory/index.tsx +++ /dev/null @@ -1,295 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { JobDetailInfoModel } from '@/pages/DataStudio/BottomContainer/JobExecHistory/components/JobDetailInfoModel'; -import { getCurrentTab } from '@/pages/DataStudio/function'; -import { DataStudioTabsItemType, StateType } from '@/pages/DataStudio/model'; -import { queryList } from '@/services/api'; -import { API_CONSTANTS } from '@/services/endpoints'; -import { JobExecutionHistory } from '@/types/Studio/data'; -import { formatDateToYYYYMMDDHHMMSS } from '@/utils/function'; -import { l } from '@/utils/intl'; -import { ErrorMessage } from '@/utils/messages'; -import { ClusterOutlined, FireOutlined, RocketOutlined } from '@ant-design/icons'; -import { ActionType, ProList } from '@ant-design/pro-components'; -import { ProListMetas } from '@ant-design/pro-list'; -import { useUpdateEffect } from 'ahooks'; -import { Badge, Divider, Empty, Space, Tag, Typography } from 'antd'; -import React, { useRef, useState } from 'react'; -import { connect } from 'umi'; - -const { Link, Paragraph, Text } = Typography; - -const JobExecHistory: React.FC = (props) => { - const { tabs } = props; - - const currentTab = getCurrentTab(tabs.panes, tabs.activeKey) as DataStudioTabsItemType; - - const refAction = useRef(); - - useUpdateEffect(() => { - refAction.current?.reload(); - }, [tabs.activeKey]); - - const [modalVisit, setModalVisit] = useState(false); - const [historyData, setHistoryData] = useState(); - const [type, setType] = useState(1); - const showDetail = (row: JobExecutionHistory, type: number) => { - setHistoryData(row); - setModalVisit(true); - setType(type); - }; - - const handleCancel = () => { - setModalVisit(false); - }; - - const renderMetaDescription = (item: JobExecutionHistory) => { - return ( - <> - - <> - - [{item.jobManagerAddress}] - - - {l('global.table.startTime')}:{formatDateToYYYYMMDDHHMMSS(item.startTime)} - - {l('global.table.finishTime')}:{formatDateToYYYYMMDDHHMMSS(item.endTime)} - - - - ); - }; - - const renderSubTitle = (item: JobExecutionHistory) => { - return ( - - {item.jobName ? ( - - {item.jobName} - - ) : ( - l('global.job.status.failed-tip') - )} - - {item.clusterName ? ( - - {item.clusterName} - - ) : ( - - {l('pages.devops.jobinfo.localenv')} - - )} - {item.type && ( - - {item.type} - - )} - {item.status == 2 ? ( - - - {l('global.job.status.success')} - - ) : item.status == 1 ? ( - - - {l('global.job.status.running')} - - ) : item.status == 3 ? ( - - - {l('global.job.status.failed')} - - ) : item.status == 4 ? ( - - - {l('global.job.status.canceled')} - - ) : item.status == 0 ? ( - - - {l('global.job.status.initiating')} - - ) : ( - - - {l('global.job.status.unknown')} - - )} - - ); - }; - - const renderActions = (item: JobExecutionHistory) => { - return [ - showDetail(item, 1)}> - {l('pages.datastudio.label.history.execConfig')} - , - showDetail(item, 2)}> - {l('pages.datastudio.label.history.statement')} - , - { - if (item.status != 2) { - await ErrorMessage(l('pages.datastudio.label.history.notSuccess')); - return; - } - showDetail(item, 3); - }} - > - {l('pages.datastudio.label.history.result')} - , - showDetail(item, 4)}> - {l('pages.datastudio.label.history.error')} - - ]; - }; - - const buildMetaInfo = (): ProListMetas => { - return { - title: { - dataIndex: 'jobId', - title: 'JobId', - render: (_, row) => { - return ( - - - {row.jobId ?? l('global.job.status.failed-tip')} - - - ); - } - }, - description: { - search: false, - render: (_, row) => renderMetaDescription(row) - }, - subTitle: { - render: (_, row) => renderSubTitle(row), - search: false - }, - actions: { - render: (text, row) => renderActions(row), - search: false - }, - jobName: { - dataIndex: 'jobName', - // title: l('pages.datastudio.label.history.jobName'), - title: 'JobName' - }, - clusterId: { - dataIndex: 'clusterId', - // title: l('pages.datastudio.label.history.runningCluster'), - title: 'ClusterId' - }, - status: { - // 自己扩展的字段,主要用于筛选,不在列表中显示 - title: l('global.table.status'), - valueType: 'select', - valueEnum: { - '': { text: '全部', status: 'ALL' }, - 0: { - text: '初始化中', - status: 'INITIALIZE' - }, - 1: { - text: '运行中', - status: 'RUNNING' - }, - 2: { - text: '成功', - status: 'SUCCESS' - }, - 3: { - text: '失败', - status: 'FAILED' - }, - 4: { - text: '取消', - status: 'CANCEL' - } - } - }, - startTime: { - dataIndex: 'startTime', - title: l('global.table.startTime'), - valueType: 'dateTimeRange' - }, - endTime: { - dataIndex: 'endTime', - title: l('global.table.finishTime'), - valueType: 'dateTimeRange' - } - }; - }; - - return ( - <> - {tabs.panes.length === 0 ? ( - - ) : ( - - actionRef={refAction} - search={{ - filterType: 'light' - }} - size={'small'} - rowKey='id' - params={{ taskId: currentTab?.task?.id }} - dateFormatter={'string'} - headerTitle={l('pages.datastudio.label.history.title', '', { name: currentTab?.label })} - request={(params, sorter, filter: any) => - queryList(API_CONSTANTS.HISTORY_LIST, { - ...{ ...params, taskId: currentTab?.params?.taskId }, - sorter: { id: 'descend' }, - filter - }) - } - pagination={{ - defaultPageSize: 5, - showSizeChanger: true - }} - metas={buildMetaInfo()} - options={{ - search: false, - setting: false, - density: false - }} - /> - )} - - - - ); -}; - -export default connect(({ Studio }: { Studio: StateType }) => ({ - tabs: Studio.tabs -}))(JobExecHistory); diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/Lineage/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/Lineage/index.tsx deleted file mode 100644 index e31acc8e72..0000000000 --- a/dinky-web/src/pages/DataStudio/BottomContainer/Lineage/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import LineageGraph from '@/components/LineageGraph'; -import { getCurrentData, mapDispatchToProps } from '@/pages/DataStudio/function'; -import { StateType } from '@/pages/DataStudio/model'; -import { getDataByParams } from '@/services/BusinessCrud'; -import { API_CONSTANTS } from '@/services/endpoints'; -import { LineageDetailInfo } from '@/types/DevOps/data'; -import { l } from '@/utils/intl'; -import { connect } from '@umijs/max'; -import { Card, Result } from 'antd'; -import React, { useEffect } from 'react'; - -interface StudioLineageParams { - type: number; - statementSet: boolean; - dialect: string; - databaseId: number; - statement: string; - envId: number; - fragment: boolean; - variables: any; - taskId: number; -} - -const Lineage: React.FC = (props) => { - const { - tabs: { panes, activeKey }, - bottomHeight - } = props; - const [lineageData, setLineageData] = React.useState({ - tables: [], - relations: [] - }); - const [loading, setLoading] = React.useState(false); - const currentData = getCurrentData(panes, activeKey); - - const queryLineageData = () => { - setLoading(true); - // 组装参数 statementSet type dialect databaseId - if (!currentData) return; - const { type, statementSet, dialect, databaseId, statement, envId, fragment, id } = currentData; - const params: StudioLineageParams = { - type: 1, // todo: 暂时写死 ,后续优化 - dialect: dialect, - envId: envId ?? -1, - fragment: fragment, - statement: statement, - statementSet: statementSet, - databaseId: databaseId ?? 0, - variables: {}, - taskId: id - }; - getDataByParams(API_CONSTANTS.STUDIO_GET_LINEAGE, params).then((res) => { - if (res) { - setLoading(false); - setLineageData(res as LineageDetailInfo); - } - }); - }; - - useEffect(() => { - queryLineageData(); - }, [activeKey, currentData]); - - return ( - - {lineageData && (lineageData.tables.length !== 0 || lineageData.relations.length !== 0) ? ( - - ) : ( - - )} - - ); -}; - -export default connect( - ({ Studio }: { Studio: StateType }) => ({ - tabs: Studio.tabs, - bottomHeight: Studio.bottomContainer.height - }), - mapDispatchToProps -)(Lineage); diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/Result/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/Result/index.tsx deleted file mode 100644 index 327d081506..0000000000 --- a/dinky-web/src/pages/DataStudio/BottomContainer/Result/index.tsx +++ /dev/null @@ -1,306 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { - assert, - convertMockResultToList, - getCurrentData, - getCurrentTab, - isDataStudioTabsItemType, - mapDispatchToProps -} from '@/pages/DataStudio/function'; -import { isSql } from '@/pages/DataStudio/HeaderContainer/function'; -import { StateType, TaskDataType } from '@/pages/DataStudio/model'; -import { handleGetOption, handleGetOptionWithoutMsg } from '@/services/BusinessCrud'; -import { DIALECT } from '@/services/constants'; -import { API_CONSTANTS } from '@/services/endpoints'; -import { transformTableDataToCsv } from '@/utils/function'; -import { l } from '@/utils/intl'; -import { QuestionCircleOutlined, SearchOutlined } from '@ant-design/icons'; -import { Highlight } from '@ant-design/pro-layout/es/components/Help/Search'; -import { Button, Empty, Input, InputRef, Space, Table, Tabs, Tooltip } from 'antd'; -import { ColumnsType, ColumnType } from 'antd/es/table'; -import { FilterConfirmProps } from 'antd/es/table/interface'; -import { DataIndex } from 'rc-table/es/interface'; -import { useRef, useState } from 'react'; -import { connect } from 'umi'; -import { useAsyncEffect } from 'ahooks'; - -type Data = { - [c: string]: any; - columns?: string[]; - rowData?: object[]; -}; -type DataList = Data[]; -const Result = (props: any) => { - const { - tabs: { panes, activeKey }, - historyExecId, - initIsRefresh - } = props; - const [data, setData] = useState({}); - const [dataList, setDataList] = useState([]); - const [loading, setLoading] = useState(true); - const currentTabs = getCurrentTab(panes, activeKey); - const current = getCurrentData(panes, activeKey) as TaskDataType; - - const [searchText, setSearchText] = useState(''); - const [searchedColumn, setSearchedColumn] = useState(''); - const searchInput = useRef(null); - const handleReset = (clearFilters: () => void) => { - clearFilters(); - setSearchText(''); - }; - const handleSearch = ( - selectedKeys: string[], - confirm: (param?: FilterConfirmProps) => void, - dataIndex: DataIndex - ) => { - confirm(); - setSearchText(selectedKeys[0]); - setSearchedColumn(dataIndex.toString()); - }; - const getColumnSearchProps = (dataIndex: string): ColumnType => ({ - filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( -
e.stopPropagation()}> - setSelectedKeys(e.target.value ? [e.target.value] : [])} - onPressEnter={() => handleSearch(selectedKeys as string[], confirm, dataIndex)} - style={{ marginBottom: 8, display: 'block' }} - /> - - - - -
- ), - filterIcon: (filtered: boolean) => ( - - ), - onFilter: (value, record) => - record[dataIndex] - .toString() - .toLowerCase() - .includes((value as string).toLowerCase()), - onFilterDropdownOpenChange: (visible) => { - if (visible) { - setTimeout(() => searchInput.current?.select(), 100); - } - }, - render: (text) => - searchedColumn === dataIndex ? ( - - ) : ( - text - ) - }); - - const loadData = async (isRefresh?: boolean) => { - if (!isDataStudioTabsItemType(currentTabs)) { - return; - } - - const consoleData = currentTabs.console; - if (consoleData.result && !isRefresh && !consoleData.result.mockSinkResult) { - setData(consoleData.result); - } else if (consoleData.results && !isRefresh && !consoleData.result.mockSinkResult) { - setDataList(consoleData.results); - } else { - if (assert(current?.dialect, [DIALECT.FLINK_SQL], true, 'includes')) { - // flink sql - // to do: get job data by history id list, not flink jid - if (current?.id) { - let historyId = historyExecId; - if (!historyId) { - const res = await handleGetOptionWithoutMsg(API_CONSTANTS.GET_LATEST_HISTORY_BY_ID, { - id: current.id - }); - const historyData = res.data; - if (historyData) { - historyId = historyData.id; - } - } - if (historyId) { - const tableData = await handleGetOption( - API_CONSTANTS.GET_JOB_DATA, - l('global.getdata.tips'), - { - jobId: historyId - } - ); - const data = tableData.data; - if (tableData.success && data?.success) { - //mockSinkResult - if (data.mockSinkResult == true) { - consoleData.results = convertMockResultToList(data); - setDataList(consoleData.results); - } else { - consoleData.result = data; - setData(data); - } - } else { - consoleData.result = {}; - setData({}); - } - } - } - } - } - setLoading(false); - }; - - useAsyncEffect(async () => { - setData({}); - setDataList([]); - await loadData(initIsRefresh); - }, [currentTabs?.console?.refreshResult, currentTabs?.console?.refreshResults, currentTabs?.id]); - - const getColumns = (columns: string[] = []) => { - return columns?.map((item) => { - return { - title: item, - dataIndex: item, - sorter: (a, b) => a[item] - b[item], - ...getColumnSearchProps(item) - }; - }) as ColumnsType; - }; - - const showDetail = async () => { - setLoading(true); - await loadData(true); - setLoading(false); - }; - - const renderFlinkSQLContent = () => { - return ( - <> - {current?.jobInstanceId && !data.destroyed ? ( - <> - - - - - ) : undefined} - - ); - }; - const renderDownloadButton = () => { - if (current && data.columns) { - const _utf = '\uFEFF'; - const csvDataBlob = new Blob([_utf + transformTableDataToCsv(data.columns!, data.rowData!)], { - type: 'text/csv' - }); - const url = URL.createObjectURL(csvDataBlob); - return ( - - ); - } - return undefined; - }; - - const renderTips = () => { - return ( - <> - {current?.jobInstanceId && data.truncationFlag ? ( - - - - ) : undefined} - - ); - }; - - return ( -
-
- {renderTips()} - {renderDownloadButton()} - {current && isSql(current?.dialect, true) && renderFlinkSQLContent()} -
- {data.columns ? ( - { - return { ...item, key: index }; - })} - loading={loading} - /> - ) : dataList.length > 0 ? ( - - {dataList.map((data, index) => { - return ( - -
{ - return { ...item, key: index }; - })} - loading={loading} - /> - - ); - })} - - ) : ( - - )} - - ); -}; - -export default connect( - ({ Studio }: { Studio: StateType }) => ({ - tabs: Studio.tabs - }), - mapDispatchToProps -)(Result); diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/TableData/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/TableData/index.tsx deleted file mode 100644 index db7e11b98a..0000000000 --- a/dinky-web/src/pages/DataStudio/BottomContainer/TableData/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { TaskDataType } from '@/pages/DataStudio/model'; -import { postAll } from '@/services/api'; -import { l } from '@/utils/intl'; -import { useModel } from '@@/exports'; -import { Modal, Select } from 'antd'; -import TextArea from 'antd/es/input/TextArea'; -import { Tab } from 'rc-tabs/lib/interface.d'; -import { useEffect, useState } from 'react'; -import { SseData, Topic } from '@/models/UseWebSocketModel'; - -export async function getPrintTables(statement: string) { - return postAll('api/printTable/getPrintTables', { statement }); -} - -/*--- Clear Console ---*/ -export type PrintTable = { - tableName: string; - fullTableName: string; -}; - -export const DataPage = (props: any) => { - const { style, title } = props; - const [consoleInfo, setConsoleInfo] = useState(''); - const { subscribeTopic } = useModel('UseWebSocketModel', (model: any) => ({ - subscribeTopic: model.subscribeTopic - })); - - useEffect(() => { - if (title) { - return subscribeTopic(Topic.PRINT_TABLE, [title.fullTableName], (data: SseData) => { - if (data?.data[title.fullTableName]) { - setConsoleInfo( - (preConsoleInfo) => preConsoleInfo + '\n' + data.data[title.fullTableName] - ); - } - }); - } - }, []); - - return