Skip to content

Conversation

AlexRubik
Copy link
Contributor

@AlexRubik AlexRubik commented Sep 24, 2025

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-26031

📔 Objective

Jira Description:
The draft pull request includes changes to the drawer state to be more easily consumable. This scope of this ticket is to capture the changes made to the drawer state and usage across components.

Changes in scope:

Create the drawerDetailsSubject in the RiskInsightsDataService and update the usage regarding this state

  • See the Drawer functions section in the data service

Update angular components that are using this state

  • Take note of the special case getters in the risk-insights.component.ts file for syncing the drawer state to the service state

Refactors the Risk Insights drawer state management from individual properties to a unified reactive observable pattern, improving maintainability and performance. Based on patterns established in draft PR #16005.

Changes by File:

Core Service Layer

  • risk-insights-data.service.ts:
    • Replaced 6 individual drawer properties (openDrawer, drawerInvokerId, etc.) with unified drawerDetailsSubject BehaviorSubject
    • Added reactive Observable getters (drawerDetails$, isActiveDrawerType$(), isDrawerOpenForInvoker$())
    • Implemented smart toggle logic in drawer setter methods to preserve click-to-toggle UX
    • Centralized all drawer state management in single typed DrawerDetails object

Main Component Integration

  • risk-insights.component.ts:

    • Added special case getter/setter for isDrawerOpen to sync component two-way binding with service state
    • Implemented subscription to drawerDetails$ with takeUntilDestroyed() cleanup
    • Enables reactive patterns while maintaining template simplicity
  • risk-insights.component.html:

    • Replaced direct property access with @if (dataService.drawerDetails$ | async; as drawerDetails) pattern
    • Updated isActiveDrawerType() calls to reactive isActiveDrawerType$() | async
    • Uses unified drawerDetails object throughout template for better performance

Applications Components

  • all-applications.component.html & critical-applications.component.html:

    • Replaced dataService.drawerInvokerId comparisons with (dataService.drawerDetails$ | async)?.invokerId
    • Updated table component bindings from function callbacks to direct reactive properties
  • all-applications.component.ts & critical-applications.component.ts:

    • Removed deprecated isDrawerOpenForTableRow() and trackByFunction() methods
    • Cleaned up unused imports for better code hygiene

Table Component

⚠️ These changes might be conflicting with this pending PR for PM-25616. I lean towards pulling in the current/target PR (PM-26031, drawer refactor) and resolving potential conflicts in the separate scrollable table pr (25616).

  • app-table-row-scrollable.component.ts:

    • Updated input from isDrawerIsOpenForThisRecord function to openApplication string property
    • Simplifies component interface and improves performance
  • app-table-row-scrollable.component.html:

    • Replaced all function calls with direct string comparisons (row.applicationName === openApplication)
    • Eliminates 9 function calls per table row for better rendering performance

Key Benefits

  • Reactive Architecture: All drawer state now uses Observable patterns for automatic updates
  • Performance: Eliminated function calls in templates with direct property comparisons
  • Type Safety: Unified DrawerDetails interface provides strong typing throughout
  • Maintainability: Centralized state management makes future changes easier
  • UX Preservation: Maintains original toggle behavior (click same button twice to close)

Testing Notes

  • All linting passes with no errors
  • Prettier formatting verified across all files
  • Drawer toggle behavior preserved (open/close/switch functionality)
  • Reactive updates work automatically when drawer state changes

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

…ith BehaviorSubject

- Replace individual drawer properties with unified drawerDetailsSubject
- Add reactive Observable getters for drawer state checking
- Update all drawer methods to use centralized state management
- Add private _isDrawerOpen property for internal state tracking
- Subscribe to drawerDetails$ changes with takeUntilDestroyed cleanup
- Implement getter/setter for isDrawerOpen to sync component <-> service
- Enable two-way binding while maintaining reactive patterns
…servable patterns

- Replace dataService.openDrawer with isDrawerOpen special case getter
- Wrap drawer in @if block with drawerDetails$ | async for single subscription
- Update isActiveDrawerType() calls to reactive isActiveDrawerType$() | async
- Replace direct property access with unified drawerDetails object
- Use modern @if control flow syntax for better performance
…bservable patterns

- Replace dataService.drawerInvokerId with drawerDetails$ | async in card highlighting
- Update app-table-row-scrollable input from isDrawerIsOpenForThisRecord function to openApplication string
…ive observable patterns

- Replace dataService.drawerInvokerId with drawerDetails$ | async in card highlighting
- Update table component binding from isDrawerIsOpenForThisRecord to openApplication
- Use reactive drawer state checking for consistent behavior with all-applications
- Remove unused trackByFunction that's no longer needed in template
- Remove getSelectedUrls function that's not used anywhere
- Remove isDrawerOpenForTableRow replaced by reactive openApplication binding
- Clean up unused ApplicationHealthReportDetail import
- Simplifies component interface following reactive pattern migration
…nctions

- Remove unused trackByFunction that's no longer needed in template
- Remove isDrawerOpenForTableRow replaced by reactive openApplication binding
…s with string comparison

- Replace isDrawerIsOpenForThisRecord(row.applicationName) with row.applicationName === openApplication
- Use direct string comparison instead of function calls for better performance
- Matches updated component input from function to string property
- Simplifies template logic following reactive pattern migration
… setter methods

- Add toggle logic to check if same drawer type and invoker are already open
- Close drawer when clicking same button twice (preserves original UX)
- Switch drawer content when clicking different button
- Maintains reactive patterns while restoring expected behavior
@AlexRubik AlexRubik self-assigned this Sep 24, 2025
@AlexRubik AlexRubik requested a review from a team as a code owner September 24, 2025 16:27
Copy link

codecov bot commented Sep 24, 2025

Codecov Report

❌ Patch coverage is 0% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.29%. Comparing base (8ba22f3) to head (3e28619).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...sk-insights/services/risk-insights-data.service.ts 0.00% 27 Missing ⚠️
...irt/access-intelligence/risk-insights.component.ts 0.00% 9 Missing ⚠️
.../access-intelligence/all-applications.component.ts 0.00% 1 Missing ⚠️
...ss-intelligence/critical-applications.component.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #16580      +/-   ##
==========================================
- Coverage   38.30%   38.29%   -0.01%     
==========================================
  Files        3404     3404              
  Lines       97592    97591       -1     
  Branches    14683    14692       +9     
==========================================
- Hits        37380    37373       -7     
- Misses      58585    58591       +6     
  Partials     1627     1627              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

github-actions bot commented Sep 24, 2025

Logo
Checkmarx One – Scan Summary & Details3db09267-fc4e-4159-abb9-8cd94f7e486f

Great job! No new security vulnerabilities introduced in this pull request

- the logic replacing these functions will be in pr16523
Copy link
Contributor

@Banrion Banrion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments to improve duplicate subscriptions. You can most likely remove the observable function that checks the drawer type if it's not used outside of the components.

[ngClass]="{
'tw-bg-primary-100': dataService.drawerInvokerId === 'allAppsOrgAtRiskMembers',
'tw-bg-primary-100':
(dataService.drawerDetails$ | async)?.invokerId === 'allAppsOrgAtRiskMembers',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Avoid multiple subscriptions via dataService.drawerDetails$ | async). Each async usage creates a new subscription. You can create a variable above the card to capture the drawer details in the html.

</div>
</bit-drawer-body>
</ng-container>
@if (dataService.isActiveDrawerType$(drawerTypes.AppAtRiskMembers) | async) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Use drawerDetails with boolean function

…e function per review feedback

- Keep original isActiveDrawerType() as boolean function using drawerDetailsSubject.value
- Maintain isActiveDrawerType$() as Observable version for reactive templates
- Apply same pattern to isDrawerOpenForInvoker() for consistency
- Addresses review feedback to preserve existing function signatures
…ription for drawer state per review feedback
@AlexRubik AlexRubik requested a review from a team as a code owner September 26, 2025 15:59
@AlexRubik AlexRubik requested a review from Banrion September 26, 2025 16:56
Copy link

@Banrion Banrion merged commit 979e370 into main Sep 26, 2025
61 checks passed
@Banrion Banrion deleted the dirt/pm-26031/drawer-service branch September 26, 2025 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants