Skip to content

fix(profile): hide unavailable sidebar settings#5042

Open
Cokefish9527 wants to merge 1 commit into
QuantumNous:mainfrom
Cokefish9527:fix/upstream-profile-sidebar-settings-visibility
Open

fix(profile): hide unavailable sidebar settings#5042
Cokefish9527 wants to merge 1 commit into
QuantumNous:mainfrom
Cokefish9527:fix/upstream-profile-sidebar-settings-visibility

Conversation

@Cokefish9527
Copy link
Copy Markdown

@Cokefish9527 Cokefish9527 commented May 22, 2026

⚠️ 提交说明 / PR Notice

Important

  • 本描述已按代码逻辑人工整理,未直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

修复普通用户个人资料页“左侧边栏个人设置”展示范围不跟随管理员设置的问题。

原先 SidebarModulesCard 使用固定配置渲染用户可调整的侧边栏区域和模块,没有读取管理员配置 SidebarModulesAdmin。因此管理员关闭“聊天区域”“游乐场”或“聊天”后,普通用户个人中心仍能看到对应开关。

本次新增用户个人设置展示过滤逻辑:先按管理员配置过滤可展示的区域和子模块,再用于渲染、默认初始化和重置。普通用户只能进一步隐藏管理员已开放的模块,不能看到或恢复管理员未开放的模块。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Related: Cokefish9527/aiapi114#61

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有 Issues 与 PRs,确认不是重复提交。
  • Bug fix 说明: 此 PR 修复管理员配置与普通用户个人设置展示不一致的问题,并关联了 fork 仓库中的复现记录。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

验证已通过:

  • node --input-type=module -e "...filterSidebarSectionDefsByAdminConfig assertions..."
  • node node_modules/eslint/bin/eslint.js src/features/profile/components/sidebar-modules-card.tsx src/features/profile/lib/sidebar-modules.ts
  • npm run typecheck
  • npm run build
  • git diff --cached --check

说明:本 PR 不提交测试文件;已用内联 Node 断言覆盖管理员关闭整个聊天区域、仅关闭游乐场子模块两类关键逻辑。

Summary by CodeRabbit

  • New Features

    • Sidebar modules are now configurable through administrator settings, with support for enabling/disabling specific sections and modules.
  • Refactor

    • Improved internal handling of sidebar configuration loading and reset functionality to align with admin settings.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Walkthrough

The PR introduces admin-controlled sidebar module visibility by extracting filtering logic into a reusable library and integrating it into the sidebar modules card component. New types define the configuration structure, a filter function applies admin settings to sections and modules, and the component uses memoized filtered definitions throughout config loading, reset, and rendering workflows.

Changes

Admin-controlled sidebar module visibility

Layer / File(s) Summary
Admin config types and filtering logic
web/default/src/features/profile/lib/sidebar-modules.ts
Exports SidebarSectionDef, SidebarModulesConfig, and SidebarModuleConfig types. Implements filterSidebarSectionDefsByAdminConfig to safely parse admin JSON configuration and filter sections/modules based on per-section enabled flags and per-module boolean toggles, removing disabled sections or sections with no visible modules.
Component integration with admin filtering
web/default/src/features/profile/components/sidebar-modules-card.tsx
Imports useStatus and useMemo; builds memoized sectionDefs and visibleSectionDefs from admin configuration via the filter helper. Updates loadConfig, handleReset, and render to use filtered visibleSectionDefs instead of hard-coded definitions. Changes effect wiring to depend on memoized loadConfig callback.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Sidebar modules, now trimmed by admin's hand,
Hidden or shown by configuration command,
No hard-coded lists, just filters so clean,
Each section and module—exactly foreseen!
hops away

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(profile): hide unavailable sidebar settings' accurately and concisely captures the main change: using admin configuration to filter and hide sidebar modules/sections that administrators have disabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/default/src/features/profile/components/sidebar-modules-card.tsx`:
- Around line 148-152: The effect calling loadConfig currently depends on
visibleSectionDefs and thus refetches and overwrites local config when
visibility toggles; make loadConfig stable (wrap it in useCallback without
referencing visibleSectionDefs) and remove visibleSectionDefs from the useEffect
dependency array so useEffect(() => { void Promise.resolve().then(() =>
loadConfig()) }, [loadConfig]) does not retrigger on visibility changes; then
add a separate effect that merges visibleSectionDefs into the local config state
(e.g., updateConfig or setConfig) without clobbering unsaved user edits,
referencing visibleSectionDefs, config, and the state updater to reconcile
visibility changes.

In `@web/default/src/features/profile/lib/sidebar-modules.ts`:
- Around line 33-57: The current logic lets malformed but non-empty
adminConfigValue fall back to returning the user's sections (fail-open). Change
behavior so that when adminConfigValue is present (non-null/non-empty string)
but parseAdminConfig returns null (parsing failed), treat that as an explicit
"no modules allowed" (fail-closed): in filterSidebarSectionDefsByAdminConfig,
check if adminConfigValue && adminConfig == null and in that case return an
empty array (or filter out all modules) instead of returning the original
sections; alternatively modify parseAdminConfig to return a distinct
error/marker for invalid input and handle that marker in
filterSidebarSectionDefsByAdminConfig to enforce the closed behavior. Ensure you
reference parseAdminConfig, filterSidebarSectionDefsByAdminConfig and the
adminConfigValue variable when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee381681-91b6-492d-8352-3cd08da0b9b3

