ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nc...@apache.org
Subject [02/50] [abbrv] ambari git commit: AMBARI-19622. Need abilities to add a custom action node and import a workflow xml with custom action (Padma Priya via pallavkul)
Date Wed, 25 Jan 2017 18:56:51 GMT
AMBARI-19622. Need abilities to add a custom action node and import a workflow xml with custom
action (Padma Priya via pallavkul)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3e5185ac
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3e5185ac
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3e5185ac

Branch: refs/heads/branch-dev-patch-upgrade
Commit: 3e5185acaea24bfeb28f4b10da6d3a94c90dcacd
Parents: 9abe8da
Author: pallavkul <pallav.kul@gmail.com>
Authored: Mon Jan 23 15:00:03 2017 +0530
Committer: pallavkul <pallav.kul@gmail.com>
Committed: Mon Jan 23 15:00:03 2017 +0530

----------------------------------------------------------------------
 .../ui/app/components/flow-designer.js          | 11 +++
 .../ui/app/components/workflow-action-editor.js | 77 ++++++++++++++++----
 .../ui/app/components/workflow-actions.js       |  5 ++
 .../ui/app/domain/action-type-resolver.js       | 10 ++-
 .../ui/app/domain/actionjob_hanlder.js          | 22 +++++-
 .../resources/ui/app/domain/node-handler.js     | 10 +--
 .../src/main/resources/ui/app/styles/app.less   |  4 +
 .../app/templates/components/flow-designer.hbs  | 25 +++++++
 .../components/workflow-action-editor.hbs       | 16 ++++
 .../templates/components/workflow-actions.hbs   |  3 +
 .../main/resources/ui/app/utils/common-utils.js |  4 +
 .../main/resources/ui/app/utils/constants.js    |  3 +-
 12 files changed, 169 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
index 8bbe831..1822a20 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
@@ -775,6 +775,17 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       this.set('showCreateKillNode', false);
     },
     addNode(type){
+      if(type === 'custom'){
+        this.$('#customTypeModal').modal('show');
+      }else{
+        this.send('addAction', type);
+      }
+    },
+    createCustomAction(type){
+      this.send('addAction', type);
+      this.set('customActionType', '');
+    },
+    addAction(type){
       this.createSnapshot();
       var currentTransition=this.get("currentTransition");
       this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode, currentTransition.sourceNodeId,
currentTransition.targetNode.id),type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
index 8a3c7cf..f2d3ba8 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
@@ -17,6 +17,7 @@
 
 import Ember from 'ember';
 import Constants from '../utils/constants';
