perf(json-editor): unify admin JSON editing experience (#6421)
* perf(json-editor): improve JSON editing experience - integrate Yace for syntax highlighting, history, indentation, auto-closing, and smart line breaks. - add copy support, cursor location feedback, and synchronized content and line-number scrolling. - extract JSON editor utilities and cover key interactions with unit tests. * perf(system-settings): improve JSON configuration editing - replace raw JSON textareas with the shared editor for highlighting, validation, copy, and formatting. - preserve field-specific examples and make placeholders visible through the transparent editor layer. - remove duplicate formatting controls while keeping existing form validation and save behavior. * perf(json-editor): standardize JSON inputs across admin settings - replace pure JSON textareas with the shared editor across system settings and channel workflows. - preserve form focus, validation, placeholders, and visual or JSON editing modes. - add happy-dom component coverage for form bindings, controlled updates, and formatting. * fix(json-code-editor): address accessibility review findings - Drop the unconditional aria-label that overrode every field's label-derived accessible name; add an optional ariaLabel prop and set it at call sites without an associated label - Associate standalone Labels via htmlFor/id in channel-affinity views - Hide the highlight mirror and line-number layers from the accessibility tree (aria-hidden) - Give the line-number gutter an opaque background so horizontally scrolled code no longer slides under it - Degrade to no scroll sync instead of destroying the editor when the line-number layer is not found
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
||||
sideDrawerFormClassName,
|
||||
sideDrawerHeaderClassName,
|
||||
} from '@/components/drawer-layout'
|
||||
import { JsonCodeEditor } from '@/components/json-code-editor'
|
||||
import { MultiSelect } from '@/components/multi-select'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
@@ -59,7 +60,6 @@ import {
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
} from '@/components/ui/sheet'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
|
||||
import {
|
||||
checkClusterNameAvailability,
|
||||
@@ -702,10 +702,14 @@ export function CreateDeploymentDrawer({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Environment variables (JSON)')}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className='min-h-24 font-mono text-xs'
|
||||
<JsonCodeEditor
|
||||
value={field.value || ''}
|
||||
onChange={field.onChange}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
textareaRef={field.ref}
|
||||
placeholder='{"KEY":"VALUE"}'
|
||||
{...field}
|
||||
heightClassName='h-40 min-h-40 max-h-40'
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
@@ -722,10 +726,14 @@ export function CreateDeploymentDrawer({
|
||||
{t('Secret environment variables (JSON)')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className='min-h-24 font-mono text-xs'
|
||||
<JsonCodeEditor
|
||||
value={field.value || ''}
|
||||
onChange={field.onChange}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
textareaRef={field.ref}
|
||||
placeholder='{"SECRET":"VALUE"}'
|
||||
{...field}
|
||||
heightClassName='h-40 min-h-40 max-h-40'
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
||||
@@ -26,6 +26,7 @@ import { toast } from 'sonner'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { Dialog } from '@/components/dialog'
|
||||
import { JsonCodeEditor } from '@/components/json-code-editor'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Collapsible,
|
||||
@@ -41,7 +42,6 @@ import {
|
||||
FormMessage,
|
||||
} from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
|
||||
import { getDeployment, updateDeployment } from '../../api'
|
||||
import { deploymentsQueryKeys } from '../../lib'
|
||||
@@ -398,10 +398,14 @@ export function UpdateConfigDialog({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Env (JSON object)')}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className='min-h-40 font-mono text-xs'
|
||||
<JsonCodeEditor
|
||||
value={field.value || ''}
|
||||
onChange={field.onChange}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
textareaRef={field.ref}
|
||||
placeholder='{"KEY":"VALUE"}'
|
||||
{...field}
|
||||
heightClassName='h-40 min-h-40 max-h-40'
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
@@ -415,10 +419,14 @@ export function UpdateConfigDialog({
|
||||
<FormItem>
|
||||
<FormLabel>{t('Secret env (JSON object)')}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className='min-h-40 font-mono text-xs'
|
||||
<JsonCodeEditor
|
||||
value={field.value || ''}
|
||||
onChange={field.onChange}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
textareaRef={field.ref}
|
||||
placeholder='{"SECRET":"VALUE"}'
|
||||
{...field}
|
||||
heightClassName='h-40 min-h-40 max-h-40'
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
||||
Reference in New Issue
Block a user