diff --git a/libs/vault/src/cipher-view/additional-options/additional-options.component.ts b/libs/vault/src/cipher-view/additional-options/additional-options.component.ts index d590fbf3d5..9f8f034d59 100644 --- a/libs/vault/src/cipher-view/additional-options/additional-options.component.ts +++ b/libs/vault/src/cipher-view/additional-options/additional-options.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { CommonModule } from "@angular/common"; import { Component, Input } from "@angular/core"; @@ -31,5 +29,5 @@ import { ], }) export class AdditionalOptionsComponent { - @Input() notes: string; + @Input() notes: string = ""; } diff --git a/libs/vault/src/cipher-view/cipher-view.component.ts b/libs/vault/src/cipher-view/cipher-view.component.ts index d525b88d92..57af96258f 100644 --- a/libs/vault/src/cipher-view/cipher-view.component.ts +++ b/libs/vault/src/cipher-view/cipher-view.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { CommonModule } from "@angular/common"; import { Component, Input, OnChanges, OnDestroy } from "@angular/core"; import { firstValueFrom, Observable, Subject, takeUntil } from "rxjs"; @@ -48,19 +46,19 @@ import { ViewIdentitySectionsComponent } from "./view-identity-sections/view-ide ], }) export class CipherViewComponent implements OnChanges, OnDestroy { - @Input({ required: true }) cipher: CipherView; + @Input({ required: true }) cipher: CipherView | null = null; /** * Optional list of collections the cipher is assigned to. If none are provided, they will be fetched using the * `CipherService` and the `collectionIds` property of the cipher. */ - @Input() collections: CollectionView[]; + @Input() collections?: CollectionView[]; /** Should be set to true when the component is used within the Admin Console */ @Input() isAdminConsole?: boolean = false; - organization$: Observable; - folder$: Observable; + organization$: Observable | undefined; + folder$: Observable | undefined; private destroyed$: Subject = new Subject(); cardIsExpired: boolean = false; @@ -86,24 +84,38 @@ export class CipherViewComponent implements OnChanges, OnDestroy { } get hasCard() { + if (!this.cipher) { + return false; + } + const { cardholderName, code, expMonth, expYear, number } = this.cipher.card; return cardholderName || code || expMonth || expYear || number; } get hasLogin() { + if (!this.cipher) { + return false; + } + const { username, password, totp } = this.cipher.login; return username || password || totp; } get hasAutofill() { - return this.cipher.login?.uris.length > 0; + const uris = this.cipher?.login?.uris.length ?? 0; + + return uris > 0; } get hasSshKey() { - return this.cipher.sshKey?.privateKey; + return !!this.cipher?.sshKey?.privateKey; } async loadCipherData() { + if (!this.cipher) { + return; + } + // Load collections if not provided and the cipher has collectionIds if ( this.cipher.collectionIds && diff --git a/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts b/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts index a4faa663bf..0c42c2ddda 100644 --- a/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts +++ b/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts @@ -11,7 +11,6 @@ import { EventType } from "@bitwarden/common/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { - CardComponent, FormFieldModule, SectionComponent, SectionHeaderComponent, @@ -37,7 +36,6 @@ type TotpCodeValues = { imports: [ CommonModule, JslibModule, - CardComponent, SectionComponent, SectionHeaderComponent, TypographyModule, diff --git a/libs/vault/src/cipher-view/read-only-cipher-card/read-only-cipher-card.component.ts b/libs/vault/src/cipher-view/read-only-cipher-card/read-only-cipher-card.component.ts index 73fb570f56..9005ea9674 100644 --- a/libs/vault/src/cipher-view/read-only-cipher-card/read-only-cipher-card.component.ts +++ b/libs/vault/src/cipher-view/read-only-cipher-card/read-only-cipher-card.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { AfterViewInit, Component, ContentChildren, QueryList } from "@angular/core"; import { CardComponent, BitFormFieldComponent } from "@bitwarden/components"; @@ -14,14 +12,16 @@ import { CardComponent, BitFormFieldComponent } from "@bitwarden/components"; * A thin wrapper around the `bit-card` component that disables the bottom border for the last form field. */ export class ReadOnlyCipherCardComponent implements AfterViewInit { - @ContentChildren(BitFormFieldComponent) formFields: QueryList; + @ContentChildren(BitFormFieldComponent) formFields?: QueryList; ngAfterViewInit(): void { // Disable the bottom border for the last form field - if (this.formFields.last) { + if (this.formFields?.last) { // Delay model update until next change detection cycle setTimeout(() => { - this.formFields.last.disableReadOnlyBorder = true; + if (this.formFields) { + this.formFields.last.disableReadOnlyBorder = true; + } }); } } diff --git a/libs/vault/src/cipher-view/view-identity-sections/view-identity-sections.component.ts b/libs/vault/src/cipher-view/view-identity-sections/view-identity-sections.component.ts index bb9b8d0a9a..fdd5bb66a5 100644 --- a/libs/vault/src/cipher-view/view-identity-sections/view-identity-sections.component.ts +++ b/libs/vault/src/cipher-view/view-identity-sections/view-identity-sections.component.ts @@ -1,12 +1,9 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { NgIf } from "@angular/common"; import { Component, Input, OnInit } from "@angular/core"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { - CardComponent, FormFieldModule, IconButtonModule, SectionComponent, @@ -23,7 +20,6 @@ import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only- imports: [ NgIf, JslibModule, - CardComponent, SectionComponent, SectionHeaderComponent, TypographyModule, @@ -33,11 +29,11 @@ import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only- ], }) export class ViewIdentitySectionsComponent implements OnInit { - @Input() cipher: CipherView; + @Input({ required: true }) cipher: CipherView | null = null; - showPersonalDetails: boolean; - showIdentificationDetails: boolean; - showContactDetails: boolean; + showPersonalDetails: boolean = false; + showIdentificationDetails: boolean = false; + showContactDetails: boolean = false; ngOnInit(): void { this.showPersonalDetails = this.hasPersonalDetails(); @@ -47,6 +43,10 @@ export class ViewIdentitySectionsComponent implements OnInit { /** Returns all populated address fields */ get addressFields(): string { + if (!this.cipher) { + return ""; + } + const { address1, address2, address3, fullAddressPart2, country } = this.cipher.identity; return [address1, address2, address3, fullAddressPart2, country].filter(Boolean).join("\n"); } @@ -58,18 +58,30 @@ export class ViewIdentitySectionsComponent implements OnInit { /** Returns true when any of the "personal detail" attributes are populated */ private hasPersonalDetails(): boolean { + if (!this.cipher) { + return false; + } + const { username, company, fullName } = this.cipher.identity; return Boolean(fullName || username || company); } /** Returns true when any of the "identification detail" attributes are populated */ private hasIdentificationDetails(): boolean { + if (!this.cipher) { + return false; + } + const { ssn, passportNumber, licenseNumber } = this.cipher.identity; return Boolean(ssn || passportNumber || licenseNumber); } /** Returns true when any of the "contact detail" attributes are populated */ private hasContactDetails(): boolean { + if (!this.cipher) { + return false; + } + const { email, phone } = this.cipher.identity; return Boolean(email || phone || this.addressFields);