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:
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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 }}"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user