diff --git a/frontend/src/app/Helpers/helper.service.ts b/frontend/src/app/Helpers/helper.service.ts index cfb0d3d..24d485e 100644 --- a/frontend/src/app/Helpers/helper.service.ts +++ b/frontend/src/app/Helpers/helper.service.ts @@ -1,8 +1,42 @@ 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() {} + 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({ + symbol: data.data[i].symbol, + }); + } + }); + return shares; + } + + formatKeywordsData(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; + } } diff --git a/frontend/src/app/Services/bot.service.ts b/frontend/src/app/Services/bot.service.ts index 27c8290..0e764cd 100644 --- a/frontend/src/app/Services/bot.service.ts +++ b/frontend/src/app/Services/bot.service.ts @@ -13,4 +13,100 @@ export class BotService { private http: HttpClient, private tokenStorage: TokenStorageService ) {} + + /** + * @returns Observable + */ + public getKeywords(): Observable { + 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 { + 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 { + 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 { + 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(symbol: string): Observable { + return this.http.post( + API_URL + 'share', + { + symbol, + }, + { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + this.tokenStorage.getToken(), + }), + } + ); + } + + /** + * @param {string} share + * @returns Observable + */ + public deleteShare(share: string): Observable { + return this.http.delete(API_URL + 'share', { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + this.tokenStorage.getToken(), + }), + body: { + share, + }, + }); + } } diff --git a/frontend/src/app/Services/data.service.ts b/frontend/src/app/Services/data.service.ts index 213e35b..46fcc10 100644 --- a/frontend/src/app/Services/data.service.ts +++ b/frontend/src/app/Services/data.service.ts @@ -57,7 +57,6 @@ export class DataService { ): Observable { time = time + 'T12:00:00.000Z'; price.toFixed(2); - console.log(this.tokenStorage.getToken()); return this.http.post( API_URL + 'transaction', { diff --git a/frontend/src/app/Views/bot-settings/bot-settings.component.html b/frontend/src/app/Views/bot-settings/bot-settings.component.html index 58d7a42..cee4a8a 100644 --- a/frontend/src/app/Views/bot-settings/bot-settings.component.html +++ b/frontend/src/app/Views/bot-settings/bot-settings.component.html @@ -1 +1,58 @@ -

bot-settings works!

+ + + + Keywords + + + Keywords + + + {{ keyword.name }} + + + + + + + + + + + Shares + + + Shares + + + {{ share.symbol }} + + + + + + + + + diff --git a/frontend/src/app/Views/bot-settings/bot-settings.component.scss b/frontend/src/app/Views/bot-settings/bot-settings.component.scss index e69de29..aee2dde 100644 --- a/frontend/src/app/Views/bot-settings/bot-settings.component.scss +++ b/frontend/src/app/Views/bot-settings/bot-settings.component.scss @@ -0,0 +1,26 @@ +.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%; +} diff --git a/frontend/src/app/Views/bot-settings/bot-settings.component.ts b/frontend/src/app/Views/bot-settings/bot-settings.component.ts index 40bd01b..1e0c8a7 100644 --- a/frontend/src/app/Views/bot-settings/bot-settings.component.ts +++ b/frontend/src/app/Views/bot-settings/bot-settings.component.ts @@ -1,15 +1,102 @@ import { Component, OnInit } from '@angular/core'; +import { C, COMMA, ENTER, F } from '@angular/cdk/keycodes'; +import { MatChipInputEvent } from '@angular/material/chips'; +import { BotService } from 'src/app/Services/bot.service'; +import { HelperService } from 'src/app/Helpers/helper.service'; + +export interface Fruit { + name: string; +} + +export interface Share { + symbol: string; +} + +export interface Keyword { + name: string; +} @Component({ selector: 'app-bot-settings', templateUrl: './bot-settings.component.html', - styleUrls: ['./bot-settings.component.scss'] + styleUrls: ['./bot-settings.component.scss'], }) export class BotSettingsComponent implements OnInit { + keywords: Keyword[] = []; + shares: Share[] = []; - constructor() { } + constructor(private botService: BotService, private helper: HelperService) {} ngOnInit(): void { + this.shares = this.helper.formatShareData(); + this.helper.formatKeywordsData(this.keywords); } + addOnBlur = true; + readonly separatorKeysCodes = [ENTER, COMMA] as const; + + async addKeyword(event: MatChipInputEvent): Promise { + const value = (event.value || '').trim(); + + // Add keyword to database + if (value && !this.keywords.includes({ name: value })) { + console.log('Added: ' + value); + this.botService.createKeyword(value).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(this.keywords); + } + } + + async removeKeyword(keyword: Keyword): Promise { + this.botService.deleteKeyword(keyword.name).subscribe((result) => { + console.log(result); + }); + + await this.helper.delay(1000); + + this.keywords = []; + this.keywords = this.helper.formatKeywordsData(this.keywords); + } + + async addShare(event: MatChipInputEvent): Promise { + const value = (event.value || '').trim(); + + // Add share to database + if (value && !this.shares.includes({ symbol: value })) { + console.log('Added: ' + value); + this.botService.createShare(value).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 { + this.botService.deleteShare(share.symbol).subscribe((result) => { + console.log(result); + }); + + await this.helper.delay(1000); + + this.shares = []; + this.shares = this.helper.formatShareData(); + } } diff --git a/frontend/src/app/Views/profile/profile.component.ts b/frontend/src/app/Views/profile/profile.component.ts index 324d7a8..6ce31bf 100644 --- a/frontend/src/app/Views/profile/profile.component.ts +++ b/frontend/src/app/Views/profile/profile.component.ts @@ -1,9 +1,6 @@ -import { i18nMetaToJSDoc } from '@angular/compiler/src/render3/view/i18n/meta'; import { Component, OnInit } from '@angular/core'; import { FormControl, PatternValidator, Validators } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import { BotService } from 'src/app/Services/bot.service'; -import { DataService } from 'src/app/Services/data.service'; import { ProfileService } from 'src/app/Services/profile.service'; import { ConfirmationDialogComponent } from './confirmation-dialog/confirmation-dialog.component'; diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 122dc77..958f243 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -12,6 +12,7 @@ import { MatTableModule } from '@angular/material/table'; import { MatMenuModule } from '@angular/material/menu'; import { MatDialogModule } from '@angular/material/dialog'; import { MatInputModule } from '@angular/material/input'; +import { MatChipsModule } from '@angular/material/chips'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -53,6 +54,7 @@ import { ConfirmationDialogComponent } from './Views/profile/confirmation-dialog MatDialogModule, MatInputModule, ReactiveFormsModule, + MatChipsModule, ], providers: [], bootstrap: [AppComponent],