Sorting n inporgress

This commit is contained in:
Aleksandra Usacheva 2021-01-22 16:44:58 +03:00
parent 468d8c6fbb
commit 6ba324fc65
14 changed files with 164 additions and 27 deletions

5
package-lock.json generated
View File

@ -7873,6 +7873,11 @@
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"lodash-es": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.20.tgz",
"integrity": "sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA=="
},
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",

View File

@ -33,6 +33,7 @@
"coerce-property": "^0.3.2",
"keycloak-angular": "^8.0.1",
"keycloak-js": "^11.0.3",
"lodash-es": "^4.17.20",
"ngx-papaparse": "^4.0.4",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",

View File

@ -58,6 +58,6 @@ export class CreateTemplateComponent implements OnInit {
}
navigateToEdit(id): void {
this.router.navigate([`../templates/${id}`], { fragment: this.operationType.toString() });
this.router.navigate([`../template/${id}`], { fragment: this.operationType.toString() });
}
}

View File

@ -1,10 +1,14 @@
import { SortOrder } from '../../shared/constants/sort-order';
export enum Actions {
createTemplate = 'createTemplate',
editTemplate = 'editTemplate',
removeTemplate = 'removeTemplate',
sortTemplates = 'sortTemplates',
}
export interface Action {
type: Actions;
templateID?: string;
sortDirection?: SortOrder;
}

View File

@ -1,13 +1,35 @@
<div fxLayout="column" fxLayoutGap="8px">
<div fxLayout="row" fxLayoutAlign="end center">
<div fxLayout="row" fxLayoutAlign="space-between center">
<fb-templates-search (valueChanges)="search($event)"></fb-templates-search>
<button mat-button color="primary" (click)="createTemplate()">CREATE TEMPLATE</button>
</div>
<mat-card *ngIf="(templates$ | async)?.length > 0; else Empty">
<mat-card-content>
<fb-templates-table (action)="action($event)" [templates]="templates$ | async"></fb-templates-table>
<div *ngIf="response$ | async as response; else Empty">
<mat-card *ngIf="response.templateModels.length > 0; else Empty">
<mat-card-content fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="space-around stretch">
<fb-templates-table
(action)="action($event)"
[templates]="response.templateModels"
></fb-templates-table>
<button
fxFlex="100"
mat-button
*ngIf="response.templateModels.length < response.count"
(click)="fetchMore()"
[disabled]="inProgress$ | async"
>
SHOW MORE
</button>
</mat-card-content>
<mat-card-footer *ngIf="inProgress$ | async">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</mat-card-footer>
</mat-card>
</div>
</div>
<ng-template #Empty>
<fb-empty-search-result></fb-empty-search-result>
<div *ngIf="inProgress$ | async" fxLayout="row" fxLayoutAlign="center">
<mat-progress-spinner color="primary" mode="indeterminate" diameter="128"></mat-progress-spinner>
</div>
<fb-empty-search-result *ngIf="!(inProgress$ | async)"></fb-empty-search-result>
</ng-template>

View File

@ -12,7 +12,8 @@ import { RemoveTemplateService } from '../../services/remove-template.service';
providers: [FetchTemplatesService, RemoveTemplateService],
})
export class P2pTemplatesComponent {
templates$ = this.fetchTemplatesService.templates$;
response$ = this.fetchTemplatesService.response$;
inProgress$ = this.fetchTemplatesService.inProgress$;
constructor(
private router: Router,
@ -39,6 +40,9 @@ export class P2pTemplatesComponent {
templateID: action.templateID,
});
break;
case Actions.sortTemplates:
this.fetchTemplatesService.fetch({ type: OperationType.Payment, sortOrder: action.sortDirection });
break;
default:
console.error('Wrong template action.');
}
@ -47,4 +51,10 @@ export class P2pTemplatesComponent {
createTemplate() {
this.action({ type: Actions.createTemplate });
}
search(searchValue: string) {
this.fetchTemplatesService.fetch({ type: OperationType.PeerToPeer, searchValue });
}
fetchMore() {}
}

View File

