@revenexx/studio-integrations 1.3.0 → 1.4.1

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +457 -0
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/components/Integrations/CanvasShortcutsDialog.d.vue.ts +9 -0
  4. package/dist/runtime/components/Integrations/CanvasShortcutsDialog.vue +53 -0
  5. package/dist/runtime/components/Integrations/CanvasShortcutsDialog.vue.d.ts +9 -0
  6. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +61 -29
  7. package/dist/runtime/components/Integrations/EditorTip.vue +2 -15
  8. package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +10 -0
  9. package/dist/runtime/components/Integrations/NodeConfigField.vue +94 -49
  10. package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +10 -0
  11. package/dist/runtime/components/Integrations/NodeInspector.vue +37 -60
  12. package/dist/runtime/components/Integrations/RunDetailPanel.vue +80 -33
  13. package/dist/runtime/components/Integrations/TemplateCard.d.vue.ts +0 -4
  14. package/dist/runtime/components/Integrations/TemplateCard.vue +3 -6
  15. package/dist/runtime/components/Integrations/TemplateCard.vue.d.ts +0 -4
  16. package/dist/runtime/components/Integrations/TemplateInstallStep.d.vue.ts +25 -0
  17. package/dist/runtime/components/Integrations/TemplateInstallStep.vue +198 -0
  18. package/dist/runtime/components/Integrations/TemplateInstallStep.vue.d.ts +25 -0
  19. package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +2 -2
  20. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +22 -40
  21. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +2 -2
  22. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +94 -65
  23. package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +36 -2
  24. package/dist/runtime/components/Integrations/WorkflowEditor.vue +165 -56
  25. package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +36 -2
  26. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +6 -2
  27. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +4 -106
  28. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +6 -2
  29. package/dist/runtime/components/Integrations/WorkflowsTable.vue +22 -11
  30. package/dist/runtime/composables/useCanvasShortcuts.d.ts +34 -0
  31. package/dist/runtime/composables/useCanvasShortcuts.js +11 -8
  32. package/dist/runtime/composables/useCredentialTypes.js +3 -9
  33. package/dist/runtime/composables/useIntegrationsCredentials.js +6 -14
  34. package/dist/runtime/composables/useIntegrationsNodes.js +2 -2
  35. package/dist/runtime/composables/useIntegrationsRuns.js +8 -13
  36. package/dist/runtime/composables/useIntegrationsSecrets.js +5 -5
  37. package/dist/runtime/composables/useIntegrationsTemplates.js +5 -8
  38. package/dist/runtime/composables/useIntegrationsTriggers.js +1 -4
  39. package/dist/runtime/composables/useIntegrationsWorkflows.js +5 -7
  40. package/dist/runtime/data/canvasShortcuts.d.ts +208 -0
  41. package/dist/runtime/data/canvasShortcuts.js +68 -0
  42. package/dist/runtime/i18n/messages/de.json +30 -16
  43. package/dist/runtime/i18n/messages/en.json +30 -16
  44. package/dist/runtime/pages/integrations/credentials.vue +40 -18
  45. package/dist/runtime/pages/integrations/templates/[slug].vue +22 -132
  46. package/dist/runtime/pages/integrations/workflows/[id].vue +128 -33
  47. package/dist/runtime/utils/apiEnvelope.d.ts +27 -0
  48. package/dist/runtime/utils/apiEnvelope.js +20 -0
  49. package/dist/runtime/utils/apiError.d.ts +35 -8
  50. package/dist/runtime/utils/apiError.js +12 -12
  51. package/dist/runtime/utils/configDefaults.d.ts +18 -0
  52. package/dist/runtime/utils/configDefaults.js +7 -0
  53. package/dist/runtime/utils/errorPathAdvice.d.ts +60 -0
  54. package/dist/runtime/utils/errorPathAdvice.js +19 -0
  55. package/dist/runtime/utils/notify.d.ts +2 -2
  56. package/dist/runtime/utils/runEnvelope.d.ts +12 -0
  57. package/dist/runtime/utils/runEnvelope.js +2 -1
  58. package/dist/runtime/utils/selectOptions.d.ts +48 -0
  59. package/dist/runtime/utils/selectOptions.js +19 -0
  60. package/dist/runtime/utils/shortcutLabel.d.ts +40 -0
  61. package/dist/runtime/utils/shortcutLabel.js +48 -0
  62. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,462 @@
