[PM-8527] Identity Add Edit Browser V2 (#10016)

* Add Identity Edit Section for Browser V2 Edit Work
This commit is contained in:
Jason Ng 2024-07-10 12:25:20 -04:00 committed by GitHub
parent aa57260756
commit 91294e9c4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 299 additions and 0 deletions

View File

@ -3607,6 +3607,15 @@
"filters": {
"message": "Filters"
},
"personalDetails": {
"message": "Personal details"
},
"identification": {
"message": "Identification"
},
"contactInfo": {
"message": "Contact info"
},
"downloadAttachment": {
"message": "Download - $ITEMNAME$",
"placeholders": {

View File

@ -55,6 +55,9 @@ export class OpenAttachmentsComponent implements OnInit {
}
async ngOnInit(): Promise<void> {
if (!this.cipherId) {
return;
}
const cipherDomain = await this.cipherService.get(this.cipherId);
const cipher = await cipherDomain.decrypt(
await this.cipherService.getKeyForCipherKeyDecryption(cipherDomain),

View File

@ -1,6 +1,7 @@
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { CardDetailsSectionComponent } from "./components/card-details-section/card-details-section.component";
import { IdentitySectionComponent } from "./components/identity/identity.component";
import { ItemDetailsSectionComponent } from "./components/item-details/item-details-section.component";
/**
@ -10,6 +11,7 @@ import { ItemDetailsSectionComponent } from "./components/item-details/item-deta
export type CipherForm = {
itemDetails?: ItemDetailsSectionComponent["itemDetailsForm"];
cardDetails?: CardDetailsSectionComponent["cardDetailsForm"];
identityDetails?: IdentitySectionComponent["identityForm"];
};
/**

View File

@ -6,6 +6,12 @@
[originalCipherView]="originalCipherView"
></vault-item-details-section>
<vault-identity-section
*ngIf="config.cipherType === CipherType.Identity"
[disabled]="config.mode === 'partial-edit'"
[originalCipherView]="originalCipherView"
></vault-identity-section>
<vault-card-details-section
*ngIf="config.cipherType === CipherType.Card"
[originalCipherView]="originalCipherView"

View File

@ -36,6 +36,7 @@ import { CipherFormService } from "../abstractions/cipher-form.service";
import { CipherForm, CipherFormContainer } from "../cipher-form-container";
import { CardDetailsSectionComponent } from "./card-details-section/card-details-section.component";
import { IdentitySectionComponent } from "./identity/identity.component";
import { ItemDetailsSectionComponent } from "./item-details/item-details-section.component";
@Component({
@ -59,6 +60,7 @@ import { ItemDetailsSectionComponent } from "./item-details/item-details-section
SelectModule,
ItemDetailsSectionComponent,
CardDetailsSectionComponent,
IdentitySectionComponent,
NgIf,
],
})

View File

@ -0,0 +1,141 @@
<form [formGroup]="identityForm">
<bit-section>
<bit-section-header>
<h2 bitTypography="h5">{{ "personalDetails" | i18n }}</h2>
</bit-section-header>
<bit-card>
<bit-form-field>
<bit-label>
{{ "title" | i18n }}
</bit-label>
<bit-select formControlName="title">
<bit-option
*ngFor="let title of identityTitleOptions"
[value]="title.value"
[label]="title.name"
>
</bit-option>
</bit-select>
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "firstName" | i18n }}
</bit-label>
<input bitInput formControlName="firstName" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "lastName" | i18n }}
</bit-label>
<input bitInput formControlName="lastName" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "username" | i18n }}
</bit-label>
<input bitInput formControlName="username" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "company" | i18n }}
</bit-label>
<input bitInput formControlName="company" />
</bit-form-field>
</bit-card>
</bit-section>
<bit-section>
<bit-section-header>
<h2 bitTypography="h5">{{ "identification" | i18n }}</h2>
</bit-section-header>
<bit-card>
<bit-form-field>
<bit-label>
{{ "ssn" | i18n }}
</bit-label>
<input formControlName="ssn" bitInput type="password" />
<button type="button" bitIconButton bitPasswordInputToggle></button>
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "passportNumber" | i18n }}
</bit-label>
<input formControlName="passportNumber" bitInput type="password" />
<button type="button" bitIconButton bitPasswordInputToggle></button>
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "licenseNumber" | i18n }}
</bit-label>
<input bitInput formControlName="licenseNumber" />
</bit-form-field>
</bit-card>
</bit-section>
<bit-section>
<bit-section-header>
<h2 bitTypography="h5">{{ "contactInfo" | i18n }}</h2>
</bit-section-header>
<bit-card>
<bit-form-field>
<bit-label>
{{ "email" | i18n }}
</bit-label>
<input bitInput formControlName="email" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "phone" | i18n }}
</bit-label>
<input bitInput formControlName="phone" />
</bit-form-field>
</bit-card>
</bit-section>
<bit-section>
<bit-section-header>
<h2 bitTypography="h5">{{ "address" | i18n }}</h2>
</bit-section-header>
<bit-card>
<bit-form-field>
<bit-label>
{{ "address1" | i18n }}
</bit-label>
<input bitInput formControlName="address1" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "address2" | i18n }}
</bit-label>
<input bitInput formControlName="address2" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "address3" | i18n }}
</bit-label>
<input bitInput formControlName="address3" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "cityTown" | i18n }}
</bit-label>
<input bitInput formControlName="city" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "stateProvince" | i18n }}
</bit-label>
<input bitInput formControlName="state" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "zipPostalCode" | i18n }}
</bit-label>
<input bitInput formControlName="postalCode" />
</bit-form-field>
<bit-form-field>
<bit-label>
{{ "country" | i18n }}
</bit-label>
<input bitInput formControlName="country" />
</bit-form-field>
</bit-card>
</bit-section>
</form>

View File

@ -0,0 +1,136 @@
import { CommonModule } from "@angular/common";
import { Component, Input, OnInit } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormBuilder, ReactiveFormsModule } from "@angular/forms";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view";
import {
ButtonModule,
SectionComponent,
SectionHeaderComponent,
CardComponent,
FormFieldModule,
IconButtonModule,
SelectModule,
} from "@bitwarden/components";
import { CipherFormContainer } from "../../cipher-form-container";
@Component({
standalone: true,
selector: "vault-identity-section",
templateUrl: "./identity.component.html",
imports: [
CommonModule,
ButtonModule,
JslibModule,
ReactiveFormsModule,
SectionComponent,
SectionHeaderComponent,
CardComponent,
FormFieldModule,
IconButtonModule,
SelectModule,
],
})
export class IdentitySectionComponent implements OnInit {
@Input() originalCipherView: CipherView;
@Input() disabled: boolean;
identityTitleOptions = [
{ name: "-- " + this.i18nService.t("select") + " --", value: null },
{ name: this.i18nService.t("mr"), value: this.i18nService.t("mr") },
{ name: this.i18nService.t("mrs"), value: this.i18nService.t("mrs") },
{ name: this.i18nService.t("ms"), value: this.i18nService.t("ms") },
{ name: this.i18nService.t("mx"), value: this.i18nService.t("mx") },
{ name: this.i18nService.t("dr"), value: this.i18nService.t("dr") },
];
protected identityForm = this.formBuilder.group({
title: [null],
firstName: [""],
lastName: [""],
username: [""],
company: [""],
ssn: [""],
passportNumber: [""],
licenseNumber: [""],
email: [""],
phone: [""],
address1: [""],
address2: [""],
address3: [""],
city: [""],
state: [""],
postalCode: [""],
country: [""],
});
constructor(
private cipherFormContainer: CipherFormContainer,
private formBuilder: FormBuilder,
private i18nService: I18nService,
) {
this.cipherFormContainer.registerChildForm("identityDetails", this.identityForm);
this.identityForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
const data = new IdentityView();
data.title = value.title;
data.firstName = value.firstName;
data.lastName = value.lastName;
data.username = value.username;
data.company = value.company;
data.ssn = value.ssn;
data.passportNumber = value.passportNumber;
data.licenseNumber = value.licenseNumber;
data.email = value.email;
data.phone = value.phone;
data.address1 = value.address1;
data.address2 = value.address2;
data.address3 = value.address3;
data.city = value.city;
data.state = value.state;
data.postalCode = value.postalCode;
data.country = value.country;
this.cipherFormContainer.patchCipher({
identity: data,
});
});
}
ngOnInit() {
// If true will disable all inputs
if (this.disabled) {
this.identityForm.disable();
}
if (this.originalCipherView && this.originalCipherView.id) {
this.populateFormData();
}
}
populateFormData() {
const { identity } = this.originalCipherView;
this.identityForm.setValue({
title: identity.title,
firstName: identity.firstName,
lastName: identity.lastName,
username: identity.username,
company: identity.company,
ssn: identity.ssn,
passportNumber: identity.passportNumber,
licenseNumber: identity.licenseNumber,
email: identity.email,
phone: identity.phone,
address1: identity.address1,
address2: identity.address2,
address3: identity.address3,
city: identity.city,
state: identity.state,
postalCode: identity.postalCode,
country: identity.country,
});
}
}