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')]
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)])
46 return render_to_response(template, context, context_instance=RequestContext(request))
53 def dashboard(request):
54 return ('osqaadmin/dashboard.html', {
55 'settings_pack': unicode(settings.SETTINGS_PACK),
56 'statistics': get_statistics(),
57 'recent_activity': get_recent_activity(),
58 'flagged_posts': get_flagged_posts(),
62 def interface_switch(request):
63 if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
64 settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
66 return HttpResponseRedirect(reverse('admin_index'))
69 def statistics(request):
70 today = datetime.now()
71 last_month = today - timedelta(days=30)
73 last_month_questions = Question.objects.filter_state(deleted=False).filter(added_at__gt=last_month
74 ).order_by('added_at').values_list('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(added_at__gt=(datetime.now() - timedelta(days=1))).count(),
174 'total_answers': Answer.objects.filter_state(deleted=False).count(),
175 'answers_last_24': Answer.objects.filter_state(deleted=False).filter(added_at__gt=(datetime.now() - timedelta(days=1))).count(),
179 def go_bootstrap(request):
180 #todo: this is the quick and dirty way of implementing a bootstrap mode
182 from forum_modules.default_badges import settings as dbsets
183 dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
184 dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
185 dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
186 dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
187 dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
188 dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
189 dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
190 dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
191 dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
192 dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
193 dbsets.STELLAR_QUESTION_FAVS.set_value(3)
194 dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
195 dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
196 dbsets.CIVIC_DUTY_VOTES.set_value(15)
197 dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
198 dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
199 dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
200 dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
201 dbsets.GURU_UP_VOTES.set_value(4)
202 dbsets.NECROMANCER_UP_VOTES.set_value(2)
203 dbsets.NECROMANCER_DIF_DAYS.set_value(30)
204 dbsets.TAXONOMIST_USE_COUNT.set_value(5)
208 settings.REP_TO_VOTE_UP.set_value(0)
209 settings.REP_TO_VOTE_DOWN.set_value(15)
210 settings.REP_TO_FLAG.set_value(15)
211 settings.REP_TO_COMMENT.set_value(0)
212 settings.REP_TO_LIKE_COMMENT.set_value(0)
213 settings.REP_TO_UPLOAD.set_value(0)
214 settings.REP_TO_CREATE_TAGS.set_value(0)
215 settings.REP_TO_CLOSE_OWN.set_value(60)
216 settings.REP_TO_REOPEN_OWN.set_value(120)
217 settings.REP_TO_RETAG.set_value(150)
218 settings.REP_TO_EDIT_WIKI.set_value(200)
219 settings.REP_TO_EDIT_OTHERS.set_value(400)
220 settings.REP_TO_CLOSE_OTHERS.set_value(600)
221 settings.REP_TO_DELETE_COMMENTS.set_value(400)
222 settings.REP_TO_VIEW_FLAGS.set_value(30)
224 settings.INITIAL_REP.set_value(1)
225 settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
226 settings.REP_GAIN_BY_UPVOTED.set_value(15)
227 settings.REP_LOST_BY_DOWNVOTED.set_value(1)
228 settings.REP_LOST_BY_DOWNVOTING.set_value(0)
229 settings.REP_GAIN_BY_ACCEPTED.set_value(25)
230 settings.REP_GAIN_BY_ACCEPTING.set_value(5)
231 settings.REP_LOST_BY_FLAGGED.set_value(2)
232 settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
233 settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
235 settings.SETTINGS_PACK.set_value("bootstrap")
237 request.user.message_set.create(message=_('Bootstrap mode enabled'))
238 return HttpResponseRedirect(reverse('admin_index'))
241 def go_defaults(request):
242 for setting in Setting.sets['badges']:
244 for setting in Setting.sets['minrep']:
246 for setting in Setting.sets['repgain']:
249 settings.SETTINGS_PACK.set_value("default")
251 request.user.message_set.create(message=_('All values reverted to defaults'))
252 return HttpResponseRedirect(reverse('admin_index'))
256 def recalculate_denormalized(request):
257 for n in Node.objects.all():
259 n.score = n.votes.aggregate(score=Sum('value'))['score']
260 if not n.score: n.score = 0
263 for u in User.objects.all():
264 u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
267 request.user.message_set.create(message=_('All values recalculated'))
268 return HttpResponseRedirect(reverse('admin_index'))
271 def maintenance(request):
273 if 'close' in request.POST or 'adjust' in request.POST:
274 form = MaintenanceModeForm(request.POST)
277 settings.MAINTAINANCE_MODE.set_value({
278 'allow_ips': form.cleaned_data['ips'],
279 'message': form.cleaned_data['message']})
281 if 'close' in request.POST:
282 message = _('Maintenance mode enabled')
284 message = _('Settings adjusted')
286 request.user.message_set.create(message=message)
288 return HttpResponseRedirect(reverse('admin_maintenance'))
289 elif 'open' in request.POST:
290 settings.MAINTAINANCE_MODE.set_value(None)
291 request.user.message_set.create(message=_("Your site is now running normally"))
292 return HttpResponseRedirect(reverse('admin_maintenance'))
294 form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
295 'message': _('Currently down for maintenance. We\'ll be back soon')})
297 return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
301 def flagged_posts(request):
302 return ('osqaadmin/flagged_posts.html', {
303 'flagged_posts': get_flagged_posts(),
307 def static_pages(request):
308 pages = Page.objects.all()
310 return ('osqaadmin/static_pages.html', {
315 def edit_page(request, id=None):
317 page = get_object_or_404(Page, id=id)
322 form = PageForm(page, request.POST)
325 if form.has_changed():
327 page = NewPageAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data).node
329 EditPageAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
331 if ('publish' in request.POST) and (not page.published):
332 PublishAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save()
333 elif ('unpublish' in request.POST) and page.published:
334 page.nstate.published.cancel(ip=request.META['REMOTE_ADDR'])
336 return HttpResponseRedirect(reverse('admin_edit_page', kwargs={'id': page.id}))
339 form = PageForm(page)
342 published = page.published
346 return ('osqaadmin/edit_page.html', {
349 'published': published