feat(studio): inline flow editor — YAML highlighting + Run (v0.50.0)
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
New top-level destination "Editor" (Cmd+5) ships as Studio's
fifth surface. The editor reads + writes flow YAML directly
under ~/.fai/data/flows/ via dart:io — the hub picks up the
changes on the next listFlows / runSavedFlow call.
Layout: two-pane shell. Left (240 px) is the file list; right
flexes to the code pane and an optional results column when
Run produces output. Top toolbar exposes:
* filename + dirty-mark
* New flow (scaffolds from a debug.echo template)
* Save (writes the active file to disk)
* Run (saves first if dirty, calls
HubService.runSavedFlow, surfaces typed FlowOutputs in
a side panel)
* Refresh
YAML highlighting via flutter_code_editor + the highlight
package's yaml language. Lightweight style map mapping the
five token classes that actually appear in flow YAML
(attr / string / number / comment / subst for the
${{ ... }} template syntax) to FaiTheme colors — keeps the
editor visually consistent with the rest of Studio.
New-flow naming uses a FilteringTextInputFormatter that
restricts the name to [a-z0-9_-]. A "name already exists"
SnackBar surfaces the conflict instead of silently
overwriting.
Bilingual strings shipped (en.arb + de.arb) for every
operator-facing string: toolbar buttons, dialogs, empty
states, file-exists error, run-output header.
New deps:
* flutter_code_editor ^0.3.5
* highlight (transitive — pinned as direct so the
yaml-language import has its declared dependency).
Smoke-test (test/flow_editor_test.dart) pumps the page and
asserts the empty-state + toolbar render without throwing
on hosts that don't have ~/.fai/data/flows yet. The full
file-list + open-on-tap flow needs a writable HOME override
which dart:io's read-only Platform.environment doesn't allow
inside a test isolate — that path lives in the integration
suite as a follow-up.
Version bumps:
* pubspec.yaml: 0.49.1 → 0.50.0
* main.dart kStudioVersion: 0.42.0 → 0.50.0 (had drifted
behind pubspec; brought back into sync as part of this
bump)
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
570c38b238
commit
bb793e64a9
15 changed files with 1291 additions and 5 deletions
|
|
@ -1381,5 +1381,37 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"storeSourceTemporal": "Temporal"
|
||||
"storeSourceTemporal": "Temporal",
|
||||
|
||||
"navFlowEditor": "Editor",
|
||||
"flowEditorNew": "Neuer Flow",
|
||||
"flowEditorSave": "Speichern",
|
||||
"flowEditorRun": "Ausführen",
|
||||
"flowEditorRefresh": "Datei-Liste neu laden",
|
||||
"flowEditorRunOutput": "LAUF-ERGEBNIS",
|
||||
"flowEditorEmptyTitle": "Kein Flow geöffnet",
|
||||
"flowEditorEmptyBody": "Wähle links einen aus oder klicke Neuer Flow um einen neuen anzulegen.",
|
||||
"flowEditorListEmptyTitle": "Keine gespeicherten Flows",
|
||||
"flowEditorListEmptyBody": "Klicke Neuer Flow um aus einer Vorlage zu starten.",
|
||||
"flowEditorDiscardTitle": "Ungespeicherte Änderungen verwerfen?",
|
||||
"flowEditorDiscardBody": "Beim Wechsel der Datei gehen alle noch nicht gespeicherten Änderungen verloren.",
|
||||
"flowEditorDiscardKeep": "Weiterbearbeiten",
|
||||
"flowEditorDiscardThrow": "Verwerfen",
|
||||
"flowEditorNewDialogTitle": "Neuer Flow",
|
||||
"flowEditorNewDialogLabel": "Flow-Name",
|
||||
"flowEditorNewDialogHelper": "Kleinbuchstaben, Ziffern, Bindestrich, Unterstrich",
|
||||
"flowEditorNewDialogCancel": "Abbrechen",
|
||||
"flowEditorNewDialogCreate": "Anlegen",
|
||||
"flowEditorNewTemplateComment": "Von Studios Flow-Editor erstellt. Bearbeiten, speichern, ausführen.",
|
||||
"@flowEditorNewTemplateComment": {
|
||||
"placeholders": {
|
||||
"name": {"type": "String"}
|
||||
}
|
||||
},
|
||||
"flowEditorAlreadyExists": "Ein Flow namens \"{name}\" existiert bereits.",
|
||||
"@flowEditorAlreadyExists": {
|
||||
"placeholders": {
|
||||
"name": {"type": "String"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1384,5 +1384,37 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"storeSourceTemporal": "Temporal"
|
||||
"storeSourceTemporal": "Temporal",
|
||||
|
||||
"navFlowEditor": "Editor",
|
||||
"flowEditorNew": "New flow",
|
||||
"flowEditorSave": "Save",
|
||||
"flowEditorRun": "Run",
|
||||
"flowEditorRefresh": "Refresh file list",
|
||||
"flowEditorRunOutput": "RUN OUTPUT",
|
||||
"flowEditorEmptyTitle": "No flow open",
|
||||
"flowEditorEmptyBody": "Pick one from the left, or click New flow to start a fresh one.",
|
||||
"flowEditorListEmptyTitle": "No saved flows",
|
||||
"flowEditorListEmptyBody": "Click New flow to scaffold one from a template.",
|
||||
"flowEditorDiscardTitle": "Discard unsaved changes?",
|
||||
"flowEditorDiscardBody": "Switching files will throw away the edits you haven't saved.",
|
||||
"flowEditorDiscardKeep": "Keep editing",
|
||||
"flowEditorDiscardThrow": "Throw away",
|
||||
"flowEditorNewDialogTitle": "New flow",
|
||||
"flowEditorNewDialogLabel": "Flow name",
|
||||
"flowEditorNewDialogHelper": "lowercase letters, digits, hyphen, underscore",
|
||||
"flowEditorNewDialogCancel": "Cancel",
|
||||
"flowEditorNewDialogCreate": "Create",
|
||||
"flowEditorNewTemplateComment": "Generated by Studio's Flow editor. Edit, save, run.",
|
||||
"@flowEditorNewTemplateComment": {
|
||||
"placeholders": {
|
||||
"name": {"type": "String"}
|
||||
}
|
||||
},
|
||||
"flowEditorAlreadyExists": "A flow named \"{name}\" already exists.",
|
||||
"@flowEditorAlreadyExists": {
|
||||
"placeholders": {
|
||||
"name": {"type": "String"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3727,6 +3727,132 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Temporal'**
|
||||
String get storeSourceTemporal;
|
||||
|
||||
/// No description provided for @navFlowEditor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Editor'**
|
||||
String get navFlowEditor;
|
||||
|
||||
/// No description provided for @flowEditorNew.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'New flow'**
|
||||
String get flowEditorNew;
|
||||
|
||||
/// No description provided for @flowEditorSave.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save'**
|
||||
String get flowEditorSave;
|
||||
|
||||
/// No description provided for @flowEditorRun.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Run'**
|
||||
String get flowEditorRun;
|
||||
|
||||
/// No description provided for @flowEditorRefresh.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Refresh file list'**
|
||||
String get flowEditorRefresh;
|
||||
|
||||
/// No description provided for @flowEditorRunOutput.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'RUN OUTPUT'**
|
||||
String get flowEditorRunOutput;
|
||||
|
||||
/// No description provided for @flowEditorEmptyTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No flow open'**
|
||||
String get flowEditorEmptyTitle;
|
||||
|
||||
/// No description provided for @flowEditorEmptyBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pick one from the left, or click New flow to start a fresh one.'**
|
||||
String get flowEditorEmptyBody;
|
||||
|
||||
/// No description provided for @flowEditorListEmptyTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No saved flows'**
|
||||
String get flowEditorListEmptyTitle;
|
||||
|
||||
/// No description provided for @flowEditorListEmptyBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Click New flow to scaffold one from a template.'**
|
||||
String get flowEditorListEmptyBody;
|
||||
|
||||
/// No description provided for @flowEditorDiscardTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Discard unsaved changes?'**
|
||||
String get flowEditorDiscardTitle;
|
||||
|
||||
/// No description provided for @flowEditorDiscardBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Switching files will throw away the edits you haven\'t saved.'**
|
||||
String get flowEditorDiscardBody;
|
||||
|
||||
/// No description provided for @flowEditorDiscardKeep.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Keep editing'**
|
||||
String get flowEditorDiscardKeep;
|
||||
|
||||
/// No description provided for @flowEditorDiscardThrow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Throw away'**
|
||||
String get flowEditorDiscardThrow;
|
||||
|
||||
/// No description provided for @flowEditorNewDialogTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'New flow'**
|
||||
String get flowEditorNewDialogTitle;
|
||||
|
||||
/// No description provided for @flowEditorNewDialogLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Flow name'**
|
||||
String get flowEditorNewDialogLabel;
|
||||
|
||||
/// No description provided for @flowEditorNewDialogHelper.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'lowercase letters, digits, hyphen, underscore'**
|
||||
String get flowEditorNewDialogHelper;
|
||||
|
||||
/// No description provided for @flowEditorNewDialogCancel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cancel'**
|
||||
String get flowEditorNewDialogCancel;
|
||||
|
||||
/// No description provided for @flowEditorNewDialogCreate.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Create'**
|
||||
String get flowEditorNewDialogCreate;
|
||||
|
||||
/// No description provided for @flowEditorNewTemplateComment.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Generated by Studio\'s Flow editor. Edit, save, run.'**
|
||||
String flowEditorNewTemplateComment(String name);
|
||||
|
||||
/// No description provided for @flowEditorAlreadyExists.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'A flow named \"{name}\" already exists.'**
|
||||
String flowEditorAlreadyExists(String name);
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -2180,4 +2180,75 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get storeSourceTemporal => 'Temporal';
|
||||
|
||||
@override
|
||||
String get navFlowEditor => 'Editor';
|
||||
|
||||
@override
|
||||
String get flowEditorNew => 'Neuer Flow';
|
||||
|
||||
@override
|
||||
String get flowEditorSave => 'Speichern';
|
||||
|
||||
@override
|
||||
String get flowEditorRun => 'Ausführen';
|
||||
|
||||
@override
|
||||
String get flowEditorRefresh => 'Datei-Liste neu laden';
|
||||
|
||||
@override
|
||||
String get flowEditorRunOutput => 'LAUF-ERGEBNIS';
|
||||
|
||||
@override
|
||||
String get flowEditorEmptyTitle => 'Kein Flow geöffnet';
|
||||
|
||||
@override
|
||||
String get flowEditorEmptyBody =>
|
||||
'Wähle links einen aus oder klicke Neuer Flow um einen neuen anzulegen.';
|
||||
|
||||
@override
|
||||
String get flowEditorListEmptyTitle => 'Keine gespeicherten Flows';
|
||||
|
||||
@override
|
||||
String get flowEditorListEmptyBody =>
|
||||
'Klicke Neuer Flow um aus einer Vorlage zu starten.';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardTitle => 'Ungespeicherte Änderungen verwerfen?';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardBody =>
|
||||
'Beim Wechsel der Datei gehen alle noch nicht gespeicherten Änderungen verloren.';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardKeep => 'Weiterbearbeiten';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardThrow => 'Verwerfen';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogTitle => 'Neuer Flow';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogLabel => 'Flow-Name';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogHelper =>
|
||||
'Kleinbuchstaben, Ziffern, Bindestrich, Unterstrich';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogCancel => 'Abbrechen';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogCreate => 'Anlegen';
|
||||
|
||||
@override
|
||||
String flowEditorNewTemplateComment(String name) {
|
||||
return 'Von Studios Flow-Editor erstellt. Bearbeiten, speichern, ausführen.';
|
||||
}
|
||||
|
||||
@override
|
||||
String flowEditorAlreadyExists(String name) {
|
||||
return 'Ein Flow namens \"$name\" existiert bereits.';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2185,4 +2185,75 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get storeSourceTemporal => 'Temporal';
|
||||
|
||||
@override
|
||||
String get navFlowEditor => 'Editor';
|
||||
|
||||
@override
|
||||
String get flowEditorNew => 'New flow';
|
||||
|
||||
@override
|
||||
String get flowEditorSave => 'Save';
|
||||
|
||||
@override
|
||||
String get flowEditorRun => 'Run';
|
||||
|
||||
@override
|
||||
String get flowEditorRefresh => 'Refresh file list';
|
||||
|
||||
@override
|
||||
String get flowEditorRunOutput => 'RUN OUTPUT';
|
||||
|
||||
@override
|
||||
String get flowEditorEmptyTitle => 'No flow open';
|
||||
|
||||
@override
|
||||
String get flowEditorEmptyBody =>
|
||||
'Pick one from the left, or click New flow to start a fresh one.';
|
||||
|
||||
@override
|
||||
String get flowEditorListEmptyTitle => 'No saved flows';
|
||||
|
||||
@override
|
||||
String get flowEditorListEmptyBody =>
|
||||
'Click New flow to scaffold one from a template.';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardTitle => 'Discard unsaved changes?';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardBody =>
|
||||
'Switching files will throw away the edits you haven\'t saved.';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardKeep => 'Keep editing';
|
||||
|
||||
@override
|
||||
String get flowEditorDiscardThrow => 'Throw away';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogTitle => 'New flow';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogLabel => 'Flow name';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogHelper =>
|
||||
'lowercase letters, digits, hyphen, underscore';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogCancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get flowEditorNewDialogCreate => 'Create';
|
||||
|
||||
@override
|
||||
String flowEditorNewTemplateComment(String name) {
|
||||
return 'Generated by Studio\'s Flow editor. Edit, save, run.';
|
||||
}
|
||||
|
||||
@override
|
||||
String flowEditorAlreadyExists(String name) {
|
||||
return 'A flow named \"$name\" already exists.';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue