2019-06-23 03:35:23 -07:00
|
|
|
<template>
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.container">
|
2019-06-23 03:35:23 -07:00
|
|
|
<BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @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-06-20 12:39:24 -07:00
|
|
|
<div v-show="!hasRunError && hasNodeRun && ((jsonData && jsonData.length > 0) || (binaryData && binaryData.length > 0))" @click.stop :class="$style.displayModes">
|
2022-04-11 06:12:13 -07:00
|
|
|
<n8n-radio-buttons
|
|
|
|
:value="displayMode"
|
|
|
|
:options="buttons"
|
|
|
|
@input="onDisplayModeChange"
|
|
|
|
/>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div :class="$style.runSelector" v-if="maxRunIndex > 0" >
|
2022-05-23 08:56:15 -07:00
|
|
|
<n8n-select size="small" :value="runIndex" @input="onRunIndexChange" @click.stop>
|
2022-04-11 06:12:13 -07:00
|
|
|
<template slot="prepend">{{ $locale.baseText('ndv.output.run') }}</template>
|
|
|
|
<n8n-option v-for="option in (maxRunIndex + 1)" :label="getRunLabel(option)" :value="option - 1" :key="option"></n8n-option>
|
|
|
|
</n8n-select>
|
2022-05-23 08:56:15 -07:00
|
|
|
|
|
|
|
|
|
|
|
<n8n-tooltip placement="right" v-if="canLinkRuns" :content="$locale.baseText(linkedRuns ? 'runData.unlinking.hint': 'runData.linking.hint')">
|
|
|
|
<n8n-icon-button v-if="linkedRuns" icon="unlink" type="text" size="small" @click="unlinkRun" />
|
|
|
|
<n8n-icon-button v-else icon="link" type="text" size="small" @click="linkRun" />
|
|
|
|
</n8n-tooltip>
|
|
|
|
|
|
|
|
<slot name="run-info"></slot>
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="maxOutputIndex > 0" :class="{[$style.tabs]: displayMode === 'table'}">
|
2022-05-23 08:56:15 -07:00
|
|
|
<n8n-tabs :value="currentOutputIndex" @input="onBranchChange" :options="branches" />
|
2022-04-11 06:12:13 -07:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && dataCount > 0 && maxRunIndex === 0" :class="$style.itemsCount">
|
|
|
|
<n8n-text>
|
2022-05-23 08:56:15 -07:00
|
|
|
{{ dataCount }} {{ $locale.baseText('ndv.output.items', {adjustToNumber: dataCount}) }}
|
2022-04-11 06:12:13 -07:00
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div :class="$style.dataContainer" ref="dataContainer">
|
|
|
|
<div v-if="hasNodeRun && !hasRunError && displayMode === 'json' && state.path !== deselectedPlaceholder" :class="$style.copyButton">
|
2020-12-18 09:55:53 -08:00
|
|
|
<el-dropdown trigger="click" @command="handleCopyClick">
|
|
|
|
<span class="el-dropdown-link">
|
2021-12-15 04:16:53 -08:00
|
|
|
<n8n-icon-button :title="$locale.baseText('runData.copyToClipboard')" icon="copy" />
|
2020-12-18 09:55:53 -08:00
|
|
|
</span>
|
|
|
|
<el-dropdown-menu slot="dropdown">
|
2021-11-10 10:41:40 -08:00
|
|
|
<el-dropdown-item :command="{command: 'itemPath'}">
|
2021-12-15 04:16:53 -08:00
|
|
|
{{ $locale.baseText('runData.copyItemPath') }}
|
2021-11-10 10:41:40 -08:00
|
|
|
</el-dropdown-item>
|
|
|
|
<el-dropdown-item :command="{command: 'parameterPath'}">
|
2021-12-15 04:16:53 -08:00
|
|
|
{{ $locale.baseText('runData.copyParameterPath') }}
|
2021-11-10 10:41:40 -08:00
|
|
|
</el-dropdown-item>
|
|
|
|
<el-dropdown-item :command="{command: 'value'}">
|
2021-12-15 04:16:53 -08:00
|
|
|
{{ $locale.baseText('runData.copyValue') }}
|
2021-11-10 10:41:40 -08:00
|
|
|
</el-dropdown-item>
|
2020-12-18 09:55:53 -08:00
|
|
|
</el-dropdown-menu>
|
|
|
|
</el-dropdown>
|
|
|
|
</div>
|
2022-04-11 06:12:13 -07:00
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
<div v-if="isExecuting" :class="$style.center">
|
|
|
|
<div :class="$style.spinner"><n8n-spinner type="ring" /></div>
|
|
|
|
<n8n-text>{{ executingMessage }}</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<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-05-23 08:56:15 -07:00
|
|
|
<div v-else-if="hasNodeRun && hasRunError" :class="$style.errorDisplay">
|
2022-04-11 06:12:13 -07:00
|
|
|
<NodeErrorView :error="workflowRunData[node.name][runIndex].error" />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && jsonData && jsonData.length === 0 && branches.length > 1" :class="$style.center">
|
|
|
|
<n8n-text>
|
2022-05-23 08:56:15 -07:00
|
|
|
{{ noDataInBranchMessage }}
|
2022-04-11 06:12:13 -07:00
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && jsonData && jsonData.length === 0" :class="$style.center">
|
2022-05-23 08:56:15 -07:00
|
|
|
<slot name="no-output-data"></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 }})"></span></n8n-text>
|
|
|
|
|
|
|
|
<n8n-button
|
|
|
|
type="outline"
|
|
|
|
: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
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
<div v-else-if="hasNodeRun && displayMode === 'table' && tableData && tableData.columns && tableData.columns.length === 0 && binaryData.length > 0" :class="$style.center">
|
|
|
|
<n8n-text>
|
|
|
|
{{ $locale.baseText('runData.switchToBinary.info') }}
|
|
|
|
<a @click="switchToBinary">
|
|
|
|
{{ $locale.baseText('runData.switchToBinary.binary') }}
|
|
|
|
</a>
|
|
|
|
</n8n-text>
|
|
|
|
</div>
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
<div v-else-if="hasNodeRun && displayMode === 'table' && tableData && tableData.columns && tableData.columns.length === 0" :class="$style.dataDisplay">
|
|
|
|
<table :class="$style.table">
|
|
|
|
<tr>
|
|
|
|
<th :class="$style.emptyCell"></th>
|
|
|
|
</tr>
|
|
|
|
<tr v-for="(row, index1) in tableData.data" :key="index1">
|
|
|
|
<td>
|
2022-05-23 08:56:15 -07:00
|
|
|
<n8n-text>{{ $locale.baseText('runData.emptyItemHint') }}</n8n-text>
|
2022-04-11 06:12:13 -07:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && displayMode === 'table' && tableData" :class="$style.dataDisplay">
|
|
|
|
<table :class="$style.table">
|
|
|
|
<tr>
|
|
|
|
<th v-for="column in (tableData.columns || [])" :key="column">{{column}}</th>
|
|
|
|
</tr>
|
|
|
|
<tr v-for="(row, index1) in tableData.data" :key="index1">
|
|
|
|
<td v-for="(data, index2) in row" :key="index2">{{ [null, undefined].includes(data) ? ' ' : data }}</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else-if="hasNodeRun && displayMode === 'json'" :class="$style.jsonDisplay">
|
|
|
|
<vue-json-pretty
|
|
|
|
:data="jsonData"
|
|
|
|
:deep="10"
|
|
|
|
v-model="state.path"
|
|
|
|
:showLine="true"
|
|
|
|
:showLength="true"
|
|
|
|
selectableType="single"
|
|
|
|
path=""
|
|
|
|
:highlightSelectedNode="true"
|
|
|
|
:selectOnClickNode="true"
|
|
|
|
@click="dataItemClicked"
|
|
|
|
class="json-data"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<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">
|
|
|
|
<div :class="$style.binaryIndex" v-if="binaryData.length > 1">
|
|
|
|
<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 :class="$style.binaryCell" v-for="(binaryData, key) in binaryDataEntry" :key="index + '_' + key">
|
|
|
|
<div>
|
|
|
|
<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></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-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.binaryButtonContainer">
|
|
|
|
<n8n-button size="small" :label="$locale.baseText('runData.showBinaryData')" class="binary-data-show-data-button" @click="displayBinaryData(index, key)" />
|
|
|
|
<n8n-button v-if="isDownloadable(index, key)" size="small" type="outline" :label="$locale.baseText('runData.downloadBinaryData')" class="binary-data-show-data-button" @click="downloadBinaryData(index, key)" />
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-04-11 06:12:13 -07:00
|
|
|
<div :class="$style.pagination" v-if="hasNodeRun && !hasRunError && dataCount > pageSize">
|
|
|
|
<el-pagination
|
|
|
|
background
|
|
|
|
:hide-on-single-page="true"
|
|
|
|
:current-page.sync="currentPage"
|
|
|
|
:pager-count="5"
|
|
|
|
:page-size="pageSize"
|
|
|
|
layout="prev, pager, next"
|
2022-05-23 08:56:15 -07:00
|
|
|
@current-change="onCurrentPageChange"
|
2022-04-11 06:12:13 -07:00
|
|
|
:total="dataCount">
|
|
|
|
</el-pagination>
|
|
|
|
|
|
|
|
<div :class="$style.pageSizeSelector">
|
|
|
|
<n8n-select size="mini" :value="pageSize" @input="onPageSizeChange">
|
|
|
|
<template slot="prepend">{{ $locale.baseText('ndv.output.pageSize') }}</template>
|
|
|
|
<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>
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2020-12-18 09:55:53 -08:00
|
|
|
//@ts-ignore
|
|
|
|
import VueJsonPretty from 'vue-json-pretty';
|
2019-06-23 03:35:23 -07:00
|
|
|
import {
|
|
|
|
GenericValue,
|
2022-03-28 03:59:53 -07:00
|
|
|
IBinaryData,
|
2019-06-23 03:35:23 -07:00
|
|
|
IBinaryKeyData,
|
|
|
|
IDataObject,
|
|
|
|
INodeExecutionData,
|
2021-11-19 01:17:13 -08:00
|
|
|
INodeTypeDescription,
|
2019-06-23 03:35:23 -07:00
|
|
|
IRunData,
|
|
|
|
IRunExecutionData,
|
|
|
|
ITaskData,
|
|
|
|
} from 'n8n-workflow';
|
|
|
|
|
|
|
|
import {
|
|
|
|
IBinaryDisplayData,
|
|
|
|
IExecutionResponse,
|
|
|
|
INodeUi,
|
2022-05-23 08:56:15 -07:00
|
|
|
IRunDataDisplayMode,
|
2022-04-11 06:12:13 -07:00
|
|
|
ITab,
|
2019-06-23 03:35:23 -07:00
|
|
|
ITableData,
|
|
|
|
} from '@/Interface';
|
|
|
|
|
2020-05-23 15:53:06 -07:00
|
|
|
import {
|
|
|
|
MAX_DISPLAY_DATA_SIZE,
|
|
|
|
MAX_DISPLAY_ITEMS_AUTO_ALL,
|
|
|
|
} from '@/constants';
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
|
2022-04-11 06:12:13 -07:00
|
|
|
import WarningTooltip from '@/components/WarningTooltip.vue';
|
2021-11-10 10:41:40 -08:00
|
|
|
import NodeErrorView from '@/components/Error/NodeErrorView.vue';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2020-12-18 09:55:53 -08:00
|
|
|
import { copyPaste } from '@/components/mixins/copyPaste';
|
2021-05-05 17:46:33 -07:00
|
|
|
import { externalHooks } from "@/components/mixins/externalHooks";
|
2019-06-23 03:35:23 -07:00
|
|
|
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
|
|
|
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
|
|
|
|
|
|
|
import mixins from 'vue-typed-mixins';
|
|
|
|
|
2022-03-28 03:59:53 -07:00
|
|
|
import { saveAs } from 'file-saver';
|
|
|
|
|
2020-12-18 09:55:53 -08:00
|
|
|
// A path that does not exist so that nothing is selected by default
|
|
|
|
const deselectedPlaceholder = '_!^&*';
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
export default mixins(
|
2020-12-18 09:55:53 -08:00
|
|
|
copyPaste,
|
2021-05-05 17:46:33 -07:00
|
|
|
externalHooks,
|
2019-06-23 03:35:23 -07:00
|
|
|
genericHelpers,
|
|
|
|
nodeHelpers,
|
|
|
|
)
|
|
|
|
.extend({
|
|
|
|
name: 'RunData',
|
|
|
|
components: {
|
|
|
|
BinaryDataDisplay,
|
2021-04-16 09:33:36 -07:00
|
|
|
NodeErrorView,
|
2020-12-18 09:55:53 -08:00
|
|
|
VueJsonPretty,
|
2022-04-11 06:12:13 -07:00
|
|
|
WarningTooltip,
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-05-23 08:56:15 -07:00
|
|
|
props: {
|
|
|
|
nodeUi: {
|
|
|
|
}, // INodeUi | null
|
|
|
|
runIndex: {
|
|
|
|
type: Number,
|
|
|
|
},
|
|
|
|
linkedRuns: {
|
|
|
|
type: Boolean,
|
|
|
|
},
|
|
|
|
canLinkRuns: {
|
|
|
|
type: Boolean,
|
|
|
|
},
|
|
|
|
tooMuchDataTitle: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
noDataInBranchMessage: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
isExecuting: {
|
|
|
|
type: Boolean,
|
|
|
|
},
|
|
|
|
executingMessage: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
sessionId: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
paneType: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
overrideOutputs: {
|
|
|
|
type: Array,
|
|
|
|
},
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
binaryDataPreviewActive: false,
|
2019-10-02 06:30:51 -07:00
|
|
|
dataSize: 0,
|
2020-12-18 09:55:53 -08:00
|
|
|
deselectedPlaceholder,
|
|
|
|
state: {
|
|
|
|
value: '' as object | number | string,
|
|
|
|
path: deselectedPlaceholder,
|
|
|
|
},
|
2019-10-02 06:30:51 -07:00
|
|
|
showData: false,
|
2019-06-23 03:35:23 -07:00
|
|
|
outputIndex: 0,
|
|
|
|
binaryDataDisplayVisible: false,
|
|
|
|
binaryDataDisplayData: null as IBinaryDisplayData | null,
|
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],
|
2019-06-23 03:35:23 -07:00
|
|
|
};
|
|
|
|
},
|
2021-09-15 01:11:59 -07:00
|
|
|
mounted() {
|
|
|
|
this.init();
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
computed: {
|
2022-05-23 08:56:15 -07:00
|
|
|
activeNode(): INodeUi {
|
|
|
|
return this.$store.getters.activeNode;
|
|
|
|
},
|
|
|
|
displayMode(): IRunDataDisplayMode {
|
|
|
|
return this.$store.getters['ui/getPanelDisplayMode'](this.paneType);
|
|
|
|
},
|
|
|
|
node(): INodeUi | null {
|
|
|
|
return (this.nodeUi as INodeUi | null) || null;
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
nodeType (): INodeTypeDescription | null {
|
|
|
|
if (this.node) {
|
|
|
|
return this.$store.getters.nodeType(this.node.type, this.node.typeVersion);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
buttons(): Array<{label: string, value: string}> {
|
|
|
|
const defaults = [
|
|
|
|
{ label: this.$locale.baseText('runData.table'), value: 'table'},
|
|
|
|
{ label: this.$locale.baseText('runData.json'), value: 'json'},
|
|
|
|
];
|
|
|
|
if (this.binaryData.length) {
|
|
|
|
return [ ...defaults,
|
|
|
|
{ label: this.$locale.baseText('runData.binary'), value: 'binary'},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return defaults;
|
|
|
|
},
|
2021-08-29 04:36:17 -07:00
|
|
|
hasNodeRun(): boolean {
|
2022-05-23 08:56:15 -07:00
|
|
|
return Boolean(!this.isExecuting && this.node && this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name));
|
2021-08-29 04:36:17 -07:00
|
|
|
},
|
|
|
|
hasRunError(): boolean {
|
|
|
|
return Boolean(this.node && this.workflowRunData && this.workflowRunData[this.node.name] && this.workflowRunData[this.node.name][this.runIndex] && this.workflowRunData[this.node.name][this.runIndex].error);
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
workflowExecution (): IExecutionResponse | null {
|
|
|
|
return this.$store.getters.getWorkflowExecution;
|
|
|
|
},
|
|
|
|
workflowRunData (): IRunData | null {
|
|
|
|
if (this.workflowExecution === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
const executionData: IRunExecutionData = this.workflowExecution.data;
|
2022-04-11 06:12:13 -07:00
|
|
|
if (executionData && executionData.resultData) {
|
|
|
|
return executionData.resultData.runData;
|
2020-07-10 01:12:30 -07: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
|
|
|
},
|
|
|
|
dataSizeInMB(): string {
|
|
|
|
return (this.dataSize / 1024 / 1000).toLocaleString();
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
maxOutputIndex (): number {
|
|
|
|
if (this.node === null) {
|
|
|
|
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;
|
|
|
|
if (taskData && taskData.main) {
|
|
|
|
return taskData.main.length - 1;
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
return 0;
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
maxRunIndex (): number {
|
|
|
|
if (this.node === null) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const runData: IRunData | null = this.workflowRunData;
|
|
|
|
|
|
|
|
if (runData === null || !runData.hasOwnProperty(this.node.name)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runData[this.node.name].length) {
|
|
|
|
return runData[this.node.name].length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
inputData (): INodeExecutionData[] {
|
2022-05-23 08:56:15 -07:00
|
|
|
let inputData = this.getNodeInputData(this.node, this.runIndex, this.currentOutputIndex);
|
2019-12-23 12:54:27 -08:00
|
|
|
if (inputData.length === 0 || !Array.isArray(inputData)) {
|
2019-06-23 03:35:23 -07:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
const offset = this.pageSize * (this.currentPage - 1);
|
|
|
|
inputData = inputData.slice(offset, offset + this.pageSize);
|
2020-05-23 15:53:06 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
return inputData;
|
|
|
|
},
|
|
|
|
jsonData (): IDataObject[] {
|
|
|
|
return this.convertToJson(this.inputData);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
tableData (): ITableData | undefined {
|
2022-04-11 06:12:13 -07:00
|
|
|
return this.convertToTable(this.inputData);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
binaryData (): IBinaryKeyData[] {
|
2022-05-23 08:56:15 -07:00
|
|
|
if (!this.node) {
|
2019-06-23 03:35:23 -07:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2022-06-20 12:39:24 -07:00
|
|
|
const binaryData = this.getBinaryData(this.workflowRunData, this.node.name, this.runIndex, this.currentOutputIndex);
|
|
|
|
return binaryData.filter((data) => Boolean(data && Object.keys(data).length));
|
2022-05-23 08:56:15 -07:00
|
|
|
},
|
|
|
|
currentOutputIndex(): number {
|
|
|
|
if (this.overrideOutputs && this.overrideOutputs.length && !this.overrideOutputs.includes(this.outputIndex)) {
|
|
|
|
return this.overrideOutputs[0] as number;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.outputIndex;
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-04-11 06:12:13 -07:00
|
|
|
branches (): ITab[] {
|
|
|
|
function capitalize(name: string) {
|
|
|
|
return name.charAt(0).toLocaleUpperCase() + name.slice(1);
|
|
|
|
}
|
|
|
|
const branches: ITab[] = [];
|
|
|
|
for (let i = 0; i <= this.maxOutputIndex; i++) {
|
2022-05-23 08:56:15 -07:00
|
|
|
if (this.overrideOutputs && !this.overrideOutputs.includes(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
const itemsCount = this.getDataCount(this.runIndex, i);
|
2022-05-23 08:56:15 -07:00
|
|
|
const items = this.$locale.baseText('ndv.output.items', {adjustToNumber: itemsCount});
|
2022-04-11 06:12:13 -07:00
|
|
|
let outputName = this.getOutputName(i);
|
|
|
|
if (`${outputName}` === `${i}`) {
|
|
|
|
outputName = `${this.$locale.baseText('ndv.output')} ${outputName}`;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
outputName = capitalize(`${this.getOutputName(i)} ${this.$locale.baseText('ndv.output.branch')}`);
|
|
|
|
}
|
|
|
|
branches.push({
|
|
|
|
label: itemsCount ? `${outputName} (${itemsCount} ${items})` : outputName,
|
|
|
|
value: i,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return branches;
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
methods: {
|
2022-05-23 08:56:15 -07:00
|
|
|
switchToBinary() {
|
|
|
|
this.onDisplayModeChange('binary');
|
|
|
|
},
|
|
|
|
onBranchChange(value: number) {
|
|
|
|
this.outputIndex = value;
|
|
|
|
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
showTooMuchData() {
|
|
|
|
this.showData = true;
|
|
|
|
this.$telemetry.track('User clicked ndv button', {
|
|
|
|
node_type: this.activeNode.type,
|
|
|
|
workflow_id: this.$store.getters.workflowId,
|
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
|
|
|
type: 'showTooMuchData',
|
|
|
|
});
|
|
|
|
},
|
|
|
|
linkRun() {
|
|
|
|
this.$emit('linkRun');
|
|
|
|
},
|
|
|
|
unlinkRun() {
|
|
|
|
this.$emit('unlinkRun');
|
|
|
|
},
|
|
|
|
onCurrentPageChange() {
|
|
|
|
this.$telemetry.track('User changed ndv page', {
|
|
|
|
node_type: this.activeNode.type,
|
|
|
|
workflow_id: this.$store.getters.workflowId,
|
|
|
|
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
|
|
|
onPageSizeChange(pageSize: number) {
|
|
|
|
this.pageSize = pageSize;
|
|
|
|
const maxPage = Math.ceil(this.dataCount / this.pageSize);
|
|
|
|
if (maxPage < this.currentPage) {
|
|
|
|
this.currentPage = maxPage;
|
|
|
|
}
|
2022-05-23 08:56:15 -07:00
|
|
|
|
|
|
|
this.$telemetry.track('User changed ndv page size', {
|
|
|
|
node_type: this.activeNode.type,
|
|
|
|
workflow_id: this.$store.getters.workflowId,
|
|
|
|
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
|
|
|
onDisplayModeChange(displayMode: IRunDataDisplayMode) {
|
2022-04-11 06:12:13 -07:00
|
|
|
const previous = this.displayMode;
|
2022-05-23 08:56:15 -07:00
|
|
|
this.$store.commit('ui/setPanelDisplayMode', {pane: this.paneType, mode: displayMode});
|
2022-04-11 06:12:13 -07:00
|
|
|
|
|
|
|
const dataContainer = this.$refs.dataContainer;
|
|
|
|
if (dataContainer) {
|
|
|
|
const dataDisplay = (dataContainer as Element).children[0];
|
|
|
|
|
|
|
|
if (dataDisplay){
|
|
|
|
dataDisplay.scrollTo(0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.closeBinaryDataDisplay();
|
|
|
|
this.$externalHooks().run('runData.displayModeChanged', { newValue: displayMode, oldValue: previous });
|
2022-05-23 08:56:15 -07:00
|
|
|
if(this.activeNode) {
|
|
|
|
this.$telemetry.track('User changed ndv item view', {
|
|
|
|
previous_view: previous,
|
|
|
|
new_view: displayMode,
|
|
|
|
node_type: this.activeNode.type,
|
|
|
|
workflow_id: this.$store.getters.workflowId,
|
|
|
|
session_id: this.sessionId,
|
|
|
|
pane: this.paneType,
|
|
|
|
});
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
getRunLabel(option: number) {
|
|
|
|
let itemsCount = 0;
|
|
|
|
for (let i = 0; i <= this.maxOutputIndex; i++) {
|
|
|
|
itemsCount += this.getDataCount(option - 1, i);
|
|
|
|
}
|
2022-05-23 08:56:15 -07:00
|
|
|
const items = this.$locale.baseText('ndv.output.items', {adjustToNumber: itemsCount});
|
2022-04-11 06:12:13 -07:00
|
|
|
const itemsLabel = itemsCount > 0 ? ` (${itemsCount} ${items})` : '';
|
|
|
|
return option + this.$locale.baseText('ndv.output.of') + (this.maxRunIndex+1) + itemsLabel;
|
|
|
|
},
|
|
|
|
getDataCount(runIndex: number, outputIndex: number) {
|
|
|
|
if (this.node === null) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const runData: IRunData | null = this.workflowRunData;
|
|
|
|
|
|
|
|
if (runData === null || !runData.hasOwnProperty(this.node.name)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runData[this.node.name].length <= runIndex) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runData[this.node.name][runIndex].hasOwnProperty('error')) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!runData[this.node.name][runIndex].hasOwnProperty('data') ||
|
|
|
|
runData[this.node.name][runIndex].data === undefined
|
|
|
|
) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const inputData = this.getMainInputData(runData[this.node.name][runIndex].data!, outputIndex);
|
|
|
|
|
|
|
|
return inputData.length;
|
|
|
|
},
|
2021-09-15 01:11:59 -07:00
|
|
|
init() {
|
|
|
|
// Reset the selected output index every time another node gets selected
|
|
|
|
this.outputIndex = 0;
|
|
|
|
this.refreshDataSize();
|
2022-05-23 08:56:15 -07:00
|
|
|
this.closeBinaryDataDisplay();
|
|
|
|
if (this.binaryData.length > 0) {
|
|
|
|
this.$store.commit('ui/setPanelDisplayMode', {pane: this.paneType, mode: 'binary'});
|
|
|
|
}
|
|
|
|
else if (this.displayMode === 'binary') {
|
|
|
|
this.$store.commit('ui/setPanelDisplayMode', {pane: this.paneType, mode: 'table'});
|
2021-09-15 01:11:59 -07:00
|
|
|
}
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
closeBinaryDataDisplay () {
|
|
|
|
this.binaryDataDisplayVisible = false;
|
|
|
|
this.binaryDataDisplayData = null;
|
|
|
|
},
|
|
|
|
convertToJson (inputData: INodeExecutionData[]): IDataObject[] {
|
|
|
|
const returnData: IDataObject[] = [];
|
|
|
|
inputData.forEach((data) => {
|
|
|
|
if (!data.hasOwnProperty('json')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
returnData.push(data.json);
|
|
|
|
});
|
|
|
|
|
|
|
|
return returnData;
|
|
|
|
},
|
|
|
|
convertToTable (inputData: INodeExecutionData[]): ITableData | undefined {
|
|
|
|
const tableData: GenericValue[][] = [];
|
|
|
|
const tableColumns: string[] = [];
|
|
|
|
let leftEntryColumns: string[], entryRows: GenericValue[];
|
|
|
|
// Go over all entries
|
|
|
|
let entry: IDataObject;
|
|
|
|
inputData.forEach((data) => {
|
|
|
|
if (!data.hasOwnProperty('json')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
entry = data.json;
|
|
|
|
|
|
|
|
// Go over all keys of entry
|
|
|
|
entryRows = [];
|
|
|
|
leftEntryColumns = Object.keys(entry);
|
|
|
|
|
|
|
|
// Go over all the already existing column-keys
|
|
|
|
tableColumns.forEach((key) => {
|
|
|
|
if (entry.hasOwnProperty(key)) {
|
|
|
|
// Entry does have key so add its value
|
|
|
|
entryRows.push(entry[key]);
|
|
|
|
// Remove key so that we know that it got added
|
|
|
|
leftEntryColumns.splice(leftEntryColumns.indexOf(key), 1);
|
|
|
|
} else {
|
|
|
|
// Entry does not have key so add null
|
|
|
|
entryRows.push(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Go over all the columns the entry has but did not exist yet
|
|
|
|
leftEntryColumns.forEach((key) => {
|
|
|
|
// Add the key for all runs in the future
|
|
|
|
tableColumns.push(key);
|
|
|
|
// Add the value
|
|
|
|
entryRows.push(entry[key]);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add the data of the entry
|
|
|
|
tableData.push(entryRows);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Make sure that all entry-rows have the same length
|
|
|
|
tableData.forEach((entryRows) => {
|
|
|
|
if (tableColumns.length > entryRows.length) {
|
|
|
|
// Has to less entries so add the missing ones
|
|
|
|
entryRows.push.apply(entryRows, new Array(tableColumns.length - entryRows.length));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
|
|
|
columns: tableColumns,
|
|
|
|
data: tableData,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
clearExecutionData () {
|
|
|
|
this.$store.commit('setWorkflowExecutionData', null);
|
|
|
|
this.updateNodesExecutionIssues();
|
|
|
|
},
|
2020-12-18 09:55:53 -08:00
|
|
|
dataItemClicked (path: string, data: object | number | string) {
|
|
|
|
this.state.value = data;
|
|
|
|
},
|
2022-03-28 03:59:53 -07:00
|
|
|
isDownloadable (index: number, key: string): boolean {
|
|
|
|
const binaryDataItem: IBinaryData = this.binaryData[index][key];
|
|
|
|
return !!(binaryDataItem.mimeType && binaryDataItem.fileName);
|
|
|
|
},
|
|
|
|
async downloadBinaryData (index: number, key: string) {
|
|
|
|
const binaryDataItem: IBinaryData = this.binaryData[index][key];
|
|
|
|
|
|
|
|
let bufferString = 'data:' + binaryDataItem.mimeType + ';base64,';
|
|
|
|
if(binaryDataItem.id) {
|
|
|
|
bufferString += await this.restApi().getBinaryBufferString(binaryDataItem.id);
|
|
|
|
} else {
|
|
|
|
bufferString += binaryDataItem.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = await fetch(bufferString);
|
|
|
|
const blob = await data.blob();
|
|
|
|
saveAs(blob, binaryDataItem.fileName);
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
displayBinaryData (index: number, key: string) {
|
|
|
|
this.binaryDataDisplayVisible = true;
|
|
|
|
|
|
|
|
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;
|
2021-11-19 01:17:13 -08:00
|
|
|
if (!nodeType || !nodeType.outputNames || nodeType.outputNames.length <= outputIndex) {
|
2020-12-18 09:55:53 -08:00
|
|
|
return outputIndex + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodeType.outputNames[outputIndex];
|
|
|
|
},
|
|
|
|
convertPath (path: string): string {
|
|
|
|
// TODO: That can for sure be done fancier but for now it works
|
|
|
|
const placeholder = '*___~#^#~___*';
|
|
|
|
let inBrackets = path.match(/\[(.*?)\]/g);
|
|
|
|
|
|
|
|
if (inBrackets === null) {
|
|
|
|
inBrackets = [];
|
|
|
|
} else {
|
|
|
|
inBrackets = inBrackets.map(item => item.slice(1, -1)).map(item => {
|
|
|
|
if (item.startsWith('"') && item.endsWith('"')) {
|
|
|
|
return item.slice(1, -1);
|
|
|
|
}
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
const withoutBrackets = path.replace(/\[(.*?)\]/g, placeholder);
|
|
|
|
const pathParts = withoutBrackets.split('.');
|
|
|
|
const allParts = [] as string[];
|
|
|
|
pathParts.forEach(part => {
|
|
|
|
let index = part.indexOf(placeholder);
|
|
|
|
while(index !== -1) {
|
|
|
|
if (index === 0) {
|
|
|
|
allParts.push(inBrackets!.shift() as string);
|
|
|
|
part = part.substr(placeholder.length);
|
|
|
|
} else {
|
|
|
|
allParts.push(part.substr(0, index));
|
|
|
|
part = part.substr(index);
|
|
|
|
}
|
|
|
|
index = part.indexOf(placeholder);
|
|
|
|
}
|
|
|
|
if (part !== '') {
|
|
|
|
allParts.push(part);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return '["' + allParts.join('"]["') + '"]';
|
|
|
|
},
|
|
|
|
handleCopyClick (commandData: { command: string }) {
|
|
|
|
const newPath = this.convertPath(this.state.path);
|
|
|
|
|
|
|
|
let value: string;
|
|
|
|
if (commandData.command === 'value') {
|
|
|
|
if (typeof this.state.value === 'object') {
|
|
|
|
value = JSON.stringify(this.state.value, null, 2);
|
|
|
|
} else {
|
|
|
|
value = this.state.value.toString();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let startPath = '';
|
|
|
|
let path = '';
|
|
|
|
if (commandData.command === 'itemPath') {
|
|
|
|
const pathParts = newPath.split(']');
|
|
|
|
const index = pathParts[0].slice(1);
|
|
|
|
path = pathParts.slice(1).join(']');
|
|
|
|
startPath = `$item(${index}).$node["${this.node!.name}"].json`;
|
|
|
|
} else if (commandData.command === 'parameterPath') {
|
|
|
|
path = newPath.split(']').slice(1).join(']');
|
|
|
|
startPath = `$node["${this.node!.name}"].json`;
|
|
|
|
}
|
|
|
|
if (!path.startsWith('[') && !path.startsWith('.') && path) {
|
|
|
|
path += '.';
|
|
|
|
}
|
|
|
|
value = `{{ ${startPath + path} }}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.copyToClipboard(value);
|
|
|
|
},
|
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;
|
|
|
|
|
|
|
|
// Check how much data there is to display
|
2022-05-23 08:56:15 -07:00
|
|
|
const inputData = this.getNodeInputData(this.node, this.runIndex, this.currentOutputIndex);
|
2020-05-23 14:54:56 -07:00
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
const offset = this.pageSize * (this.currentPage - 1);
|
|
|
|
const jsonItems = inputData.slice(offset, offset + this.pageSize).map(item => item.json);
|
2020-05-23 14:54:56 -07:00
|
|
|
|
|
|
|
this.dataSize = JSON.stringify(jsonItems).length;
|
2019-10-04 04:27:50 -07:00
|
|
|
|
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);
|
|
|
|
},
|
2019-10-04 04:27:50 -07:00
|
|
|
},
|
|
|
|
watch: {
|
2021-09-15 01:11:59 -07:00
|
|
|
node() {
|
|
|
|
this.init();
|
2019-10-04 04:27:50 -07:00
|
|
|
},
|
|
|
|
jsonData () {
|
|
|
|
this.refreshDataSize();
|
|
|
|
},
|
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
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
</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%;
|
2022-05-23 08:56:15 -07:00
|
|
|
background-color: var(--color-background-base);
|
2022-04-11 06:12:13 -07:00
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
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-06-20 12:39:24 -07:00
|
|
|
height: 30px;
|
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
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
.dataContainer {
|
|
|
|
position: relative;
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.dataDisplay {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
padding-left: var(--spacing-s);
|
|
|
|
right: 0;
|
|
|
|
overflow-y: auto;
|
|
|
|
line-height: 1.5;
|
|
|
|
word-break: normal;
|
|
|
|
height: 100%;
|
|
|
|
padding-bottom: var(--spacing-3xl);
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
.errorDisplay {
|
|
|
|
composes: dataDisplay;
|
|
|
|
padding-right: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
.jsonDisplay {
|
|
|
|
composes: dataDisplay;
|
|
|
|
background-color: var(--color-background-base);
|
|
|
|
padding-top: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.tabs {
|
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.table {
|
|
|
|
border-collapse: separate;
|
|
|
|
text-align: left;
|
|
|
|
width: calc(100% - var(--spacing-s));
|
|
|
|
margin-right: var(--spacing-s);
|
|
|
|
font-size: var(--font-size-s);
|
|
|
|
|
|
|
|
th {
|
|
|
|
padding: var(--spacing-2xs);
|
|
|
|
background-color: var(--color-background-base);
|
|
|
|
border-top: var(--border-base);
|
|
|
|
border-bottom: var(--border-base);
|
|
|
|
border-left: var(--border-base);
|
|
|
|
position: sticky;
|
|
|
|
top: 0;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
td {
|
|
|
|
padding: var(--spacing-2xs);
|
|
|
|
border-bottom: var(--border-base);
|
|
|
|
border-left: var(--border-base);
|
|
|
|
overflow-wrap: break-word;
|
|
|
|
max-width: 300px;
|
|
|
|
white-space: pre-wrap;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
|
2022-04-11 06:12:13 -07:00
|
|
|
th:last-child, td:last-child {
|
|
|
|
border-right: var(--border-base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.emptyCell {
|
|
|
|
height: 32px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.itemsCount {
|
|
|
|
margin-left: var(--spacing-s);
|
|
|
|
margin-bottom: var(--spacing-s);
|
|
|
|
}
|
|
|
|
|
|
|
|
.runSelector {
|
|
|
|
max-width: 200px;
|
|
|
|
margin-left: var(--spacing-s);
|
|
|
|
margin-bottom: var(--spacing-s);
|
2022-05-23 08:56:15 -07:00
|
|
|
display: flex;
|
|
|
|
|
|
|
|
> * {
|
|
|
|
margin-right: var(--spacing-4xs);
|
|
|
|
}
|
2022-04-11 06:12:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.copyButton {
|
|
|
|
height: 30px;
|
|
|
|
top: 12px;
|
|
|
|
right: 24px;
|
|
|
|
position: absolute;
|
|
|
|
z-index: 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pagination {
|
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
bottom: 0;
|
|
|
|
padding: 5px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.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;
|
|
|
|
background-color: #fff;
|
|
|
|
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 {
|
|
|
|
color: $--color-primary;
|
|
|
|
font-weight: 600;
|
|
|
|
font-size: 1.2em;
|
|
|
|
padding-bottom: 0.5em;
|
|
|
|
margin-bottom: 0.5em;
|
|
|
|
border-bottom: 1px solid #ccc;
|
|
|
|
}
|
|
|
|
|
|
|
|
.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;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pageSizeSelector {
|
|
|
|
text-transform: capitalize;
|
|
|
|
max-width: 150px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.displayModes {
|
2022-05-23 08:56:15 -07:00
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
flex-grow: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.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
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
.vjs-tree {
|
|
|
|
color: var(--color-json-default);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree.is-highlight-selected {
|
|
|
|
background-color: var(--color-json-highlight);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-value__null {
|
|
|
|
color: var(--color-json-null);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-value__boolean {
|
|
|
|
color: var(--color-json-boolean);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-value__number {
|
|
|
|
color: var(--color-json-number);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-value__string {
|
|
|
|
color: var(--color-json-string);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-key {
|
|
|
|
color: var(--color-json-key);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-tree__brackets {
|
|
|
|
color: var(--color-json-brackets);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-tree__brackets:hover {
|
|
|
|
color: var(--color-json-brackets-hover);
|
|
|
|
}
|
|
|
|
|
|
|
|
.vjs-tree .vjs-tree__content.has-line {
|
|
|
|
border-left: 1px dotted var(--color-json-line);
|
|
|
|
}
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
</style>
|