Commit 4162909f by benjaoming

Fix Issue #7 (in setup.py) + Add forms in settings tab, save new permissions and…

Fix Issue #7 (in setup.py) + Add forms in settings tab, save new permissions and notification preferences
parent 15a363d0
Not implemented - will be ASAP
==============================
* Permission system in settings tab
* Notification system
* Simple user account handling: login/register etc.
Ideas Ideas
===== =====
* Build TOCs and use bootstrap scrollspy * Build TOCs and use bootstrap scrollspy
* Notification system should be it's own separate app * Notification system should be it's own separate app
* Statistics page for wiki owners * Statistics page for wiki owners
* Auto-merge for conflicting concurrent revisions * Auto-merge for conflicting concurrent revisions **DONE**
* Add revision conflict detection for concurrent editing * Add revision conflict detection for concurrent editing **DONE**
* Make a comments plugin for commenting inline * Make a comments plugin for commenting inline
Management script Management script
......
...@@ -18,9 +18,8 @@ class NotificationType(models.Model): ...@@ -18,9 +18,8 @@ class NotificationType(models.Model):
class Settings(models.Model): class Settings(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
interval = models.SmallIntegerField(choices=settings.INTERVALS, verbose_name=_(u'interval')) interval = models.SmallIntegerField(choices=settings.INTERVALS, verbose_name=_(u'interval'),
send_emails = models.BooleanField(default=True) default=settings.INTERVALS_DEFAULT)
send_emails_type = models.ManyToManyField(NotificationType)
class Subscription(models.Model): class Subscription(models.Model):
...@@ -28,6 +27,7 @@ class Subscription(models.Model): ...@@ -28,6 +27,7 @@ class Subscription(models.Model):
notification_type = models.ForeignKey(NotificationType) notification_type = models.ForeignKey(NotificationType)
object_id = models.CharField(max_length=64, null=True, blank=True, object_id = models.CharField(max_length=64, null=True, blank=True,
help_text=_(u'Leave this blank to subscribe to any kind of object')) help_text=_(u'Leave this blank to subscribe to any kind of object'))
send_emails = models.BooleanField(default=True)
class Notification(models.Model): class Notification(models.Model):
......
...@@ -22,6 +22,8 @@ INTERVALS = getattr(django_settings, "NOTIFY_INTERVALS", ...@@ -22,6 +22,8 @@ INTERVALS = getattr(django_settings, "NOTIFY_INTERVALS",
(DAILY, _(u'daily')), (DAILY, _(u'daily')),
(WEEKLY, _(u'weekly'))]) (WEEKLY, _(u'weekly'))])
INTERVALS_DEFAULT = INSTANTLY
# Minimum logging and digital garbage! Don't save too much crap! # Minimum logging and digital garbage! Don't save too much crap!
# After how many days should viewed notifications be deleted? # After how many days should viewed notifications be deleted?
......
...@@ -10,7 +10,7 @@ def read(fname): ...@@ -10,7 +10,7 @@ def read(fname):
def build_media_pattern(base_folder, file_extension): def build_media_pattern(base_folder, file_extension):
return ["%s/%s*.%s" % (base_folder, "*/"*x, file_extension) for x in range(5)] return ["%s/%s*.%s" % (base_folder, "*/"*x, file_extension) for x in range(10)]
template_patterns = ( build_media_pattern("templates", "html") + template_patterns = ( build_media_pattern("templates", "html") +
build_media_pattern("static", "js") + build_media_pattern("static", "js") +
......
...@@ -49,7 +49,6 @@ class EditForm(forms.Form): ...@@ -49,7 +49,6 @@ class EditForm(forms.Form):
data = kwargs.get('data', None) data = kwargs.get('data', None)
if data: if data:
self.presumed_revision = data.get('current_revision', None) self.presumed_revision = data.get('current_revision', None)
print self.initial_revision.id, self.presumed_revision
if not str(self.presumed_revision) == str(self.initial_revision.id): if not str(self.presumed_revision) == str(self.initial_revision.id):
newdata = {} newdata = {}
for k,v in data.items(): for k,v in data.items():
...@@ -81,12 +80,13 @@ class SelectWidgetBootstrap(forms.Select): ...@@ -81,12 +80,13 @@ class SelectWidgetBootstrap(forms.Select):
function setBtnGroupVal(elem) { function setBtnGroupVal(elem) {
selected_a = $(elem).parentsUntil('ul').find('a[selected]'); selected_a = $(elem).parentsUntil('ul').find('a[selected]');
if (selected_a.length > 0) { if (selected_a.length > 0) {
val = $(elem).parentsUntil('ul').find('a[selected]').attr('data-value'); val = selected_a.attr('data-value');
label = $(elem).parentsUntil('ul').find('a[selected]').html(); label = selected_a.html();
} else { } else {
$(elem).parentsUntil('ul').find('a').first().attr('selected', 'selected'); $(elem).parentsUntil('ul').find('a').first().attr('selected', 'selected');
setBtnGroupVal(elem); setBtnGroupVal(elem);
} }
alert(val);
$(elem).val(val); $(elem).val(val);
$(elem).parents('.btn-group').find('.btn-group-label').html(label); $(elem).parents('.btn-group').find('.btn-group-label').html(label);
} }
...@@ -97,7 +97,8 @@ class SelectWidgetBootstrap(forms.Select): ...@@ -97,7 +97,8 @@ class SelectWidgetBootstrap(forms.Select):
$('.btn-group-form li a').click(function() { $('.btn-group-form li a').click(function() {
$(this).parent().siblings().find('a').attr('selected', ''); $(this).parent().siblings().find('a').attr('selected', '');
$(this).attr('selected', 'selected'); $(this).attr('selected', 'selected');
setBtnGroupVal(this); setBtnGroupVal($(this).parentsUntil('div').parent().find('input.btn-group-value').first());
alert($(this).parentsUntil('div').parent().find('input.btn-group-value').first().val());
}); });
}) })
</script> </script>
...@@ -137,7 +138,7 @@ class SelectWidgetBootstrap(forms.Select): ...@@ -137,7 +138,7 @@ class SelectWidgetBootstrap(forms.Select):
def render_option(self, selected_choices, option_value, option_label): def render_option(self, selected_choices, option_value, option_label):
option_value = force_unicode(option_value) option_value = force_unicode(option_value)
selected_html = (option_value in selected_choices) and u' selected="selected"' or '' selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
return u'<li><a href="#" data-value="%s"%s>%s</a></li>' % ( return u'<li><a href="javascript:void(0)" data-value="%s"%s>%s</a></li>' % (
escape(option_value), selected_html, escape(option_value), selected_html,
conditional_escape(force_unicode(option_label))) conditional_escape(force_unicode(option_label)))
...@@ -200,8 +201,22 @@ class PermissionsForm(forms.ModelForm): ...@@ -200,8 +201,22 @@ class PermissionsForm(forms.ModelForm):
group = forms.ModelChoiceField(models.Group.objects.all(), widget=SelectWidgetBootstrap(), group = forms.ModelChoiceField(models.Group.objects.all(), widget=SelectWidgetBootstrap(),
empty_label=_(u'(none)'), required=False) empty_label=_(u'(none)'), required=False)
def __init__(self, article, *args, **kwargs): def get_usermessage(self):
return super(PermissionsForm, self).__init__(*args, **kwargs) if self.changed_data:
return _('Your permission settings were updated.')
else:
return _('Your permission settings were unchanged, so nothing saved.')
def __init__(self, article, user, *args, **kwargs):
self.article = article
self.user = user
kwargs['instance'] = article
super(PermissionsForm, self).__init__(*args, **kwargs)
print self.data
if user.is_superuser:
self.fields['group'].queryset = models.Group.objects.all()
else:
self.fields['group'].queryset = models.Group.objects.filter(user=user)
class Meta: class Meta:
model = models.Article model = models.Article
......
from django import forms from django import forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
import models
from django_notify.models import Settings, NotificationType
from django.contrib.contenttypes.models import ContentType
from django.utils.safestring import mark_safe
class SubscriptionForm(forms.Form): class SubscriptionForm(forms.Form):
settings_form_id = "notifications" settings_form_id = "notifications"
...@@ -8,11 +13,42 @@ class SubscriptionForm(forms.Form): ...@@ -8,11 +13,42 @@ class SubscriptionForm(forms.Form):
settings_order = 1 settings_order = 1
settings_write_access = False settings_write_access = False
def __init__(self, article, *args, **kwargs): def __init__(self, article, user, *args, **kwargs):
self.article = article self.article = article
self.user = user
initial = kwargs.pop('initial', None)
self.settings = Settings.objects.get_or_create(user=user,)[0]
self.notification_type = NotificationType.objects.get_or_create(key=models.NOTIFICATION_ARTICLE_EDIT,
content_type=ContentType.objects.get_for_model(article))[0]
self.edit_notifications=models.ArticleSubscription.objects.filter(settings=self.settings,
article=article,
notification_type=self.notification_type)
if not initial:
initial = {'edit': bool(self.edit_notifications),
'edit_email': bool(self.edit_notifications.filter(send_emails=True))}
kwargs['initial'] = initial
super(SubscriptionForm, self).__init__(*args, **kwargs) super(SubscriptionForm, self).__init__(*args, **kwargs)
notify_edit = forms.BooleanField(required=False, label=_(u'Notify me on article edits')) edit = forms.BooleanField(required=False, label=_(u'When this article is edited'))
receive_email = forms.BooleanField(required=False, label=_(u'Notify me directly by email')) edit_email = forms.BooleanField(required=False, label=_(u'Also receive emails about article edits'),
widget=forms.CheckboxInput(attrs={'onclick': mark_safe("$('#id_edit').attr('checked', $(this).is(':checked'));")}))
def get_usermessage(self):
if self.changed_data:
return _('Your notification settings were updated.')
else:
return _('Your notification settings were unchanged, so nothing saved.')
def save(self, *args, **kwargs):
cd = self.cleaned_data
if not self.changed_data:
return
if cd['edit']:
edit_notification = models.ArticleSubscription.objects.get_or_create(settings=self.settings,
article=self.article,
notification_type=self.notification_type)[0]
edit_notification.send_emails = cd['edit_email']
edit_notification.save()
else:
self.edit_notifications.delete()
...@@ -3,10 +3,12 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -3,10 +3,12 @@ from django.utils.translation import ugettext_lazy as _
from wiki.models import pluginbase from wiki.models import pluginbase
NOTIFICATION_ARTICLE_EDIT = 'article_edit'
class ArticleSubscription(pluginbase.ArticlePlugin, Subscription): class ArticleSubscription(pluginbase.ArticlePlugin, Subscription):
def __unicode__(self): def __unicode__(self):
return (_(u"%(user)s subscribing to %(article)s (%(type)s)") % return (_(u"%(user)s subscribing to %(article)s (%(type)s)") %
{'user': self.user.username, {'user': self.settings.user.username,
'article': self.article.current_revision.title, 'article': self.article.current_revision.title,
'type': self.notification_type.label}) 'type': self.notification_type.label})
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
<div class="tab-content"> <div class="tab-content">
{% for form in forms %} {% for form in forms %}
<form method="POST" class="form-horizontal" id="settings_form"> <form method="POST" class="form-horizontal" id="settings_form" action="?f={{form.action}}">
<h2>{{ form.settings_form_headline }}</h2> <h2>{{ form.settings_form_headline }}</h2>
<div class="well"> <div class="well">
{% wiki_form form %} {% wiki_form form %}
</div> </div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" name="save" value="1" class="btn btn-large btn-primary" onclick="this.form.target=''; this.form.action='{% url 'wiki:edit_url' urlpath.path %}'"> <button type="submit" name="save" value="1" class="btn btn-large btn-primary">
<span class="icon-ok"></span> <span class="icon-ok"></span>
{% trans "Save changes" %} {% trans "Save changes" %}
</button> </button>
......
...@@ -166,24 +166,48 @@ class Settings(TemplateView): ...@@ -166,24 +166,48 @@ class Settings(TemplateView):
self.article = article self.article = article
return super(Settings, self).dispatch(request, *args, **kwargs) return super(Settings, self).dispatch(request, *args, **kwargs)
def get_forms(self,): def get_form_classes(self,):
""" """
Return all settings forms that can be filled in Return all settings forms that can be filled in
""" """
settings_forms = plugins_registry._settings_forms settings_forms = [F for F in plugins_registry._settings_forms]
if (self.request.user and self.request.user.is_superuser or if (self.request.user and self.request.user.is_superuser or
self.article.owner == self.request.user): self.article.owner == self.request.user):
settings_forms.append(self.permission_form_class) settings_forms.append(self.permission_form_class)
settings_forms.sort(key=lambda form: form.settings_order) settings_forms.sort(key=lambda form: form.settings_order)
for i in range(len(settings_forms)):
setattr(settings_forms[i], 'action', 'form%d' % i)
return settings_forms return settings_forms
def post(self, *args, **kwargs):
self.forms = []
for Form in self.get_form_classes():
if Form.action == self.request.GET.get('f', None):
form = Form(self.article, self.request.user,self.request.POST)
if form.is_valid():
form.save()
usermessage = form.get_usermessage()
if usermessage:
messages.success(self.request, usermessage)
return redirect('wiki:settings_url', self.urlpath.path)
else:
form = Form(self.article, self.request.user)
self.forms.append(form)
return super(Settings, self).get(*args, **kwargs)
def get(self, *args, **kwargs):
self.forms = []
for Form in self.get_form_classes():
self.forms.append(Form(self.article, self.request.user))
return super(Settings, self).get(*args, **kwargs)
def get_success_url(self): def get_success_url(self):
return redirect('wiki:settings_url', self.urlpath.path) return redirect('wiki:settings_url', self.urlpath.path)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['urlpath'] = self.urlpath kwargs['urlpath'] = self.urlpath
kwargs['article'] = self.article kwargs['article'] = self.article
kwargs['forms'] = [F(self.article) for F in self.get_forms()] kwargs['forms'] = self.forms
return kwargs return kwargs
class History(ListView): class History(ListView):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment