refactor tabs

This commit is contained in:
Mutasem 2022-03-29 17:32:23 +02:00
parent 0bb3c6498d
commit 4344cc67a8
7 changed files with 194 additions and 89 deletions

View file

@ -0,0 +1,54 @@
import N8nTabs from './Tabs.vue';
import { action } from '@storybook/addon-actions';
export default {
title: 'Atoms/Tabs',
component: N8nTabs,
argTypes: {
},
parameters: {
backgrounds: { default: '--color-background-xlight' },
},
};
const methods = {
onInput: action('input'),
};
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: {
N8nTabs,
},
template:
`<n8n-tabs v-model="val" v-bind="$props" @input="onInput">
</n8n-tabs>`,
methods,
data() {
return {
val: '',
};
},
});
export const Example = Template.bind({});
Example.args = {
options: [
{
label: 'Test',
value: 'test',
},
{
label: 'Github',
value: 'github',
href: 'https://github.com/',
},
{
label: 'Settings',
value: 'settings',
icon: 'cog',
align: 'right',
},
],
};

View file

@ -0,0 +1,99 @@
<template>
<div :class="$style.tabs">
<div v-for="option in options" :key="option.value" :class="{ [$style.alignRight]: option.align === 'right' }">
<a
v-if="option.href"
target="_blank"
:href="option.href"
:class="[$style.link, $style.tab]"
@click="handleTabClick"
>
<div>
{{ option.label }}
<span :class="$style.external"><n8n-icon icon="external-link-alt" size="small" /></span>
</div>
</a>
<div
v-else
:class="{ [$style.tab]: true, [$style.activeTab]: value === option.value }"
@click="() => handleTabClick(option.value)"
>
<n8n-icon v-if="option.icon" :icon="option.icon" size="small" />
<span v-if="option.label">{{ option.label }}</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import N8nIcon from '../N8nIcon';
export default Vue.extend({
name: 'N8nTabs',
components: {
N8nIcon,
},
props: {
value: {
type: String,
},
options: {
},
},
methods: {
handleTabClick(tab: string) {
this.$emit('input', tab);
},
},
});
</script>
<style lang="scss" module>
.tabs {
color: var(--color-text-base);
font-weight: var(--font-weight-bold);
display: flex;
width: 100%;
}
.tab {
display: block;
padding: 0 var(--spacing-s) var(--spacing-2xs) var(--spacing-s);
padding-bottom: var(--spacing-2xs);
font-size: var(--font-size-s);
cursor: pointer;
&:hover {
color: var(--color-primary);
}
}
.activeTab {
color: var(--color-primary);
border-bottom: var(--color-primary) 2px solid;
}
.alignRight {
margin-left: auto;
}
.link {
cursor: pointer;
color: var(--color-text-base);
&:hover {
color: var(--color-primary);
.external {
display: inline-block;
}
}
}
.external {
display: none;
}
</style>

View file

@ -0,0 +1,3 @@
import N8nTabs from './Tabs.vue';
export default N8nTabs;

View file

