Added grappelli inlines for contentlets and attributes which become active if grappel...
authorStephen Burrows <stephen.r.burrows@gmail.com>
Tue, 26 Oct 2010 13:50:51 +0000 (09:50 -0400)
committerStephen Burrows <stephen.r.burrows@gmail.com>
Tue, 26 Oct 2010 13:50:51 +0000 (09:50 -0400)
admin/base.py
admin/pages.py
templates/admin/philo/edit_inline/grappelli_tabular_attribute.html [new file with mode: 0644]
templates/admin/philo/edit_inline/grappelli_tabular_container.html [new file with mode: 0644]

index f4a5f2f..cb814b7 100644 (file)
@@ -1,3 +1,4 @@
+from django.conf import settings
 from django.contrib import admin
 from django.contrib.contenttypes import generic
 from philo.models import Tag, Attribute
@@ -12,12 +13,15 @@ class AttributeInline(generic.GenericTabularInline):
        ct_fk_field = 'entity_object_id'
        model = Attribute
        extra = 1
-       template = 'admin/philo/edit_inline/tabular_attribute.html'
        allow_add = True
        classes = COLLAPSE_CLASSES
        form = AttributeForm
        formset = AttributeInlineFormSet
-       exclude = ['value_object_id']
+       fields = ['key', 'value_content_type']
+       if 'grappelli' in settings.INSTALLED_APPS:
+               template = 'admin/philo/edit_inline/grappelli_tabular_attribute.html'
+       else:
+               template = 'admin/philo/edit_inline/tabular_attribute.html'
 
 
 class EntityAdmin(admin.ModelAdmin):
index 234b9d8..15b06d9 100644 (file)
@@ -1,3 +1,4 @@
+from django.conf import settings
 from django.contrib import admin
 from django import forms
 from philo.admin.base import COLLAPSE_CLASSES
@@ -13,7 +14,11 @@ class ContentletInline(admin.StackedInline):
        formset = ContentletInlineFormSet
        form = ContentletForm
        can_delete = False
-       template = 'admin/philo/edit_inline/tabular_container.html'
+       classes = ('collapse-open', 'collapse','open')
+       if 'grappelli' in settings.INSTALLED_APPS:
+               template = 'admin/philo/edit_inline/grappelli_tabular_container.html'
+       else:
+               template = 'admin/philo/edit_inline/tabular_container.html'
 
 
 class ContentReferenceInline(admin.StackedInline):
@@ -23,7 +28,11 @@ class ContentReferenceInline(admin.StackedInline):
        formset = ContentReferenceInlineFormSet
        form = ContentReferenceForm
        can_delete = False
-       template = 'admin/philo/edit_inline/tabular_container.html'
+       classes = ('collapse-open', 'collapse','open')
+       if 'grappelli' in settings.INSTALLED_APPS:
+               template = 'admin/philo/edit_inline/grappelli_tabular_container.html'
+       else:
+               template = 'admin/philo/edit_inline/tabular_container.html'
 
 
 class PageAdmin(ViewAdmin):
