Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/core/xoslib/dashboards/xosAdminDashboard.html b/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
index 1544d9f..2364b83 100644
--- a/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
+++ b/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
@@ -30,6 +30,10 @@
 
 <div id="xos-error-dialog" title="Error Message">
 </div>

+

+<div id="xos-addchild-dialog" title="Add Child">

+<div id="xos-addchild-detail"></div>

+</div>

 
 <div id="contentPanel">
 <div id="contentTitle">
diff --git a/planetstack/core/xoslib/static/js/xosAdminSite.js b/planetstack/core/xoslib/static/js/xosAdminSite.js
index 36ffd0b..d265630 100644
--- a/planetstack/core/xoslib/static/js/xosAdminSite.js
+++ b/planetstack/core/xoslib/static/js/xosAdminSite.js
@@ -19,7 +19,9 @@
     linkedObjs1: "#linkedObjs1",
     linkedObjs2: "#linkedObjs2",
     linkedObjs3: "#linkedObjs3",
-    linkedObjs4: "#linkedObjs4"
+    linkedObjs4: "#linkedObjs4",
+
+    addChildDetail: "#xos-addchild-detail"
 });
 
 XOSAdminApp.navigateToModel = function(app, detailClass, detailNavLink, model) {
@@ -108,23 +110,28 @@
         listViewName = collection_name + "ListView";

         detailViewName = collection_name + "DetailView";

 

-        api[api_command] = XOSAdminApp.listViewShower(listViewName, collection_name, "detail", collection_name);

+        api[api_command] = XOSAdminApp.createListHandler(listViewName, collection_name, "detail", collection_name);

         routes[nav_url] = api_command;

 

         nav_url = collection_name + "/:id";

         api_command = "detail" + firstCharUpper(collection_name);

 

-        api[api_command] = XOSAdminApp.detailShower(detailViewName, collection_name, "detail", name);

+        api[api_command] = XOSAdminApp.createDetailHandler(detailViewName, collection_name, "detail", name);

         routes[nav_url] = api_command;

 

         nav_url = "add" + firstCharUpper(name);

         api_command = "add" + firstCharUpper(name);

-        api[api_command] = XOSAdminApp.addShower(detailViewName, collection_name, "detail", name);

+        api[api_command] = XOSAdminApp.createAddHandler(detailViewName, collection_name, "detail", name);

+        routes[nav_url] = api_command;

+

+        nav_url = "addChild" + firstCharUpper(name) + "/:parentModel/:parentField/:parentId";

+        api_command = "addChild" + firstCharUpper(name);

+        api[api_command] = XOSAdminApp.createAddChildHandler(detailViewName, collection_name);

         routes[nav_url] = api_command;

 

         nav_url = "delete" + firstCharUpper(name) + "/:id";

         api_command = "delete" + firstCharUpper(name);

-        api[api_command] = XOSAdminApp.deleteShower(collection_name, name);

+        api[api_command] = XOSAdminApp.createDeleteHandler(collection_name, name);

         routes[nav_url] = api_command;

     };

 

diff --git a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
index e5ca413..de03ddf 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -351,8 +351,8 @@
                            relatedCollections: {"slivers": "slice", "sliceDeployments": "slice", "slicePrivileges": "slice", "networks": "owner"},
                            foreignCollections: ["services", "sites"],
                            modelName: "slice",
-                           validate: function(attrs, options) {
-                               errors = XOSModel.prototype.validate(this, attrs, options);
+                           xosValidate: function(attrs, options) {
+                               errors = XOSModel.prototype.xosValidate(this, attrs, options);
                                // validate that slice.name starts with site.login_base
                                site = attrs.site || this.site;
                                if ((site!=undefined) && (attrs.name!=undefined)) {
diff --git a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
index eb8008c..d2af0aa 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
@@ -16,6 +16,13 @@
         prevPage: function() {

              return this.routeStack.slice(-2)[0];
         },
+
+        showPreviousURL: function() {
+            prevPage = this.prevPage();
+            if (prevPage) {
+                this.navigate("#"+prevPage, {trigger: false, replace: true} );
+            }
+        },
     });

 
 
@@ -84,7 +91,7 @@
         }
     },
 
