From 6c0f6ccf8e533621eeac585eead6405c545f5876 Mon Sep 17 00:00:00 2001 From: Santiago Suarez Date: Wed, 22 Apr 2026 21:21:18 -0500 Subject: [PATCH 01/10] feat: redesign Advanced Settings page with grouped sections and type-specific inputs Redesigns the Advanced Settings page in Studio for course authors. Instead of a flat alphabetical list of ~82 settings, settings are now organized into collapsible sections by functional category, with type-aware input components and a search/filter bar. New components: - SettingsFilters: search bar with collapse/expand all and deprecated settings toggle - SettingsSection: collapsible section using Paragon Collapsible.Advanced, renders settings grouped by category; supports subcategory grouping (Content Blocks) - CourseDisplayOverrides: dedicated UI for display-override fields with enable/disable toggle and blocked state messaging - BooleanInput, StringInput, NumberInput, EnumInput, JsonInput: type-specific inputs New data layer: - settingsCategories.ts: maps all settings keys to 13 categories with display order, exported constants, and subcategory map for Content Blocks - fieldTypes.ts: getFieldType() and serializeValue() utilities; ENUM_OPTIONS definitions - fieldTypeMessages.ts: i18n messages for enum labels and field placeholders - types.ts: shared TypeScript interfaces (SettingData, SettingEntry, SetEditedSettings) Modified: - SettingCard.tsx: renders type-specific input components instead of a single generic field; passes displayName as aria-label for accessibility - AdvancedSettings.tsx: groups settings via groupSettingsByCategory(), renders one SettingsSection per category; data layer (React Query, API calls, selectors) untouched - AdvancedSettings.scss: styles for section headers, collapsible triggers, subcategory labels Not modified: Redux store, API layer, thunks, selectors, routing. --- package-lock.json | 22 + package.json | 1 + .../AdvancedSettings.test.tsx | 78 ++-- src/advanced-settings/AdvancedSettings.tsx | 125 +++--- .../data/fieldTypeMessages.ts | 410 ++++++++++++++++++ src/advanced-settings/data/fieldTypes.test.ts | 97 +++++ src/advanced-settings/data/fieldTypes.ts | 157 +++++++ .../data/settingsCategories.test.ts | 96 ++++ .../data/settingsCategories.ts | 199 +++++++++ src/advanced-settings/data/types.ts | 18 + .../scss/AdvancedSettings.scss | 90 +++- .../setting-card/SettingCard.test.jsx | 20 +- .../setting-card/SettingCard.tsx | 228 +++++++--- .../setting-card/inputs/BooleanInput.test.tsx | 36 ++ .../setting-card/inputs/BooleanInput.tsx | 22 + .../setting-card/inputs/EnumInput.test.tsx | 39 ++ .../setting-card/inputs/EnumInput.tsx | 40 ++ .../setting-card/inputs/JsonInput.test.tsx | 104 +++++ .../setting-card/inputs/JsonInput.tsx | 80 ++++ .../setting-card/inputs/NumberInput.test.tsx | 59 +++ .../setting-card/inputs/NumberInput.tsx | 37 ++ .../setting-card/inputs/StringInput.test.tsx | 51 +++ .../setting-card/inputs/StringInput.tsx | 26 ++ .../settings-filters/SettingsFilters.test.tsx | 79 ++++ .../settings-filters/SettingsFilters.tsx | 58 +++ .../settings-filters/messages.ts | 41 ++ .../CourseDisplayOverrides.test.tsx | 112 +++++ .../CourseDisplayOverrides.tsx | 128 ++++++ .../settings-section/SettingsSection.test.tsx | 102 +++++ .../settings-section/SettingsSection.tsx | 203 +++++++++ .../settings-section/messages.ts | 116 +++++ 31 files changed, 2688 insertions(+), 186 deletions(-) create mode 100644 src/advanced-settings/data/fieldTypeMessages.ts create mode 100644 src/advanced-settings/data/fieldTypes.test.ts create mode 100644 src/advanced-settings/data/fieldTypes.ts create mode 100644 src/advanced-settings/data/settingsCategories.test.ts create mode 100644 src/advanced-settings/data/settingsCategories.ts create mode 100644 src/advanced-settings/data/types.ts create mode 100644 src/advanced-settings/setting-card/inputs/BooleanInput.test.tsx create mode 100644 src/advanced-settings/setting-card/inputs/BooleanInput.tsx create mode 100644 src/advanced-settings/setting-card/inputs/EnumInput.test.tsx create mode 100644 src/advanced-settings/setting-card/inputs/EnumInput.tsx create mode 100644 src/advanced-settings/setting-card/inputs/JsonInput.test.tsx create mode 100644 src/advanced-settings/setting-card/inputs/JsonInput.tsx create mode 100644 src/advanced-settings/setting-card/inputs/NumberInput.test.tsx create mode 100644 src/advanced-settings/setting-card/inputs/NumberInput.tsx create mode 100644 src/advanced-settings/setting-card/inputs/StringInput.test.tsx create mode 100644 src/advanced-settings/setting-card/inputs/StringInput.tsx create mode 100644 src/advanced-settings/settings-filters/SettingsFilters.test.tsx create mode 100644 src/advanced-settings/settings-filters/SettingsFilters.tsx create mode 100644 src/advanced-settings/settings-filters/messages.ts create mode 100644 src/advanced-settings/settings-section/CourseDisplayOverrides.test.tsx create mode 100644 src/advanced-settings/settings-section/CourseDisplayOverrides.tsx create mode 100644 src/advanced-settings/settings-section/SettingsSection.test.tsx create mode 100644 src/advanced-settings/settings-section/SettingsSection.tsx create mode 100644 src/advanced-settings/settings-section/messages.ts diff --git a/package-lock.json b/package-lock.json index 434bfcbc07..9c4d20beab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "AGPL-3.0", "dependencies": { "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-json": "^6.0.2", "@codemirror/lang-markdown": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lint": "^6.2.1", @@ -2263,6 +2264,16 @@ "@lezer/javascript": "^1.0.0" } }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, "node_modules/@codemirror/lang-markdown": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", @@ -5231,6 +5242,17 @@ "@lezer/lr": "^1.3.0" } }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@lezer/lr": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.8.tgz", diff --git a/package.json b/package.json index ddc79a196c..35d1cb62fd 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-json": "^6.0.2", "@codemirror/lang-markdown": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lint": "^6.2.1", diff --git a/src/advanced-settings/AdvancedSettings.test.tsx b/src/advanced-settings/AdvancedSettings.test.tsx index 8b9d73aa70..ceabd89fc2 100644 --- a/src/advanced-settings/AdvancedSettings.test.tsx +++ b/src/advanced-settings/AdvancedSettings.test.tsx @@ -12,24 +12,27 @@ import { advancedSettingsMock } from './__mocks__'; import { getCourseAdvancedSettingsApiUrl } from './data/api'; import AdvancedSettings from './AdvancedSettings'; import messages from './messages'; - -let axiosMock; -const mockPathname = '/foo-bar'; -const courseId = '123'; - -// Mock the TextareaAutosize component -jest.mock('react-textarea-autosize', () => - jest.fn((props) => ( -