Skip to content

Commit f2e8159

Browse files
committed
+ RailsPathLinkHandler: open server when clicked on localhost:3000
Start server automatically if preview is not ready
1 parent 63fe9e1 commit f2e8159

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

patches/@tutorialkit+react+1.5.0.patch

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ index 109e4eb..4906be4 100644
1919
case 'jpg':
2020
case 'jpeg':
2121
diff --git a/node_modules/@tutorialkit/react/dist/Panels/PreviewPanel.js b/node_modules/@tutorialkit/react/dist/Panels/PreviewPanel.js
22-
index 8fe0723..46d363c 100644
22+
index 8fe0723..66a4e34 100644
2323
--- a/node_modules/@tutorialkit/react/dist/Panels/PreviewPanel.js
2424
+++ b/node_modules/@tutorialkit/react/dist/Panels/PreviewPanel.js
2525
@@ -1,7 +1,7 @@
@@ -40,7 +40,7 @@ index 8fe0723..46d363c 100644
4040
useEffect(() => {
4141
if (!iframe.ref) {
4242
return;
43-
@@ -83,16 +85,122 @@ function Preview({ preview, iframe, previewCount, first, last, toggleTerminal, i
43+
@@ -83,16 +85,123 @@ function Preview({ preview, iframe, previewCount, first, last, toggleTerminal, i
4444
iframe.ref.title = preview.title;
4545
}
4646
}, [preview.url, iframe.ref]);
@@ -128,6 +128,7 @@ index 8fe0723..46d363c 100644
128128
+ _jsx("input", {
129129
+ type: "text",
130130
+ value: urlPath,
131+
+ name: "tutorialkit-preview-navigation",
131132
+ onChange: (e) => setCurrentUrlPath(e.target.value),
132133
+ className: "bg-transparent border-none focus:outline-none text-sm flex-1",
133134
+ onKeyDown: (e) => {

src/components/RailsPathLinkHandler.tsx

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
import { useEffect } from 'react';
2+
import { useStore } from '@nanostores/react';
23
import tutorialStore from "tutorialkit:store";
4+
import { webcontainer } from 'tutorialkit:core';
5+
import type { PreviewInfo } from '@tutorialkit/runtime';
6+
7+
const ensureRailsServerStarted = async (preview: PreviewInfo) => {
8+
if (preview.ready) return;
9+
10+
const terminalConfig = tutorialStore.terminalConfig.get()
11+
const terminal = terminalConfig.panels.find(panel => panel.type === 'terminal');
12+
if (!terminal || !terminal.process) return;
13+
14+
terminal.input(`bin/rails s\n`);
15+
16+
await new Promise<void>((resolve, reject) => {
17+
const tid = setTimeout(() => {
18+
clearInterval(tick);
19+
reject();
20+
}, 10000);
21+
22+
const tick = setInterval(() => {
23+
if (preview.ready) {
24+
clearInterval(tick);
25+
clearTimeout(tid);
26+
resolve();
27+
}
28+
}, 200);
29+
});
30+
}
331

432
export default function RailsPathLinkHandler() {
33+
const previews = useStore(tutorialStore.previews);
34+
535
useEffect(() => {
6-
function handleClick(event: MouseEvent) {
36+
async function handleClick(event: MouseEvent) {
737
const target = event.target as HTMLElement;
838
const link = target.closest('.rails-path-link');
939

@@ -14,6 +44,41 @@ export default function RailsPathLinkHandler() {
1444
if (railsPath) {
1545
tutorialStore.setSelectedFile(`/workspace/store/${railsPath}`);
1646
}
47+
return;
48+
}
49+
50+
if (target.tagName === 'A') {
51+
const linkTarget = target as HTMLAnchorElement;
52+
53+
if (linkTarget.href.startsWith('http://localhost:3000')) {
54+
event.preventDefault();
55+
56+
const railsPreview = previews.find((pr) => pr.port === 3000);
57+
58+
if (!railsPreview) return;
59+
60+
try {
61+
await ensureRailsServerStarted(railsPreview)
62+
} catch(e) {
63+
console.error("failed to start Rails server", e);
64+
return;
65+
}
66+
67+
const input = document.querySelector('input[type="text"][name="tutorialkit-preview-navigation"]') as HTMLInputElement;
68+
if (!input) return;
69+
70+
const newPath = linkTarget.href.replace('http://localhost:3000/', '');
71+
72+
input.value = newPath;
73+
const ev = new KeyboardEvent('keydown', {
74+
key: 'Enter',
75+
code: 'Enter',
76+
keyCode: 13,
77+
bubbles: true,
78+
cancelable: true,
79+
});
80+
input.dispatchEvent(ev);
81+
}
1782
}
1883
}
1984

@@ -22,7 +87,7 @@ export default function RailsPathLinkHandler() {
2287
return () => {
2388
document.removeEventListener('click', handleClick);
2489
};
25-
}, []);
90+
}, [previews]);
2691

2792
return null;
2893
}

0 commit comments

Comments
 (0)