📥 Commits

Reviewing files that changed from the base of the PR and between f2c7647 and 71ef9f3.

📒 Files selected for processing (2)
  • web/default/src/features/profile/components/sidebar-modules-card.tsx
  • web/default/src/features/profile/lib/sidebar-modules.ts

Comment on lines +148 to 152
}, [visibleSectionDefs])

useEffect(() => {
loadConfig()
void Promise.resolve().then(() => loadConfig())
}, [loadConfig])
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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid refetch-triggered local state overwrite during edits.

Line 148 ties loadConfig to visibleSectionDefs, so language/status changes retrigger Line 151 load and can overwrite unsaved user toggles in config.

Suggested direction
-import { useCallback, useEffect, useMemo, useState } from 'react'
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@
+  const hasLoadedRef = useRef(false)
@@
   useEffect(() => {
-    void Promise.resolve().then(() => loadConfig())
+    if (hasLoadedRef.current) return
+    hasLoadedRef.current = true
+    void loadConfig()
   }, [loadConfig])

Then reconcile visibility changes in a separate state-merge path instead of reloading from the API.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}, [visibleSectionDefs])
useEffect(() => {
loadConfig()
void Promise.resolve().then(() => loadConfig())
}, [loadConfig])
}, [visibleSectionDefs])
const hasLoadedRef = useRef(false)
useEffect(() => {
if (hasLoadedRef.current) return
hasLoadedRef.current = true
void loadConfig()
}, [loadConfig])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/profile/components/sidebar-modules-card.tsx` around
lines 148 - 152, The effect calling loadConfig currently depends on
visibleSectionDefs and thus refetches and overwrites local config when
visibility toggles; make loadConfig stable (wrap it in useCallback without
referencing visibleSectionDefs) and remove visibleSectionDefs from the useEffect
dependency array so useEffect(() => { void Promise.resolve().then(() =>
loadConfig()) }, [loadConfig]) does not retrigger on visibility changes; then
add a separate effect that merges visibleSectionDefs into the local config state
(e.g., updateConfig or setConfig) without clobbering unsaved user edits,
referencing visibleSectionDefs, config, and the state updater to reconcile
visibility changes.

Comment on lines +33 to +57
const parseAdminConfig = (
adminConfigValue: string | null | undefined
): SidebarModulesConfig | null => {
if (!adminConfigValue || adminConfigValue.trim() === '') return null

try {
const parsed = JSON.parse(adminConfigValue) as unknown
if (!parsed || typeof parsed !== 'object') return null
return parsed as SidebarModulesConfig
} catch {
return null
}
}

/**
* Limits the user's personal sidebar settings to modules still allowed by the
* administrator-wide sidebar configuration.
*/
export function filterSidebarSectionDefsByAdminConfig(
sections: SidebarSectionDef[],
adminConfigValue: string | null | undefined
): SidebarSectionDef[] {
const adminConfig = parseAdminConfig(adminConfigValue)
if (!adminConfig) return sections

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail-open behavior on invalid admin JSON re-exposes restricted toggles.

At Line 56, malformed but non-empty admin config falls back to sections unchanged, which can show modules that admins intended to disable. This should fail closed when config is present but invalid.

Suggested fix
-const parseAdminConfig = (
+const parseAdminConfig = (
   adminConfigValue: string | null | undefined
-): SidebarModulesConfig | null => {
-  if (!adminConfigValue || adminConfigValue.trim() === '') return null
+): SidebarModulesConfig | 'absent' | 'invalid' => {
+  if (!adminConfigValue || adminConfigValue.trim() === '') return 'absent'

   try {
     const parsed = JSON.parse(adminConfigValue) as unknown
-    if (!parsed || typeof parsed !== 'object') return null
+    if (!parsed || typeof parsed !== 'object') return 'invalid'
     return parsed as SidebarModulesConfig
   } catch {
-    return null
+    return 'invalid'
   }
 }
@@
   const adminConfig = parseAdminConfig(adminConfigValue)
-  if (!adminConfig) return sections
+  if (adminConfig === 'absent') return sections
+  if (adminConfig === 'invalid') return []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/profile/lib/sidebar-modules.ts` around lines 33 -
57, The current logic lets malformed but non-empty adminConfigValue fall back to
returning the user's sections (fail-open). Change behavior so that when
adminConfigValue is present (non-null/non-empty string) but parseAdminConfig
returns null (parsing failed), treat that as an explicit "no modules allowed"
(fail-closed): in filterSidebarSectionDefsByAdminConfig, check if
adminConfigValue && adminConfig == null and in that case return an empty array
(or filter out all modules) instead of returning the original sections;
alternatively modify parseAdminConfig to return a distinct error/marker for
invalid input and handle that marker in filterSidebarSectionDefsByAdminConfig to
enforce the closed behavior. Ensure you reference parseAdminConfig,
filterSidebarSectionDefsByAdminConfig and the adminConfigValue variable when
making the change.

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.

1 participant