FE-1041: show more webhooks (#197)

* FE-1041: show more webhooks
This commit is contained in:
Aleksandra Usacheva 2020-04-17 18:10:48 +03:00 committed by GitHub
parent fba331d92e
commit 64e0676661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 112 additions and 36 deletions

View File

@ -1,4 +1,4 @@
.dsh-integrations {
max-width: 720px;
margin: auto;
margin: auto auto 20px;
}

View File

@ -1,43 +1,71 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import sortBy from 'lodash.sortby';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { catchError, filter, map, shareReplay, switchMap } from 'rxjs/operators';
import { BehaviorSubject, combineLatest, Observable, of, Subject } from 'rxjs';
import { catchError, filter, first, map, pluck, shareReplay, switchMap } from 'rxjs/operators';
import { Webhook } from '../../../../api-codegen/capi/swagger-codegen';
import { WebhooksService } from '../../../../api/webhooks';
import { booleanDebounceTime, progress, SHARE_REPLAY_CONF } from '../../../../custom-operators';
const WEBHOOK_LIMIT = 10;
@Injectable()
export class ReceiveWebhooksService {
private webhooksState$ = new BehaviorSubject(null);
private receiveWebhooks$ = new Subject();
private webhooksOffset$: BehaviorSubject<number> = new BehaviorSubject(WEBHOOK_LIMIT);
private webhooksState$: BehaviorSubject<Webhook[]> = new BehaviorSubject(null);
private receiveWebhooks$: Subject<void> = new Subject();
webhooks$: Observable<Webhook[]> = this.webhooksState$.pipe(
filter(s => !!s),
map(w => sortBy(w, i => !i.active)),
switchMap(webhooks => combineLatest([this.webhooksOffset$, of(webhooks)])),
map(([offset, webhooks]) => webhooks.slice(0, offset)),
shareReplay(SHARE_REPLAY_CONF)
);
webhooksReceived$ = this.webhooks$.pipe(
map(s => !!s),
shareReplay(SHARE_REPLAY_CONF)
);
isLoading$ = progress(this.receiveWebhooks$, this.webhooksState$).pipe(
isLoading$: Observable<boolean> = progress(this.receiveWebhooks$, this.webhooks$).pipe(
booleanDebounceTime(),
shareReplay(SHARE_REPLAY_CONF)
);
hasMore$: Observable<boolean> = combineLatest([this.webhooksState$, this.webhooksOffset$]).pipe(
map(([webhooks, offset]) => webhooks?.length > offset),
shareReplay(SHARE_REPLAY_CONF)
);
constructor(
private webhooksService: WebhooksService,
private snackBar: MatSnackBar,
private transloco: TranslocoService
private transloco: TranslocoService,
private route: ActivatedRoute,
private router: Router
) {
this.isLoading$.subscribe();
this.route.queryParams
.pipe(
first(),
pluck('offset'),
filter(l => !!l),
map(offset => parseInt(offset, 10))
)
.subscribe(offset => {
this.webhooksOffset$.next(offset);
});
this.webhooksOffset$.subscribe(offset => {
this.router.navigate([location.pathname], {
queryParams: {
offset
}
});
});
this.receiveWebhooks$
.pipe(
switchMap(_ =>
switchMap(() =>
this.webhooksService.getWebhooks().pipe(
catchError(err => {
console.error(err);
@ -47,10 +75,16 @@ export class ReceiveWebhooksService {
)
)
)
.subscribe(webhooks => this.webhooksState$.next(webhooks));
.subscribe(webhooks => {
this.webhooksState$.next(webhooks);
});
}
receiveWebhooks() {
this.receiveWebhooks$.next();
}
getMoreWebhooks() {
this.webhooksOffset$.next(this.webhooksOffset$.value + WEBHOOK_LIMIT);
}
}

View File

@ -1,4 +1,4 @@
import { Component, Inject, Input, OnChanges, SimpleChanges } from '@angular/core';
import { ChangeDetectionStrategy, Component, Inject, Input, OnChanges, SimpleChanges } from '@angular/core';
import isEqual from 'lodash.isequal';
import { pluck } from 'rxjs/operators';
@ -11,7 +11,8 @@ type InvoicesEventTypesEnum = InvoicesTopic.EventTypesEnum;
@Component({
selector: 'dsh-webhook-panel',
templateUrl: 'webhook-panel.component.html',
providers: [WebhookPanelService]
providers: [WebhookPanelService],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class WebhookPanelComponent implements OnChanges {
@Input()

View File

@ -16,12 +16,10 @@
<dsh-spinner></dsh-spinner>
</div>
<dsh-empty-search-result
*ngIf="!(webhooks$ | async)?.length && (webhooksReceived$ | async)"
[text]="t.emptyResult"
></dsh-empty-search-result>
<dsh-empty-search-result *ngIf="(webhooks$ | async)?.length === 0" [text]="t.emptyResult"></dsh-empty-search-result>
<div fxLayout="column" [fxLayoutGap]="layoutGap" *ngIf="!(isLoading$ | async)">
<dsh-webhook-panel *ngFor="let webhook of webhooks$ | async" [webhook]="webhook"></dsh-webhook-panel>
<dsh-show-more-panel *ngIf="hasMore$ | async" (showMore)="getMoreWebhooks()"></dsh-show-more-panel>
</div>
</div>

View File

@ -5,12 +5,13 @@ import { CreateWebhookService } from './create-webhook.service';
import { ReceiveWebhooksService } from './receive-webhooks.service';
@Component({
templateUrl: 'webhooks.component.html'
templateUrl: 'webhooks.component.html',
providers: [ReceiveWebhooksService, CreateWebhookService]
})
export class WebhooksComponent implements OnInit {
webhooks$ = this.receiveWebhooksService.webhooks$;
isLoading$ = this.receiveWebhooksService.isLoading$;
webhooksReceived$ = this.receiveWebhooksService.webhooksReceived$;
hasMore$ = this.receiveWebhooksService.hasMore$;
constructor(
private receiveWebhooksService: ReceiveWebhooksService,
@ -25,4 +26,8 @@ export class WebhooksComponent implements OnInit {
createWebhook() {
this.createWebhookService.createWebhook();
}
getMoreWebhooks() {
this.receiveWebhooksService.getMoreWebhooks();
}
}

View File

@ -12,12 +12,10 @@ import { TranslocoModule } from '@ngneat/transloco';
import { ButtonModule } from '@dsh/components/buttons';
import { EmptySearchResultModule } from '@dsh/components/empty-search-result';
import { SpinnerModule } from '@dsh/components/indicators';
import { ShowMorePanelModule } from '@dsh/components/show-more-panel';
import { ShopService } from '../../../../api/shop';
import { WebhooksModule as ApiWebhooksModule } from '../../../../api/webhooks';
import { CreateWebhookService } from './create-webhook.service';
import { CreateWebhookComponent } from './create-webhook/create-webhook.component';
import { ReceiveWebhooksService } from './receive-webhooks.service';
import { WebhookPanelModule } from './webhook-panel/webhook-panel.module';
import { WebhooksRoutingModule } from './webhooks-routing.module';
import { WebhooksComponent } from './webhooks.component';
@ -38,10 +36,10 @@ import { WebhooksComponent } from './webhooks.component';
TranslocoModule,
WebhookPanelModule,
SpinnerModule,
EmptySearchResultModule
EmptySearchResultModule,
ShowMorePanelModule
],
declarations: [WebhooksComponent, CreateWebhookComponent],
entryComponents: [CreateWebhookComponent],
providers: [ReceiveWebhooksService, CreateWebhookService, ShopService]
entryComponents: [CreateWebhookComponent]
})
export class WebhooksModule {}

View File

@ -66,7 +66,7 @@ export class SearchFormService {
}
private initForm(defaultLimit = 20): FormGroup {
const form = this.fb.group({
return this.fb.group({
date: {
begin: moment().startOf('month'),
end: moment().endOf('month')
@ -88,6 +88,5 @@ export class SearchFormService {
paymentAmountTo: '',
rrn: ''
});
return form;
}
}

View File

@ -12,11 +12,8 @@
<dsh-payouts-search-form></dsh-payouts-search-form>
<ng-container *ngIf="!(isInit$ | async)">
<dsh-payouts-panels-list></dsh-payouts-panels-list>
<dsh-card *ngIf="hasMore$ | async" class="dsh-payouts-show-more" fxLayout>
<button dsh-button (click)="fetchMore()" [disabled]="isLoading$ | async" fxFlex *transloco="let t">
{{ (isLoading$ | async) ? t.loading : t.showMore }}
</button>
</dsh-card>
<dsh-show-more-panel *ngIf="hasMore$ | async" (showMore)="fetchMore()" [isLoading]="isLoading$ | async">
</dsh-show-more-panel>
<div *ngIf="!(payouts$ | async)?.length && !(doAction$ | async)" class="mat-headline dsh-payouts-empty">
<ng-container *transloco="let t">
{{ t.emptySearchResult }}

View File

@ -13,6 +13,7 @@ import { RangeDatepickerModule } from '@dsh/components/form-controls';
import { SpinnerModule } from '@dsh/components/indicators';
import { LayoutModule } from '@dsh/components/layout';
import { ScrollUpModule } from '@dsh/components/navigation';
import { ShowMorePanelModule } from '@dsh/components/show-more-panel';
import { SearchModule } from '../../../api';
import { PayoutPanelModule } from './payouts-panels-list';
@ -39,7 +40,8 @@ import { SearchFormComponent } from './search-form';
MatInputModule,
SpinnerModule,
ScrollUpModule,
RangeDatepickerModule
RangeDatepickerModule,
ShowMorePanelModule
],
declarations: [PayoutsComponent, SearchFormComponent],
exports: [PayoutsComponent]

View File

@ -0,0 +1 @@
export * from './show-more-panel.module';

View File

@ -0,0 +1,5 @@
<dsh-card class="dsh-show-more-panel" fxLayout>
<button dsh-button (click)="getMore()" [disabled]="isLoading" fxFlex *transloco="let t">
{{ isLoading ? t.loading : t.showMore }}
</button>
</dsh-card>

View File

@ -0,0 +1,3 @@
.dsh-show-more-panel {
padding: 10px 20px;
}

View File

@ -0,0 +1,18 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'dsh-show-more-panel',
templateUrl: 'show-more-panel.component.html',
styleUrls: ['show-more-panel.component.scss']
})
export class ShowMorePanelComponent {
@Input()
isLoading = false;
@Output()
showMore: EventEmitter<void> = new EventEmitter();
getMore() {
this.showMore.emit();
}
}

View File

@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { FlexModule } from '@angular/flex-layout';
import { TranslocoModule } from '@ngneat/transloco';
import { ButtonModule } from '@dsh/components/buttons';
import { CardModule } from '@dsh/components/layout';
import { ShowMorePanelComponent } from './show-more-panel.component';
@NgModule({
declarations: [ShowMorePanelComponent],
imports: [CardModule, ButtonModule, FlexModule, TranslocoModule],
exports: [ShowMorePanelComponent]
})
export class ShowMorePanelModule {}