1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 02:03:39 +00:00

[PM-20988][PM-20986][PM-20983][PM-20971][PM-21019] - Multiple defect fixes for desktop cipher form update (#14559)

* multiple bug fixes

* favor getters to local state

* fix tests
This commit is contained in:
Jordan Aasen
2025-05-02 14:21:08 -07:00
committed by GitHub
parent fdfb0196d0
commit 237002b633
6 changed files with 31 additions and 29 deletions

View File

@@ -2007,6 +2007,21 @@
"message": "Premium", "message": "Premium",
"description": "Premium membership" "description": "Premium membership"
}, },
"freeOrgsCannotUseAttachments": {
"message": "Free organizations cannot use attachments"
},
"singleFieldNeedsAttention": {
"message": "1 field needs your attention."
},
"multipleFieldsNeedAttention": {
"message": "$COUNT$ fields need your attention.",
"placeholders": {
"count": {
"content": "$1",
"example": "2"
}
}
},
"cardExpiredTitle": { "cardExpiredTitle": {
"message": "Expired card" "message": "Expired card"
}, },

View File

@@ -44,7 +44,7 @@
<button <button
type="button" type="button"
class="primary" class="primary"
*ngIf="cipher.id && !cipher?.organizationId && !cipher.isDeleted && action !== 'clone'" *ngIf="cipher.id && !cipher?.organizationId && !cipher.isDeleted && action === 'view'"
(click)="clone()" (click)="clone()"
appA11yTitle="{{ 'clone' | i18n }}" appA11yTitle="{{ 'clone' | i18n }}"
> >

View File

@@ -13,7 +13,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { firstValueFrom, Subject, takeUntil, switchMap } from "rxjs"; import { firstValueFrom, Subject, takeUntil, switchMap } from "rxjs";
import { filter, map, take } from "rxjs/operators"; import { filter, map, take } from "rxjs/operators";
import { CollectionView } from "@bitwarden/admin-console/common"; import { CollectionService, CollectionView } from "@bitwarden/admin-console/common";
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ModalService } from "@bitwarden/angular/services/modal.service";
import { VaultViewPasswordHistoryService } from "@bitwarden/angular/services/view-password-history.service"; import { VaultViewPasswordHistoryService } from "@bitwarden/angular/services/view-password-history.service";
@@ -29,7 +29,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SyncService } from "@bitwarden/common/platform/sync"; import { SyncService } from "@bitwarden/common/platform/sync";
import { CipherId, UserId } from "@bitwarden/common/types/guid"; import { CipherId, CollectionId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { PremiumUpgradePromptService } from "@bitwarden/common/vault/abstractions/premium-upgrade-prompt.service"; import { PremiumUpgradePromptService } from "@bitwarden/common/vault/abstractions/premium-upgrade-prompt.service";
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service"; import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
@@ -175,6 +175,7 @@ export class VaultV2Component implements OnInit, OnDestroy {
private cipherService: CipherService, private cipherService: CipherService,
private formConfigService: CipherFormConfigService, private formConfigService: CipherFormConfigService,
private premiumUpgradePromptService: PremiumUpgradePromptService, private premiumUpgradePromptService: PremiumUpgradePromptService,
private collectionService: CollectionService,
) {} ) {}
async ngOnInit() { async ngOnInit() {
@@ -359,7 +360,7 @@ export class VaultV2Component implements OnInit, OnDestroy {
this.cipherId = cipher.id; this.cipherId = cipher.id;
this.cipher = cipher; this.cipher = cipher;
this.collections = this.collections =
this.vaultFilterComponent?.collections.fullList.filter((c) => this.vaultFilterComponent?.collections?.fullList.filter((c) =>
cipher.collectionIds.includes(c.id), cipher.collectionIds.includes(c.id),
) ?? null; ) ?? null;
this.action = "view"; this.action = "view";
@@ -548,6 +549,9 @@ export class VaultV2Component implements OnInit, OnDestroy {
this.cipherId = null; this.cipherId = null;
this.action = "view"; this.action = "view";
await this.vaultItemsComponent?.refresh().catch(() => {}); await this.vaultItemsComponent?.refresh().catch(() => {});
this.collections = await firstValueFrom(
this.collectionService.decryptedCollectionViews$(cipher.collectionIds as CollectionId[]),
);
this.cipherId = cipher.id; this.cipherId = cipher.id;
this.cipher = cipher; this.cipher = cipher;
if (this.activeUserId) { if (this.activeUserId) {

View File

@@ -1,4 +1,4 @@
<bit-section *ngIf="showPersonalDetails"> <bit-section *ngIf="hasPersonalDetails">
<bit-section-header> <bit-section-header>
<h2 bitTypography="h6">{{ "personalDetails" | i18n }}</h2> <h2 bitTypography="h6">{{ "personalDetails" | i18n }}</h2>
</bit-section-header> </bit-section-header>
@@ -66,7 +66,7 @@
</read-only-cipher-card> </read-only-cipher-card>
</bit-section> </bit-section>
<bit-section *ngIf="showIdentificationDetails"> <bit-section *ngIf="hasIdentificationDetails">
<bit-section-header> <bit-section-header>
<h2 bitTypography="h6">{{ "identification" | i18n }}</h2> <h2 bitTypography="h6">{{ "identification" | i18n }}</h2>
</bit-section-header> </bit-section-header>
@@ -155,7 +155,7 @@
</read-only-cipher-card> </read-only-cipher-card>
</bit-section> </bit-section>
<bit-section *ngIf="showContactDetails"> <bit-section *ngIf="hasContactDetails">
<bit-section-header> <bit-section-header>
<h2 bitTypography="h6">{{ "contactInfo" | i18n }}</h2> <h2 bitTypography="h6">{{ "contactInfo" | i18n }}</h2>
</bit-section-header> </bit-section-header>

View File

@@ -43,7 +43,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
personalDetailSection = fixture.debugElement.query(By.directive(SectionHeaderComponent)); personalDetailSection = fixture.debugElement.query(By.directive(SectionHeaderComponent));
@@ -61,7 +60,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective)); const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective));
@@ -86,7 +84,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
identificationDetailSection = fixture.debugElement.query( identificationDetailSection = fixture.debugElement.query(
@@ -106,7 +103,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective)); const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective));
@@ -129,7 +125,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
contactDetailSection = fixture.debugElement.query(By.directive(SectionHeaderComponent)); contactDetailSection = fixture.debugElement.query(By.directive(SectionHeaderComponent));
@@ -151,7 +146,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective)); const fields = fixture.debugElement.queryAll(By.directive(BitInputDirective));
@@ -174,7 +168,6 @@ describe("ViewIdentitySectionsComponent", () => {
}, },
} as CipherView; } as CipherView;
component.ngOnInit();
fixture.detectChanges(); fixture.detectChanges();
let textarea = fixture.debugElement.query(By.css("textarea")); let textarea = fixture.debugElement.query(By.css("textarea"));

