1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-11 14:48:46 +01:00

[PM-14345] Enabling drag and drop for cipher fields (#12067)

* enabling drag and drop for cipher fields

* adding drag and drop to totp and fido

* removing code changes to wrong file

* undoing uneeded change

* Changes suggested by Shane

* fixes

* fixes

* moving export to the correct spot

---------

Co-authored-by: --global <>
This commit is contained in:
cd-bitwarden 2024-12-10 12:55:02 -05:00 committed by GitHub
parent 4003d30b46
commit 83dc66dd56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 105 additions and 30 deletions

View File

@ -0,0 +1,22 @@
import { Directive, HostListener, Input } from "@angular/core";
@Directive({
selector: "[appTextDrag]",
standalone: true,
host: {
draggable: "true",
class: "tw-cursor-move",
},
})
export class TextDragDirective {
@Input({
alias: "appTextDrag",
required: true,
})
data = "";
@HostListener("dragstart", ["$event"])
onDragStart(event: DragEvent) {
event.dataTransfer.setData("text", this.data);
}
}

View File

@ -43,6 +43,7 @@ import { LaunchClickDirective } from "./directives/launch-click.directive";
import { NotPremiumDirective } from "./directives/not-premium.directive";
import { StopClickDirective } from "./directives/stop-click.directive";
import { StopPropDirective } from "./directives/stop-prop.directive";
import { TextDragDirective } from "./directives/text-drag.directive";
import { TrueFalseValueDirective } from "./directives/true-false-value.directive";
import { CreditCardNumberPipe } from "./pipes/credit-card-number.pipe";
import { PluralizePipe } from "./pipes/pluralize.pipe";
@ -81,6 +82,7 @@ import { IconComponent } from "./vault/components/icon.component";
IconModule,
LinkModule,
IconModule,
TextDragDirective,
],
declarations: [
A11yInvalidDirective,
@ -150,6 +152,7 @@ import { IconComponent } from "./vault/components/icon.component";
NoInvoicesComponent,
ManageTaxInformationComponent,
TwoFactorIconComponent,
TextDragDirective,
],
providers: [
CreditCardNumberPipe,

View File

@ -4,8 +4,8 @@
</bit-section-header>
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
<bit-form-field disableReadOnlyBorder>
<bit-label>{{ "note" | i18n }}</bit-label>
<textarea readonly bitInput rows="5" aria-readonly="true">{{ notes }}</textarea>
<bit-label [appTextDrag]="notes">{{ "note" | i18n }}</bit-label>
<textarea readonly id="notes" bitInput rows="5" aria-readonly="true">{{ notes }}</textarea>
<button
bitSuffix
bitIconButton="bwi-clone"

View File

@ -4,8 +4,9 @@
</bit-section-header>
<read-only-cipher-card>
<bit-form-field *ngIf="card.cardholderName">
<bit-label>{{ "cardholderName" | i18n }}</bit-label>
<bit-label [appTextDrag]="card.cardholderName">{{ "cardholderName" | i18n }}</bit-label>
<input
id="cardholderName"
readonly
bitInput
type="text"
@ -15,8 +16,9 @@
/>
</bit-form-field>
<bit-form-field *ngIf="card.number">
<bit-label>{{ "number" | i18n }}</bit-label>
<bit-label [appTextDrag]="card.number">{{ "number" | i18n }}</bit-label>
<input
id="cardNumber"
readonly
bitInput
type="password"
@ -45,8 +47,9 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="card.expiration">
<bit-label>{{ "expiration" | i18n }}</bit-label>
<bit-label [appTextDrag]="card.expiration">{{ "expiration" | i18n }}</bit-label>
<input
id="expiration"
readonly
bitInput
type="text"
@ -56,8 +59,9 @@
/>
</bit-form-field>
<bit-form-field *ngIf="card.code">
<bit-label>{{ "securityCode" | i18n }}</bit-label>
<bit-label [appTextDrag]="card.code">{{ "securityCode" | i18n }}</bit-label>
<input
id="securityCode"
readonly
bitInput
type="password"

View File

@ -10,7 +10,7 @@
data-testid="custom-field"
>
<bit-form-field *ngIf="field.type === fieldType.Text" [disableReadOnlyBorder]="last">
<bit-label>{{ field.name }}</bit-label>
<bit-label [appTextDrag]="field.value">{{ field.name }}</bit-label>
<input readonly bitInput type="text" [value]="field.value" aria-readonly="true" />
<button
bitIconButton="bwi-clone"
@ -24,7 +24,7 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="field.type === fieldType.Hidden" [disableReadOnlyBorder]="last">
<bit-label>{{ field.name }}</bit-label>
<bit-label [appTextDrag]="field.value">{{ field.name }}</bit-label>
<input
readonly
bitInput
@ -59,7 +59,9 @@
aria-readonly="true"
disabled
/>
<bit-label> {{ field.name }} </bit-label>
<bit-label [appTextDrag]="field.value">
{{ field.name }}
</bit-label>
</bit-form-control>
<bit-form-field *ngIf="field.type === fieldType.Linked" [disableReadOnlyBorder]="last">
<bit-label> {{ "cfTypeLinked" | i18n }}: {{ field.name }} </bit-label>

View File

@ -7,11 +7,12 @@
[disableMargin]="!cipher.collectionIds?.length && !showOwnership && !cipher.folderId"
[disableReadOnlyBorder]="!cipher.collectionIds?.length && !showOwnership && !cipher.folderId"
>
<bit-label>
<bit-label [appTextDrag]="cipher.name">
{{ "itemName" | i18n }}
</bit-label>
<input
readonly
id="itemName"
bitInput
type="text"
[value]="cipher.name"

View File

@ -4,10 +4,11 @@
</bit-section-header>
<read-only-cipher-card>
<bit-form-field *ngIf="cipher.login.username">
<bit-label>
<bit-label [appTextDrag]="cipher.login.username">
{{ "username" | i18n }}
</bit-label>
<input
id="userName"
readonly
bitInput
type="text"
@ -27,8 +28,9 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.login.password">
<bit-label>{{ "password" | i18n }}</bit-label>
<bit-label [appTextDrag]="cipher.login.password">{{ "password" | i18n }}</bit-label>
<input
id="password"
readonly
bitInput
type="password"
@ -80,8 +82,11 @@
></bit-color-password>
</div>
<bit-form-field *ngIf="cipher.login?.fido2Credentials?.length > 0">
<bit-label>{{ "typePasskey" | i18n }} </bit-label>
<bit-label [appTextDrag]="fido2CredentialCreationDateValue"
>{{ "typePasskey" | i18n }}
</bit-label>
<input
id="fido"
readonly
bitInput
type="text"
@ -91,7 +96,7 @@
/>
</bit-form-field>
<bit-form-field *ngIf="cipher.login.totp">
<bit-label
<bit-label [appTextDrag]="totpCodeCopyObj?.totpCode"
>{{ "verificationCodeTotp" | i18n }}
<span
*ngIf="!(isPremium$ | async)"
@ -105,6 +110,7 @@
</span>
</bit-label>
<input
id="totp"
readonly
bitInput
[type]="!(isPremium$ | async) ? 'password' : 'text'"

View File

@ -5,8 +5,14 @@
<read-only-cipher-card>
<bit-form-field *ngIf="cipher.identity.fullName">
<bit-label>{{ "name" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.fullName" readonly data-testid="name" />
<bit-label [appTextDrag]="cipher.identity.fullName">{{ "name" | i18n }}</bit-label>
<input
bitInput
id="fullName"
[value]="cipher.identity.fullName"
readonly
data-testid="name"
/>
<button
type="button"
bitIconButton="bwi-clone"
@ -19,8 +25,14 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.identity.username">
<bit-label>{{ "username" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.username" readonly data-testid="username" />
<bit-label [appTextDrag]="cipher.identity.username">{{ "username" | i18n }}</bit-label>
<input
bitInput
id="username"
[value]="cipher.identity.username"
readonly
data-testid="username"
/>
<button
type="button"
bitIconButton="bwi-clone"
@ -32,8 +44,14 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.identity.company">
<bit-label>{{ "company" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.company" readonly data-testid="company" />
<bit-label [appTextDrag]="cipher.identity.company">{{ "company" | i18n }}</bit-label>
<input
bitInput
id="company"
[value]="cipher.identity.company"
readonly
data-testid="company"
/>
<button
type="button"
bitIconButton="bwi-clone"
@ -55,8 +73,15 @@
<read-only-cipher-card>
<bit-form-field *ngIf="cipher.identity.ssn">
<bit-label>{{ "ssn" | i18n }}</bit-label>
<input bitInput type="password" [value]="cipher.identity.ssn" readonly data-testid="ssn" />
<bit-label [appTextDrag]="cipher.identity.ssn">{{ "ssn" | i18n }}</bit-label>
<input
bitInput
id="ssn"
type="password"
[value]="cipher.identity.ssn"
readonly
data-testid="ssn"
/>
<button
type="button"
bitIconButton
@ -76,8 +101,11 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.identity.passportNumber">
<bit-label>{{ "passportNumber" | i18n }}</bit-label>
<bit-label [appTextDrag]="cipher.identity.passportNumber">{{
"passportNumber" | i18n
}}</bit-label>
<input
id="passportNumber"
bitInput
type="password"
[value]="cipher.identity.passportNumber"
@ -103,8 +131,16 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.identity.licenseNumber">
<bit-label>{{ "licenseNumber" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.licenseNumber" readonly data-testid="license" />
<bit-label [appTextDrag]="cipher.identity.licenseNumber">{{
"licenseNumber" | i18n
}}</bit-label>
<input
bitInput
id="licenseNumber"
[value]="cipher.identity.licenseNumber"
readonly
data-testid="license"
/>
<button
type="button"
bitIconButton="bwi-clone"
@ -126,8 +162,8 @@
<read-only-cipher-card>
<bit-form-field *ngIf="cipher.identity.email">
<bit-label>{{ "email" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.email" readonly data-testid="email" />
<bit-label [appTextDrag]="cipher.identity.email">{{ "email" | i18n }}</bit-label>
<input bitInput id="email" [value]="cipher.identity.email" readonly data-testid="email" />
<button
type="button"
bitIconButton="bwi-clone"
@ -140,8 +176,8 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="cipher.identity.phone">
<bit-label>{{ "phone" | i18n }}</bit-label>
<input bitInput [value]="cipher.identity.phone" readonly data-testid="phone" />
<bit-label [appTextDrag]="cipher.identity.phone">{{ "phone" | i18n }}</bit-label>
<input bitInput id="phone" [value]="cipher.identity.phone" readonly data-testid="phone" />
<button
type="button"
bitIconButton="bwi-clone"
@ -154,9 +190,10 @@
></button>
</bit-form-field>
<bit-form-field *ngIf="addressFields">
<bit-label>{{ "address" | i18n }}</bit-label>
<bit-label [appTextDrag]="addressFields">{{ "address" | i18n }}</bit-label>
<textarea
bitInput
id="address"
class="tw-resize-none"
[value]="addressFields"
[rows]="addressRows"