Просмотр исходного кода

gh-1874 Configmgr - Enable deletion of attributes

  - In XML view clicking 'Delete' from the context menu,
    deletes the attribute and its' value.
  - No validation is done on the delete.
  - Context menu 'Delete' is available only for attributes.
  - Only attributes that can be specified using an unambiguous XPath will
    succeed.
  - Deleted optional attributes appear in red.
  - Context menu closes when clicking off the menu.
  - After delete, nested XML Tree View refreshes to previous location.
  - Incorporated changes based on review feedback
    - Fix handling when deleting EnvSetttings
    - Improve focus after refreshing table

Signed-off-by: Gleb Aronsky <gleb.aronsky@lexisnexis.com>
Gleb Aronsky 12 лет назад
Родитель
Сommit
2459037c02

+ 173 - 0
esp/files/scripts/configmgr/configmgr.js

@@ -1796,6 +1796,104 @@ function createEnvXmlView(allrows, compName, subRecordIndex) {
         width: "100%"
       });
 
+      function onContextMenuBeforeShowDeleteContextMenu(p_sType, p_aArgs) {
+        var record = top.document.rightDT.getRecordSet().getRecord(top.document.rightDT.getSelectedRows()[0]);
+        var pp = parseParamsForXPath( record.getData('params'), top.document.rightDT.getRecordSet().getRecord(top.document.rightDT.getSelectedRows()[0]).getData('name'),
+                   top.document.rightDT.getRecordSet().getRecord(top.document.rightDT.getSelectedRows()[0]).getData('value'),
+                   record.getData('hasChildren') == undefined ? false : record.getData('hasChildren') );
+
+        var xmlStr = "<XmlArgs><Setting operation=\"delete\" params= \"" + pp + "\"/></XmlArgs>";
+
+        YAHOO.util.Connect.asyncRequest('POST', '/WsDeploy/HandleAttributeDelete', {
+          success: function(o) {
+            top.document.forms['treeForm'].isChanged.value = "true";
+            top.document.choice = new Array();
+            top.document.choice[0] = top.document.rightDT.getRecordIndex(top.document.rightDT.getSelectedRows()[0]);
+            var recDepth =  top.document.rightDT.getRecord(top.document.choice[0])._oData.depth;
+
+            var index = 0;
+            for (counter = top.document.choice[0]; counter >= 0; counter--)
+            {
+              if (top.document.rightDT.getRecord(counter)._oData.depth < recDepth)
+              {
+                top.document.choice[index] = top.document.rightDT.getRecord(counter).getData('params');
+                recDepth = top.document.rightDT.getRecord(counter)._oData.depth;
+                index++;
+              }
+            }
+
+            top.document.doJumpToChoice = true;
+            doPageRefresh();
+
+             YAHOO.util.UserAction.click(top.document.rightDT.getFirstTrEl());
+           },
+          failure: function(o) {
+            alert("Failed to delete attribute.  (XPath maybe ambiguous. A manual edit of the XML configuration file maybe required to delete this attribute.) ");
+            },
+          scope: this
+        },
+          top.document.navDT.getFileName(true) + 'XmlArgs=' + xmlStr + '&bLeaf=' + (record.getData('hasChildren') == undefined ? false : !record.getData('hasChildren') ));
+        }
+      function onContextMenuXBeforeShow(p_sType, p_aArgs)
+      {
+        if (top.document.getElementById('ReadWrite').checked == true)
+          oContextMenuX.cfg.setProperty('disabled',false);
+        else
+          oContextMenuX.cfg.setProperty('disabled',true);
+
+        top.document.ContextMenuCenter = this;
+      }
+
+      function onTriggerContextMenu(p_oEvent)
+      {
+        if (top.document.rightDT.getRecord(top.document.rightDT.getSelectedRows()[0])._oData.hasChildren == true)  // only allow attributes to be deleted
+          this.cancel();
+      }
+      var aMenuItemsX = [{text: "Delete", onclick: { fn: onContextMenuBeforeShowDeleteContextMenu}  }];
+      top.document.rightDT = dt;
+      top.document.rightDT.expandRecord = function(id) {
+      var recSet = top.document.rightDT.getRecordSet();
+
+      if (typeof (id) === 'undefined') {
+        var tdEl = top.document.rightDT.getFirstTdEl(recSet.getRecord(0));
+        var children = Dom.getChildren(tdEl);
+        if (Dom.hasClass(children[0].children[0].children[0], 'yui-button')) {
+          children[0].children[0].children[0].click();
+          return;
+        }
+      }
+
+      var recSetLen = recSet.getLength();
+      for (var i = 0; i < recSetLen; i++) {
+        var r = recSet.getRecord(i);
+        if (r.getData('id') === id) {
+          if (r.getData('parent') != -1)
+            top.document.rightDT.expandRecord(r.getData('parent'));
+          var tdEl = top.document.rightDT.getFirstTdEl(r);
+          var children = Dom.getChildren(tdEl);
+          if (Dom.hasClass(children[0].children[0].children[0], 'yui-button') &&
+                Dom.hasClass(children[0].children[0].children[0], 'buttoncollapsed')) {
+            children[0].children[0].children[0].click();
+            break;
+          }
+          else {
+            top.document.rightDT.unselectAllRows();
+            top.document.rightDT.selectRow(r);
+            break;
+          }
+        }
+        }
+      }
+
+      var oContextMenuX = new YAHOO.widget.ContextMenu( "EnvironmentTabCM2", { trigger: dt.getTbodyEl(), lazyload: true, itemdata: aMenuItemsX, container: tabNameTemp});
+      top.document.ContextMenuCenter = oContextMenuX;
+
+
+     oContextMenuX.subscribe("triggerContextMenu", onTriggerContextMenu);
+
+      oContextMenuX.dt = dt;
+      oContextMenuX.subscribe("beforeShow",onContextMenuXBeforeShow);
+
       tab.dt = dt;
       tab.dataSource = myDataSource;
       dt.subscribe("rowMouseoutEvent", dt.onEventUnhighlightRow);
