Merge pull request #5149 from mempool/mononaut/accurate-timestamps-hover

Accurate timestamps on hover
This commit is contained in:
softsimon 2024-06-10 00:16:07 +04:00 committed by GitHub
commit 8382a27a7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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 { AppPreloadingStrategy } from './app.preloading-strategy';
import { ServicesApiServices } from './services/services-api.service';
import { DatePipe } from '@angular/common';
const providers = [
ElectrsApiService,
@ -45,6 +46,7 @@ const providers = [
FiatShortenerPipe,
FiatCurrencyPipe,
CapAddressPipe,
DatePipe,
AppPreloadingStrategy,
ServicesApiServices,
PreloadService,

View File

@ -35,7 +35,7 @@
{{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sat|sat">sat</span>
</td>
<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>
</ng-container>
<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>
</td>
<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>
</ng-container>
</tr>

View File

@ -14,7 +14,7 @@
</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-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>
</tbody>
<div class="">&nbsp;</div>

View File

@ -158,7 +158,7 @@
<tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton">
<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-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-size">
<div class="progress">

View File

@ -14,7 +14,7 @@
<a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a>
</td>
<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 class="text-right">{{ diffChange.difficultyShorten }}</td>
<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>
</td>
<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>
</tr>
</ng-container>

View File

@ -31,7 +31,7 @@
</ng-container>
</td>
<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 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>

View File

@ -197,7 +197,7 @@
&lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm:ss' }}
</td>
<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 class="coinbase">
<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.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
</span>
<app-time kind="since" [time]="tree.time"></app-time>
<app-time kind="since" [time]="tree.time" [showTooltip]="true"></app-time>
</p>
<div class="timeline-wrapper" [class.mined]="tree.mined">
<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 { StateService } from '../../services/state.service';
import { dates } from '../../shared/i18n/dates';
import { DatePipe } from '@angular/common';
@Component({
selector: 'app-time',
template: `{{ text }}`,
templateUrl: './time.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TimeComponent implements OnInit, OnChanges, OnDestroy {
interval: number;
text: string;
tooltip: string;
precisionThresholds = {
year: 100,
month: 18,
@ -26,6 +28,7 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
@Input() kind: 'plain' | 'since' | 'until' | 'span' | 'before' | 'within' = 'plain';
@Input() fastRender = false;
@Input() fixedRender = false;
@Input() showTooltip = false;
@Input() relative = false;
@Input() precision: number = 0;
@Input() numUnits: number = 1;
@ -36,6 +39,7 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
constructor(
private ref: ChangeDetectorRef,
private stateService: StateService,
private datePipe: DatePipe,
) {
this.intervals = {
year: 31536000,
@ -78,13 +82,20 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
switch (this.kind) {
case 'since':
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;
case 'until':
case 'within':
seconds = (+new Date(this.time) - +new Date()) / 1000;
this.tooltip = this.datePipe.transform(new Date(this.time), 'yyyy-MM-dd HH:mm');
break;
default:
seconds = Math.floor(this.time);
this.tooltip = '';
}
if (!this.showTooltip || this.relative) {
this.tooltip = '';
}
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="value">
@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 {
<span class="skeleton-loader" style="max-width: 50%;"></span>
}
@ -86,7 +86,7 @@
<div class="value">
&lrm;{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}
<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>

View File

@ -450,7 +450,7 @@
@if (transactionTime > 0) {
<tr>
<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>
}
} @else {
@ -464,7 +464,7 @@
} @else if (transactionTime > 0) {
<tr>
<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>
} @else {
<tr>

View File

@ -8,7 +8,7 @@
<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 && 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>
</div>
</div>

View File

@ -110,7 +110,7 @@
<tbody *ngIf="blocks$ | async as blocks; else blocksSkeleton">
<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-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-size">
<div class="progress">