Skip to content

Commit c898804

Browse files
full screen IDE for job editing (#3800)
* initial * panels * Fix padding * styles * chevron * Fix inspector footer layout to properly position Edit and Delete buttons - Move Edit button to leftButtons prop in JobInspector - Move Delete button to rightButtons prop in JobInspector - Remove justify-end from InspectorLayout footer wrapper that was overriding InspectorFooter's justify-between - Remove border and padding from InspectorFooter (handled by parent) - Buttons now properly space apart with Edit on left, Delete on right * Add Escape key shortcut to close full-screen IDE - Add useHotkeys and useHotkeysContext imports - Create "ide" scope that's enabled when IDE is open - Handle Escape key to call onClose() - Enable Escape in Monaco editor via enableOnFormTags - Update component documentation to mention keyboard shortcut - Follow same pattern as InspectorLayout for scope management --------- Co-authored-by: Stuart Corbishley <corbish@gmail.com>
1 parent 5c19590 commit c898804

File tree

11 files changed

+577
-96
lines changed

11 files changed

+577
-96
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to
1717

1818
### Added
1919

20+
- Added full-screen IDE for job editing
21+
[#3708](https://github.com/OpenFn/lightning/issues/3708)
2022
- Show collaborative editor toggle (beaker icon) when creating new workflows
2123
[#3797](https://github.com/OpenFn/lightning/pull/3797)
2224
- Auto-format code on commit with git hooks

assets/js/collaborative-editor/components/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function Header({
186186
>
187187
<span className="hero-signal-slash w-6 h-6 mr-2 text-red-500"></span>
188188
</div>
189-
<div className="relative">
189+
<div className="relative flex gap-2">
190190
{projectId && workflowId && (
191191
<RunButton projectId={projectId} workflowId={workflowId} />
192192
)}

assets/js/collaborative-editor/components/WorkflowEditor.tsx

Lines changed: 50 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,22 @@ import { useState } from "react";
66

77
import { useURLState } from "../../react/lib/use-url-state";
88
import type { WorkflowState as YAMLWorkflowState } from "../../yaml/types";
9-
import { useSession } from "../hooks/useSession";
109
import { useIsNewWorkflow } from "../hooks/useSessionContext";
1110
import {
12-
useCurrentJob,
1311
useNodeSelection,
1412
useWorkflowActions,
1513
useWorkflowState,
1614
useWorkflowStoreContext,
1715
} from "../hooks/useWorkflow";
1816

19-
import { CollaborativeMonaco } from "./CollaborativeMonaco";
2017
import { CollaborativeWorkflowDiagram } from "./diagram/CollaborativeWorkflowDiagram";
18+
import { FullScreenIDE } from "./ide/FullScreenIDE";
2119
import { Inspector } from "./inspector";
2220
import { LeftPanel } from "./left-panel";
2321

2422
export function WorkflowEditor() {
2523
const { hash, searchParams, updateSearchParams } = useURLState();
26-
const { job: currentJob, ytext: currentJobYText } = useCurrentJob();
2724
const { currentNode, selectNode } = useNodeSelection();
28-
const { awareness } = useSession();
2925
const workflowStore = useWorkflowStoreContext();
3026
const isNewWorkflow = useIsNewWorkflow();
3127
const { saveWorkflow } = useWorkflowActions();
@@ -55,6 +51,10 @@ export function WorkflowEditor() {
5551
// Default to template method if no method specified and panel is open
5652
const leftPanelMethod = showLeftPanel ? currentMethod || "template" : null;
5753

54+
// Check if IDE should be open
55+
const isIDEOpen = searchParams.get("editor") === "open";
56+
const selectedJobId = searchParams.get("job");
57+
5858
const handleCloseInspector = () => {
5959
selectNode(null);
6060
};
@@ -90,81 +90,58 @@ export function WorkflowEditor() {
9090
handleCloseLeftPanel();
9191
};
9292

93+
const handleCloseIDE = () => {
94+
updateSearchParams({ editor: null });
95+
};
96+
9397
return (
9498
<div className="relative flex h-full w-full">
95-
{/* Main content area - flex grows to fill remaining space */}
96-
<div
97-
className={`flex-1 relative transition-all duration-300 ease-in-out ${
98-
showLeftPanel ? "ml-[33.333333%]" : "ml-0"
99-
}`}
100-
>
101-
<CollaborativeWorkflowDiagram inspectorId="inspector" />
102-
103-
{/* Inspector slides in from the right and appears on top
104-
This div is also the wrapper which is used to calculate the overlap
105-
between the inspector and the diagram. */}
106-
{workflow && (
99+
{/* Canvas and Inspector - hidden when IDE open */}
100+
{!isIDEOpen && (
101+
<>
102+
{/* Main content area - flex grows to fill remaining space */}
107103
<div
108-
id="inspector"
109-
className={`absolute top-0 right-0 h-full transition-transform duration-300 ease-in-out ${
110-
showInspector
111-
? "translate-x-0"
112-
: "translate-x-full pointer-events-none"
104+
className={`flex-1 relative transition-all duration-300 ease-in-out ${
105+
showLeftPanel ? "ml-[33.333333%]" : "ml-0"
113106
}`}
114107
>
115-
<Inspector
116-
workflow={workflow}
117-
currentNode={currentNode}
118-
onClose={handleCloseInspector}
119-
/>
120-
</div>
121-
)}
122-
</div>
123-
124-
{/* Left Panel - Workflow creation methods (absolute positioned, slides over) */}
125-
<LeftPanel
126-
method={leftPanelMethod}
127-
onMethodChange={handleMethodChange}
128-
onImport={handleImport}
129-
onClosePanel={handleCloseLeftPanel}
130-
onSave={handleSaveAndClose}
131-
/>
132-
133-
{false && ( // Leaving this here for now, but we'll remove/replace it in the future
134-
<div className="flex flex-col h-full">
135-
{/* Main Content */}
136-
137-
{/* Right Panel - Split vertically */}
138-
<div className="flex-1 min-w-0 flex flex-col overflow-y-auto">
139-
{/* Workflow Diagram */}
140-
<div className="flex-none h-1/3 border-b border-gray-200">
141-
<CollaborativeWorkflowDiagram />
142-
</div>
143-
144-
{/* Bottom Right - Monaco Editor */}
145-
<div className="flex-1 min-h-0">
146-
{currentJob && currentJobYText && awareness ? (
147-
<CollaborativeMonaco
148-
ytext={currentJobYText}
149-
awareness={awareness}
150-
adaptor="common"
151-
disabled={false}
152-
className="h-full w-full"
108+
<CollaborativeWorkflowDiagram inspectorId="inspector" />
109+
110+
{/* Inspector slides in from the right and appears on top
111+
This div is also the wrapper which is used to calculate the overlap
112+
between the inspector and the diagram. */}
113+
{workflow && (
114+
<div
115+
id="inspector"
116+
className={`absolute top-0 right-0 h-full transition-transform duration-300 ease-in-out ${
117+
showInspector
118+
? "translate-x-0"
119+
: "translate-x-full pointer-events-none"
120+
}`}
121+
>
122+
<Inspector
123+
workflow={workflow}
124+
currentNode={currentNode}
125+
onClose={handleCloseInspector}
153126
/>
154-
) : (
155-
<div className="flex items-center justify-center h-full text-gray-500">
156-
<div className="text-center">
157-
<p className="text-lg">Select a job to edit</p>
158-
<p className="text-sm">
159-
Choose a job from the sidebar to start editing with the
160-
collaborative Monaco editor
161-
</p>
162-
</div>
163-
</div>
164-
)}
165-
</div>
127+
</div>
128+
)}
166129
</div>
167-
</div>
130+
131+
{/* Left Panel - Workflow creation methods (absolute positioned, slides over) */}
132+
<LeftPanel
133+
method={leftPanelMethod}
134+
onMethodChange={handleMethodChange}
135+
onImport={handleImport}
136+
onClosePanel={handleCloseLeftPanel}
137+
onSave={handleSaveAndClose}
138+
/>
139+
</>
140+
)}
141+
142+
{/* Full-Screen IDE - replaces canvas when open */}
143+
{isIDEOpen && selectedJobId && (
144+
<FullScreenIDE jobId={selectedJobId} onClose={handleCloseIDE} />
168145
)}
169146
</div>
170147
);

0 commit comments

Comments
 (0)