@@ -1870,6 +1968,26 @@ function createEnvXmlView(allrows, compName, subRecordIndex) {
         top.document.navDT.getWaitDlg().hide();
 
         top.document.stopWait(document);
+
+        var lastCounter2 = 0;
+        if (top.document.doJumpToChoice == true)
+        {
+          for (counter = top.document.choice.length-1; counter >= 0; counter--)
+          {
+            for (counter2 = lastCounter2; true; counter2++)
+            {
+              if (this.getRecord(counter2).getData('params') == top.document.choice[counter])
+              {
+                this.expandRecord(counter2);
+                lastCounter2 = counter2;
+                break;
+              }
+            }
+          }
+
+          Dom.getChildren(this.getFirstTdEl(this.getRecord(this.getRecordIndex(this.getSelectedRows()[0]))))[0].children[0].children[0].focus();
+          top.document.doJumpToChoice = false;
+        }
       });
 
       dt.subscribe("tableKeyEvent", function(oArgs) {
@@ -3420,6 +3538,61 @@ function setChildrenOf(parent, rec) {
   childrenOf[parent][childrenOf[parent].length] = rec;
 }
 
+function parseParamsForXPath(params, key, value, hasChildren)
+{
+  var splitParams = params.split(":");
+  var xpath = "";
+
+  for (idx = splitParams.length-1; idx >= 0; idx--)
+  {
+    var pcTypePos = splitParams[idx].indexOf("pcType");
+    var pcNamePos = splitParams[idx].indexOf("pcName");
+
+    if (pcTypePos != -1)
+    {
+      if ( splitParams[idx].substr(pcTypePos+7) === "Environment" )
+        xpath = "./";
+      else
+       xpath = xpath + splitParams[idx].substr(pcTypePos+7) + "/";
+    }
+    else if (pcNamePos != -1)
+    {
+      if (splitParams[idx].substr(pcNamePos+8) != "")
+      {
+        if (xpath[xpath.length-1] === ']')
+        {
+          xpath = xpath + "/";
+        }
+        xpath = xpath + splitParams[idx-1].substr(pcTypePos+8);
+        xpath = xpath + "[@name='" + splitParams[idx].substr(pcNamePos+7) + "']";
+        idx--;
+      }
+      else if (xpath[xpath.length-1] == ']')
+      {
+        xpath = xpath + "/";
+      }
+    }
+  }
+
+  if (hasChildren == true || xpath.substr(0,14) == "./EnvSettings/")
+    return xpath;
+
+  if (key === "name")
+  {
+    xpath = xpath + "]";
+  }
+  else
+  {
+    if (xpath[xpath.length-1] == '/')
+    {
+      xpath = xpath.substring(0,xpath.length-1);
+    }
+    xpath = xpath + "[@" + key + "='" + value + "']"
+  }
+
+  return xpath;
+}
+
 function initEnvXmlType(i) {
   i.name_extra = "";
   i.name_ctrlType = 0;

+ 16 - 0
esp/scm/WsDeploy.ecm

@@ -251,6 +251,20 @@ ESPresponse [exceptions_inline, encode(0)] HandleThorTopologyResponse
     string CompName;
 };
 
+ESPrequest HandleAttributeDeleteRequest
+{
+    string Operation;
+    string XmlArgs;
+    bool bLeaf;
+    ESPstruct WsDeployReqInfo ReqInfo;
+};
+
+ESPresponse [exceptions_inline, encode(0)] HandleAttributeDeleteResponse
+{
+    string Status;
+    string CompName;
+};
+
 ESPrequest HandleComponentRequest
 {
     string Operation;
@@ -551,6 +565,8 @@ ESPservice [exceptions_inline("xslt/exceptions.xslt")] WsDeploy
         HandleRoxieOperation(HandleRoxieOperationRequest, HandleRoxieOperationResponse);
     ESPmethod[description("Add computers to Thor topology"), help("")] 
         HandleThorTopology(HandleThorTopologyRequest, HandleThorTopologyResponse);
+   ESPmethod[description("Handle branch or leaf deletes from XML view"), help("")]
+        HandleAttributeDelete(HandleAttributeDeleteRequest, HandleAttributeDeleteResponse);
     ESPmethod[description("Handle new component operations like add & delete in the environment"), help("")] 
         HandleComponent(HandleComponentRequest, HandleComponentResponse);
     ESPmethod[description("Handle new instance operations like add & delete in the environment"), help("")] 

+ 74 - 0
esp/services/WsDeploy/WsDeployService.cpp

@@ -4098,6 +4098,69 @@ bool CWsDeployFileInfo::getBuildServerDirs(IEspContext &context, IEspGetBuildSer
   return true;
 }
 
+bool CWsDeployFileInfo::handleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp)
+{
+  synchronized block(m_mutex);
+  const char* xmlArg = req.getXmlArgs();
+
+  if (!xmlArg || !*xmlArg)
+    return false;
+
+  Owned<IPropertyTree> pSrcTree = createPTreeFromXMLString(xmlArg);
+
+  Owned<IPropertyTreeIterator> iter = pSrcTree->getElements("Setting[@operation='delete']");
+
+  if (iter->first() == false)
+    return false;
+
+  IPropertyTree* pSetting = &iter->query();
+  Owned<IPropertyTree> pEnvRoot = &m_Environment->getPTree();
+  StringBuffer xpath2 =  pSetting->queryProp("@params");
+  IPropertyTree* pComp = pEnvRoot->queryPropTree(xpath2.str());
+
+  if (pComp == NULL)
+    throw MakeStringException(-1,"Bad XPath %s (Try refreshing the browser?)", xpath2.str());
+
+  StringBuffer xml;
+  StringBuffer attrib;
+
+  int count = xpath2.length()-2;
+
+  if (count <= 0)
+    throw MakeStringException(-1,"Bad XPath %s (Try refreshing the browser?)", xpath2.str());
+
+  while (xpath2[count] != '=' || xpath2[count+1] != '\'')
+    count--;
+  count--;
+
+  for (int i=count; i >= 0 && xpath2[i] != '['; i--)
+    attrib.insert(0,xpath2[i]);
+
+  int index = xpath2.length()-1;
+
+  while (index > 0)
+  {
+    if (xpath2[index] == '/')
+      break;
+    index--;
+  }
+
+  char rootXPath[index+2];
+  memset(rootXPath,0,sizeof(rootXPath));
+  xpath2.getChars(0,index+1,rootXPath);
+
+  if (req.getBLeaf() == true)
+    pComp->removeProp(attrib);
+  else if (strlen(rootXPath) >= 14 && strncmp(rootXPath,"./EnvSettings/",14) == 0)
+    pEnvRoot->queryPropTree("./EnvSettings")->removeTree(pComp);
+  else
+    pEnvRoot->queryPropTree(rootXPath)->removeTree(pComp);
+
+  resp.setStatus("true");
+  resp.setCompName(XML_TAG_SOFTWARE);
+
+  return true;
+}
 
 bool CWsDeployFileInfo::handleComponent(IEspContext &context, IEspHandleComponentRequest &req, IEspHandleComponentResponse &resp)
 {
@@ -6722,6 +6785,12 @@ bool CWsDeployEx::onHandleComponent(IEspContext &context, IEspHandleComponentReq
   return fi->handleComponent(context, req, resp);
 }
 
+bool CWsDeployEx::onHandleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp)
+{
+  CWsDeployFileInfo* fi = getFileInfo(req.getReqInfo().getFileName());
+  return fi->handleAttributeDelete(context, req, resp);
+}
+
 bool CWsDeployEx::onHandleInstance(IEspContext &context, IEspHandleInstanceRequest &req, IEspHandleInstanceResponse &resp)
 {
   CWsDeployFileInfo* fi = getFileInfo(req.getReqInfo().getFileName());
@@ -6978,6 +7047,11 @@ bool CWsDeployExCE::onHandleComponent(IEspContext &context, IEspHandleComponentR
   return supportedInEEOnly();
 }
 
+bool CWsDeployExCE::onHandleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp)
+{
+  return supportedInEEOnly();
+}
+
 bool CWsDeployExCE::onHandleInstance(IEspContext &context, IEspHandleInstanceRequest &req, IEspHandleInstanceResponse &resp)
 {
   return supportedInEEOnly();

+ 3 - 0
esp/services/WsDeploy/WsDeployService.hpp

@@ -471,6 +471,7 @@ public:
     virtual bool getComputersForRoxie(IEspContext &context, IEspGetComputersForRoxieRequest &req, IEspGetComputersForRoxieResponse &resp);
     virtual bool handleRoxieOperation(IEspContext &context, IEspHandleRoxieOperationRequest &req, IEspHandleRoxieOperationResponse &resp);
     virtual bool handleThorTopology(IEspContext &context, IEspHandleThorTopologyRequest &req, IEspHandleThorTopologyResponse &resp);
+    virtual bool handleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp);
     virtual bool handleComponent(IEspContext &context, IEspHandleComponentRequest &req, IEspHandleComponentResponse &resp);
     virtual bool handleComponentCopy(IPropertyTree *pComponents, IPropertyTree *pEnvRoot);
     virtual bool handleHardwareCopy(IPropertyTree *pComponents, IPropertyTree *pEnvRoot);
@@ -952,6 +953,7 @@ public:
     virtual bool onGetComputersForRoxie(IEspContext &context, IEspGetComputersForRoxieRequest &req, IEspGetComputersForRoxieResponse &resp);
     virtual bool onHandleRoxieOperation(IEspContext &context, IEspHandleRoxieOperationRequest &req, IEspHandleRoxieOperationResponse &resp);
     virtual bool onHandleThorTopology(IEspContext &context, IEspHandleThorTopologyRequest &req, IEspHandleThorTopologyResponse &resp);
+    virtual bool onHandleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp);
     virtual bool onHandleComponent(IEspContext &context, IEspHandleComponentRequest &req, IEspHandleComponentResponse &resp);
     virtual bool onHandleInstance(IEspContext &context, IEspHandleInstanceRequest &req, IEspHandleInstanceResponse &resp);
     virtual bool onHandleEspServiceBindings(IEspContext &context, IEspHandleEspServiceBindingsRequest &req, IEspHandleEspServiceBindingsResponse &resp);
@@ -1022,6 +1024,7 @@ public:
     virtual bool onGetComputersForRoxie(IEspContext &context, IEspGetComputersForRoxieRequest &req, IEspGetComputersForRoxieResponse &resp);
     virtual bool onHandleRoxieOperation(IEspContext &context, IEspHandleRoxieOperationRequest &req, IEspHandleRoxieOperationResponse &resp);
     virtual bool onHandleThorTopology(IEspContext &context, IEspHandleThorTopologyRequest &req, IEspHandleThorTopologyResponse &resp);
+    virtual bool onHandleAttributeDelete(IEspContext &context, IEspHandleAttributeDeleteRequest &req, IEspHandleAttributeDeleteResponse &resp);
     virtual bool onHandleComponent(IEspContext &context, IEspHandleComponentRequest &req, IEspHandleComponentResponse &resp);
     virtual bool onHandleInstance(IEspContext &context, IEspHandleInstanceRequest &req, IEspHandleInstanceResponse &resp);
     virtual bool onHandleEspServiceBindings(IEspContext &context, IEspHandleEspServiceBindingsRequest &req, IEspHandleEspServiceBindingsResponse &resp);