1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 14:53:33 +00:00

[PM-14038] - priority applications UI (#11723)

* priority applications UI

* add security icon
This commit is contained in:
Jordan Aasen
2024-10-30 11:25:06 -07:00
committed by GitHub
parent ab3d760dfd
commit 18f7d64a6d
6 changed files with 145 additions and 18 deletions

View File

@@ -11,5 +11,5 @@ import { ButtonModule, NoItemsModule, Icons } from "@bitwarden/components";
imports: [ButtonModule, CommonModule, JslibModule, NoItemsModule],
})
export class NoPriorityAppsComponent {
noItemsIcon = Icons.NoResults;
noItemsIcon = Icons.Security;
}

View File

@@ -1,15 +1,38 @@
<bit-container>
<p>{{ "passwordsReportDesc" | i18n }}</p>
<div *ngIf="loading">
<i
class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
<p>{{ "passwordsReportDesc" | i18n }}</p>
<div *ngIf="loading">
<i
class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</div>
<div class="tw-mt-4" *ngIf="!dataSource.data.length">
<tools-no-priority-apps></tools-no-priority-apps>
</div>
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
<div class="tw-flex tw-gap-6">
<tools-card
class="tw-flex-1"
[title]="'atRiskMembers' | i18n"
[value]="totalMembersMap.size - 3"
[maxValue]="totalMembersMap.size"
>
</tools-card>
<tools-card
class="tw-flex-1"
[title]="'atRiskApplications' | i18n"
[value]="totalMembersMap.size - 1"
[maxValue]="totalMembersMap.size"
>
</tools-card>
</div>
<div *ngIf="!dataSource.data.length">
<tools-no-priority-apps></tools-no-priority-apps>
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
<i class="bwi bwi-star-f tw-mr-2"></i>
{{ "markAppAsCritical" | i18n }}
</button>
</div>
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
<div class="tw-flex tw-gap-6">
@@ -30,7 +53,15 @@
</div>
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
<button
class="tw-rounded-lg"
type="button"
buttonType="secondary"
[disabled]="!selectedIds.size"
bitButton
[bitAction]="markAppsAsCritical"
appA11yTitle="{{ 'markAppAsCritical' | i18n }}"
>
<i class="bwi bwi-star-f tw-mr-2"></i>
{{ "markAppAsCritical" | i18n }}
</button>
@@ -47,9 +78,14 @@
</tr>
</ng-container>
<ng-template body let-rows$>
<tr bitRow *ngFor="let r of rows$ | async">
<tr bitRow *ngFor="let r of rows$ | async; trackBy: trackByFunction">
<td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon>
<input
bitCheckbox
type="checkbox"
[checked]="selectedIds.has(r.id)"
(change)="onCheckboxChange(r.id, $event)"
/>
</td>
<td bitCell>
<ng-container>
@@ -84,4 +120,4 @@
</ng-template>
</bit-table>
</div>
</bit-container>
</div>

View File

@@ -11,7 +11,13 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { BadgeVariant, SearchModule, TableDataSource, TableModule } from "@bitwarden/components";
import {
BadgeVariant,
SearchModule,
TableDataSource,
TableModule,
ToastService,
} from "@bitwarden/components";
import { CardComponent } from "@bitwarden/tools-card";
import { HeaderModule } from "../../layouts/header/header.module";
@@ -53,6 +59,8 @@ export class PasswordHealthMembersComponent implements OnInit {
loading = true;
selectedIds: Set<number> = new Set<number>();
protected searchControl = new FormControl("", { nonNullable: true });
private destroyRef = inject(DestroyRef);
@@ -63,6 +71,7 @@ export class PasswordHealthMembersComponent implements OnInit {
protected auditService: AuditService,
protected i18nService: I18nService,
protected activatedRoute: ActivatedRoute,
protected toastService: ToastService,
) {
this.searchControl.valueChanges
.pipe(debounceTime(200), takeUntilDestroyed())
@@ -91,7 +100,7 @@ export class PasswordHealthMembersComponent implements OnInit {
await passwordHealthService.generateReport();
this.dataSource.data = passwordHealthService.reportCiphers;
this.dataSource.data = []; //passwordHealthService.reportCiphers;
this.exposedPasswordMap = passwordHealthService.exposedPasswordMap;
this.passwordStrengthMap = passwordHealthService.passwordStrengthMap;
@@ -99,4 +108,32 @@ export class PasswordHealthMembersComponent implements OnInit {
this.totalMembersMap = passwordHealthService.totalMembersMap;
this.loading = false;
}
markAppsAsCritical = async () => {
// TODO: Send to API once implemented
return new Promise((resolve) => {
setTimeout(() => {
this.selectedIds.clear();
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("appsMarkedAsCritical"),
});
resolve(true);
}, 1000);
});
};
trackByFunction(_: number, item: CipherView) {
return item.id;
}
onCheckboxChange(id: number, event: Event) {
const isChecked = (event.target as HTMLInputElement).checked;
if (isChecked) {
this.selectedIds.add(id);
} else {
this.selectedIds.delete(id);
}
}
}

View File

@@ -65,6 +65,9 @@
"markAppAsCritical": {
"message": "Mark app as critical"
},
"appsMarkedAsCritical": {
"message": "Apps marked as critical"
},
"application": {
"message": "Application"
},