mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
FE-954: claim management API integration (#89)
This commit is contained in:
parent
f42a011eff
commit
3374d55ee6
2
.npmrc
Normal file
2
.npmrc
Normal file
@ -0,0 +1,2 @@
|
||||
@rbkmoney:registry=https://npm.pkg.github.com/
|
||||
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
|
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -15,9 +15,11 @@ build('control-center', 'docker-host') {
|
||||
def pipeline = {
|
||||
runStage('init') {
|
||||
withGithubSshCredentials {
|
||||
withGithubToken {
|
||||
sh 'make wc_init'
|
||||
}
|
||||
}
|
||||
}
|
||||
runStage('build') {
|
||||
sh 'make wc_build'
|
||||
}
|
||||
|
4
Makefile
4
Makefile
@ -20,7 +20,7 @@ BASE_IMAGE_TAG := 2b4570bc1d9631c10aaed2132eb87eb9003f3471
|
||||
BUILD_IMAGE_TAG := f3732d29a5e622aabf80542b5138b3631a726adb
|
||||
|
||||
GIT_SSH_COMMAND :=
|
||||
DOCKER_RUN_OPTS = -e GIT_SSH_COMMAND='$(GIT_SSH_COMMAND)' -e NG_CLI_ANALYTICS=ci
|
||||
DOCKER_RUN_OPTS = -e GIT_SSH_COMMAND='$(GIT_SSH_COMMAND)' -e NG_CLI_ANALYTICS=ci -e NPM_TOKEN='$(GITHUB_TOKEN)'
|
||||
|
||||
CALL_W_CONTAINER := init build clean submodules
|
||||
|
||||
@ -53,7 +53,7 @@ clean:
|
||||
compile-damsel: damsel-client damsel-model damsel-meta
|
||||
|
||||
damsel-client:
|
||||
@$(foreach file,domain_config payment_processing merch_stat,echo $(file); thrift -r -gen js:node,runtime_package=woody_js/dist/thrift -o ./src/app/thrift ./node_modules/damsel/proto/$(file).thrift;)
|
||||
@$(foreach file,domain_config payment_processing merch_stat claim_management,echo $(file); thrift -r -gen js:node,runtime_package=woody_js/dist/thrift -o ./src/app/thrift ./node_modules/damsel/proto/$(file).thrift;)
|
||||
|
||||
damsel-meta:
|
||||
npm run damsel-meta
|
||||
|
62
package-lock.json
generated
62
package-lock.json
generated
@ -2402,6 +2402,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@rbkmoney/partial-fetcher": {
|
||||
"version": "1.0.4",
|
||||
"requires": {
|
||||
"rxjs": "^6.5.3"
|
||||
}
|
||||
},
|
||||
"@schematics/angular": {
|
||||
"version": "8.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.6.tgz",
|
||||
@ -2477,6 +2483,12 @@
|
||||
"@types/jasmine": "*"
|
||||
}
|
||||
},
|
||||
"@types/jwt-decode": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jwt-decode/-/jwt-decode-2.2.1.tgz",
|
||||
"integrity": "sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/lodash": {
|
||||
"version": "4.14.116",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.116.tgz",
|
||||
@ -5222,8 +5234,8 @@
|
||||
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
|
||||
},
|
||||
"damsel": {
|
||||
"version": "git+ssh://git@github.com/rbkmoney/damsel.git#b563890354447a5e175a9a318b33233a926a5e9c",
|
||||
"from": "git+ssh://git@github.com/rbkmoney/damsel.git#b563890354447a5e175a9a318b33233a926a5e9c"
|
||||
"version": "git+ssh://git@github.com/rbkmoney/damsel.git#5a78a602632a1dbbc5f294361d1538cff4a27040",
|
||||
"from": "git+ssh://git@github.com/rbkmoney/damsel.git#5a78a602632a1dbbc5f294361d1538cff4a27040"
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
@ -7884,6 +7896,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jwt-decode": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz",
|
||||
"integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk="
|
||||
},
|
||||
"karma": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-4.3.0.tgz",
|
||||
@ -11755,27 +11772,6 @@
|
||||
"integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-es": {
|
||||
"version": "3.3.9",
|
||||
"resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
|
||||
"integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
|
||||
"requires": {
|
||||
"commander": "~2.13.0",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
|
||||
"integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA=="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
|
||||
@ -11838,6 +11834,11 @@
|
||||
"y18n": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
|
||||
"integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA=="
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
|
||||
@ -11954,6 +11955,15 @@
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"uglify-es": {
|
||||
"version": "3.3.9",
|
||||
"resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
|
||||
"integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
|
||||
"requires": {
|
||||
"commander": "~2.13.0",
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -14068,8 +14078,8 @@
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"woody_js": {
|
||||
"version": "git+ssh://git@github.com/rbkmoney/woody_js.git#d2c90a54861593fa794afe3b09c4febb9d6e37d0",
|
||||
"from": "git+ssh://git@github.com/rbkmoney/woody_js.git#d2c90a54861593fa794afe3b09c4febb9d6e37d0",
|
||||
"version": "git+ssh://git@github.com/rbkmoney/woody_js.git#bc2c9f86cae470a0fe99730ca4a30b204058214b",
|
||||
"from": "git+ssh://git@github.com/rbkmoney/woody_js.git#bc2c9f86cae470a0fe99730ca4a30b204058214b",
|
||||
"requires": {
|
||||
"babel-core": "6.26.3",
|
||||
"babel-loader": "7.1.4",
|
||||
@ -14271,7 +14281,7 @@
|
||||
},
|
||||
"stream-http": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "http://registry.npmjs.org/stream-http/-/stream-http-2.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.3.1.tgz",
|
||||
"integrity": "sha1-fh3IcQLD4xsy5mDwTKMfI929HVI=",
|
||||
"requires": {
|
||||
"builtin-status-codes": "^2.0.0",
|
||||
|
@ -12,6 +12,7 @@
|
||||
"damsel-meta": "thrift-ts node_modules/damsel/proto -o src/assets/meta-damsel.json --json --pack --prettify",
|
||||
"machinegun-model": "thrift-ts node_modules/machinegun_proto/proto -o src/app/machinegun/gen-model -d false",
|
||||
"fistful-model": "thrift-ts node_modules/fistful-proto/proto -o src/app/fistful/gen-model -d false",
|
||||
"codegen": "npm run damsel-model; npm run damsel-meta; npm run machinegun-model; npm run fistful-model",
|
||||
"prettier": "prettier \"**/*.{html,js,ts,css,md,json,prettierrc,svg}\" --write",
|
||||
"check": "prettier \"**/*.{html,js,ts,css,md,json,prettierrc,svg}\" --list-different"
|
||||
},
|
||||
@ -30,12 +31,14 @@
|
||||
"@angular/platform-browser-dynamic": "^8.2.8",
|
||||
"@angular/platform-server": "^8.2.8",
|
||||
"@angular/router": "^8.2.8",
|
||||
"@rbkmoney/partial-fetcher": "^1.0.4",
|
||||
"angular2-prettyjson": "3.0.1",
|
||||
"core-js": "^2.5.4",
|
||||
"damsel": "git+ssh://git@github.com/rbkmoney/damsel.git#b563890354447a5e175a9a318b33233a926a5e9c",
|
||||
"damsel": "git+ssh://git@github.com/rbkmoney/damsel.git#5a78a602632a1dbbc5f294361d1538cff4a27040",
|
||||
"fistful-proto": "git+ssh://git@github.com/rbkmoney/fistful-proto.git#59b72ba54ec0e7f1af1d9b83aba10883ac985019",
|
||||
"hammerjs": "^2.0.8",
|
||||
"jsonc-parser": "^2.0.2",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"keycloak-angular": "6.0.0",
|
||||
"keycloak-js": "4.5.0",
|
||||
"lodash-es": "^4.17.10",
|
||||
@ -45,7 +48,7 @@
|
||||
"rxjs": "^6.5.3",
|
||||
"thrift-ts": "git+ssh://git@github.com/rbkmoney/thrift-ts.git#a5e3830ad30d5717e5e627ddcefa8f4d8918b174",
|
||||
"uuid": "^3.3.2",
|
||||
"woody_js": "git+ssh://git@github.com/rbkmoney/woody_js.git#d2c90a54861593fa794afe3b09c4febb9d6e37d0",
|
||||
"woody_js": "git+ssh://git@github.com/rbkmoney/woody_js.git#bc2c9f86cae470a0fe99730ca4a30b204058214b",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -54,6 +57,7 @@
|
||||
"@angular/compiler-cli": "^8.2.8",
|
||||
"@types/jasmine": "~2.8.6",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/jwt-decode": "^2.2.1",
|
||||
"@types/lodash-es": "^4.17.1",
|
||||
"@types/node": "~8.9.4",
|
||||
"@types/uuid": "^3.4.3",
|
||||
|
@ -20,7 +20,6 @@ import {
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { ClaimsModule } from './claims/claims.module';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { ClaimModule } from './claim/claim.module';
|
||||
import { PayoutsModule } from './payouts/payouts.module';
|
||||
@ -30,6 +29,7 @@ import { PartyModule } from './party/party.module';
|
||||
import { DomainModule } from './domain';
|
||||
import { RepairingModule } from './repairing/repairing.module';
|
||||
import { DepositsModule } from './deposits/deposits.module';
|
||||
import { ClaimMgtModule } from './claim-mgt/claim-mgt.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
@ -44,8 +44,8 @@ import { DepositsModule } from './deposits/deposits.module';
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
ClaimsModule,
|
||||
ClaimModule,
|
||||
ClaimMgtModule,
|
||||
PayoutsModule,
|
||||
PaymentAdjustmentModule,
|
||||
PartiesModule,
|
||||
|
28
src/app/claim-mgt/claim-mgt-routing.module.ts
Normal file
28
src/app/claim-mgt/claim-mgt-routing.module.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppAuthGuardService } from '../app-auth-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'claims',
|
||||
loadChildren: () => import('./claims').then(m => m.ClaimsModule),
|
||||
canActivate: [AppAuthGuardService],
|
||||
data: {
|
||||
roles: ['claim:get']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'party',
|
||||
loadChildren: () => import('./claim').then(m => m.ClaimModule),
|
||||
canActivate: [AppAuthGuardService],
|
||||
data: {
|
||||
roles: ['claim:get']
|
||||
}
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ClaimMgtRouting {}
|
7
src/app/claim-mgt/claim-mgt.module.ts
Normal file
7
src/app/claim-mgt/claim-mgt.module.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ClaimMgtRouting } from './claim-mgt-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ClaimMgtRouting]
|
||||
})
|
||||
export class ClaimMgtModule {}
|
21
src/app/claim-mgt/claim/claim-routing.module.ts
Normal file
21
src/app/claim-mgt/claim/claim-routing.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppAuthGuardService } from '../../app-auth-guard.service';
|
||||
import { ClaimComponent } from './claim.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: ':party_id/claim/:claim_id',
|
||||
component: ClaimComponent,
|
||||
canActivate: [AppAuthGuardService],
|
||||
data: {
|
||||
roles: ['claim:get']
|
||||
}
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ClaimRoutingModule {}
|
1
src/app/claim-mgt/claim/claim.component.html
Normal file
1
src/app/claim-mgt/claim/claim.component.html
Normal file
@ -0,0 +1 @@
|
||||
Claim
|
6
src/app/claim-mgt/claim/claim.component.ts
Normal file
6
src/app/claim-mgt/claim/claim.component.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claim.component.html'
|
||||
})
|
||||
export class ClaimComponent {}
|
9
src/app/claim-mgt/claim/claim.module.ts
Normal file
9
src/app/claim-mgt/claim/claim.module.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ClaimComponent } from './claim.component';
|
||||
import { ClaimRoutingModule } from './claim-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ClaimRoutingModule],
|
||||
declarations: [ClaimComponent]
|
||||
})
|
||||
export class ClaimModule {}
|
1
src/app/claim-mgt/claim/index.ts
Normal file
1
src/app/claim-mgt/claim/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './claim.module';
|
@ -1,14 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { ClaimsComponent } from './claims.component';
|
||||
import { AppAuthGuardService } from '../app-auth-guard.service';
|
||||
import { AppAuthGuardService } from '../../app-auth-guard.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'claims',
|
||||
path: '',
|
||||
component: ClaimsComponent,
|
||||
canActivate: [AppAuthGuardService],
|
||||
data: {
|
@ -1,15 +1,15 @@
|
||||
<table mat-table [dataSource]="claims">
|
||||
<ng-container matColumnDef="partyID">
|
||||
<th mat-header-cell *matHeaderCellDef>Party ID</th>
|
||||
<td mat-cell *matCellDef="let claim">{{ claim.partyId }}</td>
|
||||
<td mat-cell *matCellDef="let claim">{{ claim.party_id }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="claimID">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Claim ID</th>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">{{ claim.claimId }}</td>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">{{ claim.id }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef>Status</th>
|
||||
<td mat-cell *matCellDef="let claim">{{ claim.status }}</td>
|
||||
<td mat-cell *matCellDef="let claim">{{ getClaimStatus(claim.status) }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="revision">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Revision</th>
|
||||
@ -18,19 +18,19 @@
|
||||
<ng-container matColumnDef="createdAt">
|
||||
<th fxHide.xs mat-header-cell *matHeaderCellDef>Created at</th>
|
||||
<td fxHide.xs mat-cell *matCellDef="let claim">
|
||||
{{ claim.createdAt | date: 'dd.MM.yyyy HH:mm:ss' }}
|
||||
{{ claim.created_at | date: 'dd.MM.yyyy HH:mm:ss' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="updatedAt">
|
||||
<th fxHide.sm fxHide.xs mat-header-cell *matHeaderCellDef>Updated at</th>
|
||||
<td fxHide.sm fxHide.xs mat-cell *matCellDef="let claim">
|
||||
{{ claim.updatedAt | date: 'dd.MM.yyyy HH:mm:ss' }}
|
||||
{{ claim.updated_at | date: 'dd.MM.yyyy HH:mm:ss' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="claimDetailButton">
|
||||
<th mat-header-cell *matHeaderCellDef class="action-cell"></th>
|
||||
<td mat-cell *matCellDef="let claim" class="action-cell">
|
||||
<button mat-icon-button (click)="navigateToClaim(claim)">
|
||||
<button mat-icon-button (click)="navigateToClaim(claim.party_id, claim.id)">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</td>
|
@ -1,8 +1,8 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ClaimInfo } from '../../papi/model';
|
||||
import { ClaimActionType } from '../../claim/claim-action-type';
|
||||
import { Claim, ClaimStatus } from '../../../gen-damsel/claim_management';
|
||||
import { extractClaimStatus } from '../../../shared/extract-claim-status';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-claims-table',
|
||||
@ -11,10 +11,9 @@ import { ClaimActionType } from '../../claim/claim-action-type';
|
||||
})
|
||||
export class ClaimsTableComponent {
|
||||
@Input()
|
||||
claims: ClaimInfo[];
|
||||
claims: Claim[];
|
||||
|
||||
displayedColumns = [
|
||||
'partyID',
|
||||
'claimID',
|
||||
'status',
|
||||
'revision',
|
||||
@ -25,8 +24,11 @@ export class ClaimsTableComponent {
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
navigateToClaim(claim: ClaimInfo) {
|
||||
const c = claim as any;
|
||||
this.router.navigate([`/claims/${c.partyId}/${ClaimActionType.edit}/${c.claimId}`]);
|
||||
navigateToClaim(partyID: string, claimID: number) {
|
||||
this.router.navigate([`party/${partyID}/claim/${claimID}`]);
|
||||
}
|
||||
|
||||
getClaimStatus(status: ClaimStatus) {
|
||||
return extractClaimStatus(status);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
<mat-card-content>
|
||||
<cc-search-form (valueChanges)="search($event)"></cc-search-form>
|
||||
</mat-card-content>
|
||||
<mat-card-footer *ngIf="isLoading">
|
||||
<mat-card-footer *ngIf="(isLoading$ | async)">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</mat-card-footer>
|
||||
</mat-card>
|
||||
@ -14,5 +14,15 @@
|
||||
<cc-claim-actions></cc-claim-actions>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div class="mat-elevation-z2"><cc-claims-table [claims]="claims"></cc-claims-table></div>
|
||||
<div class="mat-elevation-z2" fxLayout="column">
|
||||
<cc-claims-table [claims]="claims$ | async"></cc-claims-table>
|
||||
<button
|
||||
mat-raised-button
|
||||
*ngIf="(hasMore$ | async)"
|
||||
(click)="fetchMore()"
|
||||
[disabled]="isLoading$ | async"
|
||||
>
|
||||
Load more...
|
||||
</button>
|
||||
</div>
|
||||
</cc-card-container>
|
29
src/app/claim-mgt/claims/claims.component.ts
Normal file
29
src/app/claim-mgt/claims/claims.component.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { ClaimsService } from './claims.service';
|
||||
import { SearchFormValue } from './search-form/search-form-value';
|
||||
import { ClaimStatus } from '../../papi/model/claim-statuses';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claims.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class ClaimsComponent implements OnInit {
|
||||
isLoading$ = this.claimService.isLoading$;
|
||||
claims$ = this.claimService.claims$;
|
||||
hasMore$ = this.claimService.hasMore$;
|
||||
|
||||
constructor(private claimService: ClaimsService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.search({ statuses: [ClaimStatus.pending] });
|
||||
}
|
||||
|
||||
search(searchFormValue: SearchFormValue) {
|
||||
this.claimService.search(searchFormValue);
|
||||
}
|
||||
|
||||
fetchMore() {
|
||||
this.claimService.fetchMore();
|
||||
}
|
||||
}
|
@ -18,18 +18,20 @@ import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { CdkTableModule } from '@angular/cdk/table';
|
||||
|
||||
import { ClaimsComponent } from './claims.component';
|
||||
import { ClaimsRoutingModule } from './claims-routing.module';
|
||||
import { PapiModule } from '../papi/papi.module';
|
||||
import { PapiModule } from '../../papi/papi.module';
|
||||
import { SearchFormComponent } from './search-form/search-form.component';
|
||||
import { ClaimsTableComponent } from './claims-table/claims-table.component';
|
||||
import { ClaimActionsComponent } from './claim-actions/claim-actions.component';
|
||||
import { CreateClaimComponent } from './create-claim/create-claim.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { ClaimsService } from './claims.service';
|
||||
import { ClaimManagementService } from '../../thrift/claim-management.service';
|
||||
import { ClaimsRoutingModule } from './claims-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
ClaimsRoutingModule,
|
||||
CommonModule,
|
||||
FlexLayoutModule,
|
||||
PapiModule,
|
||||
ReactiveFormsModule,
|
||||
@ -54,6 +56,7 @@ import { SharedModule } from '../shared/shared.module';
|
||||
ClaimActionsComponent,
|
||||
CreateClaimComponent
|
||||
],
|
||||
entryComponents: [CreateClaimComponent]
|
||||
entryComponents: [CreateClaimComponent],
|
||||
providers: [ClaimsService, ClaimManagementService]
|
||||
})
|
||||
export class ClaimsModule {}
|
53
src/app/claim-mgt/claims/claims.service.ts
Normal file
53
src/app/claim-mgt/claims/claims.service.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { Observable } from 'rxjs';
|
||||
import { catchError, map, shareReplay } from 'rxjs/operators';
|
||||
import { FetchResult, PartialFetcher } from '@rbkmoney/partial-fetcher';
|
||||
|
||||
import { ClaimManagementService } from '../../thrift/claim-management.service';
|
||||
import { SearchFormValue } from './search-form/search-form-value';
|
||||
import { booleanDebounceTime } from '../../shared/operators';
|
||||
import { convertFormValueToParams } from './convert-form-value-to-params';
|
||||
import { Claim } from '../../gen-damsel/claim_management';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimsService extends PartialFetcher<Claim, SearchFormValue> {
|
||||
private readonly searchLimit = 20;
|
||||
|
||||
claims$: Observable<Claim> = this.searchResult$.pipe(
|
||||
catchError(() => {
|
||||
this.snackBar.open('An error occurred while processing your search', 'OK');
|
||||
return [];
|
||||
})
|
||||
);
|
||||
|
||||
isLoading$: Observable<boolean> = this.doAction$.pipe(
|
||||
booleanDebounceTime(),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
constructor(
|
||||
private claimManagementService: ClaimManagementService,
|
||||
private snackBar: MatSnackBar
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected fetch(
|
||||
searchFormValue: SearchFormValue,
|
||||
continuationToken: string
|
||||
): Observable<FetchResult<Claim>> {
|
||||
return this.claimManagementService
|
||||
.searchClaims({
|
||||
...convertFormValueToParams(searchFormValue),
|
||||
continuation_token: continuationToken,
|
||||
limit: this.searchLimit
|
||||
})
|
||||
.pipe(
|
||||
map(r => ({
|
||||
result: r.result,
|
||||
continuationToken: r.continuation_token
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
19
src/app/claim-mgt/claims/convert-form-value-to-params.ts
Normal file
19
src/app/claim-mgt/claims/convert-form-value-to-params.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { SearchFormValue } from './search-form/search-form-value';
|
||||
|
||||
export const convertFormValueToParams = (params: SearchFormValue) => {
|
||||
const result = {};
|
||||
for (const k in params) {
|
||||
if (params.hasOwnProperty(k)) {
|
||||
if (k === 'statuses') {
|
||||
result[k] = (params[k] as string[]).reduce((acc, cv) => [...acc, { [cv]: {} }], []);
|
||||
} else {
|
||||
const v = params[k].trim();
|
||||
if (v === '') {
|
||||
break;
|
||||
}
|
||||
result[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialogRef } from '@angular/material';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ClaimActionType } from '../../claim/claim-action-type';
|
||||
import { ClaimActionType } from '../../../claim/claim-action-type';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'create-claim.component.html'
|
1
src/app/claim-mgt/claims/index.ts
Normal file
1
src/app/claim-mgt/claims/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './claims.module';
|
@ -0,0 +1,7 @@
|
||||
import * as domain from '../../../gen-damsel/domain';
|
||||
import { ClaimStatus } from '../../../papi/model/claim-statuses';
|
||||
|
||||
export interface SearchFormValue {
|
||||
party_id?: domain.PartyID;
|
||||
statuses?: ClaimStatus[];
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
<form fxLayout="row" fxLayout.xs="column" fxLayoutGap="20px" [formGroup]="form">
|
||||
<mat-form-field fxFlex="15" fxFlex.sm="30">
|
||||
<mat-select placeholder="Claim status" formControlName="claimStatus">
|
||||
<mat-option [value]="null">any</mat-option>
|
||||
<mat-select placeholder="Claim status" formControlName="statuses" multiple>
|
||||
<mat-option *ngFor="let status of claimStatuses" [value]="status">{{
|
||||
status
|
||||
}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="30" fxFlex.sm="70">
|
||||
<input matInput placeholder="Party ID" formControlName="partyId" />
|
||||
<input matInput placeholder="Party ID" formControlName="party_id" />
|
||||
</mat-form-field>
|
||||
</form>
|
@ -2,8 +2,8 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { SearchFormService } from './search-form.service';
|
||||
import { ClaimSearchParams } from '../../papi/params';
|
||||
import { debounceTime } from 'rxjs/internal/operators';
|
||||
import { SearchFormValue } from './search-form-value';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-search-form',
|
||||
@ -12,7 +12,7 @@ import { debounceTime } from 'rxjs/internal/operators';
|
||||
})
|
||||
export class SearchFormComponent implements OnInit {
|
||||
@Output()
|
||||
valueChanges: EventEmitter<ClaimSearchParams> = new EventEmitter();
|
||||
valueChanges: EventEmitter<SearchFormValue> = new EventEmitter();
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
@ -21,11 +21,11 @@ export class SearchFormComponent implements OnInit {
|
||||
constructor(private searchFormService: SearchFormService) {}
|
||||
|
||||
ngOnInit() {
|
||||
const { claimStatuses, form, formValueToSearchParams } = this.searchFormService;
|
||||
const { form, claimStatuses } = this.searchFormService;
|
||||
this.claimStatuses = claimStatuses;
|
||||
this.form = form;
|
||||
this.form.valueChanges
|
||||
.pipe(debounceTime(300))
|
||||
.subscribe(value => this.valueChanges.emit(formValueToSearchParams(value)));
|
||||
this.form.valueChanges.pipe(debounceTime(300)).subscribe(value => {
|
||||
this.valueChanges.emit(value);
|
||||
});
|
||||
}
|
||||
}
|
24
src/app/claim-mgt/claims/search-form/search-form.service.ts
Normal file
24
src/app/claim-mgt/claims/search-form/search-form.service.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import values from 'lodash-es/values';
|
||||
import { ClaimStatus } from '../../../papi/model/claim-statuses';
|
||||
|
||||
@Injectable()
|
||||
export class SearchFormService {
|
||||
form: FormGroup;
|
||||
|
||||
claimStatuses: string[];
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
this.claimStatuses = values(ClaimStatus);
|
||||
this.form.patchValue({ statuses: [ClaimStatus.pending] });
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
statuses: '',
|
||||
party_id: ''
|
||||
});
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { ClaimInfoDetailsComponent } from './claim-info-details.component';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('ClaimInfoDetailsComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
|
@ -1,39 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
|
||||
import { ClaimService } from '../papi/claim.service';
|
||||
import { ClaimSearchParams } from '../papi/params';
|
||||
import { ClaimInfo } from '../papi/model';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'claims.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class ClaimsComponent implements OnInit {
|
||||
isLoading = false;
|
||||
|
||||
claims: ClaimInfo[];
|
||||
|
||||
constructor(private claimService: ClaimService, private snackBar: MatSnackBar) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.search({ claimStatus: 'pending' });
|
||||
}
|
||||
|
||||
search(params: ClaimSearchParams) {
|
||||
this.isLoading = true;
|
||||
this.claimService.getClaims(params).subscribe(
|
||||
claims => {
|
||||
this.isLoading = false;
|
||||
this.claims = claims.reverse();
|
||||
},
|
||||
(error: HttpErrorResponse) => {
|
||||
this.isLoading = false;
|
||||
this.snackBar.open(`${error.status}: ${error.message}`, 'OK', {
|
||||
duration: 1500
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import values from 'lodash-es/values';
|
||||
import mapValues from 'lodash-es/mapValues';
|
||||
import isString from 'lodash-es/isString';
|
||||
|
||||
import { ClaimStatus } from '../../papi/model/claim-statuses';
|
||||
import { ClaimSearchParams } from '../../papi/params';
|
||||
|
||||
@Injectable()
|
||||
export class SearchFormService {
|
||||
form: FormGroup;
|
||||
|
||||
claimStatuses: string[];
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.form = this.prepareForm();
|
||||
this.claimStatuses = values(ClaimStatus);
|
||||
}
|
||||
|
||||
formValueToSearchParams(formValue): ClaimSearchParams {
|
||||
return mapValues(formValue, value => {
|
||||
let result = value;
|
||||
if (value === '') {
|
||||
result = null;
|
||||
} else if (isString(value)) {
|
||||
result = value.trim();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private prepareForm(): FormGroup {
|
||||
return this.fb.group({
|
||||
claimStatus: 'pending',
|
||||
partyId: ''
|
||||
});
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { DomainPair } from './domain-group/domain-group';
|
||||
import { DomainPair } from './domain-group';
|
||||
|
||||
@Injectable()
|
||||
export class DomainDetailsService {
|
||||
|
@ -2,12 +2,12 @@ import { Component, OnInit, Input, OnChanges, SimpleChanges, ViewChild } from '@
|
||||
import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';
|
||||
|
||||
import { DomainGroup } from '../domain-group';
|
||||
import { DomainDetailsService } from '../../../domain-info/domain-details.service';
|
||||
import { DomainDetailsService } from '../../domain-details.service';
|
||||
import { toTableGroup, toDataSource } from './table-group';
|
||||
import { sortData } from './sort-table-data';
|
||||
import { filterPredicate } from './filter-predicate';
|
||||
import { TableDataSource, TableGroup } from './model';
|
||||
import { DetailsContainerService } from '../../../domain-info/details-container.service';
|
||||
import { DetailsContainerService } from '../../details-container.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-group-table',
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { parse } from '../../jsonc/json-parser';
|
||||
import {
|
||||
CodeLensProvider,
|
||||
ITextModel,
|
||||
CancellationToken,
|
||||
ICodeLensSymbol,
|
||||
ProviderResult
|
||||
} from '../../monaco-editor/model';
|
||||
} from '../../monaco-editor';
|
||||
|
||||
export class DomainObjCodeLensProvider implements CodeLensProvider {
|
||||
get language() {
|
||||
|
@ -3,7 +3,7 @@ import { MatSnackBar, MatDialog } from '@angular/material';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { MonacoFile, CodeLensProvider, CompletionProvider } from '../../monaco-editor/model';
|
||||
import { MonacoFile, CodeLensProvider, CompletionProvider } from '../../monaco-editor';
|
||||
import { DomainObjModificationService } from './domain-obj-modification.service';
|
||||
import { DomainObjCodeLensProvider } from './domain-obj-code-lens-provider';
|
||||
import { DomainObjCompletionProvider } from './domain-obj-completion-provider';
|
||||
|
@ -11,7 +11,7 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { DomainObjModificationComponent } from './domain-obj-modification.component';
|
||||
import { MonacoEditorModule } from '../../monaco-editor/monaco-editor.module';
|
||||
import { MonacoEditorModule } from '../../monaco-editor';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { ResetConfirmDialogComponent } from './reset-confirm-dialog/reset-confirm-dialog.component';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { Router } from '@angular/router';
|
||||
import { MatCheckboxChange, MatSnackBar } from '@angular/material';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { MonacoFile, IDiffEditorOptions } from '../../monaco-editor/model';
|
||||
import { MonacoFile, IDiffEditorOptions } from '../../monaco-editor';
|
||||
import { toMonacoFile } from '../utils';
|
||||
import { DomainModificationModel } from '../domain-modification-model';
|
||||
import { DomainObjReviewService } from './domain-obj-review.service';
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from '@angular/material';
|
||||
|
||||
import { DomainObjReviewComponent } from './domain-obj-review.component';
|
||||
import { MonacoEditorModule } from '../../monaco-editor/monaco-editor.module';
|
||||
import { MonacoEditorModule } from '../../monaco-editor';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
|
||||
@NgModule({
|
||||
|
@ -4,7 +4,7 @@ import { DomainRoutingModule } from './domain-routing.module';
|
||||
import { DomainService } from './domain.service';
|
||||
import { MetadataService } from './metadata.service';
|
||||
import { DomainObjModificationModule } from './domain-obj-modification';
|
||||
import { DomainInfoModule } from './domain-info/domain-info.module';
|
||||
import { DomainInfoModule } from './domain-info';
|
||||
import { DamselMetaModule } from '../damsel-meta/damsel-meta.module';
|
||||
import { DomainObjReviewModule } from './domain-obj-review';
|
||||
import { DomainReviewService } from './domain-review.service';
|
||||
|
@ -5,11 +5,12 @@ import { DepositParams } from './gen-model/fistful';
|
||||
import { DepositParams as DepositParamsObject } from './gen-nodejs/fistful_types';
|
||||
import { ThriftService } from '../thrift';
|
||||
import * as FistfulAdmin from './gen-nodejs/FistfulAdmin';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class FistfulAdminService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/v1/admin', FistfulAdmin);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/admin', FistfulAdmin);
|
||||
}
|
||||
|
||||
createDeposit(params: DepositParams): Observable<void> {
|
||||
|
@ -5,11 +5,12 @@ import { ThriftService } from '../thrift';
|
||||
import { RepairScenario, SessionID } from './gen-model/withdrawal_session';
|
||||
import { RepairScenario as RepairScenarioObject } from './gen-nodejs/withdrawal_session_types';
|
||||
import * as Repairer from './gen-nodejs/Repairer';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class RepairerService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/v1/repair/withdrawal/session', Repairer);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/repair/withdrawal/session', Repairer);
|
||||
}
|
||||
|
||||
repair = (id: SessionID, scenario: RepairScenario): Observable<void> =>
|
||||
|
@ -9,11 +9,12 @@ import {
|
||||
import { ThriftService } from '../thrift';
|
||||
import { Namespace } from './gen-model/base';
|
||||
import { Reference, MachineDescriptor, Machine } from './gen-model/state_processing';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class AutomatonService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/v1/automaton', Automaton);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/automaton', Automaton);
|
||||
}
|
||||
|
||||
simpleRepair = (ns: Namespace, ref: Reference): Observable<void> =>
|
||||
|
@ -6,7 +6,8 @@ import { map } from 'rxjs/operators';
|
||||
import { ClaimCreated, ClaimInfo, PartyModificationUnit } from './model';
|
||||
import { ConfigService } from '../core/config.service';
|
||||
import { decode, encode } from '../shared/java-thrift-formatter';
|
||||
import { ClaimAcceptParams, ClaimDenyParams, ClaimSearchParams } from './params';
|
||||
import { ClaimAcceptParams, ClaimDenyParams } from './params';
|
||||
import { ClaimSearchQuery } from '../gen-damsel/claim_management';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimService {
|
||||
@ -16,7 +17,7 @@ export class ClaimService {
|
||||
this.papiEndpoint = configService.config.papiEndpoint;
|
||||
}
|
||||
|
||||
getClaims(params: ClaimSearchParams): Observable<ClaimInfo[]> {
|
||||
getClaims(params: ClaimSearchQuery): Observable<ClaimInfo[]> {
|
||||
return this.http.post<ClaimInfo[]>(`${this.papiEndpoint}/walk/claim/search`, params);
|
||||
}
|
||||
|
||||
|
@ -2,5 +2,7 @@ export enum ClaimStatus {
|
||||
accepted = 'accepted',
|
||||
denied = 'denied',
|
||||
revoked = 'revoked',
|
||||
pending = 'pending'
|
||||
pending = 'pending',
|
||||
review = 'review',
|
||||
pending_acceptance = 'pending_acceptance'
|
||||
}
|
||||
|
14
src/app/shared/extract-claim-status.ts
Normal file
14
src/app/shared/extract-claim-status.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ClaimStatus as UnionClaimStatus } from '../gen-damsel/claim_management';
|
||||
import { ClaimStatus } from '../papi/model/claim-statuses';
|
||||
|
||||
export const claimStatusByUnionClaimStatus: { [name in keyof UnionClaimStatus]-?: ClaimStatus } = {
|
||||
accepted: ClaimStatus.accepted,
|
||||
denied: ClaimStatus.denied,
|
||||
revoked: ClaimStatus.revoked,
|
||||
pending: ClaimStatus.pending,
|
||||
review: ClaimStatus.review,
|
||||
pending_acceptance: ClaimStatus.pending_acceptance
|
||||
};
|
||||
|
||||
export const extractClaimStatus = (status: UnionClaimStatus): ClaimStatus =>
|
||||
claimStatusByUnionClaimStatus[Object.keys(status)[0] as keyof UnionClaimStatus];
|
11
src/app/shared/operators/boolean-debounce-time.ts
Normal file
11
src/app/shared/operators/boolean-debounce-time.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { distinctUntilChanged, debounce } from 'rxjs/operators';
|
||||
import { timer, empty, Observable } from 'rxjs';
|
||||
|
||||
export const booleanDebounceTime = (timeoutMs: number = 500) => (
|
||||
s: Observable<boolean>
|
||||
): Observable<boolean> =>
|
||||
s.pipe(
|
||||
distinctUntilChanged(),
|
||||
debounce(v => (v ? timer(timeoutMs) : empty())),
|
||||
distinctUntilChanged()
|
||||
);
|
1
src/app/shared/operators/index.ts
Normal file
1
src/app/shared/operators/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './boolean-debounce-time';
|
18
src/app/thrift/claim-management.service.ts
Normal file
18
src/app/thrift/claim-management.service.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { ThriftService } from '../thrift';
|
||||
import * as ClaimManagement from './gen-nodejs/ClaimManagement';
|
||||
import { ClaimSearchQuery, ClaimSearchResponse } from '../gen-damsel/claim_management';
|
||||
import { ClaimSearchQuery as ClaimSearchQueryType } from './gen-nodejs/claim_management_types';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class ClaimManagementService extends ThriftService {
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/cm', ClaimManagement);
|
||||
}
|
||||
|
||||
searchClaims = (query: ClaimSearchQuery): Observable<ClaimSearchResponse> =>
|
||||
this.toObservableAction('SearchClaims')(new ClaimSearchQueryType(query));
|
||||
}
|
@ -4,11 +4,12 @@ import { Observable } from 'rxjs';
|
||||
import * as Repository from './gen-nodejs/Repository';
|
||||
import { ThriftService } from './thrift-service';
|
||||
import { Reference, Snapshot, Commit, Version, Limit } from '../gen-damsel/domain_config';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class DomainService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/v1/domain/repository', Repository);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/domain/repository', Repository);
|
||||
}
|
||||
|
||||
checkout: (reference: Reference) => Observable<Snapshot> = this.toObservableAction('Checkout');
|
||||
|
@ -5,11 +5,12 @@ import * as MerchantStatistics from './gen-nodejs/MerchantStatistics';
|
||||
import { ThriftService } from './thrift-service';
|
||||
import { StatRequest, StatResponse } from '../gen-damsel/merch_stat';
|
||||
import { StatRequest as ThriftStatRequest } from './gen-nodejs/merch_stat_types';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class MerchantStatisticsService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/stat', MerchantStatistics);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/stat', MerchantStatistics);
|
||||
}
|
||||
|
||||
getPayments = (req: StatRequest): Observable<StatResponse> =>
|
||||
|
@ -2,12 +2,7 @@ import cloneDeep from 'lodash-es/cloneDeep';
|
||||
import last from 'lodash-es/last';
|
||||
import dropRight from 'lodash-es/dropRight';
|
||||
|
||||
import {
|
||||
ProviderObject,
|
||||
TerminalSelector,
|
||||
TerminalDecision,
|
||||
TerminalRef
|
||||
} from '../../gen-damsel/domain';
|
||||
import { ProviderObject, TerminalDecision, TerminalRef } from '../../gen-damsel/domain';
|
||||
import { toGenTerminalDecision } from '../converters';
|
||||
import { checkSelector } from './utils';
|
||||
|
||||
|
@ -16,11 +16,12 @@ import { ThriftService } from './thrift-service';
|
||||
import * as Invoicing from './gen-nodejs/Invoicing';
|
||||
import { InvoiceID } from '../gen-damsel/domain';
|
||||
import { share, switchMap, first } from 'rxjs/operators';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentProcessingService extends ThriftService {
|
||||
constructor(zone: NgZone) {
|
||||
super(zone, '/v1/processing/invoicing', Invoicing);
|
||||
constructor(zone: NgZone, keycloakService: KeycloakService) {
|
||||
super(zone, keycloakService, '/v1/processing/invoicing', Invoicing);
|
||||
}
|
||||
|
||||
getPaymentAdjustment = (
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { NgZone } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { timeout } from 'rxjs/operators';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { map, timeout } from 'rxjs/operators';
|
||||
import connectClient from 'woody_js';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import * as jwtDecode from 'jwt-decode';
|
||||
|
||||
type Exception<N = string, T = {}> = {
|
||||
name: N;
|
||||
@ -9,10 +11,17 @@ type Exception<N = string, T = {}> = {
|
||||
} & T;
|
||||
|
||||
export class ThriftService {
|
||||
protected realm = 'internal';
|
||||
|
||||
protected endpoint: string;
|
||||
protected service: any;
|
||||
|
||||
constructor(private zone: NgZone, endpoint: string, thriftService: any) {
|
||||
constructor(
|
||||
private zone: NgZone,
|
||||
private keycloakService: KeycloakService,
|
||||
endpoint: string,
|
||||
thriftService: any
|
||||
) {
|
||||
this.endpoint = endpoint;
|
||||
this.service = thriftService;
|
||||
}
|
||||
@ -20,30 +29,49 @@ export class ThriftService {
|
||||
protected toObservableAction<T extends (...A: any[]) => Observable<any>>(name: string): T {
|
||||
return ((...args) =>
|
||||
Observable.create(observer => {
|
||||
this.zone.run(() => {
|
||||
try {
|
||||
this.createClient(msg => {
|
||||
const cb = msg => {
|
||||
observer.error(msg);
|
||||
observer.complete();
|
||||
})[name](...args, (ex: Exception, result) => {
|
||||
};
|
||||
this.zone.run(() => {
|
||||
try {
|
||||
this.createClient(cb).subscribe(client =>
|
||||
client[name](...args, (ex: Exception, result) => {
|
||||
ex ? observer.error(ex) : observer.next(result);
|
||||
observer.complete();
|
||||
});
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
observer.error(e);
|
||||
observer.complete();
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}).pipe(timeout(60000))) as any;
|
||||
}
|
||||
|
||||
private createClient(errorCb: Function) {
|
||||
private createClient(errorCb: Function): Observable<any> {
|
||||
return from(this.keycloakService.getToken()).pipe(
|
||||
map(token => {
|
||||
const { email, preferred_username, sub } = jwtDecode(token);
|
||||
return connectClient(
|
||||
location.hostname,
|
||||
location.port,
|
||||
this.endpoint,
|
||||
this.service,
|
||||
{
|
||||
headers: {
|
||||
'woody.meta-user-identity.email': email,
|
||||
'woody.meta-user-identity.realm': 'external',
|
||||
'woody.meta-user-identity.username': preferred_username,
|
||||
'woody.meta-user-identity.id': sub,
|
||||
'x-rbk-meta-user-identity.email': email,
|
||||
'x-rbk-meta-user-identity.realm': 'external',
|
||||
'x-rbk-meta-user-identity.username': preferred_username,
|
||||
'x-rbk-meta-user-identity.id': sub
|
||||
}
|
||||
},
|
||||
errorCb
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { PaymentProcessingService } from './payment-processing.service';
|
||||
import { MerchantStatisticsService } from './merchant-statistics.service';
|
||||
import { DomainTypedManager } from './domain-typed-manager';
|
||||
import { DomainCacheService } from './domain-cache.service';
|
||||
import { ClaimManagementService } from './claim-management.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
@ -12,7 +13,8 @@ import { DomainCacheService } from './domain-cache.service';
|
||||
DomainTypedManager,
|
||||
PaymentProcessingService,
|
||||
MerchantStatisticsService,
|
||||
DomainCacheService
|
||||
DomainCacheService,
|
||||
ClaimManagementService
|
||||
]
|
||||
})
|
||||
export class ThriftModule {}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"module": "es2015",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
|
Loading…
Reference in New Issue
Block a user