Publish from private repository

This commit is contained in:
Gitea Actions
2026-08-01 12:08:49 +00:00
commit 6f7fd61ee9
695 changed files with 69563 additions and 0 deletions
@@ -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;
}
});
}
}
}