]> git.openstreetmap.org Git - osqa.git/blob - forum/views/admin.py
New optional admin interface, and closing OSQA 253.
[osqa.git] / forum / views / admin.py
1 from datetime import datetime, timedelta
2 import time
3
4 from django.shortcuts import render_to_response
5 from django.core.urlresolvers import reverse
6 from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
7 from django.template import RequestContext
8 from django.utils.translation import ugettext as _
9 from django.utils import simplejson
10 from django.db.models import Sum
11
12 from forum.settings.base import Setting
13 from forum.settings.forms import SettingsSetForm
14
15 from forum.models import Question, Answer, User, Node, Action
16 from forum import settings
17
18 def super_user_required(fn):
19     def wrapper(request, *args, **kwargs):
20         if request.user.is_authenticated() and request.user.is_superuser:
21             return fn(request, *args, **kwargs)
22         else:
23             return HttpResponseForbidden()
24
25     return wrapper
26
27 def admin_page(fn):
28     @super_user_required
29     def wrapper(request, *args, **kwargs):
30         res = fn(request, *args, **kwargs)
31         if isinstance(res, tuple):
32             template, context = res
33             context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
34             context['allsets'] = Setting.sets
35             context['othersets'] = sorted(
36                     [s for s in Setting.sets.values() if not s.name in
37                     ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'badges', 'about', 'faq', 'sidebar',
38                     'form', 'moderation')]
39                     , lambda s1, s2: s1.weight - s2.weight)
40             return render_to_response(template, context, context_instance=RequestContext(request))
41         else:
42             return res
43
44     return wrapper
45
46 @admin_page
47 def dashboard(request):
48     return ('osqaadmin/dashboard.html', {
49         'settings_pack': unicode(settings.SETTINGS_PACK),
50         'statistics': get_statistics(),
51         'recent_activity': get_recent_activity(),
52     })
53
54 @super_user_required
55 def interface_switch(request):
56     if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
57         settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
58
59     return HttpResponseRedirect(reverse('admin_index'))
60
61 @admin_page
62 def statistics(request):
63     today = datetime.now()
64     last_month = today - timedelta(days=30)
65
66     last_month_questions = Question.objects.filter(deleted=None, added_at__gt=last_month
67                                                   ).order_by('added_at').values_list('added_at', flat=True)
68
69     last_month_n_questions = Question.objects.filter(deleted=None, added_at__lt=last_month).count()
70     qgraph_data = simplejson.dumps([
71             (time.mktime(d.timetuple()) * 1000, i + last_month_n_questions)
72             for i, d in enumerate(last_month_questions)
73     ])
74
75     last_month_users = User.objects.filter(date_joined__gt=last_month
76                                                   ).order_by('date_joined').values_list('date_joined', flat=True)
77
78     last_month_n_users = User.objects.filter(date_joined__lt=last_month).count()
79
80     ugraph_data = simplejson.dumps([
81             (time.mktime(d.timetuple()) * 1000, i + last_month_n_users)
82             for i, d in enumerate(last_month_users)
83     ])
84
85     return 'osqaadmin/statistics.html', {
86         'graphs': [
87             {
88                 'id': 'questions_graph',
89                 'caption': _("Questions Graph"),
90                 'data': qgraph_data
91             },{
92                 'id': 'userss_graph',
93                 'caption': _("Users Graph"),
94                 'data': ugraph_data
95             }
96         ]
97     }
98
99
100 @admin_page
101 def settings_set(request, set_name):
102     set = Setting.sets.get(set_name, None)
103
104     if set is None:
105         raise Http404
106
107     if request.POST:
108         form = SettingsSetForm(set, data=request.POST, files=request.FILES)
109
110         if form.is_valid():
111             form.save()
112             request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
113
114             if set_name in ('minrep', 'badges', 'repgain'):
115                 settings.SETTINGS_PACK.set_value("custom")
116
117         return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
118     else:
119         form = SettingsSetForm(set)
120
121     return 'osqaadmin/set.html', {
122         'form': form,
123         'markdown': set.markdown,
124     }
125
126
127 def get_recent_activity():
128     return Action.objects.order_by('-action_date')[0:30]
129
130 def get_statistics():
131     return {
132         'total_users': User.objects.all().count(),
133         'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
134         'total_questions': Question.objects.filter(deleted=None).count(),
135         'questions_last_24': Question.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
136         'total_answers': Answer.objects.filter(deleted=None).count(),
137         'answers_last_24': Answer.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
138     }
139
140 @super_user_required
141 def go_bootstrap(request):
142     #todo: this is the quick and dirty way of implementing a bootstrap mode
143     try:
144         from forum_modules.default_badges import settings as dbsets
145         dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
146         dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
147         dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
148         dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
149         dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
150         dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
151         dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
152         dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
153         dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
154         dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
155         dbsets.STELLAR_QUESTION_FAVS.set_value(3)
156         dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
157         dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
158         dbsets.CIVIC_DUTY_VOTES.set_value(15)
159         dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
160         dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
161         dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
162         dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
163         dbsets.GURU_UP_VOTES.set_value(4)
164         dbsets.NECROMANCER_UP_VOTES.set_value(2)
165         dbsets.NECROMANCER_DIF_DAYS.set_value(30)
166         dbsets.TAXONOMIST_USE_COUNT.set_value(5)
167     except:
168         pass
169
170     settings.REP_TO_VOTE_UP.set_value(0)
171     settings.REP_TO_VOTE_DOWN.set_value(15)
172     settings.REP_TO_FLAG.set_value(15)
173     settings.REP_TO_COMMENT.set_value(0)
174     settings.REP_TO_LIKE_COMMENT.set_value(0)
175     settings.REP_TO_UPLOAD.set_value(0)
176     settings.REP_TO_CLOSE_OWN.set_value(60)
177     settings.REP_TO_REOPEN_OWN.set_value(120)
178     settings.REP_TO_RETAG.set_value(150)
179     settings.REP_TO_EDIT_WIKI.set_value(200)
180     settings.REP_TO_EDIT_OTHERS.set_value(400)
181     settings.REP_TO_CLOSE_OTHERS.set_value(600)
182     settings.REP_TO_DELETE_COMMENTS.set_value(400)
183     settings.REP_TO_VIEW_FLAGS.set_value(30)
184
185     settings.INITIAL_REP.set_value(1)
186     settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
187     settings.REP_GAIN_BY_UPVOTED.set_value(15)
188     settings.REP_LOST_BY_UPVOTE_CANCELED.set_value(15)
189     settings.REP_LOST_BY_DOWNVOTED.set_value(1)
190     settings.REP_LOST_BY_DOWNVOTING.set_value(0)
191     settings.REP_GAIN_BY_DOWNVOTE_CANCELED.set_value(1)
192     settings.REP_GAIN_BY_CANCELING_DOWNVOTE.set_value(0)
193     settings.REP_GAIN_BY_ACCEPTED.set_value(25)
194     settings.REP_LOST_BY_ACCEPTED_CANCELED.set_value(25)
195     settings.REP_GAIN_BY_ACCEPTING.set_value(5)
196     settings.REP_LOST_BY_CANCELING_ACCEPTED.set_value(5)
197     settings.REP_LOST_BY_FLAGGED.set_value(2)
198     settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
199     settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
200
201     settings.SETTINGS_PACK.set_value("bootstrap")
202
203     request.user.message_set.create(message=_('Bootstrap mode enabled'))
204     return HttpResponseRedirect(reverse('admin_index'))
205
206 @super_user_required
207 def go_defaults(request):
208     for setting in Setting.sets['badges']:
209         setting.to_default()
210     for setting in Setting.sets['minrep']:
211         setting.to_default()
212     for setting in Setting.sets['repgain']:
213         setting.to_default()
214
215     settings.SETTINGS_PACK.set_value("default")
216
217     request.user.message_set.create(message=_('All values reverted to defaults'))
218     return HttpResponseRedirect(reverse('admin_index'))
219
220
221 @super_user_required
222 def recalculate_denormalized(request):
223     for n in Node.objects.all():
224         n = n.leaf
225         n.score = n.votes.aggregate(score=Sum('value'))['score']
226         if not n.score: n.score = 0
227         n.save()
228
229     for u in User.objects.all():
230         u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
231         u.save()
232
233     request.user.message_set.create(message=_('All values recalculated'))
234     return HttpResponseRedirect(reverse('admin_index'))
235