+import CommonUtils from '../utils/common-utils';
 import {SlaInfo} from '../domain/sla-info';
 
 export default Ember.Component.extend( Ember.Evented,{
@@ -40,6 +41,7 @@ export default Ember.Component.extend( Ember.Evented,{
   clonedActionModel : {},
   showingFileBrowser : false,
   childComponents : new Map(),
+  errors : Ember.A([]),
   isActionNode : Ember.computed('nodeType',function(){
     if(this.get('nodeType') === 'action'){
       return true;
@@ -58,13 +60,43 @@ export default Ember.Component.extend( Ember.Evented,{
     return this.get('actionIcons')[this.get('actionType')];
   }),
   saveClicked : false,
-  containsUnsupportedProperties : Ember.computed('actionModel.unsupportedProperties', function(){
-    return this.get('actionModel.unsupportedProperties') ? !Ember.isEmpty(Object.keys(this.get('actionModel.unsupportedProperties')))
: false;
-  }),
-  unsupportedPropertiesXml : Ember.computed('actionModel.unsupportedProperties', function(){
-    if(this.get('containsUnsupportedProperties')){
-      var x2js = new X2JS();
+  unsupportedPropertiesXml : Ember.computed('actionModel.unsupportedProperties', {
+    get(key){
+      let x2js = new X2JS();
       return vkbeautify.xml(x2js.json2xml_str(this.get('actionModel.unsupportedProperties')));
+    },
+    set(key, value) {
+      let x2js = new X2JS();
+      var temp = x2js.xml_str2json(vkbeautify.xmlmin(`<unsupportedProperties>${value}</unsupportedProperties>`));
+      this.set('actionModel.unsupportedProperties', temp.unsupportedProperties);
+      Object.keys(this.get('actionModel.unsupportedProperties')).forEach(key =>{
+        this.set(`actionModel.${key}`, this.get(`actionModel.unsupportedProperties.${key}`));
+      });
+      return value;
+    }
+  }),
+  actionXml : Ember.computed('actionModel', {
+    get(key) {
+      let x2js = new X2JS();
+      var startTag = `<${this.get('actionType')}`;
+      Object.keys(this.get('actionModel')).forEach(key => {
+        if(key.startsWith('_')){
+          startTag = `${startTag} ${key.substr(1)}="${this.get('actionModel')[key]}"`;
+        }
+      });
+      startTag = `${startTag}>`;
+      return vkbeautify.xml(`${startTag}${x2js.json2xml_str(this.get('actionModel'))}</${this.get('actionType')}>`);
+    },
+    set(key, value) {
+      let x2js = new X2JS();
+      this.set('errors', Ember.A([]));
+      let temp = x2js.xml_str2json(vkbeautify.xmlmin(value));
+      if(temp){
+        this.set('actionModel', temp[this.get('actionType')]);
+      }else{
+        this.get('errors').pushObject({message:'Action Xml is syntatically incorrect'});
+      }
+      return value;
     }
   }),
   fileBrowser : Ember.inject.service('file-browser'),
@@ -87,15 +119,30 @@ export default Ember.Component.extend( Ember.Evented,{
       errorNode : errorNode
     });
     this.set('transition',transition);
-    if (Ember.isBlank(this.get("actionModel.jobTracker"))){
-      this.set('actionModel.jobTracker',Constants.rmDefaultValue);
-    }
-    if (Ember.isBlank(this.get("actionModel.nameNode"))){
-      this.set('actionModel.nameNode','${nameNode}');
+    if(CommonUtils.isSupportedAction(this.get('actionType'))){
+      if (Ember.isBlank(this.get("actionModel.jobTracker"))){
+        this.set('actionModel.jobTracker',Constants.rmDefaultValue);
+      }
+      if (Ember.isBlank(this.get("actionModel.nameNode"))){
+        this.set('actionModel.nameNode','${nameNode}');
+      }
     }
-    if(this.get('nodeType') === 'action' && this.get('actionModel.slaInfo') === undefined){
+    if(this.get('nodeType') === 'action' && CommonUtils.isSupportedAction(this.get('actionType'))
&& this.get('actionModel.slaInfo') === undefined){
       this.set('actionModel.slaInfo', SlaInfo.create({}));
     }
+    if(!CommonUtils.isSupportedAction(this.get('actionType')) && !this.get('actionModel.slaInfo')){
+      this.set('customSlaInfo',  SlaInfo.create({}));
+    }else{
+      this.set('customSlaInfo',  this.get('actionModel.slaInfo'));
+      this.set('customSlaEnabled', this.get('actionModel.slaEnabled'));
+      delete this.get('actionModel').slaInfo;
+      delete this.get('actionModel').slaEnabled;
+    }
+    if(this.get('actionModel.unsupportedProperties') && !Ember.isEmpty(Object.keys(this.get('actionModel.unsupportedProperties')))){
+      this.set('containsUnsupportedProperties', true);
+    }else{
+      this.set('containsUnsupportedProperties', false);
+    }
   }.on('init'),
   initialize : function(){
     this.$('#action_properties_dialog').modal({
@@ -150,10 +197,14 @@ export default Ember.Component.extend( Ember.Evented,{
     },
     save () {
       var isChildComponentsValid = this.validateChildrenComponents();
-      if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+      if(this.get('validations.isInvalid') || !isChildComponentsValid || this.get('errors').length
> 0) {
         this.set('showErrorMessage', true);
         return;
       }
+      if(!CommonUtils.isSupportedAction(this.get('actionType'))){
+        this.set('actionModel.slaInfo',  this.get('customSlaInfo'));
+        this.set('actionModel.slaEnabled', this.get('customSlaEnabled'));
+      }
       this.processMultivaluedComponents();
       this.processStaticProps();
       this.$('#action_properties_dialog').modal('hide');

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
index 7c78eea..2f8cdaa 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
@@ -16,10 +16,15 @@
 */
 
 import Ember from 'ember';
+import Constants from '../utils/constants';
+
 export default Ember.Component.extend({
   clipboardHasContents : Ember.computed.oneWay('clipboard', function(){
     return !Ember.isEmpty(this.get('clipboard'));
   }),
+  initialize : function(){
+    this.set('customActionEnabled', Constants.customActionEnabled);
+  }.on('init'),
   actions : {
     addAction : function(type){
       this.$(".dr_action").css("background-color", "#fff");

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
index c25b953..8cbcfaf 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
@@ -55,7 +55,15 @@ var ActionTypeResolver=Ember.Object.extend({
     return resolvedType;
   },
   getActionJobHandler(jobType){
-    return this.actionJobHandlerMap.get(jobType);
+    if(this.actionJobHandlerMap.has(jobType)) {
+      return this.actionJobHandlerMap.get(jobType);
+    }else{
+      var customActionJobHandler = actionJobHandler.CustomActionJobHandler.create({
+        actionType : jobType
+      });
+      this.actionJobHandlerMap.set(jobType,customActionJobHandler);
+      return customActionJobHandler;
+    }
   }
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
index 4cc89ef..34a9a4a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
@@ -337,6 +337,26 @@ var MapRedActionJobHandler=ActionJobHandler.extend({
   }
 });
 
+var CustomActionJobHandler=ActionJobHandler.extend({
+  actionType:'',
+  mapping:null,
+  init(){
+    this.mapping=[];
+  },
+  handleImport(actionNode,json){
+    actionNode.set('domain', json);
+  },
+  handle(nodeDomain,nodeObj,nodeName){
+    var customDomain = {};
+    Object.keys(nodeDomain).forEach(key =>{
+      if(key !== 'slaInfo' && key !== 'slaEnabled' && key!=='credentials'){
+        customDomain[key] = nodeDomain[key];
+      }
+    });
+    nodeObj[this.get("actionType")] = customDomain;
+  }
+});
+
 var FSActionJobHandler=ActionJobHandler.extend({
   actionType:"fs",
   mapping:null,
@@ -544,4 +564,4 @@ var FSActionJobHandler=ActionJobHandler.extend({
     });
   }
 });
-export{ActionJobHandler,JavaActionJobHandler,PigActionJobHandler,HiveActionJobHandler,SqoopActionJobHandler,ShellActionJobHandler,
EmailActionJobHandler,SparkActionJobHandler,MapRedActionJobHandler, Hive2ActionJobHandler,
SubWFActionJobHandler, DistCpJobHandler, SshActionJobHandler, FSActionJobHandler};
+export{ActionJobHandler,JavaActionJobHandler,PigActionJobHandler,HiveActionJobHandler,SqoopActionJobHandler,ShellActionJobHandler,
EmailActionJobHandler,SparkActionJobHandler,MapRedActionJobHandler, Hive2ActionJobHandler,
SubWFActionJobHandler, DistCpJobHandler, SshActionJobHandler, FSActionJobHandler, CustomActionJobHandler};

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
index 6bc305a..28ea527 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
@@ -125,16 +125,16 @@ var ActionNodeHandler= NodeHandler.extend({
       return actionNode;
     }
     var actionJobHandler=this.get("actionTypeResolver").getActionJobHandler(actionType);
-    if (!actionJobHandler){
-      console.error("cannot handle unsupported action type:"+actionType+" for "+nodeJson._name);//TODO
error handling...
-      return actionNode;
+    if(actionJobHandler){
+      actionJobHandler.handleImport(actionNode,nodeJson[actionType]);
     }
-    actionJobHandler.handleImport(actionNode,nodeJson[actionType]);
     if (nodeJson.info && nodeJson.info.__prefix==="sla") {
       actionNode.domain.slaEnabled=true;
       this.slaMapper.handleImport(actionNode.domain,nodeJson.info,"slaInfo");
     }
-    actionNode.domain.credentials=nodeJson._cred;
+    if(nodeJson._cred){
+      actionNode.domain.credentials=nodeJson._cred;
+    }
     return actionNode;
   },
   handleImportTransitions(node,json,nodeMap){

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
index 05bdb5a..d91eb3b 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
@@ -1632,3 +1632,7 @@ input:invalid {
   padding: 3px;
   overflow-y: auto;
 }
+.custom-action-xml{
+  width: 100%;
+  min-height: 175px;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
index 95c8c3b..38d8eaf 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
@@ -377,3 +377,28 @@
 {{#if showKillNodeManager}}
   {{#killnode-manager killNodes=workflow.killNodes killNode=killNode createKillnodeError=createKillnodeError
createKillNode="createKillNode" deleteNode="deleteNode" addKillNodeMode=addKillNodeMode editMode=editMode
closeKillNodeManager="closeKillNodeManager"}}{{/killnode-manager}}
 {{/if}}
+
+<div id="customTypeModal" class="modal fade" role="dialog">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal">&times;</button>
+        <h4 class="modal-title">Custom Action</h4>
+      </div>
+      <div class="modal-body">
+        <form class="form-horizontal">
+          <div class="form-group">
+            <label for="inputEmail" class="control-label col-xs-2">Type</label>
+            <div class="col-xs-7">
+              {{input type="text" class="form-control" name="job-tracker" value=customActionType
placeholder="Custom Action Type"}}
+            </div>
+          </div>
+        </form>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+        <button type="button" class="btn btn-primary" data-dismiss="modal" {{action 'createCustomAction'
customActionType}}>OK</button>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
index b36578d..bb089c0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
@@ -64,6 +64,22 @@
                   {{#fs-action actionModel=actionModel transition=transition killNodes=killNodes
openFileBrowser="openFileBrowser" register="registerChild" addKillNode="addKillNode" currentNode=currentNode
credentials=credentials}}{{/fs-action}}
                 {{else if (eq actionType 'sub-workflow')}}
                   {{#sub-workflow actionModel=actionModel transition=transition killNodes=killNodes
openFileBrowser="openFileBrowser" register="registerChild" addKillNode="addKillNode" currentNode=currentNode
credentials=credentials}}{{/sub-workflow}}
+                {{else}}
+                    <div class="panel panel-default">
+                      <div class="panel-heading">Action XML</div>
+                      <div class="panel-body handlerPanel">
+                        {{designer-errors errors=errors}}
+                        {{textarea class="custom-action-xml" value=actionXml}}
+                      </div>
+                    </div>
+                    <div class="panel panel-default">
+                      <div class="panel-heading">Transition</div>
+                      <div class="panel-body handlerPanel">
+                        {{#transition-config transition=transition killNodes=killNodes currentNode=currentNode}}{{/transition-config}}
+                      </div>
+                    </div>
+                    {{#action-credential-config credentials=credentials actionCredentials=actionModel.credentials}}{{/action-credential-config}}
+                    {{#sla-info slaInfo=customSlaInfo slaEnabled=customSlaEnabled}}{{/sla-info}}
               {{/if}}
               {{#if containsUnsupportedProperties}}
                 <div id="unsupported-props" class=" panel panel-default">

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
index 6d672b4..badf320 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
@@ -55,6 +55,9 @@
           <li class="dr_action disabled hide" data-name="Stream" data-type="stream">
<i class="fa fa-exchange"></i> Stream </li>
           <li {{action 'addAction' 'email'}} class="dr_action  enabled" data-name="Email"
data-type="email"> <i class="fa fa-envelope"></i> Email </li>
           <li {{action 'addAction' 'fs'}} class="dr_action  enabled" data-name="fs" data-type="fs">
<i class="fa fa-folder-o"></i> FS </li>
+          {{#if customActionEnabled}}
+            <li {{action 'addAction' 'custom'}} class="dr_action  enabled" data-name="custom"
data-type="custom"> <i class="fa fa-magic" aria-hidden="true"></i> Custom </li>
+          {{/if}}
       </ul>
     </div>
     <div class="clearfix"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/utils/common-utils.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/utils/common-utils.js b/contrib/views/wfmanager/src/main/resources/ui/app/utils/common-utils.js
index e3be7da..8cc40d6 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/utils/common-utils.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/utils/common-utils.js
@@ -16,6 +16,7 @@
  */
 
 import Ember from 'ember';
+import Constants from '../utils/constants';
 export default Ember.Object.create({
   extractSchemaVersion(xmlns){
     return xmlns.substring(xmlns.lastIndexOf(":")+1);
@@ -25,5 +26,8 @@ export default Ember.Object.create({
   },
   setTestContext(context){
     window.flowDesignerTestContext=context;
+  },
+  isSupportedAction(actionType){
+    return Object.values(Constants.actions).findBy('name', actionType)? true : false;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/3e5185ac/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js b/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
index fc20359..9126819 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
@@ -88,5 +88,6 @@ export default Ember.Object.create({
   persistWorkInProgressInterval : 30000,
   elConstants : [
     '${YEAR}', '${MONTH}', '${DAY}', '${HOUR}', '${MINUTE}'
-  ]
+  ],
+  customActionEnabled : false
 });


Mime
View raw message