mirror of
https://github.com/mempool/mempool.git
synced 2025-01-03 20:24:28 +01:00
Merge pull request #508 from mempool/simon/bisq-new-dashboard
New Bisq Markets Dashboard Design
This commit is contained in:
commit
f137f45cef
@ -8,11 +8,9 @@
|
|||||||
<div class="spinner-border text-light"></div>
|
<div class="spinner-border text-light"></div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<div class="chart-container">
|
<ng-container *ngIf="volumes$ | async as volumes; else loadingVolumes">
|
||||||
<ng-container *ngIf="volumes$ | async as volumes; else loadingVolumes">
|
<app-lightweight-charts-area [data]="volumes.data" [lineData]="volumes.linesData"></app-lightweight-charts-area>
|
||||||
<app-lightweight-charts-area [data]="volumes.data" [lineData]="volumes.linesData"></app-lightweight-charts-area>
|
</ng-container>
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
<div class="container-xl">
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2">
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" i18n="bisq-dashboard.market-price-title">Bisq Market Price</h5>
|
||||||
|
<div class="big-fiat">
|
||||||
|
<span class="green-color" *ngIf="bisqMarketPrice; else loading">{{ bisqMarketPrice | currency:'USD':'symbol':'1.2-2' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" i18n="bisq-dashboard.price-index-title">Bisq Price Index</h5>
|
||||||
|
<div class="big-fiat">
|
||||||
|
<span class="green-color" *ngIf="usdPrice$ | async as usdPrice; else loading">{{ usdPrice | currency:'USD':'symbol':'1.2-2' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2">
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">US Dollar - BTC/USD</h5>
|
||||||
|
<div class="chart-container">
|
||||||
|
<ng-container *ngIf="hlocData$ | async as hlocData; else loadingSpinner">
|
||||||
|
<app-lightweight-charts [height]="300" [data]="hlocData.hloc" [volumeData]="hlocData.volume" [precision]="2"></app-lightweight-charts>
|
||||||
|
<br>
|
||||||
|
<div class="text-center"><a href="" [routerLink]="['/bisq/market/btc_usd']" i18n="dashboard.view-all">View all »</a></div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title" i18n="Bisq markets title">Bisq Trading Volume</h5>
|
||||||
|
<div class="chart-container">
|
||||||
|
<ng-container *ngIf="volumes$ | async as volumes; else loadingSpinner">
|
||||||
|
<app-lightweight-charts-area [height]="300" [data]="volumes.data" [lineData]="volumes.linesData"></app-lightweight-charts-area>
|
||||||
|
<br>
|
||||||
|
<div class="text-center"><a href="" [routerLink]="['/bisq/markets']" i18n="dashboard.view-all">View all »</a></div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2">
|
||||||
|
<ng-container *ngIf="{ value: (tickers$ | async) } as tickers">
|
||||||
|
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-center">
|
||||||
|
<ng-template [ngIf]="stateService.env.OFFICIAL_BISQ_MARKETS" [ngIfElse]="nonOfficialMarkets" i18n="Bisq All Markets">Markets</ng-template>
|
||||||
|
<ng-template #nonOfficialMarkets i18n="Bisq Bitcoin Markets">Bitcoin Markets</ng-template>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="table table-borderless table-striped">
|
||||||
|
<thead>
|
||||||
|
<th><ng-container i18n>Currency</ng-container> <button [disabled]="(sort$ | async) === 'name'" class="btn btn-link btn-sm" (click)="sort('name')"><fa-icon [icon]="['fas', 'chevron-down']" [fixedWidth]="true"></fa-icon></button></th>
|
||||||
|
<th i18n>Price</th>
|
||||||
|
<th><ng-container i18n="Trades amount 7D">Trades (7d)</ng-container> <button [disabled]="(sort$ | async) === 'trades'" class="btn btn-link btn-sm" (click)="sort('trades')"><fa-icon [icon]="['fas', 'chevron-down']" [fixedWidth]="true"></fa-icon></button></th>
|
||||||
|
</thead>
|
||||||
|
<tbody *ngIf="tickers.value; else loadingTmpl">
|
||||||
|
<tr *ngFor="let ticker of tickers.value; trackBy: trackByFn;">
|
||||||
|
<td><a [routerLink]="['/market' | relativeUrl, ticker.pair_url]">{{ ticker.name }})</a></td>
|
||||||
|
<td>
|
||||||
|
<app-fiat *ngIf="ticker.market.rtype === 'crypto'; else fiat" [value]="ticker.last * 100000000"></app-fiat>
|
||||||
|
<ng-template #fiat>
|
||||||
|
<span class="green-color">{{ ticker.last | currency: ticker.market.rsymbol }}</span>
|
||||||
|
</ng-template>
|
||||||
|
</td>
|
||||||
|
<td>{{ ticker.volume?.num_trades ? ticker.volume?.num_trades : 0 }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center"><a href="" [routerLink]="['/bisq/markets']" i18n="dashboard.view-all">View all »</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-center" i18n="Latest Trades header">Latest Trades</h5>
|
||||||
|
<app-bisq-trades [trades$]="trades$" view="small"></app-bisq-trades>
|
||||||
|
<div class="text-center"><a href="" [routerLink]="['/bisq/markets']" i18n="dashboard.view-all">View all »</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #loadingTmpl>
|
||||||
|
<tr *ngFor="let i of [1,2,3,4,5,6,7,8,9,10]">
|
||||||
|
<td *ngFor="let j of [1, 2, 3]"><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #loadingSpinner>
|
||||||
|
<div class="text-center loadingGraphs">
|
||||||
|
<div class="spinner-border text-light"></div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #loading>
|
||||||
|
<div class="skeleton-loader shorter"></div>
|
||||||
|
</ng-template>
|
@ -0,0 +1,84 @@
|
|||||||
|
#volumeHolder {
|
||||||
|
height: 500px;
|
||||||
|
background-color: #000;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadingGraphs {
|
||||||
|
position: relative;
|
||||||
|
top: 45%;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
font-size: 13px;
|
||||||
|
@media(min-width: 576px){
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-fiat {
|
||||||
|
color: #3bcc49;
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background-color: #1d1f31;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
color: #4a68b9;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-block {
|
||||||
|
float: left;
|
||||||
|
width: 350px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #2d3348;
|
||||||
|
height: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-warning {
|
||||||
|
background-color: #b58800 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-loader {
|
||||||
|
max-width: 100%;
|
||||||
|
&.shorter {
|
||||||
|
max-width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-padding {
|
||||||
|
padding: 1.25rem 2rem 1.25rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-card {
|
||||||
|
height: 100%;
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
height: 385px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,192 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
|
import { Observable, combineLatest, BehaviorSubject, of } from 'rxjs';
|
||||||
|
import { map, share, switchMap } from 'rxjs/operators';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
import { StateService } from 'src/app/services/state.service';
|
||||||
|
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||||
|
import { BisqApiService } from '../bisq-api.service';
|
||||||
|
import { Trade } from '../bisq.interfaces';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-main-bisq-dashboard',
|
||||||
|
templateUrl: './bisq-main-dashboard.component.html',
|
||||||
|
styleUrls: ['./bisq-main-dashboard.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class BisqMainDashboardComponent implements OnInit {
|
||||||
|
tickers$: Observable<any>;
|
||||||
|
volumes$: Observable<any>;
|
||||||
|
trades$: Observable<Trade[]>;
|
||||||
|
sort$ = new BehaviorSubject<string>('trades');
|
||||||
|
hlocData$: Observable<any>;
|
||||||
|
usdPrice$: Observable<number>;
|
||||||
|
isLoadingGraph = true;
|
||||||
|
bisqMarketPrice = 0;
|
||||||
|
|
||||||
|
allowCryptoCoins = ['usdc', 'l-btc', 'bsq'];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private websocketService: WebsocketService,
|
||||||
|
private bisqApiService: BisqApiService,
|
||||||
|
public stateService: StateService,
|
||||||
|
private seoService: SeoService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.seoService.setTitle(`Markets`);
|
||||||
|
this.websocketService.want(['blocks']);
|
||||||
|
|
||||||
|
this.usdPrice$ = this.stateService.conversions$.asObservable().pipe(
|
||||||
|
map((conversions) => conversions.USD)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.volumes$ = this.bisqApiService.getAllVolumesDay$()
|
||||||
|
.pipe(
|
||||||
|
map((volumes) => {
|
||||||
|
const data = volumes.map((volume) => {
|
||||||
|
return {
|
||||||
|
time: volume.period_start,
|
||||||
|
value: volume.volume,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const linesData = volumes.map((volume) => {
|
||||||
|
return {
|
||||||
|
time: volume.period_start,
|
||||||
|
value: volume.num_trades,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: data,
|
||||||
|
linesData: linesData,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const getMarkets = this.bisqApiService.getMarkets$().pipe(share());
|
||||||
|
|
||||||
|
this.tickers$ = combineLatest([
|
||||||
|
this.bisqApiService.getMarketsTicker$(),
|
||||||
|
getMarkets,
|
||||||
|
this.bisqApiService.getMarketVolumesByTime$('7d'),
|
||||||
|
])
|
||||||
|
.pipe(
|
||||||
|
map(([tickers, markets, volumes]) => {
|
||||||
|
|
||||||
|
const newTickers = [];
|
||||||
|
for (const t in tickers) {
|
||||||
|
|
||||||
|
if (!this.stateService.env.OFFICIAL_BISQ_MARKETS) {
|
||||||
|
const pair = t.split('_');
|
||||||
|
if (pair[1] === 'btc' && this.allowCryptoCoins.indexOf(pair[0]) === -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mappedTicker: any = tickers[t];
|
||||||
|
|
||||||
|
mappedTicker.pair_url = t;
|
||||||
|
mappedTicker.pair = t.replace('_', '/').toUpperCase();
|
||||||
|
mappedTicker.market = markets[t];
|
||||||
|
mappedTicker.volume = volumes[t];
|
||||||
|
mappedTicker.name = `${mappedTicker.market.rtype === 'crypto' ? mappedTicker.market.lname : mappedTicker.market.rname} (${mappedTicker.market.rtype === 'crypto' ? mappedTicker.market.lsymbol : mappedTicker.market.rsymbol}`;
|
||||||
|
newTickers.push(mappedTicker);
|
||||||
|
}
|
||||||
|
return newTickers;
|
||||||
|
}),
|
||||||
|
switchMap((tickers) => combineLatest([this.sort$, of(tickers)])),
|
||||||
|
map(([sort, tickers]) => {
|
||||||
|
if (sort === 'trades') {
|
||||||
|
tickers.sort((a, b) => (b.volume && b.volume.num_trades || 0) - (a.volume && a.volume.num_trades || 0));
|
||||||
|
} else if (sort === 'volumes') {
|
||||||
|
tickers.sort((a, b) => (b.volume && b.volume.volume || 0) - (a.volume && a.volume.volume || 0));
|
||||||
|
} else if (sort === 'name') {
|
||||||
|
tickers.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
}
|
||||||
|
return tickers.slice(0, 10);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.trades$ = combineLatest([
|
||||||
|
this.bisqApiService.getMarketTrades$('all'),
|
||||||
|
getMarkets,
|
||||||
|
])
|
||||||
|
.pipe(
|
||||||
|
map(([trades, markets]) => {
|
||||||
|
if (!this.stateService.env.OFFICIAL_BISQ_MARKETS) {
|
||||||
|
trades = trades.filter((trade) => {
|
||||||
|
const pair = trade.market.split('_');
|
||||||
|
return !(pair[1] === 'btc' && this.allowCryptoCoins.indexOf(pair[0]) === -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return trades.map((trade => {
|
||||||
|
trade._market = markets[trade.market];
|
||||||
|
return trade;
|
||||||
|
})).slice(0, 10);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.hlocData$ = this.bisqApiService.getMarketsHloc$('btc_usd', 'day')
|
||||||
|
.pipe(
|
||||||
|
map((hlocData) => {
|
||||||
|
this.isLoadingGraph = false;
|
||||||
|
|
||||||
|
hlocData = hlocData.map((h) => {
|
||||||
|
h.time = h.period_start;
|
||||||
|
return h;
|
||||||
|
});
|
||||||
|
|
||||||
|
const hlocVolume = hlocData.map((h) => {
|
||||||
|
return {
|
||||||
|
time: h.time,
|
||||||
|
value: h.volume_right,
|
||||||
|
color: h.close > h.avg ? 'rgba(0, 41, 74, 0.7)' : 'rgba(0, 41, 74, 1)',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add whitespace
|
||||||
|
if (hlocData.length > 1) {
|
||||||
|
const newHloc = [];
|
||||||
|
newHloc.push(hlocData[0]);
|
||||||
|
|
||||||
|
const period = 86400;
|
||||||
|
let periods = 0;
|
||||||
|
const startingDate = hlocData[0].period_start;
|
||||||
|
let index = 1;
|
||||||
|
while (true) {
|
||||||
|
periods++;
|
||||||
|
if (hlocData[index].period_start > startingDate + period * periods) {
|
||||||
|
newHloc.push({
|
||||||
|
time: startingDate + period * periods,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
newHloc.push(hlocData[index]);
|
||||||
|
index++;
|
||||||
|
if (!hlocData[index]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hlocData = newHloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bisqMarketPrice = hlocData[hlocData.length - 1].close;
|
||||||
|
|
||||||
|
return {
|
||||||
|
hloc: hlocData,
|
||||||
|
volume: hlocVolume,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
trackByFn(index: number) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(by: string) {
|
||||||
|
this.sort$.next(by);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
<table class="table table-borderless table-striped">
|
<table class="table table-borderless table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<th i18n>Date</th>
|
<th i18n>Date</th>
|
||||||
<th i18n>Price</th>
|
<th *ngIf="view === 'all'" i18n>Price</th>
|
||||||
<th><ng-container *ngTemplateOutlet="amount; context: {$implicit: 'BTC' }"></ng-container></th>
|
<th><ng-container *ngTemplateOutlet="amount; context: {$implicit: 'BTC' }"></ng-container></th>
|
||||||
<th>
|
<th>
|
||||||
<ng-template [ngIf]="market" [ngIfElse]="noMarket"><ng-container *ngTemplateOutlet="amount; context: {$implicit: market.lsymbol === 'BTC' ? market.rsymbol : market.lsymbol }"></ng-container></ng-template>
|
<ng-template [ngIf]="market" [ngIfElse]="noMarket"><ng-container *ngTemplateOutlet="amount; context: {$implicit: market.lsymbol === 'BTC' ? market.rsymbol : market.lsymbol }"></ng-container></ng-template>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
<td>
|
<td>
|
||||||
{{ trade.trade_date | date:'yyyy-MM-dd HH:mm' }}
|
{{ trade.trade_date | date:'yyyy-MM-dd HH:mm' }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td *ngIf="view === 'all'">
|
||||||
<ng-container *ngIf="(trade._market || market).rtype === 'fiat'; else priceCrypto"><span class="green-color">{{ trade.price | currency: (trade._market || market).rsymbol }}</span></ng-container>
|
<ng-container *ngIf="(trade._market || market).rtype === 'fiat'; else priceCrypto"><span class="green-color">{{ trade.price | currency: (trade._market || market).rsymbol }}</span></ng-container>
|
||||||
<ng-template #priceCrypto>{{ trade.price | number: '1.2-' + (trade._market || market).rprecision }} <span class="symbol">{{ (trade._market || market).rsymbol }}</span></ng-template>
|
<ng-template #priceCrypto>{{ trade.price | number: '1.2-' + (trade._market || market).rprecision }} <span class="symbol">{{ (trade._market || market).rsymbol }}</span></ng-template>
|
||||||
</td>
|
</td>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<ng-template #loadingTmpl>
|
<ng-template #loadingTmpl>
|
||||||
<tr *ngFor="let i of [1,2,3,4,5,6,7,8,9,10]">
|
<tr *ngFor="let i of [1,2,3,4,5,6,7,8,9,10]">
|
||||||
<td *ngFor="let j of [1, 2, 3, 4]"><span class="skeleton-loader"></span></td>
|
<td *ngFor="let j of loadingColumns"><span class="skeleton-loader"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -7,7 +7,16 @@ import { Observable } from 'rxjs';
|
|||||||
styleUrls: ['./bisq-trades.component.scss'],
|
styleUrls: ['./bisq-trades.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class BisqTradesComponent {
|
export class BisqTradesComponent implements OnChanges {
|
||||||
@Input() trades$: Observable<any>;
|
@Input() trades$: Observable<any>;
|
||||||
@Input() market: any;
|
@Input() market: any;
|
||||||
|
@Input() view: 'all' | 'small' = 'all';
|
||||||
|
|
||||||
|
loadingColumns = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
if (this.view === 'small') {
|
||||||
|
this.loadingColumns = [1, 2, 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.component';
|
import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.component';
|
||||||
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
||||||
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
||||||
|
import { BisqMainDashboardComponent } from './bisq-main-dashboard/bisq-main-dashboard.component';
|
||||||
import { BisqIconComponent } from './bisq-icon/bisq-icon.component';
|
import { BisqIconComponent } from './bisq-icon/bisq-icon.component';
|
||||||
import { BisqTransactionDetailsComponent } from './bisq-transaction-details/bisq-transaction-details.component';
|
import { BisqTransactionDetailsComponent } from './bisq-transaction-details/bisq-transaction-details.component';
|
||||||
import { BisqTransfersComponent } from './bisq-transfers/bisq-transfers.component';
|
import { BisqTransfersComponent } from './bisq-transfers/bisq-transfers.component';
|
||||||
@ -42,6 +43,7 @@ import { BisqTradesComponent } from './bisq-trades/bisq-trades.component';
|
|||||||
BisqDashboardComponent,
|
BisqDashboardComponent,
|
||||||
BisqMarketComponent,
|
BisqMarketComponent,
|
||||||
BisqTradesComponent,
|
BisqTradesComponent,
|
||||||
|
BisqMainDashboardComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BisqRoutingModule,
|
BisqRoutingModule,
|
||||||
|
@ -10,10 +10,15 @@ import { BisqStatsComponent } from './bisq-stats/bisq-stats.component';
|
|||||||
import { ApiDocsComponent } from '../components/api-docs/api-docs.component';
|
import { ApiDocsComponent } from '../components/api-docs/api-docs.component';
|
||||||
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
||||||
import { BisqMarketComponent } from './bisq-market/bisq-market.component';
|
import { BisqMarketComponent } from './bisq-market/bisq-market.component';
|
||||||
|
import { BisqMainDashboardComponent } from './bisq-main-dashboard/bisq-main-dashboard.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
component: BisqMainDashboardComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'markets',
|
||||||
component: BisqDashboardComponent,
|
component: BisqDashboardComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createChart, CrosshairMode, isBusinessDay } from 'lightweight-charts';
|
import { createChart, CrosshairMode, isBusinessDay } from 'lightweight-charts';
|
||||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDestroy } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-lightweight-charts-area',
|
selector: 'app-lightweight-charts-area',
|
||||||
@ -7,10 +7,11 @@ import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDes
|
|||||||
styleUrls: ['./lightweight-charts-area.component.scss'],
|
styleUrls: ['./lightweight-charts-area.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class LightweightChartsAreaComponent implements OnChanges, OnDestroy {
|
export class LightweightChartsAreaComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() data: any;
|
@Input() data: any;
|
||||||
@Input() lineData: any;
|
@Input() lineData: any;
|
||||||
@Input() precision: number;
|
@Input() precision: number;
|
||||||
|
@Input() height = 500;
|
||||||
|
|
||||||
areaSeries: any;
|
areaSeries: any;
|
||||||
volumeSeries: any;
|
volumeSeries: any;
|
||||||
@ -18,12 +19,14 @@ export class LightweightChartsAreaComponent implements OnChanges, OnDestroy {
|
|||||||
lineSeries: any;
|
lineSeries: any;
|
||||||
container: any;
|
container: any;
|
||||||
|
|
||||||
width = 1110;
|
width: number;
|
||||||
height = 500;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private element: ElementRef,
|
private element: ElementRef,
|
||||||
) {
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.width = this.element.nativeElement.parentElement.offsetWidth;
|
||||||
this.container = document.createElement('div');
|
this.container = document.createElement('div');
|
||||||
const chartholder = this.element.nativeElement.appendChild(this.container);
|
const chartholder = this.element.nativeElement.appendChild(this.container);
|
||||||
|
|
||||||
@ -112,16 +115,22 @@ export class LightweightChartsAreaComponent implements OnChanges, OnDestroy {
|
|||||||
toolTip.style.left = left + 'px';
|
toolTip.style.left = left + 'px';
|
||||||
toolTip.style.top = top + 'px';
|
toolTip.style.top = top + 'px';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
businessDayToString(businessDay) {
|
businessDayToString(businessDay) {
|
||||||
return businessDay.year + '-' + businessDay.month + '-' + businessDay.day;
|
return businessDay.year + '-' + businessDay.month + '-' + businessDay.day;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (!this.data) {
|
if (!changes.value || changes.value.isFirstChange()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.updateData();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData() {
|
||||||
this.areaSeries.setData(this.data);
|
this.areaSeries.setData(this.data);
|
||||||
this.lineSeries.setData(this.lineData);
|
this.lineSeries.setData(this.lineData);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createChart, CrosshairMode } from 'lightweight-charts';
|
import { createChart, CrosshairMode } from 'lightweight-charts';
|
||||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDestroy } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-lightweight-charts',
|
selector: 'app-lightweight-charts',
|
||||||
@ -7,10 +7,11 @@ import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, OnDes
|
|||||||
styleUrls: ['./lightweight-charts.component.scss'],
|
styleUrls: ['./lightweight-charts.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class LightweightChartsComponent implements OnChanges, OnDestroy {
|
export class LightweightChartsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() data: any;
|
@Input() data: any;
|
||||||
@Input() volumeData: any;
|
@Input() volumeData: any;
|
||||||
@Input() precision: number;
|
@Input() precision: number;
|
||||||
|
@Input() height = 500;
|
||||||
|
|
||||||
lineSeries: any;
|
lineSeries: any;
|
||||||
volumeSeries: any;
|
volumeSeries: any;
|
||||||
@ -18,10 +19,12 @@ export class LightweightChartsComponent implements OnChanges, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private element: ElementRef,
|
private element: ElementRef,
|
||||||
) {
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.chart = createChart(this.element.nativeElement, {
|
this.chart = createChart(this.element.nativeElement, {
|
||||||
width: 1110,
|
width: this.element.nativeElement.parentElement.offsetWidth,
|
||||||
height: 500,
|
height: this.height,
|
||||||
layout: {
|
layout: {
|
||||||
backgroundColor: '#000000',
|
backgroundColor: '#000000',
|
||||||
textColor: '#d1d4dc',
|
textColor: '#d1d4dc',
|
||||||
@ -52,12 +55,22 @@ export class LightweightChartsComponent implements OnChanges, OnDestroy {
|
|||||||
bottom: 0,
|
bottom: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (!this.data) {
|
if (!changes.value || changes.value.isFirstChange()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.updateData();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.chart.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData() {
|
||||||
this.lineSeries.setData(this.data);
|
this.lineSeries.setData(this.data);
|
||||||
this.volumeSeries.setData(this.volumeData);
|
this.volumeSeries.setData(this.volumeData);
|
||||||
|
|
||||||
@ -70,8 +83,4 @@ export class LightweightChartsComponent implements OnChanges, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.chart.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user