feat(editor): Improve trigger panel (#3509)

* add panel

* add workflow activation hints

* support service trigger nodes

* update polling state

* support more views

* update when trigger panel shows

* update start/error nodes

* add cron/interval info box

* clean up start node

* fix up webhook views

* remove console log

* add listening state

* clean up loading state

* update loading state

* fix up animation

* update views

* add executions hint

* update views

* update accordian styling

* address more issues

* disable execute button if issues

* disable if it has issues

* add stop waiting button

* can activate workflow when dsiabled

* update el

* fix has issues

* add margin bttm

* update views

* close ndv

* add shake

* update copies

* add error when polling node is missing one

* update package lock

* hide switch

* hide binary data that's missing keys

* hide main bar if ndv is open

* remove waiting to execute

* change accordion bg color

* capitalize text

* disable trigger panel in read only views

* remove webhook title

* update webhook desc

* update component

* update webhook executions note

* update header

* update webhook url

* update exec help

* bring back waiting to execute for non triggers

* add transition fade

* set shake

* add helpful tooltip

* add nonactive text

* add inactive text

* hide trigger panel by default

* remove unused import

* update pulse animation

* handle empty values for options

* update text

* add flag for mock manual executions

* add overrides

* Add overrides

* update check

* update package lock; show button for others

* hide more info

* update other core nodes

* update service name

* remove panel from nodes

* update panel

* last tweaks

* add telemetry event

* add telemetry; address issues

* address feedback

* address feedback

* address feedback

* fix previous

* fix previous

* fix bug

* fix bug with webhookbased

* add extra break

* update telemetry

* update telemetry

* add telemetry req

* add info icon story; use icon component

* clean css; en.json

* clean en.json

* rename key

* add key

* sort keys alpha

* handle activation if active + add previous state to telemetry

* stop activation if active

* remove unnessary tracking

* remove unused import

* remove unused

* remove unnessary flag

* rewrite in ts

* move pulse to design system

* clean up

* clean up

* clean up

* disable tslint check

* disable tslint check
This commit is contained in:
Mutasem Aldmour
2022-06-20 21:39:24 +02:00
committed by GitHub
parent 88dea330b9
commit a2f628927d
43 changed files with 44574 additions and 108041 deletions

View File

@@ -17,6 +17,7 @@ import { workflowHelpers } from '@/components/mixins/workflowHelpers';
import mixins from 'vue-typed-mixins';
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
import { getTriggerNodeServiceName } from '../helpers';
export const pushConnection = mixins(
externalHooks,
@@ -266,10 +267,29 @@ export const pushConnection = mixins(
const execution = this.$store.getters.getWorkflowExecution;
if (execution && execution.executedNode) {
this.$showMessage({
title: this.$locale.baseText('pushConnection.nodeExecutedSuccessfully'),
type: 'success',
});
const node = this.$store.getters.getNodeByName(execution.executedNode);
const nodeType = node && this.$store.getters.nodeType(node.type, node.typeVersion);
const nodeOutput = execution && execution.executedNode && execution.data && execution.data.resultData && execution.data.resultData.runData && execution.data.resultData.runData[execution.executedNode];
if (node && nodeType && !nodeOutput) {
this.$showMessage({
title: this.$locale.baseText('pushConnection.pollingNode.dataNotFound', {
interpolate: {
service: getTriggerNodeServiceName(nodeType),
},
}),
message: this.$locale.baseText('pushConnection.pollingNode.dataNotFound.message', {
interpolate: {
service: getTriggerNodeServiceName(nodeType),
},
}),
type: 'success',
});
} else {
this.$showMessage({
title: this.$locale.baseText('pushConnection.nodeExecutedSuccessfully'),
type: 'success',
});
}
}
else {
this.$showMessage({

View File

@@ -0,0 +1,98 @@
import { externalHooks } from '@/components/mixins/externalHooks';
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
import { showMessage } from '@/components/mixins/showMessage';
import mixins from 'vue-typed-mixins';
import { LOCAL_STORAGE_ACTIVATION_FLAG, PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_ACTIVE_MODAL_KEY } from '@/constants';
export const workflowActivate = mixins(
externalHooks,
workflowHelpers,
showMessage,
)
.extend({
data() {
return {
updatingWorkflowActivation: false,
};
},
methods: {
async activateCurrentWorkflow(telemetrySource?: string) {
const workflowId = this.$store.getters.workflowId;
return this.updateWorkflowActivation(workflowId, true, telemetrySource);
},
async updateWorkflowActivation(workflowId: string | undefined, newActiveState: boolean, telemetrySource?: string) {
this.updatingWorkflowActivation = true;
const nodesIssuesExist = this.$store.getters.nodesIssuesExist as boolean;
let currWorkflowId: string | undefined = workflowId;
if (!currWorkflowId || currWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
const saved = await this.saveCurrentWorkflow();
if (!saved) {
this.updatingWorkflowActivation = false;
return;
}
currWorkflowId = this.$store.getters.workflowId as string;
}
const isCurrentWorkflow = currWorkflowId === this.$store.getters['workflowId'];
const activeWorkflows = this.$store.getters.getActiveWorkflows;
const isWorkflowActive = activeWorkflows.includes(currWorkflowId);
this.$telemetry.track('User set workflow active status', { workflow_id: currWorkflowId, is_active: newActiveState, previous_status: isWorkflowActive, ndv_input: telemetrySource === 'ndv' });
try {
if (isWorkflowActive && newActiveState) {
this.$showMessage({
title: this.$locale.baseText('workflowActivator.workflowIsActive'),
type: 'success',
});
this.updatingWorkflowActivation = false;
return;
}
if (isCurrentWorkflow && nodesIssuesExist) {
this.$showMessage({
title: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title'),
message: this.$locale.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.message'),
type: 'error',
});
this.updatingWorkflowActivation = false;
return;
}
await this.updateWorkflow({workflowId: currWorkflowId, active: newActiveState});
} catch (error) {
const newStateName = newActiveState === true ? 'activated' : 'deactivated';
this.$showError(
error,
this.$locale.baseText(
'workflowActivator.showError.title',
{ interpolate: { newStateName } },
) + ':',
);
this.updatingWorkflowActivation = false;
return;
}
const activationEventName = isCurrentWorkflow ? 'workflow.activeChangeCurrent' : 'workflow.activeChange';
this.$externalHooks().run(activationEventName, { workflowId: currWorkflowId, active: newActiveState });
this.$emit('workflowActiveChanged', { id: currWorkflowId, active: newActiveState });
this.updatingWorkflowActivation = false;
if (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');
}
}
},
},
});

View File

@@ -29,6 +29,7 @@ import {
NodeHelpers,
IExecuteData,
INodeConnection,
IWebhookDescription,
} from 'n8n-workflow';
import {
@@ -428,6 +429,33 @@ export const workflowHelpers = mixins(
return nodeData;
},
getWebhookExpressionValue (webhookData: IWebhookDescription, key: string): string {
if (webhookData[key] === undefined) {
return 'empty';
}
try {
return this.resolveExpression(webhookData[key] as string) as string;
} catch (e) {
return this.$locale.baseText('nodeWebhooks.invalidExpression');
}
},
getWebhookUrl (webhookData: IWebhookDescription, node: INode, showUrlFor?: string): string {
if (webhookData.restartWebhook === true) {
return '$resumeWebhookUrl';
}
let baseUrl = this.$store.getters.getWebhookUrl;
if (showUrlFor === 'test') {
baseUrl = this.$store.getters.getWebhookTestUrl;
}
const workflowId = this.$store.getters.workflowId;
const path = this.getWebhookExpressionValue(webhookData, 'path');
const isFullPath = this.getWebhookExpressionValue(webhookData, 'isFullPath') as unknown as boolean || false;
return NodeHelpers.getNodeWebhookUrl(baseUrl, workflowId, node, path, isFullPath);
},
resolveParameter(parameter: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) {
const itemIndex = 0;

View File

@@ -60,12 +60,6 @@ export const workflowRun = mixins(
async runWorkflow (nodeName?: string, source?: string): Promise<IExecutionPushResponse | undefined> {
const workflow = this.getWorkflow();
if(nodeName) {
this.$telemetry.track('User clicked execute node button', { node_type: nodeName, workflow_id: this.$store.getters.workflowId });
} else {
this.$telemetry.track('User clicked execute workflow button', { workflow_id: this.$store.getters.workflowId });
}
if (this.$store.getters.isActionActive('workflowRunning') === true) {
return;
}