fix(editor): Execution page bug fixes (#5122)

* fix(editor): Global exec list adding tooltips

* fix(editor): Global exec list fix indefinite waiting status display

* fix(editor): Global exec list fix indefinite waiting status display

* fix(editor): Global exec list remove ellipsis menu from running execs
This commit is contained in:
Csaba Tuncsik 2023-01-13 12:42:34 +01:00 committed by GitHub
parent 14454243e7
commit 665eaef925
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 50 deletions

View file

@ -60,6 +60,7 @@
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@ -86,10 +87,13 @@
</td>
<td>
<div :class="$style.statusColumn">
<span v-if="execution.stoppedAt === undefined" :class="$style.spinner">
<span v-if="isRunning(execution)" :class="$style.spinner">
<font-awesome-icon icon="spinner" spin />
</span>
<i18n :path="getStatusTextTranslationPath(execution)">
<i18n
v-if="!isWaitTillIndefinite(execution)"
:path="getStatusTextTranslationPath(execution)"
>
<template #status>
<span :class="$style.status">{{ getStatusText(execution) }}</span>
</template>
@ -109,6 +113,12 @@
<execution-time v-else :start-time="execution.startedAt" />
</template>
</i18n>
<n8n-tooltip v-else placement="top">
<template #content>
<span>{{ getStatusTooltipText(execution) }}</span>
</template>
<span :class="$style.status">{{ getStatusText(execution) }}</span>
</n8n-tooltip>
</div>
</td>
<td>
@ -129,18 +139,15 @@
</span>
</td>
<td>
<font-awesome-icon v-if="execution.mode === 'manual'" icon="flask" />
<n8n-tooltip v-if="execution.mode === 'manual'" placement="top">
<template #content>
<span>{{ $locale.baseText('executionsList.test') }}</span>
</template>
<font-awesome-icon icon="flask" />
</n8n-tooltip>
</td>
<td>
<div :class="$style.actionsContainer">
<n8n-button
v-if="execution.stoppedAt === undefined || execution.waitTill"
size="small"
outline
:label="$locale.baseText('executionsList.stop')"
@click.stop="stopExecution(execution.id)"
:loading="stoppingExecutions.includes(execution.id)"
/>
<div :class="$style.buttonCell">
<n8n-button
v-if="execution.stoppedAt !== undefined && execution.id"
size="small"
@ -151,7 +158,23 @@
</div>
</td>
<td>
<el-dropdown trigger="click" @command="handleActionItemClick">
<div :class="$style.buttonCell">
<n8n-button
v-if="execution.stoppedAt === undefined || execution.waitTill"
size="small"
outline
:label="$locale.baseText('executionsList.stop')"
@click.stop="stopExecution(execution.id)"
:loading="stoppingExecutions.includes(execution.id)"
/>
</div>
</td>
<td>
<el-dropdown
v-if="!isRunning(execution)"
trigger="click"
@command="handleActionItemClick"
>
<span class="retry-button">
<n8n-icon-button
text
@ -235,7 +258,7 @@ import Vue from 'vue';
import ExecutionTime from '@/components/ExecutionTime.vue';
import WorkflowActivator from '@/components/WorkflowActivator.vue';
import { externalHooks } from '@/mixins/externalHooks';
import { VIEWS } from '@/constants';
import { VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
import { restApi } from '@/mixins/restApi';
import { genericHelpers } from '@/mixins/genericHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
@ -254,6 +277,8 @@ import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui';
import { useWorkflowsStore } from '@/stores/workflows';
type ExecutionStatus = 'failed' | 'success' | 'waiting' | 'running' | 'unknown';
export default mixins(externalHooks, genericHelpers, executionHelpers, restApi, showMessage).extend(
{
name: 'ExecutionsList',
@ -528,22 +553,6 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
this.deleteExecution(commandData.execution);
}
},
getRowClass(execution: IExecutionsSummary): string {
const classes: string[] = [this.$style.execRow];
if (execution.waitTill) {
classes.push(this.$style.waiting);
} else if (execution.stoppedAt === undefined) {
classes.push(this.$style.running);
} else if (execution.finished) {
classes.push(this.$style.success);
} else if (execution.stoppedAt !== null) {
classes.push(this.$style.failed);
} else {
classes.push(this.$style.unknown);
}
return classes.join(' ');
},
getWorkflowName(workflowId: string): string | undefined {
const workflow = this.workflows.find((data) => data.id === workflowId);
if (workflow === undefined) {
@ -784,16 +793,35 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
this.isDataLoading = false;
},
getStatus(execution: IExecutionsSummary): ExecutionStatus {
let status: ExecutionStatus = 'unknown';
if (execution.waitTill) {
status = 'waiting';
} else if (execution.stoppedAt === undefined) {
status = 'running';
} else if (execution.finished) {
status = 'success';
} else if (execution.stoppedAt !== null) {
status = 'failed';
} else {
status = 'unknown';
}
return status;
},
getRowClass(execution: IExecutionsSummary): string {
return [this.$style.execRow, this.$style[this.getStatus(execution)]].join(' ');
},
getStatusText(entry: IExecutionsSummary): string {
const status = this.getStatus(entry);
let text = '';
if (entry.waitTill) {
if (status === 'waiting') {
text = this.$locale.baseText('executionsList.waiting');
} else if (entry.stoppedAt === undefined) {
} else if (status === 'running') {
text = this.$locale.baseText('executionsList.running');
} else if (entry.finished) {
} else if (status === 'success') {
text = this.$locale.baseText('executionsList.succeeded');
} else if (entry.stoppedAt !== null) {
} else if (status === 'failed') {
text = this.$locale.baseText('executionsList.error');
} else {
text = this.$locale.baseText('executionsList.unknown');
@ -802,15 +830,16 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
return text;
},
getStatusTextTranslationPath(entry: IExecutionsSummary): string {
const status = this.getStatus(entry);
let path = '';
if (entry.waitTill) {
if (status === 'waiting') {
path = 'executionsList.statusWaiting';
} else if (entry.stoppedAt === undefined) {
} else if (status === 'running') {
path = 'executionsList.statusRunning';
} else if (entry.finished) {
} else if (status === 'success') {
path = 'executionsList.statusText';
} else if (entry.stoppedAt !== null) {
} else if (status === 'failed') {
path = 'executionsList.statusText';
} else {
path = 'executionsList.statusUnknown';
@ -818,6 +847,18 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
return path;
},
getStatusTooltipText(entry: IExecutionsSummary): string {
const status = this.getStatus(entry);
let text = '';
if (status === 'waiting' && this.isWaitTillIndefinite(entry)) {
text = this.$locale.baseText(
'executionsList.statusTooltipText.theWorkflowIsWaitingIndefinitely',
);
}
return text;
},
async stopExecution(activeExecutionId: string) {
try {
// Add it to the list of currently stopping executions that we
@ -868,6 +909,15 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
}
this.isDataLoading = true;
},
isWaitTillIndefinite(execution: IExecutionsSummary): boolean {
if (!execution.waitTill) {
return false;
}
return new Date(execution.waitTill).toISOString() === WAIT_TIME_UNLIMITED;
},
isRunning(execution: IExecutionsSummary): boolean {
return this.getStatus(execution) === 'running';
},
},
},
);
@ -936,6 +986,10 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
color: var(--color-danger);
}
.waiting & {
color: var(--color-secondary);
}
.success & {
font-weight: var(--font-weight-normal);
}
@ -949,7 +1003,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
}
}
.actionsContainer {
.buttonCell {
overflow: hidden;
button {
@ -960,10 +1014,6 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, restApi,
.execRow:hover & {
transform: translateX(0);
}
&:not(:first-child) {
margin-left: 5px;
}
}
}

View file

@ -64,12 +64,16 @@
activatorIcon="redo"
@select="onRetryMenuItemSelect"
/>
<font-awesome-icon
v-if="execution.mode === 'manual'"
:class="[$style.icon, $style.manual]"
:title="$locale.baseText('executionsList.manual')"
icon="flask"
/>
<n8n-tooltip v-if="execution.mode === 'manual'" placement="top">
<template #content>
<span>{{ $locale.baseText('executionsList.test') }}</span>
</template>
<font-awesome-icon
v-if="execution.mode === 'manual'"
:class="[$style.icon, $style.manual]"
icon="flask"
/>
</n8n-tooltip>
</div>
</router-link>
</div>

View file

@ -454,7 +454,7 @@
"executionsList.selectStatus": "Select Status",
"executionsList.selectWorkflow": "Select Workflow",
"executionsList.selected": "{numSelected} execution selected:",
"executionsList.manual": "Manual execution",
"executionsList.test": "Test execution",
"executionsList.showError.handleDeleteSelected.title": "Problem deleting executions",
"executionsList.showError.loadMore.title": "Problem loading executions",
"executionsList.showError.loadWorkflows.title": "Problem loading workflows",
@ -484,6 +484,7 @@
"executionsList.workflowExecutions": "Workflow Executions",
"executionsList.view": "View",
"executionsList.stop": "Stop",
"executionsList.statusTooltipText.theWorkflowIsWaitingIndefinitely": "The workflow is waiting indefinitely for an incoming webhook call.",
"executionSidebar.executionName": "Execution {id}",
"executionSidebar.searchPlaceholder": "Search executions...",
"executionView.onPaste.title": "Cannot paste here",