default workflows, qol touches
This commit is contained in:
@@ -1358,6 +1358,7 @@ function Flow() {
|
||||
break;
|
||||
case 'executing':
|
||||
setExecutingNodeId(String(msg.data.node));
|
||||
updateNodeData(String(msg.data.node), { warning: null, error: null });
|
||||
setStatus({ text: `Executing node ${msg.data.node}…`, level: 'info' });
|
||||
break;
|
||||
case 'execution_complete':
|
||||
@@ -2178,16 +2179,20 @@ function Flow() {
|
||||
});
|
||||
|
||||
// Load any .md files from frontend/public/ as help tabs
|
||||
const isFirstVisit = !localStorage.getItem('tono_visited');
|
||||
fetch('/help-docs')
|
||||
.then((r) => r.ok ? r.json() : [])
|
||||
.then((docs: any[]) => {
|
||||
if (!docs.length) return;
|
||||
const filtered = isFirstVisit ? docs : docs.filter((d: any) => d.title !== 'Getting Started');
|
||||
if (!filtered.length) return;
|
||||
setHelpTabs((prev) => {
|
||||
const existing = new Set(prev.map((t) => t.label));
|
||||
const newTabs = docs.filter((d: any) => !existing.has(d.title)).map((d: any) => ({ label: d.title, content: d.content }));
|
||||
const newTabs = filtered.filter((d: any) => !existing.has(d.title)).map((d: any) => ({ label: d.title, content: d.content }));
|
||||
return newTabs.length ? [...prev, ...newTabs] : prev;
|
||||
});
|
||||
setActiveHelpTab((cur) => cur || docs[0].title);
|
||||
setActiveHelpTab((cur) => cur || filtered[0].title);
|
||||
localStorage.setItem('tono_visited', '1');
|
||||
})
|
||||
.catch(() => {});
|
||||
}, [loadDefaultWorkflow]);
|
||||
@@ -3200,6 +3205,15 @@ function Flow() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="toolbar-group">
|
||||
<button className="btn" onClick={openJournalTab} title="Open journal">
|
||||
✎ Journal
|
||||
</button>
|
||||
<button className="btn" onClick={() => openDocByFilename('getting-started.md')} title="Getting started guide">
|
||||
? Help
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`status-bar ${status.level}`}>{status.text}</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ function JournalTab({ content, onChange, onOpenDoc }: JournalTabProps) {
|
||||
{isEditing ? 'Preview' : 'Edit'}
|
||||
</button>
|
||||
{isEditing && (
|
||||
<span className="node-help-journal-hint">Ctrl+Enter to preview</span>
|
||||
<span className="node-help-journal-hint">Esc or Ctrl+Enter to preview</span>
|
||||
)}
|
||||
</div>
|
||||
{isEditing ? (
|
||||
@@ -221,6 +221,10 @@ function JournalTab({ content, onChange, onOpenDoc }: JournalTabProps) {
|
||||
e.preventDefault();
|
||||
setIsEditing(false);
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
setIsEditing(false);
|
||||
}
|
||||
}}
|
||||
placeholder="Write your notes here (Markdown supported)…"
|
||||
autoFocus
|
||||
@@ -266,7 +270,10 @@ function HelpPanelManager({ tabs, activeTab, onTabSelect, onTabClose, onTabConte
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' && activeTab) onTabClose(activeTab);
|
||||
if (e.key === 'Escape' && activeTab) {
|
||||
if (e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLInputElement) return;
|
||||
onTabClose(activeTab);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handler);
|
||||
return () => document.removeEventListener('keydown', handler);
|
||||
|
||||
Reference in New Issue
Block a user