manager: rough (re-)ordering of pages
This is not perfect as it uses Sortable from jquery-ui which is adapted for flat lists, not nested lists, and ideally we would want to create multiple placeholders per element, to make it clear the lement is moved as a child or as a sibling.
This commit is contained in:
parent
f11420e24f
commit
6cedb0e9d2
|
@ -19,6 +19,7 @@ import inspect
|
|||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.db.models import Max
|
||||
from django.forms import models as model_forms
|
||||
from django.template import Context
|
||||
from django.utils.html import strip_tags
|
||||
|
@ -35,10 +36,23 @@ class Page(models.Model):
|
|||
slug = models.SlugField()
|
||||
template_name = models.CharField(max_length=50)
|
||||
parent = models.ForeignKey('self', null=True, blank=True)
|
||||
order = models.PositiveIntegerField()
|
||||
|
||||
_level = None
|
||||
_children = None
|
||||
|
||||
class Meta:
|
||||
ordering = ['order']
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.order:
|
||||
max_order = Page.objects.all().aggregate(Max('order')).get('order__max') or 0
|
||||
self.order = max_order + 1
|
||||
return super(Page, self).save(*args, **kwargs)
|
||||
|
||||
def get_online_url(self):
|
||||
parts = [self.slug]
|
||||
page = self
|
||||
|
@ -50,6 +64,19 @@ class Page(models.Model):
|
|||
def has_children(self):
|
||||
return Page.objects.filter(parent_id=self.id).exists()
|
||||
|
||||
@classmethod
|
||||
def get_as_reordered_flat_hierarchy(cls, object_list):
|
||||
reordered = []
|
||||
def fill_list(object_sublist, level=0, parent=None):
|
||||
for page in object_sublist:
|
||||
page._children = [x for x in object_list if x.parent_id == page.id]
|
||||
if page.parent == parent:
|
||||
page.level = level
|
||||
reordered.append(page)
|
||||
fill_list(object_sublist, level=level+1, parent=page)
|
||||
fill_list(object_list)
|
||||
return reordered
|
||||
|
||||
|
||||
class CellBase(models.Model):
|
||||
page = models.ForeignKey(Page)
|
||||
|
|
|
@ -22,6 +22,7 @@ from combo.data.models import Page
|
|||
class PageForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Page
|
||||
exclude = ('order', )
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PageForm, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -135,3 +135,18 @@ li.cell-type input:checked ~ ul {
|
|||
}
|
||||
|
||||
.icon-eye-open:before { content: "\f06e "; }
|
||||
|
||||
div#pages-list > div {
|
||||
border: 1px solid #eee;
|
||||
margin: 0.5ex 0;
|
||||
box-shadow: rgba(0, 0, 0, 0.04) 0px 1px 1px 0px;
|
||||
padding: 1ex;
|
||||
}
|
||||
|
||||
div#pages-list > div.level-1 {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
div#pages-list > div.level-2 {
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,52 @@
|
|||
function init_pages_list()
|
||||
{
|
||||
if ($('#pages-list').length == 0)
|
||||
return;
|
||||
var list_offset = $('#pages-list').offset().left;
|
||||
$('#pages-list').sortable({
|
||||
stop: function(event, ui) {
|
||||
var moved_page_id = ui.item.data('page-id');
|
||||
/* 25 is the per-level margin-left applied to pages, it needs to be kept
|
||||
* in sync with the css file */
|
||||
var item_offset = ui.offset.left - list_offset + parseInt($(ui.item).data('level'))*25;
|
||||
var new_level = Math.abs(Math.round(item_offset / 25));
|
||||
console.log(new_level);
|
||||
if (new_level <= 0) {
|
||||
new_level = 0;
|
||||
} else {
|
||||
var previous_page = $('#pages-list div[data-page-id=' + moved_page_id + ']').prev();
|
||||
var previous_page_level = parseInt($(previous_page).data('level'));
|
||||
if (new_level > previous_page_level+1) {
|
||||
new_level = previous_page_level+1;
|
||||
}
|
||||
}
|
||||
|
||||
var new_parent = null;
|
||||
if (new_level != 0) {
|
||||
new_parent = $($(ui.item).prevAll('[data-level='+(new_level-1)+']')[0]).data('page-id');
|
||||
}
|
||||
/* remove classes and add new values */
|
||||
$(ui.item).removeClass('level-0').removeClass('level-1').removeClass('level-2');
|
||||
$(ui.item).addClass('level-' + new_level);
|
||||
$(ui.item).data('level', new_level).attr('data-level', new_level);
|
||||
|
||||
var new_order = $('#pages-list div').map(function() { return $(this).data('page-id'); }).get().join();
|
||||
|
||||
$.ajax({
|
||||
url: $('#pages-list').data('page-order-url'),
|
||||
data: {'new-order': new_order,
|
||||
'moved-page-id': moved_page_id,
|
||||
'moved-page-new-parent': new_parent
|
||||
},
|
||||
success: function(data, status) {
|
||||
$('#pages-list').replaceWith($(data).find('#pages-list'));
|
||||
init_pages_list();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('div.cell-list h3').on('click', function() {
|
||||
$(this).parent().toggleClass('toggled').toggleClass('untoggled');
|
||||
|
@ -6,6 +55,7 @@ $(function() {
|
|||
$(this).parents('.toggled').toggleClass('toggled').toggleClass('untoggled');
|
||||
return false;
|
||||
});
|
||||
init_pages_list();
|
||||
$('.cell-list').sortable({
|
||||
connectWith: '.cell-list',
|
||||
handle: 'h3',
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
<ul>
|
||||
{% if parent %}
|
||||
<li><a href="{% if parent.parent_id %}?parent={{ parent.parent_id }}{% else %}.{% endif %}">..</a></li>
|
||||
{% endif %}
|
||||
<div id="pages-list" data-page-order-url="{% url 'combo-manager-page-order' %}">
|
||||
{% for page in object_list %}
|
||||
<li><a href="{% url 'combo-manager-page-view' pk=page.id %}">{{ page.title }}</a>
|
||||
{% if page.has_children %}<a href="?parent={{ page.id }}">+</a>{% endif %}
|
||||
</li>
|
||||
<div class="level-{{page.level}}" data-page-id="{{page.id}}" data-level="{{page.level}}">
|
||||
<a href="{% url 'combo-manager-page-view' pk=page.id %}">{{ page.title }}</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a href="{% url 'combo-manager-page-add' %}">+</a>
|
||||
|
||||
|
|
|
@ -36,5 +36,7 @@ urlpatterns = patterns('combo.views',
|
|||
name='combo-manager-page-delete-cell'),
|
||||
url(r'^pages/(?P<page_pk>\w+)/order$', views.cell_order,
|
||||
name='combo-manager-cell-order'),
|
||||
url(r'^pages/order$', views.page_order,
|
||||
name='combo-manager-page-order'),
|
||||
(r'^ckeditor/', include('ckeditor.urls')),
|
||||
)
|
||||
|
|
|
@ -19,6 +19,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.forms import models as model_forms
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.views.decorators.csrf import requires_csrf_token
|
||||
from django.views.generic import (TemplateView, RedirectView, DetailView,
|
||||
CreateView, UpdateView, ListView, DeleteView)
|
||||
|
@ -38,18 +39,9 @@ class PagesListView(ListView):
|
|||
model = Page
|
||||
template_name = 'combo/pages_list.html'
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super(PagesListView, self).get_queryset()
|
||||
try:
|
||||
parent_id = self.request.GET['parent']
|
||||
except KeyError:
|
||||
return queryset.filter(parent_id__isnull=True)
|
||||
return queryset.filter(parent_id=parent_id)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.object_list = Page.get_as_reordered_flat_hierarchy(self.object_list)
|
||||
context = super(PagesListView, self).get_context_data(**kwargs)
|
||||
if self.request.GET.get('parent'):
|
||||
context['parent'] = Page.objects.get(id=self.request.GET['parent'])
|
||||
return context
|
||||
|
||||
|
||||
|
@ -169,3 +161,17 @@ def cell_order(request, page_pk):
|
|||
cell.placeholder = new_placeholder
|
||||
cell.save()
|
||||
return HttpResponse(status=206)
|
||||
|
||||
|
||||
def page_order(request):
|
||||
new_order = [int(x) for x in request.GET['new-order'].split(',')]
|
||||
moved_page = Page.objects.get(id=request.GET['moved-page-id']);
|
||||
if request.GET['moved-page-new-parent']:
|
||||
moved_page.parent_id = request.GET['moved-page-new-parent'];
|
||||
else:
|
||||
moved_page.parent_id = None
|
||||
moved_page.save()
|
||||
for page in Page.objects.filter(parent_id=moved_page.parent_id):
|
||||
page.order = new_order.index(page.id)+1
|
||||
page.save()
|
||||
return redirect(reverse('combo-manager-pages-list'))
|
||||
|
|
Loading…
Reference in New Issue