mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
* refactor(editor): Turn showMessage mixin to composable (#6081) * refactor(editor): move $getExecutionError from showMessages mixin to pushConnection (it is used there only) * refactor(editor): resolve showMessage mixin methods * fix(editor): use composable instead of mixin * fix(editor): resolve conflicts * fix(editor): replace clearAllStickyNotifications * fix(editor): replace confirmMessage * fix(editor): replace confirmMessage * fix(editor): replace confirmMessage * fix(editor): remove last confirmMessage usage * fix(editor): remove $prompt usage * fix(editor): remove $show methods * fix(editor): lint fix * fix(editor): lint fix * fix(editor): fixes after review * fix(editor): Fix external hook call in App * fix(editor): mixins & composables * fix: add pushConnection setup composables to components as well * fix(editor): mixins & composables * fix(editor): mixins & composables * fix: add void on non-await async calls * fix: fix close without connecting confirmation * fix: remove .only --------- Co-authored-by: Alex Grozav <alex@grozav.com>
267 lines
5.9 KiB
Vue
267 lines
5.9 KiB
Vue
<template>
|
|
<div
|
|
:class="{
|
|
['execution-card']: true,
|
|
[$style.executionCard]: true,
|
|
[$style.active]: isActive,
|
|
[$style[executionUIDetails.name]]: true,
|
|
[$style.highlight]: highlight,
|
|
[$style.showGap]: showGap,
|
|
}"
|
|
>
|
|
<router-link
|
|
:class="$style.executionLink"
|
|
:to="{
|
|
name: VIEWS.EXECUTION_PREVIEW,
|
|
params: { workflowId: currentWorkflow, executionId: execution.id },
|
|
}"
|
|
:data-test-execution-status="executionUIDetails.name"
|
|
>
|
|
<div :class="$style.description">
|
|
<n8n-text color="text-dark" :bold="true" size="medium" data-test-id="execution-time">
|
|
{{ executionUIDetails.startTime }}
|
|
</n8n-text>
|
|
<div :class="$style.executionStatus">
|
|
<n8n-spinner
|
|
v-if="executionUIDetails.name === 'running'"
|
|
size="small"
|
|
:class="[$style.spinner, 'mr-4xs']"
|
|
/>
|
|
<n8n-text :class="$style.statusLabel" size="small">{{
|
|
executionUIDetails.label
|
|
}}</n8n-text>
|
|
<n8n-text
|
|
v-if="executionUIDetails.name === 'running'"
|
|
:color="isActive ? 'text-dark' : 'text-base'"
|
|
size="small"
|
|
>
|
|
{{ $locale.baseText('executionDetails.runningTimeRunning') }}
|
|
<execution-time :start-time="execution.startedAt" />
|
|
</n8n-text>
|
|
<n8n-text
|
|
v-else-if="executionUIDetails.runningTime !== ''"
|
|
:color="isActive ? 'text-dark' : 'text-base'"
|
|
size="small"
|
|
>
|
|
{{
|
|
$locale.baseText('executionDetails.runningTimeFinished', {
|
|
interpolate: { time: executionUIDetails?.runningTime },
|
|
})
|
|
}}
|
|
</n8n-text>
|
|
</div>
|
|
<div v-if="execution.mode === 'retry'">
|
|
<n8n-text :color="isActive ? 'text-dark' : 'text-base'" size="small">
|
|
{{ $locale.baseText('executionDetails.retry') }} #{{ execution.retryOf }}
|
|
</n8n-text>
|
|
</div>
|
|
</div>
|
|
<div :class="$style.icons">
|
|
<n8n-action-dropdown
|
|
v-if="executionUIDetails.name === 'error'"
|
|
:class="[$style.icon, $style.retry]"
|
|
:items="retryExecutionActions"
|
|
activatorIcon="redo"
|
|
data-test-id="retry-execution-button"
|
|
@select="onRetryMenuItemSelect"
|
|
/>
|
|
<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>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import type { IExecutionsSummary } from '@/Interface';
|
|
import mixins from 'vue-typed-mixins';
|
|
import type { IExecutionUIData } from '@/mixins/executionsHelpers';
|
|
import { executionHelpers } from '@/mixins/executionsHelpers';
|
|
import { VIEWS } from '@/constants';
|
|
import ExecutionTime from '@/components/ExecutionTime.vue';
|
|
|
|
export default mixins(executionHelpers).extend({
|
|
name: 'execution-card',
|
|
components: {
|
|
ExecutionTime,
|
|
},
|
|
data() {
|
|
return {
|
|
VIEWS,
|
|
};
|
|
},
|
|
props: {
|
|
execution: {
|
|
type: Object as () => IExecutionsSummary,
|
|
required: true,
|
|
},
|
|
highlight: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
showGap: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
computed: {
|
|
retryExecutionActions(): object[] {
|
|
return [
|
|
{
|
|
id: 'current-workflow',
|
|
label: this.$locale.baseText('executionsList.retryWithCurrentlySavedWorkflow'),
|
|
},
|
|
{
|
|
id: 'original-workflow',
|
|
label: this.$locale.baseText('executionsList.retryWithOriginalWorkflow'),
|
|
},
|
|
];
|
|
},
|
|
executionUIDetails(): IExecutionUIData {
|
|
return this.getExecutionUIDetails(this.execution);
|
|
},
|
|
isActive(): boolean {
|
|
return this.execution.id === this.$route.params.executionId;
|
|
},
|
|
},
|
|
methods: {
|
|
onRetryMenuItemSelect(action: string): void {
|
|
this.$emit('retryExecution', { execution: this.execution, command: action });
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style module lang="scss">
|
|
.executionCard {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding-right: var(--spacing-m);
|
|
|
|
&.active {
|
|
border-left: var(--spacing-4xs) var(--border-style-base) transparent !important;
|
|
|
|
.executionStatus {
|
|
color: var(--color-text-dark) !important;
|
|
}
|
|
}
|
|
|
|
&:hover,
|
|
&.active {
|
|
.executionLink {
|
|
background-color: var(--color-foreground-light);
|
|
}
|
|
}
|
|
|
|
&.running {
|
|
.spinner {
|
|
position: relative;
|
|
top: 1px;
|
|
}
|
|
&,
|
|
& .executionLink {
|
|
border-left: var(--spacing-4xs) var(--border-style-base) hsl(var(--color-warning-h), 94%, 80%);
|
|
}
|
|
.statusLabel,
|
|
.spinner {
|
|
color: var(--color-warning);
|
|
}
|
|
}
|
|
|
|
&.success {
|
|
&,
|
|
& .executionLink {
|
|
border-left: var(--spacing-4xs) var(--border-style-base) hsl(var(--color-success-h), 60%, 70%);
|
|
}
|
|
}
|
|
|
|
&.waiting {
|
|
&,
|
|
& .executionLink {
|
|
border-left: var(--spacing-4xs) var(--border-style-base)
|
|
hsl(var(--color-secondary-h), 94%, 80%);
|
|
}
|
|
.statusLabel {
|
|
color: var(--color-secondary);
|
|
}
|
|
}
|
|
|
|
&.error {
|
|
&,
|
|
& .executionLink {
|
|
border-left: var(--spacing-4xs) var(--border-style-base) hsl(var(--color-danger-h), 94%, 80%);
|
|
}
|
|
.statusLabel {
|
|
color: var(--color-danger);
|
|
}
|
|
}
|
|
|
|
&.unknown {
|
|
&,
|
|
& .executionLink {
|
|
border-left: var(--spacing-4xs) var(--border-style-base) var(--color-text-light);
|
|
}
|
|
}
|
|
}
|
|
|
|
.executionLink {
|
|
display: flex;
|
|
width: 100%;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
color: var(--color-text-base);
|
|
font-size: var(--font-size-xs);
|
|
padding: var(--spacing-xs);
|
|
padding-right: var(--spacing-s);
|
|
position: relative;
|
|
left: calc(
|
|
-1 * var(--spacing-4xs)
|
|
); // Hide link border under card border so it's not visible when not hovered
|
|
|
|
&:active {
|
|
.icon,
|
|
.statusLabel {
|
|
color: var(--color-text-base);
|
|
}
|
|
}
|
|
}
|
|
|
|
.icons {
|
|
display: flex;
|
|
align-items: baseline;
|
|
}
|
|
|
|
.icon {
|
|
font-size: var(--font-size-s);
|
|
|
|
&.retry {
|
|
svg {
|
|
color: var(--color-primary);
|
|
}
|
|
}
|
|
|
|
&.manual {
|
|
position: relative;
|
|
top: 1px;
|
|
}
|
|
|
|
& + & {
|
|
margin-left: var(--spacing-2xs);
|
|
}
|
|
}
|
|
.showGap {
|
|
margin-bottom: var(--spacing-2xs);
|
|
.executionLink {
|
|
border-bottom: 1px solid var(--color-foreground-dark);
|
|
}
|
|
}
|
|
</style>
|