2015-03-15 23:54:55 +01:00
/ * *
* Copyright 2015 IBM Corp .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* * /
RED . deploy = ( function ( ) {
var deploymentTypes = {
2015-04-02 00:24:47 +02:00
"full" : { img : "red/images/deploy-full-o.png" } ,
"nodes" : { img : "red/images/deploy-nodes-o.png" } ,
"flows" : { img : "red/images/deploy-flows-o.png" }
2015-03-15 23:54:55 +01:00
}
2015-06-10 15:52:58 +02:00
var ignoreDeployWarnings = {
unknown : false ,
unusedConfig : false ,
invalid : false
}
2015-03-15 23:54:55 +01:00
var deploymentType = "full" ;
function changeDeploymentType ( type ) {
deploymentType = type ;
$ ( "#btn-deploy img" ) . attr ( "src" , deploymentTypes [ type ] . img ) ;
}
2015-04-10 16:13:40 +02:00
/ * *
* options :
* type : "default" - Button with drop - down options - no further customisation available
* type : "simple" - Button without dropdown . Customisations :
* label : the text to display - default : "Deploy"
* icon : the icon to use . Null removes the icon . default : "red/images/deploy-full-o.png"
* /
function init ( options ) {
options = options || { } ;
var type = options . type || "default" ;
2015-03-15 23:54:55 +01:00
2015-04-10 16:13:40 +02:00
if ( type == "default" ) {
$ ( '<li><span class="deploy-button-group button-group">' +
2015-04-13 22:50:40 +02:00
'<a id="btn-deploy" class="deploy-button disabled" href="#"><img id="btn-deploy-icon" src="red/images/deploy-full-o.png"> <span>Deploy</span></a>' +
'<a id="btn-deploy-options" data-toggle="dropdown" class="deploy-button" href="#"><i class="fa fa-caret-down"></i></a>' +
2015-04-10 16:13:40 +02:00
'</span></li>' ) . prependTo ( ".header-toolbar" ) ;
RED . menu . init ( { id : "btn-deploy-options" ,
options : [
2015-04-20 12:17:27 +02:00
{ id : "deploymenu-item-full" , toggle : "deploy-type" , icon : "red/images/deploy-full.png" , label : "Full" , sublabel : "Deploys everything in the workspace" , selected : true , onselect : function ( s ) { if ( s ) { changeDeploymentType ( "full" ) } } } ,
2015-04-13 17:48:38 +02:00
{ id : "deploymenu-item-flow" , toggle : "deploy-type" , icon : "red/images/deploy-flows.png" , label : "Modified Flows" , sublabel : "Only deploys flows that contain changed nodes" , onselect : function ( s ) { if ( s ) { changeDeploymentType ( "flows" ) } } } ,
{ id : "deploymenu-item-node" , toggle : "deploy-type" , icon : "red/images/deploy-nodes.png" , label : "Modified Nodes" , sublabel : "Only deploys nodes that have changed" , onselect : function ( s ) { if ( s ) { changeDeploymentType ( "nodes" ) } } }
2015-04-10 16:13:40 +02:00
]
} ) ;
} else if ( type == "simple" ) {
var label = options . label || "Deploy" ;
var icon = 'red/images/deploy-full-o.png' ;
if ( options . hasOwnProperty ( 'icon' ) ) {
icon = options . icon ;
}
$ ( '<li><span class="deploy-button-group button-group">' +
2015-04-13 22:50:40 +02:00
'<a id="btn-deploy" class="deploy-button disabled" href="#">' +
2015-04-13 17:48:38 +02:00
( icon ? '<img id="btn-deploy-icon" src="' + icon + '"> ' : '' ) +
2015-04-10 16:13:40 +02:00
'<span>' + label + '</span></a>' +
'</span></li>' ) . prependTo ( ".header-toolbar" ) ;
}
2015-03-15 23:54:55 +01:00
$ ( '#btn-deploy' ) . click ( function ( ) { save ( ) ; } ) ;
$ ( "#node-dialog-confirm-deploy" ) . dialog ( {
title : "Confirm deploy" ,
modal : true ,
autoOpen : false ,
2015-06-10 15:52:58 +02:00
width : 550 ,
height : "auto" ,
2015-03-15 23:54:55 +01:00
buttons : [
{
text : "Confirm deploy" ,
click : function ( ) {
2015-06-10 15:52:58 +02:00
var ignoreChecked = $ ( "#node-dialog-confirm-deploy-hide" ) . prop ( "checked" ) ;
if ( ignoreChecked ) {
ignoreDeployWarnings [ $ ( "#node-dialog-confirm-deploy-type" ) . val ( ) ] = true ;
}
2015-03-15 23:54:55 +01:00
save ( true ) ;
$ ( this ) . dialog ( "close" ) ;
}
} ,
{
text : "Cancel" ,
click : function ( ) {
$ ( this ) . dialog ( "close" ) ;
}
}
2015-06-10 15:52:58 +02:00
] ,
create : function ( ) {
$ ( "#node-dialog-confirm-deploy" ) . parent ( ) . find ( "div.ui-dialog-buttonpane" )
. append ( '<div style="height:0; vertical-align: middle; display:inline-block;">' +
'<input style="vertical-align:top;" type="checkbox" id="node-dialog-confirm-deploy-hide">' +
'<label style="display:inline;" for="node-dialog-confirm-deploy-hide"> do not warn about this again</label>' +
'<input type="hidden" id="node-dialog-confirm-deploy-type">' +
'</div>' ) ;
}
2015-03-15 23:54:55 +01:00
} ) ;
2015-03-17 16:38:31 +01:00
2015-03-15 23:54:55 +01:00
RED . nodes . on ( 'change' , function ( state ) {
if ( state . dirty ) {
2015-03-16 00:48:02 +01:00
window . onbeforeunload = function ( ) {
2015-03-17 16:38:31 +01:00
return "You have undeployed changes.\n\nLeaving this page will lose these changes." ;
2015-03-16 00:48:02 +01:00
}
2015-03-15 23:54:55 +01:00
$ ( "#btn-deploy" ) . removeClass ( "disabled" ) ;
} else {
2015-03-16 00:48:02 +01:00
window . onbeforeunload = null ;
2015-03-15 23:54:55 +01:00
$ ( "#btn-deploy" ) . addClass ( "disabled" ) ;
}
} ) ;
}
2015-03-17 16:38:31 +01:00
2015-03-15 23:54:55 +01:00
function save ( force ) {
if ( RED . nodes . dirty ( ) ) {
//$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy
if ( ! force ) {
2015-06-10 15:52:58 +02:00
var hasUnknown = false ;
var hasInvalid = false ;
var hasUnusedConfig = false ;
2015-03-15 23:54:55 +01:00
var unknownNodes = [ ] ;
RED . nodes . eachNode ( function ( node ) {
2015-06-10 15:52:58 +02:00
hasInvalid = hasInvalid || ! node . valid ;
2015-03-15 23:54:55 +01:00
if ( node . type === "unknown" ) {
if ( unknownNodes . indexOf ( node . name ) == - 1 ) {
unknownNodes . push ( node . name ) ;
}
}
} ) ;
2015-06-10 15:52:58 +02:00
hasUnknown = unknownNodes . length > 0 ;
var unusedConfigNodes = { } ;
RED . nodes . eachConfig ( function ( node ) {
if ( node . users . length === 0 ) {
var label = "" ;
if ( typeof node . _def . label == "function" ) {
label = node . _def . label . call ( node ) ;
} else {
label = node . _def . label ;
}
label = label || node . id ;
unusedConfigNodes [ node . type ] = unusedConfigNodes [ node . type ] || [ ] ;
unusedConfigNodes [ node . type ] . push ( label ) ;
hasUnusedConfig = true ;
2015-03-15 23:54:55 +01:00
}
2015-06-10 15:52:58 +02:00
} ) ;
$ ( "#node-dialog-confirm-deploy-config" ) . hide ( ) ;
$ ( "#node-dialog-confirm-deploy-unknown" ) . hide ( ) ;
$ ( "#node-dialog-confirm-deploy-unused" ) . hide ( ) ;
var showWarning = false ;
if ( hasUnknown && ! ignoreDeployWarnings . unknown ) {
showWarning = true ;
$ ( "#node-dialog-confirm-deploy-type" ) . val ( "unknown" ) ;
$ ( "#node-dialog-confirm-deploy-unknown" ) . show ( ) ;
$ ( "#node-dialog-confirm-deploy-unknown-list" )
. html ( "<li>" + unknownNodes . join ( "</li><li>" ) + "</li>" ) ;
} else if ( hasInvalid && ! ignoreDeployWarnings . invalid ) {
showWarning = true ;
$ ( "#node-dialog-confirm-deploy-type" ) . val ( "invalid" ) ;
$ ( "#node-dialog-confirm-deploy-config" ) . show ( ) ;
} else if ( hasUnusedConfig && ! ignoreDeployWarnings . unusedConfig ) {
showWarning = true ;
$ ( "#node-dialog-confirm-deploy-type" ) . val ( "unusedConfig" ) ;
$ ( "#node-dialog-confirm-deploy-unused" ) . show ( ) ;
var unusedNodeLabels = [ ] ;
var unusedTypes = Object . keys ( unusedConfigNodes ) . sort ( ) ;
unusedTypes . forEach ( function ( type ) {
unusedConfigNodes [ type ] . forEach ( function ( label ) {
unusedNodeLabels . push ( type + ": " + label ) ;
} ) ;
} ) ;
$ ( "#node-dialog-confirm-deploy-unused-list" )
. html ( "<li>" + unusedNodeLabels . join ( "</li><li>" ) + "</li>" ) ;
}
if ( showWarning ) {
$ ( "#node-dialog-confirm-deploy-hide" ) . prop ( "checked" , false ) ;
2015-03-15 23:54:55 +01:00
$ ( "#node-dialog-confirm-deploy" ) . dialog ( "open" ) ;
return ;
}
}
2015-06-10 15:52:58 +02:00
2015-03-15 23:54:55 +01:00
var nns = RED . nodes . createCompleteNodeSet ( ) ;
2015-04-13 17:48:38 +02:00
$ ( "#btn-deploy-icon" ) . removeClass ( 'fa-download' ) ;
$ ( "#btn-deploy-icon" ) . addClass ( 'spinner' ) ;
2015-03-15 23:54:55 +01:00
RED . nodes . dirty ( false ) ;
$ . ajax ( {
url : "flows" ,
type : "POST" ,
data : JSON . stringify ( nns ) ,
contentType : "application/json; charset=utf-8" ,
headers : {
"Node-RED-Deployment-Type" : deploymentType
}
} ) . done ( function ( data , textStatus , xhr ) {
RED . notify ( "Successfully deployed" , "success" ) ;
RED . nodes . eachNode ( function ( node ) {
if ( node . changed ) {
node . dirty = true ;
node . changed = false ;
}
if ( node . credentials ) {
delete node . credentials ;
}
} ) ;
RED . nodes . eachConfig ( function ( confNode ) {
if ( confNode . credentials ) {
delete confNode . credentials ;
}
} ) ;
// Once deployed, cannot undo back to a clean state
RED . history . markAllDirty ( ) ;
RED . view . redraw ( ) ;
} ) . fail ( function ( xhr , textStatus , err ) {
RED . nodes . dirty ( true ) ;
if ( xhr . responseText ) {
2015-03-30 15:16:04 +02:00
RED . notify ( "<strong>Error</strong>: " + xhr . responseJSON . message , "error" ) ;
2015-03-15 23:54:55 +01:00
} else {
RED . notify ( "<strong>Error</strong>: no response from server" , "error" ) ;
}
} ) . always ( function ( ) {
2015-04-13 17:48:38 +02:00
$ ( "#btn-deploy-icon" ) . removeClass ( 'spinner' ) ;
$ ( "#btn-deploy-icon" ) . addClass ( 'fa-download' ) ;
2015-03-15 23:54:55 +01:00
} ) ;
}
}
return {
init : init
}
} ) ( ) ;