@ -58,6 +58,7 @@ import N8nSelect from './N8nSelect';
import N8nSpinner from './N8nSpinner';
import N8nSquareButton from './N8nSquareButton';
import N8nTags from './N8nTags';
import N8nTabs from './N8nTabs';
import N8nTag from './N8nTag';
import N8nText from './N8nText';
import N8nTooltip from './N8nTooltip';
@ -92,6 +93,7 @@ export {
N8nSelect,
N8nSpinner,
N8nSquareButton,
N8nTabs,
N8nTags,
N8nTag,
N8nText,

View file

@ -1,32 +1,23 @@
<template>
<div :class="$style.tabs">
<div
:class="{ [$style.activeTab]: value === 'params' }"
@click="() => handleTabClick('params')"
>
{{ $locale.baseText('nodeSettings.parameters') }}
</div>
<a
v-if="documentationUrl"
target="_blank"
:href="documentationUrl"
:class="$style.docsTab"
@click="onDocumentationUrlClick"
>
<div>
{{ $locale.baseText('nodeSettings.docs') }}
<font-awesome-icon :class="$style.external" icon="external-link-alt" size="sm" />
</div>
</a>
<div
:class="{ [$style.settingsTab]: true, [$style.activeTab]: value === 'settings' }"
@click="() => handleTabClick('settings')"
>
<font-awesome-icon icon="cog" />
</div>
</div>
<n8n-tabs
:options="[
{
label: $locale.baseText('nodeSettings.parameters'),
value: 'params'
},
{
label: $locale.baseText('nodeSettings.docs'),
value: 'docs',
href: documentationUrl,
},
{
icon: 'cog',
value: 'settings',
align: 'right',
}]"
:value="value"
@input="onTabSelect"
/>
</template>
<script lang="ts">
@ -65,64 +56,19 @@ export default mixins(
},
},
methods: {
onDocumentationUrlClick () {
if (this.nodeType) {
onTabSelect(tab: string) {
if (tab === 'docs' && this.nodeType) {
this.$externalHooks().run('dataDisplay.onDocumentationUrlClick', { nodeType: this.nodeType as INodeTypeDescription, documentationUrl: this.documentationUrl });
}
},
handleTabClick(tab: string) {
this.$emit('input', tab);
if(tab === 'settings' && this.nodeType) {
this.$telemetry.track('User viewed node settings', { node_type: (this.nodeType as INodeTypeDescription).name, workflow_id: this.$store.getters.workflowId });
}
if (tab === 'settings' || tab === 'params') {
this.$emit('input', tab);
}
},
},
});
</script>
<style lang="scss" module>
.tabs {
color: var(--color-text-base);
font-weight: var(--font-weight-bold);
display: flex;
width: 100%;
> * {
padding: 0 var(--spacing-s) var(--spacing-2xs) var(--spacing-s);
padding-bottom: var(--spacing-2xs);
font-size: var(--font-size-s);
cursor: pointer;
&:hover {
color: var(--color-primary);
}
}
}
.activeTab {
color: var(--color-primary);
border-bottom: var(--color-primary) 2px solid;
}
.settingsTab {
margin-left: auto;
}
.docsTab {
cursor: pointer;
color: var(--color-text-base);
&:hover {
color: var(--color-primary);
.external {
display: inline-block;
}
}
}
.external {
display: none;
}
</style>

View file

@ -30,22 +30,18 @@
<!-- <n8n-text :bold="true" v-if="maxOutputIndex > 0">
| {{ $locale.baseText('runData.output') }}:
</n8n-text> -->
<!-- <span class="opts" v-if="maxOutputIndex > 0" >
<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>
</n8n-select>
</span> -->
<!-- <n8n-text :bold="true" v-if="maxRunIndex > 0">
| {{ $locale.baseText('runData.dataOfExecution') }}:
</n8n-text> -->
<span class="opts">
<!-- <span class="opts">
<n8n-select v-if="maxRunIndex > 0" size="mini" v-model="runIndex" @click.stop>
<n8n-option v-for="option in (maxRunIndex + 1)" :label="option + '/' + (maxRunIndex+1)" :value="option-1" :key="option">
</n8n-option>
</n8n-select>
</span>
</span> -->
</div>
<div v-if="!hasRunError" @click.stop>
@ -76,7 +72,10 @@
</div>
<div>
<n8n-text v-if="hasNodeRun && dataCount > 0">
<el-tabs v-model="outputIndex" v-if="maxOutputIndex > 0">
<el-tab-pane v-for="option in (maxOutputIndex + 1)" :label="getOutputName(option-1)" :value="option -1" :key="option"></el-tab-pane>
</el-tabs>
<n8n-text v-else-if="hasNodeRun && dataCount > 0">
{{ dataCount }} {{ $locale.baseText(dataCount === 1 ? 'node.output.item' : 'node.output.items') }}
</n8n-text>
</div>

View file

@ -64,6 +64,7 @@ import {
N8nRadioButtons,
N8nSelect,
N8nSpinner,
N8nTabs,
N8nFormInputs,
N8nFormBox,
N8nSquareButton,
@ -101,6 +102,7 @@ Vue.use(N8nSpinner);
Vue.use(N8nRadioButtons);
Vue.component('n8n-square-button', N8nSquareButton);
Vue.use(N8nTags);
Vue.component('n8n-tabs', N8nTabs);
Vue.use(N8nTag);
Vue.component('n8n-text', N8nText);
Vue.use(N8nTooltip);