fixes from testing

This commit is contained in:
conblem
2025-06-25 16:44:13 +02:00
parent 9a71fdcc03
commit edf2017922
18 changed files with 100 additions and 66 deletions

View File

@@ -30,6 +30,8 @@
"@fortawesome/angular-fontawesome": "^0.13.0", "@fortawesome/angular-fontawesome": "^0.13.0",
"@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2",
"@ng-icons/core": "^25.0.0",
"@ng-icons/heroicons": "^25.0.0",
"@ngx-translate/core": "^15.0.0", "@ngx-translate/core": "^15.0.0",
"@tanstack/angular-query-experimental": "^5.75.4", "@tanstack/angular-query-experimental": "^5.75.4",
"@zitadel/client": "1.2.0", "@zitadel/client": "1.2.0",

View File

@@ -240,7 +240,6 @@ export class AppComponent {
this.translate.onLangChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((language: LangChangeEvent) => { this.translate.onLangChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((language: LangChangeEvent) => {
this.document.documentElement.lang = language.lang; this.document.documentElement.lang = language.lang;
this.language = language.lang;
}); });
} }
@@ -290,7 +289,6 @@ export class AppComponent {
? userprofile.human.profile?.preferredLanguage ? userprofile.human.profile?.preferredLanguage
: fallbackLang; : fallbackLang;
this.translate.use(lang); this.translate.use(lang);
this.language = lang;
this.document.documentElement.lang = lang; this.document.documentElement.lang = lang;
}); });
} }

View File

@@ -76,6 +76,7 @@ import { PosthogService } from './services/posthog.service';
import { NewHeaderComponent } from './modules/new-header/new-header.component'; import { NewHeaderComponent } from './modules/new-header/new-header.component';
import { provideTanStackQuery, QueryClient, withDevtools } from '@tanstack/angular-query-experimental'; import { provideTanStackQuery, QueryClient, withDevtools } from '@tanstack/angular-query-experimental';
import { CdkOverlayOrigin } from '@angular/cdk/overlay'; import { CdkOverlayOrigin } from '@angular/cdk/overlay';
import { provideNgIconsConfig } from '@ng-icons/core';
registerLocaleData(localeDe); registerLocaleData(localeDe);
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/de.json')); i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/de.json'));
@@ -251,6 +252,9 @@ const authConfig: AuthConfig = {
new QueryClient(), new QueryClient(),
withDevtools(() => ({ loadDevtools: 'auto' })), withDevtools(() => ({ loadDevtools: 'auto' })),
), ),
provideNgIconsConfig({
size: '1rem',
}),
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
exports: [], exports: [],

View File

@@ -24,9 +24,9 @@
*ngFor="let key of FEATURE_KEYS" *ngFor="let key of FEATURE_KEYS"
[toggleStateKey]="key" [toggleStateKey]="key"
[toggleState]="toggleStates[key]" [toggleState]="toggleStates[key]"
(toggleChange)="saveFeatures(key, $event)" (toggleChange)="saveFeatures(toggleStates, key, $event)"
></cnsl-feature-toggle> ></cnsl-feature-toggle>
<cnsl-login-v2-feature-toggle [toggleState]="toggleStates.loginV2" (toggleChanged)="saveFeatures('loginV2', $event)" /> <cnsl-login-v2-feature-toggle [toggleState]="toggleStates.loginV2" (toggleChanged)="saveFeatures(toggleStates, 'loginV2', $event)" />
</div> </div>
</cnsl-card> </cnsl-card>
</div> </div>

View File

