From 9df0e602d3df7535874170722f6b3ff2602d94b7 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 22 Nov 2022 10:05:14 +0900 Subject: [PATCH] longer input/output connectors on flow diagram & new nav logic --- .../tx-bowtie-graph-tooltip.component.html | 17 +++++- .../tx-bowtie-graph-tooltip.component.ts | 4 ++ .../tx-bowtie-graph.component.html | 21 +++++-- .../tx-bowtie-graph.component.scss | 11 +++- .../tx-bowtie-graph.component.ts | 57 ++++++++++++------- 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.html b/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.html index cbf2f7d5a..6262c56a7 100644 --- a/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.html +++ b/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.html @@ -22,13 +22,13 @@ -

Peg In

+

Peg In

-

Peg Out

+

Peg Out

{{ line.pegout.slice(0, -4) }} @@ -38,7 +38,7 @@ -

+

Input Output @@ -46,6 +46,17 @@ #{{ line.index + 1 }}

+ +

+ Transaction  + {{ line.txid.slice(0, 8) }}... + {{ line.txid.slice(-4) }} +

+ +

Output  #{{ line.vout + 1 }}

+

Input  #{{ line.vin + 1 }}

+
+

Confidential

diff --git a/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.ts b/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.ts index 4e450a7dc..54c58ffab 100644 --- a/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.ts +++ b/frontend/src/app/components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component.ts @@ -5,6 +5,9 @@ interface Xput { type: 'input' | 'output' | 'fee'; value?: number; index?: number; + txid?: string; + vin?: number; + vout?: number; address?: string; rest?: number; coinbase?: boolean; @@ -21,6 +24,7 @@ interface Xput { export class TxBowtieGraphTooltipComponent implements OnChanges { @Input() line: Xput | void; @Input() cursorPosition: { x: number, y: number }; + @Input() isConnector: boolean = false; tooltipPosition = { x: 0, y: 0 }; diff --git a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.html b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.html index c736e5548..23346f405 100644 --- a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.html +++ b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.html @@ -49,6 +49,14 @@ + + + + + + + + @@ -77,9 +85,9 @@ [attr.d]="input.connectorPath" class="input connector {{input.class}}" [class.highlight]="inputData[i].index === inputIndex" - (pointerover)="onHover($event, 'input', i);" - (pointerout)="onBlur($event, 'input', i);" - (click)="onClick($event, 'input', inputData[i].index);" + (pointerover)="onHover($event, 'input-connector', i);" + (pointerout)="onBlur($event, 'input-connector', i);" + (click)="onClick($event, 'input-connector', inputData[i].index);" /> diff --git a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.scss b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.scss index 71bf5e97b..7c9ecf0ce 100644 --- a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.scss +++ b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.scss @@ -24,7 +24,7 @@ } } - .line:hover, .connector:hover + .marker-target + .line, .marker-target:hover + .line { + .line:hover, .marker-target:hover + .line { z-index: 10; cursor: pointer; &.input { @@ -50,6 +50,15 @@ } } + .connector:hover { + &.input { + fill: url(#input-hover-connector-gradient); + } + &.output { + fill: url(#output-hover-connector-gradient); + } + } + .marker-target { stroke: none; fill: transparent; diff --git a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.ts b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.ts index f6deb496c..39164314a 100644 --- a/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.ts +++ b/frontend/src/app/components/tx-bowtie-graph/tx-bowtie-graph.component.ts @@ -19,6 +19,9 @@ interface Xput { type: 'input' | 'output' | 'fee'; value?: number; index?: number; + txid?: string; + vin?: number; + vout?: number; address?: string; rest?: number; coinbase?: boolean; @@ -52,9 +55,12 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { outputs: SvgLine[]; middle: SvgLine; midWidth: number; + txWidth: number; + connectorWidth: number; combinedWeight: number; isLiquid: boolean = false; hoverLine: Xput | void = null; + hoverConnector: boolean = false; tooltipPosition = { x: 0, y: 0 }; outspends: Outspend[] = []; @@ -62,16 +68,16 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { refreshOutspends$: ReplaySubject = new ReplaySubject(); gradientColors = { - '': ['#9339f4', '#105fb0', '#9339f433'], - bisq: ['#9339f4', '#105fb0', '#9339f433'], + '': ['#9339f4', '#105fb0', '#9339f400'], + bisq: ['#9339f4', '#105fb0', '#9339f400'], // liquid: ['#116761', '#183550'], - liquid: ['#09a197', '#0f62af', '#09a19733'], + liquid: ['#09a197', '#0f62af', '#09a19700'], // 'liquidtestnet': ['#494a4a', '#272e46'], - 'liquidtestnet': ['#d2d2d2', '#979797', '#d2d2d233'], + 'liquidtestnet': ['#d2d2d2', '#979797', '#d2d2d200'], // testnet: ['#1d486f', '#183550'], - testnet: ['#4edf77', '#10a0af', '#4edf7733'], + testnet: ['#4edf77', '#10a0af', '#4edf7700'], // signet: ['#6f1d5d', '#471850'], - signet: ['#d24fc8', '#a84fd2', '#d24fc833'], + signet: ['#d24fc8', '#a84fd2', '#d24fc800'], }; gradient: string[] = ['#105fb0', '#105fb0']; @@ -121,7 +127,9 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { this.isLiquid = (this.network === 'liquid' || this.network === 'liquidtestnet'); this.gradient = this.gradientColors[this.network]; this.midWidth = Math.min(10, Math.ceil(this.width / 100)); - this.combinedWeight = Math.min(this.maxCombinedWeight, Math.floor((this.width - (2 * this.midWidth)) / 6)); + this.txWidth = this.connectors ? Math.max(this.width - 200, this.width * 0.8) : this.width - 20; + this.combinedWeight = Math.min(this.maxCombinedWeight, Math.floor((this.txWidth - (2 * this.midWidth)) / 6)); + this.connectorWidth = (this.width - this.txWidth) / 2; const totalValue = this.calcTotalValue(this.tx); let voutWithFee = this.tx.vout.map((v, i) => { @@ -144,6 +152,8 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { return { type: 'input', value: v?.prevout?.value, + txid: v.txid, + vout: v.vout, address: v?.prevout?.scriptpubkey_address || v?.prevout?.scriptpubkey_type?.toUpperCase(), index: i, coinbase: v?.is_coinbase, @@ -271,7 +281,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { // required to prevent this line overlapping its neighbor if (this.tooltip || !xputs[i].rest) { - const w = (this.width - Math.max(lastWeight, line.weight)) / 2; // approximate horizontal width of the curved section of the line + const w = (this.width - Math.max(lastWeight, line.weight) - (2 * this.connectorWidth)) / 2; // approximate horizontal width of the curved section of the line const y1 = line.outerY; const y2 = line.innerY; const t = (lastWeight + line.weight) / 2; // distance between center of this line and center of previous line @@ -319,7 +329,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { } makePath(side: 'in' | 'out', outer: number, inner: number, weight: number, offset: number, pad: number): string { - const start = (weight * 0.5) + 10; + const start = (weight * 0.5) + this.connectorWidth; const curveStart = Math.max(start + 1, pad - offset); const end = this.width / 2 - (this.midWidth * 0.9) + 1; const curveEnd = end - offset - 10; @@ -339,7 +349,8 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { makeConnectorPath(side: 'in' | 'out', y: number, inner, weight: number): string { const halfWidth = weight * 0.5; - const offset = Math.max(2, halfWidth * 0.2); + const offset = 10; //Math.max(2, halfWidth * 0.2); + const lineEnd = this.connectorWidth; // align with for svg horizontal gradient bug correction if (Math.round(y) === Math.round(inner)) { @@ -347,15 +358,16 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { } if (side === 'in') { - return `M ${10 - offset} ${y - halfWidth} L ${halfWidth + 10 - offset} ${y} L ${10 - offset} ${y + halfWidth} L -10 ${ y + halfWidth} L -10 ${y - halfWidth}`; + return `M ${lineEnd - offset} ${y - halfWidth} L ${halfWidth + lineEnd - offset} ${y} L ${lineEnd - offset} ${y + halfWidth} L -${10} ${ y + halfWidth} L -${10} ${y - halfWidth}`; } else { - return `M ${this.width - halfWidth - 10 + offset} ${y - halfWidth} L ${this.width - 10 + offset} ${y} L ${this.width - halfWidth - 10 + offset} ${y + halfWidth} L ${this.width + 10} ${ y + halfWidth} L ${this.width + 10} ${y - halfWidth}`; + return `M ${this.width - halfWidth - lineEnd + offset} ${y - halfWidth} L ${this.width - lineEnd + offset} ${y} L ${this.width - halfWidth - lineEnd + offset} ${y + halfWidth} L ${this.width + 10} ${ y + halfWidth} L ${this.width + 10} ${y - halfWidth}`; } } makeMarkerPath(side: 'in' | 'out', y: number, inner, weight: number): string { const halfWidth = weight * 0.5; - const offset = Math.max(2, halfWidth * 0.2); + const offset = 10; //Math.max(2, halfWidth * 0.2); + const lineEnd = this.connectorWidth; // align with for svg horizontal gradient bug correction if (Math.round(y) === Math.round(inner)) { @@ -363,9 +375,9 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { } if (side === 'in') { - return `M ${10 - offset} ${y - halfWidth} L ${halfWidth + 10 - offset} ${y} L ${10 - offset} ${y + halfWidth} L ${offset + weight} ${ y + halfWidth} L ${offset + weight} ${y - halfWidth}`; + return `M ${lineEnd - offset} ${y - halfWidth} L ${halfWidth + lineEnd - offset} ${y} L ${lineEnd - offset} ${y + halfWidth} L ${weight + lineEnd} ${ y + halfWidth} L ${weight + lineEnd} ${y - halfWidth}`; } else { - return `M ${this.width - halfWidth - 10 + offset} ${y - halfWidth} L ${this.width - 10 + offset} ${y} L ${this.width - halfWidth - 10 + offset} ${y + halfWidth} L ${this.width - halfWidth - 10} ${ y + halfWidth} L ${this.width - halfWidth - 10} ${y - halfWidth}`; + return `M ${this.width - halfWidth - lineEnd + offset} ${y - halfWidth} L ${this.width - lineEnd + offset} ${y} L ${this.width - halfWidth - lineEnd + offset} ${y + halfWidth} L ${this.width - halfWidth - lineEnd} ${ y + halfWidth} L ${this.width - halfWidth - lineEnd} ${y - halfWidth}`; } } @@ -383,26 +395,31 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { } onHover(event, side, index): void { - if (side === 'input') { + if (side.startsWith('input')) { this.hoverLine = { ...this.inputData[index], index }; + this.hoverConnector = (side === 'input-connector'); + } else { this.hoverLine = { - ...this.outputData[index] + ...this.outputData[index], + ...this.outspends[this.outputData[index].index] }; + this.hoverConnector = (side === 'output-connector'); } } onBlur(event, side, index): void { this.hoverLine = null; + this.hoverConnector = false; } onClick(event, side, index): void { - if (side === 'input') { + if (side.startsWith('input')) { const input = this.tx.vin[index]; - if (input && !input.is_coinbase && !input.is_pegin && input.txid && input.vout != null) { + if (side === 'input-connector' && input && !input.is_coinbase && !input.is_pegin && input.txid && input.vout != null) { this.router.navigate([this.relativeUrlPipe.transform('/tx'), input.txid], { queryParamsHandling: 'merge', fragment: (new URLSearchParams({ @@ -422,7 +439,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges { } else { const output = this.tx.vout[index]; const outspend = this.outspends[index]; - if (output && outspend && outspend.spent && outspend.txid) { + if (side === 'output-connector' && output && outspend && outspend.spent && outspend.txid) { this.router.navigate([this.relativeUrlPipe.transform('/tx'), outspend.txid], { queryParamsHandling: 'merge', fragment: (new URLSearchParams({