@revenexx/studio-integrations 3.8.4 → 3.8.5
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 +6 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +1 -1
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +65 -65
- package/dist/runtime/i18n/messages/de.json +7 -7
- package/dist/runtime/i18n/messages/en.json +7 -7
- package/dist/runtime/pages/integrations/workflows/[id].vue +30 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @revenexx/studio-integrations
|
|
2
2
|
|
|
3
|
+
## 3.8.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2c66daf: A run's record is now headed by the workflow and "Run #" with the run's number, instead of the identifier the engine gave the run. The engine's own fields — history length, workflow and run identifiers, workflow type, task queue — and, for a run still going, the stack trace now sit under "Technical details", folded until opened. The two ways back from a failed run are one header button, "Run again" ("Erneut ausführen"), that opens "Resume from the failed step" ("Ab fehlgeschlagenem Schritt fortsetzen") and "Run again from the start" ("Komplett neu ausführen"); the resume no longer stands on its own above the record, and a run row's menu uses the same two names. New message keys `integration.editor.action.rerun` and `integration.runs.detail.technical.title`; `integration.runs.confirm.resume` and `integration.runs.notice.started` are gone with the record's own resume.
|
|
8
|
+
|
|
3
9
|
## 3.8.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/module.json
CHANGED
|
@@ -102,7 +102,7 @@ function confirmStop(a) {
|
|
|
102
102
|
<MoreHorizontal :size="16" />
|
|
103
103
|
</Button>
|
|
104
104
|
</DropdownMenuTrigger>
|
|
105
|
-
<DropdownMenuContent align="end" class="w-
|
|
105
|
+
<DropdownMenuContent align="end" class="w-64" @click.stop>
|
|
106
106
|
<DropdownMenuItem @select="viewDetails">{{ t("integration.runs.menu.viewDetails") }}</DropdownMenuItem>
|
|
107
107
|
<DropdownMenuItem @select="viewReplay">{{ t("integration.runs.menu.replay") }}</DropdownMenuItem>
|
|
108
108
|
<DropdownMenuSeparator v-if="hasAny" />
|
|
@@ -9,7 +9,6 @@ import { IntegrationsApiError, errorReason } from "../../utils/apiError";
|
|
|
9
9
|
import { createPollBudget, SAFETY_POLL_MS } from "../../utils/pollBudget";
|
|
10
10
|
import { formatDuration } from "../../utils/formatDuration";
|
|
11
11
|
import { unwrapRun } from "../../utils/runEnvelope";
|
|
12
|
-
import { acceptsResume } from "../../utils/runFeedQuery";
|
|
13
12
|
import { splitRunOutputs } from "../../utils/runOutputs";
|
|
14
13
|
import { formatDateTime, formatTime } from "../../utils/formatDateTime";
|
|
15
14
|
const props = defineProps({
|
|
@@ -26,8 +25,7 @@ const {
|
|
|
26
25
|
getHistory,
|
|
27
26
|
getStackTrace,
|
|
28
27
|
cancelRun,
|
|
29
|
-
terminateRun
|
|
30
|
-
resumeRun
|
|
28
|
+
terminateRun
|
|
31
29
|
} = useIntegrationsRuns();
|
|
32
30
|
const DETAILS_POLL_MS = 3e3;
|
|
33
31
|
const HISTORY_POLL_MS = 1e4;
|
|
@@ -493,8 +491,6 @@ function actionLabel(a) {
|
|
|
493
491
|
return t("integration.runs.action.cancel");
|
|
494
492
|
case "terminate":
|
|
495
493
|
return t("integration.runs.action.terminate");
|
|
496
|
-
case "resume":
|
|
497
|
-
return t("integration.runs.action.resume");
|
|
498
494
|
}
|
|
499
495
|
}
|
|
500
496
|
function confirmQuestion(a) {
|
|
@@ -503,8 +499,6 @@ function confirmQuestion(a) {
|
|
|
503
499
|
return t("integration.runs.confirm.cancel");
|
|
504
500
|
case "terminate":
|
|
505
501
|
return t("integration.runs.confirm.terminate");
|
|
506
|
-
case "resume":
|
|
507
|
-
return t("integration.runs.confirm.resume");
|
|
508
502
|
}
|
|
509
503
|
}
|
|
510
504
|
function actionErrorFallback(a) {
|
|
@@ -513,17 +507,12 @@ function actionErrorFallback(a) {
|
|
|
513
507
|
return t("integration.runs.error.cancel");
|
|
514
508
|
case "terminate":
|
|
515
509
|
return t("integration.runs.error.terminate");
|
|
516
|
-
case "resume":
|
|
517
|
-
return t("integration.runs.error.resume");
|
|
518
510
|
}
|
|
519
511
|
}
|
|
520
512
|
const apiStatusRaw = computed(() => pickStr(runData.value, ["status"]));
|
|
521
513
|
const isActive = computed(() => !isTerminal.value);
|
|
522
514
|
const canStop = computed(() => isActive.value && hasTemporal.value);
|
|
523
|
-
const
|
|
524
|
-
return acceptsResume(apiStatusRaw.value || props.run.apiStatus, props.run.status) && hasTemporal.value;
|
|
525
|
-
});
|
|
526
|
-
const hasActions = computed(() => canStop.value || canResume.value);
|
|
515
|
+
const hasActions = computed(() => canStop.value);
|
|
527
516
|
const armed = ref(null);
|
|
528
517
|
const actionBusy = ref(false);
|
|
529
518
|
const actionError = ref(null);
|
|
@@ -552,20 +541,15 @@ async function confirmAction() {
|
|
|
552
541
|
actionBusy.value = true;
|
|
553
542
|
actionError.value = null;
|
|
554
543
|
try {
|
|
555
|
-
let res = null;
|
|
556
544
|
switch (a) {
|
|
557
545
|
case "cancel":
|
|
558
|
-
|
|
546
|
+
await cancelRun(props.run.workflowId, props.run.id);
|
|
559
547
|
break;
|
|
560
548
|
case "terminate":
|
|
561
|
-
|
|
562
|
-
break;
|
|
563
|
-
case "resume":
|
|
564
|
-
res = await resumeRun(props.run.workflowId, props.run.id);
|
|
549
|
+
await terminateRun(props.run.workflowId, props.run.id);
|
|
565
550
|
break;
|
|
566
551
|
}
|
|
567
|
-
|
|
568
|
-
actionNotice.value = a === "resume" && newId && newId !== String(props.run.id) ? t("integration.runs.notice.started", { id: newId }) : t("integration.runs.notice.requested", { action: actionLabel(a) });
|
|
552
|
+
actionNotice.value = t("integration.runs.notice.requested", { action: actionLabel(a) });
|
|
569
553
|
armed.value = null;
|
|
570
554
|
await loadAll();
|
|
571
555
|
startPollingIfNeeded();
|
|
@@ -582,8 +566,8 @@ async function confirmAction() {
|
|
|
582
566
|
<div class="space-y-4 text-sm">
|
|
583
567
|
<!-- ── Details view: overview strip + result. ─────────────────────────── -->
|
|
584
568
|
<template v-if="view === 'details'">
|
|
585
|
-
<!-- Toolbar —
|
|
586
|
-
|
|
569
|
+
<!-- Toolbar — the two stops of a run still going; hidden entirely for one
|
|
570
|
+
that has ended (its ways back are the header's menu, data auto-polls). -->
|
|
587
571
|
<div v-if="hasActions" class="flex items-center gap-2">
|
|
588
572
|
<!-- confirm step: one click arms, second confirms -->
|
|
589
573
|
<template v-if="armed">
|
|
@@ -602,7 +586,6 @@ async function confirmAction() {
|
|
|
602
586
|
<template v-else>
|
|
603
587
|
<Button v-if="canStop" variant="outline" size="sm" @click="arm('cancel')">{{ actionLabel("cancel") }}</Button>
|
|
604
588
|
<Button v-if="canStop" variant="outline" size="sm" class="text-rose-600 hover:bg-rose-500/10" @click="arm('terminate')">{{ actionLabel("terminate") }}</Button>
|
|
605
|
-
<Button v-if="canResume" variant="outline" size="sm" @click="arm('resume')">{{ actionLabel("resume") }}</Button>
|
|
606
589
|
</template>
|
|
607
590
|
</div>
|
|
608
591
|
|
|
@@ -614,7 +597,8 @@ async function confirmAction() {
|
|
|
614
597
|
{{ actionNotice }}
|
|
615
598
|
</div>
|
|
616
599
|
|
|
617
|
-
<!-- Overview —
|
|
600
|
+
<!-- Overview — how the run ended, when, and why it failed. What the engine
|
|
601
|
+
calls the run lives under Technical details below (PO-692). -->
|
|
618
602
|
<section class="rounded-md border border-black/[0.06] bg-white p-4 space-y-3">
|
|
619
603
|
<div class="grid gap-x-6 gap-y-3 sm:grid-cols-2 xl:grid-cols-4">
|
|
620
604
|
<div>
|
|
@@ -633,26 +617,6 @@ async function confirmAction() {
|
|
|
633
617
|
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.completed") }}</div>
|
|
634
618
|
<div class="tabular-nums">{{ formatDateTime(completedAt) }}</div>
|
|
635
619
|
</div>
|
|
636
|
-
<div>
|
|
637
|
-
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.historyLength") }}</div>
|
|
638
|
-
<div class="tabular-nums">{{ dHistoryLength ?? "\u2014" }}</div>
|
|
639
|
-
</div>
|
|
640
|
-
<div class="min-w-0">
|
|
641
|
-
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.workflow") }}</div>
|
|
642
|
-
<div class="truncate font-mono text-xs leading-5" :title="temporalWorkflowId ?? '\u2014'">{{ temporalWorkflowId ?? "\u2014" }}</div>
|
|
643
|
-
</div>
|
|
644
|
-
<div class="min-w-0">
|
|
645
|
-
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.runId") }}</div>
|
|
646
|
-
<div class="truncate font-mono text-xs leading-5" :title="temporalRunId ?? '\u2014'">{{ temporalRunId ?? "\u2014" }}</div>
|
|
647
|
-
</div>
|
|
648
|
-
<div class="min-w-0">
|
|
649
|
-
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.workflowType") }}</div>
|
|
650
|
-
<div class="truncate font-mono text-xs leading-5">{{ dWorkflowType ?? "\u2014" }}</div>
|
|
651
|
-
</div>
|
|
652
|
-
<div class="min-w-0">
|
|
653
|
-
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.taskQueue") }}</div>
|
|
654
|
-
<div class="truncate font-mono text-xs leading-5">{{ dTaskQueue ?? "\u2014" }}</div>
|
|
655
|
-
</div>
|
|
656
620
|
</div>
|
|
657
621
|
<div v-if="errorMessage" class="rounded-md border border-rose-500/20 bg-rose-500/5 px-3 py-2 text-rose-700">
|
|
658
622
|
{{ errorMessage }}
|
|
@@ -693,28 +657,64 @@ async function confirmAction() {
|
|
|
693
657
|
<pre v-else class="rounded-md bg-muted/40 p-3 text-xs overflow-x-auto max-h-[28rem]">{{ json(runResult) }}</pre>
|
|
694
658
|
</section>
|
|
695
659
|
|
|
696
|
-
<!--
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
660
|
+
<!-- Technical details — what the engine calls this run, and the live call
|
|
661
|
+
stack of a run still going. Written for whoever operates the engine, not
|
|
662
|
+
for whoever reads why a run failed, so it starts folded (PO-692). The
|
|
663
|
+
stack trace stays a running run's only: it asks the worker where the run
|
|
664
|
+
is now, and a run that has ended is nowhere. -->
|
|
665
|
+
<details class="group rounded-md border border-black/[0.06] bg-white" data-testid="run-technical-details">
|
|
666
|
+
<summary class="flex cursor-pointer select-none items-center gap-2 px-4 py-3 font-mono text-xs uppercase tracking-wide text-muted-foreground">
|
|
667
|
+
<span aria-hidden="true" class="text-[10px] transition-transform group-open:rotate-90">▶</span>
|
|
668
|
+
<span>{{ t("integration.runs.detail.technical.title") }}</span>
|
|
669
|
+
</summary>
|
|
670
|
+
<div class="space-y-3 px-4 pb-4">
|
|
671
|
+
<div class="grid gap-x-6 gap-y-3 sm:grid-cols-2 xl:grid-cols-4">
|
|
672
|
+
<div>
|
|
673
|
+
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.historyLength") }}</div>
|
|
674
|
+
<div class="tabular-nums">{{ dHistoryLength ?? "\u2014" }}</div>
|
|
675
|
+
</div>
|
|
676
|
+
<div class="min-w-0">
|
|
677
|
+
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.workflow") }}</div>
|
|
678
|
+
<div class="truncate font-mono text-xs leading-5" :title="temporalWorkflowId ?? '\u2014'">{{ temporalWorkflowId ?? "\u2014" }}</div>
|
|
679
|
+
</div>
|
|
680
|
+
<div class="min-w-0">
|
|
681
|
+
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.runId") }}</div>
|
|
682
|
+
<div class="truncate font-mono text-xs leading-5" :title="temporalRunId ?? '\u2014'">{{ temporalRunId ?? "\u2014" }}</div>
|
|
683
|
+
</div>
|
|
684
|
+
<div class="min-w-0">
|
|
685
|
+
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.workflowType") }}</div>
|
|
686
|
+
<div class="truncate font-mono text-xs leading-5">{{ dWorkflowType ?? "\u2014" }}</div>
|
|
687
|
+
</div>
|
|
688
|
+
<div class="min-w-0">
|
|
689
|
+
<div class="text-[10px] uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.field.taskQueue") }}</div>
|
|
690
|
+
<div class="truncate font-mono text-xs leading-5">{{ dTaskQueue ?? "\u2014" }}</div>
|
|
691
|
+
</div>
|
|
692
|
+
</div>
|
|
693
|
+
|
|
694
|
+
<!-- Stack trace (non-terminal runs only, lazy) -->
|
|
695
|
+
<section v-if="!isTerminal" class="space-y-3 border-t border-black/[0.06] pt-3">
|
|
696
|
+
<div class="flex items-center gap-2">
|
|
697
|
+
<h4 class="font-mono text-xs uppercase tracking-wide text-muted-foreground">{{ t("integration.runs.detail.stackTrace.title") }}</h4>
|
|
698
|
+
<div class="flex-1" />
|
|
699
|
+
<Button variant="outline" size="sm" :disabled="stackLoading" @click="loadStack">
|
|
700
|
+
{{ stackEnabled ? t("integration.runs.detail.stackTrace.action.reload") : t("integration.runs.detail.stackTrace.action.load") }}
|
|
701
|
+
</Button>
|
|
702
|
+
</div>
|
|
705
703
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
704
|
+
<p v-if="!stackEnabled" class="text-xs text-muted-foreground">
|
|
705
|
+
{{ t("integration.runs.detail.stackTrace.hint") }}
|
|
706
|
+
</p>
|
|
707
|
+
<div v-else-if="stackLoading" class="flex items-center gap-2 text-muted-foreground">
|
|
708
|
+
<RefreshIcon :size="14" class="animate-spin" /> {{ t("integration.runs.detail.stackTrace.loading") }}
|
|
709
|
+
</div>
|
|
710
|
+
<p v-else-if="stackError" class="text-rose-700">{{ stackError }}</p>
|
|
711
|
+
<pre
|
|
712
|
+
v-else-if="stackTrace"
|
|
713
|
+
class="rounded-md bg-slate-900 text-slate-100 p-3 text-xs overflow-auto max-h-56 whitespace-pre-wrap leading-relaxed"
|
|
714
|
+
>{{ stackTrace }}</pre>
|
|
715
|
+
</section>
|
|
711
716
|
</div>
|
|
712
|
-
|
|
713
|
-
<pre
|
|
714
|
-
v-else-if="stackTrace"
|
|
715
|
-
class="rounded-md bg-slate-900 text-slate-100 p-3 text-xs overflow-auto max-h-56 whitespace-pre-wrap leading-relaxed"
|
|
716
|
-
>{{ stackTrace }}</pre>
|
|
717
|
-
</section>
|
|
717
|
+
</details>
|
|
718
718
|
</template>
|
|
719
719
|
|
|
720
720
|
<!-- ── Timeline view: steps + the stacked history. ─────────────────────── -->
|
|
@@ -387,8 +387,9 @@
|
|
|
387
387
|
"integration.editor.action.more.aria": "Weitere Aktionen für diesen Workflow",
|
|
388
388
|
"integration.editor.action.more.label": "Aktionen",
|
|
389
389
|
"integration.editor.action.pause.title": "Workflow pausieren",
|
|
390
|
-
"integration.editor.action.
|
|
391
|
-
"integration.editor.action.retry
|
|
390
|
+
"integration.editor.action.rerun": "Erneut ausführen",
|
|
391
|
+
"integration.editor.action.retry": "Komplett neu ausführen",
|
|
392
|
+
"integration.editor.action.retry.title": "Alle Schritte laufen erneut, auch die bereits erfolgreichen – E-Mails werden zum Beispiel noch einmal gesendet. Verwendet den aktuell gespeicherten Stand des Workflows, mit dem Trigger-Payload dieses Runs.",
|
|
392
393
|
"integration.editor.action.save.label": "Speichern",
|
|
393
394
|
"integration.editor.action.save.saving": "Wird gespeichert…",
|
|
394
395
|
"integration.editor.action.state.label": "Workflow-Status",
|
|
@@ -953,10 +954,9 @@
|
|
|
953
954
|
"integration.revisions.error.loadFailed": "Der Versionsverlauf konnte nicht geladen werden.",
|
|
954
955
|
"integration.runs.action.back": "Zurück",
|
|
955
956
|
"integration.runs.action.cancel": "Run stoppen",
|
|
956
|
-
"integration.runs.action.resume": "
|
|
957
|
+
"integration.runs.action.resume": "Ab fehlgeschlagenem Schritt fortsetzen",
|
|
957
958
|
"integration.runs.action.terminate": "Terminieren",
|
|
958
959
|
"integration.runs.confirm.cancel": "Diesen Run stoppen?",
|
|
959
|
-
"integration.runs.confirm.resume": "Diesen Run fortsetzen?",
|
|
960
960
|
"integration.runs.confirm.terminate": "Diesen Run terminieren?",
|
|
961
961
|
"integration.runs.detail.error.details.expired": "Verlauf ist nicht mehr verfügbar (Aufbewahrung abgelaufen, kein Snapshot vorhanden).",
|
|
962
962
|
"integration.runs.detail.error.details.generic": "Temporal-Details konnten nicht geladen werden.",
|
|
@@ -996,6 +996,7 @@
|
|
|
996
996
|
"integration.runs.detail.steps.loading": "Schritte werden geladen…",
|
|
997
997
|
"integration.runs.detail.steps.payloadsLoading": "Eingabe und Ausgabe dieses Schritts werden geladen…",
|
|
998
998
|
"integration.runs.detail.steps.title": "Schritte",
|
|
999
|
+
"integration.runs.detail.technical.title": "Technische Details",
|
|
999
1000
|
"integration.runs.detail.timeline.label.activity": "Aktivität",
|
|
1000
1001
|
"integration.runs.detail.timeline.label.timer": "Timer",
|
|
1001
1002
|
"integration.runs.detail.timeline.label.workflow": "Workflow",
|
|
@@ -1011,12 +1012,11 @@
|
|
|
1011
1012
|
"integration.runs.menu.aria.actions": "Aktionen für Run #{id}",
|
|
1012
1013
|
"integration.runs.menu.cancel": "Run stoppen",
|
|
1013
1014
|
"integration.runs.menu.replay": "Wiedergabe",
|
|
1014
|
-
"integration.runs.menu.resume": "
|
|
1015
|
-
"integration.runs.menu.retry": "
|
|
1015
|
+
"integration.runs.menu.resume": "Ab fehlgeschlagenem Schritt fortsetzen",
|
|
1016
|
+
"integration.runs.menu.retry": "Komplett neu ausführen",
|
|
1016
1017
|
"integration.runs.menu.terminate": "Terminieren",
|
|
1017
1018
|
"integration.runs.menu.viewDetails": "Details anzeigen",
|
|
1018
1019
|
"integration.runs.notice.requested": "{action} angefordert.",
|
|
1019
|
-
"integration.runs.notice.started": "Run #{id} gestartet.",
|
|
1020
1020
|
"integration.runs.payload.expertToggle.label": "Experte (JSON)",
|
|
1021
1021
|
"integration.runs.payload.extrasNote": "Zusätzliche Payload-Schlüssel aus der Expertenansicht bleiben erhalten: {keys}",
|
|
1022
1022
|
"integration.runs.payload.file.dropHint": "Datei hier ablegen oder klicken zum Auswählen",
|
|
@@ -387,8 +387,9 @@
|
|
|
387
387
|
"integration.editor.action.more.aria": "More actions for this workflow",
|
|
388
388
|
"integration.editor.action.more.label": "Actions",
|
|
389
389
|
"integration.editor.action.pause.title": "Pause this workflow",
|
|
390
|
-
"integration.editor.action.
|
|
391
|
-
"integration.editor.action.retry
|
|
390
|
+
"integration.editor.action.rerun": "Run again",
|
|
391
|
+
"integration.editor.action.retry": "Run again from the start",
|
|
392
|
+
"integration.editor.action.retry.title": "Every step runs again, including those that already succeeded — e-mails are sent again, for example. Uses the workflow as it is saved now, with this run's trigger payload.",
|
|
392
393
|
"integration.editor.action.save.label": "Save",
|
|
393
394
|
"integration.editor.action.save.saving": "Saving…",
|
|
394
395
|
"integration.editor.action.state.label": "Workflow status",
|
|
@@ -953,10 +954,9 @@
|
|
|
953
954
|
"integration.revisions.error.loadFailed": "Could not load the revision history.",
|
|
954
955
|
"integration.runs.action.back": "Back",
|
|
955
956
|
"integration.runs.action.cancel": "Cancel run",
|
|
956
|
-
"integration.runs.action.resume": "Resume",
|
|
957
|
+
"integration.runs.action.resume": "Resume from the failed step",
|
|
957
958
|
"integration.runs.action.terminate": "Terminate",
|
|
958
959
|
"integration.runs.confirm.cancel": "Cancel this run?",
|
|
959
|
-
"integration.runs.confirm.resume": "Resume this run?",
|
|
960
960
|
"integration.runs.confirm.terminate": "Terminate this run?",
|
|
961
961
|
"integration.runs.detail.error.details.expired": "History is no longer available (retention expired and no snapshot).",
|
|
962
962
|
"integration.runs.detail.error.details.generic": "Could not load Temporal details.",
|
|
@@ -996,6 +996,7 @@
|
|
|
996
996
|
"integration.runs.detail.steps.loading": "Loading steps…",
|
|
997
997
|
"integration.runs.detail.steps.payloadsLoading": "Loading this step's input and output…",
|
|
998
998
|
"integration.runs.detail.steps.title": "Steps",
|
|
999
|
+
"integration.runs.detail.technical.title": "Technical details",
|
|
999
1000
|
"integration.runs.detail.timeline.label.activity": "Activity",
|
|
1000
1001
|
"integration.runs.detail.timeline.label.timer": "Timer",
|
|
1001
1002
|
"integration.runs.detail.timeline.label.workflow": "Workflow",
|
|
@@ -1011,12 +1012,11 @@
|
|
|
1011
1012
|
"integration.runs.menu.aria.actions": "Actions for run #{id}",
|
|
1012
1013
|
"integration.runs.menu.cancel": "Cancel run",
|
|
1013
1014
|
"integration.runs.menu.replay": "Replay",
|
|
1014
|
-
"integration.runs.menu.resume": "Resume",
|
|
1015
|
-
"integration.runs.menu.retry": "
|
|
1015
|
+
"integration.runs.menu.resume": "Resume from the failed step",
|
|
1016
|
+
"integration.runs.menu.retry": "Run again from the start",
|
|
1016
1017
|
"integration.runs.menu.terminate": "Terminate",
|
|
1017
1018
|
"integration.runs.menu.viewDetails": "View details",
|
|
1018
1019
|
"integration.runs.notice.requested": "{action} requested.",
|
|
1019
|
-
"integration.runs.notice.started": "Started run #{id}.",
|
|
1020
1020
|
"integration.runs.payload.expertToggle.label": "Expert (JSON)",
|
|
1021
1021
|
"integration.runs.payload.extrasNote": "Additional payload keys from the expert view are kept: {keys}",
|
|
1022
1022
|
"integration.runs.payload.file.dropHint": "Drop a file here or click to choose",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
3
|
-
import { AltArrowLeft as ArrowLeft, AltArrowRight as Chevron, CheckCircle, RefreshCircle as Loader2, MenuDots as MoreHorizontal, Play, Refresh as RetryIcon, Diskette as Save, SidebarMinimalistic as RailIcon } from "#solar-icons";
|
|
3
|
+
import { AltArrowDown as ArrowDown, AltArrowLeft as ArrowLeft, AltArrowRight as Chevron, CheckCircle, RefreshCircle as Loader2, MenuDots as MoreHorizontal, Play, Refresh as RetryIcon, Diskette as Save, SidebarMinimalistic as RailIcon } from "#solar-icons";
|
|
4
4
|
import {
|
|
5
5
|
AlertDialog,
|
|
6
6
|
AlertDialogCancel,
|
|
@@ -48,7 +48,7 @@ import { payloadFieldsFromBlob } from "../../../data/payloadForm";
|
|
|
48
48
|
import { eventTopicOf } from "../../../data/eventTrigger";
|
|
49
49
|
import { isShapeIssue, saveRefusalLines } from "../../../data/saveRefusal";
|
|
50
50
|
import WorkflowIconView from "../../../components/Integrations/WorkflowIconView.vue";
|
|
51
|
-
import { DEFAULT_RUN_DIRECTION, DEFAULT_RUN_SORT } from "../../../utils/runFeedQuery";
|
|
51
|
+
import { DEFAULT_RUN_DIRECTION, DEFAULT_RUN_SORT, acceptsResume } from "../../../utils/runFeedQuery";
|
|
52
52
|
import { keepOpenBeside } from "../../../utils/dialog";
|
|
53
53
|
import { executionModeLabel } from "../../../utils/executionMode";
|
|
54
54
|
const t = useIntegrationsT();
|
|
@@ -325,7 +325,7 @@ async function onRevisionRestored() {
|
|
|
325
325
|
draft.value = null;
|
|
326
326
|
settleBuildStatus();
|
|
327
327
|
}
|
|
328
|
-
const { trigger: triggerRun, loadForWorkflow, fetchRun, getRun, getSteps, retryRun } = useIntegrationsRuns();
|
|
328
|
+
const { trigger: triggerRun, loadForWorkflow, fetchRun, getRun, getSteps, retryRun, resumeRun } = useIntegrationsRuns();
|
|
329
329
|
const running = ref(false);
|
|
330
330
|
const waitingMode = ref(null);
|
|
331
331
|
const payloadText = ref("{}");
|
|
@@ -766,13 +766,18 @@ function closeRun(target) {
|
|
|
766
766
|
void router.replace({ query: { ...route.query, run: void 0, view: void 0 } });
|
|
767
767
|
}
|
|
768
768
|
const canRetryOpenRun = computed(() => openRun.value?.status === "failed");
|
|
769
|
+
const canResumeOpenRun = computed(() => {
|
|
770
|
+
const r = openRun.value;
|
|
771
|
+
return !!r && acceptsResume(r.apiStatus, r.status) && !!r.temporalRunId;
|
|
772
|
+
});
|
|
773
|
+
const canRerunOpenRun = computed(() => canRetryOpenRun.value || canResumeOpenRun.value);
|
|
769
774
|
const retryBusy = ref(false);
|
|
770
|
-
async function retryOpenRun() {
|
|
775
|
+
async function retryOpenRun(kind = "retry") {
|
|
771
776
|
const source = openRun.value;
|
|
772
777
|
if (!source || retryBusy.value) return;
|
|
773
778
|
retryBusy.value = true;
|
|
774
779
|
try {
|
|
775
|
-
const res = await retryRun(source.workflowId, source.id);
|
|
780
|
+
const res = kind === "resume" ? await resumeRun(source.workflowId, source.id) : await retryRun(source.workflowId, source.id);
|
|
776
781
|
const newId = res && typeof res === "object" && "id" in res ? String(res.id) : null;
|
|
777
782
|
toast.success(newId && newId !== source.id ? t("integration.editor.retry.toast.started", { id: newId }) : t("integration.editor.retry.toast.requested"));
|
|
778
783
|
void loadRuns(1, { silent: true });
|
|
@@ -780,7 +785,7 @@ async function retryOpenRun() {
|
|
|
780
785
|
await router.push({ query: { ...route.query, run: newId, view: void 0 } });
|
|
781
786
|
}
|
|
782
787
|
} catch (e) {
|
|
783
|
-
toast.error(errorReason(e, t("integration.editor.retry.error.generic")));
|
|
788
|
+
toast.error(errorReason(e, kind === "resume" ? t("integration.runs.error.resume") : t("integration.editor.retry.error.generic")));
|
|
784
789
|
} finally {
|
|
785
790
|
retryBusy.value = false;
|
|
786
791
|
}
|
|
@@ -920,9 +925,10 @@ async function confirmDeactivate() {
|
|
|
920
925
|
<Chevron :size="15" weight="Outline" class="shrink-0 text-muted-foreground/50" />
|
|
921
926
|
<button type="button" class="shrink-0 font-normal text-muted-foreground/80 transition-colors hover:text-primary" @click="closeRun('runs')">{{ t("integration.editor.breadcrumb.runs") }}</button>
|
|
922
927
|
<Chevron :size="15" weight="Outline" class="shrink-0 text-muted-foreground/50" />
|
|
923
|
-
<!-- The
|
|
924
|
-
|
|
925
|
-
|
|
928
|
+
<!-- The run number the operator knows from the dialog and the
|
|
929
|
+
lists (PO-692). The engine's own run id is for whoever runs the
|
|
930
|
+
engine, and sits under the record's Technical details. -->
|
|
931
|
+
<span class="shrink-0">{{ t("integration.editor.breadcrumb.runNumber", { id: openRunId }) }}</span>
|
|
926
932
|
</template>
|
|
927
933
|
<template v-else>
|
|
928
934
|
<span class="flex size-7 shrink-0 items-center justify-center rounded-md bg-slate-100 text-slate-500">
|
|
@@ -976,11 +982,21 @@ async function confirmDeactivate() {
|
|
|
976
982
|
|
|
977
983
|
<!-- Run open: run-scoped actions replace the workflow Save. -->
|
|
978
984
|
<template v-if="openRunId">
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
<
|
|
982
|
-
|
|
983
|
-
|
|
985
|
+
<!-- The two ways back from a failed run, behind one button. -->
|
|
986
|
+
<DropdownMenu v-if="canRerunOpenRun">
|
|
987
|
+
<DropdownMenuTrigger as-child>
|
|
988
|
+
<Button variant="outline" class="h-7 text-sm" :disabled="retryBusy">
|
|
989
|
+
<Loader2 v-if="retryBusy" :size="12" class="animate-spin" />
|
|
990
|
+
<RetryIcon v-else :size="12" />
|
|
991
|
+
{{ t("integration.editor.action.rerun") }}
|
|
992
|
+
<ArrowDown :size="12" />
|
|
993
|
+
</Button>
|
|
994
|
+
</DropdownMenuTrigger>
|
|
995
|
+
<DropdownMenuContent align="end">
|
|
996
|
+
<DropdownMenuItem v-if="canResumeOpenRun" @select="retryOpenRun('resume')">{{ t("integration.runs.action.resume") }}</DropdownMenuItem>
|
|
997
|
+
<DropdownMenuItem v-if="canRetryOpenRun" :title="t('integration.editor.action.retry.title')" @select="retryOpenRun('retry')">{{ t("integration.editor.action.retry") }}</DropdownMenuItem>
|
|
998
|
+
</DropdownMenuContent>
|
|
999
|
+
</DropdownMenu>
|
|
984
1000
|
<Button class="h-7 text-sm" @click="closeRun('editor')">
|
|
985
1001
|
<ArrowLeft :size="12" />
|
|
986
1002
|
{{ t("integration.editor.action.backToWorkflow") }}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revenexx/studio-integrations",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Integration Studio (core: workflows, node editor, runs, schedules, credentials, secrets, audit) as a standalone, publishable Nuxt module.",
|
|
6
6
|
"repository": {
|