[PM-9638] Browser V2 Item Details Defects (#10124)
* Item Details Refactored. Created OrgIcon directive, Added screen reader logic, removed excess styling.
This commit is contained in:
parent
6041c460b7
commit
0e0c44b90b
|
@ -3850,5 +3850,8 @@
|
||||||
"example": "3"
|
"example": "3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"itemLocation": {
|
||||||
|
"message": "Item Location"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,10 @@
|
||||||
<app-vault-icon slot="start" [cipher]="cipher"></app-vault-icon>
|
<app-vault-icon slot="start" [cipher]="cipher"></app-vault-icon>
|
||||||
<span data-testid="item-name">{{ cipher.name }}</span>
|
<span data-testid="item-name">{{ cipher.name }}</span>
|
||||||
<i
|
<i
|
||||||
class="bwi bwi-sm"
|
|
||||||
*ngIf="cipher.organizationId"
|
*ngIf="cipher.organizationId"
|
||||||
[ngClass]="cipher.orgIcon"
|
appOrgIcon
|
||||||
|
[tierType]="cipher.organization.productTierType"
|
||||||
|
[size]="'small'"
|
||||||
[appA11yTitle]="orgIconTooltip(cipher)"
|
[appA11yTitle]="orgIconTooltip(cipher)"
|
||||||
></i>
|
></i>
|
||||||
<span slot="secondary">{{ cipher.subTitle }}</span>
|
<span slot="secondary">{{ cipher.subTitle }}</span>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
SectionHeaderComponent,
|
SectionHeaderComponent,
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
import { OrgIconDirective } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
|
import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
|
||||||
import { PopupCipherView } from "../../../views/popup-cipher.view";
|
import { PopupCipherView } from "../../../views/popup-cipher.view";
|
||||||
|
@ -33,6 +34,7 @@ import { ItemMoreOptionsComponent } from "../item-more-options/item-more-options
|
||||||
RouterLink,
|
RouterLink,
|
||||||
ItemCopyActionsComponent,
|
ItemCopyActionsComponent,
|
||||||
ItemMoreOptionsComponent,
|
ItemMoreOptionsComponent,
|
||||||
|
OrgIconDirective,
|
||||||
],
|
],
|
||||||
selector: "app-vault-list-items-container",
|
selector: "app-vault-list-items-container",
|
||||||
templateUrl: "vault-list-items-container.component.html",
|
templateUrl: "vault-list-items-container.component.html",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||||
|
|
||||||
|
@ -21,21 +20,4 @@ export class PopupCipherView extends CipherView {
|
||||||
this.collections = collections;
|
this.collections = collections;
|
||||||
this.organization = organization;
|
this.organization = organization;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the bwi icon for the cipher according to the organization type.
|
|
||||||
*/
|
|
||||||
get orgIcon(): "bwi-family" | "bwi-business" | null {
|
|
||||||
switch (this.organization?.productTierType) {
|
|
||||||
case ProductTierType.Free:
|
|
||||||
case ProductTierType.Families:
|
|
||||||
return "bwi-family";
|
|
||||||
case ProductTierType.Teams:
|
|
||||||
case ProductTierType.Enterprise:
|
|
||||||
case ProductTierType.TeamsStarter:
|
|
||||||
return "bwi-business";
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,36 +3,68 @@
|
||||||
<h2 bitTypography="h6">{{ "itemDetails" | i18n }}</h2>
|
<h2 bitTypography="h6">{{ "itemDetails" | i18n }}</h2>
|
||||||
</bit-section-header>
|
</bit-section-header>
|
||||||
<bit-card>
|
<bit-card>
|
||||||
<div class="tw-pb-2 tw-mb-4 tw-border-0 tw-border-b tw-border-solid tw-border-secondary-300">
|
<div>
|
||||||
<label class="tw-block tw-w-full tw-mb-1 tw-text-xs tw-text-muted tw-select-none">
|
<label class="tw-block tw-w-full tw-mb-1 tw-text-xs tw-text-muted tw-select-none">
|
||||||
{{ "itemName" | i18n }}
|
{{ "itemName" | i18n }}
|
||||||
</label>
|
</label>
|
||||||
<input readonly bitInput type="text" [value]="cipher.name" aria-readonly="true" />
|
<input readonly bitInput type="text" [value]="cipher.name" aria-readonly="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="cipher.collectionIds || cipher.organizationId || cipher.folderId">
|
<ul
|
||||||
<p
|
[attr.aria-label]="'itemLocation' | i18n"
|
||||||
*ngIf="!cipher.organizationId"
|
*ngIf="cipher.collectionIds || cipher.organizationId || cipher.folderId"
|
||||||
[ngClass]="{ 'tw-mb-3': cipher.collectionIds }"
|
>
|
||||||
bitTypography="body2"
|
<li
|
||||||
>
|
|
||||||
<i class="bwi bwi-user bwi-lg bwi-fw"></i> {{ "ownerYou" | i18n }}
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
*ngIf="cipher.organizationId && organization"
|
*ngIf="cipher.organizationId && organization"
|
||||||
|
class="tw-flex tw-list-none"
|
||||||
[ngClass]="{ 'tw-mb-3': cipher.collectionIds }"
|
[ngClass]="{ 'tw-mb-3': cipher.collectionIds }"
|
||||||
bitTypography="body2"
|
bitTypography="body2"
|
||||||
|
[attr.aria-label]="('owner' | i18n) + organization.name"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-business bwi-lg bwi-fw"></i> {{ organization.name }}
|
<i
|
||||||
</p>
|
class="tw-pt-1"
|
||||||
<ul *ngIf="cipher.collectionIds && collections" [ngClass]="{ 'tw-mb-2': cipher.folderId }">
|
appOrgIcon
|
||||||
<p *ngFor="let collection of collections" class="tw-mb-1" bitTypography="body2">
|
[tierType]="organization.productTierType"
|
||||||
<i class="bwi bwi-collection bwi-lg bwi-fw"></i> {{ collection.name }}
|
[size]="'large'"
|
||||||
</p>
|
[title]="'owner' | i18n"
|
||||||
</ul>
|
></i>
|
||||||
<p *ngIf="cipher.folderId && folder" bitTypography="body2">
|
<span aria-hidden="true" class="tw-pl-1 tw-mb-1">
|
||||||
<i class="bwi bwi-folder bwi-lg bwi-fw"></i> {{ folder.name }}
|
{{ organization.name }}
|
||||||
</p>
|
</span>
|
||||||
</div>
|
</li>
|
||||||
|
<li
|
||||||
|
class="tw-list-none"
|
||||||
|
*ngIf="cipher.collectionIds && collections"
|
||||||
|
[attr.aria-label]="'collection' | i18n"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
*ngFor="let collection of collections; let last = last"
|
||||||
|
class="tw-flex tw-list-none"
|
||||||
|
bitTypography="body2"
|
||||||
|
[ngClass]="{ 'tw-mb-3': last }"
|
||||||
|
[attr.aria-label]="collection.name"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="bwi bwi-collection bwi-lg tw-pt-1"
|
||||||
|
aria-hidden="true"
|
||||||
|
[title]="'collection' | i18n"
|
||||||
|
></i>
|
||||||
|
<span aria-hidden="true" class="tw-pl-1 tw-mb-1">
|
||||||
|
{{ collection.name }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
*ngIf="cipher.folderId && folder"
|
||||||
|
bitTypography="body2"
|
||||||
|
class="tw-flex tw-list-none"
|
||||||
|
[attr.aria-label]="('folder' | i18n) + folder.name"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-folder bwi-lg tw-pt-1" aria-hidden="true" [title]="'folder' | i18n"></i>
|
||||||
|
<span aria-hidden="true" class="tw-pl-1 tw-mb-1">{{ folder.name }} </span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</bit-card>
|
</bit-card>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
|
|
@ -13,6 +13,8 @@ import {
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { OrgIconDirective } from "../../components/org-icon.directive";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-item-details-v2",
|
selector: "app-item-details-v2",
|
||||||
templateUrl: "item-details-v2.component.html",
|
templateUrl: "item-details-v2.component.html",
|
||||||
|
@ -24,6 +26,7 @@ import {
|
||||||
SectionComponent,
|
SectionComponent,
|
||||||
SectionHeaderComponent,
|
SectionHeaderComponent,
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
|
OrgIconDirective,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ItemDetailsV2Component {
|
export class ItemDetailsV2Component {
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Directive, ElementRef, HostBinding, Input, Renderer2 } from "@angular/core";
|
||||||
|
|
||||||
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
|
|
||||||
|
export type OrgIconSize = "default" | "small" | "large";
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
standalone: true,
|
||||||
|
selector: "[appOrgIcon]",
|
||||||
|
})
|
||||||
|
export class OrgIconDirective {
|
||||||
|
@Input({ required: true }) tierType: ProductTierType;
|
||||||
|
@Input() size?: OrgIconSize = "default";
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private el: ElementRef,
|
||||||
|
private renderer: Renderer2,
|
||||||
|
) {
|
||||||
|
this.renderer.setAttribute(this.el.nativeElement, "aria-hidden", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
get iconSize(): "bwi-sm" | "bwi-lg" | "" {
|
||||||
|
switch (this.size) {
|
||||||
|
case "small":
|
||||||
|
return "bwi-sm";
|
||||||
|
case "large":
|
||||||
|
return "bwi-lg";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get orgIcon(): string {
|
||||||
|
switch (this.tierType) {
|
||||||
|
case ProductTierType.Free:
|
||||||
|
case ProductTierType.Families:
|
||||||
|
return "bwi-family";
|
||||||
|
case ProductTierType.Teams:
|
||||||
|
case ProductTierType.Enterprise:
|
||||||
|
case ProductTierType.TeamsStarter:
|
||||||
|
return "bwi-business";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostBinding("class") get classList() {
|
||||||
|
return ["bwi", this.iconSize, this.orgIcon];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
export { PasswordRepromptService } from "./services/password-reprompt.service";
|
export { PasswordRepromptService } from "./services/password-reprompt.service";
|
||||||
export { CopyCipherFieldService, CopyAction } from "./services/copy-cipher-field.service";
|
export { CopyCipherFieldService, CopyAction } from "./services/copy-cipher-field.service";
|
||||||
export { CopyCipherFieldDirective } from "./components/copy-cipher-field.directive";
|
export { CopyCipherFieldDirective } from "./components/copy-cipher-field.directive";
|
||||||
|
export { OrgIconDirective } from "./components/org-icon.directive";
|
||||||
|
|
||||||
export * from "./cipher-view";
|
export * from "./cipher-view";
|
||||||
export * from "./cipher-form";
|
export * from "./cipher-form";
|
||||||
|
|
Loading…
Reference in New Issue