diff --git a/cypress/e2e/4-node-creator.cy.ts b/cypress/e2e/4-node-creator.cy.ts index e11dc9b3f2203..f3efd655b2f18 100644 --- a/cypress/e2e/4-node-creator.cy.ts +++ b/cypress/e2e/4-node-creator.cy.ts @@ -70,11 +70,20 @@ describe('Node Creator', () => { .should('exist') .should('contain.text', 'We didn\'t make that... yet'); + nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image'); + nodeCreatorFeature.getters.creatorItem().should('have.length', 1); + + nodeCreatorFeature.getters.searchBar().find('input').clear().type('this node totally does not exist'); + nodeCreatorFeature.getters.creatorItem().should('have.length', 0); + + nodeCreatorFeature.getters.searchBar().find('input').clear() + nodeCreatorFeature.getters.getCreatorItem('On App Event').click(); + nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image'); nodeCreatorFeature.getters.creatorItem().should('have.length', 0); nodeCreatorFeature.getters.noResults() .should('exist') - .should('contain.text', 'To see results, click here'); + .should('contain.text', 'To see all results, click here'); nodeCreatorFeature.getters.noResults().contains('click here').click(); nodeCreatorFeature.getters.nodeCreatorTabs().should('exist'); @@ -85,6 +94,7 @@ describe('Node Creator', () => { }) it('should add manual trigger node', () => { + cy.get('.el-loading-mask').should('not.exist'); nodeCreatorFeature.getters.canvasAddButton().click(); nodeCreatorFeature.getters.getCreatorItem('Manually').click(); @@ -95,7 +105,7 @@ describe('Node Creator', () => { nodeCreatorFeature.getters.nodeCreator().should('not.exist'); // TODO: Replace once we have canvas feature utils - cy.get('div').contains("On clicking 'execute'").should('exist'); + cy.get('div').contains("Add first step").should('exist'); }) it('check if non-core nodes are rendered', () => { cy.wait('@nodesIntercept').then((interception) => { @@ -144,7 +154,7 @@ describe('Node Creator', () => { nodeCreatorFeature.getters.getCreatorItem(customCategory).should('exist'); nodeCreatorFeature.actions.toggleCategory(customCategory); - nodeCreatorFeature.getters.getCreatorItem(customNode).findChildByTestId('node-item-community-tooltip').should('exist'); + nodeCreatorFeature.getters.getCreatorItem(customNode).findChildByTestId('node-creator-item-tooltip').should('exist'); nodeCreatorFeature.getters.getCreatorItem(customNode).contains(customNodeDescription).should('exist'); nodeCreatorFeature.actions.selectNode(customNode); diff --git a/cypress/e2e/7-workflow-actions.cy.ts b/cypress/e2e/7-workflow-actions.cy.ts index 495614d569a9a..b7d903b9ba40e 100644 --- a/cypress/e2e/7-workflow-actions.cy.ts +++ b/cypress/e2e/7-workflow-actions.cy.ts @@ -66,7 +66,7 @@ describe('Workflow Actions', () => { it('should add more tags', () => { WorkflowPage.getters.newTagLink().click(); WorkflowPage.actions.addTags(TEST_WF_TAGS); - WorkflowPage.getters.workflowTagElements().first().click(); + WorkflowPage.getters.firstWorkflowTagElement().click(); WorkflowPage.actions.addTags(['Another one']); WorkflowPage.getters.workflowTagElements().should('have.length', TEST_WF_TAGS.length + 1); }); @@ -74,7 +74,7 @@ describe('Workflow Actions', () => { it('should remove tags by clicking X in tag', () => { WorkflowPage.getters.newTagLink().click(); WorkflowPage.actions.addTags(TEST_WF_TAGS); - WorkflowPage.getters.workflowTagElements().first().click(); + WorkflowPage.getters.firstWorkflowTagElement().click(); WorkflowPage.getters.workflowTagsContainer().find('.el-tag__close').first().click(); cy.get('body').type('{enter}'); WorkflowPage.getters.workflowTagElements().should('have.length', TEST_WF_TAGS.length - 1); @@ -83,7 +83,7 @@ describe('Workflow Actions', () => { it('should remove tags from dropdown', () => { WorkflowPage.getters.newTagLink().click(); WorkflowPage.actions.addTags(TEST_WF_TAGS); - WorkflowPage.getters.workflowTagElements().first().click(); + WorkflowPage.getters.firstWorkflowTagElement().click(); WorkflowPage.getters.workflowTagsDropdown().find('li').first().click(); cy.get('body').type('{enter}'); WorkflowPage.getters.workflowTagElements().should('have.length', TEST_WF_TAGS.length - 1); diff --git a/cypress/pages/features/node-creator.ts b/cypress/pages/features/node-creator.ts index 54dc9790ba815..dad6f6ebe50d9 100644 --- a/cypress/pages/features/node-creator.ts +++ b/cypress/pages/features/node-creator.ts @@ -16,12 +16,13 @@ export class NodeCreator extends BasePage { creatorItem: () => cy.getByTestId('item-iterator-item'), communityNodeTooltip: () => cy.getByTestId('node-item-community-tooltip'), noResults: () => cy.getByTestId('categorized-no-results'), - nodeItemName: () => cy.getByTestId('node-item-name'), + nodeItemName: () => cy.getByTestId('node-creator-item-name'), activeSubcategory: () => cy.getByTestId('categorized-items-subcategory'), expandedCategories: () => this.getters.creatorItem().find('>div').filter('.active').invoke('text'), }; actions = { openNodeCreator: () => { + cy.get('.el-loading-mask').should('not.exist'); this.getters.plusButton().click(); this.getters.nodeCreator().should('be.visible') }, diff --git a/cypress/pages/workflow.ts b/cypress/pages/workflow.ts index 77001f2fc0dd2..3e0369ec7b24a 100644 --- a/cypress/pages/workflow.ts +++ b/cypress/pages/workflow.ts @@ -10,6 +10,7 @@ export class WorkflowPage extends BasePage { workflowTagsContainer: () => cy.getByTestId('workflow-tags-container'), workflowTagsInput: () => this.getters.workflowTagsContainer().then(($el) => cy.wrap($el.find('input').first())), workflowTagElements: () => cy.get('[data-test-id="workflow-tags-container"] span.tags > span'), + firstWorkflowTagElement: () => cy.get('[data-test-id="workflow-tags-container"] span.tags > span:nth-child(1)'), workflowTagsDropdown: () => cy.getByTestId('workflow-tags-dropdown'), newTagLink: () => cy.getByTestId('new-tag-link'), saveButton: () => cy.getByTestId('workflow-save-button'), @@ -43,12 +44,14 @@ export class WorkflowPage extends BasePage { addInitialNodeToCanvas: (nodeDisplayName: string) => { this.getters.canvasPlusButton().click(); this.getters.nodeCreatorSearchBar().type(nodeDisplayName); - this.getters.nodeCreatorSearchBar().type('{enter}{esc}'); + this.getters.nodeCreatorSearchBar().type('{enter}'); + cy.get('body').type('{esc}'); }, addNodeToCanvas: (nodeDisplayName: string) => { this.getters.nodeCreatorPlusButton().click(); this.getters.nodeCreatorSearchBar().type(nodeDisplayName); - this.getters.nodeCreatorSearchBar().type('{enter}{esc}'); + this.getters.nodeCreatorSearchBar().type('{enter}'); + cy.get('body').type('{esc}'); }, openNodeNdv: (nodeTypeName: string) => { this.getters.canvasNodeByName(nodeTypeName).dblclick(); diff --git a/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.stories.ts b/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.stories.ts new file mode 100644 index 0000000000000..7991eccca4b7d --- /dev/null +++ b/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.stories.ts @@ -0,0 +1,58 @@ +/* tslint:disable:variable-name */ +import N8nNodeCreatorNode from './NodeCreatorNode.vue'; +import { StoryFn } from '@storybook/vue'; + +export default { + title: 'Modules/Node Creator Node', + component: N8nNodeCreatorNode, +}; + +const DefaultTemplate: StoryFn = (args, { argTypes }) => ({ + props: Object.keys(argTypes), + components: { + N8nNodeCreatorNode, + }, + template: ` + + + + `, +}); + +export const WithTitle = DefaultTemplate.bind({}); +WithTitle.args = { + title: 'Node with title', + tooltipHtml: 'Bold tooltip', + description: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et vehicula ipsum, eu facilisis lacus. Aliquam commodo vel elit eget mollis. Quisque ac elit non purus iaculis placerat. Quisque fringilla ultrices nisi sed porta.', +}; + +const PanelTemplate: StoryFn = (args, { argTypes }) => ({ + props: Object.keys(argTypes), + components: { + N8nNodeCreatorNode, + }, + data() { + return { + isPanelActive: false, + }; + }, + template: ` + + + + + `, +}); +export const WithPanel = PanelTemplate.bind({}); +WithPanel.args = { + title: 'Node with panel', + isTrigger: true, +}; diff --git a/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue b/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue new file mode 100644 index 0000000000000..4e0aef14a932f --- /dev/null +++ b/packages/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue @@ -0,0 +1,125 @@ + + + + + + + diff --git a/packages/design-system/src/components/N8nNodeCreatorNode/TriggerIcon.vue b/packages/design-system/src/components/N8nNodeCreatorNode/TriggerIcon.vue new file mode 100644 index 0000000000000..dda6b227e72ec --- /dev/null +++ b/packages/design-system/src/components/N8nNodeCreatorNode/TriggerIcon.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/packages/design-system/src/components/N8nNodeCreatorNode/index.ts b/packages/design-system/src/components/N8nNodeCreatorNode/index.ts new file mode 100644 index 0000000000000..657f0d26f29e8 --- /dev/null +++ b/packages/design-system/src/components/N8nNodeCreatorNode/index.ts @@ -0,0 +1,3 @@ +import NodeCreatorNode from './NodeCreatorNode.vue'; + +export default NodeCreatorNode; diff --git a/packages/design-system/src/components/N8nNodeIcon/NodeIcon.vue b/packages/design-system/src/components/N8nNodeIcon/NodeIcon.vue index 79234705d1381..80948018a3427 100644 --- a/packages/design-system/src/components/N8nNodeIcon/NodeIcon.vue +++ b/packages/design-system/src/components/N8nNodeIcon/NodeIcon.vue @@ -2,24 +2,35 @@
- + +
- +
-
+
{{ nodeTypeName ? nodeTypeName.charAt(0) : '?' }} ?
+
@@ -91,7 +102,7 @@ export default Vue.extend({ diff --git a/packages/editor-ui/src/components/Node/NodeCreator/CategorizedItems.vue b/packages/editor-ui/src/components/Node/NodeCreator/CategorizedItems.vue index 9d6b50b62bfa8..ae18d680d3377 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/CategorizedItems.vue +++ b/packages/editor-ui/src/components/Node/NodeCreator/CategorizedItems.vue @@ -1,15 +1,14 @@