Improve workflow activation (#2692)

* feat: activator disabled based on thiggers

* feat: tooltip over inactive switch

* feat: message for trigger types

* feat: deactivate on save if trigger is removed

* chore: refactor executions modal

* feat: calculate service name if possible

* feat: alert on activation

* chore: fix linting

* feat: always enable activator when active

* fix: adjust the alert

* feat: take disabled state into account

* feat: automatically save on activation

* feat: rely on nodes name and edit messages

* feat: isolate state for each activator instance

* feat: create activation modal component

* feat: activationModal checkbox and trigger message

* feat: add activation messages to node config

* chore: style activation modal

* chore: style fixes

* feat: refactor disabled state

* chore: refactor modal

* chore: refactor modal

* chore: tidy the node config

* chore: refactor and styling tweaks

* chore: minor fixes

* fix: check webhooks from ui nodes

* chore: remove saving prompt

* chore: explicit current workflow evaluation

* feat: add settings link to activation modal

* fix: immediately load executions on render

* feat: exclude error trigger from trigger nodes

* chore: add i18n keys

* fix: check localstorage more strictly

* fix: handle refresh in execution list

* remove unnessary event

* remove comment

* fix closing executions modal bugs

* update closing

* update translation key

* fix translation keys

* fix modal closing

* fix closing

* fix drawer closing

* close all modals when opening executions

* update key

* close all modals when opening workflow or new page

* delete unnessary comment

* clean up import

* clean up unnessary initial data

* clean up activator impl

* rewrite

* fix open modal bug

* simply remove error

* refactor activation logic

* fix i18n and such

* remove changes

* revert saving changes

* Revert "revert saving changes"

25c29d10553ebcc11939ff29938e8a5ac6b3ffae

* add translation

* fix new workflows saving

* clean up modal impl

* clean up impl

* refactor common code out

* remove active changes from saving

* refactor differently

* revert unnessary change

* set dirty false

* fix i18n bug

* avoid opening two modals

* fix tooltips

* add comment

* address other comments

* address comments

Co-authored-by: saintsebastian <tilitidam@gmail.com>
This commit is contained in:
Mutasem Aldmour
2022-01-21 18:00:00 +01:00
committed by GitHub
parent a9cef48048
commit 49bf786e5b
25 changed files with 372 additions and 174 deletions

View File

@@ -1,19 +1,22 @@
<template>
<div class="workflow-activator">
<el-switch
v-loading="loading"
element-loading-spinner="el-icon-loading"
:value="workflowActive"
@change="activeChanged"
:title="workflowActive ? $locale.baseText('workflowActivator.deactivateWorkflow') : $locale.baseText('workflowActivator.activateWorkflow')"
:disabled="disabled || loading"
:active-color="getActiveColor"
inactive-color="#8899AA">
</el-switch>
<n8n-tooltip :disabled="!disabled" placement="bottom">
<div slot="content">{{ $locale.baseText('workflowActivator.thisWorkflowHasNoTriggerNodes') }}</div>
<el-switch
v-loading="loading"
:value="workflowActive"
@change="activeChanged"
:title="workflowActive ? $locale.baseText('workflowActivator.deactivateWorkflow') : $locale.baseText('workflowActivator.activateWorkflow')"
:disabled="disabled || loading"
:active-color="getActiveColor"
inactive-color="#8899AA"
element-loading-spinner="el-icon-loading">
</el-switch>
</n8n-tooltip>
<div class="could-not-be-started" v-if="couldNotBeStarted">
<n8n-tooltip placement="top">
<div @click="displayActivationError" slot="content">{{ $locale.baseText('workflowActivator.theWorkflowIsSetToBeActiveBut') }}</div>
<div @click="displayActivationError" slot="content" v-html="$locale.baseText('workflowActivator.theWorkflowIsSetToBeActiveBut')"></div>
<font-awesome-icon @click="displayActivationError" icon="exclamation-triangle" />
</n8n-tooltip>
</div>
@@ -27,13 +30,17 @@ import { genericHelpers } from '@/components/mixins/genericHelpers';
import { restApi } from '@/components/mixins/restApi';
import { showMessage } from '@/components/mixins/showMessage';
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
import {
IWorkflowDataUpdate,
} from '../Interface';
import mixins from 'vue-typed-mixins';
import { mapGetters } from "vuex";
import {
WORKFLOW_ACTIVE_MODAL_KEY,
LOCAL_STORAGE_ACTIVATION_FLAG,
} from '@/constants';
import { getActivatableTriggerNodes } from './helpers';
export default mixins(
externalHooks,
genericHelpers,
@@ -45,7 +52,6 @@ export default mixins(
{
name: 'WorkflowActivator',
props: [
'disabled',
'workflowActive',
'workflowId',
],
@@ -74,59 +80,47 @@ export default mixins(
}
return '#13ce66';
},
isCurrentWorkflow(): boolean {
return this.$store.getters['workflowId'] === this.workflowId;
},
disabled(): boolean {
const isNewWorkflow = !this.workflowId;
if (isNewWorkflow || this.isCurrentWorkflow) {
return !this.workflowActive && !this.containsTrigger;
}
return false;
},
containsTrigger(): boolean {
const foundTriggers = getActivatableTriggerNodes(this.$store.getters.workflowTriggerNodes);
return foundTriggers.length > 0;
},
},
methods: {
async activeChanged (newActiveState: boolean) {
if (this.workflowId === undefined) {
this.$showMessage({
title: this.$locale.baseText('workflowActivator.showMessage.activeChangedWorkflowIdUndefined.title'),
message: this.$locale.baseText('workflowActivator.showMessage.activeChangedWorkflowIdUndefined.message'),
type: 'error',
});
return;
}
if (this.nodesIssuesExist === true) {
this.$showMessage({
title: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title'),
message: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.message'),
type: 'error',
});
return;
}
// Set that the active state should be changed
let data: IWorkflowDataUpdate = {};
const activeWorkflowId = this.$store.getters.workflowId;
if (newActiveState === true && this.workflowId === activeWorkflowId) {
// If the currently active workflow gets activated save the whole
// workflow. If that would not happen then it could be quite confusing
// for people because it would activate a different version of the workflow
// than the one they can currently see.
if (this.dirtyState) {
const importConfirm = await this.confirmMessage(
this.$locale.baseText('workflowActivator.confirmMessage.message'),
this.$locale.baseText('workflowActivator.confirmMessage.headline'),
'warning',
this.$locale.baseText('workflowActivator.confirmMessage.confirmButtonText'),
this.$locale.baseText('workflowActivator.confirmMessage.cancelButtonText'),
);
if (importConfirm === false) {
return;
}
}
// Get the current workflow data that it gets saved together with the activation
data = await this.getWorkflowDataToSave();
}
data.active = newActiveState;
this.loading = true;
if (!this.workflowId) {
const saved = await this.saveCurrentWorkflow();
if (!saved) {
this.loading = false;
return;
}
}
try {
await this.restApi().updateWorkflow(this.workflowId, data);
if (this.isCurrentWorkflow && this.nodesIssuesExist) {
this.$showMessage({
title: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title'),
message: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.message'),
type: 'error',
});
this.loading = false;
return;
}
await this.updateWorkflow({workflowId: this.workflowId, active: newActiveState});
} catch (error) {
const newStateName = newActiveState === true ? 'activated' : 'deactivated';
this.$showError(
@@ -141,27 +135,21 @@ export default mixins(
return;
}
const currentWorkflowId = this.$store.getters.workflowId;
let activationEventName = 'workflow.activeChange';
if (currentWorkflowId === this.workflowId) {
// If the status of the current workflow got changed
// commit it specifically
this.$store.commit('setActive', newActiveState);
activationEventName = 'workflow.activeChangeCurrent';
}
if (newActiveState === true) {
this.$store.commit('setWorkflowActive', this.workflowId);
} else {
this.$store.commit('setWorkflowInactive', this.workflowId);
}
const activationEventName = this.isCurrentWorkflow ? 'workflow.activeChangeCurrent' : 'workflow.activeChange';
this.$externalHooks().run(activationEventName, { workflowId: this.workflowId, active: newActiveState });
this.$telemetry.track('User set workflow active status', { workflow_id: this.workflowId, is_active: newActiveState });
this.$emit('workflowActiveChanged', { id: this.workflowId, active: newActiveState });
this.loading = false;
this.$store.dispatch('settings/fetchPromptsData');
if (this.isCurrentWorkflow) {
if (newActiveState && window.localStorage.getItem(LOCAL_STORAGE_ACTIVATION_FLAG) !== 'true') {
this.$store.dispatch('ui/openModal', WORKFLOW_ACTIVE_MODAL_KEY);
}
else {
this.$store.dispatch('settings/fetchPromptsData');
}
}
},
async displayActivationError () {
let errorMessage: string;
@@ -192,7 +180,8 @@ export default mixins(
);
</script>
<style scoped>
<style lang="scss" scoped>
.workflow-activator {
display: inline-block;
}
@@ -206,4 +195,5 @@ export default mixins(
::v-deep .el-loading-spinner {
margin-top: -10px;
}
</style>