refactor(editor): Migrate NodeDetailsView.vue to use script setup (no-changelog) (#9762)

This commit is contained in:
Ricardo Espinoza 2024-06-17 09:53:35 -07:00 committed by GitHub
parent be7249f568
commit f7d7404907
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -138,8 +138,8 @@
</el-dialog>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, onBeforeUnmount, computed, watch } from 'vue';
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, computed, watch } from 'vue';
import { createEventBus } from 'n8n-design-system/utils';
import type { IRunData, ConnectionTypes } from 'n8n-workflow';
import { jsonParse, NodeHelpers, NodeConnectionType } from 'n8n-workflow';
@ -177,28 +177,7 @@ import { useTelemetry } from '@/composables/useTelemetry';
import { useI18n } from '@/composables/useI18n';
import { storeToRefs } from 'pinia';
export default defineComponent({
name: 'NodeDetailsView',
components: {
NodeSettings,
InputPanel,
OutputPanel,
NDVDraggablePanels,
TriggerPanel,
},
props: {
readOnly: {
type: Boolean,
},
renaming: {
type: Boolean,
},
isProductionExecutionPreview: {
type: Boolean,
default: false,
},
},
emits: [
const emit = defineEmits([
'saveKeyboardShortcut',
'valueChanged',
'nodeTypeSelected',
@ -206,64 +185,70 @@ export default defineComponent({
'openConnectionNodeCreator',
'redrawNode',
'stopExecution',
],
setup(props, { emit }) {
const ndvStore = useNDVStore();
const externalHooks = useExternalHooks();
const nodeHelpers = useNodeHelpers();
const { activeNode } = storeToRefs(ndvStore);
const pinnedData = usePinnedData(activeNode);
const router = useRouter();
const workflowHelpers = useWorkflowHelpers({ router });
const workflowActivate = useWorkflowActivate();
const nodeTypesStore = useNodeTypesStore();
const uiStore = useUIStore();
const workflowsStore = useWorkflowsStore();
const settingsStore = useSettingsStore();
const deviceSupport = useDeviceSupport();
const telemetry = useTelemetry();
const i18n = useI18n();
const message = useMessage();
]);
const settingsEventBus = createEventBus();
const redrawRequired = ref(false);
const runInputIndex = ref(-1);
const runOutputIndex = ref(-1);
const isLinkingEnabled = ref(true);
const selectedInput = ref<string | undefined>();
const triggerWaitingWarningEnabled = ref(false);
const isDragging = ref(false);
const mainPanelPosition = ref(0);
const pinDataDiscoveryTooltipVisible = ref(false);
const avgInputRowHeight = ref(0);
const avgOutputRowHeight = ref(0);
const isInputPaneActive = ref(false);
const isOutputPaneActive = ref(false);
const isPairedItemHoveringEnabled = ref(true);
const props = defineProps<{
readOnly: boolean;
renaming: boolean;
isProductionExecutionPreview: boolean;
}>();
//computed
const ndvStore = useNDVStore();
const externalHooks = useExternalHooks();
const nodeHelpers = useNodeHelpers();
const { activeNode } = storeToRefs(ndvStore);
const pinnedData = usePinnedData(activeNode);
const router = useRouter();
const workflowHelpers = useWorkflowHelpers({ router });
const workflowActivate = useWorkflowActivate();
const nodeTypesStore = useNodeTypesStore();
const uiStore = useUIStore();
const workflowsStore = useWorkflowsStore();
const settingsStore = useSettingsStore();
const deviceSupport = useDeviceSupport();
const telemetry = useTelemetry();
const i18n = useI18n();
const message = useMessage();
const pushRef = computed(() => ndvStore.pushRef);
const settingsEventBus = createEventBus();
const redrawRequired = ref(false);
const runInputIndex = ref(-1);
const runOutputIndex = ref(-1);
const isLinkingEnabled = ref(true);
const selectedInput = ref<string | undefined>();
const triggerWaitingWarningEnabled = ref(false);
const isDragging = ref(false);
const mainPanelPosition = ref(0);
const pinDataDiscoveryTooltipVisible = ref(false);
const avgInputRowHeight = ref(0);
const avgOutputRowHeight = ref(0);
const isInputPaneActive = ref(false);
const isOutputPaneActive = ref(false);
const isPairedItemHoveringEnabled = ref(true);
const activeNodeType = computed(() => {
//computed
const pushRef = computed(() => ndvStore.pushRef);
const activeNodeType = computed(() => {
if (activeNode.value) {
return nodeTypesStore.getNodeType(activeNode.value.type, activeNode.value.typeVersion);
}
return null;
});
});
const workflowRunning = computed(() => uiStore.isActionActive('workflowRunning'));
const workflowRunning = computed(() => uiStore.isActionActive('workflowRunning'));
const showTriggerWaitingWarning = computed(
const showTriggerWaitingWarning = computed(
() =>
triggerWaitingWarningEnabled.value &&
!!activeNodeType.value &&
!activeNodeType.value.group.includes('trigger') &&
workflowRunning.value &&
workflowsStore.executionWaitingForWebhook,
);
);
const workflowRunData = computed(() => {
const workflowRunData = computed(() => {
if (workflowExecution.value === null) {
return null;
}
@ -275,22 +260,21 @@ export default defineComponent({
}
return null;
});
});
const workflow = computed(() => workflowHelpers.getCurrentWorkflow());
const workflow = computed(() => workflowHelpers.getCurrentWorkflow());
const parentNodes = computed(() => {
const parentNodes = computed(() => {
if (activeNode.value) {
return (
workflow.value.getParentNodesByDepth(activeNode.value.name, 1).map(({ name }) => name) ||
[]
workflow.value.getParentNodesByDepth(activeNode.value.name, 1).map(({ name }) => name) || []
);
} else {
return [];
}
});
});
const parentNode = computed(() => {
const parentNode = computed(() => {
for (const parentNodeName of parentNodes.value) {
if (workflowsStore?.pinnedWorkflowData?.[parentNodeName]) {
return parentNodeName;
@ -301,29 +285,29 @@ export default defineComponent({
}
}
return parentNodes.value[0];
});
});
const inputNodeName = computed<string | undefined>(() => {
const inputNodeName = computed<string | undefined>(() => {
return selectedInput.value || parentNode.value;
});
});
const inputNode = computed(() => {
const inputNode = computed(() => {
if (inputNodeName.value) {
return workflowsStore.getNodeByName(inputNodeName.value);
}
return null;
});
});
const inputSize = computed(() => ndvStore.ndvInputDataWithPinnedData.length);
const inputSize = computed(() => ndvStore.ndvInputDataWithPinnedData.length);
const isTriggerNode = computed(
const isTriggerNode = computed(
() =>
!!activeNodeType.value &&
(activeNodeType.value.group.includes('trigger') ||
activeNodeType.value.name === START_NODE_TYPE),
);
);
const showTriggerPanel = computed(() => {
const showTriggerPanel = computed(() => {
const override = !!activeNodeType.value?.triggerPanel;
if (typeof activeNodeType.value?.triggerPanel === 'boolean') {
return override;
@ -335,31 +319,29 @@ export default defineComponent({
return (
!props.readOnly && isTriggerNode.value && (isWebhookBasedNode || isPollingNode || override)
);
});
});
const hasOutputConnection = computed(() => {
const hasOutputConnection = computed(() => {
if (!activeNode.value) return false;
const outgoingConnections = workflowsStore.outgoingConnectionsByNodeName(
activeNode.value.name,
);
const outgoingConnections = workflowsStore.outgoingConnectionsByNodeName(activeNode.value.name);
// Check if there's at-least one output connection
return (Object.values(outgoingConnections)?.[0]?.[0] ?? []).length > 0;
});
});
const isExecutableTriggerNode = computed(() => {
const isExecutableTriggerNode = computed(() => {
if (!activeNodeType.value) return false;
return EXECUTABLE_TRIGGER_NODE_TYPES.includes(activeNodeType.value.name);
});
});
const isActiveStickyNode = computed(
const isActiveStickyNode = computed(
() => !!ndvStore.activeNode && ndvStore.activeNode.type === STICKY_NODE_TYPE,
);
);
const workflowExecution = computed(() => workflowsStore.getWorkflowExecution);
const workflowExecution = computed(() => workflowsStore.getWorkflowExecution);
const maxOutputRun = computed(() => {
const maxOutputRun = computed(() => {
if (activeNode.value === null) {
return 0;
}
@ -375,15 +357,15 @@ export default defineComponent({
}
return 0;
});
});
const outputRun = computed(() =>
const outputRun = computed(() =>
runOutputIndex.value === -1
? maxOutputRun.value
: Math.min(runOutputIndex.value, maxOutputRun.value),
);
);
const maxInputRun = computed(() => {
const maxInputRun = computed(() => {
if (inputNode.value === null || activeNode.value === null) {
return 0;
}
@ -394,11 +376,7 @@ export default defineComponent({
return 0;
}
const outputs = NodeHelpers.getNodeOutputs(
workflow.value,
workflowNode,
activeNodeType.value,
);
const outputs = NodeHelpers.getNodeOutputs(workflow.value, workflowNode, activeNodeType.value);
let node = inputNode.value;
@ -417,9 +395,9 @@ export default defineComponent({
}
return 0;
});
});
const inputRun = computed(() => {
const inputRun = computed(() => {
if (isLinkingEnabled.value && maxOutputRun.value === maxInputRun.value) {
return outputRun.value;
}
@ -428,40 +406,37 @@ export default defineComponent({
}
return Math.min(runInputIndex.value, maxInputRun.value);
});
});
const canLinkRuns = computed(
const canLinkRuns = computed(
() => maxOutputRun.value > 0 && maxOutputRun.value === maxInputRun.value,
);
);
const linked = computed(() => isLinkingEnabled.value && canLinkRuns.value);
const linked = computed(() => isLinkingEnabled.value && canLinkRuns.value);
const inputPanelMargin = computed(() => (isTriggerNode.value ? 0 : 80));
const inputPanelMargin = computed(() => (isTriggerNode.value ? 0 : 80));
const featureRequestUrl = computed(() => {
const featureRequestUrl = computed(() => {
if (!activeNodeType.value) {
return '';
}
return `${BASE_NODE_SURVEY_URL}${activeNodeType.value.name}`;
});
});
const outputPanelEditMode = computed(() => ndvStore.outputPanelEditMode);
const outputPanelEditMode = computed(() => ndvStore.outputPanelEditMode);
const isWorkflowRunning = computed(() => uiStore.isActionActive('workflowRunning'));
const isWorkflowRunning = computed(() => uiStore.isActionActive('workflowRunning'));
const isExecutionWaitingForWebhook = computed(() => workflowsStore.executionWaitingForWebhook);
const isExecutionWaitingForWebhook = computed(() => workflowsStore.executionWaitingForWebhook);
const blockUi = computed(() => isWorkflowRunning.value || isExecutionWaitingForWebhook.value);
const blockUi = computed(() => isWorkflowRunning.value || isExecutionWaitingForWebhook.value);
const foreignCredentials = computed(() => {
const foreignCredentials = computed(() => {
const credentials = activeNode.value?.credentials;
const usedCredentials = workflowsStore.usedCredentials;
const foreignCredentialsArray: string[] = [];
if (
credentials &&
settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)
) {
if (credentials && settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
Object.values(credentials).forEach((credential) => {
if (
credential.id &&
@ -474,17 +449,17 @@ export default defineComponent({
}
return foreignCredentialsArray;
});
});
const hasForeignCredential = computed(() => foreignCredentials.value.length > 0);
const hasForeignCredential = computed(() => foreignCredentials.value.length > 0);
//methods
//methods
const setIsTooltipVisible = ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
const setIsTooltipVisible = ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
pinDataDiscoveryTooltipVisible.value = isTooltipVisible;
};
};
const onKeyDown = (e: KeyboardEvent) => {
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 's' && deviceSupport.isCtrlKeyPressed(e)) {
e.stopPropagation();
e.preventDefault();
@ -493,9 +468,9 @@ export default defineComponent({
emit('saveKeyboardShortcut', e);
}
};
};
const onInputItemHover = (e: { itemIndex: number; outputIndex: number } | null) => {
const onInputItemHover = (e: { itemIndex: number; outputIndex: number } | null) => {
if (e === null || !inputNodeName.value || !isPairedItemHoveringEnabled.value) {
ndvStore.setHoveringItem(null);
return;
@ -508,20 +483,20 @@ export default defineComponent({
itemIndex: e.itemIndex,
};
ndvStore.setHoveringItem(item);
};
};
const onInputTableMounted = (e: { avgRowHeight: number }) => {
const onInputTableMounted = (e: { avgRowHeight: number }) => {
avgInputRowHeight.value = e.avgRowHeight;
};
};
const onWorkflowActivate = () => {
const onWorkflowActivate = () => {
ndvStore.activeNodeName = null;
setTimeout(() => {
void workflowActivate.activateCurrentWorkflow('ndv');
}, 1000);
};
};
const onOutputItemHover = (e: { itemIndex: number; outputIndex: number }) => {
const onOutputItemHover = (e: { itemIndex: number; outputIndex: number }) => {
if (e === null || !activeNode.value || !isPairedItemHoveringEnabled.value) {
ndvStore.setHoveringItem(null);
return;
@ -534,9 +509,9 @@ export default defineComponent({
itemIndex: e.itemIndex,
};
ndvStore.setHoveringItem(item);
};
};
const onFeatureRequestClick = () => {
const onFeatureRequestClick = () => {
window.open(featureRequestUrl.value, '_blank');
if (activeNode.value) {
telemetry.track('User clicked ndv link', {
@ -547,9 +522,9 @@ export default defineComponent({
type: 'i-wish-this-node-would',
});
}
};
};
const onDragEnd = (e: { windowWidth: number; position: number }) => {
const onDragEnd = (e: { windowWidth: number; position: number }) => {
isDragging.value = false;
telemetry.track('User moved parameters pane', {
// example method for tracking
@ -561,73 +536,73 @@ export default defineComponent({
workflow_id: workflowsStore.workflowId,
});
mainPanelPosition.value = e.position;
};
};
const onDragStart = (e: { position: number }) => {
const onDragStart = (e: { position: number }) => {
isDragging.value = true;
mainPanelPosition.value = e.position;
};
};
const onPanelsInit = (e: { position: number }) => {
const onPanelsInit = (e: { position: number }) => {
mainPanelPosition.value = e.position;
};
};
const onLinkRunToOutput = () => {
const onLinkRunToOutput = () => {
isLinkingEnabled.value = true;
trackLinking('output');
};
};
const onUnlinkRun = (pane: string) => {
const onUnlinkRun = (pane: string) => {
runInputIndex.value = runOutputIndex.value;
isLinkingEnabled.value = false;
trackLinking(pane);
};
};
const onNodeExecute = () => {
const onNodeExecute = () => {
setTimeout(() => {
if (!activeNode.value || !workflowRunning.value) {
return;
}
triggerWaitingWarningEnabled.value = true;
}, 1000);
};
};
const openSettings = () => {
const openSettings = () => {
settingsEventBus.emit('openSettings');
};
};
const trackLinking = (pane: string) => {
const trackLinking = (pane: string) => {
telemetry.track('User changed ndv run linking', {
node_type: activeNodeType.value ? activeNodeType.value.name : '',
push_ref: pushRef.value,
linked: linked.value,
pane,
});
};
};
const onLinkRunToInput = () => {
const onLinkRunToInput = () => {
runOutputIndex.value = runInputIndex.value;
isLinkingEnabled.value = true;
trackLinking('input');
};
};
const valueChanged = (parameterData: IUpdateInformation) => {
const valueChanged = (parameterData: IUpdateInformation) => {
emit('valueChanged', parameterData);
};
};
const nodeTypeSelected = (nodeTypeName: string) => {
const nodeTypeSelected = (nodeTypeName: string) => {
emit('nodeTypeSelected', nodeTypeName);
};
};
const onSwitchSelectedNode = (nodeTypeName: string) => {
const onSwitchSelectedNode = (nodeTypeName: string) => {
emit('switchSelectedNode', nodeTypeName);
};
};
const onOpenConnectionNodeCreator = (nodeTypeName: string, connectionType: ConnectionTypes) => {
const onOpenConnectionNodeCreator = (nodeTypeName: string, connectionType: ConnectionTypes) => {
emit('openConnectionNodeCreator', nodeTypeName, connectionType);
};
};
const close = async () => {
const close = async () => {
if (isDragging.value) {
return;
}
@ -675,35 +650,35 @@ export default defineComponent({
triggerWaitingWarningEnabled.value = false;
ndvStore.activeNodeName = null;
ndvStore.resetNDVPushRef();
};
};
const trackRunChange = (run: number, pane: string) => {
const trackRunChange = (run: number, pane: string) => {
telemetry.track('User changed ndv run dropdown', {
push_ref: pushRef.value,
run_index: run,
node_type: activeNodeType.value ? activeNodeType.value?.name : '',
pane,
});
};
};
const onRunOutputIndexChange = (run: number) => {
const onRunOutputIndexChange = (run: number) => {
runOutputIndex.value = run;
trackRunChange(run, 'output');
};
};
const onRunInputIndexChange = (run: number) => {
const onRunInputIndexChange = (run: number) => {
runInputIndex.value = run;
if (linked.value) {
runOutputIndex.value = run;
}
trackRunChange(run, 'input');
};
};
const onOutputTableMounted = (e: { avgRowHeight: number }) => {
const onOutputTableMounted = (e: { avgRowHeight: number }) => {
avgOutputRowHeight.value = e.avgRowHeight;
};
};
const onInputNodeChange = (value: string, index: number) => {
const onInputNodeChange = (value: string, index: number) => {
runInputIndex.value = -1;
isLinkingEnabled.value = true;
selectedInput.value = value;
@ -715,29 +690,29 @@ export default defineComponent({
selection_value: index,
input_node_type: inputNode.value ? inputNode.value.type : '',
});
};
};
const onStopExecution = () => {
const onStopExecution = () => {
emit('stopExecution');
};
};
const activateInputPane = () => {
const activateInputPane = () => {
isInputPaneActive.value = true;
isOutputPaneActive.value = false;
};
};
const activateOutputPane = () => {
const activateOutputPane = () => {
isInputPaneActive.value = false;
isOutputPaneActive.value = true;
};
};
const onSearch = (search: string) => {
const onSearch = (search: string) => {
isPairedItemHoveringEnabled.value = !search;
};
};
//watchers
//watchers
watch(
watch(
activeNode,
(node, oldNode) => {
if (node && node.name !== oldNode?.name && !isActiveStickyNode.value) {
@ -777,9 +752,7 @@ export default defineComponent({
parameters_pane_position: mainPanelPosition.value,
input_first_connector_runs: maxInputRun.value,
output_first_connector_runs: maxOutputRun.value,
selected_view_inputs: isTriggerNode.value
? 'trigger'
: ndvStore.inputPanelDisplayMode,
selected_view_inputs: isTriggerNode.value ? 'trigger' : ndvStore.inputPanelDisplayMode,
selected_view_outputs: ndvStore.outputPanelDisplayMode,
input_connectors: parentNodes.value.length,
output_connectors: outgoingConnections?.main?.length,
@ -797,97 +770,33 @@ export default defineComponent({
}
},
{ immediate: true },
);
watch(maxOutputRun, () => {
);
watch(maxOutputRun, () => {
runOutputIndex.value = -1;
});
});
watch(maxInputRun, () => {
watch(maxInputRun, () => {
runInputIndex.value = -1;
});
});
watch(inputNodeName, (nodeName) => {
watch(inputNodeName, (nodeName) => {
setTimeout(() => {
ndvStore.setInputNodeName(nodeName);
}, 0);
});
});
watch(inputRun, (inputRun) => {
watch(inputRun, (inputRun) => {
setTimeout(() => {
ndvStore.setInputRunIndex(inputRun);
}, 0);
});
});
onMounted(() => {
onMounted(() => {
dataPinningEventBus.on('data-pinning-discovery', setIsTooltipVisible);
});
});
onBeforeUnmount(() => {
onBeforeUnmount(() => {
dataPinningEventBus.off('data-pinning-discovery', setIsTooltipVisible);
});
return {
externalHooks,
nodeHelpers,
pinnedData,
workflowHelpers,
workflowActivate,
redrawRequired,
isInputPaneActive,
isDragging,
activeNodeType,
pushRef,
workflowRunning,
showTriggerWaitingWarning,
activeNode,
isExecutableTriggerNode,
showTriggerPanel,
hasOutputConnection,
blockUi,
isActiveStickyNode,
isTriggerNode,
workflow,
canLinkRuns,
inputRun,
linked,
inputNodeName,
inputSize,
hasForeignCredential,
outputRun,
isOutputPaneActive,
foreignCredentials,
featureRequestUrl,
settingsEventBus,
inputPanelMargin,
nodeTypeSelected,
onOutputItemHover,
onOutputTableMounted,
onInputTableMounted,
onRunOutputIndexChange,
onStopExecution,
activateInputPane,
activateOutputPane,
onSearch,
onInputNodeChange,
onRunInputIndexChange,
onLinkRunToInput,
valueChanged,
onSwitchSelectedNode,
onOpenConnectionNodeCreator,
close,
onKeyDown,
onInputItemHover,
onWorkflowActivate,
onFeatureRequestClick,
onDragEnd,
onDragStart,
onPanelsInit,
onLinkRunToOutput,
onUnlinkRun,
onNodeExecute,
openSettings,
};
},
});
</script>