فهرست منبع

[web] Scope ds-nav split test to project list (#22689)

* Add `dsNavStyle` prop, so `sidebar-navigation-ui-update` doesn't change all pages

* Use `useIsDsNav` instead of `useSplitTestContext`

* Create a `useDsNavStyle` hook

* Use `useDsNavStyle`

* Add comment on `useIsDsNav` and `NavStyleContext`

* Revert "Hide nav dropdown chevron icon in welcome page"

This reverts commit 78b5ba85

* Move `DsNavStyleProvider` usage to project-list-ds-nav.tsx

* Fix typo

* Simplify `useDsNavStyle` conditions

GitOrigin-RevId: df3fe66d772919c40df69d357bee6949ab413928
Antoine Clausse 1 سال پیش
والد
کامیت
f9cc0c3bf4

+ 3 - 3
services/web/frontend/js/features/project-list/components/add-affiliation.tsx

@@ -3,7 +3,7 @@ import { useProjectListContext } from '../context/project-list-context'
 import getMeta from '../../../utils/meta'
 import classNames from 'classnames'
 import OLButton from '@/features/ui/components/ol/ol-button'
-import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
+import { useDsNavStyle } from '@/features/project-list/components/use-is-ds-nav'
 
 export function useAddAffiliation() {
   const { totalProjectsCount } = useProjectListContext()
@@ -22,7 +22,7 @@ type AddAffiliationProps = {
 function AddAffiliation({ className }: AddAffiliationProps) {
   const { t } = useTranslation()
   const { show } = useAddAffiliation()
-  const isDsNav = useIsDsNav()
+  const dsNavStyle = useDsNavStyle()
 
   if (!show) {
     return null
@@ -32,7 +32,7 @@ function AddAffiliation({ className }: AddAffiliationProps) {
 
   return (
     <div className={classes}>
-      <p className={isDsNav ? 'text-muted' : undefined}>
+      <p className={dsNavStyle ? 'text-muted' : undefined}>
         {t('are_you_affiliated_with_an_institution')}
       </p>
       <OLButton variant="secondary" href="/user/settings">

+ 11 - 9
services/web/frontend/js/features/project-list/components/project-list-root.tsx

@@ -3,10 +3,7 @@ import {
   ProjectListProvider,
   useProjectListContext,
 } from '../context/project-list-context'
-import {
-  SplitTestProvider,
-  useSplitTestContext,
-} from '@/shared/context/split-test-context'
+import { SplitTestProvider } from '@/shared/context/split-test-context'
 import { ColorPickerProvider } from '../context/color-picker-context'
 import * as eventTracking from '../../../infrastructure/event-tracking'
 import { useTranslation } from 'react-i18next'
@@ -21,6 +18,10 @@ import Footer from '@/features/ui/components/bootstrap-5/footer/footer'
 import WelcomePageContent from '@/features/project-list/components/welcome-page-content'
 import ProjectListDefault from '@/features/project-list/components/project-list-default'
 import { ProjectListDsNav } from '@/features/project-list/components/project-list-ds-nav'
+import {
+  DsNavStyleProvider,
+  useIsDsNav,
+} from '@/features/project-list/components/use-is-ds-nav'
 
 function ProjectListRoot() {
   const { isReady } = useWaitForI18n()
@@ -75,16 +76,13 @@ function ProjectListPageContent() {
   const { totalProjectsCount, isLoading, loadProgress } =
     useProjectListContext()
 
-  const { splitTestVariants } = useSplitTestContext()
-
   useEffect(() => {
     eventTracking.sendMB('loads_v2_dash', {})
   }, [])
 
   const { t } = useTranslation()
 
-  const hasDsNav =
-    splitTestVariants['sidebar-navigation-ui-update'] === 'active'
+  const hasDsNav = useIsDsNav()
 
   if (isLoading) {
     const loadingComponent = (
@@ -109,7 +107,11 @@ function ProjectListPageContent() {
       </DefaultPageContentWrapper>
     )
   } else if (hasDsNav) {
-    return <ProjectListDsNav />
+    return (
+      <DsNavStyleProvider>
+        <ProjectListDsNav />
+      </DsNavStyleProvider>
+    )
   } else {
     return (
       <DefaultPageContentWrapper>

+ 2 - 4
services/web/frontend/js/features/project-list/components/sidebar/sidebar-filters.tsx

@@ -5,7 +5,7 @@ import {
 } from '../../context/project-list-context'
 import TagsList from './tags-list'
 import ProjectsFilterMenu from '../projects-filter-menu'
-import { useSplitTestContext } from '@/shared/context/split-test-context'
+import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
 
 type SidebarFilterProps = {
   filter: Filter
@@ -30,9 +30,7 @@ export function SidebarFilter({ filter, text }: SidebarFilterProps) {
 
 export default function SidebarFilters() {
   const { t } = useTranslation()
-  const { splitTestVariants } = useSplitTestContext()
-  const hasDsNav =
-    splitTestVariants['sidebar-navigation-ui-update'] === 'active'
+  const hasDsNav = useIsDsNav()
 
   return (
     <ul className="list-unstyled project-list-filters">

+ 0 - 6
services/web/frontend/js/features/project-list/components/use-is-ds-nav.ts

@@ -1,6 +0,0 @@
-import { useSplitTestContext } from '@/shared/context/split-test-context'
-
-export const useIsDsNav = () => {
-  const { splitTestVariants } = useSplitTestContext()
-  return splitTestVariants['sidebar-navigation-ui-update'] === 'active'
-}

+ 27 - 0
services/web/frontend/js/features/project-list/components/use-is-ds-nav.tsx

@@ -0,0 +1,27 @@
+import { createContext, type FC, type ReactNode, useContext } from 'react'
+import { useSplitTestContext } from '@/shared/context/split-test-context'
+
+/**
+ * This hook returns whether the user has the split-test assignment 'sidebar-navigation-ui-update'
+ */
+export const useIsDsNav = () => {
+  const { splitTestVariants } = useSplitTestContext()
+  return splitTestVariants['sidebar-navigation-ui-update'] === 'active'
+}
+
+/**
+ * This context wraps elements that should be styled according to the sidebar-navigation-ui-update redesign
+ * It doesn't exactly match the split-test assignment because it's only used in the project-list page
+ */
+const DsNavStyleContext = createContext<boolean | undefined>(undefined)
+
+export const DsNavStyleProvider: FC<{
+  children: ReactNode
+}> = ({ children }) => (
+  <DsNavStyleContext.Provider value>{children}</DsNavStyleContext.Provider>
+)
+
+export const useDsNavStyle = () => {
+  const context = useContext(DsNavStyleContext)
+  return context ?? false
+}

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/navbar/account-menu-items.tsx

@@ -5,7 +5,7 @@ import type { NavbarSessionUser } from '@/features/ui/components/types/navbar'
 import DropdownListItem from '@/features/ui/components/bootstrap-5/dropdown-list-item'
 import NavDropdownDivider from './nav-dropdown-divider'
 import NavDropdownLinkItem from './nav-dropdown-link-item'
-import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
+import { useDsNavStyle } from '@/features/project-list/components/use-is-ds-nav'
 import { SignOut } from '@phosphor-icons/react'
 
 export function AccountMenuItems({
@@ -17,7 +17,7 @@ export function AccountMenuItems({
 }) {
   const { t } = useTranslation()
   const logOutFormId = 'logOutForm'
-  const isDsNav = useIsDsNav()
+  const dsNavStyle = useDsNavStyle()
   return (
     <>
       <Dropdown.Item as="li" disabled role="menuitem">
@@ -48,7 +48,7 @@ export function AccountMenuItems({
           className="d-flex align-items-center justify-content-between"
         >
           <span>{t('log_out')}</span>
-          {isDsNav && <SignOut size={16} />}
+          {dsNavStyle && <SignOut size={16} />}
         </Dropdown.Item>
         <form id={logOutFormId} method="POST" action="/logout">
           <input type="hidden" name="_csrf" value={getMeta('ol-csrfToken')} />

+ 3 - 5
services/web/frontend/js/features/ui/components/bootstrap-5/navbar/nav-dropdown-menu.tsx

@@ -1,7 +1,7 @@
 import { type ReactNode, useState } from 'react'
 import { Dropdown } from 'react-bootstrap-5'
 import { CaretUp, CaretDown } from '@phosphor-icons/react'
-import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
+import { useDsNavStyle } from '@/features/project-list/components/use-is-ds-nav'
 
 export default function NavDropdownMenu({
   title,
@@ -15,7 +15,7 @@ export default function NavDropdownMenu({
   onToggle?: (nextShow: boolean) => void
 }) {
   const [show, setShow] = useState(false)
-  const isDsNav = useIsDsNav()
+  const dsNavStyle = useDsNavStyle()
   // Can't use a NavDropdown here because it's impossible to render the menu as
   // a <ul> element using NavDropdown
   const Caret = show ? CaretUp : CaretDown
@@ -31,9 +31,7 @@ export default function NavDropdownMenu({
     >
       <Dropdown.Toggle role="menuitem">
         {title}
-        {isDsNav && (
-          <Caret weight="bold" className="ms-2 navbar-dropdown-caret" />
-        )}
+        {dsNavStyle && <Caret weight="bold" className="ms-2" />}
       </Dropdown.Toggle>
       <Dropdown.Menu as="ul" role="menu" align="end">
         {children}

+ 0 - 5
services/web/frontend/stylesheets/bootstrap-5/pages/project-list-ds-nav.scss

@@ -316,9 +316,4 @@
       @include body-xs;
     }
   }
-
-  // Only show the dropdown caret icon in the DS nav version of the project dashboard
-  .navbar-dropdown-caret {
-    display: unset;
-  }
 }

+ 0 - 5
services/web/frontend/stylesheets/bootstrap-5/pages/project-list.scss

@@ -775,8 +775,3 @@ form.project-search {
     inset: 0;
   }
 }
-
-// Hide expander caret icon by default so that it only ever appears in the DS nav version of the project dashboard
-.navbar-dropdown-caret {
-  display: none;
-}