From 75e9f739d0c719c7ad2ed72bd7bd9d23e3de2e8e Mon Sep 17 00:00:00 2001 From: hlomzik Date: Mon, 1 Jun 2020 18:05:31 +0700 Subject: [PATCH] Improve and fix side panel styles * Highlight relations of selected region * Show number and color of region in the corresponding relation * Tidy up mock-up * Fix alignment and text-overflow * Rewrite Node/NodeMinimal --- src/components/Entities/Entities.js | 104 +++---- src/components/Entities/Entities.module.scss | 24 +- src/components/Entity/Entity.js | 2 +- src/components/Node/Node.js | 274 ++++++------------ src/components/Node/Node.module.scss | 14 + src/components/Relations/Relations.js | 8 +- .../Relations/Relations.module.scss | 9 + 7 files changed, 171 insertions(+), 264 deletions(-) diff --git a/src/components/Entities/Entities.js b/src/components/Entities/Entities.js index afc907620..6546a50fd 100644 --- a/src/components/Entities/Entities.js +++ b/src/components/Entities/Entities.js @@ -27,70 +27,56 @@ const RenderSubState = observer(({ item, idx }) => { }); const EntityItem = observer(({ item, idx }) => { - const selected = item.selected ? "#f1f1f1" : "transparent"; - // const selected = item.selected ? "1px dashed #00aeff" : "none"; - const oneColor = item.getOneColor(); + const classnames = [styles.lstitem, item.hidden === true && styles.hidden, item.selected && styles.selected].filter( + Boolean, + ); - let opacity = 1.0; - let style = {}; + const oneColor = item.getOneColor(); + let badgeStyle = {}; if (oneColor) { - style = { + badgeStyle = { backgroundColor: oneColor, }; } else { - style = { + badgeStyle = { backgroundColor: "#fff", color: "#999", boxShadow: "0 0 0 1px #d9d9d9 inset", }; } - if (item.hidden === true) { - opacity = 0.3; - } - return ( -
- { - getRoot(item).completionStore.selected.regionStore.unselectAll(); - item.selectRegion(); - }} - onMouseOver={() => { - item.toggleHighlight(); - }} - onMouseOut={() => { - item.toggleHighlight(); - }} - > - - -   + { + getRoot(item).completionStore.selected.regionStore.unselectAll(); + item.selectRegion(); + }} + onMouseOver={() => { + item.toggleHighlight(); + }} + onMouseOut={() => { + item.toggleHighlight(); + }} + > + + + + {!item.editable && } + + {item.score && ( + + {item.score.toFixed(2)} - -
- {item.readonly && ro} - - {item.score && ( - - {item.score.toFixed(2)} - - )} -
-
- {/*
*/} - {/* {item.selected && } */} - {/*
*/} -
+ )} + ); }); @@ -233,19 +219,11 @@ export default observer(({ store, regionStore }) => { {regions.length > 0 && ( -
- - e.preventDefault()}> - Sort - - -     - {/* */} - {/* e.preventDefault()}> */} - {/* Group */} - {/* */} - {/* */} -
+ + e.preventDefault()}> + Sort + + )} {!regions.length &&

No Regions created yet

} diff --git a/src/components/Entities/Entities.module.scss b/src/components/Entities/Entities.module.scss index 8db8a363c..5e4e0d7cc 100644 --- a/src/components/Entities/Entities.module.scss +++ b/src/components/Entities/Entities.module.scss @@ -16,14 +16,24 @@ .lstitem { cursor: pointer; align-items: center; + justify-content: start; display: flex; + position: relative; + + & > *:not(:last-child), + & [role="img"] { + margin-right: 6px; + } + + &.hidden { + opacity: 0.3; + } + + &.selected { + background: #f1f1f1; + } } -.confbadge { - background: #efefef; - padding-left: 4px; - border-radius: 10px; - padding-right: 5px; - font-size: 12px; - margin-left: 2px; +.list .lstitem { + border-bottom: none; } diff --git a/src/components/Entity/Entity.js b/src/components/Entity/Entity.js index 374e797d0..58bbd2484 100644 --- a/src/components/Entity/Entity.js +++ b/src/components/Entity/Entity.js @@ -67,7 +67,7 @@ export default observer(({ store, completion }) => { return ( -

+

(id: {node.id}){" "} {!node.editable && }

diff --git a/src/components/Node/Node.js b/src/components/Node/Node.js index c6e7c0394..9918309b7 100644 --- a/src/components/Node/Node.js +++ b/src/components/Node/Node.js @@ -1,5 +1,5 @@ import React, { Fragment } from "react"; -import { Icon } from "antd"; +import { Badge } from "antd"; import { getType, getRoot } from "mobx-state-tree"; import { observer } from "mobx-react"; import { @@ -16,120 +16,55 @@ import { import styles from "./Node.module.scss"; -const pt = { paddingTop: "4px" }; - const NodeViews = { - TextRegionModel: (node, click) => ( - - - -   - {node.text.substring(0, 23)} - {node.text.length > 26 && "..."} - - - ), - - HyperTextRegionModel: (node, click) => ( - - - -   HTML   - {node.text} - - - ), - - AudioRegionModel: (node, click) => ( - - - -   Audio {node.start.toFixed(2)} - {node.end.toFixed(2)} - - - ), - - TextAreaRegionModel: (node, click) => ( - - - -   Input {node._value} - - - ), - - RectRegionModel: (node, click) => { - const w = node.width * node.scaleX; - const y = node.height * node.scaleY; - return ( - - - -   Rectangle {w.toFixed(2)} x {y.toFixed(2)} - - - ); - }, - - PolygonRegionModel: (node, click) => ( - - - -   Polygon - - - ), - - EllipseRegionModel: (node, click) => { - const radiusX = node.radiusX * node.scaleX; - const radiusY = node.radiusY * node.scaleY; - const rotation = node.rotation; - return ( + TextRegionModel: ["Text", FontColorsOutlined, node => {node.text.substring(0, 100)}], + + HyperTextRegionModel: ["HTML", FontColorsOutlined, node => {node.text}], + + AudioRegionModel: ["Audio", AudioOutlined, node => `Audio ${node.start.toFixed(2)} - ${node.end.toFixed(2)}`], + + TextAreaRegionModel: [ + "Input", + MessageOutlined, + node => ( - - -   Ellipse {radiusX.toFixed(2)} x {radiusY.toFixed(2)}, θ = {rotation.toFixed(2)}°, center = ( - {node.x.toFixed(2)}, {node.y.toFixed(2)}) - + Input {node._value} - ); - }, - - KeyPointRegionModel: (node, click) => ( - - - -   KeyPoint - - - ), - - BrushRegionModel: (node, click) => ( - - - -   Brush - - - ), - - ChoicesModel: (node, click) => ( - - - -   Classification - - - ), - - TextAreaModel: (node, click) => ( - - - -   Input - - - ), + ), + ], + + RectRegionModel: [ + "Rect", + BlockOutlined, + node => { + const w = node.width * node.scaleX; + const y = node.height * node.scaleY; + return `Rectangle ${w.toFixed(2)} x ${y.toFixed(2)}`; + }, + ], + + PolygonRegionModel: ["Polygon", GatewayOutlined, () => `Polygon`], + + EllipseRegionModel: [ + "Ellipse", + Loading3QuartersOutlined, + node => { + const radiusX = node.radiusX * node.scaleX; + const radiusY = node.radiusY * node.scaleY; + const rotation = node.rotation; + return `Ellipse ${radiusX.toFixed(2)} x ${radiusY.toFixed(2)}, θ = ${rotation.toFixed(2)}°, + center = (${node.x.toFixed(2)}, ${node.y.toFixed(2)})`; + }, + ], + + // @todo add coords + KeyPointRegionModel: ["KeyPoint", EyeOutlined, () => `KeyPoint`], + + BrushRegionModel: ["Brush", HighlightOutlined, () => `Brush`], + + ChoicesModel: ["Classification", ApartmentOutlined, () => `Classification`], + + TextAreaModel: ["Input", MessageOutlined, () => `Input`], }; const Node = observer(({ node, onClick }) => { @@ -145,88 +80,45 @@ const Node = observer(({ node, onClick }) => { const name = getType(node).name; if (!(name in NodeViews)) console.error(`No ${name} in NodeView`); - return NodeViews[name](node, onClick || click); -}); - -const NodeMinimal = ({ node }) => { - if (getType(node).name === "TextRegionModel") { - return ( - -   Text - - ); - } - - if (getType(node).name === "RectRegionModel") { - return ( - - -   Rect - - ); - } + const [, Icon, getContent] = NodeViews[name]; - if (getType(node).name === "EllipseRegionModel") { - return ( - - -   Ellipse - - ); - } - - if (getType(node).name === "AudioRegionModel") { - return ( - - -   Audio - - ); - } - - if (getType(node).name === "TextAreaRegionModel") { - return ( - - -   Input - - ); - } - - if (getType(node).name === "HyperTextRegionModel") { - return ( - -   HTML - - ); - } - - if (getType(node).name === "PolygonRegionModel") { - return ( - - -   Polygon - - ); - } + return ( + + + {getContent(node)} + + ); +}); - if (getType(node).name === "KeyPointRegionModel") { - return ( - - -   KeyPoint - - ); +const NodeMinimal = observer(({ node }) => { + const { sortedRegions: regions } = getRoot(node).completionStore.selected.regionStore; + const index = regions.indexOf(node); + const name = getType(node).name; + if (!(name in NodeViews)) return null; + + const oneColor = node.getOneColor(); + let badgeStyle = {}; + + if (oneColor) { + badgeStyle = { + backgroundColor: oneColor, + }; + } else { + badgeStyle = { + backgroundColor: "#fff", + color: "#999", + boxShadow: "0 0 0 1px #d9d9d9 inset", + }; } - if (getType(node).name === "BrushRegionModel") { - return ( - - -   Brush - - ); - } -}; + const [text, Icon] = NodeViews[name]; + return ( + + {index >= 0 && } + + {text} + + ); +}); export { Node, NodeMinimal }; diff --git a/src/components/Node/Node.module.scss b/src/components/Node/Node.module.scss index 18e5dedd9..4edbe720e 100644 --- a/src/components/Node/Node.module.scss +++ b/src/components/Node/Node.module.scss @@ -1,6 +1,20 @@ .node { + flex-basis: 100%; color: #262626; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + &:hover { color: #1890ff; } } + +.minimal { + display: flex; + align-items: center; + & > * { + margin-right: 6px; + } +} diff --git a/src/components/Relations/Relations.js b/src/components/Relations/Relations.js index 0cf4fdca8..56998301c 100644 --- a/src/components/Relations/Relations.js +++ b/src/components/Relations/Relations.js @@ -1,6 +1,6 @@ import React, { Fragment } from "react"; import { Popover, Select, Divider, List, Button, Dropdown, Menu } from "antd"; -import { isValidReference } from "mobx-state-tree"; +import { isValidReference, getRoot } from "mobx-state-tree"; import { observer } from "mobx-react"; import { ArrowLeftOutlined, ArrowRightOutlined, SwapOutlined, MoreOutlined, DeleteOutlined } from "@ant-design/icons"; @@ -70,8 +70,12 @@ const Relation = observer(({ store, rl }) => { }); const ListItem = observer(({ item }) => { + const node = getRoot(item).completionStore.selected.highlightedNode; + const isSelected = node === item.node1 || node === item.node2; + return ( { @@ -81,7 +85,7 @@ const ListItem = observer(({ item }) => { item.toggleHighlight(); }} > -
+
diff --git a/src/components/Relations/Relations.module.scss b/src/components/Relations/Relations.module.scss index 571c98b76..f3fc49d5a 100644 --- a/src/components/Relations/Relations.module.scss +++ b/src/components/Relations/Relations.module.scss @@ -3,6 +3,15 @@ overflow-y: auto; } +.item { + display: flex; + justify-content: space-between; +} + +.selected { + background: #f1f1f1; +} + .block { display: flex; align-items: center;