Reorganisation + Electron fixes (#118)
* Updates package versions
* Updating versions with RCs
* Updated landing page with stock images
* Begins refactoring of websocket
Adds Help component
* Dark theme for charts
* event Event
* Adds cryptocurrency font
Updates wallet to use it
* Rejigs the location of assets
* rxjs update
wallet font correction
* renaming websocket service
* Refactors websocket use
Destroys and subscribes appropriately
Also handles when websocket is not available with intervals
* Fixes issues with electron by rebasing with Maxime GRIS electron builder
* License change
* Readme update
* Parses available and enabled currencies to create an object {Name:X, Enabled:Y}
* Adds methods to convert from string arrays to objects with enabled status for all currencies
* Uses a localstorage cache for config for 15 minutes
* Moves handling of settings to config object
* Fix typescripting
* Fixes issue with saving and loading
* Slows websocket repeats
Adds cool new dictionary style item and iterable.
Updatres currency-list.component to list all enabled currencies and exchanges (still doesn't do anything)
* Updates selected-currency.component to display all currencies ticker updates if there is no selected currency
Will display only selected currency results once it is set
Sets a new property to ensure all currency names are consistent for currency list plans
* Fixes issue where only one component could listen to the websocket at once
Allows you to select a currency in exchange grid mode
* Adds selected currency support to buy & sell components
Updates selected currency ticker to update on change faster
* Adds Online status indicator
* Removal of console.logs for working features
* Allows currency-list.component to aggregate on currency and list exchanges that match it
* Highlights selected currency in currency-list.component
Allows you to select a currency
@@ -53,6 +53,10 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'currency-list',
|
||||
component: CurrencyListComponent
|
||||
},
|
||||
{
|
||||
path: 'help',
|
||||
component: CurrencyListComponent
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@@ -1,58 +1,70 @@
|
||||
<app-navbar class="navbar mat-elevation-z6"></app-navbar>
|
||||
|
||||
<mat-sidenav-container class="container ">
|
||||
<mat-sidenav #sidenav mode="side" class="sidebar" opened="true">
|
||||
<mat-nav-list>
|
||||
<mat-list-item routerLink="dashboard" routerLinkActive="dashboard-highlight">
|
||||
<mat-icon>view_quilt</mat-icon>
|
||||
<h3>Dashboard</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="wallet" routerLinkActive="wallet-highlight">
|
||||
<mat-icon>account_balance_wallet</mat-icon>
|
||||
<h3>Wallet</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="trading" routerLinkActive="trading-highlight">
|
||||
<mat-icon>swap_horiz</mat-icon>
|
||||
<h3>Trading</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="history" routerLinkActive="history-highlight">
|
||||
<mat-icon>history</mat-icon>
|
||||
<h3>History</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="settings" routerLinkActive="settings-highlight">
|
||||
<mat-icon>settings</mat-icon>
|
||||
<h3>Settings</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="donate" routerLinkActive="donate-highlight">
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
<h3>Donate</h3>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item>
|
||||
<mat-icon>grade</mat-icon>
|
||||
<a href="https://github.com/thrasher-/gocryptotrader" target="_blank">
|
||||
<h3>GitHub</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>view_agenda</mat-icon>
|
||||
<a href="https://trello.com/b/ZAhMhpOy/gocryptotrader" target="_blank">
|
||||
<h3>Trello</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>apps</mat-icon>
|
||||
<a href="https://gocryptotrader.herokuapp.com/" target="_blank">
|
||||
<h3>Slack</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>bug_report</mat-icon>
|
||||
<a href="https://github.com/thrasher-/gocryptotrader/issues/new" target="_blank">
|
||||
<h3>Report a bug</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
<router-outlet class="main"></router-outlet>
|
||||
</mat-sidenav-container>
|
||||
<mat-sidenav #sidenav mode="side" class="sidebar" opened="true">
|
||||
<mat-nav-list>
|
||||
<mat-list-item routerLink="dashboard" routerLinkActive="dashboard-highlight">
|
||||
<mat-icon>view_quilt</mat-icon>
|
||||
<h3>Dashboard</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="wallet" routerLinkActive="wallet-highlight">
|
||||
<mat-icon>account_balance_wallet</mat-icon>
|
||||
<h3>Wallet</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="trading" routerLinkActive="trading-highlight">
|
||||
<mat-icon>swap_horiz</mat-icon>
|
||||
<h3>Trading</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="history" routerLinkActive="history-highlight">
|
||||
<mat-icon>history</mat-icon>
|
||||
<h3>History</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="settings" routerLinkActive="settings-highlight">
|
||||
<mat-icon>settings</mat-icon>
|
||||
<h3>Settings</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="help_outline" routerLinkActive="help-highlight">
|
||||
<mat-icon>help</mat-icon>
|
||||
<h3>Help</h3>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="donate" routerLinkActive="donate-highlight">
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
<h3>Donate</h3>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item>
|
||||
<mat-icon>grade</mat-icon>
|
||||
<a href="https://github.com/thrasher-/gocryptotrader" target="_blank">
|
||||
<h3>GitHub</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>view_agenda</mat-icon>
|
||||
<a href="https://trello.com/b/ZAhMhpOy/gocryptotrader" target="_blank">
|
||||
<h3>Trello</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>apps</mat-icon>
|
||||
<a href="https://gocryptotrader.herokuapp.com/" target="_blank">
|
||||
<h3>Slack</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<mat-icon>bug_report</mat-icon>
|
||||
<a href="https://github.com/thrasher-/gocryptotrader/issues/new" target="_blank">
|
||||
<h3>Report a bug</h3>
|
||||
</a>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-list-item *ngIf="isConnected" matTooltip="Online!">
|
||||
<mat-icon>network_wifi</mat-icon>
|
||||
</mat-list-item>
|
||||
<mat-list-item *ngIf="!isConnected" matTooltip="Offline">
|
||||
<mat-icon>signal_wifi_off</mat-icon>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
|
||||
</mat-sidenav>
|
||||
<router-outlet class="main"></router-outlet>
|
||||
</mat-sidenav-container>
|
||||
@@ -41,6 +41,10 @@
|
||||
color: blueviolet !important;
|
||||
}
|
||||
|
||||
.help-highlight {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.settings-highlight {
|
||||
color: magenta !important;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ElectronService } from './providers/electron.service';
|
||||
import { MatSidenav } from '@angular/material';
|
||||
import { SidebarService } from './services/sidebar/sidebar.service';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import {WebsocketResponseHandlerService }from './services/websocket-response-handler/websocket-response-handler.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -11,10 +12,12 @@ import { Router, NavigationEnd } from '@angular/router';
|
||||
})
|
||||
export class AppComponent {
|
||||
sidebarService: SidebarService
|
||||
public currentUrl:string;
|
||||
public currentUrl: string;
|
||||
@ViewChild('sidenav') public sidenav: MatSidenav;
|
||||
private ws : WebsocketResponseHandlerService;
|
||||
public isConnected :boolean = false;
|
||||
|
||||
constructor(public electronService: ElectronService,something: SidebarService, private router:Router) {
|
||||
constructor(public electronService: ElectronService, sidebarService: SidebarService, private router: Router, private websocketHandler: WebsocketResponseHandlerService) {
|
||||
|
||||
if (electronService.isElectron()) {
|
||||
console.log('Mode electron');
|
||||
@@ -26,18 +29,26 @@ export class AppComponent {
|
||||
console.log('Mode web');
|
||||
}
|
||||
|
||||
this.sidebarService = something;
|
||||
|
||||
router.events.subscribe(event => {
|
||||
this.isConnected = this.websocketHandler.isConnected;
|
||||
this.sidebarService = sidebarService;
|
||||
router.events.subscribe(event => {
|
||||
|
||||
if (event instanceof NavigationEnd ) {
|
||||
console.log("current url",event.url); // event.url has current url
|
||||
this.currentUrl = event.url;
|
||||
}
|
||||
});
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.isConnected = this.websocketHandler.isConnected;
|
||||
console.log("current url", event.url); // event.url has current url
|
||||
this.currentUrl = event.url;
|
||||
}
|
||||
});
|
||||
var interval = setInterval(() => {
|
||||
this.isConnected = this.websocketHandler.isConnected;
|
||||
}, 2000);
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.sidebarService.setSidenav(this.sidenav);
|
||||
}
|
||||
//This will be replaced with a log in prompt which will then add the credentials to session storage
|
||||
window.sessionStorage["username"] = "admin";
|
||||
window.sessionStorage["password"] = "e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a";
|
||||
}
|
||||
}
|
||||
|
||||
23
web/src/app/app.config.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { CONF_LOCAL } from '../environments/environment.local';
|
||||
import { CONF_DEV } from '../environments/environment.dev';
|
||||
import { CONF_PROD } from '../environments/environment.prod';
|
||||
|
||||
const ENV = 'local';
|
||||
|
||||
const LOCAL: String = 'local';
|
||||
const DEV: String = 'dev';
|
||||
const PROD: String = 'prod';
|
||||
|
||||
let conf: any;
|
||||
|
||||
console.log('Env', ENV);
|
||||
|
||||
if (ENV === PROD) {
|
||||
conf = CONF_PROD;
|
||||
} else if (ENV === DEV) {
|
||||
conf = CONF_DEV;
|
||||
} else {
|
||||
conf = CONF_LOCAL;
|
||||
}
|
||||
|
||||
export const AppConfig = Object.assign({}, conf);
|
||||
@@ -42,9 +42,10 @@ import { DonateComponent } from './pages/donate/donate.component';
|
||||
import { NavbarComponent } from './shared/navbar/navbar.component';
|
||||
import { AllEnabledCurrencyTickersComponent } from './shared/all-updates-ticker/all-updates-ticker.component';
|
||||
import { ThemePickerComponent } from './shared/theme-picker/theme-picker';
|
||||
import {IterateMapPipe, EnabledCurrenciesPipe} from './shared/classes/pipes';
|
||||
//services
|
||||
import { WebsocketService } from './services/websocket/websocket.service';
|
||||
import { WebsocketHandlerService } from './services/websocket-handler/websocket-handler.service';
|
||||
import { WebsocketResponseHandlerService } from './services/websocket-response-handler/websocket-response-handler.service';
|
||||
import { SidebarService } from './services/sidebar/sidebar.service';
|
||||
import { ElectronService } from './providers/electron.service';
|
||||
import { StyleManagerService } from './services/style-manager/style-manager.service';
|
||||
@@ -69,6 +70,7 @@ 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({
|
||||
@@ -95,6 +97,9 @@ import { SellFormComponent } from './shared/sell-form/sell-form.component';
|
||||
ExchangeGridComponent,
|
||||
CurrencyListComponent,
|
||||
SellFormComponent,
|
||||
HelpComponent,
|
||||
IterateMapPipe,
|
||||
EnabledCurrenciesPipe
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@@ -124,7 +129,7 @@ import { SellFormComponent } from './shared/sell-form/sell-form.component';
|
||||
providers: [
|
||||
ElectronService,
|
||||
WebsocketService,
|
||||
WebsocketHandlerService,
|
||||
WebsocketResponseHandlerService,
|
||||
SidebarService,
|
||||
StyleManagerService,
|
||||
ThemeStorageService,
|
||||
|
||||
@@ -1,35 +1,23 @@
|
||||
<mat-list>
|
||||
<h3 matSubheader>Poloniex</h3>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>BTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>LTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>ETH_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
<h3 matSubheader>Kraken</h3>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>BTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>LTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>ETH_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel *ngFor="let currency of exchangeCurrencies | iterateMap">
|
||||
<mat-expansion-panel-header [ngClass]="{'selected' : selectedCurrency == currency.value}" >
|
||||
<mat-panel-title>
|
||||
{{currency.value}}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
image and blurb
|
||||
<div>
|
||||
<i>Only displaying enabled currencies</i>
|
||||
</div>
|
||||
<form class="form-content">
|
||||
<mat-list>
|
||||
<mat-list-item [ngClass]="{'selected' : selectedExchange == exchange}" *ngFor="let exchange of currency.key" >
|
||||
<h4 matLine>{{exchange}}</h4>
|
||||
<button mat-button (click)="selectCurrency(exchange, currency.value)">SELECT</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</form>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
@@ -6,4 +6,8 @@
|
||||
}
|
||||
.ETH {
|
||||
color:darkslategrey;
|
||||
}
|
||||
|
||||
.selected, .selected:hover, .selected:focus, .selected::selection {
|
||||
background: rgba(100,250,100,0.2);
|
||||
}
|
||||
@@ -1,15 +1,73 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, Pipe, PipeTransform} 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 { EnabledCurrenciesPipe, IterateMapPipe} from './../../shared/classes/pipes';
|
||||
|
||||
@Component({
|
||||
selector: 'app-currency-list',
|
||||
templateUrl: './currency-list.component.html',
|
||||
styleUrls: ['./currency-list.component.scss']
|
||||
styleUrls: ['./currency-list.component.scss'],
|
||||
})
|
||||
export class CurrencyListComponent implements OnInit {
|
||||
public settings: Config = new Config();
|
||||
private ws: WebsocketResponseHandlerService;
|
||||
public selectedCurrency :string;
|
||||
public selectedExchange :string;
|
||||
public exchangeCurrencies: Map <string, string[] > = new Map < string, string[] > ();
|
||||
|
||||
constructor() { }
|
||||
|
||||
constructor(private websocketHandler: WebsocketResponseHandlerService) {
|
||||
this.selectedExchange = window.localStorage["selectedExchange"];
|
||||
this.selectedCurrency = window.localStorage["selectedCurrency"];
|
||||
this.ws = websocketHandler;
|
||||
this.ws.shared.subscribe(msg => {
|
||||
if (msg.event === WebSocketMessageType.GetConfig) {
|
||||
this.settings.setConfig(msg.data);
|
||||
this.getExchangeCurrencies();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
public selectCurrency(exchange:string,currency:string) {
|
||||
window.localStorage["selectedExchange"] = exchange;
|
||||
window.localStorage["selectedCurrency"] = currency;
|
||||
this.selectedExchange = window.localStorage["selectedExchange"];
|
||||
this.selectedCurrency = window.localStorage["selectedCurrency"];
|
||||
}
|
||||
|
||||
public getExchangeCurrencies(): void {
|
||||
for (var i = 0; i < this.settings.Exchanges.length; i++) {
|
||||
if (this.settings.Exchanges[i].Enabled === true) {
|
||||
for (var j = 0; j < this.settings.Exchanges[i].Pairs.length; j++) {
|
||||
if(this.settings.Exchanges[i].Pairs[j].Enabled) {
|
||||
if(this.exchangeCurrencies.has(this.settings.Exchanges[i].Pairs[j].ParsedName)) {
|
||||
var array = this.exchangeCurrencies.get(this.settings.Exchanges[i].Pairs[j].ParsedName);
|
||||
array.push(this.settings.Exchanges[i].Name);
|
||||
this.exchangeCurrencies.set(this.settings.Exchanges[i].Pairs[j].ParsedName, array);
|
||||
} else {
|
||||
var exchangeArray = new Array<string>();
|
||||
exchangeArray.push(this.settings.Exchanges[i].Name);
|
||||
this.exchangeCurrencies.set(this.settings.Exchanges[i].Pairs[j].ParsedName, exchangeArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.exchangeCurrencies.forEach((value: string[], key: string) => {});
|
||||
}
|
||||
|
||||
private getSettings(): void {
|
||||
if (this.settings.isConfigCacheValid()) {
|
||||
this.settings.setConfig(JSON.parse(window.localStorage['config']))
|
||||
this.getExchangeCurrencies();
|
||||
} else {
|
||||
this.ws.messages.next(WebSocketMessage.GetSettingsMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ mat-card-footer button {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
right: 5rem;
|
||||
bottom: 3rem;
|
||||
bottom: 5rem;
|
||||
left: auto;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
@@ -49,7 +49,7 @@ mat-card-footer button {
|
||||
|
||||
.buy-sell-card {
|
||||
width: 20rem;
|
||||
height: 22rem;
|
||||
height: 24rem;
|
||||
margin-left: auto;
|
||||
margin-right: 1rem;
|
||||
z-index: 3;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<mat-card class="full-card">
|
||||
<mat-card class="full-card">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Donations</mat-card-title>
|
||||
<mat-card-subtitle>We give our thanks</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<img class="heart" src="/assets/early-dumb-donate.png"/>
|
||||
<p>If this framework helped you in any way, or you would like to support the developers working on it, please donate</p>
|
||||
<mat-list>
|
||||
<mat-list-item >
|
||||
<mat-icon mat-list-icon class="BTC">attach_money</mat-icon>
|
||||
<h4 mat-line>Address:</h4>
|
||||
<h4 mat-line>1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<img class="heart" src="./assets/images/donate.png" />
|
||||
<p>If this framework helped you in any way, or you would like to support the developers working on it, please donate</p>
|
||||
<mat-list>
|
||||
<mat-list-item>
|
||||
<mat-icon mat-list-icon class="BTC">attach_money</mat-icon>
|
||||
<h4 mat-line>Address:</h4>
|
||||
<h4 mat-line>1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,59 +1,22 @@
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel >
|
||||
<mat-expansion-panel-header>
|
||||
<mat-expansion-panel *ngFor="let exchange of exchangeCurrencies | iterateMap">
|
||||
<mat-expansion-panel-header [ngClass]="{'selected' : selectedExchange == exchange.value}">
|
||||
<mat-panel-title>
|
||||
Poloniex
|
||||
{{exchange.value}}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
image and blurb
|
||||
<div>
|
||||
<i>Only displaying enabled currencies</i>
|
||||
</div>
|
||||
<form class="form-content">
|
||||
<mat-list>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>BTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
<mat-list-item [ngClass]="{'selected' : selectedCurrency == currency.ParsedName}" *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>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>LTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>ETH_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</form>
|
||||
</mat-expansion-panel><mat-expansion-panel >
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Kraken
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
image and blurb
|
||||
<form class="form-content">
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>BTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>LTC_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item >
|
||||
<mat-icon matListIcon>attach_money</mat-icon>
|
||||
<h4 matLine>ETH_USD</h4>
|
||||
<button mat-button>SELECT</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</form>
|
||||
</mat-expansion-panel>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.selected, .selected:hover, .selected:focus, .selected::selection {
|
||||
background: rgba(100,250,100,0.2);
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, Pipe, PipeTransform} 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 { EnabledCurrenciesPipe, IterateMapPipe} from './../../shared/classes/pipes';
|
||||
|
||||
@Component({
|
||||
selector: 'app-exchange-grid',
|
||||
@@ -6,10 +10,54 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./exchange-grid.component.scss']
|
||||
})
|
||||
export class ExchangeGridComponent implements OnInit {
|
||||
public settings: Config = new Config();
|
||||
private ws: WebsocketResponseHandlerService;
|
||||
public selectedCurrency :string;
|
||||
public selectedExchange :string;
|
||||
public exchangeCurrencies: Map < string, CurrencyPairRedux[] > = new Map < string, CurrencyPairRedux[] > ();
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
constructor(private websocketHandler: WebsocketResponseHandlerService) {
|
||||
this.selectedExchange = window.localStorage["selectedExchange"];
|
||||
this.selectedCurrency = window.localStorage["selectedCurrency"];
|
||||
this.ws = websocketHandler;
|
||||
this.ws.shared.subscribe(msg => {
|
||||
if (msg.event === WebSocketMessageType.GetConfig) {
|
||||
this.settings.setConfig(msg.data);
|
||||
this.getExchangeCurrencies();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
|
||||
public selectCurrency(exchange:string,currency:string) {
|
||||
window.localStorage["selectedExchange"] = exchange;
|
||||
window.localStorage["selectedCurrency"] = currency;
|
||||
this.selectedExchange = window.localStorage["selectedExchange"];
|
||||
this.selectedCurrency = window.localStorage["selectedCurrency"];
|
||||
}
|
||||
|
||||
public getExchangeCurrencies(): void {
|
||||
for (var i = 0; i < this.settings.Exchanges.length; i++) {
|
||||
if (this.settings.Exchanges[i].Enabled === true) {
|
||||
this.exchangeCurrencies.set(this.settings.Exchanges[i].Name, this.settings.Exchanges[i].Pairs)
|
||||
}
|
||||
}
|
||||
this.exchangeCurrencies.forEach((value: CurrencyPairRedux[], key: string) => {});
|
||||
}
|
||||
|
||||
private getSettings(): void {
|
||||
if (this.settings.isConfigCacheValid()) {
|
||||
this.settings.setConfig(JSON.parse(window.localStorage['config']))
|
||||
this.getExchangeCurrencies();
|
||||
} else {
|
||||
this.ws.messages.next(WebSocketMessage.GetSettingsMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
3
web/src/app/pages/help/help.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<p>
|
||||
help works!
|
||||
</p>
|
||||
0
web/src/app/pages/help/help.component.scss
Normal file
25
web/src/app/pages/help/help.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HelpComponent } from './help.component';
|
||||
|
||||
describe('HelpComponent', () => {
|
||||
let component: HelpComponent;
|
||||
let fixture: ComponentFixture<HelpComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HelpComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HelpComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/help/help.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-help',
|
||||
templateUrl: './help.component.html',
|
||||
styleUrls: ['./help.component.scss']
|
||||
})
|
||||
export class HelpComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,56 @@
|
||||
<div class="docs-homepage-promo">
|
||||
<h2 class="mat-h1">Welcome to GoCryptoTrader</h2>
|
||||
|
||||
<h1 class="mat-h1">Welcome to GoCryptoTrader</h1>
|
||||
<p>GoCryptoTrader is a multi-currency, multi-exchange trader for cryptocurrencies</p>
|
||||
<p>It is under active development and you can see its development progress by clicking the trello button to the left</p>
|
||||
<p>If you like what you see, consider clicking the donation button to the left</p>
|
||||
<div class="docs-homepage-row">
|
||||
<div class="docs-homepage-promo-img">
|
||||
<img src="./assets/exchanges.jpg" />
|
||||
</div>
|
||||
<div class="docs-homepage-promo-desc">
|
||||
<h2>Multi-currency, multi-exchange</h2>
|
||||
<p>With support for over 25 of the top cryptocurrency exchanges</p>
|
||||
<div class="docs-homepage-bottom-start">
|
||||
<a mat-raised-button class="docs-button" routerLink="dashboard">Get started</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="docs-homepage-row docs-homepage-reverse-row">
|
||||
<div class="docs-homepage-promo-img">
|
||||
<img src="./assets/loop.png" />
|
||||
</div>
|
||||
|
||||
<div class="docs-homepage-promo-desc">
|
||||
<h2>High speed, low drag</h2>
|
||||
<p>Constant checking of all enabled exchanges* to get you the most up to date information</p>
|
||||
<div class="docs-homepage-bottom-start">
|
||||
<a mat-raised-button class="docs-button" routerLink="dashboard">Get started</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="docs-homepage-row">
|
||||
<div class="docs-homepage-promo-img">
|
||||
<img src="./assets/centralised.png" />
|
||||
</div>
|
||||
<div class="docs-homepage-promo-desc">
|
||||
<h2>Centralised management</h2>
|
||||
<p>Add and manage all your wallets from one application</p>
|
||||
<div class="docs-homepage-bottom-start">
|
||||
<a mat-raised-button class="docs-button" routerLink="dashboard">Get started</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="docs-homepage-row docs-homepage-reverse-row">
|
||||
<div class="docs-homepage-promo-img">
|
||||
<img src="./assets/material.png" />
|
||||
</div>
|
||||
<div class="docs-homepage-promo-desc">
|
||||
<h2>Optimized for Angular</h2>
|
||||
<p>The latest tech with Material design lets you focus on what's important</p>
|
||||
<div class="docs-homepage-bottom-start">
|
||||
<a mat-raised-button class="docs-button" routerLink="dashboard">Get started</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="docs-homepage-bottom-start">
|
||||
<a mat-raised-button class="docs-button" routerLink="dashboard">Get started</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +1,71 @@
|
||||
.example-card {
|
||||
width: 400px;
|
||||
}
|
||||
.docs-homepage-promo {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.docs-homepage-promo h2 {
|
||||
font-size: 25px;
|
||||
font-weight: 400;
|
||||
margin: 0 0 16px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.docs-homepage-promo p {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 28px;
|
||||
margin: 0 0 24px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.docs-homepage-promo-img img {
|
||||
max-width: 90%;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.docs-homepage-promo-desc {
|
||||
line-height: 2;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.docs-homepage-promo-desc,
|
||||
.docs-homepage-promo-img {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.docs-homepage-promo-img {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.docs-homepage-row {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
width: 50%;
|
||||
margin: 60px 0;
|
||||
}
|
||||
|
||||
.docs-homepage-reverse-row {
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: reverse;
|
||||
-ms-flex-direction: row-reverse;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel *ngIf="settings.SMSGlobal != null">
|
||||
<mat-expansion-panel-header >
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
SMS Global
|
||||
</mat-panel-title>
|
||||
@@ -15,7 +15,7 @@
|
||||
SMS configuration and contact management
|
||||
<mat-icon>phone_iphone</mat-icon>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
</mat-expansion-panel-header>
|
||||
<form class="form-content">
|
||||
<mat-checkbox name="smsEnabled" [(ngModel)]="settings.SMSGlobal.Enabled">Enabled</mat-checkbox>
|
||||
<div mat-line></div>
|
||||
@@ -53,25 +53,23 @@
|
||||
<form class="form-content">
|
||||
<mat-checkbox name="exchangeEnabled" [(ngModel)]="exchange.Enabled">Enabled</mat-checkbox>
|
||||
<div mat-line></div>
|
||||
<mat-form-field>
|
||||
<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*">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="apiClientId" [(ngModel)]="exchange.ClientID" [disabled]="!exchange.Enabled" placeholder="API ClientID">
|
||||
</mat-form-field>
|
||||
<div mat-line></div>
|
||||
<mat-panel-description>
|
||||
Enabled Currency pairs {{enabledCurrencies.selectedOptions.selected.length}} - Managed via config temporarily
|
||||
</mat-panel-description>
|
||||
<div mat-line></div>
|
||||
<mat-selection-list #enabledCurrencies>
|
||||
<mat-list-option [disabled]="!exchange.Enabled || true" *ngFor="let currency of exchange.AvailablePairs.split(',')">
|
||||
{{currency}}
|
||||
</mat-list-option>
|
||||
</mat-selection-list>
|
||||
<mat-form-field>
|
||||
<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*">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="apiClientId" [(ngModel)]="exchange.ClientID" [disabled]="!exchange.Enabled" placeholder="API ClientID">
|
||||
</mat-form-field>
|
||||
<div mat-line></div>
|
||||
<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>
|
||||
</form>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
||||
@@ -1,145 +1,50 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketHandlerService } from './../../services/websocket-handler/websocket-handler.service';
|
||||
import { Component, OnInit, OnDestroy } 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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss']
|
||||
styleUrls: ['./settings.component.scss'],
|
||||
})
|
||||
|
||||
|
||||
export class SettingsComponent implements OnInit {
|
||||
public settings: Config = null;
|
||||
private ws: WebsocketHandlerService;
|
||||
private failCount = 0;
|
||||
private timer: any;
|
||||
public settings: Config = new Config();
|
||||
private ws: WebsocketResponseHandlerService;
|
||||
|
||||
private getSettingsMessage = {
|
||||
Event: 'GetConfig',
|
||||
data: null,
|
||||
};
|
||||
|
||||
constructor(private websocketHandler: WebsocketHandlerService) {
|
||||
constructor(private websocketHandler: WebsocketResponseHandlerService) {
|
||||
this.ws = websocketHandler;
|
||||
this.ws.messages.subscribe(msg => {
|
||||
|
||||
if (msg.Event === 'GetConfig') {
|
||||
this.settings = <Config>msg.data;
|
||||
} else if (msg.Event === 'SaveConfig') {
|
||||
// something!
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
this.ws.shared.subscribe(msg => {
|
||||
if (msg.event === WebSocketMessageType.GetConfig) {
|
||||
this.settings.setConfig(msg.data);
|
||||
} else if (msg.event === WebSocketMessageType.SaveConfig) {
|
||||
// check if err is returned, then display some notification
|
||||
}
|
||||
});
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
|
||||
private getSettings(): void {
|
||||
this.ws.messages.next(this.getSettingsMessage);
|
||||
this.resendMessageIfPageRefreshed();
|
||||
if(this.settings.isConfigCacheValid()) {
|
||||
this.settings.setConfig(JSON.parse(window.localStorage['config']))
|
||||
} else {
|
||||
this.ws.messages.next(WebSocketMessage.GetSettingsMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private saveSettings(): void {
|
||||
//Send the message
|
||||
|
||||
this.settings.fromReduxToArray()
|
||||
var settingsSave = {
|
||||
Event: 'SaveConfig',
|
||||
data: this.settings,
|
||||
}
|
||||
this.ws.messages.next(settingsSave);
|
||||
}
|
||||
|
||||
//there has to be a better way
|
||||
private resendMessageIfPageRefreshed(): void {
|
||||
if (this.failCount <= 10) {
|
||||
setTimeout(() => {
|
||||
if (this.settings === null) {
|
||||
//console.log(this.failCount);
|
||||
//console.log('Settings hasnt been set. Trying again');
|
||||
this.failCount++;
|
||||
this.getSettings();
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
// something has gone wrong
|
||||
console.log('Could not load settings. Check if GocryptoTrader server is running, otherwise open a ticket');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export interface CurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Delimiter: string;
|
||||
}
|
||||
|
||||
export interface PortfolioAddresses {
|
||||
Addresses?: any;
|
||||
}
|
||||
|
||||
export interface Contact {
|
||||
Name: string;
|
||||
Number: string;
|
||||
Enabled: boolean;
|
||||
}
|
||||
|
||||
export interface SMSGlobal {
|
||||
Enabled: boolean;
|
||||
Username: string;
|
||||
Password: string;
|
||||
Contacts: Contact[];
|
||||
}
|
||||
|
||||
export interface Webserver {
|
||||
Enabled: boolean;
|
||||
AdminUsername: string;
|
||||
AdminPassword: string;
|
||||
ListenAddress: string;
|
||||
WebsocketConnectionLimit: number;
|
||||
WebsocketAllowInsecureOrigin: boolean;
|
||||
}
|
||||
|
||||
export interface ConfigCurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Index: string;
|
||||
Delimiter: string;
|
||||
}
|
||||
|
||||
export interface RequestCurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Index: string;
|
||||
Delimiter: string;
|
||||
Separator: string;
|
||||
}
|
||||
|
||||
export interface Exchange {
|
||||
Name: string;
|
||||
Enabled: boolean;
|
||||
Verbose: boolean;
|
||||
Websocket: boolean;
|
||||
RESTPollingDelay: number;
|
||||
AuthenticatedAPISupport: boolean;
|
||||
APIKey: string;
|
||||
APISecret: string;
|
||||
AvailablePairs: string;
|
||||
EnabledPairs: string;
|
||||
BaseCurrencies: string;
|
||||
AssetTypes: string;
|
||||
ConfigCurrencyPairFormat: ConfigCurrencyPairFormat;
|
||||
RequestCurrencyPairFormat: RequestCurrencyPairFormat;
|
||||
ClientID: string;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
Name: string;
|
||||
EncryptConfig?: number;
|
||||
Cryptocurrencies: string;
|
||||
CurrencyExchangeProvider: string;
|
||||
CurrencyPairFormat: CurrencyPairFormat;
|
||||
PortfolioAddresses: PortfolioAddresses;
|
||||
SMSGlobal: SMSGlobal;
|
||||
Webserver: Webserver;
|
||||
Exchanges: Exchange[];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coin_totals">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<i [ngClass]="coin.icon"></i>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
@@ -26,21 +26,21 @@
|
||||
</mat-expansion-panel-header>
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.online_summary.BTC">
|
||||
<mat-icon mat-list-icon class="BTC">{{coinIcon('BTC')}}</mat-icon>
|
||||
<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">
|
||||
<mat-icon mat-list-icon class="LTC">{{coinIcon('LTC')}}</mat-icon>
|
||||
<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">
|
||||
<mat-icon mat-list-icon class="ETH">{{coinIcon('ETH')}}</mat-icon>
|
||||
<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>
|
||||
@@ -55,21 +55,21 @@
|
||||
</mat-expansion-panel-header>
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.offline_summary.BTC">
|
||||
<mat-icon mat-list-icon class="BTC">{{coinIcon('BTC')}}</mat-icon>
|
||||
<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">
|
||||
<mat-icon mat-list-icon class="LTC">{{coinIcon('LTC')}}</mat-icon>
|
||||
<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">
|
||||
<mat-icon mat-list-icon class="ETH">{{coinIcon('ETH')}}</mat-icon>
|
||||
<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>
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coins_online">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<i [ngClass]="coin.icon"></i>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coins_offline">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<i [ngClass]="coin.icon"></i>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketHandlerService } from './../../services/websocket-handler/websocket-handler.service';
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { WebsocketResponseHandlerService } from './../../services/websocket-response-handler/websocket-response-handler.service';
|
||||
import { Wallet, CoinTotal } from './../../shared/classes/wallet';
|
||||
import {Sort} from '@angular/material';
|
||||
import { Sort } from '@angular/material';
|
||||
import { WebSocketMessageType, WebSocketMessage } from './../../shared/classes/websocket';
|
||||
|
||||
@Component({
|
||||
selector: 'app-wallet',
|
||||
templateUrl: './wallet.component.html',
|
||||
styleUrls: ['./wallet.component.scss']
|
||||
styleUrls: ['./wallet.component.scss'],
|
||||
})
|
||||
|
||||
export class WalletComponent implements OnInit {
|
||||
private ws: WebsocketHandlerService;
|
||||
private ws: WebsocketResponseHandlerService;
|
||||
private failCount = 0;
|
||||
private timer: any;
|
||||
public wallet: Wallet;
|
||||
displayedColumns = ['coin', 'balance'];
|
||||
|
||||
private getWalletMessage = {
|
||||
Event: 'GetPortfolio',
|
||||
event: 'GetPortfolio',
|
||||
data: null,
|
||||
};
|
||||
|
||||
constructor(private websocketHandler: WebsocketHandlerService) {
|
||||
constructor(private websocketHandler: WebsocketResponseHandlerService) {
|
||||
this.wallet= null;
|
||||
this.ws = websocketHandler;
|
||||
this.ws.messages.subscribe(msg => {
|
||||
if (msg.Event === 'GetPortfolio') {
|
||||
console.log(JSON.stringify(msg.data));
|
||||
this.ws.shared.subscribe(msg => {
|
||||
if (msg.event === WebSocketMessageType.GetPortfolio) {
|
||||
this.wallet = <Wallet>msg.data;
|
||||
|
||||
this.attachIcon(this.wallet.coin_totals);
|
||||
this.attachIcon(this.wallet.coins_offline);
|
||||
this.attachIcon(this.wallet.coins_online);
|
||||
@@ -44,11 +43,19 @@ export class WalletComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.setWallet();
|
||||
}
|
||||
|
||||
private setWallet():void {
|
||||
this.ws.messages.next(this.getWalletMessage);
|
||||
}
|
||||
|
||||
public coinIcon(coin:string) :string {
|
||||
switch(coin) {
|
||||
case "BTC": return "attach_money";
|
||||
case "LTC": return "attach_money";
|
||||
case "ETH": return "attach_money";
|
||||
case "BTC": return "cc BTC";
|
||||
case "LTC": return "cc LTC";
|
||||
case "ETH": return "cc ETH";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,28 +67,5 @@ export class WalletComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.setWallet();
|
||||
}
|
||||
|
||||
//there has to be a better way
|
||||
private resendMessageIfPageRefreshed(): void {
|
||||
if (this.failCount <= 10) {
|
||||
setTimeout(() => {
|
||||
if (this.wallet === null || this.wallet === undefined) {
|
||||
this.failCount++;
|
||||
this.setWallet();
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
console.log('Could not load wallet. Check if GocryptoTrader server is running, otherwise open a ticket');
|
||||
}
|
||||
}
|
||||
|
||||
private setWallet():void {
|
||||
this.ws.messages.next(this.getWalletMessage);
|
||||
this.resendMessageIfPageRefreshed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { WebsocketHandlerService } from './websocket-handler.service';
|
||||
|
||||
describe('WebsocketHandlerService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [WebsocketHandlerService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([WebsocketHandlerService], (service: WebsocketHandlerService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs/Rx';
|
||||
import { WebsocketService } from './../../services/websocket/websocket.service';
|
||||
|
||||
const WEBSOCKET_URL = 'ws://localhost:9050/ws';
|
||||
|
||||
export interface Message {
|
||||
Event: string,
|
||||
data:any,
|
||||
Exchange:string,
|
||||
AssetType:string
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class WebsocketHandlerService {
|
||||
public messages: Subject<any>;
|
||||
|
||||
private authenticateMessage = {
|
||||
Event:'auth',
|
||||
data:{"username":"admin","password":"e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a"},
|
||||
}
|
||||
|
||||
public authenticate() {
|
||||
this.messages.next(this.authenticateMessage);
|
||||
}
|
||||
|
||||
constructor(wsService: WebsocketService) {
|
||||
this.messages = <Subject<Message>>wsService
|
||||
.connect(WEBSOCKET_URL)
|
||||
.map((response: MessageEvent): Message => {
|
||||
|
||||
let data = JSON.parse(response.data);
|
||||
// variables aren't consistent yet. Here's a hack!
|
||||
var dataData = data.Data === undefined ? data.data : data.Data;
|
||||
var eventEvent = data.Event === undefined ? data.event : data.Event;
|
||||
return {
|
||||
Event: eventEvent,
|
||||
data: dataData,
|
||||
Exchange: data.exchange,
|
||||
AssetType: data.assetType
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { WebsocketResponseHandlerService } from './websocket-response-handler.service';
|
||||
|
||||
describe('WebsocketHandlerService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [WebsocketResponseHandlerService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([WebsocketResponseHandlerService], (service: WebsocketResponseHandlerService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { NgModule, Injectable, Optional, SkipSelf } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs/Rx';
|
||||
import { WebsocketService } from './../../services/websocket/websocket.service';
|
||||
import { WebSocketMessage } from './../../shared/classes/websocket';
|
||||
|
||||
const WEBSOCKET_URL = 'ws://localhost:9050/ws';
|
||||
|
||||
@NgModule({
|
||||
})
|
||||
export class WebsocketResponseHandlerService {
|
||||
public messages: Subject<any>;
|
||||
public shared: Observable<WebSocketMessage>;
|
||||
public isConnected :boolean = false;
|
||||
|
||||
constructor(@Optional() @SkipSelf() parentModule: WebsocketResponseHandlerService, wsService: WebsocketService) {
|
||||
this.messages = <Subject<WebSocketMessage>>wsService
|
||||
.connect(WEBSOCKET_URL)
|
||||
|
||||
.map((response: MessageEvent): WebSocketMessage => {
|
||||
this.isConnected = wsService.isConnected;
|
||||
let websocketResponseMessage = JSON.parse(response.data);
|
||||
var websocketResponseData = websocketResponseMessage.Data === undefined ? websocketResponseMessage.data : websocketResponseMessage.Data;
|
||||
var websocketResponseEvent = websocketResponseMessage.Event === undefined ? websocketResponseMessage.event : websocketResponseMessage.Event;
|
||||
let responseMessage = new WebSocketMessage();
|
||||
|
||||
responseMessage.event = websocketResponseEvent;
|
||||
responseMessage.data = websocketResponseData;
|
||||
responseMessage.exchange = websocketResponseMessage.exchange;
|
||||
responseMessage.assetType = websocketResponseMessage.assetType;
|
||||
|
||||
return responseMessage;
|
||||
});
|
||||
this.isConnected = wsService.isConnected;
|
||||
|
||||
this.shared = this.messages.share(); //multicast
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,62 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Subject, Observable, Observer } from 'rxjs/Rx';
|
||||
import { Injectable, Optional, SkipSelf, NgModule } from '@angular/core';
|
||||
import { Subject, Observable, Observer } from 'rxjs/Rx';
|
||||
import { WebSocketMessage } from './../../shared/classes/websocket';
|
||||
|
||||
@Injectable()
|
||||
@NgModule()
|
||||
export class WebsocketService {
|
||||
constructor() { }
|
||||
public isConnected :boolean = false;
|
||||
constructor (@Optional() @SkipSelf() parentModule: WebsocketService) {
|
||||
if (parentModule) {
|
||||
throw new Error(
|
||||
'WebsocketService is already loaded. Import it in the AppModule only');
|
||||
}
|
||||
}
|
||||
|
||||
private subject: Subject<MessageEvent>;
|
||||
|
||||
public connect(url): Subject<MessageEvent> {
|
||||
if (!this.subject) {
|
||||
this.subject = this.create(url);
|
||||
}
|
||||
}
|
||||
return this.subject;
|
||||
}
|
||||
|
||||
private authenticateMessage = {
|
||||
Event:'auth',
|
||||
data:{"username":"admin","password":"e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a"},
|
||||
}
|
||||
|
||||
private isAuth = false;
|
||||
|
||||
private create(url): Subject<MessageEvent> {
|
||||
let ws = new WebSocket(url);
|
||||
|
||||
let observable = Observable.create(
|
||||
(obs: Observer<MessageEvent>) => {
|
||||
ws.onmessage = obs.next.bind(obs);
|
||||
ws.onerror = obs.error.bind(obs);
|
||||
ws.onclose = obs.complete.bind(obs);
|
||||
return ws.close.bind(ws);
|
||||
})
|
||||
let observer = {
|
||||
next: (data: any) => {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify(this.authenticateMessage));
|
||||
|
||||
ws.send(JSON.stringify(data));
|
||||
(obs: Observer<MessageEvent>) => {
|
||||
ws.onmessage = obs.next.bind(obs);
|
||||
ws.onerror = obs.error.bind(obs);
|
||||
ws.onclose = () => {
|
||||
this.isConnected = false;
|
||||
obs.complete.bind(obs) };
|
||||
ws.onopen = () => {
|
||||
this.isConnected = true;
|
||||
ws.send(JSON.stringify(WebSocketMessage.CreateAuthenticationMessage()));
|
||||
};
|
||||
return ws.close.bind(ws);
|
||||
})
|
||||
let observer = {
|
||||
next: (data: any) => {
|
||||
var counter = 0;
|
||||
var interval = setInterval(() => {
|
||||
if (counter == 10) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify(data));
|
||||
clearInterval(interval);
|
||||
this.isConnected = true;
|
||||
}
|
||||
counter++;
|
||||
}, 400);
|
||||
|
||||
if (ws.readyState !== WebSocket.OPEN) {
|
||||
new Error("Failed to send message to websocket after 10 attempts");
|
||||
this.isConnected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Subject.create(observer, observable);
|
||||
}
|
||||
return Subject.create(observer, observable);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
<div *ngIf="showTicker" class="one-time-animation" >
|
||||
<p>{{message}}</p>
|
||||
</div>
|
||||
{{tickerCard.Exchange}} {{tickerCard.CurrencyPair}} Last: {{this.tickerCard.Last}}
|
||||
@@ -1,61 +1,86 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketHandlerService } from './../../services/websocket-handler/websocket-handler.service';
|
||||
import {Component, OnInit, OnDestroy }from '@angular/core';
|
||||
import {WebsocketResponseHandlerService }from './../../services/websocket-response-handler/websocket-response-handler.service';
|
||||
import {WebSocketMessageType }from './../../shared/classes/websocket';
|
||||
|
||||
@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 {
|
||||
private ws: WebsocketHandlerService;
|
||||
allCurrencies:ExchangeCurrency[];
|
||||
tickerCard: TickerUpdate;
|
||||
showTicker:boolean;
|
||||
message:string;
|
||||
allCurrencies:ExchangeCurrency[] = < ExchangeCurrency[] > []; ;
|
||||
private ws:WebsocketResponseHandlerService;
|
||||
tickerCard:TickerUpdate = new TickerUpdate();
|
||||
showTicker:boolean = true;
|
||||
message:string;
|
||||
|
||||
constructor(private websocketHandler: WebsocketHandlerService) {
|
||||
this.ws = websocketHandler;
|
||||
this.allCurrencies = <ExchangeCurrency[]>[];
|
||||
this.ws.messages.subscribe(msg => {
|
||||
if (msg.Event === 'ticker_update') {
|
||||
this.showTicker = false;
|
||||
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;
|
||||
|
||||
if(this.tickerCard.Last > 0) {
|
||||
this.showTicker = true;
|
||||
this.message = this.tickerCard.Exchange + " " + this.tickerCard.CurrencyPair + " Last: " + this.tickerCard.Last;
|
||||
constructor(private websocketHandler: WebsocketResponseHandlerService) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
this.updateTicker(msg)
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
ngOnInit() { }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
currencyPair:string;
|
||||
exchangeName:string;
|
||||
}
|
||||
|
||||
export interface CurrencyPair {
|
||||
delimiter: string;
|
||||
first_currency: string;
|
||||
second_currency: string;
|
||||
delimiter:string;
|
||||
first_currency:string;
|
||||
second_currency:string;
|
||||
}
|
||||
|
||||
export interface TickerUpdate {
|
||||
Pair: CurrencyPair;
|
||||
CurrencyPair: string;
|
||||
Last: number;
|
||||
High: number;
|
||||
Low: number;
|
||||
Bid: number;
|
||||
Ask: number;
|
||||
Volume: number;
|
||||
PriceATH: number;
|
||||
Exchange:string;
|
||||
export class TickerUpdate {
|
||||
Pair:CurrencyPair;
|
||||
CurrencyPair:string;
|
||||
Last:number;
|
||||
High:number;
|
||||
Low:number;
|
||||
Bid:number;
|
||||
Ask:number;
|
||||
Volume:number;
|
||||
PriceATH:number;
|
||||
Exchange:string;
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
<form class="form-content">
|
||||
<div *ngIf="showErrorMessage">
|
||||
<h4>{{chooseCurrencyMessage}}</h4>
|
||||
<button routerLink="/exchange-grid" mat-raised-button color="primary">Choose currency</button>
|
||||
</div>
|
||||
<div *ngIf="!showErrorMessage">
|
||||
<mat-form-field>
|
||||
<input matInput disabled="disabled" name="exchange" [ngModel]="exchangeName" placeholder="Exchange">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput disabled="disabled" name="currency" [ngModel]="currencyName" placeholder="Currency">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-form-field>
|
||||
<input matInput name="smsUsername" placeholder="Amount">
|
||||
<input matInput name="amount" placeholder="Amount">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="smsPassword" placeholder="Offer">
|
||||
<input matInput name="offer" placeholder="Offer">
|
||||
</mat-form-field>
|
||||
<div mat-line></div>
|
||||
<div class="spacer">
|
||||
<button mat-raised-button color="primary">CONFIRM BUY</button>
|
||||
<button [disabled]="showErrorMessage" mat-raised-button color="primary">CONFIRM BUY</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -6,9 +6,20 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./buy-form.component.scss']
|
||||
})
|
||||
export class BuyFormComponent implements OnInit {
|
||||
public exchangeName :string;
|
||||
public currencyName :string;
|
||||
public chooseCurrencyMessage :string = "Please select a currency";
|
||||
public showErrorMessage :boolean;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
if (window.localStorage["selectedExchange"] !== undefined &&
|
||||
window.localStorage["selectedCurrency"] !== undefined) {
|
||||
this.exchangeName = window.localStorage["selectedExchange"];
|
||||
this.currencyName = window.localStorage["selectedCurrency"];
|
||||
} else {
|
||||
this.showErrorMessage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
export class Config {
|
||||
Name: string;
|
||||
EncryptConfig?: number;
|
||||
Cryptocurrencies: string;
|
||||
CurrencyExchangeProvider: string;
|
||||
CurrencyPairFormat: CurrencyPairFormat;
|
||||
PortfolioAddresses: PortfolioAddresses;
|
||||
SMSGlobal: SMSGlobal;
|
||||
Webserver: Webserver;
|
||||
Exchanges: Exchange[];
|
||||
|
||||
public isConfigCacheValid() : boolean {
|
||||
let dateStored = +new Date(window.localStorage['configDate']);
|
||||
let dateNow = +new Date();
|
||||
var dateDifference = Math.abs(dateNow - dateStored)
|
||||
var diffMins = Math.floor((dateDifference / 1000) / 60);
|
||||
(diffMins)
|
||||
|
||||
if(isNaN(new Date(dateStored).getTime()) || diffMins > 15) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public setConfig(data: any) : void {
|
||||
var configData = <Config>data;
|
||||
this.Cryptocurrencies = configData.Cryptocurrencies
|
||||
this.CurrencyExchangeProvider = configData.CurrencyExchangeProvider
|
||||
this.Exchanges = configData.Exchanges
|
||||
this.CurrencyPairFormat = configData.CurrencyPairFormat
|
||||
this.EncryptConfig = configData.EncryptConfig
|
||||
this.Exchanges = configData.Exchanges
|
||||
this.Name = configData.Name
|
||||
this.PortfolioAddresses = configData.PortfolioAddresses
|
||||
this.SMSGlobal = configData.SMSGlobal
|
||||
this.Webserver = configData.Webserver
|
||||
this.fromArrayToRedux()
|
||||
}
|
||||
|
||||
public fromArrayToRedux() : void {
|
||||
for (var i = 0; i < this.Exchanges.length; i++) {
|
||||
this.Exchanges[i].Pairs = new Array<CurrencyPairRedux>();
|
||||
var avail = this.Exchanges[i].AvailablePairs.split(',');
|
||||
var enabled = this.Exchanges[i].EnabledPairs.split(',');
|
||||
for (var j = 0; j < avail.length; j++) {
|
||||
var currencyPair = new CurrencyPairRedux();
|
||||
currencyPair.Name = avail[j]
|
||||
currencyPair.ParsedName = this.stripCurrencyCharacters(avail[j]);
|
||||
if (enabled.indexOf(avail[j]) > 0) {
|
||||
currencyPair.Enabled = true;
|
||||
} else {
|
||||
currencyPair.Enabled = false;
|
||||
}
|
||||
this.Exchanges[i].Pairs.push(currencyPair);
|
||||
}
|
||||
}
|
||||
window.localStorage['config'] = JSON.stringify(this);
|
||||
window.localStorage['configDate'] = new Date().toString();
|
||||
}
|
||||
|
||||
public parseSettings() : void {
|
||||
|
||||
}
|
||||
|
||||
private stripCurrencyCharacters(name:string) :string {
|
||||
name = name.replace('_', '');
|
||||
name = name.replace('-', '');
|
||||
name = name.replace(' ', '');
|
||||
name = name.toLocaleUpperCase();
|
||||
return name;
|
||||
}
|
||||
|
||||
public fromReduxToArray() : void {
|
||||
for (var i = 0; i < this.Exchanges.length; i++) {
|
||||
// Step 1, iterate over the Pairs
|
||||
var enabled = this.Exchanges[i].EnabledPairs.split(',');
|
||||
for (var j = 0; j < this.Exchanges[i].Pairs.length; j++) {
|
||||
if (this.Exchanges[i].Pairs[j].Enabled) {
|
||||
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 {
|
||||
Name: string;
|
||||
ParsedName: string;
|
||||
Enabled: boolean;
|
||||
}
|
||||
|
||||
export interface CurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Delimiter: string;
|
||||
}
|
||||
|
||||
export interface PortfolioAddresses {
|
||||
Addresses?: any;
|
||||
}
|
||||
|
||||
export interface Contact {
|
||||
Name: string;
|
||||
Number: string;
|
||||
Enabled: boolean;
|
||||
}
|
||||
|
||||
export interface SMSGlobal {
|
||||
Enabled: boolean;
|
||||
Username: string;
|
||||
Password: string;
|
||||
Contacts: Contact[];
|
||||
}
|
||||
|
||||
export interface Webserver {
|
||||
Enabled: boolean;
|
||||
AdminUsername: string;
|
||||
AdminPassword: string;
|
||||
ListenAddress: string;
|
||||
WebsocketConnectionLimit: number;
|
||||
WebsocketAllowInsecureOrigin: boolean;
|
||||
}
|
||||
|
||||
export interface ConfigCurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Index: string;
|
||||
Delimiter: string;
|
||||
}
|
||||
|
||||
export interface RequestCurrencyPairFormat {
|
||||
Uppercase: boolean;
|
||||
Index: string;
|
||||
Delimiter: string;
|
||||
Separator: string;
|
||||
}
|
||||
|
||||
export interface Exchange {
|
||||
Name: string;
|
||||
Enabled: boolean;
|
||||
Verbose: boolean;
|
||||
Websocket: boolean;
|
||||
RESTPollingDelay: number;
|
||||
AuthenticatedAPISupport: boolean;
|
||||
APIKey: string;
|
||||
APISecret: string;
|
||||
AvailablePairs: string;
|
||||
EnabledPairs: string;
|
||||
BaseCurrencies: string;
|
||||
AssetTypes: string;
|
||||
ConfigCurrencyPairFormat: ConfigCurrencyPairFormat;
|
||||
RequestCurrencyPairFormat: RequestCurrencyPairFormat;
|
||||
ClientID: string;
|
||||
Pairs: CurrencyPairRedux[];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
45
web/src/app/shared/classes/pipes.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Component, OnInit, OnDestroy, Pipe, PipeTransform } from '@angular/core';
|
||||
import { CurrencyPairRedux } from './../../shared/classes/config';
|
||||
|
||||
|
||||
@Pipe({
|
||||
name: 'iterateMap'
|
||||
})
|
||||
export class IterateMapPipe implements PipeTransform {
|
||||
transform(iterable: any, args: any[]): any {
|
||||
let result = [];
|
||||
|
||||
if (iterable.entries) {
|
||||
iterable.forEach((key, value) => {
|
||||
result.push({
|
||||
key,
|
||||
value
|
||||
});
|
||||
});
|
||||
} else {
|
||||
for (let key in iterable) {
|
||||
if (iterable.hasOwnProperty(key)) {
|
||||
result.push({
|
||||
key,
|
||||
value: iterable[key]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'enabledCurrencies'
|
||||
})
|
||||
export class EnabledCurrenciesPipe implements PipeTransform {
|
||||
transform(items: CurrencyPairRedux[], args: any[]): any {
|
||||
if (!items) {
|
||||
return items;
|
||||
}
|
||||
return items.filter(item => item.Enabled === true);
|
||||
}
|
||||
}
|
||||
|
||||
32
web/src/app/shared/classes/websocket.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export class WebSocketMessage {
|
||||
public event: string;
|
||||
public data: any;
|
||||
public exchange: string;
|
||||
public assetType: string;
|
||||
|
||||
public static CreateAuthenticationMessage(): WebSocketMessage {
|
||||
var response = new WebSocketMessage();
|
||||
|
||||
response.event = WebSocketMessageType.Auth;
|
||||
response.data = { "username": window.sessionStorage["username"], "password": window.sessionStorage["password"] };
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
public static GetSettingsMessage() : WebSocketMessage {
|
||||
var response = new WebSocketMessage();
|
||||
|
||||
response.event = WebSocketMessageType.GetConfig;
|
||||
response.data = null;
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export class WebSocketMessageType {
|
||||
public static Auth: string = "auth";
|
||||
public static GetConfig: string = "GetConfig";
|
||||
public static SaveConfig: string = "SaveConfig";
|
||||
public static GetPortfolio: string = "GetPortfolio";
|
||||
public static TickerUpdate: string = "ticker_update";
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
</a>
|
||||
<app-selected-currency></app-selected-currency>
|
||||
<div class="flex-spacer"></div>
|
||||
<app-all-updates-ticker></app-all-updates-ticker>
|
||||
<theme-picker></theme-picker>
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ export class PriceHistoryComponent implements OnInit {
|
||||
|
||||
public options = {
|
||||
"type": "serial",
|
||||
"theme": "light",
|
||||
"theme": "dark",
|
||||
"dataDateFormat": "YYYY-MM-DD",
|
||||
"zoomOutOnDataUpdate": false,
|
||||
"valueAxes": [{
|
||||
@@ -158,7 +158,6 @@ export class PriceHistoryComponent implements OnInit {
|
||||
e.chart.firstPoint = e.item;
|
||||
}
|
||||
|
||||
//console.log(e.item);
|
||||
e.chart.validateData();
|
||||
}
|
||||
}],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<button mat-button routerLink="exchange-grid" matTooltip="Change currency">POLONIEX: BTC_USD (placeholder)</button>
|
||||
|
||||
<button class="currency-button" mat-button routerLink="exchange-grid" matTooltip="Change currency"><app-all-updates-ticker></app-all-updates-ticker></button>
|
||||
<button mat-icon-button routerLink="currency-list" matTooltip="View currency list">
|
||||
<mat-icon>
|
||||
view_list
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.currency-button {
|
||||
width: 20rem;
|
||||
text-align: left;
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
<form class="form-content">
|
||||
<mat-form-field>
|
||||
<input matInput name="smsUsername" placeholder="Amount">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="smsPassword" placeholder="Offer">
|
||||
</mat-form-field>
|
||||
<div mat-line></div>
|
||||
<div *ngIf="showErrorMessage">
|
||||
<h4>{{chooseCurrencyMessage}}</h4>
|
||||
<button routerLink="/exchange-grid" mat-raised-button color="primary">Choose currency</button>
|
||||
</div>
|
||||
<div *ngIf="!showErrorMessage">
|
||||
<mat-form-field>
|
||||
<input matInput disabled="disabled" name="exchange" [ngModel]="exchangeName" placeholder="Exchange">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput disabled="disabled" name="currency" [ngModel]="currencyName" placeholder="Currency">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-form-field>
|
||||
<input matInput name="amount" placeholder="Amount">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="offer" placeholder="Offer">
|
||||
</mat-form-field>
|
||||
<div mat-line></div>
|
||||
<div class="spacer">
|
||||
<button mat-raised-button color="primary">CONFIRM SELL</button>
|
||||
</div>
|
||||
</form>
|
||||
<button [disabled]="showErrorMessage" mat-raised-button color="primary">CONFIRM SELL</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -6,10 +6,20 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./sell-form.component.scss']
|
||||
})
|
||||
export class SellFormComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
public exchangeName :string;
|
||||
public currencyName :string;
|
||||
public chooseCurrencyMessage :string = "Please select a currency";
|
||||
public showErrorMessage :boolean;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
if (window.localStorage["selectedExchange"] !== undefined &&
|
||||
window.localStorage["selectedCurrency"] !== undefined) {
|
||||
this.exchangeName = window.localStorage["selectedExchange"];
|
||||
this.currencyName = window.localStorage["selectedCurrency"];
|
||||
} else {
|
||||
this.showErrorMessage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export class ThemePickerComponent {
|
||||
if (theme.isDefault) {
|
||||
this.styleManager.removeStyle('theme');
|
||||
} else {
|
||||
this.styleManager.setStyle('theme', `assets/${theme.href}`);
|
||||
this.styleManager.setStyle('theme', `assets/themes/${theme.href}`);
|
||||
}
|
||||
|
||||
if (this.currentTheme) {
|
||||
|
||||
BIN
web/src/assets/centralised.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
106
web/src/assets/css/cryptocoins-colors.css
Normal file
@@ -0,0 +1,106 @@
|
||||
i.cc.ARCH, i.cc.ARCH-alt { color: #002652; }
|
||||
i.cc.BANX, i.cc.BANX-alt { color: #225BA6; }
|
||||
i.cc.BC, i.cc.BC-alt { color: #202121; }
|
||||
i.cc.BCN, i.cc.BCN-alt { color: #964F51; }
|
||||
i.cc.BTC, i.cc.BTC-alt { color: #F7931A; }
|
||||
i.cc.BTCD, i.cc.BTCD-alt { color: #2A72DC; }
|
||||
i.cc.BTS, i.cc.BTS-alt { color: #03A9E0; }
|
||||
i.cc.DASH, i.cc.DASH-alt { color: #1c75bc; }
|
||||
i.cc.DOGE, i.cc.DOGE-alt { color: #BA9F33; }
|
||||
i.cc.FC2, i.cc.FC2-alt { color: #040405; }
|
||||
i.cc.FTC, i.cc.FTC-alt { color: #679EF1; }
|
||||
i.cc.GEMZ, i.cc.GEMZ-alt { color: #e86060; }
|
||||
i.cc.GRC, i.cc.GRC-alt { color: #88A13C; }
|
||||
i.cc.IFC, i.cc.IFC-alt { color: #ed272d; }
|
||||
i.cc.KORE, i.cc.KORE-alt { color: #DF4124; }
|
||||
i.cc.LTC, i.cc.LTC-alt { color: #838383; }
|
||||
i.cc.MAID, i.cc.MAID-alt { color: #5492D6; }
|
||||
i.cc.MSC, i.cc.MSC-alt { color: #1D4983; }
|
||||
i.cc.NBT { color: #FFC93D; }
|
||||
i.cc.NMC, i.cc.NMC-alt { color: #6787B7; }
|
||||
i.cc.NOTE, i.cc.NOTE-alt { color: #42daff; }
|
||||
i.cc.NXT, i.cc.NXT-alt { color: #008FBB; }
|
||||
i.cc.OPAL, i.cc.OPAL-alt { color: #7193AA; }
|
||||
i.cc.POT, i.cc.POT-alt { color: #105B2F; }
|
||||
i.cc.PPC, i.cc.PPC-alt { color: #3FA30C; }
|
||||
i.cc.QRK, i.cc.QRK-alt { color: #22AABF; }
|
||||
i.cc.RBT, i.cc.RBT-alt { color: #0d4982; }
|
||||
i.cc.SDC, i.cc.SDC-alt { color: #981D2D; }
|
||||
i.cc.STR, i.cc.STR-alt { color: #08B5E5; }
|
||||
i.cc.SYNC, i.cc.SYNC-alt { color: #008DD2; }
|
||||
i.cc.UNITY, i.cc.UNITY-alt { color: #ED8527; }
|
||||
i.cc.VIOR, i.cc.VIOR-alt { color: #1F52A4; }
|
||||
i.cc.VPN, i.cc.VPN-alt { color: #589700; }
|
||||
i.cc.VRC, i.cc.VRC-alt { color: #418bca; }
|
||||
i.cc.VTC, i.cc.VTC-alt { color: #1b5c2e; }
|
||||
i.cc.XCP, i.cc.XCP-alt { color: #EC1550; }
|
||||
i.cc.XEM, i.cc.XEM-alt { color: #41bf76; }
|
||||
i.cc.XMR { color: #FF6600; }
|
||||
i.cc.XRP, i.cc.XRP-alt { color: #346AA9; }
|
||||
i.cc.YBC, i.cc.YBC-alt { color: #D6C154; }
|
||||
i.cc.DMD, i.cc.DMD-alt { color: #5497b2; }
|
||||
i.cc.FRK, i.cc.FRK-alt { color: #0633cd; }
|
||||
i.cc.IOC, i.cc.IOC-alt { color: #2fa3de; }
|
||||
i.cc.LDOGE, i.cc.LDOGE-alt { color: #ffcc00; }
|
||||
i.cc.MTR, i.cc.MTR-alt { color: #b92429; }
|
||||
i.cc.MUE, i.cc.MUE-alt { color: #f5a10e; }
|
||||
i.cc.XAI, i.cc.XAI-alt { color: #2ef99f; }
|
||||
i.cc.XBS, i.cc.XBS-alt { color: #d3261d; }
|
||||
i.cc.XPM, i.cc.XPM-alt { color: #e5b625; }
|
||||
i.cc.BAY, i.cc.BAY-alt { color: #584ba1; }
|
||||
i.cc.DGB, i.cc.DGB-alt { color: #0066cc; }
|
||||
i.cc.EMC, i.cc.EMC-alt { color: #674c8c; }
|
||||
i.cc.ETH, i.cc.ETH-alt { color: #282828; }
|
||||
i.cc.MINT, i.cc.MINT-alt { color: #006835; }
|
||||
i.cc.MONA, i.cc.MONA-alt { color: #a99364; }
|
||||
i.cc.MRC { color: #4279bd; }
|
||||
i.cc.NEU, i.cc.NEU-alt { color: #2983c0; }
|
||||
i.cc.NVC, i.cc.NVC-alt { color: #ecab41; }
|
||||
i.cc.AEON, i.cc.AEON-alt { color: #164450; }
|
||||
i.cc.AMP, i.cc.AMP-alt { color: #048DD2; }
|
||||
i.cc.ANC, i.cc.ANC-alt { color: #000; }
|
||||
i.cc.BTA { color: #210094; }
|
||||
i.cc.CLAM, i.cc.CLAM-alt { color: #D6AB31; }
|
||||
i.cc.CLOAK, i.cc.CLOAK-alt { color: #DF3F1E; }
|
||||
i.cc.DCR, i.cc.DCR-alt { color: #43A2CA; }
|
||||
i.cc.NEOS, i.cc.NEOS-alt { color: #3771B1; }
|
||||
i.cc.NLG, i.cc.NLG-alt { color: #003E7E; }
|
||||
i.cc.OK, i.cc.OK-alt { color: #0165A4; }
|
||||
i.cc.OMNI, i.cc.OMNI-alt { color: #18347E; }
|
||||
i.cc.RBY, i.cc.RBY-alt { color: #D31F26; }
|
||||
i.cc.SCOT, i.cc.SCOT-alt { color: #3498DB; }
|
||||
i.cc.SJCX, i.cc.SJCX-alt { color: #003366; }
|
||||
i.cc.START, i.cc.START-alt { color: #01AEF0; }
|
||||
i.cc.SYS, i.cc.SYS-alt { color: #0098DA; }
|
||||
i.cc.VNL, i.cc.VNL-alt { color: #404249; }
|
||||
i.cc.TX, i.cc.TX-alt { color: #1F8BCC; }
|
||||
i.cc.XVG, i.cc.XVG-alt { color: #42AFB2; }
|
||||
i.cc.FCT, i.cc.FCT-alt { color: #2175BB; }
|
||||
i.cc.GDC, i.cc.GDC-alt { color: #E9A226; }
|
||||
i.cc.JBS, i.cc.JBS-alt { color: #1A8BCD; }
|
||||
i.cc.LISK, i.cc.LISK-alt { color: #1A6896; }
|
||||
i.cc.PIGGY, i.cc.PIGGY-alt { color: #F27A7A; }
|
||||
i.cc.RBIES, i.cc.RBIES-alt { color: #C62436; }
|
||||
i.cc.SAR, i.cc.SAR-alt { color: #1B72B8; }
|
||||
i.cc.SLG, i.cc.SLG-alt { color: #5A6875; }
|
||||
i.cc.USDT, i.cc.USDT-alt { color: #2CA07A; }
|
||||
i.cc.ZEIT, i.cc.ZEIT-alt { color: #ACACAC; }
|
||||
i.cc.DGD, i.cc.DGX { color: #D8A24A; }
|
||||
i.cc.ADC, i.cc.ADC-alt { color: #3CB0E5; }
|
||||
i.cc.BSD, i.cc.BSD-alt { color: #1186E7; }
|
||||
i.cc.DAO, i.cc.DAO-alt { color: #FF3B3B; }
|
||||
i.cc.ERC, i.cc.ERC-alt { color: #101E84; }
|
||||
i.cc.ETC, i.cc.ETC-alt { color: #669073; }
|
||||
i.cc.GLD, i.cc.GLD-alt { color: #E8BE24; }
|
||||
i.cc.GRS { color: #648FA0; }
|
||||
i.cc.KOBO { color: #80C342; }
|
||||
i.cc.LBC, i.cc.LBC-alt { color: #015C47; }
|
||||
i.cc.PINK, i.cc.PINK-alt { color: #ED31CA; }
|
||||
i.cc.RDD, i.cc.RDD-alt { color: #ED1C24; }
|
||||
i.cc.RISE, i.cc.RISE-alt { color: #43CEA2; }
|
||||
i.cc.SIA, i.cc.SIA-alt { color: #00CBA0; }
|
||||
i.cc.SLS, i.cc.SLS-alt { color: #1EB549; }
|
||||
i.cc.SNRG, i.cc.SNRG-alt { color: #160363; }
|
||||
i.cc.STEEM, i.cc.STEEM-alt { color: #1A5099; }
|
||||
i.cc.STRAT, i.cc.STRAT-alt { color: #33C7F5; }
|
||||
i.cc.SWIFT, i.cc.SWIFT-alt { color: #428BCA; }
|
||||
645
web/src/assets/css/cryptocoins.css
Normal file
@@ -0,0 +1,645 @@
|
||||
@font-face {
|
||||
font-family: 'cryptocoins';
|
||||
src: url('./../fonts/cryptocoins.eot?d2eit9');
|
||||
src: url('./../fonts/cryptocoins.eot?d2eit9#iefix') format('embedded-opentype'),
|
||||
url('./../fonts/cryptocoins.ttf?d2eit9') format('truetype'),
|
||||
url('./../fonts/cryptocoins.woff?d2eit9') format('woff'),
|
||||
url('./../fonts/cryptocoins.svg?d2eit9#cryptocoins') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
i.cc {
|
||||
/* use !important to prevent issues with browser extensions that change fonts */
|
||||
font-family: 'cryptocoins' !important;
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
i.cc.SAR:before {
|
||||
content: "\e900";
|
||||
}
|
||||
i.cc.SAR-alt:before {
|
||||
content: "\e901";
|
||||
}
|
||||
i.cc.SCOT:before {
|
||||
content: "\e902";
|
||||
}
|
||||
i.cc.SCOT-alt:before {
|
||||
content: "\e903";
|
||||
}
|
||||
i.cc.SDC:before {
|
||||
content: "\e904";
|
||||
}
|
||||
i.cc.SDC-alt:before {
|
||||
content: "\e905";
|
||||
}
|
||||
i.cc.SIA:before {
|
||||
content: "\e906";
|
||||
}
|
||||
i.cc.SIA-alt:before {
|
||||
content: "\e907";
|
||||
}
|
||||
i.cc.SJCX:before {
|
||||
content: "\e908";
|
||||
}
|
||||
i.cc.SJCX-alt:before {
|
||||
content: "\e909";
|
||||
}
|
||||
i.cc.SLG:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
i.cc.SLG-alt:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
i.cc.SLS:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
i.cc.SLS-alt:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
i.cc.SNRG:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
i.cc.SNRG-alt:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
i.cc.START:before {
|
||||
content: "\e910";
|
||||
}
|
||||
i.cc.START-alt:before {
|
||||
content: "\e911";
|
||||
}
|
||||
i.cc.STEEM:before {
|
||||
content: "\e912";
|
||||
}
|
||||
i.cc.STEEM-alt:before {
|
||||
content: "\e913";
|
||||
}
|
||||
i.cc.STR:before {
|
||||
content: "\e914";
|
||||
}
|
||||
i.cc.STR-alt:before {
|
||||
content: "\e915";
|
||||
}
|
||||
i.cc.STRAT:before {
|
||||
content: "\e916";
|
||||
}
|
||||
i.cc.STRAT-alt:before {
|
||||
content: "\e917";
|
||||
}
|
||||
i.cc.SWIFT:before {
|
||||
content: "\e918";
|
||||
}
|
||||
i.cc.SWIFT-alt:before {
|
||||
content: "\e919";
|
||||
}
|
||||
i.cc.SYNC:before {
|
||||
content: "\e91a";
|
||||
}
|
||||
i.cc.SYNC-alt:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
i.cc.SYS:before {
|
||||
content: "\e91c";
|
||||
}
|
||||
i.cc.SYS-alt:before {
|
||||
content: "\e91d";
|
||||
}
|
||||
i.cc.TX:before {
|
||||
content: "\e91e";
|
||||
}
|
||||
i.cc.TX-alt:before {
|
||||
content: "\e91f";
|
||||
}
|
||||
i.cc.UNITY:before {
|
||||
content: "\e920";
|
||||
}
|
||||
i.cc.UNITY-alt:before {
|
||||
content: "\e921";
|
||||
}
|
||||
i.cc.USDT:before {
|
||||
content: "\e922";
|
||||
}
|
||||
i.cc.USDT-alt:before {
|
||||
content: "\e923";
|
||||
}
|
||||
i.cc.VIOR:before {
|
||||
content: "\e924";
|
||||
}
|
||||
i.cc.VIOR-alt:before {
|
||||
content: "\e925";
|
||||
}
|
||||
i.cc.VNL:before {
|
||||
content: "\e926";
|
||||
}
|
||||
i.cc.VNL-alt:before {
|
||||
content: "\e927";
|
||||
}
|
||||
i.cc.VPN:before {
|
||||
content: "\e928";
|
||||
}
|
||||
i.cc.VPN-alt:before {
|
||||
content: "\e929";
|
||||
}
|
||||
i.cc.VRC:before {
|
||||
content: "\e92a";
|
||||
}
|
||||
i.cc.VRC-alt:before {
|
||||
content: "\e92b";
|
||||
}
|
||||
i.cc.VTC:before {
|
||||
content: "\e92c";
|
||||
}
|
||||
i.cc.VTC-alt:before {
|
||||
content: "\e92d";
|
||||
}
|
||||
i.cc.XAI:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
i.cc.XAI-alt:before {
|
||||
content: "\e92f";
|
||||
}
|
||||
i.cc.XBS:before {
|
||||
content: "\e930";
|
||||
}
|
||||
i.cc.XBS-alt:before {
|
||||
content: "\e931";
|
||||
}
|
||||
i.cc.XCP:before {
|
||||
content: "\e932";
|
||||
}
|
||||
i.cc.XCP-alt:before {
|
||||
content: "\e933";
|
||||
}
|
||||
i.cc.XEM:before {
|
||||
content: "\e934";
|
||||
}
|
||||
i.cc.XEM-alt:before {
|
||||
content: "\e935";
|
||||
}
|
||||
i.cc.XMR:before {
|
||||
content: "\e936";
|
||||
}
|
||||
i.cc.XPM:before {
|
||||
content: "\e937";
|
||||
}
|
||||
i.cc.XPM-alt:before {
|
||||
content: "\e938";
|
||||
}
|
||||
i.cc.XRP:before {
|
||||
content: "\e939";
|
||||
}
|
||||
i.cc.XRP-alt:before {
|
||||
content: "\e93a";
|
||||
}
|
||||
i.cc.XVG:before {
|
||||
content: "\e93b";
|
||||
}
|
||||
i.cc.XVG-alt:before {
|
||||
content: "\e93c";
|
||||
}
|
||||
i.cc.YBC:before {
|
||||
content: "\e93d";
|
||||
}
|
||||
i.cc.YBC-alt:before {
|
||||
content: "\e93e";
|
||||
}
|
||||
i.cc.ZEIT:before {
|
||||
content: "\e93f";
|
||||
}
|
||||
i.cc.ZEIT-alt:before {
|
||||
content: "\e940";
|
||||
}
|
||||
i.cc.MAID:before {
|
||||
content: "\e941";
|
||||
}
|
||||
i.cc.MAID-alt:before {
|
||||
content: "\e942";
|
||||
}
|
||||
i.cc.MINT:before {
|
||||
content: "\e943";
|
||||
}
|
||||
i.cc.MINT-alt:before {
|
||||
content: "\e944";
|
||||
}
|
||||
i.cc.MONA:before {
|
||||
content: "\e945";
|
||||
}
|
||||
i.cc.MONA-alt:before {
|
||||
content: "\e946";
|
||||
}
|
||||
i.cc.MRC:before {
|
||||
content: "\e947";
|
||||
}
|
||||
i.cc.MSC:before {
|
||||
content: "\e948";
|
||||
}
|
||||
i.cc.MSC-alt:before {
|
||||
content: "\e949";
|
||||
}
|
||||
i.cc.MTR:before {
|
||||
content: "\e94a";
|
||||
}
|
||||
i.cc.MTR-alt:before {
|
||||
content: "\e94b";
|
||||
}
|
||||
i.cc.MUE:before {
|
||||
content: "\e94c";
|
||||
}
|
||||
i.cc.MUE-alt:before {
|
||||
content: "\e94d";
|
||||
}
|
||||
i.cc.NBT:before {
|
||||
content: "\e94e";
|
||||
}
|
||||
i.cc.NEOS:before {
|
||||
content: "\e94f";
|
||||
}
|
||||
i.cc.NEOS-alt:before {
|
||||
content: "\e950";
|
||||
}
|
||||
i.cc.NEU:before {
|
||||
content: "\e951";
|
||||
}
|
||||
i.cc.NEU-alt:before {
|
||||
content: "\e952";
|
||||
}
|
||||
i.cc.NLG:before {
|
||||
content: "\e953";
|
||||
}
|
||||
i.cc.NLG-alt:before {
|
||||
content: "\e954";
|
||||
}
|
||||
i.cc.NMC:before {
|
||||
content: "\e955";
|
||||
}
|
||||
i.cc.NMC-alt:before {
|
||||
content: "\e956";
|
||||
}
|
||||
i.cc.NOTE:before {
|
||||
content: "\e957";
|
||||
}
|
||||
i.cc.NOTE-alt:before {
|
||||
content: "\e958";
|
||||
}
|
||||
i.cc.NVC:before {
|
||||
content: "\e959";
|
||||
}
|
||||
i.cc.NVC-alt:before {
|
||||
content: "\e95a";
|
||||
}
|
||||
i.cc.NXT:before {
|
||||
content: "\e95b";
|
||||
}
|
||||
i.cc.NXT-alt:before {
|
||||
content: "\e95c";
|
||||
}
|
||||
i.cc.OK:before {
|
||||
content: "\e95d";
|
||||
}
|
||||
i.cc.OK-alt:before {
|
||||
content: "\e95e";
|
||||
}
|
||||
i.cc.OMNI:before {
|
||||
content: "\e95f";
|
||||
}
|
||||
i.cc.OMNI-alt:before {
|
||||
content: "\e960";
|
||||
}
|
||||
i.cc.OPAL:before {
|
||||
content: "\e961";
|
||||
}
|
||||
i.cc.OPAL-alt:before {
|
||||
content: "\e962";
|
||||
}
|
||||
i.cc.PIGGY:before {
|
||||
content: "\e963";
|
||||
}
|
||||
i.cc.PIGGY-alt:before {
|
||||
content: "\e964";
|
||||
}
|
||||
i.cc.PINK:before {
|
||||
content: "\e965";
|
||||
}
|
||||
i.cc.PINK-alt:before {
|
||||
content: "\e966";
|
||||
}
|
||||
i.cc.POT:before {
|
||||
content: "\e967";
|
||||
}
|
||||
i.cc.POT-alt:before {
|
||||
content: "\e968";
|
||||
}
|
||||
i.cc.PPC:before {
|
||||
content: "\e969";
|
||||
}
|
||||
i.cc.PPC-alt:before {
|
||||
content: "\e96a";
|
||||
}
|
||||
i.cc.QRK:before {
|
||||
content: "\e96b";
|
||||
}
|
||||
i.cc.QRK-alt:before {
|
||||
content: "\e96c";
|
||||
}
|
||||
i.cc.RBIES:before {
|
||||
content: "\e96d";
|
||||
}
|
||||
i.cc.RBIES-alt:before {
|
||||
content: "\e96e";
|
||||
}
|
||||
i.cc.RBT:before {
|
||||
content: "\e96f";
|
||||
}
|
||||
i.cc.RBT-alt:before {
|
||||
content: "\e970";
|
||||
}
|
||||
i.cc.RBY:before {
|
||||
content: "\e971";
|
||||
}
|
||||
i.cc.RBY-alt:before {
|
||||
content: "\e972";
|
||||
}
|
||||
i.cc.RDD:before {
|
||||
content: "\e973";
|
||||
}
|
||||
i.cc.RDD-alt:before {
|
||||
content: "\e974";
|
||||
}
|
||||
i.cc.RISE:before {
|
||||
content: "\e975";
|
||||
}
|
||||
i.cc.RISE-alt:before {
|
||||
content: "\e976";
|
||||
}
|
||||
i.cc.GDC:before {
|
||||
content: "\e977";
|
||||
}
|
||||
i.cc.GDC-alt:before {
|
||||
content: "\e978";
|
||||
}
|
||||
i.cc.GEMZ:before {
|
||||
content: "\e979";
|
||||
}
|
||||
i.cc.GEMZ-alt:before {
|
||||
content: "\e97a";
|
||||
}
|
||||
i.cc.GLD:before {
|
||||
content: "\e97b";
|
||||
}
|
||||
i.cc.GLD-alt:before {
|
||||
content: "\e97c";
|
||||
}
|
||||
i.cc.GRC:before {
|
||||
content: "\e97d";
|
||||
}
|
||||
i.cc.GRC-alt:before {
|
||||
content: "\e97e";
|
||||
}
|
||||
i.cc.GRS:before {
|
||||
content: "\e97f";
|
||||
}
|
||||
i.cc.IFC:before {
|
||||
content: "\e980";
|
||||
}
|
||||
i.cc.IFC-alt:before {
|
||||
content: "\e981";
|
||||
}
|
||||
i.cc.IOC:before {
|
||||
content: "\e982";
|
||||
}
|
||||
i.cc.IOC-alt:before {
|
||||
content: "\e983";
|
||||
}
|
||||
i.cc.JBS:before {
|
||||
content: "\e984";
|
||||
}
|
||||
i.cc.JBS-alt:before {
|
||||
content: "\e985";
|
||||
}
|
||||
i.cc.KOBO:before {
|
||||
content: "\e986";
|
||||
}
|
||||
i.cc.KORE:before {
|
||||
content: "\e987";
|
||||
}
|
||||
i.cc.KORE-alt:before {
|
||||
content: "\e988";
|
||||
}
|
||||
i.cc.LBC:before {
|
||||
content: "\e989";
|
||||
}
|
||||
i.cc.LBC-alt:before {
|
||||
content: "\e98a";
|
||||
}
|
||||
i.cc.LDOGE:before {
|
||||
content: "\e98b";
|
||||
}
|
||||
i.cc.LDOGE-alt:before {
|
||||
content: "\e98c";
|
||||
}
|
||||
i.cc.LISK:before {
|
||||
content: "\e98d";
|
||||
}
|
||||
i.cc.LISK-alt:before {
|
||||
content: "\e98e";
|
||||
}
|
||||
i.cc.LTC:before {
|
||||
content: "\e98f";
|
||||
}
|
||||
i.cc.LTC-alt:before {
|
||||
content: "\e990";
|
||||
}
|
||||
i.cc.ADC:before {
|
||||
content: "\e991";
|
||||
}
|
||||
i.cc.ADC-alt:before {
|
||||
content: "\e992";
|
||||
}
|
||||
i.cc.AEON:before {
|
||||
content: "\e993";
|
||||
}
|
||||
i.cc.AEON-alt:before {
|
||||
content: "\e994";
|
||||
}
|
||||
i.cc.AMP:before {
|
||||
content: "\e995";
|
||||
}
|
||||
i.cc.AMP-alt:before {
|
||||
content: "\e996";
|
||||
}
|
||||
i.cc.ANC:before {
|
||||
content: "\e997";
|
||||
}
|
||||
i.cc.ANC-alt:before {
|
||||
content: "\e998";
|
||||
}
|
||||
i.cc.ARCH:before {
|
||||
content: "\e999";
|
||||
}
|
||||
i.cc.ARCH-alt:before {
|
||||
content: "\e99a";
|
||||
}
|
||||
i.cc.BANX:before {
|
||||
content: "\e99b";
|
||||
}
|
||||
i.cc.BANX-alt:before {
|
||||
content: "\e99c";
|
||||
}
|
||||
i.cc.BAY:before {
|
||||
content: "\e99d";
|
||||
}
|
||||
i.cc.BAY-alt:before {
|
||||
content: "\e99e";
|
||||
}
|
||||
i.cc.BC:before {
|
||||
content: "\e99f";
|
||||
}
|
||||
i.cc.BC-alt:before {
|
||||
content: "\e9a0";
|
||||
}
|
||||
i.cc.BCN:before {
|
||||
content: "\e9a1";
|
||||
}
|
||||
i.cc.BCN-alt:before {
|
||||
content: "\e9a2";
|
||||
}
|
||||
i.cc.BSD:before {
|
||||
content: "\e9a3";
|
||||
}
|
||||
i.cc.BSD-alt:before {
|
||||
content: "\e9a4";
|
||||
}
|
||||
i.cc.BTA:before {
|
||||
content: "\e9a5";
|
||||
}
|
||||
i.cc.BTC:before {
|
||||
content: "\e9a6";
|
||||
}
|
||||
i.cc.BTC-alt:before {
|
||||
content: "\e9a7";
|
||||
}
|
||||
i.cc.BTCD:before {
|
||||
content: "\e9a8";
|
||||
}
|
||||
i.cc.BTCD-alt:before {
|
||||
content: "\e9a9";
|
||||
}
|
||||
i.cc.BTS:before {
|
||||
content: "\e9aa";
|
||||
}
|
||||
i.cc.BTS-alt:before {
|
||||
content: "\e9ab";
|
||||
}
|
||||
i.cc.CLAM:before {
|
||||
content: "\e9ac";
|
||||
}
|
||||
i.cc.CLAM-alt:before {
|
||||
content: "\e9ad";
|
||||
}
|
||||
i.cc.CLOAK:before {
|
||||
content: "\e9ae";
|
||||
}
|
||||
i.cc.CLOAK-alt:before {
|
||||
content: "\e9af";
|
||||
}
|
||||
i.cc.DAO:before {
|
||||
content: "\e9b0";
|
||||
}
|
||||
i.cc.DAO-alt:before {
|
||||
content: "\e9b1";
|
||||
}
|
||||
i.cc.DASH:before {
|
||||
content: "\e9b2";
|
||||
}
|
||||
i.cc.DASH-alt:before {
|
||||
content: "\e9b3";
|
||||
}
|
||||
i.cc.DCR:before {
|
||||
content: "\e9b4";
|
||||
}
|
||||
i.cc.DCR-alt:before {
|
||||
content: "\e9b5";
|
||||
}
|
||||
i.cc.DGB:before {
|
||||
content: "\e9b6";
|
||||
}
|
||||
i.cc.DGB-alt:before {
|
||||
content: "\e9b7";
|
||||
}
|
||||
i.cc.DGD:before {
|
||||
content: "\e9b8";
|
||||
}
|
||||
i.cc.DGX:before {
|
||||
content: "\e9b9";
|
||||
}
|
||||
i.cc.DMD:before {
|
||||
content: "\e9ba";
|
||||
}
|
||||
i.cc.DMD-alt:before {
|
||||
content: "\e9bb";
|
||||
}
|
||||
i.cc.DOGE:before {
|
||||
content: "\e9bc";
|
||||
}
|
||||
i.cc.DOGE-alt:before {
|
||||
content: "\e9bd";
|
||||
}
|
||||
i.cc.EMC:before {
|
||||
content: "\e9be";
|
||||
}
|
||||
i.cc.EMC-alt:before {
|
||||
content: "\e9bf";
|
||||
}
|
||||
i.cc.ERC:before {
|
||||
content: "\e9c0";
|
||||
}
|
||||
i.cc.ERC-alt:before {
|
||||
content: "\e9c1";
|
||||
}
|
||||
i.cc.ETC:before {
|
||||
content: "\e9c2";
|
||||
}
|
||||
i.cc.ETC-alt:before {
|
||||
content: "\e9c3";
|
||||
}
|
||||
i.cc.ETH:before {
|
||||
content: "\e9c4";
|
||||
}
|
||||
i.cc.ETH-alt:before {
|
||||
content: "\e9c5";
|
||||
}
|
||||
i.cc.FC2:before {
|
||||
content: "\e9c6";
|
||||
}
|
||||
i.cc.FC2-alt:before {
|
||||
content: "\e9c7";
|
||||
}
|
||||
i.cc.FCT:before {
|
||||
content: "\e9c8";
|
||||
}
|
||||
i.cc.FCT-alt:before {
|
||||
content: "\e9c9";
|
||||
}
|
||||
i.cc.FRK:before {
|
||||
content: "\e9ca";
|
||||
}
|
||||
i.cc.FRK-alt:before {
|
||||
content: "\e9cb";
|
||||
}
|
||||
i.cc.FTC:before {
|
||||
content: "\e9cc";
|
||||
}
|
||||
i.cc.FTC-alt:before {
|
||||
content: "\e9cd";
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
BIN
web/src/assets/exchanges.jpg
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
web/src/assets/fonts/cryptocoins.eot
Normal file
216
web/src/assets/fonts/cryptocoins.svg
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
web/src/assets/fonts/cryptocoins.ttf
Normal file
BIN
web/src/assets/fonts/cryptocoins.woff
Normal file
7
web/src/assets/i18n/en.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"PAGES": {
|
||||
"HOME": {
|
||||
"TITLE": "App works !"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
web/src/assets/images/centralised.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
web/src/assets/images/donate.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
web/src/assets/images/exchanges.jpg
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
web/src/assets/images/loop.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
web/src/assets/images/material.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
web/src/assets/images/page-logo.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
@@ -240,7 +240,7 @@ deltaY:b,delta2X:c,delta2Y:e,index:this.index}),this.prevDeltaX=a,this.prevDelta
|
||||
this.mouseY,"changed"))},handleMouseOut:function(){this.enabled&&this.rolledOver&&(this.leaveCursor||this.setIndex(void 0),this.forceShow=!1,this.hideCursor(),this.rolledOver=!1)},showCursorAt:function(a){var b=this.chart.categoryAxis;b&&this.setPosition(b.categoryToCoordinate(a),a)},setPosition:function(a,b){var c=this.chart,e=c.categoryAxis;if(e){var d,f;void 0===b&&(b=e.coordinateToValue(a));e.showBalloonAt(b,a);this.forceShow=!0;e.stickBalloonToCategory?c.rotate?this.fixHLine(a,0):this.fixVLine(a,
|
||||
0):(this.showCursor(),c.rotate?this.hhLine.translate(0,a):this.vvLine.translate(a,0));c.rotate?d=a:f=a;c.rotate?(this.vvLine&&this.vvLine.hide(),this.hhLine&&this.hhLine.show()):(this.hhLine&&this.hhLine.hide(),this.vvLine&&this.vvLine.show());this.updateFullLine();this.isHidden=!1;this.dispatchMovedEvent(f,d,"moved",!0)}},enableDrawing:function(a){this.enabled=!a;this.hideCursor();this.drawing=a},syncWithCursor:function(a,b){clearTimeout(this.syncTO);a&&(a.isHidden?this.hideCursor(!0):this.syncWithCursorReal(a,
|
||||
b))},isZooming:function(a){this.zooming=a},syncWithCursorReal:function(a,b){var c=a.vvLine,e=a.hhLine;this.index=a.index;this.forceShow=!0;this.zooming&&this.pan||this.showCursor(!0);this.hideGraphBalloons=b;this.justReleased=a.justReleased;this.zooming=a.zooming;this.index0=a.index0;this.mouseX0=a.mouseX0;this.mouseY0=a.mouseY0;this.mouse2X0=a.mouse2X0;this.mouse2Y0=a.mouse2Y0;this.timestamp0=a.timestamp0;this.prevDeltaX=a.prevDeltaX;this.prevDeltaY=a.prevDeltaY;this.prevDelta2X=a.prevDelta2X;this.prevDelta2Y=
|
||||
a.prevDelta2Y;this.fx=a.fx;this.fy=a.fy;a.zooming&&this.updateSelection();var d=a.mouseX,f=a.mouseY;this.rotate?(d=NaN,this.vvLine&&this.vvLine.hide(),this.hhLine&&e&&(isNaN(a.fy)?this.hhLine.translate(0,a.mouseY):this.fixHLine(a.fy,0))):(f=NaN,this.hhLine&&this.hhLine.hide(),this.vvLine&&c&&(isNaN(a.fx)?this.vvLine.translate(a.mouseX,0):this.fixVLine(a.fx,0)));this.dispatchMovedEvent(d,f,"moved",!0)}})})();(function(){var d=window.AmCharts;d.SimpleChartScrollbar=d.Class({construct:function(a){this.createEvents("zoomed","zoomStarted","zoomEnded");this.backgroundColor="#D4D4D4";this.backgroundAlpha=1;this.selectedBackgroundColor="#EFEFEF";this.scrollDuration=this.selectedBackgroundAlpha=1;this.resizeEnabled=!0;this.hideResizeGrips=!1;this.scrollbarHeight=20;this.updateOnReleaseOnly=!1;9>document.documentMode&&(this.updateOnReleaseOnly=!0);this.dragIconHeight=this.dragIconWidth=35;this.dragIcon="dragIconRoundBig";
|
||||
a.prevDelta2Y;this.fx=a.fx;this.fy=a.fy;a.zooming&&this.updateSelection();var d=a.mouseX,f=a.mouseY;this.rotate?(d=NaN,this.vvLine&&this.vvLine.hide(),this.hhLine&&e&&(isNaN(a.fy)?this.hhLine.translate(0,a.mouseY):this.fixHLine(a.fy,0))):(f=NaN,this.hhLine&&this.hhLine.hide(),this.vvLine&&c&&(isNaN(a.fx)?this.vvLine.translate(a.mouseX,0):this.fixVLine(a.fx,0)));this.dispatchMovedEvent(d,f,"moved",!0)}})})();(function(){var d=window.AmCharts;d.SimpleChartScrollbar=d.Class({construct:function(a){this.createEvents("zoomed","zoomStarted","zoomEnded");this.backgroundColor="#D4D4D4";this.backgroundAlpha=1;this.selectedBackgroundColor="#EFEFEF";this.scrollDuration=this.selectedBackgroundAlpha=1;this.resizeEnabled=!0;this.hideResizeGrips=!1;this.scrollbarHeight=20;this.updateOnReleaseOnly=!1;9>document.documentMode&&(this.updateOnReleaseOnly=!0);this.dragIconHeight=this.dragIconWidth=35;this.dragIcon="../images/dragIconRoundBig.svg";
|
||||
this.dragCursorHover="cursor: move; cursor: grab; cursor: -moz-grab; cursor: -webkit-grab;";this.dragCursorDown="cursor: move; cursor: grab; cursor: -moz-grabbing; cursor: -webkit-grabbing;";this.vResizeCursor="ns-resize";this.hResizeCursor="ew-resize";this.enabled=!0;this.percentStart=this.offset=0;this.percentEnd=1;d.applyTheme(this,a,"SimpleChartScrollbar")},getPercents:function(){var a=this.getDBox(),b=a.x,c=a.y,e=a.width,a=a.height;this.rotate?(b=1-c/this.height,c=1-(c+a)/this.height):(c=b/this.width,
|
||||
b=(b+e)/this.width);this.percentStart=c;this.percentEnd=b},draw:function(){var a=this;a.destroy();if(a.enabled){var b=a.chart.container,c=a.rotate,e=a.chart;e.panRequired=!0;var g=b.set();a.set=g;c?d.setCN(e,g,"scrollbar-vertical"):d.setCN(e,g,"scrollbar-horizontal");e.scrollbarsSet.push(g);var f,h;c?(f=a.scrollbarHeight,h=e.plotAreaHeight):(h=a.scrollbarHeight,f=e.plotAreaWidth);a.width=f;if((a.height=h)&&f){var k=d.rect(b,f,h,a.backgroundColor,a.backgroundAlpha,1,a.backgroundColor,a.backgroundAlpha);
|
||||
d.setCN(e,k,"scrollbar-bg");a.bg=k;g.push(k);k=d.rect(b,f,h,"#000",.005);g.push(k);a.invisibleBg=k;k.click(function(){a.handleBgClick()}).mouseover(function(){a.handleMouseOver()}).mouseout(function(){a.handleMouseOut()}).touchend(function(){a.handleBgClick()});k=d.rect(b,f,h,a.selectedBackgroundColor,a.selectedBackgroundAlpha);d.setCN(e,k,"scrollbar-bg-selected");a.selectedBG=k;g.push(k);f=d.rect(b,f,h,"#000",.005);a.dragger=f;g.push(f);f.mousedown(function(b){a.handleDragStart(b)}).mouseup(function(){a.handleDragStop()}).mouseover(function(){a.handleDraggerOver()}).mouseout(function(){a.handleMouseOut()}).touchstart(function(b){a.handleDragStart(b)}).touchend(function(){a.handleDragStop()});
|
||||
196
web/src/assets/js/dark.js
Normal file
@@ -0,0 +1,196 @@
|
||||
AmCharts.themes.dark = {
|
||||
|
||||
|
||||
|
||||
AmCoordinateChart: {
|
||||
colors: ["#ae85c9", "#aab9f7", "#b6d2ff", "#c9e6f2", "#c9f0e1", "#e8d685", "#e0ad63", "#d48652", "#d27362", "#495fba", "#7a629b", "#8881cc"]
|
||||
},
|
||||
|
||||
AmPieChart: {
|
||||
colors: ["#495fba", "#e8d685", "#ae85c9", "#c9f0e1", "#d48652", "#629b6d", "#719dc3", "#719dc3"]
|
||||
},
|
||||
|
||||
AmStockChart: {
|
||||
colors: ["#495fba", "#e8d685", "#ae85c9", "#c9f0e1", "#d48652", "#629b6d", "#719dc3", "#719dc3"]
|
||||
},
|
||||
|
||||
AmSlicedChart: {
|
||||
outlineAlpha: 1,
|
||||
outlineThickness: 2,
|
||||
labelTickColor: "#FFFFFF",
|
||||
labelTickAlpha: 0.3
|
||||
},
|
||||
|
||||
AmRectangularChart: {
|
||||
zoomOutButtonColor: '#FFFFFF',
|
||||
zoomOutButtonRollOverAlpha: 0.15,
|
||||
zoomOutButtonImage: "lensWhite.png"
|
||||
},
|
||||
|
||||
AxisBase: {
|
||||
axisColor: "#FFFFFF",
|
||||
axisAlpha: 0.3,
|
||||
gridAlpha: 0.1,
|
||||
gridColor: "#FFFFFF"
|
||||
},
|
||||
|
||||
ChartScrollbar: {
|
||||
backgroundColor: "#FFFFFF",
|
||||
backgroundAlpha: 0.2,
|
||||
graphFillAlpha: 0.5,
|
||||
graphLineAlpha: 0,
|
||||
selectedBackgroundColor: "#000000",
|
||||
selectedBackgroundAlpha: 0.25,
|
||||
gridAlpha: 0.15
|
||||
},
|
||||
|
||||
ChartCursor: {
|
||||
cursorColor: "#FFFFFF",
|
||||
color: "#000000",
|
||||
cursorAlpha: 0.5
|
||||
},
|
||||
|
||||
AmLegend: {
|
||||
color: "#919191"
|
||||
},
|
||||
|
||||
AmGraph: {
|
||||
lineAlpha: 0.9
|
||||
},
|
||||
|
||||
|
||||
GaugeArrow: {
|
||||
color: "#FFFFFF",
|
||||
alpha: 0.8,
|
||||
nailAlpha: 0,
|
||||
innerRadius: "40%",
|
||||
nailRadius: 15,
|
||||
startWidth: 15,
|
||||
borderAlpha: 0.8,
|
||||
nailBorderAlpha: 0
|
||||
},
|
||||
|
||||
GaugeAxis: {
|
||||
tickColor: "#FFFFFF",
|
||||
tickAlpha: 1,
|
||||
tickLength: 15,
|
||||
minorTickLength: 8,
|
||||
axisThickness: 3,
|
||||
axisColor: '#FFFFFF',
|
||||
axisAlpha: 1,
|
||||
bandAlpha: 0.8
|
||||
},
|
||||
|
||||
TrendLine: {
|
||||
lineColor: "#c03246",
|
||||
lineAlpha: 0.8
|
||||
},
|
||||
|
||||
// ammap
|
||||
AreasSettings: {
|
||||
alpha: 0.8,
|
||||
color: "#FFFFFF",
|
||||
colorSolid: "#000000",
|
||||
unlistedAreasAlpha: 0.4,
|
||||
unlistedAreasColor: "#FFFFFF",
|
||||
outlineColor: "#000000",
|
||||
outlineAlpha: 0.5,
|
||||
outlineThickness: 0.5,
|
||||
rollOverColor: "#3c5bdc",
|
||||
rollOverOutlineColor: "#000000",
|
||||
selectedOutlineColor: "#000000",
|
||||
selectedColor: "#f15135",
|
||||
unlistedAreasOutlineColor: "#000000",
|
||||
unlistedAreasOutlineAlpha: 0.5
|
||||
},
|
||||
|
||||
LinesSettings: {
|
||||
color: "#FFFFFF",
|
||||
alpha: 0.8
|
||||
},
|
||||
|
||||
ImagesSettings: {
|
||||
alpha: 0.8,
|
||||
labelColor: "#FFFFFF",
|
||||
color: "#FFFFFF",
|
||||
labelRollOverColor: "#3c5bdc"
|
||||
},
|
||||
|
||||
ZoomControl: {
|
||||
buttonRollOverColor: "#3c5bdc",
|
||||
buttonFillColor: "#f15135",
|
||||
buttonFillAlpha: 0.8,
|
||||
buttonBorderColor: "#FFFFFF",
|
||||
gridBackgroundColor: "#FFFFFF",
|
||||
gridAlpha: 0.8
|
||||
},
|
||||
|
||||
SmallMap: {
|
||||
mapColor: "#FFFFFF",
|
||||
rectangleColor: "#f15135",
|
||||
backgroundColor: "#000000",
|
||||
backgroundAlpha: 0.7,
|
||||
borderThickness: 1,
|
||||
borderAlpha: 0.8
|
||||
},
|
||||
|
||||
// the defaults below are set using CSS syntax, you can use any existing css property
|
||||
// if you don't use Stock chart, you can delete lines below
|
||||
PeriodSelector: {
|
||||
color: "#e7e7e7"
|
||||
},
|
||||
|
||||
PeriodButton: {
|
||||
color: "#e7e7e7",
|
||||
backgroundColor: "#282828",
|
||||
borderStyle: "solid",
|
||||
borderColor: "#585858",
|
||||
borderWidth: "1px",
|
||||
MozBorderRadius: "5px",
|
||||
borderRadius: "5px",
|
||||
margin: "1px",
|
||||
outline: "none"
|
||||
},
|
||||
|
||||
PeriodButtonSelected: {
|
||||
color: "#FFFFFF",
|
||||
backgroundColor: "#414c7b",
|
||||
borderStyle: "solid",
|
||||
borderColor: "#3f4b80",
|
||||
borderWidth: "1px",
|
||||
MozBorderRadius: "5px",
|
||||
borderRadius: "5px",
|
||||
margin: "1px",
|
||||
outline: "none"
|
||||
},
|
||||
|
||||
PeriodInputField: {
|
||||
color: "#e7e7e7",
|
||||
background: "transparent",
|
||||
borderStyle: "solid",
|
||||
borderColor: "#585858",
|
||||
borderWidth: "1px",
|
||||
outline: "none"
|
||||
},
|
||||
|
||||
DataSetSelector: {
|
||||
color: "#e7e7e7",
|
||||
selectedBackgroundColor: "#414c7b",
|
||||
rollOverBackgroundColor: "#000000"
|
||||
},
|
||||
|
||||
DataSetCompareList: {
|
||||
color: "#e7e7e7",
|
||||
borderStyle: "solid",
|
||||
borderColor: "#585858",
|
||||
borderWidth: "1px"
|
||||
},
|
||||
|
||||
DataSetSelect: {
|
||||
borderStyle: "solid",
|
||||
borderColor: "#585858",
|
||||
borderWidth: "1px",
|
||||
outline: "none"
|
||||
}
|
||||
|
||||
};
|
||||
|
Before Width: | Height: | Size: 664 B After Width: | Height: | Size: 664 B |