@ -1,13 +1,35 @@
<div fxLayout="column" fxLayoutGap="8px">
<div fxLayout="row" fxLayoutAlign="end center">
<div fxLayout="row" fxLayoutAlign="space-between center">
<fb-templates-search (valueChanges)="search($event)"></fb-templates-search>
<button mat-button color="primary" (click)="createTemplate()">CREATE TEMPLATE</button>
</div>
<mat-card *ngIf="(templates$ | async)?.length > 0; else Empty">
<mat-card-content>
<fb-templates-table (action)="action($event)" [templates]="templates$ | async"></fb-templates-table>
<div *ngIf="response$ | async as response; else Empty">
<mat-card *ngIf="response.templateModels.length > 0; else Empty">
<mat-card-content fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="space-around stretch">
<fb-templates-table
(action)="action($event)"
[templates]="response.templateModels"
></fb-templates-table>
<button
fxFlex="100"
mat-button
*ngIf="response.templateModels.length < response.count"
(click)="fetchMore()"
[disabled]="inProgress$ | async"
>
SHOW MORE
</button>
</mat-card-content>
<mat-card-footer *ngIf="inProgress$ | async">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</mat-card-footer>
</mat-card>
</div>
</div>
<ng-template #Empty>
<fb-empty-search-result></fb-empty-search-result>
<div *ngIf="inProgress$ | async" fxLayout="row" fxLayoutAlign="center">
<mat-progress-spinner color="primary" mode="indeterminate" diameter="128"></mat-progress-spinner>
</div>
<fb-empty-search-result *ngIf="!(inProgress$ | async)"></fb-empty-search-result>
</ng-template>

View File

@ -12,14 +12,14 @@ import { RemoveTemplateService } from '../../services/remove-template.service';
providers: [FetchTemplatesService, RemoveTemplateService],
})
export class PaymentTemplatesComponent {
templates$ = this.fetchTemplatesService.templates$;
response$ = this.fetchTemplatesService.response$;
inProgress$ = this.fetchTemplatesService.inProgress$;
constructor(
private router: Router,
private fetchTemplatesService: FetchTemplatesService,
private removeTemplateService: RemoveTemplateService
) {
this.fetchTemplatesService.fetch({ type: OperationType.Payment });
this.removeTemplateService.removed$.subscribe(() => {
this.fetchTemplatesService.fetch({ type: OperationType.Payment });
});
@ -39,6 +39,9 @@ export class PaymentTemplatesComponent {
templateID: action.templateID,
});
break;
case Actions.sortTemplates:
this.fetchTemplatesService.fetch({ type: OperationType.Payment, sortOrder: action.sortDirection });
break;
default:
console.error('Wrong template action.');
}
@ -47,4 +50,10 @@ export class PaymentTemplatesComponent {
createTemplate() {
this.action({ type: Actions.createTemplate });
}
search(searchValue: string) {
this.fetchTemplatesService.fetch({ type: OperationType.Payment, searchValue });
}
fetchMore() {}
}

View File

@ -0,0 +1,5 @@
<form fxLayout="row" fxLayoutGap="16px" [formGroup]="form">
<mat-form-field appearance="outline">
<input matInput placeholder="Search" formControlName="searchQuery" type="string" autocomplete="false" />
</mat-form-field>
</form>

View File

@ -0,0 +1,26 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { debounceTime, map, take } from 'rxjs/operators';
import { removeEmptyProperties } from '../../../../shared/utils/remove-empty-properties';
@Component({
selector: 'fb-templates-search',
templateUrl: 'templates-search.component.html',
})
export class TemplatesSearchComponent {
@Output() valueChanges: EventEmitter<string> = new EventEmitter();
form: FormGroup = this.fb.group({
searchQuery: '',
});
constructor(private route: ActivatedRoute, private router: Router, private fb: FormBuilder) {
this.form.valueChanges.pipe(debounceTime(600), map(removeEmptyProperties)).subscribe((v) => {
this.router.navigate([location.pathname], { queryParams: v });
this.valueChanges.emit(v.searchQuery);
});
this.route.queryParams.pipe(take(1)).subscribe((v) => this.form.patchValue(v));
}
}

View File

