mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 12:44:07 -08:00
feat(editor): Add node name and version to NDV node settings (#7731)
<img width="580" alt="image" src="https://github.com/n8n-io/n8n/assets/8850410/85ac1c6e-9116-436a-a2ed-8d0ac162a287"> <img width="580" alt="image" src="https://github.com/n8n-io/n8n/assets/8850410/08b37377-cef5-4f80-80c0-addfdd37f728"> --------- Co-authored-by: Giulio Andreini <andreini@netseven.it>
This commit is contained in:
parent
902beffce5
commit
da851986f6
|
@ -1,7 +1,6 @@
|
|||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { getPopper, getVisiblePopper, getVisibleSelect } from '../utils';
|
||||
import { META_KEY } from '../constants';
|
||||
import { NDV, WorkflowPage } from '../pages';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
@ -368,4 +367,23 @@ describe('NDV', () => {
|
|||
// Should call the endpoint only once (on mount), not for every keystroke
|
||||
cy.get('@fetchParameterOptions').should('have.been.calledOnce');
|
||||
});
|
||||
|
||||
it('should show node name and version in settings', () => {
|
||||
cy.createFixtureWorkflow('Test_workflow_ndv_version.json', `NDV test version ${uuid()}`);
|
||||
|
||||
workflowPage.actions.openNode('Edit Fields (old)');
|
||||
ndv.actions.openSettings();
|
||||
ndv.getters.nodeVersion().should('have.text', 'Set node version 2 (Latest version: 3.2)');
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('Edit Fields (latest)');
|
||||
ndv.actions.openSettings();
|
||||
ndv.getters.nodeVersion().should('have.text', 'Edit Fields (Set) node version 3.2 (Latest)');
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openNode('Function');
|
||||
ndv.actions.openSettings();
|
||||
ndv.getters.nodeVersion().should('have.text', 'Function node version 1 (Deprecated)');
|
||||
ndv.actions.close();
|
||||
});
|
||||
});
|
||||
|
|
49
cypress/fixtures/Test_workflow_ndv_version.json
Normal file
49
cypress/fixtures/Test_workflow_ndv_version.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "Node versions",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "aadaed66-84ed-4cf8-bf21-082e9a65db76",
|
||||
"name": "When clicking \"Execute Workflow\"",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1540,
|
||||
780
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "93d73a85-82f0-4380-a032-713d5dc82b32",
|
||||
"name": "Function",
|
||||
"type": "n8n-nodes-base.function",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
2040,
|
||||
780
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "50f322d9-c622-4dd0-8d38-e851502739dd",
|
||||
"name": "Edit Fields (old)",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1880,
|
||||
780
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "93aaadac-55fe-4618-b1eb-f63e61d1446a",
|
||||
"name": "Edit Fields (latest)",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.2,
|
||||
"position": [
|
||||
1720,
|
||||
780
|
||||
]
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {}
|
||||
}
|
|
@ -81,6 +81,8 @@ export class NDV extends BasePage {
|
|||
sqlEditorContainer: () => cy.getByTestId('sql-editor-container'),
|
||||
searchInput: () => cy.getByTestId('ndv-search'),
|
||||
pagination: () => cy.getByTestId('ndv-data-pagination'),
|
||||
nodeVersion: () => cy.getByTestId('node-version'),
|
||||
nodeSettingsTab: () => cy.getByTestId('tab-settings'),
|
||||
};
|
||||
|
||||
actions = {
|
||||
|
@ -225,6 +227,10 @@ export class NDV extends BasePage {
|
|||
});
|
||||
this.actions.validateExpressionPreview(fieldName, `node doesn't exist`);
|
||||
},
|
||||
|
||||
openSettings: () => {
|
||||
this.getters.nodeSettingsTab().click();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<div
|
||||
v-else
|
||||
:class="{ [$style.tab]: true, [$style.activeTab]: modelValue === option.value }"
|
||||
:data-test-id="`tab-${option.value}`"
|
||||
@click="() => handleTabClick(option.value)"
|
||||
>
|
||||
<n8n-icon v-if="option.icon" :icon="option.icon" size="medium" />
|
||||
|
|
|
@ -152,6 +152,17 @@
|
|||
@valueChanged="valueChanged"
|
||||
@parameterBlur="onParameterBlur"
|
||||
/>
|
||||
<div class="node-version" data-test-id="node-version">
|
||||
{{
|
||||
$locale.baseText('nodeSettings.nodeVersion', {
|
||||
interpolate: {
|
||||
node: nodeType?.displayName as string,
|
||||
version: node.typeVersion.toString(),
|
||||
},
|
||||
})
|
||||
}}
|
||||
<span>({{ nodeVersionTag }})</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<n8n-block-ui :show="blockUI" />
|
||||
|
@ -258,6 +269,29 @@ export default defineComponent({
|
|||
|
||||
return '';
|
||||
},
|
||||
nodeTypeVersions(): number[] {
|
||||
if (!this.node) return [];
|
||||
return this.nodeTypesStore.getNodeVersions(this.node.type);
|
||||
},
|
||||
latestVersion(): number {
|
||||
return Math.max(...this.nodeTypeVersions);
|
||||
},
|
||||
isLatestNodeVersion(): boolean {
|
||||
return this.latestVersion === this.node?.typeVersion;
|
||||
},
|
||||
nodeVersionTag(): string {
|
||||
if (!this.nodeType || this.nodeType.hidden) {
|
||||
return this.$locale.baseText('nodeSettings.deprecated');
|
||||
}
|
||||
|
||||
if (this.isLatestNodeVersion) {
|
||||
return this.$locale.baseText('nodeSettings.latest');
|
||||
}
|
||||
|
||||
return this.$locale.baseText('nodeSettings.latestVersion', {
|
||||
interpolate: { version: this.latestVersion.toString() },
|
||||
});
|
||||
},
|
||||
nodeTypeDescription(): string {
|
||||
if (this.nodeType?.description) {
|
||||
const shortNodeType = this.$locale.shortNodeType(this.nodeType.name);
|
||||
|
@ -1126,6 +1160,14 @@ export default defineComponent({
|
|||
top: -25px;
|
||||
}
|
||||
|
||||
.node-version {
|
||||
border-top: var(--border-base);
|
||||
font-size: var(--font-size-xs);
|
||||
font-size: var(--font-size-2xs);
|
||||
padding: var(--spacing-xs) 0 var(--spacing-2xs) 0;
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
.parameter-value {
|
||||
input.expression {
|
||||
border-style: dashed;
|
||||
|
|
|
@ -995,6 +995,11 @@
|
|||
"nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)",
|
||||
"nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)",
|
||||
"nodeSettings.hasForeignCredential": "To edit this node, either:<br/>a) Ask {owner} to share the credential with you, or<br/>b) Duplicate the node and add your own credential",
|
||||
"nodeSettings.latest": "Latest",
|
||||
"nodeSettings.deprecated": "Deprecated",
|
||||
"nodeSettings.latestVersion": "Latest version: {version}",
|
||||
"nodeSettings.nodeVersion": "{node} node version {version}",
|
||||
"nodeView.addNode": "Add node",
|
||||
"nodeView.openNodesPanel": "Open nodes panel",
|
||||
"nodeView.addATriggerNodeFirst": "Add a <a data-action='showNodeCreator'>Trigger Node</a> first",
|
||||
"nodeView.addOrEnableTriggerNode": "<a data-action='showNodeCreator'>Add</a> or enable a Trigger node to execute the workflow",
|
||||
|
|
|
@ -84,6 +84,11 @@ export const useNodeTypesStore = defineStore(STORES.NODE_TYPES, {
|
|||
return nodeType ?? null;
|
||||
};
|
||||
},
|
||||
getNodeVersions() {
|
||||
return (nodeTypeName: string): number[] => {
|
||||
return Object.keys(this.nodeTypes[nodeTypeName] ?? {}).map(Number);
|
||||
};
|
||||
},
|
||||
getCredentialOnlyNodeType() {
|
||||
return (nodeTypeName: string, version?: number): INodeTypeDescription | null => {
|
||||
const credentialName = getCredentialTypeName(nodeTypeName);
|
||||
|
|
Loading…
Reference in a new issue