1 from datetime import datetime, timedelta
4 from django.shortcuts import render_to_response, get_object_or_404
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 from forum.settings.base import Setting
12 from forum.forms import MaintenanceModeForm, PageForm
13 from forum.settings.forms import SettingsSetForm
15 from forum.models import Question, Answer, User, Node, Action, Page
16 from forum.actions import NewPageAction, EditPageAction, PublishAction
17 from forum import settings
19 def super_user_required(fn):
20 def wrapper(request, *args, **kwargs):
21 if request.user.is_authenticated() and request.user.is_superuser:
22 return fn(request, *args, **kwargs)
24 return HttpResponseForbidden()
30 def wrapper(request, *args, **kwargs):
31 res = fn(request, *args, **kwargs)
32 if isinstance(res, tuple):
33 template, context = res
34 context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
35 context['allsets'] = Setting.sets
36 context['othersets'] = sorted(
37 [s for s in Setting.sets.values() if not s.name in
38 ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'badges', 'about', 'faq', 'sidebar',
39 'form', 'moderation', 'css', 'headandfoot', 'head')]
40 , lambda s1, s2: s1.weight - s2.weight)
42 unsaved = request.session.get('previewing_settings', {})
43 context['unsaved'] = set([getattr(settings, s).set.name for s in unsaved.keys() if hasattr(settings, s)])
45 return render_to_response(template, context, context_instance=RequestContext(request))
52 def dashboard(request):
53 return ('osqaadmin/dashboard.html', {
54 'settings_pack': unicode(settings.SETTINGS_PACK),
55 'statistics': get_statistics(),
56 'recent_activity': get_recent_activity(),
57 'flagged_posts': get_flagged_posts(),
61 def interface_switch(request):
62 if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
63 settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
65 return HttpResponseRedirect(reverse('admin_index'))
68 def statistics(request):
69 today = datetime.now()
70 last_month = today - timedelta(days=30)
72 last_month_questions = Question.objects.filter_state(deleted=False).filter(added_at__gt=last_month
73 ).order_by('added_at').values_list(
74 'added_at', flat=True)
76 last_month_n_questions = Question.objects.filter_state(deleted=False).filter(added_at__lt=last_month).count()
77 qgraph_data = simplejson.dumps([
78 (time.mktime(d.timetuple()) * 1000, i + last_month_n_questions)
79 for i, d in enumerate(last_month_questions)
82 last_month_users = User.objects.filter(date_joined__gt=last_month
83 ).order_by('date_joined').values_list('date_joined', flat=True)
85 last_month_n_users = User.objects.filter(date_joined__lt=last_month).count()
87 ugraph_data = simplejson.dumps([
88 (time.mktime(d.timetuple()) * 1000, i + last_month_n_users)
89 for i, d in enumerate(last_month_users)
92 return 'osqaadmin/statistics.html', {
95 'id': 'questions_graph',
96 'caption': _("Questions Graph"),
100 'caption': _("Users Graph"),
108 def settings_set(request, set_name):
109 set = Setting.sets.get(set_name, {})
110 current_preview = request.session.get('previewing_settings', {})
116 form = SettingsSetForm(set, data=request.POST, files=request.FILES)
119 if 'preview' in request.POST:
120 current_preview.update(form.cleaned_data)
121 request.session['previewing_settings'] = current_preview
123 return HttpResponseRedirect(reverse('index'))
126 current_preview.pop(s.name, None)
128 request.session['previewing_settings'] = current_preview
130 if not 'reset' in request.POST:
132 request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
134 if set_name in ('minrep', 'badges', 'repgain'):
135 settings.SETTINGS_PACK.set_value("custom")
137 return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
139 form = SettingsSetForm(set, unsaved=current_preview)
141 return 'osqaadmin/set.html', {
143 'markdown': set.markdown,
147 def get_default(request, set_name, var_name):
148 set = Setting.sets.get(set_name, None)
149 if set is None: raise Http404
151 setting = dict([(s.name, s) for s in set]).get(var_name, None)
152 if setting is None: raise Http404
156 if request.is_ajax():
157 return HttpResponse(setting.default)
159 return HttpResponseRedirect(reverse('admin_set', kwargs={'set_name': set_name}))
162 def get_recent_activity():
163 return Action.objects.order_by('-action_date')[0:30]
165 def get_flagged_posts():
166 return Action.objects.filter(canceled=False, action_type="flag").order_by('-action_date')[0:30]
168 def get_statistics():
170 'total_users': User.objects.all().count(),
171 'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
172 'total_questions': Question.objects.filter_state(deleted=False).count(),
173 'questions_last_24': Question.objects.filter_state(deleted=False).filter(
174 added_at__gt=(datetime.now() - timedelta(days=1))).count(),
175 'total_answers': Answer.objects.filter_state(deleted=False).count(),
176 'answers_last_24': Answer.objects.filter_state(deleted=False).filter(
177 added_at__gt=(datetime.now() - timedelta(days=1))).count(),
181 def go_bootstrap(request):
182 #todo: this is the quick and dirty way of implementing a bootstrap mode
184 from forum_modules.default_badges import settings as dbsets
185 dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
186 dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
187 dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
188 dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
189 dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
190 dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
191 dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
192 dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
193 dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
194 dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
195 dbsets.STELLAR_QUESTION_FAVS.set_value(3)
196 dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
197 dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
198 dbsets.CIVIC_DUTY_VOTES.set_value(15)
199 dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
200 dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
201 dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
202 dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
203 dbsets.GURU_UP_VOTES.set_value(4)
204 dbsets.NECROMANCER_UP_VOTES.set_value(2)
205 dbsets.NECROMANCER_DIF_DAYS.set_value(30)
206 dbsets.TAXONOMIST_USE_COUNT.set_value(5)
210 settings.REP_TO_VOTE_UP.set_value(0)
211 settings.REP_TO_VOTE_DOWN.set_value(15)
212 settings.REP_TO_FLAG.set_value(15)
213 settings.REP_TO_COMMENT.set_value(0)
214 settings.REP_TO_LIKE_COMMENT.set_value(0)
215 settings.REP_TO_UPLOAD.set_value(0)
216 settings.REP_TO_CREATE_TAGS.set_value(0)
217 settings.REP_TO_CLOSE_OWN.set_value(60)
218 settings.REP_TO_REOPEN_OWN.set_value(120)
219 settings.REP_TO_RETAG.set_value(150)
220 settings.REP_TO_EDIT_WIKI.set_value(200)
221 settings.REP_TO_EDIT_OTHERS.set_value(400)
222 settings.REP_TO_CLOSE_OTHERS.set_value(600)
223 settings.REP_TO_DELETE_COMMENTS.set_value(400)
224 settings.REP_TO_VIEW_FLAGS.set_value(30)
226 settings.INITIAL_REP.set_value(1)
227 settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
228 settings.REP_GAIN_BY_UPVOTED.set_value(15)
229 settings.REP_LOST_BY_DOWNVOTED.set_value(1)
230 settings.REP_LOST_BY_DOWNVOTING.set_value(0)
231 settings.REP_GAIN_BY_ACCEPTED.set_value(25)
232 settings.REP_GAIN_BY_ACCEPTING.set_value(5)
233 settings.REP_LOST_BY_FLAGGED.set_value(2)
234 settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
235 settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
237 settings.SETTINGS_PACK.set_value("bootstrap")
239 request.user.message_set.create(message=_('Bootstrap mode enabled'))
240 return HttpResponseRedirect(reverse('admin_index'))
243 def go_defaults(request):
244 for setting in Setting.sets['badges']:
246 for setting in Setting.sets['minrep']:
248 for setting in Setting.sets['repgain']:
251 settings.SETTINGS_PACK.set_value("default")
253 request.user.message_set.create(message=_('All values reverted to defaults'))
254 return HttpResponseRedirect(reverse('admin_index'))
258 def recalculate_denormalized(request):
259 for n in Node.objects.all():
261 n.score = n.votes.aggregate(score=Sum('value'))['score']
262 if not n.score: n.score = 0
265 for u in User.objects.all():
266 u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
269 request.user.message_set.create(message=_('All values recalculated'))
270 return HttpResponseRedirect(reverse('admin_index'))
273 def maintenance(request):
275 if 'close' in request.POST or 'adjust' in request.POST:
276 form = MaintenanceModeForm(request.POST)
279 settings.MAINTAINANCE_MODE.set_value({
280 'allow_ips': form.cleaned_data['ips'],
281 'message': form.cleaned_data['message']})
283 if 'close' in request.POST:
284 message = _('Maintenance mode enabled')
286 message = _('Settings adjusted')
288 request.user.message_set.create(message=message)
290 return HttpResponseRedirect(reverse('admin_maintenance'))
291 elif 'open' in request.POST:
292 settings.MAINTAINANCE_MODE.set_value(None)
293 request.user.message_set.create(message=_("Your site is now running normally"))
294 return HttpResponseRedirect(reverse('admin_maintenance'))
296 form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
297 'message': _('Currently down for maintenance. We\'ll be back soon')})
299 return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None
304 def flagged_posts(request):
305 return ('osqaadmin/flagged_posts.html', {
306 'flagged_posts': get_flagged_posts(),
310 def static_pages(request):
311 pages = Page.objects.all()
313 return ('osqaadmin/static_pages.html', {
318 def edit_page(request, id=None):
320 page = get_object_or_404(Page, id=id)
325 form = PageForm(page, request.POST)
328 if form.has_changed():
330 page = NewPageAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data
333 EditPageAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save(
334 data=form.cleaned_data)
336 if ('publish' in request.POST) and (not page.published):
337 PublishAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save()
338 elif ('unpublish' in request.POST) and page.published:
339 page.nstate.published.cancel(ip=request.META['REMOTE_ADDR'])
341 return HttpResponseRedirect(reverse('admin_edit_page', kwargs={'id': page.id}))
344 form = PageForm(page)
347 published = page.published
351 return ('osqaadmin/edit_page.html', {
354 'published': published