Skip to content

GDB-14779: Solr deprecation banner is not sticky#3012

Open
boyan-tonchev wants to merge 1 commit into
masterfrom
GDB-14779-deprecate-banner-is-not-sticky
Open

GDB-14779: Solr deprecation banner is not sticky#3012
boyan-tonchev wants to merge 1 commit into
masterfrom
GDB-14779-deprecate-banner-is-not-sticky

Conversation

@boyan-tonchev

@boyan-tonchev boyan-tonchev commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

  • Kept the deprecation banner sticky together with the application header.
  • Added user preferences infrastructure for storing user-specific UI settings.
  • Implemented persistence of the Solr deprecation banner dismissed state for authenticated users.

Why

  • The deprecation banner was rendered outside of the sticky header container, causing it to scroll out of view instead of remaining visible with the header.
  • Users should not have to dismiss the Solr deprecation banner every time they visit the application when they are authenticated.
  • Anonymous users cannot be identified, so their dismissed state should be preserved only for the current browser session.

How

  • Moved the deprecation banner into the sticky header container so both the header and the banner remain fixed at the top while scrolling.
  • Introduced models, context, storage, and service classes for managing user-specific preferences.
  • Persisted the dismissed banner state per authenticated user while keeping the preference in memory for anonymous users.

Checklist

  • Branch name
  • Target branch
  • Commit messages
  • Squash commits
  • MR name
  • MR Description
  • Tests
  • Browser support verified

@boyan-tonchev boyan-tonchev force-pushed the GDB-14779-deprecate-banner-is-not-sticky branch 3 times, most recently from 1c684f0 to e29dc46 Compare June 26, 2026 08:35
* @returns {@code true} if preferences should be persisted.
*/
private shouldPersistPreferences(): boolean {
return this.securityContextService.getSecurityConfig()?.enabled === true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can use config.isEnabled()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

* @returns {@code true} if preferences should be persisted.
*/
private shouldPersistPreferences(): boolean {
return this.securityContextService.getSecurityConfig()?.enabled === true

@plamen-yordanov plamen-yordanov Jun 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Without security enabled the user is an admin (or a repo manager if there is override auth). Shouldn't those be able to persist their preferences? If a user should be explicitly logged in, you can replace all of this with authentication.service#isLoggedIn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will check this. If security is disabled and getIsLoggedIn() returns false, I'll change it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we can go with logged in users only.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

/**
* Context service responsible for storing user-specific data for the current application session.
*/
export class UserContextService extends ContextService<UserContextFields> implements DeriveContextServiceContract<UserContextFields, UserContextFieldParams>, LifecycleHooks {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This must be UserPreferencesContextService

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Initially, the name was UserPreferencesContextService, but I thought it could be used in the future for other user-related properties.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed and moved

@svilenvelikov svilenvelikov Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why are these services in the domain package? They have nothing to do with the domains. Move them outside

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I thought of them as user-related, so I placed them next to the user service. I'll rename UserPreferencesContextService and move them back to where they were.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved


return this.userPreferencesStorageService
.getUsersPreferences()
.getUserPreferences(username) ?? new UserPreferences();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This should be something like this

this.userPreferencesStorageService
      .getPreferences()
      .getPreferenceByUsername(username)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@boyan-tonchev boyan-tonchev force-pushed the GDB-14779-deprecate-banner-is-not-sticky branch from e29dc46 to 131c05e Compare June 26, 2026 10:34
let securityContextService: jest.Mocked<SecurityContextService>;
let authenticationService: jest.Mocked<AuthenticationService>;

let storage: Record<string, string>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We have a StorageMock. Why don't you use it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reimplemented

let authenticationService: jest.Mocked<AuthenticationService>;

let storage: Record<string, string>;
let context: Record<string, unknown>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do you need to mock the context?! Why not just using the actual context service and just spy on it if you need.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reimplemented


return this.userPreferencesStorageService
.getUsersPreferences()
.getUserPreferences(username);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this is still unchanged

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

* Indicates whether the user has dismissed the Solr deprecation banner.
* When {@code true}, the banner is not shown again for the user.
*/
dismissSolrDeprecationBanner = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

rename this to either dismissedSolrDeprecationBanner or isSolrDeprecationBannerDismissed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

## What
- Kept the deprecation banner sticky together with the application header.
- Added user preferences infrastructure for storing user-specific UI settings.
- Implemented persistence of the Solr deprecation banner dismissed state for authenticated users.

## Why
- The deprecation banner was rendered outside of the sticky header container, causing it to scroll out of view instead of remaining visible with the header.
- Users should not have to dismiss the Solr deprecation banner every time they visit the application when they are authenticated.
- Anonymous users cannot be identified, so their dismissed state should be preserved only for the current browser session.

## How
- Moved the deprecation banner into the sticky header container so both the header and the banner remain fixed at the top while scrolling.
- Introduced models, context, storage, and service classes for managing user-specific preferences.
- Persisted the dismissed banner state per authenticated user while keeping the preference in memory for anonymous users.
@boyan-tonchev boyan-tonchev force-pushed the GDB-14779-deprecate-banner-is-not-sticky branch from 131c05e to 8ca3896 Compare June 26, 2026 14:32
@sonarqubecloud

Copy link
Copy Markdown

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.

3 participants