From 45c77fac41ee97131531253c966eba9fd3f4b8ba Mon Sep 17 00:00:00 2001 From: mehmet turac Date: Fri, 22 May 2026 11:11:01 +0300 Subject: [PATCH] fix(web): restore manual source edit tabs (#1854) * fix(web): restore manual source edit tabs * test: target active manual edit preview --- apps/web/src/components/FileViewer.tsx | 5 + apps/web/src/components/ManualEditPanel.tsx | 232 ++++++++++++++++-- apps/web/src/index.css | 26 ++ .../FileViewer.manual-edit-history.test.tsx | 64 +++++ .../tests/components/ManualEditPanel.test.tsx | 73 +++++- 5 files changed, 375 insertions(+), 25 deletions(-) diff --git a/apps/web/src/components/FileViewer.tsx b/apps/web/src/components/FileViewer.tsx index 6cca5a38bd..91468e257a 100644 --- a/apps/web/src/components/FileViewer.tsx +++ b/apps/web/src/components/FileViewer.tsx @@ -4859,6 +4859,9 @@ function HtmlViewer({ setSource(result.source); sourceRef.current = result.source; setInlinedSource(null); + if (patch.kind !== 'set-style') { + setManualEditFrozenSource(result.source); + } setManualEditHistory((current) => [entry, ...current]); setManualEditUndone([]); setManualEditDraft((current) => ({ ...current, fullSource: result.source })); @@ -4912,6 +4915,7 @@ function HtmlViewer({ setSource(latest.beforeSource); sourceRef.current = latest.beforeSource; setInlinedSource(null); + setManualEditFrozenSource(latest.beforeSource); setManualEditHistory(rest); setManualEditUndone((current) => [latest, ...current]); setManualEditDraft((current) => ({ ...current, fullSource: latest.beforeSource })); @@ -4943,6 +4947,7 @@ function HtmlViewer({ setSource(latest.afterSource); sourceRef.current = latest.afterSource; setInlinedSource(null); + setManualEditFrozenSource(latest.afterSource); setManualEditUndone(rest); setManualEditHistory((current) => [latest, ...current]); setManualEditDraft((current) => ({ ...current, fullSource: latest.afterSource })); diff --git a/apps/web/src/components/ManualEditPanel.tsx b/apps/web/src/components/ManualEditPanel.tsx index 4b960e75cf..c7c3d284d8 100644 --- a/apps/web/src/components/ManualEditPanel.tsx +++ b/apps/web/src/components/ManualEditPanel.tsx @@ -29,10 +29,11 @@ export function ManualEditPanel({ onDraftChange, onStyleChange, onInvalidStyle, + onApplyPatch, onError, onClearSelection, - onApplyPatch, onPickImage, + busy = false, pageStylesEnabled = true, }: { targets: ManualEditTarget[]; @@ -65,6 +66,10 @@ export function ManualEditPanel({ useEffect(() => { selectedTargetRef.current = selectedTarget; }, [selectedTarget]); + const [activeTab, setActiveTab] = useState('style'); + const tab = targetForInspector + ? (activeTab === 'page' ? 'style' : activeTab) + : (activeTab === 'source' ? 'source' : 'page'); const changeTargetStyle = (key: keyof ManualEditStyles, value: string) => { const nextStyles = { ...draft.styles, [key]: value }; @@ -81,31 +86,134 @@ export function ManualEditPanel({ onError(''); onStyleChange?.(targetForInspector.id, normalized.styles, `Style: ${targetForInspector.label}`); }; + const applyAttributes = () => { + if (!targetForInspector) return; + try { + const parsed = JSON.parse(draft.attributesText) as unknown; + if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') throw new Error(); + const attributes = Object.fromEntries( + Object.entries(parsed as Record).map(([key, value]) => [key, String(value)]), + ); + onError(''); + onApplyPatch({ id: targetForInspector.id, kind: 'set-attributes', attributes }, `Attributes: ${targetForInspector.label}`); + } catch { + onError('Invalid attributes JSON.'); + } + }; + const applyContent = () => { + if (!targetForInspector) return; + if (targetForInspector.kind === 'link') { + onApplyPatch({ id: targetForInspector.id, kind: 'set-link', text: draft.text, href: draft.href }, `Content: ${targetForInspector.label}`); + return; + } + if (targetForInspector.kind === 'image') { + onApplyPatch({ id: targetForInspector.id, kind: 'set-image', src: draft.src, alt: draft.alt }, `Content: ${targetForInspector.label}`); + return; + } + onApplyPatch({ id: targetForInspector.id, kind: 'set-text', value: draft.text }, `Content: ${targetForInspector.label}`); + }; return (