2022-10-24 11:17:25 -07:00
import { PropType } from "vue" ;
2019-06-23 03:35:23 -07:00
import mixins from 'vue-typed-mixins' ;
2022-10-24 11:17:25 -07:00
import { IJsPlumbInstance , IEndpointOptions , INodeUi , XYPosition } from '@/Interface' ;
2020-10-23 04:44:34 -07:00
import { deviceSupportHelpers } from '@/components/mixins/deviceSupportHelpers' ;
2022-08-03 04:06:53 -07:00
import { NO_OP_NODE_TYPE , STICKY_NODE_TYPE } from '@/constants' ;
2021-11-19 01:17:13 -08:00
import * as CanvasHelpers from '@/views/canvasHelpers' ;
import {
INodeTypeDescription ,
} from 'n8n-workflow' ;
2021-12-03 09:53:55 -08:00
import { getStyleTokenValue } from '../helpers' ;
2022-10-26 01:02:56 -07:00
import { readonly } from 'vue' ;
2019-06-23 03:35:23 -07:00
2020-10-23 04:44:34 -07:00
export const nodeBase = mixins (
deviceSupportHelpers ,
) . extend ( {
2019-06-23 03:35:23 -07:00
mounted ( ) {
// Initialize the node
if ( this . data !== null ) {
2022-10-26 01:02:56 -07:00
try {
this . __addNode ( this . data ) ;
} catch ( error ) {
// This breaks when new nodes are loaded into store but workflow tab is not currently active
// Shouldn't affect anything
}
2019-06-23 03:35:23 -07:00
}
} ,
computed : {
data ( ) : INodeUi {
2021-11-19 01:17:13 -08:00
return this . $store . getters . getNodeByName ( this . name ) ;
2019-06-23 03:35:23 -07:00
} ,
2021-11-19 01:17:13 -08:00
nodeId ( ) : string {
2022-08-03 04:06:53 -07:00
return this . data . id ;
2019-06-23 03:35:23 -07:00
} ,
} ,
feat(editor, core, cli): implement new workflow experience (#4358)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node (#4108)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node
* feat(editor): Do not show duplicate button if canvas contains `maxNodes` amount of nodes
* feat(ManualTrigger node): Implement ManualTrigger node (#4110)
* feat(ManualTrigger node): Implement ManualTrigger node
* :memo: Remove generics doc items from ManualTrigger node
* feat(editor-ui): Trigger tab redesign (#4150)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* 🎨 Use kebab case for main-panel and icon component
* :label: Improve types
* feat(editor-ui): Redesign search input inside node creator panel (#4204)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* :sparkles: Redesign search input and unify usage of categorized items
* :label: Use lowercase "Boolean" as `isSearchVisible` computed return type
* :fire: Remove useless emit
* :sparkles: Implement no result view based on subcategory, minor fixes
* :art: Remove unused properties
* feat(node-email): Change EmailReadImap display name and name (#4239)
* feat(editor-ui): Implement "Choose a Triger" action and related behaviour (#4226)
* :sparkles: Implement "Choose a Triger" action and related behaviour
* :mute: Lint fix
* :recycle: Remove PlaceholderTrigger node, add a button instead
* :art: Merge onMouseEnter and onMouseLeave to a single function
* :bulb: Add comment
* :fire: Remove PlaceholderNode registration
* :art: Rename TriggerPlaceholderButton to CanvasAddButton
* :sparkles: Add method to unregister custom action and rework CanvasAddButton centering logic
* :art: Run `setRecenteredCanvasAddButtonPosition` on `CanvasAddButton` mount
* fix(editor): Fix selecting of node from node-creator panel by clicking
* :twisted_rightwards_arrows: Merge fixes
* fix(editor): Show execute workflow trigger instead of workflow trigger in the trigger helper panel
* feat(editor): Fix node creator panel slide transition (#4261)
* fix(editor): Fix node creator panel slide-in/slide-out transitions
* :art: Fix naming
* :art: Use kebab-case for transition component name
* feat(editor): Disable execution and show notice when user tries to run workflow without enabled triggers
* fix(editor): Address first batch of new WF experience review (#4279)
* fix(editor): Fix first batch of review items
* bug(editor): Fix nodeview canvas add button centering
* :mute: Fix linter errors
* bug(ManualTrigger Node): Fix manual trigger node execution
* fix(editor): Do not show canvas add button in execution or demo mode and prevent clicking if creator is open
* fix(editor): do not show pin data tooltip for manual trigger node
* fix(editor): do not use nodeViewOffset on zoomToFit
* :lipstick: Add margin for last node creator item and set font-weight to 700 for category title
* :sparkles: Position welcome note next to the added trigger node
* :bug: Remve always true welcome note
* feat(editor): Minor UI and UX tweaks (#4328)
* :lipstick: Make top viewport buttons less prominent
* :sparkles: Allow user to switch to all tabs if it contains filter results, move nodecreator state props to its own module
* :mute: Fix linting errors
* :mute: Fix linting errors
* :mute: Fix linting errors
* chore(build): Ping Turbo version to 1.5.5
* :lipstick: Minor traigger panel and node view style changes
* :speech_balloon: Update display name of execute workflow trigger
* feat(core, editor): Update subworkflow execution logic (#4269)
* :sparkles: Implement `findWorkflowStart`
* :zap: Extend `WorkflowOperationError`
* :zap: Add `WorkflowOperationError` to toast
* :blue_book: Extend interface
* :sparkles: Add `subworkflowExecutionError` to store
* :sparkles: Create `SubworkflowOperationError`
* :zap: Render subworkflow error as node error
* :truck: Move subworkflow start validation to `cli`
* :zap: Reset subworkflow execution error state
* :fire: Remove unused import
* :zap: Adjust CLI commands
* :fire: Remove unneeded check
* :fire: Remove stray log
* :zap: Simplify syntax
* :zap: Sort in case both Start and EWT present
* :recycle: Address Omar's feedback
* :fire: Remove unneeded lint exception
* :pencil2: Fix copy
* :shirt: Fix lint
* fix: moved find start node function to catchable place
Co-authored-by: Omar Ajoue <krynble@gmail.com>
* :lipstick: Change ExecuteWorkflow node to primary
* :sparkles: Allow user to navigate to all tab if it contains search results
* :bug: Fixed canvas control button while in demo, disable workflow activation for non-activavle nodes and revert zoomToFit bottom offset
* :fix: Do not chow request text if there's results
* :speech_balloon: Update noResults text
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
2022-10-18 05:23:22 -07:00
props : {
name : {
type : String ,
} ,
instance : {
2022-10-24 11:17:25 -07:00
type : Object as PropType < IJsPlumbInstance > ,
feat(editor, core, cli): implement new workflow experience (#4358)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node (#4108)
* feat(ExecuteWorkflowTrigger node): Implement ExecuteWorkflowTrigger node
* feat(editor): Do not show duplicate button if canvas contains `maxNodes` amount of nodes
* feat(ManualTrigger node): Implement ManualTrigger node (#4110)
* feat(ManualTrigger node): Implement ManualTrigger node
* :memo: Remove generics doc items from ManualTrigger node
* feat(editor-ui): Trigger tab redesign (#4150)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* 🎨 Use kebab case for main-panel and icon component
* :label: Improve types
* feat(editor-ui): Redesign search input inside node creator panel (#4204)
* :construction: Begin with TriggerPanel implementation, add Other Trigger Nodes subcategory
* :construction: Extracted categorized categories/subcategory/nodes rendering into its own component — CategorizedItems, removed SubcategoryPanel, added translations
* :sparkles: Implement MainPanel background scrim
* :recycle: Move `categoriesWithNodes`, 'visibleNodeTypes` and 'categorizedItems` to store, implemented dynamic categories count based on `selectedType`
* :bug: Fix SlideTransition for all the NodeCreato panels
* :lipstick: Fix cursos for CategoryItem and NodeItem
* :bug: Make sure ALL_NODE_FILTER is always set when MainPanel is mounted
* :art: Address PR comments
* label: Use Array type for CategorizedItems props
* :label: Add proper types for Vue props
* 🎨 Use standard component registration for CategorizedItems inside TriggerHelperPanel
* :sparkles: Redesign search input and unify usage of categorized items
* :label: Use lowercase "Boolean" as `isSearchVisible` computed return type
* :fire: Remove useless emit
* :sparkles: Implement no result view based on subcategory, minor fixes
* :art: Remove unused properties
* feat(node-email): Change EmailReadImap display name and name (#4239)
* feat(editor-ui): Implement "Choose a Triger" action and related behaviour (#4226)
* :sparkles: Implement "Choose a Triger" action and related behaviour
* :mute: Lint fix
* :recycle: Remove PlaceholderTrigger node, add a button instead
* :art: Merge onMouseEnter and onMouseLeave to a single function
* :bulb: Add comment
* :fire: Remove PlaceholderNode registration
* :art: Rename TriggerPlaceholderButton to CanvasAddButton
* :sparkles: Add method to unregister custom action and rework CanvasAddButton centering logic
* :art: Run `setRecenteredCanvasAddButtonPosition` on `CanvasAddButton` mount
* fix(editor): Fix selecting of node from node-creator panel by clicking
* :twisted_rightwards_arrows: Merge fixes
* fix(editor): Show execute workflow trigger instead of workflow trigger in the trigger helper panel
* feat(editor): Fix node creator panel slide transition (#4261)
* fix(editor): Fix node creator panel slide-in/slide-out transitions
* :art: Fix naming
* :art: Use kebab-case for transition component name
* feat(editor): Disable execution and show notice when user tries to run workflow without enabled triggers
* fix(editor): Address first batch of new WF experience review (#4279)
* fix(editor): Fix first batch of review items
* bug(editor): Fix nodeview canvas add button centering
* :mute: Fix linter errors
* bug(ManualTrigger Node): Fix manual trigger node execution
* fix(editor): Do not show canvas add button in execution or demo mode and prevent clicking if creator is open
* fix(editor): do not show pin data tooltip for manual trigger node
* fix(editor): do not use nodeViewOffset on zoomToFit
* :lipstick: Add margin for last node creator item and set font-weight to 700 for category title
* :sparkles: Position welcome note next to the added trigger node
* :bug: Remve always true welcome note
* feat(editor): Minor UI and UX tweaks (#4328)
* :lipstick: Make top viewport buttons less prominent
* :sparkles: Allow user to switch to all tabs if it contains filter results, move nodecreator state props to its own module
* :mute: Fix linting errors
* :mute: Fix linting errors
* :mute: Fix linting errors
* chore(build): Ping Turbo version to 1.5.5
* :lipstick: Minor traigger panel and node view style changes
* :speech_balloon: Update display name of execute workflow trigger
* feat(core, editor): Update subworkflow execution logic (#4269)
* :sparkles: Implement `findWorkflowStart`
* :zap: Extend `WorkflowOperationError`
* :zap: Add `WorkflowOperationError` to toast
* :blue_book: Extend interface
* :sparkles: Add `subworkflowExecutionError` to store
* :sparkles: Create `SubworkflowOperationError`
* :zap: Render subworkflow error as node error
* :truck: Move subworkflow start validation to `cli`
* :zap: Reset subworkflow execution error state
* :fire: Remove unused import
* :zap: Adjust CLI commands
* :fire: Remove unneeded check
* :fire: Remove stray log
* :zap: Simplify syntax
* :zap: Sort in case both Start and EWT present
* :recycle: Address Omar's feedback
* :fire: Remove unneeded lint exception
* :pencil2: Fix copy
* :shirt: Fix lint
* fix: moved find start node function to catchable place
Co-authored-by: Omar Ajoue <krynble@gmail.com>
* :lipstick: Change ExecuteWorkflow node to primary
* :sparkles: Allow user to navigate to all tab if it contains search results
* :bug: Fixed canvas control button while in demo, disable workflow activation for non-activavle nodes and revert zoomToFit bottom offset
* :fix: Do not chow request text if there's results
* :speech_balloon: Update noResults text
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
2022-10-18 05:23:22 -07:00
} ,
isReadOnly : {
type : Boolean ,
} ,
isActive : {
type : Boolean ,
} ,
hideActions : {
type : Boolean ,
} ,
disableSelecting : {
type : Boolean ,
} ,
showCustomTooltip : {
type : Boolean ,
} ,
} ,
2019-06-23 03:35:23 -07:00
methods : {
2021-11-19 01:17:13 -08:00
__addInputEndpoints ( node : INodeUi , nodeTypeData : INodeTypeDescription ) {
2019-06-23 03:35:23 -07:00
// Add Inputs
2021-11-19 01:17:13 -08:00
let index ;
const indexData : {
2019-06-23 03:35:23 -07:00
[ key : string ] : number ;
} = { } ;
2021-11-19 01:17:13 -08:00
nodeTypeData . inputs . forEach ( ( inputName : string , i : number ) = > {
2019-06-23 03:35:23 -07:00
// Increment the index for inputs with current name
if ( indexData . hasOwnProperty ( inputName ) ) {
indexData [ inputName ] ++ ;
} else {
indexData [ inputName ] = 0 ;
}
index = indexData [ inputName ] ;
// Get the position of the anchor depending on how many it has
2021-11-19 01:17:13 -08:00
const anchorPosition = CanvasHelpers . ANCHOR_POSITIONS . input [ nodeTypeData . inputs . length ] [ index ] ;
2019-06-23 03:35:23 -07:00
2021-11-19 01:17:13 -08:00
const newEndpointData : IEndpointOptions = {
2022-08-03 04:06:53 -07:00
uuid : CanvasHelpers.getInputEndpointUUID ( this . nodeId , index ) ,
2019-06-23 03:35:23 -07:00
anchor : anchorPosition ,
2021-11-19 01:17:13 -08:00
maxConnections : - 1 ,
endpoint : 'Rectangle' ,
endpointStyle : CanvasHelpers.getInputEndpointStyle ( nodeTypeData , '--color-foreground-xdark' ) ,
endpointHoverStyle : CanvasHelpers.getInputEndpointStyle ( nodeTypeData , '--color-primary' ) ,
2019-06-23 03:35:23 -07:00
isSource : false ,
2021-12-03 09:53:55 -08:00
isTarget : ! this . isReadOnly && nodeTypeData . inputs . length > 1 , // only enabled for nodes with multiple inputs.. otherwise attachment handled by connectionDrag event in NodeView,
2019-06-23 03:35:23 -07:00
parameters : {
2022-08-03 04:06:53 -07:00
nodeId : this.nodeId ,
2019-06-23 03:35:23 -07:00
type : inputName ,
index ,
} ,
2021-12-03 09:53:55 -08:00
enabled : ! this . isReadOnly , // enabled in default case to allow dragging
cssClass : 'rect-input-endpoint' ,
2021-11-19 01:17:13 -08:00
dragAllowedWhenFull : true ,
2019-06-23 03:35:23 -07:00
dropOptions : {
tolerance : 'touch' ,
hoverClass : 'dropHover' ,
} ,
} ;
2019-08-02 06:56:05 -07:00
if ( nodeTypeData . inputNames ) {
// Apply input names if they got set
newEndpointData . overlays = [
2021-11-19 01:17:13 -08:00
CanvasHelpers . getInputNameOverlay ( nodeTypeData . inputNames [ index ] ) ,
2019-08-02 06:56:05 -07:00
] ;
}
2022-10-24 11:17:25 -07:00
const endpoint = this . instance . addEndpoint ( this . nodeId , newEndpointData ) ;
if ( ! Array . isArray ( endpoint ) ) {
endpoint . __meta = {
nodeName : node.name ,
nodeId : this.nodeId ,
index : i ,
totalEndpoints : nodeTypeData.inputs.length ,
} ;
}
2019-06-23 03:35:23 -07:00
2019-08-02 06:56:05 -07:00
// TODO: Activate again if it makes sense. Currently makes problems when removing
// connection on which the input has a name. It does not get hidden because
// the endpoint to which it connects when letting it go over the node is
// different to the regular one (have different ids). So that seems to make
// problems when hiding the input-name.
// if (index === 0 && inputName === 'main') {
// // Make the first main-input the default one to connect to when connection gets dropped on node
2021-11-19 01:17:13 -08:00
// this.instance.makeTarget(this.nodeId, newEndpointData);
2019-08-02 06:56:05 -07:00
// }
2019-06-23 03:35:23 -07:00
} ) ;
2021-11-19 01:17:13 -08:00
} ,
__addOutputEndpoints ( node : INodeUi , nodeTypeData : INodeTypeDescription ) {
let index ;
const indexData : {
[ key : string ] : number ;
} = { } ;
2019-06-23 03:35:23 -07:00
2021-11-19 01:17:13 -08:00
nodeTypeData . outputs . forEach ( ( inputName : string , i : number ) = > {
2019-06-23 03:35:23 -07:00
// Increment the index for outputs with current name
if ( indexData . hasOwnProperty ( inputName ) ) {
indexData [ inputName ] ++ ;
} else {
indexData [ inputName ] = 0 ;
}
index = indexData [ inputName ] ;
// Get the position of the anchor depending on how many it has
2021-11-19 01:17:13 -08:00
const anchorPosition = CanvasHelpers . ANCHOR_POSITIONS . output [ nodeTypeData . outputs . length ] [ index ] ;
2019-06-23 03:35:23 -07:00
2021-11-19 01:17:13 -08:00
const newEndpointData : IEndpointOptions = {
2022-08-03 04:06:53 -07:00
uuid : CanvasHelpers.getOutputEndpointUUID ( this . nodeId , index ) ,
2019-06-23 03:35:23 -07:00
anchor : anchorPosition ,
2021-11-19 01:17:13 -08:00
maxConnections : - 1 ,
endpoint : 'Dot' ,
endpointStyle : CanvasHelpers.getOutputEndpointStyle ( nodeTypeData , '--color-foreground-xdark' ) ,
endpointHoverStyle : CanvasHelpers.getOutputEndpointStyle ( nodeTypeData , '--color-primary' ) ,
isSource : true ,
2019-06-23 03:35:23 -07:00
isTarget : false ,
2021-11-19 01:17:13 -08:00
enabled : ! this . isReadOnly ,
2019-06-23 03:35:23 -07:00
parameters : {
2022-08-03 04:06:53 -07:00
nodeId : this.nodeId ,
2019-06-23 03:35:23 -07:00
type : inputName ,
index ,
} ,
2021-12-03 09:53:55 -08:00
cssClass : 'dot-output-endpoint' ,
2021-11-19 01:17:13 -08:00
dragAllowedWhenFull : false ,
2022-10-24 11:17:25 -07:00
dragProxy : [ 'Rectangle' , { width : 1 , height : 1 , strokeWidth : 0 } ] ,
2019-06-23 03:35:23 -07:00
} ;
if ( nodeTypeData . outputNames ) {
// Apply output names if they got set
newEndpointData . overlays = [
2021-11-19 01:17:13 -08:00
CanvasHelpers . getOutputNameOverlay ( nodeTypeData . outputNames [ index ] ) ,
2019-06-23 03:35:23 -07:00
] ;
}
2022-10-24 11:17:25 -07:00
const endpoint = this . instance . addEndpoint ( this . nodeId , { . . . newEndpointData } ) ;
if ( ! Array . isArray ( endpoint ) ) {
endpoint . __meta = {
nodeName : node.name ,
nodeId : this.nodeId ,
index : i ,
totalEndpoints : nodeTypeData.outputs.length ,
} ;
}
2021-12-03 09:53:55 -08:00
if ( ! this . isReadOnly ) {
const plusEndpointData : IEndpointOptions = {
2022-08-03 04:06:53 -07:00
uuid : CanvasHelpers.getOutputEndpointUUID ( this . nodeId , index ) ,
2021-12-03 09:53:55 -08:00
anchor : anchorPosition ,
maxConnections : - 1 ,
endpoint : 'N8nPlus' ,
isSource : true ,
isTarget : false ,
enabled : ! this . isReadOnly ,
endpointStyle : {
fill : getStyleTokenValue ( '--color-xdark' ) ,
outlineStroke : 'none' ,
hover : false ,
showOutputLabel : nodeTypeData.outputs.length === 1 ,
size : nodeTypeData.outputs.length >= 3 ? 'small' : 'medium' ,
2021-12-15 04:16:53 -08:00
hoverMessage : this.$locale.baseText ( 'nodeBase.clickToAddNodeOrDragToConnect' ) ,
2021-12-03 09:53:55 -08:00
} ,
endpointHoverStyle : {
fill : getStyleTokenValue ( '--color-primary' ) ,
outlineStroke : 'none' ,
hover : true , // hack to distinguish hover state
} ,
parameters : {
2022-08-03 04:06:53 -07:00
nodeId : this.nodeId ,
2021-12-03 09:53:55 -08:00
type : inputName ,
index ,
} ,
cssClass : 'plus-draggable-endpoint' ,
dragAllowedWhenFull : false ,
2022-10-24 11:17:25 -07:00
dragProxy : [ 'Rectangle' , { width : 1 , height : 1 , strokeWidth : 0 } ] ,
2021-12-03 09:53:55 -08:00
} ;
2022-10-24 11:17:25 -07:00
const plusEndpoint = this . instance . addEndpoint ( this . nodeId , plusEndpointData ) ;
if ( ! Array . isArray ( plusEndpoint ) ) {
plusEndpoint . __meta = {
nodeName : node.name ,
nodeId : this.nodeId ,
index : i ,
totalEndpoints : nodeTypeData.outputs.length ,
} ;
}
2021-12-03 09:53:55 -08:00
}
2019-06-23 03:35:23 -07:00
} ) ;
2021-11-19 01:17:13 -08:00
} ,
__makeInstanceDraggable ( node : INodeUi ) {
2020-06-07 15:34:15 -07:00
// TODO: This caused problems with displaying old information
// https://github.com/jsplumb/katavorio/wiki
// https://jsplumb.github.io/jsplumb/home.html
// Make nodes draggable
2021-11-19 01:17:13 -08:00
this . instance . draggable ( this . nodeId , {
grid : [ CanvasHelpers . GRID_SIZE , CanvasHelpers . GRID_SIZE ] ,
2020-06-07 15:34:15 -07:00
start : ( params : { e : MouseEvent } ) = > {
if ( this . isReadOnly === true ) {
// Do not allow to move nodes in readOnly mode
return false ;
}
:sparkles: Improve Waiting Webhook call state in WF Canvas (#2430)
* N8N-2586 Improve Waiting Webhook call state in WF Canvas
* N8N-2586 Added watcher for showing Webhook's Node Tooltip on execution
* N8N-2586 Show helping tooltip for trigger node if wokrflow is running, it is a trigger node, if it is only one trigger node in WF
* N8N-2586 Rework/Move logic to computed property, Created getter for ActveTriggerNodesInWokrflow, Add style to trigger node's tooltip, remove comments
* N8N-2586 Added EventTriggerDescription prop in INodeTypeDescription Interface, Updated Logic for TriggerNode Tooltip based on the new prop
* N8N-2586 Add new use cases/watcher to show Trigger Nodes Tooltip / If has issues, if paused, if wokrlfow is running, Refactor Getter
* N8N-2586 Added z-index to tooltip, Added new Scenario for Tooltip if it is Draged&Droped on the WF
* N8N-2586 Refactor computed property for draged nodes
* N8N-2586 Fixed Conflicts
* N8N-2586 Fixed Tooltip
* N8N-2586 Dont show tooltip on core trigger nodes that execute automatically
* N8N-2586 Fixed Webhook tooltip when adding/deleting canvas during WF execution
* N8N-2586 Updated Logic, Simplify the code
* N8N-2586 Simplify Code
* N8N-2586 Added check for nodetype
* update dragging to use local state
* N8N-2586 Added eventTriggerDescription to Interval Node
* add comment, use new getter
* update to always check
Co-authored-by: Mutasem <mutdmour@gmail.com>
2021-11-25 14:33:41 -08:00
// @ts-ignore
this . dragging = true ;
2020-06-07 15:34:15 -07:00
feat(editor): Add Workflow Stickies (Notes) (#3154)
* N8N-3029 Add Node Type for Wokrflow Stickies/Notes
* N8N-3029 Update Content, Update Aliasses
* N8N-3030 Created N8N Sticky Component in Design System
* N8N-3030 Fixed Code spaccing Sticky Component
* N8N-3030 Fixed Code spaccing StickyStories Component
* N8N-3030 Fixed Code spaccing Markdown Component
* N8N-3030 Added Sticky Colors Pallete into Storybook, Update Color Variables for Sticky Component
* N8N-3030 Added Unfocus Event
* N8N-3030 Update Default Placeholder, Markdown Styles, Fixed Edit State, Added Text to EditState, Fixed Height of Area, Turned off Resize of textarea
* N8N-3030 Update Sticky Overflow, Update Hover States, Updated Markdown Overflow
* N8N-3030, N8N-3031 - Add Resize to Sticky, Created N8n-Resize component
* N8N-3031 Fixed Importing Components in Editor-ui
* N8N-3031 Fixed Resize Component, Fixed Gradient
* N8N-3030, N8N-3031 Update Note Description
* N8N-3032 Hotfix Building Storybook
* N8N-3032 - Select Behaviour, Changes in Resize Component, Emit on Width/Height/Top/Left Change
* N8N-3032 Update Resize Component to emmit left/top, Update Dynamic Resize on Selected Background
* N8N-3032 Updated / Dragging vs Resizing, prevent open Modal for stickies
* N8N-3032 Added ID props to n8n-sticky // dynamic id for multi resizing in NodeView
* N8N-3033 Add dynamic size Tooltip on Sticky
* N8N-3033 Updated Z-index for Sticky Component
* N8N-3033 Updated N8N-Resize Component, Fixed SelectedBackround for Sticky Component
* N8N-3033 Refactor
* N8N-3033 Focus/Defocus on TextArea
* N8N-3033 Fixed Resizing on NW Point
* N8N-3030 Save content in vuex on input change
* N8N-3033 Fixed Resizer, Save Width and Height in Vue
* N8N-3033 Hide Sticky Footer on small height/width
* N8N-3033 Fixed Resizer
* N8N-3033 Dynamic Z-index for Stickies
* N8N-3033 Dynamic Z-index for Stickies
* N8N-3033 Removed static z-index for select sticky class
* N8N-3034 Added Telemetry
* N8N-3030 Formatter
* N8N-3030 Format code
* N8N-3030 Fixed Selecting Stickies
* N8N-3033 Fixed Notifications
* N8N-3030 Added new paddings for Default Stickies
* N8N-3033 Prevent Scrolling NodeView when Sticky is in Edit mode and Mouse is Over the TextArea
* N8N-3030 Prevent double clicking to switch state of Sticky component in Edit Mode
* N8N-3033 Fixed Z-index of Stickies
* N8N-3033 Prevent delete node when in EditMode
* N8N-3030 Prevent Delete Button to delete the Sticky while in Edit Mode
* N8N-3030 Change EditMode (emit) on keyboard shortucts, update Markdown Links & Images, Added new props
* N8N-3030 Sticky Component - No padding when hiding footer text
* N8N-3033 Fix Resizing enter into Edit Mode
* N8N-3033 Selecting different nodes - exit the edit mode
* N8N-3033 Auto Select Text in text-area by default - Sticky Component
* N8N-3033 Prevent Default behaviour for CTRL + X, CTRL + A when Sticky is Active && inEditMode
* N8N-3033 Refactor Resizer, Refactor Sticky, Update zIndex inEditMode
* N8N-3033 Updated Default Text // Node-base, Storybook
* N8N-3033 Add Resizing in EditMode - Components update
* N8N-3033 Fixed Footer - Show/Hide on Resize in EditMode
* N8N-3033 Fix ActiveSticky on Init
* N8N-3033 Refactor Sticky in Vuex, Fixed Init Sticky Tweaks, Prevent Modal Openning, Save on Keyboard shortcuts
* Stickies - Update Note node with new props
* N8N-3030 Updated Default Note text, Update the Markdown Link
* N8N-3030 CMD-C does not copy the text fix
* N8N-3030 Fix Max Zoom / Zoom out shortcuts disabled in editState
* N8N-3030 Z-index fixed during Edit Mode typing
* N8N-3030 Prevent Autoselect Text in Stickies if the text is not default
* N8N-3030 Fixed ReadOnly Bugs / Prevent showing Tooltip, Resizing
* N8N-3030 Added Sticky Creator Button
* N8N-3030 Update Icon / Sticky Creator Button
* N8N-3033 Update Sticky Icon / StickyCreator Button
* update package lock
* 🔩 update note props
* 🚿 clean props
* 🔧 linting
* :wrench: fix spacing
* remove resize component
* remove resize component
* ✂ clean up sticky
* revert back to height width
* revert back to height/width
* replace zindex property
* replace default text property
* use i18n to translate
* update package lock
* move resize
* clean up how height/width are set
* fix resize for sticky to support left/top
* clean up resize
* fix lasso/highlight bug
* remove unused props
* fix zoom to fit
* fix padding for demo view
* fix readonly
* remove iseditable, use active state
* clean up keyboard events
* chang button size, no edit on insert
* scale resizing correctly
* make active on resize
* fix select on resize/move
* use outline icon
* allow for multiple line breaks
* fix multi line bug
* fix edit mode outline
* keep edit open as one resizes
* respect multiple spaces
* fix scrolling bug
* clean up hover impl
* clean up references to note
* disable for rename
* fix drifting while drag
* fix mouse cursor on resize
* fix sticky min height
* refactor resize into component
* fix pulling too far bug
* fix delete/cut all bug
* fix padding bottom
* fix active change on resize
* add transition to button
* Fix sticky markdown click
* add solid fa icon
* update node graph, telemetry event
* add snapping
* change alt text
* update package lock
* fix bug in button hover
* add back transition
* clean up resize
* add grid size as param
* remove breaks
* clean up markdown
* lint fixes
* fix spacing
* clean up markdown colors
* clean up classes in resize
* clean up resize
* update sticky story
* fix spacing
* clean up classes
* revert change
* revert change
* revert change
* clean up sticky component
* remove unused component
* remove unnessary data
* remove unnessary data
* clean up actions
* clean up sticky size
* clean up unnessary border style
* fix bug
* replace sticky note name
* update description
* remove support for multi spaces
* update tracking name
* update telemetry reqs
* fix enter bug
* update alt text
* update sticky notes doc url
* fix readonly bug
* update class name
* update quote marks
Co-authored-by: SchnapsterDog <olivertrajceski@yahoo.com>
2022-04-25 03:38:37 -07:00
const isSelected = this . $store . getters . isNodeSelected ( this . data . name ) ;
const nodeName = this . data . name ;
if ( this . data . type === STICKY_NODE_TYPE && ! isSelected ) {
setTimeout ( ( ) = > {
this . $emit ( 'nodeSelected' , nodeName , false , true ) ;
} , 0 ) ;
}
if ( params . e && ! isSelected ) {
2020-06-07 15:34:15 -07:00
// Only the node which gets dragged directly gets an event, for all others it is
// undefined. So check if the currently dragged node is selected and if not clear
// the drag-selection.
this . instance . clearDragSelection ( ) ;
this . $store . commit ( 'resetSelectedNodes' ) ;
}
this . $store . commit ( 'addActiveAction' , 'dragActive' ) ;
return true ;
} ,
stop : ( params : { e : MouseEvent } ) = > {
:sparkles: Improve Waiting Webhook call state in WF Canvas (#2430)
* N8N-2586 Improve Waiting Webhook call state in WF Canvas
* N8N-2586 Added watcher for showing Webhook's Node Tooltip on execution
* N8N-2586 Show helping tooltip for trigger node if wokrflow is running, it is a trigger node, if it is only one trigger node in WF
* N8N-2586 Rework/Move logic to computed property, Created getter for ActveTriggerNodesInWokrflow, Add style to trigger node's tooltip, remove comments
* N8N-2586 Added EventTriggerDescription prop in INodeTypeDescription Interface, Updated Logic for TriggerNode Tooltip based on the new prop
* N8N-2586 Add new use cases/watcher to show Trigger Nodes Tooltip / If has issues, if paused, if wokrlfow is running, Refactor Getter
* N8N-2586 Added z-index to tooltip, Added new Scenario for Tooltip if it is Draged&Droped on the WF
* N8N-2586 Refactor computed property for draged nodes
* N8N-2586 Fixed Conflicts
* N8N-2586 Fixed Tooltip
* N8N-2586 Dont show tooltip on core trigger nodes that execute automatically
* N8N-2586 Fixed Webhook tooltip when adding/deleting canvas during WF execution
* N8N-2586 Updated Logic, Simplify the code
* N8N-2586 Simplify Code
* N8N-2586 Added check for nodetype
* update dragging to use local state
* N8N-2586 Added eventTriggerDescription to Interval Node
* add comment, use new getter
* update to always check
Co-authored-by: Mutasem <mutdmour@gmail.com>
2021-11-25 14:33:41 -08:00
// @ts-ignore
this . dragging = false ;
2020-06-07 15:34:15 -07:00
if ( this . $store . getters . isActionActive ( 'dragActive' ) ) {
const moveNodes = this . $store . getters . getSelectedNodes . slice ( ) ;
const selectedNodeNames = moveNodes . map ( ( node : INodeUi ) = > node . name ) ;
if ( ! selectedNodeNames . includes ( this . data . name ) ) {
// If the current node is not in selected add it to the nodes which
// got moved manually
moveNodes . push ( this . data ) ;
2019-06-23 03:35:23 -07:00
}
2020-06-07 15:34:15 -07:00
// This does for some reason just get called once for the node that got clicked
// even though "start" and "drag" gets called for all. So lets do for now
// some dirty DOM query to get the new positions till I have more time to
// create a proper solution
2022-09-02 07:13:17 -07:00
let newNodePosition : XYPosition ;
2020-06-07 15:34:15 -07:00
moveNodes . forEach ( ( node : INodeUi ) = > {
2022-08-03 04:06:53 -07:00
const element = document . getElementById ( node . id ) ;
2020-06-07 15:34:15 -07:00
if ( element === null ) {
return ;
2019-06-23 03:35:23 -07:00
}
2022-09-02 07:13:17 -07:00
newNodePosition = [
2020-06-07 15:34:15 -07:00
parseInt ( element . style . left ! . slice ( 0 , - 2 ) , 10 ) ,
parseInt ( element . style . top ! . slice ( 0 , - 2 ) , 10 ) ,
] ;
const updateInformation = {
name : node.name ,
properties : {
// @ts-ignore, draggable does not have definitions
2022-09-02 07:13:17 -07:00
position : newNodePosition ,
2020-06-07 15:34:15 -07:00
} ,
} ;
this . $store . commit ( 'updateNodeProperties' , updateInformation ) ;
} ) ;
2021-11-19 01:17:13 -08:00
this . $emit ( 'moved' , node ) ;
2020-06-07 15:34:15 -07:00
}
} ,
filter : '.node-description, .node-description .node-name, .node-description .node-subtitle' ,
} ) ;
2021-11-19 01:17:13 -08:00
} ,
__addNode ( node : INodeUi ) {
2022-08-01 13:43:50 -07:00
let nodeTypeData = this . $store . getters [ 'nodeTypes/getNodeType' ] ( node . type , node . typeVersion ) as INodeTypeDescription | null ;
2021-11-19 01:17:13 -08:00
if ( ! nodeTypeData ) {
// If node type is not know use by default the base.noOp data to display it
2022-08-01 13:43:50 -07:00
nodeTypeData = this . $store . getters [ 'nodeTypes/getNodeType' ] ( NO_OP_NODE_TYPE ) as INodeTypeDescription ;
2021-11-19 01:17:13 -08:00
}
2020-06-07 15:34:15 -07:00
2021-11-19 01:17:13 -08:00
this . __addInputEndpoints ( node , nodeTypeData ) ;
this . __addOutputEndpoints ( node , nodeTypeData ) ;
this . __makeInstanceDraggable ( node ) ;
2019-06-23 03:35:23 -07:00
} ,
2021-08-08 02:14:09 -07:00
touchEnd ( e : MouseEvent ) {
if ( this . isTouchDevice ) {
if ( this . $store . getters . isActionActive ( 'dragActive' ) ) {
this . $store . commit ( 'removeActiveAction' , 'dragActive' ) ;
}
}
} ,
2020-10-23 09:15:52 -07:00
mouseLeftClick ( e : MouseEvent ) {
2020-12-23 23:37:13 -08:00
// @ts-ignore
const path = e . path || ( e . composedPath && e . composedPath ( ) ) ;
for ( let index = 0 ; index < path . length ; index ++ ) {
if ( path [ index ] . className && typeof path [ index ] . className === 'string' && path [ index ] . className . includes ( 'no-select-on-click' ) ) {
return ;
}
}
2020-10-23 09:15:52 -07:00
if ( ! this . isTouchDevice ) {
if ( this . $store . getters . isActionActive ( 'dragActive' ) ) {
this . $store . commit ( 'removeActiveAction' , 'dragActive' ) ;
2019-07-17 10:05:03 -07:00
} else {
2022-10-11 01:06:33 -07:00
if ( ! this . isCtrlKeyPressed ( e ) ) {
2020-10-23 09:15:52 -07:00
this . $emit ( 'deselectAllNodes' ) ;
}
if ( this . $store . getters . isNodeSelected ( this . data . name ) ) {
this . $emit ( 'deselectNode' , this . name ) ;
} else {
this . $emit ( 'nodeSelected' , this . name ) ;
}
2019-07-17 10:05:03 -07:00
}
2019-06-23 03:35:23 -07:00
}
} ,
} ,
} ) ;