mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 02:03:39 +00:00
[PM-26352] drawers for activity cards (#16895)
* new drawer functions for crit apps * logic for triggering the drawer functions in components * cleanup unused logic and rename "navigation" to "action" - ... since the click is now triggering the drawer instead of navigating to another tab/page * null check for reportData in drawer methods * use criticalReportResults$ to avoid duplicating logic * use criticalReportResults$ to avoid dupe logic * remove unused code
This commit is contained in:
@@ -175,6 +175,65 @@ export class RiskInsightsDataService {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setDrawerForCriticalAtRiskMembers = async (invokerId: string = ""): Promise<void> => {
|
||||||
|
const { open, activeDrawerType, invokerId: currentInvokerId } = this.drawerDetailsSubject.value;
|
||||||
|
const shouldClose =
|
||||||
|
open && activeDrawerType === DrawerType.OrgAtRiskMembers && currentInvokerId === invokerId;
|
||||||
|
|
||||||
|
if (shouldClose) {
|
||||||
|
this.closeDrawer();
|
||||||
|
} else {
|
||||||
|
const reportResults = await firstValueFrom(this.criticalReportResults$);
|
||||||
|
if (!reportResults?.reportData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate at-risk member list from critical applications
|
||||||
|
const atRiskMemberDetails = getAtRiskMemberList(reportResults.reportData);
|
||||||
|
|
||||||
|
this.drawerDetailsSubject.next({
|
||||||
|
open: true,
|
||||||
|
invokerId,
|
||||||
|
activeDrawerType: DrawerType.OrgAtRiskMembers,
|
||||||
|
atRiskMemberDetails,
|
||||||
|
appAtRiskMembers: null,
|
||||||
|
atRiskAppDetails: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setDrawerForCriticalAtRiskApps = async (invokerId: string = ""): Promise<void> => {
|
||||||
|
const { open, activeDrawerType, invokerId: currentInvokerId } = this.drawerDetailsSubject.value;
|
||||||
|
const shouldClose =
|
||||||
|
open && activeDrawerType === DrawerType.OrgAtRiskApps && currentInvokerId === invokerId;
|
||||||
|
|
||||||
|
if (shouldClose) {
|
||||||
|
this.closeDrawer();
|
||||||
|
} else {
|
||||||
|
const reportResults = await firstValueFrom(this.criticalReportResults$);
|
||||||
|
if (!reportResults?.reportData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter critical applications for those with at-risk passwords
|
||||||
|
const criticalAtRiskApps = reportResults.reportData
|
||||||
|
.filter((app) => app.atRiskPasswordCount > 0)
|
||||||
|
.map((app) => ({
|
||||||
|
applicationName: app.applicationName,
|
||||||
|
atRiskPasswordCount: app.atRiskPasswordCount,
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.drawerDetailsSubject.next({
|
||||||
|
open: true,
|
||||||
|
invokerId,
|
||||||
|
activeDrawerType: DrawerType.OrgAtRiskApps,
|
||||||
|
atRiskMemberDetails: [],
|
||||||
|
appAtRiskMembers: null,
|
||||||
|
atRiskAppDetails: criticalAtRiskApps,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ------------------------------ Critical application methods --------------
|
// ------------------------------ Critical application methods --------------
|
||||||
saveCriticalApplications(selectedUrls: string[]) {
|
saveCriticalApplications(selectedUrls: string[]) {
|
||||||
return this.orchestrator.saveCriticalApplications$(selectedUrls);
|
return this.orchestrator.saveCriticalApplications$(selectedUrls);
|
||||||
|
|||||||
@@ -23,11 +23,11 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (showNavigationLink && !buttonText) {
|
@if (showActionLink && !buttonText) {
|
||||||
<div class="tw-flex tw-items-baseline tw-mt-4 tw-gap-2">
|
<div class="tw-flex tw-items-baseline tw-mt-4 tw-gap-2">
|
||||||
<p bitTypography="body1">
|
<p bitTypography="body1">
|
||||||
<a bitLink (click)="navigateToLink(navigationLink)" rel="noreferrer">
|
<a bitLink href="#" (click)="onActionClick(); $event.preventDefault()" rel="noreferrer">
|
||||||
{{ navigationText }}
|
{{ actionText }}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -37,25 +37,14 @@ export class ActivityCardComponent {
|
|||||||
@Input() metricDescription: string = "";
|
@Input() metricDescription: string = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The link to navigate to for more information
|
* The text to display for the action link
|
||||||
*/
|
*/
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
@Input() actionText: string = "";
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
|
||||||
@Input() navigationLink: string = "";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text to display for the navigation link
|
* Show action link
|
||||||
*/
|
*/
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
@Input() showActionLink: boolean = false;
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
|
||||||
@Input() navigationText: string = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show Navigation link
|
|
||||||
*/
|
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
|
||||||
@Input() showNavigationLink: boolean = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon class to display next to metrics (e.g., "bwi-exclamation-triangle").
|
* Icon class to display next to metrics (e.g., "bwi-exclamation-triangle").
|
||||||
@@ -86,13 +75,18 @@ export class ActivityCardComponent {
|
|||||||
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
|
// eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref
|
||||||
@Output() buttonClick = new EventEmitter<void>();
|
@Output() buttonClick = new EventEmitter<void>();
|
||||||
|
|
||||||
constructor(private router: Router) {}
|
/**
|
||||||
|
* Event emitted when action link is clicked
|
||||||
|
*/
|
||||||
|
@Output() actionClick = new EventEmitter<void>();
|
||||||
|
|
||||||
navigateToLink = async (navigationLink: string) => {
|
constructor(private router: Router) {}
|
||||||
await this.router.navigateByUrl(navigationLink);
|
|
||||||
};
|
|
||||||
|
|
||||||
onButtonClick = () => {
|
onButtonClick = () => {
|
||||||
this.buttonClick.emit();
|
this.buttonClick.emit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onActionClick = () => {
|
||||||
|
this.actionClick.emit();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
[title]="'atRiskMembers' | i18n"
|
[title]="'atRiskMembers' | i18n"
|
||||||
[cardMetrics]="'membersAtRiskCount' | i18n: totalCriticalAppsAtRiskMemberCount"
|
[cardMetrics]="'membersAtRiskCount' | i18n: totalCriticalAppsAtRiskMemberCount"
|
||||||
[metricDescription]="'membersWithAccessToAtRiskItemsForCriticalApps' | i18n"
|
[metricDescription]="'membersWithAccessToAtRiskItemsForCriticalApps' | i18n"
|
||||||
navigationText="{{ 'viewAtRiskMembers' | i18n }}"
|
actionText="{{ 'viewAtRiskMembers' | i18n }}"
|
||||||
navigationLink="{{ getLinkForRiskInsightsTab(RiskInsightsTabType.AllApps) }}"
|
[showActionLink]="totalCriticalAppsAtRiskMemberCount > 0"
|
||||||
[showNavigationLink]="totalCriticalAppsAtRiskMemberCount > 0"
|
(actionClick)="onViewAtRiskMembers()"
|
||||||
>
|
>
|
||||||
</dirt-activity-card>
|
</dirt-activity-card>
|
||||||
</li>
|
</li>
|
||||||
@@ -35,9 +35,9 @@
|
|||||||
: ('criticalApplicationsAreAtRisk'
|
: ('criticalApplicationsAreAtRisk'
|
||||||
| i18n: totalCriticalAppsAtRiskCount : totalCriticalAppsCount)
|
| i18n: totalCriticalAppsAtRiskCount : totalCriticalAppsCount)
|
||||||
"
|
"
|
||||||
navigationText="{{ 'viewAtRiskApplications' | i18n }}"
|
actionText="{{ 'viewAtRiskApplications' | i18n }}"
|
||||||
navigationLink="{{ getLinkForRiskInsightsTab(RiskInsightsTabType.CriticalApps) }}"
|
[showActionLink]="totalCriticalAppsAtRiskCount > 0"
|
||||||
[showNavigationLink]="totalCriticalAppsAtRiskCount > 0"
|
(actionClick)="onViewAtRiskApplications()"
|
||||||
>
|
>
|
||||||
</dirt-activity-card>
|
</dirt-activity-card>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { getById } from "@bitwarden/common/platform/misc";
|
|||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||||
|
|
||||||
import { RiskInsightsTabType } from "../models/risk-insights.models";
|
|
||||||
import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component";
|
import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component";
|
||||||
|
|
||||||
import { ActivityCardComponent } from "./activity-card.component";
|
import { ActivityCardComponent } from "./activity-card.component";
|
||||||
@@ -82,15 +81,6 @@ export class AllActivityComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get RiskInsightsTabType() {
|
|
||||||
return RiskInsightsTabType;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkForRiskInsightsTab(tabIndex: RiskInsightsTabType): string {
|
|
||||||
const organizationId = this.activatedRoute.snapshot.paramMap.get("organizationId");
|
|
||||||
return `/organizations/${organizationId}/access-intelligence/risk-insights?tabIndex=${tabIndex}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the review new applications button click.
|
* Handles the review new applications button click.
|
||||||
* Opens a dialog showing the list of new applications that can be marked as critical.
|
* Opens a dialog showing the list of new applications that can be marked as critical.
|
||||||
@@ -102,4 +92,20 @@ export class AllActivityComponent implements OnInit {
|
|||||||
|
|
||||||
await firstValueFrom(dialogRef.closed);
|
await firstValueFrom(dialogRef.closed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the "View at-risk members" link click.
|
||||||
|
* Opens the at-risk members drawer for critical applications only.
|
||||||
|
*/
|
||||||
|
onViewAtRiskMembers = async () => {
|
||||||
|
await this.dataService.setDrawerForCriticalAtRiskMembers("activityTabAtRiskMembers");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the "View at-risk applications" link click.
|
||||||
|
* Opens the at-risk applications drawer for critical applications only.
|
||||||
|
*/
|
||||||
|
onViewAtRiskApplications = async () => {
|
||||||
|
await this.dataService.setDrawerForCriticalAtRiskApps("activityTabAtRiskApplications");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user