mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-23 11:44:06 -08:00
refactor(editor): Improve linting for component and prop names (no-changelog) (#8169)
This commit is contained in:
parent
639afcd7a5
commit
68cff4c59e
|
@ -4,7 +4,7 @@
|
|||
module.exports = {
|
||||
plugins: ['vue'],
|
||||
|
||||
extends: ['plugin:vue/vue3-essential', '@vue/typescript', './base'],
|
||||
extends: ['plugin:vue/vue3-recommended', '@vue/typescript', './base'],
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
|
@ -37,6 +37,22 @@ module.exports = {
|
|||
'vue/no-unused-components': 'error',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'vue/component-name-in-template-casing': [
|
||||
'error',
|
||||
'PascalCase',
|
||||
{
|
||||
registeredComponentsOnly: true,
|
||||
},
|
||||
],
|
||||
'vue/no-reserved-component-names': [
|
||||
'error',
|
||||
{
|
||||
disallowVueBuiltInComponents: true,
|
||||
disallowVue3BuiltInComponents: false,
|
||||
},
|
||||
],
|
||||
'vue/prop-name-casing': ['error', 'camelCase'],
|
||||
'vue/attribute-hyphenation': ['error', 'always'],
|
||||
|
||||
// TODO: fix these
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
<template>
|
||||
<div :class="['n8n-action-box', $style.container]" data-test-id="action-box">
|
||||
<div :class="$style.emoji" v-if="emoji">
|
||||
<div v-if="emoji" :class="$style.emoji">
|
||||
{{ emoji }}
|
||||
</div>
|
||||
<div :class="$style.heading" v-if="heading || $slots.heading">
|
||||
<n8n-heading size="xlarge" align="center">
|
||||
<div v-if="heading || $slots.heading" :class="$style.heading">
|
||||
<N8nHeading size="xlarge" align="center">
|
||||
<slot name="heading">{{ heading }}</slot>
|
||||
</n8n-heading>
|
||||
</N8nHeading>
|
||||
</div>
|
||||
<div :class="$style.description" @click="$emit('descriptionClick', $event)">
|
||||
<n8n-text color="text-base">
|
||||
<N8nText color="text-base">
|
||||
<slot name="description">
|
||||
<span v-html="description"></span>
|
||||
</slot>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
</div>
|
||||
<n8n-button
|
||||
<N8nButton
|
||||
v-if="buttonText"
|
||||
:label="buttonText"
|
||||
:type="buttonType"
|
||||
size="large"
|
||||
@click="$emit('click:button', $event)"
|
||||
/>
|
||||
<n8n-callout
|
||||
<N8nCallout
|
||||
v-if="calloutText"
|
||||
:theme="calloutTheme"
|
||||
:icon="calloutIcon"
|
||||
:class="$style.callout"
|
||||
>
|
||||
<n8n-text color="text-base">
|
||||
<N8nText color="text-base">
|
||||
<span size="small" v-html="calloutText"></span>
|
||||
</n8n-text>
|
||||
</n8n-callout>
|
||||
</N8nText>
|
||||
</N8nCallout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -43,7 +43,7 @@ import N8nCallout from '../N8nCallout';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-action-box',
|
||||
name: 'N8nActionBox',
|
||||
components: {
|
||||
N8nButton,
|
||||
N8nHeading,
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<template>
|
||||
<div :class="['action-dropdown-container', $style.actionDropdownContainer]">
|
||||
<el-dropdown
|
||||
<ElDropdown
|
||||
ref="elementDropdown"
|
||||
:placement="placement"
|
||||
:trigger="trigger"
|
||||
@command="onSelect"
|
||||
:popper-class="{ [$style.shadow]: true, [$style.hideArrow]: hideArrow }"
|
||||
@command="onSelect"
|
||||
@visible-change="onVisibleChange"
|
||||
ref="elementDropdown"
|
||||
>
|
||||
<slot v-if="$slots.activator" name="activator" />
|
||||
<n8n-icon-button
|
||||
v-else
|
||||
@blur="onButtonBlur"
|
||||
type="tertiary"
|
||||
text
|
||||
:class="$style.activator"
|
||||
:size="activatorSize"
|
||||
:icon="activatorIcon"
|
||||
@blur="onButtonBlur"
|
||||
/>
|
||||
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu :class="$style.userActionsMenu">
|
||||
<el-dropdown-item
|
||||
<ElDropdownMenu :class="$style.userActionsMenu">
|
||||
<ElDropdownItem
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:command="item.id"
|
||||
|
@ -31,22 +31,22 @@
|
|||
>
|
||||
<div :class="getItemClasses(item)" :data-test-id="`${testIdPrefix}-item-${item.id}`">
|
||||
<span v-if="item.icon" :class="$style.icon">
|
||||
<n8n-icon :icon="item.icon" :size="iconSize" />
|
||||
<N8nIcon :icon="item.icon" :size="iconSize" />
|
||||
</span>
|
||||
<span :class="$style.label">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<n8n-keyboard-shortcut
|
||||
<N8nKeyboardShortcut
|
||||
v-if="item.shortcut"
|
||||
v-bind="item.shortcut"
|
||||
:class="$style.shortcut"
|
||||
>
|
||||
</n8n-keyboard-shortcut>
|
||||
</N8nKeyboardShortcut>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</ElDropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -75,7 +75,7 @@ export interface IActionDropdownItem {
|
|||
// It can be used in different parts of editor UI while ActionToggle
|
||||
// is designed to be used in card components.
|
||||
export default defineComponent({
|
||||
name: 'n8n-action-dropdown',
|
||||
name: 'N8nActionDropdown',
|
||||
components: {
|
||||
ElDropdown,
|
||||
ElDropdownMenu,
|
||||
|
@ -83,10 +83,6 @@ export default defineComponent({
|
|||
N8nIcon,
|
||||
N8nKeyboardShortcut,
|
||||
},
|
||||
data() {
|
||||
const testIdPrefix = this.$attrs['data-test-id'];
|
||||
return { testIdPrefix };
|
||||
},
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<IActionDropdownItem[]>,
|
||||
|
@ -121,6 +117,10 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const testIdPrefix = this.$attrs['data-test-id'];
|
||||
return { testIdPrefix };
|
||||
},
|
||||
methods: {
|
||||
getItemClasses(item: IActionDropdownItem): Record<string, boolean> {
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<span @click.stop.prevent :class="$style.container" data-test-id="action-toggle">
|
||||
<el-dropdown
|
||||
<span :class="$style.container" data-test-id="action-toggle" @click.stop.prevent>
|
||||
<ElDropdown
|
||||
:placement="placement"
|
||||
:size="size"
|
||||
trigger="click"
|
||||
|
@ -9,7 +9,7 @@
|
|||
>
|
||||
<slot>
|
||||
<span :class="{ [$style.button]: true, [$style[theme]]: !!theme }">
|
||||
<n8n-icon
|
||||
<N8nIcon
|
||||
:icon="iconOrientation === 'horizontal' ? 'ellipsis-h' : 'ellipsis-v'"
|
||||
:size="iconSize"
|
||||
/>
|
||||
|
@ -17,8 +17,8 @@
|
|||
</slot>
|
||||
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu data-test-id="action-toggle-dropdown">
|
||||
<el-dropdown-item
|
||||
<ElDropdownMenu data-test-id="action-toggle-dropdown">
|
||||
<ElDropdownItem
|
||||
v-for="action in actions"
|
||||
:key="action.value"
|
||||
:command="action.value"
|
||||
|
@ -27,17 +27,17 @@
|
|||
>
|
||||
{{ action.label }}
|
||||
<div :class="$style.iconContainer">
|
||||
<n8n-icon
|
||||
<N8nIcon
|
||||
v-if="action.type === 'external-link'"
|
||||
icon="external-link-alt"
|
||||
size="xsmall"
|
||||
color="text-base"
|
||||
/>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</ElDropdown>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -49,7 +49,7 @@ import N8nIcon from '../N8nIcon';
|
|||
import type { UserAction } from '@/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-action-toggle',
|
||||
name: 'N8nActionToggle',
|
||||
components: {
|
||||
ElDropdown,
|
||||
ElDropdownMenu,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div :class="alertBoxClassNames" role="alert">
|
||||
<div :class="$style.content">
|
||||
<span v-if="showIcon || $slots.icon" :class="$style.icon">
|
||||
<n8n-icon v-if="showIcon" :icon="icon" />
|
||||
<N8nIcon v-if="showIcon" :icon="icon" />
|
||||
<slot v-else-if="$slots.icon" name="icon" />
|
||||
</span>
|
||||
<div :class="$style.text">
|
||||
|
|
|
@ -24,7 +24,10 @@ const sizes: { [size: string]: number } = {
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-avatar',
|
||||
name: 'N8nAvatar',
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
props: {
|
||||
firstName: {
|
||||
type: String,
|
||||
|
@ -48,9 +51,6 @@ export default defineComponent({
|
|||
],
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
computed: {
|
||||
initials() {
|
||||
return (
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<span :class="['n8n-badge', $style[theme]]">
|
||||
<n8n-text :size="size" :bold="bold" :compact="true">
|
||||
<N8nText :size="size" :bold="bold" :compact="true">
|
||||
<slot></slot>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -12,6 +12,9 @@ import N8nText from '../N8nText';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
N8nText,
|
||||
},
|
||||
props: {
|
||||
theme: {
|
||||
type: String,
|
||||
|
@ -30,9 +33,6 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
N8nText,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
aria-live="polite"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<span :class="$style.icon" v-if="loading || icon">
|
||||
<n8n-spinner v-if="loading" :size="size" />
|
||||
<n8n-icon v-else-if="icon" :icon="icon" :size="size" />
|
||||
<span v-if="loading || icon" :class="$style.icon">
|
||||
<N8nSpinner v-if="loading" :size="size" />
|
||||
<N8nIcon v-else-if="icon" :icon="icon" :size="size" />
|
||||
</span>
|
||||
<span v-if="label || $slots.default">
|
||||
<slot>{{ label }}</slot>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div :class="classes" role="alert">
|
||||
<div :class="$style.messageSection">
|
||||
<div :class="$style.icon" v-if="!iconless">
|
||||
<n8n-icon :icon="getIcon" :size="getIconSize" />
|
||||
<div v-if="!iconless" :class="$style.icon">
|
||||
<N8nIcon :icon="getIcon" :size="getIconSize" />
|
||||
</div>
|
||||
<n8n-text size="small">
|
||||
<N8nText size="small">
|
||||
<slot />
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
|
@ -28,7 +28,7 @@ const CALLOUT_DEFAULT_ICONS: { [key: string]: string } = {
|
|||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-callout',
|
||||
name: 'N8nCallout',
|
||||
components: {
|
||||
N8nText,
|
||||
N8nIcon,
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div :class="classes" v-bind="$attrs">
|
||||
<div :class="$style.icon" v-if="$slots.prepend">
|
||||
<div v-if="$slots.prepend" :class="$style.icon">
|
||||
<slot name="prepend" />
|
||||
</div>
|
||||
<div :class="$style.content">
|
||||
<div :class="$style.header" v-if="$slots.header">
|
||||
<div v-if="$slots.header" :class="$style.header">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
<div :class="$style.body" v-if="$slots.default">
|
||||
<div v-if="$slots.default" :class="$style.body">
|
||||
<slot />
|
||||
</div>
|
||||
<div :class="$style.footer" v-if="$slots.footer">
|
||||
<div v-if="$slots.footer" :class="$style.footer">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,7 +24,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-card',
|
||||
name: 'N8nCard',
|
||||
inheritAttrs: true,
|
||||
props: {
|
||||
hoverable: {
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
<el-checkbox
|
||||
<ElCheckbox
|
||||
v-bind="$props"
|
||||
ref="checkbox"
|
||||
:class="['n8n-checkbox', $style.n8nCheckbox]"
|
||||
:disabled="disabled"
|
||||
:indeterminate="indeterminate"
|
||||
:modelValue="modelValue"
|
||||
:model-value="modelValue"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
>
|
||||
<slot></slot>
|
||||
<n8n-input-label
|
||||
<N8nInputLabel
|
||||
v-if="label"
|
||||
:label="label"
|
||||
:tooltipText="tooltipText"
|
||||
:tooltip-text="tooltipText"
|
||||
:bold="false"
|
||||
:size="labelSize"
|
||||
@click.prevent="onLabelClick"
|
||||
/>
|
||||
</el-checkbox>
|
||||
</ElCheckbox>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -26,7 +26,7 @@ import { ElCheckbox } from 'element-plus';
|
|||
import N8nInputLabel from '../N8nInputLabel';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-checkbox',
|
||||
name: 'N8nCheckbox',
|
||||
components: {
|
||||
ElCheckbox,
|
||||
N8nInputLabel,
|
||||
|
|
|
@ -64,21 +64,21 @@ const onActiveChange = (value: string) => {
|
|||
</script>
|
||||
<template>
|
||||
<span :class="['n8n-color-picker', $style.component]">
|
||||
<el-color-picker
|
||||
<ElColorPicker
|
||||
v-model="model"
|
||||
v-bind="colorPickerProps"
|
||||
@change="onChange"
|
||||
@active-change="onActiveChange"
|
||||
/>
|
||||
<n8n-input
|
||||
<N8nInput
|
||||
v-if="showInput"
|
||||
:class="$style.input"
|
||||
:disabled="props.disabled"
|
||||
:size="props.size"
|
||||
:modelValue="color"
|
||||
:model-value="color"
|
||||
:name="name"
|
||||
@update:modelValue="onInput"
|
||||
type="text"
|
||||
@update:modelValue="onInput"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -9,13 +9,12 @@ import N8nOption from '../N8nOption';
|
|||
import N8nPagination from '../N8nPagination';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-datatable',
|
||||
name: 'N8nDatatable',
|
||||
components: {
|
||||
N8nSelect,
|
||||
N8nOption,
|
||||
N8nPagination,
|
||||
},
|
||||
emits: ['update:currentPage', 'update:rowsPerPage'],
|
||||
props: {
|
||||
columns: {
|
||||
type: Array as PropType<DatatableColumn[]>,
|
||||
|
@ -38,6 +37,7 @@ export default defineComponent({
|
|||
default: 10,
|
||||
},
|
||||
},
|
||||
emits: ['update:currentPage', 'update:rowsPerPage'],
|
||||
setup(props, { emit }) {
|
||||
const { t } = useI18n();
|
||||
const rowsPerPageOptions = ref([10, 25, 50, 100]);
|
||||
|
@ -130,10 +130,10 @@ export default defineComponent({
|
|||
</thead>
|
||||
<tbody>
|
||||
<template v-for="row in visibleRows">
|
||||
<slot name="row" :columns="columns" :row="row" :getTdValue="getTdValue">
|
||||
<slot name="row" :columns="columns" :row="row" :get-td-value="getTdValue">
|
||||
<tr :key="row.id">
|
||||
<td v-for="column in columns" :key="column.id" :class="column.classes">
|
||||
<component v-if="column.render" :is="column.render" :row="row" :column="column" />
|
||||
<component :is="column.render" v-if="column.render" :row="row" :column="column" />
|
||||
<span v-else>{{ getTdValue(row, column) }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -143,33 +143,33 @@ export default defineComponent({
|
|||
</table>
|
||||
|
||||
<div :class="$style.pagination">
|
||||
<n8n-pagination
|
||||
<N8nPagination
|
||||
v-if="totalPages > 1"
|
||||
background
|
||||
:pager-count="5"
|
||||
:page-size="rowsPerPage"
|
||||
layout="prev, pager, next"
|
||||
:total="totalRows"
|
||||
:currentPage="currentPage"
|
||||
:current-page="currentPage"
|
||||
@update:currentPage="onUpdateCurrentPage"
|
||||
/>
|
||||
|
||||
<div :class="$style.pageSizeSelector">
|
||||
<n8n-select
|
||||
<N8nSelect
|
||||
size="mini"
|
||||
:modelValue="rowsPerPage"
|
||||
@update:modelValue="onRowsPerPageChange"
|
||||
:model-value="rowsPerPage"
|
||||
teleported
|
||||
@update:modelValue="onRowsPerPageChange"
|
||||
>
|
||||
<template #prepend>{{ t('datatable.pageSize') }}</template>
|
||||
<n8n-option
|
||||
<N8nOption
|
||||
v-for="size in rowsPerPageOptions"
|
||||
:key="size"
|
||||
:label="`${size}`"
|
||||
:value="size"
|
||||
/>
|
||||
<n8n-option :label="`All`" value="*"> </n8n-option>
|
||||
</n8n-select>
|
||||
<N8nOption :label="`All`" value="*"> </N8nOption>
|
||||
</N8nSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
<template>
|
||||
<div :class="['n8n-form-box', $style.container]">
|
||||
<div v-if="title" :class="$style.heading">
|
||||
<n8n-heading size="xlarge">
|
||||
<N8nHeading size="xlarge">
|
||||
{{ title }}
|
||||
</n8n-heading>
|
||||
</N8nHeading>
|
||||
</div>
|
||||
<div :class="$style.inputsContainer">
|
||||
<n8n-form-inputs
|
||||
<N8nFormInputs
|
||||
:inputs="inputs"
|
||||
:eventBus="formBus"
|
||||
:columnView="true"
|
||||
:event-bus="formBus"
|
||||
:column-view="true"
|
||||
@update="onUpdateModelValue"
|
||||
@submit="onSubmit"
|
||||
/>
|
||||
</div>
|
||||
<div :class="$style.buttonsContainer" v-if="secondaryButtonText || buttonText">
|
||||
<div v-if="secondaryButtonText || buttonText" :class="$style.buttonsContainer">
|
||||
<span v-if="secondaryButtonText" :class="$style.secondaryButtonContainer">
|
||||
<n8n-link size="medium" theme="text" @click="onSecondaryButtonClick">
|
||||
<N8nLink size="medium" theme="text" @click="onSecondaryButtonClick">
|
||||
{{ secondaryButtonText }}
|
||||
</n8n-link>
|
||||
</N8nLink>
|
||||
</span>
|
||||
<n8n-button
|
||||
<N8nButton
|
||||
v-if="buttonText"
|
||||
:label="buttonText"
|
||||
:loading="buttonLoading"
|
||||
|
@ -30,9 +30,9 @@
|
|||
/>
|
||||
</div>
|
||||
<div :class="$style.actionContainer">
|
||||
<n8n-link v-if="redirectText && redirectLink" :to="redirectLink">
|
||||
<N8nLink v-if="redirectText && redirectLink" :to="redirectLink">
|
||||
{{ redirectText }}
|
||||
</n8n-link>
|
||||
</N8nLink>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
@ -47,7 +47,7 @@ import N8nButton from '../N8nButton';
|
|||
import { createEventBus } from '../../utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-form-box',
|
||||
name: 'N8nFormBox',
|
||||
components: {
|
||||
N8nHeading,
|
||||
N8nFormInputs,
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
<template>
|
||||
<n8n-checkbox
|
||||
<N8nCheckbox
|
||||
v-if="type === 'checkbox'"
|
||||
v-bind="$props"
|
||||
ref="inputRef"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
@focus="onFocus"
|
||||
ref="inputRef"
|
||||
/>
|
||||
<n8n-input-label
|
||||
<N8nInputLabel
|
||||
v-else-if="type === 'toggle'"
|
||||
:inputName="name"
|
||||
:input-name="name"
|
||||
:label="label"
|
||||
:tooltipText="tooltipText"
|
||||
:tooltip-text="tooltipText"
|
||||
:required="required && showRequiredAsterisk"
|
||||
>
|
||||
<template #content>
|
||||
{{ tooltipText }}
|
||||
</template>
|
||||
<el-switch
|
||||
:modelValue="modelValue"
|
||||
<ElSwitch
|
||||
:model-value="modelValue"
|
||||
:active-color="activeColor"
|
||||
:inactive-color="inactiveColor"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
></el-switch>
|
||||
</n8n-input-label>
|
||||
<n8n-input-label
|
||||
></ElSwitch>
|
||||
</N8nInputLabel>
|
||||
<N8nInputLabel
|
||||
v-else
|
||||
:inputName="name"
|
||||
:input-name="name"
|
||||
:label="label"
|
||||
:tooltipText="tooltipText"
|
||||
:tooltip-text="tooltipText"
|
||||
:required="required && showRequiredAsterisk"
|
||||
>
|
||||
<div :class="showErrors ? $style.errorInput : ''" @keydown.stop @keydown.enter="onEnter">
|
||||
<slot v-if="hasDefaultSlot" />
|
||||
<n8n-select
|
||||
:class="{ [$style.multiSelectSmallTags]: tagSize === 'small' }"
|
||||
<N8nSelect
|
||||
v-else-if="type === 'select' || type === 'multi-select'"
|
||||
:modelValue="modelValue"
|
||||
:class="{ [$style.multiSelectSmallTags]: tagSize === 'small' }"
|
||||
:model-value="modelValue"
|
||||
:placeholder="placeholder"
|
||||
:multiple="type === 'multi-select'"
|
||||
ref="inputRef"
|
||||
:disabled="disabled"
|
||||
:name="name"
|
||||
:teleported="teleported"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
:name="name"
|
||||
:teleported="teleported"
|
||||
ref="inputRef"
|
||||
>
|
||||
<n8n-option
|
||||
<N8nOption
|
||||
v-for="option in options || []"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
|
@ -54,38 +54,38 @@
|
|||
:disabled="!!option.disabled"
|
||||
size="small"
|
||||
/>
|
||||
</n8n-select>
|
||||
<n8n-input
|
||||
</N8nSelect>
|
||||
<N8nInput
|
||||
v-else
|
||||
:name="name"
|
||||
ref="inputRef"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
:modelValue="modelValue"
|
||||
:model-value="modelValue"
|
||||
:maxlength="maxlength"
|
||||
:autocomplete="autocomplete"
|
||||
:disabled="disabled"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
@blur="onBlur"
|
||||
@focus="onFocus"
|
||||
ref="inputRef"
|
||||
/>
|
||||
</div>
|
||||
<div :class="$style.errors" v-if="showErrors">
|
||||
<div v-if="showErrors" :class="$style.errors">
|
||||
<span v-text="validationError" />
|
||||
<n8n-link
|
||||
v-if="documentationUrl && documentationText"
|
||||
:to="documentationUrl"
|
||||
:newWindow="true"
|
||||
:new-window="true"
|
||||
size="small"
|
||||
theme="danger"
|
||||
>
|
||||
{{ documentationText }}
|
||||
</n8n-link>
|
||||
</div>
|
||||
<div :class="$style.infoText" v-else-if="infoText">
|
||||
<div v-else-if="infoText" :class="$style.infoText">
|
||||
<span size="small" v-text="infoText" />
|
||||
</div>
|
||||
</n8n-input-label>
|
||||
</N8nInputLabel>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
:class="{ [`mt-${verticalSpacing}`]: verticalSpacing && index > 0 }"
|
||||
>
|
||||
<n8n-text
|
||||
color="text-base"
|
||||
v-if="input.properties.type === 'info'"
|
||||
color="text-base"
|
||||
tag="div"
|
||||
:size="input.properties.labelSize"
|
||||
:align="input.properties.labelAlignment"
|
||||
|
@ -17,16 +17,16 @@
|
|||
>
|
||||
{{ input.properties.label }}
|
||||
</n8n-text>
|
||||
<n8n-form-input
|
||||
<N8nFormInput
|
||||
v-else
|
||||
v-bind="input.properties"
|
||||
:name="input.name"
|
||||
:label="input.properties.label || ''"
|
||||
:modelValue="values[input.name]"
|
||||
:model-value="values[input.name]"
|
||||
:data-test-id="input.name"
|
||||
:showValidationWarnings="showValidationWarnings"
|
||||
:show-validation-warnings="showValidationWarnings"
|
||||
:teleported="teleported"
|
||||
:tagSize="tagSize"
|
||||
:tag-size="tagSize"
|
||||
@update:modelValue="(value) => onUpdateModelValue(input.name, value)"
|
||||
@validate="(value) => onValidate(input.name, value)"
|
||||
@enter="onSubmit"
|
||||
|
@ -47,7 +47,7 @@ import type { EventBus } from '../../utils';
|
|||
import { createEventBus } from '../../utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-form-inputs',
|
||||
name: 'N8nFormInputs',
|
||||
components: {
|
||||
N8nFormInput,
|
||||
ResizeObserver,
|
||||
|
@ -87,20 +87,6 @@ export default defineComponent({
|
|||
validity: {} as { [key: string]: boolean },
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.inputs.forEach((input) => {
|
||||
if (input.hasOwnProperty('initialValue')) {
|
||||
this.values = {
|
||||
...this.values,
|
||||
[input.name]: input.initialValue,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
if (this.eventBus) {
|
||||
this.eventBus.on('submit', () => this.onSubmit());
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredInputs(): IFormInput[] {
|
||||
return this.inputs.filter((input) =>
|
||||
|
@ -117,6 +103,25 @@ export default defineComponent({
|
|||
return true;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
isReadyToSubmit(ready: boolean) {
|
||||
this.$emit('ready', ready);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.inputs.forEach((input) => {
|
||||
if (input.hasOwnProperty('initialValue')) {
|
||||
this.values = {
|
||||
...this.values,
|
||||
[input.name]: input.initialValue,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
if (this.eventBus) {
|
||||
this.eventBus.on('submit', () => this.onSubmit());
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onUpdateModelValue(name: string, value: unknown) {
|
||||
this.values = {
|
||||
|
@ -146,11 +151,6 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
isReadyToSubmit(ready: boolean) {
|
||||
this.$emit('ready', ready);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-heading',
|
||||
name: 'N8nHeading',
|
||||
props: {
|
||||
tag: {
|
||||
type: String,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<n8n-text :size="size" :color="color" :compact="true" class="n8n-icon" v-bind="$attrs">
|
||||
<font-awesome-icon :icon="icon" :spin="spin" :class="$style[size]" />
|
||||
</n8n-text>
|
||||
<N8nText :size="size" :color="color" :compact="true" class="n8n-icon" v-bind="$attrs">
|
||||
<FontAwesomeIcon :icon="icon" :spin="spin" :class="$style[size]" />
|
||||
</N8nText>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -11,7 +11,7 @@ import N8nText from '../N8nText';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-icon',
|
||||
name: 'N8nIcon',
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
N8nText,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<n8n-button square v-bind="{ ...$attrs, ...$props }" />
|
||||
<N8nButton square v-bind="{ ...$attrs, ...$props }" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -8,7 +8,7 @@ import N8nButton from '../N8nButton';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-icon-button',
|
||||
name: 'N8nIconButton',
|
||||
components: {
|
||||
N8nButton,
|
||||
},
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<div :class="['accordion', $style.container]">
|
||||
<div :class="{ [$style.header]: true, [$style.expanded]: expanded }" @click="toggle">
|
||||
<n8n-icon
|
||||
<N8nIcon
|
||||
v-if="headerIcon"
|
||||
:icon="headerIcon.icon"
|
||||
:color="headerIcon.color"
|
||||
size="small"
|
||||
class="mr-2xs"
|
||||
/>
|
||||
<n8n-text :class="$style.headerText" color="text-base" size="small" align="left" bold>{{
|
||||
<N8nText :class="$style.headerText" color="text-base" size="small" align="left" bold>{{
|
||||
title
|
||||
}}</n8n-text>
|
||||
<n8n-icon :icon="expanded ? 'chevron-up' : 'chevron-down'" bold />
|
||||
}}</N8nText>
|
||||
<N8nIcon :icon="expanded ? 'chevron-up' : 'chevron-down'" bold />
|
||||
</div>
|
||||
<div
|
||||
v-if="expanded"
|
||||
|
@ -23,16 +23,16 @@
|
|||
<div v-for="item in items" :key="item.id" :class="$style.accordionItem">
|
||||
<n8n-tooltip :disabled="!item.tooltip">
|
||||
<template #content>
|
||||
<div v-html="item.tooltip" @click="onTooltipClick(item.id, $event)"></div>
|
||||
<div @click="onTooltipClick(item.id, $event)" v-html="item.tooltip"></div>
|
||||
</template>
|
||||
<n8n-icon :icon="item.icon" :color="item.iconColor" size="small" class="mr-2xs" />
|
||||
<N8nIcon :icon="item.icon" :color="item.iconColor" size="small" class="mr-2xs" />
|
||||
</n8n-tooltip>
|
||||
<n8n-text size="small" color="text-base">{{ item.label }}</n8n-text>
|
||||
<N8nText size="small" color="text-base">{{ item.label }}</N8nText>
|
||||
</div>
|
||||
</div>
|
||||
<n8n-text color="text-base" size="small" align="left">
|
||||
<N8nText color="text-base" size="small" align="left">
|
||||
<span v-html="description"></span>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
<slot name="customContent"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,7 +55,7 @@ export interface IAccordionItem {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-info-accordion',
|
||||
name: 'N8nInfoAccordion',
|
||||
components: {
|
||||
N8nText,
|
||||
N8nIcon,
|
||||
|
@ -84,17 +84,17 @@ export default defineComponent({
|
|||
default: () => createEventBus(),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.eventBus.on('expand', () => {
|
||||
this.expanded = true;
|
||||
});
|
||||
this.expanded = this.initiallyExpanded;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.expanded = !this.expanded;
|
||||
|
|
|
@ -8,23 +8,23 @@
|
|||
[$style.bold]: bold,
|
||||
}"
|
||||
>
|
||||
<n8n-tooltip
|
||||
<N8nTooltip
|
||||
v-if="type === 'tooltip'"
|
||||
:placement="tooltipPlacement"
|
||||
:popperClass="$style.tooltipPopper"
|
||||
:popper-class="$style.tooltipPopper"
|
||||
:disabled="type !== 'tooltip'"
|
||||
>
|
||||
<span :class="$style.iconText" :style="{ color: iconData.color }">
|
||||
<n8n-icon :icon="iconData.icon" />
|
||||
<N8nIcon :icon="iconData.icon" />
|
||||
</span>
|
||||
<template #content>
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
</n8n-tooltip>
|
||||
<span :class="$style.iconText" v-else>
|
||||
<n8n-icon :icon="iconData.icon" />
|
||||
</N8nTooltip>
|
||||
<span v-else :class="$style.iconText">
|
||||
<N8nIcon :icon="iconData.icon" />
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
|
@ -39,7 +39,7 @@ import N8nTooltip from '../N8nTooltip';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-info-tip',
|
||||
name: 'N8nInfoTip',
|
||||
components: {
|
||||
N8nIcon,
|
||||
N8nTooltip,
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<template>
|
||||
<el-input
|
||||
<ElInput
|
||||
ref="innerInput"
|
||||
:size="computedSize"
|
||||
:class="['n8n-input', ...classes]"
|
||||
:autoComplete="autocomplete"
|
||||
:autocomplete="autocomplete"
|
||||
:name="name"
|
||||
ref="innerInput"
|
||||
v-bind="{ ...$props, ...$attrs }"
|
||||
>
|
||||
<template #prepend v-if="$slots.prepend">
|
||||
<template v-if="$slots.prepend" #prepend>
|
||||
<slot name="prepend" />
|
||||
</template>
|
||||
<template #append v-if="$slots.append">
|
||||
<template v-if="$slots.append" #append>
|
||||
<slot name="append" />
|
||||
</template>
|
||||
<template #prefix v-if="$slots.prefix">
|
||||
<template v-if="$slots.prefix" #prefix>
|
||||
<slot name="prefix" />
|
||||
</template>
|
||||
<template #suffix v-if="$slots.suffix">
|
||||
<template v-if="$slots.suffix" #suffix>
|
||||
<slot name="suffix" />
|
||||
</template>
|
||||
</el-input>
|
||||
</ElInput>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -31,7 +31,7 @@ import { uid } from '../../utils';
|
|||
type InputRef = InstanceType<typeof ElInput>;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-input',
|
||||
name: 'N8nInput',
|
||||
components: {
|
||||
ElInput,
|
||||
},
|
||||
|
|
|
@ -7,7 +7,7 @@ exports[`N8nInput > should render correctly 1`] = `
|
|||
<!--v-if-->
|
||||
<div class="el-input__wrapper">
|
||||
<!-- prefix slot -->
|
||||
<!--v-if--><input class="el-input__inner" autocomplete="off" name="input" rows="2" maxlength="Infinity" title="" type="text" tabindex="0" placeholder=""><!-- suffix slot -->
|
||||
<!--v-if--><input class="el-input__inner" name="input" rows="2" maxlength="Infinity" title="" type="text" autocomplete="off" tabindex="0" placeholder=""><!-- suffix slot -->
|
||||
<!--v-if-->
|
||||
</div><!-- append slot -->
|
||||
<!--v-if-->
|
||||
|
|
|
@ -12,22 +12,22 @@
|
|||
[$style.overflow]: !!$slots.options,
|
||||
}"
|
||||
>
|
||||
<div :class="$style.title" v-if="label">
|
||||
<n8n-text :bold="bold" :size="size" :compact="compact" :color="color">
|
||||
<div v-if="label" :class="$style.title">
|
||||
<N8nText :bold="bold" :size="size" :compact="compact" :color="color">
|
||||
{{ label }}
|
||||
<n8n-text color="primary" :bold="bold" :size="size" v-if="required">*</n8n-text>
|
||||
</n8n-text>
|
||||
<N8nText v-if="required" color="primary" :bold="bold" :size="size">*</N8nText>
|
||||
</N8nText>
|
||||
</div>
|
||||
<span
|
||||
:class="[$style.infoIcon, showTooltip ? $style.visible : $style.hidden]"
|
||||
v-if="tooltipText && label"
|
||||
:class="[$style.infoIcon, showTooltip ? $style.visible : $style.hidden]"
|
||||
>
|
||||
<n8n-tooltip placement="top" :popper-class="$style.tooltipPopper">
|
||||
<n8n-icon icon="question-circle" size="small" />
|
||||
<N8nTooltip placement="top" :popper-class="$style.tooltipPopper">
|
||||
<N8nIcon icon="question-circle" size="small" />
|
||||
<template #content>
|
||||
<div v-html="addTargetBlank(tooltipText)" />
|
||||
</template>
|
||||
</n8n-tooltip>
|
||||
</N8nTooltip>
|
||||
</span>
|
||||
<div
|
||||
v-if="$slots.options && label"
|
||||
|
@ -55,7 +55,7 @@ import { addTargetBlank } from '../utils/helpers';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-input-label',
|
||||
name: 'N8nInputLabel',
|
||||
components: {
|
||||
N8nText,
|
||||
N8nIcon,
|
||||
|
|
|
@ -4,15 +4,15 @@ import { defineComponent } from 'vue';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'N8nInputNumber',
|
||||
props: {
|
||||
...ElInputNumber.props,
|
||||
},
|
||||
components: {
|
||||
ElInputNumber,
|
||||
},
|
||||
props: {
|
||||
...ElInputNumber.props,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-input-number v-bind="{ ...$props, ...$attrs }" />
|
||||
<ElInputNumber v-bind="{ ...$props, ...$attrs }" />
|
||||
</template>
|
||||
|
|
|
@ -31,7 +31,7 @@ const keys = computed(() => {
|
|||
|
||||
<template>
|
||||
<div :class="$style.shortcut">
|
||||
<div v-for="key of keys" :class="$style.keyWrapper" :key="key">
|
||||
<div v-for="key of keys" :key="key" :class="$style.keyWrapper">
|
||||
<div :class="$style.key">{{ key }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<n8n-route :to="to" :newWindow="newWindow" v-bind="$attrs" class="n8n-link">
|
||||
<N8nRoute :to="to" :new-window="newWindow" v-bind="$attrs" class="n8n-link">
|
||||
<span :class="$style[`${underline ? `${theme}-underline` : theme}`]">
|
||||
<n8n-text :size="size" :bold="bold">
|
||||
<N8nText :size="size" :bold="bold">
|
||||
<slot></slot>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
</span>
|
||||
</n8n-route>
|
||||
</N8nRoute>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -14,7 +14,11 @@ import N8nText from '../N8nText';
|
|||
import N8nRoute from '../N8nRoute';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-link',
|
||||
name: 'N8nLink',
|
||||
components: {
|
||||
N8nText,
|
||||
N8nRoute,
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
type: String,
|
||||
|
@ -41,10 +45,6 @@ export default defineComponent({
|
|||
['primary', 'danger', 'text', 'secondary'].includes(value),
|
||||
},
|
||||
},
|
||||
components: {
|
||||
N8nText,
|
||||
N8nRoute,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<el-skeleton
|
||||
<ElSkeleton
|
||||
:loading="loading"
|
||||
:animated="animated"
|
||||
:class="['n8n-loading', `n8n-loading-${variant}`]"
|
||||
|
@ -13,7 +13,7 @@
|
|||
[$style.h1Last]: item === rows && rows > 1 && shrinkLast,
|
||||
}"
|
||||
>
|
||||
<el-skeleton-item :variant="variant" />
|
||||
<ElSkeletonItem :variant="variant" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="variant === 'p'">
|
||||
|
@ -24,15 +24,15 @@
|
|||
[$style.pLast]: item === rows && rows > 1 && shrinkLast,
|
||||
}"
|
||||
>
|
||||
<el-skeleton-item :variant="variant" />
|
||||
<ElSkeletonItem :variant="variant" />
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.custom" v-else-if="variant === 'custom'">
|
||||
<el-skeleton-item />
|
||||
<div v-else-if="variant === 'custom'" :class="$style.custom">
|
||||
<ElSkeletonItem />
|
||||
</div>
|
||||
<el-skeleton-item v-else :variant="variant" />
|
||||
<ElSkeletonItem v-else :variant="variant" />
|
||||
</template>
|
||||
</el-skeleton>
|
||||
</ElSkeleton>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -40,7 +40,7 @@ import { ElSkeleton, ElSkeletonItem } from 'element-plus';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-loading',
|
||||
name: 'N8nLoading',
|
||||
components: {
|
||||
ElSkeleton,
|
||||
ElSkeletonItem,
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
v-if="!loading"
|
||||
ref="editor"
|
||||
:class="$style[theme]"
|
||||
v-html="htmlContent"
|
||||
@click="onClick"
|
||||
v-html="htmlContent"
|
||||
/>
|
||||
<div v-else :class="$style.markdown">
|
||||
<div v-for="(block, index) in loadingBlocks" :key="index">
|
||||
<n8n-loading :loading="loading" :rows="loadingRows" animated variant="p" />
|
||||
<N8nLoading :loading="loading" :rows="loadingRows" animated variant="p" />
|
||||
<div :class="$style.spacer" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -62,10 +62,10 @@ export interface Options {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'N8nMarkdown',
|
||||
components: {
|
||||
N8nLoading,
|
||||
},
|
||||
name: 'n8n-markdown',
|
||||
props: {
|
||||
content: {
|
||||
type: String,
|
||||
|
|
|
@ -15,33 +15,33 @@
|
|||
<div v-if="$slots.menuPrefix" :class="$style.menuPrefix">
|
||||
<slot name="menuPrefix"></slot>
|
||||
</div>
|
||||
<el-menu :defaultActive="defaultActive" :collapse="collapsed">
|
||||
<n8n-menu-item
|
||||
<ElMenu :default-active="defaultActive" :collapse="collapsed">
|
||||
<N8nMenuItem
|
||||
v-for="item in upperMenuItems"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
:compact="collapsed"
|
||||
:tooltipDelay="tooltipDelay"
|
||||
:tooltip-delay="tooltipDelay"
|
||||
:mode="mode"
|
||||
:activeTab="activeTab"
|
||||
:active-tab="activeTab"
|
||||
:handle-select="onSelect"
|
||||
/>
|
||||
</el-menu>
|
||||
</ElMenu>
|
||||
</div>
|
||||
<div :class="[$style.lowerContent, 'pb-2xs']">
|
||||
<slot name="beforeLowerMenu"></slot>
|
||||
<el-menu :defaultActive="defaultActive" :collapse="collapsed">
|
||||
<n8n-menu-item
|
||||
<ElMenu :default-active="defaultActive" :collapse="collapsed">
|
||||
<N8nMenuItem
|
||||
v-for="item in lowerMenuItems"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
:compact="collapsed"
|
||||
:tooltipDelay="tooltipDelay"
|
||||
:tooltip-delay="tooltipDelay"
|
||||
:mode="mode"
|
||||
:activeTab="activeTab"
|
||||
:active-tab="activeTab"
|
||||
:handle-select="onSelect"
|
||||
/>
|
||||
</el-menu>
|
||||
</ElMenu>
|
||||
<div v-if="$slots.menuSuffix" :class="$style.menuSuffix">
|
||||
<slot name="menuSuffix"></slot>
|
||||
</div>
|
||||
|
@ -61,16 +61,11 @@ import { defineComponent } from 'vue';
|
|||
import type { IMenuItem, RouteObject } from '../../types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-menu',
|
||||
name: 'N8nMenu',
|
||||
components: {
|
||||
ElMenu,
|
||||
N8nMenuItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: this.value,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
|
@ -106,22 +101,10 @@ export default defineComponent({
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.mode === 'router') {
|
||||
const found = this.items.find((item) => {
|
||||
return (
|
||||
(Array.isArray(item.activateOnRouteNames) &&
|
||||
item.activateOnRouteNames.includes(this.currentRoute.name || '')) ||
|
||||
(Array.isArray(item.activateOnRoutePaths) &&
|
||||
item.activateOnRoutePaths.includes(this.currentRoute.path))
|
||||
);
|
||||
});
|
||||
this.activeTab = found ? found.id : '';
|
||||
} else {
|
||||
this.activeTab = this.items.length > 0 ? this.items[0].id : '';
|
||||
}
|
||||
|
||||
this.$emit('update:modelValue', this.activeTab);
|
||||
data() {
|
||||
return {
|
||||
activeTab: this.value,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
upperMenuItems(): IMenuItem[] {
|
||||
|
@ -143,6 +126,23 @@ export default defineComponent({
|
|||
);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.mode === 'router') {
|
||||
const found = this.items.find((item) => {
|
||||
return (
|
||||
(Array.isArray(item.activateOnRouteNames) &&
|
||||
item.activateOnRouteNames.includes(this.currentRoute.name || '')) ||
|
||||
(Array.isArray(item.activateOnRoutePaths) &&
|
||||
item.activateOnRoutePaths.includes(this.currentRoute.path))
|
||||
);
|
||||
});
|
||||
this.activeTab = found ? found.id : '';
|
||||
} else {
|
||||
this.activeTab = this.items.length > 0 ? this.items[0].id : '';
|
||||
}
|
||||
|
||||
this.$emit('update:modelValue', this.activeTab);
|
||||
},
|
||||
methods: {
|
||||
onSelect(item: IMenuItem): void {
|
||||
if (item && item.type === 'link' && item.properties) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="['n8n-menu-item', $style.item]">
|
||||
<el-sub-menu
|
||||
<ElSubMenu
|
||||
v-if="item.children?.length"
|
||||
:id="item.id"
|
||||
:class="{
|
||||
|
@ -13,7 +13,7 @@
|
|||
:popper-class="submenuPopperClass"
|
||||
>
|
||||
<template #title>
|
||||
<n8n-icon
|
||||
<N8nIcon
|
||||
v-if="item.icon"
|
||||
:class="$style.icon"
|
||||
:icon="item.icon"
|
||||
|
@ -26,21 +26,21 @@
|
|||
:key="child.id"
|
||||
:item="child"
|
||||
:compact="false"
|
||||
:tooltipDelay="tooltipDelay"
|
||||
:popperClass="popperClass"
|
||||
:tooltip-delay="tooltipDelay"
|
||||
:popper-class="popperClass"
|
||||
:mode="mode"
|
||||
:activeTab="activeTab"
|
||||
:active-tab="activeTab"
|
||||
:handle-select="handleSelect"
|
||||
/>
|
||||
</el-sub-menu>
|
||||
<n8n-tooltip
|
||||
</ElSubMenu>
|
||||
<N8nTooltip
|
||||
v-else
|
||||
placement="right"
|
||||
:content="item.label"
|
||||
:disabled="!compact"
|
||||
:show-after="tooltipDelay"
|
||||
>
|
||||
<el-menu-item
|
||||
<ElMenuItem
|
||||
:id="item.id"
|
||||
:class="{
|
||||
[$style.menuItem]: true,
|
||||
|
@ -53,14 +53,14 @@
|
|||
:index="item.id"
|
||||
@click="handleSelect(item)"
|
||||
>
|
||||
<n8n-icon
|
||||
<N8nIcon
|
||||
v-if="item.icon"
|
||||
:class="$style.icon"
|
||||
:icon="item.icon"
|
||||
:size="item.customIconSize || 'large'"
|
||||
/>
|
||||
<span :class="$style.label">{{ item.label }}</span>
|
||||
<n8n-tooltip
|
||||
<N8nTooltip
|
||||
v-if="item.secondaryIcon"
|
||||
:class="$style.secondaryIcon"
|
||||
:placement="item.secondaryIcon?.tooltip?.placement || 'right'"
|
||||
|
@ -68,10 +68,10 @@
|
|||
:disabled="compact || !item.secondaryIcon?.tooltip?.content"
|
||||
:show-after="tooltipDelay"
|
||||
>
|
||||
<n8n-icon :icon="item.secondaryIcon.name" :size="item.secondaryIcon.size || 'small'" />
|
||||
</n8n-tooltip>
|
||||
</el-menu-item>
|
||||
</n8n-tooltip>
|
||||
<N8nIcon :icon="item.secondaryIcon.name" :size="item.secondaryIcon.size || 'small'" />
|
||||
</N8nTooltip>
|
||||
</ElMenuItem>
|
||||
</N8nTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -84,7 +84,7 @@ import { defineComponent } from 'vue';
|
|||
import type { IMenuItem, RouteObject } from '../../types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-menu-item',
|
||||
name: 'N8nMenuItem',
|
||||
components: {
|
||||
ElSubMenu,
|
||||
ElMenuItem,
|
||||
|
|
|
@ -36,18 +36,18 @@ const i18n = useI18n();
|
|||
</div>
|
||||
<div>
|
||||
<div :class="$style.details">
|
||||
<span :class="$style.name" v-text="title" data-test-id="node-creator-item-name" />
|
||||
<el-tag v-if="tag" :class="$style.tag" size="small" round type="success">
|
||||
<span :class="$style.name" data-test-id="node-creator-item-name" v-text="title" />
|
||||
<ElTag v-if="tag" :class="$style.tag" size="small" round type="success">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<font-awesome-icon
|
||||
icon="bolt"
|
||||
</ElTag>
|
||||
<FontAwesomeIcon
|
||||
v-if="isTrigger"
|
||||
icon="bolt"
|
||||
size="xs"
|
||||
:title="i18n.baseText('nodeCreator.nodeItem.triggerIconTitle')"
|
||||
:class="$style.triggerIcon"
|
||||
/>
|
||||
<n8n-tooltip
|
||||
<N8nTooltip
|
||||
v-if="!!$slots.tooltip"
|
||||
placement="top"
|
||||
data-test-id="node-creator-item-tooltip"
|
||||
|
@ -56,7 +56,7 @@ const i18n = useI18n();
|
|||
<slot name="tooltip" />
|
||||
</template>
|
||||
<n8n-icon :class="$style.tooltipIcon" icon="cube" />
|
||||
</n8n-tooltip>
|
||||
</N8nTooltip>
|
||||
</div>
|
||||
<p
|
||||
v-if="description"
|
||||
|
@ -66,8 +66,8 @@ const i18n = useI18n();
|
|||
/>
|
||||
</div>
|
||||
<slot name="dragContent" />
|
||||
<button :class="$style.panelIcon" v-if="showActionArrow">
|
||||
<font-awesome-icon :class="$style.panelArrow" icon="arrow-right" />
|
||||
<button v-if="showActionArrow" :class="$style.panelIcon">
|
||||
<FontAwesomeIcon :class="$style.panelArrow" icon="arrow-right" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -9,20 +9,20 @@
|
|||
:style="iconStyleData"
|
||||
>
|
||||
<!-- ElementUI tooltip is prone to memory-leaking so we only render it if we really need it -->
|
||||
<n8n-tooltip :placement="tooltipPosition" :disabled="!showTooltip" v-if="showTooltip">
|
||||
<N8nTooltip v-if="showTooltip" :placement="tooltipPosition" :disabled="!showTooltip">
|
||||
<template #content>{{ nodeTypeName }}</template>
|
||||
<div v-if="type !== 'unknown'" :class="$style.icon">
|
||||
<img v-if="type === 'file'" :src="src" :class="$style.nodeIconImage" />
|
||||
<font-awesome-icon v-else :icon="name" :class="$style.iconFa" :style="fontStyleData" />
|
||||
<FontAwesomeIcon v-else :icon="name" :class="$style.iconFa" :style="fontStyleData" />
|
||||
</div>
|
||||
<div v-else :class="$style.nodeIconPlaceholder">
|
||||
{{ nodeTypeName ? nodeTypeName.charAt(0) : '?' }}
|
||||
</div>
|
||||
</n8n-tooltip>
|
||||
</N8nTooltip>
|
||||
<template v-else>
|
||||
<div v-if="type !== 'unknown'" :class="$style.icon">
|
||||
<img v-if="type === 'file'" :src="src" :class="$style.nodeIconImage" />
|
||||
<font-awesome-icon v-else :icon="name" :style="fontStyleData" />
|
||||
<FontAwesomeIcon v-else :icon="name" :style="fontStyleData" />
|
||||
<div v-if="badge" :class="$style.badge" :style="badgeStyleData">
|
||||
<n8n-node-icon :type="badge.type" :src="badge.src" :size="badgeSize"></n8n-node-icon>
|
||||
</div>
|
||||
|
@ -41,7 +41,7 @@ import { defineComponent, type PropType } from 'vue';
|
|||
import N8nTooltip from '../N8nTooltip';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-node-icon',
|
||||
name: 'N8nNodeIcon',
|
||||
components: {
|
||||
N8nTooltip,
|
||||
FontAwesomeIcon,
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div :id="id" :class="classes" role="alert" @click="onClick">
|
||||
<div class="notice-content">
|
||||
<n8n-text size="small" :compact="true">
|
||||
<N8nText size="small" :compact="true">
|
||||
<slot>
|
||||
<span
|
||||
:class="showFullContent ? $style['expanded'] : $style['truncated']"
|
||||
:id="`${id}-content`"
|
||||
:class="showFullContent ? $style['expanded'] : $style['truncated']"
|
||||
role="region"
|
||||
v-html="sanitizeHtml(showFullContent ? fullContent : content)"
|
||||
/>
|
||||
</slot>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -23,8 +23,11 @@ import Locale from '../../mixins/locale';
|
|||
import { uid } from '../../utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-notice',
|
||||
name: 'N8nNotice',
|
||||
directives: {},
|
||||
components: {
|
||||
N8nText,
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
id: {
|
||||
|
@ -44,9 +47,6 @@ export default defineComponent({
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
N8nText,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showFullContent: false,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`components > N8nNotice > props > content > should render HTML 1`] = `
|
||||
"<div id="notice" class="notice notice warning" role="alert">
|
||||
<div class="notice-content"><span class="n8n-text compact size-small regular"><span class="truncated" id="notice-content" role="region"><strong>Hello world!</strong> This is a notice.</span></span></div>
|
||||
<div class="notice-content"><span class="n8n-text compact size-small regular"><span id="notice-content" class="truncated" role="region"><strong>Hello world!</strong> This is a notice.</span></span></div>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
|
|
|
@ -3,15 +3,15 @@ import { ElOption } from 'element-plus';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
...ElOption.props,
|
||||
},
|
||||
components: {
|
||||
ElOption,
|
||||
},
|
||||
props: {
|
||||
...ElOption.props,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-option v-bind="{ ...$props, ...$attrs }"><slot /></el-option>
|
||||
<ElOption v-bind="{ ...$props, ...$attrs }"><slot /></ElOption>
|
||||
</template>
|
||||
|
|
|
@ -3,17 +3,17 @@ import { defineComponent } from 'vue';
|
|||
import { ElPagination } from 'element-plus';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
...ElPagination.props,
|
||||
},
|
||||
components: {
|
||||
ElPagination,
|
||||
},
|
||||
props: {
|
||||
...ElPagination.props,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-pagination
|
||||
<ElPagination
|
||||
class="is-background"
|
||||
layout="prev, pager, next"
|
||||
v-bind="{ ...$props, ...$attrs }"
|
||||
|
|
|
@ -4,22 +4,22 @@ import { defineComponent } from 'vue';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'N8nPopover',
|
||||
props: {
|
||||
...ElPopover.props,
|
||||
},
|
||||
components: {
|
||||
ElPopover,
|
||||
},
|
||||
props: {
|
||||
...ElPopover.props,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span>
|
||||
<el-popover v-bind="{ ...$props, ...$attrs }">
|
||||
<ElPopover v-bind="{ ...$props, ...$attrs }">
|
||||
<template #reference>
|
||||
<slot name="reference" />
|
||||
</template>
|
||||
<slot />
|
||||
</el-popover>
|
||||
</ElPopover>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-pulse',
|
||||
name: 'N8nPulse',
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-radio-button',
|
||||
name: 'N8nRadioButton',
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
|
|
|
@ -28,7 +28,10 @@ export interface RadioOption {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-radio-buttons',
|
||||
name: 'N8nRadioButtons',
|
||||
components: {
|
||||
RadioButton,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
|
@ -44,9 +47,6 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
RadioButton,
|
||||
},
|
||||
methods: {
|
||||
onClick(option: { label: string; value: string; disabled?: boolean }) {
|
||||
if (this.disabled || option.disabled) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import type { PropType, ComponentPublicInstance } from 'vue';
|
|||
import { computed, defineComponent, onMounted, onBeforeMount, ref, nextTick, watch } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-recycle-scroller',
|
||||
name: 'N8nRecycleScroller',
|
||||
props: {
|
||||
itemSize: {
|
||||
type: Number,
|
||||
|
@ -223,16 +223,16 @@ export default defineComponent({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="recycle-scroller-wrapper" ref="wrapperRef">
|
||||
<div class="recycle-scroller" :style="scrollerStyles" ref="scrollerRef">
|
||||
<div class="recycle-scroller-items-wrapper" :style="itemsStyles" ref="itemsRef">
|
||||
<div ref="wrapperRef" class="recycle-scroller-wrapper">
|
||||
<div ref="scrollerRef" class="recycle-scroller" :style="scrollerStyles">
|
||||
<div ref="itemsRef" class="recycle-scroller-items-wrapper" :style="itemsStyles">
|
||||
<div
|
||||
v-for="item in itemsVisible"
|
||||
:key="item[itemKey]"
|
||||
class="recycle-scroller-item"
|
||||
:ref="(element) => (itemRefs[item[itemKey]] = element)"
|
||||
class="recycle-scroller-item"
|
||||
>
|
||||
<slot :item="item" :updateItemSize="onUpdateItemSize" />
|
||||
<slot :item="item" :update-item-size="onUpdateItemSize" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -47,7 +47,7 @@ const directionsCursorMaps: { [key: string]: string } = {
|
|||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-resize',
|
||||
name: 'N8nResize',
|
||||
props: {
|
||||
isResizingEnabled: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-route',
|
||||
name: 'N8nRoute',
|
||||
props: {
|
||||
to: {
|
||||
type: String || Object,
|
||||
|
|
|
@ -9,22 +9,22 @@
|
|||
<div v-if="$slots.prepend" :class="$style.prepend">
|
||||
<slot name="prepend" />
|
||||
</div>
|
||||
<el-select
|
||||
<ElSelect
|
||||
v-bind="{ ...$props, ...listeners }"
|
||||
:modelValue="modelValue"
|
||||
ref="innerSelect"
|
||||
:model-value="modelValue"
|
||||
:size="computedSize"
|
||||
:class="$style[classes]"
|
||||
:popper-class="popperClass"
|
||||
ref="innerSelect"
|
||||
>
|
||||
<template #prefix v-if="$slots.prefix">
|
||||
<template v-if="$slots.prefix" #prefix>
|
||||
<slot name="prefix" />
|
||||
</template>
|
||||
<template #suffix v-if="$slots.suffix">
|
||||
<template v-if="$slots.suffix" #suffix>
|
||||
<slot name="suffix" />
|
||||
</template>
|
||||
<slot></slot>
|
||||
</el-select>
|
||||
</ElSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -41,7 +41,7 @@ export interface IProps {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-select',
|
||||
name: 'N8nSelect',
|
||||
components: {
|
||||
ElSelect,
|
||||
},
|
||||
|
|
|
@ -26,11 +26,6 @@ describe('components', () => {
|
|||
|
||||
it('should select an option', async () => {
|
||||
const n8nSelectTestComponent = defineComponent({
|
||||
template: `
|
||||
<n8n-select v-model="selected">
|
||||
<n8n-option v-for="o in options" :key="o" :value="o" :label="o" />
|
||||
</n8n-select>
|
||||
`,
|
||||
setup() {
|
||||
const options = ref(['1', '2', '3']);
|
||||
const selected = ref('');
|
||||
|
@ -40,6 +35,11 @@ describe('components', () => {
|
|||
selected,
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<n8n-select v-model="selected">
|
||||
<n8n-option v-for="o in options" :key="o" :value="o" :label="o" />
|
||||
</n8n-select>
|
||||
`,
|
||||
});
|
||||
|
||||
const { container } = render(n8nSelectTestComponent, {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<n8n-icon v-else icon="spinner" :size="size" spin />
|
||||
<N8nIcon v-else icon="spinner" :size="size" spin />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -16,7 +16,7 @@ import N8nIcon from '../N8nIcon';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-spinner',
|
||||
name: 'N8nSpinner',
|
||||
components: {
|
||||
N8nIcon,
|
||||
},
|
||||
|
|
|
@ -9,51 +9,51 @@
|
|||
:style="styles"
|
||||
@keydown.prevent
|
||||
>
|
||||
<n8n-resize-wrapper
|
||||
:isResizingEnabled="!readOnly"
|
||||
<N8nResizeWrapper
|
||||
:is-resizing-enabled="!readOnly"
|
||||
:height="height"
|
||||
:width="width"
|
||||
:minHeight="minHeight"
|
||||
:minWidth="minWidth"
|
||||
:min-height="minHeight"
|
||||
:min-width="minWidth"
|
||||
:scale="scale"
|
||||
:gridSize="gridSize"
|
||||
:grid-size="gridSize"
|
||||
@resizeend="onResizeEnd"
|
||||
@resize="onResize"
|
||||
@resizestart="onResizeStart"
|
||||
>
|
||||
<div v-show="!editMode" :class="$style.wrapper" @dblclick.stop="onDoubleClick">
|
||||
<n8n-markdown
|
||||
<N8nMarkdown
|
||||
theme="sticky"
|
||||
:content="modelValue"
|
||||
:withMultiBreaks="true"
|
||||
:with-multi-breaks="true"
|
||||
@markdown-click="onMarkdownClick"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-show="editMode"
|
||||
:class="{ 'full-height': !shouldShowFooter, 'sticky-textarea': true }"
|
||||
@click.stop
|
||||
@mousedown.stop
|
||||
@mouseup.stop
|
||||
@keydown.esc="onInputBlur"
|
||||
@keydown.stop
|
||||
:class="{ 'full-height': !shouldShowFooter, 'sticky-textarea': true }"
|
||||
>
|
||||
<n8n-input
|
||||
:modelValue="modelValue"
|
||||
<N8nInput
|
||||
ref="input"
|
||||
:model-value="modelValue"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
@blur="onInputBlur"
|
||||
@update:modelValue="onUpdateModelValue"
|
||||
@wheel="onInputScroll"
|
||||
ref="input"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="editMode && shouldShowFooter" :class="$style.footer">
|
||||
<n8n-text size="xsmall" aligh="right">
|
||||
<N8nText size="xsmall" aligh="right">
|
||||
<span v-html="t('sticky.markdownHint')"></span>
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
</div>
|
||||
</n8n-resize-wrapper>
|
||||
</N8nResizeWrapper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -66,7 +66,13 @@ import Locale from '../../mixins/locale';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-sticky',
|
||||
name: 'N8nSticky',
|
||||
components: {
|
||||
N8nInput,
|
||||
N8nMarkdown,
|
||||
N8nResizeWrapper,
|
||||
N8nText,
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
modelValue: {
|
||||
|
@ -116,12 +122,6 @@ export default defineComponent({
|
|||
default: 1,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
N8nInput,
|
||||
N8nMarkdown,
|
||||
N8nResizeWrapper,
|
||||
N8nText,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isResizing: false,
|
||||
|
@ -152,6 +152,19 @@ export default defineComponent({
|
|||
return this.resHeight > 100 && this.resWidth > 155;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
editMode(newMode, prevMode) {
|
||||
setTimeout(() => {
|
||||
if (newMode && !prevMode && this.$refs.input) {
|
||||
const textarea = this.$refs.input as HTMLTextAreaElement;
|
||||
if (this.defaultText === this.modelValue) {
|
||||
textarea.select();
|
||||
}
|
||||
textarea.focus();
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onDoubleClick() {
|
||||
if (!this.readOnly) {
|
||||
|
@ -187,19 +200,6 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
editMode(newMode, prevMode) {
|
||||
setTimeout(() => {
|
||||
if (newMode && !prevMode && this.$refs.input) {
|
||||
const textarea = this.$refs.input as HTMLTextAreaElement;
|
||||
if (this.defaultText === this.modelValue) {
|
||||
textarea.select();
|
||||
}
|
||||
textarea.focus();
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div :class="['n8n-tabs', $style.container]">
|
||||
<div :class="$style.back" v-if="scrollPosition > 0" @click="scrollLeft">
|
||||
<n8n-icon icon="chevron-left" size="small" />
|
||||
<div v-if="scrollPosition > 0" :class="$style.back" @click="scrollLeft">
|
||||
<N8nIcon icon="chevron-left" size="small" />
|
||||
</div>
|
||||
<div :class="$style.next" v-if="canScrollRight" @click="scrollRight">
|
||||
<n8n-icon icon="chevron-right" size="small" />
|
||||
<div v-if="canScrollRight" :class="$style.next" @click="scrollRight">
|
||||
<N8nIcon icon="chevron-right" size="small" />
|
||||
</div>
|
||||
<div ref="tabs" :class="$style.tabs">
|
||||
<div
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:id="option.value"
|
||||
:key="option.value"
|
||||
:class="{ [$style.alignRight]: option.align === 'right' }"
|
||||
>
|
||||
<n8n-tooltip :disabled="!option.tooltip" placement="bottom">
|
||||
<template #content>
|
||||
<div v-html="option.tooltip" @click="handleTooltipClick(option.value, $event)" />
|
||||
<div @click="handleTooltipClick(option.value, $event)" v-html="option.tooltip" />
|
||||
</template>
|
||||
<a
|
||||
v-if="option.href"
|
||||
|
@ -27,7 +27,7 @@
|
|||
<div>
|
||||
{{ option.label }}
|
||||
<span :class="$style.external"
|
||||
><n8n-icon icon="external-link-alt" size="small"
|
||||
><N8nIcon icon="external-link-alt" size="small"
|
||||
/></span>
|
||||
</div>
|
||||
</a>
|
||||
|
@ -38,7 +38,7 @@
|
|||
:data-test-id="`tab-${option.value}`"
|
||||
@click="() => handleTabClick(option.value)"
|
||||
>
|
||||
<n8n-icon v-if="option.icon" :icon="option.icon" size="medium" />
|
||||
<N8nIcon v-if="option.icon" :icon="option.icon" size="medium" />
|
||||
<span v-if="option.label">{{ option.label }}</span>
|
||||
</div>
|
||||
</n8n-tooltip>
|
||||
|
@ -66,6 +66,23 @@ export default defineComponent({
|
|||
components: {
|
||||
N8nIcon,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
options: {
|
||||
type: Array as PropType<N8nTabOptions[]>,
|
||||
default: (): N8nTabOptions[] => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrollPosition: 0,
|
||||
canScrollRight: false,
|
||||
resizeObserver: null as ResizeObserver | null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const container = this.$refs.tabs as HTMLDivElement | undefined;
|
||||
if (container) {
|
||||
|
@ -94,23 +111,6 @@ export default defineComponent({
|
|||
this.resizeObserver.disconnect();
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrollPosition: 0,
|
||||
canScrollRight: false,
|
||||
resizeObserver: null as ResizeObserver | null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
options: {
|
||||
type: Array as PropType<N8nTabOptions[]>,
|
||||
default: (): N8nTabOptions[] => [],
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleTooltipClick(tab: string, event: MouseEvent) {
|
||||
this.$emit('tooltipClick', tab, event);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-tag',
|
||||
name: 'N8nTag',
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div :class="['n8n-tags', $style.tags]">
|
||||
<n8n-tag
|
||||
<N8nTag
|
||||
v-for="tag in visibleTags"
|
||||
:key="tag.id"
|
||||
:text="tag.name"
|
||||
@click="$emit('click:tag', tag.id, $event)"
|
||||
/>
|
||||
<n8n-link
|
||||
<N8nLink
|
||||
v-if="truncate && !showAll && hiddenTagsLength > 0"
|
||||
theme="text"
|
||||
underline
|
||||
|
@ -14,7 +14,7 @@
|
|||
@click.stop.prevent="onExpand"
|
||||
>
|
||||
{{ t('tags.showMore', `${hiddenTagsLength}`) }}
|
||||
</n8n-link>
|
||||
</N8nLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -31,17 +31,12 @@ export interface ITag {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-tags',
|
||||
mixins: [Locale],
|
||||
name: 'N8nTags',
|
||||
components: {
|
||||
N8nTag,
|
||||
N8nLink,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAll: false,
|
||||
};
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
tags: {
|
||||
type: Array as PropType<ITag[]>,
|
||||
|
@ -56,6 +51,11 @@ export default defineComponent({
|
|||
default: 3,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAll: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
visibleTags(): ITag[] {
|
||||
if (this.truncate && !this.showAll && this.tags.length > this.truncateAt) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'n8n-text',
|
||||
name: 'N8nText',
|
||||
props: {
|
||||
bold: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<el-tooltip v-bind="{ ...$props, ...$attrs }" :popperClass="$props.popperClass ?? 'n8n-tooltip'">
|
||||
<ElTooltip v-bind="{ ...$props, ...$attrs }" :popper-class="$props.popperClass ?? 'n8n-tooltip'">
|
||||
<slot />
|
||||
<template #content>
|
||||
<slot name="content">
|
||||
|
@ -10,14 +10,14 @@
|
|||
:class="$style.buttons"
|
||||
:style="{ justifyContent: justifyButtons }"
|
||||
>
|
||||
<n8n-button
|
||||
<N8nButton
|
||||
v-for="button in buttons"
|
||||
:key="button.attrs.label"
|
||||
v-bind="{ ...button.attrs, ...button.listeners }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</ElTooltip>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -28,12 +28,12 @@ import type { IN8nButton } from '@/types';
|
|||
import N8nButton from '../N8nButton';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-tooltip',
|
||||
inheritAttrs: false,
|
||||
name: 'N8nTooltip',
|
||||
components: {
|
||||
ElTooltip,
|
||||
N8nButton,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...ElTooltip.props,
|
||||
content: {
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div class="n8n-tree">
|
||||
<div v-for="(label, i) in Object.keys(value)" :key="i" :class="classes">
|
||||
<div :class="$style.simple" v-if="isSimple(value[label])">
|
||||
<slot v-if="$slots.label" name="label" v-bind:label="label" v-bind:path="getPath(label)" />
|
||||
<div v-if="isSimple(value[label])" :class="$style.simple">
|
||||
<slot v-if="$slots.label" name="label" :label="label" :path="getPath(label)" />
|
||||
<span v-else>{{ label }}</span>
|
||||
<span>:</span>
|
||||
<slot v-if="$slots.value" name="value" v-bind:value="value[label]" />
|
||||
<slot v-if="$slots.value" name="value" :value="value[label]" />
|
||||
<span v-else>{{ value[label] }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<slot v-if="$slots.label" name="label" v-bind:label="label" v-bind:path="getPath(label)" />
|
||||
<slot v-if="$slots.label" name="label" :label="label" :path="getPath(label)" />
|
||||
<span v-else>{{ label }}</span>
|
||||
<n8n-tree
|
||||
:path="getPath(label)"
|
||||
:depth="depth + 1"
|
||||
:value="value[label]"
|
||||
:nodeClass="nodeClass"
|
||||
:node-class="nodeClass"
|
||||
>
|
||||
<template v-for="(index, name) in $slots" #[name]="data">
|
||||
<slot :name="name" v-bind="data"></slot>
|
||||
|
@ -31,7 +31,7 @@ import type { PropType } from 'vue';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-tree',
|
||||
name: 'N8nTree',
|
||||
components: {},
|
||||
props: {
|
||||
value: {
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="$style.avatarContainer">
|
||||
<n8n-avatar :firstName="firstName" :lastName="lastName" />
|
||||
<N8nAvatar :first-name="firstName" :last-name="lastName" />
|
||||
</div>
|
||||
|
||||
<div v-if="isPendingUser" :class="$style.pendingUser">
|
||||
<n8n-text :bold="true">{{ email }}</n8n-text>
|
||||
<span :class="$style.pendingBadge"><n8n-badge :bold="true">Pending</n8n-badge></span>
|
||||
<N8nText :bold="true">{{ email }}</N8nText>
|
||||
<span :class="$style.pendingBadge"><N8nBadge :bold="true">Pending</N8nBadge></span>
|
||||
</div>
|
||||
<div v-else :class="$style.infoContainer">
|
||||
<div>
|
||||
<n8n-text :bold="true" color="text-dark">
|
||||
<N8nText :bold="true" color="text-dark">
|
||||
{{ firstName }} {{ lastName }}
|
||||
{{ isCurrentUser ? t('nds.userInfo.you') : '' }}
|
||||
</n8n-text>
|
||||
</N8nText>
|
||||
<span v-if="disabled" :class="$style.pendingBadge">
|
||||
<n8n-badge :bold="true">Disabled</n8n-badge>
|
||||
<N8nBadge :bold="true">Disabled</N8nBadge>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-text data-test-id="user-email" size="small" color="text-light">{{ email }}</n8n-text>
|
||||
<N8nText data-test-id="user-email" size="small" color="text-light">{{ email }}</N8nText>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -33,13 +33,13 @@ import Locale from '../../mixins/locale';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-users-info',
|
||||
mixins: [Locale],
|
||||
name: 'N8nUsersInfo',
|
||||
components: {
|
||||
N8nAvatar,
|
||||
N8nText,
|
||||
N8nBadge,
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
firstName: {
|
||||
type: String,
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
<n8n-select
|
||||
<N8nSelect
|
||||
data-test-id="user-select-trigger"
|
||||
v-bind="$attrs"
|
||||
:modelValue="modelValue"
|
||||
:model-value="modelValue"
|
||||
:filterable="true"
|
||||
:filterMethod="setFilter"
|
||||
:filter-method="setFilter"
|
||||
:placeholder="placeholder"
|
||||
:default-first-option="true"
|
||||
teleported
|
||||
:popper-class="$style.limitPopperWidth"
|
||||
:noDataText="t('nds.userSelect.noMatchingUsers')"
|
||||
:no-data-text="t('nds.userSelect.noMatchingUsers')"
|
||||
:size="size"
|
||||
@blur="onBlur"
|
||||
@focus="onFocus"
|
||||
>
|
||||
<template #prefix v-if="$slots.prefix">
|
||||
<template v-if="$slots.prefix" #prefix>
|
||||
<slot name="prefix" />
|
||||
</template>
|
||||
<n8n-option
|
||||
<N8nOption
|
||||
v-for="user in sortedUsers"
|
||||
:key="user.id"
|
||||
:value="user.id"
|
||||
|
@ -25,9 +25,9 @@
|
|||
:label="getLabel(user)"
|
||||
:disabled="user.disabled"
|
||||
>
|
||||
<n8n-user-info v-bind="user" :isCurrentUser="currentUserId === user.id" />
|
||||
</n8n-option>
|
||||
</n8n-select>
|
||||
<N8nUserInfo v-bind="user" :is-current-user="currentUserId === user.id" />
|
||||
</N8nOption>
|
||||
</N8nSelect>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -41,13 +41,13 @@ import type { PropType } from 'vue';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-user-select',
|
||||
mixins: [Locale],
|
||||
name: 'N8nUserSelect',
|
||||
components: {
|
||||
N8nUserInfo,
|
||||
N8nSelect,
|
||||
N8nOption,
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
users: {
|
||||
type: Array as PropType<IUser[]>,
|
||||
|
|
|
@ -76,11 +76,11 @@ const menuHeight = computed(() => {
|
|||
popper-class="user-stack-popper"
|
||||
>
|
||||
<div :class="$style.avatars" data-test-id="user-stack-avatars">
|
||||
<n8n-avatar
|
||||
<N8nAvatar
|
||||
v-for="user in flatUserList.slice(0, visibleAvatarCount)"
|
||||
:key="user.id"
|
||||
:firstName="user.firstName"
|
||||
:lastName="user.lastName"
|
||||
:first-name="user.firstName"
|
||||
:last-name="user.lastName"
|
||||
:class="$style.avatar"
|
||||
:data-test-id="`user-stack-avatar-${user.id}`"
|
||||
size="small"
|
||||
|
@ -101,9 +101,9 @@ const menuHeight = computed(() => {
|
|||
:data-test-id="`user-stack-info-${user.id}`"
|
||||
:class="$style.userInfoContainer"
|
||||
>
|
||||
<n8n-user-info
|
||||
<N8nUserInfo
|
||||
v-bind="user"
|
||||
:isCurrentUser="user.email === props.currentUserEmail"
|
||||
:is-current-user="user.email === props.currentUserEmail"
|
||||
/>
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
:class="i === sortedUsers.length - 1 ? $style.itemContainer : $style.itemWithBorder"
|
||||
:data-test-id="`user-list-item-${user.email}`"
|
||||
>
|
||||
<n8n-user-info
|
||||
<N8nUserInfo
|
||||
v-bind="user"
|
||||
:isCurrentUser="currentUserId === user.id"
|
||||
:isSamlLoginEnabled="isSamlLoginEnabled"
|
||||
:is-current-user="currentUserId === user.id"
|
||||
:is-saml-login-enabled="isSamlLoginEnabled"
|
||||
/>
|
||||
<div :class="$style.badgeContainer">
|
||||
<n8n-badge v-if="user.isOwner" theme="tertiary" bold>
|
||||
<N8nBadge v-if="user.isOwner" theme="tertiary" bold>
|
||||
{{ t('nds.auth.roles.owner') }}
|
||||
</n8n-badge>
|
||||
</N8nBadge>
|
||||
<slot v-if="!user.isOwner && !readonly" name="actions" :user="user" />
|
||||
<n8n-action-toggle
|
||||
<N8nActionToggle
|
||||
v-if="
|
||||
!user.isOwner &&
|
||||
user.signInType !== 'ldap' &&
|
||||
|
@ -44,13 +44,13 @@ import type { PropType } from 'vue';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-users-list',
|
||||
mixins: [Locale],
|
||||
name: 'N8nUsersList',
|
||||
components: {
|
||||
N8nActionToggle,
|
||||
N8nBadge,
|
||||
N8nUserInfo,
|
||||
},
|
||||
mixins: [Locale],
|
||||
props: {
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -1,118 +1,12 @@
|
|||
import type { Plugin } from 'vue';
|
||||
import {
|
||||
N8nActionBox,
|
||||
N8nActionDropdown,
|
||||
N8nActionToggle,
|
||||
N8nAlert,
|
||||
N8nAvatar,
|
||||
N8nBadge,
|
||||
N8nBlockUi,
|
||||
N8nButton,
|
||||
N8nCallout,
|
||||
N8nCard,
|
||||
N8nCheckbox,
|
||||
N8nCircleLoader,
|
||||
N8nColorPicker,
|
||||
N8nDatatable,
|
||||
N8nFormBox,
|
||||
N8nFormInputs,
|
||||
N8nFormInput,
|
||||
N8nHeading,
|
||||
N8nIcon,
|
||||
N8nIconButton,
|
||||
N8nInfoAccordion,
|
||||
N8nInfoTip,
|
||||
N8nInput,
|
||||
N8nInputLabel,
|
||||
N8nInputNumber,
|
||||
N8nLink,
|
||||
N8nLoading,
|
||||
N8nMarkdown,
|
||||
N8nMenu,
|
||||
N8nMenuItem,
|
||||
N8nNodeCreatorNode,
|
||||
N8nNodeIcon,
|
||||
N8nNotice,
|
||||
N8nOption,
|
||||
N8nPopover,
|
||||
N8nPulse,
|
||||
N8nRadioButtons,
|
||||
N8nRecycleScroller,
|
||||
N8nResizeWrapper,
|
||||
N8nSelect,
|
||||
N8nSpinner,
|
||||
N8nSticky,
|
||||
N8nTabs,
|
||||
N8nTag,
|
||||
N8nTags,
|
||||
N8nText,
|
||||
N8nTooltip,
|
||||
N8nTree,
|
||||
N8nUserInfo,
|
||||
N8nUserSelect,
|
||||
N8nUsersList,
|
||||
N8nResizeObserver,
|
||||
N8nKeyboardShortcut,
|
||||
N8nUserStack,
|
||||
} from './components';
|
||||
import type { Component, Plugin } from 'vue';
|
||||
import * as components from './components';
|
||||
|
||||
export interface N8nPluginOptions {}
|
||||
|
||||
export const N8nPlugin: Plugin<N8nPluginOptions> = {
|
||||
install: (app) => {
|
||||
app.component('n8n-action-box', N8nActionBox);
|
||||
app.component('n8n-action-dropdown', N8nActionDropdown);
|
||||
app.component('n8n-action-toggle', N8nActionToggle);
|
||||
app.component('n8n-alert', N8nAlert);
|
||||
app.component('n8n-avatar', N8nAvatar);
|
||||
app.component('n8n-badge', N8nBadge);
|
||||
app.component('n8n-block-ui', N8nBlockUi);
|
||||
app.component('n8n-button', N8nButton);
|
||||
app.component('n8n-callout', N8nCallout);
|
||||
app.component('n8n-card', N8nCard);
|
||||
app.component('n8n-checkbox', N8nCheckbox);
|
||||
app.component('n8n-circle-loader', N8nCircleLoader);
|
||||
app.component('n8n-color-picker', N8nColorPicker);
|
||||
app.component('n8n-datatable', N8nDatatable);
|
||||
app.component('n8n-form-box', N8nFormBox);
|
||||
app.component('n8n-form-inputs', N8nFormInputs);
|
||||
app.component('n8n-form-input', N8nFormInput);
|
||||
app.component('n8n-heading', N8nHeading);
|
||||
app.component('n8n-icon', N8nIcon);
|
||||
app.component('n8n-icon-button', N8nIconButton);
|
||||
app.component('n8n-info-accordion', N8nInfoAccordion);
|
||||
app.component('n8n-info-tip', N8nInfoTip);
|
||||
app.component('n8n-input', N8nInput);
|
||||
app.component('n8n-input-label', N8nInputLabel);
|
||||
app.component('n8n-input-number', N8nInputNumber);
|
||||
app.component('n8n-link', N8nLink);
|
||||
app.component('n8n-loading', N8nLoading);
|
||||
app.component('n8n-markdown', N8nMarkdown);
|
||||
app.component('n8n-menu', N8nMenu);
|
||||
app.component('n8n-menu-item', N8nMenuItem);
|
||||
app.component('n8n-node-creator-node', N8nNodeCreatorNode);
|
||||
app.component('n8n-node-icon', N8nNodeIcon);
|
||||
app.component('n8n-notice', N8nNotice);
|
||||
app.component('n8n-option', N8nOption);
|
||||
app.component('n8n-popover', N8nPopover);
|
||||
app.component('n8n-pulse', N8nPulse);
|
||||
app.component('n8n-radio-buttons', N8nRadioButtons);
|
||||
app.component('n8n-recycle-scroller', N8nRecycleScroller);
|
||||
app.component('n8n-resize-wrapper', N8nResizeWrapper);
|
||||
app.component('n8n-select', N8nSelect);
|
||||
app.component('n8n-spinner', N8nSpinner);
|
||||
app.component('n8n-sticky', N8nSticky);
|
||||
app.component('n8n-tabs', N8nTabs);
|
||||
app.component('n8n-tag', N8nTag);
|
||||
app.component('n8n-tags', N8nTags);
|
||||
app.component('n8n-text', N8nText);
|
||||
app.component('n8n-tooltip', N8nTooltip);
|
||||
app.component('n8n-tree', N8nTree);
|
||||
app.component('n8n-user-stack', N8nUserStack);
|
||||
app.component('n8n-user-info', N8nUserInfo);
|
||||
app.component('n8n-users-list', N8nUsersList);
|
||||
app.component('n8n-user-select', N8nUserSelect);
|
||||
app.component('n8n-resize-observer', N8nResizeObserver);
|
||||
app.component('n8n-keyboard-shortcut', N8nKeyboardShortcut);
|
||||
for (const [name, component] of Object.entries(components)) {
|
||||
app.component(name, component as unknown as Component);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -53,19 +53,19 @@ function getHex(hsl: string): string {
|
|||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'color-circles',
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
hsl: {} as { [color: string]: string },
|
||||
};
|
||||
},
|
||||
name: 'ColorCircles',
|
||||
props: {
|
||||
colors: {
|
||||
type: Array as PropType<string[]>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
hsl: {} as { [color: string]: string },
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const setColors = () => {
|
||||
this.colors.forEach((color) => {
|
||||
|
|
|
@ -22,13 +22,7 @@ import type { PropType } from 'vue';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'sizes',
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
sizes: {} as Record<string, { rem: string; px: number }>,
|
||||
};
|
||||
},
|
||||
name: 'Sizes',
|
||||
props: {
|
||||
variables: {
|
||||
type: Array as PropType<string[]>,
|
||||
|
@ -39,6 +33,12 @@ export default defineComponent({
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
sizes: {} as Record<string, { rem: string; px: number }>,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const setSizes = () => {
|
||||
this.variables.forEach((variable: string) => {
|
||||
|
|
|
@ -20,13 +20,7 @@ import type { PropType } from 'vue';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'variable-table',
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
values: {} as Record<string, string>,
|
||||
};
|
||||
},
|
||||
name: 'VariableTable',
|
||||
props: {
|
||||
variables: {
|
||||
type: Array as PropType<string[]>,
|
||||
|
@ -37,6 +31,12 @@ export default defineComponent({
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
observer: null as null | MutationObserver,
|
||||
values: {} as Record<string, string>,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const setValues = () => {
|
||||
this.variables.forEach((variable) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-for="size in sizes" class="spacing-group" :key="size">
|
||||
<div v-for="size in sizes" :key="size" class="spacing-group">
|
||||
<div class="spacing-example" :class="`${property[0]}${side ? side[0] : ''}-${size}`">
|
||||
<div class="spacing-box" />
|
||||
<div class="label">{{ property[0] }}{{ side ? side[0] : '' }}-{{ size }}</div>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
}"
|
||||
>
|
||||
<div id="banners" :class="$style.banners">
|
||||
<banner-stack v-if="!isDemoMode" />
|
||||
<BannerStack v-if="!isDemoMode" />
|
||||
</div>
|
||||
<div id="header" :class="$style.header">
|
||||
<router-view name="header"></router-view>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<keep-alive v-if="$route.meta.keepWorkflowAlive" include="NodeView" :max="1">
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
<component v-else :is="Component" />
|
||||
<component :is="Component" v-else />
|
||||
</router-view>
|
||||
</div>
|
||||
<Modals />
|
||||
|
@ -102,12 +102,16 @@ export default defineComponent({
|
|||
loading: true,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
logHiringBanner() {
|
||||
if (this.settingsStore.isHiringBannerEnabled && !this.isDemoMode) {
|
||||
console.log(HIRING_BANNER);
|
||||
watch: {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
async 'usersStore.currentUser'(currentValue, previousValue) {
|
||||
if (currentValue && !previousValue) {
|
||||
await initializeAuthenticatedFeatures();
|
||||
}
|
||||
},
|
||||
defaultLocale(newLocale) {
|
||||
void loadLanguage(newLocale);
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.logHiringBanner();
|
||||
|
@ -117,16 +121,12 @@ export default defineComponent({
|
|||
void useExternalHooks().run('app.mount');
|
||||
this.loading = false;
|
||||
},
|
||||
watch: {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
async 'usersStore.currentUser'(currentValue, previousValue) {
|
||||
if (currentValue && !previousValue) {
|
||||
await initializeAuthenticatedFeatures();
|
||||
methods: {
|
||||
logHiringBanner() {
|
||||
if (this.settingsStore.isHiringBannerEnabled && !this.isDemoMode) {
|
||||
console.log(HIRING_BANNER);
|
||||
}
|
||||
},
|
||||
defaultLocale(newLocale) {
|
||||
void loadLanguage(newLocale);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Modal
|
||||
max-width="540px"
|
||||
:title="$locale.baseText('about.aboutN8n')"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
:name="ABOUT_MODAL_KEY"
|
||||
:center="true"
|
||||
>
|
||||
|
@ -48,10 +48,10 @@
|
|||
<template #footer>
|
||||
<div class="action-buttons">
|
||||
<n8n-button
|
||||
@click="closeDialog"
|
||||
float="right"
|
||||
:label="$locale.baseText('about.close')"
|
||||
data-test-id="close-about-modal-button"
|
||||
@click="closeDialog"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
<template #footer="{ close }">
|
||||
<div :class="$style.footer">
|
||||
<el-checkbox :modelValue="checked" @update:modelValue="handleCheckboxChange">{{
|
||||
<el-checkbox :model-value="checked" @update:modelValue="handleCheckboxChange">{{
|
||||
$locale.baseText('generic.dontShowAgain')
|
||||
}}</el-checkbox>
|
||||
<n8n-button @click="close" :label="$locale.baseText('activationModal.gotIt')" />
|
||||
<n8n-button :label="$locale.baseText('activationModal.gotIt')" @click="close" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<slot name="button" v-if="$slots.button" />
|
||||
<slot v-if="$slots.button" name="button" />
|
||||
<n8n-button
|
||||
v-else-if="buttonLabel"
|
||||
:label="buttonLoading && buttonLoadingLabel ? buttonLoadingLabel : buttonLabel"
|
||||
|
@ -40,11 +40,6 @@ import { defineComponent } from 'vue';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'Banner',
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
theme: {
|
||||
type: String,
|
||||
|
@ -70,6 +65,11 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
expand() {
|
||||
this.expanded = true;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<div v-if="windowVisible" :class="['binary-data-window', binaryData?.fileType]">
|
||||
<n8n-button
|
||||
@click.stop="closeWindow"
|
||||
size="small"
|
||||
class="binary-data-window-back"
|
||||
:title="$locale.baseText('binaryDataDisplay.backToOverviewPage')"
|
||||
icon="arrow-left"
|
||||
:label="$locale.baseText('binaryDataDisplay.backToList')"
|
||||
@click.stop="closeWindow"
|
||||
/>
|
||||
|
||||
<div class="binary-data-window-wrapper">
|
||||
<div v-if="!binaryData">
|
||||
{{ $locale.baseText('binaryDataDisplay.noDataFoundToDisplay') }}
|
||||
</div>
|
||||
<BinaryDataDisplayEmbed v-else :binaryData="binaryData" />
|
||||
<BinaryDataDisplayEmbed v-else :binary-data="binaryData" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -34,6 +34,10 @@ export default defineComponent({
|
|||
components: {
|
||||
BinaryDataDisplayEmbed,
|
||||
},
|
||||
props: [
|
||||
'displayData', // IBinaryData
|
||||
'windowVisible', // boolean
|
||||
],
|
||||
setup() {
|
||||
const nodeHelpers = useNodeHelpers();
|
||||
|
||||
|
@ -41,10 +45,6 @@ export default defineComponent({
|
|||
nodeHelpers,
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'displayData', // IBinaryData
|
||||
'windowVisible', // boolean
|
||||
],
|
||||
computed: {
|
||||
...mapStores(useWorkflowsStore),
|
||||
binaryData(): IBinaryData | null {
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
<source :src="embedSource" :type="binaryData.mimeType" />
|
||||
{{ $locale.baseText('binaryDataDisplay.yourBrowserDoesNotSupport') }}
|
||||
</audio>
|
||||
<vue-json-pretty
|
||||
<VueJsonPretty
|
||||
v-else-if="binaryData.fileType === 'json'"
|
||||
:data="data"
|
||||
:deep="3"
|
||||
:showLength="true"
|
||||
:show-length="true"
|
||||
/>
|
||||
<run-data-html v-else-if="binaryData.fileType === 'html'" :inputHtml="data" />
|
||||
<RunDataHtml v-else-if="binaryData.fileType === 'html'" :input-html="data" />
|
||||
<embed v-else :src="embedSource" class="binary-data" :class="embedClass()" />
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<span>
|
||||
<slot v-bind:bp="bp" v-bind:value="value" />
|
||||
<slot :bp="bp" :value="value" />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -31,24 +31,6 @@ export default defineComponent({
|
|||
width: window.innerWidth,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('resize', this.onResize);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.onResize);
|
||||
},
|
||||
methods: {
|
||||
onResize() {
|
||||
void this.callDebounced('onResizeEnd', { debounceTime: 50 });
|
||||
},
|
||||
async onResizeEnd() {
|
||||
this.width = window.innerWidth;
|
||||
await this.$nextTick();
|
||||
|
||||
const bannerHeight = await getBannerRowHeight();
|
||||
useUIStore().updateBannersHeight(bannerHeight);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
bp(): string {
|
||||
if (this.width < BREAKPOINT_SM) {
|
||||
|
@ -94,5 +76,23 @@ export default defineComponent({
|
|||
return this.valueDefault;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('resize', this.onResize);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.onResize);
|
||||
},
|
||||
methods: {
|
||||
onResize() {
|
||||
void this.callDebounced('onResizeEnd', { debounceTime: 50 });
|
||||
},
|
||||
async onResizeEnd() {
|
||||
this.width = window.innerWidth;
|
||||
await this.$nextTick();
|
||||
|
||||
const bannerHeight = await getBannerRowHeight();
|
||||
useUIStore().updateBannersHeight(bannerHeight);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -6,55 +6,55 @@
|
|||
[$style.demoZoomMenu]: isDemo,
|
||||
}"
|
||||
>
|
||||
<keyboard-shortcut-tooltip
|
||||
<KeyboardShortcutTooltip
|
||||
:label="$locale.baseText('nodeView.zoomToFit')"
|
||||
:shortcut="{ keys: ['1'] }"
|
||||
>
|
||||
<n8n-icon-button
|
||||
@click="zoomToFit"
|
||||
type="tertiary"
|
||||
size="large"
|
||||
icon="expand"
|
||||
data-test-id="zoom-to-fit"
|
||||
@click="zoomToFit"
|
||||
/>
|
||||
</keyboard-shortcut-tooltip>
|
||||
<keyboard-shortcut-tooltip
|
||||
</KeyboardShortcutTooltip>
|
||||
<KeyboardShortcutTooltip
|
||||
:label="$locale.baseText('nodeView.zoomIn')"
|
||||
:shortcut="{ keys: ['+'] }"
|
||||
>
|
||||
<n8n-icon-button
|
||||
@click="zoomIn"
|
||||
type="tertiary"
|
||||
size="large"
|
||||
icon="search-plus"
|
||||
data-test-id="zoom-in-button"
|
||||
@click="zoomIn"
|
||||
/>
|
||||
</keyboard-shortcut-tooltip>
|
||||
<keyboard-shortcut-tooltip
|
||||
</KeyboardShortcutTooltip>
|
||||
<KeyboardShortcutTooltip
|
||||
:label="$locale.baseText('nodeView.zoomOut')"
|
||||
:shortcut="{ keys: ['-'] }"
|
||||
>
|
||||
<n8n-icon-button
|
||||
@click="zoomOut"
|
||||
type="tertiary"
|
||||
size="large"
|
||||
icon="search-minus"
|
||||
data-test-id="zoom-out-button"
|
||||
@click="zoomOut"
|
||||
/>
|
||||
</keyboard-shortcut-tooltip>
|
||||
<keyboard-shortcut-tooltip
|
||||
</KeyboardShortcutTooltip>
|
||||
<KeyboardShortcutTooltip
|
||||
:label="$locale.baseText('nodeView.resetZoom')"
|
||||
:shortcut="{ keys: ['0'] }"
|
||||
>
|
||||
<n8n-icon-button
|
||||
v-if="nodeViewScale !== 1 && !isDemo"
|
||||
@click="resetZoom"
|
||||
type="tertiary"
|
||||
size="large"
|
||||
icon="undo"
|
||||
data-test-id="reset-zoom-button"
|
||||
@click="resetZoom"
|
||||
/>
|
||||
</keyboard-shortcut-tooltip>
|
||||
</KeyboardShortcutTooltip>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="CHANGE_PASSWORD_MODAL_KEY"
|
||||
@enter="onSubmit"
|
||||
:title="$locale.baseText('auth.changePassword')"
|
||||
:center="true"
|
||||
width="460px"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
@enter="onSubmit"
|
||||
>
|
||||
<template #content>
|
||||
<n8n-form-inputs
|
||||
:inputs="config"
|
||||
:eventBus="formBus"
|
||||
:columnView="true"
|
||||
:event-bus="formBus"
|
||||
:column-view="true"
|
||||
@update="onInput"
|
||||
@submit="onSubmit"
|
||||
/>
|
||||
|
@ -20,9 +20,9 @@
|
|||
<n8n-button
|
||||
:loading="loading"
|
||||
:label="$locale.baseText('auth.changePassword')"
|
||||
@click="onSubmitClick"
|
||||
float="right"
|
||||
data-test-id="change-password-button"
|
||||
@click="onSubmitClick"
|
||||
/>
|
||||
</template>
|
||||
</Modal>
|
||||
|
|
|
@ -117,19 +117,19 @@ function closeDialog() {
|
|||
<Modal
|
||||
max-width="960px"
|
||||
:title="i18n.baseText('chatEmbed.title')"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
:name="CHAT_EMBED_MODAL_KEY"
|
||||
:center="true"
|
||||
>
|
||||
<template #content>
|
||||
<div :class="$style.container">
|
||||
<n8n-tabs :options="tabs" v-model="currentTab" />
|
||||
<n8n-tabs v-model="currentTab" :options="tabs" />
|
||||
|
||||
<div v-if="currentTab !== 'cdn'">
|
||||
<n8n-text>
|
||||
{{ i18n.baseText('chatEmbed.install') }}
|
||||
</n8n-text>
|
||||
<CodeNodeEditor :modelValue="commonCode.install" isReadOnly />
|
||||
<CodeNodeEditor :model-value="commonCode.install" is-read-only />
|
||||
</div>
|
||||
|
||||
<n8n-text>
|
||||
|
@ -139,10 +139,10 @@ function closeDialog() {
|
|||
</template>
|
||||
</i18n-t>
|
||||
</n8n-text>
|
||||
<HtmlEditor v-if="currentTab === 'cdn'" :modelValue="cdnCode" isReadOnly />
|
||||
<HtmlEditor v-if="currentTab === 'vue'" :modelValue="vueCode" isReadOnly />
|
||||
<CodeNodeEditor v-if="currentTab === 'react'" :modelValue="reactCode" isReadOnly />
|
||||
<CodeNodeEditor v-if="currentTab === 'other'" :modelValue="otherCode" isReadOnly />
|
||||
<HtmlEditor v-if="currentTab === 'cdn'" :model-value="cdnCode" is-read-only />
|
||||
<HtmlEditor v-if="currentTab === 'vue'" :model-value="vueCode" is-read-only />
|
||||
<CodeNodeEditor v-if="currentTab === 'react'" :model-value="reactCode" is-read-only />
|
||||
<CodeNodeEditor v-if="currentTab === 'other'" :model-value="otherCode" is-read-only />
|
||||
|
||||
<n8n-info-tip>
|
||||
{{ i18n.baseText('chatEmbed.packageInfo.description') }}
|
||||
|
@ -155,7 +155,7 @@ function closeDialog() {
|
|||
|
||||
<template #footer>
|
||||
<div class="action-buttons">
|
||||
<n8n-button @click="closeDialog" float="right" :label="i18n.baseText('chatEmbed.close')" />
|
||||
<n8n-button float="right" :label="i18n.baseText('chatEmbed.close')" @click="closeDialog" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
|
|
|
@ -249,8 +249,8 @@ onMounted(() => {
|
|||
<span
|
||||
v-show="prompt.length > 1"
|
||||
:class="$style.counter"
|
||||
v-text="`${prompt.length} / ${ASK_AI_MAX_PROMPT_LENGTH}`"
|
||||
data-test-id="ask-ai-prompt-counter"
|
||||
v-text="`${prompt.length} / ${ASK_AI_MAX_PROMPT_LENGTH}`"
|
||||
/>
|
||||
<a href="https://docs.n8n.io/code-examples/ai-code" target="_blank" :class="$style.help">
|
||||
<n8n-icon icon="question-circle" color="text-light" size="large" />{{
|
||||
|
@ -260,29 +260,29 @@ onMounted(() => {
|
|||
</div>
|
||||
<N8nInput
|
||||
v-model="prompt"
|
||||
@input="onPromptInput"
|
||||
:class="$style.input"
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
:maxlength="ASK_AI_MAX_PROMPT_LENGTH"
|
||||
:placeholder="i18n.baseText('codeNodeEditor.askAi.placeholder')"
|
||||
data-test-id="ask-ai-prompt-input"
|
||||
@input="onPromptInput"
|
||||
/>
|
||||
</div>
|
||||
<div :class="$style.controls">
|
||||
<div :class="$style.loader" v-if="isLoading">
|
||||
<div v-if="isLoading" :class="$style.loader">
|
||||
<transition name="text-fade-in-out" mode="out-in">
|
||||
<div v-text="loadingString" :key="loadingPhraseIndex" />
|
||||
<div :key="loadingPhraseIndex" v-text="loadingString" />
|
||||
</transition>
|
||||
<n8n-circle-loader :radius="8" :progress="loaderProgress" :stroke-width="3" />
|
||||
</div>
|
||||
<n8n-tooltip :disabled="isSubmitEnabled" v-else>
|
||||
<N8nTooltip v-else :disabled="isSubmitEnabled">
|
||||
<div>
|
||||
<N8nButton
|
||||
:disabled="!isSubmitEnabled"
|
||||
@click="onSubmit"
|
||||
size="small"
|
||||
data-test-id="ask-ai-cta"
|
||||
@click="onSubmit"
|
||||
>
|
||||
{{ i18n.baseText('codeNodeEditor.askAi.generateCode') }}
|
||||
</N8nButton>
|
||||
|
@ -290,18 +290,18 @@ onMounted(() => {
|
|||
<template #content>
|
||||
<span
|
||||
v-if="!hasExecutionData"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.noInputData')"
|
||||
data-test-id="ask-ai-cta-tooltip-no-input-data"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.noInputData')"
|
||||
/>
|
||||
<span
|
||||
v-else-if="prompt.length === 0"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.noPrompt')"
|
||||
data-test-id="ask-ai-cta-tooltip-no-prompt"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.noPrompt')"
|
||||
/>
|
||||
<span
|
||||
v-else-if="isEachItemMode"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.onlyAllItemsMode')"
|
||||
data-test-id="ask-ai-cta-tooltip-only-all-items-mode"
|
||||
v-text="i18n.baseText('codeNodeEditor.askAi.onlyAllItemsMode')"
|
||||
/>
|
||||
<span
|
||||
v-else-if="prompt.length < ASK_AI_MIN_PROMPT_LENGTH"
|
||||
|
@ -313,7 +313,7 @@ onMounted(() => {
|
|||
"
|
||||
/>
|
||||
</template>
|
||||
</n8n-tooltip>
|
||||
</N8nTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div
|
||||
ref="codeNodeEditorContainer"
|
||||
:class="['code-node-editor', $style['code-node-editor-container'], language]"
|
||||
@mouseover="onMouseOver"
|
||||
@mouseout="onMouseOut"
|
||||
ref="codeNodeEditorContainer"
|
||||
>
|
||||
<el-tabs
|
||||
type="card"
|
||||
v-if="aiEnabled"
|
||||
ref="tabs"
|
||||
v-model="activeTab"
|
||||
v-if="aiEnabled"
|
||||
type="card"
|
||||
:before-leave="onBeforeTabLeave"
|
||||
>
|
||||
<el-tab-pane
|
||||
|
@ -26,9 +26,9 @@
|
|||
>
|
||||
<!-- Key the AskAI tab to make sure it re-mounts when changing tabs -->
|
||||
<AskAI
|
||||
@replaceCode="onReplaceCode"
|
||||
:has-changes="hasChanges"
|
||||
:key="activeTab"
|
||||
:has-changes="hasChanges"
|
||||
@replaceCode="onReplaceCode"
|
||||
@started-loading="isLoadingAIResponse = true"
|
||||
@finished-loading="isLoadingAIResponse = false"
|
||||
/>
|
||||
|
@ -73,11 +73,11 @@ import { useMessage } from '@/composables/useMessage';
|
|||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'code-node-editor',
|
||||
mixins: [linterExtension, completerExtension, workflowHelpers],
|
||||
name: 'CodeNodeEditor',
|
||||
components: {
|
||||
AskAI,
|
||||
},
|
||||
mixins: [linterExtension, completerExtension, workflowHelpers],
|
||||
props: {
|
||||
aiButtonEnabled: {
|
||||
type: Boolean,
|
||||
|
@ -184,6 +184,67 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (!this.isReadOnly) codeNodeEditorEventBus.off('error-line-number', this.highlightLine);
|
||||
},
|
||||
mounted() {
|
||||
if (!this.isReadOnly) codeNodeEditorEventBus.on('error-line-number', this.highlightLine);
|
||||
|
||||
const { isReadOnly, language } = this;
|
||||
const extensions: Extension[] = [
|
||||
...readOnlyEditorExtensions,
|
||||
EditorState.readOnly.of(isReadOnly),
|
||||
EditorView.editable.of(!isReadOnly),
|
||||
codeNodeEditorTheme({ isReadOnly, customMinHeight: this.rows }),
|
||||
];
|
||||
|
||||
if (!isReadOnly) {
|
||||
const linter = this.createLinter(language);
|
||||
if (linter) {
|
||||
extensions.push(this.linterCompartment.of(linter));
|
||||
}
|
||||
|
||||
extensions.push(
|
||||
...writableEditorExtensions,
|
||||
EditorView.domEventHandlers({
|
||||
focus: () => {
|
||||
this.isEditorFocused = true;
|
||||
},
|
||||
blur: () => {
|
||||
this.isEditorFocused = false;
|
||||
},
|
||||
}),
|
||||
|
||||
EditorView.updateListener.of((viewUpdate) => {
|
||||
if (!viewUpdate.docChanged) return;
|
||||
|
||||
this.trackCompletion(viewUpdate);
|
||||
|
||||
this.$emit('update:modelValue', this.editor?.state.doc.toString());
|
||||
this.hasChanges = true;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const [languageSupport, ...otherExtensions] = this.languageExtensions;
|
||||
extensions.push(this.languageCompartment.of(languageSupport), ...otherExtensions);
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: this.modelValue ?? this.placeholder,
|
||||
extensions,
|
||||
});
|
||||
|
||||
this.editor = new EditorView({
|
||||
parent: this.$refs.codeNodeEditor as HTMLDivElement,
|
||||
state,
|
||||
});
|
||||
|
||||
// empty on first load, default param value
|
||||
if (!this.modelValue) {
|
||||
this.refreshPlaceholder();
|
||||
this.$emit('update:modelValue', this.placeholder);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCurrentEditorContent() {
|
||||
return this.editor?.state.doc.toString() ?? '';
|
||||
|
@ -311,67 +372,6 @@ export default defineComponent({
|
|||
} catch {}
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (!this.isReadOnly) codeNodeEditorEventBus.off('error-line-number', this.highlightLine);
|
||||
},
|
||||
mounted() {
|
||||
if (!this.isReadOnly) codeNodeEditorEventBus.on('error-line-number', this.highlightLine);
|
||||
|
||||
const { isReadOnly, language } = this;
|
||||
const extensions: Extension[] = [
|
||||
...readOnlyEditorExtensions,
|
||||
EditorState.readOnly.of(isReadOnly),
|
||||
EditorView.editable.of(!isReadOnly),
|
||||
codeNodeEditorTheme({ isReadOnly, customMinHeight: this.rows }),
|
||||
];
|
||||
|
||||
if (!isReadOnly) {
|
||||
const linter = this.createLinter(language);
|
||||
if (linter) {
|
||||
extensions.push(this.linterCompartment.of(linter));
|
||||
}
|
||||
|
||||
extensions.push(
|
||||
...writableEditorExtensions,
|
||||
EditorView.domEventHandlers({
|
||||
focus: () => {
|
||||
this.isEditorFocused = true;
|
||||
},
|
||||
blur: () => {
|
||||
this.isEditorFocused = false;
|
||||
},
|
||||
}),
|
||||
|
||||
EditorView.updateListener.of((viewUpdate) => {
|
||||
if (!viewUpdate.docChanged) return;
|
||||
|
||||
this.trackCompletion(viewUpdate);
|
||||
|
||||
this.$emit('update:modelValue', this.editor?.state.doc.toString());
|
||||
this.hasChanges = true;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const [languageSupport, ...otherExtensions] = this.languageExtensions;
|
||||
extensions.push(this.languageCompartment.of(languageSupport), ...otherExtensions);
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: this.modelValue ?? this.placeholder,
|
||||
extensions,
|
||||
});
|
||||
|
||||
this.editor = new EditorView({
|
||||
parent: this.$refs.codeNodeEditor as HTMLDivElement,
|
||||
state,
|
||||
});
|
||||
|
||||
// empty on first load, default param value
|
||||
if (!this.modelValue) {
|
||||
this.refreshPlaceholder();
|
||||
this.$emit('update:modelValue', this.placeholder);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<template>
|
||||
<div @keydown.stop class="collection-parameter">
|
||||
<div class="collection-parameter" @keydown.stop>
|
||||
<div class="collection-parameter-wrapper">
|
||||
<div v-if="getProperties.length === 0" class="no-items-exist">
|
||||
<n8n-text size="small">{{ $locale.baseText('collectionParameter.noProperties') }}</n8n-text>
|
||||
</div>
|
||||
|
||||
<Suspense>
|
||||
<parameter-input-list
|
||||
<ParameterInputList
|
||||
:parameters="getProperties"
|
||||
:nodeValues="nodeValues"
|
||||
:node-values="nodeValues"
|
||||
:path="path"
|
||||
:hideDelete="hideDelete"
|
||||
:hide-delete="hideDelete"
|
||||
:indent="true"
|
||||
:isReadOnly="isReadOnly"
|
||||
:is-read-only="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
</Suspense>
|
||||
|
@ -22,16 +22,16 @@
|
|||
v-if="(parameter.options ?? []).length === 1"
|
||||
type="tertiary"
|
||||
block
|
||||
@click="optionSelected((parameter.options ?? [])[0].name)"
|
||||
:label="getPlaceholderText"
|
||||
@click="optionSelected((parameter.options ?? [])[0].name)"
|
||||
/>
|
||||
<div v-else class="add-option">
|
||||
<n8n-select
|
||||
v-model="selectedOption"
|
||||
:placeholder="getPlaceholderText"
|
||||
size="small"
|
||||
@update:modelValue="optionSelected"
|
||||
filterable
|
||||
@update:modelValue="optionSelected"
|
||||
>
|
||||
<n8n-option
|
||||
v-for="item in parameterOptions"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<n8n-card :class="$style.card" v-bind="$attrs">
|
||||
<template #header v-if="!loading">
|
||||
<span v-text="title" :class="$style.title" />
|
||||
<template v-if="!loading" #header>
|
||||
<span :class="$style.title" v-text="title" />
|
||||
</template>
|
||||
<n8n-loading :loading="loading" :rows="3" variant="p" />
|
||||
<template #footer v-if="!loading">
|
||||
<template v-if="!loading" #footer>
|
||||
<slot name="footer" />
|
||||
</template>
|
||||
</n8n-card>
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
width="540px"
|
||||
:name="COMMUNITY_PACKAGE_INSTALL_MODAL_KEY"
|
||||
:title="$locale.baseText('settings.communityNodes.installModal.title')"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
:center="true"
|
||||
:beforeClose="onModalClose"
|
||||
:showClose="!loading"
|
||||
:before-close="onModalClose"
|
||||
:show-close="!loading"
|
||||
>
|
||||
<template #content>
|
||||
<div :class="[$style.descriptionContainer, 'p-s']">
|
||||
|
@ -30,15 +30,15 @@
|
|||
<n8n-input-label
|
||||
:class="$style.labelTooltip"
|
||||
:label="$locale.baseText('settings.communityNodes.installModal.packageName.label')"
|
||||
:tooltipText="
|
||||
:tooltip-text="
|
||||
$locale.baseText('settings.communityNodes.installModal.packageName.tooltip', {
|
||||
interpolate: { npmURL: NPM_KEYWORD_SEARCH_URL },
|
||||
})
|
||||
"
|
||||
>
|
||||
<n8n-input
|
||||
name="packageNameInput"
|
||||
v-model="packageName"
|
||||
name="packageNameInput"
|
||||
type="text"
|
||||
:maxlength="214"
|
||||
:placeholder="
|
||||
|
@ -60,8 +60,8 @@
|
|||
v-model="userAgreed"
|
||||
:class="[$style.checkbox, checkboxWarning ? $style.error : '', 'mt-l']"
|
||||
:disabled="loading"
|
||||
@update:modelValue="onCheckboxChecked"
|
||||
data-test-id="user-agreement-checkbox"
|
||||
@update:modelValue="onCheckboxChecked"
|
||||
>
|
||||
<n8n-text>
|
||||
{{ $locale.baseText('settings.communityNodes.installModal.checkbox.label') }} </n8n-text
|
||||
|
@ -83,8 +83,8 @@
|
|||
"
|
||||
size="large"
|
||||
float="right"
|
||||
@click="onInstallClick"
|
||||
data-test-id="install-community-package-button"
|
||||
@click="onInstallClick"
|
||||
/>
|
||||
</template>
|
||||
</Modal>
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
width="540px"
|
||||
:name="COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY"
|
||||
:title="getModalContent.title"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
:center="true"
|
||||
:showClose="!loading"
|
||||
:beforeClose="onModalClose"
|
||||
:show-close="!loading"
|
||||
:before-close="onModalClose"
|
||||
>
|
||||
<template #content>
|
||||
<n8n-text>{{ getModalContent.message }}</n8n-text>
|
||||
<div
|
||||
:class="$style.descriptionContainer"
|
||||
v-if="mode === COMMUNITY_PACKAGE_MANAGE_ACTIONS.UPDATE"
|
||||
:class="$style.descriptionContainer"
|
||||
>
|
||||
<n8n-info-tip theme="info" type="note" :bold="false">
|
||||
<span v-text="getModalContent.description"></span>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="modalName"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
:center="true"
|
||||
:closeOnPressEscape="false"
|
||||
:beforeClose="closeDialog"
|
||||
customClass="contact-prompt-modal"
|
||||
:close-on-press-escape="false"
|
||||
:before-close="closeDialog"
|
||||
custom-class="contact-prompt-modal"
|
||||
width="460px"
|
||||
>
|
||||
<template #header>
|
||||
|
@ -26,7 +26,7 @@
|
|||
</template>
|
||||
<template #footer>
|
||||
<div :class="$style.footer">
|
||||
<n8n-button label="Send" float="right" @click="send" :disabled="!isEmailValid" />
|
||||
<n8n-button label="Send" float="right" :disabled="!isEmailValid" @click="send" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
|
@ -46,8 +46,8 @@ import { useToast } from '@/composables/useToast';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'ContactPromptModal',
|
||||
mixins: [workflowHelpers],
|
||||
components: { Modal },
|
||||
mixins: [workflowHelpers],
|
||||
props: ['modalName'],
|
||||
setup() {
|
||||
return {
|
||||
|
|
|
@ -43,19 +43,19 @@ function onVisibleChange(open: boolean) {
|
|||
top: `${position[1]}px`,
|
||||
}"
|
||||
>
|
||||
<n8n-action-dropdown
|
||||
<N8nActionDropdown
|
||||
ref="dropdown"
|
||||
:items="actions"
|
||||
placement="bottom-start"
|
||||
data-test-id="context-menu"
|
||||
:hideArrow="target.source !== 'node-button'"
|
||||
:hide-arrow="target.source !== 'node-button'"
|
||||
@select="onActionSelect"
|
||||
@visibleChange="onVisibleChange"
|
||||
>
|
||||
<template #activator>
|
||||
<div :class="$style.activator"></div>
|
||||
</template>
|
||||
</n8n-action-dropdown>
|
||||
</N8nActionDropdown>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
[$style.collapsed]: collapse,
|
||||
'ph-no-capture': redactValue,
|
||||
}"
|
||||
@click="copy"
|
||||
data-test-id="copy-input"
|
||||
@click="copy"
|
||||
>
|
||||
<span ref="copyInputValue">{{ value }}</span>
|
||||
<div :class="$style.copyButton">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<n8n-card :class="$style.cardLink" @click="onClick">
|
||||
<template #prepend>
|
||||
<credential-icon :credential-type-name="credentialType ? credentialType.name : ''" />
|
||||
<CredentialIcon :credential-type-name="credentialType ? credentialType.name : ''" />
|
||||
</template>
|
||||
<template #header>
|
||||
<n8n-heading tag="h2" bold :class="$style.cardHeading">
|
||||
|
@ -12,7 +12,7 @@
|
|||
<n8n-text color="text-light" size="small">
|
||||
<span v-if="credentialType">{{ credentialType.displayName }} | </span>
|
||||
<span v-show="data"
|
||||
>{{ $locale.baseText('credentials.item.updated') }} <time-ago :date="data.updatedAt" /> |
|
||||
>{{ $locale.baseText('credentials.item.updated') }} <TimeAgo :date="data.updatedAt" /> |
|
||||
</span>
|
||||
<span v-show="data"
|
||||
>{{ $locale.baseText('credentials.item.created') }} {{ formattedCreatedAtDate }}
|
||||
|
@ -20,7 +20,7 @@
|
|||
</n8n-text>
|
||||
</div>
|
||||
<template #append>
|
||||
<div :class="$style.cardActions" ref="cardActions">
|
||||
<div ref="cardActions" :class="$style.cardActions">
|
||||
<enterprise-edition :features="[EnterpriseEditionFeature.Sharing]">
|
||||
<n8n-badge v-if="credentialPermissions.isOwner" class="mr-xs" theme="tertiary" bold>
|
||||
{{ $locale.baseText('credentials.item.owner') }}
|
||||
|
@ -54,16 +54,6 @@ export const CREDENTIAL_LIST_ITEM_ACTIONS = {
|
|||
};
|
||||
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
EnterpriseEditionFeature,
|
||||
};
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
...useMessage(),
|
||||
};
|
||||
},
|
||||
components: {
|
||||
TimeAgo,
|
||||
CredentialIcon,
|
||||
|
@ -88,6 +78,16 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
...useMessage(),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
EnterpriseEditionFeature,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useCredentialsStore, useUIStore, useUsersStore),
|
||||
currentUser(): IUser | null {
|
||||
|
|
|
@ -118,18 +118,18 @@ defineExpose({
|
|||
<template>
|
||||
<div v-if="filteredNodeAuthOptions.length > 0" data-test-id="node-auth-type-selector">
|
||||
<div v-for="parameter in authRelatedFields" :key="parameter.name" class="mb-l">
|
||||
<parameter-input-full
|
||||
<ParameterInputFull
|
||||
:parameter="parameter"
|
||||
:value="authRelatedFieldsValues[parameter.name] || parameter.default"
|
||||
:path="parameter.name"
|
||||
:displayOptions="false"
|
||||
:display-options="false"
|
||||
@update="valueChanged"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<n8n-input-label
|
||||
:label="$locale.baseText('credentialEdit.credentialConfig.authTypeSelectorLabel')"
|
||||
:tooltipText="$locale.baseText('credentialEdit.credentialConfig.authTypeSelectorTooltip')"
|
||||
:tooltip-text="$locale.baseText('credentialEdit.credentialConfig.authTypeSelectorTooltip')"
|
||||
:required="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="$style.container" data-test-id="node-credentials-config-container">
|
||||
<banner
|
||||
<Banner
|
||||
v-show="showValidationWarning"
|
||||
theme="danger"
|
||||
:message="
|
||||
|
@ -13,7 +13,7 @@
|
|||
"
|
||||
/>
|
||||
|
||||
<banner
|
||||
<Banner
|
||||
v-if="authError && !showValidationWarning"
|
||||
theme="danger"
|
||||
:message="
|
||||
|
@ -25,40 +25,40 @@
|
|||
)
|
||||
"
|
||||
:details="authError"
|
||||
:buttonLabel="$locale.baseText('credentialEdit.credentialConfig.retry')"
|
||||
buttonLoadingLabel="Retrying"
|
||||
:buttonTitle="$locale.baseText('credentialEdit.credentialConfig.retryCredentialTest')"
|
||||
:buttonLoading="isRetesting"
|
||||
:button-label="$locale.baseText('credentialEdit.credentialConfig.retry')"
|
||||
button-loading-label="Retrying"
|
||||
:button-title="$locale.baseText('credentialEdit.credentialConfig.retryCredentialTest')"
|
||||
:button-loading="isRetesting"
|
||||
@click="$emit('retest')"
|
||||
/>
|
||||
|
||||
<banner
|
||||
<Banner
|
||||
v-show="showOAuthSuccessBanner && !showValidationWarning"
|
||||
theme="success"
|
||||
:message="$locale.baseText('credentialEdit.credentialConfig.accountConnected')"
|
||||
:buttonLabel="$locale.baseText('credentialEdit.credentialConfig.reconnect')"
|
||||
:buttonTitle="$locale.baseText('credentialEdit.credentialConfig.reconnectOAuth2Credential')"
|
||||
:button-label="$locale.baseText('credentialEdit.credentialConfig.reconnect')"
|
||||
:button-title="$locale.baseText('credentialEdit.credentialConfig.reconnectOAuth2Credential')"
|
||||
@click="$emit('oauth')"
|
||||
>
|
||||
<template #button v-if="isGoogleOAuthType">
|
||||
<template v-if="isGoogleOAuthType" #button>
|
||||
<p
|
||||
v-text="`${$locale.baseText('credentialEdit.credentialConfig.reconnect')}:`"
|
||||
:class="$style.googleReconnectLabel"
|
||||
v-text="`${$locale.baseText('credentialEdit.credentialConfig.reconnect')}:`"
|
||||
/>
|
||||
<GoogleAuthButton @click="$emit('oauth')" />
|
||||
</template>
|
||||
</banner>
|
||||
</Banner>
|
||||
|
||||
<banner
|
||||
<Banner
|
||||
v-show="testedSuccessfully && !showValidationWarning"
|
||||
theme="success"
|
||||
:message="$locale.baseText('credentialEdit.credentialConfig.connectionTestedSuccessfully')"
|
||||
:buttonLabel="$locale.baseText('credentialEdit.credentialConfig.retry')"
|
||||
:buttonLoadingLabel="$locale.baseText('credentialEdit.credentialConfig.retrying')"
|
||||
:buttonTitle="$locale.baseText('credentialEdit.credentialConfig.retryCredentialTest')"
|
||||
:buttonLoading="isRetesting"
|
||||
@click="$emit('retest')"
|
||||
:button-label="$locale.baseText('credentialEdit.credentialConfig.retry')"
|
||||
:button-loading-label="$locale.baseText('credentialEdit.credentialConfig.retrying')"
|
||||
:button-title="$locale.baseText('credentialEdit.credentialConfig.retryCredentialTest')"
|
||||
:button-loading="isRetesting"
|
||||
data-test-id="credentials-config-container-test-success"
|
||||
@click="$emit('retest')"
|
||||
/>
|
||||
|
||||
<template v-if="credentialPermissions.update">
|
||||
|
@ -73,7 +73,7 @@
|
|||
|
||||
<AuthTypeSelector
|
||||
v-if="showAuthTypeSelector && isNewCredential"
|
||||
:credentialType="credentialType"
|
||||
:credential-type="credentialType"
|
||||
@authTypeChanged="onAuthTypeChange"
|
||||
/>
|
||||
|
||||
|
@ -81,17 +81,17 @@
|
|||
v-if="isOAuthType && credentialProperties.length"
|
||||
:label="$locale.baseText('credentialEdit.credentialConfig.oAuthRedirectUrl')"
|
||||
:value="oAuthCallbackUrl"
|
||||
:copyButtonText="$locale.baseText('credentialEdit.credentialConfig.clickToCopy')"
|
||||
:copy-button-text="$locale.baseText('credentialEdit.credentialConfig.clickToCopy')"
|
||||
:hint="
|
||||
$locale.baseText('credentialEdit.credentialConfig.subtitle', { interpolate: { appName } })
|
||||
"
|
||||
:toastTitle="
|
||||
:toast-title="
|
||||
$locale.baseText('credentialEdit.credentialConfig.redirectUrlCopiedToClipboard')
|
||||
"
|
||||
:redactValue="true"
|
||||
:redact-value="true"
|
||||
/>
|
||||
</template>
|
||||
<enterprise-edition v-else :features="[EnterpriseEditionFeature.Sharing]">
|
||||
<EnterpriseEdition v-else :features="[EnterpriseEditionFeature.Sharing]">
|
||||
<div>
|
||||
<n8n-info-tip :bold="false">
|
||||
{{
|
||||
|
@ -101,14 +101,14 @@
|
|||
}}
|
||||
</n8n-info-tip>
|
||||
</div>
|
||||
</enterprise-edition>
|
||||
</EnterpriseEdition>
|
||||
|
||||
<CredentialInputs
|
||||
v-if="credentialType && credentialPermissions.update"
|
||||
:credentialData="credentialData"
|
||||
:credentialProperties="credentialProperties"
|
||||
:documentationUrl="documentationUrl"
|
||||
:showValidationWarnings="showValidationWarning"
|
||||
:credential-data="credentialData"
|
||||
:credential-properties="credentialProperties"
|
||||
:documentation-url="documentationUrl"
|
||||
:show-validation-warnings="showValidationWarning"
|
||||
@update="onDataChange"
|
||||
/>
|
||||
|
||||
|
@ -119,7 +119,7 @@
|
|||
!isOAuthConnected &&
|
||||
credentialPermissions.isOwner
|
||||
"
|
||||
:isGoogleOAuthType="isGoogleOAuthType"
|
||||
:is-google-o-auth-type="isGoogleOAuthType"
|
||||
@click="$emit('oauth')"
|
||||
/>
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="modalName"
|
||||
:customClass="$style.credentialModal"
|
||||
:eventBus="modalBus"
|
||||
:custom-class="$style.credentialModal"
|
||||
:event-bus="modalBus"
|
||||
:loading="loading"
|
||||
:beforeClose="beforeClose"
|
||||
:before-close="beforeClose"
|
||||
width="70%"
|
||||
height="80%"
|
||||
>
|
||||
|
@ -12,15 +12,15 @@
|
|||
<div :class="$style.header">
|
||||
<div :class="$style.credInfo">
|
||||
<div :class="$style.credIcon">
|
||||
<CredentialIcon :credentialTypeName="defaultCredentialTypeName" />
|
||||
<CredentialIcon :credential-type-name="defaultCredentialTypeName" />
|
||||
</div>
|
||||
<InlineNameEdit
|
||||
:modelValue="credentialName"
|
||||
:model-value="credentialName"
|
||||
:subtitle="credentialType ? credentialType.displayName : ''"
|
||||
:readonly="!credentialPermissions.update || !credentialType"
|
||||
type="Credential"
|
||||
@update:modelValue="onNameEdit"
|
||||
data-test-id="credential-name"
|
||||
@update:modelValue="onNameEdit"
|
||||
/>
|
||||
</div>
|
||||
<div :class="$style.credActions">
|
||||
|
@ -31,20 +31,20 @@
|
|||
type="tertiary"
|
||||
:disabled="isSaving"
|
||||
:loading="isDeleting"
|
||||
@click="deleteCredential"
|
||||
data-test-id="credential-delete-button"
|
||||
@click="deleteCredential"
|
||||
/>
|
||||
<SaveButton
|
||||
v-if="(hasUnsavedChanges || credentialId) && credentialPermissions.save"
|
||||
:saved="!hasUnsavedChanges && !isTesting"
|
||||
:isSaving="isSaving || isTesting"
|
||||
:savingLabel="
|
||||
:is-saving="isSaving || isTesting"
|
||||
:saving-label="
|
||||
isTesting
|
||||
? $locale.baseText('credentialEdit.credentialEdit.testing')
|
||||
: $locale.baseText('credentialEdit.credentialEdit.saving')
|
||||
"
|
||||
@click="saveCredential"
|
||||
data-test-id="credential-save-button"
|
||||
@click="saveCredential"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,28 +56,28 @@
|
|||
<n8n-menu
|
||||
mode="tabs"
|
||||
:items="sidebarItems"
|
||||
:transparentBackground="true"
|
||||
:transparent-background="true"
|
||||
@select="onTabSelect"
|
||||
></n8n-menu>
|
||||
</div>
|
||||
<div v-if="activeTab === 'connection'" :class="$style.mainContent" ref="content">
|
||||
<div v-if="activeTab === 'connection'" ref="content" :class="$style.mainContent">
|
||||
<CredentialConfig
|
||||
:credentialType="credentialType"
|
||||
:credentialProperties="credentialProperties"
|
||||
:credentialData="credentialData"
|
||||
:credentialId="credentialId"
|
||||
:showValidationWarning="showValidationWarning"
|
||||
:authError="authError"
|
||||
:testedSuccessfully="testedSuccessfully"
|
||||
:isOAuthType="isOAuthType"
|
||||
:isOAuthConnected="isOAuthConnected"
|
||||
:isRetesting="isRetesting"
|
||||
:parentTypes="parentTypes"
|
||||
:requiredPropertiesFilled="requiredPropertiesFilled"
|
||||
:credentialPermissions="credentialPermissions"
|
||||
:credential-type="credentialType"
|
||||
:credential-properties="credentialProperties"
|
||||
:credential-data="credentialData"
|
||||
:credential-id="credentialId"
|
||||
:show-validation-warning="showValidationWarning"
|
||||
:auth-error="authError"
|
||||
:tested-successfully="testedSuccessfully"
|
||||
:is-o-auth-type="isOAuthType"
|
||||
:is-o-auth-connected="isOAuthConnected"
|
||||
:is-retesting="isRetesting"
|
||||
:parent-types="parentTypes"
|
||||
:required-properties-filled="requiredPropertiesFilled"
|
||||
:credential-permissions="credentialPermissions"
|
||||
:mode="mode"
|
||||
:selectedCredential="selectedCredential"
|
||||
:showAuthTypeSelector="requiredCredentials"
|
||||
:selected-credential="selectedCredential"
|
||||
:show-auth-type-selector="requiredCredentials"
|
||||
@update="onDataChange"
|
||||
@oauth="oAuthCredentialAuthorize"
|
||||
@retest="retestCredential"
|
||||
|
@ -88,24 +88,24 @@
|
|||
<div v-else-if="activeTab === 'sharing' && credentialType" :class="$style.mainContent">
|
||||
<CredentialSharing
|
||||
:credential="currentCredential"
|
||||
:credentialData="credentialData"
|
||||
:credentialId="credentialId"
|
||||
:credentialPermissions="credentialPermissions"
|
||||
:modalBus="modalBus"
|
||||
:credential-data="credentialData"
|
||||
:credential-id="credentialId"
|
||||
:credential-permissions="credentialPermissions"
|
||||
:modal-bus="modalBus"
|
||||
@update:modelValue="onChangeSharedWith"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="activeTab === 'details' && credentialType" :class="$style.mainContent">
|
||||
<CredentialInfo
|
||||
:nodeAccess="nodeAccess"
|
||||
:nodesWithAccess="nodesWithAccess"
|
||||
:currentCredential="currentCredential"
|
||||
:credentialPermissions="credentialPermissions"
|
||||
:node-access="nodeAccess"
|
||||
:nodes-with-access="nodesWithAccess"
|
||||
:current-credential="currentCredential"
|
||||
:credential-permissions="credentialPermissions"
|
||||
@accessChange="onNodeAccessChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="activeTab.startsWith('coming-soon')" :class="$style.mainContent">
|
||||
<FeatureComingSoon :featureId="activeTab.split('/')[1]"></FeatureComingSoon>
|
||||
<FeatureComingSoon :feature-id="activeTab.split('/')[1]"></FeatureComingSoon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
fallback: node.displayName,
|
||||
})
|
||||
"
|
||||
:modelValue="!!nodeAccess[node.name]"
|
||||
:model-value="!!nodeAccess[node.name]"
|
||||
@update:modelValue="(val) => onNodeAccessChange(node.name, val)"
|
||||
/>
|
||||
<n8n-text v-else>
|
||||
|
@ -75,10 +75,10 @@ import type { INodeTypeDescription } from 'n8n-workflow';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'CredentialInfo',
|
||||
props: ['nodesWithAccess', 'nodeAccess', 'currentCredential', 'credentialPermissions'],
|
||||
components: {
|
||||
TimeAgo,
|
||||
},
|
||||
props: ['nodesWithAccess', 'nodeAccess', 'currentCredential', 'credentialPermissions'],
|
||||
methods: {
|
||||
onNodeAccessChange(name: string, value: string) {
|
||||
this.$emit('accessChange', {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div @keydown.stop :class="$style.container" v-if="credentialProperties.length">
|
||||
<div v-if="credentialProperties.length" :class="$style.container" @keydown.stop>
|
||||
<form
|
||||
v-for="parameter in credentialProperties"
|
||||
:key="parameter.name"
|
||||
|
@ -9,14 +9,14 @@
|
|||
>
|
||||
<!-- Why form? to break up inputs, to prevent Chrome autofill -->
|
||||
<n8n-notice v-if="parameter.type === 'notice'" :content="parameter.displayName" />
|
||||
<parameter-input-expanded
|
||||
<ParameterInputExpanded
|
||||
v-else
|
||||
:parameter="parameter"
|
||||
:value="credentialData[parameter.name]"
|
||||
:documentationUrl="documentationUrl"
|
||||
:showValidationWarnings="showValidationWarnings"
|
||||
:documentation-url="documentationUrl"
|
||||
:show-validation-warnings="showValidationWarnings"
|
||||
:label="label"
|
||||
eventSource="credentials"
|
||||
event-source="credentials"
|
||||
@update="valueChanged"
|
||||
/>
|
||||
</form>
|
||||
|
@ -31,15 +31,15 @@ import ParameterInputExpanded from '../ParameterInputExpanded.vue';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'CredentialsInput',
|
||||
components: {
|
||||
ParameterInputExpanded,
|
||||
},
|
||||
props: [
|
||||
'credentialProperties',
|
||||
'credentialData', // ICredentialsDecryptedResponse
|
||||
'documentationUrl',
|
||||
'showValidationWarnings',
|
||||
],
|
||||
components: {
|
||||
ParameterInputExpanded,
|
||||
},
|
||||
data(): { label: IParameterLabel } {
|
||||
return {
|
||||
label: {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
uiStore.contextBasedTranslationKeys.credentials.sharing.unavailable.description,
|
||||
)
|
||||
"
|
||||
:buttonText="
|
||||
:button-text="
|
||||
$locale.baseText(
|
||||
uiStore.contextBasedTranslationKeys.credentials.sharing.unavailable.button,
|
||||
)
|
||||
|
@ -26,7 +26,7 @@
|
|||
:description="
|
||||
$locale.baseText('credentialEdit.credentialSharing.isDefaultUser.description')
|
||||
"
|
||||
:buttonText="$locale.baseText('credentialEdit.credentialSharing.isDefaultUser.button')"
|
||||
:button-text="$locale.baseText('credentialEdit.credentialSharing.isDefaultUser.button')"
|
||||
@click:button="goToUsersSettings"
|
||||
/>
|
||||
</div>
|
||||
|
@ -61,7 +61,7 @@
|
|||
class="mb-s"
|
||||
size="large"
|
||||
:users="usersList"
|
||||
:currentUserId="usersStore.currentUser.id"
|
||||
:current-user-id="usersStore.currentUser.id"
|
||||
:placeholder="$locale.baseText('credentialEdit.credentialSharing.select.placeholder')"
|
||||
data-test-id="credential-sharing-modal-users-select"
|
||||
@update:modelValue="onAddSharee"
|
||||
|
@ -73,7 +73,7 @@
|
|||
<n8n-users-list
|
||||
:actions="usersListActions"
|
||||
:users="sharedWithList"
|
||||
:currentUserId="usersStore.currentUser.id"
|
||||
:current-user-id="usersStore.currentUser.id"
|
||||
:readonly="!credentialPermissions.share"
|
||||
@delete="onRemoveSharee"
|
||||
/>
|
||||
|
@ -151,6 +151,9 @@ export default defineComponent({
|
|||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
void this.loadUsers();
|
||||
},
|
||||
methods: {
|
||||
async onAddSharee(userId: string) {
|
||||
const sharee = { ...this.usersStore.getUserById(userId), isOwner: false };
|
||||
|
@ -196,9 +199,6 @@ export default defineComponent({
|
|||
void this.uiStore.goToUpgrade('credential_sharing', 'upgrade-credentials-sharing');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
void this.loadUsers();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div>
|
||||
<img v-if="filePath" :class="$style.credIcon" :src="filePath" />
|
||||
<NodeIcon v-else-if="relevantNode" :nodeType="relevantNode" :size="28" />
|
||||
<span :class="$style.fallback" v-else></span>
|
||||
<NodeIcon v-else-if="relevantNode" :node-type="relevantNode" :size="28" />
|
||||
<span v-else :class="$style.fallback"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -104,16 +104,16 @@ listenForCredentialChanges({
|
|||
[$style.invisible]: !props.selectedCredentialId,
|
||||
}"
|
||||
:title="i18n.baseText('nodeCredentials.updateCredential')"
|
||||
@click="editCredential()"
|
||||
data-test-id="credential-edit-button"
|
||||
@click="editCredential()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<n8n-button
|
||||
v-else
|
||||
:label="`Create new ${props.appName} credential`"
|
||||
@click="createNewCredential"
|
||||
data-test-id="create-credential"
|
||||
@click="createNewCredential"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -40,13 +40,13 @@ const onCredentialSelected = (credentialId: string) => {
|
|||
<template>
|
||||
<n8n-select
|
||||
size="small"
|
||||
:modelValue="props.selectedCredentialId"
|
||||
:model-value="props.selectedCredentialId"
|
||||
@update:modelValue="onCredentialSelected"
|
||||
>
|
||||
<n8n-option
|
||||
v-for="item in props.credentialOptions"
|
||||
:data-test-id="`node-credentials-select-item-${item.id}`"
|
||||
:key="item.id"
|
||||
:data-test-id="`node-credentials-select-item-${item.id}`"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
|
@ -56,8 +56,8 @@ const onCredentialSelected = (credentialId: string) => {
|
|||
</div>
|
||||
</n8n-option>
|
||||
<n8n-option
|
||||
data-test-id="node-credentials-select-item-new"
|
||||
:key="NEW_CREDENTIALS_TEXT"
|
||||
data-test-id="node-credentials-select-item-new"
|
||||
:value="NEW_CREDENTIALS_TEXT"
|
||||
:label="NEW_CREDENTIALS_TEXT"
|
||||
>
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
<div>
|
||||
<div :class="$style['parameter-value-container']">
|
||||
<n8n-select
|
||||
ref="innerSelect"
|
||||
:size="inputSize"
|
||||
filterable
|
||||
:modelValue="displayValue"
|
||||
:model-value="displayValue"
|
||||
:placeholder="
|
||||
parameter.placeholder ? getPlaceholder() : $locale.baseText('parameterInput.select')
|
||||
"
|
||||
:title="displayTitle"
|
||||
:disabled="isReadOnly"
|
||||
ref="innerSelect"
|
||||
data-test-id="credential-select"
|
||||
@update:modelValue="(value) => $emit('update:modelValue', value)"
|
||||
@keydown.stop
|
||||
@focus="$emit('setFocus')"
|
||||
@blur="$emit('onBlur')"
|
||||
data-test-id="credential-select"
|
||||
>
|
||||
<n8n-option
|
||||
v-for="credType in supportedCredentialTypes"
|
||||
:value="credType.name"
|
||||
:key="credType.name"
|
||||
:value="credType.name"
|
||||
:label="credType.displayName"
|
||||
data-test-id="credential-select-option"
|
||||
>
|
||||
|
@ -39,15 +39,15 @@
|
|||
<slot name="issues-and-options" />
|
||||
</div>
|
||||
|
||||
<scopes-notice
|
||||
<ScopesNotice
|
||||
v-if="scopes.length > 0"
|
||||
:activeCredentialType="activeCredentialType"
|
||||
:active-credential-type="activeCredentialType"
|
||||
:scopes="scopes"
|
||||
/>
|
||||
<div>
|
||||
<node-credentials
|
||||
<NodeCredentials
|
||||
:node="node"
|
||||
:overrideCredType="node.parameters[parameter.name]"
|
||||
:override-cred-type="node.parameters[parameter.name]"
|
||||
@credentialSelected="(updateInformation) => $emit('credentialSelected', updateInformation)"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="CREDENTIAL_SELECT_MODAL_KEY"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
width="50%"
|
||||
:center="true"
|
||||
:loading="loading"
|
||||
maxWidth="460px"
|
||||
minHeight="250px"
|
||||
max-width="460px"
|
||||
min-height="250px"
|
||||
>
|
||||
<template #header>
|
||||
<h2 :class="$style.title">
|
||||
|
@ -19,22 +19,22 @@
|
|||
{{ $locale.baseText('credentialSelectModal.selectAnAppOrServiceToConnectTo') }}
|
||||
</div>
|
||||
<n8n-select
|
||||
ref="select"
|
||||
filterable
|
||||
defaultFirstOption
|
||||
default-first-option
|
||||
:placeholder="$locale.baseText('credentialSelectModal.searchForApp')"
|
||||
size="xlarge"
|
||||
ref="select"
|
||||
:modelValue="selected"
|
||||
@update:modelValue="onSelect"
|
||||
:model-value="selected"
|
||||
data-test-id="new-credential-type-select"
|
||||
@update:modelValue="onSelect"
|
||||
>
|
||||
<template #prefix>
|
||||
<font-awesome-icon icon="search" />
|
||||
</template>
|
||||
<n8n-option
|
||||
v-for="credential in credentialsStore.allCredentialTypes"
|
||||
:value="credential.name"
|
||||
:key="credential.name"
|
||||
:value="credential.name"
|
||||
:label="credential.displayName"
|
||||
filterable
|
||||
data-test-id="new-credential-type-select-option"
|
||||
|
@ -49,8 +49,8 @@
|
|||
float="right"
|
||||
size="large"
|
||||
:disabled="!selected"
|
||||
@click="openCredentialType"
|
||||
data-test-id="new-credential-type-button"
|
||||
@click="openCredentialType"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -79,6 +79,14 @@ export default defineComponent({
|
|||
externalHooks,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalBus: createEventBus(),
|
||||
selected: '',
|
||||
loading: true,
|
||||
CREDENTIAL_SELECT_MODAL_KEY,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
await this.credentialsStore.fetchCredentialTypes(false);
|
||||
|
@ -92,14 +100,6 @@ export default defineComponent({
|
|||
}
|
||||
}, 0);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalBus: createEventBus(),
|
||||
selected: '',
|
||||
loading: true,
|
||||
CREDENTIAL_SELECT_MODAL_KEY,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useCredentialsStore, useUIStore, useWorkflowsStore),
|
||||
},
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="modalName"
|
||||
@enter="onSubmit"
|
||||
:title="title"
|
||||
:center="true"
|
||||
width="460px"
|
||||
:eventBus="modalBus"
|
||||
:event-bus="modalBus"
|
||||
@enter="onSubmit"
|
||||
>
|
||||
<template #content>
|
||||
<div>
|
||||
|
@ -14,14 +14,14 @@
|
|||
$locale.baseText('settings.users.confirmUserDeletion')
|
||||
}}</n8n-text>
|
||||
</div>
|
||||
<div :class="$style.content" v-else>
|
||||
<div v-else :class="$style.content">
|
||||
<div>
|
||||
<n8n-text color="text-base">{{
|
||||
$locale.baseText('settings.users.confirmDataHandlingAfterDeletion')
|
||||
}}</n8n-text>
|
||||
</div>
|
||||
<el-radio
|
||||
:modelValue="operation"
|
||||
:model-value="operation"
|
||||
label="transfer"
|
||||
@update:modelValue="() => setOperation('transfer')"
|
||||
>
|
||||
|
@ -29,19 +29,19 @@
|
|||
$locale.baseText('settings.users.transferWorkflowsAndCredentials')
|
||||
}}</n8n-text>
|
||||
</el-radio>
|
||||
<div :class="$style.optionInput" v-if="operation === 'transfer'">
|
||||
<div v-if="operation === 'transfer'" :class="$style.optionInput">
|
||||
<n8n-input-label :label="$locale.baseText('settings.users.userToTransferTo')">
|
||||
<n8n-user-select
|
||||
:users="usersStore.allUsers"
|
||||
:modelValue="transferId"
|
||||
:ignoreIds="ignoreIds"
|
||||
:currentUserId="usersStore.currentUserId"
|
||||
:model-value="transferId"
|
||||
:ignore-ids="ignoreIds"
|
||||
:current-user-id="usersStore.currentUserId"
|
||||
@update:modelValue="setTransferId"
|
||||
/>
|
||||
</n8n-input-label>
|
||||
</div>
|
||||
<el-radio
|
||||
:modelValue="operation"
|
||||
:model-value="operation"
|
||||
label="delete"
|
||||
@update:modelValue="() => setOperation('delete')"
|
||||
>
|
||||
|
@ -50,13 +50,13 @@
|
|||
}}</n8n-text>
|
||||
</el-radio>
|
||||
<div
|
||||
:class="$style.optionInput"
|
||||
v-if="operation === 'delete'"
|
||||
:class="$style.optionInput"
|
||||
data-test-id="delete-data-input"
|
||||
>
|
||||
<n8n-input-label :label="$locale.baseText('settings.users.deleteConfirmationMessage')">
|
||||
<n8n-input
|
||||
:modelValue="deleteConfirmText"
|
||||
:model-value="deleteConfirmText"
|
||||
:placeholder="$locale.baseText('settings.users.deleteConfirmationText')"
|
||||
@update:modelValue="setConfirmText"
|
||||
/>
|
||||
|
@ -70,8 +70,8 @@
|
|||
:loading="loading"
|
||||
:disabled="!enabled"
|
||||
:label="$locale.baseText('settings.users.delete')"
|
||||
@click="onSubmit"
|
||||
float="right"
|
||||
@click="onSubmit"
|
||||
/>
|
||||
</template>
|
||||
</Modal>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
ref="wrapper"
|
||||
:class="{ [$style.dragging]: isDragging }"
|
||||
@mousedown="onDragStart"
|
||||
ref="wrapper"
|
||||
>
|
||||
<slot :isDragging="isDragging"></slot>
|
||||
<slot :is-dragging="isDragging"></slot>
|
||||
|
||||
<Teleport to="body">
|
||||
<div ref="draggable" :class="$style.draggable" :style="draggableStyle" v-show="isDragging">
|
||||
<slot name="preview" :canDrop="canDrop" :el="draggingEl"></slot>
|
||||
<div v-show="isDragging" ref="draggable" :class="$style.draggable" :style="draggableStyle">
|
||||
<slot name="preview" :can-drop="canDrop" :el="draggingEl"></slot>
|
||||
</div>
|
||||
</Teleport>
|
||||
</component>
|
||||
|
@ -22,7 +22,7 @@ import { mapStores } from 'pinia';
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'draggable',
|
||||
name: 'Draggable',
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div ref="target">
|
||||
<slot :droppable="droppable" :activeDrop="activeDrop"></slot>
|
||||
<slot :droppable="droppable" :active-drop="activeDrop"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
<template>
|
||||
<Modal
|
||||
:name="modalName"
|
||||
:eventBus="modalBus"
|
||||
@enter="save"
|
||||
:event-bus="modalBus"
|
||||
:title="$locale.baseText('duplicateWorkflowDialog.duplicateWorkflow')"
|
||||
:center="true"
|
||||
width="420px"
|
||||
@enter="save"
|
||||
>
|
||||
<template #content>
|
||||
<div :class="$style.content">
|
||||
<n8n-input
|
||||
v-model="name"
|
||||
ref="nameInput"
|
||||
v-model="name"
|
||||
:placeholder="$locale.baseText('duplicateWorkflowDialog.enterWorkflowName')"
|
||||
:maxlength="MAX_WORKFLOW_NAME_LENGTH"
|
||||
/>
|
||||
<TagsDropdown
|
||||
v-if="settingsStore.areTagsEnabled"
|
||||
ref="dropdown"
|
||||
v-model="currentTagIds"
|
||||
:createEnabled="true"
|
||||
:eventBus="dropdownBus"
|
||||
:create-enabled="true"
|
||||
:event-bus="dropdownBus"
|
||||
:placeholder="$locale.baseText('duplicateWorkflowDialog.chooseOrCreateATag')"
|
||||
@blur="onTagsBlur"
|
||||
@esc="onTagsEsc"
|
||||
:placeholder="$locale.baseText('duplicateWorkflowDialog.chooseOrCreateATag')"
|
||||
ref="dropdown"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer="{ close }">
|
||||
<div :class="$style.footer">
|
||||
<n8n-button
|
||||
@click="save"
|
||||
:loading="isSaving"
|
||||
:label="$locale.baseText('duplicateWorkflowDialog.save')"
|
||||
float="right"
|
||||
@click="save"
|
||||
/>
|
||||
<n8n-button
|
||||
type="secondary"
|
||||
@click="close"
|
||||
:disabled="isSaving"
|
||||
:label="$locale.baseText('duplicateWorkflowDialog.cancel')"
|
||||
float="right"
|
||||
@click="close"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -66,8 +66,8 @@ import { useCredentialsStore } from '@/stores/credentials.store';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'DuplicateWorkflow',
|
||||
mixins: [workflowHelpers],
|
||||
components: { TagsDropdown, Modal },
|
||||
mixins: [workflowHelpers],
|
||||
props: ['modalName', 'isActive', 'data'],
|
||||
setup() {
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<slot v-if="canAccess" />
|
||||
<slot name="fallback" v-else />
|
||||
<slot v-else name="fallback" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<div class="error-header">
|
||||
<div class="error-message" v-text="getErrorMessage()" />
|
||||
<div class="error-description" v-if="error.description" v-html="getErrorDescription()"></div>
|
||||
<div v-if="error.description" class="error-description" v-html="getErrorDescription()"></div>
|
||||
</div>
|
||||
<details>
|
||||
<summary class="error-details__summary">
|
||||
|
@ -76,19 +76,19 @@
|
|||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<div class="copy-button" v-if="displayCause">
|
||||
<div v-if="displayCause" class="copy-button">
|
||||
<n8n-icon-button
|
||||
@click="copyCause"
|
||||
:title="$locale.baseText('nodeErrorView.copyToClipboard')"
|
||||
icon="copy"
|
||||
@click="copyCause"
|
||||
/>
|
||||
</div>
|
||||
<vue-json-pretty
|
||||
<VueJsonPretty
|
||||
v-if="displayCause"
|
||||
:data="error.cause"
|
||||
:deep="3"
|
||||
:showLength="true"
|
||||
selectableType="single"
|
||||
:show-length="true"
|
||||
selectable-type="single"
|
||||
path="error"
|
||||
class="json-data"
|
||||
/>
|
||||
|
@ -137,11 +137,11 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
|||
|
||||
export default defineComponent({
|
||||
name: 'NodeErrorView',
|
||||
mixins: [copyPaste],
|
||||
props: ['error'],
|
||||
components: {
|
||||
VueJsonPretty,
|
||||
},
|
||||
mixins: [copyPaste],
|
||||
props: ['error'],
|
||||
setup() {
|
||||
return {
|
||||
...useToast(),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue