From eed92f1bd1353b1831ec5165e6ba30e95b53568e Mon Sep 17 00:00:00 2001 From: Jingyi-Dify Date: Thu, 7 May 2026 15:06:46 -0700 Subject: [PATCH] fix(web): preserve settings fallbacks during main nav update - hide migrated settings tabs from the account settings sidebar - add disabled integrations destination mapping for future migration - keep legacy settings modal fallback until integrations sections are ready - restore main nav active styling and add titles for truncated labels --- .../header/account-dropdown/compliance.tsx | 3 +- .../main-nav-menu-content.tsx | 8 +- .../account-dropdown/menu-item-content.tsx | 4 +- .../workplace-selector/index.tsx | 2 +- .../__tests__/constants.spec.ts | 16 +++ .../account-setting/__tests__/index.spec.tsx | 39 ++---- .../header/account-setting/destinations.ts | 17 +++ .../header/account-setting/index.tsx | 121 +++++++++--------- .../main-nav/__tests__/index.spec.tsx | 3 +- .../main-nav/components/account-section.tsx | 3 +- .../main-nav/components/nav-link.tsx | 19 +-- .../main-nav/components/workspace-card.tsx | 26 ++-- web/context/modal-context-provider.tsx | 26 +++- 13 files changed, 169 insertions(+), 118 deletions(-) create mode 100644 web/app/components/header/account-setting/destinations.ts diff --git a/web/app/components/header/account-dropdown/compliance.tsx b/web/app/components/header/account-dropdown/compliance.tsx index 75d7200666..3a67a8d273 100644 --- a/web/app/components/header/account-dropdown/compliance.tsx +++ b/web/app/components/header/account-dropdown/compliance.tsx @@ -140,6 +140,7 @@ function ComplianceDocRowItem({ [Plan.team]: '', [Plan.enterprise]: '', } + const labelTitle = typeof label === 'string' ? label : undefined return ( {icon} -
{label}
+
{label}
{iconClassName && } - {label} + {label} ) @@ -205,10 +207,10 @@ export function MainNavMenuContent({
-
{userProfile.name}
+
{userProfile.name}
{mainNavBadge}
-
{userProfile.email}
+
{userProfile.email}
diff --git a/web/app/components/header/account-dropdown/menu-item-content.tsx b/web/app/components/header/account-dropdown/menu-item-content.tsx index bf8b1e283e..42831c48a7 100644 --- a/web/app/components/header/account-dropdown/menu-item-content.tsx +++ b/web/app/components/header/account-dropdown/menu-item-content.tsx @@ -17,10 +17,12 @@ export function MenuItemContent({ label, trailing, }: MenuItemContentProps) { + const labelTitle = typeof label === 'string' ? label : undefined + return ( <> -
{label}
+
{label}
{trailing} ) diff --git a/web/app/components/header/account-dropdown/workplace-selector/index.tsx b/web/app/components/header/account-dropdown/workplace-selector/index.tsx index a86da65797..58dc5e8296 100644 --- a/web/app/components/header/account-dropdown/workplace-selector/index.tsx +++ b/web/app/components/header/account-dropdown/workplace-selector/index.tsx @@ -97,7 +97,7 @@ const WorkplaceSelector = () => { {currentWorkspace?.name[0]?.toLocaleUpperCase()}
-
+
{currentWorkspace?.name}
diff --git a/web/app/components/header/account-setting/__tests__/constants.spec.ts b/web/app/components/header/account-setting/__tests__/constants.spec.ts index c7b3c47265..cf18f0b7e9 100644 --- a/web/app/components/header/account-setting/__tests__/constants.spec.ts +++ b/web/app/components/header/account-setting/__tests__/constants.spec.ts @@ -4,6 +4,11 @@ import { DEFAULT_ACCOUNT_SETTING_TAB, isValidAccountSettingTab, } from '../constants' +import { + enableMovedAccountSettingDestinations, + getMovedAccountSettingDestination, + movedAccountSettingDestinations, +} from '../destinations' describe('AccountSetting Constants', () => { it('should have correct ACCOUNT_SETTING_MODAL_ACTION', () => { @@ -39,4 +44,15 @@ describe('AccountSetting Constants', () => { expect(isValidAccountSettingTab('')).toBe(false) expect(isValidAccountSettingTab('invalid')).toBe(false) }) + + it('should keep migrated setting destinations disabled until integrations sections are ready', () => { + expect(enableMovedAccountSettingDestinations).toBe(false) + expect(movedAccountSettingDestinations[ACCOUNT_SETTING_TAB.PROVIDER]).toBe('/tools?section=provider') + expect(movedAccountSettingDestinations[ACCOUNT_SETTING_TAB.DATA_SOURCE]).toBe('/tools?section=data-source') + expect(movedAccountSettingDestinations[ACCOUNT_SETTING_TAB.API_BASED_EXTENSION]).toBe('/tools?section=api-based-extension') + expect(getMovedAccountSettingDestination(ACCOUNT_SETTING_TAB.PROVIDER)).toBeUndefined() + expect(getMovedAccountSettingDestination(ACCOUNT_SETTING_TAB.DATA_SOURCE)).toBeUndefined() + expect(getMovedAccountSettingDestination(ACCOUNT_SETTING_TAB.API_BASED_EXTENSION)).toBeUndefined() + expect(getMovedAccountSettingDestination(ACCOUNT_SETTING_TAB.BILLING)).toBeUndefined() + }) }) diff --git a/web/app/components/header/account-setting/__tests__/index.spec.tsx b/web/app/components/header/account-setting/__tests__/index.spec.tsx index 4bf9d1c515..6194f7bad3 100644 --- a/web/app/components/header/account-setting/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/__tests__/index.spec.tsx @@ -175,24 +175,21 @@ describe('AccountSetting', () => { // Assert // Assert expect(screen.getByText('common.userProfile.settings'))!.toBeInTheDocument() - expect(screen.getByText('common.settings.provider'))!.toBeInTheDocument() + expect(screen.queryByText('common.settings.provider'))!.not.toBeInTheDocument() expect(screen.getAllByText('common.settings.members').length).toBeGreaterThan(0) expect(screen.getByText('common.settings.billing'))!.toBeInTheDocument() - expect(screen.getByText('common.settings.dataSource'))!.toBeInTheDocument() - expect(screen.getByText('common.settings.apiBasedExtension'))!.toBeInTheDocument() + expect(screen.queryByText('common.settings.dataSource'))!.not.toBeInTheDocument() + expect(screen.queryByText('common.settings.apiBasedExtension'))!.not.toBeInTheDocument() expect(screen.getByText('custom.custom'))!.toBeInTheDocument() - expect(screen.getAllByText('common.settings.language').length).toBeGreaterThan(0) + expect(screen.queryByText('common.settings.language'))!.not.toBeInTheDocument() }) - it('should respect the initial tab', () => { + it('should keep hidden legacy tab metadata for direct entries', () => { // Act renderAccountSetting({ initialTab: ACCOUNT_SETTING_TAB.DATA_SOURCE }) // Assert - // Check that the active item title is Data Source - const titles = screen.getAllByText('common.settings.dataSource') - // One in sidebar, one in header. - expect(titles.length).toBeGreaterThan(1) + expect(screen.getByText('common.settings.dataSource'))!.toBeInTheDocument() }) it('should hide sidebar labels on mobile', () => { @@ -312,8 +309,8 @@ describe('AccountSetting', () => { // Assert // Assert expect(screen.queryByText('common.settings.provider')).not.toBeInTheDocument() - expect(screen.queryByText('common.settings.members')).not.toBeInTheDocument() - expect(screen.getByText('common.settings.language'))!.toBeInTheDocument() + expect(screen.queryByRole('button', { name: 'common.settings.members' })).not.toBeInTheDocument() + expect(screen.queryByText('common.settings.language'))!.not.toBeInTheDocument() }) it('should hide billing and custom tabs when disabled', () => { @@ -370,13 +367,11 @@ describe('AccountSetting', () => { renderAccountSetting({ onTabChange: mockOnTabChange }) // Act - fireEvent.click(screen.getByText('common.settings.provider')) + fireEvent.click(screen.getByText('common.settings.billing')) // Assert - expect(mockOnTabChange).toHaveBeenCalledWith(ACCOUNT_SETTING_TAB.PROVIDER) - // Check for content from ModelProviderPage - // Check for content from ModelProviderPage - expect(screen.getByText('common.modelProvider.models'))!.toBeInTheDocument() + expect(mockOnTabChange).toHaveBeenCalledWith(ACCOUNT_SETTING_TAB.BILLING) + expect(screen.getAllByText('common.settings.billing').length).toBeGreaterThan(1) }) it('should navigate through various tabs and show correct details', () => { @@ -389,23 +384,11 @@ describe('AccountSetting', () => { // Checking for title in header which is always there expect(screen.getAllByText('common.settings.billing').length).toBeGreaterThan(1) - // Data Source - fireEvent.click(screen.getByText('common.settings.dataSource')) - expect(screen.getAllByText('common.settings.dataSource').length).toBeGreaterThan(1) - - // API Based Extension - fireEvent.click(screen.getByText('common.settings.apiBasedExtension')) - expect(screen.getAllByText('common.settings.apiBasedExtension').length).toBeGreaterThan(1) - // Custom fireEvent.click(screen.getByText('custom.custom')) // Custom Page uses 'custom.custom' key as well. expect(screen.getAllByText('custom.custom').length).toBeGreaterThan(1) - // Language - fireEvent.click(screen.getAllByText('common.settings.language')[0]!) - expect(screen.getAllByText('common.settings.language').length).toBeGreaterThan(1) - // Members fireEvent.click(screen.getAllByText('common.settings.members')[0]!) expect(screen.getAllByText('common.settings.members').length).toBeGreaterThan(1) diff --git a/web/app/components/header/account-setting/destinations.ts b/web/app/components/header/account-setting/destinations.ts new file mode 100644 index 0000000000..cf88efb0c0 --- /dev/null +++ b/web/app/components/header/account-setting/destinations.ts @@ -0,0 +1,17 @@ +import type { AccountSettingTab } from './constants' +import { ACCOUNT_SETTING_TAB } from './constants' + +export const movedAccountSettingDestinations: Partial> = { + [ACCOUNT_SETTING_TAB.PROVIDER]: '/tools?section=provider', + [ACCOUNT_SETTING_TAB.DATA_SOURCE]: '/tools?section=data-source', + [ACCOUNT_SETTING_TAB.API_BASED_EXTENSION]: '/tools?section=api-based-extension', +} + +export const enableMovedAccountSettingDestinations = false + +export const getMovedAccountSettingDestination = (tab: AccountSettingTab) => { + if (!enableMovedAccountSettingDestinations) + return undefined + + return movedAccountSettingDestinations[tab] +} diff --git a/web/app/components/header/account-setting/index.tsx b/web/app/components/header/account-setting/index.tsx index f356bd71b2..67d156d23e 100644 --- a/web/app/components/header/account-setting/index.tsx +++ b/web/app/components/header/account-setting/index.tsx @@ -52,60 +52,70 @@ export default function AccountSetting({ const { enableBilling, enableReplaceWebAppLogo } = useProviderContext() const { isCurrentWorkspaceDatasetOperator } = useAppContext() - const workplaceGroupItems: GroupItem[] = (() => { + const settingItems: GroupItem[] = [ + { + key: ACCOUNT_SETTING_TAB.PROVIDER, + name: t('settings.provider', { ns: 'common' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.MEMBERS, + name: t('settings.members', { ns: 'common' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.BILLING, + name: t('settings.billing', { ns: 'common' }), + description: t('plansCommon.receiptInfo', { ns: 'billing' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.DATA_SOURCE, + name: t('settings.dataSource', { ns: 'common' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.API_BASED_EXTENSION, + name: t('settings.apiBasedExtension', { ns: 'common' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.CUSTOM, + name: t('custom', { ns: 'custom' }), + icon: , + activeIcon: , + }, + { + key: ACCOUNT_SETTING_TAB.LANGUAGE, + name: t('settings.language', { ns: 'common' }), + icon: , + activeIcon: , + }, + ] + const activeItem = settingItems.find(item => item.key === activeMenu) + + const visibleSettingItems: GroupItem[] = (() => { if (isCurrentWorkspaceDatasetOperator) return [] - const items: GroupItem[] = [ - { - key: ACCOUNT_SETTING_TAB.PROVIDER, - name: t('settings.provider', { ns: 'common' }), - icon: , - activeIcon: , - }, - { - key: ACCOUNT_SETTING_TAB.MEMBERS, - name: t('settings.members', { ns: 'common' }), - icon: , - activeIcon: , - }, - ] + const visibleTabs: AccountSettingTab[] = [] - if (enableBilling) { - items.push({ - key: ACCOUNT_SETTING_TAB.BILLING, - name: t('settings.billing', { ns: 'common' }), - description: t('plansCommon.receiptInfo', { ns: 'billing' }), - icon: , - activeIcon: , - }) - } + if (enableBilling) + visibleTabs.push(ACCOUNT_SETTING_TAB.BILLING) - items.push( - { - key: ACCOUNT_SETTING_TAB.DATA_SOURCE, - name: t('settings.dataSource', { ns: 'common' }), - icon: , - activeIcon: , - }, - { - key: ACCOUNT_SETTING_TAB.API_BASED_EXTENSION, - name: t('settings.apiBasedExtension', { ns: 'common' }), - icon: , - activeIcon: , - }, - ) + visibleTabs.push(ACCOUNT_SETTING_TAB.MEMBERS) - if (enableReplaceWebAppLogo || enableBilling) { - items.push({ - key: ACCOUNT_SETTING_TAB.CUSTOM, - name: t('custom', { ns: 'custom' }), - icon: , - activeIcon: , - }) - } + if (enableReplaceWebAppLogo || enableBilling) + visibleTabs.push(ACCOUNT_SETTING_TAB.CUSTOM) - return items + return visibleTabs + .map(tab => settingItems.find(item => item.key === tab)) + .filter((item): item is GroupItem => Boolean(item)) })() const media = useBreakpoints() @@ -115,22 +125,9 @@ export default function AccountSetting({ { key: 'workspace-group', name: t('settings.workplaceGroup', { ns: 'common' }), - items: workplaceGroupItems, - }, - { - key: 'account-group', - name: t('settings.generalGroup', { ns: 'common' }), - items: [ - { - key: ACCOUNT_SETTING_TAB.LANGUAGE, - name: t('settings.language', { ns: 'common' }), - icon: , - activeIcon: , - }, - ], + items: visibleSettingItems, }, ] - const activeItem = [...menuItems[0]!.items, ...menuItems[1]!.items].find(item => item.key === activeMenu) const [searchValue, setSearchValue] = useState('') @@ -215,7 +212,7 @@ export default function AccountSetting({
{activeItem?.description}
)} - {activeItem?.key === ACCOUNT_SETTING_TAB.PROVIDER && ( + {activeMenu === ACCOUNT_SETTING_TAB.PROVIDER && (
{ expect(homeLink).toHaveClass( 'border-transparent', 'backdrop-blur-[5px]', + 'text-saas-dify-blue-inverted', activeEdgeClassName, - 'after:border-components-main-nav-glass-edge-highlight-first', + 'after:border-[rgba(255,255,255,0.98)]', ) expect(homeLink.className).toContain('bg-[linear-gradient(98.077deg') }) diff --git a/web/app/components/main-nav/components/account-section.tsx b/web/app/components/main-nav/components/account-section.tsx index eaf6c61ca5..96aec31b74 100644 --- a/web/app/components/main-nav/components/account-section.tsx +++ b/web/app/components/main-nav/components/account-section.tsx @@ -24,7 +24,8 @@ const AccountSection = ({ {enableBilling && (