MI-9: Enable wallet reports (#137)

This commit is contained in:
Rinat Arsaev 2023-07-31 20:31:47 +04:00 committed by GitHub
parent e047b1f0c2
commit 4a5ef4595a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 125 additions and 52 deletions

8
package-lock.json generated
View File

@ -25,7 +25,7 @@
"@sentry/angular": "^7.56.0",
"@sentry/integrations": "^7.56.0",
"@sentry/tracing": "^7.56.0",
"@vality/ng-core": "^16.2.1-pr-33-42d91a3.0",
"@vality/ng-core": "^16.2.1-pr-33-bd23324.0",
"@vality/swag-anapi-v2": "2.0.0",
"@vality/swag-api-keys-v2": "^0.1.2-be3bbdd.0",
"@vality/swag-claim-management": "0.1.1-7a03f9b.0",
@ -6866,9 +6866,9 @@
}
},
"node_modules/@vality/ng-core": {
"version": "16.2.1-pr-33-42d91a3.0",
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-16.2.1-pr-33-42d91a3.0.tgz",
"integrity": "sha512-Ags1PPyLkeHEmjRlh3hqgo8jR4dtLpnM9EmjZ3Qa33ayfI8cki+BQANRzaH2VOgjTLcwR54QOTxm012xui2SEQ==",
"version": "16.2.1-pr-33-bd23324.0",
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-16.2.1-pr-33-bd23324.0.tgz",
"integrity": "sha512-V+aGyvD0oSfmgj8yxPolgweM6Q05XDJsuXdAAIBD1ptrTQNxkjPBTY1op5LzKGI3+Uk0MQ9ctCI5HjJd+BkQRQ==",
"dependencies": {
"@ng-matero/extensions": "^16.0.0",
"@s-libs/js-core": "^16.0.0",

View File

@ -41,7 +41,7 @@
"@sentry/angular": "^7.56.0",
"@sentry/integrations": "^7.56.0",
"@sentry/tracing": "^7.56.0",
"@vality/ng-core": "^16.2.1-pr-33-42d91a3.0",
"@vality/ng-core": "^16.2.1-pr-33-bd23324.0",
"@vality/swag-anapi-v2": "2.0.0",
"@vality/swag-api-keys-v2": "^0.1.2-be3bbdd.0",
"@vality/swag-claim-management": "0.1.1-7a03f9b.0",

View File

@ -76,7 +76,7 @@ export class DialogFiltersComponent implements OnInit {
private getInitFormValues(): AdditionalFiltersForm {
const {
depositID = '',
walletID = '',
walletID = null,
identityID = '',
sourceID = '',
depositStatus = null,

View File

@ -0,0 +1,18 @@
<div
gdColumns="1fr"
gdGap="24px"
*transloco="let t; scope: 'wallet-section'; read: 'walletSection.reports.reportFiles'"
>
<div fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="8px">
<div class="dsh-title">{{ t('title') }}</div>
<button dsh-text-button color="accent" [disabled]="!!(progress$ | async)" (click)="download()">
{{ t('downloadAll') }}
</button>
</div>
<div *ngFor="let file of files" gdColumns="auto auto" gdAlignRows="space-between" gdAlignColumns="center center">
<div class="dsh-body-1">{{ file.id }}</div>
<button dsh-icon-button (click)="download([file.id])" [disabled]="!!(progress$ | async)">
<dsh-bi icon="save"></dsh-bi>
</button>
</div>
</div>

View File

@ -0,0 +1,50 @@
import { Component, Input } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
import { NotifyLogService, progressTo } from '@vality/ng-core';
import { ReportFiles } from '@vality/swag-wallet';
import { forkJoin, EMPTY, BehaviorSubject } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { DownloadsService } from '@dsh/app/api/wallet';
import { multipleDownload } from '@dsh/utils';
@UntilDestroy()
@Component({
selector: 'dsh-files',
templateUrl: './files.component.html',
styles: [],
})
export class FilesComponent {
@Input() id: number;
@Input() files: ReportFiles[];
progress$ = new BehaviorSubject(0);
constructor(
private downloadsService: DownloadsService,
private transloco: TranslocoService,
private log: NotifyLogService
) {}
download(fileIDs: string[] = this.files.map((f) => f.id)) {
forkJoin(
fileIDs.map((fileID) =>
this.downloadsService.downloadFile({ fileID }).pipe(
catchError((err) => {
this.log.error(
err,
this.transloco.translate('reports.errors.downloadReportError', null, 'wallet-section')
);
return EMPTY;
}),
progressTo(this.progress$)
)
)
)
.pipe(untilDestroyed(this))
.subscribe((files) => {
multipleDownload(files.map((f) => f.url));
});
}
}

View File

@ -34,19 +34,17 @@
>
<ng-template let-report>
<div fxLayout="column" fxLayoutGap="24px">
<div gdColumns="1fr" gdGap="24px">
<div gdColumns="1fr" gdColumns.gt-sm="1fr 1fr 1fr" gdGap="24px">
<dsh-details-item [title]="t('status')">
<dsh-status
[color]="reportStatusColor[report.status]"
>{{ (reportStatusDict$| async)?.[report.status] }}</dsh-status
>
</dsh-details-item>
<dsh-details-item [title]="t('createdAt')">{{
report.createdAt | date : 'dd MMMM yyyy, HH:mm:ss'
}}</dsh-details-item>
</div>
<dsh-details-item [title]="t('period')"
<div gdColumns="1fr" gdColumns.gt-sm="1fr 1fr" gdGap="24px">
<dsh-details-item [title]="t('status')">
<dsh-status
[color]="reportStatusColor[report.status]"
>{{ (reportStatusDict$| async)?.[report.status] }}</dsh-status
>
</dsh-details-item>
<dsh-details-item [title]="t('createdAt')">{{
report.createdAt | date : 'dd MMMM yyyy, HH:mm:ss'
}}</dsh-details-item>
<dsh-details-item [title]="t('period')" gdColumn="1/-1"
>{{ report.fromTime | date : 'dd MMMM yyyy, HH:mm:ss' }} -
{{ report.toTime | date : 'dd MMMM yyyy, HH:mm:ss' }}</dsh-details-item
>
@ -54,7 +52,7 @@
<ng-container *ngIf="report.status === 'created'">
<mat-divider></mat-divider>
<dsh-report-files [reportID]="report.id" [files]="report.files"></dsh-report-files>
<dsh-files [id]="report.id" [files]="report.files"></dsh-files>
</ng-container>
</div>
</ng-template>

View File

@ -92,14 +92,13 @@ export class ReportsComponent implements OnInit {
.pipe(startWith(this.form.value), distinctUntilChanged(isEqual), untilDestroyed(this))
.subscribe((value) => {
void this.qp.set(value);
if (value.identityID) {
this.load();
}
this.load();
});
}
load() {
const { dateRange, identityID } = this.form.value;
if (!identityID) return;
this.fetchReportsService.load({
fromTime: dateRange.start.utc().format(),
toTime: dateRange.end.utc().format(),

View File

@ -11,8 +11,6 @@ import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { TranslocoModule } from '@ngneat/transloco';
import { ReportFilesModule } from '@dsh/app/sections/payment-section/reports/report-files';
import { ReportPipesModule } from '@dsh/app/sections/payment-section/reports/report-pipes';
import { IdentityFilterModule, ApiModelRefsModule } from '@dsh/app/shared';
import { AccordionTableModule } from '@dsh/app/shared/components/accordion-table';
import { DialogModule } from '@dsh/app/shared/components/dialog';
@ -26,11 +24,12 @@ import { BootstrapIconModule, StatusModule } from '@dsh/components/indicators';
import { DetailsItemModule } from '@dsh/components/layout';
import { CreateReportDialogComponent } from './components/create-report-dialog/create-report-dialog.component';
import { FilesComponent } from './components/files/files.component';
import { ReportsRoutingModule } from './reports-routing.module';
import { ReportsComponent } from './reports.component';
@NgModule({
declarations: [ReportsComponent, CreateReportDialogComponent],
declarations: [ReportsComponent, CreateReportDialogComponent, FilesComponent],
imports: [
CommonModule,
ReportsRoutingModule,
@ -56,10 +55,8 @@ import { ReportsComponent } from './reports.component';
IdentityFieldComponent,
BootstrapIconModule,
MatDividerModule,
ReportFilesModule,
ApiModelRefsModule,
DetailsItemModule,
ReportPipesModule,
StatusModule,
],
})

View File

@ -1,5 +1,4 @@
import { BootstrapIconName } from '@dsh/components/indicators';
import { environment } from '@dsh/environments';
export enum NavbarRouterLink {
Wallets = 'wallets',
@ -37,15 +36,11 @@ export const toNavbarItemConfig = ({
icon: BootstrapIconName.ArrowUpRightCircle,
label: withdrawals,
},
...(environment.production
? []
: [
{
routerLink: NavbarRouterLink.Reports,
icon: BootstrapIconName.FileText,
label: reports,
},
]),
{
routerLink: NavbarRouterLink.Reports,
icon: BootstrapIconName.FileText,
label: reports,
},
{
routerLink: NavbarRouterLink.Integrations,
icon: BootstrapIconName.Plug,

View File

@ -1,8 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { environment } from '@dsh/environments';
import { WalletSectionComponent } from './wallet-section.component';
const WALLET_SECTION_ROUTES: Routes = [
@ -26,14 +24,10 @@ const WALLET_SECTION_ROUTES: Routes = [
path: 'integrations',
loadChildren: () => import('./integrations').then((m) => m.IntegrationsModule),
},
...(environment.production
? []
: [
{
path: 'reports',
loadChildren: () => import('./reports').then((m) => m.ReportsModule),
},
]),
{
path: 'reports',
loadChildren: () => import('./reports').then((m) => m.ReportsModule),
},
{
path: '',
redirectTo: 'wallets',

View File

@ -2,7 +2,7 @@
<dsh-filter
[active]="isActive"
[label]="t('label')"
[activeLabel]="t('label') + ' #' + savedValue"
[activeLabel]="t('label', { name: (identity$ | async)?.name || '#' + savedValue })"
[content]="content"
(save)="save()"
(clear)="clear()"

View File

@ -1,7 +1,10 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { createControlProviders } from '@vality/ng-core';
import { Identity } from '@vality/swag-wallet';
import { combineLatest } from 'rxjs';
import { map, share } from 'rxjs/operators';
import { IdentitiesService } from '@dsh/app/api/wallet';
import { FilterSuperclass } from '@dsh/components/filter';
@Component({
@ -10,4 +13,13 @@ import { FilterSuperclass } from '@dsh/components/filter';
changeDetection: ChangeDetectionStrategy.OnPush,
providers: createControlProviders(() => IdentityFilterComponent),
})
export class IdentityFilterComponent extends FilterSuperclass<Identity['id']> {}
export class IdentityFilterComponent extends FilterSuperclass<Identity['id']> {
identity$ = combineLatest([this.identitiesService.identities$, this.savedValue$]).pipe(
map(([identities, value]) => identities.find((i) => i.id === value)),
share()
);
constructor(private identitiesService: IdentitiesService) {
super();
}
}

View File

@ -175,7 +175,7 @@
"showAllStatuses": "Show all statuses"
},
"identityFilter": {
"label": "Wallet holder"
"label": "Wallet holder: {{name}}"
},
"inputs": {
"identityField": {

View File

@ -175,7 +175,7 @@
"showAllStatuses": "Показать все статусы"
},
"identityFilter": {
"label": "Владелец кошелька"
"label": "Владелец кошелька: {{name}}"
},
"inputs": {
"identityField": {

View File

@ -56,11 +56,16 @@
"createdAt": "Created at",
"dateRangeDescription": "Reporting period",
"errors": {
"downloadReportError": "Failed to load documents",
"identityNotSpecified": "Wallet holder not specified"
},
"openCreateReport": "Create report",
"period": "Reporting period",
"report": "Report",
"reportFiles": {
"downloadAll": "Download all",
"title": "Documents"
},
"status": "Status"
},
"walletSection": {

View File

@ -56,11 +56,16 @@
"createdAt": "Дата и время создания",
"dateRangeDescription": "Период создания отчетов",
"errors": {
"downloadReportError": "Не удалось загрузить документы",
"identityNotSpecified": "Владелец кошелька не указан"
},
"openCreateReport": "Создать отчет",
"period": "Период отчетности",
"report": "Отчет",
"reportFiles": {
"downloadAll": "Загрузить все",
"title": "Документы"
},
"status": "Статус"
},
"walletSection": {