]> git.parisson.com Git - telemeta.git/commitdiff
* Created new administration interface. BEWARE: update your site urls (in
authorolivier <>
Tue, 1 May 2007 14:45:31 +0000 (14:45 +0000)
committerolivier <>
Tue, 1 May 2007 14:45:31 +0000 (14:45 +0000)
 urls.py), telemeta now provides an internal "admin/" url, that may conflict
 with django's admin.
 * Implemented edition of generic "dictionaries" (or "enumerations"). These
 are the linked tables that contained various predefined values, used in
 collections, items and/or parts
 * added "physical format" dictionary (collection field and linked table),
 see EthnomusDatabase
 * misc cleanup

telemeta/models.py
telemeta/templates/admin.html [new file with mode: 0644]
telemeta/templates/base.html
telemeta/templates/dictionary_edit.html [new file with mode: 0644]
telemeta/templates/dictionary_edit_value.html [new file with mode: 0644]
telemeta/templates/dictionary_list.html [new file with mode: 0644]
telemeta/urls.py
telemeta/views/web.py

index 0a3b893d7d847d4f4becc152d4c5f7e39a6e8c53..7c6d8995d17643b5b75c77a293451a5329ae9216 100644 (file)
@@ -19,6 +19,14 @@ class MediaCore:
             fields_dict[field.name] = getattr(self, field.name)
         return fields_dict
 
+class PhysicalFormat(models.Model):
+    value = models.CharField(maxlength=250)
+    is_dictionary = True
+    def __str__(self):
+        return self.value
+    class Meta:
+        ordering = ['value']
+        
 class MediaCollectionManager(models.Manager):
     def quick_search(self, pattern):
         return super(MediaCollectionManager, self).get_query_set().filter(
@@ -26,6 +34,7 @@ class MediaCollectionManager(models.Manager):
             Q(description__icontains=pattern)
         )
 
+
 class MediaCollection(models.Model, MediaCore):
     "Group related media items"
 
@@ -42,6 +51,7 @@ class MediaCollection(models.Model, MediaCore):
     rights = models.CharField(maxlength=250, blank=True)
     source = models.CharField(maxlength=250, blank=True)
     subject = models.CharField(maxlength=250, blank=True)
+    physical_format = models.ForeignKey(PhysicalFormat, null=True, blank=True)
 
     objects = MediaCollectionManager()
 
@@ -131,4 +141,3 @@ class MediaPart(models.Model, MediaCore):
     class Admin:
         pass
 
-
diff --git a/telemeta/templates/admin.html b/telemeta/templates/admin.html
new file mode 100644 (file)
index 0000000..e335b3c
--- /dev/null
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block extra_style %}
+<link rel="stylesheet" type="text/css" href="/css/admin.css" />
+{% endblock %}
+
+{% block content %}
+<h3>Administration</h3>
+<div class="tabs">
+<ul>
+<li>Users</li>
+
+{% if dictionaries %}
+    <li>Dictionaries
+    <ul>
+    {% for d in dictionaries %}
+        {%ifequal d.id dictionary_id %}
+            <li class="active">{{ d.name|capfirst }}</li>
+        {%else%}
+            <li><a href="/admin/dictionaries/{{ d.id }}">{{ d.name|capfirst }}</a></li>
+        {%endifequal%}
+    {% endfor %}
+    </ul>
+</li>
+{% endif %}
+</ul>
+</div>
+<div class="tabcontents">
+    {% block tabcontents %}
+    
+    
+    
+    
+    
+    {% endblock %}
+</div>
+{% endblock %}
index 0c4f6335225386683f34b2214f0e3249b7a7825e..9fb41880d24572b22ecad6e6261bf3d01bbb7a18 100644 (file)
@@ -1,9 +1,19 @@
-<html>
-<link rel="stylesheet" href="/css/style.css" />
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
+<head>
+<title>Telemeta</title>
+<link rel="stylesheet" type="text/css" href="/css/telemeta.css" />
+{% block extra_style %}{% endblock %}
+</head>
+{% load i18n %}
 <body>
-
+<!--
+{% if user.is_authenticated and user.is_staff %}
+<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
+{% endif %}
+-->
 <div id="header">
-<a href="/">Telemeta Web Interface</a>
+<a href="/"><img src="/images/logo.png"></a>
 </div>
 
 <div id="quick_search">
@@ -19,7 +29,9 @@
 <a href="/admin">Admin</a>
 </div>
 
+<div id="content">
 {% block content %}{% endblock %}
+</div>
 
 </body>
 </html>
diff --git a/telemeta/templates/dictionary_edit.html b/telemeta/templates/dictionary_edit.html
new file mode 100644 (file)
index 0000000..e5a7b3a
--- /dev/null
@@ -0,0 +1,48 @@
+{% extends "admin.html" %}
+
+{% block tabcontents %}
+    <h4>Manage {{ dictionary_name_plural|capfirst }}</h4>
+
+
+
+ <form class="addnew" id="addenum" method="post"
+        action="/admin/dictionaries/{{dictionary_id}}/add/">
+  <fieldset>
+   <legend>Add {{ dictionary_name|capfirst }}</legend>
+   <div class="field">
+    <label>Value: <input type="text" name="value"></label>
+
+   </div>
+   <div class="buttons">
+    <input type="submit" name="add" value="Add">
+   </div>
+  </fieldset>
+ </form>
+ {% if dictionary_values %}
+ <form method="POST" action="/admin/dictionaries/{{dictionary_id}}/update/">
+  <table class="listing">
+   <thead>
+    <tr><th class="sel">&nbsp;</th><th>Value</th>
+
+    </tr>
+   </thead><tbody>
+    {% for record in dictionary_values %}
+    <tr>
+     <td><input type="checkbox" name="sel" value="{{record.id}}" /></td>
+     <td><a href="/admin/dictionaries/{{dictionary_id}}/{{record.id}}">
+        {{record.value}}</a></td>
+    </tr>
+    {% endfor %}
+    </tbody>
+  </table>
+  <div class="buttons">
+   <input type="submit" name="remove" value="Remove selected items" />
+  </div>
+ </form>
+ {% else %}
+    <p class="help">This dictionary is empty.</p>
+ {% endif %}
+
+  <br style="clear: right"/>
+
+{% endblock %}
diff --git a/telemeta/templates/dictionary_edit_value.html b/telemeta/templates/dictionary_edit_value.html
new file mode 100644 (file)
index 0000000..0f205c6
--- /dev/null
@@ -0,0 +1,22 @@
+{% extends "admin.html" %}
+
+{% block tabcontents %}
+    <h4>Manage {{ dictionary_name_plural|capfirst }}</h4>
+
+ <form class="mod" id="addenum" method="post"
+        action="/admin/dictionaries/{{dictionary_id}}/{{dictionary_record.id}}/update/">
+  <fieldset>
+   <legend>Modify {{ dictionary_name|capfirst }}</legend>
+   <div class="field">
+    <label>Value: <input type="text" name="value" value="{{dictionary_record.value}}" /></label>
+
+   </div>
+   <div class="buttons">
+    <input type="submit" name="save" value="Save">
+    <input type="submit" name="cancel" value="Cancel">
+   </div>
+  </fieldset>
+ </form>
+  <br style="clear: right"/>
+
+{% endblock %}
diff --git a/telemeta/templates/dictionary_list.html b/telemeta/templates/dictionary_list.html
new file mode 100644 (file)
index 0000000..bc780f8
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block content %}
+<h3>Dictionaries</h3>
+{% if dictionaries %}
+    <ul>
+    {% for d in dictionaries %}
+        <li><a href="/dictionaries/{{ d.id }}">{{ d.name|capfirst }}</a> </li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>No dictionary.</p>
+{% endif %}
+{% endblock %}
index 09b36cbc1b56a6f161f574d7f23ed9a23a86cd3e..f08699cb642e7dc49d1646d8ac9d25199f433c2a 100644 (file)
@@ -1,5 +1,10 @@
 from django.conf.urls.defaults import *
 from telemeta.models import MediaItem, MediaCollection