diff --git a/templates/admin/philo/edit_inline/grappelli_tabular_attribute.html b/templates/admin/philo/edit_inline/grappelli_tabular_attribute.html
new file mode 100644 (file)
index 0000000..4760397
--- /dev/null
@@ -0,0 +1,215 @@
+{% load i18n adminmedia %}
+
+<!-- group -->
+<div class="group tabular{% if inline_admin_formset.opts.classes %} {{ inline_admin_formset.opts.classes|join:" " }}{% endif %}"
+       id="{{ inline_admin_formset.formset.prefix }}-group" >
+       <h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
+       <ul class="tools">
+               <li class="add-handler-container"><a href="javascript://" class="icon add-handler" title="{% trans 'Add Another' %}"> </a></li>
+       </ul>
+       {{ inline_admin_formset.formset.management_form }}
+       {{ inline_admin_formset.formset.non_form_errors }}
+       <!-- container -->
+       <div class="module table">
+               <div class="module thead">
+                       <div class="tr">
+                               {% for field in inline_admin_formset.fields %}
+                                       {% if not field.widget.is_hidden %}
+                                               <div class="th {{ field.label|lower }}{% if field.required %} required{% endif %}">{{ field.label|capfirst }}</div>
+                                       {% endif %}
+                               {% endfor %}
+                               <div class="th content_type">Content type</div>
+                               <div class="th value">Value</div>
+                               {% if inline_admin_formset.formset.can_delete %}<div class="th">&nbsp;</div>{% endif %}
+                       </div>
+               </div>
+               {% for inline_admin_form in inline_admin_formset %}
+                       <!-- element -->
+                       <div class="module tbody{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
+                               id="{{ inline_admin_formset.formset.prefix }}{% if not forloop.last %}{{ forloop.counter0 }}{% else %}-empty{% endif %}">
+                               {% if inline_admin_form.form.non_field_errors %}
+                                       <ul class="errorlist"><li>{{ inline_admin_form.form.non_field_errors }}</li></ul>
+                               {% endif %}
+                               <h3 style="display: none;"><b>{{ inline_admin_formset.opts.verbose_name|title }} #{{ forloop.counter }}</b>&nbsp;&nbsp;{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}</h3>
+                               {% spaceless %}
+                               {% for fieldset in inline_admin_form %}
+                                       {% for line in fieldset %}
+                                               {% for field in line %}
+                                                       {% if field.is_hidden %} {{ field.field }} {% endif %}
+                                               {% endfor %}
+                                       {% endfor %}
+                               {% endfor %}
+                               {% endspaceless %}
+                               <div class="tr">
+                                       {% for fieldset in inline_admin_form %}
+                                               {% for line in fieldset %}
+                                                       {% for field in line %}
+                                                               <div class="td {{ field.field.name }} {% if field.field.errors %} error{% endif %}">
+                                                                       {% if field.is_readonly %}
+                                                                               <p>{{ field.contents }}</p>
+                                                                       {% else %}
+                                                                               {{ field.field }}
+                                                                               {{ field.field.errors.as_ul }}
+                                                                       {% endif %}
+                                                               </div>
+                                                       {% endfor %}
+                                               {% endfor %}
+                                       {% endfor %}
+                                       {% with inline_admin_form.form.content_type as field %}<div class="td {{ field.name }}{% if field.errors %} error{% endif %}">{{ field }}{{ field.errors.as_ul }}</div>{% endwith %}
+                                       {% with inline_admin_form.form.value as field %}<div class="td {{ field.name }}{% if field.errors %} error{% endif %}">{{ field }}{{ field.errors.as_ul }}</div>{% endwith %}
+                                       <div class="td tools">
+                                               {% spaceless %}
+                                               <ul class="tools">
+                                                       {% if inline_admin_form.show_url %}<li class="viewsite-link-container"><a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/" class="icon viewsite-link" title="{% trans 'View on Site' %}"> </a></li>{% endif %}
+                                                       {% if inline_admin_formset.opts.sortable_field_name %}
+                                                               <li class="drag-handler-container"><a href="javascript://" class="icon drag-handler" title="{% trans 'Move Item' %}"></a></li>
+                                                       {% endif %}
+                                                       {% if inline_admin_formset.formset.can_delete %}<li class="delete-handler-container">{{ inline_admin_form.deletion_field.field }}<a href="javascript://" class="icon {% if inline_admin_form.original %}delete-handler{% else %}remove-handler{% endif %}" title="{% trans 'Remove' %}"> </a>{% endif %}
+                                               </ul>
+                                               {% endspaceless %}
+                                       </div>
+                                       {{ inline_admin_form.fk_field.field }}
+                                       {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
+                               </div>
+                       </div>
+               {% endfor %}
+       </div>
+       <div class="module add-item">
+               <a href="javascript://" class="add-handler">{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}</a>
+               <ul class="tools">
+                       <li class="add-handler-container"><a href="javascript://" class="icon add-handler" title="{% trans 'Add Item' %}"> </a></li>
+               </ul><br clear="all" />
+       </div>
+</div>
+
+<script type="text/javascript">
+(function($) {
+       $(document).ready(function($) {
+               
+               $("#{{ inline_admin_formset.formset.prefix }}-group").inline({
+                       prefix: "{{ inline_admin_formset.formset.prefix }}",
+                       deleteCssClass: "delete-handler",
+                       emptyCssClass: "empty-form",
+                       onAdded: tabular_onAdded
+               });
+               
+{% if inline_admin_formset.opts.sortable_field_name %}
+               /**
+                * sortable inlines
+                * uses onAdded() and onRemoved() of inline() call above
+                * uses sortable_updateFormIndex() and is_form_filled() from change_from.html
+                */
+               
+               // hide sortable_field(_name) from form
+               // hide div.td.{{ field.name }}
+               var position_nodes = $("#{{ inline_admin_formset.formset.prefix }}-group").find("div.td.{{ inline_admin_formset.opts.sortable_field_name }}");
+               position_nodes.hide();
+               
+               // hide its header (div.th) too (hard)
+               // "div.th.{{ inline_admin_formset.opts.sortable_field_name }}" is not correct because
+               // its div.th.<field.label> (and not name, see line#18).
+               
+               // so let's get the "position/idx" the first position div
+               var tabular_row = position_nodes.first().parent().children("div.td");
+               // get the "position" (== i) in the "table"
+               for (var i = 0; i < tabular_row.length; i++) {
+                       if ($(tabular_row[i]).hasClass("{{ inline_admin_formset.opts.sortable_field_name }}")) break;
+               }
+               // we have the same order in the header of the "table"
+               // so delete the div at the "position" (== i)
+               var position_header = $("#{{ inline_admin_formset.formset.prefix }}-group").find("div.th")[i];
+               // and hide
+               $(position_header).hide()
+               
+       {% if errors %}
+               // sort inline
+               var container = $("#{{ inline_admin_formset.formset.prefix }}-group > div.table"),
+                       dynamic_forms = container.find("div.dynamic-form"),
+                       updated = false,
+                       curr_form,
+                       real_pos;
+               
+               // loop thru all inline forms
+               for (var i = 0; i < dynamic_forms.length; i++) {
+                       curr_form = $(dynamic_forms[i]);
+                       // the real position according to the sort_field(_name)
+                       real_pos = curr_form.find("div.{{ inline_admin_formset.opts.sortable_field_name }}").find("input").val();
+                       // if there is none it's an empty inline (=> we are at the end)
+                       // TODO: klemens: maybe buggy. try continue?
+                       if (!real_pos) continue;
+                       
+                       real_pos = parseInt(real_pos, 10);
+                       
+                       // check if real position is not equal to the CURRENT position in the dom
+                       if (real_pos != container.find("div.dynamic-form").index(curr_form)) {
+                               // move to correct postition
+                               curr_form.insertBefore(container.find("div.dynamic-form")[real_pos]);
+                               // to update the inline lables
+                               updated = true;
+                       }
+               }
+               
+       {% endif %}
+               
+               $("#{{ inline_admin_formset.formset.prefix }}-group > div.table").sortable({
+                       // drag&drop the inlines with the drag-handler only
+                       handle: "a.drag-handler",
+                       // very scary magic after drap&drop operations
+                       // pretty similar to inline() widget's removeHandler()
+                       // but removeHandler() can remove the current form and just reorder the rest
+                       // if we would do the same after drag&drop we would loose some form values
+                       // because while looping inputs would have the same names and maybe overwrite each other.
+                       placeholder: 'ui-sortable-placeholder',
+                       forcePlaceholderSize: true,
+                       items: "div.dynamic-form",
+                       axis: "y",
+                       start: function(evt, ui) {
+                               ui.item.hide()
+                               ui.placeholder.height(ui.placeholder.height()-4);
+                               //sadly we have to do this every time we start dragging
+                               var template = "<div class='tr'>",
+                                       // minus 1 because we don't need the "sortable_field_name row"
+                                       len = ui.item.find("div.tr").children("div.td").length - 1;
+                               
+                               for (var i = 0; i < len; i++) {
+                                       template += "<div class='td'></div>"
+                               }
+                               
+                               template += "</div>"
+                               ui.placeholder.addClass("tbody module").append(template);
+                       },
+                       update: function(evt, ui) {
+                               ui.item.show();
+                       },
+                       appendTo: 'body',
+                       forceHelperSize: true,
+                       containment: '#{{ inline_admin_formset.formset.prefix }}-group > div.table',
+                       tolerance: 'pointer',
+                       helper: function(evt, elem) {
+                               var helper = $("<div class='module table' />");
+                               helper.html(elem.clone());
+                               return helper;
+                       },
+               });
+               
+               // sets the new positions onSubmit (0 - n)
+               $("#{{ opts.module_name }}_form").bind("submit", function(){
+                       var forms = $("#{{ inline_admin_formset.formset.prefix }}-group").find("div.dynamic-form"),
+                               form,
+                               idx = 0;
+                       for (var i = 0; i < forms.length; i++) {
+                               form = $(forms[i]);
+                               
+                               if (is_form_filled(form)) {
+                                       form.find("div.{{ inline_admin_formset.opts.sortable_field_name }}").find("input").val(idx);
+                                       idx++;
+                               }
+                       }
+               });
+               
+{% endif %}
+       
+       });     
+})(django.jQuery);
+</script>
+
diff --git a/templates/admin/philo/edit_inline/grappelli_tabular_container.html b/templates/admin/philo/edit_inline/grappelli_tabular_container.html
new file mode 100644 (file)
index 0000000..5602a38
--- /dev/null
@@ -0,0 +1,43 @@
+{% load i18n adminmedia %}
+
+<!-- group -->
+{{ inline_admin_formset.formset.management_form }}
+{% comment %}Don't render the formset at all if there aren't any forms.{% endcomment %}
+{% if inline_admin_formset.formset.forms %}
+       <fieldset class="module{% if inline_admin_formset.opts.classes %} {{ inline_admin_formset.opts.classes|join:" " }}{% endif %}">
+               <h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
+               {{ inline_admin_formset.formset.non_form_errors }}
+               {% for inline_admin_form in inline_admin_formset %}
+                       {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
+                       {{ inline_admin_form.fk_field.field }}
+                       {% spaceless %}
+                       {% for fieldset in inline_admin_form %}
+                       {% for line in fieldset %}
+                               {% for field in line %}
+                                       {% if field.is_hidden %} {{ field.field }} {% endif %}
+                               {% endfor %}
+                       {% endfor %}
+                       {% endfor %}{% endspaceless %}
+                       <div class="row cells-{{ inline_admin_form.fields|length }}{% if not inline_admin_form.fields|length_is:"2" %} cells{% endif %}{% if inline_admin_form.errors %} errors{% endif %} {% for field in inline_admin_form %}{{ field.field.name }} {% endfor %}{% if forloop.last %} empty-form{% endif %}">
+                               <div{% if not inline_admin_form.fields|length_is:"2" %} class="cell"{% endif %}>
+                                       <div class="column span-4"><label class='required' for="{{ inline_admin_form.form.content.auto_id }}{{ inline_admin_form.form.content_id.auto_id }}">{{ inline_admin_form.form.verbose_name|capfirst }}:</label>{{ inline_admin_form.form.name.as_hidden }}</div>
+                               {% for fieldset in inline_admin_form %}{% for line in fieldset %}{% for field in line %}
+                                       {% if field.field.name != 'name' %}
+                                       <div class="column span-flexible">
+                                               {% if field.is_readonly %}
+                                                       <p class="readonly">{{ field.contents }}</p>
+                                               {% else %}
+                                                       {{ field.field }}
+                                               {% endif %}
+                                               {{ inline_admin_form.errors }}
+                                               {% if field.field.field.help_text %}
+                                                       <p class="help">{{ field.field.field.help_text|safe }}</p>
+                                               {% endif %}
+                                       </div>
+                                       {% endif %}
+                               {% endfor %}{% endfor %}{% endfor %}
+                               </div>
+                       </div>
+               {% endfor %}
+       </fieldset>
+{% endif %}