fix episode pages with existing chapters
[mygpo.git] / mygpo / admin / views.py
blob9758397c19cb412eeaa8d2e24e55179a3e78b54e
1 import re
2 from itertools import count
4 from django.shortcuts import render
5 from django.contrib import messages
6 from django.core.urlresolvers import reverse
7 from django.http import HttpResponseRedirect
8 from django.utils.translation import ugettext as _
9 from django.views.generic import TemplateView
10 from django.utils.decorators import method_decorator
12 from mygpo.admin.auth import require_staff
13 from mygpo.admin.group import PodcastGrouper
14 from mygpo.core.models import Podcast, Episode
15 from mygpo.counter import Counter
16 from mygpo.maintenance.merge import PodcastMerger, IncorrectMergeException
17 from mygpo.users.models import User
18 from mygpo.admin.clients import UserAgentStats, ClientStats
19 from mygpo.api.httpresponse import JsonResponse
22 class AdminView(TemplateView):
24 @method_decorator(require_staff)
25 def dispatch(self, *args, **kwargs):
26 return super(AdminView, self).dispatch(*args, **kwargs)
29 class Overview(AdminView):
30 template_name = 'admin/overview.html'
33 class MergeSelect(AdminView):
34 template_name = 'admin/merge-select.html'
36 def get(self, request):
37 num = int(request.GET.get('podcasts', 2))
38 urls = [''] * num
40 return self.render_to_response({
41 'urls': urls,
45 class MergeBase(AdminView):
47 def _get_podcasts(self, request):
48 podcasts = []
49 for n in count():
50 podcast_url = request.POST.get('feed%d' % n, None)
51 if podcast_url is None:
52 break
54 if not podcast_url:
55 continue
57 podcast = Podcast.for_url(podcast_url)
59 if not podcast:
60 raise InvalidPodcast(podcast_url)
62 podcasts.append(Podcast.for_url(podcast_url))
64 return podcasts
67 class MergeVerify(MergeBase):
69 template_name = 'admin/merge-grouping.html'
71 def post(self, request):
73 try:
74 podcasts = self._get_podcasts(request)
76 except InvalidPodcast as ip:
77 messages.error(request,
78 _('No podcast with URL {url}').format(url=str(ip)))
80 grouper = PodcastGrouper(podcasts)
82 get_features = lambda (e_id, e): ((e.url, e.title), e_id)
84 num_groups = grouper.group(get_features)
86 return self.render_to_response({
87 'podcasts': podcasts,
88 'groups': num_groups,
92 class MergeProcess(MergeBase):
94 RE_EPISODE = re.compile(r'episode_([0-9a-fA-F]{32})')
96 def post(self, request):
98 try:
99 podcasts = self._get_podcasts(request)
101 except InvalidPodcast as ip:
102 messages.error(request,
103 _('No podcast with URL {url}').format(url=str(ip)))
105 grouper = PodcastGrouper(podcasts)
107 features = {}
108 for key, feature in request.POST.items():
109 m = self.RE_EPISODE.match(key)
110 if m:
111 episode_id = m.group(1)
112 features[episode_id] = feature
114 get_features = lambda (e_id, e): (features[e_id], e_id)
116 num_groups = grouper.group(get_features)
118 if 'renew' in request.POST:
119 return render(request, 'admin/merge-grouping.html', {
120 'podcasts': podcasts,
121 'groups': num_groups,
125 elif 'merge' in request.POST:
127 actions = Counter()
129 try:
130 # merge podcast, reassign episodes
131 pm = PodcastMerger(podcasts, actions, num_groups)
132 pm.merge()
134 except IncorrectMergeException as ime:
135 messages.error(request, str(ime))
136 return HttpResponseRedirect(reverse('admin-merge'))
138 return render(request, 'admin/merge-finished.html', {
139 'actions': actions.items(),
140 'podcast': podcasts[0],
145 class UserAgentStatsView(AdminView):
146 template_name = 'admin/useragents.html'
148 def get(self, request):
150 uas = UserAgentStats()
151 useragents = uas.get_entries()
153 return self.render_to_response({
154 'useragents': useragents.most_common(),
155 'max_users': uas.max_users,
156 'total': uas.total_users,
160 class ClientStatsView(AdminView):
161 template_name = 'admin/clients.html'
163 def get(self, request):
165 cs = ClientStats()
166 clients = cs.get_entries()
168 return self.render_to_response({
169 'clients': clients.most_common(),
170 'max_users': cs.max_users,
171 'total': cs.total_users,
175 class ClientStatsJsonView(AdminView):
176 def get(self, request):
178 cs = ClientStats()
179 clients = cs.get_entries()
181 return JsonResponse(map(self.to_dict, clients.most_common()))
183 def to_dict(self, res):
184 obj, count = res
186 if not isinstance(obj, tuple):
187 return obj, count
189 return obj._asdict(), count
192 class StatsView(AdminView):
193 """ shows general stats as HTML page """
195 template_name = 'admin/stats.html'
197 def _get_stats(self):
198 return {
199 'podcasts': Podcast.count(),
200 'episodes': Episode.count(),
201 'users': User.count(),
204 def get(self, request):
205 stats = self._get_stats()
206 return self.render_to_response({
207 'stats': stats,
211 class StatsJsonView(StatsView):
212 """ provides general stats as JSON """
214 def get(self, request):
215 stats = self._get_stats()
216 return JsonResponse(stats)