diff --git a/package-lock.json b/package-lock.json index 3544f03..351c77c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index ecd1350..aee454a 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/app/sections/template/create-template/create-template.component.ts b/src/app/sections/template/create-template/create-template.component.ts index 1ea87b1..2ad966c 100644 --- a/src/app/sections/template/create-template/create-template.component.ts +++ b/src/app/sections/template/create-template/create-template.component.ts @@ -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() }); } } diff --git a/src/app/sections/templates/action.ts b/src/app/sections/templates/action.ts index a0c4535..84fc84f 100644 --- a/src/app/sections/templates/action.ts +++ b/src/app/sections/templates/action.ts @@ -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; } diff --git a/src/app/sections/templates/components/p2p-templates/p2p-templates.component.html b/src/app/sections/templates/components/p2p-templates/p2p-templates.component.html index a01a9bc..4301cf9 100644 --- a/src/app/sections/templates/components/p2p-templates/p2p-templates.component.html +++ b/src/app/sections/templates/components/p2p-templates/p2p-templates.component.html @@ -1,13 +1,35 @@
-
+
+
- - - - - +
+ + + + + + + + + +
+ - +
+ +
+
diff --git a/src/app/sections/templates/components/p2p-templates/p2p-templates.component.ts b/src/app/sections/templates/components/p2p-templates/p2p-templates.component.ts index bd21043..395a658 100644 --- a/src/app/sections/templates/components/p2p-templates/p2p-templates.component.ts +++ b/src/app/sections/templates/components/p2p-templates/p2p-templates.component.ts @@ -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() {} } diff --git a/src/app/sections/templates/components/payment-templates/payment-templates.component.html b/src/app/sections/templates/components/payment-templates/payment-templates.component.html index a01a9bc..4301cf9 100644 --- a/src/app/sections/templates/components/payment-templates/payment-templates.component.html +++ b/src/app/sections/templates/components/payment-templates/payment-templates.component.html @@ -1,13 +1,35 @@
-
+
+
- - - - - +
+ + + + + + + + + +
+ - +
+ +
+
diff --git a/src/app/sections/templates/components/payment-templates/payment-templates.component.ts b/src/app/sections/templates/components/payment-templates/payment-templates.component.ts index 03d0078..279c7f1 100644 --- a/src/app/sections/templates/components/payment-templates/payment-templates.component.ts +++ b/src/app/sections/templates/components/payment-templates/payment-templates.component.ts @@ -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() {} } diff --git a/src/app/sections/templates/components/templates-search/templates-search.component.html b/src/app/sections/templates/components/templates-search/templates-search.component.html new file mode 100644 index 0000000..dc5f110 --- /dev/null +++ b/src/app/sections/templates/components/templates-search/templates-search.component.html @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/src/app/sections/templates/components/templates-search/templates-search.component.ts b/src/app/sections/templates/components/templates-search/templates-search.component.ts new file mode 100644 index 0000000..f70adc0 --- /dev/null +++ b/src/app/sections/templates/components/templates-search/templates-search.component.ts @@ -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 = 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)); + } +} diff --git a/src/app/sections/templates/components/templates-table/templates-table.component.ts b/src/app/sections/templates/components/templates-table/templates-table.component.ts index 2b4fbfd..3caf725 100644 --- a/src/app/sections/templates/components/templates-table/templates-table.component.ts +++ b/src/app/sections/templates/components/templates-table/templates-table.component.ts @@ -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 { diff --git a/src/app/sections/templates/services/fetch-templates.service.ts b/src/app/sections/templates/services/fetch-templates.service.ts index 715c92c..dd116de 100644 --- a/src/app/sections/templates/services/fetch-templates.service.ts +++ b/src/app/sections/templates/services/fetch-templates.service.ts @@ -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(); + 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() {} } diff --git a/src/app/sections/templates/templates.module.ts b/src/app/sections/templates/templates.module.ts index 84b5140..9924da5 100644 --- a/src/app/sections/templates/templates.module.ts +++ b/src/app/sections/templates/templates.module.ts @@ -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, diff --git a/src/app/shared/utils/remove-empty-properties.ts b/src/app/shared/utils/remove-empty-properties.ts new file mode 100644 index 0000000..88ead5b --- /dev/null +++ b/src/app/shared/utils/remove-empty-properties.ts @@ -0,0 +1,4 @@ +import identity from 'lodash-es/identity'; +import pickBy from 'lodash-es/pickBy'; + +export const removeEmptyProperties = (s) => pickBy(s, identity);