mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
⚡ Update parameter inputs to be multi-line (#2299)
* introduce analytics * add user survey backend * add user survey backend * set answers on survey submit Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * change name to personalization * lint Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * N8n 2495 add personalization modal (#2280) * update modals * add onboarding modal * implement questions * introduce analytics * simplify impl * implement survey handling * add personalized cateogry * update modal behavior * add thank you view * handle empty cases * rename modal * standarize modal names * update image, add tags to headings * remove unused file * remove unused interfaces * clean up footer spacing * introduce analytics * refactor to fix bug * update endpoint * set min height * update stories * update naming from questions to survey * remove spacing after core categories * fix bug in logic * sort nodes * rename types * merge with be * rename userSurvey * clean up rest api * use constants for keys * use survey keys * clean up types * move personalization to its own file Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> * update parameter inputs to be multiline * update spacing * Survey new options (#2300) * split up options * fix quotes * remove unused import * refactor node credentials * add user created workflow event (#2301) * update multi params * simplify env vars * fix versionCli on FE * update personalization env * clean up node detail settings * fix event User opened Credentials panel * fix font sizes across modals * clean up input spacing * fix select modal spacing * increase spacing * fix input copy * fix webhook, tab spacing, retry button * fix button sizes * fix button size * add mini xlarge sizes * fix webhook spacing * fix nodes panel event * fix workflow id in workflow execute event * improve telemetry error logging * fix config and stop process events * add flush call on n8n stop * ready for release * fix input error highlighting * revert change * update toggle spacing * fix delete positioning * keep tooltip while focused * set strict size * increase left spacing * fix sort icons * remove unnessary margin * clean unused functionality * remove unnessary css * remove duplicate tracking * only show tooltip when hovering over label * update credentials section * use includes Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
3e1fb3e0c9
commit
171f5a458c
|
@ -18,7 +18,7 @@ export default {
|
|||
size: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['small', 'medium', 'large'],
|
||||
options: ['mini', 'small', 'medium', 'large', 'xlarge'],
|
||||
},
|
||||
},
|
||||
loading: {
|
||||
|
@ -31,12 +31,6 @@ export default {
|
|||
type: 'text',
|
||||
},
|
||||
},
|
||||
iconSize: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['small', 'medium', 'large'],
|
||||
},
|
||||
},
|
||||
circle: {
|
||||
control: {
|
||||
type: 'boolean',
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
<component
|
||||
:is="$options.components.N8nSpinner"
|
||||
v-if="props.loading"
|
||||
:size="props.iconSize"
|
||||
:size="props.size"
|
||||
/>
|
||||
<component
|
||||
:is="$options.components.N8nIcon"
|
||||
v-else-if="props.icon"
|
||||
:icon="props.icon"
|
||||
:size="props.iconSize"
|
||||
:size="props.size"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="props.label">{{ props.label }}</span>
|
||||
|
@ -58,7 +58,7 @@ export default {
|
|||
type: String,
|
||||
default: 'medium',
|
||||
validator: (value: string): boolean =>
|
||||
['small', 'medium', 'large'].indexOf(value) !== -1,
|
||||
['mini', 'small', 'medium', 'large', 'xlarge'].indexOf(value) !== -1,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
|
@ -71,9 +71,6 @@ export default {
|
|||
icon: {
|
||||
type: String,
|
||||
},
|
||||
iconSize: {
|
||||
type: String,
|
||||
},
|
||||
round: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
|
|
@ -35,9 +35,6 @@ export declare class N8nButton extends N8nComponent {
|
|||
/** Button icon, accepts an icon name of font awesome icon component */
|
||||
icon: string;
|
||||
|
||||
/** Size of icon */
|
||||
iconSize: N8nComponentSize;
|
||||
|
||||
/** Full width */
|
||||
fullWidth: boolean;
|
||||
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
<template functional>
|
||||
<component
|
||||
:is="$options.components.N8nText"
|
||||
:size="props.size"
|
||||
:compact="true"
|
||||
>
|
||||
<component
|
||||
:is="$options.components.FontAwesomeIcon"
|
||||
:class="$style[`_${props.size}`]"
|
||||
:icon="props.icon"
|
||||
:spin="props.spin"
|
||||
:class="$style[props.size]"
|
||||
/>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
import N8nText from '../N8nText';
|
||||
|
||||
export default {
|
||||
name: 'n8n-icon',
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
N8nText,
|
||||
},
|
||||
props: {
|
||||
icon: {
|
||||
|
@ -23,9 +31,6 @@ export default {
|
|||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
validator: function (value: string): boolean {
|
||||
return ['small', 'medium', 'large'].indexOf(value) !== -1;
|
||||
},
|
||||
},
|
||||
spin: {
|
||||
type: Boolean,
|
||||
|
@ -35,22 +40,21 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" module>
|
||||
._small {
|
||||
font-size: 0.85em;
|
||||
height: 0.85em;
|
||||
width: 0.85em !important;
|
||||
.xlarge {
|
||||
width: var(--font-size-xl) !important;
|
||||
}
|
||||
|
||||
._medium {
|
||||
font-size: 0.95em;
|
||||
height: 0.95em;
|
||||
width: 0.95em !important;
|
||||
.large {
|
||||
width: var(--font-size-m) !important;
|
||||
}
|
||||
|
||||
._large {
|
||||
font-size: 1.22em;
|
||||
height: 1.22em;
|
||||
width: 1.22em !important;
|
||||
.medium {
|
||||
width: var(--font-size-s) !important;
|
||||
}
|
||||
|
||||
.small {
|
||||
width: var(--font-size-2xs) !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
<component :is="$options.components.N8nButton"
|
||||
:type="props.type"
|
||||
:disabled="props.disabled"
|
||||
:size="props.size === 'xlarge' ? 'large' : props.size"
|
||||
:size="props.size"
|
||||
:loading="props.loading"
|
||||
:title="props.title"
|
||||
:icon="props.icon"
|
||||
:iconSize="$options.iconSizeMap[props.size] || props.size"
|
||||
:theme="props.theme"
|
||||
@click="(e) => listeners.click && listeners.click(e)"
|
||||
circle
|
||||
|
@ -16,11 +15,6 @@
|
|||
<script lang="ts">
|
||||
import N8nButton from '../N8nButton';
|
||||
|
||||
const iconSizeMap = {
|
||||
large: 'medium',
|
||||
xlarge: 'large',
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'n8n-icon-button',
|
||||
components: {
|
||||
|
@ -36,8 +30,6 @@ export default {
|
|||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
validator: (value: string): boolean =>
|
||||
['small', 'medium', 'large', 'xlarge'].indexOf(value) !== -1,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
|
@ -55,6 +47,5 @@ export default {
|
|||
type: String,
|
||||
},
|
||||
},
|
||||
iconSizeMap,
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -12,9 +12,6 @@ export declare class N8nIconButton extends N8nComponent {
|
|||
/** Button size */
|
||||
size: N8nComponentSize | 'xlarge';
|
||||
|
||||
/** icon size */
|
||||
iconSize: N8nComponentSize;
|
||||
|
||||
/** Determine whether it's loading */
|
||||
loading: boolean;
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template functional>
|
||||
<div :class="$style.inputLabel">
|
||||
<div :class="props.label ? $style.label: ''">
|
||||
<component v-if="props.label" :is="$options.components.N8nText" :bold="true">
|
||||
<div :class="{[$style.inputLabelContainer]: !props.labelHoverableOnly}">
|
||||
<div :class="{[$style.inputLabel]: props.labelHoverableOnly, [$options.methods.getLabelClass(props, $style)]: true}">
|
||||
<component v-if="props.label" :is="$options.components.N8nText" :bold="props.bold" :size="props.size" :compact="!props.underline">
|
||||
{{ props.label }}
|
||||
<component :is="$options.components.N8nText" color="primary" :bold="true" v-if="props.required">*</component>
|
||||
<component :is="$options.components.N8nText" color="primary" :bold="props.bold" :size="props.size" v-if="props.required">*</component>
|
||||
</component>
|
||||
<span :class="$style.infoIcon" v-if="props.tooltipText">
|
||||
<span :class="[$style.infoIcon, props.showTooltip ? $style.showIcon: $style.hiddenIcon]" v-if="props.tooltipText">
|
||||
<component :is="$options.components.N8nTooltip" placement="top" :popper-class="$style.tooltipPopper">
|
||||
<component :is="$options.components.N8nIcon" icon="question-circle" />
|
||||
<component :is="$options.components.N8nIcon" icon="question-circle" size="small" />
|
||||
<div slot="content" v-html="$options.methods.addTargetBlank(props.tooltipText)"></div>
|
||||
</component>
|
||||
</span>
|
||||
|
@ -40,31 +40,97 @@ export default {
|
|||
required: {
|
||||
type: Boolean,
|
||||
},
|
||||
bold: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
validator: (value: string): boolean =>
|
||||
['small', 'medium'].includes(value),
|
||||
},
|
||||
underline: {
|
||||
type: Boolean,
|
||||
},
|
||||
showTooltip: {
|
||||
type: Boolean,
|
||||
},
|
||||
labelHoverableOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addTargetBlank,
|
||||
getLabelClass(props: {label: string, size: string, underline: boolean}, $style: any) {
|
||||
if (!props.label) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (props.underline) {
|
||||
return $style[`label-${props.size}-underline`];
|
||||
}
|
||||
|
||||
return $style[`label-${props.size}`];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.inputLabel {
|
||||
&:hover {
|
||||
--info-icon-display: inline-block;
|
||||
.inputLabelContainer:hover {
|
||||
> div > .infoIcon {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-bottom: var(--spacing-2xs);
|
||||
|
||||
* {
|
||||
margin-right: var(--spacing-4xs);
|
||||
.inputLabel:hover {
|
||||
> .infoIcon {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.infoIcon {
|
||||
color: var(--color-text-light);
|
||||
display: var(--info-icon-display, none);
|
||||
}
|
||||
|
||||
.showIcon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hiddenIcon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
* {
|
||||
margin-right: var(--spacing-5xs);
|
||||
}
|
||||
}
|
||||
|
||||
.label-small {
|
||||
composes: label;
|
||||
margin-bottom: var(--spacing-4xs);
|
||||
}
|
||||
|
||||
.label-medium {
|
||||
composes: label;
|
||||
margin-bottom: var(--spacing-2xs);
|
||||
}
|
||||
|
||||
.underline {
|
||||
border-bottom: var(--border-base);
|
||||
}
|
||||
|
||||
.label-small-underline {
|
||||
composes: label-small;
|
||||
composes: underline;
|
||||
}
|
||||
|
||||
.label-medium-underline {
|
||||
composes: label-medium;
|
||||
composes: underline;
|
||||
}
|
||||
|
||||
.tooltipPopper {
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Vue.extend({
|
|||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
validator: (value: string): boolean => ['large', 'medium', 'small'].includes(value),
|
||||
validator: (value: string): boolean => ['mini', 'small', 'medium', 'large', 'xlarge'].includes(value),
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
|
@ -26,16 +26,23 @@ export default Vue.extend({
|
|||
type: String,
|
||||
validator: (value: string): boolean => ['right', 'left', 'center'].includes(value),
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getClass(props: {size: string, bold: boolean}) {
|
||||
return `body-${props.size}${props.bold ? '-bold' : '-regular'}`;
|
||||
},
|
||||
getStyles(props: {color: string, align: string}) {
|
||||
getStyles(props: {color: string, align: string, compact: false}) {
|
||||
const styles = {} as any;
|
||||
if (props.color) {
|
||||
styles.color = `var(--color-${props.color})`;
|
||||
}
|
||||
if (props.compact) {
|
||||
styles['line-height'] = 1;
|
||||
}
|
||||
if (props.align) {
|
||||
styles['text-align'] = props.align;
|
||||
}
|
||||
|
@ -54,6 +61,22 @@ export default Vue.extend({
|
|||
font-weight: var(--font-weight-regular);
|
||||
}
|
||||
|
||||
.body-xlarge {
|
||||
font-size: var(--font-size-xl);
|
||||
line-height: var(--font-line-height-xloose);
|
||||
}
|
||||
|
||||
.body-xlarge-regular {
|
||||
composes: regular;
|
||||
composes: body-xlarge;
|
||||
}
|
||||
|
||||
.body-xlarge-bold {
|
||||
composes: bold;
|
||||
composes: body-xlarge;
|
||||
}
|
||||
|
||||
|
||||
.body-large {
|
||||
font-size: var(--font-size-m);
|
||||
line-height: var(--font-line-height-xloose);
|
||||
|
|
|
@ -7,4 +7,4 @@ export declare class N8nComponent extends Vue {
|
|||
}
|
||||
|
||||
/** Component size definition for button, input, etc */
|
||||
export type N8nComponentSize = 'large' | 'medium' | 'small';
|
||||
export type N8nComponentSize = 'xlarge' | 'large' | 'medium' | 'small' | 'mini';
|
||||
|
|
|
@ -83,6 +83,17 @@ $loading-overlay-background-color: rgba(255, 255, 255, 0.35);
|
|||
--button-border-radius: 50%;
|
||||
}
|
||||
|
||||
@include mixins.m(mini) {
|
||||
--button-padding-vertical: var(--spacing-4xs);
|
||||
--button-padding-horizontal: var(--spacing-2xs);
|
||||
--button-font-size: var(--font-size-2xs);
|
||||
|
||||
@include mixins.when(circle) {
|
||||
--button-padding-vertical: var(--spacing-4xs);
|
||||
--button-padding-horizontal: var(--spacing-4xs);
|
||||
}
|
||||
}
|
||||
|
||||
@include mixins.m(small) {
|
||||
--button-padding-vertical: var(--spacing-3xs);
|
||||
--button-padding-horizontal: var(--spacing-xs);
|
||||
|
@ -104,4 +115,15 @@ $loading-overlay-background-color: rgba(255, 255, 255, 0.35);
|
|||
--button-padding-horizontal: var(--spacing-2xs);
|
||||
}
|
||||
}
|
||||
|
||||
@include mixins.m(xlarge) {
|
||||
--button-padding-vertical: var(--spacing-xs);
|
||||
--button-padding-horizontal: var(--spacing-s);
|
||||
--button-font-size: var(--font-size-m);
|
||||
|
||||
@include mixins.when(circle) {
|
||||
--button-padding-vertical: var(--spacing-xs);
|
||||
--button-padding-horizontal: var(--spacing-xs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,8 +68,6 @@
|
|||
@include mixins.e(body) {
|
||||
padding: var.$dialog-padding-primary;
|
||||
color: var(--color-text-base);
|
||||
font-size: var.$dialog-content-font-size;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@include mixins.e(footer) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@include mixins.e(header) {
|
||||
padding: 0;
|
||||
position: relative;
|
||||
margin: 0 0 15px;
|
||||
margin: 0;
|
||||
}
|
||||
@include mixins.e(active-bar) {
|
||||
position: absolute;
|
||||
|
|
|
@ -67,6 +67,7 @@ export default mixins(
|
|||
|
||||
<style scoped lang="scss">
|
||||
.n8n-about {
|
||||
font-size: var(--font-size-s);
|
||||
.el-row {
|
||||
padding: 0.25em 0;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<template>
|
||||
<div v-if="dialogVisible">
|
||||
<el-dialog :visible="dialogVisible" append-to-body :close-on-click-modal="false" width="80%" :title="`Edit ${parameter.displayName}`" :before-close="closeDialog">
|
||||
<div class="text-editor-wrapper ignore-key-press">
|
||||
<div class="editor-description">
|
||||
{{parameter.displayName}}:
|
||||
</div>
|
||||
<div class="text-editor" @keydown.stop>
|
||||
<div class="ignore-key-press">
|
||||
<n8n-input-label :label="parameter.displayName">
|
||||
<div :class="$style.editor" @keydown.stop>
|
||||
<prism-editor :lineNumbers="true" :code="value" :readonly="isReadOnly" @change="valueChanged" language="js"></prism-editor>
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
@ -53,9 +52,8 @@ export default mixins(
|
|||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-description {
|
||||
font-weight: bold;
|
||||
padding: 0 0 0.5em 0.2em;;
|
||||
<style lang="scss" module>
|
||||
.editor {
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div @keydown.stop class="collection-parameter">
|
||||
<div class="collection-parameter-wrapper">
|
||||
<div v-if="getProperties.length === 0" class="no-items-exist">
|
||||
Currently no properties exist
|
||||
<n8n-text size="small">Currently no properties exist</n8n-text>
|
||||
</div>
|
||||
|
||||
<parameter-input-list :parameters="getProperties" :nodeValues="nodeValues" :path="path" :hideDelete="hideDelete" @valueChanged="valueChanged" />
|
||||
<parameter-input-list :parameters="getProperties" :nodeValues="nodeValues" :path="path" :hideDelete="hideDelete" :indent="true" @valueChanged="valueChanged" />
|
||||
|
||||
<div v-if="parameterOptions.length > 0 && !isReadOnly" class="param-options">
|
||||
<n8n-button
|
||||
|
@ -184,14 +184,14 @@ export default mixins(
|
|||
<style lang="scss">
|
||||
|
||||
.collection-parameter {
|
||||
padding-left: 2em;
|
||||
padding-left: var(--spacing-s);
|
||||
|
||||
.param-options {
|
||||
padding-top: 0.5em;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.no-items-exist {
|
||||
margin: 0.8em 0 0.4em 0;
|
||||
margin: var(--spacing-xs) 0;
|
||||
}
|
||||
.option {
|
||||
position: relative;
|
||||
|
|
|
@ -53,6 +53,7 @@ export default mixins(copyPaste, showMessage).extend({
|
|||
span {
|
||||
font-family: Monaco, Consolas;
|
||||
line-height: 1.5;
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
|
||||
padding: var(--spacing-xs);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<div :class="$style.credActions">
|
||||
<n8n-icon-button
|
||||
v-if="currentCredential"
|
||||
size="medium"
|
||||
size="small"
|
||||
title="Delete"
|
||||
icon="trash"
|
||||
type="text"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div :class="$style.container">
|
||||
<el-row>
|
||||
<el-col :span="8" :class="$style.accessLabel">
|
||||
<span>Allow use by</span>
|
||||
<n8n-text :compact="true" :bold="true">Allow use by</n8n-text>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<div
|
||||
|
@ -20,26 +20,26 @@
|
|||
</el-row>
|
||||
<el-row v-if="currentCredential">
|
||||
<el-col :span="8" :class="$style.label">
|
||||
<span>Created</span>
|
||||
<n8n-text :compact="true" :bold="true">Created</n8n-text>
|
||||
</el-col>
|
||||
<el-col :span="16" :class="$style.valueLabel">
|
||||
<TimeAgo :date="currentCredential.createdAt" :capitalize="true" />
|
||||
<n8n-text :compact="true"><TimeAgo :date="currentCredential.createdAt" :capitalize="true" /></n8n-text>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="currentCredential">
|
||||
<el-col :span="8" :class="$style.label">
|
||||
<span>Last modified</span>
|
||||
<n8n-text :compact="true" :bold="true">Last modified</n8n-text>
|
||||
</el-col>
|
||||
<el-col :span="16" :class="$style.valueLabel">
|
||||
<TimeAgo :date="currentCredential.updatedAt" :capitalize="true" />
|
||||
<n8n-text :compact="true"><TimeAgo :date="currentCredential.updatedAt" :capitalize="true" /></n8n-text>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="currentCredential">
|
||||
<el-col :span="8" :class="$style.label">
|
||||
<span>ID</span>
|
||||
<n8n-text :compact="true" :bold="true">ID</n8n-text>
|
||||
</el-col>
|
||||
<el-col :span="16" :class="$style.valueLabel">
|
||||
<span>{{currentCredential.id}}</span>
|
||||
<n8n-text :compact="true">{{currentCredential.id}}</n8n-text>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
width="120">
|
||||
<template slot-scope="scope">
|
||||
<div class="cred-operations">
|
||||
<n8n-icon-button title="Edit Credentials" @click.stop="editCredential(scope.row)" icon="pen" />
|
||||
<n8n-icon-button title="Delete Credentials" @click.stop="deleteCredential(scope.row)" icon="trash" />
|
||||
<n8n-icon-button title="Edit Credentials" @click.stop="editCredential(scope.row)" size="small" icon="pen" />
|
||||
<n8n-icon-button title="Delete Credentials" @click.stop="deleteCredential(scope.row)" size="small" icon="trash" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
:visible="!!node"
|
||||
:before-close="close"
|
||||
:custom-class="`classic data-display-wrapper`"
|
||||
width="80%"
|
||||
width="85%"
|
||||
append-to-body
|
||||
@opened="showDocumentHelp = true"
|
||||
>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<div class="selection-options">
|
||||
<span v-if="checkAll === true || isIndeterminate === true">
|
||||
Selected: {{numSelected}} / <span v-if="finishedExecutionsCountEstimated === true">~</span>{{finishedExecutionsCount}}
|
||||
<n8n-icon-button title="Delete Selected" icon="trash" size="small" @click="handleDeleteSelected" />
|
||||
<n8n-icon-button title="Delete Selected" icon="trash" size="mini" @click="handleDeleteSelected" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
@ -101,7 +101,7 @@
|
|||
v-if="scope.row.stoppedAt !== undefined && !scope.row.finished && scope.row.retryOf === undefined && scope.row.retrySuccessId === undefined && !scope.row.waitTill"
|
||||
type="light"
|
||||
:theme="scope.row.stoppedAt === null ? 'warning': 'danger'"
|
||||
size="small"
|
||||
size="mini"
|
||||
title="Retry execution"
|
||||
icon="redo"
|
||||
/>
|
||||
|
@ -134,10 +134,10 @@
|
|||
<template slot-scope="scope">
|
||||
<div class="actions-container">
|
||||
<span v-if="scope.row.stoppedAt === undefined || scope.row.waitTill">
|
||||
<n8n-icon-button icon="stop" title="Stop Execution" @click.stop="stopExecution(scope.row.id)" :loading="stoppingExecutions.includes(scope.row.id)" />
|
||||
<n8n-icon-button icon="stop" size="small" title="Stop Execution" @click.stop="stopExecution(scope.row.id)" :loading="stoppingExecutions.includes(scope.row.id)" />
|
||||
</span>
|
||||
<span v-if="scope.row.stoppedAt !== undefined && scope.row.id" >
|
||||
<n8n-icon-button icon="folder-open" title="Open Past Execution" @click.stop="displayExecution(scope.row)" />
|
||||
<n8n-icon-button icon="folder-open" size="small" title="Open Past Execution" @click.stop="displayExecution(scope.row)" />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -711,12 +711,10 @@ export default mixins(
|
|||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
height: 22.6px;
|
||||
line-height: 22.6px;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
font-size: var(--font-size-s);
|
||||
|
||||
&.error {
|
||||
background-color: var(--color-danger-tint-1);
|
||||
|
|
|
@ -143,6 +143,7 @@ export default mixins(
|
|||
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
|
||||
.right-side {
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
<template>
|
||||
<div @keydown.stop class="fixed-collection-parameter">
|
||||
<div v-if="getProperties.length === 0" class="no-items-exist">
|
||||
Currently no items exist
|
||||
<n8n-text size="small">Currently no items exist</n8n-text>
|
||||
</div>
|
||||
|
||||
<div v-for="property in getProperties" :key="property.name" class="fixed-collection-parameter-property">
|
||||
<div v-if="property.displayName === '' || parameter.options.length === 1"></div>
|
||||
<div v-else class="parameter-name" :title="property.displayName">{{property.displayName}}:</div>
|
||||
|
||||
<n8n-input-label
|
||||
:label="property.displayName === '' || parameter.options.length === 1 ? '' : property.displayName"
|
||||
:underline="true"
|
||||
:labelHoverableOnly="true"
|
||||
size="small"
|
||||
>
|
||||
<div v-if="multipleValues === true">
|
||||
<div v-for="(value, index) in values[property.name]" :key="property.name + index" class="parameter-item">
|
||||
<div class="parameter-item-wrapper">
|
||||
|
@ -30,6 +33,7 @@
|
|||
<parameter-input-list :parameters="property.values" :nodeValues="nodeValues" :path="getPropertyPath(property.name)" class="parameter-item" @valueChanged="valueChanged" :hideDelete="true" />
|
||||
</div>
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
|
||||
<div v-if="parameterOptions.length > 0 && !isReadOnly">
|
||||
|
@ -221,16 +225,11 @@ export default mixins(genericHelpers)
|
|||
<style scoped lang="scss">
|
||||
|
||||
.fixed-collection-parameter {
|
||||
padding: 0 0 0 1em;
|
||||
padding-left: var(--spacing-s);
|
||||
}
|
||||
|
||||
.fixed-collection-parameter-property {
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em 0;
|
||||
|
||||
.parameter-name {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
margin: var(--spacing-xs) 0;
|
||||
}
|
||||
|
||||
.delete-option {
|
||||
|
@ -244,28 +243,33 @@ export default mixins(genericHelpers)
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.parameter-item-wrapper:hover > .delete-option {
|
||||
.parameter-item:hover > .parameter-item-wrapper > .delete-option {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.parameter-item {
|
||||
position: relative;
|
||||
padding: 0 0 0 1em;
|
||||
margin: 0.6em 0 0.5em 0.1em;
|
||||
|
||||
+ .parameter-item {
|
||||
.parameter-item-wrapper {
|
||||
padding-top: 0.5em;
|
||||
border-top: 1px dashed #999;
|
||||
|
||||
.delete-option {
|
||||
top: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-items-exist {
|
||||
margin: 0.8em 0;
|
||||
margin: var(--spacing-xs) 0;
|
||||
}
|
||||
|
||||
.sort-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 1px;
|
||||
margin-top: .5em;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<template>
|
||||
<div @keydown.stop class="duplicate-parameter">
|
||||
|
||||
<div class="parameter-name">
|
||||
{{parameter.displayName}}:
|
||||
<n8n-tooltip v-if="parameter.description" class="parameter-info" placement="top" >
|
||||
<div slot="content" v-html="addTargetBlank(parameter.description)"></div>
|
||||
<font-awesome-icon icon="question-circle" />
|
||||
</n8n-tooltip>
|
||||
</div>
|
||||
<n8n-input-label
|
||||
:label="parameter.displayName"
|
||||
:tooltipText="parameter.description"
|
||||
:underline="true"
|
||||
:labelHoverableOnly="true"
|
||||
size="small"
|
||||
>
|
||||
|
||||
<div v-for="(value, index) in values" :key="index" class="duplicate-parameter-item" :class="parameter.type">
|
||||
<div class="delete-item clickable" v-if="!isReadOnly">
|
||||
|
@ -27,11 +26,12 @@
|
|||
|
||||
<div class="add-item-wrapper">
|
||||
<div v-if="values && Object.keys(values).length === 0 || isReadOnly" class="no-items-exist">
|
||||
Currently no items exist
|
||||
<n8n-text size="small">Currently no items exist</n8n-text>
|
||||
</div>
|
||||
<n8n-button v-if="!isReadOnly" fullWidth @click="addItem()" :label="addButtonText" />
|
||||
</div>
|
||||
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -48,7 +48,6 @@ import { get } from 'lodash';
|
|||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { addTargetBlank } from './helpers';
|
||||
|
||||
export default mixins(genericHelpers)
|
||||
.extend({
|
||||
|
@ -75,7 +74,6 @@ export default mixins(genericHelpers)
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
addTargetBlank,
|
||||
addItem () {
|
||||
const name = this.getPath();
|
||||
let currentValue = get(this.nodeValues, name);
|
||||
|
@ -134,11 +132,7 @@ export default mixins(genericHelpers)
|
|||
<style scoped lang="scss">
|
||||
|
||||
.duplicate-parameter-item ~.add-item-wrapper {
|
||||
margin: 1.5em 0 0em 0em;
|
||||
}
|
||||
|
||||
.add-item-wrapper {
|
||||
margin: 0.5em 0 0em 2em;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.delete-item {
|
||||
|
@ -149,23 +143,15 @@ export default mixins(genericHelpers)
|
|||
z-index: 999;
|
||||
color: #f56c6c;
|
||||
width: 15px;
|
||||
font-size: var(--font-size-2xs);
|
||||
|
||||
:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
|
||||
.duplicate-parameter {
|
||||
margin-top: 0.5em;
|
||||
.parameter-name {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .duplicate-parameter-item {
|
||||
position: relative;
|
||||
margin-top: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
|
||||
.multi > .delete-item{
|
||||
top: 0.1em;
|
||||
|
@ -179,12 +165,12 @@ export default mixins(genericHelpers)
|
|||
::v-deep .duplicate-parameter-item + .duplicate-parameter-item {
|
||||
.collection-parameter-wrapper {
|
||||
border-top: 1px dashed #999;
|
||||
padding-top: 0.5em;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
}
|
||||
|
||||
.no-items-exist {
|
||||
margin: 0 0 1em 0;
|
||||
margin: var(--spacing-xs) 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
<template>
|
||||
<div v-if="credentialTypesNodeDescriptionDisplayed.length" class="node-credentials">
|
||||
<div class="headline">
|
||||
Credentials
|
||||
<div v-if="credentialTypesNodeDescriptionDisplayed.length" :class="$style.container">
|
||||
<div v-for="credentialTypeDescription in credentialTypesNodeDescriptionDisplayed" :key="credentialTypeDescription.name">
|
||||
<n8n-input-label
|
||||
:label="`Credential for ${credentialTypeNames[credentialTypeDescription.name]}`"
|
||||
:bold="false"
|
||||
size="small"
|
||||
|
||||
:set="issues = getIssues(credentialTypeDescription.name)"
|
||||
>
|
||||
<div v-if="isReadOnly">
|
||||
<n8n-input disabled :value="selected && selected[credentialTypeDescription.name] && selected[credentialTypeDescription.name].name" size="small" />
|
||||
</div>
|
||||
|
||||
<div v-for="credentialTypeDescription in credentialTypesNodeDescriptionDisplayed" :key="credentialTypeDescription.name" class="credential-data">
|
||||
<el-row class="credential-parameter-wrapper">
|
||||
<el-col :span="10" class="parameter-name">
|
||||
{{credentialTypeNames[credentialTypeDescription.name]}}:
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="!isReadOnly" :span="12" class="parameter-value" :class="getIssues(credentialTypeDescription.name).length?'has-issues':''">
|
||||
<div :style="credentialInputWrapperStyle(credentialTypeDescription.name)">
|
||||
<div :class="issues.length ? $style.hasIssues : $style.input" v-else >
|
||||
<n8n-select :value="getSelectedId(credentialTypeDescription.name)" @change="(value) => onCredentialSelected(credentialTypeDescription.name, value)" placeholder="Select Credential" size="small">
|
||||
<n8n-option
|
||||
v-for="(item) in credentialOptions[credentialTypeDescription.name]"
|
||||
|
@ -26,26 +27,20 @@
|
|||
>
|
||||
</n8n-option>
|
||||
</n8n-select>
|
||||
</div>
|
||||
|
||||
<div class="credential-issues">
|
||||
<div :class="$style.warning" v-if="issues.length">
|
||||
<n8n-tooltip placement="top" >
|
||||
<div slot="content" v-html="'Issues:<br /> - ' + getIssues(credentialTypeDescription.name).join('<br /> - ')"></div>
|
||||
<div slot="content" v-html="'Issues:<br /> - ' + issues.join('<br /> - ')"></div>
|
||||
<font-awesome-icon icon="exclamation-triangle" />
|
||||
</n8n-tooltip>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col v-if="!isReadOnly" :span="2" class="parameter-value credential-action">
|
||||
<font-awesome-icon v-if="isCredentialExisting(credentialTypeDescription.name)" icon="pen" @click="editCredential(credentialTypeDescription.name)" class="update-credentials clickable" title="Update Credentials" />
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="isReadOnly" :span="14" class="readonly-container" >
|
||||
<n8n-input disabled :value="selected && selected[credentialTypeDescription.name] && selected[credentialTypeDescription.name].name" size="small" />
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<div :class="$style.edit" v-if="selected[credentialTypeDescription.name] && isCredentialExisting(credentialTypeDescription.name)">
|
||||
<font-awesome-icon icon="pen" @click="editCredential(credentialTypeDescription.name)" class="clickable" title="Update Credentials" />
|
||||
</div>
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -285,62 +280,39 @@ export default mixins(
|
|||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" module>
|
||||
.container {
|
||||
margin: var(--spacing-xs) 0;
|
||||
|
||||
.node-credentials {
|
||||
padding-bottom: 1em;
|
||||
margin: 0.5em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
> * {
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
}
|
||||
|
||||
.credential-issues {
|
||||
display: none;
|
||||
width: 20px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
.warning {
|
||||
min-width: 20px;
|
||||
margin-left: 5px;
|
||||
color: #ff8080;
|
||||
font-size: 1.2em;
|
||||
margin-top: 3px;
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
|
||||
.credential-data + .credential-data {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.has-issues {
|
||||
.credential-issues {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.headline {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
|
||||
.credential-parameter-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.parameter-name {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.parameter-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.credential-action {
|
||||
.edit {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--color-text-base);
|
||||
min-width: 20px;
|
||||
margin-left: 5px;
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
|
||||
.readonly-container {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
.input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hasIssues {
|
||||
composes: input;
|
||||
--input-border-color: var(--color-danger);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
</n8n-tooltip>
|
||||
</a>
|
||||
</span>
|
||||
<span v-else>No node active</span>
|
||||
</div>
|
||||
<div class="node-is-not-valid" v-if="node && !nodeValid">
|
||||
The node is not valid as its type "{{node.type}}" is unknown.
|
||||
<n8n-text>The node is not valid as its type "{{node.type}}" is unknown.</n8n-text>
|
||||
</div>
|
||||
<div class="node-parameters-wrapper" v-if="node && nodeValid">
|
||||
<el-tabs stretch @tab-click="handleTabClick">
|
||||
|
@ -21,8 +20,8 @@
|
|||
<node-credentials :node="node" @credentialSelected="credentialSelected"></node-credentials>
|
||||
<node-webhooks :node="node" :nodeType="nodeType" />
|
||||
<parameter-input-list :parameters="parametersNoneSetting" :hideDelete="true" :nodeValues="nodeValues" path="parameters" @valueChanged="valueChanged" />
|
||||
<div v-if="parametersNoneSetting.length === 0">
|
||||
This node does not have any parameters.
|
||||
<div v-if="parametersNoneSetting.length === 0" class="no-parameters">
|
||||
<n8n-text>This node does not have any parameters.</n8n-text>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Settings">
|
||||
|
@ -521,7 +520,10 @@ export default mixins(
|
|||
overflow: hidden;
|
||||
min-width: 350px;
|
||||
max-width: 350px;
|
||||
font-size: var(--font-size-s);
|
||||
|
||||
.no-parameters {
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.header-side-menu {
|
||||
padding: 1em 0 1em 1.8em;
|
||||
|
@ -547,10 +549,10 @@ export default mixins(
|
|||
|
||||
.node-parameters-wrapper {
|
||||
height: 100%;
|
||||
font-size: .9em;
|
||||
|
||||
.el-tabs__header {
|
||||
background-color: #fff5f2;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.el-tabs {
|
||||
|
@ -561,13 +563,13 @@ export default mixins(
|
|||
padding-bottom: 180px;
|
||||
|
||||
.el-tab-pane {
|
||||
margin: 0 1em;
|
||||
margin: 0 var(--spacing-s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-tabs__nav {
|
||||
padding-bottom: 1em;
|
||||
padding-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.add-option {
|
||||
|
@ -621,14 +623,6 @@ export default mixins(
|
|||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.parameter-name {
|
||||
line-height: 1.5;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.color-reset-button-wrapper {
|
||||
position: relative;
|
||||
|
||||
|
|
|
@ -128,14 +128,14 @@ export default mixins(
|
|||
<style scoped lang="scss">
|
||||
|
||||
.webhoooks {
|
||||
padding: 0.7em;
|
||||
font-size: 0.9em;
|
||||
margin: 0.5em 0;
|
||||
padding-bottom: var(--spacing-xs);
|
||||
margin: var(--spacing-xs) 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
|
||||
.headline {
|
||||
color: $--color-primary;
|
||||
font-weight: 600;
|
||||
font-size: var(--font-size-2xs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,8 +154,8 @@ export default mixins(
|
|||
margin-left: 5px;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
font-size: 0.8em;
|
||||
font-weight: 600;
|
||||
font-size: var(--font-size-2xs);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
@ -175,11 +175,11 @@ export default mixins(
|
|||
.url-field {
|
||||
display: inline-block;
|
||||
width: calc(100% - 60px);
|
||||
margin-left: 50px;
|
||||
margin-left: 55px;
|
||||
}
|
||||
|
||||
.url-selection {
|
||||
margin-top: 1em;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.minimize-button {
|
||||
|
@ -205,12 +205,11 @@ export default mixins(
|
|||
position: relative;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
font-size: 0.9em;
|
||||
font-size: var(--font-size-2xs);
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
text-overflow: initial;
|
||||
color: #404040;
|
||||
padding: 0.5em;
|
||||
text-align: left;
|
||||
direction: ltr;
|
||||
word-break: break-all;
|
||||
|
@ -219,9 +218,8 @@ export default mixins(
|
|||
.webhook-wrapper {
|
||||
line-height: 1.5;
|
||||
position: relative;
|
||||
margin: 1em 0 0.5em 0;
|
||||
margin-top: var(--spacing-xs);
|
||||
background-color: #fff;
|
||||
padding: 2px 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<code-edit :dialogVisible="codeEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeCodeEditDialog" @valueChanged="expressionUpdated"></code-edit>
|
||||
<text-edit :dialogVisible="textEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeTextEditDialog" @valueChanged="expressionUpdated"></text-edit>
|
||||
|
||||
<div v-if="isEditor === true" class="clickable" @click="displayEditDialog()">
|
||||
<div v-if="isEditor === true" class="code-edit clickable" @click="displayEditDialog()">
|
||||
<prism-editor v-if="!codeEditDialogVisible" :lineNumbers="true" :readonly="true" :code="displayValue" language="js"></prism-editor>
|
||||
</div>
|
||||
|
||||
|
@ -515,8 +515,9 @@ export default mixins(
|
|||
const classes = [];
|
||||
const rows = this.getArgument('rows');
|
||||
const isTextarea = this.parameter.type === 'string' && rows !== undefined;
|
||||
const isSwitch = this.parameter.type === 'boolean' && !this.isValueExpression;
|
||||
|
||||
if (!isTextarea) {
|
||||
if (!isTextarea && !isSwitch) {
|
||||
classes.push('parameter-value-container');
|
||||
}
|
||||
if (this.isValueExpression) {
|
||||
|
@ -664,6 +665,8 @@ export default mixins(
|
|||
(this.$refs.inputField.$el.querySelector(this.getStringInputType === 'textarea' ? 'textarea' : 'input') as HTMLInputElement).focus();
|
||||
}
|
||||
});
|
||||
|
||||
this.$emit('focus');
|
||||
},
|
||||
rgbaToHex (value: string): string | null {
|
||||
// Convert rgba to hex from: https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
|
||||
|
@ -775,8 +778,12 @@ export default mixins(
|
|||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.code-edit {
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.switch-input {
|
||||
margin: 5px 0;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.parameter-value-container {
|
||||
|
@ -804,7 +811,7 @@ export default mixins(
|
|||
text-align: right;
|
||||
float: right;
|
||||
color: #ff8080;
|
||||
font-size: 1.2em;
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
|
||||
::v-deep .color-input {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
:label="parameter.displayName"
|
||||
:tooltipText="parameter.description"
|
||||
:required="parameter.required"
|
||||
:showTooltip="focused"
|
||||
>
|
||||
<parameter-input
|
||||
:parameter="parameter"
|
||||
|
@ -12,7 +13,7 @@
|
|||
:displayOptions="true"
|
||||
:documentationUrl="documentationUrl"
|
||||
:errorHighlight="showRequiredErrors"
|
||||
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@textInput="valueChanged"
|
||||
@valueChanged="valueChanged"
|
||||
|
@ -48,7 +49,8 @@ export default Vue.extend({
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
blurred: false,
|
||||
focused: false,
|
||||
blurredEver: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -57,7 +59,7 @@ export default Vue.extend({
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.blurred || this.showValidationWarnings) {
|
||||
if (this.blurredEver || this.showValidationWarnings) {
|
||||
if (this.$props.parameter.type === 'string') {
|
||||
return !this.value;
|
||||
}
|
||||
|
@ -71,8 +73,12 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
onFocus() {
|
||||
this.focused = true;
|
||||
},
|
||||
onBlur() {
|
||||
this.blurred = true;
|
||||
this.blurredEver = true;
|
||||
this.focused = false;
|
||||
},
|
||||
valueChanged(parameterData: IUpdateInformation) {
|
||||
this.$emit('change', parameterData);
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
<template>
|
||||
<el-row class="parameter-wrapper" :class="{'multi-line': isMultiLineParameter}">
|
||||
<el-col :span="isMultiLineParameter ? 24 : 10" class="parameter-name" :class="{'multi-line': isMultiLineParameter}">
|
||||
<span class="title" :title="parameter.displayName">{{parameter.displayName}}</span>:
|
||||
<n8n-tooltip class="parameter-info" placement="top" v-if="parameter.description" >
|
||||
<div slot="content" v-html="addTargetBlank(parameter.description)"></div>
|
||||
<font-awesome-icon icon="question-circle" />
|
||||
</n8n-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="isMultiLineParameter ? 24 : 14" class="parameter-value">
|
||||
<parameter-input :parameter="parameter" :value="value" :displayOptions="displayOptions" :path="path" :isReadOnly="isReadOnly" @valueChanged="valueChanged" inputSize="small" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<n8n-input-label
|
||||
:label="parameter.displayName"
|
||||
:tooltipText="parameter.description"
|
||||
:showTooltip="focused"
|
||||
:bold="false"
|
||||
size="small"
|
||||
>
|
||||
<parameter-input
|
||||
:parameter="parameter"
|
||||
:value="value"
|
||||
:displayOptions="displayOptions"
|
||||
:path="path"
|
||||
:isReadOnly="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
inputSize="small" />
|
||||
</n8n-input-label>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -21,7 +27,6 @@ import {
|
|||
} from '@/Interface';
|
||||
|
||||
import ParameterInput from '@/components/ParameterInput.vue';
|
||||
import { addTargetBlank } from './helpers';
|
||||
|
||||
export default Vue
|
||||
.extend({
|
||||
|
@ -29,21 +34,10 @@ export default Vue
|
|||
components: {
|
||||
ParameterInput,
|
||||
},
|
||||
computed: {
|
||||
isMultiLineParameter () {
|
||||
if (this.level > 4) {
|
||||
return true;
|
||||
}
|
||||
const rows = this.getArgument('rows');
|
||||
if (rows !== undefined && rows > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
level (): number {
|
||||
return this.path.split('.').length;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focused: false,
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'displayOptions',
|
||||
|
@ -53,7 +47,6 @@ export default Vue
|
|||
'value',
|
||||
],
|
||||
methods: {
|
||||
addTargetBlank,
|
||||
getArgument (argumentName: string): string | number | boolean | undefined {
|
||||
if (this.parameter.typeOptions === undefined) {
|
||||
return undefined;
|
||||
|
@ -71,46 +64,3 @@ export default Vue
|
|||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.parameter-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.multi-line {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.option {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.parameter-info {
|
||||
background-color: #ffffffaa;
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.parameter-name {
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
.parameter-info {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
&.multi-line {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="paramter-input-list-wrapper">
|
||||
<div v-for="parameter in filteredParameters" :key="parameter.name">
|
||||
<div v-for="parameter in filteredParameters" :key="parameter.name" :class="{indent}">
|
||||
<div
|
||||
v-if="multipleValues(parameter) === true && parameter.type !== 'fixedCollection'"
|
||||
class="parameter-item"
|
||||
|
@ -14,13 +14,16 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div v-else-if="parameter.type === 'notice'" v-html="parameter.displayName" class="parameter-item parameter-notice"></div>
|
||||
<div v-else-if="parameter.type === 'notice'" class="parameter-item parameter-notice">
|
||||
<n8n-text size="small">
|
||||
<span v-html="parameter.displayName"></span>
|
||||
</n8n-text>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="['collection', 'fixedCollection'].includes(parameter.type)"
|
||||
class="multi-parameter"
|
||||
>
|
||||
<div class="parameter-name" :title="parameter.displayName">
|
||||
<div class="delete-option clickable" title="Delete" v-if="hideDelete !== true && !isReadOnly">
|
||||
<font-awesome-icon
|
||||
icon="trash"
|
||||
|
@ -29,13 +32,13 @@
|
|||
@click="deleteOption(parameter.name)"
|
||||
/>
|
||||
</div>
|
||||
{{parameter.displayName}}:
|
||||
<n8n-tooltip placement="top" class="parameter-info" v-if="parameter.description" >
|
||||
<div slot="content" v-html="addTargetBlank(parameter.description)"></div>
|
||||
<font-awesome-icon icon="question-circle"/>
|
||||
</n8n-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-input-label
|
||||
:label="parameter.displayName"
|
||||
:tooltipText="parameter.description"
|
||||
size="small"
|
||||
:underline="true"
|
||||
:labelHoverableOnly="true"
|
||||
>
|
||||
<collection-parameter
|
||||
v-if="parameter.type === 'collection'"
|
||||
:parameter="parameter"
|
||||
|
@ -52,7 +55,7 @@
|
|||
:path="getPath(parameter.name)"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
|
||||
<div v-else-if="displayNodeParameter(parameter)" class="parameter-item">
|
||||
|
@ -93,8 +96,6 @@ import { genericHelpers } from '@/components/mixins/genericHelpers';
|
|||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||
import ParameterInputFull from '@/components/ParameterInputFull.vue';
|
||||
|
||||
import { addTargetBlank } from './helpers';
|
||||
|
||||
import { get, set } from 'lodash';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
|
@ -114,6 +115,7 @@ export default mixins(
|
|||
'parameters', // INodeProperties
|
||||
'path', // string
|
||||
'hideDelete', // boolean
|
||||
'indent',
|
||||
],
|
||||
computed: {
|
||||
filteredParameters (): INodeProperties[] {
|
||||
|
@ -124,7 +126,6 @@ export default mixins(
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
addTargetBlank,
|
||||
multipleValues (parameter: INodeProperties): boolean {
|
||||
if (this.getArgument('multipleValues', parameter) === true) {
|
||||
return true;
|
||||
|
@ -260,50 +261,42 @@ export default mixins(
|
|||
position: absolute;
|
||||
z-index: 999;
|
||||
color: #f56c6c;
|
||||
font-size: var(--font-size-2xs);
|
||||
|
||||
&:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
|
||||
.indent > div {
|
||||
padding-left: var(--spacing-s);
|
||||
}
|
||||
|
||||
.multi-parameter {
|
||||
position: relative;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em 0;
|
||||
|
||||
>.parameter-name {
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid #999;
|
||||
|
||||
&:hover {
|
||||
.parameter-info {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
margin: var(--spacing-xs) 0;
|
||||
|
||||
.delete-option {
|
||||
top: 0;
|
||||
left: -0.9em;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.parameter-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.parameter-item {
|
||||
position: relative;
|
||||
margin: 8px 0;
|
||||
margin: var(--spacing-xs) 0;
|
||||
|
||||
>.delete-option {
|
||||
left: -0.9em;
|
||||
top: 0.6em;
|
||||
top: var(--spacing-5xs);
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
.parameter-item:hover > .delete-option,
|
||||
.parameter-name:hover > .delete-option {
|
||||
.multi-parameter:hover > .delete-option {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@ -311,9 +304,7 @@ export default mixins(
|
|||
background-color: #fff5d3;
|
||||
color: $--custom-font-black;
|
||||
margin: 0.3em 0;
|
||||
padding: 0.8em;
|
||||
line-height: 1.5;
|
||||
word-break: normal;
|
||||
padding: 0.7em;
|
||||
|
||||
a {
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
|
|
@ -17,31 +17,31 @@
|
|||
|
||||
<div class="header">
|
||||
<div class="title-text">
|
||||
<strong v-if="dataCount < maxDisplayItems">
|
||||
<n8n-text :bold="true" v-if="dataCount < maxDisplayItems">
|
||||
Items: {{ dataCount }}
|
||||
</strong>
|
||||
</n8n-text>
|
||||
<div v-else class="title-text">
|
||||
<strong>Items:</strong>
|
||||
<n8n-text :bold="true">Items:</n8n-text>
|
||||
<span class="opts">
|
||||
<n8n-select size="mini" v-model="maxDisplayItems" @click.stop>
|
||||
<n8n-option v-for="option in maxDisplayItemsOptions" :label="option" :value="option" :key="option" />
|
||||
</n8n-select>
|
||||
</span>/
|
||||
<strong>{{ dataCount }}</strong>
|
||||
<n8n-text :bold="true">{{ dataCount }}</n8n-text>
|
||||
</div>
|
||||
<n8n-tooltip
|
||||
v-if="runMetadata"
|
||||
placement="right"
|
||||
>
|
||||
<div slot="content">
|
||||
<strong>Start Time:</strong> {{runMetadata.startTime}}<br/>
|
||||
<strong>Execution Time:</strong> {{runMetadata.executionTime}} ms
|
||||
<n8n-text :bold="true" size="small">Start Time:</n8n-text> {{runMetadata.startTime}}<br/>
|
||||
<n8n-text :bold="true" size="small">Execution Time:</n8n-text> {{runMetadata.executionTime}} ms
|
||||
</div>
|
||||
<font-awesome-icon icon="info-circle" class="primary-color" />
|
||||
</n8n-tooltip>
|
||||
<span v-if="maxOutputIndex > 0">
|
||||
<n8n-text :bold="true" v-if="maxOutputIndex > 0">
|
||||
| Output:
|
||||
</span>
|
||||
</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">
|
||||
|
@ -49,9 +49,9 @@
|
|||
</n8n-select>
|
||||
</span>
|
||||
|
||||
<span v-if="maxRunIndex > 0">
|
||||
<n8n-text :bold="true" v-if="maxRunIndex > 0">
|
||||
| Data of Execution:
|
||||
</span>
|
||||
</n8n-text>
|
||||
<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">
|
||||
|
@ -186,7 +186,7 @@
|
|||
</span>
|
||||
<div v-else class="message">
|
||||
<div>
|
||||
<strong>No data</strong><br />
|
||||
<n8n-text :bold="true">No data</n8n-text ><br />
|
||||
<br />
|
||||
Data returned by this node will display here<br />
|
||||
</div>
|
||||
|
@ -659,6 +659,7 @@ export default mixins(
|
|||
overflow-y: auto;
|
||||
line-height: 1.5;
|
||||
word-break: normal;
|
||||
font-size: var(--font-size-s);
|
||||
|
||||
.binary-data-row {
|
||||
display: inline-flex;
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
<div v-if="dialogVisible">
|
||||
<el-dialog :visible="dialogVisible" append-to-body width="80%" :title="`Edit ${parameter.displayName}`" :before-close="closeDialog">
|
||||
|
||||
<div class="text-editor-wrapper ignore-key-press">
|
||||
<div class="editor-description">
|
||||
{{parameter.displayName}}:
|
||||
</div>
|
||||
<div class="text-editor" @keydown.stop @keydown.esc="closeDialog()">
|
||||
<div class="ignore-key-press">
|
||||
<n8n-input-label :label="parameter.displayName">
|
||||
<div @keydown.stop @keydown.esc="closeDialog()">
|
||||
<n8n-input v-model="tempValue" type="textarea" ref="inputField" :value="value" :placeholder="parameter.placeholder" @change="valueChanged" @keydown.stop="noOp" :rows="15" />
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
|
||||
</el-dialog>
|
||||
|
@ -60,10 +59,3 @@ export default Vue.extend({
|
|||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-description {
|
||||
font-weight: bold;
|
||||
padding: 0 0 0.5em 0.2em;;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -516,6 +516,7 @@ export default mixins(
|
|||
|
||||
<style scoped lang="scss">
|
||||
.workflow-settings {
|
||||
font-size: var(--font-size-s);
|
||||
.el-row {
|
||||
padding: 0.25em 0;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,6 @@ import dateformat from 'dateformat';
|
|||
|
||||
const KEYWORDS_TO_FILTER = ['API', 'OAuth1', 'OAuth2'];
|
||||
|
||||
export function addTargetBlank(html: string) {
|
||||
return html.includes('href=')
|
||||
? html.replace(/href=/g, 'target="_blank" href=')
|
||||
: html;
|
||||
}
|
||||
|
||||
export function convertToDisplayDate (epochTime: number) {
|
||||
return dateformat(epochTime, 'yyyy-mm-dd HH:MM:ss');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue