all list and listitem views now use generic templates
authorScott Baker <smbaker@gmail.com>
Wed, 10 Dec 2014 00:59:08 +0000 (16:59 -0800)
committerScott Baker <smbaker@gmail.com>
Wed, 10 Dec 2014 00:59:08 +0000 (16:59 -0800)
planetstack/core/xoslib/static/js/xosAdminSite.js
planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
planetstack/core/xoslib/static/js/xoslib/xosHelper.js
planetstack/core/xoslib/templates/xosAdmin.html

index b9068b5..5274a81 100644 (file)
@@ -24,10 +24,6 @@ XOSAdminApp.addRegions({
     addChildDetail: "#xos-addchild-detail"
 });
 
-XOSAdminApp.navigateToModel = function(app, detailClass, detailNavLink, model) {
-     XOSAdminApp.Router.navigate(detailNavLink + "/" + model.id, {trigger: true});
-};\r
-\r
 XOSAdminApp.navigate = function(what, modelName, modelId) {\r
     collection_name = modelName + "s";\r
     if (what=="list") {\r
@@ -69,6 +65,14 @@ XOSAdminApp.buildViews = function() {
                                                            app: XOSAdminApp});\r
      XOSAdminApp["genericDetailView"] = genericDetailClass;\r
 \r
+     genericItemViewClass = XOSItemView.extend({template: "#xos-listitem-template",\r
+                                                app: XOSAdminApp});\r
+     XOSAdminApp["genericItemView"] = genericItemViewClass;\r
+\r
+     genericListViewClass = XOSListView.extend({template: "#xos-list-template",\r
+                                                app: XOSAdminApp});\r
+     XOSAdminApp["genericListView"] = genericListViewClass;\r
+\r
      for (var index in OBJS) {\r
          name = OBJS[index];
          tr_template = '#xosAdmin-' + name + '-listitem-template';
@@ -77,7 +81,6 @@ XOSAdminApp.buildViews = function() {
          add_child_template = '#xosAdmin-' + name + '-add-child-template';
          collection_name = name + "s";
          region_name = name + "List";
-         detailNavLink = collection_name;
 
          if ($(detail_template).length) {
              detailClass = XOSDetailView.extend({
@@ -99,20 +102,29 @@ XOSAdminApp.buildViews = function() {
          }\r
          XOSAdminApp[collection_name + "AddChildView"] = addClass;\r
 \r
-         itemViewClass = XOSItemView.extend({
-             detailClass: detailClass,
-             template: tr_template,
-             app: XOSAdminApp,
-             detailNavLink: detailNavLink,
-         });
-
-         listViewClass = XOSListView.extend({
-             childView: itemViewClass,
-             template: table_template,
-             collection: xos[collection_name],
-             title: name + "s",
-             app: XOSAdminApp,
-         });
+         if ($(tr_template).length) {\r
+             itemViewClass = XOSItemView.extend({\r
+                 template: tr_template,\r
+                 app: XOSAdminApp,
+             });
+         } else {
+             itemViewClass = genericItemViewClass;
+         }
+
+         if ($(table_template).length) {
+             listViewClass = XOSListView.extend({
+                 childView: itemViewClass,
+                 template: table_template,
+                 collection: xos[collection_name],
+                 title: name + "s",
+                 app: XOSAdminApp,
+             });
+         } else {
+             listViewClass = genericListViewClass.extend( { childView: itemViewClass,
+                                                            collection: xos[collection_name],
+                                                            title: name + "s",
+                                                           } );
+         }
 
          XOSAdminApp[collection_name + "ListView"] = listViewClass;
 
index f02aed8..1303633 100644 (file)
@@ -323,6 +323,7 @@ if (! window.XOSLIB_LOADED ) {
         attrs.inputType = attrs.inputType || {};
         attrs.foreignFields = attrs.foreignFields || {};
         attrs.readOnlyFields = attrs.readOnlyFields || [];
+        attrs.detailLinkFields = attrs.detailLinkFields || ["id","name"];
 
         if (!attrs.collectionName) {
             attrs.collectionName = modelName + "s";
@@ -334,7 +335,7 @@ if (! window.XOSLIB_LOADED ) {
 
         for (key in attrs) {
             value = attrs[key];
-            if ($.inArray(key, ["urlRoot", "modelName", "collectionName", "addFields", "detailFields", "foreignFields", "inputType", "relatedCollections", "foreignCollections"])>=0) {
+            if ($.inArray(key, ["urlRoot", "modelName", "collectionName", "listFields", "addFields", "detailFields", "foreignFields", "inputType", "relatedCollections", "foreignCollections"])>=0) {
                 modelAttrs[key] = value;
                 collectionAttrs[key] = value;
             }
@@ -384,6 +385,7 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["slices", "deployments", "images", "nodes", "users"],
                             foreignFields: {"creator": "users", "image": "images", "node": "nodes", "deploymentNetwork": "deployments", "slice": "slices"},
                             modelName: "sliver",
+                            listFields: ["id", "name", "instance_id", "instance_name", "slice", "deploymentNetwork", "image", "node", "flavor"],
                             addFields: ["slice", "deploymentNetwork", "image", "node"],
                             detailFields: ["name", "instance_id", "instance_name", "slice", "deploymentNetwork", "image", "node", "creator"],
                             preSave: function() { if (!this.attributes.name && this.attributes.slice) { this.attributes.name = xos.idToName(this.attributes.slice, "slices", "name"); } },
@@ -393,7 +395,8 @@ if (! window.XOSLIB_LOADED ) {
                            relatedCollections: {"slivers": "slice", "sliceDeployments": "slice", "slicePrivileges": "slice", "networks": "owner"},
                            foreignCollections: ["services", "sites"],
                            foreignFields: {"service": "services", "site": "sites"},
-                           detailFields: ["name", "site", "enabled", "description", "url", "max_slivers"],
+                           listFields: ["id", "name", "enabled", "description", "slice_url", "site", "max_slivers", "service"],
+                           detailFields: ["name", "site", "enabled", "description", "slice_url", "max_slivers"],
                            inputType: {"enabled": "checkbox"},
                            modelName: "slice",
                            xosValidate: function(attrs, options) {
@@ -415,6 +418,7 @@ if (! window.XOSLIB_LOADED ) {
                            foreignCollections: ["slices", "deployments"],
                            modelName: "sliceDeployment",
                            foreignFields: {"slice": "slices", "deployment": "deployments"},
+                           listFields: ["id", "slice", "deployment", "tenant_id"],
                            detailFields: ["slice", "deployment", "tenant_id"],
                            });
 
@@ -422,11 +426,13 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["slices", "users", "sliceRoles"],
                             modelName: "slicePrivilege",
                             foreignFields: {"user": "users", "slice": "slices", "role": "sliceRoles"},
+                            listFields: ["id", "user", "slice", "role"],
                             detailFields: ["user", "slice", "role"],
                             });
 
         define_model(this, {urlRoot: SLICEROLE_API,
                             modelName: "sliceRole",
+                            listFields: ["id", "role"],
                             detailFields: ["role"],
                             });
 
@@ -434,12 +440,14 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["sites", "deployments"],
                             modelName: "node",
                             foreignFields: {"site": "sites", "deployment": "deployments"},
+                            listFields: ["id", "name", "site", "deployment"],
                             detailFields: ["name", "site", "deployment"],
                             });
 
         define_model(this, {urlRoot: SITE_API,
                             relatedCollections: {"users": "site", "slices": "site", "nodes": "site"},
                             modelName: "site",
+                            listFields: ["id", "name", "site_url", "enabled", "login_base", "is_public", "abbreviated_name"],
                             detailFields: ["name", "abbreviated_name", "url", "enabled", "is_public", "login_base"],
                             inputType: {"enabled": "checkbox", "is_public": "checkbox"},
                             });
@@ -449,6 +457,7 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["sites"],
                             modelName: "user",
                             foreignFields: {"site": "sites"},
+                            listFields: ["id", "username", "firstname", "lastname", "phone", "user_url", "site"],
                             detailFields: ["username", "firstname", "lastname", "phone", "user_url", "site"],
                             });
 
@@ -456,23 +465,27 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["users","deployments"],
                             modelName: "userDeployment",
                             foreignFields: {"deployment": "deployments", "user": "users"},
+                            listFields: ["id", "user", "deployment", "kuser_id"],
                             detailFields: ["user", "deployment", "kuser_id"],
                             });
 
         define_model(this, { urlRoot: DEPLOYMENT_API,
                              relatedCollections: {"nodes": "deployment", "slivers": "deploymentNetwork", "networkDeployments": "deployment", "userDeployments": "deployment"},
                              modelName: "deployment",
+                             listFields: ["id", "name", "backend_type", "admin_tenant"],
                              detailFields: ["name", "backend_type", "admin_tenant"],
                              });
 
         define_model(this, {urlRoot: IMAGE_API,
                             model: this.image,
                             modelName: "image",
+                            listFields: ["id", "name", "disk_format", "container_format", "path"],
                             detailFields: ["name", "disk_format", "admin_tenant"],
                             });
 
         define_model(this, {urlRoot: NETWORKTEMPLATE_API,
                             modelName: "networkTemplate",
+                            listFields: ["id", "name", "visibility", "translation", "sharedNetworkName", "sharedNetworkId"],
                             detailFields: ["name", "description", "visibility", "translation", "sharedNetworkName", "sharedNetworkId"],
                             });
 
@@ -481,27 +494,32 @@ if (! window.XOSLIB_LOADED ) {
                             foreignCollections: ["slices", "networkTemplates"],
                             modelName: "network",
                             foreignFields: {"template": "networkTemplates", "owner": "slices"},
+                            listFields: ["id", "name", "template", "ports", "labels", "owner"],
                             detailFields: ["name", "template", "ports", "labels", "owner"],
                             });
 
         define_model(this, {urlRoot: NETWORKSLIVER_API,
                             modelName: "networkSliver",
                             foreignFields: {"network": "networks", "sliver": "slivers"},
+                            listFields: ["id", "network", "sliver", "ip", "port_id"],
                             detailFields: ["network", "sliver", "ip", "port_id"],
                             });
 
         define_model(this, {urlRoot: NETWORKDEPLOYMENT_API,
                             modelName: "networkDeployment",
                             foreignFields: {"network": "networks", "deployment": "deployments"},
+                            listFields: ["id", "network", "deployment", "net_id"],
                             detailFields: ["network", "deployment", "net_id"],
                             });
 
         define_model(this, {urlRoot: SERVICE_API,
                             modelName: "service",
+                            listFields: ["id", "name", "enabled", "versionNumber", "published"],
                             detailFields: ["name", "description", "versionNumber"],
                             });
 
         // enhanced REST
+        // XXX this really needs to somehow be combined with Slice, to avoid duplication
         define_model(this, {urlRoot: SLICEPLUS_API,
                             relatedCollections: {'slivers': "slice"},
                             modelName: "slicePlus",
index 9e69aa7..019bae9 100644 (file)
@@ -530,8 +530,10 @@ XOSDetailView = Marionette.ItemView.extend({
              templateHelpers: function() { return { modelName: this.model.modelName,
                                                     collectionName: this.model.collectionName,
                                                     addFields: this.model.addFields,
+                                                    listFields: this.model.listFields,
                                                     detailFields: this.model.detailFields,
                                                     foreignFields: this.model.foreignFields,
+                                                    detailLinkFields: this.model.detailLinkFields,
                                                     inputType: this.model.inputType,
                                                     model: this.model,
                                          }},
@@ -543,7 +545,6 @@ XOSDetailView = Marionette.ItemView.extend({
       extend with:
          app - MarionetteApplication
          template - template (See XOSHelper.html)
-         detailClass - class of detail view, probably an XOSDetailView
 */
 
 XOSItemView = Marionette.ItemView.extend({
@@ -552,9 +553,11 @@ XOSItemView = Marionette.ItemView.extend({
 
              templateHelpers: function() { return { modelName: this.model.modelName,
                                                     collectionName: this.model.collectionName,
+                                                    listFields: this.model.listFields,
                                                     addFields: this.model.addFields,
                                                     detailFields: this.model.detailFields,
                                                     foreignFields: this.model.foreignFields,
+                                                    detailLinkFields: this.model.detailLinkFields,
                                                     inputType: this.model.inputType,
                                                     model: this.model,
                                          }},
@@ -634,7 +637,10 @@ XOSListView = FilteredCompositeView.extend({
 
              templateHelpers: function() {
                 return { title: this.title,
-                         addChildHash: this.getAddChildHash() };
+                         addChildHash: this.getAddChildHash(),
+                         foreignFields: this.collection.foreignFields,
+                         listFields: this.collection.listFields,
+                         detailLinkFields: this.collection.detailLinkFields, };
              },
 });
 
index 3848fc0..8047580 100644 (file)
   <table>\r
   <% _.each(addFields, function(fieldName) { %>\r
      <tr><td><%= fieldNameToHumanReadable(fieldName) %>:</td>\r
-        <% readOnly = $.inArray(fieldName, model.readOnlyFields)>=0 ? " readonly" : "";  console.log(fieldName + " " + readOnly); console.log(model.readOnlyFields); %>\r
+        <% readOnly = $.inArray(fieldName, model.readOnlyFields)>=0 ? " readonly" : "";  %>\r
         <% if (fieldName in foreignFields) { %>\r
             <td><%= idToSelect(fieldName, model.attributes[fieldName], foreignFields[fieldName], "humanReadableName", readOnly) %></td>\r
         <% } else if (inputType[fieldName] == "checkbox") { %>\r
   <table>\r
   <% console.log(model); _.each(detailFields, function(fieldName) { %>\r
      <tr><td><%= fieldNameToHumanReadable(fieldName) %>:</td>\r
+        <% readOnly = $.inArray(fieldName, model.readOnlyFields)>=0 ? " readonly" : "";  console.log(fieldName + " " + readOnly); console.log(model.readOnlyFields); %>\r
         <% if (fieldName in foreignFields) { %>\r
-            <td><%= idToSelect(fieldName, model.attributes[fieldName], foreignFields[fieldName], "humanReadableName") %></td>\r
+            <td><%= idToSelect(fieldName, model.attributes[fieldName], foreignFields[fieldName], "humanReadableName", readOnly) %></td>\r
         <% } else if (inputType[fieldName] == "checkbox") { %>\r
-            <td><input type="checkbox" name="<%= fieldName %>" <% if (model.attributes[fieldName]) print("checked"); %>></td>\r
+            <td><input type="checkbox" name="<%= fieldName %>" <% if (model.attributes[fieldName]) print("checked"); %><%= readOnly %>></td>\r
         <% } else { %>\r
-            <td><input type="text" name="<%= fieldName %>" value="<%= model.attributes[fieldName] %>"></td>\r
+            <td><input type="text" name="<%= fieldName %>" value="<%= model.attributes[fieldName] %>"<%= readOnly %>></td>\r
         <% } %>\r
      </tr>\r
   <% }); %>\r
   </form>\r
 </script>
 
-<!-- Deployment -->
-
-<script type="text/template" id="xosAdmin-deployment-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>backend</th>
-     <th>admin_tenant</th>
-     <th># sites</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-deployment-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= backend_type %></td>
-  <td><%= admin_tenant %></td>
-  <td><%= typeof sites != 'undefined' && sites.length || 0 %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Image -->
-
-<script type="text/template" id="xosAdmin-image-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>disk_format</th>
-     <th>container_format</th>
-     <th>path</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-image-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= disk_format %></td>
-  <td><%= container_format %></td>
-  <td><%= path %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- NetworkTemplate -->
-
-<script type="text/template" id="xosAdmin-networkTemplate-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>description</th>
-     <th>visibility</th>
-     <th>translation</th>
-     <th>sharedNetworkName</th>
-     <th>sharedNetworkId</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-networkTemplate-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= description %></td>
-  <td><%= visibility %></td>
-  <td><%= translation %></td>
-  <td><%= sharedNetworkName %></td>
-  <td><%= sharedNetworkId %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Network -->
-
-<script type="text/template" id="xosAdmin-network-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>template</th>
-     <th>ports</th>
-     <th>labels</th>
-     <th>owner</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-network-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= idToName(template,"networkTemplates","name") %></td>
-  <td><%= ports %></td>
-  <td><%= labels %></td>
-  <td><%= idToName(owner,"slices","name") %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- NetworkSliver -->
-
-<script type="text/template" id="xosAdmin-networkSliver-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>network</th>
-     <th>sliver</th>
-     <th>ip</th>
-     <th>port_id</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-networkSliver-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= idToName(network,"networks","name") %></td>
-  <td><%= idToName(sliver,"slivers","name") %></td>
-  <td><%= ip %></td>
-  <td><%= port_id %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- NetworkDeployment -->
-
-<script type="text/template" id="xosAdmin-networkDeployment-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>network</th>
-     <th>deployment</th>
-     <th>net_id</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-networkDeployment-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= idToName(network,"networks","name") %></td>
-  <td><%= idToName(deployment,"deployments","name") %></td>
-  <td><%= net_id %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Node -->
-
-<script type="text/template" id="xosAdmin-node-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>site</th>
-     <th>deployment</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-node-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= idToName(site,"sites","name") %></td>
-  <td><%= idToName(deployment,"deployments","name") %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- SliceRole -->
-
-<script type="text/template" id="xosAdmin-sliceRole-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>role</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-sliceRole-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= role %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Service -->
-
-<script type="text/template" id="xosAdmin-service-list-template">
+<script type="text/template" id="xos-list-template">
   <h3 class="xos-list-title"><%= title %></h3>
   <%= xosListHeaderTemplate() %>
   <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>description</th>
-     <th>enabled</th>
-     <th>versionNumber</th>
-     <th>published</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-service-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= description %></td>
-  <td><%= enabled %></td>
-  <td><%= versionNumber %></td>
-  <td><%= published %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Site -->
-
-<script type="text/template" id="xosAdmin-site-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>url</th>
-     <th>enabled</th>
-     <th>login_base</th>
-     <th>is_public</th>
-     <th>abbreviated_name</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-site-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= site_url %></td>
-  <td><%= enabled %></td>
-  <td><%= login_base %></td>
-  <td><%= is_public %></td>
-  <td><%= abbreviated_name %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- Slice -->
-
-<script type="text/template" id="xosAdmin-slice-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>enabled</th>
-     <th>omf_friendly</th>
-     <th>description</th>
-     <th>slice_url</th>
-     <th>site</th>
-     <th>max_slivers</th>
-     <th>service</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-slice-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= enabled %></td>
-  <td><%= omf_friendly %></td>
-  <td><%= description %></td>
-  <td><%= slice_url %></td>
-  <td><%= idToName(site,"sites","name") %></td>
-  <td><%= max_slivers %></td>
-  <td><%= idToName(service,"services","name") %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- SliceDeployment -->
-
-<script type="text/template" id="xosAdmin-sliceDeployment-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>slice</th>
-     <th>deployment</th>
-     <th>tenant_id</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-sliceDeployment-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= idToName(slice,"slices","name") %></td>
-  <td><%= idToName(deployment,"deployments","name") %></td>
-  <td><%= tenant_id %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- SlicePrivilege -->
-
-<script type="text/template" id="xosAdmin-slicePrivilege-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>user</th>
-     <th>slice</th>
-     <th>role</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-<script type="text/template" id="xosAdmin-slicePrivilege-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= idToName(user,"users","username") %></td>
-  <td><%= idToName(slice,"slices","name") %></td>
-  <td><%= idToName(role,"sliceRoles","role") %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-
-<!-- Sliver -->
-
-<script type="text/template" id="xosAdmin-sliver-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>name</th>
-     <th>instance_id</th>
-     <th>instance_name</th>
-     <th>image</th>
-     <th>creator</th>
-     <th>slice</th>
-     <th>node</th>
-     <th>deploymentNetwork</th>
-     <th>flavor</th>
-     <th>userData</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-sliver-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: name}) %></td>
-  <td><%= instance_id %></td>
-  <td><%= instance_name %></td>
-  <td><%= idToName(image,"images","name") %></td>
-  <td><%= idToName(creator,"users","name") %></td>
-  <td><%= idToName(slice,"slices","name") %></td>
-  <td><%= idToName(node,"nodes","name") %></td>
-  <td><%= idToName(deploymentNetwork,"deployments","name") %></td>
-  <td><%= flavor %></td>
-  <td><%= userData %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- User -->
-
-<script type="text/template" id="xosAdmin-user-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>username</th>
-     <th>firstname</th>
-     <th>lastname</th>
-     <th>phone</th>
-     <th>user_url</th>
-     <th>site</th>
-     <th>delete</th>
-  </tr></thead>
-  <tbody></tbody>
-  </table>
-  <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
-</script>
-
-
-<script type="text/template" id="xosAdmin-user-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: username}) %></td>
-  <td><%= firstname %></td>
-  <td><%= lastname %></td>
-  <td><%= phone %></td>
-  <td><%= user_url %></td>
-  <td><%= idToName(site,"sites","name") %></td>
-  <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
-</script>
-
-<!-- UserDeployments -->
-
-<script type="text/template" id="xosAdmin-userDeployment-list-template">
-  <h3 class="xos-list-title"><%= title %></h3>
-  <%= xosListHeaderTemplate() %>
-  <table class="test-table">
-  <thead><tr>
-     <th>id</th>
-     <th>user</th>
-     <th>deployment</th>
-     <th>kuser_id</th>
-     <th>delete</th>
+  <thead>
+  <tr>
+  <% _.each(listFields, function(fieldName) { %>
+      <th><%= fieldNameToHumanReadable(fieldName) %></th>
+  <% }); %>
+  <th>delete</th>
   </tr></thead>
   <tbody></tbody>
   </table>
   <%= xosListFooterTemplate({addChildHash: addChildHash}) %>
 </script>
 
-<script type="text/template" id="xosAdmin-userDeployment-listitem-template">
-  <td> <%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: id}) %></td>
-  <td><%= idToName(user,"users","username") %></td>
-  <td><%= idToName(deployment,"deployments","name") %></td>
-  <td><%= kuser_id %></td>
+<script type="text/template" id="xos-listitem-template">
+  <% _.each(listFields, function(fieldName) { %>
+      <% if ($.inArray(fieldName, model.detailLinkFields)>=0) { %>
+          <td><%= xosDetailLinkTemplate({collectionName: collectionName, id: id, text: model.attributes[fieldName]}) %></td>
+      <% } else if (fieldName in foreignFields) { %>
+          <td><%= idToName(model.attributes[fieldName], foreignFields[fieldName], "humanReadableName") %></td>
+      <% } else { %>
+      <td><%= model.attributes[fieldName] %></td>
+      <% } %>
+  <% }); %>
   <td><%= xosDeleteButtonTemplate({modelName: modelName, id: id}) %></td>
 </script>