Merge branch 'master' into mononaut/fix-mobile-bottom-nav
This commit is contained in:
@@ -138,6 +138,10 @@
|
||||
"translation": "src/locale/messages.hi.xlf",
|
||||
"baseHref": "/hi/"
|
||||
},
|
||||
"ne": {
|
||||
"translation": "src/locale/messages.ne.xlf",
|
||||
"baseHref": "/ne/"
|
||||
},
|
||||
"lt": {
|
||||
"translation": "src/locale/messages.lt.xlf",
|
||||
"baseHref": "/lt/"
|
||||
|
||||
@@ -116,6 +116,7 @@ export const languages: Language[] = [
|
||||
// { code: 'hr', name: 'Hrvatski' }, // Croatian
|
||||
// { code: 'id', name: 'Bahasa Indonesia' },// Indonesian
|
||||
{ code: 'hi', name: 'हिन्दी' }, // Hindi
|
||||
{ code: 'ne', name: 'नेपाली' }, // Nepalese
|
||||
{ code: 'it', name: 'Italiano' }, // Italian
|
||||
{ code: 'he', name: 'עברית' }, // Hebrew
|
||||
{ code: 'ka', name: 'ქართული' }, // Georgian
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<div class="container-xl">
|
||||
<h1 i18n="shared.address">Address</h1>
|
||||
<span class="address-link">
|
||||
<a [routerLink]="['/address/' | relativeUrl, addressString]">
|
||||
<span class="d-inline d-lg-none">{{ addressString | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressString }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="addressString"></app-clipboard>
|
||||
<app-truncate [text]="addressString" [lastChars]="8" [link]="['/address/' | relativeUrl, addressString]">
|
||||
<app-clipboard [text]="addressString"></app-clipboard>
|
||||
</app-truncate>
|
||||
</span>
|
||||
<br>
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<h1 i18n="shared.transaction">Transaction</h1>
|
||||
</div>
|
||||
|
||||
<span class="tx-link float-left">
|
||||
<a [routerLink]="['/tx' | relativeUrl, bisqTx.id]">
|
||||
<span class="d-inline d-lg-none">{{ bisqTx.id | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ bisqTx.id }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="bisqTx.id"></app-clipboard>
|
||||
<span class="tx-link">
|
||||
<span class="txid">
|
||||
<app-truncate [text]="bisqTx.id" [lastChars]="12" [link]="['/tx/' | relativeUrl, bisqTx.id]">
|
||||
<app-clipboard [text]="bisqTx.id"></app-clipboard>
|
||||
</app-truncate>
|
||||
</span>
|
||||
</span>
|
||||
<span class="grow"></span>
|
||||
<div class="container-buttons">
|
||||
|
||||
@@ -6,17 +6,16 @@
|
||||
<div class="col-md">
|
||||
<div class="row d-flex justify-content-between">
|
||||
<div class="title-wrapper">
|
||||
<h1 class="title truncated"><span class="first">{{addressString.slice(0,-4)}}</span><span class="last-four">{{addressString.slice(-4)}}</span></h1>
|
||||
<h1 class="title"><app-truncate [text]="addressString"></app-truncate></h1>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr *ngIf="addressInfo && addressInfo.unconfidential">
|
||||
<td i18n="address.unconfidential">Unconfidential</td>
|
||||
<td><a [routerLink]="['/address/' | relativeUrl, addressInfo.unconfidential]">
|
||||
<span class="d-inline d-lg-none">{{ addressInfo.unconfidential | shortenString : 14 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressInfo.unconfidential }}</span>
|
||||
</a> <app-clipboard [text]="addressInfo.unconfidential"></app-clipboard></td>
|
||||
<td>
|
||||
<app-truncate [text]="addressInfo.unconfidential" [lastChars]="7" [link]="['/address/' | relativeUrl, addressInfo.unconfidential]"></app-truncate>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template [ngIf]="!address.electrum">
|
||||
<tr>
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
<div class="title-address">
|
||||
<h1 i18n="shared.address">Address</h1>
|
||||
<div class="tx-link">
|
||||
<a [routerLink]="['/address/' | relativeUrl, addressString]" >
|
||||
<span class="d-inline d-lg-none">{{ addressString | shortenString : 18 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressString }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="addressString"></app-clipboard>
|
||||
<app-truncate [text]="addressString" [lastChars]="8" [link]="['/address/' | relativeUrl, addressString]">
|
||||
<app-clipboard [text]="addressString"></app-clipboard>
|
||||
</app-truncate>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,10 +19,11 @@
|
||||
<tbody>
|
||||
<tr *ngIf="addressInfo && addressInfo.unconfidential">
|
||||
<td i18n="address.unconfidential">Unconfidential</td>
|
||||
<td><a [routerLink]="['/address/' | relativeUrl, addressInfo.unconfidential]">
|
||||
<span class="d-inline d-lg-none">{{ addressInfo.unconfidential | shortenString : 14 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressInfo.unconfidential }}</span>
|
||||
</a> <app-clipboard [text]="addressInfo.unconfidential"></app-clipboard></td>
|
||||
<td>
|
||||
<app-truncate [text]="addressInfo.unconfidential" [lastChars]="8" [link]="['/address/' | relativeUrl, addressInfo.unconfidential]">
|
||||
<app-clipboard [text]="addressInfo.unconfidential"></app-clipboard>
|
||||
</app-truncate>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template [ngIf]="!address.electrum">
|
||||
<tr>
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
<div class="title-asset">
|
||||
<h1 i18n="asset|Liquid Asset page title">Asset</h1>
|
||||
<div class="tx-link">
|
||||
<a [routerLink]="['/assets/asset/' | relativeUrl, assetString]">
|
||||
<span class="d-inline d-lg-none">{{ assetString | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ assetString }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="assetString"></app-clipboard>
|
||||
<app-truncate [text]="assetString" [lastChars]="8" [link]="['/assets/asset/' | relativeUrl, assetString]">
|
||||
<app-clipboard [text]="assetString"></app-clipboard>
|
||||
</app-truncate>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -213,6 +213,7 @@ export class BlockFeeRatesGraphComponent implements OnInit {
|
||||
},
|
||||
},
|
||||
legend: (data.series.length === 0) ? undefined : {
|
||||
padding: [10, 75],
|
||||
data: data.legends,
|
||||
selected: JSON.parse(this.storageService.getValue('fee_rates_legend')) ?? {
|
||||
'Min': true,
|
||||
|
||||
@@ -10,12 +10,13 @@ const defaultHoverColor = hexToColor('1bd8f4');
|
||||
|
||||
const feeColors = mempoolFeeColors.map(hexToColor);
|
||||
const auditFeeColors = feeColors.map((color) => darken(desaturate(color, 0.3), 0.9));
|
||||
const marginalFeeColors = feeColors.map((color) => darken(desaturate(color, 0.8), 1.1));
|
||||
const auditColors = {
|
||||
censored: hexToColor('f344df'),
|
||||
missing: darken(desaturate(hexToColor('f344df'), 0.3), 0.7),
|
||||
added: hexToColor('0099ff'),
|
||||
selected: darken(desaturate(hexToColor('0099ff'), 0.3), 0.7),
|
||||
}
|
||||
};
|
||||
|
||||
// convert from this class's update format to TxSprite's update format
|
||||
function toSpriteUpdate(params: ViewUpdateParams): SpriteUpdateParams {
|
||||
@@ -161,13 +162,13 @@ export default class TxView implements TransactionStripped {
|
||||
case 'censored':
|
||||
return auditColors.censored;
|
||||
case 'missing':
|
||||
return auditColors.missing;
|
||||
return marginalFeeColors[feeLevelIndex] || marginalFeeColors[mempoolFeeColors.length - 1];
|
||||
case 'fresh':
|
||||
return auditColors.missing;
|
||||
case 'added':
|
||||
return auditColors.added;
|
||||
case 'selected':
|
||||
return auditColors.selected;
|
||||
return marginalFeeColors[feeLevelIndex] || marginalFeeColors[mempoolFeeColors.length - 1];
|
||||
case 'found':
|
||||
if (this.context === 'projected') {
|
||||
return auditFeeColors[feeLevelIndex] || auditFeeColors[mempoolFeeColors.length - 1];
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
<tr *ngIf="tx && tx.status && tx.status.length">
|
||||
<td class="td-width" i18n="transaction.audit-status">Audit status</td>
|
||||
<ng-container [ngSwitch]="tx?.status">
|
||||
<td *ngSwitchCase="'found'" i18n="transaction.audit.match">match</td>
|
||||
<td *ngSwitchCase="'censored'" i18n="transaction.audit.removed">removed</td>
|
||||
<td *ngSwitchCase="'missing'" i18n="transaction.audit.marginal">marginal fee rate</td>
|
||||
<td *ngSwitchCase="'fresh'" i18n="transaction.audit.recently-broadcast">recently broadcast</td>
|
||||
<td *ngSwitchCase="'added'" i18n="transaction.audit.added">added</td>
|
||||
<td *ngSwitchCase="'selected'" i18n="transaction.audit.marginal">marginal fee rate</td>
|
||||
<td *ngSwitchCase="'found'" i18n="transaction.audit.match">Match</td>
|
||||
<td *ngSwitchCase="'censored'" i18n="transaction.audit.removed">Removed</td>
|
||||
<td *ngSwitchCase="'missing'" i18n="transaction.audit.marginal">Marginal fee rate</td>
|
||||
<td *ngSwitchCase="'fresh'" i18n="transaction.audit.recently-broadcasted">Recently broadcasted</td>
|
||||
<td *ngSwitchCase="'added'" i18n="transaction.audit.added">Added</td>
|
||||
<td *ngSwitchCase="'selected'" i18n="transaction.audit.marginal">Marginal fee rate</td>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -4,8 +4,7 @@ import { StateService } from '../../services/state.service';
|
||||
import { specialBlocks } from '../../app.constants';
|
||||
import { BlockExtended } from '../../interfaces/node-api.interface';
|
||||
import { Location } from '@angular/common';
|
||||
import { config } from 'process';
|
||||
import { CacheService } from 'src/app/services/cache.service';
|
||||
import { CacheService } from '../../services/cache.service';
|
||||
|
||||
interface BlockchainBlock extends BlockExtended {
|
||||
placeholder?: boolean;
|
||||
|
||||
@@ -64,26 +64,6 @@
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
|
||||
&.truncated {
|
||||
text-overflow: unset;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
|
||||
.first {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: -2px;
|
||||
}
|
||||
|
||||
.last-four {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .title-wrapper {
|
||||
|
||||
@@ -13,21 +13,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.rewards-per-tx" i18n-ngbTooltip="mining.rewards-per-tx"
|
||||
ngbTooltip="Reward Per Tx" placement="bottom" #rewardspertx [disableTooltip]="!isEllipsisActive(rewardspertx)">Reward Per Tx</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-per-tx-desc" ngbTooltip="Average miners' reward per transaction in the past 144 blocks" placement="bottom">
|
||||
<h5 class="card-title" i18n="mining.fees-per-block" i18n-ngbTooltip="mining.fees-per-block"
|
||||
ngbTooltip="Avg Block Fees" placement="bottom" #rewardsperblock [disableTooltip]="!isEllipsisActive(rewardsperblock)">Avg Block Fees</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.fees-per-block-desc" ngbTooltip="Average fees per block in the past 144 blocks" placement="bottom">
|
||||
<div class="fee-text">
|
||||
{{ rewardStats.rewardPerTx | amountShortener: 2 }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">sats/tx</span>
|
||||
{{ (rewardStats.feePerBlock / 100000000) | amountShortener: 4 }}
|
||||
<span i18n="shared.btc-block|BTC/block">BTC/block</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-fiat [value]="rewardStats.rewardPerTx"></app-fiat>
|
||||
<app-fiat [value]="rewardStats.feePerBlock"></app-fiat>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.average-fee" i18n-ngbTooltip="mining.average-fee"
|
||||
ngbTooltip="Average Fee" placement="bottom" #averagefee [disableTooltip]="!isEllipsisActive(averagefee)">Average Fee</h5>
|
||||
ngbTooltip="Avg Tx Fee" placement="bottom" #averagefee [disableTooltip]="!isEllipsisActive(averagefee)">Avg Tx Fee</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.average-fee" ngbTooltip="Fee paid on average for each transaction in the past 144 blocks" placement="bottom">
|
||||
<div class="fee-text">{{ rewardStats.feePerTx | amountShortener: 2 }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">sats/tx</span>
|
||||
|
||||
@@ -42,8 +42,8 @@ export class RewardStatsComponent implements OnInit {
|
||||
map((stats) => {
|
||||
return {
|
||||
totalReward: stats.totalReward,
|
||||
rewardPerTx: stats.totalReward / stats.totalTx,
|
||||
feePerTx: stats.totalFee / stats.totalTx,
|
||||
feePerBlock: stats.totalFee / 144,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</app-preview-title>
|
||||
<div class="row d-flex justify-content-between full-width-row">
|
||||
<div class="title-wrapper">
|
||||
<h1 class="title truncated"><span class="first">{{txId.slice(0,-4)}}</span><span class="last-four">{{txId.slice(-4)}}</span></h1>
|
||||
<h1 class="title truncated"><app-truncate [text]="txId"></app-truncate></h1>
|
||||
</div>
|
||||
<div *ngIf="network !== 'liquid' && network !== 'liquidtestnet'" class="features">
|
||||
<app-tx-features [tx]="tx"></app-tx-features>
|
||||
|
||||
@@ -3,21 +3,25 @@
|
||||
<div class="title-block">
|
||||
<div *ngIf="rbfTransaction" class="alert alert-mempool" role="alert">
|
||||
<span i18n="transaction.rbf.replacement|RBF replacement">This transaction has been replaced by:</span>
|
||||
<a class="alert-link" [routerLink]="['/tx/' | relativeUrl, rbfTransaction.txid]">
|
||||
<span class="d-inline d-lg-none">{{ rbfTransaction.txid | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ rbfTransaction.txid }}</span>
|
||||
</a>
|
||||
<app-truncate [text]="rbfTransaction.txid" [lastChars]="12" [link]="['/tx/' | relativeUrl, rbfTransaction.txid]"></app-truncate>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!rbfTransaction || rbfTransaction?.size">
|
||||
<div *ngIf="rbfReplaces?.length" class="alert alert-mempool" role="alert">
|
||||
<span i18n="transaction.rbf.replaced|RBF replaced">This transaction replaced:</span>
|
||||
<div class="tx-list">
|
||||
<app-truncate [text]="replaced" [lastChars]="12" *ngFor="let replaced of rbfReplaces" [link]="['/tx/' | relativeUrl, replaced]"></app-truncate>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!rbfTransaction || rbfTransaction?.size || tx">
|
||||
<h1 i18n="shared.transaction">Transaction</h1>
|
||||
|
||||
<span class="tx-link float-left">
|
||||
<a [routerLink]="['/tx/' | relativeUrl, txId]">
|
||||
<span class="d-inline d-lg-none">{{ txId | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ txId }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="txId"></app-clipboard>
|
||||
<span class="tx-link">
|
||||
<span class="txid">
|
||||
<app-truncate [text]="txId" [lastChars]="12" [link]="['/tx/' | relativeUrl, txId]">
|
||||
<app-clipboard [text]="txId"></app-clipboard>
|
||||
</app-truncate>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="container-buttons">
|
||||
@@ -28,7 +32,10 @@
|
||||
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||
</button>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="tx && !tx?.status.confirmed">
|
||||
<ng-template [ngIf]="tx && !tx?.status?.confirmed && replaced">
|
||||
<button type="button" class="btn btn-sm btn-danger" i18n="transaction.unconfirmed|Transaction unconfirmed state">Replaced</button>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="tx && !tx?.status?.confirmed && !replaced">
|
||||
<button type="button" class="btn btn-sm btn-danger" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
|
||||
</ng-template>
|
||||
</div>
|
||||
@@ -91,7 +98,7 @@
|
||||
<div class="col-sm">
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<ng-template [ngIf]="transactionTime !== 0">
|
||||
<ng-template [ngIf]="transactionTime !== 0 && !replaced">
|
||||
<tr *ngIf="transactionTime === -1; else firstSeenTmpl">
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
@@ -103,7 +110,7 @@
|
||||
</tr>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<tr>
|
||||
<tr *ngIf="!replaced">
|
||||
<td class="td-width" i18n="transaction.eta|Transaction ETA">ETA</td>
|
||||
<td>
|
||||
<ng-template [ngIf]="txInBlockIndex === undefined" [ngIfElse]="estimationTmpl">
|
||||
@@ -144,12 +151,12 @@
|
||||
<br>
|
||||
|
||||
<h2 class="text-left">CPFP <fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" size="xs"></fa-icon></h2>
|
||||
<div class="box">
|
||||
<table class="table table-borderless table-striped">
|
||||
<div class="box cpfp-details">
|
||||
<table class="table table-fixed table-borderless table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="transactions-list.vout.scriptpubkey-type">Type</th>
|
||||
<th i18n="dashboard.latest-transactions.txid">TXID</th>
|
||||
<th class="txids" i18n="dashboard.latest-transactions.txid">TXID</th>
|
||||
<th class="d-none d-lg-table-cell" i18n="transaction.vsize|Transaction Virtual Size">Virtual size</th>
|
||||
<th i18n="transaction.fee-rate|Transaction fee rate">Fee rate</th>
|
||||
<th class="d-none d-lg-table-cell"></th>
|
||||
@@ -159,10 +166,8 @@
|
||||
<ng-template [ngIf]="cpfpInfo?.descendants?.length">
|
||||
<tr *ngFor="let cpfpTx of cpfpInfo.descendants">
|
||||
<td><span class="badge badge-primary" i18n="transaction.descendant|Descendant">Descendant</span></td>
|
||||
<td><a [routerLink]="['/tx' | relativeUrl, cpfpTx.txid]">
|
||||
<span class="d-inline d-lg-none">{{ cpfpTx.txid | shortenString : 8 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ cpfpTx.txid }}</span>
|
||||
</a>
|
||||
<td>
|
||||
<app-truncate [text]="cpfpTx.txid" [link]="['/tx' | relativeUrl, cpfpTx.txid]"></app-truncate>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell" [innerHTML]="cpfpTx.weight / 4 | vbytes: 2"></td>
|
||||
<td>{{ cpfpTx.fee / (cpfpTx.weight / 4) | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
@@ -172,11 +177,8 @@
|
||||
<ng-template [ngIf]="cpfpInfo?.bestDescendant">
|
||||
<tr>
|
||||
<td><span class="badge badge-success" i18n="transaction.descendant|Descendant">Descendant</span></td>
|
||||
<td>
|
||||
<a [routerLink]="['/tx' | relativeUrl, cpfpInfo.bestDescendant.txid]">
|
||||
<span class="d-inline d-lg-none">{{ cpfpInfo.bestDescendant.txid | shortenString : 8 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ cpfpInfo.bestDescendant.txid }}</span>
|
||||
</a>
|
||||
<td class="txids">
|
||||
<app-truncate [text]="cpfpInfo.bestDescendant.txid" [link]="['/tx' | relativeUrl, cpfpInfo.bestDescendant.txid]"></app-truncate>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell" [innerHTML]="cpfpInfo.bestDescendant.weight / 4 | vbytes: 2"></td>
|
||||
<td>{{ cpfpInfo.bestDescendant.fee / (cpfpInfo.bestDescendant.weight / 4) | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
@@ -186,10 +188,8 @@
|
||||
<ng-template [ngIf]="cpfpInfo?.ancestors?.length">
|
||||
<tr *ngFor="let cpfpTx of cpfpInfo.ancestors">
|
||||
<td><span class="badge badge-primary" i18n="transaction.ancestor|Transaction Ancestor">Ancestor</span></td>
|
||||
<td><a [routerLink]="['/tx' | relativeUrl, cpfpTx.txid]">
|
||||
<span class="d-inline d-lg-none">{{ cpfpTx.txid | shortenString : 8 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ cpfpTx.txid }}</span>
|
||||
</a>
|
||||
<td class="txids">
|
||||
<app-truncate [text]="cpfpTx.txid" [link]="['/tx' | relativeUrl, cpfpTx.txid]"></app-truncate>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell" [innerHTML]="cpfpTx.weight / 4 | vbytes: 2"></td>
|
||||
<td>{{ cpfpTx.fee / (cpfpTx.weight / 4) | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
|
||||
@@ -19,22 +19,32 @@
|
||||
}
|
||||
}
|
||||
.tx-link {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: baseline;
|
||||
width: 0;
|
||||
max-width: 100%;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 8px;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
@media (min-width: 651px) {
|
||||
display: flex;
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 0px;
|
||||
margin-right: 1em;
|
||||
top: 1px;
|
||||
position: relative;
|
||||
}
|
||||
@media (max-width: 650px) {
|
||||
width: 100%;
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.txid {
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.td-width {
|
||||
@@ -188,4 +198,16 @@
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cpfp-details {
|
||||
.txids {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.tx-list {
|
||||
.alert-link {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -40,15 +40,21 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
transactionTime = -1;
|
||||
subscription: Subscription;
|
||||
fetchCpfpSubscription: Subscription;
|
||||
fetchRbfSubscription: Subscription;
|
||||
fetchCachedTxSubscription: Subscription;
|
||||
txReplacedSubscription: Subscription;
|
||||
blocksSubscription: Subscription;
|
||||
queryParamsSubscription: Subscription;
|
||||
urlFragmentSubscription: Subscription;
|
||||
fragmentParams: URLSearchParams;
|
||||
rbfTransaction: undefined | Transaction;
|
||||
replaced: boolean = false;
|
||||
rbfReplaces: string[];
|
||||
cpfpInfo: CpfpInfo | null;
|
||||
showCpfpDetails = false;
|
||||
fetchCpfp$ = new Subject<string>();
|
||||
fetchRbfHistory$ = new Subject<string>();
|
||||
fetchCachedTx$ = new Subject<string>();
|
||||
now = new Date().getTime();
|
||||
timeAvg$: Observable<number>;
|
||||
liquidUnblinding = new LiquidUnblinding();
|
||||
@@ -122,7 +128,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
}),
|
||||
delay(2000)
|
||||
)))
|
||||
)),
|
||||
catchError(() => {
|
||||
return of(null);
|
||||
})
|
||||
)
|
||||
),
|
||||
catchError(() => {
|
||||
return of(null);
|
||||
@@ -155,6 +165,49 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
this.cpfpInfo = cpfpInfo;
|
||||
});
|
||||
|
||||
this.fetchRbfSubscription = this.fetchRbfHistory$
|
||||
.pipe(
|
||||
switchMap((txId) =>
|
||||
this.apiService
|
||||
.getRbfHistory$(txId)
|
||||
),
|
||||
catchError(() => {
|
||||
return of([]);
|
||||
})
|
||||
).subscribe((replaces) => {
|
||||
this.rbfReplaces = replaces;
|
||||
});
|
||||
|
||||
this.fetchCachedTxSubscription = this.fetchCachedTx$
|
||||
.pipe(
|
||||
switchMap((txId) =>
|
||||
this.apiService
|
||||
.getRbfCachedTx$(txId)
|
||||
),
|
||||
catchError(() => {
|
||||
return of(null);
|
||||
})
|
||||
).subscribe((tx) => {
|
||||
if (!tx) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tx = tx;
|
||||
if (tx.fee === undefined) {
|
||||
this.tx.fee = 0;
|
||||
}
|
||||
this.tx.feePerVsize = tx.fee / (tx.weight / 4);
|
||||
this.isLoadingTx = false;
|
||||
this.error = undefined;
|
||||
this.waitingForTransaction = false;
|
||||
this.graphExpanded = false;
|
||||
this.setupGraph();
|
||||
|
||||
if (!this.tx?.status?.confirmed) {
|
||||
this.fetchRbfHistory$.next(this.tx.txid);
|
||||
}
|
||||
});
|
||||
|
||||
this.subscription = this.route.paramMap
|
||||
.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
@@ -268,6 +321,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
} else {
|
||||
this.fetchCpfp$.next(this.tx.txid);
|
||||
}
|
||||
this.fetchRbfHistory$.next(this.tx.txid);
|
||||
}
|
||||
setTimeout(() => { this.applyFragment(); }, 0);
|
||||
},
|
||||
@@ -299,6 +353,10 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
this.rbfTransaction = rbfTransaction;
|
||||
this.cacheService.setTxCache([this.rbfTransaction]);
|
||||
this.replaced = true;
|
||||
if (rbfTransaction && !this.tx) {
|
||||
this.fetchCachedTx$.next(this.txId);
|
||||
}
|
||||
});
|
||||
|
||||
this.queryParamsSubscription = this.route.queryParams.subscribe((params) => {
|
||||
@@ -364,8 +422,10 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
this.waitingForTransaction = false;
|
||||
this.isLoadingTx = true;
|
||||
this.rbfTransaction = undefined;
|
||||
this.replaced = false;
|
||||
this.transactionTime = -1;
|
||||
this.cpfpInfo = null;
|
||||
this.rbfReplaces = [];
|
||||
this.showCpfpDetails = false;
|
||||
document.body.scrollTo(0, 0);
|
||||
this.leaveTransaction();
|
||||
@@ -431,6 +491,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
this.fetchCpfpSubscription.unsubscribe();
|
||||
this.fetchRbfSubscription.unsubscribe();
|
||||
this.fetchCachedTxSubscription.unsubscribe();
|
||||
this.txReplacedSubscription.unsubscribe();
|
||||
this.blocksSubscription.unsubscribe();
|
||||
this.queryParamsSubscription.unsubscribe();
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
<ng-container *ngFor="let tx of transactions; let i = index; trackBy: trackByFn">
|
||||
<div *ngIf="!transactionPage" class="header-bg box tx-page-container">
|
||||
<a class="float-left" [routerLink]="['/tx/' | relativeUrl, tx.txid]">
|
||||
<span style="float: left;" class="d-block d-md-none">{{ tx.txid | shortenString : 16 }}</span>
|
||||
<span style="float: left;" class="d-none d-md-block">{{ tx.txid }}</span>
|
||||
<a class="tx-link" [routerLink]="['/tx/' | relativeUrl, tx.txid]">
|
||||
<app-truncate [text]="tx.txid"></app-truncate>
|
||||
</a>
|
||||
<div class="float-right">
|
||||
<div>
|
||||
<ng-template [ngIf]="tx.status.confirmed">‎{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-template>
|
||||
<ng-template [ngIf]="!tx.status.confirmed && tx.firstSeen">
|
||||
<i><app-time-since [time]="tx.firstSeen" [fastRender]="true"></app-time-since></i>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="header-bg box" infiniteScroll [alwaysCallback]="true" [infiniteScrollDistance]="2" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="onScroll()" [attr.data-cy]="'tx-' + i">
|
||||
@@ -18,7 +16,7 @@
|
||||
<div *ngIf="errorUnblinded" class="error-unblinded">{{ errorUnblinded }}</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table table-borderless smaller-text table-sm table-tx-vin">
|
||||
<table class="table table-fixed table-borderless smaller-text table-sm table-tx-vin">
|
||||
<tbody>
|
||||
<ng-template ngFor let-vin let-vindex="index" [ngForOf]="tx.vin.slice(0, getVinLimit(tx))" [ngForTrackBy]="trackByIndexFn">
|
||||
<tr [ngClass]="{
|
||||
@@ -49,7 +47,7 @@
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</td>
|
||||
<td>
|
||||
<td class="address-cell">
|
||||
<div [ngSwitch]="true">
|
||||
<ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid' && network !== 'liquidtestnet'"> <span i18n="transactions-list.newly-generated-coins">(Newly Generated Coins)</span></ng-template><br /><a placement="bottom" [ngbTooltip]="vin.scriptsig | hex2ascii"><span class="badge badge-secondary scriptmessage longer">{{ vin.scriptsig | hex2ascii }}</span></a></ng-container>
|
||||
<ng-container *ngSwitchCase="vin.is_pegin">
|
||||
@@ -66,12 +64,8 @@
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<ng-template #defaultAddress>
|
||||
<a class="shortable-address" *ngIf="vin.prevout.scriptpubkey_address; else vinScriptPubkeyType" [routerLink]="['/address/' | relativeUrl, vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vin.prevout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-inline-flex justify-content-start">
|
||||
<span class="addr-left flex-grow-1" [style]="vin.prevout.scriptpubkey_address.length > 40 ? 'max-width: 235px' : ''">{{ vin.prevout.scriptpubkey_address }}</span>
|
||||
<span *ngIf="vin.prevout.scriptpubkey_address.length > 40" class="addr-right">{{ vin.prevout.scriptpubkey_address | capAddress: 40: 10 }}</span>
|
||||
</span>
|
||||
<a class="address" *ngIf="vin.prevout.scriptpubkey_address; else vinScriptPubkeyType" [routerLink]="['/address/' | relativeUrl, vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
|
||||
<app-truncate [text]="vin.prevout.scriptpubkey_address" [lastChars]="8"></app-truncate>
|
||||
</a>
|
||||
<ng-template #vinScriptPubkeyType>
|
||||
{{ vin.prevout.scriptpubkey_type?.toUpperCase() }}
|
||||
@@ -100,7 +94,7 @@
|
||||
</tr>
|
||||
<tr *ngIf="(showDetails$ | async) === true">
|
||||
<td colspan="3" class="details-container" >
|
||||
<table class="table table-striped table-borderless details-table mb-3">
|
||||
<table class="table table-striped table-fixed table-borderless details-table mb-3">
|
||||
<tbody>
|
||||
<ng-template [ngIf]="vin.scriptsig">
|
||||
<tr>
|
||||
@@ -112,9 +106,23 @@
|
||||
<td style="text-align: left;">{{ vin.scriptsig }}</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<tr *ngIf="vin.witness">
|
||||
<tr *ngIf="vin.witness" class="vin-witness">
|
||||
<td i18n="transactions-list.witness">Witness</td>
|
||||
<td style="text-align: left;">{{ vin.witness.join(' ') }}</td>
|
||||
<td style="text-align: left;">
|
||||
<ng-container *ngFor="let witness of vin.witness; index as i">
|
||||
<input type="checkbox" [id]="'tx' + vindex + 'witness' + i" style="display: none;">
|
||||
<p class="witness-item" [class.accordioned]="witness.length > 1000">
|
||||
{{ witness }}
|
||||
</p>
|
||||
<div class="witness-toggle" *ngIf="witness.length > 1000">
|
||||
<span class="ellipsis">...</span>
|
||||
<label [for]="'tx' + vindex + 'witness' + i" class="btn btn-sm btn-primary mt-2">
|
||||
<span class="show-all" i18n="show-all">Show all</span>
|
||||
<span class="show-less" i18n="show-less">Show less</span>
|
||||
</label>
|
||||
</div>
|
||||
</ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngIf="vin.inner_redeemscript_asm">
|
||||
<td i18n="transactions-list.p2sh-redeem-script">P2SH redeem script</td>
|
||||
@@ -153,7 +161,7 @@
|
||||
<ng-template #showMoreInputsLabel>
|
||||
<span i18n="show-more">Show more</span>
|
||||
</ng-template>
|
||||
({{ tx.vin.length - getVinLimit(tx) }} <span i18n="inputs-remaining">remaining</span>)
|
||||
(<ng-container *ngTemplateOutlet="xRemaining; context: {$implicit: tx.vin.length - getVinLimit(tx)}"></ng-container>)
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -162,20 +170,16 @@
|
||||
</div>
|
||||
<div class="w-100 d-block d-md-none"></div>
|
||||
<div class="col mobile-bottomcol">
|
||||
<table class="table table-borderless smaller-text table-sm table-tx-vout">
|
||||
<table class="table table-fixed table-borderless smaller-text table-sm table-tx-vout">
|
||||
<tbody>
|
||||
<ng-template ngFor let-vout let-vindex="index" [ngForOf]="tx.vout.slice(0, getVoutLimit(tx))" [ngForTrackBy]="trackByIndexFn">
|
||||
<tr [ngClass]="{
|
||||
'assetBox': assetsMinimal && assetsMinimal[vout.asset] && vout.scriptpubkey_address && tx.vin && !tx.vin[0].is_coinbase && tx._unblinded || outputIndex === vindex,
|
||||
'highlight': vout.scriptpubkey_address === this.address && this.address !== ''
|
||||
}">
|
||||
<td>
|
||||
<a class="shortable-address" *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/' | relativeUrl, vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-inline-flex justify-content-start">
|
||||
<span class="addr-left flex-grow-1" [style]="vout.scriptpubkey_address.length > 40 ? 'max-width: 235px' : ''">{{ vout.scriptpubkey_address }}</span>
|
||||
<span *ngIf="vout.scriptpubkey_address.length > 40" class="addr-right">{{ vout.scriptpubkey_address | capAddress: 40: 10 }}</span>
|
||||
</span>
|
||||
<td class="address-cell">
|
||||
<a class="address" *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/' | relativeUrl, vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
||||
<app-truncate [text]="vout.scriptpubkey_address" [lastChars]="8"></app-truncate>
|
||||
</a>
|
||||
<div>
|
||||
<app-address-labels [vout]="vout" [channel]="tx._channels && tx._channels.outputs[vindex] ? tx._channels.outputs[vindex] : null"></app-address-labels>
|
||||
@@ -185,13 +189,11 @@
|
||||
<ng-container i18n="transactions-list.peg-out-to">Peg-out to <ng-container *ngTemplateOutlet="pegOutLink"></ng-container></ng-container>
|
||||
<ng-template #pegOutLink>
|
||||
<a *ngIf="stateService.env.BASE_MODULE === 'liquid'; else localPegoutLink" [attr.href]="'https://mempool.space/address/' + vout.pegout.scriptpubkey_address" title="{{ vout.pegout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.pegout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.pegout.scriptpubkey_address | shortenString : 35 }}</span>
|
||||
<app-truncate [text]="vout.pegout.scriptpubkey_address"></app-truncate>
|
||||
</a>
|
||||
<ng-template #localPegoutLink>
|
||||
<a [routerLink]="['/address/', vout.pegout.scriptpubkey_address]" title="{{ vout.pegout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.pegout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.pegout.scriptpubkey_address | shortenString : 35 }}</span>
|
||||
<app-truncate [text]="vout.pegout.scriptpubkey_address"></app-truncate>
|
||||
</a>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
@@ -270,7 +272,7 @@
|
||||
<ng-template #showMoreOutputsLabel>
|
||||
<span i18n="show-more">Show more</span>
|
||||
</ng-template>
|
||||
({{ tx.vout.length - getVoutLimit(tx) }} <span i18n="outputs-remaining">remaining</span>)
|
||||
(<ng-container *ngTemplateOutlet="xRemaining; context: {$implicit: tx.vout.length - getVoutLimit(tx)}"></ng-container>)
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -324,3 +326,5 @@
|
||||
<br />
|
||||
<a [routerLink]="['/assets/asset/' | relativeUrl, item.asset]">{{ item.asset | shortenString : 13 }}</a>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #xRemaining let-x i18n="x-remaining">{{ x }} remaining</ng-template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
.arrow-td {
|
||||
width: 20px;
|
||||
width: 30px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
@@ -45,6 +45,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
td.amount {
|
||||
width: 32.5%;
|
||||
}
|
||||
|
||||
.extra-info {
|
||||
display: none;
|
||||
@media (min-width: 576px) {
|
||||
@@ -81,6 +85,10 @@
|
||||
}
|
||||
|
||||
.tx-page-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
white-space: nowrap;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
@@ -97,9 +105,7 @@
|
||||
&:first-child {
|
||||
color: #ffffff66;
|
||||
white-space: pre-wrap;
|
||||
@media (min-width: 476px) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
width: 150px;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
word-break: break-all;
|
||||
@@ -130,14 +136,7 @@ h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.addr-left {
|
||||
font-family: monospace;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: -7px
|
||||
}
|
||||
|
||||
.addr-right {
|
||||
.address {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
@@ -146,3 +145,50 @@ h2 {
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tx-link {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
margin-inline-end: 2em;
|
||||
}
|
||||
|
||||
.vin-witness {
|
||||
.witness-item.accordioned {
|
||||
max-height: 300px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
input:checked + .witness-item.accordioned {
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.witness-toggle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1em;
|
||||
|
||||
.show-all {
|
||||
display: inline;
|
||||
}
|
||||
.show-less {
|
||||
display: none;
|
||||
}
|
||||
.ellipsis {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
input:checked ~ .witness-toggle {
|
||||
.show-all {
|
||||
display: none;
|
||||
}
|
||||
.show-less {
|
||||
display: inline;
|
||||
}
|
||||
.ellipsis {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,7 @@
|
||||
<p *ngIf="!isConnector">Peg Out</p>
|
||||
<p *ngIf="line.value != null"><app-amount [satoshis]="line.value"></app-amount></p>
|
||||
<p class="address">
|
||||
<span class="first">{{ line.pegout.slice(0, -4) }}</span>
|
||||
<span class="last-four">{{ line.pegout.slice(-4) }}</span>
|
||||
<app-truncate [text]="line.pegout"></app-truncate>
|
||||
</p>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
@@ -49,8 +48,7 @@
|
||||
<ng-container *ngIf="isConnector && line.txid">
|
||||
<p>
|
||||
<span i18n="transaction">Transaction</span>
|
||||
<span class="first">{{ line.txid.slice(0, 8) }}</span>...
|
||||
<span class="last-four">{{ line.txid.slice(-4) }}</span>
|
||||
<app-truncate [text]="line.txid"></app-truncate>
|
||||
</p>
|
||||
<ng-container [ngSwitch]="line.type">
|
||||
<p *ngSwitchCase="'input'"><span i18n="transaction.output">Output</span> #{{ line.vout + 1 }}</p>
|
||||
@@ -60,8 +58,7 @@
|
||||
<p *ngIf="line.value == null && line.confidential" i18n="shared.confidential">Confidential</p>
|
||||
<p *ngIf="line.value != null"><app-amount [satoshis]="line.value"></app-amount></p>
|
||||
<p *ngIf="line.type !== 'fee' && line.address" class="address">
|
||||
<span class="first">{{ line.address.slice(0, -4) }}</span>
|
||||
<span class="last-four">{{ line.address.slice(-4) }}</span>
|
||||
<app-truncate [text]="line.address"></app-truncate>
|
||||
</p>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@@ -17,22 +17,5 @@
|
||||
.address {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
justify-content: flex-start;
|
||||
|
||||
.first {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: -2px;
|
||||
}
|
||||
|
||||
.last-four {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let transaction of transactions$ | async; let i = index;">
|
||||
<td class="table-cell-txid"><a [routerLink]="['/tx' | relativeUrl, transaction.txid]">{{ transaction.txid | shortenString : 10 }}</a></td>
|
||||
<td class="table-cell-txid">
|
||||
<a [routerLink]="['/tx' | relativeUrl, transaction.txid]">
|
||||
<app-truncate [text]="transaction.txid" [lastChars]="5"></app-truncate>
|
||||
</a>
|
||||
</td>
|
||||
<td class="table-cell-satoshis"><app-amount *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'; else liquidAmount" [satoshis]="transaction.value" digitsInfo="1.2-4" [noFiat]="true"></app-amount><ng-template #liquidAmount i18n="shared.confidential">Confidential</ng-template></td>
|
||||
<td class="table-cell-fiat" *ngIf="(network$ | async) === ''" ><app-fiat [value]="transaction.value" digitsInfo="1.0-0"></app-fiat></td>
|
||||
<td class="table-cell-fees">{{ transaction.fee / transaction.vsize | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
|
||||
@@ -12,7 +12,8 @@ if (browserWindowEnv.BASE_MODULE && (browserWindowEnv.BASE_MODULE === 'bisq' ||
|
||||
routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'api/rest'
|
||||
redirectTo: 'api/rest',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'api/:type',
|
||||
@@ -20,11 +21,13 @@ if (browserWindowEnv.BASE_MODULE && (browserWindowEnv.BASE_MODULE === 'bisq' ||
|
||||
},
|
||||
{
|
||||
path: 'api',
|
||||
redirectTo: 'api/rest'
|
||||
redirectTo: 'api/rest',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'api/rest'
|
||||
redirectTo: 'api/rest',
|
||||
pathMatch: 'full'
|
||||
}
|
||||
];
|
||||
} else {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<div class="mb-2 box-top">
|
||||
<div class="box-left text-truncate">
|
||||
<h3 class="mb-0 text-truncate">{{ channel.alias || '?' }}</h3>
|
||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.public_key]" >
|
||||
{{ channel.public_key | shortenString : 12 }}
|
||||
</a>
|
||||
<app-clipboard [text]="channel.public_key"></app-clipboard>
|
||||
<app-truncate [text]="channel.public_key" [lastChars]="6" [link]="['/lightning/node' | relativeUrl, channel.public_key]">
|
||||
<app-clipboard [text]="channel.public_key"></app-clipboard>
|
||||
</app-truncate>
|
||||
</div>
|
||||
<div class="box-right">
|
||||
<div class="second-line"><ng-container *ngTemplateOutlet="xChannels; context: {$implicit: channel.channels }"></ng-container></div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 767.98px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,13 @@
|
||||
.tx-link {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
@media (min-width: 650px) {
|
||||
@media (min-width: 768px) {
|
||||
top: 1px;
|
||||
position: relative;
|
||||
align-self: end;
|
||||
margin-left: 15px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
margin-bottom: 4px;
|
||||
top: 1px;
|
||||
position: relative;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
order: 2;
|
||||
|
||||
@@ -49,10 +49,9 @@
|
||||
<td class="alias text-left">
|
||||
<div>{{ node.alias || '?' }}</div>
|
||||
<div class="second-line">
|
||||
<a [routerLink]="['/lightning/node' | relativeUrl, node.public_key]">
|
||||
<span>{{ node.public_key | shortenString : publicKeySize }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="node.public_key" size="small"></app-clipboard>
|
||||
<app-truncate [text]="node.public_key" [maxWidth]="200" [lastChars]="6" [link]="['/lightning/node' | relativeUrl, node.public_key]">
|
||||
<app-clipboard [text]="node.public_key" size="small"></app-clipboard>
|
||||
</app-truncate>
|
||||
</div>
|
||||
</td>
|
||||
<td class="alias text-left d-none d-md-table-cell">
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
<!-- Top nodes per capacity -->
|
||||
<div class="col">
|
||||
<div class="card" style="height: 409px">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<a class="title-link" href="" [routerLink]="['/lightning/nodes/rankings/liquidity' | relativeUrl]">
|
||||
<h5 class="card-title d-inline" i18n="lightning.liquidity-ranking">Liquidity Ranking</h5>
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
<!-- Top nodes per channels -->
|
||||
<div class="col">
|
||||
<div class="card" style="height: 409px">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<a class="title-link" href="" [routerLink]="['/lightning/nodes/rankings/connectivity' | relativeUrl]">
|
||||
<h5 class="card-title d-inline" i18n="lightning.connectivity-ranking">Connectivity Ranking</h5>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<div class="title-container mb-2" *ngIf="!error">
|
||||
<h1 class="mb-0 text-truncate">{{ node.alias }}</h1>
|
||||
<span class="tx-link">
|
||||
<a [routerLink]="['/lightning/node' | relativeUrl, node.public_key]">
|
||||
<span class="d-inline d-lg-none">{{ node.public_key | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ node.public_key }}</span>
|
||||
</a>
|
||||
<app-clipboard [text]="node.public_key"></app-clipboard>
|
||||
<span class="node-id">
|
||||
<app-truncate [text]="node.public_key" [lastChars]="8" [link]="['/lightning/node' | relativeUrl, node.public_key]">
|
||||
<app-clipboard [text]="node.public_key"></app-clipboard>
|
||||
</app-truncate>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasDetails" class="text-right mt-3">
|
||||
<button type="button" class="btn btn-outline-info btn-sm btn-details" (click)="toggleShowDetails()" i18n="node.details|Node Details">Details</button>
|
||||
<button type="button" class="btn btn-outline-info btn-sm btn-details" (click)="toggleShowDetails()" i18n="transaction.details|Transaction Details">Details</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!error">
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.node-id {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.qr-wrapper {
|
||||
background-color: #FFF;
|
||||
padding: 10px;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<div class="spinner-border text-light"></div>
|
||||
</div>
|
||||
|
||||
<table class="table table-borderless text-center m-auto" style="max-width: 900px">
|
||||
<table class="table table-borderless table-fixed text-center m-auto" style="max-width: 900px">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left rank" i18n="mining.rank">Rank</th>
|
||||
|
||||
@@ -42,14 +42,14 @@
|
||||
}
|
||||
|
||||
.rank {
|
||||
width: 20%;
|
||||
width: 8%;
|
||||
@media (max-width: 576px) {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 20%;
|
||||
width: 36%;
|
||||
@media (max-width: 576px) {
|
||||
width: 80%;
|
||||
max-width: 150px;
|
||||
@@ -59,21 +59,21 @@
|
||||
}
|
||||
|
||||
.share {
|
||||
width: 20%;
|
||||
width: 15%;
|
||||
@media (max-width: 576px) {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
|
||||
.nodes {
|
||||
width: 20%;
|
||||
width: 15%;
|
||||
@media (max-width: 576px) {
|
||||
width: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
.capacity {
|
||||
width: 20%;
|
||||
width: 26%;
|
||||
@media (max-width: 576px) {
|
||||
width: 10%;
|
||||
max-width: 100px;
|
||||
@@ -91,3 +91,8 @@ a:hover .link {
|
||||
.flag {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.text-truncate .link {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<app-toggle [textLeft]="'Sort by nodes'" [textRight]="'capacity'" [checked]="true" (toggleStatusChanged)="onGroupToggleStatusChanged($event)"></app-toggle>
|
||||
</div>
|
||||
|
||||
<table class="table table-borderless text-center m-auto" style="max-width: 900px" *ngIf="!widget">
|
||||
<table class="table table-borderless table-fixed text-center m-auto" style="max-width: 900px" *ngIf="!widget">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="rank text-left pl-0" i18n="mining.rank">Rank</th>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</h1>
|
||||
|
||||
<div [class]="widget ? 'widget' : 'full'">
|
||||
<table class="table table-borderless">
|
||||
<table class="table table-borderless table-fixed">
|
||||
<thead>
|
||||
<th class="rank"></th>
|
||||
<th class="alias text-left" i18n="nodes.alias">Alias</th>
|
||||
@@ -29,10 +29,10 @@
|
||||
{{ node.channels | number }}
|
||||
</td>
|
||||
<td *ngIf="!widget" class="timestamp-first text-left">
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.firstSeen"></app-timestamp>
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.firstSeen" [hideTimeSince]="true"></app-timestamp>
|
||||
</td>
|
||||
<td *ngIf="!widget" class="timestamp-update text-left">
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.updatedAt"></app-timestamp>
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.updatedAt" [hideTimeSince]="true"></app-timestamp>
|
||||
</td>
|
||||
<td *ngIf="!widget" class="location text-right text-truncate">
|
||||
<app-geolocation [data]="node.geolocation" [type]="'list-isp'"></app-geolocation>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.container-xl {
|
||||
max-width: 1400px;
|
||||
padding-bottom: 100px;
|
||||
@media (min-width: 767.98px) {
|
||||
@media (min-width: 960px) {
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
@@ -15,40 +15,44 @@
|
||||
width: 5%;
|
||||
}
|
||||
.widget .rank {
|
||||
@media (min-width: 767.98px) {
|
||||
@media (min-width: 960px) {
|
||||
width: 13%;
|
||||
}
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.full .alias {
|
||||
width: 10%;
|
||||
width: 20%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 350px;
|
||||
@media (max-width: 767.98px) {
|
||||
max-width: 175px;
|
||||
@media (max-width: 960px) {
|
||||
width: 40%;
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
.widget .alias {
|
||||
width: 55%;
|
||||
width: 60%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 350px;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
max-width: 175px;
|
||||
}
|
||||
}
|
||||
|
||||
.full .capacity {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
.widget .capacity {
|
||||
width: 32%;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
@@ -57,28 +61,31 @@
|
||||
.full .channels {
|
||||
width: 15%;
|
||||
padding-right: 50px;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .timestamp-first {
|
||||
width: 15%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .timestamp-update {
|
||||
width: 15%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .location {
|
||||
width: 10%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 15%;
|
||||
@media (max-width: 960px) {
|
||||
width: 30%;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,10 @@
|
||||
<app-amount [satoshis]="node.capacity" [digitsInfo]="'1.2-2'" [noFiat]="true"></app-amount>
|
||||
</td>
|
||||
<td *ngIf="!widget" class="timestamp-first text-left">
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.firstSeen"></app-timestamp>
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.firstSeen" [hideTimeSince]="true"></app-timestamp>
|
||||
</td>
|
||||
<td *ngIf="!widget" class="timestamp-update text-left">
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.updatedAt"></app-timestamp>
|
||||
<app-timestamp [customFormat]="'yyyy-MM-dd'" [unixTime]="node.updatedAt" [hideTimeSince]="true"></app-timestamp>
|
||||
</td>
|
||||
<td *ngIf="!widget" class="location text-right text-truncate">
|
||||
<app-geolocation [data]="node.geolocation" [type]="'list-isp'"></app-geolocation>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.container-xl {
|
||||
max-width: 1400px;
|
||||
padding-bottom: 100px;
|
||||
@media (min-width: 767.98px) {
|
||||
@media (min-width: 960px) {
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
@@ -15,70 +15,77 @@
|
||||
width: 5%;
|
||||
}
|
||||
.widget .rank {
|
||||
@media (min-width: 767.98px) {
|
||||
@media (min-width: 960px) {
|
||||
width: 13%;
|
||||
}
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.full .alias {
|
||||
width: 10%;
|
||||
width: 20%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 350px;
|
||||
@media (max-width: 767.98px) {
|
||||
max-width: 175px;
|
||||
@media (max-width: 960px) {
|
||||
width: 40%;
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
.widget .alias {
|
||||
width: 55%;
|
||||
width: 60%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 350px;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
max-width: 175px;
|
||||
}
|
||||
}
|
||||
|
||||
.full .channels {
|
||||
.full .capacity {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
.widget .channels {
|
||||
.widget .capacity {
|
||||
width: 32%;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.full .capacity {
|
||||
.full .channels {
|
||||
width: 15%;
|
||||
padding-right: 50px;
|
||||
@media (max-width: 767.98px) {
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .timestamp-first {
|
||||
width: 15%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .timestamp-update {
|
||||
width: 15%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 10%;
|
||||
@media (max-width: 960px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.full .location {
|
||||
width: 10%;
|
||||
@media (max-width: 767.98px) {
|
||||
width: 15%;
|
||||
@media (max-width: 960px) {
|
||||
width: 30%;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITrans
|
||||
import { Observable } from 'rxjs';
|
||||
import { StateService } from './state.service';
|
||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||
import { Outspend } from '../interfaces/electrs.interface';
|
||||
import { Outspend, Transaction } from '../interfaces/electrs.interface';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -119,6 +119,14 @@ export class ApiService {
|
||||
return this.httpClient.get<AddressInformation>(this.apiBaseUrl + this.apiBasePath + '/api/v1/validate-address/' + address);
|
||||
}
|
||||
|
||||
getRbfHistory$(txid: string): Observable<string[]> {
|
||||
return this.httpClient.get<string[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/tx/' + txid + '/replaces');
|
||||
}
|
||||
|
||||
getRbfCachedTx$(txid: string): Observable<Transaction> {
|
||||
return this.httpClient.get<Transaction>(this.apiBaseUrl + this.apiBasePath + '/api/v1/tx/' + txid + '/cached');
|
||||
}
|
||||
|
||||
listLiquidPegsMonth$(): Observable<LiquidPegs[]> {
|
||||
return this.httpClient.get<LiquidPegs[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/pegs/month');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<span *ngIf="seconds === undefined">-</span>
|
||||
<span *ngIf="seconds !== undefined">
|
||||
‎{{ seconds * 1000 | date: customFormat ?? 'yyyy-MM-dd HH:mm' }}
|
||||
<div class="lg-inline">
|
||||
<div class="lg-inline" *ngIf="!hideTimeSince">
|
||||
<i class="symbol">(<app-time-since [time]="seconds" [fastRender]="true"></app-time-since>)</i>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
@@ -10,6 +10,7 @@ export class TimestampComponent implements OnChanges {
|
||||
@Input() unixTime: number;
|
||||
@Input() dateString: string;
|
||||
@Input() customFormat: string;
|
||||
@Input() hideTimeSince: boolean = false;
|
||||
|
||||
seconds: number | undefined = undefined;
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<span class="truncate" [style.max-width]="maxWidth ? maxWidth + 'px' : null">
|
||||
<ng-container *ngIf="link">
|
||||
<a [routerLink]="link" class="truncate-link">
|
||||
<ng-container *ngIf="rtl; then rtlTruncated; else ltrTruncated;"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!link">
|
||||
<ng-container *ngIf="rtl; then rtlTruncated; else ltrTruncated;"></ng-container>
|
||||
</ng-container>
|
||||
<ng-content></ng-content>
|
||||
</span>
|
||||
|
||||
<ng-template #ltrTruncated>
|
||||
<span class="first">{{text.slice(0,-lastChars)}}</span><span class="last-four">{{text.slice(-lastChars)}}</span>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #rtlTruncated>
|
||||
<span class="first">{{text.slice(lastChars)}}</span><span class="last-four">{{text.slice(0,lastChars)}}</span>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,26 @@
|
||||
.truncate {
|
||||
text-overflow: unset;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
|
||||
.truncate-link {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.first {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.last-four {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-truncate',
|
||||
templateUrl: './truncate.component.html',
|
||||
styleUrls: ['./truncate.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TruncateComponent {
|
||||
@Input() text: string;
|
||||
@Input() link: any = null;
|
||||
@Input() lastChars: number = 4;
|
||||
@Input() maxWidth: number = null;
|
||||
rtl: boolean;
|
||||
|
||||
constructor(
|
||||
@Inject(LOCALE_ID) private locale: string,
|
||||
) {
|
||||
if (this.locale.startsWith('ar') || this.locale.startsWith('fa') || this.locale.startsWith('he')) {
|
||||
this.rtl = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,6 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
})
|
||||
export class Decimal2HexPipe implements PipeTransform {
|
||||
transform(decimal: number): string {
|
||||
return `0x` + decimal.toString(16);
|
||||
return `0x` + ( decimal.toString(16) ).padStart(8, '0');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index
|
||||
import { SvgImagesComponent } from '../components/svg-images/svg-images.component';
|
||||
import { ChangeComponent } from '../components/change/change.component';
|
||||
import { SatsComponent } from './components/sats/sats.component';
|
||||
import { TruncateComponent } from './components/truncate/truncate.component';
|
||||
import { SearchResultsComponent } from '../components/search-form/search-results/search-results.component';
|
||||
import { TimestampComponent } from './components/timestamp/timestamp.component';
|
||||
import { ToggleComponent } from './components/toggle/toggle.component';
|
||||
@@ -152,6 +153,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
|
||||
SvgImagesComponent,
|
||||
ChangeComponent,
|
||||
SatsComponent,
|
||||
TruncateComponent,
|
||||
SearchResultsComponent,
|
||||
TimestampComponent,
|
||||
ToggleComponent,
|
||||
@@ -252,6 +254,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
|
||||
SvgImagesComponent,
|
||||
ChangeComponent,
|
||||
SatsComponent,
|
||||
TruncateComponent,
|
||||
SearchResultsComponent,
|
||||
TimestampComponent,
|
||||
ToggleComponent,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
6425
frontend/src/locale/messages.da.xlf
Normal file
6425
frontend/src/locale/messages.da.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
6744
frontend/src/locale/messages.ne.xlf
Normal file
6744
frontend/src/locale/messages.ne.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user