Permalink
Browse files

Bug fixing, cleaning:

- edit_plugin call fixed in admin
- copy_plugin permission check in admin added (must be added to frontend also)
- `Loading...` message for remote calls in change_list
- overridden $.ajax function in change_list.js, so we get the loader displayed always
- add_page fixed - allows to add page under itself. NOTE that this is a permission change, page.add_page_parmission returns True also if can_add is granted only on children or descendants
- move_page bug fixed
- added moderation notifications over email
  • Loading branch information...
1 parent 5b999fc commit d0a945f6c740950d3fa3d8ae761f99699a23026e pcicman committed Jun 9, 2009
View
@@ -3,3 +3,4 @@
*.DS_Store
cms/media/cms_page_media/
example/run
+example/local_settings.py
View
@@ -6,7 +6,7 @@
from django.contrib.admin.options import IncorrectLookupParameters
from django.contrib.admin.util import unquote
from django.contrib.admin.views.decorators import staff_member_required
-from django.core.exceptions import PermissionDenied
+from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.db import models
from django.forms import Widget, TextInput, Textarea, CharField, HiddenInput
from django.http import HttpResponseRedirect, HttpResponse, Http404
@@ -41,6 +41,7 @@
get_test_moderation_level, moderator_should_approve, approve_page
from django.core.urlresolvers import reverse
from cms.utils.admin import render_admin_menu_item
+from django.utils.functional import curry
PAGE_ADMIN_INLINES = []
@@ -310,7 +311,7 @@ def get_urls(self):
self.admin_site.admin_view(add_plugin),
name='%s_add_plugin' % info),
url(r'^(?:[0-9]+)/edit-plugin/([0-9]+)/$',
- self.admin_site.admin_view(edit_plugin),
+ self.admin_site.admin_view(curry(edit_plugin, admin_site=self.admin_site)),
name='%s_edit_plugin' % info),
url(r'^(?:[0-9]+)/remove-plugin/$',
self.admin_site.admin_view(remove_plugin),
@@ -648,7 +649,7 @@ def move_page(self, request, page_id, extra_context=None):
return HttpResponseRedirect('../../')
try:
- page = self.model.get(pk=page_id)
+ page = self.model.objects.get(pk=page_id)
target = self.model.objects.get(pk=target)
except self.model.DoesNotExist:
return HttpResponse("error")
@@ -709,11 +710,10 @@ def copy_page(self, request, page_id, extra_context=None):
if target is not None and position is not None and site is not None:
try:
target = self.model.objects.get(pk=target)
- except self.model.DoesNotExist:
- return HttpResponse("error")
- try:
+ # does he haves permissions to copy this page under target?
+ assert target.has_add_permission(request)
site = Site.objects.get(pk=site)
- except:
+ except (ObjectDoesNotExist, AssertionError):
return HttpResponse("error")
#context.update({'error': _('Page could not been moved.')})
else:
@@ -235,7 +235,7 @@ div#sitemap li, div#sitemap ul{list-style-type: none;}
#sitemap li .col-language a{text-transform:uppercase;}
#sitemap li .col-language a:hover{text-decoration:underline;}
-#sitemap li .col-actions { width: 65px; }
+#sitemap li .col-actions { width: 80px; }
#sitemap li .col-published {width:65px;}
#sitemap li .col-navigation { width: 65px; }
#sitemap li .col-softroot { width: 20px; }
@@ -444,3 +444,7 @@ div#sitemap ul.header li{
/* softroot icon */
#sitemap li .col-softroot span.icon { background-position: -80px 0px; }
+
+
+/* loading message */
+#loader-message { position: fixed; top: 0px; right: 0px; padding: 4px 8px; background-color: #f1f8ff; display: none;}
@@ -75,6 +75,24 @@ $(document).ready(function() {
var selected_page = false;
var action = false;
+ var _oldAjax = $.ajax;
+
+ $.ajax = function(s){
+ // just override ajax function, so the loader message gets displayed
+ // always
+ $('#loader-message').show();
+
+ callback = s.success || false;
+ s.success = function(data, status){
+ if (callback) {
+ callback(data, status);
+ }
+ $('#loader-message').hide();
+ }
+ // TODO: add error state!
+ return _oldAjax(s);
+ }
+
/**
* Reloads tree item (one line). If some filtering is found, adds
@@ -94,16 +112,13 @@ $(document).ready(function() {
data['fitlered'] = 1;
}
-
-
- $.post(url, data, function(response){
+ $.post(url, data, function(response){
if (callback) callback(response);
var target = $(el).parents('div.cont:first');
var parent = target.parent();
target.replace(response);
parent.find('div.cont:first').yft();
});
-
/*
$.post(url, data, function(response){
if (callback) callback(response);
@@ -115,8 +130,12 @@ $(document).ready(function() {
tree.refresh();
*/
}
-
- // let's start event delegation
+
+ function refresh(){
+ window.location = window.location.href;
+ }
+
+ // let's start event delegation
$('#changelist li').click(function(e) {
// I want a link to check the class
@@ -207,15 +226,21 @@ $(document).ready(function() {
value += $(el).attr("checked") ? parseInt($(el).val()) : 0;
})
- reloadItem(jtarget, "/admin/cms/page/" + pageId + "/change-moderation/", { moderate: value });
+ // just reload the page for now in callback...
+ // TODO: this must be changed sometimes to reloading just the portion
+ // of the tree = current node + descendants
+ reloadItem(jtarget, "/admin/cms/page/" + pageId + "/change-moderation/", { moderate: value }, refresh);
e.stopPropagation();
return true;
}
// quick approve
if(jtarget.hasClass("approve")) {
var pageId = jtarget.parents('li[id^=page_]').attr('id').split('_')[1];
- reloadItem(jtarget, "/admin/cms/page/" + pageId + "/approve/?node=1", { });
+ // just reload the page for now in callback...
+ // TODO: this must be changed sometimes to reloading just the portion
+ // of the tree = current node + descendants
+ reloadItem(jtarget, "/admin/cms/page/" + pageId + "/approve/?node=1", {}, refresh);
e.stopPropagation();
return false;
}
@@ -373,15 +398,15 @@ function moveTreeItem(item_id, target_id, position, tree){
function copyTreeItem(item_id, target_id, position, tree, site){
-
+
$.post("./"+item_id+"/copy-page/", {
position:position,
target:target_id,
site:site
},
function(html) {
if(html=="ok"){
- window.location=window.location.href
+ window.location = window.location.href;
}else{
moveError($('#page_'+item_id + " div.col1:eq(0)"))
}
View
@@ -1,4 +1,3 @@
-from publisher.errors import MpttCantPublish
import urllib2
from os.path import join
from datetime import datetime, date
@@ -13,6 +12,7 @@
from django.template.loader import render_to_string
from django.core.exceptions import ValidationError
from publisher import Publisher, Mptt
+from publisher.errors import MpttCantPublish
from cms.utils.urlutils import urljoin
import mptt
from cms import settings
@@ -117,7 +117,11 @@ def move_page(self, target, position='first-child'):
def copy_page(self, target, site, position='first-child'):
"""
copy a page and all its descendants to a new location
+
+ Doesn't checks for add page permissions anymore, this is done in PageAdmin.
"""
+ from cms.utils.moderator import update_moderation_message
+
descendants = [self] + list(self.get_descendants().filter(sites__pk=site.pk).order_by('-rght'))
tree = [target]
level_dif = self.level - target.level - 1
@@ -135,9 +139,13 @@ def copy_page(self, target, site, position='first-child'):
page.rght = None
page.lft = None
page.tree_id = None
- page.status = Page.DRAFT
+
+ page.status = Page.MODERATOR_CHANGED
page.parent = tree[-1]
page.save()
+
+ update_moderation_message(self, _('Page was copied.'))
+
if first:
first = False
page.move_to(target, position)
@@ -187,8 +195,6 @@ def save(self, no_signals=False, change_state=True):
# always change state to need approvement when there is some change
self.moderator_state = Page.MODERATOR_NEED_APPROVEMENT
- print ">> page.save() page moderators:", self.get_moderator_queryset().all()
-
if self.pk and not self.get_moderator_queryset().count():
# existing page without moderator - publish it directly
publish_directly = True
@@ -211,7 +217,6 @@ def save(self, no_signals=False, change_state=True):
super(Page, self).save()
if publish_directly:
- print ">> Publish directly"
self.publish()
def get_calculated_status(self):
@@ -544,7 +549,6 @@ def publish(self):
# for publishing (because of the parent)
publish_set = self.children.filter(moderator_state = Page.MODERATOR_APPROVED_WAITING_FOR_PARENTS)
for page in publish_set:
- print ">> publish children:", page
# recursive call to all childrens....
page.moderator_state = Page.MODERATOR_APPROVED
page.save(change_state=False)
@@ -750,6 +754,7 @@ def save(self, force_insert=False, force_update=False):
# don't allow `empty` objects
return
return super(AbstractPagePermission, self).save(force_insert, force_update)
+
class GlobalPagePermission(AbstractPagePermission):
"""Permissions for all pages (global).
@@ -762,6 +767,7 @@ class Meta:
__unicode__ = lambda self: "%s :: GLOBAL" % self.audience
+
class PagePermission(AbstractPagePermission):
"""Page permissions for single page
"""
@@ -775,7 +781,9 @@ class Meta:
verbose_name_plural = _('Page permissions')
def __unicode__(self):
- return "%s :: %s" % (self.audience, unicode(dict(ACCESS_CHOICES)[self.grant_on][1]))
+ page = self.page_id and unicode(self.page) or "None"
+ return "%s :: %s has: %s" % (page, self.audience, unicode(dict(ACCESS_CHOICES)[self.grant_on][1]))
+
class ExtUser(User):
"""Cms specific user data, required for permission system
View
@@ -383,7 +383,6 @@ def __get_id_list(self, user, attr):
# all mark
return PagePermissionsPermissionManager.GRANT_ALL
-
from cms.models import GlobalPagePermission, PagePermission, MASK_PAGE,\
MASK_CHILDREN, MASK_DESCENDANTS
@@ -400,16 +399,16 @@ def __get_id_list(self, user, attr):
qs.order_by('page__tree_id', 'page__level', 'page__lft')
# default is denny...
-
page_id_allow_list = []
for permission in qs:
is_allowed = getattr(permission, attr)
if is_allowed:
- if permission.grant_on & MASK_PAGE:
+ # can add is special - we are actually adding page under current page
+ if permission.grant_on & MASK_PAGE or attr is "can_add":
page_id_allow_list.append(permission.page.id)
if permission.grant_on & MASK_CHILDREN:
page_id_allow_list.extend(permission.page.get_children().values_list('id', flat=True))
elif permission.grant_on & MASK_DESCENDANTS:
page_id_allow_list.extend(permission.page.get_descendants().values_list('id', flat=True))
- print "> perm u:", user, "attr:", attr, page_id_allow_list
+ #print "> perm u:", user, "attr:", attr, page_id_allow_list
return page_id_allow_list
@@ -0,0 +1,11 @@
+{% extends 'admin/cms/email/base.html' %}
+{% load i18n %}
+
+{% block content %}
+ <p>{% blocktrans %}Page <a href="{{ admin_url }}">{{ page }}</a> may require approvement by you.{% endblocktrans %}</p>
+
+ {% if page.pagemoderatorstate_set.count %}
+ <h3>{% trans 'Last changes' %}</h3>
+ {% include 'admin/cms/page/moderation_messages.html' %}
+ {% endif %}
+{% endblock %}
@@ -0,0 +1,85 @@
+{% load i18n %}<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head height="100%">
+<title>{{ title }}</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="Content-Language" content="en-us" />
+<style type="text/css" media="screen">
+ html,
+ body,
+ .grid {
+ height: 100%;
+ }
+
+ .header {
+ margin-bottom: 40px;
+ }
+
+ .content {
+ padding: 28px;
+ font-family: Lucida Grande;
+ font-size: 12px;
+ }
+
+ .content h1 {
+ font-family: Georgia;
+ font-size: 23px;
+ font-weight: normal;
+ }
+
+ .content a,
+ .content a:active,
+ .content a:visited,
+ .content a:hover {
+ text-decoration: underline;
+ }
+
+ .content p {
+ margin-bottom: 20px;
+ }
+
+ .content .box {
+ width: 100%;
+ margin: 10px 0;
+ padding: 8px;
+
+ font-family: Georgia;
+ font-size: 15px;
+ }
+
+ .content .box h2 {
+ font-size: 18px;
+ font-weight: normal;
+ }
+
+ .content .box table {
+ margin-bottom: 10px;
+ }
+
+ .data {
+ line-height: 24px;
+ }
+
+</style>
+</head>
+
+<body topmargin="0" leftmargin="0" marginheight="0" marginwidth="0" height="100%">
+
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" class="grid">
+ <tr>
+ <td width="100%" class="content" valign="top">
+ <div class="header">
+ <h1>{{ title }}</h1>
+ {% block header %}{% endblock %}
+ </div>
+ {% block content %}{% endblock %}
+ </td>
+ </tr>
+ <tr>
+ <td class="content">
+ Generated by <a href="http://www.django-cms.org">django cms</a> {% now "d.m.Y H:i:s" %}
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
Oops, something went wrong.

0 comments on commit d0a945f

Please sign in to comment.