@@ -21,7 +21,7 @@ import {
} from '@zitadel/proto/zitadel/feature/v2/instance_pb'; } from '@zitadel/proto/zitadel/feature/v2/instance_pb';
import { Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb'; import { Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb';
import { MessageInitShape } from '@bufbuild/protobuf'; import { MessageInitShape } from '@bufbuild/protobuf';
import { firstValueFrom, Observable, ReplaySubject, shareReplay, switchMap } from 'rxjs'; import { Observable, ReplaySubject, shareReplay, switchMap } from 'rxjs';
import { filter, map, startWith } from 'rxjs/operators'; import { filter, map, startWith } from 'rxjs/operators';
import { LoginV2FeatureToggleComponent } from '../feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component'; import { LoginV2FeatureToggleComponent } from '../feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component';
@@ -133,18 +133,22 @@ export class FeaturesComponent {
); );
} }
public async saveFeatures<TKey extends ToggleStateKeys, TValue extends ToggleStates[TKey]>(key: TKey, value: TValue) { public async saveFeatures<TKey extends ToggleStateKeys, TValue extends ToggleStates[TKey]>(
const toggleStates = { ...(await firstValueFrom(this.toggleStates$)), [key]: value }; toggleStates: ToggleStates,
key: TKey,
value: TValue,
) {
const newToggleStates = { ...toggleStates, [key]: value };
const req = FEATURE_KEYS.reduce<MessageInitShape<typeof SetInstanceFeaturesRequestSchema>>((acc, key) => { const req = FEATURE_KEYS.reduce<MessageInitShape<typeof SetInstanceFeaturesRequestSchema>>((acc, key) => {
acc[key] = toggleStates[key].enabled; acc[key] = newToggleStates[key].enabled;
return acc; return acc;
}, {}); }, {});
// to save special flags they have to be handled here // to save special flags they have to be handled here
req.loginV2 = { req.loginV2 = {
required: toggleStates.loginV2.enabled, required: newToggleStates.loginV2.enabled,
baseUri: toggleStates.loginV2.baseUri, baseUri: newToggleStates.loginV2.baseUri,
}; };
try { try {

View File

@@ -1,6 +1,6 @@
<button class="header-button" cnslInput> <button class="header-button" cnslInput>
<ng-content></ng-content> <ng-content></ng-content>
<div class="cnsl-action-button"> <div class="cnsl-action-button">
<i class="las la-arrows-alt-v"></i> <ng-icon size="1.2rem" name="heroChevronUpDown"></ng-icon>
</div> </div>
</button> </button>

View File

@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { heroChevronUpDown } from '@ng-icons/heroicons/outline';
@Component({ @Component({
selector: 'cnsl-header-button', selector: 'cnsl-header-button',
@@ -6,5 +8,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
styleUrls: ['./header-button.component.scss'], styleUrls: ['./header-button.component.scss'],
standalone: true, standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgIconComponent],
providers: [provideIcons({ heroChevronUpDown })],
}) })
export class HeaderButtonComponent {} export class HeaderButtonComponent {}

View File

@@ -2,13 +2,13 @@
<span class="dropdown-label">{{ 'MENU.INSTANCEOVERVIEW' | translate }}</span> <span class="dropdown-label">{{ 'MENU.INSTANCEOVERVIEW' | translate }}</span>
<a (click)="setInstance(instance)" mat-button class="dropdown-button" <a (click)="setInstance(instance)" mat-button class="dropdown-button"
>{{ instance.name }} >{{ instance.name }}
<i class="las la-1x la-angle-right"></i> <ng-icon name="heroChevronRight"></ng-icon>
</a> </a>
</div> </div>
<div class="footer"> <div class="footer">
<a [routerLink]="['/instance']" (click)="settingsClicked.emit()" mat-button class="dropdown-button settings-button"> <a [routerLink]="['/instance']" (click)="settingsClicked.emit()" mat-button class="dropdown-button settings-button">
<h3>{{ 'MENU.SETTINGS' | translate }}</h3> <h3>{{ 'MENU.SETTINGS' | translate }}</h3>
<i class="las la-1x la-cog"></i> <ng-icon name="heroCog8ToothSolid"></ng-icon>
</a> </a>
</div> </div>

View File

@@ -3,6 +3,9 @@ import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { Router, RouterLink } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
import { InstanceDetail } from '@zitadel/proto/zitadel/instance_pb'; import { InstanceDetail } from '@zitadel/proto/zitadel/instance_pb';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { heroCog8ToothSolid } from '@ng-icons/heroicons/solid';
import { heroChevronRight } from '@ng-icons/heroicons/outline';
@Component({ @Component({
selector: 'cnsl-instance-selector', selector: 'cnsl-instance-selector',
@@ -10,7 +13,8 @@ import { InstanceDetail } from '@zitadel/proto/zitadel/instance_pb';
styleUrls: ['./instance-selector.component.scss'], styleUrls: ['./instance-selector.component.scss'],
standalone: true, standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TranslateModule, MatButtonModule, RouterLink], imports: [TranslateModule, MatButtonModule, RouterLink, NgIconComponent],
providers: [provideIcons({ heroCog8ToothSolid, heroChevronRight })],
}) })
export class InstanceSelectorComponent { export class InstanceSelectorComponent {
@Output() public instanceChanged = new EventEmitter<string>(); @Output() public instanceChanged = new EventEmitter<string>();

View File

@@ -1,4 +1,5 @@
<div class="new-header-wrapper"> <div class="new-header-wrapper">
<span routerLink="/" class="new-header-title">CONSOLE</span>
<ng-container *ngIf="myInstanceQuery.data()?.instance as instance"> <ng-container *ngIf="myInstanceQuery.data()?.instance as instance">
<ng-container *ngTemplateOutlet="slash"></ng-container> <ng-container *ngTemplateOutlet="slash"></ng-container>
<cnsl-header-button <cnsl-header-button
@@ -26,13 +27,15 @@
></cnsl-organization-selector> ></cnsl-organization-selector>
</cnsl-header-dropdown> </cnsl-header-dropdown>
</ng-container> </ng-container>
<ng-container *ngTemplateOutlet="slash"></ng-container> <ng-container *ngIf="['org.read'] | hasRole | async">
<cnsl-header-button cdkOverlayOrigin #orgTrigger="cdkOverlayOrigin" (click)="isOrgDropdownOpen.set(!isOrgDropdownOpen())"> <ng-container *ngTemplateOutlet="slash"></ng-container>
<ng-container *ngIf="activeOrganizationQuery.data() as org">{{ org.name }}</ng-container> <cnsl-header-button cdkOverlayOrigin #orgTrigger="cdkOverlayOrigin" (click)="isOrgDropdownOpen.set(!isOrgDropdownOpen())">
</cnsl-header-button> <ng-container *ngIf="activeOrganizationQuery.data() as org">{{ org.name }}</ng-container>
<cnsl-header-dropdown [trigger]="orgTrigger" [isOpen]="isOrgDropdownOpen()" (closed)="isOrgDropdownOpen.set(false)"> </cnsl-header-button>
<cnsl-organization-selector (orgChanged)="isOrgDropdownOpen.set(false)"></cnsl-organization-selector> <cnsl-header-dropdown [trigger]="orgTrigger" [isOpen]="isOrgDropdownOpen()" (closed)="isOrgDropdownOpen.set(false)">
</cnsl-header-dropdown> <cnsl-organization-selector (orgChanged)="isOrgDropdownOpen.set(false)"></cnsl-organization-selector>
</cnsl-header-dropdown>
</ng-container>
</div> </div>
<ng-template #slash> <ng-template #slash>

View File

@@ -1,7 +1,14 @@
.new-header-wrapper { .new-header-wrapper {
padding-left: 5px;
padding-right: 5px; padding-right: 5px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
gap: 5px; gap: 5px;
} }
.new-header-title {
font-weight: 900;
letter-spacing: 3px;
font-size: 0.8rem;
}

View File

@@ -17,6 +17,7 @@ import { toSignal } from '@angular/core/rxjs-interop';
import { BreakpointObserver } from '@angular/cdk/layout'; import { BreakpointObserver } from '@angular/cdk/layout';
import { NewAdminService } from '../../services/new-admin.service'; import { NewAdminService } from '../../services/new-admin.service';
import { NewAuthService } from '../../services/new-auth.service'; import { NewAuthService } from '../../services/new-auth.service';
import { RouterLink } from '@angular/router';
@Component({ @Component({
selector: 'cnsl-new-header', selector: 'cnsl-new-header',
@@ -37,6 +38,7 @@ import { NewAuthService } from '../../services/new-auth.service';
NgTemplateOutlet, NgTemplateOutlet,
AsyncPipe, AsyncPipe,
HasRolePipeModule, HasRolePipeModule,
RouterLink,
], ],
}) })
export class NewHeaderComponent { export class NewHeaderComponent {

View File

@@ -1,17 +1,14 @@
<div cdkTrapFocus class="focus-trapper"> <div cdkTrapFocus class="focus-trapper">
<!-- <div *ngIf="organizationsQuery.isPending() || setOrgId.isPending()">-->
<!-- Loading organizations...-->
<!-- </div>-->
<div class="org-header"> <div class="org-header">
<button *ngIf="backButton" (click)="backButtonPressed.emit()" mat-button class="dropdown-button"> <button *ngIf="backButton" (click)="backButtonPressed.emit()" mat-button class="dropdown-button">
<span class="back-button"> <span class="back-button">
<i class="las la-arrow-alt-circle-left"></i> <ng-icon name="heroArrowLeftCircleSolid"></ng-icon>
<h3>Back to {{ backButton }}</h3> <h3>Back to {{ backButton }}</h3>
</span> </span>
</button> </button>
<span class="dropdown-label">{{ 'MENU.ORGANIZATION' | translate }}</span> <span class="dropdown-label">{{ 'MENU.ORGANIZATION' | translate }}</span>
<form [formGroup]="form" class="form"> <form [formGroup]="form" class="form">
<i class="las la-1x la-search search-icon"></i> <ng-icon class="search-icon" name="heroMagnifyingGlass"></ng-icon>
<input <input
class="search-input" class="search-input"
autocomplete="off" autocomplete="off"
@@ -25,7 +22,7 @@
<!-- Make sure active org is always at the top --> <!-- Make sure active org is always at the top -->
<a *ngIf="activeOrgIfSearchMatches() as org" class="dropdown-button" mat-button (click)="changeOrg(org.id)"> <a *ngIf="activeOrgIfSearchMatches() as org" class="dropdown-button" mat-button (click)="changeOrg(org.id)">
{{ org.name }} {{ org.name }}
<i class="las la-1x la-check"></i> <ng-icon name="heroCheck"></ng-icon>
</a> </a>
<ng-container *ngFor="let page of organizationsQuery.data()?.pages; last as lastPage"> <ng-container *ngFor="let page of organizationsQuery.data()?.pages; last as lastPage">
<ng-container *ngFor="let org of page.result; trackBy: trackOrg"> <ng-container *ngFor="let org of page.result; trackBy: trackOrg">
@@ -33,15 +30,17 @@
{{ org.name }} {{ org.name }}
</a> </a>
</ng-container> </ng-container>
<button <ng-container *ngIf="lastPage && page.details?.totalResult as totalResult">
class="dropdown-button" <button
mat-stroked-button class="dropdown-button"
*ngIf="lastPage && page.details?.totalResult as totalResult" mat-stroked-button
(click)="organizationsQuery.fetchNextPage()" *ngIf="totalResult > QUERY_LIMIT"
[disabled]="!organizationsQuery.hasNextPage() || organizationsQuery.isFetchingNextPage()" (click)="organizationsQuery.fetchNextPage()"
> [disabled]="!organizationsQuery.hasNextPage() || organizationsQuery.isFetchingNextPage()"
...{{ totalResult - loadedOrgsCount() }} {{ 'PAGINATOR.MORE' | translate }} >
</button> ...{{ totalResult - loadedOrgsCount() }} {{ 'PAGINATOR.MORE' | translate }}
</button>
</ng-container>
</ng-container> </ng-container>
</div> </div>
</div> </div>

View File

@@ -62,7 +62,7 @@
.search-icon { .search-icon {
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: scaleX(-1) translate(0, -50%); transform: translate(0, -50%);
// default input padding // default input padding
left: 10px; left: 10px;
color: if($is-dark-theme, #ffffff60, #00000060); color: if($is-dark-theme, #ffffff60, #00000060);

View File

@@ -4,7 +4,7 @@ import { NewOrganizationService } from 'src/app/services/new-organization.servic
import { NgForOf, NgIf } from '@angular/common'; import { NgForOf, NgIf } from '@angular/common';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { FormBuilder, FormControl, ReactiveFormsModule } from '@angular/forms'; import { FormBuilder, FormControl, ReactiveFormsModule } from '@angular/forms';
import { ListOrganizationsRequestSchema } from '@zitadel/proto/zitadel/org/v2/org_service_pb'; import { ListOrganizationsRequestSchema, ListOrganizationsResponse } from '@zitadel/proto/zitadel/org/v2/org_service_pb';
import { MessageInitShape } from '@bufbuild/protobuf'; import { MessageInitShape } from '@bufbuild/protobuf';
import { debounceTime } from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import { toSignal } from '@angular/core/rxjs-interop'; import { toSignal } from '@angular/core/rxjs-interop';
@@ -17,6 +17,9 @@ import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from '../../input/input.module'; import { InputModule } from '../../input/input.module';
import { MatOptionModule } from '@angular/material/core'; import { MatOptionModule } from '@angular/material/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { heroCheck, heroMagnifyingGlass } from '@ng-icons/heroicons/outline';
import { heroArrowLeftCircleSolid } from '@ng-icons/heroicons/solid';
type NameQuery = Extract< type NameQuery = Extract<
NonNullable<MessageInitShape<typeof ListOrganizationsRequestSchema>['queries']>[number]['query'], NonNullable<MessageInitShape<typeof ListOrganizationsRequestSchema>['queries']>[number]['query'],
@@ -41,7 +44,9 @@ const QUERY_LIMIT = 5;
MatMenuModule, MatMenuModule,
InputModule, InputModule,
MatOptionModule, MatOptionModule,
NgIconComponent,
], ],
providers: [provideIcons({ heroCheck, heroMagnifyingGlass, heroArrowLeftCircleSolid })],
}) })
export class OrganizationSelectorComponent { export class OrganizationSelectorComponent {
@Input() @Input()
@@ -142,29 +147,29 @@ export class OrganizationSelectorComponent {
queries: query ? [{ query }] : undefined, queries: query ? [{ query }] : undefined,
}, },
placeholderData: keepPreviousData, placeholderData: keepPreviousData,
getNextPageParam: (lastPage, _, pageParam) => getNextPageParam: (lastPage, pages, pageParam) =>
// if we received less than the limit last time we are at the end this.countLoadedOrgs(pages) < (lastPage.details?.totalResult ?? BigInt(Number.MAX_SAFE_INTEGER))
lastPage.result.length < pageParam.query.limit ? {
? undefined
: {
...pageParam, ...pageParam,
query: { query: {
...pageParam.query, ...pageParam.query,
offset: pageParam.query.offset + BigInt(lastPage.result.length), offset: pageParam.query.offset + BigInt(lastPage.result.length),
}, },
}, }
: undefined,
}; };
}); });
} }
private getLoadedOrgsCount(organizationsQuery: ReturnType<typeof this.getOrganizationsQuery>) { private getLoadedOrgsCount(organizationsQuery: ReturnType<typeof this.getOrganizationsQuery>) {
return computed(() => { return computed(() => this.countLoadedOrgs(organizationsQuery.data()?.pages));
const pages = organizationsQuery.data()?.pages; }
if (!pages) {
return BigInt(0); private countLoadedOrgs(pages?: ListOrganizationsResponse[]) {
} if (!pages) {
return pages.reduce((acc, page) => acc + BigInt(page.result.length), BigInt(0)); return BigInt(0);
}); }
return pages.reduce((acc, page) => acc + BigInt(page.result.length), BigInt(0));
} }
private getActiveOrgIfSearchMatches(nameQuery: Signal<NameQuery | undefined>) { private getActiveOrgIfSearchMatches(nameQuery: Signal<NameQuery | undefined>) {
@@ -187,4 +192,6 @@ export class OrganizationSelectorComponent {
protected trackOrg(_: number, { id }: Organization): string { protected trackOrg(_: number, { id }: Organization): string {
return id; return id;
} }
protected readonly QUERY_LIMIT = QUERY_LIMIT;
} }

View File

@@ -89,14 +89,6 @@ export class AuthUserDetailComponent implements OnInit {
return ''; return '';
}); });
protected savedLanguage = computed(() => {
const user = this.user.data();
if (!user || user.type.case !== 'human' || !user.type.value.profile?.preferredLanguage) {
return this.translate.defaultLang;
}
return user.type.value.profile?.preferredLanguage;
});
constructor( constructor(
private translate: TranslateService, private translate: TranslateService,
private toast: ToastService, private toast: ToastService,
@@ -141,10 +133,6 @@ export class AuthUserDetailComponent implements OnInit {
this.toast.showError(error); this.toast.showError(error);
} }
}); });
effect(() => {
this.translate.use(this.savedLanguage());
});
} }
ngOnInit(): void { ngOnInit(): void {

View File

@@ -44,8 +44,6 @@ export class NewOrganizationService {
} }
public async setOrgId(orgId?: string) { public async setOrgId(orgId?: string) {
console.log('beboop', orgId);
console.trace(orgId);
const organization = await this.queryClient.fetchQuery(this.organizationByIdQueryOptions(orgId ?? this.getOrgId()())); const organization = await this.queryClient.fetchQuery(this.organizationByIdQueryOptions(orgId ?? this.getOrgId()()));
if (organization) { if (organization) {
this.storage.setItem(StorageKey.organizationId, orgId, StorageLocation.session); this.storage.setItem(StorageKey.organizationId, orgId, StorageLocation.session);

View File

@@ -2641,6 +2641,20 @@
read-package-up "^11.0.0" read-package-up "^11.0.0"
semver "^7.3.8" semver "^7.3.8"
"@ng-icons/core@^25.0.0":
version "25.6.1"
resolved "https://registry.yarnpkg.com/@ng-icons/core/-/core-25.6.1.tgz#471c2597af226c5b6f53ec5d39c8ec680964b9b2"
integrity sha512-o6vCttlzXvDZRYiOKOULr7fsX8gY/DwwxzBSrBQzwa/at+pC0xRoe6uczJ9Ato+y1EDWP/PlrEMAQfvokBA6tQ==
dependencies:
tslib "^2.2.0"
"@ng-icons/heroicons@^25.0.0":
version "25.6.1"
resolved "https://registry.yarnpkg.com/@ng-icons/heroicons/-/heroicons-25.6.1.tgz#e6cd64c68c22e3ae4d93a1a1b7daa537f6d9d600"
integrity sha512-QGTIIl+S6/w2vQvYGP1zNLbNvJLLRS+1evlOPWZZzWow+77qRxs0E96CukSsjItBFUnLKvzuOfMBBcNtb2SIHQ==
dependencies:
tslib "^2.2.0"
"@ngtools/webpack@16.2.16": "@ngtools/webpack@16.2.16":
version "16.2.16" version "16.2.16"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-16.2.16.tgz#512da8f3459faafd0cc1f7f7cbec96b678377be6" resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-16.2.16.tgz#512da8f3459faafd0cc1f7f7cbec96b678377be6"
@@ -8719,7 +8733,7 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.4.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
tslib@^2.1.0, tslib@^2.7.0: tslib@^2.1.0, tslib@^2.2.0, tslib@^2.7.0:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==