]> git.openstreetmap.org Git - osqa.git/blob - forum/views/admin.py
Closing OSQA 201, Add a "site maintenance" switch and page.
[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, MaintenanceModeForm
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 @super_user_required
127 def get_default(request, set_name, var_name):
128     set = Setting.sets.get(set_name, None)
129     if set is None: raise Http404
130
131     setting = dict([(s.name, s) for s in set]).get(var_name, None)
132     if setting is None: raise Http404
133
134     setting.to_default()
135
136     if request.is_ajax():
137         return HttpResponse(setting.default)
138     else:
139         return HttpResponseRedirect(reverse('admin_set', kwargs={'set_name': set_name}))
140
141
142 def get_recent_activity():
143     return Action.objects.order_by('-action_date')[0:30]
144
145 def get_statistics():
146     return {
147         'total_users': User.objects.all().count(),
148         'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
149         'total_questions': Question.objects.filter(deleted=None).count(),
150         'questions_last_24': Question.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
151         'total_answers': Answer.objects.filter(deleted=None).count(),
152         'answers_last_24': Answer.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
153     }
154
155 @super_user_required
156 def go_bootstrap(request):
157     #todo: this is the quick and dirty way of implementing a bootstrap mode
158     try:
159         from forum_modules.default_badges import settings as dbsets
160         dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
161         dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
162         dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
163         dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
164         dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
165         dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
166         dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
167         dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
168         dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
169         dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
170         dbsets.STELLAR_QUESTION_FAVS.set_value(3)
171         dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
172         dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
173         dbsets.CIVIC_DUTY_VOTES.set_value(15)
174         dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
175         dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
176         dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
177         dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
178         dbsets.GURU_UP_VOTES.set_value(4)
179         dbsets.NECROMANCER_UP_VOTES.set_value(2)
180         dbsets.NECROMANCER_DIF_DAYS.set_value(30)
181         dbsets.TAXONOMIST_USE_COUNT.set_value(5)
182     except:
183         pass
184
185     settings.REP_TO_VOTE_UP.set_value(0)
186     settings.REP_TO_VOTE_DOWN.set_value(15)
187     settings.REP_TO_FLAG.set_value(15)
188     settings.REP_TO_COMMENT.set_value(0)
189     settings.REP_TO_LIKE_COMMENT.set_value(0)
190     settings.REP_TO_UPLOAD.set_value(0)
191     settings.REP_TO_CLOSE_OWN.set_value(60)
192     settings.REP_TO_REOPEN_OWN.set_value(120)
193     settings.REP_TO_RETAG.set_value(150)
194     settings.REP_TO_EDIT_WIKI.set_value(200)
195     settings.REP_TO_EDIT_OTHERS.set_value(400)
196     settings.REP_TO_CLOSE_OTHERS.set_value(600)
197     settings.REP_TO_DELETE_COMMENTS.set_value(400)
198     settings.REP_TO_VIEW_FLAGS.set_value(30)
199
200     settings.INITIAL_REP.set_value(1)
201     settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
202     settings.REP_GAIN_BY_UPVOTED.set_value(15)
203     settings.REP_LOST_BY_DOWNVOTED.set_value(1)
204     settings.REP_LOST_BY_DOWNVOTING.set_value(0)
205     settings.REP_GAIN_BY_ACCEPTED.set_value(25)
206     settings.REP_GAIN_BY_ACCEPTING.set_value(5)
207     settings.REP_LOST_BY_FLAGGED.set_value(2)
208     settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
209     settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
210
211     settings.SETTINGS_PACK.set_value("bootstrap")
212
213     request.user.message_set.create(message=_('Bootstrap mode enabled'))
214     return HttpResponseRedirect(reverse('admin_index'))
215
216 @super_user_required
217 def go_defaults(request):
218     for setting in Setting.sets['badges']:
219         setting.to_default()
220     for setting in Setting.sets['minrep']:
221         setting.to_default()
222     for setting in Setting.sets['repgain']:
223         setting.to_default()
224
225     settings.SETTINGS_PACK.set_value("default")
226
227     request.user.message_set.create(message=_('All values reverted to defaults'))
228     return HttpResponseRedirect(reverse('admin_index'))
229
230
231 @super_user_required
232 def recalculate_denormalized(request):
233     for n in Node.objects.all():
234         n = n.leaf
235         n.score = n.votes.aggregate(score=Sum('value'))['score']
236         if not n.score: n.score = 0
237         n.save()
238
239     for u in User.objects.all():
240         u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
241         u.save()
242
243     request.user.message_set.create(message=_('All values recalculated'))
244     return HttpResponseRedirect(reverse('admin_index'))
245
246 @admin_page
247 def maintenance(request):
248     if request.POST:
249         if 'close' in request.POST or 'adjust' in request.POST:
250             form = MaintenanceModeForm(request.POST)
251
252             if form.is_valid():
253                 settings.MAINTAINANCE_MODE.set_value({
254                     'allow_ips': form.cleaned_data['ips'],
255                     'message': form.cleaned_data['message']})
256
257                 if 'close' in request.POST:
258                     message = _('Maintenance mode enabled')
259                 else:
260                     message = _('Settings adjusted')
261
262                 request.user.message_set.create(message=message)
263
264                 return HttpResponseRedirect(reverse('admin_maintenance'))
265         elif 'open' in request.POST:
266             settings.MAINTAINANCE_MODE.set_value(None)
267             request.user.message_set.create(message=_("Your site is now running normally"))
268             return HttpResponseRedirect(reverse('admin_maintenance'))
269     else:
270         form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
271                                             'message': _('Currently down for maintenance. We\'ll be back soon')})
272
273     return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
274
275