diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js
index 4ca5f79974d3a39de7033ec71328019cd3f1659f..228d946dac3f2943be47d926b616195eeda4c59f 100644
--- a/frontend/.eslintrc.js
+++ b/frontend/.eslintrc.js
@@ -29,6 +29,8 @@ module.exports = {
'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off',
'react-hooks/rules-of-hooks': 'error',
- 'react-hooks/exhaustive-deps': 'warn'
+ 'react-hooks/exhaustive-deps': 'warn',
+ '@typescript-eslint/no-explicit-any': 'error',
+ 'no-console': 'warn'
}
};
diff --git a/frontend/components/GraphPage/NodeInfo.tsx b/frontend/components/GraphPage/NodeInfo.tsx
index 793cc9e7e1d409dc291f2b268b6389ea15daa33d..3f5cf56d92a04cf12dfb6a53217983f7a2cdb927 100644
--- a/frontend/components/GraphPage/NodeInfo.tsx
+++ b/frontend/components/GraphPage/NodeInfo.tsx
@@ -1,6 +1,8 @@
import React, {FunctionComponent} from 'react';
import {useTranslation} from '~/utils/i18n';
import {NodeType, TypedNode} from '~/resource/graph';
+import styled from 'styled-components';
+import {WithStyled} from '~/utils/style';
const typeName: {[k in NodeType]: string} = {
[NodeType.Input]: 'input',
@@ -12,6 +14,27 @@ export interface NodeInfoProps {
node?: TypedNode | {type: 'unknown'; guessType: NodeType; msg: string};
}
+const DataList: FunctionComponent<{items: {key: string; value: string | string[]}[]} & WithStyled> = props => {
+ return (
+
+ {props.items.map(({key, value}) => (
+ -
+ {key}: {value}
+
+ ))}
+
+ );
+};
+
+const PropertyList = styled(DataList)`
+ padding: 0;
+ list-style: none;
+ color: #666;
+ li + li {
+ margin-top: 1em;
+ }
+`;
+
const NodeInfo: FunctionComponent = props => {
const {t} = useTranslation(['graphs']);
if (!props.node) {
@@ -23,46 +46,28 @@ const NodeInfo: FunctionComponent = props => {
case NodeType.Input:
case NodeType.Output:
return (
-
- -
- {t('node-type')}: {typeName[node.type]}
-
- -
- {t('node-name')}: {node.name}
-
- -
- {t('node-data-shape')}: {node.shape}
-
- -
- {t('node-data-type')}: {node.data_type}
-
-
+
);
case NodeType.Op:
return (
-
- -
- {t('node-type')}: {typeName[node.type]}
-
- -
- {t('input')}: {node.input}
-
- -
- {t('op-type')}: {node.opType}
-
- -
- {t('output')}: {node.output}
-
-
+
);
case 'unknown':
- return (
-
- -
- {t('node-type')}: {typeName[node.guessType]}
-
-
- );
+ return ;
default:
return <>>;
}
diff --git a/frontend/pages/graphs.tsx b/frontend/pages/graphs.tsx
index e3a9f4463e08ae24d9548984b7d0d1845bf673a7..0a3b0f2dca28fb5bf785213dbdf5332116ff4b0d 100644
--- a/frontend/pages/graphs.tsx
+++ b/frontend/pages/graphs.tsx
@@ -41,6 +41,41 @@ const GraphSvg = styled('svg')`
.node {
cursor: pointer;
+
+ .label-container {
+ stroke-width: 3px;
+ stroke: #e6e6e6;
+ &.rect {
+ rx: 10;
+ ry: 10;
+ }
+ }
+
+ &.operator {
+ .label-container {
+ fill: #cdd9da;
+ }
+ }
+
+ &.output {
+ .label-container {
+ stroke-dasharray: 5, 5;
+ stroke: #e6e6e6;
+ fill: #cad2d0;
+ }
+ }
+
+ &.input {
+ .label-container {
+ fill: #d5d3d8;
+ }
+ }
+
+ &.active {
+ .label-container {
+ stroke: #25c9ff;
+ }
+ }
}
.edgePath path.path {
@@ -55,9 +90,9 @@ const MAX_SCALE = 4;
const useDag = (graph?: Graph) => {
const [displaySwitch, setDisplaySwitch] = useState({
- detail: true,
- input: true,
- output: true
+ detail: false,
+ input: false,
+ output: false
});
const facts = useMemo(() => collectDagFacts(graph), [graph]);
@@ -134,17 +169,23 @@ const useDagreD3 = (graph: Graph | undefined) => {
.on('end', () => svg.classed('grabbing', false));
svg.call(zoom);
+ let prevDom: HTMLElement | undefined;
// install event listeners
svg.selectAll('g.node').on('click', v => {
const uid = v as string;
- const {type} = g.node(uid);
- const dagNode = dagInfo.findNode(type, uid);
- if (!dagNode) {
+ const {type, elem: dom} = g.node(uid);
+ if (prevDom) {
+ prevDom.classList.remove('active');
+ }
+ dom.classList.add('active');
+ prevDom = dom;
+ const node = dagInfo.findNode(type, uid);
+ if (!node) {
setCurrentNode({type: 'unknown', guessType: type, msg: uid});
return;
}
- setCurrentNode({...dagNode, type});
+ setCurrentNode({...node, type});
});
const fitScreen = () => {
@@ -209,21 +250,21 @@ const Graphs: NextI18NextPage = () => {
-
+
-
+
diff --git a/frontend/public/static/locales/en/common.json b/frontend/public/static/locales/en/common.json
index 5b47327d35afb142b34495d37a35dfff17c42452..6a7b98d6984d7bc04c969420612cfe8ee4260806 100644
--- a/frontend/public/static/locales/en/common.json
+++ b/frontend/public/static/locales/en/common.json
@@ -10,10 +10,6 @@
"select": "Please Select",
"runs": "Runs",
"select-runs": "Select Runs",
- "scale": "Scale",
- "download-image": "Download Image",
- "restore-image": "Restore Image",
- "node-info": "Node Info",
"running": "Running",
"stopped": "Stopped",
"loading": "Loading"
diff --git a/frontend/public/static/locales/en/graphs.json b/frontend/public/static/locales/en/graphs.json
index 6d8675162d2b9ee4fb455f0af2e1b233aed17101..75b39d521f2666fa8b7fab8cb58d6f6059785498 100644
--- a/frontend/public/static/locales/en/graphs.json
+++ b/frontend/public/static/locales/en/graphs.json
@@ -1,4 +1,8 @@
{
+ "scale": "Scale",
+ "download-image": "Download Image",
+ "restore-image": "Restore Image",
+ "node-info": "Node Info",
"node-type": "Node Type",
"node-name": "Node Name",
"node-data-shape": "Shape",
@@ -6,5 +10,5 @@
"output": "Output",
"op-type": "Operator Type",
"node-data-type": "Data Type",
- "click-node": "Click a node to display"
+ "click-node": "Click a node to view its detail"
}
diff --git a/frontend/public/static/locales/zh/graphs.json b/frontend/public/static/locales/zh/graphs.json
index 0967ef424bce6791893e9a57bb952f80fd536e93..12493b89c8be0634cc60d4523f19a903e9a2a009 100644
--- a/frontend/public/static/locales/zh/graphs.json
+++ b/frontend/public/static/locales/zh/graphs.json
@@ -1 +1,14 @@
-{}
+{
+ "scale": "比例",
+ "download-image": "下载图片",
+ "restore-image": "还原图片",
+ "node-info": "节点信息",
+ "node-type": "节点类型",
+ "node-name": "节点名称",
+ "node-data-shape": "数据类型",
+ "input": "输入",
+ "output": "输出",
+ "op-type": "算子类型",
+ "node-data-type": "数据类型",
+ "click-node": "点击左侧节点,查看节点信息"
+}
diff --git a/frontend/resource/graph/collectDagFacts.ts b/frontend/resource/graph/collectDagFacts.ts
index d21565f67322b3902ef06a2b04d059f3a93b06ca..b6e2501f4b93777034e8a781e27980571f613ccc 100644
--- a/frontend/resource/graph/collectDagFacts.ts
+++ b/frontend/resource/graph/collectDagFacts.ts
@@ -1,5 +1,4 @@
import {Graph, Node, NodeUID, InputNode, NodeType} from './types';
-import {OpNodeStyle, OutputNodeStyle, InputNodeStyle} from './style';
interface DagNode {
key: string;
@@ -7,7 +6,6 @@ interface DagNode {
label: string;
shape: string;
class: string;
- style: string;
}
type DagEdge = [string, string];
@@ -124,8 +122,7 @@ const expandRelations = (nodeMapping: NodeRelationMapping) => {
label: bridge,
shape: 'diamond',
class: 'output',
- type: NodeType.Output,
- style: OutputNodeStyle
+ type: NodeType.Output
});
detailLayer.edges.push([inputTo, bridge]);
@@ -158,8 +155,7 @@ type: ${inputNode.data_type}
dims: ${inputNode.shape.join(' × ')}
`,
shape: 'rect',
- class: 'input',
- style: InputNodeStyle
+ class: 'input'
});
relations.output.forEach(o => edges.push([inputNodeUID, o]));
@@ -180,8 +176,7 @@ const extractOutputLayer = (nodeRelationMapping: NodeRelationMapping) => {
type: NodeType.Output,
label: nodeUID,
shape: 'diamond',
- class: 'output',
- style: OutputNodeStyle
+ class: 'output'
});
for (const inputNode of relations.input) {
@@ -208,8 +203,7 @@ export const collectDagFacts = (graph?: Graph) => {
type: NodeType.Op,
label: n.opType,
shape: 'rect',
- class: 'operator',
- style: OpNodeStyle
+ class: 'operator'
}));
const {briefLayer: bl, detailLayer: dl} = expandRelations(nodeRelationMapping);
diff --git a/frontend/resource/graph/style.ts b/frontend/resource/graph/style.ts
deleted file mode 100644
index d3483721e5dd58afa2a4c28c9359039633ee2f8d..0000000000000000000000000000000000000000
--- a/frontend/resource/graph/style.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export const OpNodeStyle = `
-stroke-width: 3px;
-opacity: 0.1;
-rx: 10;
-ry: 10;
-stroke: #333;
-stroke-color: #41b3a3;
-fill: #008c99;
-`;
-
-export const OutputNodeStyle = `
-opacity: 0.1;
-stroke-width: 3px;
-stroke-dasharray: 5, 5;
-stroke: #333;
-stroke-color: #41b3a3;
-fill: #015249;
-`;
-
-export const InputNodeStyle = `
-opacity: 0.1;
-stroke-width: 3px;
-stroke: #333;
-stroke-color: #41b3a3;
-fill: #6c648b;
-`;