@revenexx/studio-integrations 2.0.0 → 2.1.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 +135 -0
- package/README.md +1 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +6 -6
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +134 -131
- package/dist/runtime/components/Integrations/CredentialLogo.vue +1 -1
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +1 -1
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue +6 -6
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +90 -11
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +121 -121
- package/dist/runtime/components/Integrations/NodeConfigField.vue +20 -5
- package/dist/runtime/components/Integrations/NodeInspector.vue +44 -41
- package/dist/runtime/components/Integrations/NodePalette.vue +52 -37
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +6 -5
- package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +7 -0
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +14 -2
- package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +7 -0
- package/dist/runtime/components/Integrations/RunsTable.vue +7 -26
- package/dist/runtime/components/Integrations/StickyNoteView.vue +1 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +10 -6
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +224 -225
- package/dist/runtime/components/Integrations/WorkflowExportDialog.d.vue.ts +6 -0
- package/dist/runtime/components/Integrations/WorkflowExportDialog.vue +71 -0
- package/dist/runtime/components/Integrations/WorkflowExportDialog.vue.d.ts +6 -0
- package/dist/runtime/components/Integrations/WorkflowImportFileStep.d.vue.ts +8 -0
- package/dist/runtime/components/Integrations/WorkflowImportFileStep.vue +95 -0
- package/dist/runtime/components/Integrations/WorkflowImportFileStep.vue.d.ts +8 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +5 -4
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +0 -7
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +2 -2
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +2 -3
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +14 -8
- package/dist/runtime/composables/useIntegrationsNodes.js +4 -1
- package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +3 -1
- package/dist/runtime/composables/useIntegrationsWorkflows.js +5 -22
- package/dist/runtime/composables/useNow.d.ts +17 -0
- package/dist/runtime/composables/useNow.js +16 -0
- package/dist/runtime/composables/useWorkflowFile.d.ts +21 -0
- package/dist/runtime/composables/useWorkflowFile.js +63 -0
- package/dist/runtime/data/expressionEditor.d.ts +11 -1
- package/dist/runtime/data/expressionEditor.js +2 -1
- package/dist/runtime/data/nodeIcons.d.ts +14 -0
- package/dist/runtime/data/nodeIcons.js +57 -14
- package/dist/runtime/data/nodeRunData.js +1 -1
- package/dist/runtime/data/payloadForm.js +1 -1
- package/dist/runtime/i18n/messages/de.json +42 -0
- package/dist/runtime/i18n/messages/en.json +42 -0
- package/dist/runtime/pages/integrations/audit.vue +3 -3
- package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +2 -2
- package/dist/runtime/pages/integrations/index.vue +5 -10
- package/dist/runtime/pages/integrations/schedules.vue +13 -1
- package/dist/runtime/pages/integrations/templates/index.vue +40 -40
- package/dist/runtime/pages/integrations/workflows/[id].vue +324 -244
- package/dist/runtime/types/integrations.d.ts +13 -0
- package/dist/runtime/utils/credentialState.d.ts +0 -7
- package/dist/runtime/utils/credentialState.js +0 -12
- package/dist/runtime/utils/localize.d.ts +12 -0
- package/dist/runtime/utils/localize.js +1 -1
- package/dist/runtime/utils/paletteOrder.d.ts +29 -0
- package/dist/runtime/utils/paletteOrder.js +46 -0
- package/dist/runtime/utils/relativeTime.d.ts +29 -0
- package/dist/runtime/utils/relativeTime.js +23 -0
- package/dist/runtime/utils/runFeedQuery.d.ts +12 -6
- package/dist/runtime/utils/runFeedQuery.js +3 -18
- package/dist/runtime/utils/settingValue.d.ts +33 -0
- package/dist/runtime/utils/settingValue.js +8 -0
- package/dist/runtime/utils/statusStyle.d.ts +8 -8
- package/dist/runtime/utils/statusStyle.js +4 -1
- package/dist/runtime/utils/workflowFile.d.ts +119 -0
- package/dist/runtime/utils/workflowFile.js +192 -0
- package/package.json +8 -3
|
@@ -58,9 +58,8 @@ import { inputHandleId, outputHandleId, portFromHandleId } from "../../data/hand
|
|
|
58
58
|
import { OPPOSITE_SIDE } from "./canvasSides";
|
|
59
59
|
import { deepClone } from "../../utils/deepClone";
|
|
60
60
|
import { copyToClipboard } from "../../utils/clipboard";
|
|
61
|
-
import { groupFindingsByNode } from "../../utils/validationFindings";
|
|
61
|
+
import { groupFindingsByNode, findingsByNodeField } from "../../utils/validationFindings";
|
|
62
62
|
import { reorderBranchSubtrees } from "../../data/branchReorder";
|
|
63
|
-
import { findingsByNodeField } from "../../utils/validationFindings";
|
|
64
63
|
import { resolveDisplayName, resolveLocalized } from "../../utils/localize";
|
|
65
64
|
const props = defineProps({
|
|
66
65
|
workflow: { type: Object, required: true },
|
|
@@ -1556,41 +1555,41 @@ const edgeTypes = {
|
|
|
1556
1555
|
:style="palette.mode.value === 'floating' ? palette.floatingStyle.value : void 0"
|
|
1557
1556
|
>
|
|
1558
1557
|
<div class="flex min-h-0 flex-1 flex-col overflow-hidden border border-white bg-white rounded-lg bg-gradient-to-br from-white via-violet-50/40 to-white relative overflow-hidden">
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
>
|
|
1564
|
-
<GripVertical :size="14" class="shrink-0 text-muted-foreground/60" />
|
|
1565
|
-
<span class="min-w-0 flex-1 truncate text-sm font-medium">{{ t("integration.editor.palette.title") }}</span>
|
|
1566
|
-
<DropdownMenu>
|
|
1567
|
-
<DropdownMenuTrigger as-child>
|
|
1568
|
-
<button
|
|
1569
|
-
type="button"
|
|
1570
|
-
class="flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
1571
|
-
:title="t('integration.editor.palette.action.placement.title')"
|
|
1572
|
-
>
|
|
1573
|
-
<EllipsisVertical :size="14" />
|
|
1574
|
-
</button>
|
|
1575
|
-
</DropdownMenuTrigger>
|
|
1576
|
-
<DropdownMenuContent align="end" class="w-36 rounded-lg border border-black/[0.06] bg-white p-1 shadow-lg">
|
|
1577
|
-
<DropdownMenuItem class="rounded-md text-sm" @select="palette.dock('left')">{{ t("integration.editor.palette.action.dockLeft") }}</DropdownMenuItem>
|
|
1578
|
-
<DropdownMenuItem class="rounded-md text-sm" @select="palette.dock('right')">{{ t("integration.editor.palette.action.dockRight") }}</DropdownMenuItem>
|
|
1579
|
-
<DropdownMenuItem class="rounded-md text-sm" @select="palette.floatHere(paletteShellRef)">{{ t("integration.editor.panel.action.floatHere") }}</DropdownMenuItem>
|
|
1580
|
-
<DropdownMenuSeparator class="my-1 h-px bg-black/[0.06]" />
|
|
1581
|
-
<DropdownMenuItem class="rounded-md text-sm" @select="palette.setCollapsed(true)">{{ t("integration.editor.panel.action.collapse") }}</DropdownMenuItem>
|
|
1582
|
-
</DropdownMenuContent>
|
|
1583
|
-
</DropdownMenu>
|
|
1584
|
-
<button
|
|
1585
|
-
type="button"
|
|
1586
|
-
class="flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
1587
|
-
:title="t('integration.editor.palette.action.collapse.title')"
|
|
1588
|
-
@click="palette.setCollapsed(true)"
|
|
1558
|
+
<div
|
|
1559
|
+
class="flex shrink-0 touch-none select-none items-center gap-1 border-b border-black/[0.06] bg-white px-2 py-1.5"
|
|
1560
|
+
:class="palette.dragging.value ? 'cursor-grabbing' : 'cursor-grab'"
|
|
1561
|
+
@pointerdown="palette.startDrag($event, paletteShellRef)"
|
|
1589
1562
|
>
|
|
1590
|
-
<
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1563
|
+
<GripVertical :size="14" class="shrink-0 text-muted-foreground/60" />
|
|
1564
|
+
<span class="min-w-0 flex-1 truncate text-sm font-medium">{{ t("integration.editor.palette.title") }}</span>
|
|
1565
|
+
<DropdownMenu>
|
|
1566
|
+
<DropdownMenuTrigger as-child>
|
|
1567
|
+
<button
|
|
1568
|
+
type="button"
|
|
1569
|
+
class="flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
1570
|
+
:title="t('integration.editor.palette.action.placement.title')"
|
|
1571
|
+
>
|
|
1572
|
+
<EllipsisVertical :size="14" />
|
|
1573
|
+
</button>
|
|
1574
|
+
</DropdownMenuTrigger>
|
|
1575
|
+
<DropdownMenuContent align="end" class="w-36 rounded-lg border border-black/[0.06] bg-white p-1 shadow-lg">
|
|
1576
|
+
<DropdownMenuItem class="rounded-md text-sm" @select="palette.dock('left')">{{ t("integration.editor.palette.action.dockLeft") }}</DropdownMenuItem>
|
|
1577
|
+
<DropdownMenuItem class="rounded-md text-sm" @select="palette.dock('right')">{{ t("integration.editor.palette.action.dockRight") }}</DropdownMenuItem>
|
|
1578
|
+
<DropdownMenuItem class="rounded-md text-sm" @select="palette.floatHere(paletteShellRef)">{{ t("integration.editor.panel.action.floatHere") }}</DropdownMenuItem>
|
|
1579
|
+
<DropdownMenuSeparator class="my-1 h-px bg-black/[0.06]" />
|
|
1580
|
+
<DropdownMenuItem class="rounded-md text-sm" @select="palette.setCollapsed(true)">{{ t("integration.editor.panel.action.collapse") }}</DropdownMenuItem>
|
|
1581
|
+
</DropdownMenuContent>
|
|
1582
|
+
</DropdownMenu>
|
|
1583
|
+
<button
|
|
1584
|
+
type="button"
|
|
1585
|
+
class="flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
1586
|
+
:title="t('integration.editor.palette.action.collapse.title')"
|
|
1587
|
+
@click="palette.setCollapsed(true)"
|
|
1588
|
+
>
|
|
1589
|
+
<Minus :size="14" />
|
|
1590
|
+
</button>
|
|
1591
|
+
</div>
|
|
1592
|
+
<NodePalette ref="paletteRef" class="min-h-0 flex-1" @insert="onPaletteInsert" />
|
|
1594
1593
|
</div>
|
|
1595
1594
|
</div>
|
|
1596
1595
|
</Transition>
|
|
@@ -1694,213 +1693,213 @@ const edgeTypes = {
|
|
|
1694
1693
|
<!-- Floating control pane — bottom center. -->
|
|
1695
1694
|
<div ref="controlBar" class="absolute bottom-3 left-1/2 z-10 -translate-x-1/2">
|
|
1696
1695
|
<TooltipProvider :delay-duration="250">
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1696
|
+
<div class="rounded-lg border border-gray-400/10 outline-1 outline-white/30 backdrop-blur-sm">
|
|
1697
|
+
<div class="flex items-center gap-0.5 whitespace-nowrap border border-white bg-white rounded-lg bg-gradient-to-br from-white via-violet-50/40 to-white px-2 py-1">
|
|
1698
|
+
<!-- Smart Run: the page decides what "run" means — a workflow that
|
|
1700
1699
|
consumes trigger.payload, or leaves the mode to the caller, opens
|
|
1701
1700
|
the run dialog; one that asks neither fires immediately. One
|
|
1702
1701
|
button either way. -->
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1702
|
+
<IntegrationsEditorTip :label="runWaiting ? t('integration.editor.tool.run.tooltipWaiting') : t('integration.editor.tool.run.tooltip')" :shortcut="primaryShortcut('run')">
|
|
1703
|
+
<button
|
|
1704
|
+
type="button"
|
|
1705
|
+
class="relative flex h-8 items-center gap-1.5 rounded-lg bg-gradient-to-b from-emerald-500 to-emerald-600 px-3.5 text-sm font-medium text-white transition after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:shadow-[inset_0_1px_0_rgba(255,255,255,0.3),inset_0_-2px_0_rgba(0,0,0,0.25)] hover:from-emerald-600 hover:to-emerald-600 active:translate-y-px disabled:opacity-60"
|
|
1706
|
+
:disabled="runBusy"
|
|
1707
|
+
@click="emit('run')"
|
|
1708
|
+
>
|
|
1709
|
+
<Loader2 v-if="runBusy" :size="14" class="animate-spin" />
|
|
1710
|
+
<Play v-else :size="14" />
|
|
1711
|
+
{{ runWaiting ? t("integration.editor.run.waitingForBuild") : t("integration.editor.run.button") }}
|
|
1712
|
+
</button>
|
|
1713
|
+
</IntegrationsEditorTip>
|
|
1715
1714
|
|
|
1716
|
-
|
|
1715
|
+
<div class="mx-1 h-5 w-px bg-black/10" />
|
|
1717
1716
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1717
|
+
<div class="flex items-center gap-0.5 rounded-lg bg-black/[0.05] p-0.5 shadow-[inset_0_1px_2px_rgba(15,23,42,0.12)]">
|
|
1718
|
+
<!-- Icon-only, and the tooltip is not an accessible name: each one
|
|
1720
1719
|
says what it does itself, and whether it is the active mode. -->
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1720
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.select')" :shortcut="primaryShortcut('pointerSelect')">
|
|
1721
|
+
<button
|
|
1722
|
+
type="button"
|
|
1723
|
+
:aria-label="t('integration.editor.tool.select')"
|
|
1724
|
+
:aria-pressed="pointerMode === 'select'"
|
|
1725
|
+
class="flex size-7 items-center justify-center rounded-lg transition"
|
|
1726
|
+
:class="pointerMode === 'select' ? 'bg-gradient-to-b from-white to-gray-50 text-foreground shadow-[0_1px_2px_rgba(15,23,42,0.18),inset_0_1px_0_rgba(255,255,255,0.9)]' : 'text-muted-foreground hover:text-foreground'"
|
|
1727
|
+
@click="setPointerMode('select')"
|
|
1728
|
+
>
|
|
1729
|
+
<MousePointer2 :size="14" />
|
|
1730
|
+
</button>
|
|
1731
|
+
</IntegrationsEditorTip>
|
|
1732
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.hand')" :shortcut="primaryShortcut('pointerHand')">
|
|
1733
|
+
<button
|
|
1734
|
+
type="button"
|
|
1735
|
+
:aria-label="t('integration.editor.tool.hand')"
|
|
1736
|
+
:aria-pressed="pointerMode === 'hand'"
|
|
1737
|
+
class="flex size-7 items-center justify-center rounded-lg transition"
|
|
1738
|
+
:class="pointerMode === 'hand' ? 'bg-gradient-to-b from-white to-gray-50 text-foreground shadow-[0_1px_2px_rgba(15,23,42,0.18),inset_0_1px_0_rgba(255,255,255,0.9)]' : 'text-muted-foreground hover:text-foreground'"
|
|
1739
|
+
@click="setPointerMode('hand')"
|
|
1740
|
+
>
|
|
1741
|
+
<Hand :size="14" />
|
|
1742
|
+
</button>
|
|
1743
|
+
</IntegrationsEditorTip>
|
|
1744
|
+
</div>
|
|
1746
1745
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1746
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.tidyUp')" :shortcut="primaryShortcut('tidyUp')">
|
|
1747
|
+
<button
|
|
1748
|
+
type="button"
|
|
1749
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1750
|
+
@click="tidyUp"
|
|
1751
|
+
>
|
|
1752
|
+
<LayoutGrid :size="13" />
|
|
1753
|
+
{{ t("integration.editor.tool.tidyUp") }}
|
|
1754
|
+
</button>
|
|
1755
|
+
</IntegrationsEditorTip>
|
|
1756
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.fitView.tooltip')" :shortcut="primaryShortcut('fitView')">
|
|
1757
|
+
<button
|
|
1758
|
+
type="button"
|
|
1759
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1760
|
+
@click="flow.fitView({ padding: 0.2, duration: 400, maxZoom: 1 })"
|
|
1761
|
+
>
|
|
1762
|
+
<Sparkles :size="13" />
|
|
1763
|
+
{{ t("integration.editor.tool.fitView.label") }}
|
|
1764
|
+
</button>
|
|
1765
|
+
</IntegrationsEditorTip>
|
|
1766
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.addSticky.tooltip')" :shortcut="primaryShortcut('addSticky')">
|
|
1767
|
+
<button
|
|
1768
|
+
type="button"
|
|
1769
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1770
|
+
@click="addSticky()"
|
|
1771
|
+
>
|
|
1772
|
+
<StickyNote :size="13" />
|
|
1773
|
+
{{ t("integration.editor.tool.addSticky.label") }}
|
|
1774
|
+
</button>
|
|
1775
|
+
</IntegrationsEditorTip>
|
|
1776
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.addGroup.tooltip')">
|
|
1777
|
+
<button
|
|
1778
|
+
type="button"
|
|
1779
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1780
|
+
@click="addGroupFrame"
|
|
1781
|
+
>
|
|
1782
|
+
<GroupIcon :size="13" />
|
|
1783
|
+
{{ t("integration.editor.tool.addGroup.label") }}
|
|
1784
|
+
</button>
|
|
1785
|
+
</IntegrationsEditorTip>
|
|
1786
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.variables.tooltip')" :shortcut="primaryShortcut('variables')">
|
|
1787
|
+
<button
|
|
1788
|
+
type="button"
|
|
1789
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1790
|
+
@click="variablesOpen = true"
|
|
1791
|
+
>
|
|
1792
|
+
<Braces :size="13" />
|
|
1793
|
+
{{ t("integration.editor.tool.variables.label") }}
|
|
1794
|
+
<span v-if="variableCount" class="rounded-lg bg-muted px-1.5 text-xs tabular-nums text-muted-foreground">{{ variableCount }}</span>
|
|
1795
|
+
</button>
|
|
1796
|
+
</IntegrationsEditorTip>
|
|
1797
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.state.tooltip')" :shortcut="primaryShortcut('state')">
|
|
1798
|
+
<button
|
|
1799
|
+
type="button"
|
|
1800
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1801
|
+
@click="stateOpen = true"
|
|
1802
|
+
>
|
|
1803
|
+
<Database :size="13" />
|
|
1804
|
+
{{ t("integration.editor.tool.state.label") }}
|
|
1805
|
+
<span v-if="stateCount" class="rounded-lg bg-muted px-1.5 text-xs tabular-nums text-muted-foreground">{{ stateCount }}</span>
|
|
1806
|
+
</button>
|
|
1807
|
+
</IntegrationsEditorTip>
|
|
1808
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.settings.tooltip')" :shortcut="primaryShortcut('settings')">
|
|
1809
|
+
<button
|
|
1810
|
+
type="button"
|
|
1811
|
+
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
1812
|
+
@click="emit('openSettings')"
|
|
1813
|
+
>
|
|
1814
|
+
<Settings2 :size="13" />
|
|
1815
|
+
{{ t("integration.editor.tool.settings.label") }}
|
|
1816
|
+
</button>
|
|
1817
|
+
</IntegrationsEditorTip>
|
|
1818
|
+
<!-- The overview, and the one control that has to be reachable without
|
|
1820
1819
|
already knowing a key: it is where the other keys are learnt. Its
|
|
1821
1820
|
tooltip carries `?` for the same reason — the pane teaches the key
|
|
1822
1821
|
that teaches the rest. Icon-only, so it carries a name of its own
|
|
1823
1822
|
(`specs/accessibility.md` AC-2). -->
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1823
|
+
<IntegrationsEditorTip :label="t('integration.canvas.shortcuts.dialog.title')" :shortcut="primaryShortcut('overview')">
|
|
1824
|
+
<button
|
|
1825
|
+
type="button"
|
|
1826
|
+
:aria-label="t('integration.canvas.shortcuts.dialog.title')"
|
|
1827
|
+
class="flex size-8 items-center justify-center rounded-lg text-foreground transition hover:bg-black/[0.04]"
|
|
1828
|
+
@click="shortcutsOpen = true"
|
|
1829
|
+
>
|
|
1830
|
+
<Keyboard :size="14" />
|
|
1831
|
+
</button>
|
|
1832
|
+
</IntegrationsEditorTip>
|
|
1834
1833
|
|
|
1835
|
-
|
|
1834
|
+
<div class="mx-1 h-5 w-px bg-black/10" />
|
|
1836
1835
|
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1836
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomOut')" :shortcut="primaryShortcut('zoomOut')">
|
|
1837
|
+
<button
|
|
1838
|
+
type="button"
|
|
1839
|
+
:aria-label="t('integration.editor.tool.zoomOut')"
|
|
1840
|
+
class="flex size-8 items-center justify-center rounded-lg text-foreground transition hover:bg-black/[0.04]"
|
|
1841
|
+
@click="flow.zoomOut({ duration: 150 })"
|
|
1842
|
+
>
|
|
1843
|
+
<ZoomOut :size="14" />
|
|
1844
|
+
</button>
|
|
1845
|
+
</IntegrationsEditorTip>
|
|
1846
|
+
<!-- Tooltip sits on a wrapper span so its as-child merge never
|
|
1848
1847
|
touches the dropdown trigger (merging both onto one button
|
|
1849
1848
|
swallowed the trigger's pointerdown and the menu never opened). -->
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1849
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomLevel.tooltip')" :shortcut="primaryShortcut('zoomReset')">
|
|
1850
|
+
<span class="inline-flex">
|
|
1851
|
+
<DropdownMenu v-model:open="zoomMenuOpen">
|
|
1852
|
+
<DropdownMenuTrigger as-child>
|
|
1853
|
+
<!-- The label carries the percentage because it replaces the
|
|
1855
1854
|
button's text as its accessible name: a bare "Zoom level"
|
|
1856
1855
|
would leave screen reader users with the one thing sighted
|
|
1857
1856
|
users do not need told and without the value they do. -->
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1857
|
+
<button
|
|
1858
|
+
type="button"
|
|
1859
|
+
:aria-label="t('integration.editor.tool.zoomLevel.aria', { pct: zoomPct })"
|
|
1860
|
+
class="w-12 rounded-lg py-1 text-center text-sm tabular-nums text-muted-foreground transition hover:bg-black/[0.04] hover:text-foreground"
|
|
1861
|
+
>
|
|
1862
|
+
{{ zoomPct }}
|
|
1863
|
+
</button>
|
|
1864
|
+
</DropdownMenuTrigger>
|
|
1865
|
+
<DropdownMenuContent side="top" align="center" class="w-[4.75rem] min-w-0 rounded-lg border border-black/[0.06] bg-white p-1 shadow-lg">
|
|
1866
|
+
<div class="px-0.5 pb-0.5">
|
|
1867
|
+
<input
|
|
1868
|
+
v-model="zoomInputText"
|
|
1869
|
+
type="text"
|
|
1870
|
+
inputmode="numeric"
|
|
1871
|
+
:aria-label="t('integration.editor.tool.zoomLevel.inputAria')"
|
|
1872
|
+
class="h-6 w-full rounded-md border border-black/[0.08] bg-white px-1 text-center text-sm tabular-nums focus:outline-none focus:ring-2 focus:ring-primary/40"
|
|
1873
|
+
placeholder="%"
|
|
1874
|
+
@keydown.stop
|
|
1875
|
+
@keydown.enter.prevent="applyZoomInput"
|
|
1876
|
+
>
|
|
1877
|
+
</div>
|
|
1878
|
+
<DropdownMenuSeparator class="my-1 h-px bg-black/[0.06]" />
|
|
1879
|
+
<DropdownMenuItem
|
|
1880
|
+
v-for="p in ZOOM_PRESETS"
|
|
1881
|
+
:key="p"
|
|
1882
|
+
class="justify-center rounded-md px-1 py-0.5 text-sm tabular-nums"
|
|
1883
|
+
@select="setZoomPct(p)"
|
|
1884
|
+
>
|
|
1885
|
+
{{ p }}%
|
|
1886
|
+
</DropdownMenuItem>
|
|
1887
|
+
</DropdownMenuContent>
|
|
1888
|
+
</DropdownMenu>
|
|
1889
|
+
</span>
|
|
1890
|
+
</IntegrationsEditorTip>
|
|
1891
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomIn')" :shortcut="primaryShortcut('zoomIn')">
|
|
1892
|
+
<button
|
|
1893
|
+
type="button"
|
|
1894
|
+
:aria-label="t('integration.editor.tool.zoomIn')"
|
|
1895
|
+
class="flex size-8 items-center justify-center rounded-lg text-foreground transition hover:bg-black/[0.04]"
|
|
1896
|
+
@click="flow.zoomIn({ duration: 150 })"
|
|
1877
1897
|
>
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
class="justify-center rounded-md px-1 py-0.5 text-sm tabular-nums"
|
|
1884
|
-
@select="setZoomPct(p)"
|
|
1885
|
-
>
|
|
1886
|
-
{{ p }}%
|
|
1887
|
-
</DropdownMenuItem>
|
|
1888
|
-
</DropdownMenuContent>
|
|
1889
|
-
</DropdownMenu>
|
|
1890
|
-
</span>
|
|
1891
|
-
</IntegrationsEditorTip>
|
|
1892
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomIn')" :shortcut="primaryShortcut('zoomIn')">
|
|
1893
|
-
<button
|
|
1894
|
-
type="button"
|
|
1895
|
-
:aria-label="t('integration.editor.tool.zoomIn')"
|
|
1896
|
-
class="flex size-8 items-center justify-center rounded-lg text-foreground transition hover:bg-black/[0.04]"
|
|
1897
|
-
@click="flow.zoomIn({ duration: 150 })"
|
|
1898
|
-
>
|
|
1899
|
-
<ZoomIn :size="14" />
|
|
1900
|
-
</button>
|
|
1901
|
-
</IntegrationsEditorTip>
|
|
1902
|
-
</div>
|
|
1903
|
-
</div>
|
|
1898
|
+
<ZoomIn :size="14" />
|
|
1899
|
+
</button>
|
|
1900
|
+
</IntegrationsEditorTip>
|
|
1901
|
+
</div>
|
|
1902
|
+
</div>
|
|
1904
1903
|
</TooltipProvider>
|
|
1905
1904
|
</div>
|
|
1906
1905
|
|
|
@@ -1961,9 +1960,9 @@ const edgeTypes = {
|
|
|
1961
1960
|
form as a strip down the left of an empty workbench. -->
|
|
1962
1961
|
<DialogContent
|
|
1963
1962
|
:show-close-button="false"
|
|
1964
|
-
@open-auto-focus="onConfigOpenAutoFocus"
|
|
1965
1963
|
class="flex max-w-none flex-col gap-0 overflow-hidden rounded-lg p-0 sm:max-w-none"
|
|
1966
1964
|
:class="selectionIsTrigger ? 'h-[min(520px,86vh)] w-[min(600px,94vw)]' : 'h-[min(680px,86vh)] w-[min(1100px,94vw)]'"
|
|
1965
|
+
@open-auto-focus="onConfigOpenAutoFocus"
|
|
1967
1966
|
>
|
|
1968
1967
|
<NodeInspector
|
|
1969
1968
|
v-if="selection"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare function start(id: number): Promise<void>;
|
|
2
|
+
declare const _default: import("vue").DefineComponent<{}, {
|
|
3
|
+
start: typeof start;
|
|
4
|
+
open: import("vue").Ref<boolean, boolean>;
|
|
5
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { toast } from "vue-sonner";
|
|
4
|
+
import {
|
|
5
|
+
AlertDialog,
|
|
6
|
+
AlertDialogCancel,
|
|
7
|
+
AlertDialogContent,
|
|
8
|
+
AlertDialogDescription,
|
|
9
|
+
AlertDialogFooter,
|
|
10
|
+
AlertDialogHeader,
|
|
11
|
+
AlertDialogTitle,
|
|
12
|
+
Button
|
|
13
|
+
} from "@revenexx/studio";
|
|
14
|
+
import { useWorkflowFile } from "../../composables/useWorkflowFile";
|
|
15
|
+
import { hasVariableValues } from "../../utils/workflowFile";
|
|
16
|
+
import { errorReason } from "../../utils/apiError";
|
|
17
|
+
const t = useIntegrationsT();
|
|
18
|
+
const { fileFor, download } = useWorkflowFile();
|
|
19
|
+
const open = ref(false);
|
|
20
|
+
const pending = ref(null);
|
|
21
|
+
async function start(id) {
|
|
22
|
+
let file;
|
|
23
|
+
try {
|
|
24
|
+
file = (await fileFor(id)).file;
|
|
25
|
+
} catch (e) {
|
|
26
|
+
toast.error(errorReason(e, t("integration.workflowFile.export.error")));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (hasVariableValues(file.workflow.blob)) {
|
|
30
|
+
pending.value = file;
|
|
31
|
+
open.value = true;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
finish(file);
|
|
35
|
+
}
|
|
36
|
+
function finish(file) {
|
|
37
|
+
download(file);
|
|
38
|
+
toast.success(t("integration.workflowFile.export.toast", { name: file.workflow.name }));
|
|
39
|
+
}
|
|
40
|
+
function confirm() {
|
|
41
|
+
const file = pending.value;
|
|
42
|
+
open.value = false;
|
|
43
|
+
pending.value = null;
|
|
44
|
+
if (file) finish(file);
|
|
45
|
+
}
|
|
46
|
+
defineExpose({ start, open });
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<AlertDialog :open="open" @update:open="(v) => {
|
|
51
|
+
if (!v) {
|
|
52
|
+
open = false;
|
|
53
|
+
pending = null;
|
|
54
|
+
}
|
|
55
|
+
}">
|
|
56
|
+
<AlertDialogContent>
|
|
57
|
+
<AlertDialogHeader>
|
|
58
|
+
<AlertDialogTitle>{{ t("integration.workflowFile.export.notice.title") }}</AlertDialogTitle>
|
|
59
|
+
<AlertDialogDescription>
|
|
60
|
+
{{ t("integration.workflowFile.export.notice.description") }}
|
|
61
|
+
</AlertDialogDescription>
|
|
62
|
+
</AlertDialogHeader>
|
|
63
|
+
<AlertDialogFooter>
|
|
64
|
+
<AlertDialogCancel as-child>
|
|
65
|
+
<Button variant="outline">{{ t("integration.common.action.cancel") }}</Button>
|
|
66
|
+
</AlertDialogCancel>
|
|
67
|
+
<Button @click="confirm">{{ t("integration.workflowFile.export.notice.confirm") }}</Button>
|
|
68
|
+
</AlertDialogFooter>
|
|
69
|
+
</AlertDialogContent>
|
|
70
|
+
</AlertDialog>
|
|
71
|
+
</template>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare function start(id: number): Promise<void>;
|
|
2
|
+
declare const _default: import("vue").DefineComponent<{}, {
|
|
3
|
+
start: typeof start;
|
|
4
|
+
open: import("vue").Ref<boolean, boolean>;
|
|
5
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
2
|
+
created: (id: number) => any;
|
|
3
|
+
cancel: () => any;
|
|
4
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
5
|
+
onCreated?: ((id: number) => any) | undefined;
|
|
6
|
+
onCancel?: (() => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
export default _default;
|