Skip to content

Commit

Permalink
feature #3 add priority_level for menu order.
Browse files Browse the repository at this point in the history
  • Loading branch information
wuyue92tree committed Aug 6, 2019
1 parent c03c77a commit 5020caf
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 28 deletions.
18 changes: 15 additions & 3 deletions adminlteui/admin.py
Expand Up @@ -7,10 +7,12 @@
from django.urls import path, reverse
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from django.utils.html import format_html
from django.conf import settings
from django.http.response import HttpResponse, HttpResponseForbidden
from django.http.response import HttpResponse, HttpResponseForbidden, \
HttpResponseBadRequest
from adminlteui.widgets import AdminlteSelect
from treebeard.admin import TreeAdmin
from treebeard.forms import movenodeform_factory
Expand Down Expand Up @@ -225,10 +227,10 @@ def general_option_view(self, request):
@admin.register(Menu)
class MenuAdmin(TreeAdmin):
list_display = ('name', 'position', 'link_type', 'display_link',
'display_content_type', 'display_icon',
'display_content_type', 'priority_level', 'display_icon',
'valid')
list_filter = ('position', 'link_type', 'valid')
list_editable = ('valid',)
list_editable = ('valid', 'priority_level')
form = movenodeform_factory(Menu)
change_list_template = 'adminlte/menu_change_list.html'
change_form_template = 'adminlte/menu_change_form.html'
Expand All @@ -250,6 +252,16 @@ def formfield_for_foreignkey(self, db_field, request, **kwargs):

return super().formfield_for_foreignkey(db_field, request, **kwargs)

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
try:
return super().changeform_view(request, object_id, form_url, extra_context)
except Exception as e:
messages.error(request,
_('Exception raised while add node: %s') % _(
force_str(e)))
return HttpResponseBadRequest(
_('Exception raised while add node: %s') % _(force_str(e)))

def get_urls(self):
base_urls = super().get_urls()
urls = [
Expand Down
18 changes: 18 additions & 0 deletions adminlteui/migrations/0005_menu_priority_level.py
@@ -0,0 +1,18 @@
# Generated by Django 2.2.2 on 2019-08-06 01:37

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_admin_settings', '0004_auto_20190708_1832'),
]

operations = [
migrations.AddField(
model_name='menu',
name='priority_level',
field=models.IntegerField(default=100, verbose_name='Priority Level'),
),
]
27 changes: 22 additions & 5 deletions adminlteui/models.py
@@ -1,10 +1,12 @@
# -*- coding: utf-8 -*-
import itertools
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.contrib.contenttypes.models import ContentType

from treebeard.mp_tree import MP_Node
from treebeard.mp_tree import MP_Node,\
InvalidMoveToDescendant, MP_MoveHandler


class Options(models.Model):
Expand Down Expand Up @@ -39,7 +41,8 @@ class Menu(MP_Node):
verbose_name=_('Link Type'))
link = models.CharField(max_length=255, blank=True, null=True,
verbose_name=_('Link'),
help_text=_('support admin:index or /admin/ or http://'))
help_text=_(
'support admin:index or /admin/ or http://'))
icon = models.CharField(max_length=255,
blank=True,
null=True,
Expand All @@ -50,12 +53,26 @@ class Menu(MP_Node):
on_delete=models.CASCADE,
help_text=_(
'use for permission control.'))

priority_level = models.IntegerField(default=100,
verbose_name=_('Priority Level'),
help_text=_('The bigger the priority'))
valid = models.BooleanField(default=True, verbose_name=_('Valid'))
node_order_by = ['name', 'position']
node_order_by = ['priority_level']

def move(self, target, pos=None):
"""
Moves the current node and all it's descendants to a new position
relative to another node.
:raise PathOverflow: when the library can't make room for the
node's new position
"""
if target.depth == 2:
raise InvalidMoveToDescendant(_('max depth is 2.'))
return MP_MoveHandler(self, target, pos).process()

def __str__(self):
return '{}'.format(self.name)
return '{}|{}'.format(self.name, self.priority_level)

class Meta:
verbose_name = _('Menu')
Expand Down
28 changes: 25 additions & 3 deletions adminlteui/templates/adminlte/menu_change_list.html
@@ -1,10 +1,32 @@
{% extends "admin/tree_change_list.html" %}
{% load i18n %}
{# Used for MP and NS trees #}
{% extends "admin/change_list.html" %}
{% load admin_list admin_tree adminlte_list i18n %}

{% block extrastyle %}
{{ block.super }}
{% treebeard_css %}
{% endblock %}

{% block extrahead %}
{{ block.super }}
{% treebeard_js %}
{% endblock %}

{% block object-tools-items %}
<button id="exchange_menu" class="btn btn-danger">{% trans 'Exchange Menu' %}</button>
{{ block.super }}
{% endblock %}

{% block result_list %}
{% if action_form and actions_on_top and cl.full_result_count %}
{% admin_actions %}
{% endif %}
{% adminlte_result_tree cl request %}
{% if action_form and actions_on_bottom and cl.full_result_count %}
{% admin_actions %}
{% endif %}
{% endblock %}

{% block extrajs %}
{{ block.super }}
<script>
Expand All @@ -19,4 +41,4 @@
})
});
</script>
{% endblock %}
{% endblock %}
81 changes: 81 additions & 0 deletions adminlteui/templatetags/adminlte_list.py
Expand Up @@ -4,10 +4,17 @@
)
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from django.template import Library
from django.template.loader import get_template
from django.contrib.admin.templatetags.admin_list import (
result_headers, result_hidden_fields)
import urllib.parse

