2019-06-23 03:35:23 -07:00
< template >
< div id = "side-menu" >
< executions -list :dialogVisible ="executionsListDialogVisible" @closeDialog ="closeExecutionsListOpenDialog" > < / executions -list >
< credentials -list :dialogVisible ="credentialOpenDialogVisible" @closeDialog ="closeCredentialOpenDialog" > < / credentials -list >
< credentials -edit :dialogVisible ="credentialNewDialogVisible" @closeDialog ="closeCredentialNewDialog" > < / credentials -edit >
< workflow -open @openWorkflow ="openWorkflow" :dialogVisible ="workflowOpenDialogVisible" @closeDialog ="closeWorkflowOpenDialog" > < / workflow -open >
< workflow -settings :dialogVisible ="workflowSettingsDialogVisible" @closeDialog ="closeWorkflowSettingsDialog" > < / workflow -settings >
< input type = "file" ref = "importFile" style = "display: none" v -on :change ="handleFileImport()" >
< div class = "side-menu-wrapper" : class = "{expanded: !isCollapsed}" >
< div id = "collapse-change-button" class = "clickable" @click ="isCollapsed=!isCollapsed" >
< font -awesome -icon icon = "angle-right" class = "icon" / >
< / div >
< el -menu default -active = " workflow " @select ="handleSelect" :collapse ="isCollapsed" >
< el -menu -item index = "logo" class = "logo-item" >
2019-09-22 11:56:16 -07:00
< el -tooltip placement = "top" effect = "light" >
< div slot = "content" >
n8n . io - Currently installed version { { versionCli } }
< / div >
< img src = "/n8n-icon-small.png" class = "icon" alt = "n8n.io" / >
< / e l - t o o l t i p >
2019-06-23 03:35:23 -07:00
< a href = "https://n8n.io" class = "logo-text" target = "_blank" slot = "title" >
2019-09-22 11:56:16 -07:00
n8n . io
2019-06-23 03:35:23 -07:00
< / a >
< / e l - m e n u - i t e m >
< el -submenu index = "workflow" >
< template slot = "title" >
< font -awesome -icon icon = "network-wired" / > & nbsp ;
< span slot = "title" class = "item-title-root" > Workflows < / span >
< / template >
< el -menu -item index = "workflow-new" >
< template slot = "title" >
< font -awesome -icon icon = "file" / > & nbsp ;
< span slot = "title" class = "item-title" > New < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-open" >
< template slot = "title" >
< font -awesome -icon icon = "folder-open" / > & nbsp ;
< span slot = "title" class = "item-title" > Open < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-save" :disabled ="!currentWorkflow" >
< template slot = "title" >
< font -awesome -icon icon = "save" / >
< span slot = "title" class = "item-title" > Save < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-save-as" >
< template slot = "title" >
< font -awesome -icon icon = "copy" / >
< span slot = "title" class = "item-title" > Save As < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-delete" :disabled ="!currentWorkflow" >
< template slot = "title" >
< font -awesome -icon icon = "trash" / >
< span slot = "title" class = "item-title" > Delete < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-download" >
< template slot = "title" >
< font -awesome -icon icon = "file-download" / >
< span slot = "title" class = "item-title" > Download < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-import-url" >
< template slot = "title" >
< font -awesome -icon icon = "cloud" / >
< span slot = "title" class = "item-title" > Import from URL < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-import-file" >
< template slot = "title" >
< font -awesome -icon icon = "hdd" / >
< span slot = "title" class = "item-title" > Import from File < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "workflow-settings" :disabled ="!currentWorkflow" >
< template slot = "title" >
< font -awesome -icon icon = "cog" / >
< span slot = "title" class = "item-title" > Settings < / span >
< / template >
< / e l - m e n u - i t e m >
< / e l - s u b m e n u >
< el -submenu index = "credentials" >
< template slot = "title" >
< font -awesome -icon icon = "key" / > & nbsp ;
< span slot = "title" class = "item-title-root" > Credentials < / span >
< / template >
< el -menu -item index = "credentials-new" >
< template slot = "title" >
< font -awesome -icon icon = "file" / >
< span slot = "title" class = "item-title" > New < / span >
< / template >
< / e l - m e n u - i t e m >
< el -menu -item index = "credentials-open" >
< template slot = "title" >
< font -awesome -icon icon = "folder-open" / >
< span slot = "title" class = "item-title" > Open < / span >
< / template >
< / e l - m e n u - i t e m >
< / e l - s u b m e n u >
< el -menu -item index = "executions" >
< font -awesome -icon icon = "tasks" / > & nbsp ;
< span slot = "title" class = "item-title-root" > Executions < / span >
< / e l - m e n u - i t e m >
< / e l - m e n u >
< / div >
< / div >
< / template >
< script lang = "ts" >
import Vue from 'vue' ;
import {
IExecutionResponse ,
IExecutionsStopData ,
IWorkflowDataUpdate ,
} from '../Interface' ;
import CredentialsEdit from '@/components/CredentialsEdit.vue' ;
import CredentialsList from '@/components/CredentialsList.vue' ;
import ExecutionsList from '@/components/ExecutionsList.vue' ;
import WorkflowOpen from '@/components/WorkflowOpen.vue' ;
import WorkflowSettings from '@/components/WorkflowSettings.vue' ;
import { genericHelpers } from '@/components/mixins/genericHelpers' ;
import { restApi } from '@/components/mixins/restApi' ;
import { showMessage } from '@/components/mixins/showMessage' ;
import { workflowHelpers } from '@/components/mixins/workflowHelpers' ;
import { workflowRun } from '@/components/mixins/workflowRun' ;
import { saveAs } from 'file-saver' ;
import mixins from 'vue-typed-mixins' ;
export default mixins (
genericHelpers ,
restApi ,
showMessage ,
workflowHelpers ,
workflowRun ,
)
. extend ( {
name : 'MainHeader' ,
components : {
CredentialsEdit ,
CredentialsList ,
ExecutionsList ,
WorkflowOpen ,
WorkflowSettings ,
} ,
data ( ) {
return {
isCollapsed : true ,
credentialNewDialogVisible : false ,
credentialOpenDialogVisible : false ,
executionsListDialogVisible : false ,
stopExecutionInProgress : false ,
workflowOpenDialogVisible : false ,
workflowSettingsDialogVisible : false ,
} ;
} ,
computed : {
exeuctionId ( ) : string | undefined {
return this . $route . params . id ;
} ,
executionFinished ( ) : boolean {
if ( ! this . isExecutionPage ) {
// We are not on an exeuction page so return false
return false ;
}
const fullExecution = this . $store . getters . getWorkflowExecution ;
if ( fullExecution === null ) {
// No exeuction loaded so return also false
return false ;
}
if ( fullExecution . finished === true ) {
return true ;
}
return false ;
} ,
executionWaitingForWebhook ( ) : boolean {
return this . $store . getters . executionWaitingForWebhook ;
} ,
isExecutionPage ( ) : boolean {
if ( [ 'ExecutionById' ] . includes ( this . $route . name as string ) ) {
return true ;
}
return false ;
} ,
isWorkflowActive ( ) : boolean {
return this . $store . getters . isActive ;
} ,
currentWorkflow ( ) : string {
return this . $route . params . name ;
} ,
2019-09-11 09:40:22 -07:00
versionCli ( ) : string {
return this . $store . getters . versionCli ;
} ,
2019-06-23 03:35:23 -07:00
workflowExecution ( ) : IExecutionResponse | null {
return this . $store . getters . getWorkflowExecution ;
} ,
workflowName ( ) : string {
return this . $store . getters . workflowName ;
} ,
workflowRunning ( ) : boolean {
return this . $store . getters . isActionActive ( 'workflowRunning' ) ;
} ,
} ,
methods : {
clearExecutionData ( ) {
this . $store . commit ( 'setWorkflowExecutionData' , null ) ;
this . updateNodesExecutionIssues ( ) ;
} ,
closeWorkflowOpenDialog ( ) {
this . workflowOpenDialogVisible = false ;
} ,
closeWorkflowSettingsDialog ( ) {
this . workflowSettingsDialogVisible = false ;
} ,
closeExecutionsListOpenDialog ( ) {
this . executionsListDialogVisible = false ;
} ,
closeCredentialOpenDialog ( ) {
this . credentialOpenDialogVisible = false ;
} ,
closeCredentialNewDialog ( ) {
this . credentialNewDialogVisible = false ;
} ,
async stopExecution ( ) {
const executionId = this . $store . getters . activeExecutionId ;
if ( executionId === null ) {
return ;
}
try {
this . stopExecutionInProgress = true ;
const stopData : IExecutionsStopData = await this . restApi ( ) . stopCurrentExecution ( executionId ) ;
this . $showMessage ( {
title : 'Execution stopped' ,
message : ` The execution with the id " ${ executionId } " got stopped! ` ,
type : 'success' ,
} ) ;
} catch ( error ) {
this . $showError ( error , 'Problem stopping execution' , 'There was a problem stopping the execuction:' ) ;
}
this . stopExecutionInProgress = false ;
} ,
async openWorkflow ( workflowId : string ) {
// Change to other workflow
this . $router . push ( {
name : 'NodeViewExisting' ,
params : { name : workflowId } ,
} ) ;
this . workflowOpenDialogVisible = false ;
} ,
async handleFileImport ( ) {
const reader = new FileReader ( ) ;
reader . onload = ( event : ProgressEvent ) => {
const data = ( event . target as FileReader ) . result ;
let worflowData : IWorkflowDataUpdate ;
try {
worflowData = JSON . parse ( data as string ) ;
} catch ( error ) {
this . $showMessage ( {
title : 'Could not import file' ,
message : ` The file does not contain valid JSON data. ` ,
type : 'error' ,
} ) ;
return ;
}
this . $root . $emit ( 'importWorkflowData' , { data : worflowData } ) ;
} ;
const input = this . $refs . importFile as HTMLInputElement ;
if ( input !== null && input . files !== null && input . files . length !== 0 ) {
reader . readAsText ( input ! . files [ 0 ] ! ) ;
}
} ,
async handleSelect ( key : string , keyPath : string ) {
if ( key === 'workflow-open' ) {
this . workflowOpenDialogVisible = true ;
} else if ( key === 'workflow-import-file' ) {
( this . $refs . importFile as HTMLInputElement ) . click ( ) ;
} else if ( key === 'workflow-import-url' ) {
try {
const promptResponse = await this . $prompt ( ` Workflow URL: ` , 'Import Workflow from URL:' , {
confirmButtonText : 'Import' ,
cancelButtonText : 'Cancel' ,
inputErrorMessage : 'Invalid URL' ,
inputPattern : /^http[s]?:\/\/.*\.json$/i ,
} ) ;
this . $root . $emit ( 'importWorkflowUrl' , { url : promptResponse . value } ) ;
} catch ( e ) { }
} else if ( key === 'workflow-delete' ) {
const deleteConfirmed = await this . confirmMessage ( ` Are you sure that you want to delete the workflow " ${ this . workflowName } "? ` , 'Delete Workflow?' , 'warning' , 'Yes, delete!' ) ;
if ( deleteConfirmed === false ) {
return ;
}
let result ;
try {
result = await this . restApi ( ) . deleteWorkflow ( this . currentWorkflow ) ;
} catch ( error ) {
this . $showError ( error , 'Problem deleting the workflow' , 'There was a problem deleting the workflow:' ) ;
return ;
}
this . $showMessage ( {
title : 'Workflow got deleted' ,
message : ` The workflow " ${ this . workflowName } " got deleted! ` ,
type : 'success' ,
} ) ;
this . $router . push ( { name : 'NodeViewNew' } ) ;
} else if ( key === 'workflow-download' ) {
const workflowData = await this . getWorkflowDataToSave ( ) ;
const blob = new Blob ( [ JSON . stringify ( workflowData , null , 2 ) ] , {
type : 'application/json;charset=utf-8' ,
} ) ;
let workflowName = this . $store . getters . workflowName || 'unsaved_workflow' ;
workflowName = workflowName . replace ( /[^a-z0-9]/gi , '_' ) ;
saveAs ( blob , workflowName + '.json' ) ;
} else if ( key === 'workflow-save' ) {
this . saveCurrentWorkflow ( ) ;
} else if ( key === 'workflow-save-as' ) {
this . saveCurrentWorkflow ( true ) ;
} else if ( key === 'workflow-settings' ) {
this . workflowSettingsDialogVisible = true ;
} else if ( key === 'workflow-new' ) {
this . $router . push ( { name : 'NodeViewNew' } ) ;
this . $showMessage ( {
title : 'Workflow created' ,
message : 'A new workflow got created!' ,
type : 'success' ,
} ) ;
} else if ( key === 'credentials-open' ) {
this . credentialOpenDialogVisible = true ;
} else if ( key === 'credentials-new' ) {
this . credentialNewDialogVisible = true ;
} else if ( key === 'execution-open-workflow' ) {
if ( this . workflowExecution !== null ) {
this . openWorkflow ( this . workflowExecution . workflowId as string ) ;
}
} else if ( key === 'executions' ) {
this . executionsListDialogVisible = true ;
}
} ,
} ,
async mounted ( ) {
this . $root . $on ( 'openWorkflowDialog' , async ( ) => {
this . workflowOpenDialogVisible = true ;
} ) ;
} ,
} ) ;
< / script >
< style lang = "scss" >
# collapse - change - button {
position : absolute ;
z - index : 10 ;
top : 55 px ;
left : 25 px ;
text - align : right ;
line - height : 24 px ;
height : 20 px ;
width : 20 px ;
background - color : # fff ;
border : none ;
border - radius : 15 px ;
- webkit - transition - duration : 0.5 s ;
- moz - transition - duration : 0.5 s ;
- o - transition - duration : 0.5 s ;
transition - duration : 0.5 s ;
- webkit - transition - property : - webkit - transform ;
- moz - transition - property : - moz - transform ;
- o - transition - property : - o - transform ;
transition - property : transform ;
overflow : hidden ;
. icon {
position : relative ;
left : - 5 px ;
top : - 2 px ;
}
}
# collapse - change - button : hover {
transform : scale ( 1.1 ) ;
}
. el - menu - item . logo - item {
background - color : $ -- color - primary ! important ;
height : 65 px ;
. icon {
position : relative ;
height : 23 px ;
left : - 10 px ;
top : - 2 px ;
}
}
a . logo - text {
position : relative ;
top : - 3 px ;
left : 5 px ;
font - weight : bold ;
color : # fff ;
text - decoration : none ;
}
. expanded # collapse - change - button {
- webkit - transform : translateX ( 60 px ) rotate ( 180 deg ) ;
- moz - transform : translateX ( 60 px ) rotate ( 180 deg ) ;
- o - transform : translateX ( 60 px ) rotate ( 180 deg ) ;
transform : translateX ( 60 px ) rotate ( 180 deg ) ;
}
# side - menu {
position : fixed ;
height : 100 % ;
. el - menu {
height : 100 % ;
}
}
. side - menu - wrapper {
height : 100 % ;
width : 65 px ;
& . expanded {
width : 200 px ;
}
}
< / style >