mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Merge pull request #69 from gloriousCode/master
GoCryptoTraderWeb phase 2
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# Cryptocurrency trading bot written in Golang
|
||||
|
||||

|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader)
|
||||
@@ -86,7 +86,7 @@ Make any neccessary changes to the config file.
|
||||
Run the application!
|
||||
|
||||
## Donations
|
||||
|
||||

|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to: 1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB
|
||||
|
||||
## Binaries
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
## GoCryptoTrader website
|
||||

|
||||
A website interface to interact with the main GoCryptoTrader application. It is developed with Angular 4 with support for Electron
|
||||
|
||||
## This is still in active development
|
||||
|
||||
20379
web/package-lock.json
generated
20379
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "gocryptotrader-web",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Front-end interface for GoCryptoTrader",
|
||||
"homepage": "https://github.com/thrasher-/gocryptotrader",
|
||||
"homepage": "https://github.com/thrasher-/gocryptotrader/web",
|
||||
"author": {
|
||||
"name": "Scott",
|
||||
"email": "scott@gloriousedge.com",
|
||||
@@ -46,25 +46,28 @@
|
||||
"e2e": "protractor ./protractor.conf.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^4.3.4",
|
||||
"@angular/cdk": "^2.0.0-beta.10",
|
||||
"@angular/common": "4.3.0",
|
||||
"@angular/compiler": "4.3.0",
|
||||
"@angular/core": "4.3.4",
|
||||
"@angular/forms": "4.3.0",
|
||||
"@angular/http": "4.3.0",
|
||||
"@angular/material": "^2.0.0-beta.10",
|
||||
"@angular/platform-browser": "4.3.0",
|
||||
"@angular/platform-browser-dynamic": "4.3.0",
|
||||
"@angular/router": "4.3.0",
|
||||
"@angular/animations": "5.0.2",
|
||||
"@angular/cdk": "5.0.0-rc0",
|
||||
"@angular/common": "5.0.2",
|
||||
"@angular/compiler": "5.0.2",
|
||||
"@angular/core": "5.0.2",
|
||||
"@angular/forms": "5.0.2",
|
||||
"@angular/http": "5.0.2",
|
||||
"@angular/material": "^5.0.0-rc0",
|
||||
"@angular/platform-browser": "5.0.2",
|
||||
"@angular/platform-browser-dynamic": "5.0.2",
|
||||
"@angular/router": "5.0.2",
|
||||
"@ngtools/webpack": "1.8.2",
|
||||
"core-js": "2.4.1",
|
||||
"enhanced-resolve": "3.3.0",
|
||||
"rxjs": "^5.4.3",
|
||||
"extract-text-webpack-plugin": "^3.0.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"rxjs": "^5.5.0",
|
||||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.2.1",
|
||||
"@angular/compiler-cli": "4.3.0",
|
||||
"@angular/cli": "^1.5.2",
|
||||
"@angular/compiler-cli": "5.0.2",
|
||||
"@types/bluebird": "3.5.8",
|
||||
"@types/core-js": "0.9.36",
|
||||
"@types/jasmine": "2.5.53",
|
||||
@@ -107,11 +110,11 @@
|
||||
"stylus-loader": "3.0.1",
|
||||
"ts-node": "3.1.0",
|
||||
"tslint": "5.4.3",
|
||||
"typescript": "2.4.1",
|
||||
"typescript": "2.4.2",
|
||||
"url-loader": "0.5.9",
|
||||
"webdriver-manager": "12.0.6",
|
||||
"webpack": "3.3.0",
|
||||
"webpack-dev-server": "2.5.0"
|
||||
"webpack": "3.8.1",
|
||||
"webpack-dev-server": "2.9.4"
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE.md"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,12 @@ import { HomeComponent } from './pages/home/home.component';
|
||||
import { SettingsComponent } from './pages/settings/settings.component';
|
||||
import { AboutComponent } from './pages/about/about.component';
|
||||
import { DashboardComponent } from './pages/dashboard/dashboard.component';
|
||||
import { WalletComponent } from './pages/wallet/wallet.component';
|
||||
import { DonateComponent } from './pages/donate/donate.component';
|
||||
import { HistoryComponent } from './pages/history/history.component';
|
||||
import { TradingComponent } from './pages/trading/trading.component';
|
||||
import { ExchangeGridComponent } from './pages/exchange-grid/exchange-grid.component';
|
||||
import { CurrencyListComponent } from './pages/currency-list/currency-list.component';
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
@@ -9,7 +15,7 @@ import { Routes, RouterModule } from '@angular/router';
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DashboardComponent
|
||||
component: HomeComponent
|
||||
},
|
||||
{
|
||||
path:'about',
|
||||
@@ -22,6 +28,31 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'settings',
|
||||
component: SettingsComponent
|
||||
},
|
||||
{
|
||||
path: 'wallet',
|
||||
component: WalletComponent
|
||||
}
|
||||
,
|
||||
{
|
||||
path: 'donate',
|
||||
component: DonateComponent
|
||||
},
|
||||
{
|
||||
path: 'history',
|
||||
component: HistoryComponent
|
||||
},
|
||||
{
|
||||
path: 'trading',
|
||||
component: TradingComponent
|
||||
},
|
||||
{
|
||||
path: 'exchange-grid',
|
||||
component: ExchangeGridComponent
|
||||
},
|
||||
{
|
||||
path: 'currency-list',
|
||||
component: CurrencyListComponent
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@@ -1,9 +1,58 @@
|
||||
<app-navbar></app-navbar>
|
||||
<app-navbar class="navbar mat-elevation-z6"></app-navbar>
|
||||
|
||||
<div class="sidebar"></div>
|
||||
|
||||
<div class="main">
|
||||
<div class="main-content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
.container {
|
||||
height: 100vh;
|
||||
min-height:100%;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px 70px 0;
|
||||
min-width: 86%;
|
||||
margin: 10px auto;
|
||||
overflow-x: hidden;
|
||||
margin-top:4rem;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 14%;
|
||||
position: fixed;
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.dashboard-highlight {
|
||||
color: green !important;
|
||||
}
|
||||
|
||||
.trading-highlight {
|
||||
color: orangered !important;
|
||||
}
|
||||
|
||||
.history-highlight {
|
||||
color: cornflowerblue !important;
|
||||
}
|
||||
|
||||
.wallet-highlight {
|
||||
color: blueviolet !important;
|
||||
}
|
||||
|
||||
.settings-highlight {
|
||||
color: magenta !important;
|
||||
}
|
||||
|
||||
.donate-highlight {
|
||||
color: goldenrod!important;
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit,ViewChild } from '@angular/core';
|
||||
import { ElectronService } from './providers/electron.service';
|
||||
import { MatSidenav } from '@angular/material';
|
||||
import { SidebarService } from './services/sidebar/sidebar.service';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -7,7 +10,11 @@ import { ElectronService } from './providers/electron.service';
|
||||
styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor(public electronService: ElectronService) {
|
||||
sidebarService: SidebarService
|
||||
public currentUrl:string;
|
||||
@ViewChild('sidenav') public sidenav: MatSidenav;
|
||||
|
||||
constructor(public electronService: ElectronService,something: SidebarService, private router:Router) {
|
||||
|
||||
if (electronService.isElectron()) {
|
||||
console.log('Mode electron');
|
||||
@@ -18,5 +25,19 @@ export class AppComponent {
|
||||
} else {
|
||||
console.log('Mode web');
|
||||
}
|
||||
|
||||
this.sidebarService = something;
|
||||
|
||||
router.events.subscribe(event => {
|
||||
|
||||
if (event instanceof NavigationEnd ) {
|
||||
console.log("current url",event.url); // event.url has current url
|
||||
this.currentUrl = event.url;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.sidebarService.setSidenav(this.sidenav);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,23 @@ import { NgModule, Injectable } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import {
|
||||
MdButtonModule,
|
||||
MdCardModule,
|
||||
MdMenuModule,
|
||||
MdToolbarModule,
|
||||
MdIconModule,
|
||||
MdFormFieldModule,
|
||||
MdInputModule,
|
||||
MdCheckboxModule,
|
||||
MdGridListModule,
|
||||
MdProgressSpinnerModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatMenuModule,
|
||||
MatToolbarModule,
|
||||
MatIconModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
MatSortModule,
|
||||
MatExpansionModule,
|
||||
MatLineModule,
|
||||
MatTooltipModule,
|
||||
MatTabsModule,
|
||||
} from '@angular/material';
|
||||
|
||||
|
||||
@@ -27,18 +34,40 @@ import { HomeComponent } from './pages/home/home.component';
|
||||
import { AboutComponent } from './pages/about/about.component';
|
||||
import { SettingsComponent } from './pages/settings/settings.component';
|
||||
import { DashboardComponent } from './pages/dashboard/dashboard.component';
|
||||
import { WalletComponent } from './pages/wallet/wallet.component';
|
||||
import { DonateComponent } from './pages/donate/donate.component';
|
||||
|
||||
//Shared
|
||||
import { NavbarComponent } from './shared/navbar/navbar.component';
|
||||
import { ExchangeCurrencyTickerComponent } from './shared/exchange-currency-ticker/exchange-currency-ticker.component';
|
||||
import { AllEnabledCurrencyTickersComponent } from './shared/all-enabled-currency-tickers/all-enabled-currency-tickers.component';
|
||||
import { ThemePickerComponent } from './shared/theme-picker/theme-picker';
|
||||
//services
|
||||
import { WebsocketService } from './services/websocket/websocket.service';
|
||||
import { WebsocketHandlerService } from './services/websocket-handler/websocket-handler.service';
|
||||
import { SidebarService } from './services/sidebar/sidebar.service';
|
||||
import { ElectronService } from './providers/electron.service';
|
||||
import { StyleManagerService } from './services/style-manager/style-manager.service';
|
||||
import { ThemeStorageService } from './services/theme-storage/theme-storage.service';
|
||||
|
||||
//Routing
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
import { Wallet } from './shared/classes/wallet';
|
||||
|
||||
|
||||
import * as Rx from 'rxjs/Rx';
|
||||
import { TradeHistoryComponent } from './shared/trade-history/trade-history.component';
|
||||
import { PriceHistoryComponent } from './shared/price-history/price-history.component';
|
||||
import { MyOrdersComponent } from './shared/my-orders/my-orders.component';
|
||||
import { OrdersComponent } from './shared/orders/orders.component';
|
||||
import { BuySellComponent } from './shared/buy-sell/buy-sell.component';
|
||||
import { SelectedCurrencyComponent } from './shared/selected-currency/selected-currency.component';
|
||||
import { TradingComponent } from './pages/trading/trading.component';
|
||||
import { HistoryComponent } from './pages/history/history.component';
|
||||
import { BuySellFormComponent } from './shared/buy-sell-form/buy-sell-form.component';
|
||||
import { ExchangeGridComponent } from './pages/exchange-grid/exchange-grid.component';
|
||||
import { CurrencyListComponent } from './pages/currency-list/currency-list.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@@ -50,7 +79,21 @@ import * as Rx from 'rxjs/Rx';
|
||||
SettingsComponent,
|
||||
DashboardComponent,
|
||||
ExchangeCurrencyTickerComponent,
|
||||
AllEnabledCurrencyTickersComponent
|
||||
AllEnabledCurrencyTickersComponent,
|
||||
WalletComponent,
|
||||
ThemePickerComponent,
|
||||
TradeHistoryComponent,
|
||||
PriceHistoryComponent,
|
||||
MyOrdersComponent,
|
||||
OrdersComponent,
|
||||
BuySellComponent,
|
||||
DonateComponent,
|
||||
SelectedCurrencyComponent,
|
||||
TradingComponent,
|
||||
HistoryComponent,
|
||||
BuySellFormComponent,
|
||||
ExchangeGridComponent,
|
||||
CurrencyListComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@@ -58,18 +101,32 @@ import * as Rx from 'rxjs/Rx';
|
||||
HttpModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
MdButtonModule,
|
||||
MdMenuModule,
|
||||
MdCardModule,
|
||||
MdToolbarModule,
|
||||
MdIconModule,
|
||||
MdFormFieldModule,
|
||||
MdInputModule,
|
||||
MdCheckboxModule,
|
||||
MdGridListModule,
|
||||
MdProgressSpinnerModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule,
|
||||
MatCardModule,
|
||||
MatToolbarModule,
|
||||
MatIconModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
MatSortModule,
|
||||
MatExpansionModule,
|
||||
MatLineModule,
|
||||
MatTooltipModule,
|
||||
MatTabsModule,
|
||||
],
|
||||
providers: [
|
||||
ElectronService,
|
||||
WebsocketService,
|
||||
WebsocketHandlerService,
|
||||
SidebarService,
|
||||
StyleManagerService,
|
||||
ThemeStorageService,
|
||||
],
|
||||
providers: [ElectronService,WebsocketService,WebsocketHandlerService],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
|
||||
35
web/src/app/pages/currency-list/currency-list.component.html
Normal file
35
web/src/app/pages/currency-list/currency-list.component.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<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>
|
||||
@@ -0,0 +1,9 @@
|
||||
.BTC {
|
||||
color:orange;
|
||||
}
|
||||
.LTC {
|
||||
color:silver;
|
||||
}
|
||||
.ETH {
|
||||
color:darkslategrey;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CurrencyListComponent } from './currency-list.component';
|
||||
|
||||
describe('CurrencyListComponent', () => {
|
||||
let component: CurrencyListComponent;
|
||||
let fixture: ComponentFixture<CurrencyListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CurrencyListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CurrencyListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/currency-list/currency-list.component.ts
Normal file
15
web/src/app/pages/currency-list/currency-list.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-currency-list',
|
||||
templateUrl: './currency-list.component.html',
|
||||
styleUrls: ['./currency-list.component.scss']
|
||||
})
|
||||
export class CurrencyListComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1,22 @@
|
||||
<app-all-enabled-currency-tickers></app-all-enabled-currency-tickers>
|
||||
|
||||
<button matTooltip="Trade" mat-fab color="accent" class="mat-fab mat-fab-bottom-right"><mat-icon >swap_horiz</mat-icon></button>
|
||||
<ng-template app-buy-sell></ng-template>
|
||||
<div style="width:97%;">
|
||||
<mat-grid-list cols="3" rowHeight="24rem">
|
||||
<mat-grid-tile [colspan]="tile.columns" [rowspan]="tile.rows" *ngFor="let tile of dashboard.tiles">
|
||||
<mat-card class="full-card">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{tile.title}}</mat-card-title>
|
||||
<mat-card-subtitle>{{tile.subTitle}}</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
{{tile.content}}
|
||||
</mat-card-content>
|
||||
<mat-card-footer>
|
||||
<button *ngIf="!expanded" (click)="expandTile(tile)" mat-button>EXPAND</button>
|
||||
<button *ngIf="expanded" (click)="resetTiles()" mat-button>RESTORE</button>
|
||||
</mat-card-footer>
|
||||
</mat-card>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
.full-card {
|
||||
margin: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::ng-deep mat-grid-tile.mat-grid-tile .mat-figure {
|
||||
align-items: initial;
|
||||
/*vertical alignment*/
|
||||
}
|
||||
|
||||
.mat-card-footer {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
.mat-fab {
|
||||
top: auto;
|
||||
right: 30px;
|
||||
bottom: 20px;
|
||||
left: auto;
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,65 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {Component, OnInit }from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss'],
|
||||
|
||||
@Component( {
|
||||
selector:'app-dashboard',
|
||||
templateUrl:'./dashboard.component.html',
|
||||
styleUrls:['./dashboard.component.scss'],
|
||||
})
|
||||
|
||||
export class DashboardComponent implements OnInit {
|
||||
constructor()
|
||||
{
|
||||
}
|
||||
public dashboard:any;
|
||||
public expanded:boolean = false;
|
||||
|
||||
ngOnInit() {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.resetTiles();
|
||||
}
|
||||
|
||||
public expandTile(tile:any) {
|
||||
for(var i = 0; i< this.dashboard.tiles.length; i++) {
|
||||
if(this.dashboard.tiles[i].title === tile.title ) {
|
||||
this.dashboard.tiles[i].rows = 2;
|
||||
this.dashboard.tiles[i].columns = 3;
|
||||
this.expanded = true;
|
||||
} else {
|
||||
this.dashboard.tiles[i].rows = 0;
|
||||
this.dashboard.tiles[i].columns = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public resetTiles() {
|
||||
this.expanded = false;
|
||||
this.dashboard = {tiles:[ {
|
||||
title:'Trade History:',
|
||||
subTitle:'Trade History',
|
||||
content:'<app-trade-history></app-trade-history>',
|
||||
columns:1,
|
||||
rows:2,
|
||||
}, {
|
||||
title:'Price History:',
|
||||
subTitle:'Price History',
|
||||
content:'<app-price-history></app-price-history>',
|
||||
columns:2,
|
||||
rows:1,
|
||||
}, {
|
||||
title:'My Orders:',
|
||||
subTitle:'My Orders',
|
||||
content:'<app-my-orders></app-my-orders>',
|
||||
columns:1,
|
||||
rows:1,
|
||||
}, {
|
||||
title:'Orders:',
|
||||
subTitle:'Orders',
|
||||
content:'<app-orders></app-orders>',
|
||||
columns:1,
|
||||
rows:1,
|
||||
},
|
||||
]};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
17
web/src/app/pages/donate/donate.component.html
Normal file
17
web/src/app/pages/donate/donate.component.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<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>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
13
web/src/app/pages/donate/donate.component.scss
Normal file
13
web/src/app/pages/donate/donate.component.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.BTC {
|
||||
color:orange;
|
||||
}
|
||||
|
||||
.full-card {
|
||||
width: 30%;
|
||||
margin: 0px auto !important;
|
||||
}
|
||||
|
||||
.heart {
|
||||
margin: 0px auto !important;
|
||||
display:flex;
|
||||
}
|
||||
25
web/src/app/pages/donate/donate.component.spec.ts
Normal file
25
web/src/app/pages/donate/donate.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DonateComponent } from './donate.component';
|
||||
|
||||
describe('DonateComponent', () => {
|
||||
let component: DonateComponent;
|
||||
let fixture: ComponentFixture<DonateComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DonateComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DonateComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/donate/donate.component.ts
Normal file
15
web/src/app/pages/donate/donate.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-donate',
|
||||
templateUrl: './donate.component.html',
|
||||
styleUrls: ['./donate.component.scss']
|
||||
})
|
||||
export class DonateComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
60
web/src/app/pages/exchange-grid/exchange-grid.component.html
Normal file
60
web/src/app/pages/exchange-grid/exchange-grid.component.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel >
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Poloniex
|
||||
</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><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>
|
||||
</mat-accordion>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExchangeGridComponent } from './exchange-grid.component';
|
||||
|
||||
describe('ExchangeGridComponent', () => {
|
||||
let component: ExchangeGridComponent;
|
||||
let fixture: ComponentFixture<ExchangeGridComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ExchangeGridComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ExchangeGridComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/exchange-grid/exchange-grid.component.ts
Normal file
15
web/src/app/pages/exchange-grid/exchange-grid.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-exchange-grid',
|
||||
templateUrl: './exchange-grid.component.html',
|
||||
styleUrls: ['./exchange-grid.component.scss']
|
||||
})
|
||||
export class ExchangeGridComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
3
web/src/app/pages/history/history.component.html
Normal file
3
web/src/app/pages/history/history.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<p>
|
||||
history works!
|
||||
</p>
|
||||
0
web/src/app/pages/history/history.component.scss
Normal file
0
web/src/app/pages/history/history.component.scss
Normal file
25
web/src/app/pages/history/history.component.spec.ts
Normal file
25
web/src/app/pages/history/history.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HistoryComponent } from './history.component';
|
||||
|
||||
describe('HistoryComponent', () => {
|
||||
let component: HistoryComponent;
|
||||
let fixture: ComponentFixture<HistoryComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HistoryComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HistoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/history/history.component.ts
Normal file
15
web/src/app/pages/history/history.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-history',
|
||||
templateUrl: './history.component.html',
|
||||
styleUrls: ['./history.component.scss']
|
||||
})
|
||||
export class HistoryComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
<div class="container">
|
||||
</div>
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,3 @@
|
||||
.example-card {
|
||||
width: 400px;
|
||||
}
|
||||
@@ -1,93 +1,79 @@
|
||||
<div class="loading-spinner" *ngIf="settings === null">
|
||||
<md-progress-spinner mode="indeterminate"></md-progress-spinner>
|
||||
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
|
||||
</div>
|
||||
<div *ngIf="settings !== null">
|
||||
<button (click)="saveSettings()" md-fab color="accent" class="md-fab md-fab-bottom-right">Save</button>
|
||||
<form *ngIf="settings.SMSGlobal != null">
|
||||
<md-card class="exchange-card">
|
||||
<md-card-header>
|
||||
<md-card-title>SMS Global Settings</md-card-title>
|
||||
</md-card-header>
|
||||
<md-card-content>
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<md-checkbox name="smsEnabled" [(ngModel)]="settings.SMSGlobal.Enabled">Enabled</md-checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<md-grid-list cols="2" rowHeight="3:1">
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="smsUsername" [(ngModel)]="settings.SMSGlobal.Username" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Username">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="smsPassword" [(ngModel)]="settings.SMSGlobal.Password" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Password">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
<md-grid-list cols="3" rowHeight="2:1" *ngFor="let contact of settings.SMSGlobal?.Contacts">
|
||||
<md-grid-tile>
|
||||
<md-checkbox name="contactEnabled" [disabled]="!settings?.SMSGlobal.Enabled" [(ngModel)]="contact.Enabled">Enabled</md-checkbox>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="contactUsername" [(ngModel)]="contact.Name" [disabled]="!settings.SMSGlobal.Enabled || !contact.Enabled" placeholder="Contact Name">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="contactPassword" [(ngModel)]="contact.Number" [disabled]="!settings.SMSGlobal.Enabled || !contact.Enabled" placeholder="Contact Number">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
</form>
|
||||
|
||||
<form *ngFor="let exchange of settings?.Exchanges">
|
||||
<md-card class="exchange-card">
|
||||
<md-card-header>
|
||||
<md-card-title>{{exchange.Name}} Exchange Settings</md-card-title>
|
||||
</md-card-header>
|
||||
<md-card-content>
|
||||
<table cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<md-checkbox name="exchangeEnabled" [(ngModel)]="exchange.Enabled">Enabled</md-checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<md-grid-list cols="3" rowHeight="2:1">
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="apiKey" [(ngModel)]="exchange.APIKey" [disabled]="!exchange.Enabled" placeholder="Exchange API Key">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="apiSecretKey" [(ngModel)]="exchange.APISecret" [disabled]="!exchange.Enabled" placeholder="Exchange API Secret Key">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
<md-form-field>
|
||||
<input mdInput name="apiClientId" [(ngModel)]="exchange.ClientID" [disabled]="!exchange.Enabled" placeholder="Exchange API ClientID (optional)">
|
||||
</md-form-field>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
<button matTooltip="Save" (click)="saveSettings()" mat-fab color="accent" class="mat-fab mat-fab-bottom-right"><mat-icon >save</mat-icon></button>
|
||||
|
||||
<label>Enabled Currencies</label>
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel *ngIf="settings.SMSGlobal != null">
|
||||
<mat-expansion-panel-header >
|
||||
<mat-panel-title>
|
||||
SMS Global
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
SMS configuration and contact management
|
||||
<mat-icon>phone_iphone</mat-icon>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<form class="form-content">
|
||||
<mat-checkbox name="smsEnabled" [(ngModel)]="settings.SMSGlobal.Enabled">Enabled</mat-checkbox>
|
||||
<div mat-line></div>
|
||||
<mat-form-field>
|
||||
<input matInput name="smsUsername" [(ngModel)]="settings.SMSGlobal.Username" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Username">
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="smsPassword" [(ngModel)]="settings.SMSGlobal.Password" [disabled]="!settings?.SMSGlobal.Enabled" placeholder="Password">
|
||||
</mat-form-field>
|
||||
|
||||
<md-grid-list cols="6" rowHeight="2:1">
|
||||
<md-grid-tile *ngFor="let currency of exchange.AvailablePairs.split(',')">
|
||||
<md-checkbox name="availableCurrency" [disabled]="true || !exchange.Enabled">{{currency}}</md-checkbox>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
</form>
|
||||
<div *ngFor="let contact of settings.SMSGlobal?.Contacts">
|
||||
<mat-checkbox name="contactEnabled" [disabled]="!settings?.SMSGlobal.Enabled" [(ngModel)]="contact.Enabled">Enabled</mat-checkbox>
|
||||
<div mat-line></div>
|
||||
<mat-form-field>
|
||||
<input matInput name="contactUsername" [(ngModel)]="contact.Name" [disabled]="!settings.SMSGlobal.Enabled || !contact.Enabled" placeholder="Contact Name" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput name="contactPassword" [(ngModel)]="contact.Number" [disabled]="!settings.SMSGlobal.Enabled || !contact.Enabled" placeholder="Contact Number" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
</mat-expansion-panel>
|
||||
|
||||
|
||||
<mat-expansion-panel *ngFor="let exchange of settings?.Exchanges">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{exchange.Name}}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
Exchange Settings
|
||||
<mat-icon>attach_money</mat-icon>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<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>
|
||||
</form>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
||||
</div>
|
||||
@@ -1,20 +1,12 @@
|
||||
.example-form {
|
||||
min-width: 150px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.example-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.exchange-card {
|
||||
margin-bottom: 20px;
|
||||
width: 1000px;
|
||||
}
|
||||
|
||||
.md-fab {
|
||||
margin: 0;
|
||||
// FAB
|
||||
.mat-fab {
|
||||
top: auto;
|
||||
right: 30px;
|
||||
bottom: 20px;
|
||||
left: auto;
|
||||
position: fixed;
|
||||
bottom: 5%;
|
||||
right: 2%;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
margin: 20px;
|
||||
}
|
||||
2
web/src/app/pages/trading/trading.component.html
Normal file
2
web/src/app/pages/trading/trading.component.html
Normal file
@@ -0,0 +1,2 @@
|
||||
<app-buy-sell></app-buy-sell>
|
||||
<button matTooltip="Trade" mat-fab color="accent" class="mat-fab mat-fab-bottom-right"><mat-icon >swap_horiz</mat-icon></button>
|
||||
9
web/src/app/pages/trading/trading.component.scss
Normal file
9
web/src/app/pages/trading/trading.component.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
.mat-fab {
|
||||
top: auto;
|
||||
right: 30px;
|
||||
bottom: 20px;
|
||||
left: auto;
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
}
|
||||
25
web/src/app/pages/trading/trading.component.spec.ts
Normal file
25
web/src/app/pages/trading/trading.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TradingComponent } from './trading.component';
|
||||
|
||||
describe('TradingComponent', () => {
|
||||
let component: TradingComponent;
|
||||
let fixture: ComponentFixture<TradingComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ TradingComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TradingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/pages/trading/trading.component.ts
Normal file
15
web/src/app/pages/trading/trading.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-trading',
|
||||
templateUrl: './trading.component.html',
|
||||
styleUrls: ['./trading.component.scss']
|
||||
})
|
||||
export class TradingComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
114
web/src/app/pages/wallet/wallet.component.html
Normal file
114
web/src/app/pages/wallet/wallet.component.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<div class="loading-spinner" *ngIf="wallet === null">
|
||||
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
|
||||
</div>
|
||||
<mat-accordion *ngIf="wallet !== null">
|
||||
<mat-expansion-panel [expanded]="true">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Coin Totals
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coin_totals">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Online Summary
|
||||
</mat-panel-title>
|
||||
</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>
|
||||
<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>
|
||||
<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>
|
||||
<h4 mat-line>Address: {{coin.address}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Offline Summary
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.offline_summary.BTC">
|
||||
<mat-icon mat-list-icon class="BTC">{{coinIcon('BTC')}}</mat-icon>
|
||||
<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>
|
||||
<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>
|
||||
<h4 mat-line>Address: {{coin.address}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}{{coin.coin}} - {{coin.percentage}}%</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Online Coins
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coins_online">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Offline Coins
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let coin of wallet?.coins_offline">
|
||||
<mat-icon mat-list-icon [ngClass]="coin.coin">{{coin.icon}}</mat-icon>
|
||||
<h4 mat-line>{{coin.coin}}</h4>
|
||||
<h4 mat-line>{{coin.balance}}</h4>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</mat-expansion-panel>
|
||||
|
||||
|
||||
|
||||
|
||||
</mat-accordion>
|
||||
14
web/src/app/pages/wallet/wallet.component.scss
Normal file
14
web/src/app/pages/wallet/wallet.component.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.wallet-card {
|
||||
width: 80%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.BTC {
|
||||
color:orange;
|
||||
}
|
||||
.LTC {
|
||||
color:silver;
|
||||
}
|
||||
.ETH {
|
||||
color:darkslategrey;
|
||||
}
|
||||
25
web/src/app/pages/wallet/wallet.component.spec.ts
Normal file
25
web/src/app/pages/wallet/wallet.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { WalletComponent } from './wallet.component';
|
||||
|
||||
describe('WalletComponent', () => {
|
||||
let component: WalletComponent;
|
||||
let fixture: ComponentFixture<WalletComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ WalletComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(WalletComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
87
web/src/app/pages/wallet/wallet.component.ts
Normal file
87
web/src/app/pages/wallet/wallet.component.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketHandlerService } from './../../services/websocket-handler/websocket-handler.service';
|
||||
import { Wallet, CoinTotal } from './../../shared/classes/wallet';
|
||||
import {Sort} from '@angular/material';
|
||||
|
||||
@Component({
|
||||
selector: 'app-wallet',
|
||||
templateUrl: './wallet.component.html',
|
||||
styleUrls: ['./wallet.component.scss']
|
||||
})
|
||||
|
||||
export class WalletComponent implements OnInit {
|
||||
private ws: WebsocketHandlerService;
|
||||
private failCount = 0;
|
||||
private timer: any;
|
||||
public wallet: Wallet;
|
||||
displayedColumns = ['coin', 'balance'];
|
||||
|
||||
private getWalletMessage = {
|
||||
Event: 'GetPortfolio',
|
||||
data: null,
|
||||
};
|
||||
|
||||
constructor(private websocketHandler: WebsocketHandlerService) {
|
||||
this.wallet= null;
|
||||
this.ws = websocketHandler;
|
||||
this.ws.messages.subscribe(msg => {
|
||||
if (msg.Event === 'GetPortfolio') {
|
||||
console.log(JSON.stringify(msg.data));
|
||||
this.wallet = <Wallet>msg.data;
|
||||
|
||||
this.attachIcon(this.wallet.coin_totals);
|
||||
this.attachIcon(this.wallet.coins_offline);
|
||||
this.attachIcon(this.wallet.coins_online);
|
||||
|
||||
this.attachIcon(this.wallet.offline_summary.BTC);
|
||||
this.attachIcon(this.wallet.offline_summary.ETH);
|
||||
this.attachIcon(this.wallet.offline_summary.LTC);
|
||||
|
||||
this.attachIcon(this.wallet.online_summary.BTC);
|
||||
this.attachIcon(this.wallet.online_summary.ETH);
|
||||
this.attachIcon(this.wallet.online_summary.LTC);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public coinIcon(coin:string) :string {
|
||||
switch(coin) {
|
||||
case "BTC": return "attach_money";
|
||||
case "LTC": return "attach_money";
|
||||
case "ETH": return "attach_money";
|
||||
}
|
||||
}
|
||||
|
||||
public attachIcon(items: CoinTotal[]): void {
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i].icon = this.coinIcon(items[i].coin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
web/src/app/services/sidebar/sidebar.service.spec.ts
Normal file
15
web/src/app/services/sidebar/sidebar.service.spec.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { SidebarService } from './sidebar.service';
|
||||
|
||||
describe('SidebarService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [SidebarService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([SidebarService], (service: SidebarService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
49
web/src/app/services/sidebar/sidebar.service.ts
Normal file
49
web/src/app/services/sidebar/sidebar.service.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSidenav, MatDrawerToggleResult } from '@angular/material';
|
||||
|
||||
@Injectable()
|
||||
export class SidebarService {
|
||||
private sidenav: MatSidenav;
|
||||
|
||||
/**
|
||||
* Setter for sidenav.
|
||||
*
|
||||
* @param {MatSidnav} sidenav
|
||||
*/
|
||||
public setSidenav(sidenav: MatSidenav) {
|
||||
this.sidenav = sidenav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open this sidenav, and return a Promise that will resolve when it's fully opened (or get rejected if it didn't).
|
||||
*
|
||||
* @returns Promise<MatSidnavToggleResult>
|
||||
*/
|
||||
public open(): Promise<MatDrawerToggleResult> {
|
||||
this.sidenav.open();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this sidenav, and return a Promise that will resolve when it's fully closed (or get rejected if it didn't).
|
||||
*
|
||||
* @returns Promise<MatSidnavToggleResult>
|
||||
*/
|
||||
public close(): Promise<MatDrawerToggleResult> {
|
||||
this.sidenav.close();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle this sidenav. This is equivalent to calling open() when it's already opened, or close() when it's closed.
|
||||
*
|
||||
* @param {boolean} isOpen Whether the sidenav should be open.
|
||||
*
|
||||
* @returns {Promise<MatSidnavToggleResult>}
|
||||
*/
|
||||
public toggle(isOpen?: boolean): Promise<MatDrawerToggleResult> {
|
||||
this.sidenav.toggle(isOpen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import {inject, TestBed} from '@angular/core/testing';
|
||||
import {HttpModule} from '@angular/http';
|
||||
import {StyleManagerComponent} from './style-manager.component';
|
||||
|
||||
|
||||
describe('StyleManager', () => {
|
||||
let styleManager: StyleManagerComponent;
|
||||
|
||||
beforeEach(() => TestBed.configureTestingModule({
|
||||
imports: [HttpModule],
|
||||
providers: [StyleManagerComponent]
|
||||
}));
|
||||
|
||||
beforeEach(inject([StyleManagerComponent], (sm: StyleManagerComponent) => {
|
||||
styleManager = sm;
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
let links = document.head.querySelectorAll('link');
|
||||
for (let link of Array.prototype.slice.call(links)) {
|
||||
if (link.className.includes('style-manager-')) {
|
||||
document.head.removeChild(link);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should add stylesheet to head', () => {
|
||||
styleManager.setStyle('test', 'test.css');
|
||||
let styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
|
||||
expect(styleEl).not.toBeNull();
|
||||
expect(styleEl.href.endsWith('test.css')).toBe(true);
|
||||
});
|
||||
|
||||
it('should change existing stylesheet', () => {
|
||||
styleManager.setStyle('test', 'test.css');
|
||||
let styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
|
||||
expect(styleEl).not.toBeNull();
|
||||
expect(styleEl.href.endsWith('test.css')).toBe(true);
|
||||
|
||||
styleManager.setStyle('test', 'new.css');
|
||||
expect(styleEl.href.endsWith('new.css')).toBe(true);
|
||||
});
|
||||
|
||||
it('should remove existing stylesheet', () => {
|
||||
styleManager.setStyle('test', 'test.css');
|
||||
let styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
|
||||
expect(styleEl).not.toBeNull();
|
||||
expect(styleEl.href.endsWith('test.css')).toBe(true);
|
||||
|
||||
styleManager.removeStyle('test');
|
||||
styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
|
||||
expect(styleEl).toBeNull();
|
||||
});
|
||||
});
|
||||
44
web/src/app/services/style-manager/style-manager.service.ts
Normal file
44
web/src/app/services/style-manager/style-manager.service.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
/**
|
||||
* Class for managing stylesheets. Stylesheets are loaded into named slots so that they can be
|
||||
* removed or changed later.
|
||||
*/
|
||||
@Injectable()
|
||||
export class StyleManagerService {
|
||||
/**
|
||||
* Set the stylesheet with the specified key.
|
||||
*/
|
||||
setStyle(key: string, href: string) {
|
||||
getLinkElementForKey(key).setAttribute('href', href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the stylesheet with the specified key.
|
||||
*/
|
||||
removeStyle(key: string) {
|
||||
const existingLinkElement = getExistingLinkElementByKey(key);
|
||||
if (existingLinkElement) {
|
||||
document.head.removeChild(existingLinkElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLinkElementForKey(key: string) {
|
||||
return getExistingLinkElementByKey(key) || createLinkElementWithKey(key);
|
||||
}
|
||||
|
||||
function getExistingLinkElementByKey(key: string) {
|
||||
return document.head.querySelector(`link[rel="stylesheet"].${getClassNameForKey(key)}`);
|
||||
}
|
||||
|
||||
function createLinkElementWithKey(key: string) {
|
||||
const linkEl = document.createElement('link');
|
||||
linkEl.setAttribute('rel', 'stylesheet');
|
||||
linkEl.classList.add(getClassNameForKey(key));
|
||||
document.head.appendChild(linkEl);
|
||||
return linkEl;
|
||||
}
|
||||
|
||||
function getClassNameForKey(key: string) {
|
||||
return `style-manager-${key}`;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import {ThemeStorageService} from './theme-storage.service';
|
||||
|
||||
|
||||
const testStorageKey = ThemeStorageService.storageKey;
|
||||
const testTheme = {
|
||||
primary: '#000000',
|
||||
accent: '#ffffff',
|
||||
href: 'test/path/to/theme'
|
||||
};
|
||||
const createTestData = () => {
|
||||
window.localStorage[testStorageKey] = JSON.stringify(testTheme);
|
||||
};
|
||||
const clearTestData = () => {
|
||||
window.localStorage.clear();
|
||||
};
|
||||
|
||||
describe('ThemeStorage Service', () => {
|
||||
const service = new ThemeStorageService();
|
||||
const getCurrTheme = () => JSON.parse(window.localStorage.getItem(testStorageKey));
|
||||
const secondTestTheme = {
|
||||
primary: '#666666',
|
||||
accent: '#333333',
|
||||
href: 'some/cool/path'
|
||||
};
|
||||
|
||||
beforeEach(createTestData);
|
||||
afterEach(clearTestData);
|
||||
|
||||
it('should set the current theme', () => {
|
||||
expect(getCurrTheme()).toEqual(testTheme);
|
||||
service.storeTheme(secondTestTheme);
|
||||
expect(getCurrTheme()).toEqual(secondTestTheme);
|
||||
});
|
||||
|
||||
it('should get the current theme', () => {
|
||||
const theme = service.getStoredTheme();
|
||||
expect(theme).toEqual(testTheme);
|
||||
});
|
||||
|
||||
it('should clear the stored theme data', () => {
|
||||
expect(getCurrTheme()).not.toBeNull();
|
||||
service.clearStorage();
|
||||
expect(getCurrTheme()).toBeNull();
|
||||
});
|
||||
|
||||
it('should emit an event when setTheme is called', () => {
|
||||
spyOn(service.onThemeUpdate, 'emit');
|
||||
service.storeTheme(secondTestTheme);
|
||||
expect(service.onThemeUpdate.emit).toHaveBeenCalled();
|
||||
expect(service.onThemeUpdate.emit).toHaveBeenCalledWith(secondTestTheme);
|
||||
});
|
||||
});
|
||||
39
web/src/app/services/theme-storage/theme-storage.service.ts
Normal file
39
web/src/app/services/theme-storage/theme-storage.service.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {Injectable, EventEmitter} from '@angular/core';
|
||||
|
||||
export interface DocsSiteTheme {
|
||||
href: string;
|
||||
accent: string;
|
||||
primary: string;
|
||||
isDark?: boolean;
|
||||
isDefault?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ThemeStorageService {
|
||||
static storageKey = 'docs-theme-storage-current';
|
||||
|
||||
public onThemeUpdate: EventEmitter<DocsSiteTheme> = new EventEmitter<DocsSiteTheme>();
|
||||
|
||||
public storeTheme(theme: DocsSiteTheme) {
|
||||
try {
|
||||
window.localStorage[ThemeStorageService.storageKey] = JSON.stringify(theme);
|
||||
} catch (e) { }
|
||||
|
||||
this.onThemeUpdate.emit(theme);
|
||||
}
|
||||
|
||||
public getStoredTheme(): DocsSiteTheme {
|
||||
try {
|
||||
return JSON.parse(window.localStorage[ThemeStorageService.storageKey] || null);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public clearStorage() {
|
||||
try {
|
||||
window.localStorage.removeItem(ThemeStorageService.storageKey);
|
||||
} catch (e) { }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import * as Rx from 'rxjs/Rx';
|
||||
import {Subject, Observable, Observer } from 'rxjs/Rx';
|
||||
|
||||
@Injectable()
|
||||
export class WebsocketService {
|
||||
constructor() { }
|
||||
|
||||
private subject: Rx.Subject<MessageEvent>;
|
||||
private subject: Subject<MessageEvent>;
|
||||
|
||||
public connect(url): Rx.Subject<MessageEvent> {
|
||||
public connect(url): Subject<MessageEvent> {
|
||||
if (!this.subject) {
|
||||
this.subject = this.create(url);
|
||||
}
|
||||
@@ -21,11 +21,11 @@ export class WebsocketService {
|
||||
|
||||
private isAuth = false;
|
||||
|
||||
private create(url): Rx.Subject<MessageEvent> {
|
||||
private create(url): Subject<MessageEvent> {
|
||||
let ws = new WebSocket(url);
|
||||
|
||||
let observable = Rx.Observable.create(
|
||||
(obs: Rx.Observer<MessageEvent>) => {
|
||||
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);
|
||||
@@ -40,6 +40,6 @@ let observer = {
|
||||
}
|
||||
}
|
||||
}
|
||||
return Rx.Subject.create(observer, observable);
|
||||
return Subject.create(observer, observable);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="loading-spinner" *ngIf="tickerCards === null || tickerCards.length === 0">
|
||||
<md-progress-spinner mode="indeterminate"></md-progress-spinner>
|
||||
<mat-progress-spinner color="accent" mode="indeterminate"></mat-progress-spinner>
|
||||
</div>
|
||||
<md-grid-list cols="4" rowHeight="4:3" >
|
||||
<md-grid-tile *ngFor="let ticker of tickerCards">
|
||||
<mat-grid-list cols="4" rowHeight="4:3" >
|
||||
<mat-grid-tile *ngFor="let ticker of tickerCards">
|
||||
<app-exchange-currency-ticker [ticker]="ticker" ></app-exchange-currency-ticker>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<p>
|
||||
buy-sell-form works!
|
||||
</p>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BuySellFormComponent } from './buy-sell-form.component';
|
||||
|
||||
describe('BuySellFormComponent', () => {
|
||||
let component: BuySellFormComponent;
|
||||
let fixture: ComponentFixture<BuySellFormComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BuySellFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BuySellFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/buy-sell-form/buy-sell-form.component.ts
Normal file
15
web/src/app/shared/buy-sell-form/buy-sell-form.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-buy-sell-form',
|
||||
templateUrl: './buy-sell-form.component.html',
|
||||
styleUrls: ['./buy-sell-form.component.scss']
|
||||
})
|
||||
export class BuySellFormComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
14
web/src/app/shared/buy-sell/buy-sell.component.html
Normal file
14
web/src/app/shared/buy-sell/buy-sell.component.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<mat-tab-group>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
BUY
|
||||
</ng-template>
|
||||
<app-buy-sell-form></app-buy-sell-form>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
SELL
|
||||
</ng-template>
|
||||
<app-buy-sell-form></app-buy-sell-form>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
0
web/src/app/shared/buy-sell/buy-sell.component.scss
Normal file
0
web/src/app/shared/buy-sell/buy-sell.component.scss
Normal file
25
web/src/app/shared/buy-sell/buy-sell.component.spec.ts
Normal file
25
web/src/app/shared/buy-sell/buy-sell.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BuySellComponent } from './buy-sell.component';
|
||||
|
||||
describe('BuySellComponent', () => {
|
||||
let component: BuySellComponent;
|
||||
let fixture: ComponentFixture<BuySellComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BuySellComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BuySellComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/buy-sell/buy-sell.component.ts
Normal file
15
web/src/app/shared/buy-sell/buy-sell.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit,Directive, ViewContainerRef } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-buy-sell',
|
||||
templateUrl: './buy-sell.component.html',
|
||||
styleUrls: ['./buy-sell.component.scss']
|
||||
})
|
||||
export class BuySellComponent implements OnInit {
|
||||
|
||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
0
web/src/app/shared/classes/config.ts
Normal file
0
web/src/app/shared/classes/config.ts
Normal file
22
web/src/app/shared/classes/wallet.ts
Normal file
22
web/src/app/shared/classes/wallet.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
export interface CoinTotal {
|
||||
coin: string;
|
||||
balance: number;
|
||||
percentage: number;
|
||||
address: string;
|
||||
icon:string;
|
||||
}
|
||||
|
||||
export interface Summary {
|
||||
BTC: CoinTotal[];
|
||||
ETH: CoinTotal[];
|
||||
LTC: CoinTotal[];
|
||||
}
|
||||
|
||||
export interface Wallet {
|
||||
coin_totals: CoinTotal[];
|
||||
coins_offline: CoinTotal[];
|
||||
offline_summary: Summary;
|
||||
coins_online: CoinTotal[];
|
||||
online_summary: Summary;
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
<md-card class="exchange-card one-time-animation" >
|
||||
<md-card-header>
|
||||
<md-card-title>{{ticker?.Exchange}} {{ticker?.CurrencyPair}} Ticker update</md-card-title>
|
||||
</md-card-header>
|
||||
<md-card-content>
|
||||
<md-grid-list cols="3" rowHeight="16:9" >
|
||||
<md-grid-tile>
|
||||
<mat-card class="exchange-card one-time-animation" >
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{ticker?.Exchange}} {{ticker?.CurrencyPair}} Ticker update</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<mat-grid-list cols="3" rowHeight="16:9" >
|
||||
<mat-grid-tile>
|
||||
<p>Last: {{ticker?.Last | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<p> Low: {{ticker?.Low | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<p> High: {{ticker?.High | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
</mat-grid-tile>
|
||||
|
||||
<md-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<p> Bid: {{ticker?.Bid | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<p> Ask: {{ticker?.Ask | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
<md-grid-tile>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<p>Volume: {{ticker?.Volume | number:'1.0-1'}}</p>
|
||||
</md-grid-tile>
|
||||
</md-grid-list>
|
||||
</md-card-content>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</mat-card-content>
|
||||
|
||||
|
||||
5
web/src/app/shared/my-orders/my-orders.component.html
Normal file
5
web/src/app/shared/my-orders/my-orders.component.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<mat-card class="my-orders-card" flex="33">
|
||||
<mat-card-header>
|
||||
<mat-card-title>My Orders</mat-card-title>
|
||||
</mat-card-header>
|
||||
</mat-card>
|
||||
25
web/src/app/shared/my-orders/my-orders.component.spec.ts
Normal file
25
web/src/app/shared/my-orders/my-orders.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MyOrdersComponent } from './my-orders.component';
|
||||
|
||||
describe('MyOrdersComponent', () => {
|
||||
let component: MyOrdersComponent;
|
||||
let fixture: ComponentFixture<MyOrdersComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MyOrdersComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MyOrdersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/my-orders/my-orders.component.ts
Normal file
15
web/src/app/shared/my-orders/my-orders.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-orders',
|
||||
templateUrl: './my-orders.component.html',
|
||||
styleUrls: ['./my-orders.component.scss']
|
||||
})
|
||||
export class MyOrdersComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
<!-- TODO: figure out if the <nav> should go inside of a <header> element. -->
|
||||
<nav class="docs-navbar">
|
||||
<md-toolbar color="primary">
|
||||
<a md-button class="docs-button" routerLink="/" aria-label="Angular Material">
|
||||
<span>Logo</span>
|
||||
</a>
|
||||
<a md-button class="docs-button" routerLink="dashboard">Dashboard</a>
|
||||
<a md-button class="docs-button" routerLink="about">Wallet Summary</a>
|
||||
<a md-button class="docs-button" routerLink="settings">Settings</a>
|
||||
<a md-button class="docs-button" routerLink="about">Help</a>
|
||||
<div class="flex-spacer"></div>
|
||||
<a md-button class="docs-button" href="https://github.com/thrasher-/gocryptotrader/issues" aria-label="GitHub Repository">
|
||||
Report issue
|
||||
</a>
|
||||
</md-toolbar>
|
||||
<mat-toolbar color="primary">
|
||||
<a (click)="sidebarService.toggle()" class="material-icons"></a>
|
||||
<a mat-button class="docs-button" routerLink="/" aria-label="Angular Material">
|
||||
<span>GoCryptoTrader</span>
|
||||
</a>
|
||||
<app-selected-currency></app-selected-currency>
|
||||
<div class="flex-spacer"></div>
|
||||
<theme-picker></theme-picker>
|
||||
|
||||
|
||||
</mat-toolbar>
|
||||
</nav>
|
||||
@@ -0,0 +1,7 @@
|
||||
.material-icons {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.flex-spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { SidebarService } from './../../services/sidebar/sidebar.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
@@ -6,8 +7,10 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./navbar.component.scss']
|
||||
})
|
||||
export class NavbarComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
sidebarService: SidebarService
|
||||
constructor(something: SidebarService) {
|
||||
this.sidebarService = something;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
5
web/src/app/shared/orders/orders.component.html
Normal file
5
web/src/app/shared/orders/orders.component.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<mat-card class="orders-card" flex="33">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Orders</mat-card-title>
|
||||
</mat-card-header>
|
||||
</mat-card>
|
||||
0
web/src/app/shared/orders/orders.component.scss
Normal file
0
web/src/app/shared/orders/orders.component.scss
Normal file
25
web/src/app/shared/orders/orders.component.spec.ts
Normal file
25
web/src/app/shared/orders/orders.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OrdersComponent } from './orders.component';
|
||||
|
||||
describe('OrdersComponent', () => {
|
||||
let component: OrdersComponent;
|
||||
let fixture: ComponentFixture<OrdersComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ OrdersComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(OrdersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/orders/orders.component.ts
Normal file
15
web/src/app/shared/orders/orders.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-orders',
|
||||
templateUrl: './orders.component.html',
|
||||
styleUrls: ['./orders.component.scss']
|
||||
})
|
||||
export class OrdersComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<mat-card class="price-history-card" flex="33">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Price History</mat-card-title>
|
||||
</mat-card-header>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PriceHistoryComponent } from './price-history.component';
|
||||
|
||||
describe('PriceHistoryComponent', () => {
|
||||
let component: PriceHistoryComponent;
|
||||
let fixture: ComponentFixture<PriceHistoryComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ PriceHistoryComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PriceHistoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/price-history/price-history.component.ts
Normal file
15
web/src/app/shared/price-history/price-history.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-price-history',
|
||||
templateUrl: './price-history.component.html',
|
||||
styleUrls: ['./price-history.component.scss']
|
||||
})
|
||||
export class PriceHistoryComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<button mat-button routerLink="exchange-grid" matTooltip="Change currency">POLONIEX: BTC_USD (placeholder)</button>
|
||||
<button mat-icon-button routerLink="currency-list" matTooltip="View currency list">
|
||||
<mat-icon>
|
||||
view_list
|
||||
</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button routerLink="exchange-grid" matTooltip="View exchange grid">
|
||||
<mat-icon>
|
||||
view_stream
|
||||
</mat-icon>
|
||||
</button>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SelectedCurrencyComponent } from './selected-currency.component';
|
||||
|
||||
describe('SelectedCurrencyComponent', () => {
|
||||
let component: SelectedCurrencyComponent;
|
||||
let fixture: ComponentFixture<SelectedCurrencyComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SelectedCurrencyComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SelectedCurrencyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-selected-currency',
|
||||
templateUrl: './selected-currency.component.html',
|
||||
styleUrls: ['./selected-currency.component.scss']
|
||||
})
|
||||
export class SelectedCurrencyComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
18
web/src/app/shared/theme-picker/theme-picker.html
Normal file
18
web/src/app/shared/theme-picker/theme-picker.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<button mat-icon-button [mat-menu-trigger-for]="themeMenu" matTooltip="Select a theme!"
|
||||
tabindex="-1">
|
||||
<mat-icon>format_color_fill</mat-icon>
|
||||
</button>
|
||||
|
||||
<!-- TODO: replace use of `mat-menu` here with a custom overlay -->
|
||||
<mat-menu class="docs-theme-picker-menu" #themeMenu="matMenu" x-position="before">
|
||||
<mat-grid-list cols="2">
|
||||
<mat-grid-tile *ngFor="let theme of themes">
|
||||
<div mat-menu-item (click)="installTheme(theme)">
|
||||
<div class="docs-theme-picker-swatch">
|
||||
<mat-icon class="docs-theme-chosen-icon" *ngIf="currentTheme === theme">check_circle</mat-icon>
|
||||
<div class="docs-theme-picker-primary" [style.background]="theme.primary"></div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</mat-menu>
|
||||
58
web/src/app/shared/theme-picker/theme-picker.scss
Normal file
58
web/src/app/shared/theme-picker/theme-picker.scss
Normal file
@@ -0,0 +1,58 @@
|
||||
$theme-picker-menu-padding: 8px;
|
||||
$theme-picker-grid-cell-size: 48px;
|
||||
$theme-picker-grid-cells-per-row: 2;
|
||||
$theme-picker-swatch-size: 36px;
|
||||
$theme-picker-accent-stripe-size: 6px;
|
||||
|
||||
|
||||
.docs-theme-picker-menu {
|
||||
.mat-menu-content {
|
||||
padding: $theme-picker-menu-padding;
|
||||
}
|
||||
|
||||
[mat-menu-item] {
|
||||
flex: 0 0 auto;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.docs-theme-picker-swatch {
|
||||
position: relative;
|
||||
width: $theme-picker-swatch-size;
|
||||
height: $theme-picker-swatch-size;
|
||||
margin: ($theme-picker-grid-cell-size - $theme-picker-swatch-size) / 2;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
.docs-theme-chosen-icon {
|
||||
color: white;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(0,0,0,.2);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-theme-picker-primary {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.docs-theme-picker-accent {
|
||||
position: absolute;
|
||||
bottom: $theme-picker-accent-stripe-size;
|
||||
width: 100%;
|
||||
height: $theme-picker-accent-stripe-size;
|
||||
}
|
||||
}
|
||||
25
web/src/app/shared/theme-picker/theme-picker.spec.ts
Normal file
25
web/src/app/shared/theme-picker/theme-picker.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ThemePickerComponent } from './theme-picker.component';
|
||||
|
||||
describe('ThemePickerComponent', () => {
|
||||
let component: ThemePickerComponent;
|
||||
let fixture: ComponentFixture<ThemePickerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ThemePickerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ThemePickerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
74
web/src/app/shared/theme-picker/theme-picker.ts
Normal file
74
web/src/app/shared/theme-picker/theme-picker.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import {Component, ViewEncapsulation, ChangeDetectionStrategy, NgModule} from '@angular/core';
|
||||
import { StyleManagerService } from './../../services/style-manager/style-manager.service';
|
||||
|
||||
import { ThemeStorageService,DocsSiteTheme } from './../../services/theme-storage/theme-storage.service';
|
||||
import {CommonModule} from '@angular/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'theme-picker',
|
||||
templateUrl: 'theme-picker.html',
|
||||
styleUrls: ['theme-picker.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {'aria-hidden': 'true'},
|
||||
})
|
||||
export class ThemePickerComponent {
|
||||
currentTheme;
|
||||
|
||||
themes = [
|
||||
{
|
||||
primary: '#673AB7',
|
||||
accent: '#FFC107',
|
||||
href: 'deeppurple-amber.css',
|
||||
isDark: false,
|
||||
},
|
||||
{
|
||||
primary: '#3F51B5',
|
||||
accent: '#E91E63',
|
||||
href: 'indigo-pink.css',
|
||||
isDark: false,
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
primary: '#E91E63',
|
||||
accent: '#607D8B',
|
||||
href: 'pink-bluegrey.css',
|
||||
isDark: true,
|
||||
},
|
||||
{
|
||||
primary: '#9C27B0',
|
||||
accent: '#4CAF50',
|
||||
href: 'purple-green.css',
|
||||
isDark: true,
|
||||
},
|
||||
];
|
||||
|
||||
constructor(
|
||||
public styleManager: StyleManagerService,
|
||||
private _themeStorage: ThemeStorageService
|
||||
) {
|
||||
const currentTheme = this._themeStorage.getStoredTheme();
|
||||
if (currentTheme) {
|
||||
this.installTheme(currentTheme);
|
||||
}
|
||||
}
|
||||
|
||||
installTheme(theme: DocsSiteTheme) {
|
||||
this.currentTheme = this._getCurrentThemeFromHref(theme.href);
|
||||
|
||||
if (theme.isDefault) {
|
||||
this.styleManager.removeStyle('theme');
|
||||
} else {
|
||||
this.styleManager.setStyle('theme', `assets/${theme.href}`);
|
||||
}
|
||||
|
||||
if (this.currentTheme) {
|
||||
this._themeStorage.storeTheme(this.currentTheme);
|
||||
}
|
||||
}
|
||||
|
||||
private _getCurrentThemeFromHref(href: string): DocsSiteTheme {
|
||||
return this.themes.find(theme => theme.href === href);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<mat-card class="trade-history-card" flex="33">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Trade History</mat-card-title>
|
||||
</mat-card-header>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TradeHistoryComponent } from './trade-history.component';
|
||||
|
||||
describe('TradeHistoryComponent', () => {
|
||||
let component: TradeHistoryComponent;
|
||||
let fixture: ComponentFixture<TradeHistoryComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ TradeHistoryComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TradeHistoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
web/src/app/shared/trade-history/trade-history.component.ts
Normal file
15
web/src/app/shared/trade-history/trade-history.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-trade-history',
|
||||
templateUrl: './trade-history.component.html',
|
||||
styleUrls: ['./trade-history.component.scss']
|
||||
})
|
||||
export class TradeHistoryComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
1
web/src/assets/deeppurple-amber.css
Normal file
1
web/src/assets/deeppurple-amber.css
Normal file
File diff suppressed because one or more lines are too long
BIN
web/src/assets/early-dumb-donate.png
Normal file
BIN
web/src/assets/early-dumb-donate.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
1
web/src/assets/indigo-pink.css
Normal file
1
web/src/assets/indigo-pink.css
Normal file
File diff suppressed because one or more lines are too long
BIN
web/src/assets/page-logo.png
Normal file
BIN
web/src/assets/page-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
1
web/src/assets/pink-bluegrey.css
Normal file
1
web/src/assets/pink-bluegrey.css
Normal file
File diff suppressed because one or more lines are too long
1
web/src/assets/purple-green.css
Normal file
1
web/src/assets/purple-green.css
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 14 KiB |
@@ -14,7 +14,7 @@
|
||||
</head>
|
||||
|
||||
<body class="mat-app-background">
|
||||
<app-root>Loading...</app-root>
|
||||
<app-root><img style="position: absolute;top: 25%;left: 40%; width: 25%;" src="/assets/page-logo.png" /></app-root>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -4,26 +4,47 @@ html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 20px 70px 0;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
max-width: 940px;
|
||||
width:100%;
|
||||
font-family: Roboto,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
margin-left:50%;
|
||||
margin-right:50%;
|
||||
width:100%;
|
||||
margin-left: 50%;
|
||||
margin-right: 50%;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Default settings for cards
|
||||
////////////////////////////////////////////////////////////////
|
||||
.card {
|
||||
width: 80%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Default settings for expandable tile menus
|
||||
////////////////////////////////////////////////////////////////
|
||||
.mat-expansion-panel {
|
||||
width: 80%;
|
||||
margin: 0px auto !important;
|
||||
}
|
||||
|
||||
.mat-expansion-panel-header-title,
|
||||
.mat-expansion-panel-header-description {
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.mat-expansion-panel-header-description {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mat-expansion-panel-spacing {
|
||||
margin: 16px auto !important;
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
.mat-drawer {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"module":"system",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"baseUrl": "src",
|
||||
"sourceMap": true,
|
||||
@@ -8,7 +9,7 @@
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowJs": true,
|
||||
"allowJs": false,
|
||||
"target": "es5",
|
||||
"paths": {
|
||||
"environments": [
|
||||
|
||||
@@ -9,7 +9,7 @@ const postcssUrl = require('postcss-url');
|
||||
const { NoEmitOnErrorsPlugin, LoaderOptionsPlugin, DefinePlugin, HashedModuleIdsPlugin } = require('webpack');
|
||||
const { GlobCopyWebpackPlugin, BaseHrefWebpackPlugin } = require('@angular/cli/plugins/webpack');
|
||||
const { CommonsChunkPlugin, UglifyJsPlugin } = require('webpack').optimize;
|
||||
const { AotPlugin } = require('@ngtools/webpack');
|
||||
const { AngularCompilerPlugin } = require('@ngtools/webpack');
|
||||
|
||||
const nodeModules = path.join(process.cwd(), 'node_modules');
|
||||
const entryPoints = ["inline", "polyfills", "sw-register", "styles", "vendor", "main"];
|
||||
@@ -139,7 +139,7 @@ function getPlugins() {
|
||||
"hashDigestLength": 4
|
||||
}));
|
||||
|
||||
plugins.push(new AotPlugin({
|
||||
plugins.push(new AngularCompilerPlugin({
|
||||
"mainPath": "main.ts",
|
||||
"hostReplacementPaths": {
|
||||
"environments/index.ts": "environments/index.prod.ts"
|
||||
@@ -160,7 +160,7 @@ function getPlugins() {
|
||||
}));
|
||||
|
||||
} else {
|
||||
plugins.push(new AotPlugin({
|
||||
plugins.push(new AngularCompilerPlugin({
|
||||
"mainPath": "main.ts",
|
||||
"hostReplacementPaths": {
|
||||
"environments/index.ts": "environments/index.ts"
|
||||
@@ -364,7 +364,7 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
{
|
||||
"test": /\.ts$/,
|
||||
"test": /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
|
||||
"loader": "@ngtools/webpack"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user