from treebeard.templatetags import needs_checkboxes
from treebeard.templatetags.admin_tree import check_empty_dict, get_parent_id, \
items_for_result

register = Library()

DOT = '.'
Expand Down Expand Up @@ -97,3 +104,77 @@ def adminlte_admin_list_filter(cl, spec):
'choices': choices,
'spec': spec,
})


def results(cl):
"""
reorder by priority_level
:param cl:
:return:
"""
if cl.formset:
new_result_list = []
new_forms = []
parent_nodes = cl.result_list.filter(depth=1).order_by(
'-priority_level')
for parent_node in parent_nodes:
new_result_list.append(parent_node)

child_nodes = parent_node.get_children().order_by('-priority_level')
for child_node in child_nodes:
new_result_list.append(child_node)

order_ = []
for i, obj in enumerate(new_result_list):
for j, obj_new in enumerate(cl.result_list):
if obj_new == obj:
order_.append(j)

for o in order_:
new_forms.append(cl.formset.forms[o])

for res, form in zip(new_result_list, new_forms):
yield (res.pk, get_parent_id(res), res.get_depth(),
res.get_children_count(),
list(items_for_result(cl, res, form)))
else:
new_result_list = []
parent_nodes = cl.result_list.filter(depth=1).order_by(
'-priority_level')
for parent_node in parent_nodes:
new_result_list.append(parent_node)

child_nodes = parent_node.get_children().order_by('-priority_level')
for child_node in child_nodes:
new_result_list.append(child_node)

for res in new_result_list:
yield (res.pk, get_parent_id(res), res.get_depth(),
res.get_children_count(),
list(items_for_result(cl, res, None)))


@register.inclusion_tag(
'admin/tree_change_list_results.html', takes_context=True)
def adminlte_result_tree(context, cl, request):
"""
Added 'filtered' param, so the template's js knows whether the results have
been affected by a GET param or not. Only when the results are not filtered
you can drag and sort the tree
"""

# Here I'm adding an extra col on pos 2 for the drag handlers
headers = list(result_headers(cl))
headers.insert(1 if needs_checkboxes(context) else 0, {
'text': '+',
'sortable': True,
'url': request.path,
'tooltip': _('Return to ordered tree'),
'class_attrib': mark_safe(' class="oder-grabber"')
})
return {
'filtered': not check_empty_dict(request.GET),
'result_hidden_fields': list(result_hidden_fields(cl)),
'result_headers': headers,
'results': list(results(cl)),
}
32 changes: 15 additions & 17 deletions adminlteui/templatetags/adminlte_menu.py
Expand Up @@ -51,52 +51,50 @@ def get_custom_menu(request, position):

limit_for_internal_link = set(limit_for_internal_link)
new_available_apps = []
menu = Menu.dump_bulk()
menu = Menu.get_tree().filter(depth=1).order_by('-priority_level')
for menu_item in menu:
if menu_item.get('data').get('position') != position:
if menu_item.position != position:
continue

new_available_apps_item = {}
data = (menu_item.get('data'))
if data.get('valid') is False:
if menu_item.valid is False:
continue

new_available_apps_item['name'] = data.get('name')
new_available_apps_item['icon'] = data.get('icon')
new_available_apps_item['name'] = menu_item.name
new_available_apps_item['icon'] = menu_item.icon

children = menu_item.get('children')
children = menu_item.get_children().order_by('-priority_level')
if not children:
# skip menu_item that no children and link type is devide.
if data.get('link_type') in (0, 1):
if menu_item.link_type in (0, 1):
new_available_apps_item['admin_url'] = get_reverse_link(
data.get('link'))
menu_item.link)
new_available_apps.append(new_available_apps_item)
continue
new_available_apps_item['models'] = []

for children_item in children:
if children_item.get('data').get('link_type') == 0:
if children_item.link_type == 0:
# internal link should connect a content_type, otherwise it will be hide.
if children_item.get('data').get('content_type'):
if children_item.content_type:
obj = ContentType.objects.get(
id=children_item.get('data').get('content_type'))
id=children_item.content_type.id)
# if user hasn't permission, the model will be skip.
if obj.app_label + ':' + obj.model not in limit_for_internal_link:
continue
else:
continue

if children_item.get('data').get('valid') is False:
if children_item.valid is False:
continue
new_children_item = dict()
new_children_item['name'] = children_item.get('data').get('name')
new_children_item['name'] = children_item.name
new_children_item['admin_url'] = get_reverse_link(
children_item.get('data').get('link')
children_item.link
)
if not new_children_item['admin_url']:
continue
new_children_item['icon'] = children_item.get('data').get('icon')
# new_children_item['admin_url'] = children_item.get('link')
new_children_item['icon'] = children_item.icon
new_available_apps_item['models'].append(new_children_item)
if new_available_apps_item['models']:
new_available_apps.append(new_available_apps_item)
Expand Down

0 comments on commit 5020caf

Please sign in to comment.