Merge pull request #23798 from overleaf/revert-23767-ac-remove-ds-nav-code-small

Revert "[web] Show DS Navigation for all users regardless of feature flag "

GitOrigin-RevId: 569800d75e1ef3ed6af666325213f1615c8f3a43
This commit is contained in:
Antoine Clausse
2025-02-24 09:04:37 +00:00
committed by Copybot
parent bfa5d956a0
commit aaeeb160d9
10 changed files with 67 additions and 44 deletions
@@ -1099,6 +1099,7 @@
"optional": "", "optional": "",
"or": "", "or": "",
"organization_name": "", "organization_name": "",
"organize_projects": "",
"organize_tags": "", "organize_tags": "",
"other": "", "other": "",
"other_causes_of_compile_timeouts": "", "other_causes_of_compile_timeouts": "",
@@ -1,4 +1,5 @@
import { useCallback } from 'react' import { useCallback } from 'react'
import { useSplitTestContext } from '@/shared/context/split-test-context'
import { sendMB } from '@/infrastructure/event-tracking' import { sendMB } from '@/infrastructure/event-tracking'
export type ExtraSegmentations = { export type ExtraSegmentations = {
@@ -38,11 +39,16 @@ export type ExtraSegmentations = {
} }
export const useSendProjectListMB = () => { export const useSendProjectListMB = () => {
const { splitTestVariants } = useSplitTestContext()
const hasDsNav = splitTestVariants['sidebar-navigation-ui-update'] as
| 'default'
| 'active'
return useCallback( return useCallback(
<T extends keyof ExtraSegmentations>( <T extends keyof ExtraSegmentations>(
event: T, event: T,
payload: ExtraSegmentations[T] payload: ExtraSegmentations[T]
) => sendMB(event, payload), ) =>
[] sendMB(event, { ...payload, 'sidebar-navigation-ui-update': hasDsNav }),
[hasDsNav]
) )
} }
@@ -16,8 +16,12 @@ import getMeta from '@/utils/meta'
import DefaultNavbar from '@/features/ui/components/bootstrap-5/navbar/default-navbar' import DefaultNavbar from '@/features/ui/components/bootstrap-5/navbar/default-navbar'
import Footer from '@/features/ui/components/bootstrap-5/footer/footer' import Footer from '@/features/ui/components/bootstrap-5/footer/footer'
import WelcomePageContent from '@/features/project-list/components/welcome-page-content' 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 { ProjectListDsNav } from '@/features/project-list/components/project-list-ds-nav'
import { DsNavStyleProvider } from '@/features/project-list/components/use-is-ds-nav' import {
DsNavStyleProvider,
useIsDsNav,
} from '@/features/project-list/components/use-is-ds-nav'
function ProjectListRoot() { function ProjectListRoot() {
const { isReady } = useWaitForI18n() const { isReady } = useWaitForI18n()
@@ -78,8 +82,22 @@ function ProjectListPageContent() {
const { t } = useTranslation() const { t } = useTranslation()
const hasDsNav = useIsDsNav()
if (isLoading) { if (isLoading) {
return <LoadingBranded loadProgress={loadProgress} label={t('loading')} /> const loadingComponent = (
<LoadingBranded loadProgress={loadProgress} label={t('loading')} />
)
if (hasDsNav) {
return loadingComponent
} else {
return (
<DefaultNavbarAndFooter>
<div className="loading-container">{loadingComponent}</div>
</DefaultNavbarAndFooter>
)
}
} }
if (totalProjectsCount === 0) { if (totalProjectsCount === 0) {
@@ -88,12 +106,18 @@ function ProjectListPageContent() {
<WelcomePageContent /> <WelcomePageContent />
</DefaultPageContentWrapper> </DefaultPageContentWrapper>
) )
} else { } else if (hasDsNav) {
return ( return (
<DsNavStyleProvider> <DsNavStyleProvider>
<ProjectListDsNav /> <ProjectListDsNav />
</DsNavStyleProvider> </DsNavStyleProvider>
) )
} else {
return (
<DefaultPageContentWrapper>
<ProjectListDefault />
</DefaultPageContentWrapper>
)
} }
} }
@@ -5,6 +5,7 @@ import {
} from '../../context/project-list-context' } from '../../context/project-list-context'
import TagsList from './tags-list' import TagsList from './tags-list'
import ProjectsFilterMenu from '../projects-filter-menu' import ProjectsFilterMenu from '../projects-filter-menu'
import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
type SidebarFilterProps = { type SidebarFilterProps = {
filter: Filter filter: Filter
@@ -29,6 +30,7 @@ export function SidebarFilter({ filter, text }: SidebarFilterProps) {
export default function SidebarFilters() { export default function SidebarFilters() {
const { t } = useTranslation() const { t } = useTranslation()
const hasDsNav = useIsDsNav()
return ( return (
<ul className="list-unstyled project-list-filters"> <ul className="list-unstyled project-list-filters">
@@ -37,9 +39,11 @@ export default function SidebarFilters() {
<SidebarFilter filter="shared" text={t('shared_with_you')} /> <SidebarFilter filter="shared" text={t('shared_with_you')} />
<SidebarFilter filter="archived" text={t('archived_projects')} /> <SidebarFilter filter="archived" text={t('archived_projects')} />
<SidebarFilter filter="trashed" text={t('trashed_projects')} /> <SidebarFilter filter="trashed" text={t('trashed_projects')} />
<li role="none"> {hasDsNav && (
<hr /> <li role="none">
</li> <hr />
</li>
)}
<TagsList /> <TagsList />
</ul> </ul>
) )
@@ -1,6 +1,7 @@
import { sortBy } from 'lodash' import { sortBy } from 'lodash'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { DotsThreeVertical, Plus, TagSimple } from '@phosphor-icons/react' import { DotsThreeVertical, Plus, TagSimple } from '@phosphor-icons/react'
import MaterialIcon from '../../../../shared/components/material-icon'
import { import {
UNCATEGORIZED_KEY, UNCATEGORIZED_KEY,
useProjectListContext, useProjectListContext,
@@ -13,6 +14,7 @@ import {
DropdownMenu, DropdownMenu,
DropdownToggle, DropdownToggle,
} from '@/features/ui/components/bootstrap-5/dropdown-menu' } from '@/features/ui/components/bootstrap-5/dropdown-menu'
import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
export default function TagsList() { export default function TagsList() {
const { t } = useTranslation() const { t } = useTranslation()
@@ -33,6 +35,7 @@ export default function TagsList() {
DeleteTagModal, DeleteTagModal,
} = useTag() } = useTag()
const isDsNav = useIsDsNav()
return ( return (
<> <>
<li <li
@@ -40,11 +43,15 @@ export default function TagsList() {
aria-hidden="true" aria-hidden="true"
data-testid="organize-projects" data-testid="organize-projects"
> >
{t('organize_tags')} {isDsNav ? t('organize_tags') : t('organize_projects')}
</li> </li>
<li className="tag"> <li className="tag">
<button type="button" className="tag-name" onClick={openCreateTagModal}> <button type="button" className="tag-name" onClick={openCreateTagModal}>
<Plus weight="bold" /> {isDsNav ? (
<Plus weight="bold" />
) : (
<MaterialIcon type="add" className="tag-list-icon" />
)}
<span className="name">{t('new_tag')}</span> <span className="name">{t('new_tag')}</span>
</button> </button>
@@ -67,7 +74,11 @@ export default function TagsList() {
color: getTagColor(tag), color: getTagColor(tag),
}} }}
> >
<TagSimple weight="fill" className="tag-list-icon" /> {isDsNav ? (
<TagSimple weight="fill" className="tag-list-icon" />
) : (
<MaterialIcon type="label" className="tag-list-icon" />
)}
</span> </span>
<span className="name"> <span className="name">
{tag.name}{' '} {tag.name}{' '}
@@ -83,7 +94,7 @@ export default function TagsList() {
id={`${tag._id}-dropdown-toggle`} id={`${tag._id}-dropdown-toggle`}
data-testid="tag-dropdown-toggle" data-testid="tag-dropdown-toggle"
> >
<DotsThreeVertical weight="bold" /> {isDsNav && <DotsThreeVertical weight="bold" />}
</DropdownToggle> </DropdownToggle>
<DropdownMenu className="dropdown-menu-sm-width"> <DropdownMenu className="dropdown-menu-sm-width">
<DropdownItem <DropdownItem
@@ -5,7 +5,6 @@ import classnames from 'classnames'
import OLButton from '@/features/ui/components/ol/ol-button' import OLButton from '@/features/ui/components/ol/ol-button'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { X } from '@phosphor-icons/react' import { X } from '@phosphor-icons/react'
import { useIsDsNav } from '@/features/project-list/components/use-is-ds-nav'
export function SurveyWidgetDsNav() { export function SurveyWidgetDsNav() {
const { t } = useTranslation() const { t } = useTranslation()
@@ -14,7 +13,6 @@ export function SurveyWidgetDsNav() {
`dismissed-${survey?.name}`, `dismissed-${survey?.name}`,
false false
) )
const hasDsNav = useIsDsNav()
const dismissSurvey = useCallback(() => { const dismissSurvey = useCallback(() => {
setDismissedSurvey(true) setDismissedSurvey(true)
@@ -24,12 +22,6 @@ export function SurveyWidgetDsNav() {
return null return null
} }
// Hide the survey for users who have sidebar-navigation-ui-update:
// They've had it for months. We don't need their feedback anymore
if (hasDsNav && survey?.name === 'ds-nav') {
return null
}
return ( return (
<div className={classnames('user-notifications', `survey-${survey.name}`)}> <div className={classnames('user-notifications', `survey-${survey.name}`)}>
<div className="notification-entry"> <div className="notification-entry">
+1
View File
@@ -1461,6 +1461,7 @@
"organization_name": "Organization name", "organization_name": "Organization name",
"organization_or_company_name": "Organization or company name", "organization_or_company_name": "Organization or company name",
"organization_or_company_type": "Organization or company type", "organization_or_company_type": "Organization or company type",
"organize_projects": "Organize Projects",
"organize_tags": "Organize Tags", "organize_tags": "Organize Tags",
"original_price": "Original price", "original_price": "Original price",
"other": "Other", "other": "Other",
@@ -42,7 +42,7 @@ describe('<TagsList />', function () {
it('displays the tags list', function () { it('displays the tags list', function () {
const header = screen.getByTestId('organize-projects') const header = screen.getByTestId('organize-projects')
expect(header.textContent).to.equal('Organize Tags') expect(header.textContent).to.equal('Organize Projects')
screen.getByRole('button', { screen.getByRole('button', {
name: 'New Tag', name: 'New Tag',
@@ -1,9 +1,8 @@
import { expect } from 'chai' import { expect } from 'chai'
import { fireEvent, render, screen } from '@testing-library/react' import { fireEvent, render, screen } from '@testing-library/react'
import { SurveyWidgetDsNav } from '../../../../../frontend/js/features/project-list/components/survey-widget-ds-nav' import SurveyWidget from '../../../../../frontend/js/features/project-list/components/survey-widget'
import { SplitTestProvider } from '@/shared/context/split-test-context'
describe('<SurveyWidgetDsNav />', function () { describe('<SurveyWidget />', function () {
beforeEach(function () { beforeEach(function () {
this.name = 'my-survey' this.name = 'my-survey'
this.preText = 'To help shape the future of Overleaf' this.preText = 'To help shape the future of Overleaf'
@@ -22,11 +21,7 @@ describe('<SurveyWidgetDsNav />', function () {
url: this.url, url: this.url,
}) })
render( render(<SurveyWidget />)
<SplitTestProvider>
<SurveyWidgetDsNav />
</SplitTestProvider>
)
}) })
it('shows text and link', function () { it('shows text and link', function () {
@@ -34,10 +29,9 @@ describe('<SurveyWidgetDsNav />', function () {
expect(dismissed).to.equal(null) expect(dismissed).to.equal(null)
screen.getByText(this.preText) screen.getByText(this.preText)
screen.getByText(this.linkText)
const link = screen.getByRole('link', { const link = screen.getByRole('link', {
name: 'Take survey', name: this.linkText,
}) as HTMLAnchorElement }) as HTMLAnchorElement
expect(link.href).to.equal(this.url) expect(link.href).to.equal(this.url)
}) })
@@ -69,11 +63,7 @@ describe('<SurveyWidgetDsNav />', function () {
}) })
localStorage.setItem('dismissed-my-survey', 'true') localStorage.setItem('dismissed-my-survey', 'true')
render( render(<SurveyWidget />)
<SplitTestProvider>
<SurveyWidgetDsNav />
</SplitTestProvider>
)
}) })
it('nothing is displayed', function () { it('nothing is displayed', function () {
@@ -87,11 +77,7 @@ describe('<SurveyWidgetDsNav />', function () {
describe('survey widget is not shown when no survey is configured', function () { describe('survey widget is not shown when no survey is configured', function () {
beforeEach(function () { beforeEach(function () {
render( render(<SurveyWidget />)
<SplitTestProvider>
<SurveyWidgetDsNav />
</SplitTestProvider>
)
}) })
it('nothing is displayed', function () { it('nothing is displayed', function () {
@@ -63,14 +63,12 @@ describe('<ProjectTools />', function () {
projects, projects,
totalSize: 100, totalSize: 100,
}) })
window.metaAttributesCache.set('ol-footer', { window.metaAttributesCache.set('ol-footer', {
showThinFooter: false, showThinFooter: false,
translatedLanguages: { en: 'English' }, translatedLanguages: { en: 'English' },
subdomainLang: { en: { lngCode: 'en', url: 'overleaf.com' } }, subdomainLang: { en: { lngCode: 'en', url: 'overleaf.com' } },
}) })
window.metaAttributesCache.set('ol-navbar', {
items: [],
})
fetchMock.get('/system/messages', []) fetchMock.get('/system/messages', [])
}) })