From 919d8c618b2ca550632cb25c49290a4879056975 Mon Sep 17 00:00:00 2001
From: Peter Vreman <peter.vreman@acision.com>
Date: Mon, 4 May 2009 16:17:50 +0200
Subject: [PATCH] generic list for systems

---
 cobbler/api.py                     |    4 ++
 cobbler/item_system.py             |    4 +-
 cobbler/remote.py                  |    7 +++
 django/urls.py                     |    1 +
 django/views.py                    |   68 +++++++++++++++++++++++-
 django_templates/generic_list.tmpl |  103 ++++++++++++++++++++++++++++++++++++
 setup.py                           |    1 +
 7 files changed, 185 insertions(+), 3 deletions(-)
 create mode 100644 django_templates/generic_list.tmpl

diff --git a/cobbler/api.py b/cobbler/api.py
index 15a1351..4c6f7bd 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -238,6 +238,10 @@ class BootAPI:
         self.log("get_items",[what])
         return self._config.get_items(what)
 
+    def get_field_info(self, what):
+        self.log("get_field_info",[what])
+        return self._config.get_items(what).get_field_info()
+
     def find_items(self, what, criteria=None):
         self.log("find_items",[what])
         # defaults
diff --git a/cobbler/item_system.py b/cobbler/item_system.py
index 8198e4e..79dea87 100644
--- a/cobbler/item_system.py
+++ b/cobbler/item_system.py
@@ -882,13 +882,13 @@ class System(item.Item):
            'redhat_management_server' : self.set_redhat_management_server
         }
 
-    def get_field_info(self):
+def get_field_info():
         return {
             'name' : {
                 'input_type' : 'str',
                 'width'      : 40,
                 'header'     : 'name',
-                'tooltip'    : 'name',
+                'tooltip'    : 'Name',
                 'default'    : '',
                 'webui_default' : True,
             },
diff --git a/cobbler/remote.py b/cobbler/remote.py
index 12e336c..20a8c59 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -270,6 +270,13 @@ class CobblerXMLRPCInterface:
         item = [x.to_datastruct_with_cache() for x in self.api.get_items(what)]
         return self.xmlrpc_hacks(item)
 
+    def get_field_info(self,what):
+        self._log("get_field_info(%s)"%what)
+        if what == "system":
+            return self.xmlrpc_hacks(item_system.get_field_info())
+        else:
+            raise "invalid collection name"
+
     def find_items(self, what, criteria=None,sort_field=None):
         self._log("find_items(%s)"%what)
         items = self.api.find_items(what,criteria=criteria)
diff --git a/django/urls.py b/django/urls.py
index 6efebb2..5be9dec 100644
--- a/django/urls.py
+++ b/django/urls.py
@@ -16,6 +16,7 @@ urlpatterns = patterns('',
     (r'^cobbler_web/snippet/edit/(?P<snippet_name>.+)$', snippet_edit, {'editmode':'edit'}),
     (r'^cobbler_web/snippet/save$', snippet_save),
     (r'^cobbler_web/(?P<what>\w+)/list(/(?P<page>\d+))?', list),
+    (r'^cobbler_web/(?P<what>\w+)/genlist(/(?P<page>\d+))?', genlist),
     (r'^cobbler_web/(?P<what>\w+)/modifylist/(?P<pref>[!\w]+)/(?P<value>\w+)', modify_list),
     (r'^cobbler_web/(?P<what>\w+)/addfilter/(?P<filter>.+)$', modify_filter, {'action':'add'}),
     (r'^cobbler_web/(?P<what>\w+)/removefilter/(?P<filter>.+)$', modify_filter, {'action':'remove'}),
diff --git a/django/views.py b/django/views.py
index 51b7258..03ac902 100644
--- a/django/views.py
+++ b/django/views.py
@@ -50,11 +50,77 @@ def list(request, what, page=None):
     }))
     return HttpResponse(html)
 
+def genlist(request, what, page=None):
+    if page == None:
+        page = int(request.session.get("%s_page" % what, 1))
+    limit = int(request.session.get("%s_limit" % what, 50))
+    sort_field = request.session.get("%s_sort_field" % what, None)
+    filters = simplejson.loads(request.session.get("%s_filters" % what, "{}"))
+
+    pageditems = remote.find_items_paged(what,filters,sort_field,page,limit)
+
+    list_columns = ['name','netboot_enabled','interfaces::eth0::ip_address','profile']
+
+    list_actions = {
+        'single' : [
+                { 'name': 'viewks',  'label':'Preview KS' },
+                { 'name': 'edit',    'label':'Edit' },
+                { 'name': 'rename',  'label':'Rename' },
+                { 'name': 'copy',    'label':'Copy' },
+            ],
+        'multi'  : [
+                { 'name': 'delete',  'label':'Delete' },
+                { 'name': 'netboot', 'label':'Netboot' },
+                { 'name': 'profile', 'label':'Profile' },
+                { 'name': 'power',   'label':'Power' },
+            ]
+    }
+
+    field_info = remote.get_field_info(what)
+
+    headers = []
+    for list_column in list_columns:
+        header={}
+        header['field']=list_column
+        if list_column.find("::") > 0:
+            (field_name,field_key,subfield_name)=list_column.split("::",2)
+            header['label']="%s(%s)" % (field_info[field_name].get("fields",{}).get(subfield_name,{}).get("header",""), field_key)
+        else:
+            header['label']=field_info[list_column].get("header","")
+        headers.append(header)
+
+    rows = []
+    for item in pageditems["items"]:
+        row={}
+        row['name'] = item["name"]
+        row['columns'] = []
+        for list_column in list_columns:
+            column={}
+            if list_column.find("::") > 0:
+                (field_name,field_key,subfield_name)=list_column.split("::",2)
+                column["value"]=item.get(field_name,{}).get(field_key,{}).get(subfield_name,"")
+            else:
+                column["value"]=item.get(list_column,"")
+            row['columns'].append(column)
+        rows.append(row)
+
+    t = get_template('generic_list.tmpl')
+    html = t.render(RequestContext(request,{
+        'what'      : what,
+        'headers'   : headers,
+        'rows'      : rows,
+        'actions'   : list_actions,
+        '%ss'%what  : pageditems["items"],
+        'pageinfo'  : pageditems["pageinfo"],
+        'filters'   : filters,
+    }))
+    return HttpResponse(html)
+
 
 def modify_list(request, what, pref, value=None):
     try:
         if pref == "sort":
-            old_sort=request.session["%s_sort_field" % what]
+            old_sort=request.session.get("%s_sort_field" % what,"")
             if old_sort.startswith("!"):
                 old_sort=old_sort[1:]
                 old_revsort=True
diff --git a/django_templates/generic_list.tmpl b/django_templates/generic_list.tmpl
new file mode 100644
index 0000000..88c8b61
--- /dev/null
+++ b/django_templates/generic_list.tmpl
@@ -0,0 +1,103 @@
+{% extends "master.tmpl" %}
+
+{% block content %}
+
+<script language="Javascript" src="/cobbler_webui_content/checkboxes.js" ></script>
+<script language="Javascript">
+function action_multi(actionname)
+{
+    var itemcount=items_checked_count();
+    if (
+        (itemcount == 0) &&
+        (
+         (actionname == "delete") ||
+         (actionname == "netboot") ||
+         (actionname == "profile") ||
+         (actionname == "power")
+        )
+       )
+    {
+	alert("Select the systems to " + actionname+" first");
+	return;
+    }
+    else if (
+             (itemcount != 1) &&
+             (
+              (actionname == "copy") ||
+              (actionname == "rename")
+             )
+            )
+    {
+	alert("Select only one system to " + actionname);
+	return;
+    }
+
+    document.myform.action = "/cobbler_web/system/"+actionname+"/multi";
+    document.myform.submit();
+}
+
+function action_single(actionname,target)
+{
+    if (actionname == "viewks")
+    {
+        location="/cblr/svc/op/ks/system/"+target;
+    }
+    else
+    {
+        document.myform.action = "/cobbler_web/system/"+actionname+"/"+target;
+        document.myform.submit();
+    }
+}
+</script>
+
+<div class="section_caption">Systems</div>
+
+<form name="myform" method="post" action="/cobbler_web/system/action">
+    <table class="sortable">
+    <thead>
+        <tr>
+	    <th class="text"><input type="checkbox" id="itemsall" onclick="javascript:items_check_all();"></th>
+            {% for header in headers %}
+                <th class="text"><a href="/cobbler_web/system/modifylist/sort/{{ header.field }}">{{ header.label }}</a></th>
+            {% endfor %}
+            <th class="text" colspan="4">Actions</th>
+        </tr>
+    </thead>
+    <tbody>
+        {% if rows %}
+           {% for row in rows %}
+           <tr class="{% cycle 'rowodd' 'roweven' %}">
+               <td><input type="checkbox" name="items" value="{{ row.name }}"/></td>
+
+               {% for column in row.columns %}
+                    <td>
+                    {% if column.url %}
+                        <a href="{{ column.url }}">{{ column.value }}</a>
+                    {% else %}
+                        {{ column.value }}
+                    {% endif %}
+                    </td>
+               {% endfor %}
+
+               {% for action in actions.single %}
+                    <td><input type="button" onclick='javascript:action_single('{{ action.name }}','{{ row.name }}')" value="{{ action.label }}"/></td>
+               {% endfor %}
+           </tr>
+           {% endfor %}
+        {% else %}
+           <tr><td colspan="8">No {{ what }}s found.</td></tr>
+        {% endif %}
+    </tbody>
+    </table>
+</form>
+
+{% if multi_actions %}
+    <br/>
+    Operations on selected {{ what }}s:
+    <br/>
+    {% for action in actions.multi %}
+        <input type="button" onClick="javascript:action_multi('{{ action.name }}')" value="{{ action.label }}"/>
+    {% endfor %}
+{% endif %}
+
+{% endblock content %}
diff --git a/setup.py b/setup.py
index 5931fe0..9b400d4 100644
--- a/setup.py
+++ b/setup.py
@@ -176,6 +176,7 @@ if __name__ == "__main__":
             (dj_templates, [ 'django_templates/empty.tmpl' ]),
             (dj_templates, [ 'django_templates/enoaccess.tmpl' ]),
             (dj_templates, [ 'django_templates/error_page.tmpl' ]),
+            (dj_templates, [ 'django_templates/generic_list.tmpl' ]),
             (dj_templates, [ 'django_templates/header.tmpl' ]),
             (dj_templates, [ 'django_templates/image_edit.tmpl' ]),
             (dj_templates, [ 'django_templates/image_list.tmpl' ]),
-- 
1.5.5.6

