Add latest changes from frontend branch

This commit is contained in:
kevinpauer 2022-04-05 19:29:30 +02:00
commit d3a09ea940
28 changed files with 820 additions and 116 deletions

View File

@ -1,10 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Stock } from '../Models/stock.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class HelperService { export class HelperService {
constructor() {}
constructor() { }
} }

View File

@ -1,6 +0,0 @@
export class Stock {
count = 0;
price = 0;
symbol = '';
time = '';
}

View File

@ -1,7 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
const AUTH_API = 'https://aktienbot.flokaiser.com/api/user/'; const AUTH_API = 'https://gruppe1.testsites.info/api/user';
const httpOptions = { const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }), headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
}; };
@ -11,12 +12,25 @@ const httpOptions = {
}) })
export class AuthService { export class AuthService {
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
/**
* @param {string} email
* @param {string} password
* @returns Observable
*/
login(email: string, password: string): Observable<any> { login(email: string, password: string): Observable<any> {
return this.http.post(AUTH_API + '/login', { return this.http.post(AUTH_API + '/login', {
email, email,
password, password,
}); });
} }
/**
* @param {string} email
* @param {string} username
* @param {string} password
* @returns Observable
*/
register(email: string, username: string, password: string): Observable<any> { register(email: string, username: string, password: string): Observable<any> {
return this.http.post( return this.http.post(
AUTH_API + '/register', AUTH_API + '/register',

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { BotService } from './bot.service';
describe('BotService', () => {
let service: BotService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BotService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
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
) {}
}

View File

@ -2,16 +2,23 @@ import { Injectable, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { delay, Observable } from 'rxjs'; import { delay, Observable } from 'rxjs';
import { TokenStorageService } from './token.service'; import { TokenStorageService } from './token.service';
const API_URL = 'https://aktienbot.flokaiser.com/api/'; const API_URL = 'https://gruppe1.testsites.info/api/';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class DataService { export class DataService {
/**
* @param {HttpClient} privatehttp
* @param {TokenStorageService} privatetokenStorage
*/
constructor( constructor(
private http: HttpClient, private http: HttpClient,
private tokenStorage: TokenStorageService private tokenStorage: TokenStorageService
) {} ) {}
/**
* @returns Observable
*/
public getStockData(): Observable<any> { public getStockData(): Observable<any> {
return this.http.get(API_URL + 'portfolio', { return this.http.get(API_URL + 'portfolio', {
headers: new HttpHeaders({ headers: new HttpHeaders({
@ -22,6 +29,9 @@ export class DataService {
}); });
} }
/**
* @returns Observable
*/
public getTransactionData(): Observable<any> { public getTransactionData(): Observable<any> {
return this.http.get(API_URL + 'transactions', { return this.http.get(API_URL + 'transactions', {
headers: new HttpHeaders({ headers: new HttpHeaders({
@ -32,6 +42,42 @@ export class DataService {
}); });
} }
/**
* @param {string} symbol
* @param {Date} time
* @param {number} count
* @param {number} price
* @returns Observable
*/
public createTransaction(
symbol: string,
time: string,
count: number,
price: number
): Observable<any> {
time = time + 'T12:00:00.000Z';
price.toFixed(2);
console.log(this.tokenStorage.getToken());
return this.http.post(
API_URL + 'transaction',
{
count,
price,
symbol,
time,
},
{
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Bearer ' + this.tokenStorage.getToken(),
}),
}
);
}
/**
* @returns Observable
*/
public getKeywords(): Observable<any> { public getKeywords(): Observable<any> {
return this.http.get(API_URL + 'keywords', { return this.http.get(API_URL + 'keywords', {
headers: new HttpHeaders({ headers: new HttpHeaders({

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ProfileService } from './profile.service';
describe('ProfileService', () => {
let service: ProfileService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ProfileService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,69 @@
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(),
}),
}
);
}
}

View File

@ -1,13 +1,13 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { TokenService } from './token.service'; import { TokenStorageService } from './token.service';
describe('TokenService', () => { describe('TokenStorageService', () => {
let service: TokenService; let service: TokenStorageService;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({}); TestBed.configureTestingModule({});
service = TestBed.inject(TokenService); service = TestBed.inject(TokenStorageService);
}); });
it('should be created', () => { it('should be created', () => {

View File

@ -6,20 +6,42 @@ const USER_KEY = 'auth-user';
}) })
export class TokenStorageService { export class TokenStorageService {
constructor() {} constructor() {}
/**
* @returns void
*/
signOut(): void { signOut(): void {
window.sessionStorage.clear(); window.sessionStorage.clear();
} }
/**
* @param {string} token
* @returns void
*/
public saveToken(token: string): void { public saveToken(token: string): void {
window.sessionStorage.removeItem(TOKEN_KEY); window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY, token); window.sessionStorage.setItem(TOKEN_KEY, token);
} }
/**
* @returns string
*/
public getToken(): string | null { public getToken(): string | null {
return window.sessionStorage.getItem(TOKEN_KEY); return window.sessionStorage.getItem(TOKEN_KEY);
} }
/**
* @param {any} user
* @returns void
*/
public saveUser(user: any): void { public saveUser(user: any): void {
window.sessionStorage.removeItem(USER_KEY); window.sessionStorage.removeItem(USER_KEY);
window.sessionStorage.setItem(USER_KEY, JSON.stringify(user)); window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
} }
/**
* @returns any
*/
public getUser(): any { public getUser(): any {
const user = window.sessionStorage.getItem(USER_KEY); const user = window.sessionStorage.getItem(USER_KEY);
if (user) { if (user) {

View File

@ -4,49 +4,39 @@
<div class="stockOverview"> <div class="stockOverview">
<div class="heading"> <div class="heading">
<div class="vertical-center">Aktienübersicht</div> <div class="vertical-center">Aktienübersicht</div>
<span class="spacer"></span>
<button
mat-icon-button
class="add-icon"
aria-label="Example icon-button with heart icon"
[disableRipple]="true"
>
<mat-icon>add</mat-icon>
</button>
</div> </div>
<div class="stockTable"> <mat-card class="placeholder">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8"> <div class="stockTable">
<!--- Note that these columns can be defined in any order. <table mat-table [dataSource]="dataSourceTransactions">
The actual rendered columns are set as a property on the row definition" --> <!--- 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 --> <!-- Position Column -->
<ng-container matColumnDef="position"> <ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef>Symbol</th> <th mat-header-cell *matHeaderCellDef>Symbol</th>
<td mat-cell *matCellDef="let element">{{ element.position }}</td> <td mat-cell *matCellDef="let element">{{ element.symbol }}</td>
</ng-container> </ng-container>
<!-- Name Column --> <!-- Name Column -->
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Name</th> <th mat-header-cell *matHeaderCellDef>Count</th>
<td mat-cell *matCellDef="let element">{{ element.name }}</td> <td mat-cell *matCellDef="let element">{{ element.count }}</td>
</ng-container> </ng-container>
<!-- Weight Column --> <!-- Weight Column -->
<ng-container matColumnDef="weight"> <ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef>Volume</th> <th mat-header-cell *matHeaderCellDef>Time</th>
<td mat-cell *matCellDef="let element">{{ element.weight }}</td> <td mat-cell *matCellDef="let element">{{ element.time }}</td>
</ng-container> </ng-container>
<!-- Symbol Column --> <tr mat-header-row *matHeaderRowDef="displayedColumnsStocks"></tr>
<ng-container matColumnDef="symbol"> <tr
<th mat-header-cell *matHeaderCellDef>Worth</th> mat-row
<td mat-cell *matCellDef="let element">{{ element.symbol }}</td> *matRowDef="let row; columns: displayedColumnsStocks"
</ng-container> ></tr>
</table>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> </div>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> </mat-card>
</table>
</div>
</div> </div>
</mat-grid-tile> </mat-grid-tile>
<!-- Depot Overview --> <!-- Depot Overview -->
@ -63,40 +53,51 @@
<div class="depotOverview"> <div class="depotOverview">
<div class="heading fix-right-side"> <div class="heading fix-right-side">
<div class="vertical-center">Transaktionen</div> <div class="vertical-center">Transaktionen</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> </div>
<div class="stockTable"> <mat-card class="placeholder"
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8"> ><div class="stockTable">
<!--- Note that these columns can be defined in any order. <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" --> The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column --> <!-- Position Column -->
<ng-container matColumnDef="position"> <ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef>Count</th> <th mat-header-cell *matHeaderCellDef>Count</th>
<td mat-cell *matCellDef="let element">{{ element.position }}</td> <td mat-cell *matCellDef="let element">{{ element.count }}</td>
</ng-container> </ng-container>
<!-- Name Column --> <!-- Name Column -->
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Pirce</th> <th mat-header-cell *matHeaderCellDef>Price</th>
<td mat-cell *matCellDef="let element">{{ element.name }}</td> <td mat-cell *matCellDef="let element">{{ element.price }}</td>
</ng-container> </ng-container>
<!-- Weight Column --> <!-- Weight Column -->
<ng-container matColumnDef="weight"> <ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef>Symbol</th> <th mat-header-cell *matHeaderCellDef>Symbol</th>
<td mat-cell *matCellDef="let element">{{ element.weight }}</td> <td mat-cell *matCellDef="let element">{{ element.symbol }}</td>
</ng-container> </ng-container>
<!-- Symbol Column --> <!-- Symbol Column -->
<ng-container matColumnDef="symbol"> <ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef>Time</th> <th mat-header-cell *matHeaderCellDef>Time</th>
<td mat-cell *matCellDef="let element">{{ element.symbol }}</td> <td mat-cell *matCellDef="let element">{{ element.time }}</td>
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table> </table></div
</div> ></mat-card>
</div> </div>
</mat-grid-tile> </mat-grid-tile>
</mat-grid-list> </mat-grid-list>

View File

@ -62,3 +62,11 @@ table {
.placeholder { .placeholder {
height: 100%; height: 100%;
} }
side-heading {
display: inline;
}
.mat-ripple-element {
display: none !important;
}

View File

@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { throwToolbarMixedModesError } from '@angular/material/toolbar';
import { DataService } from 'src/app/Services/data.service'; import { DataService } from 'src/app/Services/data.service';
import { TokenStorageService } from 'src/app/Services/token.service'; import { MatDialog } from '@angular/material/dialog';
import { UserDialogComponent } from './user-dialog/user-dialog.component';
export interface PeriodicElement { export interface PeriodicElement {
name: string; name: string;
@ -11,11 +11,10 @@ export interface PeriodicElement {
} }
export interface Stock { export interface Stock {
count: number;
// price: number;
symbol: string; symbol: string;
count: Float32Array; time: string;
lastTransaction: Date;
boughtPrice: Float32Array;
currentPrice: Float32Array;
} }
//symbol count lastTransaction boughtPrice currentPrice(+?) //symbol count lastTransaction boughtPrice currentPrice(+?)
@ -24,43 +23,84 @@ const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' }, { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' }, { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' }, { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
{ position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
{ position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
{ position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
{ position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
{ position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
{ position: 11, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 12, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 13, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 14, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 15, name: 'Boron', weight: 10.811, symbol: 'B' },
{ position: 16, name: 'Carbon', weight: 12.0107, symbol: 'C' },
{ position: 17, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
{ position: 18, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
{ position: 19, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
{ position: 20, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
]; ];
var TRANSACTION_DATA: TransactionData[] = [];
var STOCK_DATA: Stock[] = [];
export interface TransactionData {
symbol: string;
time: string;
count: number;
price: number;
}
@Component({ @Component({
selector: 'app-dashboard', selector: 'app-dashboard',
templateUrl: './dashboard.component.html', templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'], styleUrls: ['./dashboard.component.scss'],
}) })
export class DashboardComponent implements OnInit { export class DashboardComponent implements OnInit {
constructor(private dataService: DataService) {} constructor(private dataService: DataService, public dialog: MatDialog) {}
dataSourceTransactions: TransactionData[] = [];
dataSourceStocks: Stock[] = [];
ngOnInit() { ngOnInit() {
this.dataService.getStockData().subscribe((response: any) => { this.dataService.getStockData().subscribe((response: any) => {
console.log(response); console.log('PORTFOLIO:' + response);
//TODO map data on array for display var data = JSON.parse(response);
for (let i = 0; i < data.data.length; i++) {
STOCK_DATA.push({
count: data.data[i].count,
symbol: data.data[i].symbol,
time: data.data[i].last_transaction,
});
}
console.log(STOCK_DATA);
this.dataSourceStocks = STOCK_DATA;
//TODO move to helper service
}); });
this.dataService.getTransactionData().subscribe((response: any) => { this.dataService.getTransactionData().subscribe((response: any) => {
console.log(response); console.log('TRANSACTIONS:' + response);
//TODO map data on array for display var data = JSON.parse(response);
for (let i = 0; i < data.data.length; i++) {
TRANSACTION_DATA.push({
symbol: data.data[i].symbol,
time: data.data[i].time,
count: data.data[i].count,
price: data.data[i].price,
});
}
console.log(TRANSACTION_DATA);
this.dataSourceTransactions = TRANSACTION_DATA;
//TODO move to helper service
}); });
} }
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; symbol: string = '';
time: Date = new Date();
count: number = 0.0;
price: number = 0.0;
openDialog(): void {
const dialogRef = this.dialog.open(UserDialogComponent, {
width: '50vw',
height: '55vh',
data: {
symbol: this.symbol,
time: this.time,
count: this.count,
price: this.price,
},
});
dialogRef.afterClosed().subscribe((result) => {
console.log('The dialog was closed');
});
}
displayedColumns: string[] = ['weight', 'position', 'name', 'symbol'];
displayedColumnsStocks: string[] = ['position', 'name', 'weight'];
dataSource = ELEMENT_DATA; dataSource = ELEMENT_DATA;
} }

View File

@ -0,0 +1,61 @@
<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="symbol">Symbol</label>
<input
type="symbol"
class="form-control"
name="symbol"
[(ngModel)]="data.symbol"
required
symbol
#symbol="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>

View File

@ -0,0 +1,9 @@
.spacer {
flex-grow: 1;
width: 5%;
}
.footer-buttons {
display: flex;
width: 100%;
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserDialogComponent } from './user-dialog.component';
describe('UserDialogComponent', () => {
let component: UserDialogComponent;
let fixture: ComponentFixture<UserDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UserDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UserDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,42 @@
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 implements OnInit {
constructor(
private dataService: DataService,
public dialog: MatDialog,
public dialogRef: MatDialogRef<UserDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: TransactionData
) {}
ngOnInit(): void {}
onSubmit() {
//TODO check tat price is decimal
console.log(
this.dataService
.createTransaction(
this.data.symbol,
this.data.time,
+this.data.count,
+this.data.price.toFixed(2)
)
.subscribe((data) => {
console.log(data);
})
);
this.dialog.closeAll();
}
}

View File

@ -1,5 +1,5 @@
<mat-toolbar> <mat-toolbar>
<span>Aktienbot</span> <a href=""><span>Aktienbot</span></a>
<span class="example-spacer"></span> <span class="example-spacer"></span>
<button <button
mat-icon-button mat-icon-button

View File

@ -1,3 +1,8 @@
.example-spacer { .example-spacer {
flex: 1 1 auto; flex: 1 1 auto;
} }
a {
color: white;
text-decoration: none; /* no underline */
}

View File

@ -0,0 +1,28 @@
<div class="containeer">
<h1 mat-dialog-title>Aktion bestätigen</h1>
<div mat-dialog-content class="content">
<span>Sind sie sicher, dass sie diese Handlung abschließen wollen?</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"
>
Ok
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,18 @@
.footer-buttons {
width: 100%;
text-align: center;
}
.spacer {
flex-grow: 1;
width: 5%;
}
.inner {
display: inline-block;
width: 50%;
}
.content {
height: 80%;
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfirmationDialogComponent } from './confirmation-dialog.component';
describe('ConfirmationDialogComponent', () => {
let component: ConfirmationDialogComponent;
let fixture: ComponentFixture<ConfirmationDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConfirmationDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfirmationDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-confirmation-dialog',
templateUrl: './confirmation-dialog.component.html',
styleUrls: ['./confirmation-dialog.component.scss'],
})
export class ConfirmationDialogComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
confirm() {}
returnBack() {}
}

View File

@ -1 +1,135 @@
<p>profile works!</p> <mat-grid-list cols="2">
<mat-grid-tile>
<mat-card class="card">
<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>
<mat-card class="card">
<mat-card-title class="card-title">Add Telegram Id</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>
</mat-card-content>
</mat-card>
</mat-grid-tile>
</mat-grid-list>

View File

@ -0,0 +1,22 @@
.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%;
}

View File

@ -1,4 +1,11 @@
import { i18nMetaToJSDoc } from '@angular/compiler/src/render3/view/i18n/meta';
import { Component, OnInit } from '@angular/core'; 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';
@Component({ @Component({
selector: 'app-profile', selector: 'app-profile',
@ -6,7 +13,68 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./profile.component.scss'], styleUrls: ['./profile.component.scss'],
}) })
export class ProfileComponent implements OnInit { export class ProfileComponent implements OnInit {
constructor() {} userNameFormControl = new FormControl('', [Validators.required]);
passwordFormControl = new FormControl('', [
Validators.required,
Validators.minLength(6),
]);
telegramIdFormControl = new FormControl('', [Validators.required]);
ngOnInit(): void {} 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.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();
}
}
});
}
} }

View File

@ -1,5 +1,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { BotService } from './Services/bot.service';
import { BotSettingsComponent } from './Views/bot-settings/bot-settings.component';
import { DashboardComponent } from './Views/dashboard/dashboard.component'; import { DashboardComponent } from './Views/dashboard/dashboard.component';
import { LoginComponent } from './Views/login/login.component'; import { LoginComponent } from './Views/login/login.component';
import { ProfileComponent } from './Views/profile/profile.component'; import { ProfileComponent } from './Views/profile/profile.component';
@ -24,7 +26,7 @@ const routes: Routes = [
}, },
{ {
path: 'settings', path: 'settings',
component: ProfileComponent, component: BotSettingsComponent,
}, },
]; ];

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
@ -10,6 +10,8 @@ import { MatGridListModule } from '@angular/material/grid-list';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatTableModule } from '@angular/material/table'; import { MatTableModule } from '@angular/material/table';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@ -20,6 +22,8 @@ import { DashboardComponent } from './Views/dashboard/dashboard.component';
import { RegisterComponent } from './Views/register/register.component'; import { RegisterComponent } from './Views/register/register.component';
import { ProfileComponent } from './Views/profile/profile.component'; import { ProfileComponent } from './Views/profile/profile.component';
import { BotSettingsComponent } from './Views/bot-settings/bot-settings.component'; import { BotSettingsComponent } from './Views/bot-settings/bot-settings.component';
import { UserDialogComponent } from './Views/dashboard/user-dialog/user-dialog.component';
import { ConfirmationDialogComponent } from './Views/profile/confirmation-dialog/confirmation-dialog.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -30,6 +34,8 @@ import { BotSettingsComponent } from './Views/bot-settings/bot-settings.componen
RegisterComponent, RegisterComponent,
ProfileComponent, ProfileComponent,
BotSettingsComponent, BotSettingsComponent,
UserDialogComponent,
ConfirmationDialogComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -44,6 +50,9 @@ import { BotSettingsComponent } from './Views/bot-settings/bot-settings.componen
FormsModule, FormsModule,
HttpClientModule, HttpClientModule,
MatMenuModule, MatMenuModule,
MatDialogModule,
MatInputModule,
ReactiveFormsModule,
], ],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],