Publish from private repository
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<div>
|
||||
<form [formGroup]="addForm!" (ngSubmit)="onSubmitClick()">
|
||||
<ng-template #dialogActions>
|
||||
<button type="button" mat-flat-button class="dialog-btn-cancel" (click)="closeDialog()">Cancel</button>
|
||||
<button type="submit" class="btn-space" mat-raised-button color="primary">Save</button>
|
||||
</ng-template>
|
||||
|
||||
<app-dialog-chrome title="Add currency" [errorMessage]="errorMessage" [actions]="dialogActions">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Symbol</mat-label>
|
||||
<input matInput value={{currency.symbol}} formControlName="symbol" readonly="">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Code</mat-label>
|
||||
<input matInput value={{currency.id}} formControlName="id" readonly="">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Name</mat-label>
|
||||
<input matInput value={{currency.name}} formControlName="name">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Short Name</mat-label>
|
||||
<input matInput value={{currency.shortName}} formControlName="shortName">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width" appearance="fill">
|
||||
<mat-label>Rate</mat-label>
|
||||
<input matInput [value]="currency.rate | number:'0.2-2'" formControlName="rate" currencyMask [options]="{ prefix: currency.symbol, precision: 4 }" required>
|
||||
<mat-error *ngIf="addForm.controls?.['rate']?.hasError('required')">
|
||||
Please enter rate
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width" appearance="fill">
|
||||
<mat-label>Quantity</mat-label>
|
||||
<input matInput [value]="currency.rate | number:'0.0-0'" formControlName="quantity" currencyMask [options]="{ prefix: '', precision: 0 }" required>
|
||||
<mat-error *ngIf="addForm.controls?.['rate']?.hasError('required')">
|
||||
Please enter rate
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Rate Date</mat-label>
|
||||
<input matInput [matDatepicker]="picker3" (focus)="picker3.open()" value={{currency.rateDate}} formControlName="rateDate" required>
|
||||
<mat-hint>YYYY/MM/DD</mat-hint>
|
||||
<mat-datepicker-toggle matSuffix [for]="picker3"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker3></mat-datepicker>
|
||||
<mat-error *ngIf="addForm.controls?.['rateDate']?.hasError('required')">
|
||||
Please enter rate date
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-dialog-chrome>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,80 @@
|
||||
// angular
|
||||
import { Component, DestroyRef, inject } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { Inject } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
// libs
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
// app
|
||||
import { ApiRoutes } from '../../../api-routes';
|
||||
import { CurrencyModel } from '../../../model/currency.model';
|
||||
|
||||
@Component({
|
||||
templateUrl: './connect.currency.component.html',
|
||||
styleUrls: ['./connect.currency.component.scss'],
|
||||
})
|
||||
export class SettingsConnectCurrencyComponent {
|
||||
public addForm!: FormGroup;
|
||||
public errorMessage?: string;
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private httpClient: HttpClient,
|
||||
private dialogRef: MatDialogRef<SettingsConnectCurrencyComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public currency: CurrencyModel
|
||||
) {
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.addForm = this.fb.group({
|
||||
id: [
|
||||
this.currency.id,
|
||||
],
|
||||
symbol: [
|
||||
this.currency.symbol,
|
||||
],
|
||||
name: [
|
||||
this.currency.name,
|
||||
],
|
||||
shortName: [
|
||||
this.currency.id,
|
||||
],
|
||||
quantity: [
|
||||
this.currency.quantity || 1,
|
||||
[Validators.required],
|
||||
],
|
||||
rate: [
|
||||
this.currency.rate || 1,
|
||||
[Validators.required],
|
||||
],
|
||||
rateDate: [
|
||||
this.currency.rateDate,
|
||||
[Validators.required],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
onSubmitClick() {
|
||||
if (this.addForm.valid) {
|
||||
this.errorMessage = undefined;
|
||||
this.httpClient
|
||||
.post<CurrencyModel[]>(ApiRoutes.SettingsCurrencies, this.addForm.value)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(response => {
|
||||
this.dialogRef.close({ refresh: true });
|
||||
}, error => {
|
||||
this.errorMessage = error.detail;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<section class="content">
|
||||
<div class="content-block">
|
||||
<div class="block-header">
|
||||
<!-- breadcrumb -->
|
||||
<app-breadcrumb [title]="'Blank'" [items]="['Home','Settings']" [active_item]="'Currency'">
|
||||
</app-breadcrumb>
|
||||
</div>
|
||||
<div class="row clearfix">
|
||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="header">
|
||||
<h2><strong>My currencies</strong></h2>
|
||||
</div>
|
||||
<div class="body">
|
||||
<mat-tab-group [(selectedIndex)]="tabIndex">
|
||||
<mat-tab label="My currencies">
|
||||
<div class="body table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Name</th>
|
||||
<th>Short Name</th>
|
||||
<th>Quantity</th>
|
||||
<th>Rate</th>
|
||||
<th>Rate Date</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of myCurrencies" [class.currency-row-primary]="item.isPrimary">
|
||||
<td>{{item.code}}</td>
|
||||
<td>{{item.name}}</td>
|
||||
<td>{{item.shortName}}</td>
|
||||
<td style="text-align: end">
|
||||
{{item.quantity}}
|
||||
</td>
|
||||
<td style="text-align: end">
|
||||
{{item.rate | number: '1.2-6'}}
|
||||
{{item.symbol}}
|
||||
</td>
|
||||
<td>{{item.rateDate | date:'yyyy-MM-dd'}}</td>
|
||||
<td>
|
||||
<button class="btn-space" (click)="setRate(item)" mat-raised-button color="primary">
|
||||
Edit
|
||||
</button>
|
||||
<button class="btn-space" (click)="delete(item)" mat-raised-button color="warn">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="All currencies">
|
||||
<div class="body table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of currencies">
|
||||
<td>{{item.symbol}}</td>
|
||||
<td>{{item.id}}</td>
|
||||
<td>{{item.name}}</td>
|
||||
<td>
|
||||
<button class="btn-space" (click)="connect(item)" [disabled]="item.isConnected" mat-raised-button color="primary">
|
||||
Add
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,15 @@
|
||||
// Primary currency highlight must target cells — Bootstrap paints td backgrounds,
|
||||
// so a class on <tr> alone is invisible in light theme.
|
||||
.table tbody tr.currency-row-primary > td,
|
||||
.table tbody tr.currency-row-primary > th {
|
||||
background-color: rgba(0, 188, 212, 0.18) !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
:host-context(body.dark) {
|
||||
.table tbody tr.currency-row-primary > td,
|
||||
.table tbody tr.currency-row-primary > th {
|
||||
background-color: rgba(33, 150, 243, 0.22) !important;
|
||||
color: #cfe8ff;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// angular
|
||||
import { Component, DestroyRef, inject } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
// libs
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import Swal from 'sweetalert2';
|
||||
|
||||
// app
|
||||
import { ApiRoutes } from '../../../api-routes';
|
||||
import { SettingsConnectCurrencyComponent } from './connect.currency.component';
|
||||
import { CurrencyModel } from '../../../model/currency.model';
|
||||
import { SettingsRateCurrencyComponent } from './rate.currency.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './currency.component.html',
|
||||
styleUrls: ['./currency.component.scss'],
|
||||
})
|
||||
export class SettingsCurrencyComponent {
|
||||
public tabIndex = 0;
|
||||
|
||||
public currencies?: CurrencyModel[];
|
||||
public myCurrencies?: CurrencyModel[];
|
||||
public primaryId?: string;
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private dialogModel: MatDialog
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.load();
|
||||
}
|
||||
|
||||
connect(currency: CurrencyModel) {
|
||||
this.dialogModel.open(SettingsConnectCurrencyComponent, {
|
||||
width: '640px',
|
||||
disableClose: true,
|
||||
data: currency,
|
||||
}).afterClosed()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(x => {
|
||||
if (x && x.refresh) {
|
||||
this.tabIndex = 0;
|
||||
this.loadMyCurrency();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
disconnect(currency: CurrencyModel) {
|
||||
}
|
||||
|
||||
setRate(currency: CurrencyModel) {
|
||||
this.dialogModel.open(SettingsRateCurrencyComponent, {
|
||||
width: '640px',
|
||||
disableClose: true,
|
||||
data: currency,
|
||||
}).afterClosed()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(x => {
|
||||
if (x && x.refresh) {
|
||||
this.loadMyCurrency();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
delete(currency: CurrencyModel) {
|
||||
Swal.fire({
|
||||
title: 'Delete currency ' + currency.name,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Delete',
|
||||
showLoaderOnConfirm: true,
|
||||
preConfirm: (name) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.httpClient.delete(ApiRoutes.SettingsCurrency.replace(':id', currency.id!))
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(data => {
|
||||
resolve(data);
|
||||
}, error => {
|
||||
Swal.showValidationMessage(error.detail);
|
||||
reject();
|
||||
});
|
||||
|
||||
}).catch(x => {
|
||||
return false;
|
||||
});
|
||||
},
|
||||
allowOutsideClick: () => !Swal.isLoading(),
|
||||
}).then((result) => {
|
||||
this.load();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private load() {
|
||||
this.httpClient
|
||||
.get<CurrencyModel[]>(ApiRoutes.GeneralCurrencies)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(data => {
|
||||
this.currencies = data;
|
||||
this.loadMyCurrency();
|
||||
});
|
||||
}
|
||||
|
||||
private loadMyCurrency() {
|
||||
this.httpClient
|
||||
.get<CurrencyModel[]>(ApiRoutes.SettingsCurrencies)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(data => {
|
||||
this.myCurrencies = data
|
||||
.sort((a, b) => a.code!.localeCompare(b.code!))
|
||||
.map(myCurrency => {
|
||||
var globalCurrency = this.currencies?.find(x => x.id === myCurrency.code);
|
||||
|
||||
return {
|
||||
id: myCurrency.id,
|
||||
code: myCurrency.code,
|
||||
name: myCurrency.name,
|
||||
quantity: myCurrency.quantity,
|
||||
rate: myCurrency.rate,
|
||||
rateDate: myCurrency.rateDate,
|
||||
shortName: myCurrency.shortName,
|
||||
symbol: globalCurrency?.symbol,
|
||||
isPrimary: myCurrency.isPrimary,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<div>
|
||||
<form [formGroup]="addForm!" (ngSubmit)="onSubmitClick()">
|
||||
<ng-template #dialogActions>
|
||||
<button type="button" mat-flat-button class="dialog-btn-cancel" (click)="closeDialog()">Cancel</button>
|
||||
<button type="submit" class="btn-space" mat-raised-button color="primary">Save</button>
|
||||
</ng-template>
|
||||
|
||||
<app-dialog-chrome title="Edit currency" [error]="error" [actions]="dialogActions">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Symbol</mat-label>
|
||||
<input matInput value={{currency.symbol}} formControlName="symbol" readonly="">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Code</mat-label>
|
||||
<input matInput value={{currency.code}} formControlName="code" readonly="">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Name</mat-label>
|
||||
<input matInput value={{currency.name}} formControlName="name">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Short name</mat-label>
|
||||
<input matInput value={{currency.shortName}} formControlName="shortName">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width" appearance="fill">
|
||||
<mat-label>Rate</mat-label>
|
||||
<input matInput [value]="currency.rate | number:'0.2-2'" formControlName="rate" currencyMask
|
||||
[options]="{ prefix: '', precision: 4, inputMode: 1 }" required>
|
||||
<mat-error *ngIf="addForm.controls?.['rate']?.hasError('required')">
|
||||
Please enter rate
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width" appearance="fill">
|
||||
<mat-label>Quantity</mat-label>
|
||||
<input matInput [value]="currency.rate | number:'0.0-0'" formControlName="quantity"
|
||||
currencyMask [options]="{ prefix: '', precision: 0 }" required>
|
||||
<mat-error *ngIf="addForm.controls?.['rate']?.hasError('required')">
|
||||
Please enter rate
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="text-inside">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Rate Date</mat-label>
|
||||
<input matInput [matDatepicker]="picker3" (focus)="picker3.open()"
|
||||
value={{currency.rateDate}} formControlName="rateDate" required>
|
||||
<mat-hint>DD/MM/YYYY</mat-hint>
|
||||
<mat-datepicker-toggle matSuffix [for]="picker3"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker3></mat-datepicker>
|
||||
<mat-error *ngIf="addForm.controls?.['rateDate']?.hasError('required')">
|
||||
Please enter rate date
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="text-inside">
|
||||
<mat-checkbox class="example-margin" formControlName="isPrimary">
|
||||
Primary currency
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-dialog-chrome>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,99 @@
|
||||
// angular
|
||||
import { Component, DestroyRef, inject } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { Inject } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
// libs
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
// app
|
||||
import { ApiRoutes } from '../../../api-routes';
|
||||
import { CurrencyModel } from '../../../model/currency.model';
|
||||
|
||||
@Component({
|
||||
templateUrl: './rate.currency.component.html',
|
||||
styleUrls: ['./rate.currency.component.scss'],
|
||||
})
|
||||
export class SettingsRateCurrencyComponent {
|
||||
public addForm!: FormGroup;
|
||||
public error?: any;
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private httpClient: HttpClient,
|
||||
private dialogRef: MatDialogRef<SettingsRateCurrencyComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public currency: CurrencyModel
|
||||
) {
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.addForm = this.fb.group({
|
||||
id: [
|
||||
this.currency.id,
|
||||
],
|
||||
code: [
|
||||
this.currency.code,
|
||||
],
|
||||
symbol: [
|
||||
this.currency.symbol,
|
||||
],
|
||||
name: [
|
||||
this.currency.name,
|
||||
],
|
||||
shortName: [
|
||||
this.currency.shortName,
|
||||
],
|
||||
quantity: [
|
||||
this.currency.quantity || 1,
|
||||
[Validators.required],
|
||||
],
|
||||
rate: [
|
||||
this.currency.rate || 1,
|
||||
[Validators.required],
|
||||
],
|
||||
rateDate: [
|
||||
this.currency.rateDate,
|
||||
[Validators.required],
|
||||
],
|
||||
isPrimary: [
|
||||
this.currency.isPrimary,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
onSubmitClick() {
|
||||
this.error = undefined;
|
||||
if (this.addForm.valid) {
|
||||
this.httpClient
|
||||
.put<CurrencyModel>(ApiRoutes.SettingsCurrency.replace(':id', this.addForm.value.id), this.addForm.value)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.httpClient
|
||||
.post<CurrencyModel[]>(ApiRoutes.SettingsCurrenciesRate.replace(':id', this.addForm.value.id), this.addForm.value)
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.dialogRef.close({ refresh: true });
|
||||
},
|
||||
error: (error) => {
|
||||
this.error = error;
|
||||
},
|
||||
});
|
||||
},
|
||||
error: (error) => {
|
||||
this.error = error;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user