diff --git a/frontend/documentation/components/AppComponent.html b/frontend/documentation/components/AppComponent.html new file mode 100644 index 0000000..715fd3f --- /dev/null +++ b/frontend/documentation/components/AppComponent.html @@ -0,0 +1,501 @@ + + +
+ + ++
+ src/app/app.component.ts
+
selector | +app-root |
+
styleUrls | +./app.component.scss |
+
templateUrl | +./app.component.html |
+
+ Properties+ |
+
+
|
+
+constructor(router: Router, tokenStorage: TokenStorageService)
+ |
+ ||||||||||||
+ Defined in src/app/app.component.ts:18
+ |
+ ||||||||||||
+ Router import to show router-outlet. +
+ Parameters :
+
+
|
+
+ + + isLoggedIn + + + | +
+ Default value : false
+ |
+
+ Defined in src/app/app.component.ts:18
+ |
+
+ + + showHeader + + + | +
+ Default value : false
+ |
+
+ Defined in src/app/app.component.ts:17
+ |
+
+ + + title + + + | +
+ Type : string
+
+ |
+
+ Default value : 'Aktienbot'
+ |
+
+ Defined in src/app/app.component.ts:15
+ |
+
+ Application title. + |
+
import { Component } from '@angular/core';
+import { NavigationEnd, Router } from '@angular/router';
+import { TokenStorageService } from './Services/token.service';
+import { filter } from 'rxjs/operators';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.scss'],
+})
+export class AppComponent {
+ /**
+ * Application title.
+ */
+ title = 'Aktienbot';
+
+ showHeader = false;
+ isLoggedIn = false;
+
+ /**
+ * Router import to show router-outlet.
+ *
+ * @param router Router
+ */
+ constructor(
+ private router: Router,
+ private tokenStorage: TokenStorageService
+ ) {
+ //check if it is login or registration page, header should not show there
+ this.router.events
+ .pipe(filter((event) => event instanceof NavigationEnd))
+ .subscribe((event) => {
+ this.showHeader = !(
+ (event as NavigationEnd).url === '/login' ||
+ (event as NavigationEnd).url === '/register'
+ );
+
+ //check if token already exists from past login
+ if (this.tokenStorage.getToken()) {
+ this.isLoggedIn = true;
+ } else {
+ this.isLoggedIn = false;
+ }
+
+ //prevent user from accessing dashboard if not logged in
+ if (
+ this.isLoggedIn === false &&
+ (event as NavigationEnd).url != '/register'
+ ) {
+ this.router.navigate(['/login']);
+ }
+ });
+ }
+}
+
+ <app-header *ngIf="showHeader"></app-header>
+<router-outlet></router-outlet>
+
+
+ ./app.component.scss
+
+ +
+ src/app/Views/bot-settings/bot-settings.component.ts
+
+
+ OnInit
+
selector | +app-bot-settings |
+
styleUrls | +./bot-settings.component.scss |
+
templateUrl | +./bot-settings.component.html |
+
+ Properties+ |
+
+
|
+
+ Methods+ |
+
+
|
+
+constructor(botService: BotService, helper: HelperService, profileService: ProfileService)
+ |
+ ||||||||||||
+ + | +||||||||||||
+
+ Parameters :
+
+
|
+
+ + + Async + addShare + + + | +||||||
+
+ addShare(event: MatChipInputEvent)
+ |
+ ||||||
+ + | +||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Promise<void>
+
+
+
+
+ |
+
+ + + ngOnInit + + + | +
+ngOnInit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + Async + removeKeyword + + + | +||||||
+
+ removeKeyword(keyword: Keyword)
+ |
+ ||||||
+ + | +||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Promise<void>
+
+
+
+
+ |
+
+ + + Async + removeShare + + + | +||||||
+
+ removeShare(share: Share)
+ |
+ ||||||
+ + | +||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Promise<void>
+
+
+
+
+ |
+
+ + + setCronString + + + | +
+setCronString()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + addOnBlur + + + | +
+ Default value : true
+ |
+
+ + | +
+ + + cronForm + + + | +
+ Default value : new FormControl('0 0 1/1 * *')
+ |
+
+ + | +
+ + + Public + cronOptions + + + | +
+ Type : CronOptions
+
+ |
+
+ Default value : {
+ defaultTime: '00:00:00',
+
+ hideMinutesTab: true,
+ hideHourlyTab: true,
+ hideDailyTab: false,
+ hideWeeklyTab: true,
+ hideMonthlyTab: true,
+ hideYearlyTab: true,
+ hideAdvancedTab: true,
+ hideSpecificWeekDayTab: true,
+ hideSpecificMonthWeekTab: true,
+
+ use24HourTime: true,
+ hideSeconds: true,
+
+ cronFlavor: 'quartz', //standard or quartz
+ }
+ |
+
+ + | +
+ + + keywords + + + | +
+ Type : Keyword[]
+
+ |
+
+ Default value : []
+ |
+
+ + | +
+ + + Readonly + separatorKeysCodes + + + | +
+ Default value : [ENTER, COMMA] as const
+ |
+
+ + | +
+ + + shares + + + | +
+ Type : Share[]
+
+ |
+
+ Default value : []
+ |
+
+ + | +
import { Component, OnInit } from '@angular/core';
+import { C, COMMA, ENTER, F } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+
+import { CronOptions } from 'ngx-cron-editor';
+
+import { BotService } from 'src/app/Services/bot.service';
+import { HelperService } from 'src/app/Helpers/helper.service';
+import { ProfileService } from 'src/app/Services/profile.service';
+import { FormControl } from '@angular/forms';
+
+export interface Fruit {
+ name: string;
+}
+
+export interface Share {
+ isin: string;
+}
+
+export interface Keyword {
+ name: string;
+}
+
+@Component({
+ selector: 'app-bot-settings',
+ templateUrl: './bot-settings.component.html',
+ styleUrls: ['./bot-settings.component.scss'],
+})
+export class BotSettingsComponent implements OnInit {
+ keywords: Keyword[] = [];
+ shares: Share[] = [];
+
+ constructor(
+ private botService: BotService,
+ private helper: HelperService,
+ private profileService: ProfileService
+ ) {}
+
+ ngOnInit(): void {
+ this.shares = this.helper.formatShareData();
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ addOnBlur = true;
+ readonly separatorKeysCodes = [ENTER, COMMA] as const;
+
+ async addKeyword(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add keyword to database
+ if (value && !this.keywords.includes({ name: value })) {
+ console.log('Added: ' + value);
+ this.botService.createKeyword(value.toLowerCase()).subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+ }
+
+ async removeKeyword(keyword: Keyword): Promise<void> {
+ this.botService.deleteKeyword(keyword.name).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ async addShare(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add share to database
+ if (value && !this.shares.includes({ isin: value.toLowerCase() })) {
+ console.log('Added: ' + value);
+ this.botService.createShare(value, 'Comment').subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+ }
+
+ async removeShare(share: Share): Promise<void> {
+ this.botService.deleteShare(share.isin).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+
+ setCronString() {
+ this.profileService
+ .addCronString(this.cronForm.value)
+ .subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ cronForm = new FormControl('0 0 1/1 * *');
+ public cronOptions: CronOptions = {
+ defaultTime: '00:00:00',
+
+ hideMinutesTab: true,
+ hideHourlyTab: true,
+ hideDailyTab: false,
+ hideWeeklyTab: true,
+ hideMonthlyTab: true,
+ hideYearlyTab: true,
+ hideAdvancedTab: true,
+ hideSpecificWeekDayTab: true,
+ hideSpecificMonthWeekTab: true,
+
+ use24HourTime: true,
+ hideSeconds: true,
+
+ cronFlavor: 'quartz', //standard or quartz
+ };
+}
+
+ <mat-grid-list cols="2" rowHeight="45%">
+ <mat-grid-tile colspan="1" rowspan="1">
+ <mat-card class="card">
+ <mat-card-title class="card-title">Keywords</mat-card-title>
+ <mat-card-content>
+ <mat-form-field class="example-chip-list" appearance="fill">
+ <mat-label>Keywords</mat-label>
+ <mat-chip-list #chipList aria-label="Keyword selection">
+ <mat-chip
+ *ngFor="let keyword of keywords"
+ (removed)="removeKeyword(keyword)"
+ >
+ {{ keyword.name }}
+ <button matChipRemove>
+ <mat-icon>cancel</mat-icon>
+ </button>
+ </mat-chip>
+ <input
+ placeholder="New keyword..."
+ [matChipInputFor]="chipList"
+ [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
+ [matChipInputAddOnBlur]="addOnBlur"
+ (matChipInputTokenEnd)="addKeyword($event)"
+ />
+ </mat-chip-list>
+ </mat-form-field>
+ <span
+ >*To add a keyword, after writing, either press enter or click outside
+ of keyword input field.</span
+ >
+ </mat-card-content>
+ </mat-card>
+ </mat-grid-tile>
+ <mat-grid-tile colspan="1" rowspan="2">
+ <mat-card class="card placeholderRHS">
+ <mat-card-title class="card-title">
+ <span>Add automatic updates</span>
+ </mat-card-title>
+ <mat-card-content class="cron-content">
+ <form
+ name="form"
+ (ngSubmit)="f.form.valid && setCronString()"
+ #f="ngForm"
+ novalidate
+ class="backgorund form"
+ >
+ <cron-editor
+ class="cron-editor"
+ [formControl]="cronForm"
+ [options]="cronOptions"
+ ></cron-editor>
+ <div class="form-group footer-buttons">
+ <button class="btn btn-primary btn-block">Add</button>
+ </div>
+ </form>
+ </mat-card-content>
+ </mat-card>
+ </mat-grid-tile>
+ <mat-grid-tile colspan="1" rowspan="1">
+ <mat-card class="card">
+ <mat-card-title class="card-title">Shares</mat-card-title>
+ <mat-card-content>
+ <mat-form-field class="example-chip-list" appearance="fill">
+ <mat-label>Shares</mat-label>
+ <mat-chip-list #sharesList aria-label="Share selection">
+ <mat-chip
+ *ngFor="let share of shares"
+ (removed)="removeShare(share)"
+ >
+ {{ share.isin }}
+ <button matChipRemove>
+ <mat-icon>cancel</mat-icon>
+ </button>
+ </mat-chip>
+ <input
+ placeholder="New share..."
+ [matChipInputFor]="sharesList"
+ [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
+ [matChipInputAddOnBlur]="addOnBlur"
+ (matChipInputTokenEnd)="addShare($event)"
+ />
+ </mat-chip-list>
+ </mat-form-field>
+ <span
+ >*To add a share, after writing, either press enter or click outside
+ of keyword input field.</span
+ >
+ </mat-card-content>
+ </mat-card>
+ </mat-grid-tile>
+</mat-grid-list>
+
+
+ ./bot-settings.component.scss
+
.form {
+ width: 100%;
+}
+
+.card {
+ width: 90%;
+ height: 80%;
+ margin: 5%;
+}
+
+.example-full-width {
+ width: 100%;
+}
+
+.card-title {
+ padding-bottom: 2.5vh;
+}
+
+mat-grid {
+ width: 100%;
+ height: 100%;
+}
+
+.example-chip-list {
+ width: 100%;
+}
+
+.placeholder {
+ height: 95%;
+}
+
+.placeholderRHS {
+ height: 90%;
+}
+
+.cron-content {
+ height: 70%;
+ overflow: auto;
+}
+
+mat-card {
+ overflow: scroll;
+}
+
+ +
+ src/app/Views/profile/confirmation-dialog/confirmation-dialog.component.ts
+
selector | +app-confirmation-dialog |
+
styleUrls | +./confirmation-dialog.component.scss |
+
templateUrl | +./confirmation-dialog.component.html |
+
+ Methods+ |
+
+
|
+
+constructor()
+ |
+
+ + | +
+ + + confirm + + + | +
+confirm()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + returnBack + + + | +
+returnBack()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-confirmation-dialog',
+ templateUrl: './confirmation-dialog.component.html',
+ styleUrls: ['./confirmation-dialog.component.scss'],
+})
+export class ConfirmationDialogComponent {
+ constructor() {}
+
+ confirm() {}
+
+ returnBack() {}
+}
+
+ <div class="containeer">
+ <h1 mat-dialog-title>Confirm Action</h1>
+ <div mat-dialog-content class="content">
+ <span>Are you sure, that you want to continue?</span>
+ </div>
+ <div mat-dialog-actions class="form-group footer-buttons">
+ <div class="inner">
+ <button
+ id="cancelButton"
+ class="btn btn-primary btn-block"
+ (click)="returnBack()"
+ [mat-dialog-close]="false"
+ >
+ Cancel
+ </button>
+ </div>
+ <div class="inner">
+ <button
+ id="okButton"
+ class="btn btn-danger btn-block"
+ (click)="confirm()"
+ [mat-dialog-close]="true"
+ >
+ Yes
+ </button>
+ </div>
+ </div>
+</div>
+
+
+ ./confirmation-dialog.component.scss
+
.footer-buttons {
+ width: 100%;
+ text-align: center;
+}
+
+.spacer {
+ flex-grow: 1;
+ width: 5%;
+}
+
+.inner {
+ display: inline-block;
+ width: 50%;
+}
+
+.content {
+ height: 80%;
+}
+
+ +
+ src/app/Views/dashboard/dashboard.component.ts
+
+
+ OnInit
+
selector | +app-dashboard |
+
styleUrls | +./dashboard.component.scss |
+
templateUrl | +./dashboard.component.html |
+
+ Properties+ |
+
+
|
+
+ Methods+ |
+
+
|
+
+constructor(dataService: DataService, helper: HelperService, dialog: MatDialog)
+ |
+ ||||||||||||
+ + | +||||||||||||
+
+ Parameters :
+
+
|
+
+ + + getTransactions + + + | +
+getTransactions()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + ngOnInit + + + | +
+ngOnInit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + openDialog + + + | +
+openDialog()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + comment + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ + | +
+ + + count + + + | +
+ Type : number
+
+ |
+
+ Default value : 0.0
+ |
+
+ + | +
+ + + dataSource + + + | +
+ Default value : ELEMENT_DATA
+ |
+
+ + | +
+ + + dataSourceStocks + + + | +
+ Type : Stock[]
+
+ |
+
+ Default value : []
+ |
+
+ + | +
+ + + dataSourceTransactions + + + | +
+ Type : TransactionData[]
+
+ |
+
+ Default value : []
+ |
+
+ + | +
+ + + depotCost + + + | +
+ Type : number
+
+ |
+
+ Default value : 0
+ |
+
+ + | +
+ + + depotCurrentValue + + + | +
+ Type : number
+
+ |
+
+ Default value : 0
+ |
+
+ + | +
+ + + Public + dialog + + + | +
+ Type : MatDialog
+
+ |
+
+ + | +
+ + + displayedColumns + + + | +
+ Type : string[]
+
+ |
+
+ Default value : [
+ 'comment',
+ 'weight',
+ 'position',
+ 'name',
+ 'symbol',
+ ]
+ |
+
+ + | +
+ + + displayedColumnsStocks + + + | +
+ Type : string[]
+
+ |
+
+ Default value : [
+ 'position',
+ 'name',
+ 'weight',
+ 'current-price',
+ ]
+ |
+
+ + | +
+ + + isin + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ + | +
+ + + price + + + | +
+ Type : number
+
+ |
+
+ Default value : 0.0
+ |
+
+ + | +
+ + + profit + + + | +
+ Type : number
+
+ |
+
+ Default value : 0
+ |
+
+ + | +
+ + + time + + + | +
+ Type : Date
+
+ |
+
+ Default value : new Date()
+ |
+
+ + | +
import { Component, OnInit } from '@angular/core';
+import { DataService } from 'src/app/Services/data.service';
+import { MatDialog } from '@angular/material/dialog';
+import { UserDialogComponent } from './user-dialog/user-dialog.component';
+import { HelperService } from 'src/app/Helpers/helper.service';
+
+export interface PeriodicElement {
+ name: string;
+ position: number;
+ weight: number;
+ symbol: string;
+}
+
+export interface Stock {
+ count: number;
+ currentPrice: number;
+ symbol: string;
+ time: string;
+}
+
+//symbol count lastTransaction boughtPrice currentPrice(+?)
+
+const ELEMENT_DATA: PeriodicElement[] = [
+ { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
+ { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
+ { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
+];
+
+var TRANSACTION_DATA: TransactionData[] = [];
+var STOCK_DATA: Stock[] = [];
+
+export interface TransactionData {
+ comment: string;
+ isin: string;
+ time: string;
+ count: number;
+ price: number;
+}
+
+@Component({
+ selector: 'app-dashboard',
+ templateUrl: './dashboard.component.html',
+ styleUrls: ['./dashboard.component.scss'],
+})
+export class DashboardComponent implements OnInit {
+ constructor(
+ private dataService: DataService,
+ private helper: HelperService,
+ public dialog: MatDialog
+ ) {}
+
+ dataSourceTransactions: TransactionData[] = [];
+ dataSourceStocks: Stock[] = [];
+ depotCurrentValue: number = 0;
+ depotCost: number = 0;
+ profit: number = 0;
+
+ getTransactions() {
+ var TRANSACTION_DATA: TransactionData[] = [];
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit = this.depotCurrentValue - this.depotCost;
+ });
+ }
+
+ ngOnInit() {
+ this.dataService.getStockData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCurrentValue = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCurrentValue = data.data[i].current_price;
+ STOCK_DATA.push({
+ count: data.data[i].count,
+ currentPrice: data.data[i].current_price,
+ symbol: data.data[i].symbol,
+ time: data.data[i].last_transaction,
+ });
+ }
+ this.dataSourceStocks = STOCK_DATA;
+ //TODO move to helper service
+
+ this.profit += this.depotCurrentValue;
+ });
+
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit -= this.depotCost;
+ });
+ }
+
+ comment: string = '';
+ isin: string = '';
+ time: Date = new Date();
+ count: number = 0.0;
+ price: number = 0.0;
+
+ openDialog(): void {
+ const dialogRef = this.dialog.open(UserDialogComponent, {
+ width: '50vw',
+ data: {
+ comment: this.comment,
+ isin: this.isin,
+ time: this.time,
+ count: this.count,
+ price: this.price,
+ },
+ });
+
+ dialogRef.afterClosed().subscribe((result) => {
+ this.helper.delay(1000);
+ this.getTransactions();
+ });
+ }
+
+ displayedColumns: string[] = [
+ 'comment',
+ 'weight',
+ 'position',
+ 'name',
+ 'symbol',
+ ];
+ displayedColumnsStocks: string[] = [
+ 'position',
+ 'name',
+ 'weight',
+ 'current-price',
+ ];
+ dataSource = ELEMENT_DATA;
+}
+
+ <mat-grid-list cols="2" rowHeight="45%">
+ <!-- Stocks -->
+ <mat-grid-tile colspan="1" rowspan="2">
+ <div class="stockOverview">
+ <div class="heading">
+ <div class="vertical-center">Stocks</div>
+ </div>
+ <mat-card class="placeholder">
+ <div class="stockTableLHS">
+ <table mat-table [dataSource]="dataSourceStocks">
+ <!--- Note that these columns can be defined in any order.
+ The actual rendered columns are set as a property on the row definition" -->
+
+ <!-- Symbol Column -->
+ <ng-container matColumnDef="position">
+ <th mat-header-cell *matHeaderCellDef>Symbol</th>
+ <td mat-cell *matCellDef="let element">{{ element.symbol }}</td>
+ </ng-container>
+
+ <!-- Count Column -->
+ <ng-container matColumnDef="name">
+ <th mat-header-cell *matHeaderCellDef>Count</th>
+ <td mat-cell *matCellDef="let element">{{ element.count }}</td>
+ </ng-container>
+
+ <!-- Time Column -->
+ <ng-container matColumnDef="weight">
+ <th mat-header-cell *matHeaderCellDef>Time</th>
+ <td mat-cell *matCellDef="let element">{{ element.time }}</td>
+ </ng-container>
+
+ <!-- Time Column -->
+ <ng-container matColumnDef="current-price">
+ <th mat-header-cell *matHeaderCellDef>Current Price</th>
+ <td mat-cell *matCellDef="let element">
+ {{ element.currentPrice }}
+ </td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumnsStocks"></tr>
+ <tr
+ mat-row
+ *matRowDef="let row; columns: displayedColumnsStocks"
+ ></tr>
+ </table>
+ </div>
+ </mat-card>
+ </div>
+ </mat-grid-tile>
+ <!-- Depot Overview -->
+ <mat-grid-tile colspan="1" rowspan="1" class="right-side">
+ <div class="depotOverview">
+ <div class="heading fix-right-side">
+ <div class="vertical-center">Depot</div>
+ </div>
+ <mat-card class="placeholderRHS content-container">
+ <div class="content">
+ <div class="row">
+ <div class="col-md-4">
+ <div class="value-set">
+ <h3>Portfolio Value</h3>
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="value-set">
+ <h3>Portfolio Cost</h3>
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="value-set">
+ <h3>Portfolio Profit</h3>
+ </div>
+ </div>
+ </div>
+ <br />
+ <div class="row">
+ <div class="col-6 col-sm-4">
+ <mat-icon>savings</mat-icon
+ ><span class="money">{{ depotCurrentValue.toFixed(2) }}</span>
+ </div>
+ <div class="col-6 col-sm-4">
+ <mat-icon>paid</mat-icon
+ ><span class="money">{{ depotCost.toFixed(2) }}</span>
+ </div>
+ <div class="col-6 col-sm-4">
+ <mat-icon>account_balance</mat-icon
+ ><span
+ class="money"
+ [ngClass]="{ green: profit >= 0, red: profit < 0 }"
+ >{{ profit.toFixed(2) }}</span
+ >
+ </div>
+ </div>
+ </div>
+ </mat-card>
+ </div>
+ </mat-grid-tile>
+ <!-- Transaktions -->
+ <mat-grid-tile colspan="1" rowspan="1" class="right-side">
+ <div class="depotOverviewDown">
+ <div class="heading fix-right-side">
+ <div class="vertical-center">Transactions</div>
+ <span class="spacer"></span>
+ <button
+ mat-icon-button
+ class="add-icon"
+ aria-label="Example icon-button with heart icon"
+ [disableRipple]="true"
+ (click)="openDialog()"
+ >
+ <mat-icon>add</mat-icon>
+ </button>
+ </div>
+ <mat-card class="placeholderRHS"
+ ><div class="stockTable">
+ <table mat-table [dataSource]="dataSourceTransactions">
+ <!--- Note that these columns can be defined in any order.
+ The actual rendered columns are set as a property on the row definition" -->
+
+ <!-- Position Column -->
+ <ng-container matColumnDef="position">
+ <th mat-header-cell *matHeaderCellDef>Count</th>
+ <td mat-cell *matCellDef="let element">{{ element.count }}</td>
+ </ng-container>
+
+ <!-- Comment Column -->
+ <ng-container matColumnDef="comment">
+ <th mat-header-cell *matHeaderCellDef>Comment</th>
+ <td mat-cell *matCellDef="let element">{{ element.comment }}</td>
+ </ng-container>
+
+ <!-- Name Column -->
+ <ng-container matColumnDef="name">
+ <th mat-header-cell *matHeaderCellDef>Price</th>
+ <td mat-cell *matCellDef="let element">{{ element.price }}</td>
+ </ng-container>
+
+ <!-- Weight Column -->
+ <ng-container matColumnDef="weight">
+ <th mat-header-cell *matHeaderCellDef>ISIN</th>
+ <td mat-cell *matCellDef="let element">{{ element.isin }}</td>
+ </ng-container>
+
+ <!-- Symbol Column -->
+ <ng-container matColumnDef="symbol">
+ <th mat-header-cell *matHeaderCellDef>Time</th>
+ <td mat-cell *matCellDef="let element">{{ element.time }}</td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+ <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
+ </table></div
+ ></mat-card>
+ </div>
+ </mat-grid-tile>
+</mat-grid-list>
+
+
+ ./dashboard.component.scss
+
// left gird
+.stockOverview {
+ height: 100%;
+ width: 100%;
+ margin-top: 10%;
+ margin-left: 10%;
+}
+
+//right grids
+.depotOverview {
+ height: 100%;
+ width: 100%;
+ margin-top: 10%;
+ margin-left: 5%;
+ margin-right: 10%;
+ text-align: center;
+}
+
+.depotOverviewDown {
+ height: 100%;
+ width: 100%;
+ margin-left: 5%;
+ margin-right: 10%;
+}
+
+.stockTable {
+ overflow: auto;
+ height: 100%;
+ width: 100%;
+}
+
+.stockTableLHS {
+ overflow: auto;
+ height: 83%;
+ width: 100%;
+}
+
+.heading {
+ font-size: xx-large;
+ height: 10%;
+ width: 100%;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.fix-right-side {
+ height: 20%;
+}
+
+.vertical-center {
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+
+.spacer {
+ flex-grow: 1;
+}
+
+.add-icon {
+ transform: scale(2);
+ outline: none !important;
+}
+
+.right-side {
+ margin-left: 2.5%;
+}
+
+table {
+ width: 100%;
+}
+
+.placeholder {
+ height: 100%;
+}
+
+.placeholderRHS {
+ height: 80%;
+}
+
+.mat-ripple-element {
+ display: none !important;
+}
+
+.money {
+ margin-left: 2vw;
+}
+
+.green {
+ color: green;
+}
+
+.red {
+ color: red;
+}
+
+.row {
+ height: 20%;
+}
+
+.content {
+ height: inherit;
+}
+
+.content-container {
+ width: 100%;
+ display: grid;
+ align-items: center;
+}
+
+ +
+ src/app/Views/header/header.component.ts
+
selector | +app-header |
+
styleUrls | +./header.component.scss |
+
templateUrl | +./header.component.html |
+
+ Methods+ |
+
+
|
+
+constructor(tokenStorage: TokenStorageService)
+ |
+ ||||||
+ Defined in src/app/Views/header/header.component.ts:9
+ |
+ ||||||
+
+ Parameters :
+
+
|
+
+ + + logout + + + | +
+logout()
+ |
+
+ Defined in src/app/Views/header/header.component.ts:16
+ |
+
+
+
+ Returns :
+ void
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { TokenStorageService } from 'src/app/Services/token.service';
+
+@Component({
+ selector: 'app-header',
+ templateUrl: './header.component.html',
+ styleUrls: ['./header.component.scss'],
+})
+export class HeaderComponent {
+ /**
+ * @param {TokenStorageService} privatetokenStorage
+ */
+ constructor(private tokenStorage: TokenStorageService) {}
+
+ //logout() clears session storage; All user data is eradicated from it and page is reloaded
+ logout() {
+ this.tokenStorage.signOut();
+ location.reload();
+ }
+}
+
+ <mat-toolbar>
+ <a href=""><span>Aktienbot</span></a>
+ <span class="example-spacer"></span>
+ <button
+ mat-icon-button
+ aria-label="Example icon-button with heart icon"
+ routerLink="/profile"
+ >
+ <mat-icon>account_circle</mat-icon>
+ </button>
+ <button
+ mat-icon-button
+ class="example-icon favorite-icon"
+ routerLink="/settings"
+ >
+ <mat-icon>ballot</mat-icon>
+ </button>
+ <button
+ mat-icon-button
+ aria-label="Example icon-button with heart icon"
+ (click)="logout()"
+ >
+ <mat-icon>logout</mat-icon>
+ </button>
+</mat-toolbar>
+
+
+ ./header.component.scss
+
.example-spacer {
+ flex: 1 1 auto;
+}
+
+a {
+ color: white;
+ text-decoration: none; /* no underline */
+}
+
+ +
+ src/app/Views/profile/help-dialog/help-dialog.component.ts
+
selector | +app-help-dialog |
+
styleUrls | +./help-dialog.component.scss |
+
templateUrl | +./help-dialog.component.html |
+
+ Methods+ |
+
+
|
+
+constructor()
+ |
+
+ + | +
+ + + close + + + | +
+close()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-help-dialog',
+ templateUrl: './help-dialog.component.html',
+ styleUrls: ['./help-dialog.component.scss'],
+})
+export class HelpDialogComponent {
+ constructor() {}
+
+ close() {}
+}
+
+ <div class="containeer">
+ <h1 mat-dialog-title>How to add your Telegram account</h1>
+ <div mat-dialog-content class="content">
+ <span
+ >To get your UserId, you have to write "/id" or "/auth" to the bot on
+ Telegram. (<a href="https://t.me/projektaktienbot)"
+ >https://t.me/projektaktienbot)</a
+ >)</span
+ >
+ </div>
+ <div mat-dialog-actions class="form-group footer-buttons">
+ <div class="inner">
+ <button
+ id="okButton"
+ class="btn btn-secondary btn-block"
+ (click)="close()"
+ [mat-dialog-close]="true"
+ >
+ Ok
+ </button>
+ </div>
+ </div>
+</div>
+
+
+ ./help-dialog.component.scss
+
.footer-buttons {
+ width: 100%;
+ text-align: center;
+}
+
+.spacer {
+ flex-grow: 1;
+ width: 5%;
+}
+
+.inner {
+ display: inline-block;
+ width: 100%;
+}
+
+.content {
+ height: 80%;
+}
+
+ +
+ src/app/Views/login/login.component.ts
+
+
+ OnInit
+
selector | +app-login |
+
styleUrls | +./login.component.scss |
+
templateUrl | +./login.component.html |
+
+ Properties+ |
+
+
|
+
+ Methods+ |
+
+
|
+
+constructor(authService: AuthService, tokenStorage: TokenStorageService, router: Router)
+ |
+ ||||||||||||
+ Defined in src/app/Views/login/login.component.ts:19
+ |
+ ||||||||||||
+
+ Parameters :
+
+
|
+
+ + + ngOnInit + + + | +
+ngOnInit()
+ |
+
+ Defined in src/app/Views/login/login.component.ts:33
+ |
+
+
+
+ Returns :
+ void
+
+ |
+
+ + + onSubmit + + + | +
+onSubmit()
+ |
+
+ Defined in src/app/Views/login/login.component.ts:41
+ |
+
+
+
+ Returns :
+ void
+
+ |
+
+ + + reloadPage + + + | +
+reloadPage()
+ |
+
+ Defined in src/app/Views/login/login.component.ts:61
+ |
+
+
+
+ Returns :
+ void
+
+ |
+
+ + + accountName + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ Defined in src/app/Views/login/login.component.ts:19
+ |
+
+ + + errorMessage + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ Defined in src/app/Views/login/login.component.ts:18
+ |
+
+ + + form + + + | +
+ Type : any
+
+ |
+
+ Default value : {
+ email: null,
+ password: null,
+ }
+ |
+
+ Defined in src/app/Views/login/login.component.ts:12
+ |
+
+ + + isLoggedIn + + + | +
+ Default value : false
+ |
+
+ Defined in src/app/Views/login/login.component.ts:16
+ |
+
+ + + isLoginFailed + + + | +
+ Default value : false
+ |
+
+ Defined in src/app/Views/login/login.component.ts:17
+ |
+
import { Component, OnInit } from '@angular/core';
+import { AuthService } from '../../Services/auth.service';
+import { TokenStorageService } from '../../Services/token.service';
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'app-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.scss'],
+})
+export class LoginComponent implements OnInit {
+ form: any = {
+ email: null,
+ password: null,
+ };
+ isLoggedIn = false;
+ isLoginFailed = false;
+ errorMessage = '';
+ accountName = '';
+
+ /**
+ * @param {AuthService} privateauthService
+ * @param {TokenStorageService} privatetokenStorage
+ * @param {Router} privaterouter
+ */
+ constructor(
+ private authService: AuthService,
+ private tokenStorage: TokenStorageService,
+ private router: Router
+ ) {}
+
+ //ngOnInit() checks if a user is logged in
+ ngOnInit(): void {
+ this.tokenStorage.signOut();
+ if (this.tokenStorage.getToken()) {
+ this.isLoggedIn = true;
+ }
+ }
+
+ //onSubmit() saves valuable information in session storage
+ onSubmit(): void {
+ const { email, password } = this.form;
+ this.authService.login(email, password).subscribe(
+ (data) => {
+ this.tokenStorage.saveToken(data.data.token);
+ this.tokenStorage.saveUser(data.data);
+
+ this.isLoginFailed = false;
+ this.isLoggedIn = true;
+ this.accountName = email;
+ this.router.navigate(['']);
+ },
+ (err) => {
+ this.errorMessage = err.error.message;
+ this.isLoginFailed = true;
+ }
+ );
+ }
+
+ //reloadPage() reloads the page
+ reloadPage(): void {
+ window.location.reload();
+ }
+}
+
+ <div class="col-md-4 login-container">
+ <div class="card card-container no-border">
+ <img
+ id="profile-img"
+ src="https://i.kym-cdn.com/entries/icons/mobile/000/029/959/Screen_Shot_2019-06-05_at_1.26.32_PM.jpg"
+ class="profile-img-card"
+ />
+ <form
+ *ngIf="!isLoggedIn"
+ name="form"
+ (ngSubmit)="f.form.valid && onSubmit()"
+ #f="ngForm"
+ novalidate
+ class="backgorund"
+ >
+ <div class="form-group">
+ <label for="email">Email</label>
+ <input
+ type="email"
+ class="form-control"
+ name="email"
+ [(ngModel)]="form.email"
+ required
+ email
+ #email="ngModel"
+ />
+ <div class="alert-danger" *ngIf="email.errors && f.submitted">
+ <div *ngIf="email.errors?.['required']">Email is required</div>
+ <div *ngIf="email.errors?.['email']">
+ Email must be a valid email address
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="password">Password</label>
+ <input
+ type="password"
+ class="form-control"
+ name="password"
+ [(ngModel)]="form.password"
+ required
+ minlength="6"
+ #password="ngModel"
+ />
+ <div
+ class="alert alert-danger"
+ role="alert"
+ *ngIf="password.errors && f.submitted"
+ >
+ <div *ngIf="password.errors?.['required']">Password is required</div>
+ <div *ngIf="password.errors?.['minlength']">
+ Password must be at least 6 characters
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <button class="btn btn-primary btn-block">Login</button>
+ </div>
+ <div class="form-group">
+ <div
+ class="alert alert-danger"
+ role="alert"
+ *ngIf="f.submitted && isLoginFailed"
+ >
+ Login failed: {{ errorMessage }}
+ </div>
+ </div>
+ </form>
+ <div class="alert alert-success" *ngIf="isLoggedIn">
+ Logged in as {{ accountName }}.
+ </div>
+ <button class="btn btn-secondary btn-block" routerLink="/register">
+ Sign up
+ </button>
+ </div>
+</div>
+
+
+ ./login.component.scss
+
.login-container {
+ margin: auto;
+ width: 60vh;
+ padding-top: 10vh;
+}
+
+.no-border {
+ border: none;
+}
+
+.backgorund {
+ background-color: #181a1b;
+ color: white;
+}
+
+ +
+ src/app/Views/profile/profile.component.ts
+
+
+ OnInit
+
selector | +app-profile |
+
styleUrls | +./profile.component.scss |
+
templateUrl | +./profile.component.html |
+
+ Properties+ |
+
+
|
+
+ Methods+ |
+
+
|
+
+constructor(profileService: ProfileService, dialog: MatDialog)
+ |
+ |||||||||
+ + | +|||||||||
+
+ Parameters :
+
+
|
+
+ + + ngOnInit + + + | +
+ngOnInit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + onSubmit + + + | +
+onSubmit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + openDialog + + + | +||||||
+openDialog(action: string)
+ |
+ ||||||
+ + | +||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ void
+
+
+
+
+ |
+
+ + + openHelp + + + | +
+openHelp()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + updateUser + + + | +
+updateUser()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + Public + dialog + + + | +
+ Type : MatDialog
+
+ |
+
+ + | +
+ + + form + + + | +
+ Type : any
+
+ |
+
+ Default value : {
+ username: null,
+ email: 'example@web.com',
+ password: 'password',
+ }
+ |
+
+ + | +
+ + + passwordFormControl + + + | +
+ Default value : new FormControl('', [
+ Validators.required,
+ Validators.minLength(6),
+ ])
+ |
+
+ + | +
+ + + telegramIdFormControl + + + | +
+ Default value : new FormControl('', [Validators.required])
+ |
+
+ + | +
+ + + userId + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ + | +
+ + + userNameFormControl + + + | +
+ Default value : new FormControl('', [Validators.required])
+ |
+
+ + | +
import { Component, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+import { MatDialog } from '@angular/material/dialog';
+import { ProfileService } from 'src/app/Services/profile.service';
+import { ConfirmationDialogComponent } from './confirmation-dialog/confirmation-dialog.component';
+import { HelpDialogComponent } from './help-dialog/help-dialog.component';
+
+@Component({
+ selector: 'app-profile',
+ templateUrl: './profile.component.html',
+ styleUrls: ['./profile.component.scss'],
+})
+export class ProfileComponent implements OnInit {
+ userNameFormControl = new FormControl('', [Validators.required]);
+ passwordFormControl = new FormControl('', [
+ Validators.required,
+ Validators.minLength(6),
+ ]);
+ telegramIdFormControl = new FormControl('', [Validators.required]);
+
+ userId = '';
+
+ form: any = {
+ username: null,
+ email: 'example@web.com',
+ password: 'password',
+ };
+
+ constructor(
+ private profileService: ProfileService,
+ public dialog: MatDialog
+ ) {}
+
+ ngOnInit(): void {
+ this.profileService.getUserData().subscribe((result) => {
+ console.log(result);
+ result = JSON.parse(result);
+ this.form.username = result.data.username;
+ this.form.password = result.data.password;
+ this.form.email = result.data.email;
+ this.userId = result.data.telegram_user_id;
+ });
+ }
+
+ onSubmit() {
+ if (this.userId != '') {
+ console.log(this.userId);
+ this.profileService.addTelegramId(this.userId).subscribe((result) => {
+ console.log(result);
+ });
+ }
+ }
+
+ updateUser() {
+ const { username, email, password } = this.form;
+ this.profileService
+ .updateProfile(this.form.username, this.form.password)
+ .subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ openDialog(action: string) {
+ const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
+ width: '50vw',
+ height: '20vh',
+ });
+
+ dialogRef.afterClosed().subscribe((result) => {
+ if (result === true) {
+ if (action === 'addTelegram') {
+ this.onSubmit();
+ } else if (action === 'updateUser') {
+ this.updateUser();
+ }
+ }
+ });
+ }
+
+ openHelp() {
+ const dialogRef = this.dialog.open(HelpDialogComponent, {
+ width: '50vw',
+ height: '20vh',
+ });
+ }
+}
+
+ <mat-grid-list cols="2" rowHeight="45%">
+ <mat-grid-tile colspan="1" rowspan="2">
+ <mat-card class="card placeholder">
+ <mat-card-title class="card-title">Profile Information</mat-card-title>
+ <mat-card-content>
+ <form
+ class="example-form form"
+ name="form"
+ (ngSubmit)="f.form.valid && openDialog('updateUser')"
+ #f="ngForm"
+ novalidate
+ >
+ <mat-form-field class="example-full-width" appearance="fill">
+ <mat-label>Username</mat-label>
+ <input
+ type="text"
+ name="username"
+ matInput
+ [formControl]="userNameFormControl"
+ placeholder="Ex. patrick-bateman"
+ [(ngModel)]="form.username"
+ #username
+ />
+ <mat-error *ngIf="userNameFormControl.hasError('required')">
+ Username is <strong>required</strong>
+ </mat-error>
+ </mat-form-field>
+ <mat-form-field class="example-full-width" appearance="fill">
+ <mat-label>{{ form.email }}</mat-label>
+ <input
+ type="email"
+ matInput
+ name="email"
+ disabled
+ placeholder="Ex. patrickbateman@example.com"
+ />
+ </mat-form-field>
+ <mat-form-field class="example-full-width" appearance="fill">
+ <mat-label>Password</mat-label>
+ <input
+ type="password"
+ matInput
+ name="password"
+ [formControl]="passwordFormControl"
+ placeholder="Password"
+ minlength="6"
+ [(ngModel)]="form.password"
+ #password
+ />
+ <mat-error
+ *ngIf="
+ passwordFormControl.hasError('minlength') &&
+ !passwordFormControl.hasError('required')
+ "
+ >
+ Please enter a valid password
+ </mat-error>
+ <mat-error *ngIf="passwordFormControl.hasError('required')">
+ Password is <strong>required</strong>
+ </mat-error>
+ </mat-form-field>
+ <mat-form-field class="example-full-width" appearance="fill">
+ <mat-label>Repeat Password</mat-label>
+ <input
+ type="password"
+ matInput
+ [formControl]="passwordFormControl"
+ placeholder="Ex. pat@example.com"
+ />
+ <mat-error
+ *ngIf="
+ passwordFormControl.hasError('minLength') &&
+ !passwordFormControl.hasError('required')
+ "
+ >
+ Please enter a valid password
+ </mat-error>
+ <mat-error *ngIf="passwordFormControl.hasError('required')">
+ Password is <strong>required</strong>
+ </mat-error>
+ </mat-form-field>
+ <div class="form-group footer-buttons">
+ <button
+ class="btn btn-primary btn-block"
+ [disabled]="
+ passwordFormControl.hasError('required') ||
+ passwordFormControl.hasError('minLength') ||
+ userNameFormControl.hasError('required')
+ "
+ >
+ Update
+ </button>
+ </div>
+ </form>
+ </mat-card-content>
+ </mat-card>
+ </mat-grid-tile>
+ <mat-grid-tile colspan="1" rowspan="2">
+ <mat-card class="card placeholder">
+ <mat-card-title class="card-title">
+ <span>Connect Telegram Account</span>
+ </mat-card-title>
+ <mat-card-content>
+ <form
+ name="form"
+ (ngSubmit)="f.form.valid && openDialog('addTelegram')"
+ #f="ngForm"
+ novalidate
+ class="backgorund form"
+ >
+ <mat-form-field class="example-full-width" appearance="fill">
+ <mat-label>Telegram UserId</mat-label>
+ <input
+ type="text"
+ matInput
+ [formControl]="telegramIdFormControl"
+ [(ngModel)]="userId"
+ required
+ #telegramId
+ />
+ <mat-error *ngIf="telegramIdFormControl.hasError('required')">
+ Id is <strong>required</strong>
+ </mat-error>
+ </mat-form-field>
+ <div class="form-group footer-buttons">
+ <button
+ class="btn btn-primary btn-block"
+ [disabled]="telegramIdFormControl.hasError('required')"
+ >
+ Add
+ </button>
+ </div>
+ </form>
+ <button class="btn btn-secondary btn-block" (click)="openHelp()">
+ Help
+ </button>
+ </mat-card-content>
+ </mat-card>
+ </mat-grid-tile>
+</mat-grid-list>
+
+
+ ./profile.component.scss
+
.form {
+ width: 100%;
+}
+
+.card {
+ width: 90%;
+ height: 90%;
+ margin: 5%;
+}
+
+.example-full-width {
+ width: 100%;
+}
+
+.card-title {
+ padding-bottom: 2.5vh;
+}
+
+mat-grid {
+ width: 100%;
+ height: 100%;
+}
+
+.placeholder {
+ height: 95%;
+}
+
+.placeholderRHS {
+ height: 90%;
+}
+
+.cron-content {
+ height: 70%;
+ overflow: auto;
+}
+
+ +
+ src/app/Views/register/register.component.ts
+
selector | +app-register |
+
styleUrls | +./register.component.scss |
+
templateUrl | +./register.component.html |
+
+ Properties+ |
+
+
|
+
+ Methods+ |
+
+
|
+
+constructor(authService: AuthService, router: Router)
+ |
+ |||||||||
+ + | +|||||||||
+
+ Parameters :
+
+
|
+
+ + + onSubmit + + + | +
+onSubmit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + errorMessage + + + | +
+ Type : string
+
+ |
+
+ Default value : ''
+ |
+
+ + | +
+ + + form + + + | +
+ Type : any
+
+ |
+
+ Default value : {
+ email: null,
+ password: null,
+ username: null,
+ }
+ |
+
+ + | +
+ + + isSignUpFailed + + + | +
+ Default value : false
+ |
+
+ + | +
+ + + isSuccessful + + + | +
+ Default value : false
+ |
+
+ + | +
import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { AuthService } from '../../Services/auth.service';
+
+@Component({
+ selector: 'app-register',
+ templateUrl: './register.component.html',
+ styleUrls: ['./register.component.scss'],
+})
+export class RegisterComponent {
+ form: any = {
+ email: null,
+ password: null,
+ username: null,
+ };
+ isSuccessful = false;
+ isSignUpFailed = false;
+ errorMessage = '';
+
+ /**
+ * @param {AuthService} privateauthService
+ * @param {Router} privaterouter
+ */
+ constructor(private authService: AuthService, private router: Router) {}
+ onSubmit(): void {
+ const { email, username, password } = this.form;
+ this.authService.register(email, username, password).subscribe(
+ (data) => {
+ this.isSuccessful = true;
+ this.isSignUpFailed = false;
+ this.router.navigate(['/login']);
+ },
+ (err) => {
+ this.errorMessage = err.error.message;
+ this.isSignUpFailed = true;
+ }
+ );
+ }
+}
+
+ <div class="col-md-4 login-container">
+ <div class="card card-container no-border">
+ <img
+ id="profile-img"
+ src="https://i.kym-cdn.com/entries/icons/mobile/000/029/959/Screen_Shot_2019-06-05_at_1.26.32_PM.jpg"
+ class="profile-img-card"
+ />
+ <form
+ *ngIf="!isSuccessful"
+ name="form"
+ (ngSubmit)="f.form.valid && onSubmit()"
+ #f="ngForm"
+ novalidate
+ class="backgorund"
+ >
+ <div class="form-group">
+ <label for="username">Username</label>
+ <input
+ type="text"
+ class="form-control"
+ name="username"
+ [(ngModel)]="form.username"
+ required
+ minlength="3"
+ maxlength="20"
+ #username="ngModel"
+ />
+ <div class="alert-danger" *ngIf="username.errors && f.submitted">
+ <div *ngIf="username.errors?.['required']">Username is required</div>
+ <div *ngIf="username.errors?.['minlength']">
+ Username must be at least 3 characters
+ </div>
+ <div *ngIf="username.errors?.['maxlength']">
+ Username must be at most 20 characters
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="email">Email</label>
+ <input
+ type="email"
+ class="form-control"
+ name="email"
+ [(ngModel)]="form.email"
+ required
+ email
+ #email="ngModel"
+ />
+ <div class="alert-danger" *ngIf="email.errors && f.submitted">
+ <div *ngIf="email.errors?.['required']">Email is required</div>
+ <div *ngIf="email.errors?.['email']">
+ Email must be a valid email address
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="password">Password</label>
+ <input
+ type="password"
+ class="form-control"
+ name="password"
+ [(ngModel)]="form.password"
+ required
+ minlength="6"
+ #password="ngModel"
+ />
+ <div class="alert-danger" *ngIf="password.errors && f.submitted">
+ <div *ngIf="password.errors?.['required']">Password is required</div>
+ <div *ngIf="password.errors?.['minlength']">
+ Password must be at least 6 characters
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="password">Confirm Password</label>
+ <input
+ type="password"
+ class="form-control"
+ name="passwordRepeat"
+ [(ngModel)]="form.password"
+ required
+ minlength="6"
+ #passwordRepeat="ngModel"
+ />
+ <div class="alert-danger" *ngIf="password.errors && f.submitted">
+ <div *ngIf="passwordRepeat.errors?.['required']">
+ Confirmation is required
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <button class="btn btn-primary btn-block">Sign Up</button>
+ </div>
+ <div class="alert alert-warning" *ngIf="f.submitted && isSignUpFailed">
+ Signup failed!<br />{{ errorMessage }}
+ </div>
+ </form>
+ <div class="alert alert-success" *ngIf="isSuccessful">
+ Your registration is successful!
+ </div>
+ <button class="btn btn-secondary btn-block" routerLink="/login">
+ Go Back
+ </button>
+ </div>
+</div>
+
+
+ ./register.component.scss
+
.login-container {
+ margin: auto;
+ width: 60vh;
+ padding-top: 10vh;
+}
+
+.no-border {
+ border: none;
+}
+
+.backgorund {
+ background-color: #181a1b;
+ color: white;
+}
+
+ +
+ src/app/Views/dashboard/user-dialog/user-dialog.component.ts
+
selector | +app-user-dialog |
+
styleUrls | +./user-dialog.component.scss |
+
templateUrl | +./user-dialog.component.html |
+
+ Properties+ |
+
+ + | +
+ Methods+ |
+
+
|
+
+constructor(dataService: DataService, dialog: MatDialog, dialogRef: MatDialogRef<UserDialogComponent>, data: TransactionData)
+ |
+ |||||||||||||||
+ + | +|||||||||||||||
+
+ Parameters :
+
+
|
+
+ + + onSubmit + + + | +
+onSubmit()
+ |
+
+ + | +
+
+
+ Returns :
+ void
+
+ |
+
+ + + Public + data + + + | +
+ Type : TransactionData
+
+ |
+
+ Decorators :
+ +
+ @Inject(MAT_DIALOG_DATA)
+ |
+
+ + | +
+ + + Public + dialog + + + | +
+ Type : MatDialog
+
+ |
+
+ + | +
+ + + Public + dialogRef + + + | +
+ Type : MatDialogRef<UserDialogComponent>
+
+ |
+
+ + | +
import { Component, Inject, OnInit } from '@angular/core';
+import {
+ MatDialog,
+ MatDialogRef,
+ MAT_DIALOG_DATA,
+} from '@angular/material/dialog';
+import { DataService } from 'src/app/Services/data.service';
+
+import { TransactionData } from '../dashboard.component';
+
+@Component({
+ selector: 'app-user-dialog',
+ templateUrl: './user-dialog.component.html',
+ styleUrls: ['./user-dialog.component.scss'],
+})
+export class UserDialogComponent {
+ constructor(
+ private dataService: DataService,
+ public dialog: MatDialog,
+ public dialogRef: MatDialogRef<UserDialogComponent>,
+ @Inject(MAT_DIALOG_DATA) public data: TransactionData
+ ) {}
+
+ onSubmit() {
+ //TODO check that price is decimal
+ console.log(
+ this.dataService
+ .createTransaction(
+ this.data.comment,
+ this.data.isin,
+ this.data.time,
+ +this.data.count,
+ +this.data.price.toFixed(2)
+ )
+ .subscribe((data) => {
+ console.log(data);
+ })
+ );
+ this.dialog.closeAll();
+ }
+}
+
+ <h1 mat-dialog-title>Neue Transaktion hinzufügen</h1>
+<form
+ name="form"
+ (ngSubmit)="f.form.valid && onSubmit()"
+ #f="ngForm"
+ novalidate
+ class="backgorund"
+>
+ <div class="form-group">
+ <label for="comment">Comment</label>
+ <input
+ type="comment"
+ class="form-control"
+ name="comment"
+ [(ngModel)]="data.comment"
+ required
+ comment
+ #comment="ngModel"
+ />
+ </div>
+ <div class="form-group">
+ <label for="isin">isin</label>
+ <input
+ type="isin"
+ class="form-control"
+ name="isin"
+ [(ngModel)]="data.isin"
+ required
+ isin
+ #isin="ngModel"
+ />
+ </div>
+ <div class="form-group">
+ <label for="time">Time</label>
+ <input
+ type="date"
+ class="form-control"
+ name="time"
+ [(ngModel)]="data.time"
+ required
+ time
+ #time="ngModel"
+ />
+ </div>
+ <div class="form-group">
+ <label for="count">Count</label>
+ <input
+ type="count"
+ class="form-control"
+ name="count"
+ [(ngModel)]="data.count"
+ required
+ count
+ #count="ngModel"
+ />
+ </div>
+ <div class="form-group">
+ <label for="price">Price</label>
+ <input
+ class="form-control"
+ name="price"
+ [(ngModel)]="data.price"
+ required
+ #price="ngModel"
+ type="number"
+ />
+ </div>
+ <div class="form-group footer-buttons">
+ <button class="btn btn-danger btn-block" mat-dialog-close>Cancel</button>
+ <span class="spacer"></span>
+ <button class="btn btn-primary btn-block">Confirm</button>
+ </div>
+</form>
+
+
+ ./user-dialog.component.scss
+
.spacer {
+ flex-grow: 1;
+ width: 5%;
+}
+
+.footer-buttons {
+ display: flex;
+ width: 100%;
+}
+
+ File | +Type | +Identifier | +Statements | +
---|---|---|---|
+ + src/app/Helpers/auth.interceptor.ts + | +interceptor | +AuthInterceptor | ++ 0 % + (0/3) + | +
+ + src/app/Helpers/auth.interceptor.ts + | +variable | +authInterceptorProviders | ++ 0 % + (0/1) + | +
+ + src/app/Helpers/auth.interceptor.ts + | +variable | +TOKEN_HEADER_KEY | ++ 0 % + (0/1) + | +
+ + src/app/Helpers/helper.service.ts + | +injectable | +HelperService | ++ 0 % + (0/5) + | +
+ + src/app/Services/auth.service.ts + | +injectable | +AuthService | ++ 0 % + (0/4) + | +
+ + src/app/Services/auth.service.ts + | +variable | +AUTH_API | ++ 0 % + (0/1) + | +
+ + src/app/Services/auth.service.ts + | +variable | +httpOptions | ++ 0 % + (0/1) + | +
+ + src/app/Services/bot.service.ts + | +injectable | +BotService | ++ 0 % + (0/8) + | +
+ + src/app/Services/bot.service.ts + | +variable | +API_URL | ++ 0 % + (0/1) + | +
+ + src/app/Services/data.service.ts + | +injectable | +DataService | ++ 0 % + (0/6) + | +
+ + src/app/Services/data.service.ts + | +variable | +API_URL | ++ 0 % + (0/1) + | +
+ + src/app/Services/profile.service.ts + | +injectable | +ProfileService | ++ 0 % + (0/6) + | +
+ + src/app/Services/profile.service.ts + | +variable | +API_URL | ++ 0 % + (0/1) + | +
+ + src/app/Services/token.service.ts + | +injectable | +TokenStorageService | ++ 0 % + (0/7) + | +
+ + src/app/Services/token.service.ts + | +variable | +TOKEN_KEY | ++ 0 % + (0/1) + | +
+ + src/app/Services/token.service.ts + | +variable | +USER_KEY | ++ 0 % + (0/1) + | +
+ + src/app/Views/bot-settings/bot-settings.component.ts + | +component | +BotSettingsComponent | ++ 0 % + (0/14) + | +
+ + src/app/Views/bot-settings/bot-settings.component.ts + | +interface | +Fruit | ++ 0 % + (0/2) + | +
+ + src/app/Views/bot-settings/bot-settings.component.ts + | +interface | +Keyword | ++ 0 % + (0/2) + | +
+ + src/app/Views/bot-settings/bot-settings.component.ts + | +interface | +Share | ++ 0 % + (0/2) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +component | +DashboardComponent | ++ 0 % + (0/19) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +interface | +PeriodicElement | ++ 0 % + (0/5) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +interface | +Stock | ++ 0 % + (0/5) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +interface | +TransactionData | ++ 0 % + (0/6) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +variable | +ELEMENT_DATA | ++ 0 % + (0/1) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +variable | +STOCK_DATA | ++ 0 % + (0/1) + | +
+ + src/app/Views/dashboard/dashboard.component.ts + | +variable | +TRANSACTION_DATA | ++ 0 % + (0/1) + | +
+ + src/app/Views/dashboard/user-dialog/user-dialog.component.ts + | +component | +UserDialogComponent | ++ 0 % + (0/6) + | +
+ + src/app/Views/header/header.component.ts + | +component | +HeaderComponent | ++ 0 % + (0/3) + | +
+ + src/app/Views/login/login.component.ts + | +component | +LoginComponent | ++ 0 % + (0/10) + | +
+ + src/app/Views/profile/confirmation-dialog/confirmation-dialog.component.ts + | +component | +ConfirmationDialogComponent | ++ 0 % + (0/4) + | +
+ + src/app/Views/profile/help-dialog/help-dialog.component.ts + | +component | +HelpDialogComponent | ++ 0 % + (0/3) + | +
+ + src/app/Views/profile/profile.component.ts + | +component | +ProfileComponent | ++ 0 % + (0/13) + | +
+ + src/app/Views/register/register.component.ts + | +component | +RegisterComponent | ++ 0 % + (0/7) + | +
+ + src/app/app.component.ts + | +component | +AppComponent | ++ 40 % + (2/5) + | +
+ + src/environments/environment.prod.ts + | +variable | +environment | ++ 0 % + (0/1) + | +
+ + src/environments/environment.ts + | +variable | +environment | ++ 0 % + (0/1) + | +
+ + src/test.ts + | +variable | +context | ++ 0 % + (0/1) + | +
+ + src/test.ts + | +variable | +require | ++ 0 % + (0/1) + | +
This project was generated with Angular CLI version 13.2.5.
+Run ng serve
for a dev server. Navigate to http://localhost:4200/
. The app will automatically reload if you change any of the source files.
Run ng generate component component-name
to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module
.
Run ng build
to build the project. The build artifacts will be stored in the dist/
directory.
Run ng test
to execute the unit tests via Karma.
Run ng e2e
to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
To get more help on the Angular CLI use ng help
or go check out the Angular CLI Overview and Command Reference page.
+
+ src/app/Services/auth.service.ts
+
+ Methods+ |
+
+ + | +
+constructor(http: HttpClient)
+ |
+ ||||||
+ Defined in src/app/Services/auth.service.ts:13
+ |
+ ||||||
+
+ Parameters :
+
+
|
+
+ + + login + + + | +|||||||||
+login(email: string, password: string)
+ |
+ |||||||||
+ Defined in src/app/Services/auth.service.ts:21
+ |
+ |||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + register + + + | +||||||||||||
+register(email: string, username: string, password: string)
+ |
+ ||||||||||||
+ Defined in src/app/Services/auth.service.ts:34
+ |
+ ||||||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Observable } from 'rxjs';
+const AUTH_API = 'https://gruppe1.testsites.info/api/user';
+
+const httpOptions = {
+ headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
+};
+
+@Injectable({
+ providedIn: 'root',
+})
+export class AuthService {
+ constructor(private http: HttpClient) {}
+
+ /**
+ * @param {string} email
+ * @param {string} password
+ * @returns Observable
+ */
+ login(email: string, password: string): Observable<any> {
+ return this.http.post(AUTH_API + '/login', {
+ email,
+ password,
+ });
+ }
+
+ /**
+ * @param {string} email
+ * @param {string} username
+ * @param {string} password
+ * @returns Observable
+ */
+ register(email: string, username: string, password: string): Observable<any> {
+ return this.http.post(
+ AUTH_API + '/register',
+ {
+ email,
+ password,
+ username,
+ },
+ httpOptions
+ );
+ }
+}
+
+ +
+ src/app/Services/bot.service.ts
+
+ Methods+ |
+
+
|
+
+constructor(http: HttpClient, tokenStorage: TokenStorageService)
+ |
+ |||||||||
+ Defined in src/app/Services/bot.service.ts:11
+ |
+ |||||||||
+
+ Parameters :
+
+
|
+
+ + + Public + createKeyword + + + | +||||||
+
+ createKeyword(keyword: string)
+ |
+ ||||||
+ Defined in src/app/Services/bot.service.ts:34
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + createShare + + + | +|||||||||
+
+ createShare(isin: string, comment: string)
+ |
+ |||||||||
+ Defined in src/app/Services/bot.service.ts:82
+ |
+ |||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + deleteKeyword + + + | +||||||
+
+ deleteKeyword(keyword: string)
+ |
+ ||||||
+ Defined in src/app/Services/bot.service.ts:53
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + deleteShare + + + | +||||||
+
+ deleteShare(symbol: string)
+ |
+ ||||||
+ Defined in src/app/Services/bot.service.ts:102
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getKeywords + + + | +
+
+ getKeywords()
+ |
+
+ Defined in src/app/Services/bot.service.ts:20
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getSymbols + + + | +
+
+ getSymbols()
+ |
+
+ Defined in src/app/Services/bot.service.ts:68
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { TokenStorageService } from './token.service';
+
+const API_URL = 'https://gruppe1.testsites.info/api/';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class BotService {
+ constructor(
+ private http: HttpClient,
+ private tokenStorage: TokenStorageService
+ ) {}
+
+ /**
+ * @returns Observable
+ */
+ public getKeywords(): Observable<any> {
+ return this.http.get(API_URL + 'keywords', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+
+ /**
+ * @param {string} keyword
+ * @returns Observable
+ */
+ public createKeyword(keyword: string): Observable<any> {
+ return this.http.post(
+ API_URL + 'keyword',
+ {
+ keyword,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+
+ /**
+ * @param {string} keyword
+ * @returns Observable
+ */
+ public deleteKeyword(keyword: string): Observable<any> {
+ return this.http.delete(API_URL + 'keyword', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ body: {
+ keyword,
+ },
+ });
+ }
+
+ /**
+ * @returns Observable
+ */
+ public getSymbols(): Observable<any> {
+ return this.http.get(API_URL + 'shares', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+
+ /**
+ * @param {string} keyword
+ * @returns Observable
+ */
+ public createShare(isin: string, comment: string): Observable<any> {
+ return this.http.post(
+ API_URL + 'share',
+ {
+ comment,
+ isin,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+
+ /**
+ * @param {string} symbol
+ * @returns Observable
+ */
+ public deleteShare(symbol: string): Observable<any> {
+ return this.http.delete(API_URL + 'share', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ body: {
+ symbol,
+ },
+ });
+ }
+}
+
+ +
+ src/app/Services/data.service.ts
+
+ Methods+ |
+
+
|
+
+constructor(http: HttpClient, tokenStorage: TokenStorageService)
+ |
+ |||||||||
+ Defined in src/app/Services/data.service.ts:9
+ |
+ |||||||||
+
+ Parameters :
+
+
|
+
+ + + Public + createTransaction + + + | +||||||||||||||||||
+
+ createTransaction(comment: string, isin: string, time: string, count: number, price: number)
+ |
+ ||||||||||||||||||
+ Defined in src/app/Services/data.service.ts:52
+ |
+ ||||||||||||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getKeywords + + + | +
+
+ getKeywords()
+ |
+
+ Defined in src/app/Services/data.service.ts:82
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getStockData + + + | +
+
+ getStockData()
+ |
+
+ Defined in src/app/Services/data.service.ts:22
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getTransactionData + + + | +
+
+ getTransactionData()
+ |
+
+ Defined in src/app/Services/data.service.ts:35
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
import { Injectable, OnInit } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { delay, Observable } from 'rxjs';
+import { TokenStorageService } from './token.service';
+const API_URL = 'https://gruppe1.testsites.info/api/';
+@Injectable({
+ providedIn: 'root',
+})
+export class DataService {
+ /**
+ * @param {HttpClient} privatehttp
+ * @param {TokenStorageService} privatetokenStorage
+ */
+ constructor(
+ private http: HttpClient,
+ private tokenStorage: TokenStorageService
+ ) {}
+
+ /**
+ * @returns Observable
+ */
+ public getStockData(): Observable<any> {
+ return this.http.get(API_URL + 'portfolio', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+
+ /**
+ * @returns Observable
+ */
+ public getTransactionData(): Observable<any> {
+ return this.http.get(API_URL + 'transactions', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+
+ /**
+ * @param {string} symbol
+ * @param {Date} time
+ * @param {number} count
+ * @param {number} price
+ * @returns Observable
+ */
+ public createTransaction(
+ comment: string,
+ isin: string,
+ time: string,
+ count: number,
+ price: number
+ ): Observable<any> {
+ time = time + 'T12:00:00.000Z';
+ price.toFixed(2);
+ return this.http.post(
+ API_URL + 'transaction',
+ {
+ comment,
+ count,
+ isin,
+ price,
+ time,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+
+ /**
+ * @returns Observable
+ */
+ public getKeywords(): Observable<any> {
+ return this.http.get(API_URL + 'keywords', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+}
+
+ +
+ src/app/Helpers/helper.service.ts
+
+ Methods+ |
+
+
|
+
+constructor(botService: BotService)
+ |
+ ||||||
+ Defined in src/app/Helpers/helper.service.ts:8
+ |
+ ||||||
+
+ Parameters :
+
+
|
+
+ + + delay + + + | +||||||
+delay(ms: number)
+ |
+ ||||||
+ Defined in src/app/Helpers/helper.service.ts:14
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ any
+
+
+
+
+ |
+
+ + + formatKeywordsData + + + | +
+formatKeywordsData()
+ |
+
+ Defined in src/app/Helpers/helper.service.ts:31
+ |
+
+
+
+ Returns :
+ Keyword[]
+
+ |
+
+ + + formatShareData + + + | +
+formatShareData()
+ |
+
+ Defined in src/app/Helpers/helper.service.ts:18
+ |
+
+
+
+ Returns :
+ Share[]
+
+ |
+
import { Injectable } from '@angular/core';
+import { BotService } from '../Services/bot.service';
+import { Keyword, Share } from '../Views/bot-settings/bot-settings.component';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class HelperService {
+ constructor(private botService: BotService) {}
+
+ /**
+ * @param {number} ms
+ */
+ delay(ms: number) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+ }
+
+ formatShareData(): Share[] {
+ var shares: Share[] = [];
+ this.botService.getSymbols().subscribe((result) => {
+ var data = JSON.parse(result);
+ for (let i = 0; i < data.data.length; i++) {
+ shares.push({
+ isin: data.data[i].isin,
+ });
+ }
+ });
+ return shares;
+ }
+
+ formatKeywordsData(): Keyword[] {
+ var keywords: Keyword[] = [];
+ this.botService.getKeywords().subscribe((result) => {
+ var data = JSON.parse(result);
+ for (let i = 0; i < data.data.length; i++) {
+ keywords.push({
+ name: data.data[i].keyword,
+ });
+ }
+ });
+ return keywords;
+ }
+}
+
+ +
+ src/app/Services/profile.service.ts
+
+ Methods+ |
+
+
|
+
+constructor(tokenStorage: TokenStorageService, http: HttpClient)
+ |
+ |||||||||
+ Defined in src/app/Services/profile.service.ts:11
+ |
+ |||||||||
+
+ Parameters :
+
+
|
+
+ + + Public + addCronString + + + | +||||||
+
+ addCronString(cron: string)
+ |
+ ||||||
+ Defined in src/app/Services/profile.service.ts:74
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + addTelegramId + + + | +||||||
+
+ addTelegramId(telegram_user_id: string)
+ |
+ ||||||
+ Defined in src/app/Services/profile.service.ts:55
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + getUserData + + + | +
+
+ getUserData()
+ |
+
+ Defined in src/app/Services/profile.service.ts:20
+ |
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
+ + + Public + updateProfile + + + | +|||||||||
+
+ updateProfile(username: string, password: number)
+ |
+ |||||||||
+ Defined in src/app/Services/profile.service.ts:35
+ |
+ |||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<any>
+
+
+
+ Observable + + |
+
import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { TokenStorageService } from './token.service';
+
+const API_URL = 'https://gruppe1.testsites.info/api/';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class ProfileService {
+ constructor(
+ private tokenStorage: TokenStorageService,
+ private http: HttpClient
+ ) {}
+
+ /**
+ * @returns Observable
+ */
+ public getUserData(): Observable<any> {
+ return this.http.get(API_URL + 'user', {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ responseType: 'text',
+ });
+ }
+
+ /**
+ * @param {string} username
+ * @param {number} password
+ * @returns Observable
+ */
+ public updateProfile(username: string, password: number): Observable<any> {
+ return this.http.put(
+ API_URL + 'user',
+ {
+ username,
+ password,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+
+ /**
+ * @param {string} telegramUserID
+ * @returns Observable
+ */
+ public addTelegramId(telegram_user_id: string): Observable<any> {
+ return this.http.post(
+ API_URL + 'telegram',
+ {
+ telegram_user_id,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+
+ /**
+ * @param {string} cronString
+ * @returns Observable
+ */
+ public addCronString(cron: string): Observable<any> {
+ return this.http.put(
+ 'https://gruppe1.testsites.info/api/user' + '/setCron',
+ {
+ cron,
+ },
+ {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + this.tokenStorage.getToken(),
+ }),
+ }
+ );
+ }
+}
+
+ +
+ src/app/Services/token.service.ts
+
+ Methods+ |
+
+ + | +
+constructor()
+ |
+
+ Defined in src/app/Services/token.service.ts:7
+ |
+
+ + + Public + getToken + + + | +
+
+ getToken()
+ |
+
+ Defined in src/app/Services/token.service.ts:29
+ |
+
+
+
+
+
+ Returns :
+ string | null
+
+
+
+ string + + |
+
+ + + Public + getUser + + + | +
+
+ getUser()
+ |
+
+ Defined in src/app/Services/token.service.ts:45
+ |
+
+
+
+
+
+ Returns :
+ any
+
+
+
+ any + + |
+
+ + + Public + saveToken + + + | +||||||
+
+ saveToken(token: string)
+ |
+ ||||||
+ Defined in src/app/Services/token.service.ts:21
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ void
+
+
+
+ void + + |
+
+ + + Public + saveUser + + + | +||||||
+
+ saveUser(user: any)
+ |
+ ||||||
+ Defined in src/app/Services/token.service.ts:37
+ |
+ ||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ void
+
+
+
+ void + + |
+
+ + + signOut + + + | +
+signOut()
+ |
+
+ Defined in src/app/Services/token.service.ts:13
+ |
+
+
+
+
+
+ Returns :
+ void
+
+
+
+ void + + |
+
import { Injectable } from '@angular/core';
+const TOKEN_KEY = 'auth-token';
+const USER_KEY = 'auth-user';
+@Injectable({
+ providedIn: 'root',
+})
+export class TokenStorageService {
+ constructor() {}
+
+ /**
+ * @returns void
+ */
+ signOut(): void {
+ window.sessionStorage.clear();
+ }
+
+ /**
+ * @param {string} token
+ * @returns void
+ */
+ public saveToken(token: string): void {
+ window.sessionStorage.removeItem(TOKEN_KEY);
+ window.sessionStorage.setItem(TOKEN_KEY, token);
+ }
+
+ /**
+ * @returns string
+ */
+ public getToken(): string | null {
+ return window.sessionStorage.getItem(TOKEN_KEY);
+ }
+
+ /**
+ * @param {any} user
+ * @returns void
+ */
+ public saveUser(user: any): void {
+ window.sessionStorage.removeItem(USER_KEY);
+ window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
+ }
+
+ /**
+ * @returns any
+ */
+ public getUser(): any {
+ const user = window.sessionStorage.getItem(USER_KEY);
+ if (user) {
+ return JSON.parse(user);
+ }
+ return {};
+ }
+}
+
+ +
+ src/app/Helpers/auth.interceptor.ts
+
+ Methods+ |
+
+
|
+
+constructor(token: TokenStorageService)
+ |
+ ||||||
+ Defined in src/app/Helpers/auth.interceptor.ts:12
+ |
+ ||||||
+
+ Parameters :
+
+
|
+
+ + + intercept + + + | +|||||||||
+intercept(req: HttpRequest
+ |
+ |||||||||
+ Defined in src/app/Helpers/auth.interceptor.ts:14
+ |
+ |||||||||
+
+
+ Parameters :
+
+
+
+
+
+ Returns :
+ Observable<HttpEvent<any>>
+
+
+
+
+ |
+
import { HTTP_INTERCEPTORS, HttpEvent } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import {
+ HttpInterceptor,
+ HttpHandler,
+ HttpRequest,
+} from '@angular/common/http';
+import { TokenStorageService } from '../Services/token.service';
+import { Observable } from 'rxjs';
+const TOKEN_HEADER_KEY = 'Authorization';
+@Injectable()
+export class AuthInterceptor implements HttpInterceptor {
+ constructor(private token: TokenStorageService) {}
+ intercept(
+ req: HttpRequest<any>,
+ next: HttpHandler
+ ): Observable<HttpEvent<any>> {
+ let authReq = req;
+ const token = this.token.getToken();
+ if (token != null) {
+ authReq = req.clone({
+ headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token),
+ });
+ }
+ return next.handle(authReq);
+ }
+}
+export const authInterceptorProviders = [
+ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
+];
+
+ +
+ src/app/Views/bot-settings/bot-settings.component.ts
+
+ Properties+ |
+
+
|
+
+ + name + + + + + | +
+ name:
+ |
+
+ Type : string
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { C, COMMA, ENTER, F } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+
+import { CronOptions } from 'ngx-cron-editor';
+
+import { BotService } from 'src/app/Services/bot.service';
+import { HelperService } from 'src/app/Helpers/helper.service';
+import { ProfileService } from 'src/app/Services/profile.service';
+import { FormControl } from '@angular/forms';
+
+export interface Fruit {
+ name: string;
+}
+
+export interface Share {
+ isin: string;
+}
+
+export interface Keyword {
+ name: string;
+}
+
+@Component({
+ selector: 'app-bot-settings',
+ templateUrl: './bot-settings.component.html',
+ styleUrls: ['./bot-settings.component.scss'],
+})
+export class BotSettingsComponent implements OnInit {
+ keywords: Keyword[] = [];
+ shares: Share[] = [];
+
+ constructor(
+ private botService: BotService,
+ private helper: HelperService,
+ private profileService: ProfileService
+ ) {}
+
+ ngOnInit(): void {
+ this.shares = this.helper.formatShareData();
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ addOnBlur = true;
+ readonly separatorKeysCodes = [ENTER, COMMA] as const;
+
+ async addKeyword(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add keyword to database
+ if (value && !this.keywords.includes({ name: value })) {
+ console.log('Added: ' + value);
+ this.botService.createKeyword(value.toLowerCase()).subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+ }
+
+ async removeKeyword(keyword: Keyword): Promise<void> {
+ this.botService.deleteKeyword(keyword.name).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ async addShare(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add share to database
+ if (value && !this.shares.includes({ isin: value.toLowerCase() })) {
+ console.log('Added: ' + value);
+ this.botService.createShare(value, 'Comment').subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+ }
+
+ async removeShare(share: Share): Promise<void> {
+ this.botService.deleteShare(share.isin).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+
+ setCronString() {
+ this.profileService
+ .addCronString(this.cronForm.value)
+ .subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ cronForm = new FormControl('0 0 1/1 * *');
+ public cronOptions: CronOptions = {
+ defaultTime: '00:00:00',
+
+ hideMinutesTab: true,
+ hideHourlyTab: true,
+ hideDailyTab: false,
+ hideWeeklyTab: true,
+ hideMonthlyTab: true,
+ hideYearlyTab: true,
+ hideAdvancedTab: true,
+ hideSpecificWeekDayTab: true,
+ hideSpecificMonthWeekTab: true,
+
+ use24HourTime: true,
+ hideSeconds: true,
+
+ cronFlavor: 'quartz', //standard or quartz
+ };
+}
+
+ +
+ src/app/Views/bot-settings/bot-settings.component.ts
+
+ Properties+ |
+
+
|
+
+ + name + + + + + | +
+ name:
+ |
+
+ Type : string
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { C, COMMA, ENTER, F } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+
+import { CronOptions } from 'ngx-cron-editor';
+
+import { BotService } from 'src/app/Services/bot.service';
+import { HelperService } from 'src/app/Helpers/helper.service';
+import { ProfileService } from 'src/app/Services/profile.service';
+import { FormControl } from '@angular/forms';
+
+export interface Fruit {
+ name: string;
+}
+
+export interface Share {
+ isin: string;
+}
+
+export interface Keyword {
+ name: string;
+}
+
+@Component({
+ selector: 'app-bot-settings',
+ templateUrl: './bot-settings.component.html',
+ styleUrls: ['./bot-settings.component.scss'],
+})
+export class BotSettingsComponent implements OnInit {
+ keywords: Keyword[] = [];
+ shares: Share[] = [];
+
+ constructor(
+ private botService: BotService,
+ private helper: HelperService,
+ private profileService: ProfileService
+ ) {}
+
+ ngOnInit(): void {
+ this.shares = this.helper.formatShareData();
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ addOnBlur = true;
+ readonly separatorKeysCodes = [ENTER, COMMA] as const;
+
+ async addKeyword(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add keyword to database
+ if (value && !this.keywords.includes({ name: value })) {
+ console.log('Added: ' + value);
+ this.botService.createKeyword(value.toLowerCase()).subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+ }
+
+ async removeKeyword(keyword: Keyword): Promise<void> {
+ this.botService.deleteKeyword(keyword.name).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ async addShare(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add share to database
+ if (value && !this.shares.includes({ isin: value.toLowerCase() })) {
+ console.log('Added: ' + value);
+ this.botService.createShare(value, 'Comment').subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+ }
+
+ async removeShare(share: Share): Promise<void> {
+ this.botService.deleteShare(share.isin).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+
+ setCronString() {
+ this.profileService
+ .addCronString(this.cronForm.value)
+ .subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ cronForm = new FormControl('0 0 1/1 * *');
+ public cronOptions: CronOptions = {
+ defaultTime: '00:00:00',
+
+ hideMinutesTab: true,
+ hideHourlyTab: true,
+ hideDailyTab: false,
+ hideWeeklyTab: true,
+ hideMonthlyTab: true,
+ hideYearlyTab: true,
+ hideAdvancedTab: true,
+ hideSpecificWeekDayTab: true,
+ hideSpecificMonthWeekTab: true,
+
+ use24HourTime: true,
+ hideSeconds: true,
+
+ cronFlavor: 'quartz', //standard or quartz
+ };
+}
+
+ +
+ src/app/Views/dashboard/dashboard.component.ts
+
+ Properties+ |
+
+
|
+
+ + name + + + + + | +
+ name:
+ |
+
+ Type : string
+
+ |
+
+ + position + + + + + | +
+ position:
+ |
+
+ Type : number
+
+ |
+
+ + symbol + + + + + | +
+ symbol:
+ |
+
+ Type : string
+
+ |
+
+ + weight + + + + + | +
+ weight:
+ |
+
+ Type : number
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { DataService } from 'src/app/Services/data.service';
+import { MatDialog } from '@angular/material/dialog';
+import { UserDialogComponent } from './user-dialog/user-dialog.component';
+import { HelperService } from 'src/app/Helpers/helper.service';
+
+export interface PeriodicElement {
+ name: string;
+ position: number;
+ weight: number;
+ symbol: string;
+}
+
+export interface Stock {
+ count: number;
+ currentPrice: number;
+ symbol: string;
+ time: string;
+}
+
+//symbol count lastTransaction boughtPrice currentPrice(+?)
+
+const ELEMENT_DATA: PeriodicElement[] = [
+ { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
+ { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
+ { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
+];
+
+var TRANSACTION_DATA: TransactionData[] = [];
+var STOCK_DATA: Stock[] = [];
+
+export interface TransactionData {
+ comment: string;
+ isin: string;
+ time: string;
+ count: number;
+ price: number;
+}
+
+@Component({
+ selector: 'app-dashboard',
+ templateUrl: './dashboard.component.html',
+ styleUrls: ['./dashboard.component.scss'],
+})
+export class DashboardComponent implements OnInit {
+ constructor(
+ private dataService: DataService,
+ private helper: HelperService,
+ public dialog: MatDialog
+ ) {}
+
+ dataSourceTransactions: TransactionData[] = [];
+ dataSourceStocks: Stock[] = [];
+ depotCurrentValue: number = 0;
+ depotCost: number = 0;
+ profit: number = 0;
+
+ getTransactions() {
+ var TRANSACTION_DATA: TransactionData[] = [];
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit = this.depotCurrentValue - this.depotCost;
+ });
+ }
+
+ ngOnInit() {
+ this.dataService.getStockData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCurrentValue = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCurrentValue = data.data[i].current_price;
+ STOCK_DATA.push({
+ count: data.data[i].count,
+ currentPrice: data.data[i].current_price,
+ symbol: data.data[i].symbol,
+ time: data.data[i].last_transaction,
+ });
+ }
+ this.dataSourceStocks = STOCK_DATA;
+ //TODO move to helper service
+
+ this.profit += this.depotCurrentValue;
+ });
+
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit -= this.depotCost;
+ });
+ }
+
+ comment: string = '';
+ isin: string = '';
+ time: Date = new Date();
+ count: number = 0.0;
+ price: number = 0.0;
+
+ openDialog(): void {
+ const dialogRef = this.dialog.open(UserDialogComponent, {
+ width: '50vw',
+ data: {
+ comment: this.comment,
+ isin: this.isin,
+ time: this.time,
+ count: this.count,
+ price: this.price,
+ },
+ });
+
+ dialogRef.afterClosed().subscribe((result) => {
+ this.helper.delay(1000);
+ this.getTransactions();
+ });
+ }
+
+ displayedColumns: string[] = [
+ 'comment',
+ 'weight',
+ 'position',
+ 'name',
+ 'symbol',
+ ];
+ displayedColumnsStocks: string[] = [
+ 'position',
+ 'name',
+ 'weight',
+ 'current-price',
+ ];
+ dataSource = ELEMENT_DATA;
+}
+
+ +
+ src/app/Views/bot-settings/bot-settings.component.ts
+
+ Properties+ |
+
+
|
+
+ + isin + + + + + | +
+ isin:
+ |
+
+ Type : string
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { C, COMMA, ENTER, F } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+
+import { CronOptions } from 'ngx-cron-editor';
+
+import { BotService } from 'src/app/Services/bot.service';
+import { HelperService } from 'src/app/Helpers/helper.service';
+import { ProfileService } from 'src/app/Services/profile.service';
+import { FormControl } from '@angular/forms';
+
+export interface Fruit {
+ name: string;
+}
+
+export interface Share {
+ isin: string;
+}
+
+export interface Keyword {
+ name: string;
+}
+
+@Component({
+ selector: 'app-bot-settings',
+ templateUrl: './bot-settings.component.html',
+ styleUrls: ['./bot-settings.component.scss'],
+})
+export class BotSettingsComponent implements OnInit {
+ keywords: Keyword[] = [];
+ shares: Share[] = [];
+
+ constructor(
+ private botService: BotService,
+ private helper: HelperService,
+ private profileService: ProfileService
+ ) {}
+
+ ngOnInit(): void {
+ this.shares = this.helper.formatShareData();
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ addOnBlur = true;
+ readonly separatorKeysCodes = [ENTER, COMMA] as const;
+
+ async addKeyword(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add keyword to database
+ if (value && !this.keywords.includes({ name: value })) {
+ console.log('Added: ' + value);
+ this.botService.createKeyword(value.toLowerCase()).subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+ }
+
+ async removeKeyword(keyword: Keyword): Promise<void> {
+ this.botService.deleteKeyword(keyword.name).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.keywords = [];
+ this.keywords = this.helper.formatKeywordsData();
+ }
+
+ async addShare(event: MatChipInputEvent): Promise<void> {
+ const value = (event.value || '').trim();
+
+ // Add share to database
+ if (value && !this.shares.includes({ isin: value.toLowerCase() })) {
+ console.log('Added: ' + value);
+ this.botService.createShare(value, 'Comment').subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ // Clear the input value
+ event.chipInput!.clear();
+
+ if (value) {
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+ }
+
+ async removeShare(share: Share): Promise<void> {
+ this.botService.deleteShare(share.isin).subscribe((result) => {
+ console.log(result);
+ });
+
+ await this.helper.delay(1000);
+
+ this.shares = [];
+ this.shares = this.helper.formatShareData();
+ }
+
+ setCronString() {
+ this.profileService
+ .addCronString(this.cronForm.value)
+ .subscribe((result) => {
+ console.log(result);
+ });
+ }
+
+ cronForm = new FormControl('0 0 1/1 * *');
+ public cronOptions: CronOptions = {
+ defaultTime: '00:00:00',
+
+ hideMinutesTab: true,
+ hideHourlyTab: true,
+ hideDailyTab: false,
+ hideWeeklyTab: true,
+ hideMonthlyTab: true,
+ hideYearlyTab: true,
+ hideAdvancedTab: true,
+ hideSpecificWeekDayTab: true,
+ hideSpecificMonthWeekTab: true,
+
+ use24HourTime: true,
+ hideSeconds: true,
+
+ cronFlavor: 'quartz', //standard or quartz
+ };
+}
+
+ +
+ src/app/Views/dashboard/dashboard.component.ts
+
+ Properties+ |
+
+
|
+
+ + count + + + + + | +
+ count:
+ |
+
+ Type : number
+
+ |
+
+ + currentPrice + + + + + | +
+ currentPrice:
+ |
+
+ Type : number
+
+ |
+
+ + symbol + + + + + | +
+ symbol:
+ |
+
+ Type : string
+
+ |
+
+ + time + + + + + | +
+ time:
+ |
+
+ Type : string
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { DataService } from 'src/app/Services/data.service';
+import { MatDialog } from '@angular/material/dialog';
+import { UserDialogComponent } from './user-dialog/user-dialog.component';
+import { HelperService } from 'src/app/Helpers/helper.service';
+
+export interface PeriodicElement {
+ name: string;
+ position: number;
+ weight: number;
+ symbol: string;
+}
+
+export interface Stock {
+ count: number;
+ currentPrice: number;
+ symbol: string;
+ time: string;
+}
+
+//symbol count lastTransaction boughtPrice currentPrice(+?)
+
+const ELEMENT_DATA: PeriodicElement[] = [
+ { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
+ { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
+ { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
+];
+
+var TRANSACTION_DATA: TransactionData[] = [];
+var STOCK_DATA: Stock[] = [];
+
+export interface TransactionData {
+ comment: string;
+ isin: string;
+ time: string;
+ count: number;
+ price: number;
+}
+
+@Component({
+ selector: 'app-dashboard',
+ templateUrl: './dashboard.component.html',
+ styleUrls: ['./dashboard.component.scss'],
+})
+export class DashboardComponent implements OnInit {
+ constructor(
+ private dataService: DataService,
+ private helper: HelperService,
+ public dialog: MatDialog
+ ) {}
+
+ dataSourceTransactions: TransactionData[] = [];
+ dataSourceStocks: Stock[] = [];
+ depotCurrentValue: number = 0;
+ depotCost: number = 0;
+ profit: number = 0;
+
+ getTransactions() {
+ var TRANSACTION_DATA: TransactionData[] = [];
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit = this.depotCurrentValue - this.depotCost;
+ });
+ }
+
+ ngOnInit() {
+ this.dataService.getStockData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCurrentValue = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCurrentValue = data.data[i].current_price;
+ STOCK_DATA.push({
+ count: data.data[i].count,
+ currentPrice: data.data[i].current_price,
+ symbol: data.data[i].symbol,
+ time: data.data[i].last_transaction,
+ });
+ }
+ this.dataSourceStocks = STOCK_DATA;
+ //TODO move to helper service
+
+ this.profit += this.depotCurrentValue;
+ });
+
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit -= this.depotCost;
+ });
+ }
+
+ comment: string = '';
+ isin: string = '';
+ time: Date = new Date();
+ count: number = 0.0;
+ price: number = 0.0;
+
+ openDialog(): void {
+ const dialogRef = this.dialog.open(UserDialogComponent, {
+ width: '50vw',
+ data: {
+ comment: this.comment,
+ isin: this.isin,
+ time: this.time,
+ count: this.count,
+ price: this.price,
+ },
+ });
+
+ dialogRef.afterClosed().subscribe((result) => {
+ this.helper.delay(1000);
+ this.getTransactions();
+ });
+ }
+
+ displayedColumns: string[] = [
+ 'comment',
+ 'weight',
+ 'position',
+ 'name',
+ 'symbol',
+ ];
+ displayedColumnsStocks: string[] = [
+ 'position',
+ 'name',
+ 'weight',
+ 'current-price',
+ ];
+ dataSource = ELEMENT_DATA;
+}
+
+ +
+ src/app/Views/dashboard/dashboard.component.ts
+
+ Properties+ |
+
+
|
+
+ + comment + + + + + | +
+ comment:
+ |
+
+ Type : string
+
+ |
+
+ + count + + + + + | +
+ count:
+ |
+
+ Type : number
+
+ |
+
+ + isin + + + + + | +
+ isin:
+ |
+
+ Type : string
+
+ |
+
+ + price + + + + + | +
+ price:
+ |
+
+ Type : number
+
+ |
+
+ + time + + + + + | +
+ time:
+ |
+
+ Type : string
+
+ |
+
import { Component, OnInit } from '@angular/core';
+import { DataService } from 'src/app/Services/data.service';
+import { MatDialog } from '@angular/material/dialog';
+import { UserDialogComponent } from './user-dialog/user-dialog.component';
+import { HelperService } from 'src/app/Helpers/helper.service';
+
+export interface PeriodicElement {
+ name: string;
+ position: number;
+ weight: number;
+ symbol: string;
+}
+
+export interface Stock {
+ count: number;
+ currentPrice: number;
+ symbol: string;
+ time: string;
+}
+
+//symbol count lastTransaction boughtPrice currentPrice(+?)
+
+const ELEMENT_DATA: PeriodicElement[] = [
+ { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
+ { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
+ { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
+];
+
+var TRANSACTION_DATA: TransactionData[] = [];
+var STOCK_DATA: Stock[] = [];
+
+export interface TransactionData {
+ comment: string;
+ isin: string;
+ time: string;
+ count: number;
+ price: number;
+}
+
+@Component({
+ selector: 'app-dashboard',
+ templateUrl: './dashboard.component.html',
+ styleUrls: ['./dashboard.component.scss'],
+})
+export class DashboardComponent implements OnInit {
+ constructor(
+ private dataService: DataService,
+ private helper: HelperService,
+ public dialog: MatDialog
+ ) {}
+
+ dataSourceTransactions: TransactionData[] = [];
+ dataSourceStocks: Stock[] = [];
+ depotCurrentValue: number = 0;
+ depotCost: number = 0;
+ profit: number = 0;
+
+ getTransactions() {
+ var TRANSACTION_DATA: TransactionData[] = [];
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit = this.depotCurrentValue - this.depotCost;
+ });
+ }
+
+ ngOnInit() {
+ this.dataService.getStockData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCurrentValue = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCurrentValue = data.data[i].current_price;
+ STOCK_DATA.push({
+ count: data.data[i].count,
+ currentPrice: data.data[i].current_price,
+ symbol: data.data[i].symbol,
+ time: data.data[i].last_transaction,
+ });
+ }
+ this.dataSourceStocks = STOCK_DATA;
+ //TODO move to helper service
+
+ this.profit += this.depotCurrentValue;
+ });
+
+ this.dataService.getTransactionData().subscribe((response: any) => {
+ var data = JSON.parse(response);
+ this.depotCost = 0;
+ for (let i = 0; i < data.data.length; i++) {
+ this.depotCost += data.data[i].price;
+ TRANSACTION_DATA.push({
+ comment: data.data[i].comment,
+ isin: data.data[i].isin,
+ time: data.data[i].time,
+ count: data.data[i].count,
+ price: data.data[i].price,
+ });
+ }
+ this.dataSourceTransactions = TRANSACTION_DATA;
+ //TODO move to helper service
+
+ this.profit -= this.depotCost;
+ });
+ }
+
+ comment: string = '';
+ isin: string = '';
+ time: Date = new Date();
+ count: number = 0.0;
+ price: number = 0.0;
+
+ openDialog(): void {
+ const dialogRef = this.dialog.open(UserDialogComponent, {
+ width: '50vw',
+ data: {
+ comment: this.comment,
+ isin: this.isin,
+ time: this.time,
+ count: this.count,
+ price: this.price,
+ },
+ });
+
+ dialogRef.afterClosed().subscribe((result) => {
+ this.helper.delay(1000);
+ this.getTransactions();
+ });
+ }
+
+ displayedColumns: string[] = [
+ 'comment',
+ 'weight',
+ 'position',
+ 'name',
+ 'symbol',
+ ];
+ displayedColumnsStocks: string[] = [
+ 'position',
+ 'name',
+ 'weight',
+ 'current-price',
+ ];
+ dataSource = ELEMENT_DATA;
+}
+
+