more-compute 0.1.3__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- frontend/app/globals.css +322 -77
- frontend/app/layout.tsx +98 -82
- frontend/components/Cell.tsx +234 -95
- frontend/components/Notebook.tsx +430 -199
- frontend/components/{AddCellButton.tsx → cell/AddCellButton.tsx} +0 -2
- frontend/components/cell/MonacoCell.tsx +726 -0
- frontend/components/layout/ConnectionBanner.tsx +41 -0
- frontend/components/{Sidebar.tsx → layout/Sidebar.tsx} +16 -11
- frontend/components/modals/ConfirmModal.tsx +154 -0
- frontend/components/modals/SuccessModal.tsx +140 -0
- frontend/components/output/MarkdownRenderer.tsx +116 -0
- frontend/components/popups/ComputePopup.tsx +674 -365
- frontend/components/popups/MetricsPopup.tsx +11 -7
- frontend/components/popups/SettingsPopup.tsx +11 -13
- frontend/contexts/PodWebSocketContext.tsx +247 -0
- frontend/eslint.config.mjs +11 -0
- frontend/lib/monaco-themes.ts +160 -0
- frontend/lib/settings.ts +128 -26
- frontend/lib/themes.json +9973 -0
- frontend/lib/websocket-native.ts +19 -8
- frontend/lib/websocket.ts +59 -11
- frontend/next.config.ts +8 -0
- frontend/package-lock.json +1705 -3
- frontend/package.json +8 -1
- frontend/styling_README.md +18 -0
- kernel_run.py +161 -43
- more_compute-0.2.0.dist-info/METADATA +126 -0
- more_compute-0.2.0.dist-info/RECORD +100 -0
- morecompute/__version__.py +1 -0
- morecompute/execution/executor.py +31 -20
- morecompute/execution/worker.py +68 -7
- morecompute/models/__init__.py +31 -0
- morecompute/models/api_models.py +197 -0
- morecompute/notebook.py +50 -7
- morecompute/server.py +574 -94
- morecompute/services/data_manager.py +379 -0
- morecompute/services/lsp_service.py +335 -0
- morecompute/services/pod_manager.py +122 -20
- morecompute/services/pod_monitor.py +138 -0
- morecompute/services/prime_intellect.py +87 -63
- morecompute/utils/config_util.py +59 -0
- morecompute/utils/special_commands.py +11 -5
- morecompute/utils/zmq_util.py +51 -0
- frontend/components/MarkdownRenderer.tsx +0 -84
- frontend/components/popups/PythonPopup.tsx +0 -292
- more_compute-0.1.3.dist-info/METADATA +0 -173
- more_compute-0.1.3.dist-info/RECORD +0 -85
- /frontend/components/{CellButton.tsx → cell/CellButton.tsx} +0 -0
- /frontend/components/{ErrorModal.tsx → modals/ErrorModal.tsx} +0 -0
- /frontend/components/{CellOutput.tsx → output/CellOutput.tsx} +0 -0
- /frontend/components/{ErrorDisplay.tsx → output/ErrorDisplay.tsx} +0 -0
- {more_compute-0.1.3.dist-info → more_compute-0.2.0.dist-info}/WHEEL +0 -0
- {more_compute-0.1.3.dist-info → more_compute-0.2.0.dist-info}/entry_points.txt +0 -0
- {more_compute-0.1.3.dist-info → more_compute-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {more_compute-0.1.3.dist-info → more_compute-0.2.0.dist-info}/top_level.txt +0 -0
frontend/components/Cell.tsx
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
/**
|
|
2
|
+
* LEGACY COMPONENT - NO LONGER USED
|
|
3
|
+
*
|
|
4
|
+
* This component has been replaced by MonacoCell.tsx which provides:
|
|
5
|
+
* - Modern Monaco Editor (VSCode engine)
|
|
6
|
+
* - LSP support for Python autocomplete and hover
|
|
7
|
+
* - Better performance and features
|
|
8
|
+
*
|
|
9
|
+
* Kept for reference only. Do not use in new code.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
"use client";
|
|
13
|
+
|
|
14
|
+
import React, { useRef, useEffect, useState } from "react";
|
|
15
|
+
import { Cell as CellType } from "@/types/notebook";
|
|
16
|
+
import CellOutput from "./output/CellOutput";
|
|
17
|
+
import AddCellButton from "./cell/AddCellButton";
|
|
18
|
+
import MarkdownRenderer from "./output/MarkdownRenderer";
|
|
19
|
+
import CellButton from "./cell/CellButton";
|
|
20
|
+
import {
|
|
21
|
+
UpdateIcon,
|
|
22
|
+
LinkBreak2Icon,
|
|
23
|
+
PlayIcon,
|
|
24
|
+
ChevronUpIcon,
|
|
25
|
+
ChevronDownIcon,
|
|
26
|
+
} from "@radix-ui/react-icons";
|
|
27
|
+
import { Check, X } from "lucide-react";
|
|
28
|
+
import { fixIndentation } from "@/lib/api";
|
|
12
29
|
|
|
13
30
|
declare const CodeMirror: any;
|
|
14
31
|
|
|
15
32
|
interface CellProps {
|
|
16
33
|
cell: CellType;
|
|
17
34
|
index: number;
|
|
35
|
+
totalCells: number;
|
|
18
36
|
isActive: boolean;
|
|
19
37
|
isExecuting: boolean;
|
|
20
38
|
onExecute: (index: number) => void;
|
|
@@ -22,12 +40,15 @@ interface CellProps {
|
|
|
22
40
|
onDelete: (index: number) => void;
|
|
23
41
|
onUpdate: (index: number, source: string) => void;
|
|
24
42
|
onSetActive: (index: number) => void;
|
|
25
|
-
onAddCell: (type:
|
|
43
|
+
onAddCell: (type: "code" | "markdown", index: number) => void;
|
|
44
|
+
onMoveUp: (index: number) => void;
|
|
45
|
+
onMoveDown: (index: number) => void;
|
|
26
46
|
}
|
|
27
47
|
|
|
28
48
|
export const Cell: React.FC<CellProps> = ({
|
|
29
49
|
cell,
|
|
30
50
|
index,
|
|
51
|
+
totalCells,
|
|
31
52
|
isActive,
|
|
32
53
|
isExecuting,
|
|
33
54
|
onExecute,
|
|
@@ -36,38 +57,107 @@ export const Cell: React.FC<CellProps> = ({
|
|
|
36
57
|
onUpdate,
|
|
37
58
|
onSetActive,
|
|
38
59
|
onAddCell,
|
|
60
|
+
onMoveUp,
|
|
61
|
+
onMoveDown,
|
|
39
62
|
}) => {
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// REFS
|
|
65
|
+
// ============================================================================
|
|
40
66
|
const editorRef = useRef<HTMLTextAreaElement>(null);
|
|
41
|
-
const codeMirrorInstance = useRef<
|
|
42
|
-
|
|
67
|
+
const codeMirrorInstance = useRef<{
|
|
68
|
+
setValue: (value: string) => void;
|
|
69
|
+
toTextArea: () => void;
|
|
70
|
+
getValue: () => string;
|
|
71
|
+
} | null>(null);
|
|
72
|
+
const wasEditingMarkdown = useRef(false);
|
|
43
73
|
const indexRef = useRef<number>(index);
|
|
44
|
-
|
|
74
|
+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
45
75
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// STATE
|
|
78
|
+
// ============================================================================
|
|
79
|
+
const [isEditing, setIsEditing] = useState(
|
|
80
|
+
() => cell.cell_type === "code" || !cell.source?.trim()
|
|
81
|
+
);
|
|
82
|
+
const [elapsedLabel, setElapsedLabel] = useState<string | null>(
|
|
83
|
+
cell.execution_time ?? null
|
|
84
|
+
);
|
|
49
85
|
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// UTILITIES
|
|
88
|
+
// ============================================================================
|
|
50
89
|
const formatMs = (ms: number): string => {
|
|
51
90
|
if (ms < 1000) return `${ms.toFixed(0)}ms`;
|
|
52
91
|
if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
|
|
53
92
|
const totalSeconds = Math.floor(ms / 1000);
|
|
54
93
|
const minutes = Math.floor(totalSeconds / 60);
|
|
55
94
|
const seconds = totalSeconds % 60;
|
|
56
|
-
return `${minutes}:${seconds.toString().padStart(2,
|
|
95
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}s`;
|
|
57
96
|
};
|
|
58
97
|
|
|
59
98
|
const parseExecTime = (s?: string | null): number | null => {
|
|
60
99
|
if (!s) return null;
|
|
61
|
-
|
|
62
|
-
if (s.endsWith(
|
|
63
|
-
if (s.endsWith('s')) return parseFloat(s.replace('s', '')) * 1000;
|
|
100
|
+
if (s.endsWith("ms")) return parseFloat(s.replace("ms", ""));
|
|
101
|
+
if (s.endsWith("s")) return parseFloat(s.replace("s", "")) * 1000;
|
|
64
102
|
return null;
|
|
65
103
|
};
|
|
66
104
|
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// COMPUTED VALUES
|
|
107
|
+
// ============================================================================
|
|
108
|
+
const isMarkdownWithContent =
|
|
109
|
+
cell.cell_type === "markdown" && !isEditing && cell.source?.trim();
|
|
110
|
+
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// HANDLERS
|
|
113
|
+
// ============================================================================
|
|
114
|
+
const handleExecute = () => {
|
|
115
|
+
if (cell.cell_type === "markdown") {
|
|
116
|
+
onExecute(indexRef.current);
|
|
117
|
+
setIsEditing(false);
|
|
118
|
+
} else {
|
|
119
|
+
if (isExecuting) {
|
|
120
|
+
onInterrupt(indexRef.current);
|
|
121
|
+
} else {
|
|
122
|
+
onExecute(indexRef.current);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const handleCellClick = () => {
|
|
128
|
+
onSetActive(indexRef.current);
|
|
129
|
+
if (cell.cell_type === "markdown") {
|
|
130
|
+
setIsEditing(true);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleFixIndentation = async () => {
|
|
135
|
+
try {
|
|
136
|
+
const fixedCode = await fixIndentation(cell.source);
|
|
137
|
+
onUpdate(indexRef.current, fixedCode);
|
|
138
|
+
|
|
139
|
+
if (codeMirrorInstance.current) {
|
|
140
|
+
codeMirrorInstance.current.setValue(fixedCode);
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.error("Failed to fix indentation:", err);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// EFFECTS
|
|
149
|
+
// ============================================================================
|
|
150
|
+
|
|
151
|
+
// Keep indexRef in sync
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
indexRef.current = index;
|
|
154
|
+
}, [index]);
|
|
155
|
+
|
|
156
|
+
// Execution timer
|
|
67
157
|
useEffect(() => {
|
|
68
158
|
if (isExecuting) {
|
|
69
159
|
const start = Date.now();
|
|
70
|
-
setElapsedLabel(
|
|
160
|
+
setElapsedLabel("0ms");
|
|
71
161
|
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
72
162
|
intervalRef.current = setInterval(() => {
|
|
73
163
|
setElapsedLabel(formatMs(Date.now() - start));
|
|
@@ -77,10 +167,10 @@ export const Cell: React.FC<CellProps> = ({
|
|
|
77
167
|
clearInterval(intervalRef.current);
|
|
78
168
|
intervalRef.current = null;
|
|
79
169
|
}
|
|
80
|
-
// Persist final time from cell.execution_time if available
|
|
81
170
|
const ms = parseExecTime(cell.execution_time as any);
|
|
82
171
|
if (ms != null) setElapsedLabel(formatMs(ms));
|
|
83
172
|
}
|
|
173
|
+
|
|
84
174
|
return () => {
|
|
85
175
|
if (intervalRef.current) {
|
|
86
176
|
clearInterval(intervalRef.current);
|
|
@@ -88,30 +178,64 @@ export const Cell: React.FC<CellProps> = ({
|
|
|
88
178
|
}
|
|
89
179
|
};
|
|
90
180
|
}, [isExecuting, cell.execution_time]);
|
|
91
|
-
const [isEditing, setIsEditing] = useState(() => cell.cell_type === 'code' || !cell.source?.trim());
|
|
92
181
|
|
|
93
|
-
//
|
|
94
|
-
|
|
182
|
+
// Track when user is editing markdown (for auto-save on click away)
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
if (isActive && cell.cell_type === "markdown" && isEditing) {
|
|
185
|
+
wasEditingMarkdown.current = true;
|
|
186
|
+
}
|
|
187
|
+
}, [isActive, cell.cell_type]);
|
|
95
188
|
|
|
189
|
+
// Auto-save markdown when user clicks away
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
if (
|
|
192
|
+
!isActive &&
|
|
193
|
+
wasEditingMarkdown.current &&
|
|
194
|
+
cell.cell_type === "markdown"
|
|
195
|
+
) {
|
|
196
|
+
if (cell.source?.trim()) {
|
|
197
|
+
onExecute(indexRef.current);
|
|
198
|
+
setIsEditing(false);
|
|
199
|
+
}
|
|
200
|
+
wasEditingMarkdown.current = false;
|
|
201
|
+
}
|
|
202
|
+
}, [isActive, cell.cell_type]);
|
|
203
|
+
|
|
204
|
+
// CodeMirror editor initialization and cleanup
|
|
96
205
|
useEffect(() => {
|
|
97
206
|
if (isEditing) {
|
|
98
|
-
if (
|
|
207
|
+
if (
|
|
208
|
+
!codeMirrorInstance.current &&
|
|
209
|
+
editorRef.current &&
|
|
210
|
+
typeof CodeMirror !== "undefined"
|
|
211
|
+
) {
|
|
99
212
|
const editor = CodeMirror.fromTextArea(editorRef.current, {
|
|
100
|
-
mode: cell.cell_type ===
|
|
101
|
-
lineNumbers: cell.cell_type ===
|
|
102
|
-
theme:
|
|
213
|
+
mode: cell.cell_type === "code" ? "python" : "text/plain",
|
|
214
|
+
lineNumbers: cell.cell_type === "code",
|
|
215
|
+
theme: "default",
|
|
103
216
|
lineWrapping: true,
|
|
104
|
-
placeholder:
|
|
217
|
+
placeholder:
|
|
218
|
+
cell.cell_type === "code" ? "Enter code..." : "Enter markdown...",
|
|
105
219
|
});
|
|
106
220
|
codeMirrorInstance.current = editor;
|
|
107
221
|
|
|
108
|
-
editor.on(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
222
|
+
editor.on("change", (instance: any) =>
|
|
223
|
+
onUpdate(indexRef.current, instance.getValue())
|
|
224
|
+
);
|
|
225
|
+
editor.on("focus", () => onSetActive(indexRef.current));
|
|
226
|
+
editor.on("blur", () => {
|
|
227
|
+
if (cell.cell_type === "markdown") {
|
|
228
|
+
if (cell.source?.trim()) {
|
|
229
|
+
// Auto-save on blur
|
|
230
|
+
onExecute(indexRef.current);
|
|
231
|
+
setIsEditing(false);
|
|
232
|
+
}
|
|
233
|
+
// If empty, stay in editing mode but mark as no longer editing
|
|
234
|
+
wasEditingMarkdown.current = false;
|
|
235
|
+
}
|
|
112
236
|
});
|
|
113
|
-
editor.on(
|
|
114
|
-
if (event.shiftKey && event.key ===
|
|
237
|
+
editor.on("keydown", (instance: any, event: KeyboardEvent) => {
|
|
238
|
+
if (event.shiftKey && event.key === "Enter") {
|
|
115
239
|
event.preventDefault();
|
|
116
240
|
handleExecute();
|
|
117
241
|
}
|
|
@@ -129,42 +253,12 @@ export const Cell: React.FC<CellProps> = ({
|
|
|
129
253
|
}
|
|
130
254
|
}, [isEditing, cell.source]);
|
|
131
255
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
setIsEditing(false);
|
|
136
|
-
} else {
|
|
137
|
-
if (isExecuting) {
|
|
138
|
-
onInterrupt(indexRef.current);
|
|
139
|
-
} else {
|
|
140
|
-
onExecute(indexRef.current);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const handleCellClick = () => {
|
|
146
|
-
onSetActive(indexRef.current);
|
|
147
|
-
if (cell.cell_type === 'markdown') {
|
|
148
|
-
setIsEditing(true);
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const handleFixIndentation = async () => {
|
|
153
|
-
try {
|
|
154
|
-
const fixedCode = await fixIndentation(cell.source);
|
|
155
|
-
onUpdate(indexRef.current, fixedCode);
|
|
156
|
-
|
|
157
|
-
// Update CodeMirror if it's initialized
|
|
158
|
-
if (codeMirrorInstance.current) {
|
|
159
|
-
codeMirrorInstance.current.setValue(fixedCode);
|
|
160
|
-
}
|
|
161
|
-
} catch (err) {
|
|
162
|
-
console.error('Failed to fix indentation:', err);
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
256
|
+
// ============================================================================
|
|
257
|
+
// RENDER
|
|
258
|
+
// ============================================================================
|
|
166
259
|
return (
|
|
167
260
|
<div className="cell-wrapper">
|
|
261
|
+
{/* Status Indicator */}
|
|
168
262
|
{!isMarkdownWithContent && (
|
|
169
263
|
<div className="cell-status-indicator">
|
|
170
264
|
<span className="status-indicator">
|
|
@@ -176,68 +270,113 @@ export const Cell: React.FC<CellProps> = ({
|
|
|
176
270
|
) : cell.execution_count != null ? (
|
|
177
271
|
<Check size={14} color="#16a34a" />
|
|
178
272
|
) : (
|
|
179
|
-
<span
|
|
273
|
+
<span
|
|
274
|
+
style={{
|
|
275
|
+
width: "14px",
|
|
276
|
+
height: "14px",
|
|
277
|
+
display: "inline-block",
|
|
278
|
+
}}
|
|
279
|
+
></span>
|
|
180
280
|
)}
|
|
181
281
|
<span className="status-bracket">]</span>
|
|
182
282
|
</span>
|
|
183
283
|
{elapsedLabel && (
|
|
184
|
-
<span className="status-timer" title="Execution time">
|
|
284
|
+
<span className="status-timer" title="Execution time">
|
|
285
|
+
{elapsedLabel}
|
|
286
|
+
</span>
|
|
185
287
|
)}
|
|
186
288
|
</div>
|
|
187
289
|
)}
|
|
290
|
+
|
|
291
|
+
{/* Add Cell Above Button */}
|
|
188
292
|
<div className="add-cell-line add-line-above">
|
|
189
293
|
<AddCellButton onAddCell={(type) => onAddCell(type, indexRef.current)} />
|
|
190
294
|
</div>
|
|
191
295
|
|
|
296
|
+
{/* Main Cell Container */}
|
|
192
297
|
<div
|
|
193
|
-
className={`cell ${isActive ?
|
|
298
|
+
className={`cell ${isActive ? "active" : ""} ${isExecuting ? "executing" : ""} ${isMarkdownWithContent ? "markdown-display-mode" : ""}`}
|
|
194
299
|
data-cell-index={index}
|
|
195
300
|
>
|
|
196
|
-
{/*
|
|
301
|
+
{/* Hover Controls */}
|
|
197
302
|
{!isMarkdownWithContent && (
|
|
198
303
|
<div className="cell-hover-controls">
|
|
199
304
|
<div className="cell-actions-right">
|
|
200
305
|
<CellButton
|
|
201
|
-
icon={
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
306
|
+
icon={<PlayIcon className="w-6 h-6" />}
|
|
307
|
+
onClick={(e) => {
|
|
308
|
+
e.stopPropagation();
|
|
309
|
+
handleExecute();
|
|
310
|
+
}}
|
|
205
311
|
title={isExecuting ? "Stop execution" : "Run cell"}
|
|
206
312
|
isLoading={isExecuting}
|
|
207
313
|
/>
|
|
208
314
|
<CellButton
|
|
209
|
-
icon={
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
315
|
+
icon={<ChevronUpIcon className="w-6 h-6" />}
|
|
316
|
+
onClick={(e) => {
|
|
317
|
+
e.stopPropagation();
|
|
318
|
+
onMoveUp(indexRef.current);
|
|
319
|
+
}}
|
|
320
|
+
title="Move cell up"
|
|
321
|
+
disabled={index === 0}
|
|
322
|
+
/>
|
|
323
|
+
<CellButton
|
|
324
|
+
icon={<ChevronDownIcon className="w-6 h-6" />}
|
|
325
|
+
onClick={(e) => {
|
|
326
|
+
e.stopPropagation();
|
|
327
|
+
onMoveDown(indexRef.current);
|
|
328
|
+
}}
|
|
329
|
+
title="Move cell down"
|
|
330
|
+
disabled={index === totalCells - 1}
|
|
213
331
|
/>
|
|
214
332
|
<CellButton
|
|
215
|
-
icon={
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
333
|
+
icon={<LinkBreak2Icon className="w-5 h-5" />}
|
|
334
|
+
onClick={(e) => {
|
|
335
|
+
e.stopPropagation();
|
|
336
|
+
onDelete(indexRef.current);
|
|
337
|
+
}}
|
|
219
338
|
title="Delete cell"
|
|
220
339
|
/>
|
|
221
340
|
</div>
|
|
222
341
|
</div>
|
|
223
342
|
)}
|
|
224
343
|
|
|
225
|
-
|
|
344
|
+
{/* Cell Content */}
|
|
345
|
+
<div
|
|
346
|
+
className={`cell-content ${isMarkdownWithContent ? "cursor-pointer" : ""}`}
|
|
347
|
+
onClick={handleCellClick}
|
|
348
|
+
>
|
|
226
349
|
<div className="cell-input">
|
|
227
|
-
{isEditing || cell.cell_type ===
|
|
228
|
-
<div
|
|
229
|
-
|
|
350
|
+
{isEditing || cell.cell_type === "code" ? (
|
|
351
|
+
<div
|
|
352
|
+
className={`cell-editor-container ${cell.cell_type === "markdown" ? "markdown-editor-container" : "code-editor-container"}`}
|
|
353
|
+
>
|
|
354
|
+
<textarea
|
|
355
|
+
ref={editorRef}
|
|
356
|
+
defaultValue={cell.source}
|
|
357
|
+
className={`cell-editor ${cell.cell_type === "markdown" ? "markdown-editor" : "code-editor"}`}
|
|
358
|
+
/>
|
|
230
359
|
</div>
|
|
231
360
|
) : (
|
|
232
|
-
<MarkdownRenderer
|
|
361
|
+
<MarkdownRenderer
|
|
362
|
+
source={cell.source}
|
|
363
|
+
onClick={() => setIsEditing(true)}
|
|
364
|
+
/>
|
|
233
365
|
)}
|
|
234
366
|
</div>
|
|
235
|
-
<CellOutput
|
|
367
|
+
<CellOutput
|
|
368
|
+
outputs={cell.outputs}
|
|
369
|
+
error={cell.error}
|
|
370
|
+
onFixIndentation={handleFixIndentation}
|
|
371
|
+
/>
|
|
236
372
|
</div>
|
|
237
373
|
</div>
|
|
238
374
|
|
|
375
|
+
{/* Add Cell Below Button */}
|
|
239
376
|
<div className="add-cell-line add-line-below">
|
|
240
|
-
<AddCellButton
|
|
377
|
+
<AddCellButton
|
|
378
|
+
onAddCell={(type) => onAddCell(type, indexRef.current + 1)}
|
|
379
|
+
/>
|
|
241
380
|
</div>
|
|
242
381
|
</div>
|
|
243
382
|
);
|