mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 10:35:18 +00:00
Epic: New shop details page (#216)
This commit is contained in:
parent
884061fa13
commit
d7f6a8e536
@ -1 +1 @@
|
|||||||
Subproject commit ccf618949b95590d572157b248289428abeaa2e5
|
Subproject commit e1318727d4d0c3e48f5122bf3197158b6695f50e
|
@ -26,7 +26,6 @@ import { DepositsModule } from './deposits/deposits.module';
|
|||||||
import { DomainModule } from './domain';
|
import { DomainModule } from './domain';
|
||||||
import icons from './icons.json';
|
import icons from './icons.json';
|
||||||
import { NotFoundModule } from './not-found';
|
import { NotFoundModule } from './not-found';
|
||||||
import { PartyModule as OldPartyModule } from './party/party.module';
|
|
||||||
import { PaymentAdjustmentModule } from './payment-adjustment/payment-adjustment.module';
|
import { PaymentAdjustmentModule } from './payment-adjustment/payment-adjustment.module';
|
||||||
import { PayoutsModule } from './payouts/payouts.module';
|
import { PayoutsModule } from './payouts/payouts.module';
|
||||||
import { RepairingModule } from './repairing/repairing.module';
|
import { RepairingModule } from './repairing/repairing.module';
|
||||||
@ -69,7 +68,6 @@ moment.locale('en');
|
|||||||
ClaimMgtModule,
|
ClaimMgtModule,
|
||||||
PartyModule,
|
PartyModule,
|
||||||
SearchPartiesModule,
|
SearchPartiesModule,
|
||||||
OldPartyModule,
|
|
||||||
SearchClaimsModule,
|
SearchClaimsModule,
|
||||||
OperationsModule,
|
OperationsModule,
|
||||||
// It is important that NotFoundModule module should be last
|
// It is important that NotFoundModule module should be last
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
import { ConfigService } from '../core/config.service';
|
import { ConfigService } from '../core/config.service';
|
||||||
import { Category } from './model';
|
import { Category } from './model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CategoryService {
|
export class CategoryService {
|
||||||
private readonly papiEndpoint: string;
|
categories$ = this.http.get<Category[]>(
|
||||||
|
`${this.configService.config.papiEndpoint}/dmt/categories`
|
||||||
|
);
|
||||||
|
|
||||||
constructor(private http: HttpClient, configService: ConfigService) {
|
constructor(private http: HttpClient, private configService: ConfigService) {}
|
||||||
this.papiEndpoint = configService.config.papiEndpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCategories(): Observable<Category[]> {
|
|
||||||
return this.http.get<Category[]>(`${this.papiEndpoint}/dmt/categories`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map, shareReplay } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
import { decode } from '@cc/utils/java-thrift-formatter';
|
import { decode } from '@cc/utils/java-thrift-formatter';
|
||||||
|
|
||||||
import { ConfigService } from '../core/config.service';
|
import { ConfigService } from '../core/config.service';
|
||||||
import { Party, PartyID } from '../thrift-services/damsel/gen-model/domain';
|
import { Party, Shop } from '../thrift-services/damsel/gen-model/domain';
|
||||||
|
import { ContractTemplate } from './model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PartyService {
|
export class PartyService {
|
||||||
@ -16,9 +17,15 @@ export class PartyService {
|
|||||||
this.papiEndpoint = configService.config.papiEndpoint;
|
this.papiEndpoint = configService.config.papiEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
getParty = (partyID: PartyID): Observable<Party> =>
|
getParty(partyId: string): Observable<Party> {
|
||||||
this.http.get<Party>(`${this.papiEndpoint}/parties/${partyID}`).pipe(
|
return this.http
|
||||||
map((party) => decode(party)),
|
.get<ContractTemplate[]>(`${this.papiEndpoint}/parties/${partyId}`)
|
||||||
shareReplay(1)
|
.pipe(map((party) => decode(party)));
|
||||||
);
|
}
|
||||||
|
|
||||||
|
getShops = (partyID: string): Observable<Shop[]> =>
|
||||||
|
this.getParty(partyID).pipe(map((party) => Array.from(party.shops.values())));
|
||||||
|
|
||||||
|
getShop = (partyID: string, shopID: string): Observable<Shop> =>
|
||||||
|
this.getShops(partyID).pipe(map((shops) => shops.find((shop) => shop.id === shopID)));
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<cc-card-container>
|
|
||||||
<mat-spinner *ngIf="isLoading" fxFlexAlign="center"></mat-spinner>
|
|
||||||
<div *ngIf="!isLoading" fxLayout="column" fxLayoutGap="20px">
|
|
||||||
<mat-card>
|
|
||||||
<mat-card-subtitle> Party details </mat-card-subtitle>
|
|
||||||
<mat-card-content> <cc-party-info [party]="party"></cc-party-info> </mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
<mat-card>
|
|
||||||
<mat-card-subtitle> Party shops </mat-card-subtitle>
|
|
||||||
<mat-card-content> <cc-shops-table [shops]="shops"></cc-shops-table> </mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
</div>
|
|
||||||
</cc-card-container>
|
|
@ -1,36 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { ActivatedRoute } from '@angular/router';
|
|
||||||
import { combineLatest } from 'rxjs';
|
|
||||||
|
|
||||||
import { Party, Shop } from '../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { PartyService } from '../party.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: 'party-details.component.html',
|
|
||||||
styleUrls: [],
|
|
||||||
})
|
|
||||||
export class PartyDetailsComponent implements OnInit {
|
|
||||||
party: Party;
|
|
||||||
shops: Shop[];
|
|
||||||
isLoading = false;
|
|
||||||
|
|
||||||
private partyID: string;
|
|
||||||
|
|
||||||
constructor(private partyService: PartyService, private route: ActivatedRoute) {
|
|
||||||
this.route.params.subscribe((params) => {
|
|
||||||
this.partyID = params.partyID;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.isLoading = true;
|
|
||||||
combineLatest([
|
|
||||||
this.partyService.getParty(this.partyID),
|
|
||||||
this.partyService.getShops(this.partyID),
|
|
||||||
]).subscribe(([party, shops]) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.party = party;
|
|
||||||
this.shops = shops;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatCardModule } from '@angular/material/card';
|
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
||||||
import { MatInputModule } from '@angular/material/input';
|
|
||||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
||||||
import { MatTableModule } from '@angular/material/table';
|
|
||||||
|
|
||||||
import { CardContainerModule } from '@cc/components/card-container/card-container.module';
|
|
||||||
|
|
||||||
import { PartyDetailsComponent } from './party-details.component';
|
|
||||||
import { PartyInfoComponent } from './party-info/party-info.component';
|
|
||||||
import { ShopsTableComponent } from './shops-table/shops-table.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
FlexLayoutModule,
|
|
||||||
MatProgressSpinnerModule,
|
|
||||||
MatCardModule,
|
|
||||||
MatButtonModule,
|
|
||||||
MatTableModule,
|
|
||||||
MatPaginatorModule,
|
|
||||||
MatFormFieldModule,
|
|
||||||
MatInputModule,
|
|
||||||
CardContainerModule,
|
|
||||||
],
|
|
||||||
declarations: [PartyDetailsComponent, ShopsTableComponent, PartyInfoComponent],
|
|
||||||
})
|
|
||||||
export class PartyDetailsModule {}
|
|
@ -1,16 +0,0 @@
|
|||||||
<div fxLayout="row" fxLayoutGap="10px" fxLayout.sm="column" fxLayout.xs="column">
|
|
||||||
<div fxFlex="50" fxLayout="column" fxLayoutGap="10px">
|
|
||||||
<div fxLayout="row" fxLayout.xs="column">
|
|
||||||
<label fxFlex="20">Party ID:</label>
|
|
||||||
<div>{{ party?.id }}</div>
|
|
||||||
</div>
|
|
||||||
<div fxLayout="row" fxLayout.xs="column">
|
|
||||||
<label fxFlex="20">Created At:</label>
|
|
||||||
<div>{{ party?.created_at | date: 'dd.MM.yyyy HH:mm:ss' }}</div>
|
|
||||||
</div>
|
|
||||||
<div fxLayout="row" fxLayout.xs="column">
|
|
||||||
<label fxFlex="20">Revision:</label>
|
|
||||||
<div>{{ party?.revision }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
import { Party } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-party-info',
|
|
||||||
templateUrl: 'party-info.component.html',
|
|
||||||
})
|
|
||||||
export class PartyInfoComponent {
|
|
||||||
@Input() party: Party;
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
<div fxLayout fxLayoutAlign="space-between">
|
|
||||||
<mat-form-field fxFlex="35">
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
type="text"
|
|
||||||
(keyup)="applyFilter($event.target.value)"
|
|
||||||
placeholder="Filter"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<table mat-table [dataSource]="dataSource">
|
|
||||||
<ng-container matColumnDef="id">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>ID</th>
|
|
||||||
<td mat-cell *matCellDef="let shop">{{ shop.id }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="name">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Name</th>
|
|
||||||
<td mat-cell *matCellDef="let shop">{{ shop.details.name }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="url">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Url</th>
|
|
||||||
<td mat-cell *matCellDef="let shop">{{ shop.location.url }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="shopDetailButton">
|
|
||||||
<th mat-header-cell *matHeaderCellDef class="action-cell"></th>
|
|
||||||
<td mat-cell *matCellDef="let shop" class="action-cell">
|
|
||||||
<button mat-stroked-button (click)="navigateToShop(shop.id)">Details</button>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let shop; columns: displayedColumns"></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<mat-paginator [pageSizeOptions]="[10, 20, 50, 100, 250, 500]" showFirstLastButtons></mat-paginator>
|
|
@ -1,7 +0,0 @@
|
|||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-cell {
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
|
|
||||||
import { MatPaginator } from '@angular/material/paginator';
|
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
|
|
||||||
import { Shop } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-shops-table',
|
|
||||||
templateUrl: 'shops-table.component.html',
|
|
||||||
styleUrls: ['shops-table.component.scss'],
|
|
||||||
})
|
|
||||||
export class ShopsTableComponent implements OnChanges {
|
|
||||||
@Input() shops: Shop[];
|
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
|
||||||
|
|
||||||
dataSource: MatTableDataSource<Shop> = new MatTableDataSource();
|
|
||||||
displayedColumns = ['id', 'name', 'url', 'shopDetailButton'];
|
|
||||||
|
|
||||||
private partyId: string;
|
|
||||||
|
|
||||||
constructor(private router: Router, private route: ActivatedRoute) {
|
|
||||||
this.route.params.subscribe((params) => {
|
|
||||||
this.partyId = params.partyID;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges({ shops }: SimpleChanges) {
|
|
||||||
if (shops.currentValue) {
|
|
||||||
this.dataSource.data = shops.currentValue;
|
|
||||||
this.dataSource.filterPredicate = (shop: Shop, filter: string) =>
|
|
||||||
JSON.stringify(shop).toLowerCase().includes(filter);
|
|
||||||
this.dataSource.paginator = this.paginator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyFilter(filterValue: string) {
|
|
||||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
navigateToShop(shopID: string) {
|
|
||||||
this.router.navigate([`/party-old/${this.partyId}/shop/${shopID}`]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
|
|
||||||
import { AppAuthGuardService, PartyRole } from '@cc/app/shared/services';
|
|
||||||
|
|
||||||
import { PartyDetailsComponent } from './party-details/party-details.component';
|
|
||||||
import { ShopDetailsComponent } from './shop-details/shop-details.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
RouterModule.forChild([
|
|
||||||
{
|
|
||||||
path: 'party-old/:partyID',
|
|
||||||
component: PartyDetailsComponent,
|
|
||||||
canActivate: [AppAuthGuardService],
|
|
||||||
data: {
|
|
||||||
roles: [PartyRole.Get],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'party-old/:partyID/shop/:shopID',
|
|
||||||
component: ShopDetailsComponent,
|
|
||||||
canActivate: [AppAuthGuardService],
|
|
||||||
data: {
|
|
||||||
roles: [PartyRole.Get],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
exports: [RouterModule],
|
|
||||||
})
|
|
||||||
export class PartyRoutingModule {}
|
|
@ -1,3 +0,0 @@
|
|||||||
.card-container {
|
|
||||||
min-height: 120px;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
|
||||||
|
|
||||||
import { PartyDetailsModule } from './party-details/party-details.module';
|
|
||||||
import { PartyRoutingModule } from './party-routing.module';
|
|
||||||
import { PartyService } from './party.service';
|
|
||||||
import { ShopDetailsModule } from './shop-details/shop-details.module';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
PartyRoutingModule,
|
|
||||||
CommonModule,
|
|
||||||
FlexLayoutModule,
|
|
||||||
PartyDetailsModule,
|
|
||||||
ShopDetailsModule,
|
|
||||||
],
|
|
||||||
providers: [PartyService],
|
|
||||||
})
|
|
||||||
export class PartyModule {}
|
|
@ -1,64 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { map, tap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { PartyService as PapiPartyService } from '../papi/party.service';
|
|
||||||
import { Contract, Party, PayoutTool, Shop } from '../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class PartyService {
|
|
||||||
private party: Party;
|
|
||||||
|
|
||||||
constructor(private papiPartyService: PapiPartyService) {}
|
|
||||||
|
|
||||||
getParty(partyID: string): Observable<Party> {
|
|
||||||
if (this.party && this.party.id === partyID) {
|
|
||||||
return new Observable<Party>((observer) => {
|
|
||||||
observer.next(this.party);
|
|
||||||
observer.complete();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return this.papiPartyService.getParty(partyID).pipe(
|
|
||||||
tap((party) => {
|
|
||||||
this.party = party;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getShops(partyID: string): Observable<Shop[]> {
|
|
||||||
return this.getParty(partyID).pipe(map((party) => Array.from(party.shops.values())));
|
|
||||||
}
|
|
||||||
|
|
||||||
getShop(partyID: string, shopID: string): Observable<Shop> {
|
|
||||||
return this.getShops(partyID).pipe(
|
|
||||||
map((shops) => shops.find((shop) => shop.id === shopID))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getContracts(partyID: string): Observable<Contract[]> {
|
|
||||||
return this.getParty(partyID).pipe(map((party) => Array.from(party.contracts.values())));
|
|
||||||
}
|
|
||||||
|
|
||||||
getContract(partyID: string, contractID: string): Observable<Contract> {
|
|
||||||
return this.getContracts(partyID).pipe(
|
|
||||||
map((contracts) => contracts.find((contract) => contract.id === contractID))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getPayoutTools(partyID: string, contractID: string): Observable<PayoutTool[]> {
|
|
||||||
return this.getContract(partyID, contractID).pipe(
|
|
||||||
map((contract) => Array.from(contract.payout_tools.values()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getPayoutTool(
|
|
||||||
partyID: string,
|
|
||||||
contractID: string,
|
|
||||||
payoutToolID: string
|
|
||||||
): Observable<PayoutTool> {
|
|
||||||
return this.getPayoutTools(partyID, contractID).pipe(
|
|
||||||
map((payoutTools) => payoutTools.find((payoutTool) => payoutTool.id === payoutToolID))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
import { ProviderObject, TerminalObject } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { AddProviderService } from './add-provider.service';
|
|
||||||
|
|
||||||
interface AddProviderData {
|
|
||||||
partyID: string;
|
|
||||||
shopID: string;
|
|
||||||
shopCategoryID: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: 'add-provider.component.html',
|
|
||||||
styleUrls: ['add-provider.component.scss'],
|
|
||||||
providers: [AddProviderService],
|
|
||||||
})
|
|
||||||
export class AddProviderComponent implements OnInit {
|
|
||||||
terminals$: Observable<TerminalObject[]>;
|
|
||||||
providers$: Observable<ProviderObject[]>;
|
|
||||||
isLoading = false;
|
|
||||||
terminalForm: FormGroup;
|
|
||||||
providerForm: FormGroup;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private dialogRef: MatDialogRef<AddProviderComponent>,
|
|
||||||
@Inject(MAT_DIALOG_DATA) public data: AddProviderData,
|
|
||||||
private snackBar: MatSnackBar,
|
|
||||||
private addProviderService: AddProviderService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.providerForm = this.addProviderService.providerForm;
|
|
||||||
this.terminalForm = this.addProviderService.terminalForm;
|
|
||||||
this.terminals$ = this.addProviderService.getTerminals();
|
|
||||||
this.providers$ = this.addProviderService.getProviders(this.data.shopCategoryID);
|
|
||||||
}
|
|
||||||
|
|
||||||
providerFormChanged(id: number) {
|
|
||||||
this.providerForm.setValue({ id });
|
|
||||||
}
|
|
||||||
|
|
||||||
terminalFormChanged(id: number) {
|
|
||||||
this.terminalForm.setValue({ id });
|
|
||||||
}
|
|
||||||
|
|
||||||
add() {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.addProviderService.addProvider(this.data.partyID, this.data.shopID).subscribe(
|
|
||||||
() => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open('Provider successfully added', 'OK', { duration: 3000 });
|
|
||||||
this.dialogRef.close(true);
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open('An error occurred while while adding provider', 'OK');
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import {
|
|
||||||
AddDecisionToProvider,
|
|
||||||
DomainTypedManager,
|
|
||||||
filterProvidersByTerminalSelector,
|
|
||||||
} from '../../../thrift-services';
|
|
||||||
import { DomainCacheService } from '../../../thrift-services/damsel/domain-cache.service';
|
|
||||||
import {
|
|
||||||
PartyID,
|
|
||||||
ProviderObject,
|
|
||||||
ShopID,
|
|
||||||
TerminalObject,
|
|
||||||
} from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { filterProvidersByCategoryId } from '../../../thrift-services/filters';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AddProviderService {
|
|
||||||
providerForm = this.prepareForm();
|
|
||||||
terminalForm = this.prepareForm();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private fb: FormBuilder,
|
|
||||||
private domainCacheService: DomainCacheService,
|
|
||||||
private dtm: DomainTypedManager
|
|
||||||
) {}
|
|
||||||
|
|
||||||
getTerminals(): Observable<TerminalObject[]> {
|
|
||||||
return this.domainCacheService.getObjects('terminal');
|
|
||||||
}
|
|
||||||
|
|
||||||
getProviders(categoryId: number): Observable<ProviderObject[]> {
|
|
||||||
return this.domainCacheService.getObjects('provider').pipe(
|
|
||||||
map((objects) => filterProvidersByTerminalSelector(objects, 'decisions')),
|
|
||||||
map((objects) => filterProvidersByCategoryId(objects, categoryId))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
addProvider(partyID: PartyID, shopID: ShopID) {
|
|
||||||
const params = {
|
|
||||||
partyID,
|
|
||||||
shopID,
|
|
||||||
terminalID: this.terminalForm.value.id,
|
|
||||||
providerID: this.providerForm.value.id,
|
|
||||||
} as AddDecisionToProvider;
|
|
||||||
return this.dtm.addProviderDecision(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private prepareForm(): FormGroup {
|
|
||||||
return this.fb.group({
|
|
||||||
id: ['', Validators.required],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
<form [formGroup]="form" class="terminal-form" fxLayout="column" fxLayoutGap="20px">
|
|
||||||
<div fxLayout="row" fxLayout.sm="column" fxLayout.xs="column">
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<input matInput placeholder="Terminal name" required formControlName="terminalName" />
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
placeholder="Terminal description"
|
|
||||||
required
|
|
||||||
formControlName="terminalDescription"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<div fxLayout="row" fxLayout.sm="column" fxLayout.xs="column" fxLayoutGap="10px">
|
|
||||||
<label fxFlex="25">Risk coverage:</label>
|
|
||||||
<mat-radio-group
|
|
||||||
fxFlex="50"
|
|
||||||
fxLayout
|
|
||||||
fxLayoutAlign="space-between center"
|
|
||||||
formControlName="riskCoverage"
|
|
||||||
>
|
|
||||||
<mat-radio-button *ngFor="let coverage of riskCoverages" fxFlex [value]="coverage.value"
|
|
||||||
>{{ coverage.name }}
|
|
||||||
</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
</div>
|
|
||||||
<div fxLayout="column" fxLayoutGap="10px" *ngIf="options">
|
|
||||||
<div>Options:</div>
|
|
||||||
<div formArrayName="options">
|
|
||||||
<div
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.sm="column"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
*ngFor="let option of options.controls; let i = index"
|
|
||||||
[formGroupName]="i"
|
|
||||||
>
|
|
||||||
<mat-form-field fxFlex="30">
|
|
||||||
<input matInput placeholder="Key" formControlName="key" required />
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<input matInput placeholder="Value" formControlName="value" required />
|
|
||||||
</mat-form-field>
|
|
||||||
<button mat-icon-button color="basic" fxFlex="40px" (click)="removeOption(i)">
|
|
||||||
<mat-icon>clear</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div fxLayout fxLayoutAlign="end center">
|
|
||||||
<button mat-icon-button color="basic" fxFlex="40px" (click)="addOption()">
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button mat-button (click)="save()" [disabled]="!form.valid || isLoading || saved">
|
|
||||||
{{ saved ? 'SAVED' : 'SAVE TERMINAL' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
@ -1,62 +0,0 @@
|
|||||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
|
|
||||||
import { CreateTerminalFormService } from './create-terminal-form.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-create-terminal-form',
|
|
||||||
templateUrl: 'create-terminal-form.component.html',
|
|
||||||
styleUrls: ['../../add-provider.component.scss'],
|
|
||||||
providers: [CreateTerminalFormService],
|
|
||||||
})
|
|
||||||
export class CreateTerminalFormComponent implements OnInit {
|
|
||||||
@Output() terminalIdSelected: EventEmitter<number> = new EventEmitter();
|
|
||||||
|
|
||||||
form: FormGroup;
|
|
||||||
riskCoverages: Array<{ name: string; value: number }>;
|
|
||||||
options: FormGroup;
|
|
||||||
isLoading = false;
|
|
||||||
saved = false;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private createTerminalFormService: CreateTerminalFormService,
|
|
||||||
private snackBar: MatSnackBar
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
const { form } = this.createTerminalFormService;
|
|
||||||
this.form = form;
|
|
||||||
this.form.valueChanges.subscribe(() => {
|
|
||||||
this.saved = false;
|
|
||||||
});
|
|
||||||
this.riskCoverages = this.createTerminalFormService.riskCoverages;
|
|
||||||
this.options = this.form.controls.options as FormGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
addOption() {
|
|
||||||
this.createTerminalFormService.addOption();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeOption(index: number) {
|
|
||||||
this.createTerminalFormService.removeOption(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.createTerminalFormService.saveTerminal().subscribe(
|
|
||||||
(terminalID) => {
|
|
||||||
this.terminalIdSelected.emit(terminalID);
|
|
||||||
this.isLoading = false;
|
|
||||||
this.saved = true;
|
|
||||||
this.snackBar.open('Terminal successfully added', 'OK', { duration: 3000 });
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.saved = false;
|
|
||||||
this.snackBar.open('An error occurred while while adding provider', 'OK');
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
import { DomainTypedManager, TerminalOption } from '../../../../../thrift-services';
|
|
||||||
|
|
||||||
const toFormArray = (fb: FormBuilder, options: TerminalOption[]): FormArray =>
|
|
||||||
fb.array(options.map((option) => fb.group(option)));
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class CreateTerminalFormService {
|
|
||||||
form: FormGroup;
|
|
||||||
|
|
||||||
riskCoverages = [
|
|
||||||
{
|
|
||||||
name: 'low',
|
|
||||||
value: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'high',
|
|
||||||
value: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'fatal',
|
|
||||||
value: 9999,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(private fb: FormBuilder, private dtm: DomainTypedManager) {
|
|
||||||
this.form = this.prepareTerminalForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
addOption() {
|
|
||||||
(this.form.controls.options as FormArray).push(this.getOption());
|
|
||||||
}
|
|
||||||
|
|
||||||
removeOption(index: number) {
|
|
||||||
const options = this.form.controls.options as FormArray;
|
|
||||||
if (options.length > 1) {
|
|
||||||
options.removeAt(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saveTerminal(): Observable<number> {
|
|
||||||
return this.dtm.createTerminal(this.form.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getOption(): FormGroup {
|
|
||||||
return this.fb.group({
|
|
||||||
key: '',
|
|
||||||
value: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private prepareTerminalForm(): FormGroup {
|
|
||||||
return this.fb.group({
|
|
||||||
terminalName: ['', Validators.required],
|
|
||||||
terminalDescription: ['', Validators.required],
|
|
||||||
riskCoverage: ['', Validators.required],
|
|
||||||
options: toFormArray(this.fb, [{ key: '', value: '' }]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<mat-tab-group (selectedTabChange)="terminalTabChanged()">
|
|
||||||
<mat-tab label="Select terminal">
|
|
||||||
<div class="tab-container">
|
|
||||||
<cc-terminals-table
|
|
||||||
[terminals]="terminals"
|
|
||||||
(terminalIdSelected)="terminalSelected($event)"
|
|
||||||
></cc-terminals-table>
|
|
||||||
</div>
|
|
||||||
</mat-tab>
|
|
||||||
<mat-tab label="Create new terminal">
|
|
||||||
<div class="tab-container">
|
|
||||||
<cc-create-terminal-form
|
|
||||||
(terminalIdSelected)="terminalSelected($event)"
|
|
||||||
></cc-create-terminal-form>
|
|
||||||
</div>
|
|
||||||
</mat-tab>
|
|
||||||
</mat-tab-group>
|
|
@ -1,3 +0,0 @@
|
|||||||
.tab-container {
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
|
|
||||||
import { TerminalObject } from '../../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-select-terminal',
|
|
||||||
templateUrl: 'select-terminal.component.html',
|
|
||||||
styleUrls: ['select-terminal.component.scss'],
|
|
||||||
})
|
|
||||||
export class SelectTerminalComponent {
|
|
||||||
@Input() terminals: TerminalObject[];
|
|
||||||
@Output() terminalIdSelected: EventEmitter<number> = new EventEmitter();
|
|
||||||
|
|
||||||
terminalTabChanged() {
|
|
||||||
this.terminalIdSelected.emit(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
terminalSelected(id: number) {
|
|
||||||
this.terminalIdSelected.emit(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<div class="mat-dialog-title">Edit priority</div>
|
|
||||||
<mat-dialog-content>
|
|
||||||
<form [formGroup]="form">
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<input matInput type="number" formControlName="value" />
|
|
||||||
</mat-form-field>
|
|
||||||
</form>
|
|
||||||
</mat-dialog-content>
|
|
||||||
<mat-dialog-actions>
|
|
||||||
<div>
|
|
||||||
<button mat-button (click)="edit()" [disabled]="isLoading$ | async">SAVE</button>
|
|
||||||
<button mat-button [mat-dialog-close]="false" [disabled]="isLoading$ | async">
|
|
||||||
CANCEL
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<mat-progress-bar *ngIf="isLoading$ | async" mode="indeterminate"></mat-progress-bar>
|
|
||||||
</mat-dialog-actions>
|
|
@ -1,42 +0,0 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
import { PartyID, ShopID } from '../../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { TerminalID } from '../../../../thrift-services/fistful/gen-model/fistful';
|
|
||||||
import { EditTerminalDecisionPriorityService } from './edit-terminal-decision-priority.service';
|
|
||||||
|
|
||||||
export interface EditPriorityData {
|
|
||||||
partyID: PartyID;
|
|
||||||
shopID: ShopID;
|
|
||||||
terminalID: TerminalID;
|
|
||||||
providerID: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: 'edit-terminal-decision-priority.component.html',
|
|
||||||
providers: [EditTerminalDecisionPriorityService],
|
|
||||||
})
|
|
||||||
export class EditTerminalDecisionPriorityComponent implements OnInit {
|
|
||||||
isLoading$;
|
|
||||||
form: FormGroup;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private dialogRef: MatDialogRef<EditTerminalDecisionPriorityComponent>,
|
|
||||||
@Inject(MAT_DIALOG_DATA) public data: EditPriorityData,
|
|
||||||
private editPriorityService: EditTerminalDecisionPriorityService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const { isLoading$, form } = this.editPriorityService;
|
|
||||||
this.isLoading$ = isLoading$;
|
|
||||||
this.form = form;
|
|
||||||
this.editPriorityService.terminalChanged.subscribe(() => {
|
|
||||||
this.dialogRef.close(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
edit() {
|
|
||||||
this.editPriorityService.edit(this.data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
|
|
||||||
import { DomainTypedManager } from '../../../../thrift-services';
|
|
||||||
import { EditTerminalDecision } from '../edit-terminal-decision';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EditTerminalDecisionPriorityService extends EditTerminalDecision {
|
|
||||||
form = this.initForm();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private fb: FormBuilder,
|
|
||||||
public dtm: DomainTypedManager,
|
|
||||||
public snackBar: MatSnackBar
|
|
||||||
) {
|
|
||||||
super(dtm, snackBar);
|
|
||||||
}
|
|
||||||
|
|
||||||
private initForm(): FormGroup {
|
|
||||||
return this.fb.group({
|
|
||||||
value: '',
|
|
||||||
property: 'priority',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<div class="mat-dialog-title">Edit weight</div>
|
|
||||||
<mat-dialog-content>
|
|
||||||
<form [formGroup]="form">
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<input matInput type="number" formControlName="value" />
|
|
||||||
</mat-form-field>
|
|
||||||
</form>
|
|
||||||
</mat-dialog-content>
|
|
||||||
<mat-dialog-actions>
|
|
||||||
<div>
|
|
||||||
<button mat-button (click)="edit()" [disabled]="isLoading$ | async">SAVE</button>
|
|
||||||
<button mat-button [mat-dialog-close]="false" [disabled]="isLoading$ | async">
|
|
||||||
CANCEL
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<mat-progress-bar *ngIf="isLoading$ | async" mode="indeterminate"></mat-progress-bar>
|
|
||||||
</mat-dialog-actions>
|
|
@ -1,42 +0,0 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
import { PartyID, ShopID } from '../../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { TerminalID } from '../../../../thrift-services/fistful/gen-model/fistful';
|
|
||||||
import { EditTerminalDecisionWeightService } from './edit-terminal-decision-weight.service';
|
|
||||||
|
|
||||||
export interface EditWeightData {
|
|
||||||
partyID: PartyID;
|
|
||||||
shopID: ShopID;
|
|
||||||
terminalID: TerminalID;
|
|
||||||
providerID: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: 'edit-terminal-decision-weight.component.html',
|
|
||||||
providers: [EditTerminalDecisionWeightService],
|
|
||||||
})
|
|
||||||
export class EditTerminalDecisionWeightComponent implements OnInit {
|
|
||||||
isLoading$;
|
|
||||||
form: FormGroup;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private dialogRef: MatDialogRef<EditTerminalDecisionWeightComponent>,
|
|
||||||
@Inject(MAT_DIALOG_DATA) public data: EditWeightData,
|
|
||||||
private editWeightService: EditTerminalDecisionWeightService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const { isLoading$, form } = this.editWeightService;
|
|
||||||
this.isLoading$ = isLoading$;
|
|
||||||
this.form = form;
|
|
||||||
this.editWeightService.terminalChanged.subscribe(() => {
|
|
||||||
this.dialogRef.close(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
edit() {
|
|
||||||
this.editWeightService.edit(this.data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
|
|
||||||
import { DomainTypedManager } from '../../../../thrift-services';
|
|
||||||
import { EditTerminalDecision } from '../edit-terminal-decision';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EditTerminalDecisionWeightService extends EditTerminalDecision {
|
|
||||||
form = this.initForm();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private fb: FormBuilder,
|
|
||||||
public dtm: DomainTypedManager,
|
|
||||||
public snackBar: MatSnackBar
|
|
||||||
) {
|
|
||||||
super(dtm, snackBar);
|
|
||||||
}
|
|
||||||
|
|
||||||
private initForm(): FormGroup {
|
|
||||||
return this.fb.group({
|
|
||||||
value: '',
|
|
||||||
property: 'weight',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { EventEmitter } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
|
|
||||||
import { DomainTypedManager } from '../../../thrift-services';
|
|
||||||
import { EditTerminalDecisionPropertyParams } from '../../../thrift-services/damsel/operations/edit-terminal-decision-property-params';
|
|
||||||
import { EditPriorityData } from './edit-terminal-decision-priority/edit-terminal-decision-priority.component';
|
|
||||||
|
|
||||||
export interface EditTerminalDecisionFormValues {
|
|
||||||
property: string;
|
|
||||||
value: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EditTerminalDecision {
|
|
||||||
form: FormGroup;
|
|
||||||
isLoading$: Subject<boolean> = new Subject();
|
|
||||||
terminalChanged: EventEmitter<void> = new EventEmitter();
|
|
||||||
|
|
||||||
constructor(public dtm: DomainTypedManager, public snackBar: MatSnackBar) {}
|
|
||||||
|
|
||||||
edit(data: EditPriorityData, formValues?: EditTerminalDecisionFormValues) {
|
|
||||||
const params = {
|
|
||||||
...data,
|
|
||||||
...this.form.getRawValue(),
|
|
||||||
...formValues,
|
|
||||||
} as EditTerminalDecisionPropertyParams;
|
|
||||||
this.isLoading$.next(true);
|
|
||||||
this.dtm.editTerminalDecisionPropertyForShop(params).subscribe(
|
|
||||||
() => {
|
|
||||||
this.terminalChanged.emit();
|
|
||||||
this.isLoading$.next(false);
|
|
||||||
this.snackBar.open('Terminal decision successfully edited', 'OK', {
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
this.isLoading$.next(false);
|
|
||||||
this.snackBar.open('An error occurred while while editing terminal decision', 'OK');
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,212 +0,0 @@
|
|||||||
import get from 'lodash-es/get';
|
|
||||||
|
|
||||||
import {
|
|
||||||
PartyCondition,
|
|
||||||
PartyID,
|
|
||||||
Predicate,
|
|
||||||
ProviderTerminalRef,
|
|
||||||
ShopID,
|
|
||||||
TerminalDecision,
|
|
||||||
TerminalObject,
|
|
||||||
TerminalRef,
|
|
||||||
TerminalSelector,
|
|
||||||
} from '../../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
interface PredicateInfo {
|
|
||||||
shopPartyContain: boolean;
|
|
||||||
predicateType?: PredicateType;
|
|
||||||
disabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TerminalInfoGroup {
|
|
||||||
terminalIds: number[];
|
|
||||||
weights: number[];
|
|
||||||
priorities: number[];
|
|
||||||
disabled: boolean;
|
|
||||||
predicateType: PredicateType;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FlattenTerminalInfoGroup {
|
|
||||||
terminalId: number;
|
|
||||||
disabled: boolean;
|
|
||||||
predicateType: PredicateType;
|
|
||||||
priority: number;
|
|
||||||
weight: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PredicateType {
|
|
||||||
condition = 'condition',
|
|
||||||
is_not = 'is_not',
|
|
||||||
all_of = 'all_of',
|
|
||||||
any_of = 'any_of',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TerminalInfo {
|
|
||||||
terminal: TerminalObject;
|
|
||||||
disabled: boolean;
|
|
||||||
predicateType: PredicateType;
|
|
||||||
weight: number;
|
|
||||||
priority: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function inPredicates(predicates: Set<Predicate>, shopID: ShopID, partyID: PartyID): boolean {
|
|
||||||
for (const predicate of predicates) {
|
|
||||||
if (extractPredicateInfo(predicate, shopID, partyID).shopPartyContain) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function inPartyCondition(party: PartyCondition, shopID: ShopID, partyID: PartyID): boolean {
|
|
||||||
const shopIs = get(party, 'definition.shop_is');
|
|
||||||
return party.id === partyID && shopIs === shopID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDisabled(all_of: Set<Predicate>): boolean {
|
|
||||||
const constant = Array.from(all_of).find((pre) => pre.constant !== null);
|
|
||||||
return !!constant ? constant.constant : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractPredicateInfo(
|
|
||||||
{ all_of, any_of, condition, is_not }: Predicate,
|
|
||||||
shopID: ShopID,
|
|
||||||
partyID: PartyID
|
|
||||||
): PredicateInfo {
|
|
||||||
if (all_of && all_of.size > 0) {
|
|
||||||
return {
|
|
||||||
shopPartyContain: inPredicates(all_of, shopID, partyID),
|
|
||||||
predicateType: PredicateType.all_of,
|
|
||||||
disabled: isDisabled(all_of),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (any_of && any_of.size > 0) {
|
|
||||||
return {
|
|
||||||
shopPartyContain: inPredicates(any_of, shopID, partyID),
|
|
||||||
predicateType: PredicateType.any_of,
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (is_not) {
|
|
||||||
if (is_not.condition?.party) {
|
|
||||||
return {
|
|
||||||
shopPartyContain: inPartyCondition(is_not.condition.party, shopID, partyID),
|
|
||||||
predicateType: PredicateType.is_not,
|
|
||||||
disabled: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (condition && condition.party) {
|
|
||||||
if (condition.party) {
|
|
||||||
return {
|
|
||||||
shopPartyContain: inPartyCondition(condition.party, shopID, partyID),
|
|
||||||
predicateType: PredicateType.condition,
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
shopPartyContain: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const extractIdsFromValue = (value: Set<TerminalRef>): number[] =>
|
|
||||||
Array.from(value).map((v) => v.id);
|
|
||||||
|
|
||||||
// Need TerminalDecision with if_ then_
|
|
||||||
function extractIdsFromDecisions(decisions: TerminalDecision[]): number[] {
|
|
||||||
return decisions.reduce((r, { then_ }) => {
|
|
||||||
if (then_.decisions) {
|
|
||||||
r = r.concat(extractIdsFromDecisions(then_.decisions));
|
|
||||||
}
|
|
||||||
if (then_.value) {
|
|
||||||
r = r.concat(extractIdsFromValue(then_.value));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need TerminalSelector with Array instead Set
|
|
||||||
function extractIds({ decisions, value }: TerminalSelector): number[] {
|
|
||||||
if (decisions) {
|
|
||||||
return extractIdsFromDecisions(decisions);
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
return extractIdsFromValue(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractWeights(value: Set<ProviderTerminalRef>): number[] {
|
|
||||||
if (value) {
|
|
||||||
return Array.from(value).map((val: any) => val.weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractPriorities(value: Set<ProviderTerminalRef>): number[] {
|
|
||||||
if (value) {
|
|
||||||
return Array.from(value).map((val: any) => val.priority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const extractTerminalInfoGroup = (
|
|
||||||
decisions: TerminalDecision[],
|
|
||||||
shopID: ShopID,
|
|
||||||
partyID: PartyID
|
|
||||||
): TerminalInfoGroup[] =>
|
|
||||||
decisions.reduce((r, { if_, then_ }) => {
|
|
||||||
const { shopPartyContain, disabled, predicateType } = extractPredicateInfo(
|
|
||||||
if_,
|
|
||||||
shopID,
|
|
||||||
partyID
|
|
||||||
);
|
|
||||||
if (shopPartyContain) {
|
|
||||||
r = r.concat({
|
|
||||||
terminalIds: extractIds(then_),
|
|
||||||
disabled,
|
|
||||||
predicateType,
|
|
||||||
weights: extractWeights(then_.value),
|
|
||||||
priorities: extractPriorities(then_.value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const flattenGroup = (group: TerminalInfoGroup[]): FlattenTerminalInfoGroup[] =>
|
|
||||||
group.reduce(
|
|
||||||
(r, { terminalIds, disabled, predicateType, weights, priorities }) => [
|
|
||||||
...r,
|
|
||||||
...terminalIds.map((terminalId, idx) => ({
|
|
||||||
terminalId,
|
|
||||||
disabled,
|
|
||||||
predicateType,
|
|
||||||
weight: weights[idx],
|
|
||||||
priority: priorities[idx],
|
|
||||||
})),
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const enrichWithTerminal = (
|
|
||||||
groups: FlattenTerminalInfoGroup[],
|
|
||||||
terminalObjects: TerminalObject[]
|
|
||||||
): TerminalInfo[] => {
|
|
||||||
return groups.map((group) => {
|
|
||||||
return {
|
|
||||||
terminal: terminalObjects.find(({ ref: { id } }) => group.terminalId === id),
|
|
||||||
disabled: group.disabled,
|
|
||||||
predicateType: group.predicateType,
|
|
||||||
weight: group.weight,
|
|
||||||
priority: group.priority,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Need TerminalDecision with if_ then_
|
|
||||||
export function extractTerminalInfo(
|
|
||||||
decisions: TerminalDecision[],
|
|
||||||
terminalObjects: TerminalObject[],
|
|
||||||
shopID: ShopID,
|
|
||||||
partyID: PartyID
|
|
||||||
): TerminalInfo[] {
|
|
||||||
const extractedGroup = extractTerminalInfoGroup(decisions, shopID, partyID);
|
|
||||||
return enrichWithTerminal(flattenGroup(extractedGroup), terminalObjects);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
<mat-card *ngFor="let info of providerInfo">
|
|
||||||
<mat-card-content>
|
|
||||||
<mat-card-subtitle> {{ info.provider.data.name }} </mat-card-subtitle>
|
|
||||||
<cc-terminals
|
|
||||||
[terminalInfos]="info.terminalInfos"
|
|
||||||
[partyID]="partyID"
|
|
||||||
[shopID]="shopID"
|
|
||||||
[providerID]="info.provider.ref.id"
|
|
||||||
(terminalChanged)="terminalChanged.emit()"
|
|
||||||
></cc-terminals>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
|
|
||||||
import { ProviderInfo } from '../shop-details.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-provider',
|
|
||||||
templateUrl: 'provider.component.html',
|
|
||||||
styleUrls: ['provider.component.scss'],
|
|
||||||
})
|
|
||||||
export class ProviderComponent {
|
|
||||||
@Input() providerInfo: ProviderInfo[];
|
|
||||||
@Input() partyID: string;
|
|
||||||
@Input() shopID: string;
|
|
||||||
@Output() terminalChanged: EventEmitter<void> = new EventEmitter();
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
<cc-card-container>
|
|
||||||
<div *ngIf="isLoading" fxLayout fxLayoutAlign="center stretch"><mat-spinner></mat-spinner></div>
|
|
||||||
<div *ngIf="!isLoading" fxLayout="column" fxLayoutGap="20px">
|
|
||||||
<mat-card>
|
|
||||||
<mat-card-subtitle>Shop details</mat-card-subtitle>
|
|
||||||
<mat-card-content>
|
|
||||||
<cc-shop-info [shop]="shop" [partyID]="partyID"></cc-shop-info>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
<div fxLayout="row" fxLayoutGap="15px">
|
|
||||||
<mat-accordion fxFlex="50">
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title> Contract details</mat-panel-title>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
|
|
||||||
<cc-pretty-json [object]="contract"></cc-pretty-json>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
</mat-accordion>
|
|
||||||
<mat-accordion fxFlex="50">
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title> Payout tool details</mat-panel-title>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
|
|
||||||
<cc-pretty-json [object]="payoutTool"></cc-pretty-json>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
</mat-accordion>
|
|
||||||
</div>
|
|
||||||
<mat-card>
|
|
||||||
<mat-card-subtitle>Shop actions</mat-card-subtitle>
|
|
||||||
<mat-card-content>
|
|
||||||
<button mat-flat-button (click)="addProvider()">ADD PROVIDER</button>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
<div fxLayout="column" fxLayoutGap="20px">
|
|
||||||
<h4 class="mat-h4 mat-subheading-1 action-header">Providers:</h4>
|
|
||||||
<h4 class="mat-h4 mat-subheading-1" *ngIf="providerInfo.length === 0">
|
|
||||||
Providers not found
|
|
||||||
</h4>
|
|
||||||
<cc-provider
|
|
||||||
*ngIf="providerInfo.length > 0"
|
|
||||||
[providerInfo]="providerInfo"
|
|
||||||
[partyID]="partyID"
|
|
||||||
[shopID]="shop.id"
|
|
||||||
(terminalChanged)="terminalChanged()"
|
|
||||||
></cc-provider>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</cc-card-container>
|
|
@ -1,11 +0,0 @@
|
|||||||
.action-header {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
td {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import { ActivatedRoute } from '@angular/router';
|
|
||||||
import { filter, switchMap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { Contract, PayoutTool, Shop } from '../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { AddProviderComponent } from './add-provider/add-provider.component';
|
|
||||||
import { ProviderInfo, ShopDetailsService } from './shop-details.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: 'shop-details.component.html',
|
|
||||||
styleUrls: ['shop-details.component.scss'],
|
|
||||||
providers: [ShopDetailsService],
|
|
||||||
})
|
|
||||||
export class ShopDetailsComponent implements OnInit {
|
|
||||||
isLoading = false;
|
|
||||||
shop: Shop;
|
|
||||||
contract: Contract;
|
|
||||||
payoutTool: PayoutTool;
|
|
||||||
partyID: string;
|
|
||||||
providerInfo: ProviderInfo[];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private shopDetailsService: ShopDetailsService,
|
|
||||||
private dialog: MatDialog
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
addProvider() {
|
|
||||||
const config = {
|
|
||||||
data: {
|
|
||||||
shopID: this.shop.id,
|
|
||||||
partyID: this.partyID,
|
|
||||||
shopCategoryID: this.shop.category.id,
|
|
||||||
},
|
|
||||||
width: '800px',
|
|
||||||
disableClose: true,
|
|
||||||
};
|
|
||||||
const dialog = this.dialog.open(AddProviderComponent, config);
|
|
||||||
dialog
|
|
||||||
.afterClosed()
|
|
||||||
.pipe(filter((result) => result))
|
|
||||||
.subscribe(() => this.getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
terminalChanged() {
|
|
||||||
this.getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private getData() {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.route.params
|
|
||||||
.pipe(
|
|
||||||
switchMap(({ partyID, shopID }) => {
|
|
||||||
this.partyID = partyID;
|
|
||||||
return this.shopDetailsService.initialize(partyID, shopID);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(({ payoutTool, shop, contract, providerInfo }) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.payoutTool = payoutTool;
|
|
||||||
this.shop = shop;
|
|
||||||
this.contract = contract;
|
|
||||||
this.providerInfo = providerInfo;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatCardModule } from '@angular/material/card';
|
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
||||||
import { MatChipsModule } from '@angular/material/chips';
|
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
|
||||||
import { MatInputModule } from '@angular/material/input';
|
|
||||||
import { MatListModule } from '@angular/material/list';
|
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
|
||||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
||||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
||||||
import { MatRadioModule } from '@angular/material/radio';
|
|
||||||
import { MatStepperModule } from '@angular/material/stepper';
|
|
||||||
import { MatTableModule } from '@angular/material/table';
|
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
|
||||||
|
|
||||||
import { CardContainerModule } from '@cc/components/card-container/card-container.module';
|
|
||||||
import { PrettyJsonModule } from '@cc/components/pretty-json';
|
|
||||||
|
|
||||||
import { AddProviderComponent } from './add-provider/add-provider.component';
|
|
||||||
import { SelectProviderComponent } from './add-provider/select-provider/select-provider.component';
|
|
||||||
import { CreateTerminalFormComponent } from './add-provider/select-terminal/create-terminal-form/create-terminal-form.component';
|
|
||||||
import { SelectTerminalComponent } from './add-provider/select-terminal/select-terminal.component';
|
|
||||||
import { TerminalsTableComponent } from './add-provider/select-terminal/terminals-table/terminals-table.component';
|
|
||||||
import { EditTerminalDecisionPriorityComponent } from './edit-terminal-decision/edit-terminal-decision-priority/edit-terminal-decision-priority.component';
|
|
||||||
import { EditTerminalDecisionWeightComponent } from './edit-terminal-decision/edit-terminal-decision-weight/edit-terminal-decision-weight.component';
|
|
||||||
import { IsActivePipe } from './is-active.pipe';
|
|
||||||
import { ProviderComponent } from './provider/provider.component';
|
|
||||||
import { ShopDetailsComponent } from './shop-details.component';
|
|
||||||
import { CategoryComponent } from './shop-info/category/category.component';
|
|
||||||
import { ShopBlockingPipe } from './shop-info/shop-blocking.pipe';
|
|
||||||
import { ShopInfoComponent } from './shop-info/shop-info.component';
|
|
||||||
import { ShopSuspensionPipe } from './shop-info/shop-suspension.pipe';
|
|
||||||
import { TerminalComponent } from './terminal/terminal.component';
|
|
||||||
import { TerminalsComponent } from './terminals/terminals.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
MatExpansionModule,
|
|
||||||
MatListModule,
|
|
||||||
MatCardModule,
|
|
||||||
CommonModule,
|
|
||||||
MatProgressSpinnerModule,
|
|
||||||
FlexLayoutModule,
|
|
||||||
MatButtonModule,
|
|
||||||
MatDialogModule,
|
|
||||||
MatRadioModule,
|
|
||||||
MatStepperModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
MatTableModule,
|
|
||||||
MatCheckboxModule,
|
|
||||||
MatPaginatorModule,
|
|
||||||
MatFormFieldModule,
|
|
||||||
MatInputModule,
|
|
||||||
MatTabsModule,
|
|
||||||
MatIconModule,
|
|
||||||
MatProgressBarModule,
|
|
||||||
MatMenuModule,
|
|
||||||
MatProgressBarModule,
|
|
||||||
MatChipsModule,
|
|
||||||
PrettyJsonModule,
|
|
||||||
CardContainerModule,
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
ShopDetailsComponent,
|
|
||||||
ShopBlockingPipe,
|
|
||||||
ShopSuspensionPipe,
|
|
||||||
ShopInfoComponent,
|
|
||||||
ProviderComponent,
|
|
||||||
TerminalComponent,
|
|
||||||
AddProviderComponent,
|
|
||||||
TerminalsTableComponent,
|
|
||||||
CreateTerminalFormComponent,
|
|
||||||
SelectProviderComponent,
|
|
||||||
SelectTerminalComponent,
|
|
||||||
IsActivePipe,
|
|
||||||
CategoryComponent,
|
|
||||||
EditTerminalDecisionPriorityComponent,
|
|
||||||
EditTerminalDecisionWeightComponent,
|
|
||||||
TerminalsComponent,
|
|
||||||
],
|
|
||||||
entryComponents: [
|
|
||||||
AddProviderComponent,
|
|
||||||
EditTerminalDecisionPriorityComponent,
|
|
||||||
EditTerminalDecisionWeightComponent,
|
|
||||||
],
|
|
||||||
exports: [CategoryComponent],
|
|
||||||
})
|
|
||||||
export class ShopDetailsModule {}
|
|
@ -1,95 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import get from 'lodash-es/get';
|
|
||||||
import { combineLatest, Observable } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { DomainCacheService } from '../../thrift-services/damsel/domain-cache.service';
|
|
||||||
import {
|
|
||||||
Contract,
|
|
||||||
PartyID,
|
|
||||||
PayoutTool,
|
|
||||||
ProviderObject,
|
|
||||||
Shop,
|
|
||||||
ShopID,
|
|
||||||
TerminalObject,
|
|
||||||
} from '../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { PartyService } from '../party.service';
|
|
||||||
import { extractTerminalInfo, TerminalInfo } from './extract-terminal-info';
|
|
||||||
|
|
||||||
export interface ProviderInfo {
|
|
||||||
provider: ProviderObject;
|
|
||||||
terminalInfos: TerminalInfo[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Payload {
|
|
||||||
shop: Shop;
|
|
||||||
contract: Contract;
|
|
||||||
payoutTool: PayoutTool;
|
|
||||||
providerInfo: ProviderInfo[];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ShopDetailsService {
|
|
||||||
constructor(
|
|
||||||
private partyService: PartyService,
|
|
||||||
private domainCacheService: DomainCacheService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
initialize(partyID: string, shopID: string): Observable<Payload> {
|
|
||||||
return combineLatest([
|
|
||||||
this.partyService.getShop(partyID, shopID),
|
|
||||||
this.domainCacheService.getObjects('provider'),
|
|
||||||
this.domainCacheService.getObjects('terminal'),
|
|
||||||
]).pipe(
|
|
||||||
switchMap(([shop, providers, terminalObjects]) =>
|
|
||||||
this.partyService.getContract(partyID, shop.contract_id).pipe(
|
|
||||||
map((contract) => ({
|
|
||||||
contract,
|
|
||||||
providerInfo: this.toProviderInfo(
|
|
||||||
providers,
|
|
||||||
terminalObjects,
|
|
||||||
partyID,
|
|
||||||
shopID
|
|
||||||
),
|
|
||||||
shop,
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
switchMap(({ contract, providerInfo, shop }) =>
|
|
||||||
this.partyService.getPayoutTool(partyID, contract.id, shop.payout_tool_id).pipe(
|
|
||||||
map((payoutTool) => ({
|
|
||||||
payoutTool,
|
|
||||||
shop,
|
|
||||||
providerInfo,
|
|
||||||
contract,
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private toProviderInfo(
|
|
||||||
providers: ProviderObject[],
|
|
||||||
terminalObjects: TerminalObject[],
|
|
||||||
partyID: PartyID,
|
|
||||||
shopID: ShopID
|
|
||||||
): ProviderInfo[] {
|
|
||||||
return providers.reduce((r, provider) => {
|
|
||||||
const decisions = get(provider, 'data.terminal.decisions');
|
|
||||||
if (!decisions) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
const infos = extractTerminalInfo(decisions, terminalObjects, shopID, partyID);
|
|
||||||
if (infos.length === 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
...r,
|
|
||||||
{
|
|
||||||
provider,
|
|
||||||
terminalInfos: infos,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +1,4 @@
|
|||||||
|
<ng-container *ngIf="category$ | async as category; else isLoading">
|
||||||
{{ category?.name }} (ID: {{ categoryID }})
|
{{ category?.name }} (ID: {{ categoryID }})
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #isLoading> ID: {{ categoryID }} </ng-template>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
import { CategoryService } from '../../../../papi/category.service';
|
import { CategoryService } from '../../../../papi/category.service';
|
||||||
import { Category } from '../../../../thrift-services/damsel/gen-model/domain';
|
import { Category } from '../../../../thrift-services/damsel/gen-model/domain';
|
||||||
@ -8,15 +10,16 @@ import { Category } from '../../../../thrift-services/damsel/gen-model/domain';
|
|||||||
selector: 'cc-category',
|
selector: 'cc-category',
|
||||||
providers: [CategoryService],
|
providers: [CategoryService],
|
||||||
})
|
})
|
||||||
export class CategoryComponent implements OnInit {
|
export class CategoryComponent {
|
||||||
@Input() categoryID: number;
|
@Input() set category(categoryID: number) {
|
||||||
category: Category;
|
this.categoryID = categoryID;
|
||||||
|
this.category$ = this.categoryService.categories$.pipe(
|
||||||
|
map((categories) => categories.find((category) => category.id === categoryID))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
category$: Observable<Category>;
|
||||||
|
categoryID: number;
|
||||||
|
|
||||||
constructor(private categoryService: CategoryService) {}
|
constructor(private categoryService: CategoryService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.categoryService.getCategories().subscribe((categories) => {
|
|
||||||
this.category = categories.find((category) => category.id === this.categoryID);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div *ngIf="shop?.category?.id" fxLayout="row" fxLayout.xs="column">
|
<div *ngIf="shop?.category?.id" fxLayout="row" fxLayout.xs="column">
|
||||||
<label fxFlex="20">Category:</label>
|
<label fxFlex="20">Category:</label>
|
||||||
<div><cc-category [categoryID]="shop.category.id"></cc-category></div>
|
<div><cc-category [category]="shop.category.id"></cc-category></div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="shop?.location?.url" fxLayout="row" fxLayout.xs="column">
|
<div *ngIf="shop?.location?.url" fxLayout="row" fxLayout.xs="column">
|
||||||
<label fxFlex="20">URL:</label>
|
<label fxFlex="20">URL:</label>
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
import { Shop } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-shop-info',
|
|
||||||
templateUrl: 'shop-info.component.html',
|
|
||||||
})
|
|
||||||
export class ShopInfoComponent {
|
|
||||||
@Input() shop: Shop;
|
|
||||||
@Input() partyID: string;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
<div fxLayout="row" fxLayoutAlign="space-between center">
|
|
||||||
<div>
|
|
||||||
{{ terminalInfo.terminal.data.name }} - {{ terminalInfo.terminal.data.description }}
|
|
||||||
<span class="predicate-type">{{ terminalInfo.predicateType }}</span>
|
|
||||||
</div>
|
|
||||||
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="15px">
|
|
||||||
<mat-chip-list fxLayout="row" fxLayoutAlign="center">
|
|
||||||
<mat-chip [selected]="!terminalInfo.disabled">{{
|
|
||||||
!terminalInfo.disabled | ccIsActive
|
|
||||||
}}</mat-chip>
|
|
||||||
<mat-chip [selected]="!terminalInfo.disabled"
|
|
||||||
>Priority: {{ terminalInfo.priority + '' }}</mat-chip
|
|
||||||
>
|
|
||||||
<mat-chip [selected]="!terminalInfo.disabled"
|
|
||||||
>Weight: {{ terminalInfo.weight + '' }}</mat-chip
|
|
||||||
>
|
|
||||||
</mat-chip-list>
|
|
||||||
<button mat-icon-button [matMenuTriggerFor]="appMenu">
|
|
||||||
<mat-icon>more_vert</mat-icon>
|
|
||||||
</button>
|
|
||||||
<mat-menu #appMenu="matMenu">
|
|
||||||
<button mat-menu-item (click)="removeTerminal()" [disabled]="!isRemovable()">
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span>Remove</span>
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,3 +0,0 @@
|
|||||||
.predicate-type {
|
|
||||||
color: #bbbbbb;
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
|
|
||||||
import { DomainTypedManager } from '../../../thrift-services';
|
|
||||||
import { PartyID, ShopID } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { PredicateType, TerminalInfo } from '../extract-terminal-info';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-terminal',
|
|
||||||
templateUrl: 'terminal.component.html',
|
|
||||||
styleUrls: ['terminal.component.scss'],
|
|
||||||
})
|
|
||||||
export class TerminalComponent {
|
|
||||||
@Input() terminalInfo: TerminalInfo;
|
|
||||||
@Input() partyID: PartyID;
|
|
||||||
@Input() shopID: ShopID;
|
|
||||||
@Input() providerID: number;
|
|
||||||
@Output() terminalRemovedEvent: EventEmitter<void> = new EventEmitter();
|
|
||||||
|
|
||||||
isLoading = false;
|
|
||||||
|
|
||||||
constructor(private dtm: DomainTypedManager, private snackBar: MatSnackBar) {}
|
|
||||||
|
|
||||||
removeTerminal() {
|
|
||||||
this.isLoading = true;
|
|
||||||
const params = {
|
|
||||||
partyID: this.partyID,
|
|
||||||
shopID: this.shopID,
|
|
||||||
terminalID: this.terminalInfo.terminal.ref.id,
|
|
||||||
providerID: this.providerID,
|
|
||||||
};
|
|
||||||
this.dtm.removeTerminalFromShop(params).subscribe(
|
|
||||||
() => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open('Terminal successfully removed from shop', 'OK', {
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
this.terminalRemovedEvent.emit();
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open(
|
|
||||||
'An error occurred while while removing terminal from shop',
|
|
||||||
'OK'
|
|
||||||
);
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isRemovable() {
|
|
||||||
const { predicateType } = this.terminalInfo;
|
|
||||||
return predicateType === PredicateType.condition || predicateType === PredicateType.any_of;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
<div fxLayout="column">
|
|
||||||
<table mat-table [dataSource]="infos">
|
|
||||||
<ng-container matColumnDef="name">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Name</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.terminal.data.name }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="description">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Description</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">
|
|
||||||
{{ terminalInfo.terminal.data.description }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="type">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Type</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.predicateType }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="priority">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Priority</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo; let i = index">
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
(click)="changePriority('plus', i)"
|
|
||||||
[disabled]="
|
|
||||||
!isWeightOrPriorityEditable(terminalInfo.predicateType) ||
|
|
||||||
(isLoading | async)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
|
||||||
</button>
|
|
||||||
{{ terminalInfo.priority }}
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
(click)="changePriority('minus', i)"
|
|
||||||
[disabled]="
|
|
||||||
!isWeightOrPriorityEditable(terminalInfo.predicateType) ||
|
|
||||||
(isLoading | async)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="weight">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Weight</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.weight }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="status">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Status</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">
|
|
||||||
<mat-chip-list>
|
|
||||||
<mat-chip [selected]="!terminalInfo.disabled">{{
|
|
||||||
!terminalInfo.disabled | ccIsActive
|
|
||||||
}}</mat-chip>
|
|
||||||
</mat-chip-list>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="actions">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
|
||||||
<td mat-cell *matCellDef="let terminalInfo">
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
[matMenuTriggerFor]="appMenu"
|
|
||||||
[disabled]="isLoading | async"
|
|
||||||
>
|
|
||||||
<mat-icon>more_vert</mat-icon>
|
|
||||||
</button>
|
|
||||||
<mat-menu #appMenu="matMenu">
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
(click)="editPriority(terminalInfo.terminal.ref.id)"
|
|
||||||
[disabled]="
|
|
||||||
!isWeightOrPriorityEditable(terminalInfo.predicateType) ||
|
|
||||||
(isLoading | async)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<mat-icon>edit</mat-icon>
|
|
||||||
<span>Edit priority</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
(click)="editWeight(terminalInfo.terminal.ref.id)"
|
|
||||||
[disabled]="
|
|
||||||
!isWeightOrPriorityEditable(terminalInfo.predicateType) ||
|
|
||||||
(isLoading | async)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<mat-icon>edit</mat-icon>
|
|
||||||
<span>Edit weight</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
(click)="removeTerminal(terminalInfo.terminal.ref.id)"
|
|
||||||
[disabled]="!isEditable(terminalInfo.predicateType, isLoading | async)"
|
|
||||||
>
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span>Remove</span>
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let row; columns: columns"></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<mat-progress-bar *ngIf="isLoading | async" mode="indeterminate"></mat-progress-bar>
|
|
||||||
</div>
|
|
@ -1,162 +0,0 @@
|
|||||||
import {
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnChanges,
|
|
||||||
OnInit,
|
|
||||||
Output,
|
|
||||||
SimpleChanges,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
import { filter } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { DomainTypedManager } from '../../../thrift-services';
|
|
||||||
import { PartyID, ShopID } from '../../../thrift-services/damsel/gen-model/domain';
|
|
||||||
import { TerminalID } from '../../../thrift-services/fistful/gen-model/fistful';
|
|
||||||
import { EditTerminalDecisionPriorityComponent } from '../edit-terminal-decision/edit-terminal-decision-priority/edit-terminal-decision-priority.component';
|
|
||||||
import { EditTerminalDecisionPriorityService } from '../edit-terminal-decision/edit-terminal-decision-priority/edit-terminal-decision-priority.service';
|
|
||||||
import { EditTerminalDecisionWeightComponent } from '../edit-terminal-decision/edit-terminal-decision-weight/edit-terminal-decision-weight.component';
|
|
||||||
import { PredicateType, TerminalInfo } from '../extract-terminal-info';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-terminals',
|
|
||||||
templateUrl: 'terminals.component.html',
|
|
||||||
styleUrls: ['terminals.component.scss'],
|
|
||||||
providers: [EditTerminalDecisionPriorityService],
|
|
||||||
})
|
|
||||||
export class TerminalsComponent implements OnChanges, OnInit {
|
|
||||||
@Input() terminalInfos: TerminalInfo[];
|
|
||||||
@Input() partyID: PartyID;
|
|
||||||
@Input() shopID: ShopID;
|
|
||||||
@Input() providerID: number;
|
|
||||||
@Output() terminalChanged: EventEmitter<void> = new EventEmitter();
|
|
||||||
|
|
||||||
columns = ['name', 'description', 'type', 'priority', 'weight', 'status', 'actions'];
|
|
||||||
isLoading;
|
|
||||||
infos: TerminalInfo[];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private dtm: DomainTypedManager,
|
|
||||||
private snackBar: MatSnackBar,
|
|
||||||
private dialog: MatDialog,
|
|
||||||
private editPriorityService: EditTerminalDecisionPriorityService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.editPriorityService.terminalChanged.subscribe(() => {
|
|
||||||
this.terminalChanged.emit();
|
|
||||||
});
|
|
||||||
this.isLoading = this.editPriorityService.isLoading$;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
|
||||||
this.infos = this.sortInfos(changes.terminalInfos.currentValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
isEditable(predicateType: PredicateType, isLoading: boolean) {
|
|
||||||
return (
|
|
||||||
(predicateType === PredicateType.condition || predicateType === PredicateType.any_of) &&
|
|
||||||
!isLoading
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeTerminal(terminalID: TerminalID) {
|
|
||||||
this.isLoading = true;
|
|
||||||
const params = this.getModalData(terminalID);
|
|
||||||
this.dtm.removeTerminalFromShop(params).subscribe(
|
|
||||||
() => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open('Terminal successfully removed from shop', 'OK', {
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
this.terminalChanged.emit();
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.snackBar.open(
|
|
||||||
'An error occurred while while removing terminal from shop',
|
|
||||||
'OK'
|
|
||||||
);
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
editPriority(terminalID: TerminalID) {
|
|
||||||
const config = {
|
|
||||||
data: this.getModalData(terminalID),
|
|
||||||
width: '300px',
|
|
||||||
disableClose: true,
|
|
||||||
};
|
|
||||||
const dialog = this.dialog.open(EditTerminalDecisionPriorityComponent, config);
|
|
||||||
dialog
|
|
||||||
.afterClosed()
|
|
||||||
.pipe(filter((result) => result))
|
|
||||||
.subscribe(() => {
|
|
||||||
this.terminalChanged.emit();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
editWeight(terminalID: TerminalID) {
|
|
||||||
const config = {
|
|
||||||
data: this.getModalData(terminalID),
|
|
||||||
width: '300px',
|
|
||||||
disableClose: true,
|
|
||||||
};
|
|
||||||
const dialog = this.dialog.open(EditTerminalDecisionWeightComponent, config);
|
|
||||||
dialog
|
|
||||||
.afterClosed()
|
|
||||||
.pipe(filter((result) => result))
|
|
||||||
.subscribe(() => {
|
|
||||||
this.terminalChanged.emit();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
changePriority(op: string, i: number) {
|
|
||||||
const terminalID = this.infos[i].terminal.ref.id;
|
|
||||||
const basePriority = this.infos[i].priority;
|
|
||||||
const prevInfo = this.infos[i - 1];
|
|
||||||
const nexInfo = this.infos[i + 1];
|
|
||||||
|
|
||||||
let diffPlus50;
|
|
||||||
if (op === 'plus') {
|
|
||||||
diffPlus50 = prevInfo ? prevInfo.priority + 50 : basePriority + 50;
|
|
||||||
this.editPriorityService.edit(this.getModalData(terminalID), {
|
|
||||||
property: 'priority',
|
|
||||||
value: diffPlus50,
|
|
||||||
});
|
|
||||||
} else if (op === 'minus') {
|
|
||||||
diffPlus50 = nexInfo ? nexInfo.priority - 50 : 0;
|
|
||||||
this.editPriorityService.edit(this.getModalData(terminalID), {
|
|
||||||
property: 'priority',
|
|
||||||
value: diffPlus50,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isWeightOrPriorityEditable(predicate: PredicateType): boolean {
|
|
||||||
return predicate === PredicateType.condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getModalData(terminalID: TerminalID) {
|
|
||||||
return {
|
|
||||||
shopID: this.shopID,
|
|
||||||
partyID: this.partyID,
|
|
||||||
providerID: this.providerID,
|
|
||||||
terminalID,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private sortInfos(infos: TerminalInfo[]): TerminalInfo[] {
|
|
||||||
return infos.sort((a, b) => {
|
|
||||||
const aPriority = a.priority;
|
|
||||||
const bPriority = b.priority;
|
|
||||||
if (aPriority !== bPriority) {
|
|
||||||
return bPriority - aPriority;
|
|
||||||
} else {
|
|
||||||
return b.weight - a.weight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,11 +2,12 @@ import { Injectable } from '@angular/core';
|
|||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { combineLatest, Subject } from 'rxjs';
|
import { combineLatest, Subject } from 'rxjs';
|
||||||
import { map, pluck, shareReplay, startWith, switchMap } from 'rxjs/operators';
|
import { map, pluck, shareReplay, startWith, switchMap } from 'rxjs/operators';
|
||||||
import { PartyService } from 'src/app/party/party.service';
|
|
||||||
import { createDSL } from 'src/app/query-dsl';
|
import { createDSL } from 'src/app/query-dsl';
|
||||||
import { MerchantStatisticsService } from 'src/app/thrift-services/damsel/merchant-statistics.service';
|
import { MerchantStatisticsService } from 'src/app/thrift-services/damsel/merchant-statistics.service';
|
||||||
import { PaymentProcessingService } from 'src/app/thrift-services/damsel/payment-processing.service';
|
import { PaymentProcessingService } from 'src/app/thrift-services/damsel/payment-processing.service';
|
||||||
|
|
||||||
|
import { PartyService } from '../../papi/party.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ChargebackDetailsService {
|
export class ChargebackDetailsService {
|
||||||
private loadChargeback$ = new Subject<void>();
|
private loadChargeback$ = new Subject<void>();
|
||||||
|
@ -4,7 +4,7 @@ import * as moment from 'moment';
|
|||||||
import { ReplaySubject } from 'rxjs';
|
import { ReplaySubject } from 'rxjs';
|
||||||
import { debounceTime, filter, shareReplay, switchMap } from 'rxjs/operators';
|
import { debounceTime, filter, shareReplay, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { PartyService } from '../../../../party/party.service';
|
import { PartyService } from '../../../../papi/party.service';
|
||||||
import { FormValue } from '../form-value';
|
import { FormValue } from '../form-value';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<table mat-table [dataSource]="claims" fxFlex="100">
|
<table mat-table [dataSource]="claims">
|
||||||
<ng-container matColumnDef="claimID">
|
<ng-container matColumnDef="claimID">
|
||||||
<th mat-header-cell *matHeaderCellDef>Claim ID</th>
|
<th mat-header-cell *matHeaderCellDef>Claim ID</th>
|
||||||
<td mat-cell *matCellDef="let claim">{{ claim.id }}</td>
|
<td mat-cell *matCellDef="let claim">{{ claim.id }}</td>
|
||||||
|
@ -5,3 +5,7 @@ table {
|
|||||||
.action-cell {
|
.action-cell {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@ -35,7 +35,7 @@ export class ShopsTableComponent implements OnChanges {
|
|||||||
|
|
||||||
navigateToShop(shopID: string) {
|
navigateToShop(shopID: string) {
|
||||||
this.route.params.pipe(pluck('partyID')).subscribe((partyID) => {
|
this.route.params.pipe(pluck('partyID')).subscribe((partyID) => {
|
||||||
this.router.navigate([`/party-old/${partyID}/shop/${shopID}`]);
|
this.router.navigate([`/party/${partyID}/shop/${shopID}`]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@ import { PartyComponent } from './party.component';
|
|||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('../party-shops').then((m) => m.PartyShopsModule),
|
import('../party-shops').then((m) => m.PartyShopsModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'shop/:shopID',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('../shop-details').then((m) => m.ShopDetailsModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'invoice/:invoiceID/payment/:paymentID',
|
path: 'invoice/:invoiceID/payment/:paymentID',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
|
@ -63,7 +63,12 @@ export class PartyComponent {
|
|||||||
otherActiveUrlFragments: ['claim'],
|
otherActiveUrlFragments: ['claim'],
|
||||||
activateRoles: [ClaimManagementRole.GetClaims],
|
activateRoles: [ClaimManagementRole.GetClaims],
|
||||||
},
|
},
|
||||||
{ name: 'Shops', url: 'shops', activateRoles: [PartyRole.Get] },
|
{
|
||||||
|
name: 'Shops',
|
||||||
|
url: 'shops',
|
||||||
|
activateRoles: [PartyRole.Get],
|
||||||
|
otherActiveUrlFragments: ['shop'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Payment Routing Rules',
|
name: 'Payment Routing Rules',
|
||||||
url: 'payment-routing-rules',
|
url: 'payment-routing-rules',
|
||||||
|
@ -5,7 +5,7 @@ import { progress } from '@rbkmoney/partial-fetcher/dist/progress';
|
|||||||
import { combineLatest, of } from 'rxjs';
|
import { combineLatest, of } from 'rxjs';
|
||||||
import { map, pluck, shareReplay, switchMap, tap } from 'rxjs/operators';
|
import { map, pluck, shareReplay, switchMap, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { PartyService } from '../../party/party.service';
|
import { PartyService } from '../../papi/party.service';
|
||||||
import { QueryDSL } from '../../query-dsl';
|
import { QueryDSL } from '../../query-dsl';
|
||||||
import { MerchantStatisticsService } from '../../thrift-services/damsel/merchant-statistics.service';
|
import { MerchantStatisticsService } from '../../thrift-services/damsel/merchant-statistics.service';
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ export class PartiesTableComponent {
|
|||||||
this.menuItemSelected$.emit({ action, partyID });
|
this.menuItemSelected$.emit({ action, partyID });
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Wrong party action type.');
|
console.error('Wrong party action type.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
src/app/sections/shop-details/index.ts
Normal file
1
src/app/sections/shop-details/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './shop-details.module';
|
36
src/app/sections/shop-details/services/fetch-shop.service.ts
Normal file
36
src/app/sections/shop-details/services/fetch-shop.service.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { progress } from '@rbkmoney/partial-fetcher/dist/progress';
|
||||||
|
import { BehaviorSubject, merge, of, Subject } from 'rxjs';
|
||||||
|
import { catchError, filter, shareReplay, startWith, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { PartyService } from '../../../papi/party.service';
|
||||||
|
import { PartyID, ShopID } from '../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FetchShopService {
|
||||||
|
private getShop$ = new BehaviorSubject<{ partyID: PartyID; shopID: ShopID }>(null);
|
||||||
|
private hasError$: Subject<any> = new Subject();
|
||||||
|
|
||||||
|
shop$ = this.getShop$.pipe(
|
||||||
|
switchMap(({ partyID, shopID }) =>
|
||||||
|
this.partyService.getShop(partyID, shopID).pipe(
|
||||||
|
catchError((e) => {
|
||||||
|
this.hasError$.next(e);
|
||||||
|
this.snackBar.open('An error occurred while fetching shop', 'OK');
|
||||||
|
return of('error');
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
|
filter((result) => result !== 'error'),
|
||||||
|
shareReplay(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
inProgress$ = progress(this.getShop$, merge(this.shop$, this.hasError$)).pipe(startWith(true));
|
||||||
|
|
||||||
|
constructor(private partyService: PartyService, private snackBar: MatSnackBar) {}
|
||||||
|
|
||||||
|
getShop(partyID: PartyID, shopID: ShopID) {
|
||||||
|
this.getShop$.next({ shopID, partyID });
|
||||||
|
}
|
||||||
|
}
|
22
src/app/sections/shop-details/shop-details-routing.module.ts
Normal file
22
src/app/sections/shop-details/shop-details-routing.module.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { AppAuthGuardService, PartyRole } from '@cc/app/shared/services';
|
||||||
|
|
||||||
|
import { ShopDetailsComponent } from './shop-details.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild([
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: ShopDetailsComponent,
|
||||||
|
canActivate: [AppAuthGuardService],
|
||||||
|
data: {
|
||||||
|
roles: [PartyRole.Get],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ShopDetailsRoutingModule {}
|
21
src/app/sections/shop-details/shop-details.component.html
Normal file
21
src/app/sections/shop-details/shop-details.component.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<div fxLayout="column" fxLayoutGap="24px">
|
||||||
|
<cc-headline>Shop details</cc-headline>
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<cc-shop-main-info *ngIf="shop$ | async as shop" [shop]="shop"></cc-shop-main-info>
|
||||||
|
<div *ngIf="inProgress$ | async" fxLayout fxLayoutAlign="center center">
|
||||||
|
<mat-spinner diameter="64"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
<div class="cc-headline">Providers</div>
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<cc-shop-providers
|
||||||
|
[shopID]="shopID$ | async"
|
||||||
|
[partyID]="partyID$ | async"
|
||||||
|
[categoryID]="categoryID$ | async"
|
||||||
|
></cc-shop-providers>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
26
src/app/sections/shop-details/shop-details.component.ts
Normal file
26
src/app/sections/shop-details/shop-details.component.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { combineLatest } from 'rxjs';
|
||||||
|
import { pluck } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { FetchShopService } from './services/fetch-shop.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'shop-details.component.html',
|
||||||
|
providers: [FetchShopService],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ShopDetailsComponent {
|
||||||
|
partyID$ = this.route.params.pipe(pluck('partyID'));
|
||||||
|
shopID$ = this.route.params.pipe(pluck('shopID'));
|
||||||
|
|
||||||
|
shop$ = this.fetchShopService.shop$;
|
||||||
|
inProgress$ = this.fetchShopService.inProgress$;
|
||||||
|
categoryID$ = this.fetchShopService.shop$.pipe(pluck('category', 'id'));
|
||||||
|
|
||||||
|
constructor(private fetchShopService: FetchShopService, private route: ActivatedRoute) {
|
||||||
|
combineLatest([this.partyID$, this.shopID$]).subscribe(([partyID, shopID]) => {
|
||||||
|
this.fetchShopService.getShop(partyID, shopID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
27
src/app/sections/shop-details/shop-details.module.ts
Normal file
27
src/app/sections/shop-details/shop-details.module.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FlexModule } from '@angular/flex-layout';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
|
|
||||||
|
import { HeadlineModule } from '@cc/components/headline';
|
||||||
|
|
||||||
|
import { ShopDetailsRoutingModule } from './shop-details-routing.module';
|
||||||
|
import { ShopDetailsComponent } from './shop-details.component';
|
||||||
|
import { ShopMainInfoModule } from './shop-main-info';
|
||||||
|
import { ShopProvidersModule } from './shop-providers';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
ShopDetailsRoutingModule,
|
||||||
|
ShopMainInfoModule,
|
||||||
|
HeadlineModule,
|
||||||
|
FlexModule,
|
||||||
|
MatCardModule,
|
||||||
|
CommonModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
ShopProvidersModule,
|
||||||
|
],
|
||||||
|
declarations: [ShopDetailsComponent],
|
||||||
|
})
|
||||||
|
export class ShopDetailsModule {}
|
@ -0,0 +1,4 @@
|
|||||||
|
<ng-container *ngIf="category$ | async as category; else isLoading">
|
||||||
|
{{ category?.name }} (ID: {{ categoryID }})
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #isLoading> ID: {{ categoryID }} </ng-template>
|
@ -0,0 +1,26 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { CategoryService } from '../../../../../papi/category.service';
|
||||||
|
import { Category } from '../../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'category.component.html',
|
||||||
|
selector: 'cc-category',
|
||||||
|
providers: [CategoryService],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class CategoryComponent {
|
||||||
|
@Input() set category(categoryID: number) {
|
||||||
|
this.categoryID = categoryID;
|
||||||
|
this.category$ = this.categoryService.categories$.pipe(
|
||||||
|
map((categories) => categories.find((category) => category.id === categoryID))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
category$: Observable<Category>;
|
||||||
|
categoryID: number;
|
||||||
|
|
||||||
|
constructor(private categoryService: CategoryService) {}
|
||||||
|
}
|
1
src/app/sections/shop-details/shop-main-info/index.ts
Normal file
1
src/app/sections/shop-details/shop-main-info/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './shop-main-info.module';
|
@ -1,5 +1,7 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
import { getUnionKey } from '@cc/utils/get-union-key';
|
||||||
|
|
||||||
import { Blocking } from '../../../thrift-services/damsel/gen-model/domain';
|
import { Blocking } from '../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
@ -7,12 +9,13 @@ import { Blocking } from '../../../thrift-services/damsel/gen-model/domain';
|
|||||||
})
|
})
|
||||||
export class ShopBlockingPipe implements PipeTransform {
|
export class ShopBlockingPipe implements PipeTransform {
|
||||||
public transform(input: Blocking): string {
|
public transform(input: Blocking): string {
|
||||||
if (input.blocked) {
|
switch (getUnionKey(input)) {
|
||||||
|
case 'blocked':
|
||||||
return 'Blocked';
|
return 'Blocked';
|
||||||
}
|
case 'unblocked':
|
||||||
if (input.unblocked) {
|
|
||||||
return 'Unblocked';
|
return 'Unblocked';
|
||||||
}
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<div fxLayout="column" fxLayoutGap="16px">
|
||||||
|
<div
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="start center"
|
||||||
|
fxLayoutGap="16px"
|
||||||
|
fxLayout.lt-sm="column"
|
||||||
|
fxLayoutAlign.lt-sm="start"
|
||||||
|
>
|
||||||
|
<cc-details-item fxFlex title="Name">{{ shop.details.name }}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="Description">{{
|
||||||
|
shop.details.description ? shop.details.description : '-'
|
||||||
|
}}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="Category">
|
||||||
|
<cc-category [category]="shop.category.id"></cc-category>
|
||||||
|
</cc-details-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="start center"
|
||||||
|
fxLayoutGap="16px"
|
||||||
|
fxLayout.lt-sm="column"
|
||||||
|
fxLayoutAlign.lt-sm="start"
|
||||||
|
>
|
||||||
|
<cc-details-item fxFlex title="Created at">{{
|
||||||
|
shop.created_at | date: 'dd.MM.yyyy HH:mm:ss'
|
||||||
|
}}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="URL"
|
||||||
|
><a href="{{ shop.location.url }}">{{ shop.location.url }}</a></cc-details-item
|
||||||
|
>
|
||||||
|
<cc-details-item fxFlex title="Currency">{{
|
||||||
|
shop.account?.currency?.symbolic_code ? shop.account.currency.symbolic_code : '-'
|
||||||
|
}}</cc-details-item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="start center"
|
||||||
|
fxLayoutGap="16px"
|
||||||
|
fxLayout.lt-sm="column"
|
||||||
|
fxLayoutAlign.lt-sm="start"
|
||||||
|
>
|
||||||
|
<cc-details-item fxFlex title="Blocking">{{
|
||||||
|
shop.blocking | ccBlockingPipe
|
||||||
|
}}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="Suspension">
|
||||||
|
{{ shop.suspension | ccSuspensionPipe }}
|
||||||
|
</cc-details-item>
|
||||||
|
<div fxFlex></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="start center"
|
||||||
|
fxLayoutGap="16px"
|
||||||
|
fxLayout.lt-sm="column"
|
||||||
|
fxLayoutAlign.lt-sm="start"
|
||||||
|
>
|
||||||
|
<cc-details-item fxFlex title="Payout tool ID">{{
|
||||||
|
shop.payout_tool_id ? shop.payout_tool_id : '-'
|
||||||
|
}}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="Shop ID">{{ shop.id }}</cc-details-item>
|
||||||
|
<cc-details-item fxFlex title="Contract ID">{{ shop.contract_id }}</cc-details-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,13 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
import { Shop } from '../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'cc-shop-main-info',
|
||||||
|
templateUrl: 'shop-main-info.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ShopMainInfoComponent {
|
||||||
|
@Input()
|
||||||
|
shop: Shop;
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FlexModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
|
import { StatusModule } from '@cc/app/shared/components';
|
||||||
|
import { DetailsItemModule } from '@cc/components/details-item';
|
||||||
|
|
||||||
|
import { CategoryComponent } from './components/category/category.component';
|
||||||
|
import { ShopBlockingPipe } from './shop-blocking.pipe';
|
||||||
|
import { ShopMainInfoComponent } from './shop-main-info.component';
|
||||||
|
import { ShopSuspensionPipe } from './shop-suspension.pipe';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [FlexModule, DetailsItemModule, StatusModule, CommonModule],
|
||||||
|
declarations: [ShopMainInfoComponent, CategoryComponent, ShopBlockingPipe, ShopSuspensionPipe],
|
||||||
|
exports: [ShopMainInfoComponent],
|
||||||
|
})
|
||||||
|
export class ShopMainInfoModule {}
|
@ -1,5 +1,7 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
import { getUnionKey } from '@cc/utils/get-union-key';
|
||||||
|
|
||||||
import { Suspension } from '../../../thrift-services/damsel/gen-model/domain';
|
import { Suspension } from '../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
@ -7,12 +9,13 @@ import { Suspension } from '../../../thrift-services/damsel/gen-model/domain';
|
|||||||
})
|
})
|
||||||
export class ShopSuspensionPipe implements PipeTransform {
|
export class ShopSuspensionPipe implements PipeTransform {
|
||||||
public transform(input: Suspension): string {
|
public transform(input: Suspension): string {
|
||||||
if (input.active) {
|
switch (getUnionKey(input)) {
|
||||||
|
case 'active':
|
||||||
return 'Active';
|
return 'Active';
|
||||||
}
|
case 'suspended':
|
||||||
if (input.suspended) {
|
|
||||||
return 'Suspended';
|
return 'Suspended';
|
||||||
}
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<div class="mat-dialog-title">Add provider</div>
|
<div class="mat-dialog-title">Add terminal</div>
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
<mat-horizontal-stepper [linear]="true">
|
<mat-horizontal-stepper [linear]="true">
|
||||||
<mat-step [stepControl]="providerForm">
|
<mat-step [stepControl]="providerForm">
|
||||||
@ -6,7 +6,7 @@
|
|||||||
<div fxLayout="column" fxLayoutGap="20px">
|
<div fxLayout="column" fxLayoutGap="20px">
|
||||||
<cc-select-provider
|
<cc-select-provider
|
||||||
[providers]="providers$ | async"
|
[providers]="providers$ | async"
|
||||||
(providerIdSelected)="providerFormChanged($event)"
|
(providerIDSelected)="providerIDSelected($event)"
|
||||||
></cc-select-provider>
|
></cc-select-provider>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
@ -23,10 +23,10 @@
|
|||||||
<mat-step [stepControl]="terminalForm">
|
<mat-step [stepControl]="terminalForm">
|
||||||
<ng-template matStepLabel>Select or create terminal:</ng-template>
|
<ng-template matStepLabel>Select or create terminal:</ng-template>
|
||||||
<div fxLayout="column" fxLayoutGap="20px">
|
<div fxLayout="column" fxLayoutGap="20px">
|
||||||
<cc-select-terminal
|
<cc-terminals-table
|
||||||
[terminals]="terminals$ | async"
|
[terminals]="terminals$ | async"
|
||||||
(terminalIdSelected)="terminalFormChanged($event)"
|
(terminalIDSelected)="terminalIDSelected($event)"
|
||||||
></cc-select-terminal>
|
></cc-terminals-table>
|
||||||
<div><button matStepperPrevious mat-button color="primary">BACK</button></div>
|
<div><button matStepperPrevious mat-button color="primary">BACK</button></div>
|
||||||
</div>
|
</div>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
@ -37,11 +37,13 @@
|
|||||||
<button
|
<button
|
||||||
mat-button
|
mat-button
|
||||||
(click)="add()"
|
(click)="add()"
|
||||||
[disabled]="!(providerForm.valid && terminalForm.valid) || isLoading"
|
[disabled]="!(providerForm.valid && terminalForm.valid) || (inProgress$ | async)"
|
||||||
>
|
>
|
||||||
ADD
|
ADD
|
||||||
</button>
|
</button>
|
||||||
<button mat-button [mat-dialog-close]="false" [disabled]="isLoading">CANCEL</button>
|
<button mat-button [mat-dialog-close]="false" [disabled]="inProgress$ | async">
|
||||||
|
CANCEL
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar *ngIf="inProgress$ | async" mode="indeterminate"></mat-progress-bar>
|
||||||
</mat-dialog-actions>
|
</mat-dialog-actions>
|
@ -0,0 +1,52 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { DomainCacheService } from '../../../../thrift-services/damsel/domain-cache.service';
|
||||||
|
import { PartyID, ShopID } from '../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
import { AddTerminalDialogResponse } from '../types/add-terminal-dialog-response';
|
||||||
|
import { AddTerminalDecisionService } from './services/add-terminal-decision';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'add-terminal-dialog.component.html',
|
||||||
|
providers: [AddTerminalDecisionService],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class AddTerminalDialogComponent {
|
||||||
|
providers$ = this.addTerminalDecisionService.getProviders(this.data.categoryID);
|
||||||
|
terminals$ = this.domainCacheService.getObjects('terminal');
|
||||||
|
inProgress$ = this.addTerminalDecisionService.inProgress$;
|
||||||
|
|
||||||
|
providerForm = this.addTerminalDecisionService.providerForm;
|
||||||
|
terminalForm = this.addTerminalDecisionService.terminalForm;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private domainCacheService: DomainCacheService,
|
||||||
|
private addTerminalDecisionService: AddTerminalDecisionService,
|
||||||
|
public dialogRef: MatDialogRef<AddTerminalDialogComponent, AddTerminalDialogResponse>,
|
||||||
|
@Inject(MAT_DIALOG_DATA)
|
||||||
|
public data: {
|
||||||
|
shopID: ShopID;
|
||||||
|
partyID: PartyID;
|
||||||
|
categoryID: number;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
this.addTerminalDecisionService.terminalAdded$.subscribe(() => {
|
||||||
|
return this.dialogRef.close('added');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
providerIDSelected(id: number) {
|
||||||
|
this.providerForm.setValue({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
terminalIDSelected(id: number) {
|
||||||
|
this.terminalForm.setValue({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
add() {
|
||||||
|
this.addTerminalDecisionService.add({
|
||||||
|
partyID: this.data.partyID,
|
||||||
|
shopID: this.data.shopID,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FlexModule } from '@angular/flex-layout';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||||
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
|
||||||
|
import { AddTerminalDialogComponent } from './add-terminal-dialog.component';
|
||||||
|
import { SelectProviderComponent, TerminalsTableComponent } from './components';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [AddTerminalDialogComponent, SelectProviderComponent, TerminalsTableComponent],
|
||||||
|
entryComponents: [AddTerminalDialogComponent],
|
||||||
|
imports: [
|
||||||
|
MatDialogModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatProgressBarModule,
|
||||||
|
CommonModule,
|
||||||
|
MatStepperModule,
|
||||||
|
FlexModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatPaginatorModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AddTerminalDialogModule {}
|
@ -0,0 +1,2 @@
|
|||||||
|
export * from './select-provider';
|
||||||
|
export * from './terminals-table';
|
@ -0,0 +1 @@
|
|||||||
|
export * from './select-provider.component';
|
@ -1,5 +1,6 @@
|
|||||||
import { SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import {
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
@ -12,16 +13,18 @@ import {
|
|||||||
import { MatPaginator } from '@angular/material/paginator';
|
import { MatPaginator } from '@angular/material/paginator';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
|
||||||
import { ProviderObject } from '../../../../thrift-services/damsel/gen-model/domain';
|
import { ProviderObject } from '../../../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-select-provider',
|
|
||||||
templateUrl: 'select-provider.component.html',
|
templateUrl: 'select-provider.component.html',
|
||||||
styleUrls: ['../add-provider.component.scss'],
|
selector: 'cc-select-provider',
|
||||||
|
styleUrls: ['select-provider.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class SelectProviderComponent implements OnInit, OnChanges {
|
export class SelectProviderComponent implements OnInit, OnChanges {
|
||||||
@Input() providers: ProviderObject[];
|
@Input() providers: ProviderObject[];
|
||||||
@Output() providerIdSelected: EventEmitter<number> = new EventEmitter();
|
|
||||||
|
@Output() providerIDSelected: EventEmitter<number> = new EventEmitter();
|
||||||
|
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||||
|
|
||||||
@ -43,7 +46,7 @@ export class SelectProviderComponent implements OnInit, OnChanges {
|
|||||||
this.selection.changed.subscribe(() => {
|
this.selection.changed.subscribe(() => {
|
||||||
const providerSelection = Array.from(this.selection.selected.values());
|
const providerSelection = Array.from(this.selection.selected.values());
|
||||||
if (providerSelection.length > 0) {
|
if (providerSelection.length > 0) {
|
||||||
this.providerIdSelected.emit(providerSelection[0].ref.id);
|
this.providerIDSelected.emit(providerSelection[0].ref.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './terminals-table.component';
|
@ -0,0 +1,8 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th,
|
||||||
|
.td {
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import {
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
@ -12,17 +13,18 @@ import {
|
|||||||
import { MatPaginator } from '@angular/material/paginator';
|
import { MatPaginator } from '@angular/material/paginator';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
|
||||||
import { TerminalObject } from '../../../../../thrift-services/damsel/gen-model/domain';
|
import { TerminalObject } from '../../../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-terminals-table',
|
selector: 'cc-terminals-table',
|
||||||
templateUrl: 'terminals-table.component.html',
|
templateUrl: 'terminals-table.component.html',
|
||||||
styleUrls: ['../../add-provider.component.scss'],
|
styleUrls: ['terminals-table.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class TerminalsTableComponent implements OnInit, OnChanges {
|
export class TerminalsTableComponent implements OnInit, OnChanges {
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||||
@Input() terminals: TerminalObject[];
|
@Input() terminals: TerminalObject[];
|
||||||
@Output() terminalIdSelected: EventEmitter<number> = new EventEmitter();
|
@Output() terminalIDSelected: EventEmitter<number> = new EventEmitter();
|
||||||
|
|
||||||
displayedColumns: string[] = ['select', 'id', 'name', 'description'];
|
displayedColumns: string[] = ['select', 'id', 'name', 'description'];
|
||||||
dataSource: MatTableDataSource<TerminalObject> = new MatTableDataSource([]);
|
dataSource: MatTableDataSource<TerminalObject> = new MatTableDataSource([]);
|
||||||
@ -35,7 +37,7 @@ export class TerminalsTableComponent implements OnInit, OnChanges {
|
|||||||
this.selection.changed.subscribe(() => {
|
this.selection.changed.subscribe(() => {
|
||||||
const terminalSelection = Array.from(this.selection.selected.values());
|
const terminalSelection = Array.from(this.selection.selected.values());
|
||||||
if (terminalSelection.length > 0) {
|
if (terminalSelection.length > 0) {
|
||||||
this.terminalIdSelected.emit(terminalSelection[0].ref.id);
|
this.terminalIDSelected.emit(terminalSelection[0].ref.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './add-terminal-dialog.module';
|
@ -0,0 +1,72 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { progress } from '@rbkmoney/partial-fetcher/dist/progress';
|
||||||
|
import { merge, Observable, Subject } from 'rxjs';
|
||||||
|
import { map, shareReplay, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddDecisionToProvider,
|
||||||
|
DomainTypedManager,
|
||||||
|
} from '../../../../../../thrift-services/damsel';
|
||||||
|
import { DomainCacheService } from '../../../../../../thrift-services/damsel/domain-cache.service';
|
||||||
|
import {
|
||||||
|
PartyID,
|
||||||
|
ProviderObject,
|
||||||
|
ShopID,
|
||||||
|
} from '../../../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
import { addDecisionToProviderCommit } from '../../../../../../thrift-services/damsel/operations';
|
||||||
|
import {
|
||||||
|
filterProvidersByCategoryId,
|
||||||
|
filterProvidersByTerminalSelector,
|
||||||
|
} from '../../../../../../thrift-services/filters';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AddTerminalDecisionService {
|
||||||
|
private add$ = new Subject<{ shopID: ShopID; partyID: PartyID }>();
|
||||||
|
|
||||||
|
providerForm = this.prepareForm();
|
||||||
|
terminalForm = this.prepareForm();
|
||||||
|
error$ = new Subject();
|
||||||
|
|
||||||
|
terminalAdded$ = this.add$.pipe(
|
||||||
|
map((params) => ({
|
||||||
|
...params,
|
||||||
|
providerID: this.providerForm.value.id,
|
||||||
|
terminalID: this.terminalForm.value.id,
|
||||||
|
})),
|
||||||
|
switchMap((params) =>
|
||||||
|
this.domainTypedManager.getProviderFromParams<AddDecisionToProvider>(params)
|
||||||
|
),
|
||||||
|
switchMap(([params, providerObject]) =>
|
||||||
|
this.domainCacheService.commit(addDecisionToProviderCommit(providerObject, params))
|
||||||
|
),
|
||||||
|
shareReplay(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
inProgress$ = progress(this.add$, merge(this.terminalAdded$, this.error$));
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private domainCacheService: DomainCacheService,
|
||||||
|
private domainTypedManager: DomainTypedManager,
|
||||||
|
private fb: FormBuilder
|
||||||
|
) {
|
||||||
|
this.terminalAdded$.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
add(params: { shopID: ShopID; partyID: PartyID }) {
|
||||||
|
this.add$.next(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProviders(categoryID: number): Observable<ProviderObject[]> {
|
||||||
|
return this.domainCacheService.getObjects('provider').pipe(
|
||||||
|
map((objects) => filterProvidersByTerminalSelector(objects, 'decisions')),
|
||||||
|
map((objects) => filterProvidersByCategoryId(objects, categoryID))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private prepareForm(): FormGroup {
|
||||||
|
return this.fb.group({
|
||||||
|
id: ['', Validators.required],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './add-terminal-decision.service';
|
@ -0,0 +1 @@
|
|||||||
|
export * from './add-terminal-decision';
|
@ -0,0 +1,39 @@
|
|||||||
|
<div class="mat-dialog-title">
|
||||||
|
{{ data.type === terminalActionTypes.editWeight ? 'Edit weight' : null }}
|
||||||
|
{{ data.type === terminalActionTypes.editPriority ? 'Edit priority' : null }}
|
||||||
|
</div>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<mat-form-field fxFlex>
|
||||||
|
<input matInput type="number" [formControl]="editValueControl" />
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-dialog-content>
|
||||||
|
|
||||||
|
<div
|
||||||
|
mat-dialog-actions
|
||||||
|
class="dialog-actions"
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayout.xs="column"
|
||||||
|
fxLayoutAlign="space-between stretch"
|
||||||
|
fxLayoutGap="20px"
|
||||||
|
fxLayoutGap.xs="10px"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
fxFlex
|
||||||
|
fxFlex.xs="none"
|
||||||
|
(click)="save()"
|
||||||
|
[disabled]="!editValueControl.valid || (inProgress$ | async)"
|
||||||
|
>
|
||||||
|
SAVE
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
fxFlex
|
||||||
|
fxFlex.xs="none"
|
||||||
|
[mat-dialog-close]="false"
|
||||||
|
[disabled]="inProgress$ | async"
|
||||||
|
>
|
||||||
|
CANCEL
|
||||||
|
</button>
|
||||||
|
<mat-progress-bar mode="indeterminate" *ngIf="inProgress$ | async"></mat-progress-bar>
|
||||||
|
</div>
|
@ -0,0 +1,73 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||||
|
import { FormControl, Validators } from '@angular/forms';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { EditTerminalDecisionPropertyForShopService } from '../../../../../thrift-services/damsel';
|
||||||
|
import { PartyID, ShopID } from '../../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
import { TerminalID } from '../../../../../thrift-services/fistful/gen-model/fistful';
|
||||||
|
import { EditTerminalDialogResponse, TerminalActionTypes } from '../../types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'edit-terminal-dialog.component.html',
|
||||||
|
providers: [EditTerminalDecisionPropertyForShopService],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class EditTerminalDialogComponent {
|
||||||
|
editValueControl = new FormControl('', [Validators.required]);
|
||||||
|
terminalActionTypes = TerminalActionTypes;
|
||||||
|
inProgress$ = this.editTerminalDecisionPropertyForShopService.inProgress$;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private editTerminalDecisionPropertyForShopService: EditTerminalDecisionPropertyForShopService,
|
||||||
|
public dialogRef: MatDialogRef<EditTerminalDialogComponent, EditTerminalDialogResponse>,
|
||||||
|
@Inject(MAT_DIALOG_DATA)
|
||||||
|
public data: {
|
||||||
|
type: TerminalActionTypes;
|
||||||
|
terminalID: TerminalID;
|
||||||
|
providerID: number;
|
||||||
|
shopID: ShopID;
|
||||||
|
partyID: PartyID;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
this.editTerminalDecisionPropertyForShopService.edited$.subscribe(() =>
|
||||||
|
this.dialogRef.close('edited')
|
||||||
|
);
|
||||||
|
this.editTerminalDecisionPropertyForShopService.inProgress$.subscribe((progress) => {
|
||||||
|
if (progress) {
|
||||||
|
this.editValueControl.disable();
|
||||||
|
} else {
|
||||||
|
this.editValueControl.enable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
const editParams = {
|
||||||
|
providerID: this.data.providerID,
|
||||||
|
terminalID: this.data.terminalID,
|
||||||
|
partyID: this.data.partyID,
|
||||||
|
shopID: this.data.shopID,
|
||||||
|
value: this.editValueControl.value,
|
||||||
|
};
|
||||||
|
switch (this.data.type) {
|
||||||
|
case TerminalActionTypes.editWeight:
|
||||||
|
this.editTerminalDecisionPropertyForShopService.editTerminalDecisionPropertyForShop(
|
||||||
|
{
|
||||||
|
...editParams,
|
||||||
|
property: 'weight',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case TerminalActionTypes.editPriority:
|
||||||
|
this.editTerminalDecisionPropertyForShopService.editTerminalDecisionPropertyForShop(
|
||||||
|
{
|
||||||
|
...editParams,
|
||||||
|
property: 'priority',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error('Wrong terminal action!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './edit-terminal-dialog.component';
|
@ -0,0 +1 @@
|
|||||||
|
export * from './edit-terminal-dialog';
|
1
src/app/sections/shop-details/shop-providers/index.ts
Normal file
1
src/app/sections/shop-details/shop-providers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './shop-providers.module';
|
@ -0,0 +1 @@
|
|||||||
|
export * from './provider.module';
|
@ -0,0 +1,5 @@
|
|||||||
|
<div class="mat-body-1">{{ providerInfo.provider.data.name }}</div>
|
||||||
|
<cc-terminals-info-table
|
||||||
|
[terminalsInfo]="providerInfo.terminalsInfo"
|
||||||
|
(action)="action.emit($event)"
|
||||||
|
></cc-terminals-info-table>
|
@ -0,0 +1,23 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
import { PartyID, ShopID } from '../../../../thrift-services/damsel/gen-model/domain';
|
||||||
|
import { ProviderInfo, TerminalAction } from '../types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'cc-provider',
|
||||||
|
templateUrl: 'provider.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ProviderComponent {
|
||||||
|
@Input()
|
||||||
|
providerInfo: ProviderInfo;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
partyID: PartyID;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
shopID: ShopID;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
action: EventEmitter<TerminalAction> = new EventEmitter();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FlexModule } from '@angular/flex-layout';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
|
||||||
|
import { ProviderComponent } from './provider.component';
|
||||||
|
import { TerminalsInfoTableModule } from './terminals-info-table/terminals-info-table.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [ProviderComponent],
|
||||||
|
exports: [ProviderComponent],
|
||||||
|
imports: [MatCardModule, FlexModule, TerminalsInfoTableModule],
|
||||||
|
})
|
||||||
|
export class ProviderModule {}
|
@ -0,0 +1,66 @@
|
|||||||
|
<table mat-table [dataSource]="terminalsInfo" fxFlex>
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Name</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.terminal.data.name }}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="description">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Description</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">
|
||||||
|
{{ terminalInfo.terminal.data.description }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="type">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Type</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.predicateType }}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="priority">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Priority</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">
|
||||||
|
{{ terminalInfo.priority }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="weight">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Weight</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">{{ terminalInfo.weight }}</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="status">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="cc-caption">Status</th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo">
|
||||||
|
{{ !terminalInfo.disabled | ccIsActive }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="action-cell"></th>
|
||||||
|
<td mat-cell *matCellDef="let terminalInfo" class="action-cell">
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="menu">
|
||||||
|
<mat-icon>more_vert</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-menu #menu="matMenu">
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="actions(terminalActionTypes.editWeight, terminalInfo.terminal.ref.id)"
|
||||||
|
>
|
||||||
|
Edit weight
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="
|
||||||
|
actions(terminalActionTypes.editPriority, terminalInfo.terminal.ref.id)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Edit priority
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="
|
||||||
|
actions(terminalActionTypes.removeTerminal, terminalInfo.terminal.ref.id)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Remove terminal
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let shop; columns: displayedColumns"></tr>
|
||||||
|
</table>
|
@ -1,3 +1,3 @@
|
|||||||
cc-terminal {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user