-    listViewShower: function(listViewName, collection_name, regionName, title) {
+    createListHandler: function(listViewName, collection_name, regionName, title) {
         var app=this;
         return function() {
             app[regionName].show(new app[listViewName]);
@@ -97,7 +104,7 @@
         }
     },
 
-    addShower: function(detailName, collection_name, regionName, title) {
+    createAddHandler: function(detailName, collection_name, regionName, title) {
         var app=this;
         return function() {
             model = new xos[collection_name].model();
@@ -109,7 +116,41 @@
         }
     },
 
-    deleteShower: function(collection_name) {
+    createAddChildHandler: function(detailName, collection_name) {
+        var app=this;
+        return function(parent_modelName, parent_fieldName, parent_id) {
+            app.Router.showPreviousURL();
+            console.log("acs");
+            console.log(modelName);
+            console.log(parent_fieldName);
+            console.log(parent_id);
+            model = new xos[collection_name].model();
+            model.attributes[parent_fieldName] = parent_id;
+            detailViewClass = app[detailName];
+            var detailView = new detailViewClass({model: model, collection:xos[collection_name]});
+            detailView.dialog = $("xos-addchild-dialog");
+            app["addChildDetail"].show(detailView);
+            $("#xos-addchild-dialog").dialog({
+               autoOpen: false,
+               modal: true,
+               width: 640,
+               buttons : {
+                    "Save" : function() {
+                      detailView.save();
+
+                      $(this).dialog("close");
+                      // do something here
+                    },
+                    "Cancel" : function() {
+                      $(this).dialog("close");
+                    }
+                  }
+                });
+            $("#xos-addchild-dialog").dialog("open");
+        }
+    },
+
+    createDeleteHandler: function(collection_name) {
         var app=this;
         return function(model_id) {
             console.log("deleteCalled");
@@ -120,7 +161,7 @@
         }
     },
 
-    detailShower: function(detailName, collection_name, regionName, title) {
+    createDetailHandler: function(detailName, collection_name, regionName, title) {
         var app=this;
         showModelId = function(model_id) {
             $("#contentTitle").html(templateFromId("#xos-title-detail")({"title": title}));
@@ -279,10 +320,7 @@
             if (afterDelete=="list") {
                 that.navigate("list", modelName);
             } else if (afterDelete=="back") {
-                prevPage = that.Router.prevPage();
-                if (prevPage) {
-                    that.Router.navigate("#"+prevPage, {trigger: false, replace: true} );
-                }
+                that.Router.showPreviousURL();
             }
 
         });
@@ -304,15 +342,19 @@
                      "click button.btn-xos-delete": "deleteClicked",
                      "change input": "inputChanged"},
 
-            /*initialize: function() {
-                this.on('deleteConfirmed', this.deleteConfirmed);
-            },*/
-
             /* inputChanged is watching the onChange events of the input controls. We
                do this to track when this view is 'dirty', so we can throw up a warning
                if the user tries to change his slices without saving first.
             */
 
+            initialize: function() {
+                this.on("saveSuccess", this.afterSave);
+                this.synchronous = false;
+            },
+
+            afterSave: function(e) {
+            },
+
             inputChanged: function(e) {
                 this.dirty = true;
             },
@@ -320,21 +362,28 @@
             submitContinueClicked: function(e) {
                 console.log("saveContinue");
                 e.preventDefault();
+                this.afterSave = function() {};
                 this.save();
             },
 
             submitLeaveClicked: function(e) {
                 console.log("saveLeave");
                 e.preventDefault();
+                var that=this;
+                this.afterSave = function() {
+                    that.app.navigate("list", that.model.modelName);
+                }
                 this.save();
-                this.app.navigate("list", this.model.modelName);
             },
 
             submitAddAnotherClicked: function(e) {
                 console.log("saveAnother");
                 e.preventDefault();
+                var that=this;
+                this.afterSave = function() {
+                    that.app.navigate("add", that.model.modelName);
+                }
                 this.save();
-                this.app.navigate("add", this.model.modelName);
             },
 
             save: function() {
@@ -365,34 +414,23 @@
                 var infoMsgId = this.app.showInformational( {what: "save " + model.modelName + " " + model.attributes.humanReadableName, status: "", statusText: "in progress..."} );
 
                 this.model.save(data, {error: function(model, result, xhr) { that.app.saveError(model,result,xhr,infoMsgId);},
-                                       success: function(model, result, xhr) { that.app.saveSuccess(model,result,xhr,infoMsgId);}});
+                                       success: function(model, result, xhr) { that.app.saveSuccess(model,result,xhr,infoMsgId);
+                                                                               if (that.synchronous) {
+                                                                                   that.trigger("saveSuccess");
+                                                                               }
+                                                                             }});
                 this.dirty = false;
+
+                if (!this.synchronous) {
+                    this.afterSave();
+                }
             },
 
-            /*destroyModel: function() {
-                 this.app.hideError();
-                 var infoMsgId = this.app.showInformational( {what: "destroy " + model.modelName + " " + model.attributes.humanReadableName, status: "", statusText: "in progress..."} );
-                 var that = this;
-                 this.model.destroy({error: function(model, result, xhr) { that.app.destroyError(model,result,xhr,infoMsgId);},
-                                     success: function(model, result, xhr) { that.app.destroySuccess(model,result,xhr,infoMsgId);}});
+            deleteClicked: function(e) {
+                e.preventDefault();
+                this.app.deleteDialog(this.model, "list");
             },
 
-             deleteClicked: function(e) {
-                 e.preventDefault();
-                 this.app.confirmDialog(this, "deleteConfirmed");
-             },
-
-             deleteConfirmed: function() {
-                 modelName = this.model.modelName;
-                 this.destroyModel();
-                 this.app.navigate("list", modelName);
-             }, */
-
-             deleteClicked: function(e) {
-                 e.preventDefault();
-                 this.app.deleteDialog(this.model, "list");
-             },
-
             tabClick: function(tabId, regionName) {
                     region = this.app[regionName];
                     if (this.currentTabRegion != undefined) {
diff --git a/planetstack/core/xoslib/templates/xosAdmin.html b/planetstack/core/xoslib/templates/xosAdmin.html
index 854a852..3d5d1a6 100644
--- a/planetstack/core/xoslib/templates/xosAdmin.html
+++ b/planetstack/core/xoslib/templates/xosAdmin.html
@@ -83,11 +83,13 @@
     </tr>
 </script>
 
-<script type="text/template" id="xos-inline-list-buttons-template">
-           <button class="btn js-submit btn-xos-list btn-xos-add">Add</button>
-           <button class="btn js-submit btn-xos-list btn-xos-refresh">Refresh</button>
-       </td>
-    </tr>
+<script type="text/template" id="xos-list-header-template">
+    <button class="btn js-submit btn-xos-list btn-xos-add">Add</button>
+    <button class="btn js-submit btn-xos-list btn-xos-refresh">Refresh</button>
+</script>
+
+<script type="text/template" id="xos-list-footer-template">
+    <a href="#addChildSliver/slice/slice/23">Add another...</a>
 </script>
 
 <script type="text/template" id="xos-delete-button-template">
@@ -102,7 +104,7 @@
 
 <script type="text/template" id="xosAdmin-deployment-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -114,6 +116,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -142,7 +145,7 @@
 
 <script type="text/template" id="xosAdmin-image-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -154,6 +157,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-image-listitem-template">
@@ -181,7 +185,7 @@
 
 <script type="text/template" id="xosAdmin-networkTemplate-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -195,6 +199,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -228,7 +233,7 @@
 
 <script type="text/template" id="xosAdmin-network-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -241,6 +246,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-network-listitem-template">
@@ -271,7 +277,7 @@
 
 <script type="text/template" id="xosAdmin-networkSliver-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -283,6 +289,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-networkSliver-listitem-template">
@@ -311,7 +318,7 @@
 
 <script type="text/template" id="xosAdmin-networkDeployment-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -322,6 +329,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-networkDeployment-listitem-template">
@@ -348,7 +356,7 @@
 
 <script type="text/template" id="xosAdmin-node-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -359,6 +367,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -386,7 +395,7 @@
 
 <script type="text/template" id="xosAdmin-sliceRole-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -395,6 +404,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -418,7 +428,7 @@
 
 <script type="text/template" id="xosAdmin-service-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -431,6 +441,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -460,7 +471,7 @@
 
 <script type="text/template" id="xosAdmin-site-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -474,6 +485,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-site-listitem-template">
@@ -506,7 +518,7 @@
 
 <script type="text/template" id="xosAdmin-slice-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -522,6 +534,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-slice-listitem-template">
@@ -556,7 +569,7 @@
 
 <script type="text/template" id="xosAdmin-sliceDeployment-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -567,6 +580,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-sliceDeployment-listitem-template">
@@ -593,7 +607,7 @@
 
 <script type="text/template" id="xosAdmin-slicePrivilege-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -604,6 +618,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-slicePrivilege-listitem-template">
@@ -630,7 +645,7 @@
 
 <script type="text/template" id="xosAdmin-sliver-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -648,6 +663,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -686,7 +702,7 @@
 
 <script type="text/template" id="xosAdmin-user-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -700,6 +716,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 
@@ -733,7 +750,7 @@
 
 <script type="text/template" id="xosAdmin-userDeployment-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosInlineListButtonsTemplate() %>
+  <%= xosListHeaderTemplate() %>
   <table class="test-table">
   <thead><tr>
      <th>id</th>
@@ -744,6 +761,7 @@
   </tr></thead>
   <tbody></tbody>
   </table>
+  <%= xosListFooterTemplate() %>
 </script>
 
 <script type="text/template" id="xosAdmin-userDeployment-listitem-template">
@@ -768,7 +786,8 @@
 
 <script>
 xosInlineDetailButtonsTemplate = _.template($("#xos-inline-detail-buttons-template").html());
-xosInlineListButtonsTemplate = _.template($("#xos-inline-list-buttons-template").html());
+xosListHeaderTemplate = _.template($("#xos-list-header-template").html());
+xosListFooterTemplate = _.template($("#xos-list-footer-template").html());
 xosDeleteButtonTemplate = _.template($("#xos-delete-button-template").html());
 xosDetailLinkTemplate = _.template($("#xos-detail-link-template").html());
 </script>