This repository was archived by the owner on Dec 26, 2023. It is now read-only.
forked from feincms/feincms
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsplitpane_editor.py
More file actions
135 lines (111 loc) · 5.71 KB
/
Copy pathsplitpane_editor.py
File metadata and controls
135 lines (111 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from django import template
from django.conf import settings as django_settings
from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render_to_response
from django.utils.text import capfirst
from feincms import settings
class SplitPaneEditor(admin.ModelAdmin):
# This can be replaced dynamically with another condition if the need
# should arise. Using AJAX if the tree node count exceeds 25 tries to
# be a sane default only, nothing more.
delayed_tree_loading = lambda self: self.model._tree_manager.count() > 25
def changelist_view(self, request, extra_context=None):
if 'mptt' not in django_settings.INSTALLED_APPS:
# mptt_tags is needed to build the nested tree for the tree view
raise ImproperlyConfigured, 'You have to add \'mptt\' to INSTALLED_APPS to use the SplitPaneEditor'
if not self.has_change_permission(request, None):
raise PermissionDenied
if request.is_ajax():
cmd = request.REQUEST.get('__cmd')
if cmd == 'move_node':
return self._move_node(request)
elif cmd == 'subtree':
return self._subtree_view(request)
return HttpResponseBadRequest('Oops. AJAX request not understood.')
if '_tree' in request.GET:
# Left frame
return self._tree_view(request)
elif '_blank' in request.GET:
# Default content for right frame (if the user is not editing
# any items currently)
return self._blank_view(request)
elif 'pop' in request.GET:
# Delegate to default implementation for raw_id_fields etc
return super(SplitPaneEditor, self).changelist_view(request, extra_context)
return render_to_response('admin/feincms/splitpane_editor.html')
def _tree_view(self, request):
# XXX the default manager isn't guaranteed to have a method
# named "active" at all...
try:
inactive_nodes = self.model._default_manager.exclude(
id__in=self.model._default_manager.active()).values_list('id', flat=True)
except AttributeError:
inactive_nodes = []
opts = self.model._meta
context = {
'opts': opts,
'root_path': self.admin_site.root_path,
'inactive_nodes': ', '.join('#item%d' % i for i in inactive_nodes),
'FEINCMS_ADMIN_MEDIA': settings.FEINCMS_ADMIN_MEDIA,
'FEINCMS_ADMIN_TREE_DRAG_AND_DROP': settings.FEINCMS_ADMIN_TREE_DRAG_AND_DROP
}
if self.delayed_tree_loading():
context['object_list'] = self.model._tree_manager.root_nodes()
else:
context['object_list'] = self.model._tree_manager.all()
context['full_object_list'] = True
return render_to_response([
'admin/feincms/%s/%s/splitpane_editor_tree.html' % (opts.app_label, opts.object_name.lower()),
'admin/feincms/%s/splitpane_editor_tree.html' % opts.app_label,
'admin/feincms/splitpane_editor_tree.html',
], context, context_instance=template.RequestContext(request))
def _subtree_view(self, request):
parent = self.model._default_manager.get(pk=request.GET.get('parent'))
return render_to_response('admin/feincms/splitpane_editor_tree_subtree.html', {
'object_list': parent.get_children(),
})
def _blank_view(self, request):
opts = self.model._meta
return render_to_response('admin/feincms/splitpane_editor_blank.html', {
'has_add_permission': self.has_add_permission(request),
'root_path': self.admin_site.root_path,
'title': capfirst(opts.verbose_name_plural),
'opts': opts,
}, context_instance=template.RequestContext(request))
def _move_node(self, request):
destination_id = int(request.POST.get('destination'))
source_id = int(request.POST.get('source'))
position = int(request.POST.get('position'))
if destination_id == 0:
siblings = self.model._tree_manager.root_nodes()
else:
parent = self.model._tree_manager.get(pk=destination_id)
siblings = parent.get_children()
source = self.model._tree_manager.get(pk=source_id)
if siblings.count() == 0:
# This can only happen when destination != 0
# Insert dragged element as new (and only) child
self.model._tree_manager.move_node(source, parent, 'last-child')
elif position == 0:
sibling = siblings[0]
if sibling != source:
# Only do something if item was not dragged to the same place
# as it was before
self.model._tree_manager.move_node(source, siblings[0], 'left')
else:
sibling = siblings[position - 1]
if source in siblings[:position]:
# The item is a direct sibling of its former position. If the
# item's place was somewhere before its new place, we have to
# adjust the position slightly
self.model._tree_manager.move_node(source, siblings[position], 'right')
else:
# Otherwise, add it to the right of the target node. This
# works for last childs too
self.model._tree_manager.move_node(source, siblings[position - 1], 'right')
# Ensure that model save has been run
source = self.model._tree_manager.get(pk=source_id)
source.save()
return HttpResponse('OK')