mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
add CSV download buttons to at risk members and applications drawers (#17172)
* add CSV download buttons to at risk members and applications drawers --------- Co-authored-by: Alex <55413326+AlexRubik@users.noreply.github.com>
This commit is contained in:
@@ -118,6 +118,15 @@
|
|||||||
) | i18n
|
) | i18n
|
||||||
}}</span>
|
}}</span>
|
||||||
<ng-container *ngIf="drawerDetails.atRiskMemberDetails.length > 0">
|
<ng-container *ngIf="drawerDetails.atRiskMemberDetails.length > 0">
|
||||||
|
<button
|
||||||
|
bitLink
|
||||||
|
type="button"
|
||||||
|
class="tw-my-4 tw-font-bold tw-block"
|
||||||
|
(click)="downloadAtRiskMembers()"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-download tw-mr-1"></i>
|
||||||
|
{{ "downloadCSV" | i18n }}
|
||||||
|
</button>
|
||||||
<div class="tw-flex tw-justify-between tw-mt-2 tw-text-muted">
|
<div class="tw-flex tw-justify-between tw-mt-2 tw-text-muted">
|
||||||
<div bitTypography="body2" class="tw-text-sm tw-font-bold">
|
<div bitTypography="body2" class="tw-text-sm tw-font-bold">
|
||||||
{{ "email" | i18n }}
|
{{ "email" | i18n }}
|
||||||
@@ -173,6 +182,15 @@
|
|||||||
) | i18n
|
) | i18n
|
||||||
}}</span>
|
}}</span>
|
||||||
<ng-container *ngIf="drawerDetails.atRiskAppDetails.length > 0">
|
<ng-container *ngIf="drawerDetails.atRiskAppDetails.length > 0">
|
||||||
|
<button
|
||||||
|
bitLink
|
||||||
|
type="button"
|
||||||
|
class="tw-my-4 tw-font-bold tw-block"
|
||||||
|
(click)="downloadAtRiskApplications()"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-download tw-mr-1"></i>
|
||||||
|
{{ "downloadCSV" | i18n }}
|
||||||
|
</button>
|
||||||
<div class="tw-flex tw-justify-between tw-mt-2 tw-text-muted">
|
<div class="tw-flex tw-justify-between tw-mt-2 tw-text-muted">
|
||||||
<div bitTypography="body2" class="tw-text-sm tw-font-bold">
|
<div bitTypography="body2" class="tw-text-sm tw-font-bold">
|
||||||
{{ "application" | i18n }}
|
{{ "application" | i18n }}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CommonModule } from "@angular/common";
|
|||||||
import { Component, DestroyRef, OnDestroy, OnInit, inject } from "@angular/core";
|
import { Component, DestroyRef, OnDestroy, OnInit, inject } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { combineLatest, EMPTY } from "rxjs";
|
import { combineLatest, EMPTY, firstValueFrom } from "rxjs";
|
||||||
import { map, tap } from "rxjs/operators";
|
import { map, tap } from "rxjs/operators";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
@@ -13,7 +13,9 @@ import {
|
|||||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import {
|
import {
|
||||||
AsyncActionsModule,
|
AsyncActionsModule,
|
||||||
@@ -23,6 +25,8 @@ import {
|
|||||||
DrawerHeaderComponent,
|
DrawerHeaderComponent,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
import { ExportHelper } from "@bitwarden/vault-export-core";
|
||||||
|
import { exportToCSV } from "@bitwarden/web-vault/app/dirt/reports/report-utils";
|
||||||
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module";
|
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module";
|
||||||
|
|
||||||
import { AllActivityComponent } from "./activity/all-activity.component";
|
import { AllActivityComponent } from "./activity/all-activity.component";
|
||||||
@@ -88,6 +92,8 @@ export class RiskInsightsComponent implements OnInit, OnDestroy {
|
|||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
protected dataService: RiskInsightsDataService,
|
protected dataService: RiskInsightsDataService,
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
|
private fileDownloadService: FileDownloadService,
|
||||||
|
private logService: LogService,
|
||||||
) {
|
) {
|
||||||
this.route.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ tabIndex }) => {
|
this.route.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ tabIndex }) => {
|
||||||
this.tabIndex = !isNaN(Number(tabIndex)) ? Number(tabIndex) : RiskInsightsTabType.AllApps;
|
this.tabIndex = !isNaN(Number(tabIndex)) ? Number(tabIndex) : RiskInsightsTabType.AllApps;
|
||||||
@@ -207,4 +213,66 @@ export class RiskInsightsComponent implements OnInit, OnDestroy {
|
|||||||
"import",
|
"import",
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* downloads at risk members as CSV
|
||||||
|
*/
|
||||||
|
downloadAtRiskMembers = async () => {
|
||||||
|
try {
|
||||||
|
const drawerDetails = await firstValueFrom(this.dataService.drawerDetails$);
|
||||||
|
|
||||||
|
// Validate drawer is open and showing the correct drawer type
|
||||||
|
if (
|
||||||
|
!drawerDetails.open ||
|
||||||
|
drawerDetails.activeDrawerType !== DrawerType.OrgAtRiskMembers ||
|
||||||
|
!drawerDetails.atRiskMemberDetails ||
|
||||||
|
drawerDetails.atRiskMemberDetails.length === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileDownloadService.download({
|
||||||
|
fileName: ExportHelper.getFileName("at-risk-members"),
|
||||||
|
blobData: exportToCSV(drawerDetails.atRiskMemberDetails, {
|
||||||
|
email: this.i18nService.t("email"),
|
||||||
|
atRiskPasswordCount: this.i18nService.t("atRiskPasswords"),
|
||||||
|
}),
|
||||||
|
blobOptions: { type: "text/plain" },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Log error for debugging
|
||||||
|
this.logService.error("Failed to download at-risk members", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* downloads at risk applications as CSV
|
||||||
|
*/
|
||||||
|
downloadAtRiskApplications = async () => {
|
||||||
|
try {
|
||||||
|
const drawerDetails = await firstValueFrom(this.dataService.drawerDetails$);
|
||||||
|
|
||||||
|
// Validate drawer is open and showing the correct drawer type
|
||||||
|
if (
|
||||||
|
!drawerDetails.open ||
|
||||||
|
drawerDetails.activeDrawerType !== DrawerType.OrgAtRiskApps ||
|
||||||
|
!drawerDetails.atRiskAppDetails ||
|
||||||
|
drawerDetails.atRiskAppDetails.length === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileDownloadService.download({
|
||||||
|
fileName: ExportHelper.getFileName("at-risk-applications"),
|
||||||
|
blobData: exportToCSV(drawerDetails.atRiskAppDetails, {
|
||||||
|
applicationName: this.i18nService.t("application"),
|
||||||
|
atRiskPasswordCount: this.i18nService.t("atRiskPasswords"),
|
||||||
|
}),
|
||||||
|
blobOptions: { type: "text/plain" },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Log error for debugging
|
||||||
|
this.logService.error("Failed to download at-risk applications", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user