Merge branch 'features/add_route_resolver' into 'develop'

add route resolver for lazy-loading

See merge request framasoft/framadate/funky-framadate-front!42
This commit is contained in:
seraph_ino 2020-06-18 16:23:08 +02:00
commit 2e913e26d0
15 changed files with 232 additions and 304 deletions

View File

@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './core/components/home/home.component';
import { PollService } from './core/services/poll.service';
import { PageNotFoundComponent } from './shared/components/page-not-found/page-not-found.component';
const routes: Routes = [
@ -10,20 +11,24 @@ const routes: Routes = [
path: 'administration',
loadChildren: () =>
import('./features/administration/administration.module').then((m) => m.AdministrationModule),
resolve: { poll: PollService },
},
{
path: 'consultation',
loadChildren: () => import('./features/consultation/consultation.module').then((m) => m.ConsultationModule),
resolve: { poll: PollService },
},
{
path: 'participation',
loadChildren: () => import('./features/participation/participation.module').then((m) => m.ParticipationModule),
resolve: { poll: PollService },
},
{
path: 'oldstuff',
loadChildren: () => import('./features/old-stuff/old-stuff.module').then((m) => m.OldStuffModule),
},
{ path: '**', component: PageNotFoundComponent },
{ path: 'page-not-found', component: PageNotFoundComponent },
];
@NgModule({

View File

@ -2,6 +2,9 @@
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link"> Tous les sondages </a>
<div class="navbar-dropdown">
<a class="navbar-item" routerLink="/consultation/poll/inexistentPoll" routerLinkActive="is-active">
« inexistentPoll »
</a>
<a
class="navbar-item"
*ngFor="let slug of slugsAvailables"

View File

@ -17,6 +17,6 @@ export class Configuration {
) {}
public static isArchived(configuration: Configuration): boolean {
return DateService.isDateInPast(configuration.expires);
return configuration.expires ? DateService.isDateInPast(configuration.expires) : undefined;
}
}

View File

@ -90,12 +90,13 @@ export class ApiService {
return response;
}
);
console.log('fetch API : asking for poll with slug=' + slug);
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(`${this.pollsEndpoint}/${slug}`);
console.log('fetch API : asking for poll with slug=' + slug, { response });
axios.interceptors.request.eject(adapterInterceptor);
return response?.data;
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
} catch (error) {
if (error.response?.status === 404) {
return undefined;

View File

@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { MessageSeverity } from '../enums/message-severity.enum';
import { Answer } from '../enums/answer.enum';
import { MessageSeverity } from '../enums/message-severity.enum';
import { Choice } from '../models/choice.model';
import { Poll } from '../models/poll.model';
import { User } from '../models/user.model';
@ -12,21 +13,39 @@ import { ToastService } from './toast.service';
@Injectable({
providedIn: 'root',
})
export class PollService {
export class PollService implements Resolve<Poll> {
private _poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
constructor(private apiService: ApiService, private toastService: ToastService) {}
constructor(private router: Router, private apiService: ApiService, private toastService: ToastService) {}
public async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Poll> {
const wantedSlug: string = state.url.split('/poll/')[1];
if (!wantedSlug && state.url.includes('administration')) {
// creation of new poll
return;
}
if (!this._poll.getValue() || !this._poll.getValue().slug || this._poll.getValue().slug !== wantedSlug) {
await this.loadPollBySlug(wantedSlug);
}
if (this._poll.getValue()) {
return this._poll.getValue();
} else {
this.router.navigate(['page-not-found']);
return;
}
}
public async loadPollBySlug(slug: string): Promise<void> {
const poll: Poll | undefined = await this.apiService.getPollBySlug(slug);
console.log({ fetchedResponse: poll });
this.updateCurrentPoll(poll);
}
public updateCurrentPoll(poll: Poll): void {
this._poll.next(poll);
}
public async getPollBySlug(slug: string): Promise<void> {
const poll: Poll | undefined = await this.apiService.getPollBySlug(slug);
this.updateCurrentPoll(poll);
}
public async saveCurrentPoll(): Promise<void> {
const pollUrl: string = await this.apiService.createPoll(this._poll.getValue());
// TODO: Maybe handle the url to update currentPoll according to backend response

View File

@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { UrlService } from './url.service';
describe('UrlService', () => {
let service: UrlService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UrlService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -1,26 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { LoaderService } from './loader.service';
import { PollService } from './poll.service';
@Injectable({
providedIn: 'root',
})
export class UrlService {
constructor(
private route: ActivatedRoute,
private pollService: PollService,
private loaderService: LoaderService
) {}
public async loadPollFromUrl(): Promise<void> {
// TODO: behavior improvement needed.
// check if pollService currentPolls slug match the url : if yes, dont fetch again.
this.loaderService.setStatus(true);
const wantedSlug: string = this.route.snapshot.firstChild.firstChild.url[1].path;
await this.pollService.getPollBySlug(wantedSlug);
this.loaderService.setStatus(false);
}
}

View File

@ -9,7 +9,7 @@ const routes: Routes = [
{ path: ':slug', redirectTo: 'poll/:slug', pathMatch: 'full' },
{ path: 'poll', component: AdministrationComponent },
{ path: 'poll/:slug', component: AdministrationComponent },
{ path: 'user-polls', component: UserPollsComponent },
{ path: 'user-polls', component: UserPollsComponent, pathMatch: 'full' },
];
@NgModule({

View File

@ -4,18 +4,8 @@
</div>
</div>
<app-spinner *ngIf="_isLoading | async"></app-spinner>
<ng-container *ngIf="!(_isLoading | async)">
<ng-container *ngIf="!(_poll | async)">
<app-page-not-found [message]="'PAGE_NOT_FOUND.POLL'"></app-page-not-found>
</ng-container>
<ng-container *ngIf="_poll | async as poll">
<div class="columns">
<div class="column">
<app-stepper [poll]="poll"></app-stepper>
</div>
</div>
</ng-container>
</ng-container>
<div class="columns">
<div class="column">
<app-stepper [poll]="poll"></app-stepper>
</div>
</div>

View File

@ -1,11 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { Poll } from '../../core/models/poll.model';
import { LoaderService } from '../../core/services/loader.service';
import { ModalService } from '../../core/services/modal.service';
import { PollService } from '../../core/services/poll.service';
import { UrlService } from '../../core/services/url.service';
import { UserService } from '../../core/services/user.service';
import { SettingsComponent } from '../../shared/components/settings/settings.component';
@ -14,22 +12,26 @@ import { SettingsComponent } from '../../shared/components/settings/settings.com
templateUrl: './administration.component.html',
styleUrls: ['./administration.component.scss'],
})
export class AdministrationComponent implements OnInit {
public _isLoading: Observable<boolean> = this.loaderService.isLoading;
public _poll: Observable<Poll> = this.pollService.poll;
export class AdministrationComponent implements OnInit, OnDestroy {
public poll: Poll;
private routeSubscription: Subscription;
constructor(
private urlService: UrlService,
private loaderService: LoaderService,
private pollService: PollService,
private userService: UserService,
private modalService: ModalService
) {}
constructor(private route: ActivatedRoute, private userService: UserService, private modalService: ModalService) {}
ngOnInit(): void {
if (!this.userService.isCurrentUserIdentifiable()) {
this.modalService.openModal(SettingsComponent);
}
this.urlService.loadPollFromUrl();
this.routeSubscription = this.route.data.subscribe((data: { poll: Poll }) => {
if (data.poll) {
this.poll = data.poll;
}
});
}
ngOnDestroy(): void {
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
}
}
}

View File

@ -4,55 +4,42 @@
</div>
</div>
<app-spinner *ngIf="_isLoading | async"></app-spinner>
<ng-container *ngIf="!(_isLoading | async)">
<ng-container *ngIf="!(_poll | async)">
<app-page-not-found [message]="'PAGE_NOT_FOUND.POLL'"></app-page-not-found>
</ng-container>
<ng-container *ngIf="_poll | async as poll">
<div class="columns">
<div class="column">
<div class="card">
<header class="card-header">
<p class="card-header-title">{{ poll.question }}</p>
<p class="card-header-icon">author : {{ poll.owner.pseudo }}</p>
</header>
<div class="card-content">
<div class="content">
<p>{{ poll.description }}</p>
<div class="buttons has-addons is-small is-right">
<button class="button" [class.is-active]="isCompactMode" (click)="isCompactMode = true">
Compact
</button>
<button
class="button"
[class.is-active]="!isCompactMode"
(click)="isCompactMode = false"
>
Detailed
</button>
</div>
<app-poll-results-compact *ngIf="isCompactMode" [poll]="poll"></app-poll-results-compact>
<app-poll-results-detailed *ngIf="!isCompactMode" [poll]="poll"></app-poll-results-detailed>
</div>
<div class="columns">
<div class="column">
<div class="card">
<header class="card-header">
<p class="card-header-title">{{ poll.question }}</p>
<p class="card-header-icon">author : {{ poll.owner?.pseudo }}</p>
</header>
<div class="card-content">
<div class="content">
<p>{{ poll.description }}</p>
<div class="buttons has-addons is-small is-right">
<button class="button" [class.is-active]="isCompactMode" (click)="isCompactMode = true">
Compact
</button>
<button class="button" [class.is-active]="!isCompactMode" (click)="isCompactMode = false">
Detailed
</button>
</div>
<footer class="card-footer" *ngIf="!isArchived(poll)">
<a routerLink="{{ '../../../participation/poll/' + poll.slug }}" class="card-footer-item">
Participer
</a>
<a routerLink="{{ '../../../administration/poll/' + poll.slug }}" class="card-footer-item">
Administrer
</a>
</footer>
<app-poll-results-compact *ngIf="isCompactMode" [poll]="poll"></app-poll-results-compact>
<app-poll-results-detailed *ngIf="!isCompactMode" [poll]="poll"></app-poll-results-detailed>
</div>
</div>
<footer class="card-footer" *ngIf="!isArchived">
<a routerLink="{{ '../../../participation/poll/' + poll.slug }}" class="card-footer-item">
Participer
</a>
<a routerLink="{{ '../../../administration/poll/' + poll.slug }}" class="card-footer-item">
Administrer
</a>
</footer>
</div>
<div class="columns">
<div class="column">
<app-comments></app-comments>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
<div class="columns">
<div class="column">
<app-comments></app-comments>
</div>
</div>

View File

@ -1,12 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { Configuration } from '../../core/models/configuration.model';
import { Poll } from '../../core/models/poll.model';
import { LoaderService } from '../../core/services/loader.service';
import { ModalService } from '../../core/services/modal.service';
import { PollService } from '../../core/services/poll.service';
import { UrlService } from '../../core/services/url.service';
import { UserService } from '../../core/services/user.service';
import { SettingsComponent } from '../../shared/components/settings/settings.component';
@ -15,15 +13,15 @@ import { SettingsComponent } from '../../shared/components/settings/settings.com
templateUrl: './consultation.component.html',
styleUrls: ['./consultation.component.scss'],
})
export class ConsultationComponent implements OnInit {
public _isLoading: Observable<boolean> = this.loaderService.isLoading;
public _poll: Observable<Poll> = this.pollService.poll;
export class ConsultationComponent implements OnInit, OnDestroy {
public isCompactMode = true;
public poll: Poll;
public isArchived: boolean;
private routeSubscription: Subscription;
constructor(
private urlService: UrlService,
private loaderService: LoaderService,
private pollService: PollService,
private router: Router,
private activatedRoute: ActivatedRoute,
private userService: UserService,
private modalService: ModalService
) {}
@ -32,10 +30,19 @@ export class ConsultationComponent implements OnInit {
if (!this.userService.isCurrentUserIdentifiable()) {
this.modalService.openModal(SettingsComponent);
}
this.urlService.loadPollFromUrl();
this.routeSubscription = this.activatedRoute.data.subscribe((data: { poll: Poll }) => {
if (data.poll) {
this.poll = data.poll;
this.isArchived = Configuration.isArchived(data.poll.configuration);
} else {
this.router.navigate(['/page-not-found']);
}
});
}
public isArchived(poll: Poll): boolean {
return Configuration.isArchived(poll.configuration);
ngOnDestroy(): void {
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
}
}
}

View File

@ -4,28 +4,20 @@
</div>
</div>
<app-spinner *ngIf="_isLoading | async"></app-spinner>
<div class="columns">
<div class="column">
<app-answers [poll]="poll" [user]="_user | async"></app-answers>
</div>
</div>
<ng-container *ngIf="!(_isLoading | async)">
<ng-container *ngIf="!(_poll | async)">
<app-page-not-found [message]="'PAGE_NOT_FOUND.POLL'"></app-page-not-found>
</ng-container>
<div class="columns">
<div class="column">
<app-add-comment [pseudo]="(_user | async)?.pseudo"></app-add-comment>
</div>
</div>
<ng-container *ngIf="_poll | async">
<div class="columns">
<div class="column">
<app-answers [poll]="_poll | async" [user]="_user | async"></app-answers>
</div>
</div>
<div class="columns">
<div class="column">
<app-add-comment [pseudo]="(_user | async)?.pseudo"></app-add-comment>
</div>
</div>
<div class="columns">
<div class="column">
<app-comments></app-comments>
</div>
</div>
</ng-container>
</ng-container>
<div class="columns">
<div class="column">
<app-comments></app-comments>
</div>
</div>

View File

@ -1,12 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import { Poll } from '../../core/models/poll.model';
import { User } from '../../core/models/user.model';
import { LoaderService } from '../../core/services/loader.service';
import { ModalService } from '../../core/services/modal.service';
import { PollService } from '../../core/services/poll.service';
import { UrlService } from '../../core/services/url.service';
import { UserService } from '../../core/services/user.service';
import { SettingsComponent } from '../../shared/components/settings/settings.component';
@ -15,15 +13,14 @@ import { SettingsComponent } from '../../shared/components/settings/settings.com
templateUrl: './participation.component.html',
styleUrls: ['./participation.component.scss'],
})
export class ParticipationComponent implements OnInit {
public _isLoading: Observable<boolean> = this.loaderService.isLoading;
public _poll: Observable<Poll> = this.pollService.poll;
export class ParticipationComponent implements OnInit, OnDestroy {
public poll: Poll;
public _user: Observable<User> = this.userService.user;
private routeSubscription: Subscription;
constructor(
private urlService: UrlService,
private loaderService: LoaderService,
private pollService: PollService,
private router: Router,
private activatedRoute: ActivatedRoute,
private userService: UserService,
private modalService: ModalService
) {}
@ -32,6 +29,18 @@ export class ParticipationComponent implements OnInit {
if (!this.userService.isCurrentUserIdentifiable()) {
this.modalService.openModal(SettingsComponent);
}
this.urlService.loadPollFromUrl();
this.routeSubscription = this.activatedRoute.data.subscribe((data: { poll: Poll }) => {
if (data.poll) {
this.poll = data.poll;
} else {
this.router.navigate(['/page-not-found']);
}
});
}
ngOnDestroy(): void {
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
}
}
}

199
yarn.lock
View File

@ -12,29 +12,29 @@
jest-preset-angular "^8.1.2"
lodash "^4.17.10"
"@angular-devkit/architect@0.901.8", "@angular-devkit/architect@>=0.900.0 < 0.1000.0":
version "0.901.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.8.tgz#d2f5f4c16fba3ed61ee27c7fc72118421ea2b45d"
integrity sha512-tK9ZQlubH6n+q+c2J9Wvfcxg3RFuRiTfJriNoodo6GHvtF2KLdPY67w3Gen0Sp172A5Q8Y927NseddNI8RZ/0A==
"@angular-devkit/architect@0.901.9", "@angular-devkit/architect@>=0.900.0 < 0.1000.0":
version "0.901.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.9.tgz#5d849a120449b2f91ec6eef44ddad74ffb7ad810"
integrity sha512-Xokyh7bv4qICHpb5Xui1jPTi6ZZvzR5tbTIxT0DFWqw16TEkFgkNubQsW6mFSR3g3CXdySMfOwWExfa/rE1ggA==
dependencies:
"@angular-devkit/core" "9.1.8"
"@angular-devkit/core" "9.1.9"
rxjs "6.5.4"
"@angular-devkit/build-angular@^0.901.2":
version "0.901.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.8.tgz#6450be4743dacf564af143c85d2a03b7bdd81551"
integrity sha512-W2RTjtPPJRbke6K7Qt9eZOPRGfFBFsYzskxsuxXwkW2RPopj6k1wUWh9Be8CtAMAUlhyPvlzviOtv3F7leYr3w==
version "0.901.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.9.tgz#a60c41497e69d663cf2c74778cc72dd262cc09a1"
integrity sha512-eC6iZQR5tr9dz/SkR3/3Y8Fau/2IzEfHlFCf2mqsOLkbc0MWyM/3RcuZQhRGdVOyzDCIbfzJGY0N3ejkEn2EUg==
dependencies:
"@angular-devkit/architect" "0.901.8"
"@angular-devkit/build-optimizer" "0.901.8"
"@angular-devkit/build-webpack" "0.901.8"
"@angular-devkit/core" "9.1.8"
"@angular-devkit/architect" "0.901.9"
"@angular-devkit/build-optimizer" "0.901.9"
"@angular-devkit/build-webpack" "0.901.9"
"@angular-devkit/core" "9.1.9"
"@babel/core" "7.9.0"
"@babel/generator" "7.9.3"
"@babel/preset-env" "7.9.0"
"@babel/template" "7.8.6"
"@jsdevtools/coverage-istanbul-loader" "3.0.3"
"@ngtools/webpack" "9.1.8"
"@ngtools/webpack" "9.1.9"
ajv "6.12.0"
autoprefixer "9.7.4"
babel-loader "8.0.6"
@ -77,7 +77,7 @@
stylus "0.54.7"
stylus-loader "3.0.2"
terser "4.6.10"
terser-webpack-plugin "2.3.5"
terser-webpack-plugin "3.0.3"
tree-kill "1.2.2"
webpack "4.42.0"
webpack-dev-middleware "3.7.2"
@ -87,10 +87,10 @@
webpack-subresource-integrity "1.4.0"
worker-plugin "4.0.3"
"@angular-devkit/build-optimizer@0.901.8":
version "0.901.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.8.tgz#55a6cecf9b963bac15f84b5db8ec211c82119954"
integrity sha512-k9DynuWKMsJk5xg+LthdsqmOlGVMVP/TEu2odiVty9gnTVlIjs1bUzs+HNAF/w11juIBcVKa690K+FkSCalo9w==
"@angular-devkit/build-optimizer@0.901.9":
version "0.901.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.9.tgz#c8018de2406c8bbf32bf74cdacd6fa1df384a8d0"
integrity sha512-AcDhE7RHmaVEaDB02MHp1PR2gdUg3+G/12pDC3GeAlfP1GD/sVBpcqPL6DHFp0dMm/FsvSfVSaXpzD7jZBeIKQ==
dependencies:
loader-utils "2.0.0"
source-map "0.7.3"
@ -98,19 +98,19 @@
typescript "3.6.5"
webpack-sources "1.4.3"
"@angular-devkit/build-webpack@0.901.8":
version "0.901.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.8.tgz#19fbac49c3f60c16d6814d61e518431503ab746a"
integrity sha512-OyLfPI0yo1Qg4I1QP8ZxEYVxrf3IDjGfpxlKXqSChpEy5m/uZmBIRDZ/n/G3+32xFc6MWEdU4EHfRrfn17ae/w==
"@angular-devkit/build-webpack@0.901.9":
version "0.901.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.9.tgz#19e783950b2f22ceaa0c33b07552bd225dcd412b"
integrity sha512-Bha9LruitixhtJm72FGzqfDfgsOsrMT3EbNSql2muyoELIYbLDOvNZjcDD06CPcOAWSg6/tH9caOTFS2Zj9yOw==
dependencies:
"@angular-devkit/architect" "0.901.8"
"@angular-devkit/core" "9.1.8"
"@angular-devkit/architect" "0.901.9"
"@angular-devkit/core" "9.1.9"
rxjs "6.5.4"
"@angular-devkit/core@9.1.8", "@angular-devkit/core@^9.0.0":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.8.tgz#7c517a14e3ddfd180858972d9f1836aa90a1248e"
integrity sha512-4k1pZwje2oh5c/ULg7pnCBzTstx3l3uF7O5tQq/KXomDDsam97IhLm6cKUqQpaoyC1NUsBV6xJARJ0PyUP5TPQ==
"@angular-devkit/core@9.1.9", "@angular-devkit/core@^9.0.0":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.9.tgz#e6283912093179313ccfc69856841e9b6b318231"
integrity sha512-SWgBh4an/Vezjw2BZ5S+bKvuK5lH6gOtR8d5YjN9vxpJSZ0GimrGjfnLlWOkwWAsU8jfn4JzofECUHwX/7EW6Q==
dependencies:
ajv "6.12.0"
fast-json-stable-stringify "2.1.0"
@ -118,12 +118,12 @@
rxjs "6.5.4"
source-map "0.7.3"
"@angular-devkit/schematics@9.1.8":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.8.tgz#8eeea0b6f9702a5b065f909cdcaf1d35cc8e2fa3"
integrity sha512-/8L5J4X6SkcFMRmrSQHvJWOPilrMWTNlv1lD+1z06D3xGJEktVxXM3gCUXhDrbMvpoi+lYtR2Fuia0E6zvyjCQ==
"@angular-devkit/schematics@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.9.tgz#1369ee586cb91ffebf12673bb839d31ad5c00357"
integrity sha512-aKuMmS3wshOTl9+01jiB50ml09fRN1WfOOtoNqwvKTEi87DrT6Mn3l0eVQo8PJK/bIq/FBmPgsIl2nsETiBSxg==
dependencies:
"@angular-devkit/core" "9.1.8"
"@angular-devkit/core" "9.1.9"
ora "4.0.3"
rxjs "6.5.4"
@ -140,15 +140,15 @@
parse5 "^5.0.0"
"@angular/cli@^9.1.2":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.8.tgz#fd143e26c913ccea5b8ac1716e1c168432ac96d3"
integrity sha512-yfF7glPo3Xm7fTJVln1bFZVXqHu8wkIGZRZGb6lsJa+QH4ePxHgn+dNYXho0MYpGUnhY7xOBW4MJzjS7E+1y5Q==
version "9.1.9"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.9.tgz#e9caced7c107c65075fe1b4c42a4712a5aeb992c"
integrity sha512-k8C0OY3oHoixd3buCgF8+VFe8YZGSGiprnbVMEF2WJHUUw87lPCu/d7dbID3AtVwdKdAB275rAt6IZEIzXInbw==
dependencies:
"@angular-devkit/architect" "0.901.8"
"@angular-devkit/core" "9.1.8"
"@angular-devkit/schematics" "9.1.8"
"@schematics/angular" "9.1.8"
"@schematics/update" "0.901.8"
"@angular-devkit/architect" "0.901.9"
"@angular-devkit/core" "9.1.9"
"@angular-devkit/schematics" "9.1.9"
"@schematics/angular" "9.1.9"
"@schematics/update" "0.901.9"
"@yarnpkg/lockfile" "1.1.0"
ansi-colors "4.1.1"
debug "4.1.1"
@ -1501,12 +1501,12 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
"@ngtools/webpack@9.1.8":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.8.tgz#50a906047b284098e5cd669e8174c9cfcaf3bafc"
integrity sha512-2Y27PrHLMyrIDmuicjp2OU7KIr9bggwMLNZdjfpcuXlOPP/BYviuhgkkYsfJysrpDRUJUHlXRJG7OJbgyFM7gQ==
"@ngtools/webpack@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.9.tgz#2098afd6f1f028238468262df2ad10afa81b82a5"
integrity sha512-7UzRL54JcK1m2PvgpchV26TF9OYipj/8+dygdjaidqOyQujWpHncdtq/ScbUsoJ44nHjIRJPhaGE00NLpWZvnA==
dependencies:
"@angular-devkit/core" "9.1.8"
"@angular-devkit/core" "9.1.9"
enhanced-resolve "4.1.1"
rxjs "6.5.4"
webpack-sources "1.4.3"
@ -1554,21 +1554,21 @@
dependencies:
mkdirp "^1.0.4"
"@schematics/angular@9.1.8":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.8.tgz#da6cd63b65776b18c43d8515bfca754dd9acdbc9"
integrity sha512-fjyAP9m4aF51OVdksRXCOF8BTyt96PqFmKK9G0kuwOzgfx2gPZNOO3wOZH6xFAMZ09y86VGzasZxZNeDdyN4sQ==
"@schematics/angular@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.9.tgz#df9f30dd7b63856121fbb9ab5dda57b443802a33"
integrity sha512-c8YGZ6pDfr8IDD1qaOjlEBAkEz14KFSxDj0hCWs0xIM0py513tu5sW8+ziYxGG4bgqpsgVR/KAxuY78iBfUVag==
dependencies:
"@angular-devkit/core" "9.1.8"
"@angular-devkit/schematics" "9.1.8"
"@angular-devkit/core" "9.1.9"
"@angular-devkit/schematics" "9.1.9"
"@schematics/update@0.901.8":
version "0.901.8"
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.8.tgz#d48be9931a2462062d4d4ac05c4b24b319bc064a"
integrity sha512-v1tEYX6yM5vuwXW7AG7OZ4OtjqRwTo3kd69LVJyOdF/d9HlqaAFU301RuEsAPwOrPqZEQdTwklH1fNJnqgpB/w==
"@schematics/update@0.901.9":
version "0.901.9"
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.9.tgz#6285611910ebf8bb4078447d2ba32931595efcd4"
integrity sha512-VChX0VO/oyfCF3y+HjMTU2qN3vGgJYxEI1V+Q9aAlwl95t3GAufuaFY1CNW3YV4XkYIjD88e3yWl8d5yO4qf4w==
dependencies:
"@angular-devkit/core" "9.1.8"
"@angular-devkit/schematics" "9.1.8"
"@angular-devkit/core" "9.1.9"
"@angular-devkit/schematics" "9.1.9"
"@yarnpkg/lockfile" "1.1.0"
ini "1.3.5"
npm-package-arg "^8.0.0"
@ -2925,30 +2925,6 @@ cacache@^12.0.0, cacache@^12.0.2:
unique-filename "^1.1.1"
y18n "^4.0.0"
cacache@^13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c"
integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==
dependencies:
chownr "^1.1.2"
figgy-pudding "^3.5.1"
fs-minipass "^2.0.0"
glob "^7.1.4"
graceful-fs "^4.2.2"
infer-owner "^1.0.4"
lru-cache "^5.1.1"
minipass "^3.0.0"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.2"
mkdirp "^0.5.1"
move-concurrently "^1.0.1"
p-map "^3.0.0"
promise-inflight "^1.0.1"
rimraf "^2.7.1"
ssri "^7.0.0"
unique-filename "^1.1.1"
cacache@^15.0.4:
version "15.0.4"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1"
@ -4374,9 +4350,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.413:
version "1.3.475"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.475.tgz#67688cc82c342f39594a412286e975eda45d8412"
integrity sha512-vcTeLpPm4+ccoYFXnepvkFt0KujdyrBU19KNEO40Pnkhta6mUi2K0Dn7NmpRcNz7BvysnSqeuIYScP003HWuYg==
version "1.3.477"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.477.tgz#7e6b931d0c1a2572101a6e9a835128c50fd49323"
integrity sha512-81p6DZ/XmHDD7O0ITJMa7ESo9bSCfE+v3Fny3MIYR0y77xmhoriu2ShNOLXcPS4eowF6dkxw6d2QqxTkS3DjBg==
elliptic@^6.0.0, elliptic@^6.5.2:
version "6.5.2"
@ -5149,7 +5125,7 @@ finalhandler@1.1.2, finalhandler@~1.1.2:
statuses "~1.5.0"
unpipe "~1.0.0"
find-cache-dir@3.3.1, find-cache-dir@^3.2.0, find-cache-dir@^3.3.1:
find-cache-dir@3.3.1, find-cache-dir@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
@ -5590,7 +5566,7 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
@ -7056,14 +7032,6 @@ jest-worker@25.1.0:
merge-stream "^2.0.0"
supports-color "^7.0.0"
jest-worker@^25.1.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1"
integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==
dependencies:
merge-stream "^2.0.0"
supports-color "^7.0.0"
jest-worker@^26.0.0:
version "26.0.0"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066"
@ -8608,7 +8576,7 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.2, p-limit@^2.3.0:
p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
@ -10244,7 +10212,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5, schema-utils@^2.7.0:
schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"
integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==
@ -10361,11 +10329,6 @@ send@0.17.1, send@latest:
range-parser "~1.2.1"
statuses "~1.5.0"
serialize-javascript@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
serialize-javascript@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea"
@ -10796,14 +10759,6 @@ ssri@^6.0.0, ssri@^6.0.1:
dependencies:
figgy-pudding "^3.5.1"
ssri@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d"
integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==
dependencies:
figgy-pudding "^3.5.1"
minipass "^3.1.1"
ssri@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808"
@ -11203,19 +11158,19 @@ terminal-link@^2.0.0:
ansi-escapes "^4.2.1"
supports-hyperlinks "^2.0.0"
terser-webpack-plugin@2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81"
integrity sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w==
terser-webpack-plugin@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-3.0.3.tgz#23bda2687b197f878a743373b9411d917adc2e45"
integrity sha512-bZFnotuIKq5Rqzrs+qIwFzGdKdffV9epG5vDSEbYzvKAhPeR5RbbrQysfPgbIIMhNAQtZD2hGwBfSKUXjXZZZw==
dependencies:
cacache "^13.0.1"
find-cache-dir "^3.2.0"
jest-worker "^25.1.0"
p-limit "^2.2.2"
schema-utils "^2.6.4"
serialize-javascript "^2.1.2"
cacache "^15.0.4"
find-cache-dir "^3.3.1"
jest-worker "^26.0.0"
p-limit "^2.3.0"
schema-utils "^2.6.6"
serialize-javascript "^3.1.0"
source-map "^0.6.1"
terser "^4.4.3"
terser "^4.6.13"
webpack-sources "^1.4.3"
terser-webpack-plugin@^1.4.3:
@ -11242,7 +11197,7 @@ terser@4.6.10:
source-map "~0.6.1"
source-map-support "~0.5.12"
terser@^4.1.2, terser@^4.4.3:
terser@^4.1.2, terser@^4.6.13:
version "4.8.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==