agent-ecosystem/src/renderer/components/team/dialogs/MembersJsonEditor.tsx
iliya 7019bf6114 feat: add team restoration and permanent deletion features
- Implemented functionality for restoring soft-deleted teams and permanently deleting teams from the system.
- Introduced new IPC channels for team restoration and permanent deletion, enhancing team management capabilities.
- Updated TeamDataService and related components to handle the new operations, ensuring data integrity during team management.
- Enhanced UI components to support team restoration and deletion actions, improving user experience and management workflows.
2026-02-26 12:15:47 +02:00

96 lines
2.7 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
import { json } from '@codemirror/lang-json';
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { EditorState } from '@codemirror/state';
import { oneDark } from '@codemirror/theme-one-dark';
import { EditorView, keymap, lineNumbers } from '@codemirror/view';
interface MembersJsonEditorProps {
value: string;
onChange: (json: string) => void;
error: string | null;
}
export const MembersJsonEditor = ({
value,
onChange,
error,
}: MembersJsonEditorProps): React.JSX.Element => {
const containerRef = useRef<HTMLDivElement>(null);
const viewRef = useRef<EditorView | null>(null);
const onChangeRef = useRef(onChange);
onChangeRef.current = onChange;
useEffect(() => {
if (!containerRef.current) return;
const state = EditorState.create({
doc: value,
extensions: [
json(),
oneDark,
lineNumbers(),
history(),
bracketMatching(),
closeBrackets(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
keymap.of([...defaultKeymap, ...historyKeymap, ...closeBracketsKeymap]),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
onChangeRef.current(update.state.doc.toString());
}
}),
EditorView.theme({
'&': {
fontSize: '12px',
maxHeight: '300px',
},
'.cm-scroller': {
overflow: 'auto',
},
'.cm-content': {
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
},
}),
],
});
const view = new EditorView({
state,
parent: containerRef.current,
});
viewRef.current = view;
return () => {
view.destroy();
viewRef.current = null;
};
// eslint-disable-next-line react-hooks/exhaustive-deps -- EditorView created once on mount
}, []);
useEffect(() => {
const view = viewRef.current;
if (!view) return;
const currentDoc = view.state.doc.toString();
if (currentDoc !== value) {
view.dispatch({
changes: { from: 0, to: currentDoc.length, insert: value },
});
}
}, [value]);
return (
<div className="space-y-1">
<div
ref={containerRef}
className="overflow-hidden rounded border border-[var(--color-border)]"
/>
{error ? <p className="text-[11px] text-red-300">{error}</p> : null}
</div>
);
};