[frontend] Add spinner when loading

This commit is contained in:
Cathy Hu 2020-09-11 15:38:46 +02:00
parent d6fc38504a
commit bc4b57aaef
17 changed files with 475 additions and 348 deletions

View file

@ -10,40 +10,46 @@
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
</form> </form>
<ng-container *ngIf="badwords$ | async as badwords"> <ng-container *ngIf="badwords$ | loading | async as badwords">
<mat-list *ngIf="badwords.length !== 0; else empty"> <ng-template [ngIf]="badwords.value">
<mat-list-item *ngFor="let badword of badwords"> <mat-list *ngIf="badwords.value.length !== 0; else empty">
<div class="entry"> <mat-list-item *ngFor="let badword of badwords.value">
<div class="regex"> <div class="entry">
{{ badword.pattern }} <div class="regex">
{{ badword.pattern }}
</div>
<button
mat-icon-button
color="primary"
aria-label="Edit"
class="button"
(click)="onEdit(badword.id)"
>
<mat-icon>edit</mat-icon>
</button>
<button
mat-icon-button
color="warn"
aria-label="Delete"
class="button"
(click)="onDelete(badword.id)"
>
<mat-icon>delete</mat-icon>
</button>
</div> </div>
<button <mat-divider></mat-divider>
mat-icon-button </mat-list-item>
color="primary" </mat-list>
aria-label="Edit" <ng-template #empty>
class="button" <div class="error-msg">No badwords configured yet.</div>
(click)="onEdit(badword.id)" </ng-template>
> </ng-template>
<mat-icon>edit</mat-icon> <ng-template [ngIf]="badwords.error"
</button> ><mat-icon class="warning">warning</mat-icon></ng-template
<button >
mat-icon-button <ng-template [ngIf]="badwords.loading">
color="warn" <mat-spinner [diameter]="45" class="spinner"></mat-spinner>
aria-label="Delete" </ng-template>
class="button"
(click)="onDelete(badword.id)"
>
<mat-icon>delete</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
</mat-list-item>
</mat-list>
</ng-container> </ng-container>
<ng-template #empty>
<div class="error-msg">
No badwords configured yet.
</div>
</ng-template>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View file

@ -10,40 +10,46 @@
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
</form> </form>
<ng-container *ngIf="triggers$ | async as triggers"> <ng-container *ngIf="triggers$ | loading | async as triggers">
<mat-list *ngIf="triggers.length !== 0; else empty"> <ng-template [ngIf]="triggers.value">
<mat-list-item *ngFor="let trigger of triggers"> <mat-list *ngIf="triggers.value.length !== 0; else empty">
<div class="entry"> <mat-list-item *ngFor="let trigger of triggers.value">
<div class="regex"> <div class="entry">
{{ trigger.pattern }} <div class="regex">
{{ trigger.pattern }}
</div>
<button
mat-icon-button
color="primary"
aria-label="Edit"
class="button"
(click)="onEdit(trigger.id)"
>
<mat-icon>edit</mat-icon>
</button>
<button
mat-icon-button
color="warn"
aria-label="Delete"
class="button"
(click)="onDelete(trigger.id)"
>
<mat-icon>delete</mat-icon>
</button>
</div> </div>
<button <mat-divider></mat-divider>
mat-icon-button </mat-list-item>
color="primary" </mat-list>
aria-label="Edit" <ng-template #empty>
class="button" <div class="error-msg">No triggers configured yet.</div>
(click)="onEdit(trigger.id)" </ng-template>
> </ng-template>
<mat-icon>edit</mat-icon> <ng-template [ngIf]="triggers.error"
</button> ><mat-icon class="warning">warning</mat-icon></ng-template
<button >
mat-icon-button <ng-template [ngIf]="triggers.loading">
color="warn" <mat-spinner [diameter]="45" class="spinner"></mat-spinner>
aria-label="Delete" </ng-template>
class="button"
(click)="onDelete(trigger.id)"
>
<mat-icon>delete</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
</mat-list-item>
</mat-list>
</ng-container> </ng-container>
<ng-template #empty>
<div class="error-msg">
No triggers configured yet.
</div>
</ng-template>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View file