@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { Sort } from '@angular/material/sort';
import { SortOrder } from '../../../../shared/constants/sort-order';
import { Template } from '../../../templates-old/model/template';
import { Action, Actions } from '../../action';
@ -20,8 +21,14 @@ export class TemplatesTableComponent {
displayedColumns: string[] = ['id', 'template', 'updatedAt', 'actions'];
sortData(sort: Sort): void {
// this.sortType = sort.direction === 'asc' ? SortOrder.ASC : SortOrder.DESC;
// this.search();
switch (sort.direction) {
case 'asc':
this.action.emit({ type: Actions.sortTemplates, sortDirection: SortOrder.ASC });
break;
case 'desc':
this.action.emit({ type: Actions.sortTemplates, sortDirection: SortOrder.DESC });
break;
}
}
removeTemplate(templateID: string): void {

View File

@ -2,7 +2,7 @@ import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { EMPTY, merge, of, Subject } from 'rxjs';
import { catchError, map, shareReplay, switchMap } from 'rxjs/operators';
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
import { ConfigService } from '../../../config';
import { OperationType } from '../../../shared/constants/operation-type';
@ -12,24 +12,27 @@ import { OperationTypeManagementService } from '../../../shared/services/operati
export interface FetchTemplatesParams {
type: OperationType;
searchValue?: string;
sortOrder?: SortOrder;
}
@Injectable()
export class FetchTemplatesService {
private SIZE = this.configService.pageSize;
private fetchTemplates$ = new Subject<FetchTemplatesParams>();
private fetchMore$;
private hasError$ = new Subject();
templates$ = this.fetchTemplates$.pipe(
response$ = this.fetchTemplates$.pipe(
switchMap((params) =>
this.operationTypeManagementService
.findTemplateService(params.type)
.findTemplates({
size: this.SIZE,
sortOrder: SortOrder.ASC,
sortOrder: params.sortOrder || SortOrder.ASC,
searchValue: params.searchValue,
})
.pipe(
map((templates) => templates.templateModels),
catchError((error: HttpErrorResponse) => {
this.snackBar.open(`${error.status}: ${error.message}`, 'OK', {
duration: 1500,
@ -42,17 +45,19 @@ export class FetchTemplatesService {
shareReplay(1)
);
inProgress$ = progress(this.fetchTemplates$, merge(this.hasError$, this.templates$));
inProgress$ = progress(this.fetchTemplates$, merge(this.hasError$, this.response$));
constructor(
private operationTypeManagementService: OperationTypeManagementService,
private configService: ConfigService,
private snackBar: MatSnackBar
) {
this.templates$.subscribe();
this.response$.subscribe();
}
fetch(params: FetchTemplatesParams) {
this.fetchTemplates$.next(params);
}
fetchMore() {}
}

View File

@ -1,10 +1,15 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FlexModule } from '@angular/flex-layout';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
@ -28,6 +33,7 @@ import { P2pTemplatesService } from '../../shared/services/template/p2p-template
import { PaymentTemplatesService } from '../../shared/services/template/payment-templates.service';
import { P2pTemplatesComponent } from './components/p2p-templates/p2p-templates.component';
import { PaymentTemplatesComponent } from './components/payment-templates/payment-templates.component';
import { TemplatesSearchComponent } from './components/templates-search/templates-search.component';
import { TemplatesTableComponent } from './components/templates-table/templates-table.component';
import { TemplatesRoutingModule } from './templates-routing.module';
import { TemplatesComponent } from './templates.component';
@ -49,8 +55,19 @@ import { TemplatesComponent } from './templates.component';
SharedPipesModule,
FlexModule,
MatSnackBarModule,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
MatProgressSpinnerModule,
MatProgressBarModule,
],
declarations: [
TemplatesComponent,
P2pTemplatesComponent,
PaymentTemplatesComponent,
TemplatesTableComponent,
TemplatesSearchComponent,
],
declarations: [TemplatesComponent, P2pTemplatesComponent, PaymentTemplatesComponent, TemplatesTableComponent],
// TODO: need to refactor these services
providers: [
OperationTypeManagementService,

View File

@ -0,0 +1,4 @@
import identity from 'lodash-es/identity';
import pickBy from 'lodash-es/pickBy';
export const removeEmptyProperties = (s) => pickBy(s, identity);