View File

@@ -1,5 +1,5 @@
import { NgIf } from "@angular/common"; import { NgIf } from "@angular/common";
import { Component, Input, OnInit } from "@angular/core"; import { Component, Input } from "@angular/core";
import { JslibModule } from "@bitwarden/angular/jslib.module"; import { JslibModule } from "@bitwarden/angular/jslib.module";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -28,19 +28,9 @@ import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only-
ReadOnlyCipherCardComponent, ReadOnlyCipherCardComponent,
], ],
}) })
export class ViewIdentitySectionsComponent implements OnInit { export class ViewIdentitySectionsComponent {
@Input({ required: true }) cipher: CipherView | null = null; @Input({ required: true }) cipher: CipherView | null = null;
showPersonalDetails: boolean = false;
showIdentificationDetails: boolean = false;
showContactDetails: boolean = false;
ngOnInit(): void {
this.showPersonalDetails = this.hasPersonalDetails();
this.showIdentificationDetails = this.hasIdentificationDetails();
this.showContactDetails = this.hasContactDetails();
}
/** Returns all populated address fields */ /** Returns all populated address fields */
get addressFields(): string { get addressFields(): string {
if (!this.cipher) { if (!this.cipher) {
@@ -57,7 +47,7 @@ export class ViewIdentitySectionsComponent implements OnInit {
} }
/** Returns true when any of the "personal detail" attributes are populated */ /** Returns true when any of the "personal detail" attributes are populated */
private hasPersonalDetails(): boolean { get hasPersonalDetails(): boolean {
if (!this.cipher) { if (!this.cipher) {
return false; return false;
} }
@@ -67,7 +57,7 @@ export class ViewIdentitySectionsComponent implements OnInit {
} }
/** Returns true when any of the "identification detail" attributes are populated */ /** Returns true when any of the "identification detail" attributes are populated */
private hasIdentificationDetails(): boolean { get hasIdentificationDetails(): boolean {
if (!this.cipher) { if (!this.cipher) {
return false; return false;
} }
@@ -77,7 +67,7 @@ export class ViewIdentitySectionsComponent implements OnInit {
} }
/** Returns true when any of the "contact detail" attributes are populated */ /** Returns true when any of the "contact detail" attributes are populated */
private hasContactDetails(): boolean { get hasContactDetails(): boolean {
if (!this.cipher) { if (!this.cipher) {
return false; return false;
} }