1
1
  # @revenexx/studio-integrations
2
2
 
3
+ ## 1.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 7bb1913: A refused credential save states each reason once: at its field, or below the form
8
+ when no field can show it (PO-477).
9
+
10
+ **What a field can carry is marked there and nowhere else.** Until now the service's
11
+ lead reason was also repeated in a red box above the Save button, so the one sentence
12
+ the operator had already read was the one thing on the surface they had to read twice
13
+ — and it crowded out the reasons that had no other place to appear.
14
+
15
+ **What no field can carry is what the box is for now.** The service keys a refusal by
16
+ validation rule, and several of those shapes name nothing either dialog draws an input
17
+ for: the access data taken as a whole, a field the credential type never handed out, a
18
+ field hidden while a managed revenexx resource is being reused, or a refusal that is
19
+ not field-keyed at all, such as a conflict or a gateway error. Any of them was silent
20
+ unless the service happened to lead with it. All of them are now stated below the form,
21
+ every message of them, still without the service's count of everything else it found.
22
+
23
+ **The refusal also puts the operator in the first marked field.** The box was what
24
+ guaranteed a refusal could not be rendered below the fold of a form that scrolls; the
25
+ focus is what guarantees it now, and it leaves the cursor where the correction has to
26
+ be typed.
27
+
28
+ Both dialogs read the refusal through one seam, so the create-and-edit dialog on
29
+ Credentials and the credential detail dialog answer the same way.
30
+
31
+ Promised behaviour: `specs/credential-create.md` AC-8 and AC-11,
32
+ `specs/credential-detail.md` AC-6.
33
+
34
+ ## 1.4.0
35
+
36
+ ### Minor Changes
37
+
38
+ - 388babd: Installing a template takes the same step from both routes into it (PO-244).
39
+
40
+ A template could be installed from two places, and the two gave the user different
41
+ workflows. From the "New workflow" dialog one press of a card installed it there and
42
+ then: the copy arrived under the template's own name, bound to none of the tenant's
43
+ credentials, with nothing said about either — and a refusal came back as a message
44
+ that disappeared. From the template's own page the same act named the copy first,
45
+ offered a credential per place that needs one, listed the secrets it references as
46
+ stored or missing, and kept a refusal on screen with what had been entered. Nobody
47
+ had decided that; the richer route simply arrived later.
48
+
49
+ The dialog's card now opens that same step in place of the list of templates, with
50
+ the way back to the list beside the name. Both routes therefore create the same
51
+ workflow, and it is created when the user confirms rather than when they press a
52
+ card. The step is one component reached from both places, so what it offers cannot
53
+ drift apart again, and while it works out what the template needs it says so —
54
+ "needs no credentials" and "not asked yet" used to look the same.
55
+
56
+ Two things a host should know. **Pressing a card no longer creates anything**, so a
57
+ test or a script that pressed one and waited for the editor now has to confirm the
58
+ step. And the template card has lost its `busy` and `disabled` props, which existed
59
+ for the install that used to start on the card itself; nothing acts on a card any
60
+ more.
61
+
62
+ - 79f42db: The run replay replays the run it was handed, and nothing else (PO-350).
63
+
64
+ The replay carried a second mode, switched by a `single` prop: a 320 px sidebar
65
+ listing the workflow's runs to browse, beside the canvas. No route in the studio
66
+ ever mounted it — the run record took the replay over and passed `single` from the
67
+ day it did — so what shipped was a surface with a defect nobody could reach: asked
68
+ for a run it did not find among the most recent ones, it replayed the newest run
69
+ instead, under a label naming the newest run. A host mounting the component the way
70
+ its own prop documented got that, quietly.
71
+
72
+ The mode is gone. The replay now walks the run it is given, whatever else the
73
+ workflow has run, and with no run given it says so rather than choosing one. Runs
74
+ are browsed on the studio's own runs table, which filters, pages and offers the row
75
+ actions the sidebar never had — and the replay no longer asks for a run list it had
76
+ no use for.
77
+
78
+ `single` is still accepted and now ignored, so a host passing it keeps working; it
79
+ is deprecated and will be dropped at the next major. The four `runsList` strings
80
+ and the run-list failure message leave with the mode.
81
+
82
+ Two more strings stay but stop pointing at it: a panel given no run to replay used
83
+ to answer _Pick a run on the right to replay it._, where the right-hand side was
84
+ that sidebar. It now says _No run to replay._ — the state, rather than an
85
+ instruction with nothing to follow it.
86
+
87
+ - 3ddba20: A workflow that leaves the run mode to its caller is asked which one, instead of
88
+ being run asynchronously (PO-428).
89
+
90
+ Pressing Run in the editor opened a dialog only where the workflow read something
91
+ from its trigger payload. A workflow whose execution mode is **Caller decides** and
92
+ whose nodes read no payload therefore never reached the offer at all: it was started
93
+ in the mode that does not wait, and a run whose result the author wanted to wait for
94
+ could not be started by hand. It now opens the same dialog, with both modes on it.
95
+ `mod+enter` follows the button, as it always has.
96
+
97
+ The dialog is named after the run rather than after the payload: **Run workflow**,
98
+ "Starts a manual run of this workflow. What it returns is shown here when it ends."
99
+ The payload is a field on it and names itself. The old description also still
100
+ promised the result on the Runs tab, which stopped being where it appears when the
101
+ dialog began showing what the run returned.
102
+
103
+ Where both modes are offered, the one that waits for the result is now the suggested
104
+ one, on the right, and it stays the suggested one however the last run was started —
105
+ the offer follows the workflow, not the last press. The mode words on the buttons are
106
+ unchanged.
107
+
108
+ Promised behaviour: `specs/run-from-editor.md` AC-1, AC-2 and AC-10.
109
+
110
+ - 1cb60f7: Every key the workflow canvas answers can be read in one place, and one of them
111
+ could not be pressed on a German keyboard (PO-431).
112
+
113
+ **Press `?` on the canvas** for a list of its keys, grouped and written the way your
114
+ own keyboard is labelled. The canvas answers two dozen shortcuts, and until now
115
+ learning them meant hovering thirteen controls and right-clicking three different
116
+ things — two of them, activating the workflow and renaming a node with Space, were
117
+ shown nowhere at all.
118
+
119
+ **Zooming in now works on every layout.** The binding was `=`, which a German
120
+ keyboard types as Shift+0 — and a Shift the layout requires to produce a character
121
+ was being counted as part of the shortcut, so the key answered on a US keyboard and
122
+ on no other. A character key is now reached however a layout types it, while a
123
+ shortcut that means Shift over a letter still needs Shift held. **Zooming in is now
124
+ `+`** — the key a German keyboard has of its own and a US one reaches with Shift; the
125
+ old `=`, which only ever worked on a US layout, is gone rather than kept as a second
126
+ undocumented way in. Zooming out is `-`, as before.
127
+
128
+ **A modifier is spelled the way its platform spells it.** The command and option keys
129
+ already followed the platform; the shift key was the glyph ⇧ everywhere, so a Windows
130
+ or Linux reader got `Ctrl+⇧+G`. On those platforms it now reads `Ctrl+Shift+G`; on a
131
+ mac nothing changes.
132
+
133
+ Behind all three: the keys live in one list that the overview, the canvas's context
134
+ menu and the control pane's tooltips all read, so a key cannot be shown in one place
135
+ and answered in another. The menu had already drifted — it offered renaming as `F2`
136
+ for a key that answers `Space` too.
137
+
138
+ Promised behaviour: `specs/canvas-keyboard-shortcuts.md` AC-4, AC-5 and AC-6.
139
+
140
+ - 4aa26a6: The editor points out an error output nobody connected, and attaches the ending
141
+ our own templates use (PO-443).
142
+
143
+ **A step that fails on a path nobody drew is not handled.** Most nodes have a red
144
+ error output; if the author never drew a line out of it, a failure there is not
145
+ carried anywhere. The platform now ends the run on it — but by then the workflow
146
+ has been running unattended for weeks. This is the half that says so while it is
147
+ still being drawn.
148
+
149
+ **A slate strip above the canvas names each step whose error output leads
150
+ nowhere**, and a line jumps to that step on the canvas. Deliberately not amber:
151
+ amber already means "fix this before it runs" in this editor twice over, and this
152
+ is not that.
153
+
154
+ **It blocks nothing.** Not activation, not saving, not starting a run. That is the
155
+ whole point of it being advice: the same fact expressed as a validation finding
156
+ would have closed the activation gate — and the run gate — on every workflow that
157
+ has an unconnected error output, including ones that have run nightly for months.
158
+ The rule is therefore computed in the editor, where no gate can read it.
159
+
160
+ **One click attaches the ending.** _Stop the run on error_ drops a Stop and Error
161
+ step below the node, wires it to the error output, and pre-fills its message the
162
+ way all eight shipped templates write theirs — the failing step by name, then its
163
+ own reason quoted out of the port that carried it. Nothing is saved until the
164
+ author saves; deleting the step undoes it.
165
+
166
+ A step nobody has connected yet is left alone, so laying out a workflow before
167
+ wiring it does not produce a wall of complaints. A step whose ports are named only
168
+ once its settings resolve is left alone too — nothing is claimed about an output
169
+ the declaration cannot name.
170
+
171
+ Promised behaviour: `specs/workflow-advice.md`, a new spec that owns what the
172
+ editor says about a workflow it has no objection to. `specs/workflow-validation.md`
173
+ keeps the gate, and the two now say so about each other.
174
+
175
+ - 1a1edc3: A node's settings keep the order it declares them in, and only the tail is
176
+ folded (PO-463).
177
+
178
+ The node configuration dialog used to draw every required setting first and fold
179
+ every optional one away. That discarded the order the node author chose and made
180
+ requiredness stand for importance, which it cannot: the API refuses a required
181
+ setting that is empty, so a setting that is central and legitimately empty — Text
182
+ Replace's replacement, whose empty value is how a search value is deleted — had
183
+ to be optional, and therefore disappeared. Text Replace showed one of its six
184
+ settings, and not the one it is named after.
185
+
186
+ The Parameters tab now draws the settings a node declares as one list, in that
187
+ order. Four or fewer are all shown; beyond four the first three are always shown
188
+ and, from the fourth on, a setting is shown when it is required and folded when
189
+ it is not. The fold keeps its single control and its count, and now stands at the
190
+ first setting it hides, so opening it puts the tail back where the node declared
191
+ it. Counted over the 51 published core node types, 157 of 203 settings reach the
192
+ open form where 103 did before, and no node shows fewer than it did.
193
+
194
+ Nothing is required of a node package: the lever is the order a node already
195
+ declares. A node whose central setting still sits past the third — HTTP Request's
196
+ body, Send Email's two bodies — moves it up in its own manifest.
197
+
198
+ - 633f3bf: The workflows list says whether it is grouped by tag, and now promises what
199
+ grouping does (PO-468).
200
+
201
+ Grouping the list by tag was offered by a button that read "Group by tags"
202
+ whether or not the list was already grouped — so pressing it once more ungrouped
203
+ a list whose control still invited grouping, and the only sign of the state was
204
+ the button's colour. It is now a switch: it shows whether grouping is on, to a
205
+ reader and to a screen reader alike.
206
+
207
+ Two behaviours the list already had are promises from here on, with tests behind
208
+ them: the grouping an operator chose is the one the list arrives in on the next
209
+ visit, kept in that browser alone, and a workflow carrying several tags stands
210
+ under each of them, with the untagged ones together under "No tags" at the end.
211
+ No shipped string changes.
212
+
213
+ - 652a08f: Every canvas now zooms between the same two ends, and the editor no longer offers a
214
+ reach that shows nothing (PO-470).
215
+
216
+ The editor went to four times full size while the run replay and the history preview
217
+ stopped at twice. That was never decided: all three stopped at twice until the
218
+ editor's zoom picker was given a 400% preset and its ceiling was raised to match.
219
+ Asked what the extra reach was for, the answer turned out to be nothing — a step's
220
+ card carries a name, a version and a mark, and at four times full size a single card
221
+ fills the canvas without saying more than it did at half that.
222
+
223
+ So the editor comes down to twice full size, where the other two canvases already
224
+ were, and the 300% and 400% entries leave its zoom menu. The menu gains 25%, the
225
+ level the wheel could always reach and the list never offered — it now spans the
226
+ whole range, ends included. Anything typed into the zoom field beyond the range
227
+ still lands at the range's end rather than being refused.
228
+
229
+ Three criteria hold it from here on: the range on all three canvases, the clamping,
230
+ and the six levels the menu offers — 25%, 50%, 75%, 100%, 150% and 200%. That last
231
+ one is named rather than described on purpose: adding, removing or moving a level
232
+ changes what the editor offers an author, and it should take a decision rather than
233
+ a tweak.
234
+
235
+ ### Patch Changes
236
+
237
+ - 2b6af97: Three copy-catalogue entries have their source back (PO-244).
238
+
239
+ The catalogue records where each shipped string is used, and recomputing those
240
+ references after the template install step moved lost three of them: the
241
+ publisher badges — Official, Partner, Community — are looked up through a map
242
+ rather than named in a `t()` call, so a scan for `t('…')` did not find them. A
243
+ unit test guards exactly that, and it is why this was caught on `main` rather
244
+ than by a reader finding an entry that points nowhere. No shipped string changes.
245
+
246
+ - aff19fa: One answer to whether a response carries a `data` envelope, checked against the
247
+ service (PO-394).
248
+
249
+ Nine expressions in five composables each decided for themselves whether the
250
+ Integrations API had wrapped a single record, with a spelling that worked either
251
+ way — so nothing recorded which endpoints wrap, and a response in an unexpected
252
+ shape was handed to the caller as the envelope itself and drawn as empty fields.
253
+ They now share `unwrapRecord` and `unwrapList` in `src/runtime/utils/`, which
254
+ carry the service's rule as a table read from its controller bodies: **a
255
+ collection is wrapped in `data`, a single record is bare** — with templates as
256
+ the exception, because there the envelope follows the presenter rather than the
257
+ shape. A record that arrives in neither shape now fails visibly instead of
258
+ rendering blank, and the message a person sees is the page's own copy.
259
+
260
+ No promised behaviour changes. Three routes in the test mock answered a wrapped
261
+ record where the service answers a bare one — one of them contradicting a
262
+ contract this repository had signed a fortnight earlier — and now answer as the
263
+ service does; the envelope question is signed for the templates, workflows and
264
+ runs surfaces in `e2e/support/api-contract.json`.
265
+
266
+ - 2db01ec: A step in a run's timeline opens on what it was handed and what it gave back (PO-421).
267
+
268
+ The **Show payloads** button is gone. It was a fetch switch dressed as a display
269
+ switch: a step opened on an instruction to press it, and pressing it re-read every
270
+ step of the run with its payloads, whether or not the operator went on to open a
271
+ second one. Opening a step now reads them itself, once, and says so while they are
272
+ on their way.
273
+
274
+ What comes back is kept per step scheduling and merged into the reads that keep a
275
+ live run current, so the three-second poll neither blanks an open step nor goes back
276
+ to storage for payloads it already has. A step opened while it was still running is
277
+ read once more when it ends, and only then — the status a payload was read in is
278
+ what decides, so a step that legitimately returned nothing is not re-read on every
279
+ poll, and a read that failed is not retried three seconds later.
280
+
281
+ A failed payload read now leaves the timeline standing and says so inside the open
282
+ step. Before, it shared the read that draws the list of steps, which empties that
283
+ list when it fails.
284
+
285
+ Promised behaviour: `specs/run-detail.md` AC-7, and AC-15 for what an open step keeps
286
+ while its run goes on.
287
+
288
+ - 122659e: An option that stands for no choice can be chosen, and no longer takes the node
289
+ dialog with it (PO-422).
290
+
291
+ A node may offer "no choice" as an entry in a list — the format the file came in as,
292
+ unchanged, all kinds — by declaring an option with an empty value. Three published
293
+ node types do. The control underneath the studio's lists reserves the empty value for
294
+ "nothing selected" and refused the entry outright: the list did not open, and the
295
+ refusal tore down the dialog's dismissal machinery on its way out. From that click
296
+ on, the next list opened anywhere in the form stayed open — Escape and a click
297
+ outside both did nothing — and the only way out was to abandon the dialog with
298
+ everything half set in it.
299
+
300
+ Such an option is now carried through the list under a substitute value and written
301
+ back as the empty string the node reads. It keeps its own label and its place, and it
302
+ is still there once another option has been chosen, so a setting given a value can be
303
+ put back to no choice. A setting the platform is holding as nothing — the empty string
304
+ comes back as null — reads as that option rather than as a placeholder; a setting the
305
+ workflow holds nothing at all for still reads as the placeholder, because no choice
306
+ has been made.
307
+
308
+ - 107db51: Running a run again, above an open run's record, is offered for a run that failed
309
+ (PO-427).
310
+
311
+ It used to be offered for every run that had ended, a successful one included, under
312
+ the word **Retry** — and the press does not repeat that run: it starts a fresh run of
313
+ the workflow as it is saved now, carrying the old run's trigger payload. Over a run
314
+ that had succeeded, that meant doing everything the run already did to the systems at
315
+ the far end, behind a word saying nothing had happened yet. The button now reads **Run
316
+ again**, says in its title what it really runs, and stands over a failed run only. A
317
+ run's own row still offers it whatever the outcome, from behind its actions menu.
318
+
319
+ A press that the platform accepts now leaves the operator looking at the run it
320
+ started, instead of on the run they had just replaced with only a message naming the
321
+ new one. Stepping back returns to the run that failed, so the two can be compared —
322
+ and because the run just started is not over, the button that started it is gone
323
+ rather than standing ready to start a third.
324
+
325
+ Promised behaviour: `specs/run-detail.md` AC-16 and AC-17.
326
+
327
+ - 4a90a4b: A setting inside a list row is drawn as what it declares, and a new row starts from
328
+ what the node declared (PO-436).
329
+
330
+ A node setting that sits inside a repeating row was always drawn as an empty text
331
+ box, whatever its manifest said: the choices it offers, its default, whether it is
332
+ required, the sentence under it. The manifest schema permits all of that on a nested
333
+ setting and the engine reads it — only the form stopped one level short. Each
334
+ sub-setting is now drawn by the same renderer the rest of the form uses, so a
335
+ declared choice arrives as a list of its named options, a boolean as a switch, an
336
+ expression-capable setting as the mapping control, each with its own description and
337
+ required marker. Every control in a row still says which setting and which row it
338
+ belongs to, so a screen reader can still tell two rows apart.
339
+
340
+ The sharper half was the seeding. A new row was created with an empty string under
341
+ every one of its keys, which is a value rather than an absence — so a node's own
342
+ default could not apply, and the one published node with a choice inside its rows
343
+ (Set Fields) stopped every run with `Unknown operation ""` until the author guessed
344
+ one of three words nothing on screen named. A new row now carries each sub-setting's
345
+ declared default and leaves a setting that has none out of the row entirely.
346
+
347
+ One kind of setting is still withheld inside a row: the kind whose options — or
348
+ whose whole set of settings — the platform is asked for while the dialog is open.
349
+ That request carries the values the setting belongs to, and a row is not those
350
+ values. No published node declares one there.
351
+
352
+ **And a row's settings now answer their own conditions.** A node may say that one setting
353
+ in a row means something only under one of another's choices — Set Fields says it about
354
+ the value it writes and about the path it moves a field to. That condition was read by the
355
+ platform when it judged a saved workflow and by nothing on screen, so both boxes stood
356
+ under every action, each explaining in its own small print when it counted.
357
+
358
+ The condition is read against **the row**, which is where the node wrote it and where the
359
+ platform resolves it: two rows of one list show different settings, each according to its
360
+ own choice. And what was typed into a setting a row withdraws goes with it, in that row
361
+ alone — a value nowhere on screen is a value nobody can correct, and it would otherwise be
362
+ saved and read as though the author had meant it.
363
+
364
+ AC-27 and AC-28 gained the clause, and the gap the spec recorded about a row is closed. A
365
+ group is now the one shape left where a declared condition has nothing to hide.
366
+
367
+ - c0d4083: The view a workflow opens on is fitted to the canvas as it actually is (PO-446).
368
+
369
+ `fitView` reads the canvas out of the DOM, and it was being asked before Vue's
370
+ pending changes had been applied — the band above the canvas that points out an
371
+ unconnected error output among them. So the drawing was placed for a canvas a
372
+ frame out of date, and the same workflow opened at two different zooms depending
373
+ on which side of that frame it landed: measured at `scale(0.717)` with the layout
374
+ settled and `scale(0.626)` without.
375
+
376
+ At the smaller zoom the drawing sits far enough to the left that a step — or a
377
+ connection dot on one — can end up behind the node palette, and a card behind a
378
+ panel takes no pointer at all: it can be seen, and clicking it does nothing. The
379
+ opening view is now placed after the layout has settled, so a workflow opens the
380
+ same way every time.
381
+
382
+ What this does not do is stop a panel covering a card where the drawing genuinely
383
+ reaches under one. That is the older question PO-443 left open — the fit knows
384
+ nothing about what floats over the canvas — and it stays open, with what two
385
+ attempted fixes cost measured in PO-446.
386
+
387
+ - 9f155b3: A run's record offers the addresses in its result whole or not at all: every one of
388
+ them where there are at most fifty, none where there are more. It used to offer the
389
+ first eight and drop the rest without saying so. Promised by `specs/run-detail.md`
390
+ AC-19.
391
+ - 6a9a97f: The workflow editor's header survives a long workflow name (PO-461).
392
+
393
+ Beside a name too long for the room, the badge saying how the workflow
394
+ dispatches was cut off mid-word, and the two status texts next to Save — the
395
+ chip reporting a queued build and the unsaved-changes marker — broke onto a
396
+ second line inside boxes one line high, so their text ran over its own border.
397
+ The breadcrumb was laid out inline, so it sized to its content rather than to
398
+ the heading it sits in and nothing in it ever shrank; the two status texts were
399
+ the only items in the actions row not drawn as buttons, and so the only two that
400
+ could wrap. The name is now the only thing in the header that gives way, and it
401
+ gives way as an ellipsis — with the whole of it on the name itself, so pointing
402
+ at a shortened name shows what was cut.
403
+
404
+ The control that folds the studio navigation away is icon-only while the
405
+ navigation is standing, and carries its words again once it is folded — the way
406
+ back is the direction that needs them. Its accessible name is unchanged in both
407
+ directions, so anything addressing it by name is unaffected.
408
+
409
+ - 7bb3a25: Space renames a node on the canvas, which the Keyboard shortcuts list has been
410
+ promising since it existed (PO-472).
411
+
412
+ **Press `Space` on a selected node** and its configuration opens with the name
413
+ selected, exactly as `F2` does. The list under `?` has offered both keys all along,
414
+ and the second of them answered nothing: the library that draws the canvas binds
415
+ Space as a pan key of its own, on the document, and claimed the keystroke before the
416
+ canvas's own bindings were consulted. That pan key is now switched off, and holding
417
+ Space gains rather than loses: with the key claimed, Space over a drag neither panned
418
+ the canvas nor drew the selection rectangle, so the gesture did nothing at all. The
419
+ one thing that changes is Space held over the scroll wheel, which zooms now instead
420
+ of panning, the way the wheel alone already did.
421
+
422
+ **Every key in that list is now pressed by a test.** The test this shipped past
423
+ read the `Space` cap out of the list and never pressed it — and it was not alone:
424
+ of the twenty-six gestures the list offers, ten were proven by a test that pressed
425
+ them and sixteen were not, `Space` among the sixteen. All sixteen have one now, so
426
+ the surface built so that the list and the keyboard could not disagree is checked in
427
+ the direction that matters.
428
+
429
+ Promised behaviour: `specs/canvas-keyboard-shortcuts.md` AC-7.
430
+
431
+ - 3d07d03: Six behaviours the studio already had are now promises with tests behind them
432
+ (PO-475).
433
+
434
+ Nothing ships differently. What changes is what may change silently afterwards:
435
+ each of these was deliberate in the code, visible on screen, and held by no test,
436
+ so any of them could have gone the day somebody touched the surface.
437
+
438
+ - **A credential cannot be saved without a name**, and picking a system fills one
439
+ in so nobody starts from an empty field. Clearing it puts saving out of reach
440
+ again.
441
+ - **A node's mark is the same wherever the node is named in full** — on the canvas,
442
+ in the header of its own configuration, and in a template's drawing of the flow
443
+ it installs.
444
+ - **A node the catalogue marks with nothing is still marked**, with the same
445
+ generic mark every such node gets. Nothing in today's catalogue is in that state,
446
+ so this had never been seen.
447
+ - **A node whose type this installation does not know still opens.** It says it has
448
+ no configuration, and the settings the engine applies around every node are still
449
+ there — which is what makes a workflow with a withdrawn package repairable.
450
+ - **A double-click zooms the run replay and the history preview.** Neither carries
451
+ a zoom control, so it is the only way in; the editor answers the same gesture by
452
+ opening a node, which is why it turns the zoom off and these two do not.
453
+ - **A group folded shut is drawn open on those two surfaces.** A fold is how an
454
+ author makes their own canvas fit; a replay answers which nodes ran.
455
+
456
+ Promised behaviour: `specs/credential-create.md` AC-10, `specs/node-marks.md` AC-5
457
+ and AC-6, `specs/node-configuration.md` AC-32, `specs/readonly-canvases.md` AC-4,
458
+ `specs/group-frames.md` AC-11.
459
+
3
460
  ## 1.3.0
