Commits

David Jean Louis committed fca6b85

implemented dashboard preferences persistence in the database

Comments (0)

Files changed (8)

admin_tools/dashboard/forms.py

+from django import forms
+
+from admin_tools.dashboard.models import DashboardPreferences
+
+
+class DashboardPreferencesForm(forms.ModelForm):
+    """
+    This form allows the user to edit dashboard preferences. It doesn't show
+    the user field. It expects the user to be passed in from the view.
+    """
+
+    def __init__(self, user, *args, **kwargs):
+        super(DashboardPreferencesForm, self).__init__(*args, **kwargs)
+        self.user = user
+
+    def save(self, *args, **kwargs):
+        preferences = super(DashboardPreferencesForm, self).save(
+            commit=False,
+            *args,
+            **kwargs
+        )
+        preferences.user = self.user
+        preferences.save()
+        return preferences
+
+    class Meta:
+        fields = ('data',)
+        model = DashboardPreferences

admin_tools/dashboard/models.py

 This module contains the base classes for the dashboard and dashboard modules.
 """
 
+from django.db import models
 from django.contrib import admin
 from django.contrib.contenttypes.models import ContentType
 from django.core.urlresolvers import reverse
 from admin_tools.utils import AppListElementMixin
 
 
+class DashboardPreferences(models.Model):
+    """
+    This model represents the dashboard preferences for a user.
+    """
+    user = models.ForeignKey('auth.User')
+    data = models.TextField()
+
+    def __unicode__(self):
+        return "%s dashboard preferences" % self.user.username
+
+    class Meta:
+        db_table = 'admin_tools_dashboard_preferences'
+        ordering = ('user',)
+    
+
 class Dashboard(object):
     """
     Base class for dashboards.

admin_tools/dashboard/templates/dashboard/dashboard.html

 <script type="text/javascript">
 // <![CDATA[
 jQuery(function($) {
-    $('#{{ dashboard.get_id }}').dashboard({
-        'columns': {{ dashboard.columns }}
-    });
+    jQuery.getJSON(
+        '{% url admin-tools-dashboard-get-preferences %}',
+        function(data) {
+            $('#{{ dashboard.get_id }}').dashboard({
+                'columns': {{ dashboard.columns }},
+                'load_preferences_function': function(options) {
+                    return data;
+                },
+                'save_preferences_function': function(options, preferences) {
+                    jQuery.post(
+                        '{% url admin-tools-dashboard-set-preferences %}',
+                        { data: JSON.stringify(preferences) }
+                    );
+                }
+            });
+         }
+    );
 });
 //]]>
 </script>

admin_tools/dashboard/templates/dashboard/preferences_form.html

+{% extends "admin/base_site.html" %}
+
+{% block content %}
+
+<form action="." method="POST">
+    {{ form.as_p }}
+    <p><input type="submit" value="Save" /></p>
+</form>
+
+{% endblock %}

admin_tools/dashboard/urls.py

+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('admin_tools.dashboard.views',
+    url(r'^get_preferences/$', 'get_preferences', name='admin-tools-dashboard-get-preferences'),
+    url(r'^set_preferences/$', 'set_preferences', name='admin-tools-dashboard-set-preferences'),
+)

admin_tools/dashboard/views.py

-# Create your views here.
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import get_object_or_404
+from django.utils import simplejson
+from django.views.generic.simple import direct_to_template
+
+try:
+    from django.views.decorators import csrf_exempt
+except ImportError:
+    from django.contrib.csrf.middleware import csrf_exempt
+
+from forms import DashboardPreferencesForm
+from models import DashboardPreferences
+
+
+@login_required
+@csrf_exempt
+def set_preferences(request):
+    """
+    This view serves and validates a preferences form.
+    """
+    try:
+        preferences = DashboardPreferences.objects.get(user=request.user)
+    except DashboardPreferences.DoesNotExist:
+        preferences = None
+    if request.method == "POST":
+        form = DashboardPreferencesForm(
+            user=request.user,
+            data=request.POST,
+            instance=preferences
+        )
+        if form.is_valid():
+            preferences = form.save()
+            if request.is_ajax():
+                return HttpResponse('true')
+            request.user.message_set.create(message='Preferences saved')
+        elif request.is_ajax():
+            return HttpResponse('false')
+    else:
+        form = DashboardPreferencesForm(user=request.user, instance=preferences)
+    return direct_to_template(request, 'dashboard/preferences_form.html', {
+        'form': form,   
+    })
+
+
+@login_required
+@csrf_exempt
+def get_preferences(request):
+    """
+    Returns the dashboard preferences for the current user in json format.
+    If no preferences are found, the return value is an empty json object.
+    """
+    try:
+        preferences = DashboardPreferences.objects.get(user=request.user)
+        data = preferences.data
+    except DashboardPreferences.DoesNotExist:
+        data = '{}'
+    return HttpResponse(data, mimetype='application/json')
+

admin_tools/media/admin_tools/js/jquery/jquery.dashboard.js

                 panel_id: 'dashboard-panel',
                 dashboard_id: this.attr('id'),
                 dashboard_module_class: 'dashboard-module',
-                columns: 2
+                columns: 2,
+                load_preferences_function: false,
+                save_preferences_function: false
             }    
             var options = $.extend(defaults, options);
 
     });
 
     var preferences = false;
