diff --git a/dinky-web/src/components/FlinkDag/component/DagNode.tsx b/dinky-web/src/components/FlinkDag/component/DagDataNode.tsx similarity index 74% rename from dinky-web/src/components/FlinkDag/component/DagNode.tsx rename to dinky-web/src/components/FlinkDag/component/DagDataNode.tsx index f645535edb..542191c360 100644 --- a/dinky-web/src/components/FlinkDag/component/DagNode.tsx +++ b/dinky-web/src/components/FlinkDag/component/DagDataNode.tsx @@ -18,25 +18,30 @@ */ import StatusTag from '@/components/JobTags/StatusTag'; -import { Jobs } from '@/types/DevOps/data'; import { Card, Col, Row, Tag, Typography } from 'antd'; -const { Text } = Typography; +const { Text, Paragraph } = Typography; -const DagNode = (props: any) => { +const DagDataNode = (props: any) => { const { node } = props; - const vertices: Jobs.JobVertices = node?.getData(); + const data: any = node?.getData(); return ( {vertices.parallelism}} + title={data.name} + extra={{data.parallelism}} > + +
+ {data.description} +
+
+ BackPressure: @@ -51,7 +56,7 @@ const DagNode = (props: any) => { Status: - + Idle:50% @@ -60,4 +65,4 @@ const DagNode = (props: any) => {
); }; -export default DagNode; +export default DagDataNode; diff --git a/dinky-web/src/components/FlinkDag/component/DagPlanNode.tsx b/dinky-web/src/components/FlinkDag/component/DagPlanNode.tsx new file mode 100644 index 0000000000..cb7cdf2a2a --- /dev/null +++ b/dinky-web/src/components/FlinkDag/component/DagPlanNode.tsx @@ -0,0 +1,46 @@ +/* + * + * 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 { Card, Typography } from 'antd'; + +const { Text, Paragraph } = Typography; + +const DagPlanNode = (props: any) => { + const { node } = props; + const data: any = node?.getData(); + + return ( + {data.parallelism}} + > + +
+ {data.description} +
+
+
+ ); +}; +export default DagPlanNode; diff --git a/dinky-web/src/components/FlinkDag/functions.tsx b/dinky-web/src/components/FlinkDag/functions.tsx index 69c5ee345e..c88cdfab77 100644 --- a/dinky-web/src/components/FlinkDag/functions.tsx +++ b/dinky-web/src/components/FlinkDag/functions.tsx @@ -17,94 +17,69 @@ * */ +import { JOB_STATUS } from '@/pages/DevOps/constants'; import { Jobs } from '@/types/DevOps/data'; import { Graph, Path } from '@antv/x6'; -export const buildEdge = (job: Jobs.Job) => { +export const buildDag = (job: Jobs.JobPlan) => { const edges: any = []; + const nodes: any = []; - for (let node of job.plan.nodes) { - if (node.inputs) { - const sources = node.inputs; - for (let i = 0; i < sources.length; i++) { - const plan_node = sources[i]; - edges.push({ - attrs: { - line: { - strokeDasharray: '5', - stroke: '#3471F9', - style: { - animation: 'running-line 30s infinite linear' - } - }, - label: { - text: plan_node.ship_strategy - } - }, - label: plan_node.ship_strategy, - id: `${plan_node.id}-${i}`, - shape: 'data-processing-curve', - zIndex: -1, - source: { - cell: `${plan_node.id}`, - port: `${plan_node.id}-out` - }, - target: { - cell: `${node.id}`, - port: `${node.id}-in` - }, - data: node - }); - } - } - } - return edges; -}; + if (!job) return { nodes: nodes, edges: edges }; -export const buildNode = (job: Jobs.Job) => { - const nodes: any = {}; - - for (let vertice of job.vertices) { - nodes[vertice.id] = { - id: vertice.id, + job.nodes.forEach((node) => { + nodes.push({ + id: node.id, shape: 'data-processing-dag-node', ports: [ { - id: `${vertice.id}-in`, + id: `${node.id}-in`, group: 'in' }, { - id: `${vertice.id}-out`, + id: `${node.id}-out`, group: 'out' } ], - data: vertice - }; - } - return nodes; -}; + data: node + }); + + node.inputs?.forEach((plan_node) => { + edges.push({ + label: plan_node.ship_strategy, + id: `${node.id}-${plan_node.num}`, + shape: 'data-processing-curve', + zIndex: -1, + source: { + cell: `${plan_node.id}`, + port: `${plan_node.id}-out` + }, + target: { + cell: `${node.id}`, + port: `${node.id}-in` + }, + data: node + }); + }); + }); -export const buildData = (job: Jobs.Job) => { - const nodes = Object.values(buildNode(job)); - return { nodes: nodes, edges: buildEdge(job) }; + return { nodes: nodes, edges: edges }; }; -export const updateEdge = (job: Jobs.Job, graph?: Graph) => { - if (graph) { - const nodes = buildNode(job); +export const updateDag = (job: Jobs.JobVertices[], graph?: Graph) => { + if (!job || !graph) return; - graph.getCells().forEach((node) => { - const data = node.getData(); - if (nodes[data.id]) { - console.log(nodes[data.id]); - node.setData(nodes[data.id].data); + if (job && graph) { + job.forEach((vertice) => { + const node = graph.getCellById(vertice.id); + if (node) { + node.setData({ ...node.getData(), ...vertice }); } }); graph.getEdges().forEach((edge) => { - const node = edge.getSourceNode()?.getData(); - - if (node.status == 'RUNNING') { + const nodeData = edge.getSourceNode()?.getData(); + if (nodeData.status == JOB_STATUS.RUNNING) { edge.attr({ line: { stroke: '#3471F9' } }); edge.attr('line/strokeDasharray', 5); edge.attr('line/strokeWidth', 2); @@ -113,11 +88,11 @@ export const updateEdge = (job: Jobs.Job, graph?: Graph) => { edge.attr('line/strokeDasharray', 0); edge.attr('line/style/animation', ''); edge.attr('line/strokeWidth', 1); - if (node.status == 'FINISHED') { + if (nodeData.status == JOB_STATUS.FINISHED) { edge.attr('line/stroke', '#52c41a'); - } else if (node.status == 'CANCELED') { + } else if (nodeData.status == JOB_STATUS.CANCELED) { edge.attr('line/stroke', '#ffe7ba'); - } else if (node.status == 'FAILED') { + } else if (nodeData.status == JOB_STATUS.FAILED) { edge.attr('line/stroke', '#ff4d4f'); } else { edge.attr('line/stroke', '#bfbfbf'); diff --git a/dinky-web/src/components/FlinkDag/index.tsx b/dinky-web/src/components/FlinkDag/index.tsx index 1b10892e61..4eff6e5899 100644 --- a/dinky-web/src/components/FlinkDag/index.tsx +++ b/dinky-web/src/components/FlinkDag/index.tsx @@ -17,9 +17,10 @@ * */ -import DagNode from '@/components/FlinkDag/component/DagNode'; +import DagDataNode from '@/components/FlinkDag/component/DagDataNode'; +import DagPlanNode from '@/components/FlinkDag/component/DagPlanNode'; import { edgeConfig, graphConfig, layoutConfig, portConfig } from '@/components/FlinkDag/config'; -import { buildData, regConnect, updateEdge } from '@/components/FlinkDag/functions'; +import { buildDag, regConnect, updateDag } from '@/components/FlinkDag/functions'; import { Jobs } from '@/types/DevOps/data'; import { DagreLayout } from '@antv/layout'; import { Edge, Graph } from '@antv/x6'; @@ -27,9 +28,16 @@ import { register } from '@antv/x6-react-shape'; import { useEffect, useRef, useState } from 'react'; import './index.css'; -const FlinkDag = (props: { jobDetail: Jobs.JobInfoDetail }) => { +export type DagProps = { + job: Jobs.Job; + onlyPlan?: boolean; +}; + +const FlinkDag = (props: DagProps) => { const container = useRef(null); - const job = props.jobDetail.jobDataDto.job; + + const { job, onlyPlan = false } = props; + const [graph, setGraph] = useState(); const [curentJob, setCurentJob] = useState(); @@ -38,7 +46,7 @@ const FlinkDag = (props: { jobDetail: Jobs.JobInfoDetail }) => { shape: 'data-processing-dag-node', width: 212, height: 48, - component: DagNode, + component: onlyPlan ? DagPlanNode : DagDataNode, ports: portConfig }); @@ -67,11 +75,12 @@ const FlinkDag = (props: { jobDetail: Jobs.JobInfoDetail }) => { }; graph.zoomToFit(zoomOptions); graph.centerContent(); + updateDag(job.vertices, graph); return graph; }; useEffect(() => { - const flinkData = buildData(job); + const flinkData = buildDag(job.plan); // Clean up old data if (graph) { graph.clearCells(); @@ -80,7 +89,7 @@ const FlinkDag = (props: { jobDetail: Jobs.JobInfoDetail }) => { }, [curentJob]); useEffect(() => { - updateEdge(job, graph); + updateDag(job.vertices, graph); if (curentJob != job.jid) { setCurentJob(job.jid); } diff --git a/dinky-web/src/components/JobTags/JobLifeCycleTag.tsx b/dinky-web/src/components/JobTags/JobLifeCycleTag.tsx new file mode 100644 index 0000000000..d558327863 --- /dev/null +++ b/dinky-web/src/components/JobTags/JobLifeCycleTag.tsx @@ -0,0 +1,77 @@ +/* + * 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 { StatusTagProps } from '@/components/JobTags/data'; +import { JOB_LIFE_CYCLE } from '@/pages/DevOps/constants'; +import { l } from '@/utils/intl'; +import { + CameraOutlined, + CarryOutOutlined, + CloseCircleOutlined, + EditOutlined +} from '@ant-design/icons'; +import { Tag } from 'antd'; + +/** + * Renders a tag for the job life cycle based on the provided step. + * + * @returns {JSX.Element} - The tag representing the job life cycle. + * @param props + */ +const JobLifeCycleTag = (props: StatusTagProps) => { + const { status, animation = true, bordered = true } = props; + + const buildParam = () => { + switch (status) { + case JOB_LIFE_CYCLE.DEVELOP: + return { + icon: , + color: 'default', + text: l('global.table.lifecycle.dev') + }; + case JOB_LIFE_CYCLE.RELEASE: + return { + icon: , + color: 'green', + text: l('global.table.lifecycle.publish') + }; + + case JOB_LIFE_CYCLE.ONLINE: + return { + icon: , + color: 'blue', + text: l('global.table.lifecycle.online') + }; + default: + return { + icon: , + color: 'default', + text: status + }; + } + }; + + const param = buildParam(); + return ( + + {param.text} + + ); +}; + +export default JobLifeCycleTag; diff --git a/dinky-web/src/components/JobTags/StatusTag.tsx b/dinky-web/src/components/JobTags/StatusTag.tsx index 326819571b..14d8e450b6 100644 --- a/dinky-web/src/components/JobTags/StatusTag.tsx +++ b/dinky-web/src/components/JobTags/StatusTag.tsx @@ -16,6 +16,7 @@ * */ +import { StatusTagProps } from '@/components/JobTags/data'; import { JOB_STATUS } from '@/pages/DevOps/constants'; import { CheckCircleOutlined, @@ -27,12 +28,12 @@ import { } from '@ant-design/icons'; import { Tag } from 'antd'; -export interface StatusTagProps { - status: string; - animation?: boolean; - bordered?: boolean; -} - +/** + * Renders a tag for the job status based on the provided status. + * + * @returns {JSX.Element} - The tag representing the job status. + * @param props + */ const StatusTag = (props: StatusTagProps) => { const { status, animation = true, bordered = true } = props; @@ -84,8 +85,8 @@ const StatusTag = (props: StatusTagProps) => { default: return { icon: , - color: 'error', - text: 'FAILED' + color: 'default', + text: 'UNKNOWN Status' }; } }; diff --git a/dinky-web/src/components/JobTags/data.d.ts b/dinky-web/src/components/JobTags/data.d.ts new file mode 100644 index 0000000000..ff0c38f5d2 --- /dev/null +++ b/dinky-web/src/components/JobTags/data.d.ts @@ -0,0 +1,5 @@ +export interface StatusTagProps { + status?: any; + animation?: boolean; + bordered?: boolean; +} diff --git a/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/function.tsx b/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/function.tsx deleted file mode 100644 index 75167c8180..0000000000 --- a/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/function.tsx +++ /dev/null @@ -1,60 +0,0 @@ -const escape2Html = (str: string) => { - let arrEntities: Record = { - lt: '<', - gt: '>', - nbsp: ' ', - amp: '&', - quot: '"' - }; - return str.replace(/&(lt|gt|nbsp|amp|quot);/gi, function (all, t) { - return arrEntities[t]; - }); -}; -const getRangeText = (str: string) => { - str = escape2Html(str); - // @ts-ignore - const canvas = getRangeText.canvas || (getRangeText.canvas = document.createElement('canvas')); - const context = canvas.getContext('2d'); - context.font = '10px sans-serif'; - let result = ''; - let count = 1; - for (let i = 0, len = str.length; i < len; i++) { - result += str[i]; - let width = context.measureText(result).width; - if (width >= 110 * count) { - result += '\r\n'; - count++; - } - } - return result; -}; - -export const buildGraphData = (data: any) => { - const edges = []; - for (const i in data.nodes) { - data.nodes[i].id = data.nodes[i].id.toString(); - data.nodes[i].value = { - title: data.nodes[i].pact, - items: [ - { - text: getRangeText(data.nodes[i].description) - }, - { - text: '\r\nParallelism: ', - value: '\r\n ' + data.nodes[i].parallelism - } - ] - }; - if (data.nodes[i].inputs) { - for (let j in data.nodes[i].inputs) { - edges.push({ - source: data.nodes[i].inputs[j].id.toString(), - target: data.nodes[i].id.toString(), - value: data.nodes[i].inputs[j].ship_strategy - }); - } - } - } - data.edges = edges; - return data; -}; diff --git a/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/index.tsx b/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/index.tsx index 67653fcd4c..e00e221d71 100644 --- a/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/index.tsx +++ b/dinky-web/src/pages/DataStudio/HeaderContainer/FlinkGraph/index.tsx @@ -1,85 +1,27 @@ -import { FlowAnalysisGraph } from '@ant-design/charts'; -import { FlowAnalysisGraphConfig } from '@ant-design/graphs/es/components/flow-analysis-graph'; +import FlinkDag from '@/components/FlinkDag'; +import { Jobs } from '@/types/DevOps/data'; import { Empty } from 'antd'; import { StateType } from 'rmc-input-number'; import { connect } from 'umi'; -const FlinkGraph = (props: any) => { +const FlinkGraph = (props: { data: Jobs.JobPlan }) => { const { data } = props; - const config: FlowAnalysisGraphConfig = { - data, - height: 350, - nodeCfg: { - size: [160, 65], - items: { - autoEllipsis: false, - padding: [10], - containerStyle: { - fill: '#fff', - width: '100px' - }, - style: (cfg, group, type) => { - const styles = { - value: { - fill: '#000' - }, - text: { - fill: '#222', - width: '100px' - } - }; - return styles[type]; - } - }, - nodeStateStyles: { - hover: { - stroke: '#1890ff', - lineWidth: 2 - } - }, - style: { - fill: '#40a9ff', - stroke: '#1890ff' - } - }, - edgeCfg: { - type: 'polyline', - label: { - style: { - fill: '#666', - fontSize: 12, - fillOpacity: 1 - } - }, - endArrow: { - fill: '#333' - }, - edgeStateStyles: { - hover: { - stroke: '#1890ff', - lineWidth: 2 - } - } - }, - markerCfg: (cfg) => { - const { edges } = data; - return { - position: 'right', - show: edges.find((item) => item.source === cfg.id), - collapsed: !edges.find((item) => item.source === cfg.id) - }; - }, - behaviors: ['drag-canvas', 'zoom-canvas', 'drag-node'] - /*layout: { - rankdir: 'TB', - ranksepFunc: () => 20, - },*/ - }; + const job = { + plan: data + } as Jobs.Job; return ( - <>{data ? : } + <> + {data ? ( +
+ +
+ ) : ( + + )} + ); }; -export default connect(({ Studio }: { Studio: StateType }) => ({}))(FlinkGraph); +export default connect(({}: { Studio: StateType }) => ({}))(FlinkGraph); diff --git a/dinky-web/src/pages/DataStudio/HeaderContainer/index.tsx b/dinky-web/src/pages/DataStudio/HeaderContainer/index.tsx index 2e6466c226..c439f89aa8 100644 --- a/dinky-web/src/pages/DataStudio/HeaderContainer/index.tsx +++ b/dinky-web/src/pages/DataStudio/HeaderContainer/index.tsx @@ -20,7 +20,6 @@ import { FlexCenterDiv } from '@/components/StyledComponents'; import { getCurrentData, getCurrentTab, mapDispatchToProps } from '@/pages/DataStudio/function'; import Explain from '@/pages/DataStudio/HeaderContainer/Explain'; import FlinkGraph from '@/pages/DataStudio/HeaderContainer/FlinkGraph'; -import { buildGraphData } from '@/pages/DataStudio/HeaderContainer/FlinkGraph/function'; import { buildBreadcrumbItems, projectCommonShow @@ -245,7 +244,7 @@ const HeaderContainer = (props: any) => { title: l('pages.datastudio.editor.explan.tip'), width: '100%', icon: null, - content: , + content: , cancelButtonProps: { style: { display: 'none' } } }); } diff --git a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/JobOverview.tsx b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/JobOverview.tsx index dc4dc4d0f8..886af7f529 100644 --- a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/JobOverview.tsx +++ b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/JobOverview.tsx @@ -35,7 +35,7 @@ const JobConfigTab = (props: JobProps) => { height: '40vh' }} > - + diff --git a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/FlinkTable.tsx b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/FlinkTable.tsx index 1cb97587a7..564d7f1c26 100644 --- a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/FlinkTable.tsx +++ b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/FlinkTable.tsx @@ -1,4 +1,4 @@ -import { TagJobStatus } from '@/pages/DevOps/function'; +import StatusTag from '@/components/JobTags/StatusTag'; import { JobProps } from '@/pages/DevOps/JobDetail/data'; import { parseByteStr, parseMilliSecondStr, parseNumStr } from '@/utils/function'; import { l } from '@/utils/intl'; @@ -42,7 +42,7 @@ const FlinkTable = (props: JobProps): JSX.Element => { dataIndex: 'status', sorter: true, render: (dom, entity) => { - return <>{TagJobStatus(entity.status)}; + return ; } }, { diff --git a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/JobDesc.tsx b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/JobDesc.tsx index d4a808ae4f..3e1f4f6ff9 100644 --- a/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/JobDesc.tsx +++ b/dinky-web/src/pages/DevOps/JobDetail/JobOverview/components/JobDesc.tsx @@ -1,4 +1,4 @@ -import { TagJobStatus } from '@/pages/DevOps/function'; +import StatusTag from '@/components/JobTags/StatusTag'; import { JobProps } from '@/pages/DevOps/JobDetail/data'; import { parseSecondStr } from '@/utils/function'; import { l } from '@/utils/intl'; @@ -58,7 +58,7 @@ const JobDesc = (props: JobProps) => { - {TagJobStatus(jobDetail?.instance?.status)} + diff --git a/dinky-web/src/pages/DevOps/JobDetail/index.tsx b/dinky-web/src/pages/DevOps/JobDetail/index.tsx index cb8b455bf1..a1177ef009 100644 --- a/dinky-web/src/pages/DevOps/JobDetail/index.tsx +++ b/dinky-web/src/pages/DevOps/JobDetail/index.tsx @@ -17,8 +17,7 @@ * */ -import Lineage from '@/components/FlinkDag'; -import { TagJobLifeCycle } from '@/pages/DevOps/function'; +import JobLifeCycleTag from '@/components/JobTags/JobLifeCycleTag'; import CheckPoints from '@/pages/DevOps/JobDetail/CheckPointsTab'; import JobLogsTab from '@/pages/DevOps/JobDetail/JobLogs/JobLogsTab'; import JobMetrics from '@/pages/DevOps/JobDetail/JobMetrics'; @@ -72,14 +71,14 @@ const JobDetail = (props: any) => { [OperatorEnum.JOB_VERSION]: , [OperatorEnum.JOB_CHECKPOINTS]: , [OperatorEnum.JOB_METRICS]: , - [OperatorEnum.JOB_LINEAGE]: , + // [OperatorEnum.JOB_LINEAGE]: , [OperatorEnum.JOB_ALERT]: , [OperatorEnum.JOB_GRAPH]: }; useRequest( { - url: API_CONSTANTS.GET_JOB_DETAIL, + url: API_CONSTANTS.REFESH_JOB_DETAIL, params: { id: id } }, { @@ -127,7 +126,7 @@ const JobDetail = (props: any) => { return ( } ghost={false} extra={} onBack={() => window.history.back()} diff --git a/dinky-web/src/pages/DevOps/JobList/components/JobHistoryList.tsx b/dinky-web/src/pages/DevOps/JobList/components/JobHistoryList.tsx index 9119db45c2..86607e0d37 100644 --- a/dinky-web/src/pages/DevOps/JobList/components/JobHistoryList.tsx +++ b/dinky-web/src/pages/DevOps/JobList/components/JobHistoryList.tsx @@ -1,4 +1,4 @@ -import { TagJobStatus } from '@/pages/DevOps/function'; +import StatusTag from '@/components/JobTags/StatusTag'; import { queryList } from '@/services/api'; import { API_CONSTANTS } from '@/services/endpoints'; import { Jobs } from '@/types/DevOps/data'; @@ -36,7 +36,7 @@ const JobHistoryList = (props: HistoryProps) => { { title: l('global.table.status'), dataIndex: 'status', - render: (_: any, row: { status: string | undefined }) => TagJobStatus(row.status) + render: (_: any, row: { status: string | undefined }) => }, { title: l('global.table.useTime'), diff --git a/dinky-web/src/pages/DevOps/JobList/index.tsx b/dinky-web/src/pages/DevOps/JobList/index.tsx index f2fa9349ca..0800d8be2f 100644 --- a/dinky-web/src/pages/DevOps/JobList/index.tsx +++ b/dinky-web/src/pages/DevOps/JobList/index.tsx @@ -1,9 +1,6 @@ -import { - JOB_STATUS_FILTER, - LIFECYCLE_FILTER, - TagJobLifeCycle, - TagJobStatus -} from '@/pages/DevOps/function'; +import JobLifeCycleTag from '@/components/JobTags/JobLifeCycleTag'; +import StatusTag from '@/components/JobTags/StatusTag'; +import { JOB_STATUS_FILTER, LIFECYCLE_FILTER } from '@/pages/DevOps/function'; import JobHistoryList from '@/pages/DevOps/JobList/components/JobHistoryList'; import { queryList } from '@/services/api'; import { PROTABLE_OPTIONS_PUBLIC } from '@/services/constants'; @@ -36,7 +33,7 @@ const JobList = () => { hideInSearch: true, filterMultiple: false, dataIndex: 'step', - render: (_: any, row: { step: number }) => TagJobLifeCycle(row.step) + render: (_: any, row: { step: number }) => }, { title: l('global.table.runmode'), @@ -64,7 +61,7 @@ const JobList = () => { filterMultiple: false, hideInSearch: true, dataIndex: 'status', - render: (_: any, row: Jobs.JobInstance) => TagJobStatus(row.status) + render: (_: any, row: Jobs.JobInstance) => }, Table.EXPAND_COLUMN, { diff --git a/dinky-web/src/pages/DevOps/function.tsx b/dinky-web/src/pages/DevOps/function.tsx index dd1b281c3e..86de579110 100644 --- a/dinky-web/src/pages/DevOps/function.tsx +++ b/dinky-web/src/pages/DevOps/function.tsx @@ -17,108 +17,6 @@ import { JOB_LIFE_CYCLE, JOB_STATUS } from '@/pages/DevOps/constants'; import { l } from '@/utils/intl'; -import { - CameraOutlined, - CarryOutOutlined, - CheckCircleOutlined, - ClockCircleOutlined, - CloseCircleOutlined, - EditOutlined, - MinusCircleOutlined, - QuestionCircleOutlined, - SyncOutlined -} from '@ant-design/icons'; -import { Tag } from 'antd'; - -/** - * Renders a tag for the job life cycle based on the provided step. - * - * @param {number} step - The step in the job life cycle. - * @returns {JSX.Element} - The tag representing the job life cycle. - */ -export const TagJobLifeCycle = (step?: number) => { - switch (step) { - case JOB_LIFE_CYCLE.DEVELOP: - return ( - } color='default'> - {l('global.table.lifecycle.dev')} - - ); - case JOB_LIFE_CYCLE.RELEASE: - return ( - } color='green'> - {l('global.table.lifecycle.publish')} - - ); - case JOB_LIFE_CYCLE.ONLINE: - return ( - } color='blue'> - {l('global.table.lifecycle.online')} - - ); - default: - return step; - } -}; - -/** - * Renders a tag for the job status based on the provided status. - * - * @param {string|undefined} status - The status of the job. - * @returns {JSX.Element} - The tag representing the job status. - */ -export const TagJobStatus = (status: string | undefined) => { - switch (status) { - case JOB_STATUS.RUNNING: - return ( - } color='green'> - RUNNING - - ); - case JOB_STATUS.FINISHED: - return ( - } color='blue'> - FINISHED - - ); - case JOB_STATUS.CANCELED: - return ( - } color='orange'> - CANCELED - - ); - case JOB_STATUS.INITIALIZING: - return ( - } color='default'> - INITIALIZING - - ); - case JOB_STATUS.RESTARTING: - return ( - } color='default'> - RESTARTING - - ); - case JOB_STATUS.CREATED: - return ( - } color='default'> - CREATED - - ); - case JOB_STATUS.UNKNOWN: - return ( - } color='default'> - UNKNOWN - - ); - default: - return ( - } color='error'> - FAILED - - ); - } -}; /** * Generates an array of options for the life cycle filter. diff --git a/dinky-web/src/pages/Metrics/Job/index.tsx b/dinky-web/src/pages/Metrics/Job/index.tsx index 44515cd770..3856c437ee 100644 --- a/dinky-web/src/pages/Metrics/Job/index.tsx +++ b/dinky-web/src/pages/Metrics/Job/index.tsx @@ -84,7 +84,7 @@ const Job = () => { * @returns {Promise} */ const getFlinkTaskDetail = async (id: number) => { - return await getData(API_CONSTANTS.GET_JOB_DETAIL, { id: id }); + return await getData(API_CONSTANTS.REFESH_JOB_DETAIL, { id: id }); }; /** diff --git a/dinky-web/src/services/endpoints.tsx b/dinky-web/src/services/endpoints.tsx index 89d5ec9731..3c6d1d56e1 100644 --- a/dinky-web/src/services/endpoints.tsx +++ b/dinky-web/src/services/endpoints.tsx @@ -216,6 +216,7 @@ export enum API_CONSTANTS { GET_JOB_LIST = '/api/jobInstance', GET_JOB_BY_ID = '/api/jobInstance/getOneById', GET_JOB_DETAIL = '/api/jobInstance/getJobInfoDetail', + REFESH_JOB_DETAIL = '/api/jobInstance/refreshJobInfoDetail', GET_JOB_VERSION = '/api/task/version', GET_JOBMANAGER_LOG = 'api/jobInstance/getJobManagerLog', GET_JOBMANAGER_STDOUT = 'api/jobInstance/getJobManagerStdOut', diff --git a/dinky-web/src/types/DevOps/data.d.ts b/dinky-web/src/types/DevOps/data.d.ts index e4fc47f162..8fe76ce874 100644 --- a/dinky-web/src/types/DevOps/data.d.ts +++ b/dinky-web/src/types/DevOps/data.d.ts @@ -93,6 +93,30 @@ declare namespace Jobs { metrics: VetricsMetrics; }; + export type JobNodeInput = { + num: number; + id: string; + ship_strategy: string; + exchange: string; + }; + + export type JobNode = { + id: string; + parallelism: number; + operator: string; + operator_strategy: string; + description: string; + inputs: JobNodeInput[]; + optimizer_properties: any; + }; + + export type JobPlan = { + jid: string; + name: string; + type: string; + nodes: JobNode[]; + }; + export type Job = { jid: string; name: string; @@ -106,8 +130,9 @@ declare namespace Jobs { timestamps: any; vertices: JobVertices[]; 'status-counts': any; - plan: any; + plan: JobPlan; }; + export type JobDataDtoItem = { id: number; job: Job;