1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-05 03:03:26 +00:00

delete custom component, put custom formatting in simple dialog, add trad modal behavior

This commit is contained in:
Alex
2025-08-30 19:10:36 -04:00
parent f38ccb32f8
commit 615a0eb555
4 changed files with 126 additions and 131 deletions

View File

@@ -1,3 +1,68 @@
<!-- Risk Insights First Report Prompt -->
@if (showFirstReportPromptDialog) {
<!-- Modal backdrop -->
<div
class="tw-fixed tw-bg-black tw-bg-opacity-30 tw-inset-0 tw-z-50 tw-flex tw-items-center tw-justify-center tw-p-4"
(click)="closePrompt()"
cdkTrapFocus
cdkTrapFocusAutoCapture
>
<!-- Modal container - prevent click propagation -->
<div
(click)="$event.stopPropagation()"
class="tw-flex tw-justify-center tw-max-h-[90vh] tw-overflow-y-auto"
>
<bit-simple-dialog class="!tw-w-auto !tw-max-w-4xl" hideIcon="true">
<span bitDialogTitle>Welcome to Risk insights</span>
<span bitDialogContent>
<div class="tw-text-left">
<p class="tw-text-muted tw-mb-6 tw-text-center">
To get started, follow these steps to find potential security risks.
</p>
<div class="tw-space-y-4">
<div
class="tw-bg-background-alt tw-p-4 tw-rounded-lg tw-border tw-border-solid tw-border-secondary-100"
>
<h3 class="tw-font-semibold tw-text-main tw-mb-2">
1. Enforce organization data ownership
<span class="tw-text-muted tw-font-normal">(recommended)</span>
</h3>
<p class="tw-text-muted tw-leading-relaxed">
Turn on the
<a
href="https://bitwarden.com/help/policies/#enforce-organization-data-ownership"
target="_blank"
rel="noopener noreferrer"
class="tw-text-primary-600 tw-underline hover:tw-text-primary-700 tw-cursor-pointer"
>enforce organization data ownership policy</a
>
to get complete visibility of all organization vault data. This setting can be
enabled at any time.
</p>
</div>
<div
class="tw-bg-background-alt tw-p-4 tw-rounded-lg tw-border tw-border-solid tw-border-secondary-100"
>
<h3 class="tw-font-semibold tw-text-main tw-mb-2">2. Run the report</h3>
<p class="tw-text-muted tw-leading-relaxed">
Run the report to see a detailed view of potential at-risk passwords across your
most critical applications.
</p>
</div>
</div>
</div>
</span>
<ng-container bitDialogFooter>
<button bitButton buttonType="primary" type="button" (click)="runReport()">
Run Report
</button>
</ng-container>
</bit-simple-dialog>
</div>
</div>
}
@if (dataService.isLoading$ | async) {
<tools-risk-insights-loading></tools-risk-insights-loading>
} @else {

View File

@@ -1,3 +1,4 @@
import { CdkTrapFocus } from "@angular/cdk/a11y";
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormControl } from "@angular/forms";
@@ -26,6 +27,8 @@ import {
TableDataSource,
ToastService,
DialogService,
ButtonModule,
DialogModule,
} from "@bitwarden/components";
import { CardComponent } from "@bitwarden/dirt-card";
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module";
@@ -33,12 +36,14 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
import { AppTableRowScrollableComponent } from "./app-table-row-scrollable.component";
import { NoDataModalComponent } from "./no-data-modal.component";
import { ApplicationsLoadingComponent } from "./risk-insights-loading.component";
@Component({
selector: "tools-all-applications",
templateUrl: "./all-applications.component.html",
host: {
"(keydown.escape)": "handleEscape($event)", // escape dialog with keyboard
},
imports: [
ApplicationsLoadingComponent,
HeaderModule,
@@ -49,6 +54,9 @@ import { ApplicationsLoadingComponent } from "./risk-insights-loading.component"
SharedModule,
AppTableRowScrollableComponent,
IconButtonModule,
ButtonModule,
DialogModule,
CdkTrapFocus,
],
})
export class AllApplicationsComponent implements OnInit {
@@ -64,8 +72,9 @@ export class AllApplicationsComponent implements OnInit {
totalAtRiskApplicationCount: 0,
};
private hasShownNoDataModal = false; // Flag to prevent multiple modals
private hasShownFirstReportPrompt = false; // Flag to prevent multiple prompts
private organizationId: string | null = null;
protected showFirstReportPromptDialog = false; // Controls visibility of the simple dialog
destroyRef = inject(DestroyRef);
constructor(
@@ -95,36 +104,70 @@ export class AllApplicationsComponent implements OnInit {
.subscribe((report) => {
// Check if we already have data in the dataSource (from previous session)
if (this.dataSource.data.length > 0) {
this.hasShownNoDataModal = false; // Reset flag since we have data
this.hasShownFirstReportPrompt = false; // Reset flag since we have data
return;
}
if (report && report.data && report.data.length > 0) {
this.dataSource.data = report.data;
// this.applicationSummary = this.reportService.generateApplicationsSummary(report.data);
this.hasShownNoDataModal = false; // Reset flag when data is available
} else if (!this.hasShownNoDataModal) {
// Show modal only once when no report data is available
void this.showNoDataModal();
this.hasShownFirstReportPrompt = false; // Reset flag when data is available
if (this.showFirstReportPromptDialog) {
this.closePrompt(); // Use closePrompt method to properly restore scroll
}
} else if (!this.hasShownFirstReportPrompt) {
// Show prompt only once when no report data is available
void this.showFirstReportPrompt();
}
});
}
}
/**
* Shows a modal prompting users to run a report when no data is available
* Shows a prompt encouraging users to run their first report
*/
private async showNoDataModal(): Promise<void> {
// Set flag to prevent multiple modals
this.hasShownNoDataModal = true;
private async showFirstReportPrompt(): Promise<void> {
// Set flag to prevent multiple prompts
this.hasShownFirstReportPrompt = true;
this.dialogService.open(NoDataModalComponent, {
data: {
organizationId: this.organizationId,
riskInsightsDataService: this.dataService,
},
disableClose: false,
});
// Show the simple dialog and prevent body scroll
this.showFirstReportPromptDialog = true;
document.body.classList.add("tw-overflow-hidden");
}
/**
* Runs the report and closes the prompt
*/
async runReport(): Promise<void> {
// Close the prompt first
this.closePrompt();
// Add a small delay to ensure prompt closes before triggering the report
await new Promise((resolve) => setTimeout(resolve, 100));
// Trigger the report generation
if (this.dataService) {
this.dataService.triggerReport();
}
}
/**
* Closes the prompt (called when clicking backdrop or pressing Escape)
*/
closePrompt(): void {
this.showFirstReportPromptDialog = false;
// Restore body scroll
document.body.classList.remove("tw-overflow-hidden");
}
/**
* Handles Escape key press to close prompt
*/
handleEscape(event: KeyboardEvent): void {
if (this.showFirstReportPromptDialog) {
this.closePrompt();
event.stopPropagation();
}
}
goToCreateNewLoginItem = async () => {

View File

@@ -1,83 +0,0 @@
<section
class="tw-flex tw-w-full tw-flex-col tw-self-center tw-overflow-hidden tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-text-main tw-rounded-xl tw-p-4 tw-max-h-[90vh] md:tw-max-w-3xl"
>
<!-- Header -->
<header class="tw-flex tw-justify-center tw-items-center tw-gap-4 tw-p-4">
<h2 class="tw-text-main tw-mb-0 tw-text-xl tw-font-semibold tw-flex tw-items-center tw-gap-3">
Welcome to Risk insights
</h2>
</header>
<!-- Content -->
<div class="tw-relative tw-flex-1 tw-flex tw-flex-col tw-overflow-hidden tw-bg-background">
<div class="tw-p-4 tw-overflow-y-auto">
<!-- Introduction -->
<p class="tw-text-muted tw-mb-6 tw-text-center">
To get started, follow these steps to find potential security risks.
</p>
<!-- Steps -->
<div class="tw-space-y-4">
<!-- Step 1 -->
<div
class="tw-bg-background-alt tw-p-4 tw-rounded-lg tw-border tw-border-solid tw-border-secondary-100"
>
<div class="tw-flex tw-items-start tw-gap-3">
<div
class="tw-flex-shrink-0 tw-size-8 tw-bg-primary-600 tw-text-contrast tw-rounded-full tw-flex tw-items-center tw-justify-center tw-font-semibold tw-text-sm"
>
1
</div>
<div class="tw-flex-1">
<h3 class="tw-font-semibold tw-text-main tw-mb-2">
Enforce organization data ownership
<span class="tw-text-muted tw-font-normal">(recommended)</span>
</h3>
<p class="tw-text-muted tw-leading-relaxed">
Turn on the
<a
href="https://bitwarden.com/help/policies/#enforce-organization-data-ownership"
target="_blank"
rel="noopener noreferrer"
class="tw-text-primary-600 tw-underline hover:tw-text-primary-700 tw-cursor-pointer"
>enforce organization data ownership policy</a
>
to get complete visibility of all organization vault data. This setting can be
enabled at any time.
</p>
</div>
</div>
</div>
<!-- Step 2 -->
<div
class="tw-bg-background-alt tw-p-4 tw-rounded-lg tw-border tw-border-solid tw-border-secondary-100"
>
<div class="tw-flex tw-items-start tw-gap-3">
<div
class="tw-flex-shrink-0 tw-size-8 tw-bg-primary-600 tw-text-contrast tw-rounded-full tw-flex tw-items-center tw-justify-center tw-font-semibold tw-text-sm"
>
2
</div>
<div class="tw-flex-1">
<h3 class="tw-font-semibold tw-text-main tw-mb-2">Run the report</h3>
<p class="tw-text-muted tw-leading-relaxed">
Run the report to see a detailed view of potential at-risk passwords across your
most critical applications.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer
class="tw-flex tw-flex-row tw-items-center tw-justify-center tw-gap-2 tw-bg-background tw-p-4"
>
<button bitButton buttonType="primary" type="button" (click)="runReport()" cdkFocusInitial>
Run Report
</button>
</footer>
</section>

View File

@@ -1,30 +0,0 @@
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core";
import { ButtonModule } from "@bitwarden/components";
@Component({
selector: "tools-no-data-modal",
templateUrl: "./no-data-modal.component.html",
standalone: true,
imports: [ButtonModule],
})
export class NoDataModalComponent {
constructor(
public dialogRef: DialogRef<boolean>,
@Inject(DIALOG_DATA) public data: any,
) {}
async runReport(): Promise<void> {
// Close the modal first
this.dialogRef.close(true);
// Add a small delay to ensure modal closes before triggering the report
await new Promise((resolve) => setTimeout(resolve, 100));
// Trigger the report generation
if (this.data.riskInsightsDataService) {
this.data.riskInsightsDataService.triggerReport();
}
}
}