diff --git a/packages/frontend/src/components/Chain.tsx b/packages/frontend/src/components/Chain.tsx index ed6bc2c..a2d2c84 100644 --- a/packages/frontend/src/components/Chain.tsx +++ b/packages/frontend/src/components/Chain.tsx @@ -115,7 +115,12 @@ export class Chain extends React.Component {
{ this.nodes().map((node) => { - const location = node.location || [0, 0, ''] as Types.NodeLocation; + const location = node.location; + + if (!location || location[0] == null || location[1] == null) { + // Skip nodes with unknown location + return null; + } const { left, top } = this.pixelPosition(location[0], location[1]); diff --git a/packages/frontend/src/components/Node/Location.css b/packages/frontend/src/components/Node/Location.css index 8eff339..a489cc6 100644 --- a/packages/frontend/src/components/Node/Location.css +++ b/packages/frontend/src/components/Node/Location.css @@ -15,6 +15,16 @@ transition: border-color 0.25s linear; } +.Node-Location-ping { + position: absolute; + left: 2px; + top: 2px; + width: 0; + height: 0; + border: 1px solid transparent; + display: none; +} + .Node-Location-odd { border-color: #bbb; } @@ -24,6 +34,13 @@ border-color: #d64ca8; } +.Node-Location-synced .Node-Location-ping { + border: 1px solid #fff; + border-radius: 30px; + display: block; + animation: ping 1s forwards; +} + .Node-Location:hover { z-index: 3; border-color: #fff; @@ -55,3 +72,21 @@ .Node-Location-details td:nth-child(even) { padding-left: 0.2em; } + +@keyframes ping { + from { + left: 2px; + right: 2px; + width: 0; + height: 0; + border-color: rgba(255,255,255,1); + } + + to { + left: -13px; + top: -13px; + width: 30px; + height: 30px; + border-color: rgba(255,255,255,0); + } +} diff --git a/packages/frontend/src/components/Node/Location.tsx b/packages/frontend/src/components/Node/Location.tsx index a3059b5..7327a3e 100644 --- a/packages/frontend/src/components/Node/Location.tsx +++ b/packages/frontend/src/components/Node/Location.tsx @@ -51,6 +51,7 @@ class Location extends React.Component
); }