mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
refactor header
This commit is contained in:
parent
865b795733
commit
56f02b3362
|
@ -0,0 +1,57 @@
|
||||||
|
<template>
|
||||||
|
<label role="radio" tabindex="-1" :class="$style.container" aria-checked="true">
|
||||||
|
<input type="radio" tabindex="-1" autocomplete="off" :class="$style.input" :value="value">
|
||||||
|
<div :class="{[$style.button]: true, [$style.active]: active}" @click="$emit('click')">{{ label }}</div>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'n8n-radio-button',
|
||||||
|
props: {
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.container {
|
||||||
|
display: inline-block;
|
||||||
|
outline: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
opacity: 0;
|
||||||
|
outline: 0;
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
border-radius: 0;
|
||||||
|
padding: var(--spacing-2xs) 15px;
|
||||||
|
font-size: var(--font-size-2xs);
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
color: var(--color-text-base);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background-color: var(--color-foreground-xlight);
|
||||||
|
color: var(--color-text-dark);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,51 @@
|
||||||
|
import N8nRadioButtons from './RadioButtons.vue';
|
||||||
|
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Atoms/RadioButtons',
|
||||||
|
component: N8nRadioButtons,
|
||||||
|
argTypes: {
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
backgrounds: { default: '--color-background-xlight' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const methods = {
|
||||||
|
onInput: action('input'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const Template = (args, { argTypes }) => ({
|
||||||
|
props: Object.keys(argTypes),
|
||||||
|
components: {
|
||||||
|
N8nRadioButtons,
|
||||||
|
},
|
||||||
|
template:
|
||||||
|
`<n8n-radio-buttons v-model="val" v-bind="$props" @input="onInput">
|
||||||
|
</n8n-radio-buttons>`,
|
||||||
|
methods,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
val: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Example = Template.bind({});
|
||||||
|
Example.args = {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Test',
|
||||||
|
value: 'test',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'World',
|
||||||
|
value: 'world',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Hello',
|
||||||
|
value: 'hello',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
<template>
|
||||||
|
<div role="radiogroup" :class="$style.radioGroup">
|
||||||
|
<RadioButton
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option.value"
|
||||||
|
v-bind="option"
|
||||||
|
:active="value === option.value"
|
||||||
|
@click="(e) => onClick(option.value, e)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import RadioButton from './RadioButton';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'n8n-radio-buttons',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
RadioButton,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick(value) {
|
||||||
|
this.$emit('input', value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
|
||||||
|
.radioGroup {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 0;
|
||||||
|
background-color: var(--color-foreground-base);
|
||||||
|
padding: var(--spacing-5xs);
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import N8nRadioButtons from './RadioButtons.vue';
|
||||||
|
|
||||||
|
export default N8nRadioButtons;
|
|
@ -53,6 +53,7 @@ import N8nMenu from './N8nMenu';
|
||||||
import N8nMenuItem from './N8nMenuItem';
|
import N8nMenuItem from './N8nMenuItem';
|
||||||
import N8nLink from './N8nLink';
|
import N8nLink from './N8nLink';
|
||||||
import N8nOption from './N8nOption';
|
import N8nOption from './N8nOption';
|
||||||
|
import N8nRadioButtons from './N8nRadioButtons';
|
||||||
import N8nSelect from './N8nSelect';
|
import N8nSelect from './N8nSelect';
|
||||||
import N8nSpinner from './N8nSpinner';
|
import N8nSpinner from './N8nSpinner';
|
||||||
import N8nSquareButton from './N8nSquareButton';
|
import N8nSquareButton from './N8nSquareButton';
|
||||||
|
@ -87,6 +88,7 @@ export {
|
||||||
N8nMenu,
|
N8nMenu,
|
||||||
N8nMenuItem,
|
N8nMenuItem,
|
||||||
N8nOption,
|
N8nOption,
|
||||||
|
N8nRadioButtons,
|
||||||
N8nSelect,
|
N8nSelect,
|
||||||
N8nSpinner,
|
N8nSpinner,
|
||||||
N8nSquareButton,
|
N8nSquareButton,
|
||||||
|
|
|
@ -285,8 +285,8 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
--color-background-light-h: 220;
|
--color-background-light-h: 220;
|
||||||
--color-background-light-s: 27.3%;
|
--color-background-light-s: 60%;
|
||||||
--color-background-light-l: 97.8%;
|
--color-background-light-l: 99%;
|
||||||
--color-background-light: hsl(
|
--color-background-light: hsl(
|
||||||
var(--color-background-light-h),
|
var(--color-background-light-h),
|
||||||
var(--color-background-light-s),
|
var(--color-background-light-s),
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="run-data-view" v-loading="workflowRunning">
|
<div :class="['run-data-view', $style.container]" v-loading="workflowRunning">
|
||||||
<BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @close="closeBinaryDataDisplay"/>
|
<BinaryDataDisplay :windowVisible="binaryDataDisplayVisible" :displayData="binaryDataDisplayData" @close="closeBinaryDataDisplay"/>
|
||||||
|
|
||||||
<div class="header">
|
<div :class="$style.header">
|
||||||
|
<div>
|
||||||
|
<span :class="$style.title">{{ $locale.baseText('runData.output') }}</span>
|
||||||
|
<n8n-tooltip
|
||||||
|
v-if="runMetadata"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<div slot="content">
|
||||||
|
<n8n-text :bold="true" size="small">{{ $locale.baseText('runData.startTime') + ':' }}</n8n-text> {{runMetadata.startTime}}<br/>
|
||||||
|
<n8n-text :bold="true" size="small">{{ $locale.baseText('runData.executionTime') + ':' }}</n8n-text> {{runMetadata.executionTime}} {{ $locale.baseText('runData.ms') }}
|
||||||
|
</div>
|
||||||
|
<font-awesome-icon icon="info-circle" :class="$style.infoIcon" />
|
||||||
|
</n8n-tooltip>
|
||||||
|
</div>
|
||||||
<div class="title-text">
|
<div class="title-text">
|
||||||
<n8n-text :bold="true" v-if="dataCount < maxDisplayItems">
|
<!-- <n8n-text :bold="true" v-if="dataCount < maxDisplayItems">
|
||||||
{{ $locale.baseText('runData.items') }}: {{ dataCount }}
|
{{ $locale.baseText('runData.items') }}: {{ dataCount }}
|
||||||
</n8n-text>
|
</n8n-text>
|
||||||
<div v-else class="title-text">
|
<div v-else class="title-text">
|
||||||
|
@ -15,20 +28,11 @@
|
||||||
</n8n-select>
|
</n8n-select>
|
||||||
</span>/
|
</span>/
|
||||||
<n8n-text :bold="true">{{ dataCount }}</n8n-text>
|
<n8n-text :bold="true">{{ dataCount }}</n8n-text>
|
||||||
</div>
|
</div> -->
|
||||||
<n8n-tooltip
|
|
||||||
v-if="runMetadata"
|
<!-- <n8n-text :bold="true" v-if="maxOutputIndex > 0">
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<div slot="content">
|
|
||||||
<n8n-text :bold="true" size="small">{{ $locale.baseText('runData.startTime') + ':' }}</n8n-text> {{runMetadata.startTime}}<br/>
|
|
||||||
<n8n-text :bold="true" size="small">{{ $locale.baseText('runData.executionTime') + ':' }}</n8n-text> {{runMetadata.executionTime}} {{ $locale.baseText('runData.ms') }}
|
|
||||||
</div>
|
|
||||||
<font-awesome-icon icon="info-circle" class="primary-color" />
|
|
||||||
</n8n-tooltip>
|
|
||||||
<n8n-text :bold="true" v-if="maxOutputIndex > 0">
|
|
||||||
| {{ $locale.baseText('runData.output') }}:
|
| {{ $locale.baseText('runData.output') }}:
|
||||||
</n8n-text>
|
</n8n-text> -->
|
||||||
<span class="opts" v-if="maxOutputIndex > 0" >
|
<span class="opts" v-if="maxOutputIndex > 0" >
|
||||||
<n8n-select size="mini" v-model="outputIndex" @click.stop>
|
<n8n-select size="mini" v-model="outputIndex" @click.stop>
|
||||||
<n8n-option v-for="option in (maxOutputIndex + 1)" :label="getOutputName(option-1)" :value="option -1" :key="option">
|
<n8n-option v-for="option in (maxOutputIndex + 1)" :label="getOutputName(option-1)" :value="option -1" :key="option">
|
||||||
|
@ -48,13 +52,12 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hasNodeRun && !hasRunError" class="title-data-display-selector" @click.stop>
|
<div v-if="hasNodeRun && !hasRunError" class="title-data-display-selector" @click.stop>
|
||||||
<el-radio-group v-model="displayMode" size="mini">
|
<n8n-radio-buttons
|
||||||
<el-radio-button :label="$locale.baseText('runData.json')" :disabled="showData === false"></el-radio-button>
|
v-model="displayMode"
|
||||||
<el-radio-button :label="$locale.baseText('runData.table')"></el-radio-button>
|
:options="buttons"
|
||||||
<el-radio-button :label="$locale.baseText('runData.binary')" v-if="binaryData.length !== 0"></el-radio-button>
|
/>
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hasNodeRun && !hasRunError && displayMode === $locale.baseText('runData.json') && state.path !== deselectedPlaceholder" class="select-button">
|
<div v-if="hasNodeRun && !hasRunError && displayMode === 'json' && state.path !== deselectedPlaceholder" class="select-button">
|
||||||
<el-dropdown trigger="click" @command="handleCopyClick">
|
<el-dropdown trigger="click" @command="handleCopyClick">
|
||||||
<span class="el-dropdown-link">
|
<span class="el-dropdown-link">
|
||||||
<n8n-icon-button :title="$locale.baseText('runData.copyToClipboard')" icon="copy" />
|
<n8n-icon-button :title="$locale.baseText('runData.copyToClipboard')" icon="copy" />
|
||||||
|
@ -98,14 +101,14 @@
|
||||||
<n8n-button
|
<n8n-button
|
||||||
icon="eye"
|
icon="eye"
|
||||||
:label="$locale.baseText('runData.displayDataAnyway')"
|
:label="$locale.baseText('runData.displayDataAnyway')"
|
||||||
@click="displayMode = $locale.baseText('runData.table');showData = true;"
|
@click="displayMode = 'table';showData = true;"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="[$locale.baseText('runData.json'), $locale.baseText('runData.table')].includes(displayMode)">
|
<div v-else-if="['json', 'table'].includes(displayMode)">
|
||||||
<div v-if="jsonData.length === 0" class="no-data">
|
<div v-if="jsonData.length === 0" class="no-data">
|
||||||
{{ $locale.baseText('runData.noTextDataFound') }}
|
{{ $locale.baseText('runData.noTextDataFound') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="displayMode === $locale.baseText('runData.table')">
|
<div v-else-if="displayMode === 'table'">
|
||||||
<div v-if="tableData !== null && tableData.columns.length === 0" class="no-data">
|
<div v-if="tableData !== null && tableData.columns.length === 0" class="no-data">
|
||||||
{{ $locale.baseText('runData.entriesExistButThey') }}
|
{{ $locale.baseText('runData.entriesExistButThey') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -119,7 +122,7 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<vue-json-pretty
|
<vue-json-pretty
|
||||||
v-else-if="displayMode === $locale.baseText('runData.json')"
|
v-else-if="displayMode === 'json'"
|
||||||
:data="jsonData"
|
:data="jsonData"
|
||||||
:deep="10"
|
:deep="10"
|
||||||
v-model="state.path"
|
v-model="state.path"
|
||||||
|
@ -133,7 +136,7 @@
|
||||||
class="json-data"
|
class="json-data"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="displayMode === $locale.baseText('runData.binary')">
|
<div v-else-if="displayMode === 'binary'">
|
||||||
<div v-if="binaryData.length === 0" class="no-data">
|
<div v-if="binaryData.length === 0" class="no-data">
|
||||||
{{ $locale.baseText('runData.noBinaryDataFound') }}
|
{{ $locale.baseText('runData.noBinaryDataFound') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -249,7 +252,7 @@ export default mixins(
|
||||||
binaryDataPreviewActive: false,
|
binaryDataPreviewActive: false,
|
||||||
dataSize: 0,
|
dataSize: 0,
|
||||||
deselectedPlaceholder,
|
deselectedPlaceholder,
|
||||||
displayMode: this.$locale.baseText('runData.table'),
|
displayMode: 'table',
|
||||||
state: {
|
state: {
|
||||||
value: '' as object | number | string,
|
value: '' as object | number | string,
|
||||||
path: deselectedPlaceholder,
|
path: deselectedPlaceholder,
|
||||||
|
@ -269,6 +272,19 @@ export default mixins(
|
||||||
this.init();
|
this.init();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
buttons(): {label: string, value: string}[] {
|
||||||
|
const defaults = [
|
||||||
|
{ label: this.$locale.baseText('runData.json'), value: 'json'},
|
||||||
|
{ label: this.$locale.baseText('runData.table'), value: 'table'},
|
||||||
|
];
|
||||||
|
if (this.binaryData.length) {
|
||||||
|
return [ ...defaults,
|
||||||
|
{ label: this.$locale.baseText('runData.binary'), value: 'binary'},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaults;
|
||||||
|
},
|
||||||
hasNodeRun(): boolean {
|
hasNodeRun(): boolean {
|
||||||
return Boolean(this.node && this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name));
|
return Boolean(this.node && this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name));
|
||||||
},
|
},
|
||||||
|
@ -426,10 +442,10 @@ export default mixins(
|
||||||
this.outputIndex = 0;
|
this.outputIndex = 0;
|
||||||
this.maxDisplayItems = 25;
|
this.maxDisplayItems = 25;
|
||||||
this.refreshDataSize();
|
this.refreshDataSize();
|
||||||
if (this.displayMode === this.$locale.baseText('runData.binary')) {
|
if (this.displayMode === 'binary') {
|
||||||
this.closeBinaryDataDisplay();
|
this.closeBinaryDataDisplay();
|
||||||
if (this.binaryData.length === 0) {
|
if (this.binaryData.length === 0) {
|
||||||
this.displayMode = this.$locale.baseText('runData.table');
|
this.displayMode = 'table';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -638,13 +654,40 @@ export default mixins(
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" module>
|
||||||
|
.infoIcon {
|
||||||
|
color: var(--color-foreground-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.run-data-view {
|
.title {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--color-text-light);
|
||||||
|
letter-spacing: 3px;
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
margin-right: var(--spacing-2xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #f9f9f9;
|
background-color: var(--color-background-light);
|
||||||
|
padding: var(--spacing-s) var(--spacing-s) 0 var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> *:first-child {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
|
||||||
|
.run-data-view {
|
||||||
|
|
||||||
.data-display-content {
|
.data-display-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -767,50 +810,47 @@ export default mixins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
// .header {
|
||||||
padding-top: 10px;
|
// display: flex;
|
||||||
padding-left: 10px;
|
// align-items: center;
|
||||||
|
// height: 40px;
|
||||||
|
|
||||||
display: flex;
|
// .select-button {
|
||||||
align-items: center;
|
// height: 30px;
|
||||||
height: 40px;
|
// top: 50px;
|
||||||
|
// right: 30px;
|
||||||
|
// position: absolute;
|
||||||
|
// text-align: right;
|
||||||
|
// width: 200px;
|
||||||
|
// z-index: 10;
|
||||||
|
// }
|
||||||
|
|
||||||
.select-button {
|
// .title-text {
|
||||||
height: 30px;
|
// display: inline-flex;
|
||||||
top: 50px;
|
// align-items: center;
|
||||||
right: 30px;
|
|
||||||
position: absolute;
|
|
||||||
text-align: right;
|
|
||||||
width: 200px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-text {
|
// > * {
|
||||||
display: inline-flex;
|
// margin-right: 2px;
|
||||||
align-items: center;
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
> * {
|
// .title-data-display-selector {
|
||||||
margin-right: 2px;
|
// position: absolute;
|
||||||
}
|
// left: calc(50% - 105px);
|
||||||
}
|
// width: 210px;
|
||||||
|
// display: inline-block;
|
||||||
|
// text-align: center;
|
||||||
|
|
||||||
.title-data-display-selector {
|
// .entry.active {
|
||||||
position: absolute;
|
// font-weight: bold;
|
||||||
left: calc(50% - 105px);
|
// }
|
||||||
width: 210px;
|
// }
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.entry.active {
|
// .opts {
|
||||||
font-weight: bold;
|
// width: 80px;
|
||||||
}
|
// z-index: 1;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
.opts {
|
|
||||||
width: 80px;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -61,6 +61,7 @@ import {
|
||||||
N8nMenu,
|
N8nMenu,
|
||||||
N8nMenuItem,
|
N8nMenuItem,
|
||||||
N8nOption,
|
N8nOption,
|
||||||
|
N8nRadioButtons,
|
||||||
N8nSelect,
|
N8nSelect,
|
||||||
N8nSpinner,
|
N8nSpinner,
|
||||||
N8nFormInputs,
|
N8nFormInputs,
|
||||||
|
@ -97,6 +98,7 @@ Vue.use(N8nMenuItem);
|
||||||
Vue.use(N8nOption);
|
Vue.use(N8nOption);
|
||||||
Vue.use(N8nSelect);
|
Vue.use(N8nSelect);
|
||||||
Vue.use(N8nSpinner);
|
Vue.use(N8nSpinner);
|
||||||
|
Vue.use(N8nRadioButtons);
|
||||||
Vue.component('n8n-square-button', N8nSquareButton);
|
Vue.component('n8n-square-button', N8nSquareButton);
|
||||||
Vue.use(N8nTags);
|
Vue.use(N8nTags);
|
||||||
Vue.use(N8nTag);
|
Vue.use(N8nTag);
|
||||||
|
|
Loading…
Reference in a new issue