-    var cookie_name = false;
 
     var _initialize = function(elt, options) {
-        if (cookie_name === false) {
-            cookie_name = 'admin-tools.' + options.dashboard_id;
-        }
+        // load preferences
         if (preferences === false) {
-            var json_str = $.cookie(cookie_name);
-            preferences = json_str ? JSON.parse(json_str) : {};
+            if (options.load_preferences_function) {
+                preferences = options.load_preferences_function(options);
+            } else {
+                var json_str = $.cookie('admin-tools.' + options.dashboard_id);
+                preferences = json_str ? JSON.parse(json_str) : {};
+            }
         }
         // set ids if not set
         elt.children('div[id!=' + options.panel_id +']').each(function(index) {
     var _restore_positions = function(elt, options) {
         // restore positions
         try {
-            var saved_positions = _get_preference('positions');
+            var saved_positions = _get_preference(options, 'positions');
         } catch (e) {
             return;
         }
     var _columnize = function(elt, options) {
         var elts = elt.children('div[id!=' + options.panel_id +']');
         var size = Math.ceil(elts.length / options.columns);
-        var sizes = _get_preference('columns');
+        var sizes = _get_preference(options, 'columns');
         var percent = Math.floor(100 / options.columns);
         var start = 0;
         var stop = 0;
         elt.children().children('.disabled').each(function() {
             _delete_element($(this), options);
         });
-        if (preferences['disabled']) {
-            $.each(preferences['disabled'], function(k, v) {
+        if (_get_preference(options, 'disabled')) {
+            $.each(_get_preference(options, 'disabled'), function(k, v) {
                 v ? _delete_element($('#'+k), options) : _add_element($('#'+k), options);
             });
         }
-        if (preferences['collapsed']) {
-            $.each(preferences['collapsed'], function(k, v) {
+        if (_get_preference(options, 'collapsed')) {
+            $.each(_get_preference(options, 'collapsed'), function(k, v) {
                 if (v) {
                     _toggle_element($('#'+k), options);
                 }
             cursor: 'crosshair',
             opacity: 0.7,
             update: function() {
-                _set_preference('positions', false, _get_positions(elt, options));
+                _set_preference(options, 'positions', false, _get_positions(elt, options));
                 var columns = [];
                 elt.children('.dashboard-column').each(function() {
                     columns.push($(this).children().length);
                 });
-                _set_preference('columns', false, columns);
+                _set_preference(options, 'columns', false, columns, true);
             }
         });
     };
         elt.find('h2 a.toggle-icon').toggleClass('collapsed');
         elt.children('div').slideToggle();
         if (save_preference) {
-            _set_preference('collapsed', elt.attr('id'), elt.find('h2 a.toggle-icon').hasClass('collapsed'));
+            _set_preference(options, 'collapsed', elt.attr('id'), elt.find('h2 a.toggle-icon').hasClass('collapsed'), true);
         }
     };
 
         elt.fadeOut('fast');
         $('#' + options.panel_id).show();
         if (save_preference) {
-            _set_preference('disabled', elt.attr('id'), true);
+            _set_preference(options, 'disabled', elt.attr('id'), true, true);
         }
     };
 
         elt.removeClass('disabled');
         elt.fadeIn('fast');
         if (save_preference) {
-            _set_preference('disabled', elt.attr('id'), false);
+            _set_preference(options, 'disabled', elt.attr('id'), false, true);
         }
         // if there's no element in the panel, hide it
         if (!$('#' + options.panel_id).find('li').length) {
         }
     };
 
-    var _get_preference = function(cat, id, defaultval) {
+    var load_preferences = function(options) {
+        if (options.load_preferences_function) {
+            return options.load_preferences_function(options);
+        }
+        if (preferences === false) {
+            var json_str = $.cookie('admin-tools.' + options.dashboard_id);
+            preferences = json_str ? JSON.parse(json_str) : {};
+        }
+        return preferences;
+    }
+
+    var _get_preference = function(options, cat, id, defaultval) {
         try {
             if (preferences[cat] == undefined) {
                 preferences[cat] = {};
         }
     };
 
-    var _set_preference = function(cat, id, val) {
+    // quick hack to ensure that we do not save preferences if they are 
+    // not modified...
+    var last_saved_preferences = null;
+
+    var _set_preference = function(options, cat, id, val, save) {
         try {
             if (preferences[cat] == undefined) {
                 preferences[cat] = {};
             }
         } catch (e) {
         }
-        $.cookie(cookie_name, JSON.stringify(preferences), {expires: 1825});
+        // save preferences
+        if (save && JSON.stringify(preferences) != last_saved_preferences) {
+            if (options.save_preferences_function) {
+                options.save_preferences_function(options, preferences);
+            } else {
+                $.cookie(cookie_name, JSON.stringify(preferences), {expires: 1825});
+            }
+            last_saved_preferences = JSON.stringify(preferences);
+        }
     };
 
     var _get_positions = function(elt, options) {

admin_tools/urls.py

 
 urlpatterns = patterns('',
     url(r'^menu/', include('admin_tools.menu.urls')),
+    url(r'^dashboard/', include('admin_tools.dashboard.urls')),
 )