Accurate timestamps on hover

This commit is contained in:
Mononaut 2024-06-08 23:28:44 +00:00
parent 0c3ef4eabc
commit 3149199c8a
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
15 changed files with 30 additions and 16 deletions

View File

@ -27,6 +27,7 @@ import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-st
import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe'; import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe';
import { AppPreloadingStrategy } from './app.preloading-strategy'; import { AppPreloadingStrategy } from './app.preloading-strategy';
import { ServicesApiServices } from './services/services-api.service'; import { ServicesApiServices } from './services/services-api.service';
import { DatePipe } from '@angular/common';
const providers = [ const providers = [
ElectrsApiService, ElectrsApiService,
@ -45,6 +46,7 @@ const providers = [
FiatShortenerPipe, FiatShortenerPipe,
FiatCurrencyPipe, FiatCurrencyPipe,
CapAddressPipe, CapAddressPipe,
DatePipe,
AppPreloadingStrategy, AppPreloadingStrategy,
ServicesApiServices, ServicesApiServices,
PreloadService, PreloadService,

View File

@ -35,7 +35,7 @@
{{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> {{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sat|sat">sat</span>
</td> </td>
<td class="time text-right"> <td class="time text-right">
<app-time kind="since" [time]="acceleration.added" [fastRender]="true"></app-time> <app-time kind="since" [time]="acceleration.added" [fastRender]="true" [showTooltip]="true"></app-time>
</td> </td>
</ng-container> </ng-container>
<ng-container *ngIf="!pending"> <ng-container *ngIf="!pending">
@ -55,7 +55,7 @@
<span *ngIf="acceleration.status.includes('failed')" class="badge badge-danger" i18n="accelerator.canceled">Failed <span *ngIf="acceleration.status === 'failed_provisional'">🔄</span></span> <span *ngIf="acceleration.status.includes('failed')" class="badge badge-danger" i18n="accelerator.canceled">Failed <span *ngIf="acceleration.status === 'failed_provisional'">🔄</span></span>
</td> </td>
<td class="date text-right" *ngIf="!this.widget"> <td class="date text-right" *ngIf="!this.widget">
<app-time kind="since" [time]="acceleration.added" [fastRender]="true"></app-time> <app-time kind="since" [time]="acceleration.added" [fastRender]="true" [showTooltip]="true"></app-time>
</td> </td>
</ng-container> </ng-container>
</tr> </tr>

View File

@ -14,7 +14,7 @@
</td> </td>
<td class="table-cell-satoshis"><app-amount [satoshis]="transaction.value" digitsInfo="1.2-4" [noFiat]="true"></app-amount></td> <td class="table-cell-satoshis"><app-amount [satoshis]="transaction.value" digitsInfo="1.2-4" [noFiat]="true"></app-amount></td>
<td class="table-cell-fiat" ><app-fiat [value]="transaction.value" [blockConversion]="transaction.price" digitsInfo="1.0-0"></app-fiat></td> <td class="table-cell-fiat" ><app-fiat [value]="transaction.value" [blockConversion]="transaction.price" digitsInfo="1.0-0"></app-fiat></td>
<td class="table-cell-date"><app-time kind="since" [time]="transaction.time" [fastRender]="true"></app-time></td> <td class="table-cell-date"><app-time kind="since" [time]="transaction.time" [fastRender]="true" [showTooltip]="true"></app-time></td>
</tr> </tr>
</tbody> </tbody>
<div class="">&nbsp;</div> <div class="">&nbsp;</div>

View File

@ -158,7 +158,7 @@
<tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton"> <tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton">
<tr *ngFor="let block of blocks; let i = index; trackBy: trackByBlock"> <tr *ngFor="let block of blocks; let i = index; trackBy: trackByBlock">
<td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td> <td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
<td class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></td> <td class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true" [showTooltip]="true"></app-time></td>
<td class="table-cell-transaction-count">{{ block.tx_count | number }}</td> <td class="table-cell-transaction-count">{{ block.tx_count | number }}</td>
<td class="table-cell-size"> <td class="table-cell-size">
<div class="progress"> <div class="progress">

View File

@ -14,7 +14,7 @@
<a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a> <a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a>
</td> </td>
<td class="date text-left"> <td class="date text-left">
<app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true" [precision]="1"></app-time> <app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true" [precision]="1" [showTooltip]="true"></app-time>
</td> </td>
<td class="text-right">{{ diffChange.difficultyShorten }}</td> <td class="text-right">{{ diffChange.difficultyShorten }}</td>
<td class="text-right" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'"> <td class="text-right" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">

View File

@ -26,7 +26,7 @@
<app-amount [satoshis]="utxo.amount" [noFiat]="true" [forceBtc]="true"></app-amount> <app-amount [satoshis]="utxo.amount" [noFiat]="true" [forceBtc]="true"></app-amount>
</td> </td>
<td class="timestamp text-left widget"> <td class="timestamp text-left widget">
<app-time kind="since" [time]="utxo.blocktime"></app-time> <app-time kind="since" [time]="utxo.blocktime" [showTooltip]="true"></app-time>
</td> </td>
</tr> </tr>
</ng-container> </ng-container>

View File

@ -31,7 +31,7 @@
</ng-container> </ng-container>
</td> </td>
<td class="timestamp text-left widget"> <td class="timestamp text-left widget">
<app-time kind="since" [time]="peg.blocktime"></app-time> <app-time kind="since" [time]="peg.blocktime" [showTooltip]="true"></app-time>
</td> </td>
<td class="amount text-right widget" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}"> <td class="amount text-right widget" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}">
<app-amount [satoshis]="peg.amount" [noFiat]="true" [forceBtc]="true" [addPlus]="true"></app-amount> <app-amount [satoshis]="peg.amount" [noFiat]="true" [forceBtc]="true" [addPlus]="true"></app-amount>

View File

@ -197,7 +197,7 @@
&lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm:ss' }} &lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm:ss' }}
</td> </td>
<td class="mined"> <td class="mined">
<app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time> <app-time kind="since" [time]="block.timestamp" [fastRender]="true" [showTooltip]="true"></app-time>
</td> </td>
<td class="coinbase"> <td class="coinbase">
<span class="badge badge-secondary scriptmessage longer"> <span class="badge badge-secondary scriptmessage longer">

View File

@ -23,7 +23,7 @@
<span *ngIf="tree.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span> <span *ngIf="tree.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="tree.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span> <span *ngIf="tree.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
</span> </span>
<app-time kind="since" [time]="tree.time"></app-time> <app-time kind="since" [time]="tree.time" [showTooltip]="true"></app-time>
</p> </p>
<div class="timeline-wrapper" [class.mined]="tree.mined"> <div class="timeline-wrapper" [class.mined]="tree.mined">
<app-rbf-timeline [replacements]="tree"></app-rbf-timeline> <app-rbf-timeline [replacements]="tree"></app-rbf-timeline>

View File

@ -0,0 +1 @@
<span [ngbTooltip]="tooltip">{{ text }}</span>

View File

@ -1,15 +1,17 @@
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core';
import { StateService } from '../../services/state.service'; import { StateService } from '../../services/state.service';
import { dates } from '../../shared/i18n/dates'; import { dates } from '../../shared/i18n/dates';
import { DatePipe } from '@angular/common';
@Component({ @Component({
selector: 'app-time', selector: 'app-time',
template: `{{ text }}`, templateUrl: './time.component.html',
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class TimeComponent implements OnInit, OnChanges, OnDestroy { export class TimeComponent implements OnInit, OnChanges, OnDestroy {
interval: number; interval: number;
text: string; text: string;
tooltip: string;
precisionThresholds = { precisionThresholds = {
year: 100, year: 100,
month: 18, month: 18,
@ -26,6 +28,7 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
@Input() kind: 'plain' | 'since' | 'until' | 'span' | 'before' | 'within' = 'plain'; @Input() kind: 'plain' | 'since' | 'until' | 'span' | 'before' | 'within' = 'plain';
@Input() fastRender = false; @Input() fastRender = false;
@Input() fixedRender = false; @Input() fixedRender = false;
@Input() showTooltip = false;
@Input() relative = false; @Input() relative = false;
@Input() precision: number = 0; @Input() precision: number = 0;
@Input() numUnits: number = 1; @Input() numUnits: number = 1;
@ -36,6 +39,7 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
constructor( constructor(
private ref: ChangeDetectorRef, private ref: ChangeDetectorRef,
private stateService: StateService, private stateService: StateService,
private datePipe: DatePipe,
) { ) {
this.intervals = { this.intervals = {
year: 31536000, year: 31536000,
@ -78,13 +82,20 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
switch (this.kind) { switch (this.kind) {
case 'since': case 'since':
seconds = Math.floor((+new Date() - +new Date(this.dateString || this.time * 1000)) / 1000); seconds = Math.floor((+new Date() - +new Date(this.dateString || this.time * 1000)) / 1000);
this.tooltip = this.datePipe.transform(new Date(this.dateString || this.time * 1000), 'yyyy-MM-dd HH:mm');
break; break;
case 'until': case 'until':
case 'within': case 'within':
seconds = (+new Date(this.time) - +new Date()) / 1000; seconds = (+new Date(this.time) - +new Date()) / 1000;
this.tooltip = this.datePipe.transform(new Date(this.time), 'yyyy-MM-dd HH:mm');
break; break;
default: default:
seconds = Math.floor(this.time); seconds = Math.floor(this.time);
this.tooltip = '';
}
if (!this.showTooltip || this.relative) {
this.tooltip = '';
} }
if (seconds < 1 && this.kind === 'span') { if (seconds < 1 && this.kind === 'span') {

View File

@ -59,7 +59,7 @@
<div class="label" i18n="transaction.first-seen|Transaction first seen">First seen</div> <div class="label" i18n="transaction.first-seen|Transaction first seen">First seen</div>
<div class="value"> <div class="value">
@if (transactionTime > 0) { @if (transactionTime > 0) {
<i><app-time kind="since" [time]="transactionTime" [fastRender]="true"></app-time></i> <i><app-time kind="since" [time]="transactionTime" [fastRender]="true" [showTooltip]="true"></app-time></i>
} @else { } @else {
<span class="skeleton-loader" style="max-width: 50%;"></span> <span class="skeleton-loader" style="max-width: 50%;"></span>
} }
@ -86,7 +86,7 @@
<div class="value"> <div class="value">
&lrm;{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }} &lrm;{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}
<div class="lg-inline"> <div class="lg-inline">
<i class="symbol">(<app-time kind="since" [time]="tx.status.block_time" [fastRender]="true"></app-time>)</i> <i class="symbol">(<app-time kind="since" [time]="tx.status.block_time" [fastRender]="true" [showTooltip]="true"></app-time>)</i>
</div> </div>
</div> </div>
</div> </div>

View File

@ -450,7 +450,7 @@
@if (transactionTime > 0) { @if (transactionTime > 0) {
<tr> <tr>
<td i18n="transaction.confirmed|Transaction Confirmed state">Confirmed</td> <td i18n="transaction.confirmed|Transaction Confirmed state">Confirmed</td>
<td><app-time kind="span" [time]="tx.status.block_time - transactionTime" [fastRender]="true" [relative]="true"></app-time></td> <td><app-time kind="span" [time]="tx.status.block_time" [fastRender]="true" [showTooltip]="true"></app-time></td>
</tr> </tr>
} }
} @else { } @else {
@ -464,7 +464,7 @@
} @else if (transactionTime > 0) { } @else if (transactionTime > 0) {
<tr> <tr>
<td i18n="transaction.first-seen|Transaction first seen">First seen</td> <td i18n="transaction.first-seen|Transaction first seen">First seen</td>
<td><i><app-time kind="since" [time]="transactionTime" [fastRender]="true"></app-time></i></td> <td><i><app-time kind="since" [time]="transactionTime" [fastRender]="true" [showTooltip]="true"></app-time></i></td>
</tr> </tr>
} @else { } @else {
<tr> <tr>

View File

@ -8,7 +8,7 @@
<div> <div>
<ng-template [ngIf]="tx.status.confirmed">&lrm;{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-template> <ng-template [ngIf]="tx.status.confirmed">&lrm;{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-template>
<ng-template [ngIf]="!tx.status.confirmed && tx.firstSeen"> <ng-template [ngIf]="!tx.status.confirmed && tx.firstSeen">
<i><app-time kind="since" [time]="tx.firstSeen" [fastRender]="true"></app-time></i> <i><app-time kind="since" [time]="tx.firstSeen" [fastRender]="true" [showTooltip]="true"></app-time></i>
</ng-template> </ng-template>
</div> </div>
</div> </div>

View File

@ -110,7 +110,7 @@
<tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton"> <tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton">
<tr *ngFor="let block of blocks; let i = index; trackBy: trackByBlock"> <tr *ngFor="let block of blocks; let i = index; trackBy: trackByBlock">
<td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td> <td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
<td class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></td> <td class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true" [showTooltip]="true"></app-time></td>
<td class="table-cell-transaction-count">{{ block.tx_count | number }}</td> <td class="table-cell-transaction-count">{{ block.tx_count | number }}</td>
<td class="table-cell-size"> <td class="table-cell-size">
<div class="progress"> <div class="progress">