feat(editor): Change default node names depending on node operation and resource (#15954)

This commit is contained in:
Charlie Kolb
2025-06-10 08:50:46 +02:00
committed by GitHub
parent 33f8fab791
commit c92701cbdf
21 changed files with 574 additions and 182 deletions

View File

@@ -2,6 +2,7 @@ import { computed } from 'vue';
import {
CHAIN_LLM_LANGCHAIN_NODE_TYPE,
NodeConnectionTypes,
NodeHelpers,
type IDataObject,
type INodeParameters,
} from 'n8n-workflow';
@@ -43,11 +44,14 @@ import { useExternalHooks } from '@/composables/useExternalHooks';
import { sortNodeCreateElements, transformNodeType } from '../utils';
import { useI18n } from '@n8n/i18n';
import { useCanvasStore } from '@/stores/canvas.store';
import { useCanvasOperations } from '@/composables/useCanvasOperations';
import findLast from 'lodash/findLast';
export const useActions = () => {
const nodeCreatorStore = useNodeCreatorStore();
const nodeTypesStore = useNodeTypesStore();
const i18n = useI18n();
const canvasOperations = useCanvasOperations();
const singleNodeOpenSources = [
NODE_CREATOR_OPEN_SOURCES.PLUS_ENDPOINT,
NODE_CREATOR_OPEN_SOURCES.NODE_CONNECTION_ACTION,
@@ -305,7 +309,7 @@ export const useActions = () => {
return { nodes, connections };
}
// Hook into addNode action to set the last node parameters & track the action selected
// Hook into addNode action to set the last node parameters, adjust default name and track the action selected
function setAddedNodeActionParameters(
action: IUpdateInformation,
telemetry?: Telemetry,
@@ -313,10 +317,25 @@ export const useActions = () => {
) {
const { $onAction: onWorkflowStoreAction } = useWorkflowsStore();
const storeWatcher = onWorkflowStoreAction(
({ name, after, store: { setLastNodeParameters }, args }) => {
({ name, after, store: { setLastNodeParameters, allNodes }, args }) => {
if (name !== 'addNode' || args[0].type !== action.key) return;
after(() => {
const node = findLast(allNodes, (n) => n.type === action.key);
const nodeType = node && nodeTypesStore.getNodeType(node.type, node.typeVersion);
const wasDefaultName =
nodeType && NodeHelpers.isDefaultNodeName(node.name, nodeType, node.parameters ?? {});
setLastNodeParameters(action);
// We update the default name here based on the chosen resource and operation
if (wasDefaultName) {
const newName = NodeHelpers.makeNodeName(node.parameters, nodeType);
// Account for unique-ified nodes with `<name><digit>`
if (!node.name.startsWith(newName)) {
// setTimeout to allow remaining events trigger by node addition to finish
setTimeout(async () => await canvasOperations.renameNode(node.name, newName));
}
}
if (telemetry) trackActionSelected(action, telemetry, rootView);
// Unsubscribe from the store watcher
storeWatcher();

View File

@@ -53,6 +53,7 @@ import { importCurlEventBus, ndvEventBus } from '@/event-bus';
import { ProjectTypes } from '@/types/projects.types';
import { updateDynamicConnections } from '@/utils/nodeSettingsUtils';
import FreeAiCreditsCallout from '@/components/FreeAiCreditsCallout.vue';
import { useCanvasOperations } from '@/composables/useCanvasOperations';
const props = withDefaults(
defineProps<{
@@ -96,6 +97,7 @@ const telemetry = useTelemetry();
const nodeHelpers = useNodeHelpers();
const externalHooks = useExternalHooks();
const i18n = useI18n();
const canvasOperations = useCanvasOperations();
const nodeValid = ref(true);
const openPanel = ref<'params' | 'settings'>('params');
@@ -579,6 +581,15 @@ const valueChanged = (parameterData: IUpdateInformation) => {
}
}
if (NodeHelpers.isDefaultNodeName(_node.name, nodeType, node.value?.parameters ?? {})) {
const newName = NodeHelpers.makeNodeName(nodeParameters ?? {}, nodeType);
// Account for unique-ified nodes with `<name><digit>`
if (!_node.name.startsWith(newName)) {
// We need a timeout here to support events reacting to the valueChange based on node names
setTimeout(async () => await canvasOperations.renameNode(_node.name, newName));
}
}
for (const key of Object.keys(nodeParameters as object)) {
if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) {
setValue(`parameters.${key}`, nodeParameters[key] as string);

View File

@@ -910,7 +910,10 @@ export function useCanvasOperations() {
options: { viewport?: ViewportBoundaries; forcePosition?: boolean } = {},
) {
const id = node.id ?? nodeHelpers.assignNodeId(node as INodeUi);
const name = node.name ?? (nodeTypeDescription.defaults.name as string);
const name =
node.name ??
nodeHelpers.getDefaultNodeName(node) ??
(nodeTypeDescription.defaults.name as string);
const type = nodeTypeDescription.name;
const typeVersion = node.typeVersion;
const position =

View File

@@ -29,6 +29,7 @@ import type {
} from 'n8n-workflow';
import type {
AddedNode,
ICredentialsResponse,
INodeUi,
INodeUpdatePropertiesInformation,
@@ -986,6 +987,21 @@ export function useNodeHelpers() {
return nodeIssues;
}
function getDefaultNodeName(node: AddedNode | INode) {
const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (nodeType === null) return null;
const parameters = NodeHelpers.getNodeParameters(
nodeType?.properties,
node.parameters ?? {},
true,
false,
node.typeVersion ? { typeVersion: node.typeVersion } : null,
nodeType,
);
return NodeHelpers.makeNodeName(parameters ?? {}, nodeType);
}
return {
hasProxyAuth,
isCustomApiCallSelected,
@@ -1019,5 +1035,6 @@ export function useNodeHelpers() {
isSingleExecution,
getNodeHints,
nodeIssuesToString,
getDefaultNodeName,
};
}