2019-06-23 03:35:23 -07:00
|
|
|
<template>
|
2023-11-15 07:19:48 -08:00
|
|
|
<div :class="['run-data', $style.container]" @mouseover="activatePane">
|
2022-08-02 01:36:11 -07:00
|
|
|
<n8n-callout
|
2022-11-14 04:28:26 -08:00
|
|
|
v-if="canPinData && hasPinData && !editMode.enabled && !isProductionExecutionPreview"
|
2022-07-20 08:50:39 -07:00
|
|
|
theme="secondary"
|
|
|
|
icon="thumbtack"
|
2023-03-16 02:19:12 -07:00
|
|
|
:class="$style.pinnedDataCallout"
|
2022-07-20 08:50:39 -07:00
|
|
|
>
|
|
|
|
{{ $locale.baseText('runData.pindata.thisDataIsPinned') }}
|
2023-12-28 00:49:58 -08:00
|
|
|
<span v-if="!isReadOnlyRoute && !readOnlyEnv" class="ml-4xs">
|
2022-07-20 08:50:39 -07:00
|
|
|
<n8n-link
|
|
|
|
theme="secondary"
|
|
|
|
size="small"
|
|
|
|
underline
|
|
|
|
bold
|
2023-07-28 00:51:07 -07:00
|
|
|
@click.stop="onTogglePinData({ source: 'banner-link' })"
|
2022-07-20 08:50:39 -07:00
|
|
|
>
|
|
|
|
{{ $locale.baseText('runData.pindata.unpin') }}
|
|
|
|
</n8n-link>
|
|
|
|
</span>
|
|
|
|
<template #trailingContent>
|
|
|
|
<n8n-link
|
|
|
|
:to="dataPinningDocsUrl"
|
|
|
|
size="small"
|
|
|
|
theme="secondary"
|
|
|
|
bold
|
|
|
|
underline
|
|
|
|
@click="onClickDataPinningDocsLink"
|
|
|
|
>
|
|
|
|
{{ $locale.baseText('runData.pindata.learnMore') }}
|
|
|
|
</n8n-link>
|
|
|
|
</template>
|
2022-08-02 01:36:11 -07:00
|
|
|
</n8n-callout>
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
<BinaryDataDisplay
|
2023-12-28 00:49:58 -08:00
|
|
|
:window-visible="binaryDataDisplayVisible"
|
|
|
|
:display-data="binaryDataDisplayData"
|
2019-06-23 03:35:23 -07:00
|
|
|
@close="closeBinaryDataDisplay"
|
|
|
|
/>
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.header">
|
2022-05-23 08:56:15 -07:00
|
|
|
<slot name="header"></slot>
|
2022-04-11 06:12:13 -07:00
|
|
|
|
2022-11-28 07:54:13 -08:00
|
|
|
<div
|
|
|
|
v-show="!hasRunError"
|
|
|
|
:class="$style.displayModes"
|
|
|
|
data-test-id="run-data-pane-header"
|
2023-12-28 00:49:58 -08:00
|
|
|
@click.stop
|
2022-11-28 07:54:13 -08:00
|
|
|
>
|
2022-04-11 06:12:13 -07:00
|
|
|
<n8n-radio-buttons
|
2022-07-20 08:50:39 -07:00
|
|
|
v-show="
|
2023-11-15 07:19:48 -08:00
|
|
|
hasNodeRun && (inputData.length || binaryData.length || search) && !editMode.enabled
|
2022-12-14 01:04:10 -08:00
|
|
|
"
|
2023-12-28 00:49:58 -08:00
|
|
|
:model-value="displayMode"
|
2022-04-11 06:12:13 -07:00
|
|
|
:options="buttons"
|
2022-12-01 00:26:38 -08:00
|
|
|
data-test-id="ndv-run-data-display-mode"
|
2023-07-28 00:51:07 -07:00
|
|
|
@update:modelValue="onDisplayModeChange"
|
2022-04-11 06:12:13 -07:00
|
|
|
/>
|
2022-07-20 08:50:39 -07:00
|
|
|
<n8n-icon-button
|
2023-07-26 00:25:01 -07:00
|
|
|
v-if="canPinData && !isReadOnlyRoute && !readOnlyEnv"
|
2022-07-20 08:50:39 -07:00
|
|
|
v-show="!editMode.enabled"
|
|
|
|
:title="$locale.baseText('runData.editOutput')"
|
|
|
|
:circle="false"
|
|
|
|
:disabled="node.disabled"
|
|
|
|
class="ml-2xs"
|
|
|
|
icon="pencil-alt"
|
|
|
|
type="tertiary"
|
2023-01-18 06:48:36 -08:00
|
|
|
data-test-id="ndv-edit-pinned-data"
|
2022-07-20 08:50:39 -07:00
|
|
|
@click="enterEditMode({ origin: 'editIconButton' })"
|
|
|
|
/>
|
|
|
|
<n8n-tooltip
|
2023-11-15 07:19:48 -08:00
|
|
|
v-if="canPinData && rawInputData.length"
|
2022-07-20 08:50:39 -07:00
|
|
|
v-show="!editMode.enabled"
|
2023-12-28 00:49:58 -08:00
|
|
|
placement="bottom-end"
|
2023-07-28 00:51:07 -07:00
|
|
|
:visible="
|
|
|
|
isControlledPinDataTooltip
|
|
|
|
? isControlledPinDataTooltip && pinDataDiscoveryTooltipVisible
|
|
|
|
: undefined
|
|
|
|
"
|
2022-07-20 08:50:39 -07:00
|
|
|
>
|
2023-12-28 00:49:58 -08:00
|
|
|
<template v-if="!isControlledPinDataTooltip" #content>
|
2023-03-16 02:19:12 -07:00
|
|
|
<div :class="$style.tooltipContainer">
|
2022-07-20 08:50:39 -07:00
|
|
|
<strong>{{ $locale.baseText('ndv.pinData.pin.title') }}</strong>
|
|
|
|
<n8n-text size="small" tag="p">
|
|
|
|
{{ $locale.baseText('ndv.pinData.pin.description') }}
|
|
|
|
|
|
|
|
<n8n-link :to="dataPinningDocsUrl" size="small">
|
|
|
|
{{ $locale.baseText('ndv.pinData.pin.link') }}
|
|
|
|
</n8n-link>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
</template>
|
2023-12-28 00:49:58 -08:00
|
|
|
<template v-else #content>
|
2023-03-16 02:19:12 -07:00
|
|
|
<div :class="$style.tooltipContainer">
|
2022-07-20 08:50:39 -07:00
|
|
|
{{ $locale.baseText('node.discovery.pinData.ndv') }}
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<n8n-icon-button
|
2023-03-16 02:19:12 -07:00
|
|
|
:class="['ml-2xs', $style.pinDataButton]"
|
2022-07-20 08:50:39 -07:00
|
|
|
type="tertiary"
|
2022-09-21 03:21:08 -07:00
|
|
|
:active="hasPinData"
|
2022-07-20 08:50:39 -07:00
|
|
|
icon="thumbtack"
|
2023-06-27 04:05:20 -07:00
|
|
|
:disabled="
|
2023-07-26 00:25:01 -07:00
|
|
|
editMode.enabled ||
|
2023-11-03 04:07:04 -07:00
|
|
|
(rawInputData.length === 0 && !hasPinData) ||
|
2023-07-26 00:25:01 -07:00
|
|
|
isReadOnlyRoute ||
|
|
|
|
readOnlyEnv
|
2023-06-27 04:05:20 -07:00
|
|
|
"
|
2023-01-18 06:48:36 -08:00
|
|
|
data-test-id="ndv-pin-data"
|
2023-12-28 00:49:58 -08:00
|
|
|
@click="onTogglePinData({ source: 'pin-icon-click' })"
|
2022-07-20 08:50:39 -07:00
|
|
|
/>
|
|
|
|
</n8n-tooltip>
|
|
|
|
|
2023-12-28 00:49:58 -08:00
|
|
|
<div v-show="editMode.enabled" :class="$style.editModeActions">
|
2022-07-20 08:50:39 -07:00
|
|
|
<n8n-button
|
|
|
|
type="tertiary"
|
|
|
|
:label="$locale.baseText('runData.editor.cancel')"
|
|
|
|
@click="onClickCancelEdit"
|
|
|
|
/>
|
|
|
|
<n8n-button
|
|
|
|
class="ml-2xs"
|
|
|
|
type="primary"
|
|
|
|
:label="$locale.baseText('runData.editor.save')"
|
|
|
|
@click="onClickSaveEdit"
|
|
|
|
/>
|
|
|
|
</div>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
2023-04-21 05:08:51 -07:00
|
|
|
<div
|
|
|
|
v-if="maxRunIndex > 0"
|
|
|
|
v-show="!editMode.enabled"
|
2023-12-28 00:49:58 -08:00
|
|
|
:class="$style.runSelector"
|
2023-04-21 05:08:51 -07:00
|
|
|
data-test-id="run-selector"
|
|
|
|
>
|
2023-11-15 07:19:48 -08:00
|
|
|
<div :class="$style.runSelectorWrapper">
|
|
|
|
<n8n-select
|
2022-07-26 00:55:27 -07:00
|
|
|
size="small"
|
2023-12-28 00:49:58 -08:00
|
|
|
:model-value="runIndex"
|
|
|
|
teleported
|
2023-11-15 07:19:48 -08:00
|
|
|
@update:modelValue="onRunIndexChange"
|
|
|
|
@click.stop
|
|
|
|
>
|
|
|
|
<template #prepend>{{ $locale.baseText('ndv.output.run') }}</template>
|
|
|
|
<n8n-option
|
|
|
|
v-for="option in maxRunIndex + 1"
|
2023-12-28 00:49:58 -08:00
|
|
|
:key="option"
|
2023-11-15 07:19:48 -08:00
|
|
|
:label="getRunLabel(option)"
|
|
|
|
:value="option - 1"
|
|
|
|
></n8n-option>
|
|
|
|
</n8n-select>
|
2023-12-28 00:49:58 -08:00
|
|
|
<n8n-tooltip v-if="canLinkRuns" placement="right">
|
2023-11-15 07:19:48 -08:00
|
|
|
<template #content>
|
|
|
|
{{ $locale.baseText(linkedRuns ? 'runData.unlinking.hint' : 'runData.linking.hint') }}
|
|
|
|
</template>
|
|
|
|
<n8n-icon-button
|
|
|
|
class="linkRun"
|
|
|
|
:icon="linkedRuns ? 'unlink' : 'link'"
|
|
|
|
text
|
|
|
|
type="tertiary"
|
|
|
|
size="small"
|
|
|
|
@click="toggleLinkRuns"
|
|
|
|
/>
|
|
|
|
</n8n-tooltip>
|
|
|
|
<slot name="run-info"></slot>
|
|
|
|
</div>
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataSearch
|
2023-11-15 07:19:48 -08:00
|
|
|
v-if="showIOSearch"
|
|
|
|
v-model="search"
|
2023-12-28 00:49:58 -08:00
|
|
|
:pane-type="paneType"
|
|
|
|
:is-area-active="isPaneActive"
|
2023-11-15 07:19:48 -08:00
|
|
|
@focus="activatePane"
|
|
|
|
/>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
2023-10-02 08:33:43 -07:00
|
|
|
<slot name="before-data" />
|
2022-04-11 06:12:13 -07:00
|
|
|
|
2023-04-21 05:08:51 -07:00
|
|
|
<div
|
|
|
|
v-if="maxOutputIndex > 0 && branches.length > 1"
|
|
|
|
:class="$style.tabs"
|
|
|
|
data-test-id="branches"
|
|
|
|
>
|
2023-07-28 00:51:07 -07:00
|
|
|
<n8n-tabs
|
2023-12-28 00:49:58 -08:00
|
|
|
:model-value="currentOutputIndex"
|
2023-07-28 00:51:07 -07:00
|
|
|
:options="branches"
|
|
|
|
@update:modelValue="onBranchChange"
|
|
|
|
/>
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataSearch
|
2023-11-15 07:19:48 -08:00
|
|
|
v-if="showIOSearch"
|
|
|
|
v-model="search"
|
2023-12-28 00:49:58 -08:00
|
|
|
:pane-type="paneType"
|
|
|
|
:is-area-active="isPaneActive"
|
2023-11-15 07:19:48 -08:00
|
|
|
@focus="activatePane"
|
|
|
|
/>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
<div
|
2023-04-03 06:04:59 -07:00
|
|
|
v-else-if="
|
2023-11-15 07:19:48 -08:00
|
|
|
hasNodeRun &&
|
|
|
|
((dataCount > 0 && maxRunIndex === 0) || search) &&
|
|
|
|
!isArtificialRecoveredEventItem
|
2023-04-03 06:04:59 -07:00
|
|
|
"
|
2022-07-20 08:50:39 -07:00
|
|
|
v-show="!editMode.enabled"
|
|
|
|
:class="$style.itemsCount"
|
2023-11-15 07:19:48 -08:00
|
|
|
data-test-id="ndv-items-count"
|
2022-07-20 08:50:39 -07:00
|
|
|
>
|
2023-11-15 07:19:48 -08:00
|
|
|
<n8n-text v-if="search">
|
|
|
|
{{
|
|
|
|
$locale.baseText('ndv.search.items', {
|
|
|
|
adjustToNumber: unfilteredDataCount,
|
|
|
|
interpolate: { matched: dataCount, total: unfilteredDataCount },
|
|
|
|
})
|
|
|
|
}}
|
2022-04-11 06:12:13 -07:00
|
|
|
</n8n-text>
|
2023-11-15 07:19:48 -08:00
|
|
|
<n8n-text v-else>
|
|
|
|
{{
|
|
|
|
$locale.baseText('ndv.output.items', {
|
|
|
|
adjustToNumber: dataCount,
|
|
|
|
interpolate: { count: dataCount },
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
</n8n-text>
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataSearch
|
2023-11-15 07:19:48 -08:00
|
|
|
v-if="showIOSearch"
|
|
|
|
v-model="search"
|
2023-12-28 00:49:58 -08:00
|
|
|
:pane-type="paneType"
|
|
|
|
:is-area-active="isPaneActive"
|
2023-11-15 07:19:48 -08:00
|
|
|
@focus="activatePane"
|
|
|
|
/>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
2023-12-28 00:49:58 -08:00
|
|
|
<div ref="dataContainer" :class="$style.dataContainer" data-test-id="ndv-data-container">
|
2023-02-06 20:47:37 -08:00
|
|
|
<div v-if="isExecuting" :class="$style.center" data-test-id="ndv-executing">
|
2022-05-23 08:56:15 -07:00
|
|
|
<div :class="$style.spinner"><n8n-spinner type="ring" /></div>
|
|
|
|
<n8n-text>{{ executingMessage }}</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
<div v-else-if="editMode.enabled" :class="$style.editMode">
|
|
|
|
<div :class="[$style.editModeBody, 'ignore-key-press']">
|
2023-12-28 00:49:58 -08:00
|
|
|
<CodeNodeEditor
|
|
|
|
:model-value="editMode.value"
|
2023-04-25 07:57:21 -07:00
|
|
|
language="json"
|
2023-07-28 00:51:07 -07:00
|
|
|
@update:modelValue="ndvStore.setOutputPanelEditModeValue($event)"
|
2022-07-20 08:50:39 -07:00
|
|
|
/>
|
|
|
|
</div>
|
2023-03-16 02:19:12 -07:00
|
|
|
<div :class="$style.editModeFooter">
|
|
|
|
<n8n-info-tip :bold="false" :class="$style.editModeFooterInfotip">
|
2022-07-20 08:50:39 -07:00
|
|
|
{{ $locale.baseText('runData.editor.copyDataInfo') }}
|
2022-08-04 05:57:19 -07:00
|
|
|
<n8n-link :to="dataEditingDocsUrl" size="small">
|
2022-07-20 08:50:39 -07:00
|
|
|
{{ $locale.baseText('generic.learnMore') }}
|
|
|
|
</n8n-link>
|
|
|
|
</n8n-info-tip>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
feat(editor, core, cli): implement new workflow experience (#4358)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node (#4108)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node
* feat(editor): Do not show duplicate button if canvas contains `maxNodes` amount of nodes
* feat(ManualTrigger node): Implement ManualTrigger node (#4110)
* feat(ManualTrigger node): Implement ManualTrigger node
* :memo: Remove generics doc items from ManualTrigger node
* feat(editor-ui): Trigger tab redesign (#4150)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* 🎨 Use kebab case for main-panel and icon component
* :label: Improve types
* feat(editor-ui): Redesign search input inside node creator panel (#4204)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* :sparkles: Redesign search input and unify usage of categorized items
* :label: Use lowercase "Boolean" as `isSearchVisible` computed return type
* :fire: Remove useless emit
* :sparkles: Implement no result view based on subcategory, minor fixes
* :art: Remove unused properties
* feat(node-email): Change EmailReadImap display name and name (#4239)
* feat(editor-ui): Implement "Choose a Triger" action and related behaviour (#4226)
* :sparkles: Implement "Choose a Triger" action and related behaviour
* :mute: Lint fix
* :recycle: Remove PlaceholderTrigger node, add a button instead
* :art: Merge onMouseEnter and onMouseLeave to a single function
* :bulb: Add comment
* :fire: Remove PlaceholderNode registration
* :art: Rename TriggerPlaceholderButton to CanvasAddButton
* :sparkles: Add method to unregister custom action and rework CanvasAddButton centering logic
* :art: Run `setRecenteredCanvasAddButtonPosition` on `CanvasAddButton` mount
* fix(editor): Fix selecting of node from node-creator panel by clicking
* :twisted_rightwards_arrows: Merge fixes
* fix(editor): Show execute workflow trigger instead of workflow trigger in the trigger helper panel
* feat(editor): Fix node creator panel slide transition (#4261)
* fix(editor): Fix node creator panel slide-in/slide-out transitions
* :art: Fix naming
* :art: Use kebab-case for transition component name
* feat(editor): Disable execution and show notice when user tries to run workflow without enabled triggers
* fix(editor): Address first batch of new WF experience review (#4279)
* fix(editor): Fix first batch of review items
* bug(editor): Fix nodeview canvas add button centering
* :mute: Fix linter errors
* bug(ManualTrigger Node): Fix manual trigger node execution
* fix(editor): Do not show canvas add button in execution or demo mode and prevent clicking if creator is open
* fix(editor): do not show pin data tooltip for manual trigger node
* fix(editor): do not use nodeViewOffset on zoomToFit
* :lipstick: Add margin for last node creator item and set font-weight to 700 for category title
* :sparkles: Position welcome note next to the added trigger node
* :bug: Remve always true welcome note
* feat(editor): Minor UI and UX tweaks (#4328)
* :lipstick: Make top viewport buttons less prominent
* :sparkles: Allow user to switch to all tabs if it contains filter results, move nodecreator state props to its own module
* :mute: Fix linting errors
* :mute: Fix linting errors
* :mute: Fix linting errors
* chore(build): Ping Turbo version to 1.5.5
* :lipstick: Minor traigger panel and node view style changes
* :speech_balloon: Update display name of execute workflow trigger
* feat(core, editor): Update subworkflow execution logic (#4269)
* :sparkles: Implement `findWorkflowStart`
* :zap: Extend `WorkflowOperationError`
* :zap: Add `WorkflowOperationError` to toast
* :blue_book: Extend interface
* :sparkles: Add `subworkflowExecutionError` to store
* :sparkles: Create `SubworkflowOperationError`
* :zap: Render subworkflow error as node error
* :truck: Move subworkflow start validation to `cli`
* :zap: Reset subworkflow execution error state
* :fire: Remove unused import
* :zap: Adjust CLI commands
* :fire: Remove unneeded check
* :fire: Remove stray log
* :zap: Simplify syntax
* :zap: Sort in case both Start and EWT present
* :recycle: Address Omar's feedback
* :fire: Remove unneeded lint exception
* :pencil2: Fix copy
* :shirt: Fix lint
* fix: moved find start node function to catchable place
Co-authored-by: Omar Ajoue <krynble@gmail.com>
* :lipstick: Change ExecuteWorkflow node to primary
* :sparkles: Allow user to navigate to all tab if it contains search results
* :bug: Fixed canvas control button while in demo, disable workflow activation for non-activavle nodes and revert zoomToFit bottom offset
* :fix: Do not chow request text if there's results
* :speech_balloon: Update noResults text
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
2022-10-18 05:23:22 -07:00
|
|
|
<div
|
|
|
|
v-else-if="paneType === 'output' && hasSubworkflowExecutionError"
|
|
|
|
:class="$style.stretchVertically"
|
|
|
|
>
|
|
|
|
<NodeErrorView :error="subworkflowExecutionError" :class="$style.errorDisplay" />
|
|
|
|
</div>
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
<div v-else-if="!hasNodeRun" :class="$style.center">
|
|
|
|
<slot name="node-not-run"></slot>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
2019-10-02 06:30:51 -07:00
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
<div v-else-if="paneType === 'input' && node.disabled" :class="$style.center">
|
|
|
|
<n8n-text>
|
|
|
|
{{ $locale.baseText('ndv.input.disabled', { interpolate: { nodeName: node.name } }) }}
|
|
|
|
<n8n-link @click="enableNode">
|
|
|
|
{{ $locale.baseText('ndv.input.disabled.cta') }}
|
|
|
|
</n8n-link>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2023-04-03 06:04:59 -07:00
|
|
|
<div v-else-if="hasNodeRun && isArtificialRecoveredEventItem" :class="$style.center">
|
2023-04-25 07:57:21 -07:00
|
|
|
<slot name="recovered-artificial-output-data"></slot>
|
2023-02-17 01:54:07 -08:00
|
|
|
</div>
|
|
|
|
|
2022-09-19 03:26:02 -07:00
|
|
|
<div v-else-if="hasNodeRun && hasRunError" :class="$style.stretchVertically">
|
|
|
|
<n8n-text v-if="isPaneTypeInput" :class="$style.center" size="large" tag="p" bold>
|
|
|
|
{{
|
|
|
|
$locale.baseText('nodeErrorView.inputPanel.previousNodeError.title', {
|
|
|
|
interpolate: { nodeName: node.name },
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
</n8n-text>
|
2023-12-28 00:49:58 -08:00
|
|
|
<slot v-else-if="$slots['content']" name="content"></slot>
|
2022-10-10 01:00:54 -07:00
|
|
|
<NodeErrorView
|
|
|
|
v-else
|
|
|
|
:error="workflowRunData[node.name][runIndex].error"
|
|
|
|
:class="$style.dataDisplay"
|
|
|
|
/>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div
|
2023-11-15 07:19:48 -08:00
|
|
|
v-else-if="
|
|
|
|
hasNodeRun && (!unfilteredDataCount || (search && !dataCount)) && branches.length > 1
|
|
|
|
"
|
2022-04-11 06:12:13 -07:00
|
|
|
:class="$style.center"
|
|
|
|
>
|
2023-11-15 07:19:48 -08:00
|
|
|
<div v-if="search">
|
|
|
|
<n8n-text tag="h3" size="large">{{
|
|
|
|
$locale.baseText('ndv.search.noMatch.title')
|
|
|
|
}}</n8n-text>
|
|
|
|
<n8n-text>
|
|
|
|
<i18n-t keypath="ndv.search.noMatch.description" tag="span">
|
|
|
|
<template #link>
|
|
|
|
<a href="#" @click="onSearchClear">
|
|
|
|
{{ $locale.baseText('ndv.search.noMatch.description.link') }}
|
|
|
|
</a>
|
|
|
|
</template>
|
|
|
|
</i18n-t>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
<n8n-text v-else>
|
2022-05-23 08:56:15 -07:00
|
|
|
{{ noDataInBranchMessage }}
|
2022-04-11 06:12:13 -07:00
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2023-11-15 07:19:48 -08:00
|
|
|
<div v-else-if="hasNodeRun && !inputData.length && !search" :class="$style.center">
|
2023-02-17 01:54:07 -08:00
|
|
|
<slot name="no-output-data">xxx</slot>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && !showData" :class="$style.center">
|
2022-05-23 08:56:15 -07:00
|
|
|
<n8n-text :bold="true" color="text-dark" size="large">{{ tooMuchDataTitle }}</n8n-text>
|
2022-04-11 06:12:13 -07:00
|
|
|
<n8n-text align="center" tag="div"
|
|
|
|
><span
|
|
|
|
v-html="
|
|
|
|
$locale.baseText('ndv.output.tooMuchData.message', {
|
|
|
|
interpolate: { size: dataSizeInMB },
|
|
|
|
})
|
2022-12-14 01:04:10 -08:00
|
|
|
"
|
2022-04-11 06:12:13 -07:00
|
|
|
></span
|
|
|
|
></n8n-text>
|
|
|
|
|
|
|
|
<n8n-button
|
2022-07-20 08:50:39 -07:00
|
|
|
outline
|
2022-04-11 06:12:13 -07:00
|
|
|
:label="$locale.baseText('ndv.output.tooMuchData.showDataAnyway')"
|
2022-05-23 08:56:15 -07:00
|
|
|
@click="showTooMuchData"
|
2022-04-11 06:12:13 -07:00
|
|
|
/>
|
2023-08-07 10:06:38 -07:00
|
|
|
|
|
|
|
<n8n-button
|
|
|
|
size="small"
|
|
|
|
:label="$locale.baseText('runData.downloadBinaryData')"
|
|
|
|
@click="downloadJsonData()"
|
|
|
|
/>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
2023-10-02 08:33:43 -07:00
|
|
|
<!-- V-else slot named content which only renders if $slots.content is passed and hasNodeRun -->
|
2023-12-28 00:49:58 -08:00
|
|
|
<slot v-else-if="hasNodeRun && $slots['content']" name="content"></slot>
|
2023-10-02 08:33:43 -07:00
|
|
|
|
2022-08-24 05:47:42 -07:00
|
|
|
<div
|
|
|
|
v-else-if="
|
|
|
|
hasNodeRun &&
|
|
|
|
displayMode === 'table' &&
|
|
|
|
binaryData.length > 0 &&
|
2023-11-15 07:19:48 -08:00
|
|
|
inputData.length === 1 &&
|
2022-08-24 05:47:42 -07:00
|
|
|
Object.keys(jsonData[0] || {}).length === 0
|
2022-12-14 01:04:10 -08:00
|
|
|
"
|
2022-08-24 05:47:42 -07:00
|
|
|
:class="$style.center"
|
|
|
|
>
|
2022-05-23 08:56:15 -07:00
|
|
|
<n8n-text>
|
|
|
|
{{ $locale.baseText('runData.switchToBinary.info') }}
|
|
|
|
<a @click="switchToBinary">
|
|
|
|
{{ $locale.baseText('runData.switchToBinary.binary') }}
|
|
|
|
</a>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2023-11-15 07:19:48 -08:00
|
|
|
<div v-else-if="showIoSearchNoMatchContent" :class="$style.center">
|
|
|
|
<n8n-text tag="h3" size="large">{{
|
|
|
|
$locale.baseText('ndv.search.noMatch.title')
|
|
|
|
}}</n8n-text>
|
|
|
|
<n8n-text>
|
|
|
|
<i18n-t keypath="ndv.search.noMatch.description" tag="span">
|
|
|
|
<template #link>
|
|
|
|
<a href="#" @click="onSearchClear">
|
|
|
|
{{ $locale.baseText('ndv.search.noMatch.description.link') }}
|
|
|
|
</a>
|
|
|
|
</template>
|
|
|
|
</i18n-t>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2023-07-28 00:51:07 -07:00
|
|
|
<Suspense v-else-if="hasNodeRun && displayMode === 'table'">
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataTable
|
2023-07-28 00:51:07 -07:00
|
|
|
:node="node"
|
2023-12-28 00:49:58 -08:00
|
|
|
:input-data="inputDataPage"
|
|
|
|
:mapping-enabled="mappingEnabled"
|
|
|
|
:distance-from-active="distanceFromActive"
|
|
|
|
:run-index="runIndex"
|
|
|
|
:page-offset="currentPageOffset"
|
|
|
|
:total-runs="maxRunIndex"
|
|
|
|
:has-default-hover-state="paneType === 'input' && !search"
|
2023-11-15 07:19:48 -08:00
|
|
|
:search="search"
|
2023-07-28 00:51:07 -07:00
|
|
|
@mounted="$emit('tableMounted', $event)"
|
|
|
|
@activeRowChanged="onItemHover"
|
|
|
|
@displayModeChange="onDisplayModeChange"
|
|
|
|
/>
|
|
|
|
</Suspense>
|
|
|
|
|
|
|
|
<Suspense v-else-if="hasNodeRun && displayMode === 'json'">
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataJson
|
|
|
|
:pane-type="paneType"
|
|
|
|
:edit-mode="editMode"
|
|
|
|
:sessio-id="sessionId"
|
2023-07-28 00:51:07 -07:00
|
|
|
:node="node"
|
2023-12-28 00:49:58 -08:00
|
|
|
:input-data="inputDataPage"
|
|
|
|
:mapping-enabled="mappingEnabled"
|
|
|
|
:distance-from-active="distanceFromActive"
|
|
|
|
:run-index="runIndex"
|
|
|
|
:total-runs="maxRunIndex"
|
2023-11-15 07:19:48 -08:00
|
|
|
:search="search"
|
2023-07-28 00:51:07 -07:00
|
|
|
/>
|
|
|
|
</Suspense>
|
|
|
|
|
|
|
|
<Suspense v-else-if="hasNodeRun && isPaneTypeOutput && displayMode === 'html'">
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataHtml :input-html="inputDataPage[0].json.html" />
|
2023-07-28 00:51:07 -07:00
|
|
|
</Suspense>
|
|
|
|
|
|
|
|
<Suspense v-else-if="hasNodeRun && isSchemaView">
|
2023-12-28 00:49:58 -08:00
|
|
|
<RunDataSchema
|
2023-07-28 00:51:07 -07:00
|
|
|
:data="jsonData"
|
2023-12-28 00:49:58 -08:00
|
|
|
:mapping-enabled="mappingEnabled"
|
|
|
|
:distance-from-active="distanceFromActive"
|
2023-07-28 00:51:07 -07:00
|
|
|
:node="node"
|
2023-12-28 00:49:58 -08:00
|
|
|
:pane-type="paneType"
|
|
|
|
:run-index="runIndex"
|
|
|
|
:total-runs="maxRunIndex"
|
2023-11-15 07:19:48 -08:00
|
|
|
:search="search"
|
2023-07-28 00:51:07 -07:00
|
|
|
/>
|
|
|
|
</Suspense>
|
2022-12-06 03:50:06 -08:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<div v-else-if="displayMode === 'binary' && binaryData.length === 0" :class="$style.center">
|
|
|
|
<n8n-text align="center" tag="div">{{
|
|
|
|
$locale.baseText('runData.noBinaryDataFound')
|
|
|
|
}}</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="displayMode === 'binary'" :class="$style.dataDisplay">
|
|
|
|
<div v-for="(binaryDataEntry, index) in binaryData" :key="index">
|
2023-12-28 00:49:58 -08:00
|
|
|
<div v-if="binaryData.length > 1" :class="$style.binaryIndex">
|
2022-04-11 06:12:13 -07:00
|
|
|
<div>
|
|
|
|
{{ index + 1 }}
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.binaryRow">
|
|
|
|
<div
|
|
|
|
v-for="(binaryData, key) in binaryDataEntry"
|
|
|
|
:key="index + '_' + key"
|
2023-12-28 00:49:58 -08:00
|
|
|
:class="$style.binaryCell"
|
2022-04-11 06:12:13 -07:00
|
|
|
>
|
2023-10-09 08:43:57 -07:00
|
|
|
<div :data-test-id="'ndv-binary-data_' + index">
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.binaryHeader">
|
|
|
|
{{ key }}
|
|
|
|
</div>
|
|
|
|
<div v-if="binaryData.fileName">
|
|
|
|
<div>
|
|
|
|
<n8n-text size="small" :bold="true"
|
|
|
|
>{{ $locale.baseText('runData.fileName') }}:
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
<div :class="$style.binaryValue">{{ binaryData.fileName }}</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="binaryData.directory">
|
|
|
|
<div>
|
|
|
|
<n8n-text size="small" :bold="true"
|
|
|
|
>{{ $locale.baseText('runData.directory') }}:
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
<div :class="$style.binaryValue">{{ binaryData.directory }}</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="binaryData.fileExtension">
|
|
|
|
<div>
|
|
|
|
<n8n-text size="small" :bold="true"
|
|
|
|
>{{ $locale.baseText('runData.fileExtension') }}:</n8n-text
|
2022-12-14 01:04:10 -08:00
|
|
|
>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
<div :class="$style.binaryValue">{{ binaryData.fileExtension }}</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="binaryData.mimeType">
|
|
|
|
<div>
|
|
|
|
<n8n-text size="small" :bold="true"
|
|
|
|
>{{ $locale.baseText('runData.mimeType') }}:
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
<div :class="$style.binaryValue">{{ binaryData.mimeType }}</div>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
2022-11-24 07:54:43 -08:00
|
|
|
<div v-if="binaryData.fileSize">
|
|
|
|
<div>
|
|
|
|
<n8n-text size="small" :bold="true"
|
|
|
|
>{{ $locale.baseText('runData.fileSize') }}:
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
<div :class="$style.binaryValue">{{ binaryData.fileSize }}</div>
|
|
|
|
</div>
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.binaryButtonContainer">
|
2022-11-24 07:54:43 -08:00
|
|
|
<n8n-button
|
|
|
|
v-if="isViewable(index, key)"
|
|
|
|
size="small"
|
|
|
|
:label="$locale.baseText('runData.showBinaryData')"
|
2023-10-09 08:43:57 -07:00
|
|
|
data-test-id="ndv-view-binary-data"
|
2022-11-24 07:54:43 -08:00
|
|
|
@click="displayBinaryData(index, key)"
|
|
|
|
/>
|
2022-07-20 08:50:39 -07:00
|
|
|
<n8n-button
|
|
|
|
v-if="isDownloadable(index, key)"
|
|
|
|
size="small"
|
|
|
|
type="secondary"
|
|
|
|
:label="$locale.baseText('runData.downloadBinaryData')"
|
2023-10-09 08:43:57 -07:00
|
|
|
data-test-id="ndv-download-binary-data"
|
2022-07-20 08:50:39 -07:00
|
|
|
@click="downloadBinaryData(index, key)"
|
|
|
|
/>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-07-20 08:50:39 -07:00
|
|
|
<div
|
2023-04-27 05:30:00 -07:00
|
|
|
v-if="
|
|
|
|
hasNodeRun &&
|
|
|
|
!hasRunError &&
|
|
|
|
binaryData.length === 0 &&
|
|
|
|
dataCount > pageSize &&
|
2023-11-03 04:07:04 -07:00
|
|
|
!isSchemaView &&
|
|
|
|
!isArtificialRecoveredEventItem
|
2023-04-27 05:30:00 -07:00
|
|
|
"
|
2022-07-20 08:50:39 -07:00
|
|
|
v-show="!editMode.enabled"
|
2023-12-28 00:49:58 -08:00
|
|
|
:class="$style.pagination"
|
2023-11-15 07:19:48 -08:00
|
|
|
data-test-id="ndv-data-pagination"
|
2022-07-20 08:50:39 -07:00
|
|
|
>
|
2022-04-11 06:12:13 -07:00
|
|
|
<el-pagination
|
|
|
|
background
|
|
|
|
:hide-on-single-page="true"
|
2023-07-28 00:51:07 -07:00
|
|
|
:current-page="currentPage"
|
2022-04-11 06:12:13 -07:00
|
|
|
:pager-count="5"
|
|
|
|
:page-size="pageSize"
|
|
|
|
layout="prev, pager, next"
|
|
|
|
:total="dataCount"
|
2023-12-28 00:49:58 -08:00
|
|
|
@update:current-page="onCurrentPageChange"
|
2022-04-11 06:12:13 -07:00
|
|
|
>
|
|
|
|
</el-pagination>
|
|
|
|
|
|
|
|
<div :class="$style.pageSizeSelector">
|
2023-07-28 00:51:07 -07:00
|
|
|
<n8n-select
|
|
|
|
size="mini"
|
2023-12-28 00:49:58 -08:00
|
|
|
:model-value="pageSize"
|
2023-07-28 00:51:07 -07:00
|
|
|
teleported
|
2023-12-28 00:49:58 -08:00
|
|
|
@update:modelValue="onPageSizeChange"
|
2023-07-28 00:51:07 -07:00
|
|
|
>
|
2022-11-18 05:59:31 -08:00
|
|
|
<template #prepend>{{ $locale.baseText('ndv.output.pageSize') }}</template>
|
2022-04-11 06:12:13 -07:00
|
|
|
<n8n-option v-for="size in pageSizes" :key="size" :label="size" :value="size">
|
|
|
|
</n8n-option>
|
|
|
|
<n8n-option :label="$locale.baseText('ndv.output.all')" :value="dataCount"> </n8n-option>
|
|
|
|
</n8n-select>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-10-31 10:59:53 -07:00
|
|
|
<n8n-block-ui :show="blockUI" :class="$style.uiBlocker" />
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2023-07-28 00:51:07 -07:00
|
|
|
import { defineAsyncComponent, defineComponent } from 'vue';
|
2023-04-24 03:18:24 -07:00
|
|
|
import type { PropType } from 'vue';
|
2023-05-16 02:43:46 -07:00
|
|
|
import { mapStores } from 'pinia';
|
2023-11-07 01:06:08 -08:00
|
|
|
import { useStorage } from '@/composables/useStorage';
|
2022-10-06 06:03:55 -07:00
|
|
|
import { saveAs } from 'file-saver';
|
2023-04-24 03:18:24 -07:00
|
|
|
import type {
|
2023-10-02 08:33:43 -07:00
|
|
|
ConnectionTypes,
|
2022-03-28 03:59:53 -07:00
|
|
|
IBinaryData,
|
2019-06-23 03:35:23 -07:00
|
|
|
IBinaryKeyData,
|
|
|
|
IDataObject,
|
|
|
|
INodeExecutionData,
|
2023-10-25 05:34:47 -07:00
|
|
|
INodeOutputConfiguration,
|
2021-11-19 01:17:13 -08:00
|
|
|
INodeTypeDescription,
|
2019-06-23 03:35:23 -07:00
|
|
|
IRunData,
|
|
|
|
IRunExecutionData,
|
|
|
|
} from 'n8n-workflow';
|
2023-10-02 08:33:43 -07:00
|
|
|
import { NodeHelpers, NodeConnectionType } from 'n8n-workflow';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2023-04-24 03:18:24 -07:00
|
|
|
import type {
|
2019-06-23 03:35:23 -07:00
|
|
|
IExecutionResponse,
|
|
|
|
INodeUi,
|
2022-11-04 06:04:31 -07:00
|
|
|
INodeUpdatePropertiesInformation,
|
2022-05-23 08:56:15 -07:00
|
|
|
IRunDataDisplayMode,
|
2022-04-11 06:12:13 -07:00
|
|
|
ITab,
|
2022-12-06 03:50:06 -08:00
|
|
|
NodePanelType,
|
2019-06-23 03:35:23 -07:00
|
|
|
} from '@/Interface';
|
|
|
|
|
2020-05-23 15:53:06 -07:00
|
|
|
import {
|
2022-07-20 08:50:39 -07:00
|
|
|
DATA_PINNING_DOCS_URL,
|
2022-08-04 05:57:19 -07:00
|
|
|
DATA_EDITING_DOCS_URL,
|
2023-03-31 00:27:33 -07:00
|
|
|
NODE_TYPES_EXCLUDED_FROM_OUTPUT_NAME_APPEND,
|
2022-07-20 08:50:39 -07:00
|
|
|
LOCAL_STORAGE_PIN_DATA_DISCOVERY_NDV_FLAG,
|
|
|
|
LOCAL_STORAGE_PIN_DATA_DISCOVERY_CANVAS_FLAG,
|
2020-05-23 15:53:06 -07:00
|
|
|
MAX_DISPLAY_DATA_SIZE,
|
|
|
|
MAX_DISPLAY_ITEMS_AUTO_ALL,
|
2022-07-20 08:50:39 -07:00
|
|
|
TEST_PIN_DATA,
|
2023-01-26 01:03:13 -08:00
|
|
|
HTML_NODE_TYPE,
|
2020-05-23 15:53:06 -07:00
|
|
|
} from '@/constants';
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
|
2021-11-10 10:41:40 -08:00
|
|
|
import NodeErrorView from '@/components/Error/NodeErrorView.vue';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-11-23 04:41:53 -08:00
|
|
|
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
|
|
import { pinData } from '@/mixins/pinData';
|
2023-11-02 01:43:02 -07:00
|
|
|
import type { PinDataSource } from '@/mixins/pinData';
|
2023-04-25 07:57:21 -07:00
|
|
|
import CodeNodeEditor from '@/components/CodeNodeEditor/CodeNodeEditor.vue';
|
2023-04-06 06:32:45 -07:00
|
|
|
import { dataPinningEventBus } from '@/event-bus';
|
2023-11-28 03:15:08 -08:00
|
|
|
import { clearJsonKey, isEmpty } from '@/utils/typesUtils';
|
|
|
|
import { executionDataToJson } from '@/utils/nodeTypesUtils';
|
|
|
|
import { searchInObject } from '@/utils/objectUtils';
|
2023-05-05 01:41:54 -07:00
|
|
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
|
|
|
import { useNDVStore } from '@/stores/ndv.store';
|
|
|
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
2023-12-08 07:59:03 -08:00
|
|
|
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
2023-11-28 03:15:08 -08:00
|
|
|
import { useToast } from '@/composables/useToast';
|
2023-10-25 05:34:47 -07:00
|
|
|
import { isObject } from 'lodash-es';
|
2023-12-06 07:28:09 -08:00
|
|
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
2020-12-18 09:55:53 -08:00
|
|
|
|
2023-07-28 00:51:07 -07:00
|
|
|
const RunDataTable = defineAsyncComponent(async () => import('@/components/RunDataTable.vue'));
|
|
|
|
const RunDataJson = defineAsyncComponent(async () => import('@/components/RunDataJson.vue'));
|
|
|
|
const RunDataSchema = defineAsyncComponent(async () => import('@/components/RunDataSchema.vue'));
|
|
|
|
const RunDataHtml = defineAsyncComponent(async () => import('@/components/RunDataHtml.vue'));
|
2023-11-15 07:19:48 -08:00
|
|
|
const RunDataSearch = defineAsyncComponent(async () => import('@/components/RunDataSearch.vue'));
|
2022-11-07 03:27:02 -08:00
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
export type EnterEditModeArgs = {
|
|
|
|
origin: 'editIconButton' | 'insertTestDataLink';
|
|
|
|
};
|
|
|
|
|
2023-05-16 02:43:46 -07:00
|
|
|
export default defineComponent({
|
2019-06-23 03:35:23 -07:00
|
|
|
name: 'RunData',
|
|
|
|
components: {
|
|
|
|
BinaryDataDisplay,
|
2022-10-06 06:03:55 -07:00
|
|
|
NodeErrorView,
|
2023-04-25 07:57:21 -07:00
|
|
|
CodeNodeEditor,
|
2022-05-23 08:56:15 -07:00
|
|
|
RunDataTable,
|
|
|
|
RunDataJson,
|
2022-12-06 03:50:06 -08:00
|
|
|
RunDataSchema,
|
2023-01-26 01:03:13 -08:00
|
|
|
RunDataHtml,
|
2023-11-15 07:19:48 -08:00
|
|
|
RunDataSearch,
|
2022-05-23 08:56:15 -07:00
|
|
|
},
|
2023-12-28 00:49:58 -08:00
|
|
|
mixins: [genericHelpers, pinData],
|
2022-10-12 05:06:28 -07:00
|
|
|
props: {
|
2022-10-31 10:59:53 -07:00
|
|
|
nodeUi: {
|
2022-11-14 04:28:26 -08:00
|
|
|
type: Object as PropType<INodeUi>,
|
2022-05-23 08:56:15 -07:00
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
runIndex: {
|
2022-07-20 08:50:39 -07:00
|
|
|
type: Number,
|
2023-11-03 04:07:04 -07:00
|
|
|
required: true,
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
linkedRuns: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
canLinkRuns: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
tooMuchDataTitle: {
|
|
|
|
type: String,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
noDataInBranchMessage: {
|
|
|
|
type: String,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
isExecuting: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
executingMessage: {
|
|
|
|
type: String,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
sessionId: {
|
|
|
|
type: String,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
paneType: {
|
2022-12-06 03:50:06 -08:00
|
|
|
type: String as PropType<NodePanelType>,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
overrideOutputs: {
|
2022-10-12 05:06:28 -07:00
|
|
|
type: Array as PropType<number[]>,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-07-20 04:32:51 -07:00
|
|
|
mappingEnabled: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-07-20 04:32:51 -07:00
|
|
|
distanceFromActive: {
|
|
|
|
type: Number,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
|
|
|
blockUI: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-11-14 04:28:26 -08:00
|
|
|
default: false,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-11-14 04:28:26 -08:00
|
|
|
isProductionExecutionPreview: {
|
2022-10-31 10:59:53 -07:00
|
|
|
type: Boolean,
|
2022-11-14 04:28:26 -08:00
|
|
|
default: false,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
isPaneActive: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-05-15 09:41:13 -07:00
|
|
|
setup() {
|
2023-12-08 07:59:03 -08:00
|
|
|
const nodeHelpers = useNodeHelpers();
|
2023-12-06 07:28:09 -08:00
|
|
|
const externalHooks = useExternalHooks();
|
|
|
|
|
2023-05-15 09:41:13 -07:00
|
|
|
return {
|
|
|
|
...useToast(),
|
2023-12-08 07:59:03 -08:00
|
|
|
externalHooks,
|
|
|
|
nodeHelpers,
|
2023-05-15 09:41:13 -07:00
|
|
|
};
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
data() {
|
|
|
|
return {
|
2023-10-02 08:33:43 -07:00
|
|
|
connectionType: NodeConnectionType.Main,
|
2019-06-23 03:35:23 -07:00
|
|
|
binaryDataPreviewActive: false,
|
2019-10-02 06:30:51 -07:00
|
|
|
dataSize: 0,
|
|
|
|
showData: false,
|
2022-10-12 05:06:28 -07:00
|
|
|
outputIndex: 0,
|
2019-06-23 03:35:23 -07:00
|
|
|
binaryDataDisplayVisible: false,
|
2022-11-24 07:54:43 -08:00
|
|
|
binaryDataDisplayData: null as IBinaryData | null,
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2020-05-23 15:53:06 -07:00
|
|
|
MAX_DISPLAY_DATA_SIZE,
|
|
|
|
MAX_DISPLAY_ITEMS_AUTO_ALL,
|
2022-04-11 06:12:13 -07:00
|
|
|
currentPage: 1,
|
|
|
|
pageSize: 10,
|
|
|
|
pageSizes: [10, 25, 50, 100],
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
pinDataDiscoveryTooltipVisible: false,
|
|
|
|
isControlledPinDataTooltip: false,
|
2023-11-15 07:19:48 -08:00
|
|
|
search: '',
|
2022-12-14 01:04:10 -08:00
|
|
|
};
|
|
|
|
},
|
2021-09-15 01:11:59 -07:00
|
|
|
mounted() {
|
|
|
|
this.init();
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-09-19 03:26:02 -07:00
|
|
|
if (!this.isPaneTypeInput) {
|
2023-01-13 03:43:51 -08:00
|
|
|
this.showPinDataDiscoveryTooltip(this.jsonData);
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setNDVBranchIndex({
|
|
|
|
pane: this.paneType as 'input' | 'output',
|
2022-10-12 05:06:28 -07:00
|
|
|
branchIndex: this.currentOutputIndex,
|
|
|
|
});
|
2023-01-26 01:03:13 -08:00
|
|
|
|
2023-11-15 07:19:48 -08:00
|
|
|
if (this.paneType === 'output') {
|
|
|
|
this.setDisplayMode();
|
|
|
|
this.activatePane();
|
|
|
|
}
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-07-28 00:51:07 -07:00
|
|
|
beforeUnmount() {
|
2022-07-20 08:50:39 -07:00
|
|
|
this.hidePinDataDiscoveryTooltip();
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
computed: {
|
2022-11-04 06:04:31 -07:00
|
|
|
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore),
|
|
|
|
activeNode(): INodeUi | null {
|
|
|
|
return this.ndvStore.activeNode;
|
2022-07-20 08:50:39 -07:00
|
|
|
},
|
|
|
|
dataPinningDocsUrl(): string {
|
|
|
|
return DATA_PINNING_DOCS_URL;
|
2021-09-15 01:11:59 -07:00
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
dataEditingDocsUrl(): string {
|
|
|
|
return DATA_EDITING_DOCS_URL;
|
|
|
|
},
|
2022-08-04 05:57:19 -07:00
|
|
|
displayMode(): IRunDataDisplayMode {
|
|
|
|
return this.ndvStore.getPanelDisplayMode(this.paneType);
|
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
node(): INodeUi | null {
|
|
|
|
return (this.nodeUi as INodeUi | null) || null;
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
nodeType(): INodeTypeDescription | null {
|
|
|
|
if (this.node) {
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
2023-03-30 23:31:19 -07:00
|
|
|
isSchemaView(): boolean {
|
|
|
|
return this.displayMode === 'schema';
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
isTriggerNode(): boolean {
|
2023-10-02 08:33:43 -07:00
|
|
|
if (this.node === null) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.nodeTypesStore.isTriggerNode(this.node.type);
|
2022-07-20 08:50:39 -07:00
|
|
|
},
|
|
|
|
canPinData(): boolean {
|
2023-10-02 08:33:43 -07:00
|
|
|
// Only "main" inputs can pin data
|
|
|
|
|
|
|
|
if (this.node === null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const workflow = this.workflowsStore.getCurrentWorkflow();
|
|
|
|
const workflowNode = workflow.getNode(this.node.name);
|
|
|
|
const inputs = NodeHelpers.getNodeInputs(workflow, workflowNode!, this.nodeType!);
|
2023-10-20 01:52:56 -07:00
|
|
|
const inputNames = NodeHelpers.getConnectionTypes(inputs);
|
2023-10-02 08:33:43 -07:00
|
|
|
|
2023-10-20 01:52:56 -07:00
|
|
|
const nonMainInputs = !!inputNames.find((inputName) => inputName !== NodeConnectionType.Main);
|
2023-10-02 08:33:43 -07:00
|
|
|
|
2022-09-19 03:26:02 -07:00
|
|
|
return (
|
2023-10-02 08:33:43 -07:00
|
|
|
!nonMainInputs &&
|
2022-09-19 03:26:02 -07:00
|
|
|
!this.isPaneTypeInput &&
|
2022-07-20 08:50:39 -07:00
|
|
|
this.isPinDataNodeType &&
|
|
|
|
!(this.binaryData && this.binaryData.length > 0)
|
|
|
|
);
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
buttons(): Array<{ label: string; value: string }> {
|
|
|
|
const defaults = [
|
|
|
|
{ label: this.$locale.baseText('runData.table'), value: 'table' },
|
|
|
|
{ label: this.$locale.baseText('runData.json'), value: 'json' },
|
|
|
|
];
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
if (this.binaryData.length) {
|
2022-12-06 03:50:06 -08:00
|
|
|
defaults.push({ label: this.$locale.baseText('runData.binary'), value: 'binary' });
|
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
const schemaView = { label: this.$locale.baseText('runData.schema'), value: 'schema' };
|
2023-10-02 08:33:43 -07:00
|
|
|
if (this.isPaneTypeInput && !isEmpty(this.jsonData)) {
|
2023-03-16 02:19:12 -07:00
|
|
|
defaults.unshift(schemaView);
|
|
|
|
} else {
|
|
|
|
defaults.push(schemaView);
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
2023-01-26 01:03:13 -08:00
|
|
|
if (
|
|
|
|
this.isPaneTypeOutput &&
|
|
|
|
this.activeNode?.type === HTML_NODE_TYPE &&
|
|
|
|
this.activeNode.parameters.operation === 'generateHtmlTemplate'
|
|
|
|
) {
|
|
|
|
defaults.unshift({ label: 'HTML', value: 'html' });
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
return defaults;
|
|
|
|
},
|
2021-08-29 04:36:17 -07:00
|
|
|
hasNodeRun(): boolean {
|
2022-07-20 08:50:39 -07:00
|
|
|
return Boolean(
|
|
|
|
!this.isExecuting &&
|
|
|
|
this.node &&
|
|
|
|
((this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name)) ||
|
|
|
|
this.hasPinData),
|
|
|
|
);
|
2021-08-29 04:36:17 -07:00
|
|
|
},
|
2023-04-03 06:04:59 -07:00
|
|
|
isArtificialRecoveredEventItem(): boolean {
|
2023-11-03 04:07:04 -07:00
|
|
|
return !!this.rawInputData?.[0]?.json?.isArtificialRecoveredEventItem;
|
2023-02-17 01:54:07 -08:00
|
|
|
},
|
feat(editor, core, cli): implement new workflow experience (#4358)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node (#4108)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node
* feat(editor): Do not show duplicate button if canvas contains `maxNodes` amount of nodes
* feat(ManualTrigger node): Implement ManualTrigger node (#4110)
* feat(ManualTrigger node): Implement ManualTrigger node
* :memo: Remove generics doc items from ManualTrigger node
* feat(editor-ui): Trigger tab redesign (#4150)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* 🎨 Use kebab case for main-panel and icon component
* :label: Improve types
* feat(editor-ui): Redesign search input inside node creator panel (#4204)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* :sparkles: Redesign search input and unify usage of categorized items
* :label: Use lowercase "Boolean" as `isSearchVisible` computed return type
* :fire: Remove useless emit
* :sparkles: Implement no result view based on subcategory, minor fixes
* :art: Remove unused properties
* feat(node-email): Change EmailReadImap display name and name (#4239)
* feat(editor-ui): Implement "Choose a Triger" action and related behaviour (#4226)
* :sparkles: Implement "Choose a Triger" action and related behaviour
* :mute: Lint fix
* :recycle: Remove PlaceholderTrigger node, add a button instead
* :art: Merge onMouseEnter and onMouseLeave to a single function
* :bulb: Add comment
* :fire: Remove PlaceholderNode registration
* :art: Rename TriggerPlaceholderButton to CanvasAddButton
* :sparkles: Add method to unregister custom action and rework CanvasAddButton centering logic
* :art: Run `setRecenteredCanvasAddButtonPosition` on `CanvasAddButton` mount
* fix(editor): Fix selecting of node from node-creator panel by clicking
* :twisted_rightwards_arrows: Merge fixes
* fix(editor): Show execute workflow trigger instead of workflow trigger in the trigger helper panel
* feat(editor): Fix node creator panel slide transition (#4261)
* fix(editor): Fix node creator panel slide-in/slide-out transitions
* :art: Fix naming
* :art: Use kebab-case for transition component name
* feat(editor): Disable execution and show notice when user tries to run workflow without enabled triggers
* fix(editor): Address first batch of new WF experience review (#4279)
* fix(editor): Fix first batch of review items
* bug(editor): Fix nodeview canvas add button centering
* :mute: Fix linter errors
* bug(ManualTrigger Node): Fix manual trigger node execution
* fix(editor): Do not show canvas add button in execution or demo mode and prevent clicking if creator is open
* fix(editor): do not show pin data tooltip for manual trigger node
* fix(editor): do not use nodeViewOffset on zoomToFit
* :lipstick: Add margin for last node creator item and set font-weight to 700 for category title
* :sparkles: Position welcome note next to the added trigger node
* :bug: Remve always true welcome note
* feat(editor): Minor UI and UX tweaks (#4328)
* :lipstick: Make top viewport buttons less prominent
* :sparkles: Allow user to switch to all tabs if it contains filter results, move nodecreator state props to its own module
* :mute: Fix linting errors
* :mute: Fix linting errors
* :mute: Fix linting errors
* chore(build): Ping Turbo version to 1.5.5
* :lipstick: Minor traigger panel and node view style changes
* :speech_balloon: Update display name of execute workflow trigger
* feat(core, editor): Update subworkflow execution logic (#4269)
* :sparkles: Implement `findWorkflowStart`
* :zap: Extend `WorkflowOperationError`
* :zap: Add `WorkflowOperationError` to toast
* :blue_book: Extend interface
* :sparkles: Add `subworkflowExecutionError` to store
* :sparkles: Create `SubworkflowOperationError`
* :zap: Render subworkflow error as node error
* :truck: Move subworkflow start validation to `cli`
* :zap: Reset subworkflow execution error state
* :fire: Remove unused import
* :zap: Adjust CLI commands
* :fire: Remove unneeded check
* :fire: Remove stray log
* :zap: Simplify syntax
* :zap: Sort in case both Start and EWT present
* :recycle: Address Omar's feedback
* :fire: Remove unneeded lint exception
* :pencil2: Fix copy
* :shirt: Fix lint
* fix: moved find start node function to catchable place
Co-authored-by: Omar Ajoue <krynble@gmail.com>
* :lipstick: Change ExecuteWorkflow node to primary
* :sparkles: Allow user to navigate to all tab if it contains search results
* :bug: Fixed canvas control button while in demo, disable workflow activation for non-activavle nodes and revert zoomToFit bottom offset
* :fix: Do not chow request text if there's results
* :speech_balloon: Update noResults text
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
2022-10-18 05:23:22 -07:00
|
|
|
subworkflowExecutionError(): Error | null {
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.workflowsStore.subWorkflowExecutionError;
|
feat(editor, core, cli): implement new workflow experience (#4358)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node (#4108)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node
* feat(editor): Do not show duplicate button if canvas contains `maxNodes` amount of nodes
* feat(ManualTrigger node): Implement ManualTrigger node (#4110)
* feat(ManualTrigger node): Implement ManualTrigger node
* :memo: Remove generics doc items from ManualTrigger node
* feat(editor-ui): Trigger tab redesign (#4150)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* 🎨 Use kebab case for main-panel and icon component
* :label: Improve types
* feat(editor-ui): Redesign search input inside node creator panel (#4204)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* :sparkles: Redesign search input and unify usage of categorized items
* :label: Use lowercase "Boolean" as `isSearchVisible` computed return type
* :fire: Remove useless emit
* :sparkles: Implement no result view based on subcategory, minor fixes
* :art: Remove unused properties
* feat(node-email): Change EmailReadImap display name and name (#4239)
* feat(editor-ui): Implement "Choose a Triger" action and related behaviour (#4226)
* :sparkles: Implement "Choose a Triger" action and related behaviour
* :mute: Lint fix
* :recycle: Remove PlaceholderTrigger node, add a button instead
* :art: Merge onMouseEnter and onMouseLeave to a single function
* :bulb: Add comment
* :fire: Remove PlaceholderNode registration
* :art: Rename TriggerPlaceholderButton to CanvasAddButton
* :sparkles: Add method to unregister custom action and rework CanvasAddButton centering logic
* :art: Run `setRecenteredCanvasAddButtonPosition` on `CanvasAddButton` mount
* fix(editor): Fix selecting of node from node-creator panel by clicking
* :twisted_rightwards_arrows: Merge fixes
* fix(editor): Show execute workflow trigger instead of workflow trigger in the trigger helper panel
* feat(editor): Fix node creator panel slide transition (#4261)
* fix(editor): Fix node creator panel slide-in/slide-out transitions
* :art: Fix naming
* :art: Use kebab-case for transition component name
* feat(editor): Disable execution and show notice when user tries to run workflow without enabled triggers
* fix(editor): Address first batch of new WF experience review (#4279)
* fix(editor): Fix first batch of review items
* bug(editor): Fix nodeview canvas add button centering
* :mute: Fix linter errors
* bug(ManualTrigger Node): Fix manual trigger node execution
* fix(editor): Do not show canvas add button in execution or demo mode and prevent clicking if creator is open
* fix(editor): do not show pin data tooltip for manual trigger node
* fix(editor): do not use nodeViewOffset on zoomToFit
* :lipstick: Add margin for last node creator item and set font-weight to 700 for category title
* :sparkles: Position welcome note next to the added trigger node
* :bug: Remve always true welcome note
* feat(editor): Minor UI and UX tweaks (#4328)
* :lipstick: Make top viewport buttons less prominent
* :sparkles: Allow user to switch to all tabs if it contains filter results, move nodecreator state props to its own module
* :mute: Fix linting errors
* :mute: Fix linting errors
* :mute: Fix linting errors
* chore(build): Ping Turbo version to 1.5.5
* :lipstick: Minor traigger panel and node view style changes
* :speech_balloon: Update display name of execute workflow trigger
* feat(core, editor): Update subworkflow execution logic (#4269)
* :sparkles: Implement `findWorkflowStart`
* :zap: Extend `WorkflowOperationError`
* :zap: Add `WorkflowOperationError` to toast
* :blue_book: Extend interface
* :sparkles: Add `subworkflowExecutionError` to store
* :sparkles: Create `SubworkflowOperationError`
* :zap: Render subworkflow error as node error
* :truck: Move subworkflow start validation to `cli`
* :zap: Reset subworkflow execution error state
* :fire: Remove unused import
* :zap: Adjust CLI commands
* :fire: Remove unneeded check
* :fire: Remove stray log
* :zap: Simplify syntax
* :zap: Sort in case both Start and EWT present
* :recycle: Address Omar's feedback
* :fire: Remove unneeded lint exception
* :pencil2: Fix copy
* :shirt: Fix lint
* fix: moved find start node function to catchable place
Co-authored-by: Omar Ajoue <krynble@gmail.com>
* :lipstick: Change ExecuteWorkflow node to primary
* :sparkles: Allow user to navigate to all tab if it contains search results
* :bug: Fixed canvas control button while in demo, disable workflow activation for non-activavle nodes and revert zoomToFit bottom offset
* :fix: Do not chow request text if there's results
* :speech_balloon: Update noResults text
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
2022-10-18 05:23:22 -07:00
|
|
|
},
|
|
|
|
hasSubworkflowExecutionError(): boolean {
|
|
|
|
return Boolean(this.subworkflowExecutionError);
|
|
|
|
},
|
2021-08-29 04:36:17 -07:00
|
|
|
hasRunError(): boolean {
|
2023-10-02 08:33:43 -07:00
|
|
|
return Boolean(this.node && this.workflowRunData?.[this.node.name]?.[this.runIndex]?.error);
|
2021-08-29 04:36:17 -07:00
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
workflowExecution(): IExecutionResponse | null {
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.workflowsStore.getWorkflowExecution;
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
workflowRunData(): IRunData | null {
|
|
|
|
if (this.workflowExecution === null) {
|
2022-04-11 06:12:13 -07:00
|
|
|
return null;
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-09-21 02:51:20 -07:00
|
|
|
const executionData: IRunExecutionData | undefined = this.workflowExecution.data;
|
2023-10-02 08:33:43 -07:00
|
|
|
if (executionData?.resultData) {
|
2022-04-11 06:12:13 -07:00
|
|
|
return executionData.resultData.runData;
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
return null;
|
2020-05-23 15:53:06 -07:00
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
dataCount(): number {
|
2022-05-23 08:56:15 -07:00
|
|
|
return this.getDataCount(this.runIndex, this.currentOutputIndex);
|
2022-04-11 06:12:13 -07:00
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
unfilteredDataCount(): number {
|
|
|
|
return this.pinData ? this.pinData.length : this.rawInputData.length;
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
dataSizeInMB(): string {
|
|
|
|
return (this.dataSize / 1024 / 1000).toLocaleString();
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
maxOutputIndex(): number {
|
2023-10-02 08:33:43 -07:00
|
|
|
if (this.node === null || this.runIndex === undefined) {
|
2019-06-23 03:35:23 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const runData: IRunData | null = this.workflowRunData;
|
|
|
|
|
|
|
|
if (runData === null || !runData.hasOwnProperty(this.node.name)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runData[this.node.name].length < this.runIndex) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
if (runData[this.node.name][this.runIndex]) {
|
|
|
|
const taskData = runData[this.node.name][this.runIndex].data;
|
2023-10-02 08:33:43 -07:00
|
|
|
if (taskData?.main) {
|
2022-05-23 08:56:15 -07:00
|
|
|
return taskData.main.length - 1;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
|
|
|
return 0;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-10-12 05:06:28 -07:00
|
|
|
currentPageOffset(): number {
|
|
|
|
return this.pageSize * (this.currentPage - 1);
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
maxRunIndex(): number {
|
|
|
|
if (this.node === null) {
|
2022-05-23 08:56:15 -07:00
|
|
|
return 0;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const runData: IRunData | null = this.workflowRunData;
|
|
|
|
|
|
|
|
if (runData === null || !runData.hasOwnProperty(this.node.name)) {
|
|
|
|
return 0;
|
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
|
|
|
if (runData[this.node.name].length) {
|
|
|
|
return runData[this.node.name].length - 1;
|
|
|
|
}
|
|
|
|
|
2019-12-23 12:54:27 -08:00
|
|
|
return 0;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2019-12-23 12:54:27 -08:00
|
|
|
rawInputData(): INodeExecutionData[] {
|
2023-11-03 04:07:04 -07:00
|
|
|
return this.getRawInputData(this.runIndex, this.currentOutputIndex, this.connectionType);
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
inputData(): INodeExecutionData[] {
|
2023-11-15 07:19:48 -08:00
|
|
|
const pinOrLiveData = this.getPinDataOrLiveData(this.rawInputData);
|
|
|
|
return this.getFilteredData(pinOrLiveData);
|
2023-11-03 04:07:04 -07:00
|
|
|
},
|
|
|
|
inputDataPage(): INodeExecutionData[] {
|
2022-06-20 12:39:24 -07:00
|
|
|
const offset = this.pageSize * (this.currentPage - 1);
|
2023-11-03 04:07:04 -07:00
|
|
|
return this.inputData.slice(offset, offset + this.pageSize);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-10-12 05:06:28 -07:00
|
|
|
jsonData(): IDataObject[] {
|
|
|
|
return executionDataToJson(this.inputData);
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
binaryData(): IBinaryKeyData[] {
|
|
|
|
if (!this.node) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2023-12-08 07:59:03 -08:00
|
|
|
const binaryData = this.nodeHelpers.getBinaryData(
|
2022-07-20 08:50:39 -07:00
|
|
|
this.workflowRunData,
|
2022-06-20 12:39:24 -07:00
|
|
|
this.node.name,
|
2022-07-20 08:50:39 -07:00
|
|
|
this.runIndex,
|
2022-05-23 08:56:15 -07:00
|
|
|
this.currentOutputIndex,
|
2022-12-14 01:04:10 -08:00
|
|
|
);
|
2022-07-20 08:50:39 -07:00
|
|
|
return binaryData.filter((data) => Boolean(data && Object.keys(data).length));
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
currentOutputIndex(): number {
|
2023-10-02 08:33:43 -07:00
|
|
|
if (this.overrideOutputs?.length && !this.overrideOutputs.includes(this.outputIndex)) {
|
|
|
|
return this.overrideOutputs[0];
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
|
|
|
return this.outputIndex;
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
branches(): ITab[] {
|
2023-10-25 05:34:47 -07:00
|
|
|
const capitalize = (name: string) => name.charAt(0).toLocaleUpperCase() + name.slice(1);
|
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
const branches: ITab[] = [];
|
2023-03-31 00:27:33 -07:00
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
for (let i = 0; i <= this.maxOutputIndex; i++) {
|
|
|
|
if (this.overrideOutputs && !this.overrideOutputs.includes(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-11-15 07:19:48 -08:00
|
|
|
const totalItemsCount = this.getRawInputData(this.runIndex, i).length;
|
2022-07-20 08:50:39 -07:00
|
|
|
const itemsCount = this.getDataCount(this.runIndex, i);
|
2023-11-15 07:19:48 -08:00
|
|
|
const items = this.search
|
|
|
|
? this.$locale.baseText('ndv.search.items', {
|
|
|
|
adjustToNumber: totalItemsCount,
|
|
|
|
interpolate: { matched: itemsCount, total: totalItemsCount },
|
|
|
|
})
|
|
|
|
: this.$locale.baseText('ndv.output.items', {
|
|
|
|
adjustToNumber: itemsCount,
|
|
|
|
interpolate: { count: itemsCount },
|
|
|
|
});
|
2022-04-11 06:12:13 -07:00
|
|
|
let outputName = this.getOutputName(i);
|
2023-10-25 05:34:47 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
if (`${outputName}` === `${i}`) {
|
2022-07-20 08:50:39 -07:00
|
|
|
outputName = `${this.$locale.baseText('ndv.output')} ${outputName}`;
|
|
|
|
} else {
|
2023-03-31 00:27:33 -07:00
|
|
|
const appendBranchWord = NODE_TYPES_EXCLUDED_FROM_OUTPUT_NAME_APPEND.includes(
|
|
|
|
this.node?.type,
|
|
|
|
)
|
|
|
|
? ''
|
|
|
|
: ` ${this.$locale.baseText('ndv.output.branch')}`;
|
|
|
|
outputName = capitalize(`${this.getOutputName(i)}${appendBranchWord}`);
|
2022-07-20 08:50:39 -07:00
|
|
|
}
|
|
|
|
branches.push({
|
2023-11-15 07:19:48 -08:00
|
|
|
label:
|
|
|
|
(this.search && itemsCount) || totalItemsCount
|
|
|
|
? `${outputName} (${items})`
|
|
|
|
: outputName,
|
2022-07-20 08:50:39 -07:00
|
|
|
value: i,
|
|
|
|
});
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
return branches;
|
|
|
|
},
|
|
|
|
editMode(): { enabled: boolean; value: string } {
|
|
|
|
return this.isPaneTypeInput
|
|
|
|
? { enabled: false, value: '' }
|
|
|
|
: this.ndvStore.outputPanelEditMode;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-08-22 08:46:22 -07:00
|
|
|
isPaneTypeInput(): boolean {
|
|
|
|
return this.paneType === 'input';
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-01-26 01:03:13 -08:00
|
|
|
isPaneTypeOutput(): boolean {
|
|
|
|
return this.paneType === 'output';
|
|
|
|
},
|
2023-07-26 00:25:01 -07:00
|
|
|
readOnlyEnv(): boolean {
|
|
|
|
return this.sourceControlStore.preferences.branchReadOnly;
|
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
showIOSearch(): boolean {
|
|
|
|
return this.hasNodeRun && !this.hasRunError;
|
|
|
|
},
|
|
|
|
showIoSearchNoMatchContent(): boolean {
|
|
|
|
return this.hasNodeRun && !this.inputData.length && this.search;
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-10-06 06:03:55 -07:00
|
|
|
methods: {
|
2023-10-25 05:34:47 -07:00
|
|
|
getResolvedNodeOutputs() {
|
|
|
|
if (this.node && this.nodeType) {
|
|
|
|
const workflow = this.workflowsStore.getCurrentWorkflow();
|
|
|
|
const workflowNode = workflow.getNode(this.node.name);
|
|
|
|
|
|
|
|
if (workflowNode) {
|
|
|
|
const outputs = NodeHelpers.getNodeOutputs(workflow, workflowNode, this.nodeType);
|
|
|
|
return outputs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
},
|
2022-10-06 06:03:55 -07:00
|
|
|
onItemHover(itemIndex: number | null) {
|
2022-10-12 05:06:28 -07:00
|
|
|
if (itemIndex === null) {
|
2022-10-06 06:03:55 -07:00
|
|
|
this.$emit('itemHover', null);
|
2022-08-22 08:46:22 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
return;
|
|
|
|
}
|
2022-10-12 05:06:28 -07:00
|
|
|
this.$emit('itemHover', {
|
2022-07-20 08:50:39 -07:00
|
|
|
outputIndex: this.currentOutputIndex,
|
2022-10-12 05:06:28 -07:00
|
|
|
itemIndex,
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
onClickDataPinningDocsLink() {
|
|
|
|
this.$telemetry.track('User clicked ndv link', {
|
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
|
|
|
session_id: this.sessionId,
|
2022-11-04 06:04:31 -07:00
|
|
|
node_type: this.activeNode?.type,
|
2022-07-20 08:50:39 -07:00
|
|
|
pane: 'output',
|
|
|
|
type: 'data-pinning-docs',
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
showPinDataDiscoveryTooltip(value: IDataObject[]) {
|
|
|
|
if (!this.isTriggerNode) {
|
|
|
|
return;
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2023-11-07 01:06:08 -08:00
|
|
|
const pinDataDiscoveryFlag = useStorage(LOCAL_STORAGE_PIN_DATA_DISCOVERY_NDV_FLAG).value;
|
2023-10-27 06:51:20 -07:00
|
|
|
|
|
|
|
if (value && value.length > 0 && !this.isReadOnlyRoute && !pinDataDiscoveryFlag) {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.pinDataDiscoveryComplete();
|
2022-07-20 08:50:39 -07:00
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
this.isControlledPinDataTooltip = true;
|
|
|
|
this.pinDataDiscoveryTooltipVisible = true;
|
2023-04-20 03:26:14 -07:00
|
|
|
dataPinningEventBus.emit('data-pinning-discovery', { isTooltipVisible: true });
|
2022-07-20 08:50:39 -07:00
|
|
|
}, 500); // Wait for NDV to open
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
hidePinDataDiscoveryTooltip() {
|
|
|
|
if (this.pinDataDiscoveryTooltipVisible) {
|
|
|
|
this.isControlledPinDataTooltip = false;
|
|
|
|
this.pinDataDiscoveryTooltipVisible = false;
|
2023-04-20 03:26:14 -07:00
|
|
|
dataPinningEventBus.emit('data-pinning-discovery', { isTooltipVisible: false });
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
pinDataDiscoveryComplete() {
|
2023-11-07 01:06:08 -08:00
|
|
|
useStorage(LOCAL_STORAGE_PIN_DATA_DISCOVERY_NDV_FLAG).value = 'true';
|
|
|
|
useStorage(LOCAL_STORAGE_PIN_DATA_DISCOVERY_CANVAS_FLAG).value = 'true';
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
enterEditMode({ origin }: EnterEditModeArgs) {
|
2022-04-11 06:12:13 -07:00
|
|
|
const inputData = this.pinData
|
2022-10-06 06:03:55 -07:00
|
|
|
? clearJsonKey(this.pinData)
|
2022-11-04 06:04:31 -07:00
|
|
|
: executionDataToJson(this.rawInputData);
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
const data = inputData.length > 0 ? inputData : TEST_PIN_DATA;
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setOutputPanelEditModeEnabled(true);
|
|
|
|
this.ndvStore.setOutputPanelEditModeValue(JSON.stringify(data, null, 2));
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
this.$telemetry.track('User opened ndv edit state', {
|
2022-11-04 06:04:31 -07:00
|
|
|
node_type: this.activeNode?.type,
|
2022-07-20 08:50:39 -07:00
|
|
|
click_type: origin === 'editIconButton' ? 'button' : 'link',
|
|
|
|
session_id: this.sessionId,
|
|
|
|
run_index: this.runIndex,
|
|
|
|
is_output_present: this.hasNodeRun || this.hasPinData,
|
|
|
|
view: !this.hasNodeRun && !this.hasPinData ? 'undefined' : this.displayMode,
|
|
|
|
is_data_pinned: this.hasPinData,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onClickCancelEdit() {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setOutputPanelEditModeEnabled(false);
|
|
|
|
this.ndvStore.setOutputPanelEditModeValue('');
|
2022-07-20 08:50:39 -07:00
|
|
|
this.onExitEditMode({ type: 'cancel' });
|
|
|
|
},
|
|
|
|
onClickSaveEdit() {
|
2023-11-02 01:43:02 -07:00
|
|
|
if (!this.node) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
const { value } = this.editMode;
|
|
|
|
|
|
|
|
this.clearAllStickyNotifications();
|
|
|
|
|
2023-11-02 01:43:02 -07:00
|
|
|
try {
|
|
|
|
this.setPinData(this.node, clearJsonKey(value) as INodeExecutionData[], 'save-edit');
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
2022-07-20 08:50:39 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setOutputPanelEditModeEnabled(false);
|
2022-07-20 08:50:39 -07:00
|
|
|
|
|
|
|
this.onExitEditMode({ type: 'save' });
|
|
|
|
},
|
|
|
|
onExitEditMode({ type }: { type: 'save' | 'cancel' }) {
|
|
|
|
this.$telemetry.track('User closed ndv edit state', {
|
2022-11-04 06:04:31 -07:00
|
|
|
node_type: this.activeNode?.type,
|
2022-07-20 08:50:39 -07:00
|
|
|
session_id: this.sessionId,
|
|
|
|
run_index: this.runIndex,
|
|
|
|
view: this.displayMode,
|
|
|
|
type,
|
|
|
|
});
|
|
|
|
},
|
2023-11-02 01:43:02 -07:00
|
|
|
async onTogglePinData({ source }: { source: PinDataSource }) {
|
|
|
|
if (!this.node) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
if (source === 'pin-icon-click') {
|
2022-08-19 06:35:39 -07:00
|
|
|
const telemetryPayload = {
|
2022-07-20 08:50:39 -07:00
|
|
|
node_type: this.activeNode.type,
|
|
|
|
session_id: this.sessionId,
|
|
|
|
run_index: this.runIndex,
|
|
|
|
view: !this.hasNodeRun && !this.hasPinData ? 'none' : this.displayMode,
|
2022-08-19 06:35:39 -07:00
|
|
|
};
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2023-12-06 07:28:09 -08:00
|
|
|
void this.externalHooks.run('runData.onTogglePinData', telemetryPayload);
|
2022-07-20 08:50:39 -07:00
|
|
|
this.$telemetry.track('User clicked pin data icon', telemetryPayload);
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2023-12-08 07:59:03 -08:00
|
|
|
this.nodeHelpers.updateNodeParameterIssues(this.node);
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2022-11-04 06:04:31 -07:00
|
|
|
if (this.hasPinData) {
|
2023-11-02 01:43:02 -07:00
|
|
|
this.unsetPinData(this.node, source);
|
2022-12-14 01:04:10 -08:00
|
|
|
return;
|
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2023-11-02 01:43:02 -07:00
|
|
|
try {
|
|
|
|
this.setPinData(this.node, this.rawInputData, 'pin-icon-click');
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
2022-12-14 01:04:10 -08:00
|
|
|
return;
|
|
|
|
}
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
if (this.maxRunIndex > 0) {
|
2023-05-15 09:41:13 -07:00
|
|
|
this.showToast({
|
2022-05-23 08:56:15 -07:00
|
|
|
title: this.$locale.baseText('ndv.pinData.pin.multipleRuns.title', {
|
|
|
|
interpolate: {
|
|
|
|
index: `${this.runIndex}`,
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
|
|
|
}),
|
2022-05-23 08:56:15 -07:00
|
|
|
message: this.$locale.baseText('ndv.pinData.pin.multipleRuns.description'),
|
|
|
|
type: 'success',
|
|
|
|
duration: 2000,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-20 08:50:39 -07:00
|
|
|
this.hidePinDataDiscoveryTooltip();
|
|
|
|
this.pinDataDiscoveryComplete();
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
switchToBinary() {
|
|
|
|
this.onDisplayModeChange('binary');
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
onBranchChange(value: number) {
|
2021-09-15 01:11:59 -07:00
|
|
|
this.outputIndex = value;
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
this.$telemetry.track('User changed ndv branch', {
|
|
|
|
session_id: this.sessionId,
|
|
|
|
branch_index: value,
|
|
|
|
node_type: this.activeNode.type,
|
|
|
|
node_type_input_selection: this.nodeType ? this.nodeType.name : '',
|
|
|
|
pane: this.paneType,
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
showTooMuchData() {
|
2019-10-02 06:30:51 -07:00
|
|
|
this.showData = true;
|
2022-05-23 08:56:15 -07:00
|
|
|
this.$telemetry.track('User clicked ndv button', {
|
|
|
|
node_type: this.activeNode.type,
|
2022-11-04 06:04:31 -07:00
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
2022-05-23 08:56:15 -07:00
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
|
|
|
type: 'showTooMuchData',
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
},
|
2023-07-28 00:51:07 -07:00
|
|
|
toggleLinkRuns() {
|
|
|
|
this.linkedRuns ? this.unlinkRun() : this.linkRun();
|
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
linkRun() {
|
|
|
|
this.$emit('linkRun');
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
unlinkRun() {
|
|
|
|
this.$emit('unlinkRun');
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-07-28 00:51:07 -07:00
|
|
|
onCurrentPageChange(value) {
|
|
|
|
this.currentPage = value;
|
2022-05-23 08:56:15 -07:00
|
|
|
this.$telemetry.track('User changed ndv page', {
|
2022-11-04 06:04:31 -07:00
|
|
|
node_type: this.activeNode?.type,
|
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
2022-05-23 08:56:15 -07:00
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
|
|
|
page_selected: this.currentPage,
|
|
|
|
page_size: this.pageSize,
|
|
|
|
items_total: this.dataCount,
|
|
|
|
});
|
2022-04-11 06:12:13 -07:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
onPageSizeChange(pageSize: number) {
|
2022-04-11 06:12:13 -07:00
|
|
|
this.pageSize = pageSize;
|
|
|
|
const maxPage = Math.ceil(this.dataCount / this.pageSize);
|
2022-12-06 03:50:06 -08:00
|
|
|
if (maxPage < this.currentPage) {
|
|
|
|
this.currentPage = maxPage;
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
|
|
|
|
this.$telemetry.track('User changed ndv page size', {
|
2022-11-04 06:04:31 -07:00
|
|
|
node_type: this.activeNode?.type,
|
2022-04-11 06:12:13 -07:00
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
|
|
|
page_selected: this.currentPage,
|
2022-05-23 08:56:15 -07:00
|
|
|
page_size: this.pageSize,
|
2022-04-11 06:12:13 -07:00
|
|
|
items_total: this.dataCount,
|
|
|
|
});
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
onDisplayModeChange(displayMode: IRunDataDisplayMode) {
|
|
|
|
const previous = this.displayMode;
|
|
|
|
this.ndvStore.setPanelDisplayMode({ pane: this.paneType, mode: displayMode });
|
|
|
|
|
2023-04-21 06:59:04 -07:00
|
|
|
const dataContainerRef = this.$refs.dataContainer as Element | undefined;
|
|
|
|
if (dataContainerRef) {
|
|
|
|
const dataDisplay = dataContainerRef.children[0];
|
2022-04-11 06:12:13 -07:00
|
|
|
|
|
|
|
if (dataDisplay) {
|
|
|
|
dataDisplay.scrollTo(0, 0);
|
2022-10-12 07:13:59 -07:00
|
|
|
}
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-10-12 07:13:59 -07:00
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
this.closeBinaryDataDisplay();
|
2023-12-06 07:28:09 -08:00
|
|
|
void this.externalHooks.run('runData.displayModeChanged', {
|
2022-04-11 06:12:13 -07:00
|
|
|
newValue: displayMode,
|
|
|
|
oldValue: previous,
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
2022-04-11 06:12:13 -07:00
|
|
|
if (this.activeNode) {
|
2022-05-23 08:56:15 -07:00
|
|
|
this.$telemetry.track('User changed ndv item view', {
|
|
|
|
previous_view: previous,
|
|
|
|
new_view: displayMode,
|
|
|
|
node_type: this.activeNode.type,
|
2022-11-04 06:04:31 -07:00
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
2022-05-23 08:56:15 -07:00
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
getRunLabel(option: number) {
|
|
|
|
let itemsCount = 0;
|
|
|
|
for (let i = 0; i <= this.maxOutputIndex; i++) {
|
2023-11-15 07:19:48 -08:00
|
|
|
itemsCount += this.getPinDataOrLiveData(this.getRawInputData(option - 1, i)).length;
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2023-11-15 07:19:48 -08:00
|
|
|
const items = this.$locale.baseText('ndv.output.items', {
|
|
|
|
adjustToNumber: itemsCount,
|
|
|
|
interpolate: { count: itemsCount },
|
|
|
|
});
|
|
|
|
const itemsLabel = itemsCount > 0 ? ` (${items})` : '';
|
2022-04-11 06:12:13 -07:00
|
|
|
return option + this.$locale.baseText('ndv.output.of') + (this.maxRunIndex + 1) + itemsLabel;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-11-03 04:07:04 -07:00
|
|
|
getRawInputData(
|
2023-10-02 08:33:43 -07:00
|
|
|
runIndex: number,
|
|
|
|
outputIndex: number,
|
|
|
|
connectionType: ConnectionTypes = NodeConnectionType.Main,
|
2023-11-03 04:07:04 -07:00
|
|
|
): INodeExecutionData[] {
|
|
|
|
let inputData: INodeExecutionData[] = [];
|
2022-04-11 06:12:13 -07:00
|
|
|
|
2023-11-03 04:07:04 -07:00
|
|
|
if (this.node) {
|
2023-12-08 07:59:03 -08:00
|
|
|
inputData = this.nodeHelpers.getNodeInputData(
|
2023-11-03 04:07:04 -07:00
|
|
|
this.node,
|
|
|
|
runIndex,
|
|
|
|
outputIndex,
|
|
|
|
this.paneType,
|
|
|
|
connectionType,
|
|
|
|
);
|
2022-12-14 01:04:10 -08:00
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
|
2023-11-03 04:07:04 -07:00
|
|
|
if (inputData.length === 0 || !Array.isArray(inputData)) {
|
|
|
|
return [];
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
2023-11-03 04:07:04 -07:00
|
|
|
return inputData;
|
|
|
|
},
|
|
|
|
getPinDataOrLiveData(inputData: INodeExecutionData[]): INodeExecutionData[] {
|
|
|
|
if (this.pinData && !this.isProductionExecutionPreview) {
|
|
|
|
return Array.isArray(this.pinData)
|
|
|
|
? this.pinData.map((value) => ({
|
|
|
|
json: value,
|
|
|
|
}))
|
|
|
|
: [
|
|
|
|
{
|
|
|
|
json: this.pinData,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
return inputData;
|
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
getFilteredData(inputData: INodeExecutionData[]): INodeExecutionData[] {
|
|
|
|
if (!this.search) {
|
|
|
|
return inputData;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.currentPage = 1;
|
|
|
|
return inputData.filter(({ json }) => searchInObject(json, this.search));
|
|
|
|
},
|
2023-11-03 04:07:04 -07:00
|
|
|
getDataCount(
|
|
|
|
runIndex: number,
|
|
|
|
outputIndex: number,
|
|
|
|
connectionType: ConnectionTypes = NodeConnectionType.Main,
|
|
|
|
) {
|
|
|
|
if (!this.node) {
|
2022-04-11 06:12:13 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-11-28 07:47:28 -08:00
|
|
|
if (this.workflowRunData?.[this.node.name]?.[runIndex]?.hasOwnProperty('error')) {
|
2022-04-11 06:12:13 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-11-03 04:07:04 -07:00
|
|
|
const rawInputData = this.getRawInputData(runIndex, outputIndex, connectionType);
|
2023-11-15 07:19:48 -08:00
|
|
|
const pinOrLiveData = this.getPinDataOrLiveData(rawInputData);
|
|
|
|
return this.getFilteredData(pinOrLiveData).length;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-11-24 07:54:43 -08:00
|
|
|
init() {
|
|
|
|
// Reset the selected output index every time another node gets selected
|
2021-09-15 01:11:59 -07:00
|
|
|
this.outputIndex = 0;
|
2022-11-24 07:54:43 -08:00
|
|
|
this.refreshDataSize();
|
2022-05-23 08:56:15 -07:00
|
|
|
this.closeBinaryDataDisplay();
|
2023-10-02 08:33:43 -07:00
|
|
|
let outputTypes: ConnectionTypes[] = [];
|
|
|
|
if (this.nodeType !== null && this.node !== null) {
|
2023-10-25 05:34:47 -07:00
|
|
|
const outputs = this.getResolvedNodeOutputs();
|
2023-10-02 08:33:43 -07:00
|
|
|
outputTypes = NodeHelpers.getConnectionTypes(outputs);
|
|
|
|
}
|
|
|
|
this.connectionType = outputTypes.length === 0 ? NodeConnectionType.Main : outputTypes[0];
|
2022-05-23 08:56:15 -07:00
|
|
|
if (this.binaryData.length > 0) {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setPanelDisplayMode({
|
|
|
|
pane: this.paneType as 'input' | 'output',
|
2022-05-23 08:56:15 -07:00
|
|
|
mode: 'binary',
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
2022-05-23 08:56:15 -07:00
|
|
|
} else if (this.displayMode === 'binary') {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setPanelDisplayMode({
|
|
|
|
pane: this.paneType as 'input' | 'output',
|
|
|
|
mode: 'table',
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
closeBinaryDataDisplay() {
|
|
|
|
this.binaryDataDisplayVisible = false;
|
|
|
|
this.binaryDataDisplayData = null;
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
clearExecutionData() {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.workflowsStore.setWorkflowExecutionData(null);
|
2023-12-08 07:59:03 -08:00
|
|
|
this.nodeHelpers.updateNodesExecutionIssues();
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-11-24 07:54:43 -08:00
|
|
|
isViewable(index: number, key: string): boolean {
|
|
|
|
const { fileType } = this.binaryData[index][key];
|
2023-10-11 03:09:19 -07:00
|
|
|
return (
|
|
|
|
!!fileType && ['image', 'audio', 'video', 'text', 'json', 'pdf', 'html'].includes(fileType)
|
|
|
|
);
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2022-11-24 07:54:43 -08:00
|
|
|
isDownloadable(index: number, key: string): boolean {
|
|
|
|
const { mimeType, fileName } = this.binaryData[index][key];
|
|
|
|
return !!(mimeType && fileName);
|
2022-03-28 03:59:53 -07:00
|
|
|
},
|
2022-11-24 07:54:43 -08:00
|
|
|
async downloadBinaryData(index: number, key: string) {
|
|
|
|
const { id, data, fileName, fileExtension, mimeType } = this.binaryData[index][key];
|
2022-12-14 01:04:10 -08:00
|
|
|
|
|
|
|
if (id) {
|
2023-04-24 01:50:49 -07:00
|
|
|
const url = this.workflowsStore.getBinaryUrl(id, 'download', fileName, mimeType);
|
2022-11-24 07:54:43 -08:00
|
|
|
saveAs(url, [fileName, fileExtension].join('.'));
|
2022-12-14 01:04:10 -08:00
|
|
|
return;
|
|
|
|
} else {
|
2022-11-24 07:54:43 -08:00
|
|
|
const bufferString = 'data:' + mimeType + ';base64,' + data;
|
2023-05-10 08:10:03 -07:00
|
|
|
const blob = await fetch(bufferString).then(async (d) => d.blob());
|
2022-11-24 07:54:43 -08:00
|
|
|
saveAs(blob, fileName);
|
2022-03-28 03:59:53 -07:00
|
|
|
}
|
|
|
|
},
|
2023-08-07 10:06:38 -07:00
|
|
|
async downloadJsonData() {
|
|
|
|
const fileName = this.node!.name.replace(/[^\w\d]/g, '_');
|
2023-11-03 04:07:04 -07:00
|
|
|
const blob = new Blob([JSON.stringify(this.rawInputData, null, 2)], {
|
|
|
|
type: 'application/json',
|
|
|
|
});
|
2023-08-07 10:06:38 -07:00
|
|
|
|
|
|
|
saveAs(blob, `${fileName}.json`);
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
displayBinaryData(index: number, key: string) {
|
|
|
|
this.binaryDataDisplayVisible = true;
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
this.binaryDataDisplayData = {
|
|
|
|
node: this.node!.name,
|
|
|
|
runIndex: this.runIndex,
|
2022-05-23 08:56:15 -07:00
|
|
|
outputIndex: this.currentOutputIndex,
|
2019-06-23 03:35:23 -07:00
|
|
|
index,
|
|
|
|
key,
|
|
|
|
};
|
|
|
|
},
|
2020-12-18 09:55:53 -08:00
|
|
|
getOutputName(outputIndex: number) {
|
|
|
|
if (this.node === null) {
|
|
|
|
return outputIndex + 1;
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
const nodeType = this.nodeType;
|
2023-10-25 05:34:47 -07:00
|
|
|
const outputs = this.getResolvedNodeOutputs();
|
|
|
|
const outputConfiguration = outputs?.[outputIndex] as INodeOutputConfiguration;
|
|
|
|
|
|
|
|
if (outputConfiguration && isObject(outputConfiguration)) {
|
|
|
|
return outputConfiguration?.displayName;
|
|
|
|
}
|
2023-10-02 08:33:43 -07:00
|
|
|
if (!nodeType?.outputNames || nodeType.outputNames.length <= outputIndex) {
|
2020-12-18 09:55:53 -08:00
|
|
|
return outputIndex + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodeType.outputNames[outputIndex];
|
|
|
|
},
|
2019-10-04 04:27:50 -07:00
|
|
|
refreshDataSize() {
|
2019-10-02 06:30:51 -07:00
|
|
|
// Hide by default the data from being displayed
|
|
|
|
this.showData = false;
|
2023-11-03 04:07:04 -07:00
|
|
|
const jsonItems = this.inputDataPage.map((item) => item.json);
|
2020-05-23 14:54:56 -07:00
|
|
|
this.dataSize = JSON.stringify(jsonItems).length;
|
2020-05-23 15:53:06 -07:00
|
|
|
if (this.dataSize < this.MAX_DISPLAY_DATA_SIZE) {
|
2019-10-04 04:27:50 -07:00
|
|
|
// Data is reasonable small (< 200kb) so display it directly
|
2019-10-02 06:30:51 -07:00
|
|
|
this.showData = true;
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
onRunIndexChange(run: number) {
|
|
|
|
this.$emit('runChange', run);
|
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
enableNode() {
|
|
|
|
if (this.node) {
|
|
|
|
const updateInformation = {
|
|
|
|
name: this.node.name,
|
|
|
|
properties: {
|
|
|
|
disabled: !this.node.disabled,
|
2022-11-04 06:04:31 -07:00
|
|
|
} as IDataObject,
|
|
|
|
} as INodeUpdatePropertiesInformation;
|
2022-12-14 01:04:10 -08:00
|
|
|
|
2022-11-04 06:04:31 -07:00
|
|
|
this.workflowsStore.updateNodeProperties(updateInformation);
|
2022-07-20 08:50:39 -07:00
|
|
|
}
|
|
|
|
},
|
2023-01-26 01:03:13 -08:00
|
|
|
setDisplayMode() {
|
|
|
|
if (!this.activeNode) return;
|
|
|
|
|
|
|
|
const shouldDisplayHtml =
|
|
|
|
this.activeNode.type === HTML_NODE_TYPE &&
|
|
|
|
this.activeNode.parameters.operation === 'generateHtmlTemplate';
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
if (shouldDisplayHtml) {
|
|
|
|
this.ndvStore.setPanelDisplayMode({
|
|
|
|
pane: 'output',
|
|
|
|
mode: 'html',
|
|
|
|
});
|
|
|
|
}
|
2023-01-26 01:03:13 -08:00
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
activatePane() {
|
|
|
|
this.$emit('activatePane');
|
|
|
|
},
|
|
|
|
onSearchClear() {
|
|
|
|
this.search = '';
|
|
|
|
document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
node() {
|
2021-09-15 01:11:59 -07:00
|
|
|
this.init();
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-01-26 01:03:13 -08:00
|
|
|
hasNodeRun() {
|
|
|
|
if (this.paneType === 'output') this.setDisplayMode();
|
|
|
|
},
|
2023-11-03 04:07:04 -07:00
|
|
|
inputDataPage: {
|
2022-10-06 06:03:55 -07:00
|
|
|
handler(data: INodeExecutionData[]) {
|
|
|
|
if (this.paneType && data) {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setNDVPanelDataIsEmpty({
|
|
|
|
panel: this.paneType as 'input' | 'output',
|
|
|
|
isEmpty: data.every((item) => isEmpty(item.json)),
|
2022-12-14 01:04:10 -08:00
|
|
|
});
|
2022-09-19 03:26:02 -07:00
|
|
|
}
|
|
|
|
},
|
2022-10-06 06:03:55 -07:00
|
|
|
immediate: true,
|
|
|
|
deep: true,
|
2019-10-04 04:27:50 -07:00
|
|
|
},
|
2022-07-20 08:50:39 -07:00
|
|
|
jsonData(value: IDataObject[]) {
|
2019-10-04 04:27:50 -07:00
|
|
|
this.refreshDataSize();
|
2023-01-13 03:43:51 -08:00
|
|
|
this.showPinDataDiscoveryTooltip(value);
|
2019-10-04 04:27:50 -07:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
binaryData(newData: IBinaryKeyData[], prevData: IBinaryKeyData[]) {
|
|
|
|
if (newData.length && !prevData.length && this.displayMode !== 'binary') {
|
|
|
|
this.switchToBinary();
|
|
|
|
} else if (!newData.length && this.displayMode === 'binary') {
|
|
|
|
this.onDisplayModeChange('table');
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-10-12 05:06:28 -07:00
|
|
|
currentOutputIndex(branchIndex: number) {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.ndvStore.setNDVBranchIndex({
|
|
|
|
pane: this.paneType as 'input' | 'output',
|
2022-10-12 05:06:28 -07:00
|
|
|
branchIndex,
|
2019-06-23 03:35:23 -07:00
|
|
|
});
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
2023-11-15 07:19:48 -08:00
|
|
|
search(newSearch: string) {
|
|
|
|
this.$emit('search', newSearch);
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
},
|
|
|
|
});
|
2019-06-23 03:35:23 -07:00
|
|
|
</script>
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<style lang="scss" module>
|
|
|
|
.infoIcon {
|
|
|
|
color: var(--color-foreground-dark);
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
.center {
|
|
|
|
display: flex;
|
|
|
|
height: 100%;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
2022-05-23 08:56:15 -07:00
|
|
|
padding: var(--spacing-s) var(--spacing-s) var(--spacing-xl) var(--spacing-s);
|
2022-04-11 06:12:13 -07:00
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
> * {
|
|
|
|
max-width: 316px;
|
|
|
|
margin-bottom: var(--spacing-2xs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.container {
|
2019-06-23 03:35:23 -07:00
|
|
|
position: relative;
|
2021-09-11 01:15:36 -07:00
|
|
|
width: 100%;
|
2019-06-23 03:35:23 -07:00
|
|
|
height: 100%;
|
2023-11-01 05:33:36 -07:00
|
|
|
background-color: var(--color-run-data-background);
|
2022-04-11 06:12:13 -07:00
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.pinnedDataCallout {
|
2022-07-20 08:50:39 -07:00
|
|
|
border-radius: inherit;
|
|
|
|
border-bottom-right-radius: 0;
|
|
|
|
border-top: 0;
|
|
|
|
border-left: 0;
|
|
|
|
border-right: 0;
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
.header {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
padding: var(--spacing-s) var(--spacing-s) 0 var(--spacing-s);
|
|
|
|
position: relative;
|
2022-09-26 03:02:14 -07:00
|
|
|
overflow-x: auto;
|
|
|
|
overflow-y: hidden;
|
|
|
|
min-height: calc(30px + var(--spacing-s));
|
2022-03-28 03:59:53 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
> *:first-child {
|
|
|
|
flex-grow: 1;
|
|
|
|
}
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.dataContainer {
|
2022-04-11 06:12:13 -07:00
|
|
|
position: relative;
|
2023-10-02 08:33:43 -07:00
|
|
|
overflow-y: auto;
|
2022-04-11 06:12:13 -07:00
|
|
|
height: 100%;
|
2022-07-20 08:50:39 -07:00
|
|
|
|
2022-10-06 06:03:55 -07:00
|
|
|
&:hover {
|
2022-07-20 08:50:39 -07:00
|
|
|
.actions-group {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
2022-10-10 01:00:54 -07:00
|
|
|
.dataDisplay {
|
2022-04-11 06:12:13 -07:00
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
2022-10-06 06:03:55 -07:00
|
|
|
padding: 0 var(--spacing-s) var(--spacing-3xl) var(--spacing-s);
|
2022-04-11 06:12:13 -07:00
|
|
|
right: 0;
|
|
|
|
overflow-y: auto;
|
2023-03-16 02:19:12 -07:00
|
|
|
line-height: var(--font-line-height-xloose);
|
2022-04-11 06:12:13 -07:00
|
|
|
word-break: normal;
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.tabs {
|
2023-11-15 07:19:48 -08:00
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
2022-04-11 06:12:13 -07:00
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.itemsCount {
|
2023-11-15 07:19:48 -08:00
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
2022-04-11 06:12:13 -07:00
|
|
|
margin-left: var(--spacing-s);
|
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.runSelector {
|
2023-11-15 07:19:48 -08:00
|
|
|
padding-left: var(--spacing-s);
|
|
|
|
padding-bottom: var(--spacing-s);
|
2022-05-23 08:56:15 -07:00
|
|
|
display: flex;
|
2023-11-15 07:19:48 -08:00
|
|
|
width: 100%;
|
2022-07-26 00:55:27 -07:00
|
|
|
align-items: center;
|
2023-11-15 07:19:48 -08:00
|
|
|
justify-content: space-between;
|
|
|
|
}
|
2022-05-23 08:56:15 -07:00
|
|
|
|
2023-11-15 07:19:48 -08:00
|
|
|
.runSelectorWrapper {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.pagination {
|
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
bottom: 0;
|
|
|
|
padding: 5px;
|
2023-10-02 08:33:43 -07:00
|
|
|
overflow-y: hidden;
|
2022-09-26 03:02:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.pageSizeSelector {
|
|
|
|
text-transform: capitalize;
|
|
|
|
max-width: 150px;
|
|
|
|
flex: 0 1 auto;
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.binaryIndex {
|
|
|
|
display: block;
|
|
|
|
padding: var(--spacing-2xs);
|
|
|
|
font-size: var(--font-size-2xs);
|
|
|
|
|
|
|
|
> * {
|
|
|
|
display: inline-block;
|
|
|
|
width: 30px;
|
|
|
|
height: 30px;
|
|
|
|
line-height: 30px;
|
|
|
|
border-radius: var(--border-radius-base);
|
|
|
|
text-align: center;
|
|
|
|
background-color: var(--color-foreground-xdark);
|
|
|
|
font-weight: var(--font-weight-bold);
|
|
|
|
color: var(--color-text-xlight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.binaryRow {
|
|
|
|
display: inline-flex;
|
|
|
|
font-size: var(--font-size-2xs);
|
|
|
|
}
|
|
|
|
|
|
|
|
.binaryCell {
|
|
|
|
display: inline-block;
|
|
|
|
width: 300px;
|
|
|
|
overflow: hidden;
|
2022-07-26 03:45:55 -07:00
|
|
|
background-color: var(--color-foreground-xlight);
|
2022-04-11 06:12:13 -07:00
|
|
|
margin-right: var(--spacing-s);
|
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
border-radius: var(--border-radius-base);
|
|
|
|
border: var(--border-base);
|
|
|
|
padding: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.binaryHeader {
|
2022-09-23 07:14:28 -07:00
|
|
|
color: $color-primary;
|
2023-03-16 02:19:12 -07:00
|
|
|
font-weight: var(--font-weight-bold);
|
2022-04-11 06:12:13 -07:00
|
|
|
font-size: 1.2em;
|
2023-03-16 02:19:12 -07:00
|
|
|
padding-bottom: var(--spacing-2xs);
|
|
|
|
margin-bottom: var(--spacing-2xs);
|
2022-07-26 03:45:55 -07:00
|
|
|
border-bottom: 1px solid var(--color-text-light);
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.binaryButtonContainer {
|
|
|
|
margin-top: 1.5em;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
> * {
|
|
|
|
flex-grow: 0;
|
|
|
|
margin-right: var(--spacing-3xs);
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
.binaryValue {
|
|
|
|
white-space: initial;
|
|
|
|
word-wrap: break-word;
|
|
|
|
}
|
|
|
|
|
|
|
|
.displayModes {
|
2022-05-23 08:56:15 -07:00
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
flex-grow: 1;
|
|
|
|
}
|
2023-03-16 02:19:12 -07:00
|
|
|
.tooltipContain {
|
2022-07-20 08:50:39 -07:00
|
|
|
max-width: 240px;
|
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.pinDataButton {
|
2022-07-20 08:50:39 -07:00
|
|
|
svg {
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
.spinner {
|
|
|
|
* {
|
|
|
|
color: var(--color-primary);
|
|
|
|
min-height: 40px;
|
|
|
|
min-width: 40px;
|
|
|
|
}
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
margin-bottom: var(--spacing-s);
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.editMode {
|
2023-04-25 07:57:21 -07:00
|
|
|
height: 100%;
|
2022-07-20 08:50:39 -07:00
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
2023-04-25 07:57:21 -07:00
|
|
|
justify-content: stretch;
|
2022-07-20 08:50:39 -07:00
|
|
|
padding-left: var(--spacing-s);
|
|
|
|
padding-right: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.editModeBody {
|
2022-07-20 08:50:39 -07:00
|
|
|
flex: 1 1 auto;
|
2023-04-25 07:57:21 -07:00
|
|
|
max-height: 100%;
|
2022-07-20 08:50:39 -07:00
|
|
|
width: 100%;
|
2023-04-25 07:57:21 -07:00
|
|
|
overflow: auto;
|
2022-07-20 08:50:39 -07:00
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.editModeFooter {
|
2023-04-25 07:57:21 -07:00
|
|
|
flex: 0 1 auto;
|
2022-07-20 08:50:39 -07:00
|
|
|
display: flex;
|
|
|
|
width: 100%;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
|
|
|
padding-top: var(--spacing-s);
|
2023-04-25 07:57:21 -07:00
|
|
|
padding-bottom: var(--spacing-s);
|
2022-07-20 08:50:39 -07:00
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.editModeFooterInfotip {
|
2022-07-20 08:50:39 -07:00
|
|
|
display: flex;
|
|
|
|
flex: 1;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
2023-03-16 02:19:12 -07:00
|
|
|
.editModeActions {
|
2022-07-20 08:50:39 -07:00
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
align-items: center;
|
|
|
|
margin-left: var(--spacing-s);
|
|
|
|
}
|
2022-09-19 03:26:02 -07:00
|
|
|
|
|
|
|
.stretchVertically {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
2022-10-31 10:59:53 -07:00
|
|
|
.uiBlocker {
|
|
|
|
border-top-left-radius: 0;
|
|
|
|
border-bottom-left-radius: 0;
|
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
</style>
|
2023-04-25 07:57:21 -07:00
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.run-data {
|
|
|
|
.code-node-editor {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
2023-11-15 07:19:48 -08:00
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
:deep(.highlight) {
|
|
|
|
background-color: #f7dc55;
|
|
|
|
color: black;
|
|
|
|
border-radius: var(--border-radius-base);
|
|
|
|
padding: 0 1px;
|
|
|
|
font-weight: normal;
|
|
|
|
font-style: normal;
|
|
|
|
}
|
|
|
|
</style>
|