Wallet management/Settings improvements (#130)

* New Branch
Splits settings out into their own areas for performance reasons

* Formatting

* Adds cutout logo for navbar

* Better settings loading screen
Better cache handling

* Adds snackbar support
Adds error websocketmessage support

* pushing from one pc to another

* Rejoins settings after failure to be able to seperate them without big rewrites

* Wallet manipulation in settings

* Reformats wallet page
Updates menu to be 'wallets'

* Lists enabled exchanges in settings before you click for modal

* Fixes currency list issue

* Fixes object reference bug in exchange-grid.component.html

* password text
This commit is contained in:
Scott
2018-06-04 19:20:59 +10:00
committed by Adrian Gallagher
parent 0478c55b45
commit a23c145ccc
22 changed files with 382 additions and 242 deletions

View File

@@ -1,5 +1,4 @@
import { HomeComponent } from './pages/home/home.component';
import { SettingsComponent } from './pages/settings/settings.component';
import { AboutComponent } from './pages/about/about.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { WalletComponent } from './pages/wallet/wallet.component';
@@ -9,6 +8,9 @@ import { TradingComponent } from './pages/trading/trading.component';
import { ExchangeGridComponent } from './pages/exchange-grid/exchange-grid.component';
import { CurrencyListComponent } from './pages/currency-list/currency-list.component';
//Settings
import { SettingsComponent } from './pages/settings/settings.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
@@ -25,10 +27,6 @@ const routes: Routes = [
path:'dashboard',
component: DashboardComponent
},
{
path: 'settings',
component: SettingsComponent
},
{
path: 'wallet',
component: WalletComponent
@@ -57,8 +55,12 @@ const routes: Routes = [
{
path: 'help',
component: CurrencyListComponent
}
},
//Settings
{
path: 'settings',
component: SettingsComponent
},
];
@NgModule({

View File

@@ -9,7 +9,7 @@
</mat-list-item>
<mat-list-item routerLink="wallet" routerLinkActive="wallet-highlight">
<mat-icon>account_balance_wallet</mat-icon>&nbsp;
<h3>Wallet</h3>
<h3>Wallets</h3>
</mat-list-item>
<mat-list-item routerLink="trading" routerLinkActive="trading-highlight">
<mat-icon>swap_horiz</mat-icon>&nbsp;
@@ -58,11 +58,11 @@
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngIf="isConnected" matTooltip="Online!">
<mat-icon>network_wifi</mat-icon>&nbsp;
</mat-list-item>
<mat-list-item *ngIf="!isConnected" matTooltip="Offline">
<mat-icon>signal_wifi_off</mat-icon>&nbsp;
</mat-list-item>
<mat-icon>network_wifi</mat-icon>&nbsp;
</mat-list-item>
<mat-list-item *ngIf="!isConnected" matTooltip="Offline">
<mat-icon>signal_wifi_off</mat-icon>&nbsp;
</mat-list-item>
</mat-nav-list>
</mat-sidenav>

View File

@@ -1,5 +1,4 @@
.container {
height: 100vh;
min-height: 100%;
}

View File

@@ -27,16 +27,20 @@ import {
MatLineModule,
MatTooltipModule,
MatTabsModule,
MatSnackBarModule,
MatDialogModule,
} from '@angular/material';
//Pages
import { AppComponent } from './app.component';
import { HomeComponent } from './pages/home/home.component';
import { AboutComponent } from './pages/about/about.component';
import { SettingsComponent } from './pages/settings/settings.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { WalletComponent } from './pages/wallet/wallet.component';
import { DonateComponent } from './pages/donate/donate.component';
import { HelpComponent } from './pages/help/help.component';
import { SettingsComponent, EnabledCurrenciesDialogueComponent } from './pages/settings/settings.component';
//Shared
import { NavbarComponent } from './shared/navbar/navbar.component';
@@ -70,7 +74,6 @@ import { BuyFormComponent } from './shared/buy-form/buy-form.component';
import { ExchangeGridComponent } from './pages/exchange-grid/exchange-grid.component';
import { CurrencyListComponent } from './pages/currency-list/currency-list.component';
import { SellFormComponent } from './shared/sell-form/sell-form.component';
import { HelpComponent } from './pages/help/help.component';
@NgModule({
@@ -99,7 +102,11 @@ import { HelpComponent } from './pages/help/help.component';
SellFormComponent,
HelpComponent,
IterateMapPipe,
EnabledCurrenciesPipe
EnabledCurrenciesPipe,
EnabledCurrenciesDialogueComponent
],
entryComponents: [
EnabledCurrenciesDialogueComponent
],
imports: [
BrowserModule,
@@ -124,6 +131,8 @@ import { HelpComponent } from './pages/help/help.component';
MatLineModule,
MatTooltipModule,
MatTabsModule,
MatSnackBarModule,
MatDialogModule,
AmChartsModule,
],
providers: [

View File

@@ -1,3 +1,5 @@
<h2>Currency List</h2>
<h3>Select and monitor currencies of the same type</h3>
<mat-accordion>
<mat-expansion-panel *ngFor="let currency of exchangeCurrencies | iterateMap">
<mat-expansion-panel-header [ngClass]="{'selected' : selectedCurrency == currency.value}" >
@@ -13,7 +15,7 @@
</div>
<form class="form-content">
<mat-list>
<mat-list-item [ngClass]="{'selected' : selectedExchange == exchange}" *ngFor="let exchange of currency.key" >
<mat-list-item [ngClass]="{'selected' : (selectedExchange == exchange && selectedCurrency == currency.value)}" *ngFor="let exchange of currency.key" >
<h4 matLine>{{exchange}}</h4>
<button mat-button (click)="selectCurrency(exchange, currency.value)">SELECT</button>
</mat-list-item>

View File

@@ -58,7 +58,6 @@ export class CurrencyListComponent implements OnInit {
}
}
}
this.exchangeCurrencies.forEach((value: string[], key: string) => {});
}
private getSettings(): void {
@@ -69,5 +68,4 @@ export class CurrencyListComponent implements OnInit {
this.ws.messages.next(WebSocketMessage.GetSettingsMessage());
}
}
}

View File

@@ -1,11 +1,11 @@
<h2>Exchange List</h2>
<h3>Select and monitor currencies from the same exchange</h3>
<mat-accordion>
<mat-expansion-panel *ngFor="let exchange of exchangeCurrencies | iterateMap">
<mat-expansion-panel-header [ngClass]="{'selected' : selectedExchange == exchange.value}">
<mat-expansion-panel-header [ngClass]="{'selected' : selectedExchange == exchange.key}">
<mat-panel-title>
{{exchange.value}}
{{exchange.value}}
</mat-panel-title>
<mat-panel-description>
</mat-panel-description>
</mat-expansion-panel-header>
image and blurb
<div>
@@ -13,7 +13,7 @@
</div>
<form class="form-content">
<mat-list>
<mat-list-item [ngClass]="{'selected' : selectedCurrency == currency.ParsedName}" *ngFor="let currency of exchange.key | enabledCurrencies" >
<mat-list-item [ngClass]="{'selected' : selectedCurrency == currency.ParsedName && selectedExchange == exchange.value }" *ngFor="let currency of exchange.key | enabledCurrencies" >
<h4 matLine>{{currency.ParsedName}}</h4>
<button mat-button (click)="selectCurrency(exchange.value,currency.ParsedName)">SELECT</button>
</mat-list-item>

View File

@@ -1,19 +1,42 @@
<div class="loading-spinner" *ngIf="settings === null">
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
</div>
<div *ngIf="settings !== null">
<div *ngIf="settings !== null && ready">
<button matTooltip="Save" (click)="saveSettings()" mat-fab color="accent" class="mat-fab mat-fab-bottom-right"><mat-icon >save</mat-icon></button>
<mat-accordion>
<mat-expansion-panel *ngIf="settings.SMSGlobal != null">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
SMS Global
Credentials
</mat-panel-title>
<mat-panel-description>
SMS configuration and contact management
<mat-icon>phone_iphone</mat-icon>
User Settings
<mat-icon>person</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<form class="form-content">
<mat-form-field>
<input matInput name="username" [(ngModel)]="settings.Webserver.AdminUsername" placeholder="Username">
</mat-form-field>
<mat-form-field>
<input matInput name="password" type="password" [(ngModel)]="settings.Webserver.AdminPassword" placeholder="Password">
</mat-form-field>
<mat-form-field>
<input type="number" matInput name="connection-limit" [(ngModel)]="settings.Webserver.WebsocketConnectionLimit" placeholder="Websocket connection limit">
</mat-form-field>
<mat-checkbox name="allow-insecure-origin" [(ngModel)]="settings.Webserver.WebsocketAllowInsecureOrigin">Allow Insecure Websocket Origin</mat-checkbox>
</form>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
SMS Notifications
</mat-panel-title>
<mat-panel-description>
Notification Settings
<mat-icon>sms</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<form class="form-content">
@@ -23,9 +46,9 @@
<input matInput name="smsUsername" [(ngModel)]="settings.SMSGlobal.Username" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Username">
</mat-form-field>
<mat-form-field>
<input matInput name="smsPassword" [(ngModel)]="settings.SMSGlobal.Password" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Password">
<input matInput name="smsPassword" type="password" [(ngModel)]="settings.SMSGlobal.Password" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Password">
</mat-form-field>
<div *ngFor="let contact of settings.SMSGlobal?.Contacts">
<mat-checkbox name="contactEnabled" [disabled]="!settings?.SMSGlobal.Enabled" [(ngModel)]="contact.Enabled">Enabled</mat-checkbox>
<div mat-line></div>
@@ -37,9 +60,39 @@
</mat-form-field>
</div>
</form>
<mat-action-row>
<button mat-button>ADD</button>
</mat-action-row>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Wallets
</mat-panel-title>
<mat-panel-description>
Wallet Address Settings
<mat-icon>account_balance_wallet</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<div *ngFor="let wallet of settings.PortfolioAddresses?.Addresses">
<mat-form-field class="long">
<input matInput name="wallet-address" [(ngModel)]="wallet.Address" placeholder="Address" />
</mat-form-field>
<mat-form-field>
<input matInput name="wallet-cointype" [(ngModel)]="wallet.CoinType" placeholder="Coin Type" />
</mat-form-field>
<mat-form-field>
<input matInput name="wallet-description" [(ngModel)]="wallet.Description" placeholder="Description" />
</mat-form-field>
<button mat-button (click)="removeWallet(wallet)">REMOVE</button>
</div>
<mat-action-row>
<button mat-button (click)="addWallet()">ADD</button>
</mat-action-row>
</mat-expansion-panel>
<mat-expansion-panel *ngFor="let exchange of settings?.Exchanges">
<mat-expansion-panel-header>
<mat-panel-title>
@@ -47,7 +100,7 @@
</mat-panel-title>
<mat-panel-description>
Exchange Settings
<mat-icon>attach_money</mat-icon>
<mat-icon>poll</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<form class="form-content">
@@ -57,7 +110,7 @@
<input matInput name="apiKey" [(ngModel)]="exchange.APIKey" [disabled]="!exchange.Enabled" placeholder="API Key*">
</mat-form-field>
<mat-form-field>
<input matInput name="apiSecretKey" [(ngModel)]="exchange.APISecret" [disabled]="!exchange.Enabled" placeholder="API Secret Key*">
<input matInput name="apiSecretKey" type="password" [(ngModel)]="exchange.APISecret" [disabled]="!exchange.Enabled" placeholder="API Secret Key*">
</mat-form-field>
<mat-form-field>
<input matInput name="apiClientId" [(ngModel)]="exchange.ClientID" [disabled]="!exchange.Enabled" placeholder="API ClientID">
@@ -66,12 +119,10 @@
<h4>
Enabled currencies
</h4>
<div *ngFor="let currency of exchange.Pairs">
<p>{{currency.Name}}</p>
<mat-checkbox name="{{currency.Name}}2" [(ngModel)]="currency.Enabled"></mat-checkbox>
</div>
<p ><span *ngFor="let pair of exchange.Pairs | enabledCurrencies; let isLast=last">{{pair.Name}}{{isLast ? '' : ', '}}</span> </p>
<button mat-button [disabled]="!exchange.Enabled" (click)="openModal(exchange.Pairs)">CHANGE</button>
</form>
</mat-expansion-panel>
</mat-accordion>
</mat-accordion>
</div>

View File

@@ -9,4 +9,17 @@
.form-content {
margin: 20px;
}
.main {
margin-top: 20px;
}
.mat-card {
height: 100%;
width: 100%;
}
.long {
width:450px;
}

View File

@@ -1,7 +1,9 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
import { WebsocketResponseHandlerService } from './../../services/websocket-response-handler/websocket-response-handler.service';
import { WebSocketMessageType, WebSocketMessage } from './../../shared/classes/websocket';
import { Config, CurrencyPairRedux } from './../../shared/classes/config';
import { Config, CurrencyPairRedux, Wallet } from './../../shared/classes/config';
import { MatSnackBar, MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';
import { WalletComponent } from '../wallet/wallet.component';
@Component({
selector: 'app-settings',
@@ -9,36 +11,68 @@ import { Config, CurrencyPairRedux } from './../../shared/classes/config';
styleUrls: ['./settings.component.scss'],
})
export class SettingsComponent implements OnInit {
export class SettingsComponent {
public settings: Config = new Config();
private ws: WebsocketResponseHandlerService;
public ready: boolean = false;
private snackBar: MatSnackBar;
private dialogue;
constructor(private websocketHandler: WebsocketResponseHandlerService) {
constructor(private websocketHandler: WebsocketResponseHandlerService, snackBar: MatSnackBar, public dialog: MatDialog) {
this.ws = websocketHandler;
this.snackBar = snackBar;
}
ngOnInit() {
this.ws.shared.subscribe(msg => {
if (msg.event === WebSocketMessageType.GetConfig) {
this.settings.setConfig(msg.data);
this.ready = true;
} else if (msg.event === WebSocketMessageType.SaveConfig) {
// check if err is returned, then display some notification
if(msg.error !== null || msg.error.length > 0) {
this.snackBar.open(msg.error, '', {
duration: 4000,
});
}
if (msg.error === null || msg.error === '') {
this.settings.clearCache();
this.getSettings();
this.snackBar.open('Success', msg.data, {
duration: 1000,
});
}
}
});
this.getSettings();
}
public addWallet() :void {
this.settings.PortfolioAddresses.Addresses.push(<Wallet>{});
}
public removeWallet(wallet:any) {
this.settings.PortfolioAddresses.Addresses.splice(this.settings.PortfolioAddresses.Addresses.indexOf(wallet), 1);
}
public openModal(pairs: any): void {
let dialogRef = this.dialog.open(EnabledCurrenciesDialogueComponent, {
width: '20%',
height: '40%',
data: { pairs: pairs }
});
}
private getSettings(): void {
if(this.settings.isConfigCacheValid()) {
this.settings.setConfig(JSON.parse(window.localStorage['config']))
this.ready = true;
} else {
this.settings.clearCache();
this.ws.messages.next(WebSocketMessage.GetSettingsMessage());
}
}
private saveSettings(): void {
this.settings.fromReduxToArray()
var settingsSave = {
Event: 'SaveConfig',
@@ -48,3 +82,25 @@ export class SettingsComponent implements OnInit {
}
}
@Component({
selector: 'dialog-overview-example-dialog',
template: '<h4>Enabled Currencies</h4><div *ngFor="let currency of data.pairs"><mat-checkbox name="{{currency.Name}}2" [(ngModel)]="currency.Enabled">{{currency.Name}}</mat-checkbox></div><button mat-raised-button color="primary" (click)="close()">DONE</button>',
})
export class EnabledCurrenciesDialogueComponent {
constructor(
public dialogRef: MatDialogRef<EnabledCurrenciesDialogueComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
public close(): void {
this.dialogRef.close();
}
}

View File

@@ -1,114 +1,84 @@
<div class="loading-spinner" *ngIf="wallet === null">
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
</div>
<mat-accordion *ngIf="wallet !== null">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
Coin Totals
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<div *ngIf="wallet !== null">
<button matTooltip="Recalculate" (click)="setWallet()" mat-fab color="accent" class="mat-fab mat-fab-bottom-right">
<mat-icon>dialpad</mat-icon>
</button>
<mat-card>
<mat-card-content>
<h4>Coin Totals</h4>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.coin_totals">
<i [ngClass]="coin.icon"></i>
<h4 mat-line>{{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
<h4 mat-line><i [ngClass]="coin.icon"></i> {{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
</mat-list>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Online Summary
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<mat-divider></mat-divider>
<h4>Offline Coins</h4>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.coins_offline">
<h4 mat-line><i [ngClass]="coin.icon"></i> {{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
</mat-list-item>
</mat-list>
<mat-divider></mat-divider>
<h4>Offline Summary</h4>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.BTC">
<i class="cc btc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.LTC">
<i class="cc ltc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.ETH">
<i class="cc eth"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
</mat-list>
<mat-divider></mat-divider>
<h4>Online Coins</h4>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.coins_online">
<i [ngClass]="coin.icon"></i>
<h4 mat-line>{{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
</mat-list-item>
</mat-list>
<mat-divider></mat-divider>
<h4> Online Summary</h4>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.online_summary.BTC">
<i class="cc btc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
<i class="cc btc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngFor="let coin of wallet?.online_summary.LTC">
<i class="cc ltc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
<i class="cc ltc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngFor="let coin of wallet?.online_summary.ETH">
<i class="cc eth"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
<i class="cc eth"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Offline Summary
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.BTC">
<i class="cc btc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.LTC">
<i class="cc ltc"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item *ngFor="let coin of wallet?.offline_summary.ETH">
<i class="cc eth"></i>
<h4 mat-line>Address: {{coin.address}}</h4>
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Online Coins
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.coins_online">
<i [ngClass]="coin.icon"></i>
<h4 mat-line>{{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Offline Coins
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
<mat-list-item *ngFor="let coin of wallet?.coins_offline">
<i [ngClass]="coin.icon"></i>
<h4 mat-line>{{coin.coin}}</h4>
<h4 mat-line>{{coin.balance}}</h4>
</mat-list-item>
</mat-list>
</mat-expansion-panel>
</mat-accordion>
</mat-list>
</mat-card-content>
</mat-card>
</div>

View File

@@ -1,7 +1,3 @@
.wallet-card {
width: 80%;
margin: 10px auto;
}
.BTC {
color:orange;
@@ -11,4 +7,24 @@
}
.ETH {
color:darkslategrey;
}
}
// FAB
.mat-fab {
top: auto;
right: 30px;
bottom: 20px;
left: auto;
position: fixed;
z-index:9;
}
mat-grid-list {
height: 90vh;
}
mat-card {
width:90%;
}
mat-grid-tile {
box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.37);
}

View File

@@ -28,6 +28,7 @@ export class WalletComponent implements OnInit {
this.ws.shared.subscribe(msg => {
if (msg.event === WebSocketMessageType.GetPortfolio) {
this.wallet = <Wallet>msg.data;
console.log(msg.data);
this.attachIcon(this.wallet.coin_totals);
this.attachIcon(this.wallet.coins_offline);
this.attachIcon(this.wallet.coins_online);

View File

@@ -10,14 +10,18 @@ const WEBSOCKET_URL = 'ws://localhost:9050/ws';
export class WebsocketResponseHandlerService {
public messages: Subject<any>;
public shared: Observable<WebSocketMessage>;
public isConnected :boolean = false;
public isConnected: boolean = false;
private ws: WebsocketService;
constructor(@Optional() @SkipSelf() parentModule: WebsocketResponseHandlerService, wsService: WebsocketService) {
this.messages = <Subject<WebSocketMessage>>wsService
this.ws = wsService;
this.messages = <Subject<WebSocketMessage>>this.ws
.connect(WEBSOCKET_URL)
.map((response: MessageEvent): WebSocketMessage => {
this.isConnected = wsService.isConnected;
var interval = setInterval(() => {
this.isConnected = this.ws.isConnected;
}, 2000);
let websocketResponseMessage = JSON.parse(response.data);
var websocketResponseData = websocketResponseMessage.Data === undefined ? websocketResponseMessage.data : websocketResponseMessage.Data;
var websocketResponseEvent = websocketResponseMessage.Event === undefined ? websocketResponseMessage.event : websocketResponseMessage.Event;
@@ -27,10 +31,11 @@ export class WebsocketResponseHandlerService {
responseMessage.data = websocketResponseData;
responseMessage.exchange = websocketResponseMessage.exchange;
responseMessage.assetType = websocketResponseMessage.assetType;
responseMessage.error = websocketResponseMessage.error;
return responseMessage;
});
this.isConnected = wsService.isConnected;
this.isConnected = this.ws.isConnected;
this.shared = this.messages.share(); //multicast
}

View File

@@ -1 +1 @@
{{tickerCard.Exchange}} {{tickerCard.CurrencyPair}} Last: {{this.tickerCard.Last}}
{{tickerCard.Exchange}} {{tickerCard.CurrencyPair}} Last: {{tickerCard.Last}}

View File

@@ -1,86 +1,56 @@
import {Component, OnInit, OnDestroy }from '@angular/core';
import {WebsocketResponseHandlerService }from './../../services/websocket-response-handler/websocket-response-handler.service';
import {WebSocketMessageType }from './../../shared/classes/websocket';
import { Component, OnInit, OnDestroy} from '@angular/core';
import { WebsocketResponseHandlerService } from './../../services/websocket-response-handler/websocket-response-handler.service';
import { WebSocketMessageType } from './../../shared/classes/websocket';
import { ExchangeCurrency, TickerUpdate } from './../../shared/classes/ticker';
@Component( {
selector:'app-all-updates-ticker',
templateUrl:'./all-updates-ticker.component.html',
styleUrls:['./all-updates-ticker.component.scss'],
@Component({
selector: 'app-all-updates-ticker',
templateUrl: './all-updates-ticker.component.html',
styleUrls: ['./all-updates-ticker.component.scss'],
})
export class AllEnabledCurrencyTickersComponent implements OnInit {
allCurrencies:ExchangeCurrency[] = < ExchangeCurrency[] > []; ;
private ws:WebsocketResponseHandlerService;
tickerCard:TickerUpdate = new TickerUpdate();
showTicker:boolean = true;
message:string;
allCurrencies: ExchangeCurrency[] = < ExchangeCurrency[] > [];;
private ws: WebsocketResponseHandlerService;
tickerCard: TickerUpdate = new TickerUpdate();
constructor(private websocketHandler: WebsocketResponseHandlerService) {
this.tickerCard.Exchange = "Loading";
this.tickerCard.CurrencyPair = "...";
this.tickerCard.Last = -1;
this.ws = websocketHandler;
this.ws.shared.subscribe(msg => {
this.tickerCard.Exchange = "Loading";
this.tickerCard.CurrencyPair = "...";
this.tickerCard.Last = -1;
this.ws = websocketHandler;
this.ws.shared.subscribe(msg => {
if (msg.event === WebSocketMessageType.TickerUpdate) {
if (window.localStorage["selectedExchange"] !== undefined &&
window.localStorage["selectedCurrency"] !== undefined) {
this.tickerCard.Exchange = window.localStorage["selectedExchange"];
this.tickerCard.CurrencyPair = window.localStorage["selectedCurrency"];
if (msg.exchange == window.localStorage["selectedExchange"]) {
if (this.stripCurrencyCharacters(msg.data.CurrencyPair) == window.localStorage["selectedCurrency"]) {
this.updateTicker(msg)
if (window.localStorage["selectedExchange"] !== undefined &&
window.localStorage["selectedCurrency"] !== undefined) {
this.tickerCard.Exchange = window.localStorage["selectedExchange"];
this.tickerCard.CurrencyPair = window.localStorage["selectedCurrency"];
if (msg.exchange == this.tickerCard.Exchange &&
this.stripCurrencyCharacters(msg.data.CurrencyPair) == this.tickerCard.CurrencyPair) {
this.updateTicker(msg)
}
}
}else {
} else {
this.updateTicker(msg)
}
}
});
}
});
}
private updateTicker(msg:any):void {
var modal = < ExchangeCurrency > {};
modal.currencyPair = msg.data.CurrencyPair;
modal.exchangeName = msg.exchange;
var ticker = < TickerUpdate > msg.data;
this.tickerCard = ticker;
this.tickerCard.Exchange = msg.exchange;
this.message = this.tickerCard.Exchange + " " + this.tickerCard.CurrencyPair + " Last: " + this.tickerCard.Last;
private updateTicker(msg: any): void {
var ticker = <TickerUpdate> msg.data;
this.tickerCard = ticker;
this.tickerCard.Exchange = msg.exchange;
}
ngOnInit() {
}
private stripCurrencyCharacters(name:string):string {
name = name.replace('_', '');
name = name.replace('-', '');
name = name.replace(' ', '');
name = name.toLocaleUpperCase();
return name;
private stripCurrencyCharacters(name: string): string {
name = name.replace('_', '');
name = name.replace('-', '');
name = name.replace(' ', '');
name = name.toLocaleUpperCase();
return name;
}
}
export interface ExchangeCurrency {
currencyPair:string;
exchangeName:string;
}
export interface CurrencyPair {
delimiter:string;
first_currency:string;
second_currency:string;
}
export class TickerUpdate {
Pair:CurrencyPair;
CurrencyPair:string;
Last:number;
High:number;
Low:number;
Bid:number;
Ask:number;
Volume:number;
PriceATH:number;
Exchange:string;
}

View File

@@ -37,7 +37,25 @@
this.PortfolioAddresses = configData.PortfolioAddresses
this.SMSGlobal = configData.SMSGlobal
this.Webserver = configData.Webserver
this.fromArrayToRedux()
if(configData.Exchanges.length > 0
&& configData.Exchanges[0].Pairs
&& configData.Exchanges[0].Pairs.length > 0) {
console.log('Successfully retrieved well-formed pairs');
return;
}
this.fromArrayToRedux();
//Rewrite to cache on parsing to redux array
this.saveToCache();
}
public saveToCache() : void {
window.localStorage['config'] = JSON.stringify(this);
window.localStorage['configDate'] = new Date().toString();
}
public clearCache() : void {
window.localStorage['config'] = null;
window.localStorage['configDate'] = null;
}
public fromArrayToRedux() : void {
@@ -57,8 +75,7 @@
this.Exchanges[i].Pairs.push(currencyPair);
}
}
window.localStorage['config'] = JSON.stringify(this);
window.localStorage['configDate'] = new Date().toString();
}
public parseSettings() : void {
@@ -82,23 +99,17 @@
if (enabled.indexOf(this.Exchanges[i].Pairs[j].Name) == -1) {
// Step 3 if its not in the enabled list, add it
enabled.push(this.Exchanges[i].Pairs[j].Name);
} else {
}
}
} else {
if (enabled.indexOf(this.Exchanges[i].Pairs[j].Name) > -1) {
enabled.splice(enabled.indexOf(this.Exchanges[i].Pairs[j].Name), 1);
} else {
}
}
}
//Step 4 JSONifiy the enabled list and set it to the this.settings.Exchanges[i].EnabledPairs
this.Exchanges[i].EnabledPairs = enabled.join();
}
}
}
export class CurrencyPairRedux {
@@ -113,7 +124,15 @@ export class CurrencyPairRedux {
}
export interface PortfolioAddresses {
Addresses?: any;
Addresses?: Wallet[];
}
export interface Wallet {
Address:string;
CoinType:string;
Balance:number;
Description:string
}
export interface Contact {

View File

@@ -0,0 +1,24 @@
export interface ExchangeCurrency {
currencyPair: string;
exchangeName: string;
}
export interface CurrencyPair {
delimiter: string;
first_currency: string;
second_currency: string;
}
export class TickerUpdate {
Pair: CurrencyPair;
CurrencyPair: string;
Last: number;
High: number;
Low: number;
Bid: number;
Ask: number;
Volume: number;
PriceATH: number;
Exchange: string;
}

View File

@@ -3,6 +3,7 @@ export class WebSocketMessage {
public data: any;
public exchange: string;
public assetType: string;
public error: string;
public static CreateAuthenticationMessage(): WebSocketMessage {
var response = new WebSocketMessage();

View File

@@ -2,8 +2,8 @@
<nav class="docs-navbar">
<mat-toolbar color="primary">
<a (click)="sidebarService.toggle()" class="material-icons">&#xE5D2;</a>
<a mat-button class="docs-button" routerLink="/" aria-label="Angular Material">
<span>GoCryptoTrader</span>
<a mat-button class="docs-button" style="width:1rem;" routerLink="/" aria-label="Angular Material">
<span ><img style="width:100%; vertical-align:middle;" src="assets/images/gctlogo-small-cutoutt.png" /></span>
</a>
<app-selected-currency></app-selected-currency>
<div class="flex-spacer"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -150,8 +150,12 @@ body {
.mat-drawer-content {
height:92% !important;
height:84% !important;
margin-top: 4rem !important;
padding-left:5px;
padding-right:5px;
padding-bottom:2rem;
padding-top:5px;
}