未验证 提交 73c30cdb 编写于 作者: N Niandalu 提交者: GitHub

feat: update graph page locale file & some code polishment (#573)

* feat: update graph page locale file & some code polishment

* feat: update graph page locale file & some code polishment

* fix: eslint violations

* fix: dedup
上级 e903e752
...@@ -29,6 +29,8 @@ module.exports = { ...@@ -29,6 +29,8 @@ module.exports = {
'react/prop-types': 'off', 'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off', 'react/react-in-jsx-scope': 'off',
'react-hooks/rules-of-hooks': 'error', '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'
} }
}; };
import React, {FunctionComponent} from 'react'; import React, {FunctionComponent} from 'react';
import {useTranslation} from '~/utils/i18n'; import {useTranslation} from '~/utils/i18n';
import {NodeType, TypedNode} from '~/resource/graph'; import {NodeType, TypedNode} from '~/resource/graph';
import styled from 'styled-components';
import {WithStyled} from '~/utils/style';
const typeName: {[k in NodeType]: string} = { const typeName: {[k in NodeType]: string} = {
[NodeType.Input]: 'input', [NodeType.Input]: 'input',
...@@ -12,6 +14,27 @@ export interface NodeInfoProps { ...@@ -12,6 +14,27 @@ export interface NodeInfoProps {
node?: TypedNode | {type: 'unknown'; guessType: NodeType; msg: string}; node?: TypedNode | {type: 'unknown'; guessType: NodeType; msg: string};
} }
const DataList: FunctionComponent<{items: {key: string; value: string | string[]}[]} & WithStyled> = props => {
return (
<ul className={props.className}>
{props.items.map(({key, value}) => (
<li key={key}>
{key}: {value}
</li>
))}
</ul>
);
};
const PropertyList = styled(DataList)`
padding: 0;
list-style: none;
color: #666;
li + li {
margin-top: 1em;
}
`;
const NodeInfo: FunctionComponent<NodeInfoProps> = props => { const NodeInfo: FunctionComponent<NodeInfoProps> = props => {
const {t} = useTranslation(['graphs']); const {t} = useTranslation(['graphs']);
if (!props.node) { if (!props.node) {
...@@ -23,46 +46,28 @@ const NodeInfo: FunctionComponent<NodeInfoProps> = props => { ...@@ -23,46 +46,28 @@ const NodeInfo: FunctionComponent<NodeInfoProps> = props => {
case NodeType.Input: case NodeType.Input:
case NodeType.Output: case NodeType.Output:
return ( return (
<ul> <PropertyList
<li> items={[
{t('node-type')}: {typeName[node.type]} {key: t('node-type'), value: typeName[node.type]},
</li> {key: t('node-name'), value: node.name},
<li> {key: t('node-data-shape'), value: node.shape},
{t('node-name')}: {node.name} {key: t('node-data-tyep'), value: node.data_type}
</li> ]}
<li> />
{t('node-data-shape')}: {node.shape}
</li>
<li>
{t('node-data-type')}: {node.data_type}
</li>
</ul>
); );
case NodeType.Op: case NodeType.Op:
return ( return (
<ul> <PropertyList
<li> items={[
{t('node-type')}: {typeName[node.type]} {key: t('node-type'), value: typeName[node.type]},
</li> {key: t('input'), value: node.input},
<li> {key: t('op-type'), value: node.opType},
{t('input')}: {node.input} {key: t('output'), value: node.output}
</li> ]}
<li> />
{t('op-type')}: {node.opType}
</li>
<li>
{t('output')}: {node.output}
</li>
</ul>
); );
case 'unknown': case 'unknown':
return ( return <PropertyList items={[{key: t('node-type'), value: typeName[node.guessType]}]} />;
<ul>
<li>
{t('node-type')}: {typeName[node.guessType]}
</li>
</ul>
);
default: default:
return <></>; return <></>;
} }
......
...@@ -41,6 +41,41 @@ const GraphSvg = styled('svg')` ...@@ -41,6 +41,41 @@ const GraphSvg = styled('svg')`
.node { .node {
cursor: pointer; 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 { .edgePath path.path {
...@@ -55,9 +90,9 @@ const MAX_SCALE = 4; ...@@ -55,9 +90,9 @@ const MAX_SCALE = 4;
const useDag = (graph?: Graph) => { const useDag = (graph?: Graph) => {
const [displaySwitch, setDisplaySwitch] = useState({ const [displaySwitch, setDisplaySwitch] = useState({
detail: true, detail: false,
input: true, input: false,
output: true output: false
}); });
const facts = useMemo(() => collectDagFacts(graph), [graph]); const facts = useMemo(() => collectDagFacts(graph), [graph]);
...@@ -134,17 +169,23 @@ const useDagreD3 = (graph: Graph | undefined) => { ...@@ -134,17 +169,23 @@ const useDagreD3 = (graph: Graph | undefined) => {
.on('end', () => svg.classed('grabbing', false)); .on('end', () => svg.classed('grabbing', false));
svg.call(zoom); svg.call(zoom);
let prevDom: HTMLElement | undefined;
// install event listeners // install event listeners
svg.selectAll('g.node').on('click', v => { svg.selectAll('g.node').on('click', v => {
const uid = v as string; const uid = v as string;
const {type} = g.node(uid); const {type, elem: dom} = g.node(uid);
const dagNode = dagInfo.findNode(type, uid); if (prevDom) {
if (!dagNode) { 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}); setCurrentNode({type: 'unknown', guessType: type, msg: uid});
return; return;
} }
setCurrentNode({...dagNode, type}); setCurrentNode({...node, type});
}); });
const fitScreen = () => { const fitScreen = () => {
...@@ -209,21 +250,21 @@ const Graphs: NextI18NextPage<GraphsProps> = () => { ...@@ -209,21 +250,21 @@ const Graphs: NextI18NextPage<GraphsProps> = () => {
<section> <section>
<SubSection> <SubSection>
<Button icon="download" onClick={downloadImage}> <Button icon="download" onClick={downloadImage}>
{t('common:download-image')} {t('download-image')}
</Button> </Button>
<Button icon="revert" onClick={fitScreen}> <Button icon="revert" onClick={fitScreen}>
{t('common:restore-image')} {t('restore-image')}
</Button> </Button>
</SubSection> </SubSection>
<SubSection> <SubSection>
<Field label={`${t('common:scale')}:`}> <Field label={`${t('scale')}:`}>
<RangeSlider min={MIN_SCALE} max={MAX_SCALE} step={0.1} value={scale} onChange={setScale} /> <RangeSlider min={MIN_SCALE} max={MAX_SCALE} step={0.1} value={scale} onChange={setScale} />
</Field> </Field>
</SubSection> </SubSection>
<SubSection> <SubSection>
<Field label={`${t('common:node-info')}:`}></Field> <Field label={`${t('node-info')}:`}></Field>
<NodeInfo node={currentNode}></NodeInfo> <NodeInfo node={currentNode}></NodeInfo>
</SubSection> </SubSection>
</section> </section>
......
...@@ -10,10 +10,6 @@ ...@@ -10,10 +10,6 @@
"select": "Please Select", "select": "Please Select",
"runs": "Runs", "runs": "Runs",
"select-runs": "Select Runs", "select-runs": "Select Runs",
"scale": "Scale",
"download-image": "Download Image",
"restore-image": "Restore Image",
"node-info": "Node Info",
"running": "Running", "running": "Running",
"stopped": "Stopped", "stopped": "Stopped",
"loading": "Loading" "loading": "Loading"
......
{ {
"scale": "Scale",
"download-image": "Download Image",
"restore-image": "Restore Image",
"node-info": "Node Info",
"node-type": "Node Type", "node-type": "Node Type",
"node-name": "Node Name", "node-name": "Node Name",
"node-data-shape": "Shape", "node-data-shape": "Shape",
...@@ -6,5 +10,5 @@ ...@@ -6,5 +10,5 @@
"output": "Output", "output": "Output",
"op-type": "Operator Type", "op-type": "Operator Type",
"node-data-type": "Data Type", "node-data-type": "Data Type",
"click-node": "Click a node to display" "click-node": "Click a node to view its detail"
} }
{} {
"scale": "比例",
"download-image": "下载图片",
"restore-image": "还原图片",
"node-info": "节点信息",
"node-type": "节点类型",
"node-name": "节点名称",
"node-data-shape": "数据类型",
"input": "输入",
"output": "输出",
"op-type": "算子类型",
"node-data-type": "数据类型",
"click-node": "点击左侧节点,查看节点信息"
}
import {Graph, Node, NodeUID, InputNode, NodeType} from './types'; import {Graph, Node, NodeUID, InputNode, NodeType} from './types';
import {OpNodeStyle, OutputNodeStyle, InputNodeStyle} from './style';
interface DagNode { interface DagNode {
key: string; key: string;
...@@ -7,7 +6,6 @@ interface DagNode { ...@@ -7,7 +6,6 @@ interface DagNode {
label: string; label: string;
shape: string; shape: string;
class: string; class: string;
style: string;
} }
type DagEdge = [string, string]; type DagEdge = [string, string];
...@@ -124,8 +122,7 @@ const expandRelations = (nodeMapping: NodeRelationMapping) => { ...@@ -124,8 +122,7 @@ const expandRelations = (nodeMapping: NodeRelationMapping) => {
label: bridge, label: bridge,
shape: 'diamond', shape: 'diamond',
class: 'output', class: 'output',
type: NodeType.Output, type: NodeType.Output
style: OutputNodeStyle
}); });
detailLayer.edges.push([inputTo, bridge]); detailLayer.edges.push([inputTo, bridge]);
...@@ -158,8 +155,7 @@ type: ${inputNode.data_type} ...@@ -158,8 +155,7 @@ type: ${inputNode.data_type}
dims: ${inputNode.shape.join(' × ')} dims: ${inputNode.shape.join(' × ')}
`, `,
shape: 'rect', shape: 'rect',
class: 'input', class: 'input'
style: InputNodeStyle
}); });
relations.output.forEach(o => edges.push([inputNodeUID, o])); relations.output.forEach(o => edges.push([inputNodeUID, o]));
...@@ -180,8 +176,7 @@ const extractOutputLayer = (nodeRelationMapping: NodeRelationMapping) => { ...@@ -180,8 +176,7 @@ const extractOutputLayer = (nodeRelationMapping: NodeRelationMapping) => {
type: NodeType.Output, type: NodeType.Output,
label: nodeUID, label: nodeUID,
shape: 'diamond', shape: 'diamond',
class: 'output', class: 'output'
style: OutputNodeStyle
}); });
for (const inputNode of relations.input) { for (const inputNode of relations.input) {
...@@ -208,8 +203,7 @@ export const collectDagFacts = (graph?: Graph) => { ...@@ -208,8 +203,7 @@ export const collectDagFacts = (graph?: Graph) => {
type: NodeType.Op, type: NodeType.Op,
label: n.opType, label: n.opType,
shape: 'rect', shape: 'rect',
class: 'operator', class: 'operator'
style: OpNodeStyle
})); }));
const {briefLayer: bl, detailLayer: dl} = expandRelations(nodeRelationMapping); const {briefLayer: bl, detailLayer: dl} = expandRelations(nodeRelationMapping);
......
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;
`;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册