4
461
 
5
462
  ### Minor Changes
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revenexx/studio-integrations",
3
3
  "configKey": "studioIntegrations",
4
- "version": "1.3.0",
4
+ "version": "1.4.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -0,0 +1,9 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ };
4
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (args_0: boolean) => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ export default _default;
@@ -0,0 +1,53 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@revenexx/studio";
4
+ import { CANVAS_SHORTCUTS, SHORTCUT_GROUPS, SHORTCUT_GROUP_LABELS, shortcutCaps } from "../../data/canvasShortcuts";
5
+ import { formatShortcut } from "../../utils/shortcutLabel";
6
+ defineProps({
7
+ open: { type: Boolean, required: true }
8
+ });
9
+ const emit = defineEmits(["update:open"]);
10
+ const t = useIntegrationsT();
11
+ const groups = computed(() => SHORTCUT_GROUPS.map((group) => ({
12
+ group,
13
+ label: t(SHORTCUT_GROUP_LABELS[group]),
14
+ items: CANVAS_SHORTCUTS.filter((s) => s.group === group).map((s) => ({
15
+ id: s.id,
16
+ label: t(s.labelKey),
17
+ // One cap per gesture, in the platform's own alphabet.
18
+ caps: shortcutCaps(s.id).map((k) => formatShortcut(k))
19
+ }))
20
+ })).filter((g) => g.items.length > 0));
21
+ </script>
22
+
23
+ <template>
24
+ <Dialog :open="open" @update:open="(v) => emit('update:open', v)">
25
+ <DialogContent class="max-w-[94vw] sm:max-w-2xl">
26
+ <DialogHeader>
27
+ <DialogTitle>{{ t("integration.canvas.shortcuts.dialog.title") }}</DialogTitle>
28
+ <DialogDescription class="text-sm">
29
+ {{ t("integration.canvas.shortcuts.dialog.description") }}
30
+ </DialogDescription>
31
+ </DialogHeader>
32
+
33
+ <div class="grid max-h-[70vh] gap-x-8 gap-y-5 overflow-y-auto sm:grid-cols-2">
34
+ <section v-for="g in groups" :key="g.group" class="min-w-0">
35
+ <h3 class="mb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
36
+ {{ g.label }}
37
+ </h3>
38
+ <ul class="space-y-1">
39
+ <li v-for="item in g.items" :key="item.id" class="flex items-baseline justify-between gap-3 text-sm">
40
+ <span class="min-w-0 truncate">{{ item.label }}</span>
41
+ <span class="flex shrink-0 items-baseline gap-1">
42
+ <template v-for="(cap, i) in item.caps" :key="cap">
43
+ <span v-if="i > 0" class="text-xs text-muted-foreground">{{ t("integration.canvas.shortcuts.or") }}</span>
44
+ <kbd class="rounded border border-black/[0.08] bg-slate-50 px-1.5 py-0.5 text-xs tabular-nums text-foreground">{{ cap }}</kbd>
45
+ </template>
46
+ </span>
47
+ </li>
48
+ </ul>
49
+ </section>
50
+ </div>
51
+ </DialogContent>
52
+ </Dialog>
53
+ </template>
@@ -0,0 +1,9 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ };
4
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (args_0: boolean) => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ export default _default;