Store sidebar navigation mode as a user preference

What does this MR do and why?

Stores the tailored sidebar navigation mode (compact / all_categories) as a user preference in the database, so the choice follows the user across browsers and devices. Today it lives only in localStorage (added in !253007 (merged)).

This is the backend half of a two-MR stack. The frontend MR (!262884) is stacked on this branch and has to deploy after it.

  • Adds user_preferences.sidebar_navigation_mode (smallint, default 0 = compact, NOT NULL).
  • Adds the UserPreference#sidebar_navigation_mode enum (prefix: true) and delegates it from User.
  • Exposes it in GraphQL as the SidebarNavigationMode enum, a field on UserPreferences, and an argument on userPreferencesUpdate. Both are marked experiment for 19.6. An explicit null is ignored, like the other non-nullable preferences.
  • Includes sidebar_navigation_mode in the logged-in super sidebar payload (SidebarsHelper#super_sidebar_logged_in_context). Logged-out users don't get the key.

The control is only shown while the hide_unpinned_sidebar_items (gitlab_com_derisk) flag is enabled.

For engineering reviewers: please confirm that userPreferencesUpdate (GraphQL) is the right write path, rather than a REST action next to Users::PinsController.

Why a dedicated column instead of JSONB

No more sidebar preferences are planned right now. A typed enum column is validated by Rails and GraphQL without needing a JSON schema, and adding another column later is cheap.

Note on db/structure.sql

The author's local database had drifted from master, so a regenerated dump picked up unrelated changes. db/structure.sql was edited by hand to add just the one column line, in the position and format Rails dumps it. The migration was checked up and down on main, ci, and sec.

References

Screenshots or screen recordings

Not applicable: backend only, no UI change.

How to set up and validate locally

  1. Run bin/rails db:migrate.
  2. In GraphiQL (/-/graphql-explorer), run:
    mutation { userPreferencesUpdate(input: { sidebarNavigationMode: ALL_CATEGORIES }) { errors userPreferences { sidebarNavigationMode } } }
    You should get ALL_CATEGORIES back.
  3. In the Rails console, User.find_by(username: 'root').sidebar_navigation_mode should return "all_categories".

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Austin Regnery

Merge request reports

Loading
Loading