@ -7,37 +7,47 @@
technology for your community to florish! technology for your community to florish!
</p> </p>
<div class="hoods-container"> <div class="hoods-container">
<mat-selection-list [multiple]="false"> <ng-container *ngIf="hoods$ | loading | async as hoods">
<div mat-subheader>Configure your hoods</div> <ng-template [ngIf]="hoods.value">
<mat-divider></mat-divider> <mat-selection-list [multiple]="false">
<a <div mat-subheader>Configure your hoods</div>
*ngFor="let hood of hoods$ | async"
[routerLink]="['/dashboard/hoods', hood.id]"
matTooltip="Edit settings of {{ hood.name }}"
>
<mat-list-option>
<div class="list-entry-container">
<mat-icon>settings</mat-icon>
<div class="list-entry">
Your Hood - <strong>{{ hood.name }}</strong>
</div>
</div>
<mat-divider></mat-divider> <mat-divider></mat-divider>
</mat-list-option> <a
</a> *ngFor="let hood of hoods.value"
</mat-selection-list> [routerLink]="['/dashboard/hoods', hood.id]"
<mat-list> matTooltip="Edit settings of {{ hood.name }}"
<div mat-subheader></div> >
<mat-list-item *ngFor="let hood of hoods$ | async"> <mat-list-option>
<a <div class="list-entry-container">
[routerLink]="['/hoods', hood.id]" <mat-icon>settings</mat-icon>
target="_blank" <div class="list-entry">
matTooltip="View public page of hood {{ hood.name }}" Your Hood - <strong>{{ hood.name }}</strong>
> </div>
<mat-icon class="open-icon">open_in_new</mat-icon> </div>
</a> <mat-divider></mat-divider>
</mat-list-item> </mat-list-option>
</mat-list> </a>
</mat-selection-list>
<mat-list>
<div mat-subheader></div>
<mat-list-item *ngFor="let hood of hoods.value">
<a
[routerLink]="['/hoods', hood.id]"
target="_blank"
matTooltip="View public page of hood {{ hood.name }}"
>
<mat-icon class="open-icon">open_in_new</mat-icon>
</a>
</mat-list-item>
</mat-list>
</ng-template>
<ng-template [ngIf]="hoods.error"
><mat-icon class="warning">warning</mat-icon></ng-template
>
<ng-template [ngIf]="hoods.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</ng-container>
</div> </div>
<button <button

View file

@ -1,43 +1,61 @@
<div *ngIf="emails$ | async as emails"> <div *ngIf="emails$ | loading | async as emails">
<mat-card *ngIf="emails.length !== 0"> <ng-template [ngIf]="emails.value">
<mat-card-header> <mat-card>
<div mat-card-avatar class="email"></div> <mat-card-header>
<mat-card-title class="platform-title"> <div mat-card-avatar class="email"></div>
E-Mail <mat-card-title class="platform-title">
<button mat-icon-button aria-label="How to use"> E-Mail
<mat-icon <button mat-icon-button aria-label="How to use">
matTooltip="How to send and receive hood broadcast messages with email" <mat-icon
class="info-button" matTooltip="How to send and receive hood broadcast messages with email"
(click)="onInfoClick()" class="info-button"
>info</mat-icon (click)="onInfoClick()"
>info</mat-icon
>
</button>
</mat-card-title>
</mat-card-header>
<mat-card-content *ngIf="emails.value.length !== 0; else noEmail">
<h3>Subscribe to E-Mail list:</h3>
<form class="input" [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field>
<mat-label>Your E-Mail</mat-label>
<input formControlName="email" matInput />
</mat-form-field>
<button
mat-icon-button
color="primary"
aria-label="Add"
class="button"
> >
</button> <mat-icon>person_add</mat-icon>
</mat-card-title> </button>
</mat-card-header> </form>
<mat-card-content> <mat-divider></mat-divider>
<h3>Subscribe to E-Mail list:</h3> <h3>Send e-mail to hood:</h3>
<form class="input" [formGroup]="form" (ngSubmit)="onSubmit()"> <mat-selection-list [multiple]="false" class="list">
<mat-form-field> <a
<mat-label>Your E-Mail</mat-label> *ngFor="let email of emails.value"
<input formControlName="email" matInput /> href="mailto:{{ email.name }}@{{ emailDomain }}"
</mat-form-field> >
<button mat-icon-button color="primary" aria-label="Add" class="button"> <mat-list-option>
<mat-icon>person_add</mat-icon> {{ email.name }}@{{ emailDomain }}
</button> <mat-divider></mat-divider>
</form> </mat-list-option>
<mat-divider></mat-divider> </a>
<h3>Send e-mail to hood:</h3> </mat-selection-list>
<mat-selection-list [multiple]="false" class="list"> </mat-card-content>
<a </mat-card>
*ngFor="let email of emails" <ng-template #noEmail>
href="mailto:{{ email.name }}@{{ emailDomain }}" <mat-card-content>
> Unfortunately your hood admin has not configured E-Mail as platform yet.
<mat-list-option> </mat-card-content>
{{ email.name }}@{{ emailDomain }} </ng-template>
<mat-divider></mat-divider> </ng-template>
</mat-list-option> <ng-template [ngIf]="emails.error"
</a> ><mat-icon class="warning">warning</mat-icon></ng-template
</mat-selection-list> >
</mat-card-content> <ng-template [ngIf]="emails.loading">
</mat-card> <mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</div> </div>

View file

@ -14,50 +14,58 @@
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<mat-list *ngIf="emails$ | async as emails"> <mat-list *ngIf="emails$ | loading | async as emails">
<mat-list-item *ngIf="emails.length === 0; else startButton"> <ng-template [ngIf]="emails.value">
<button mat-menu-item (click)="onCreate()"> <mat-list-item *ngIf="emails.value.length === 0; else startButton">
<mat-icon>add</mat-icon>
<span> Add a platform connection!</span>
</button>
<mat-divider></mat-divider>
</mat-list-item>
<ng-template #startButton>
<mat-list-item>
<div class="toggle-container">
<mat-slide-toggle
name="enableEmails"
class="toggle"
(change)="onToggle()"
[(ngModel)]="start"
></mat-slide-toggle>
</div>
<mat-divider></mat-divider>
</mat-list-item>
</ng-template>
<mat-list-item *ngFor="let email of emails">
<div class="entry">
{{ email.name }}@{{ domain }}
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onDelete(email.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()"> <button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
<span>Add another</span> <span> Add a platform connection!</span>
</button> </button>
</mat-menu> <mat-divider></mat-divider>
</mat-list-item> </mat-list-item>
<ng-template #startButton>
<mat-list-item>
<div class="toggle-container">
<mat-slide-toggle
name="enableEmails"
class="toggle"
(change)="onToggle()"
[(ngModel)]="start"
></mat-slide-toggle>
</div>
<mat-divider></mat-divider>
</mat-list-item>
</ng-template>
<mat-list-item *ngFor="let email of emails.value">
<div class="entry">
{{ email.name }}@{{ domain }}
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onDelete(email.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon>
<span>Add another</span>
</button>
</mat-menu>
</mat-list-item>
</ng-template>
<ng-template [ngIf]="emails.error"
><mat-icon class="warning">warning</mat-icon></ng-template
>
<ng-template [ngIf]="emails.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</mat-list> </mat-list>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View file

@ -1,32 +1,46 @@
<div *ngIf="telegrams$ | async as telegrams"> <div *ngIf="telegrams$ | loading | async as telegrams">
<mat-card *ngIf="telegrams.length !== 0"> <ng-template [ngIf]="telegrams.value">
<mat-card-header> <mat-card>
<div mat-card-avatar class="telegram"></div> <mat-card-header>
<mat-card-title class="platform-title"> <div mat-card-avatar class="telegram"></div>
Telegram <mat-card-title class="platform-title">
<button mat-icon-button aria-label="How to use"> Telegram
<mat-icon <button mat-icon-button aria-label="How to use">
matTooltip="How to send and receive hood broadcast messages with telegram" <mat-icon
class="info-button" matTooltip="How to send and receive hood broadcast messages with telegram"
(click)="onInfoClick()" class="info-button"
>info</mat-icon (click)="onInfoClick()"
>info</mat-icon
>
</button>
</mat-card-title>
</mat-card-header>
<mat-card-content *ngIf="telegrams.value.length !== 0; else noTelegram">
<mat-selection-list [multiple]="false" class="list">
<a
*ngFor="let telegram of telegrams.value"
href="https://t.me/{{ telegram.username }}"
routerLinkActive="router-link-active"
> >
</button> <mat-list-option>
</mat-card-title> @{{ telegram.username }}
</mat-card-header> <mat-divider></mat-divider>
<mat-card-content> </mat-list-option>
<mat-selection-list [multiple]="false" class="list"> </a>
<a </mat-selection-list>
*ngFor="let telegram of telegrams" </mat-card-content>
href="https://t.me/{{ telegram.username }}" </mat-card>
routerLinkActive="router-link-active" <ng-template #noTelegram>
> <mat-card-content>
<mat-list-option> Unfortunately your hood admin has not configured Telegram as platform
@{{ telegram.username }} yet.
<mat-divider></mat-divider> </mat-card-content>
</mat-list-option> </ng-template>
</a> </ng-template>
</mat-selection-list> <ng-template [ngIf]="telegrams.error"
</mat-card-content> ><mat-icon class="warning">warning</mat-icon></ng-template
</mat-card> >
<ng-template [ngIf]="telegrams.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</div> </div>

View file

@ -14,45 +14,53 @@
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<mat-list *ngIf="telegrams$ | async as telegrams"> <mat-list *ngIf="telegrams$ | loading | async as telegrams">
<mat-list-item *ngIf="telegrams.length === 0"> <ng-template [ngIf]="telegrams.value">
<button mat-menu-item (click)="onCreate()"> <mat-list-item *ngIf="telegrams.value.length === 0">
<mat-icon>add</mat-icon>
<span> Add a platform connection!</span>
</button>
<mat-divider></mat-divider>
</mat-list-item>
<mat-list-item *ngFor="let telegram of telegrams">
<div class="entry">
@{{ telegram.username }}
<mat-slide-toggle
[checked]="telegram.enabled === 1"
(change)="onChange(telegram)"
></mat-slide-toggle>
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onEdit(telegram.id)">
<mat-icon>edit</mat-icon>
<span>Edit</span>
</button>
<button mat-menu-item (click)="onDelete(telegram.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()"> <button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
<span>Add another</span> <span> Add a platform connection!</span>
</button> </button>
</mat-menu> <mat-divider></mat-divider>
</mat-list-item> </mat-list-item>
<mat-list-item *ngFor="let telegram of telegrams.value">
<div class="entry">
@{{ telegram.username }}
<mat-slide-toggle
[checked]="telegram.enabled === 1"
(change)="onChange(telegram)"
></mat-slide-toggle>
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onEdit(telegram.id)">
<mat-icon>edit</mat-icon>
<span>Edit</span>
</button>
<button mat-menu-item (click)="onDelete(telegram.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon>
<span>Add another</span>
</button>
</mat-menu>
</mat-list-item>
</ng-template>
<ng-template [ngIf]="telegrams.error"
><mat-icon class="warning">warning</mat-icon></ng-template
>
<ng-template [ngIf]="telegrams.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</mat-list> </mat-list>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View file

@ -1,32 +1,46 @@
<div *ngIf="twitters$ | async as twitters"> <div *ngIf="twitters$ | loading | async as twitters">
<mat-card *ngIf="twitters.length !== 0"> <ng-template [ngIf]="twitters.value">
<mat-card-header> <mat-card>
<div mat-card-avatar class="twitter"></div> <mat-card-header>
<mat-card-title class="platform-title"> <div mat-card-avatar class="twitter"></div>
Twitter <mat-card-title class="platform-title">
<button mat-icon-button aria-label="How to use"> Twitter
<mat-icon <button mat-icon-button aria-label="How to use">
matTooltip="How to send and receive hood broadcast messages with twitter" <mat-icon
class="info-button" matTooltip="How to send and receive hood broadcast messages with twitter"
(click)="onInfoClick()" class="info-button"
>info</mat-icon (click)="onInfoClick()"
>info</mat-icon
>
</button>
</mat-card-title>
</mat-card-header>
<mat-card-content *ngIf="twitters.value.length !== 0; else noTwitter">
<mat-selection-list [multiple]="false" class="list">
<a
*ngFor="let twitter of twitters.value"
href="https://twitter.com/{{ twitter.username }}"
routerLinkActive="router-link-active"
> >
</button> <mat-list-option>
</mat-card-title> @{{ twitter.username }}
</mat-card-header> <mat-divider></mat-divider>
<mat-card-content> </mat-list-option>
<mat-selection-list [multiple]="false" class="list"> </a>
<a </mat-selection-list>
*ngFor="let twitter of twitters" </mat-card-content>
href="https://twitter.com/{{ twitter.username }}" </mat-card>
routerLinkActive="router-link-active" <ng-template #noTwitter>
> <mat-card-content>
<mat-list-option> Unfortunately your hood admin has not configured Twitter as platform
@{{ twitter.username }} yet.
<mat-divider></mat-divider> </mat-card-content>
</mat-list-option> </ng-template>
</a> </ng-template>
</mat-selection-list> <ng-template [ngIf]="twitters.error"
</mat-card-content> ><mat-icon class="warning">warning</mat-icon></ng-template
</mat-card> >
<ng-template [ngIf]="twitters.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</div> </div>

View file

@ -14,41 +14,49 @@
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<mat-list *ngIf="twitters$ | async as twitters"> <mat-list *ngIf="twitters$ | loading | async as twitters">
<mat-list-item *ngIf="(twitters | twitterCorpses).length === 0"> <ng-template [ngIf]="twitters.value">
<button mat-menu-item (click)="onCreate()"> <mat-list-item *ngIf="(twitters.value | twitterCorpses).length === 0">
<mat-icon>add</mat-icon>
<span> Add a platform connection!</span>
</button>
<mat-divider></mat-divider>
</mat-list-item>
<mat-list-item *ngFor="let twitter of twitters | twitterCorpses">
<div class="entry">
@{{ twitter.username }}
<mat-slide-toggle
[checked]="twitter.enabled === 1"
(change)="onChange(twitter)"
></mat-slide-toggle>
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onDelete(twitter.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()"> <button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
<span>Add another</span> <span> Add a platform connection!</span>
</button> </button>
</mat-menu> <mat-divider></mat-divider>
</mat-list-item> </mat-list-item>
<mat-list-item *ngFor="let twitter of twitters.value | twitterCorpses">
<div class="entry">
@{{ twitter.username }}
<mat-slide-toggle
[checked]="twitter.enabled === 1"
(change)="onChange(twitter)"
></mat-slide-toggle>
<button
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="Example icon-button with a menu"
>
<mat-icon>more_vert</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onDelete(twitter.id)">
<mat-icon>delete</mat-icon>
<span>Delete</span>
</button>
<button mat-menu-item (click)="onCreate()">
<mat-icon>add</mat-icon>
<span>Add another</span>
</button>
</mat-menu>
</mat-list-item>
</ng-template>
<ng-template [ngIf]="twitters.error"
><mat-icon class="warning">warning</mat-icon></ng-template
>
<ng-template [ngIf]="twitters.loading">
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</ng-template>
</mat-list> </mat-list>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View file

@ -1,8 +1,9 @@
<app-heading-one [title]="hood.name"></app-heading-one> <ng-container *ngIf="hood$ | async as hood">
<div class="public-margin container"> <app-heading-one [title]="hood.name"></app-heading-one>
<div class="markdown"> <div class="public-margin container">
<markdown [data]="hood.landingpage"></markdown> <div class="markdown">
<markdown [data]="hood.landingpage"></markdown>
</div>
<app-platforms-info-page [hoodId]="hoodId"></app-platforms-info-page>
</div> </div>
</ng-container>
<app-platforms-info-page [hoodId]="hoodId"></app-platforms-info-page>
</div>

View file

@ -10,7 +10,7 @@ import { first } from 'rxjs/operators';
}) })
export class HoodpageComponent implements OnInit { export class HoodpageComponent implements OnInit {
hoodId; hoodId;
hood: BodyHood; hood$;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
@ -21,12 +21,7 @@ export class HoodpageComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.hoodId = this.route.snapshot.params.id; this.hoodId = this.route.snapshot.params.id;
if (this.hoodId) { if (this.hoodId) {
this.hoodsService this.hood$ = this.hoodsService.getHood(this.hoodId);
.getHood(this.hoodId)
.pipe(first())
.subscribe((data) => {
this.hood = data;
});
} }
} }
} }

View file

@ -13,29 +13,33 @@
</mat-form-field> </mat-form-field>
<mat-selection-list <mat-selection-list
[multiple]="false" [multiple]="false"
*ngIf="hoods$ | async; let hoods; else: noHoods" *ngIf="hoods$ | loading | async; let hoods"
class="list" class="list"
> >
<a <ng-template [ngIf]="hoods.value">
[routerLink]="['/organizers']" <a
*ngIf="(hoods | filter: searchText).length === 0" [routerLink]="['/organizers']"
*ngIf="(hoods.value | filter: searchText).length === 0"
>
<mat-list-option>
<p>No matching hood found. Start by creating <u>a new hood!</u></p>
</mat-list-option>
</a>
<a
*ngFor="let hood of hoods.value | filter: searchText"
[routerLink]="['/hoods', hood.id]"
>
<mat-list-option>
{{ hood.name }}
<mat-divider></mat-divider>
</mat-list-option>
</a>
</ng-template>
<ng-template [ngIf]="hoods.error"
><mat-icon class="warning">warning</mat-icon></ng-template
> >
<mat-list-option> <ng-template [ngIf]="hoods.loading">
<p>No matching hood found. Start by creating <u>a new hood!</u></p> <mat-spinner [diameter]="45" class="spinner"></mat-spinner>
</mat-list-option> </ng-template>
</a>
<a
*ngFor="let hood of hoods | filter: searchText"
[routerLink]="['/hoods', hood.id]"
>
<mat-list-option>
{{ hood.name }}
<mat-divider></mat-divider>
</mat-list-option>
</a>
</mat-selection-list> </mat-selection-list>
<ng-template #noHoods>
No hoods available yet. Create
<a [routerLink]="['/dashboard']">a new hood! </a>
</ng-template>
</div> </div>

