feat(editor): Migrate Design System and Editor UI to Vue 3 (#6476)

* feat: remove vue-fragment (no-changelog)

* feat: partial design-system migration

* feat: migrate info-accordion and info-tip components

* feat: migrate several components to vue 3

* feat: migrated several components

* feat: migrate several components

* feat: migrate several components

* feat: migrate several components

* feat: re-exported all design system components

* fix: fix design for popper components

* fix: editor kind of working, lots of issues to fix

* fix: fix several vue 3 migration issues

* fix: replace @change with @update:modelValue in several places

* fix: fix translation linking

* fix: fix inline-edit input

* fix: fix ndv and dialog design

* fix: update parameter input event bindings

* fix: rename deprecated lifecycle methods

* fix: fix json view mapping

* build: update lock file

* fix(editor): revisit last conflict with master and fix issues

* fix(editor): revisit last conflict with master and fix issues

* fix: fix expression editor bug causing code mirror to no longer be reactive

* fix: fix resource locator bug

* fix: fix vue-agile integration

* fix: remove global import for vue-agile

* fix: replace element-plus buttons with n8n-buttons everywhere

* fix(editor): Fix various element-plus styles (#6571)

* fix(editor): Fix various element-plus styles

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Remove debugging code

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Address PR comments

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* fix(editor): Fix loading in production mode [Vue 3] (#6578)

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* fix(editor): First round of e2e tests fixes with Vue 3 (#6579)

* fix(editor): Fix broken smoke and workflow list e2e tests
* ✔️ Fix failing canvas action tests. Updating some selectors used in credentials and workflow tests

* feat: add vue 3 eslint rules and fix issues

* fix: fix tags-dropdown

* fix: fix white-space issues caused by i18n-t

* fix: rename non-generic click events

* fix: fix search in resources list layout

* fix: fix datatable paginator

* fix: fix popper select caret and dropdown size

* fix: add width to action-dropdown

* fix: fix workflow settings icon not being hidden

* fix: refactor newly added code

* fix: fix merge issue

* fix: fix ndv credentials watcher

* fix: fix workflow saving and grabber notch

* fix: fix nodes list panel transition

* fix: fix node title visibility

* fix: fix data unpinning

* fix: fix value access

* fix: show  input panel only if trigger panel enabled or not trigger node

* fix: fix tags dropdown and executions status spcing

* fix(editor): Prevent execution list to load back when leaving the route (#6697)

fix(editor): prevent execution list to load back when leaving the route

* fix: fix drawer visibility

* fix: fix expression toggle padding

* fix: fix expressions editor styling

* chore: prepare for testing

* fix: fix styling for el-button without patching

* test: fix unit tests in design-system

* test: fix most unit tests

* fix: remove import cycle.

* fix: fix personalization modal tests

* fix further resource mapper test adjustments

* fix: fix multiple tests and n8n-route attr duplication

* fix: fix source control tets

* fix: fixed remaining unit tests

* fix: fix workflows and credentials e2e tests

* fix: fix localizeNodeNames

* fix: update ndv e2e tests

* fix: fix popper left placement arrow

* fix: fix 5-ndv e2e tests

* fix: fix 6-code-node e2e tests

* fix(editor): Drop click outside directive from NodeCreator (#6716)

* fix(editor): Drop click outside directive from NodeCreator

* fix(editor): make sure mouseup outside is unbound at least before the component is unmounted

* fix: fix 10-settings-log-streaming e2e tests

* fix: fix node redrawing

* fix: fix tooltip buttons styling

* fix: fix varous e2e suites

* fix: fix 15-scheduler-node e2e suite

* fix: fix route watcher

* fix: fixed param name update and credential edit

* feat: update event names

* refactor: Remove deprecated `$data` (#6576)

Co-authored-by: Alex Grozav <alex@grozav.com>

* fix: fix 17-sharing e2e suite

* fix: fix tags dropdown

* fix: fix tags manager

* fix(editor): move :deep selectors to a separate scoped style block

* fix: fix sticky component and inline text edit

* fix: update e2e tests

* fix: remove button override references

* fix(editor): Adjust spacing in templates for Vue 3 (#6744)

* fix(editor): Adjust spacing in templates

* fix: Undo unneeded change

* fix: Undo unneeded change

* fix(editor): Adjust NDV height for Vue 3 (#6742)

fix(editor): Adjust NDV height

* fix(editor): Restore collapsed sidebar items for Vue 3 (#6743)

fix(editor): Restore collapsed sidebar items

* fix: fix linting issues

* fix: fix design-system deps

* fix: post-merge fixes

* fix: update tests

* fix: increase timeout for executionslist tets

* chore: fix linting issue

* fix: fix 14-mapping e2e tests in ci

* fix: re-enable tests

* fix: fix workflow duplication e2e tests after tags update

* fix(editor): Change component prop to be typed

* fix: fix tags dropdown in duplicate wf modal

* fix: fix focus behaviour in tags selector

* fix: fix tag creation

* fix: fix log streaming e2e race condition

* fix(editor): Fix Vue 3 linting issues (#6748)

* fix(editor): Fix Vue 3 linting issues

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* fix MainSidebar linter issues

* revert pnpm lock

* update pnpm lock file

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Alex Grozav <alex@grozav.com>

* fix(editor): Some css fixes for vue3 branch (#6749)

*  Fixing filter button height

*  Update input modal button position

*  Updating tags styling

*  Fix event logging settings spacing

* 👕 Fixing lint errors

* fix: fix linting issues

* Revert to `// eslint-disable-next-line @typescript-eslint/no-misused-promises` disabling of mixins init

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* fix: fix css issue

* fix(editor): Lint fix

* fix(editor): Fix settings initialisation (#6750)

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* fix: fix initial settings loading

* fix: replace realClick with click force

* fix: fix randomly failing mapping e2e tests

* fix(editor): Fix menu item event handling

* fix: fix resource filters dropdown events (#6752)

* fix: fix resource filters dropdown events

* fix: remove teleported:false

* fix: fix event selection event naming (#6753)

* fix: removed console.log (#6754)

* fix: rever await nextTick changes

* fix: redo linting changes

* fix(editor): Redraw node connections if adding more than one node to canvas (#6755)

* fix(editor): Redraw node connections if adding more than one node to canvas

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Update position before connection two nodes

* Lint fix

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Alex Grozav <alex@grozav.com>

* fix(editor): Fix `ResourceMapper` unit tests (#6758)

* ✔️ Fix matching columns test

* ✔️ Fix multiple matching columns test

* ✔️ Removing `skip` from the last test

* fix: Allow pasting a big workflow (#6760)

* fix: pasting a big workflow

* chore: update comment

* refactor: move try/catch to function

* refactor: move try/catch to function

* fix(editor): Fix modal layer width

* fix: fix position changes

* fix: undo it.only

* fix: make undo/redo multiple steps more verbose

* fix: Fix value survey styles (#6764)

* fix: fix value survey styles

* fix: lint

* Revert "fix: lint"

72869c431f1448861df021be041b61c62f1e3118

* fix: lint

* fix(editor): Fix collapsed sub menu

* fix: Fix drawer animation (#6767)

fix: drawer animation

* fix(editor): Fix source control buttons (#6769)

* fix(editor): Fix App loading & auth  (#6768)

* fix(editor): Fix App loading & auth

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Await promises

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Fix eslint error

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Csaba Tuncsik <csaba@n8n.io>
Co-authored-by: OlegIvaniv <me@olegivaniv.com>
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
This commit is contained in:
Alex Grozav
2023-07-28 10:51:07 +03:00
committed by GitHub
parent d050b99fb2
commit dd6a4c956a
459 changed files with 8815 additions and 9913 deletions

View File

@@ -9,10 +9,10 @@
v-else
class="mr-xl"
v-model="autoRefresh"
@change="handleAutoRefreshToggle"
@update:modelValue="handleAutoRefreshToggle"
data-test-id="execution-auto-refresh-checkbox"
>
{{ $locale.baseText('executionsList.autoRefresh') }}
{{ i18n.baseText('executionsList.autoRefresh') }}
</el-checkbox>
<execution-filter
v-show="!isMounting"
@@ -26,13 +26,13 @@
v-if="allVisibleSelected && finishedExecutionsCount > 0"
:class="$style.selectAll"
:label="
$locale.baseText('executionsList.selectAll', {
i18n.baseText('executionsList.selectAll', {
adjustToNumber: finishedExecutionsCount,
interpolate: { executionNum: finishedExecutionsCount },
})
"
:value="allExistingSelected"
@change="handleCheckAllExistingChange"
:modelValue="allExistingSelected"
@update:modelValue="handleCheckAllExistingChange"
data-test-id="select-all-executions-checkbox"
/>
@@ -46,17 +46,17 @@
<tr>
<th>
<el-checkbox
:value="allVisibleSelected"
@change="handleCheckAllVisibleChange"
:modelValue="allVisibleSelected"
@update:modelValue="handleCheckAllVisibleChange"
:disabled="finishedExecutionsCount < 1"
label=""
data-test-id="select-visible-executions-checkbox"
/>
</th>
<th>{{ $locale.baseText('executionsList.name') }}</th>
<th>{{ $locale.baseText('executionsList.startedAt') }}</th>
<th>{{ $locale.baseText('executionsList.status') }}</th>
<th>{{ $locale.baseText('executionsList.id') }}</th>
<th>{{ i18n.baseText('executionsList.name') }}</th>
<th>{{ i18n.baseText('executionsList.startedAt') }}</th>
<th>{{ i18n.baseText('executionsList.status') }}</th>
<th>{{ i18n.baseText('executionsList.id') }}</th>
<th></th>
<th></th>
<th></th>
@@ -72,8 +72,8 @@
<td>
<el-checkbox
v-if="execution.stoppedAt !== undefined && execution.id"
:value="selectedItems[execution.id] || allExistingSelected"
@change="handleCheckboxChanged(execution.id)"
:modelValue="selectedItems[execution.id] || allExistingSelected"
@update:modelValue="handleCheckboxChanged(execution.id)"
label=""
data-test-id="select-execution-checkbox"
/>
@@ -81,7 +81,7 @@
<td>
<span @click.stop="displayExecution(execution)"
><a href="#" :class="$style.link">{{
execution.workflowName || $locale.baseText('executionsList.unsavedWorkflow')
execution.workflowName || i18n.baseText('executionsList.unsavedWorkflow')
}}</a></span
>
</td>
@@ -93,9 +93,10 @@
<span v-if="isRunning(execution)" :class="$style.spinner">
<font-awesome-icon icon="spinner" spin />
</span>
<i18n
<i18n-t
v-if="!isWaitTillIndefinite(execution)"
:path="getStatusTextTranslationPath(execution)"
tag="span"
:keypath="getStatusTextTranslationPath(execution)"
>
<template #status>
<span :class="$style.status">{{ getStatusText(execution) }}</span>
@@ -115,7 +116,7 @@
</span>
<execution-time v-else :start-time="execution.startedAt" />
</template>
</i18n>
</i18n-t>
<n8n-tooltip v-else placement="top">
<template #content>
<span>{{ getStatusTooltipText(execution) }}</span>
@@ -129,13 +130,13 @@
<span v-if="execution.retryOf">
<br />
<small>
({{ $locale.baseText('executionsList.retryOf') }} #{{ execution.retryOf }})
({{ i18n.baseText('executionsList.retryOf') }} #{{ execution.retryOf }})
</small>
</span>
<span v-else-if="execution.retrySuccessId">
<br />
<small>
({{ $locale.baseText('executionsList.successRetry') }} #{{
({{ i18n.baseText('executionsList.successRetry') }} #{{
execution.retrySuccessId
}})
</small>
@@ -144,7 +145,7 @@
<td>
<n8n-tooltip v-if="execution.mode === 'manual'" placement="top">
<template #content>
<span>{{ $locale.baseText('executionsList.test') }}</span>
<span>{{ i18n.baseText('executionsList.test') }}</span>
</template>
<font-awesome-icon icon="flask" />
</n8n-tooltip>
@@ -155,7 +156,7 @@
v-if="execution.stoppedAt !== undefined && execution.id"
size="small"
outline
:label="$locale.baseText('executionsList.view')"
:label="i18n.baseText('executionsList.view')"
@click.stop="displayExecution(execution)"
/>
</div>
@@ -166,7 +167,7 @@
v-if="execution.stoppedAt === undefined || execution.waitTill"
size="small"
outline
:label="$locale.baseText('executionsList.stop')"
:label="i18n.baseText('executionsList.stop')"
@click.stop="stopExecution(execution.id)"
:loading="stoppingExecutions.includes(execution.id)"
/>
@@ -183,7 +184,7 @@
text
type="tertiary"
size="mini"
:title="$locale.baseText('executionsList.retryExecution')"
:title="i18n.baseText('executionsList.retryExecution')"
icon="ellipsis-v"
/>
</span>
@@ -199,20 +200,20 @@
:class="$style.retryAction"
:command="{ command: 'currentlySaved', execution }"
>
{{ $locale.baseText('executionsList.retryWithCurrentlySavedWorkflow') }}
{{ i18n.baseText('executionsList.retryWithCurrentlySavedWorkflow') }}
</el-dropdown-item>
<el-dropdown-item
v-if="isExecutionRetriable(execution)"
:class="$style.retryAction"
:command="{ command: 'original', execution }"
>
{{ $locale.baseText('executionsList.retryWithOriginalWorkflow') }}
{{ i18n.baseText('executionsList.retryWithOriginalWorkflow') }}
</el-dropdown-item>
<el-dropdown-item
:class="$style.deleteAction"
:command="{ command: 'delete', execution }"
>
{{ $locale.baseText('generic.delete') }}
{{ i18n.baseText('generic.delete') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -227,7 +228,7 @@
:class="$style.loadedAll"
data-test-id="execution-list-empty"
>
{{ $locale.baseText('executionsList.empty') }}
{{ i18n.baseText('executionsList.empty') }}
</div>
<div
:class="$style.loadMore"
@@ -237,8 +238,8 @@
>
<n8n-button
icon="sync"
:title="$locale.baseText('executionsList.loadMore')"
:label="$locale.baseText('executionsList.loadMore')"
:title="i18n.baseText('executionsList.loadMore')"
:label="i18n.baseText('executionsList.loadMore')"
@click="loadMore()"
:loading="isDataLoading"
data-test-id="load-more-button"
@@ -249,7 +250,7 @@
:class="$style.loadedAll"
data-test-id="execution-all-loaded"
>
{{ $locale.baseText('executionsList.loadedAll') }}
{{ i18n.baseText('executionsList.loadedAll') }}
</div>
</div>
<div
@@ -259,20 +260,20 @@
>
<span>
{{
$locale.baseText('executionsList.selected', {
i18n.baseText('executionsList.selected', {
adjustToNumber: numSelected,
interpolate: { numSelected },
})
}}
</span>
<n8n-button
:label="$locale.baseText('generic.delete')"
:label="i18n.baseText('generic.delete')"
type="tertiary"
@click="handleDeleteSelected"
data-test-id="delete-selected-button"
/>
<n8n-button
:label="$locale.baseText('executionsList.clearSelection')"
:label="i18n.baseText('executionsList.clearSelection')"
type="tertiary"
@click="handleClearSelection"
data-test-id="clear-selection-button"
@@ -290,7 +291,7 @@ import { externalHooks } from '@/mixins/externalHooks';
import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
import { genericHelpers } from '@/mixins/genericHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
import { useToast, useMessage } from '@/composables';
import { useToast, useMessage, useI18n, useTelemetry } from '@/composables';
import type {
IExecutionsCurrentSummaryExtended,
IExecutionDeleteFilter,
@@ -320,7 +321,12 @@ export default defineComponent({
},
},
setup() {
const i18n = useI18n();
const telemetry = useTelemetry();
return {
i18n,
telemetry,
...useToast(),
...useMessage(),
};
@@ -359,11 +365,11 @@ export default defineComponent({
await this.loadWorkflows();
void this.$externalHooks().run('executionsList.openDialog');
this.$telemetry.track('User opened Executions log', {
this.telemetry.track('User opened Executions log', {
workflow_id: this.workflowsStore.workflowId,
});
},
beforeDestroy() {
beforeUnmount() {
this.stopAutoRefreshInterval();
document.removeEventListener('visibilitychange', this.onDocumentVisibilityChange);
},
@@ -405,7 +411,7 @@ export default defineComponent({
return executionFilterToQueryFilter(this.filter);
},
pageTitle() {
return this.$locale.baseText('executionsList.workflowExecutions');
return this.i18n.baseText('executionsList.workflowExecutions');
},
},
methods: {
@@ -455,16 +461,14 @@ export default defineComponent({
},
async handleDeleteSelected() {
const deleteExecutions = await this.confirm(
this.$locale.baseText('executionsList.confirmMessage.message', {
this.i18n.baseText('executionsList.confirmMessage.message', {
interpolate: { numSelected: this.numSelected.toString() },
}),
this.$locale.baseText('executionsList.confirmMessage.headline'),
this.i18n.baseText('executionsList.confirmMessage.headline'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'executionsList.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText('executionsList.confirmMessage.cancelButtonText'),
confirmButtonText: this.i18n.baseText('executionsList.confirmMessage.confirmButtonText'),
cancelButtonText: this.i18n.baseText('executionsList.confirmMessage.cancelButtonText'),
},
);
@@ -489,7 +493,7 @@ export default defineComponent({
this.isDataLoading = false;
this.showError(
error,
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
this.i18n.baseText('executionsList.showError.handleDeleteSelected.title'),
);
return;
@@ -497,7 +501,7 @@ export default defineComponent({
this.isDataLoading = false;
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.handleDeleteSelected.title'),
title: this.i18n.baseText('executionsList.showMessage.handleDeleteSelected.title'),
type: 'success',
});
@@ -524,7 +528,7 @@ export default defineComponent({
await this.retryExecution(commandData.execution, loadWorkflow);
this.$telemetry.track('User clicked retry execution button', {
this.telemetry.track('User clicked retry execution button', {
workflow_id: this.workflowsStore.workflowId,
execution_id: commandData.execution.id,
retry_type: loadWorkflow ? 'current' : 'original',
@@ -690,7 +694,7 @@ export default defineComponent({
);
} catch (error) {
this.isDataLoading = false;
this.showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
this.showError(error, this.i18n.baseText('executionsList.showError.loadMore.title'));
return;
}
@@ -725,15 +729,12 @@ export default defineComponent({
workflows.unshift({
id: 'all',
name: this.$locale.baseText('executionsList.allWorkflows'),
name: this.i18n.baseText('executionsList.allWorkflows'),
} as IWorkflowShortResponse);
this.workflows = workflows;
} catch (error) {
this.showError(
error,
this.$locale.baseText('executionsList.showError.loadWorkflows.title'),
);
this.showError(error, this.i18n.baseText('executionsList.showError.loadWorkflows.title'));
}
},
async retryExecution(execution: IExecutionsSummary, loadWorkflow?: boolean) {
@@ -747,22 +748,19 @@ export default defineComponent({
if (retrySuccessful) {
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
title: this.i18n.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
type: 'success',
});
} else {
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
title: this.i18n.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
type: 'error',
});
}
this.isDataLoading = false;
} catch (error) {
this.showError(
error,
this.$locale.baseText('executionsList.showError.retryExecution.title'),
);
this.showError(error, this.i18n.baseText('executionsList.showError.retryExecution.title'));
this.isDataLoading = false;
}
@@ -773,7 +771,7 @@ export default defineComponent({
try {
await Promise.all([this.loadActiveExecutions(), this.loadFinishedExecutions()]);
} catch (error) {
this.showError(error, this.$locale.baseText('executionsList.showError.refreshData.title'));
this.showError(error, this.i18n.baseText('executionsList.showError.refreshData.title'));
}
this.isDataLoading = false;
@@ -806,21 +804,21 @@ export default defineComponent({
let text = '';
if (status === 'waiting') {
text = this.$locale.baseText('executionsList.waiting');
text = this.i18n.baseText('executionsList.waiting');
} else if (status === 'canceled') {
text = this.$locale.baseText('executionsList.canceled');
text = this.i18n.baseText('executionsList.canceled');
} else if (status === 'crashed') {
text = this.$locale.baseText('executionsList.error');
text = this.i18n.baseText('executionsList.error');
} else if (status === 'new') {
text = this.$locale.baseText('executionsList.running');
text = this.i18n.baseText('executionsList.running');
} else if (status === 'running') {
text = this.$locale.baseText('executionsList.running');
text = this.i18n.baseText('executionsList.running');
} else if (status === 'success') {
text = this.$locale.baseText('executionsList.succeeded');
text = this.i18n.baseText('executionsList.succeeded');
} else if (status === 'failed') {
text = this.$locale.baseText('executionsList.error');
text = this.i18n.baseText('executionsList.error');
} else {
text = this.$locale.baseText('executionsList.unknown');
text = this.i18n.baseText('executionsList.unknown');
}
return text;
@@ -854,7 +852,7 @@ export default defineComponent({
let text = '';
if (status === 'waiting' && this.isWaitTillIndefinite(entry)) {
text = this.$locale.baseText(
text = this.i18n.baseText(
'executionsList.statusTooltipText.theWorkflowIsWaitingIndefinitely',
);
}
@@ -874,8 +872,8 @@ export default defineComponent({
this.stoppingExecutions.splice(index, 1);
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.stopExecution.title'),
message: this.$locale.baseText('executionsList.showMessage.stopExecution.message', {
title: this.i18n.baseText('executionsList.showMessage.stopExecution.title'),
message: this.i18n.baseText('executionsList.showMessage.stopExecution.message', {
interpolate: { activeExecutionId },
}),
type: 'success',
@@ -883,10 +881,7 @@ export default defineComponent({
await this.refreshData();
} catch (error) {
this.showError(
error,
this.$locale.baseText('executionsList.showError.stopExecution.title'),
);
this.showError(error, this.i18n.baseText('executionsList.showError.stopExecution.title'));
}
},
isExecutionRetriable(execution: IExecutionsSummary): boolean {
@@ -911,7 +906,7 @@ export default defineComponent({
} catch (error) {
this.showError(
error,
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
this.i18n.baseText('executionsList.showError.handleDeleteSelected.title'),
);
}
this.isDataLoading = true;