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')]
40 , lambda s1, s2: s1.weight - s2.weight)
41 return render_to_response(template, context, context_instance=RequestContext(request))
48 def dashboard(request):
49 return ('osqaadmin/dashboard.html', {
50 'settings_pack': unicode(settings.SETTINGS_PACK),
51 'statistics': get_statistics(),
52 'recent_activity': get_recent_activity(),
53 'flagged_posts': get_flagged_posts(),
57 def interface_switch(request):
58 if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
59 settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
61 return HttpResponseRedirect(reverse('admin_index'))
64 def statistics(request):
65 today = datetime.now()
66 last_month = today - timedelta(days=30)
68 last_month_questions = Question.objects.filter_state(deleted=False).filter(added_at__gt=last_month
69 ).order_by('added_at').values_list('added_at', flat=True)
71 last_month_n_questions = Question.objects.filter_state(deleted=False).filter(added_at__lt=last_month).count()
72 qgraph_data = simplejson.dumps([
73 (time.mktime(d.timetuple()) * 1000, i + last_month_n_questions)
74 for i, d in enumerate(last_month_questions)
77 last_month_users = User.objects.filter(date_joined__gt=last_month
78 ).order_by('date_joined').values_list('date_joined', flat=True)
80 last_month_n_users = User.objects.filter(date_joined__lt=last_month).count()
82 ugraph_data = simplejson.dumps([
83 (time.mktime(d.timetuple()) * 1000, i + last_month_n_users)
84 for i, d in enumerate(last_month_users)
87 return 'osqaadmin/statistics.html', {
90 'id': 'questions_graph',
91 'caption': _("Questions Graph"),
95 'caption': _("Users Graph"),
103 def settings_set(request, set_name):
104 set = Setting.sets.get(set_name, None)
110 form = SettingsSetForm(set, data=request.POST, files=request.FILES)
114 request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
116 if set_name in ('minrep', 'badges', 'repgain'):
117 settings.SETTINGS_PACK.set_value("custom")
119 return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
121 form = SettingsSetForm(set)
123 return 'osqaadmin/set.html', {
125 'markdown': set.markdown,
129 def get_default(request, set_name, var_name):
130 set = Setting.sets.get(set_name, None)
131 if set is None: raise Http404
133 setting = dict([(s.name, s) for s in set]).get(var_name, None)
134 if setting is None: raise Http404
138 if request.is_ajax():
139 return HttpResponse(setting.default)
141 return HttpResponseRedirect(reverse('admin_set', kwargs={'set_name': set_name}))
144 def get_recent_activity():
145 return Action.objects.order_by('-action_date')[0:30]
147 def get_flagged_posts():
148 return Action.objects.filter(canceled=False, action_type="flag").order_by('-action_date')[0:30]
150 def get_statistics():
152 'total_users': User.objects.all().count(),
153 'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
154 'total_questions': Question.objects.filter_state(deleted=False).count(),
155 'questions_last_24': Question.objects.filter_state(deleted=False).filter(added_at__gt=(datetime.now() - timedelta(days=1))).count(),
156 'total_answers': Answer.objects.filter_state(deleted=False).count(),
157 'answers_last_24': Answer.objects.filter_state(deleted=False).filter(added_at__gt=(datetime.now() - timedelta(days=1))).count(),
161 def go_bootstrap(request):
162 #todo: this is the quick and dirty way of implementing a bootstrap mode
164 from forum_modules.default_badges import settings as dbsets
165 dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
166 dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
167 dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
168 dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
169 dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
170 dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
171 dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
172 dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
173 dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
174 dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
175 dbsets.STELLAR_QUESTION_FAVS.set_value(3)
176 dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
177 dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
178 dbsets.CIVIC_DUTY_VOTES.set_value(15)
179 dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
180 dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
181 dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
182 dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
183 dbsets.GURU_UP_VOTES.set_value(4)
184 dbsets.NECROMANCER_UP_VOTES.set_value(2)
185 dbsets.NECROMANCER_DIF_DAYS.set_value(30)
186 dbsets.TAXONOMIST_USE_COUNT.set_value(5)
190 settings.REP_TO_VOTE_UP.set_value(0)
191 settings.REP_TO_VOTE_DOWN.set_value(15)
192 settings.REP_TO_FLAG.set_value(15)
193 settings.REP_TO_COMMENT.set_value(0)
194 settings.REP_TO_LIKE_COMMENT.set_value(0)
195 settings.REP_TO_UPLOAD.set_value(0)
196 settings.REP_TO_CREATE_TAGS.set_value(0)
197 settings.REP_TO_CLOSE_OWN.set_value(60)
198 settings.REP_TO_REOPEN_OWN.set_value(120)
199 settings.REP_TO_RETAG.set_value(150)
200 settings.REP_TO_EDIT_WIKI.set_value(200)
201 settings.REP_TO_EDIT_OTHERS.set_value(400)
202 settings.REP_TO_CLOSE_OTHERS.set_value(600)
203 settings.REP_TO_DELETE_COMMENTS.set_value(400)
204 settings.REP_TO_VIEW_FLAGS.set_value(30)
206 settings.INITIAL_REP.set_value(1)
207 settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
208 settings.REP_GAIN_BY_UPVOTED.set_value(15)
209 settings.REP_LOST_BY_DOWNVOTED.set_value(1)
210 settings.REP_LOST_BY_DOWNVOTING.set_value(0)
211 settings.REP_GAIN_BY_ACCEPTED.set_value(25)
212 settings.REP_GAIN_BY_ACCEPTING.set_value(5)
213 settings.REP_LOST_BY_FLAGGED.set_value(2)
214 settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
215 settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
217 settings.SETTINGS_PACK.set_value("bootstrap")
219 request.user.message_set.create(message=_('Bootstrap mode enabled'))
220 return HttpResponseRedirect(reverse('admin_index'))
223 def go_defaults(request):
224 for setting in Setting.sets['badges']:
226 for setting in Setting.sets['minrep']:
228 for setting in Setting.sets['repgain']:
231 settings.SETTINGS_PACK.set_value("default")
233 request.user.message_set.create(message=_('All values reverted to defaults'))
234 return HttpResponseRedirect(reverse('admin_index'))
238 def recalculate_denormalized(request):
239 for n in Node.objects.all():
241 n.score = n.votes.aggregate(score=Sum('value'))['score']
242 if not n.score: n.score = 0
245 for u in User.objects.all():
246 u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
249 request.user.message_set.create(message=_('All values recalculated'))
250 return HttpResponseRedirect(reverse('admin_index'))
253 def maintenance(request):
255 if 'close' in request.POST or 'adjust' in request.POST:
256 form = MaintenanceModeForm(request.POST)
259 settings.MAINTAINANCE_MODE.set_value({
260 'allow_ips': form.cleaned_data['ips'],
261 'message': form.cleaned_data['message']})
263 if 'close' in request.POST:
264 message = _('Maintenance mode enabled')
266 message = _('Settings adjusted')
268 request.user.message_set.create(message=message)
270 return HttpResponseRedirect(reverse('admin_maintenance'))
271 elif 'open' in request.POST:
272 settings.MAINTAINANCE_MODE.set_value(None)
273 request.user.message_set.create(message=_("Your site is now running normally"))
274 return HttpResponseRedirect(reverse('admin_maintenance'))
276 form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
277 'message': _('Currently down for maintenance. We\'ll be back soon')})
279 return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
283 def flagged_posts(request):
284 return ('osqaadmin/flagged_posts.html', {
285 'flagged_posts': get_flagged_posts(),
289 def static_pages(request):
290 pages = Page.objects.all()
292 return ('osqaadmin/static_pages.html', {
297 def edit_page(request, id=None):
299 page = get_object_or_404(Page, id=id)
304 form = PageForm(page, request.POST)
307 if form.has_changed():
309 page = NewPageAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data).node
311 EditPageAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
313 if ('publish' in request.POST) and (not page.published):
314 PublishAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save()
315 elif ('unpublish' in request.POST) and page.published:
316 page.nstate.published.cancel(ip=request.META['REMOTE_ADDR'])
318 return HttpResponseRedirect(reverse('admin_edit_page', kwargs={'id': page.id}))
321 form = PageForm(page)
324 published = page.published
328 return ('osqaadmin/edit_page.html', {
331 'published': published