+from telemeta.core import ComponentManager
+from telemeta.views.web import WebView
+
+comp_mgr = ComponentManager()
+web_view = WebView(comp_mgr)
 
 all_items = {
     'queryset': MediaItem.objects.all(),
@@ -10,12 +15,12 @@ all_collections = {
 }
 
 urlpatterns = patterns('',
-    (r'^$', 'telemeta.views.web.index'),
+    (r'^$', web_view.index),
     (r'^items/$', 'django.views.generic.list_detail.object_list', 
         dict(all_items, paginate_by=10, template_name="mediaitem_list.html")),
-    (r'^items/(?P<item_id>[0-9]+)/$', 'telemeta.views.web.item_detail'),
+    (r'^items/(?P<item_id>[0-9]+)/$', web_view.item_detail),
     (r'^items/(?P<item_id>[0-9]+)/download/(?P<format>[0-9A-Z]+)/$', 
-        'telemeta.views.web.item_export'),
+        web_view.item_export),
     #(r'^media_item/(?P<media_item_id>[0-9]+)/$', 'telemeta.views.web.media_item_edit'),
     (r'^media_item/(?P<media_item_id>[0-9]+)/update/$', 'telemeta.views.web.media_item_update'),
 
@@ -24,13 +29,23 @@ urlpatterns = patterns('',
     (r'^collections/(?P<object_id>[0-9]+)/$', 
         'django.views.generic.list_detail.object_detail',
         dict(all_collections, template_name="collection_detail.html")),
+    #(r'^dictionaries/$', web_view.dictionary_list),        
+    (r'^admin/$', web_view.admin_index),        
+    (r'^admin/dictionaries/(?P<dictionary_id>[0-9a-z]+)/$', web_view.edit_dictionary),        
+    (r'^admin/dictionaries/(?P<dictionary_id>[0-9a-z]+)/add/$', web_view.add_to_dictionary),        
+    (r'^admin/dictionaries/(?P<dictionary_id>[0-9a-z]+)/update/$', web_view.update_dictionary),        
+    (r'^admin/dictionaries/(?P<dictionary_id>[0-9a-z]+)/(?P<value_id>[0-9]+)/$',
+        web_view.edit_dictionary_value),   
+
+    (r'^admin/dictionaries/(?P<dictionary_id>[0-9a-z]+)/(?P<value_id>[0-9]+)/update/$',
+        web_view.update_dictionary_value),   
 
-    (r'^search/$', 
-        'telemeta.views.web.quick_search'),
+    (r'^search/$', web_view.quick_search),
 
 
-    # CSS (FIXME: for developement only)
-    (r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': './telemeta/css'}),
+    # CSS+Images (FIXME: for developement only)
+    (r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': './telemeta/htdocs/css'}),
+    (r'^images/(?P<path>.*)$', 'django.views.static.serve', {'document_root': './telemeta/htdocs/images'}),
 )
 
 
index 7b733db0f559914c90da9c20a8fbf1cd15c7c234..a23cedc72fdbd06251503e0744a0e4bf7d77ce4f 100644 (file)
@@ -8,26 +8,24 @@ from telemeta.models import MediaCollection
 from django.shortcuts import render_to_response
 import re
 from telemeta.core import *
-from telemeta.core import ComponentManager
 from telemeta.export import *
 from django.conf import settings
 import os
 
-def index(request):
-    "Render the homepage"
-
-    media_items = MediaItem.objects.all()
-    template = loader.get_template('index.html')
-    context = Context({
-        'media_items' : media_items,
-    })
-    return HttpResponse(template.render(context))
-
 class WebView(Component):
+    """Provide web UI methods"""
 
     exporters = ExtensionPoint(IExporter)
 
+    def index(self, request):
+        """Render the homepage"""
+
+        template = loader.get_template('index.html')
+        context = Context({})
+        return HttpResponse(template.render(context))
+
     def item_detail(self, request, item_id):
+        """Show the details of a given item"""
         item = MediaItem.objects.get(pk=item_id)
         formats = []
         for exporter in self.exporters:
@@ -35,7 +33,12 @@ class WebView(Component):
         return render_to_response('mediaitem_detail.html', 
                     {'item': item, 'export_formats': formats})
 
-    def file_stream(self, filepath):
+    def __file_stream(self, filepath):
+        """Generator for streaming a file from the disk. 
+        
+        This method shouldn't be needed anymore when bug #8 get fixed
+        """
+
         buffer_size = 0xFFFF
         f = open(filepath, 'rb')
         chunk = f.read(buffer_size)
@@ -46,6 +49,7 @@ class WebView(Component):
         f.close()            
 
     def item_export(self, request, item_id, format):                    
+        """Export a given media item in the specified format (OGG, FLAC, ...)"""
         for exporter in self.exporters:
             if exporter.get_format() == format:
                 break
@@ -68,12 +72,13 @@ class WebView(Component):
 
         outfile = exporter.process(item.id, infile, metadata, [])
 
-        response = HttpResponse(self.file_stream(outfile), mimetype = mime_type)
+        response = HttpResponse(self.__file_stream(outfile), mimetype = mime_type)
         response['Content-Disposition'] = 'attachment; filename="download.' + \
                     exporter.get_file_extension() + '"'
         return response
 
     def quick_search(self, request):
+        """Perform a simple search through collections and items core metadata"""
         pattern = request.REQUEST["pattern"]
         collections = MediaCollection.objects.quick_search(pattern)
         items = MediaItem.objects.quick_search(pattern)
@@ -81,14 +86,98 @@ class WebView(Component):
                     {'pattern': pattern, 'collections': collections, 
                      'items': items})
 
+    def __get_dictionary_list(self):
+        from django.db.models import get_models
+        models = get_models(telemeta.models)
+
+        dictionaries = []
+        for model in models:
+            if getattr(model, "is_dictionary", False):
+                dictionaries.append({"name": model._meta.verbose_name_plural, 
+                    "id": model._meta.module_name})
+        return dictionaries                    
+    
+    def __get_admin_context_vars(self):
+        return {"dictionaries": self.__get_dictionary_list()}
+
+    def admin_index(self, request):
+        return render_to_response('admin.html', self. __get_admin_context_vars())
+
+    def __get_dictionary(self, id):
+        from django.db.models import get_models
+        models = get_models(telemeta.models)
+        for model in models:
+            if model._meta.module_name == id:
+                break
+
+        if model._meta.module_name != id:
+            return None
+
+        return model
         
 
-comp_mgr = ComponentManager()
-view = WebView(comp_mgr)
-item_detail = view.item_detail
-item_export = view.item_export
-quick_search = view.quick_search
+    def edit_dictionary(self, request, dictionary_id):        
+
+        dictionary  = self.__get_dictionary(dictionary_id)
+        if dictionary == None:
+            raise Http404
+
+        vars = self.__get_admin_context_vars()
+        vars["dictionary_id"] = dictionary._meta.module_name
+        vars["dictionary_name"] = dictionary._meta.verbose_name            
+        vars["dictionary_name_plural"] = dictionary._meta.verbose_name_plural
+        vars["dictionary_values"] = dictionary.objects.all()
+        return render_to_response('dictionary_edit.html', vars)
 
+    def add_to_dictionary(self, request, dictionary_id):        
+
+        dictionary  = self.__get_dictionary(dictionary_id)
+        if dictionary == None:
+            raise Http404
+
+        dictionary_value = dictionary(value=request.POST['value'])
+        dictionary_value.save()
+
+        return self.edit_dictionary(request, dictionary_id)
+
+    def update_dictionary(self, request, dictionary_id):        
+        
+        dictionary  = self.__get_dictionary(dictionary_id)
+        if dictionary == None:
+            raise Http404
+
+        if request.POST.has_key("remove"):
+            dictionary.objects.filter(id__in=request.POST['sel']).delete()
+
+        return self.edit_dictionary(request, dictionary_id)
+
+    def edit_dictionary_value(self, request, dictionary_id, value_id):        
+
+        dictionary  = self.__get_dictionary(dictionary_id)
+        if dictionary == None:
+            raise Http404
+        
+        vars = self.__get_admin_context_vars()
+        vars["dictionary_id"] = dictionary._meta.module_name
+        vars["dictionary_name"] = dictionary._meta.verbose_name            
+        vars["dictionary_name_plural"] = dictionary._meta.verbose_name_plural
+        vars["dictionary_record"] = dictionary.objects.get(id__exact=value_id)
+        return render_to_response('dictionary_edit_value.html', vars)
+
+    def update_dictionary_value(self, request, dictionary_id, value_id):        
+
+        if request.POST.has_key("save"):
+            dictionary  = self.__get_dictionary(dictionary_id)
+            if dictionary == None:
+                raise Http404
+       
+            record = dictionary.objects.get(id__exact=value_id)
+            record.value = request.POST["value"]
+            record.save()
+
+        return self.edit_dictionary(request, dictionary_id)
+
+        
 def media_item_edit(request, media_item_id):
     "Provide MediaItem object edition"