-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[PM-27619] assign tasks component #17125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 31 commits
e09eaa6
2c09085
1846293
3fc8928
6d2d8ea
245f956
7a29406
b1da2cb
907a784
8340dc2
cf15d25
bf1c415
6912be9
5d37ede
eb74aa2
b5fdcda
a928399
a1ee9f1
c449442
286d50a
f3d87e7
580981e
ed283f1
08df1ea
8d99996
22b18ae
ba4c3e2
3050da1
ec4855c
41d02bb
b9c9737
831cf53
f7534a7
7aa3cf4
185e639
1dd92f8
32dd082
bdda6e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,6 +56,7 @@ import { | |
| OrganizationReportSummary, | ||
| ReportStatus, | ||
| ReportState, | ||
| ApplicationHealthReportDetail, | ||
| } from "../../models/report-models"; | ||
| import { MemberCipherDetailsApiService } from "../api/member-cipher-details-api.service"; | ||
| import { RiskInsightsApiService } from "../api/risk-insights-api.service"; | ||
|
|
@@ -98,14 +99,17 @@ export class RiskInsightsOrchestratorService { | |
| enrichedReportData$ = this._enrichedReportDataSubject.asObservable(); | ||
|
|
||
| // New applications that haven't been reviewed (reviewedDate === null) | ||
| newApplications$: Observable<string[]> = this.rawReportData$.pipe( | ||
| newApplications$: Observable<ApplicationHealthReportDetail[]> = this.rawReportData$.pipe( | ||
| map((reportState) => { | ||
| if (!reportState.data?.applicationData) { | ||
| return []; | ||
| } | ||
| return reportState.data.applicationData | ||
| .filter((app) => app.reviewedDate === null) | ||
| .map((app) => app.applicationName); | ||
| const reportApplications = reportState.data?.applicationData || []; | ||
|
|
||
| const newApplications = | ||
| reportState?.data?.reportData.filter((reportApp) => | ||
| reportApplications.some( | ||
| (app) => app.applicationName == reportApp.applicationName && app.reviewedDate == null, | ||
| ), | ||
Banrion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) || []; | ||
| return newApplications; | ||
| }), | ||
| distinctUntilChanged( | ||
| (prev, curr) => prev.length === curr.length && prev.every((app, i) => app === curr[i]), | ||
|
|
@@ -332,9 +336,12 @@ export class RiskInsightsOrchestratorService { | |
| } | ||
|
|
||
| // Create a set for quick lookup of the new critical apps | ||
| const newCriticalAppNamesSet = new Set(criticalApplications); | ||
| const newCriticalAppNamesSet = criticalApplications.map((ca) => ({ | ||
| applicationName: ca, | ||
| isCritical: true, | ||
| })); | ||
| const existingApplicationData = report!.applicationData || []; | ||
| const updatedApplicationData = this._mergeApplicationData( | ||
| const updatedApplicationData = this._updateApplicationData( | ||
| existingApplicationData, | ||
| newCriticalAppNamesSet, | ||
| ); | ||
|
|
@@ -443,18 +450,18 @@ export class RiskInsightsOrchestratorService { | |
| } | ||
|
|
||
| /** | ||
| * Saves review status for new applications and optionally marks selected ones as critical. | ||
| * This method: | ||
| * 1. Sets reviewedDate to current date for all applications where reviewedDate === null | ||
| * 2. Sets isCritical = true for applications in the selectedCriticalApps array | ||
| * Saves review status for new applications and optionally marks | ||
| * selected ones as critical | ||
| * | ||
| * @param selectedCriticalApps Array of application names to mark as critical (can be empty) | ||
| * @param reviewedApplications Array of application names to mark as reviewed | ||
| * @returns Observable of updated ReportState | ||
| */ | ||
| saveApplicationReviewStatus$(selectedCriticalApps: string[]): Observable<ReportState> { | ||
| this.logService.info("[RiskInsightsOrchestratorService] Saving application review status", { | ||
| criticalAppsCount: selectedCriticalApps.length, | ||
| }); | ||
| saveApplicationReviewStatus$( | ||
| reviewedApplications: OrganizationReportApplication[], | ||
| ): Observable<ReportState> { | ||
| this.logService.info( | ||
| `[RiskInsightsOrchestratorService] Saving application review status for ${reviewedApplications.length} applications`, | ||
| ); | ||
|
|
||
| return this.rawReportData$.pipe( | ||
| take(1), | ||
|
|
@@ -464,16 +471,43 @@ export class RiskInsightsOrchestratorService { | |
| this._userId$.pipe(filter((userId) => !!userId)), | ||
| ), | ||
| map(([reportState, organizationDetails, userId]) => { | ||
| const report = reportState?.data; | ||
| if (!report) { | ||
| throwError(() => Error("Tried save reviewed applications without a report")); | ||
| } | ||
|
|
||
| const existingApplicationData = reportState?.data?.applicationData || []; | ||
| const updatedApplicationData = this._updateReviewStatusAndCriticalFlags( | ||
| const updatedApplicationData = this._updateApplicationData( | ||
| existingApplicationData, | ||
| selectedCriticalApps, | ||
| reviewedApplications, | ||
| ); | ||
|
|
||
| // Updated summary data after changing critical apps | ||
| const updatedSummaryData = this.reportService.getApplicationsSummary( | ||
| report!.reportData, | ||
| updatedApplicationData, | ||
| ); | ||
| // Used for creating metrics with updated application data | ||
| const manualEnrichedApplications = report!.reportData.map( | ||
| (application): ApplicationHealthReportDetailEnriched => ({ | ||
| ...application, | ||
| isMarkedAsCritical: this.reportService.isCriticalApplication( | ||
| application, | ||
| updatedApplicationData, | ||
| ), | ||
| }), | ||
| ); | ||
| // For now, merge the report with the critical marking flag to make the enriched type | ||
| // We don't care about the individual ciphers in this instance | ||
| // After the report and enriched report types are consolidated, this mapping can be removed | ||
| // and the class will expose getCriticalApplications | ||
| const metrics = this._getReportMetrics(manualEnrichedApplications, updatedSummaryData); | ||
|
|
||
| const updatedState = { | ||
| ...reportState, | ||
| data: { | ||
| ...reportState.data, | ||
| summaryData: updatedSummaryData, | ||
| applicationData: updatedApplicationData, | ||
| }, | ||
| } as ReportState; | ||
|
|
@@ -484,9 +518,9 @@ export class RiskInsightsOrchestratorService { | |
| criticalApps: updatedApplicationData.filter((app) => app.isCritical).length, | ||
| }); | ||
|
|
||
| return { reportState, organizationDetails, updatedState, userId }; | ||
| return { reportState, organizationDetails, updatedState, userId, metrics }; | ||
| }), | ||
| switchMap(({ reportState, organizationDetails, updatedState, userId }) => { | ||
| switchMap(({ reportState, organizationDetails, updatedState, userId, metrics }) => { | ||
| return from( | ||
| this.riskInsightsEncryptionService.encryptRiskInsightsReport( | ||
| { | ||
|
|
@@ -506,10 +540,11 @@ export class RiskInsightsOrchestratorService { | |
| organizationDetails, | ||
| updatedState, | ||
| encryptedData, | ||
| metrics, | ||
| })), | ||
| ); | ||
| }), | ||
| switchMap(({ reportState, organizationDetails, updatedState, encryptedData }) => { | ||
| switchMap(({ reportState, organizationDetails, updatedState, encryptedData, metrics }) => { | ||
| this.logService.debug( | ||
| `[RiskInsightsOrchestratorService] Persisting review status - report id: ${reportState?.data?.id}`, | ||
| ); | ||
|
|
@@ -521,26 +556,44 @@ export class RiskInsightsOrchestratorService { | |
| return of({ ...reportState }); | ||
| } | ||
|
|
||
| return this.reportApiService | ||
| .updateRiskInsightsApplicationData$( | ||
| reportState.data.id, | ||
| organizationDetails.organizationId, | ||
| { | ||
| data: { | ||
| applicationData: encryptedData.encryptedApplicationData.toSdk(), | ||
| }, | ||
| // Update applications data with critical marking | ||
| const updateApplicationsCall = this.reportApiService.updateRiskInsightsApplicationData$( | ||
| reportState.data.id, | ||
| organizationDetails.organizationId, | ||
| { | ||
| data: { | ||
| applicationData: encryptedData.encryptedApplicationData.toSdk(), | ||
| }, | ||
| ) | ||
| .pipe( | ||
| map(() => updatedState), | ||
| catchError((error: unknown) => { | ||
| this.logService.error( | ||
| "[RiskInsightsOrchestratorService] Failed to save review status", | ||
| error, | ||
| ); | ||
| return of({ ...reportState, error: "Failed to save application review status" }); | ||
| }), | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| // Update summary after recomputing | ||
| const updateSummaryCall = this.reportApiService.updateRiskInsightsSummary$( | ||
| reportState.data.id, | ||
| organizationDetails.organizationId, | ||
| { | ||
| data: { | ||
| summaryData: encryptedData.encryptedSummaryData.toSdk(), | ||
| metrics: metrics.toRiskInsightsMetricsData(), | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| return forkJoin([updateApplicationsCall, updateSummaryCall]).pipe( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ Update both application and summary with metrics in review status saving |
||
| map(() => updatedState), | ||
| tap((finalState) => { | ||
| this._flagForUpdatesSubject.next({ | ||
| ...finalState, | ||
| }); | ||
| }), | ||
| catchError((error: unknown) => { | ||
| this.logService.error( | ||
| "[RiskInsightsOrchestratorService] Failed to save review status", | ||
| error, | ||
| ); | ||
| return of({ ...reportState, error: "Failed to save application review status" }); | ||
| }), | ||
| ); | ||
| }), | ||
| ); | ||
| } | ||
|
|
@@ -752,67 +805,40 @@ export class RiskInsightsOrchestratorService { | |
|
|
||
| // Updates the existing application data to include critical applications | ||
| // Does not remove critical applications not in the set | ||
| private _mergeApplicationData( | ||
| private _updateApplicationData( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ Updated to accept new object and update those values specifically. This does not handle removing elements from the array if that were needed, but it does add applications if they didn't exist in the array already. |
||
| existingApplications: OrganizationReportApplication[], | ||
| criticalApplications: Set<string>, | ||
| updatedApplications: (Partial<OrganizationReportApplication> & { applicationName: string })[], | ||
| ): OrganizationReportApplication[] { | ||
| const setToMerge = new Set(criticalApplications); | ||
| const arrayToMerge = [...updatedApplications]; | ||
|
|
||
| const updatedApps = existingApplications.map((app) => { | ||
| const foundCritical = setToMerge.has(app.applicationName); | ||
|
|
||
| if (foundCritical) { | ||
| setToMerge.delete(app.applicationName); | ||
| // Check if there is an updated app | ||
| const foundUpdatedIndex = arrayToMerge.findIndex( | ||
| (ua) => ua.applicationName == app.applicationName, | ||
| ); | ||
|
|
||
| let foundApp: Partial<OrganizationReportApplication> | null = null; | ||
| // Remove the updated app from the list | ||
| if (foundUpdatedIndex >= 0) { | ||
| foundApp = arrayToMerge[foundUpdatedIndex]; | ||
| arrayToMerge.splice(foundUpdatedIndex, 1); | ||
| } | ||
|
|
||
| return { | ||
| ...app, | ||
| isCritical: foundCritical || app.isCritical, | ||
| applicationName: app.applicationName, | ||
| isCritical: foundApp?.isCritical || app.isCritical, | ||
| reviewedDate: foundApp?.reviewedDate || app.reviewedDate, | ||
| }; | ||
| }); | ||
|
|
||
| setToMerge.forEach((applicationName) => { | ||
| updatedApps.push({ | ||
| applicationName, | ||
| isCritical: true, | ||
| const newElements: OrganizationReportApplication[] = arrayToMerge.map( | ||
| (newApp): OrganizationReportApplication => ({ | ||
| applicationName: newApp.applicationName, | ||
| isCritical: newApp.isCritical ?? false, | ||
| reviewedDate: null, | ||
| }); | ||
| }); | ||
|
|
||
| return updatedApps; | ||
| } | ||
|
|
||
| /** | ||
| * Updates review status and critical flags for applications. | ||
| * Sets reviewedDate for all apps with null reviewedDate. | ||
| * Sets isCritical flag for apps in the criticalApplications array. | ||
| * | ||
| * @param existingApplications Current application data | ||
| * @param criticalApplications Array of application names to mark as critical | ||
| * @returns Updated application data with review dates and critical flags | ||
| */ | ||
| private _updateReviewStatusAndCriticalFlags( | ||
| existingApplications: OrganizationReportApplication[], | ||
| criticalApplications: string[], | ||
| ): OrganizationReportApplication[] { | ||
| const criticalSet = new Set(criticalApplications); | ||
| const currentDate = new Date(); | ||
|
|
||
| return existingApplications.map((app) => { | ||
| const shouldMarkCritical = criticalSet.has(app.applicationName); | ||
| const needsReviewDate = app.reviewedDate === null; | ||
|
|
||
| // Only create new object if changes are needed | ||
| if (needsReviewDate || shouldMarkCritical) { | ||
| return { | ||
| ...app, | ||
| reviewedDate: needsReviewDate ? currentDate : app.reviewedDate, | ||
| isCritical: shouldMarkCritical || app.isCritical, | ||
| }; | ||
| } | ||
| }), | ||
| ); | ||
|
|
||
| return app; | ||
| }); | ||
| return updatedApps.concat(newElements); | ||
| } | ||
|
|
||
| // Toggles the isCritical flag on applications via criticalApplicationName | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ค The size difference in these two video files surprise me. Is one compressed or built upon the other somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch, one was attached as .mov to the ticket so I converted with ffmpeg. Will check / optimise