View file

@ -0,0 +1,8 @@
import { LoadingPipe } from './loading.pipe';
describe('LoadingPipe', () => {
it('create an instance', () => {
const pipe = new LoadingPipe();
expect(pipe).toBeTruthy();
});
});

View file

@ -0,0 +1,18 @@
import { Pipe, PipeTransform } from '@angular/core';
import { map, startWith, catchError } from 'rxjs/operators';
import { of, isObservable } from 'rxjs';
@Pipe({
name: 'loading',
})
export class LoadingPipe implements PipeTransform {
transform(val) {
return isObservable(val)
? val.pipe(
map((value: any) => ({ loading: false, value })),
startWith({ loading: true }),
catchError((error) => of({ loading: false, error }))
)
: val;
}
}

View file

@ -2,10 +2,3 @@
margin: 10%; margin: 10%;
text-align: center; text-align: center;
} }
.spinner {
display: block;
margin-left: auto;
margin-right: auto;
width: 40%;
}

View file

@ -10,6 +10,7 @@ import { YesNoDialogComponent } from './yes-no-dialog/yes-no-dialog.component';
import { OverlayComponent } from './overlay/overlay.component'; import { OverlayComponent } from './overlay/overlay.component';
import { HeadingOneComponent } from './heading-one/heading-one.component'; import { HeadingOneComponent } from './heading-one/heading-one.component';
import { FooterComponent } from './footer/footer.component'; import { FooterComponent } from './footer/footer.component';
import { LoadingPipe } from './loading-pipe/loading.pipe';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -19,6 +20,7 @@ import { FooterComponent } from './footer/footer.component';
OverlayComponent, OverlayComponent,
HeadingOneComponent, HeadingOneComponent,
FooterComponent, FooterComponent,
LoadingPipe,
], ],
imports: [ imports: [
MaterialModule, MaterialModule,
@ -33,6 +35,7 @@ import { FooterComponent } from './footer/footer.component';
NotFoundComponent, NotFoundComponent,
HeadingOneComponent, HeadingOneComponent,
FooterComponent, FooterComponent,
LoadingPipe,
MaterialModule, MaterialModule,
ReactiveFormsModule, ReactiveFormsModule,
FormsModule, FormsModule,

View file

@ -74,3 +74,16 @@ a {
} }
/* public pages end */ /* public pages end */
.spinner {
display: block;
margin-left: auto;
margin-right: auto;
width: 40%;
}
.warning {
color: red;
text-align: center;
min-width: 100%;
}