diff --git a/src/app/app.component.html b/src/app/app.component.html index ef717e8..3a38aec 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,30 +1,57 @@ - + ETF Demo {{timer}} microseconds to upload - {{file}} cancel - + - -
- - + + + + + +
+ +
+ + + + {{holding}} + cancel + + + + + + {{holding}} + + + +
+ + + +
- diff --git a/src/app/app.component.ts b/src/app/app.component.ts index becaf00..b18ae76 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import {Component} from '@angular/core'; +import {Component, ElementRef, EventEmitter, ViewChild} from '@angular/core'; import {timer} from './timer'; import {colorScheme} from './colorScheme'; @@ -7,10 +7,16 @@ import {colorScheme} from './colorScheme'; templateUrl: './app.component.html' }) export class AppComponent { + @ViewChild('holdingInput') holdingInput: ElementRef; + + autoCompleteList = new EventEmitter(); // Async pipe to provide autocomplete list after being filtered by the text input colorScheme = colorScheme; // colors - chartResults; // This is where the chart reads the data from - chartHeight = '100%'; // Dynamic height for chart + chartResults = []; // This is where the chart reads the data from + holdings: string[] = []; // All the merged holdings + fileNames: string[] = []; // All the filenames + mergedData = {}; // All the holdings merged together timer = window['timer']; // Async pipe to display the timed data + graphHoldings: string[] = []; // Holdings we are graphing // ngx-charts requires a different data structure than the hash map we built so I will use a setter to handle converting it when we go to save the processed data. private _data = {}; @@ -19,7 +25,7 @@ export class AppComponent { this._data = data; // merge the files together - let mergedData = Object.values(data).reduce((acc, file) => { + this.mergedData = Object.values(data).reduce((acc, file) => { Object.keys(file).forEach(key => { if(!acc[key]) acc[key] = []; file[key].forEach(val => acc[key].push(val)); @@ -27,14 +33,14 @@ export class AppComponent { return acc; }, {}); - // Take the merged data set and get everything ready for it to be charted - this.chartHeight = `${Object.keys(mergedData).length * 100}px`; - this.chartResults = Object.keys(mergedData).map(key => ({name: key, series: mergedData[key].map((val, i) => ({name: i, value: val}))})); + // Store the keys for easy referencing + this.fileNames = Object.keys(this.data); + this.holdings = Object.keys(this.mergedData).sort(); + this.autoCompleteList.next(this.holdings); } - get fileNames() { return Object.keys(this.data); } - constructor() { + // Hack to connect angular context to the native one setInterval(() => this.timer = Math.round(window['timer'] * 10) / 10, 250); } @@ -44,6 +50,12 @@ export class AppComponent { this.data = Object.assign({}, this.data); } + search(text: string) { + // Filter the holdings list by the text and push it through the async pipe + if(!text) this.autoCompleteList.next(this.holdings); + this.autoCompleteList.next(this.holdings.filter(holding => holding.toLowerCase().indexOf(text) != -1)); + } + @timer upload(fileList: FileList) { // Because we enabled uploading multiple fileNames at once we need to process each one individually @@ -74,5 +86,20 @@ export class AppComponent { }); } + updateGraph(holding?: string) { + if(holding) { + this.graphHoldings.push(holding); + this.holdingInput.nativeElement.value = ''; + } + + // Take the merged data set and get everything ready for it to be charted + this.chartResults = Object.keys(this.mergedData) + .filter(key => this.graphHoldings.indexOf(key) != -1) + .map(key => ({ + name: key, + series: this.mergedData[key].map((val, i) => ({name: i, value: val})) + })); + } + format(text) { return `${text} %`} } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d3ca1b0..246592c 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,20 +1,33 @@ import {BrowserModule} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {AppComponent} from './app.component'; -import {MatButtonModule, MatChipsModule, MatIconModule, MatToolbarModule} from '@angular/material'; +import { + MatAutocompleteModule, + MatButtonModule, + MatChipsModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatSelectModule, + MatToolbarModule +} from '@angular/material'; import {NgxChartsModule} from '@swimlane/ngx-charts'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {FormsModule} from '@angular/forms'; @NgModule({ - declarations: [ - AppComponent - ], + declarations: [AppComponent], imports: [ BrowserAnimationsModule, BrowserModule, + FormsModule, + MatAutocompleteModule, MatButtonModule, MatChipsModule, + MatFormFieldModule, MatIconModule, + MatInputModule, + MatSelectModule, MatToolbarModule, NgxChartsModule, ], diff --git a/src/styles.scss b/src/styles.scss index 1e8588b..8f2599b 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -10,6 +10,14 @@ html, body { font-family: 'Archivo', sans-serif; } +.content-height { + height: calc(100vh - 64px); +} + +.w-50 { + width: 50%; +} + // Bootstrap overrides .text-muted { color: #bbbbbb !important;