@revenexx/studio-integrations 1.1.1 → 1.2.0
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.
- package/CHANGELOG.md +483 -0
- package/README.md +3 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +6 -18
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +13 -23
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +7 -6
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue +15 -4
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +4 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +45 -19
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +4 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +5 -4
- package/dist/runtime/components/Integrations/LoadingAnnouncement.d.vue.ts +38 -0
- package/dist/runtime/components/Integrations/LoadingAnnouncement.vue +16 -0
- package/dist/runtime/components/Integrations/LoadingAnnouncement.vue.d.ts +38 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +23 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +2 -2
- package/dist/runtime/components/Integrations/NodeInspector.vue +25 -32
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +2 -2
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +2 -1
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +5 -17
- package/dist/runtime/components/Integrations/RunResponseModal.d.vue.ts +30 -8
- package/dist/runtime/components/Integrations/RunResponseModal.vue +92 -24
- package/dist/runtime/components/Integrations/RunResponseModal.vue.d.ts +30 -8
- package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +61 -3
- package/dist/runtime/components/Integrations/RunsTable.vue +129 -18
- package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +61 -3
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +10 -1
- package/dist/runtime/components/Integrations/StickyNoteView.vue +1 -1
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +18 -3
- package/dist/runtime/components/Integrations/WorkflowDeleteDialog.d.vue.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowDeleteDialog.vue +70 -0
- package/dist/runtime/components/Integrations/WorkflowDeleteDialog.vue.d.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +2 -1
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +4 -4
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +39 -28
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +17 -6
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +17 -21
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +8 -11
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +6 -7
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +7 -7
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +10 -48
- package/dist/runtime/components/Integrations/canvasSides.d.ts +48 -0
- package/dist/runtime/components/Integrations/canvasSides.js +22 -0
- package/dist/runtime/composables/useCredentialTypes.js +2 -6
- package/dist/runtime/composables/useIntegrationsAudit.js +2 -2
- package/dist/runtime/composables/useIntegrationsCredentials.js +4 -8
- package/dist/runtime/composables/useIntegrationsDeadLetters.d.ts +4 -0
- package/dist/runtime/composables/useIntegrationsDeadLetters.js +16 -1
- package/dist/runtime/composables/useIntegrationsNodes.js +2 -2
- package/dist/runtime/composables/useIntegrationsRevisions.js +2 -6
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +4 -15
- package/dist/runtime/composables/useIntegrationsRuns.js +49 -34
- package/dist/runtime/composables/useIntegrationsSchedules.js +2 -2
- package/dist/runtime/composables/useIntegrationsSecrets.js +2 -6
- package/dist/runtime/composables/useIntegrationsTemplates.js +2 -5
- package/dist/runtime/composables/useIntegrationsTriggers.js +2 -2
- package/dist/runtime/composables/useIntegrationsWorkflows.js +4 -7
- package/dist/runtime/composables/useNodeConfigResolve.js +2 -2
- package/dist/runtime/composables/useOAuthConnect.d.ts +42 -0
- package/dist/runtime/composables/useOAuthConnect.js +33 -0
- package/dist/runtime/data/expressionEditor.d.ts +17 -5
- package/dist/runtime/data/expressionEditor.js +11 -5
- package/dist/runtime/data/handleId.d.ts +61 -1
- package/dist/runtime/data/handleId.js +8 -1
- package/dist/runtime/data/payloadForm.js +3 -2
- package/dist/runtime/i18n/messages/de.json +26 -8
- package/dist/runtime/i18n/messages/en.json +26 -8
- package/dist/runtime/pages/integrations/audit.vue +7 -6
- package/dist/runtime/pages/integrations/credentials.vue +9 -21
- package/dist/runtime/pages/integrations/index.vue +55 -8
- package/dist/runtime/pages/integrations/runs.vue +116 -7
- package/dist/runtime/pages/integrations/secrets.vue +2 -1
- package/dist/runtime/pages/integrations/templates/[slug].vue +2 -1
- package/dist/runtime/pages/integrations/templates/index.vue +18 -15
- package/dist/runtime/pages/integrations/workflows/[id].vue +155 -20
- package/dist/runtime/types/integrations.d.ts +5 -0
- package/dist/runtime/utils/apiError.d.ts +21 -1
- package/dist/runtime/utils/apiError.js +1 -1
- package/dist/runtime/utils/clipboard.d.ts +33 -0
- package/dist/runtime/utils/clipboard.js +11 -0
- package/dist/runtime/utils/deepClone.d.ts +41 -0
- package/dist/runtime/utils/deepClone.js +3 -0
- package/dist/runtime/utils/formatDuration.d.ts +44 -0
- package/dist/runtime/utils/formatDuration.js +13 -0
- package/dist/runtime/utils/nodeDisplayName.d.ts +22 -0
- package/dist/runtime/utils/nodeDisplayName.js +6 -0
- package/dist/runtime/utils/notify.d.ts +1 -1
- package/dist/runtime/utils/runEnvelope.d.ts +31 -0
- package/dist/runtime/utils/runEnvelope.js +12 -0
- package/dist/runtime/utils/runFeedQuery.d.ts +135 -0
- package/dist/runtime/utils/runFeedQuery.js +66 -0
- package/dist/runtime/utils/runOutputs.d.ts +33 -0
- package/dist/runtime/utils/runOutputs.js +10 -0
- package/dist/runtime/utils/validationFindings.d.ts +26 -3
- package/dist/runtime/utils/validationFindings.js +18 -3
- package/package.json +1 -1
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"integration.audit.table.column.actor": "Akteur",
|
|
29
29
|
"integration.audit.table.column.resource": "Ressource",
|
|
30
30
|
"integration.audit.table.column.when": "Wann",
|
|
31
|
+
"integration.audit.toast.copyFailed": "Kopieren fehlgeschlagen",
|
|
31
32
|
"integration.audit.toast.copied": "Kopiert",
|
|
32
33
|
"integration.canvas.badge.trigger": "Trigger",
|
|
33
34
|
"integration.canvas.color.amber": "Bernstein",
|
|
@@ -229,6 +230,7 @@
|
|
|
229
230
|
"integration.credentials.sftpImport.empty": "Keine aktiven Plattform-SFTP-Konten. Zuerst eines unter Integration Studio → SFTP anlegen.",
|
|
230
231
|
"integration.credentials.sftpImport.error.importFailed": "Import fehlgeschlagen.",
|
|
231
232
|
"integration.credentials.sftpImport.error.readPassword": "Das Kontopasswort konnte nicht gelesen werden.",
|
|
233
|
+
"integration.credentials.sftpImport.state.loading": "SFTP-Konten werden geladen…",
|
|
232
234
|
"integration.credentials.sftpImport.title": "Plattform-SFTP-Konto importieren",
|
|
233
235
|
"integration.credentials.shared.action.testConnection": "Verbindung testen",
|
|
234
236
|
"integration.credentials.shared.authKind.apiKey": "API-Key",
|
|
@@ -263,6 +265,7 @@
|
|
|
263
265
|
"integration.dashboard.attention.healthy": "Alle Workflows in Ordnung.",
|
|
264
266
|
"integration.dashboard.attention.missedRuns": "{n} verpasster Run | {n} verpasste Runs",
|
|
265
267
|
"integration.dashboard.attention.missedRuns.hint": "Trigger haben ausgelöst, während ihr Workflow nicht laufen konnte — prüfen und erneut ausführen.",
|
|
268
|
+
"integration.dashboard.attention.state.loading": "Es wird geprüft, was Aufmerksamkeit erfordert…",
|
|
266
269
|
"integration.dashboard.attention.title": "Erfordert Aufmerksamkeit",
|
|
267
270
|
"integration.dashboard.head.title": "Dashboard · Integration Studio",
|
|
268
271
|
"integration.dashboard.header.description": "Alles, was die Revenue Cloud mit der Außenwelt verbindet.",
|
|
@@ -276,7 +279,9 @@
|
|
|
276
279
|
"integration.dashboard.kpi.runningNow.sub": "laufende Runs",
|
|
277
280
|
"integration.dashboard.kpi.scheduled.label": "Geplant",
|
|
278
281
|
"integration.dashboard.kpi.scheduled.sub": "aktive Zeitplan-Trigger",
|
|
282
|
+
"integration.dashboard.kpi.state.loading": "Kennzahlen werden geladen…",
|
|
279
283
|
"integration.dashboard.runs.empty": "Noch keine Runs.",
|
|
284
|
+
"integration.dashboard.runs.state.loading": "Letzte Runs werden geladen…",
|
|
280
285
|
"integration.dashboard.runs.title": "Letzte Runs",
|
|
281
286
|
"integration.dashboard.surface.events.hint": "Live-Events der Plattform, die Workflows abonnieren.",
|
|
282
287
|
"integration.dashboard.surface.events.label": "Event-Stream",
|
|
@@ -288,6 +293,7 @@
|
|
|
288
293
|
"integration.dashboard.surface.webhooks.hint": "Eingehende HTTP-Endpoints, die Workflows auslösen.",
|
|
289
294
|
"integration.dashboard.surface.webhooks.label": "Webhooks",
|
|
290
295
|
"integration.dashboard.templates.empty": "Noch keine Vorlagen registriert.",
|
|
296
|
+
"integration.dashboard.templates.state.loading": "Vorlagen werden geladen…",
|
|
291
297
|
"integration.dashboard.templates.title": "Mit einer Vorlage starten",
|
|
292
298
|
"integration.deadLetters.action.discard": "Verwerfen",
|
|
293
299
|
"integration.deadLetters.action.replay": "Wiederholen",
|
|
@@ -300,6 +306,7 @@
|
|
|
300
306
|
"integration.deadLetters.panel.title": "Verpasste Runs",
|
|
301
307
|
"integration.deadLetters.reason.fallback": "Kein Grund erfasst.",
|
|
302
308
|
"integration.deadLetters.state.empty": "Keine verpassten Runs. Jeder Trigger hat einen Run ausgelöst.",
|
|
309
|
+
"integration.deadLetters.state.loading": "Verpasste Runs werden geladen…",
|
|
303
310
|
"integration.deadLetters.status.discarded": "verworfen",
|
|
304
311
|
"integration.deadLetters.status.pending": "wartet",
|
|
305
312
|
"integration.deadLetters.status.replayed": "wiederholt",
|
|
@@ -317,7 +324,8 @@
|
|
|
317
324
|
"integration.editor.action.discard.label": "Verwerfen",
|
|
318
325
|
"integration.editor.action.discard.title": "Nicht gespeicherte Änderungen verwerfen",
|
|
319
326
|
"integration.editor.action.duplicate.label": "Duplizieren",
|
|
320
|
-
"integration.editor.action.
|
|
327
|
+
"integration.editor.action.more.aria": "Weitere Aktionen für diesen Workflow",
|
|
328
|
+
"integration.editor.action.more.label": "Aktionen",
|
|
321
329
|
"integration.editor.action.pause.title": "Workflow pausieren",
|
|
322
330
|
"integration.editor.action.retry": "Erneut versuchen",
|
|
323
331
|
"integration.editor.action.save.label": "Speichern",
|
|
@@ -433,6 +441,7 @@
|
|
|
433
441
|
"integration.editor.tab.editor": "Editor",
|
|
434
442
|
"integration.editor.tab.history": "Verlauf",
|
|
435
443
|
"integration.editor.tab.runs": "Runs",
|
|
444
|
+
"integration.editor.toast.deleted": "„{name}“ gelöscht",
|
|
436
445
|
"integration.editor.toast.duplicated": "Dupliziert als „{name}“",
|
|
437
446
|
"integration.editor.tool.addGroup.label": "Gruppe",
|
|
438
447
|
"integration.editor.tool.addGroup.tooltip": "Gruppenrahmen hinzufügen — hineingezogene Nodes treten ihr bei",
|
|
@@ -472,6 +481,7 @@
|
|
|
472
481
|
"integration.history.preview.title.current": "Aktuelle Version · Revision {revision}",
|
|
473
482
|
"integration.history.preview.title.revision": "Revision {revision} (schreibgeschützt)",
|
|
474
483
|
"integration.history.state.empty": "Noch keine archivierten Revisionen — speichern Sie eine Änderung, um die erste Momentaufnahme zu erstellen.",
|
|
484
|
+
"integration.history.state.loading": "Versionsverlauf wird geladen…",
|
|
475
485
|
"integration.history.toast.loadRevisionFailed": "Die Revision konnte nicht geladen werden.",
|
|
476
486
|
"integration.history.toast.restoreFailed": "Die Revision konnte nicht wiederhergestellt werden.",
|
|
477
487
|
"integration.history.toast.restored": "Revision {revision} wiederhergestellt",
|
|
@@ -728,6 +738,7 @@
|
|
|
728
738
|
"integration.nodeInspector.toast.configCopyFailed": "Konfiguration konnte nicht kopiert werden",
|
|
729
739
|
"integration.nodeInspector.toast.configPasted": "Konfiguration eingefügt",
|
|
730
740
|
"integration.nodeInspector.toast.expressionCopied": "Ausdruck kopiert. Klicken Sie zuerst in ein Feld, um ihn direkt einzufügen.",
|
|
741
|
+
"integration.nodeInspector.toast.expressionCopyFailed": "Ausdruck konnte nicht kopiert werden. Klicken Sie in ein Feld, um ihn direkt einzufügen.",
|
|
731
742
|
"integration.nodeInspector.toast.rotateFailed": "Secret konnte nicht neu erzeugt werden.",
|
|
732
743
|
"integration.nodeInspector.toast.rotateNoSecret": "Der Endpoint hat kein Secret zurückgegeben.",
|
|
733
744
|
"integration.nodeInspector.toast.samplePinned": "Beispielausgabe angeheftet",
|
|
@@ -908,13 +919,15 @@
|
|
|
908
919
|
"integration.runs.payload.parseError": "Das JSON lässt sich nicht parsen — beheben Sie den Fehler, bevor Sie zur Formularansicht zurückwechseln.",
|
|
909
920
|
"integration.runs.response.action.viewRun": "Run ansehen",
|
|
910
921
|
"integration.runs.response.action.viewRunWithId": "Run #{id} ansehen",
|
|
911
|
-
"integration.runs.response.async.started": "Run wurde gestartet
|
|
912
|
-
"integration.runs.response.async.startedWithId": "Run #{id} wurde gestartet
|
|
913
|
-
"integration.runs.response.description.async": "
|
|
922
|
+
"integration.runs.response.async.started": "Run wurde gestartet.",
|
|
923
|
+
"integration.runs.response.async.startedWithId": "Run #{id} wurde gestartet.",
|
|
924
|
+
"integration.runs.response.description.async": "Im Hintergrund gestartet",
|
|
914
925
|
"integration.runs.response.description.sync": "Synchrones Run-Ergebnis",
|
|
915
|
-
"integration.runs.response.
|
|
926
|
+
"integration.runs.response.following": "Warten, bis der Run fertig ist…",
|
|
916
927
|
"integration.runs.response.loading.async": "Wird gestartet…",
|
|
917
928
|
"integration.runs.response.loading.sync": "Wird ausgeführt…",
|
|
929
|
+
"integration.runs.response.nothingReturned": "Der Run hat nichts zurückgegeben.",
|
|
930
|
+
"integration.runs.response.runNumber": "Run #{id}",
|
|
918
931
|
"integration.runs.response.title.async": "Run gestartet",
|
|
919
932
|
"integration.runs.response.title.sync": "Run-Antwort",
|
|
920
933
|
"integration.runs.status.cancelled": "abgebrochen",
|
|
@@ -929,6 +942,8 @@
|
|
|
929
942
|
"integration.runs.table.column.trigger": "Trigger",
|
|
930
943
|
"integration.runs.table.column.workflow": "Workflow",
|
|
931
944
|
"integration.runs.table.empty": "Noch keine Runs — starten Sie einen Workflow, um diese Ansicht zu füllen.",
|
|
945
|
+
"integration.runs.table.empty.narrowed": "Keine Runs passen zu dieser Einschränkung.",
|
|
946
|
+
"integration.runs.table.filter.all": "Alle",
|
|
932
947
|
"integration.runs.table.search.placeholder": "Runs durchsuchen…",
|
|
933
948
|
"integration.runs.tabs.runs.label": "Runs",
|
|
934
949
|
"integration.runs.toast.action.requested": "{action} angefordert",
|
|
@@ -991,6 +1006,7 @@
|
|
|
991
1006
|
"integration.secrets.error.loadFailed": "Secrets konnten nicht geladen werden.",
|
|
992
1007
|
"integration.secrets.error.valueRequired": "Der Wert ist erforderlich.",
|
|
993
1008
|
"integration.secrets.form.error.invalidKey": "Der Schlüssel muss ^[A-Z0-9_]+$ entsprechen (Großbuchstaben, Ziffern, Unterstriche).",
|
|
1009
|
+
"integration.secrets.form.error.saveFailed": "Das Secret konnte nicht gespeichert werden.",
|
|
994
1010
|
"integration.secrets.form.key.label": "Schlüssel",
|
|
995
1011
|
"integration.secrets.form.key.patternLabel": "Muster:",
|
|
996
1012
|
"integration.secrets.form.value.hide": "Wert ausblenden",
|
|
@@ -1129,7 +1145,12 @@
|
|
|
1129
1145
|
"integration.workflows.create.template.noMatch": "Keine Treffer für „{query}“.",
|
|
1130
1146
|
"integration.workflows.create.template.search.aria": "Vorlagen durchsuchen",
|
|
1131
1147
|
"integration.workflows.create.template.search.placeholder": "Vorlagen durchsuchen…",
|
|
1148
|
+
"integration.workflows.create.template.state.loading": "Vorlagen werden geladen…",
|
|
1132
1149
|
"integration.workflows.create.toast.templateError": "Der Workflow konnte nicht aus dieser Vorlage erstellt werden.",
|
|
1150
|
+
"integration.workflows.delete.action.deleting": "Wird gelöscht…",
|
|
1151
|
+
"integration.workflows.delete.dialog.description": "und der gesamte Revisionsverlauf werden endgültig gelöscht.",
|
|
1152
|
+
"integration.workflows.delete.dialog.title": "Workflow löschen?",
|
|
1153
|
+
"integration.workflows.delete.error.generic": "Der Workflow konnte nicht gelöscht werden.",
|
|
1133
1154
|
"integration.workflows.duplicate.dialog.description": "Erstellt eine pausierte Kopie von „{name}“ mit allen Triggern aus.",
|
|
1134
1155
|
"integration.workflows.duplicate.dialog.title": "Workflow duplizieren",
|
|
1135
1156
|
"integration.workflows.duplicate.error.generic": "Der Workflow konnte nicht dupliziert werden.",
|
|
@@ -1175,9 +1196,6 @@
|
|
|
1175
1196
|
"integration.workflows.table.column.status": "Status",
|
|
1176
1197
|
"integration.workflows.table.column.triggers": "Trigger",
|
|
1177
1198
|
"integration.workflows.table.column.updated": "Aktualisiert",
|
|
1178
|
-
"integration.workflows.table.deleteDialog.action.deleting": "Wird gelöscht…",
|
|
1179
|
-
"integration.workflows.table.deleteDialog.description": "und der gesamte Revisionsverlauf werden endgültig gelöscht.",
|
|
1180
|
-
"integration.workflows.table.deleteDialog.title": "Workflow löschen?",
|
|
1181
1199
|
"integration.workflows.table.group.noTags": "Keine Tags",
|
|
1182
1200
|
"integration.workflows.table.lastRun.aria.never": "{name}, letzter Run: Nie ausgeführt",
|
|
1183
1201
|
"integration.workflows.table.menu.action.activate": "Aktivieren",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"integration.audit.table.column.actor": "Actor",
|
|
29
29
|
"integration.audit.table.column.resource": "Resource",
|
|
30
30
|
"integration.audit.table.column.when": "When",
|
|
31
|
+
"integration.audit.toast.copyFailed": "Could not copy",
|
|
31
32
|
"integration.audit.toast.copied": "Copied",
|
|
32
33
|
"integration.canvas.badge.trigger": "Trigger",
|
|
33
34
|
"integration.canvas.color.amber": "Amber",
|
|
@@ -229,6 +230,7 @@
|
|
|
229
230
|
"integration.credentials.sftpImport.empty": "No active platform SFTP accounts. Create one under Integration Studio → SFTP first.",
|
|
230
231
|
"integration.credentials.sftpImport.error.importFailed": "Import failed.",
|
|
231
232
|
"integration.credentials.sftpImport.error.readPassword": "Could not read the account password.",
|
|
233
|
+
"integration.credentials.sftpImport.state.loading": "Loading the SFTP accounts…",
|
|
232
234
|
"integration.credentials.sftpImport.title": "Import platform SFTP account",
|
|
233
235
|
"integration.credentials.shared.action.testConnection": "Connect",
|
|
234
236
|
"integration.credentials.shared.authKind.apiKey": "API Key",
|
|
@@ -263,6 +265,7 @@
|
|
|
263
265
|
"integration.dashboard.attention.healthy": "All workflows healthy.",
|
|
264
266
|
"integration.dashboard.attention.missedRuns": "{n} missed run | {n} missed runs",
|
|
265
267
|
"integration.dashboard.attention.missedRuns.hint": "Triggers fired while their workflow couldn't run — review & replay.",
|
|
268
|
+
"integration.dashboard.attention.state.loading": "Checking what needs attention…",
|
|
266
269
|
"integration.dashboard.attention.title": "Needs attention",
|
|
267
270
|
"integration.dashboard.head.title": "Dashboard · Integration Studio",
|
|
268
271
|
"integration.dashboard.header.description": "Everything that connects Revenue Cloud to the outside world.",
|
|
@@ -276,7 +279,9 @@
|
|
|
276
279
|
"integration.dashboard.kpi.runningNow.sub": "live executions in flight",
|
|
277
280
|
"integration.dashboard.kpi.scheduled.label": "Scheduled",
|
|
278
281
|
"integration.dashboard.kpi.scheduled.sub": "scheduled triggers active",
|
|
282
|
+
"integration.dashboard.kpi.state.loading": "Loading the key figures…",
|
|
279
283
|
"integration.dashboard.runs.empty": "No runs yet.",
|
|
284
|
+
"integration.dashboard.runs.state.loading": "Loading the latest executions…",
|
|
280
285
|
"integration.dashboard.runs.title": "Latest executions",
|
|
281
286
|
"integration.dashboard.surface.events.hint": "Live platform events that workflows subscribe to.",
|
|
282
287
|
"integration.dashboard.surface.events.label": "Event Stream",
|
|
@@ -288,6 +293,7 @@
|
|
|
288
293
|
"integration.dashboard.surface.webhooks.hint": "Inbound HTTP endpoints that trigger workflows.",
|
|
289
294
|
"integration.dashboard.surface.webhooks.label": "Webhooks",
|
|
290
295
|
"integration.dashboard.templates.empty": "No templates registered yet.",
|
|
296
|
+
"integration.dashboard.templates.state.loading": "Loading templates…",
|
|
291
297
|
"integration.dashboard.templates.title": "Start from a template",
|
|
292
298
|
"integration.deadLetters.action.discard": "Discard",
|
|
293
299
|
"integration.deadLetters.action.replay": "Replay",
|
|
@@ -300,6 +306,7 @@
|
|
|
300
306
|
"integration.deadLetters.panel.title": "Missed runs",
|
|
301
307
|
"integration.deadLetters.reason.fallback": "No reason recorded.",
|
|
302
308
|
"integration.deadLetters.state.empty": "No missed runs. Every trigger firing made it into a run.",
|
|
309
|
+
"integration.deadLetters.state.loading": "Loading the missed runs…",
|
|
303
310
|
"integration.deadLetters.status.discarded": "discarded",
|
|
304
311
|
"integration.deadLetters.status.pending": "waiting",
|
|
305
312
|
"integration.deadLetters.status.replayed": "replayed",
|
|
@@ -317,7 +324,8 @@
|
|
|
317
324
|
"integration.editor.action.discard.label": "Cancel",
|
|
318
325
|
"integration.editor.action.discard.title": "Discard unsaved changes",
|
|
319
326
|
"integration.editor.action.duplicate.label": "Duplicate",
|
|
320
|
-
"integration.editor.action.
|
|
327
|
+
"integration.editor.action.more.aria": "More actions for this workflow",
|
|
328
|
+
"integration.editor.action.more.label": "Actions",
|
|
321
329
|
"integration.editor.action.pause.title": "Pause this workflow",
|
|
322
330
|
"integration.editor.action.retry": "Retry",
|
|
323
331
|
"integration.editor.action.save.label": "Save",
|
|
@@ -433,6 +441,7 @@
|
|
|
433
441
|
"integration.editor.tab.editor": "Editor",
|
|
434
442
|
"integration.editor.tab.history": "History",
|
|
435
443
|
"integration.editor.tab.runs": "Runs",
|
|
444
|
+
"integration.editor.toast.deleted": "Deleted “{name}”",
|
|
436
445
|
"integration.editor.toast.duplicated": "Duplicated as “{name}”",
|
|
437
446
|
"integration.editor.tool.addGroup.label": "Group",
|
|
438
447
|
"integration.editor.tool.addGroup.tooltip": "Add group frame — nodes dropped inside join it",
|
|
@@ -472,6 +481,7 @@
|
|
|
472
481
|
"integration.history.preview.title.current": "Current version · revision {revision}",
|
|
473
482
|
"integration.history.preview.title.revision": "Revision {revision} (read-only)",
|
|
474
483
|
"integration.history.state.empty": "No archived revisions yet — save a change to create the first snapshot.",
|
|
484
|
+
"integration.history.state.loading": "Loading the version history…",
|
|
475
485
|
"integration.history.toast.loadRevisionFailed": "Could not load the revision.",
|
|
476
486
|
"integration.history.toast.restoreFailed": "Could not restore the revision.",
|
|
477
487
|
"integration.history.toast.restored": "Revision {revision} restored",
|
|
@@ -728,6 +738,7 @@
|
|
|
728
738
|
"integration.nodeInspector.toast.configCopyFailed": "Could not copy config",
|
|
729
739
|
"integration.nodeInspector.toast.configPasted": "Config pasted",
|
|
730
740
|
"integration.nodeInspector.toast.expressionCopied": "Expression copied. Click into a field first to insert it directly.",
|
|
741
|
+
"integration.nodeInspector.toast.expressionCopyFailed": "Could not copy the expression. Click into a field to insert it directly.",
|
|
731
742
|
"integration.nodeInspector.toast.rotateFailed": "Could not rotate the secret.",
|
|
732
743
|
"integration.nodeInspector.toast.rotateNoSecret": "The endpoint did not return a secret.",
|
|
733
744
|
"integration.nodeInspector.toast.samplePinned": "Sample output pinned",
|
|
@@ -908,13 +919,15 @@
|
|
|
908
919
|
"integration.runs.payload.parseError": "The JSON does not parse — fix it before switching back to the form.",
|
|
909
920
|
"integration.runs.response.action.viewRun": "View run",
|
|
910
921
|
"integration.runs.response.action.viewRunWithId": "View run #{id}",
|
|
911
|
-
"integration.runs.response.async.started": "Run started
|
|
912
|
-
"integration.runs.response.async.startedWithId": "Run #{id} started
|
|
913
|
-
"integration.runs.response.description.async": "
|
|
922
|
+
"integration.runs.response.async.started": "Run started.",
|
|
923
|
+
"integration.runs.response.async.startedWithId": "Run #{id} started.",
|
|
924
|
+
"integration.runs.response.description.async": "Started in the background",
|
|
914
925
|
"integration.runs.response.description.sync": "Synchronous run result",
|
|
915
|
-
"integration.runs.response.
|
|
926
|
+
"integration.runs.response.following": "Waiting for the run to finish…",
|
|
916
927
|
"integration.runs.response.loading.async": "Starting…",
|
|
917
928
|
"integration.runs.response.loading.sync": "Running…",
|
|
929
|
+
"integration.runs.response.nothingReturned": "The run returned nothing.",
|
|
930
|
+
"integration.runs.response.runNumber": "Run #{id}",
|
|
918
931
|
"integration.runs.response.title.async": "Run started",
|
|
919
932
|
"integration.runs.response.title.sync": "Run response",
|
|
920
933
|
"integration.runs.status.cancelled": "cancelled",
|
|
@@ -929,6 +942,8 @@
|
|
|
929
942
|
"integration.runs.table.column.trigger": "Trigger",
|
|
930
943
|
"integration.runs.table.column.workflow": "Workflow",
|
|
931
944
|
"integration.runs.table.empty": "No runs yet — kick off a workflow to populate this view.",
|
|
945
|
+
"integration.runs.table.empty.narrowed": "No runs match this narrowing.",
|
|
946
|
+
"integration.runs.table.filter.all": "All",
|
|
932
947
|
"integration.runs.table.search.placeholder": "Search runs…",
|
|
933
948
|
"integration.runs.tabs.runs.label": "Runs",
|
|
934
949
|
"integration.runs.toast.action.requested": "{action} requested",
|
|
@@ -991,6 +1006,7 @@
|
|
|
991
1006
|
"integration.secrets.error.loadFailed": "Could not load secrets.",
|
|
992
1007
|
"integration.secrets.error.valueRequired": "Value is required.",
|
|
993
1008
|
"integration.secrets.form.error.invalidKey": "Key must match ^[A-Z0-9_]+$ (uppercase letters, digits, underscores).",
|
|
1009
|
+
"integration.secrets.form.error.saveFailed": "Could not save the secret.",
|
|
994
1010
|
"integration.secrets.form.key.label": "Key",
|
|
995
1011
|
"integration.secrets.form.key.patternLabel": "Pattern:",
|
|
996
1012
|
"integration.secrets.form.value.hide": "Hide value",
|
|
@@ -1129,7 +1145,12 @@
|
|
|
1129
1145
|
"integration.workflows.create.template.noMatch": "Nothing matches “{query}”.",
|
|
1130
1146
|
"integration.workflows.create.template.search.aria": "Search templates",
|
|
1131
1147
|
"integration.workflows.create.template.search.placeholder": "Search templates…",
|
|
1148
|
+
"integration.workflows.create.template.state.loading": "Loading templates…",
|
|
1132
1149
|
"integration.workflows.create.toast.templateError": "Could not create the workflow from this template.",
|
|
1150
|
+
"integration.workflows.delete.action.deleting": "Deleting…",
|
|
1151
|
+
"integration.workflows.delete.dialog.description": "and all its revision history will be permanently deleted.",
|
|
1152
|
+
"integration.workflows.delete.dialog.title": "Delete workflow?",
|
|
1153
|
+
"integration.workflows.delete.error.generic": "The workflow could not be deleted.",
|
|
1133
1154
|
"integration.workflows.duplicate.dialog.description": "Creates a paused copy of “{name}” with all triggers off.",
|
|
1134
1155
|
"integration.workflows.duplicate.dialog.title": "Duplicate workflow",
|
|
1135
1156
|
"integration.workflows.duplicate.error.generic": "Could not duplicate the workflow.",
|
|
@@ -1175,9 +1196,6 @@
|
|
|
1175
1196
|
"integration.workflows.table.column.status": "Status",
|
|
1176
1197
|
"integration.workflows.table.column.triggers": "Triggers",
|
|
1177
1198
|
"integration.workflows.table.column.updated": "Updated",
|
|
1178
|
-
"integration.workflows.table.deleteDialog.action.deleting": "Deleting…",
|
|
1179
|
-
"integration.workflows.table.deleteDialog.description": "and all its revision history will be permanently deleted.",
|
|
1180
|
-
"integration.workflows.table.deleteDialog.title": "Delete workflow?",
|
|
1181
1199
|
"integration.workflows.table.group.noTags": "No tags",
|
|
1182
1200
|
"integration.workflows.table.lastRun.aria.never": "{name} last run: Never run",
|
|
1183
1201
|
"integration.workflows.table.menu.action.activate": "Activate",
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
Play as Run
|
|
11
11
|
} from "#solar-icons";
|
|
12
12
|
import { Badge, Button } from "@revenexx/studio";
|
|
13
|
-
import {
|
|
13
|
+
import { copyToClipboard } from "../../utils/clipboard";
|
|
14
14
|
const t = useIntegrationsT();
|
|
15
15
|
useHead({ title: () => t("integration.audit.head.title") });
|
|
16
16
|
const { entries, loading, error, hasMore, load, loadMore } = useIntegrationsAudit();
|
|
@@ -76,11 +76,12 @@ const columns = computed(() => [
|
|
|
76
76
|
{ key: "when", label: t("integration.audit.table.column.when"), width: "180px", sortable: true, sortGetter: (e) => e.created_at }
|
|
77
77
|
]);
|
|
78
78
|
const selected = ref(null);
|
|
79
|
-
function copy(
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
function copy(text) {
|
|
80
|
+
if (!text) return;
|
|
81
|
+
void copyToClipboard(text, {
|
|
82
|
+
copied: t("integration.audit.toast.copied"),
|
|
83
|
+
failed: t("integration.audit.toast.copyFailed")
|
|
84
|
+
});
|
|
84
85
|
}
|
|
85
86
|
const panelEl = ref(null);
|
|
86
87
|
let opener = null;
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
SelectValue
|
|
32
32
|
} from "@revenexx/studio";
|
|
33
33
|
import { toast } from "../../utils/notify";
|
|
34
|
-
import { apiFieldErrors,
|
|
34
|
+
import { apiFieldErrors, errorReason } from "../../utils/apiError";
|
|
35
35
|
import { CREDENTIAL_STATES, credentialState, credentialStateLabel } from "../../utils/credentialState";
|
|
36
36
|
import { hasRevenexxSource } from "../../utils/revenexxCredentialSource";
|
|
37
37
|
import { resolveLocalized } from "../../utils/localize";
|
|
@@ -177,35 +177,23 @@ async function submit() {
|
|
|
177
177
|
}
|
|
178
178
|
} catch (e) {
|
|
179
179
|
fieldErrors.value = apiFieldErrors(e);
|
|
180
|
-
saveError.value =
|
|
180
|
+
saveError.value = errorReason(e, t("integration.credentials.error.save"));
|
|
181
181
|
toast.error(saveError.value);
|
|
182
182
|
} finally {
|
|
183
183
|
saving.value = false;
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
const connecting = ref(null);
|
|
187
|
+
const { open: openAuthorisation } = useOAuthConnect(async (outcome) => {
|
|
188
|
+
await load(true);
|
|
189
|
+
if (outcome === "completed") toast.success(t("integration.credentials.toast.connected"));
|
|
190
|
+
});
|
|
187
191
|
async function connect(c) {
|
|
188
192
|
connecting.value = c.id;
|
|
189
193
|
try {
|
|
190
|
-
|
|
191
|
-
const popup = window.open(authorizeUrl, "oauth-connect", "width=600,height=720");
|
|
192
|
-
const onMessage = async (ev) => {
|
|
193
|
-
if (ev.data?.type === "integrations-oauth-complete") {
|
|
194
|
-
window.removeEventListener("message", onMessage);
|
|
195
|
-
await load(true);
|
|
196
|
-
toast.success(t("integration.credentials.toast.connected"));
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
window.addEventListener("message", onMessage);
|
|
200
|
-
const poll = window.setInterval(async () => {
|
|
201
|
-
if (popup?.closed) {
|
|
202
|
-
window.clearInterval(poll);
|
|
203
|
-
window.removeEventListener("message", onMessage);
|
|
204
|
-
await load(true);
|
|
205
|
-
}
|
|
206
|
-
}, 1e3);
|
|
194
|
+
openAuthorisation(await oauthAuthorizeUrl(c.id));
|
|
207
195
|
} catch (e) {
|
|
208
|
-
toast.error(e
|
|
196
|
+
toast.error(errorReason(e, t("integration.credentials.error.oauthConnect")));
|
|
209
197
|
} finally {
|
|
210
198
|
connecting.value = null;
|
|
211
199
|
}
|
|
@@ -221,7 +209,7 @@ async function confirmDelete() {
|
|
|
221
209
|
toast.success(t("integration.credentials.toast.deleted"));
|
|
222
210
|
pendingDelete.value = null;
|
|
223
211
|
} catch (e) {
|
|
224
|
-
toast.error(e
|
|
212
|
+
toast.error(errorReason(e, t("integration.credentials.error.delete")));
|
|
225
213
|
} finally {
|
|
226
214
|
deleting.value = false;
|
|
227
215
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed, ref, watch } from "vue";
|
|
3
|
+
import LoadingAnnouncement from "../../components/Integrations/LoadingAnnouncement.vue";
|
|
3
4
|
import SurfaceCard from "../../components/Integrations/SurfaceCard.vue";
|
|
4
5
|
import TemplateCard from "../../components/Integrations/TemplateCard.vue";
|
|
5
6
|
import WorkflowCreateDialog from "../../components/Integrations/WorkflowCreateDialog.vue";
|
|
6
7
|
import { Pulse as Activity, DangerTriangle as AlertTriangle, ArrowRight, Box as Boxes, ClockCircle as Clock, Database, Layers, AddCircle as Plus, Radio, MagicStick as Sparkles, LinkRound as Webhook, Programming as Workflow } from "#solar-icons";
|
|
7
8
|
import { Badge, Button } from "@revenexx/studio";
|
|
9
|
+
import { formatDuration } from "../../utils/formatDuration";
|
|
8
10
|
import { servedPaths } from "../../utils/servedPaths";
|
|
9
11
|
import { RUN_STATUS_COLUMN_WIDTH, runStatusClass, runStatusLabel } from "../../utils/statusStyle";
|
|
10
12
|
const LATEST_RUN_COLUMNS = `${RUN_STATUS_COLUMN_WIDTH} minmax(0,1fr) 100px 70px`;
|
|
@@ -22,10 +24,19 @@ const { startingPoints, loading: templatesLoading, load: loadTemplates, ensureDe
|
|
|
22
24
|
watch(() => startingPoints.value.map((t2) => t2.slug).join(","), () => {
|
|
23
25
|
if (startingPoints.value.length) void ensureDetails(startingPoints.value.map((t2) => t2.slug));
|
|
24
26
|
}, { immediate: true });
|
|
25
|
-
const { activeCount: schedulesActive, load: loadSchedules } = useIntegrationsSchedules();
|
|
27
|
+
const { activeCount: schedulesActive, loading: schedulesLoading, load: loadSchedules } = useIntegrationsSchedules();
|
|
26
28
|
const { pendingCount: missedRuns, globalLoading: missedLoading, loadGlobal: loadMissedRuns } = useIntegrationsDeadLetters();
|
|
27
|
-
const
|
|
29
|
+
const kpiWaits = computed(() => ({
|
|
30
|
+
activeWorkflows: workflowsLoading.value && !workflows.value.length,
|
|
31
|
+
runningNow: runsLoading.value && !latestRunPerWorkflow.value.length,
|
|
32
|
+
scheduled: schedulesLoading.value && schedulesActive.value === 0,
|
|
33
|
+
missedRuns: missedLoading.value && missedRuns.value === 0
|
|
34
|
+
}));
|
|
28
35
|
const latestLoading = computed(() => runsLoading.value && !latestRunPerWorkflow.value.length);
|
|
36
|
+
const awaitingKpis = computed(() => Object.values(kpiWaits.value).some(Boolean));
|
|
37
|
+
const awaitingLatestRuns = computed(() => latestLoading.value && !latestRunPerWorkflow.value.length);
|
|
38
|
+
const awaitingAttention = computed(() => (missedLoading.value || latestLoading.value) && !missedRuns.value && !failedRecent.value.length);
|
|
39
|
+
const awaitingStartingPoints = computed(() => templatesLoading.value && !startingPoints.value.length);
|
|
29
40
|
const createOpen = ref(false);
|
|
30
41
|
const NuxtLinkComp = resolveComponent("NuxtLink");
|
|
31
42
|
onMounted(() => {
|
|
@@ -51,6 +62,7 @@ function formatRelative(iso) {
|
|
|
51
62
|
const kpis = computed(() => [
|
|
52
63
|
{
|
|
53
64
|
key: "activeWorkflows",
|
|
65
|
+
waiting: kpiWaits.value.activeWorkflows,
|
|
54
66
|
label: t("integration.dashboard.kpi.activeWorkflows.label"),
|
|
55
67
|
value: activeWorkflows.value,
|
|
56
68
|
// A plural key, so the count is the second argument. Called without one it
|
|
@@ -61,6 +73,7 @@ const kpis = computed(() => [
|
|
|
61
73
|
},
|
|
62
74
|
{
|
|
63
75
|
key: "runningNow",
|
|
76
|
+
waiting: kpiWaits.value.runningNow,
|
|
64
77
|
label: t("integration.dashboard.kpi.runningNow.label"),
|
|
65
78
|
value: runningCount.value,
|
|
66
79
|
sub: t("integration.dashboard.kpi.runningNow.sub"),
|
|
@@ -69,6 +82,7 @@ const kpis = computed(() => [
|
|
|
69
82
|
},
|
|
70
83
|
{
|
|
71
84
|
key: "scheduled",
|
|
85
|
+
waiting: kpiWaits.value.scheduled,
|
|
72
86
|
label: t("integration.dashboard.kpi.scheduled.label"),
|
|
73
87
|
value: schedulesActive.value,
|
|
74
88
|
sub: t("integration.dashboard.kpi.scheduled.sub"),
|
|
@@ -77,6 +91,7 @@ const kpis = computed(() => [
|
|
|
77
91
|
},
|
|
78
92
|
{
|
|
79
93
|
key: "missedRuns",
|
|
94
|
+
waiting: kpiWaits.value.missedRuns,
|
|
80
95
|
label: t("integration.dashboard.kpi.missedRuns.label"),
|
|
81
96
|
value: missedRuns.value,
|
|
82
97
|
sub: t("integration.dashboard.kpi.missedRuns.sub"),
|
|
@@ -124,13 +139,22 @@ function surfaceCards() {
|
|
|
124
139
|
contents — named "Missed runs" alone it would announce less than the
|
|
125
140
|
three tiles beside it. -->
|
|
126
141
|
<div role="group" :aria-label="t('integration.dashboard.kpi.aria.group')" class="grid gap-2 sm:grid-cols-2 lg:grid-cols-4">
|
|
142
|
+
<!-- Four panels on this page wait on four sources, so each says so under its
|
|
143
|
+
own name (PO-251). The tiles' own names drop their figure while this is
|
|
144
|
+
true: a tile named "Active workflows: 0" from an empty list does not read
|
|
145
|
+
as waiting, it reads as an answer. -->
|
|
146
|
+
<LoadingAnnouncement
|
|
147
|
+
:label="t('integration.dashboard.kpi.aria.group')"
|
|
148
|
+
:loading="awaitingKpis"
|
|
149
|
+
:text="t('integration.dashboard.kpi.state.loading')"
|
|
150
|
+
/>
|
|
127
151
|
<component
|
|
128
152
|
:is="k.to ? NuxtLinkComp : 'div'"
|
|
129
153
|
v-for="k in kpis"
|
|
130
154
|
:key="k.key"
|
|
131
155
|
:to="k.to"
|
|
132
156
|
:role="k.to ? void 0 : 'group'"
|
|
133
|
-
:aria-label="`${k.label}: ${k.value}`"
|
|
157
|
+
:aria-label="k.waiting ? k.label : `${k.label}: ${k.value}`"
|
|
134
158
|
class="block rounded-lg border border-black/[0.06] bg-white p-3"
|
|
135
159
|
:class="k.to ? 'transition hover:border-black/20' : ''"
|
|
136
160
|
>
|
|
@@ -139,7 +163,7 @@ function surfaceCards() {
|
|
|
139
163
|
<div class="text-mono text-muted-foreground truncate">
|
|
140
164
|
{{ k.label }}
|
|
141
165
|
</div>
|
|
142
|
-
<div v-if="
|
|
166
|
+
<div v-if="k.waiting" aria-hidden="true" class="my-1.5 h-6 w-12 rounded bg-black/[0.07] animate-pulse" />
|
|
143
167
|
<div v-else class="text-2xl font-semibold tabular-nums text-[#0B0522]">
|
|
144
168
|
{{ k.value }}
|
|
145
169
|
</div>
|
|
@@ -169,6 +193,11 @@ function surfaceCards() {
|
|
|
169
193
|
{{ t("integration.common.action.viewAll") }} <ArrowRight :size="11" />
|
|
170
194
|
</NuxtLink>
|
|
171
195
|
</div>
|
|
196
|
+
<LoadingAnnouncement
|
|
197
|
+
:label="t('integration.dashboard.runs.title')"
|
|
198
|
+
:loading="awaitingLatestRuns"
|
|
199
|
+
:text="t('integration.dashboard.runs.state.loading')"
|
|
200
|
+
/>
|
|
172
201
|
<div>
|
|
173
202
|
<!-- An entry is a link, not a div that answers a click: that is what
|
|
174
203
|
makes it reachable by keyboard, and it is what gives it a name —
|
|
@@ -199,14 +228,22 @@ function surfaceCards() {
|
|
|
199
228
|
<div class="text-sm text-muted-foreground tabular-nums truncate">
|
|
200
229
|
{{ formatRelative(r.startedAt) }}
|
|
201
230
|
</div>
|
|
231
|
+
<!-- The ellipsis is this panel's own answer and not the formatter's em
|
|
232
|
+
dash: an entry here is the latest run of a workflow, so a missing
|
|
233
|
+
duration means it is still going, where the runs table counts up a
|
|
234
|
+
live figure instead. The figure itself is the shared spelling
|
|
235
|
+
(PO-383) — this cell used to divide by a thousand on the spot and
|
|
236
|
+
print two decimals, which said `0.90s` for 900 ms and `63.00s` for a
|
|
237
|
+
step the run record called `1m 3s`. -->
|
|
202
238
|
<div class="text-sm text-muted-foreground tabular-nums text-right">
|
|
203
|
-
{{ r.durationMs == null ? "\u2026" :
|
|
239
|
+
{{ r.durationMs == null ? "\u2026" : formatDuration(r.durationMs) }}
|
|
204
240
|
</div>
|
|
205
241
|
</NuxtLink>
|
|
206
|
-
<template v-if="
|
|
242
|
+
<template v-if="awaitingLatestRuns">
|
|
207
243
|
<div
|
|
208
244
|
v-for="n in 6"
|
|
209
245
|
:key="`sk-run-${n}`"
|
|
246
|
+
aria-hidden="true"
|
|
210
247
|
class="grid items-center gap-2 border-b border-black/[0.04] px-3 py-2.5 last:border-b-0"
|
|
211
248
|
:style="{ gridTemplateColumns: LATEST_RUN_COLUMNS }"
|
|
212
249
|
>
|
|
@@ -235,7 +272,12 @@ function surfaceCards() {
|
|
|
235
272
|
<h3 class="text-sm font-semibold">{{ t("integration.dashboard.attention.title") }}</h3>
|
|
236
273
|
</div>
|
|
237
274
|
</div>
|
|
238
|
-
<
|
|
275
|
+
<LoadingAnnouncement
|
|
276
|
+
:label="t('integration.dashboard.attention.title')"
|
|
277
|
+
:loading="awaitingAttention"
|
|
278
|
+
:text="t('integration.dashboard.attention.state.loading')"
|
|
279
|
+
/>
|
|
280
|
+
<div v-if="awaitingAttention" aria-hidden="true" class="space-y-2 p-3">
|
|
239
281
|
<div v-for="n in 3" :key="`sk-att-${n}`" class="h-3 rounded bg-black/[0.07] animate-pulse" :class="n === 1 ? 'w-2/3' : n === 2 ? 'w-1/2' : 'w-3/5'" />
|
|
240
282
|
</div>
|
|
241
283
|
<div v-else-if="missedRuns || failedRecent.length">
|
|
@@ -305,7 +347,12 @@ function surfaceCards() {
|
|
|
305
347
|
{{ t("integration.common.action.seeAll") }} <ArrowRight :size="11" />
|
|
306
348
|
</NuxtLink>
|
|
307
349
|
</div>
|
|
308
|
-
<
|
|
350
|
+
<LoadingAnnouncement
|
|
351
|
+
:label="t('integration.dashboard.templates.title')"
|
|
352
|
+
:loading="awaitingStartingPoints"
|
|
353
|
+
:text="t('integration.dashboard.templates.state.loading')"
|
|
354
|
+
/>
|
|
355
|
+
<div v-if="awaitingStartingPoints" aria-hidden="true" class="grid gap-2 p-3 sm:grid-cols-2 lg:grid-cols-4">
|
|
309
356
|
<div v-for="n in 4" :key="`sk-tpl-${n}`" class="rounded-md border border-black/[0.06] bg-white p-3 space-y-2">
|
|
310
357
|
<div class="h-5 w-20 rounded bg-black/[0.07] animate-pulse" />
|
|
311
358
|
<div class="h-3 w-3/4 rounded bg-black/[0.07] animate-pulse" />
|