summaryrefslogtreecommitdiff
path: root/todolists/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'todolists/views.py')
-rw-r--r--todolists/views.py185
1 files changed, 115 insertions, 70 deletions
diff --git a/todolists/views.py b/todolists/views.py
index 379189ab..7de32036 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -1,81 +1,103 @@
-from django import forms
+import json
+from django import forms
from django.http import HttpResponse
from django.conf import settings
from django.core.mail import send_mail
-from django.shortcuts import get_list_or_404, get_object_or_404, redirect
-from django.contrib.auth.decorators import login_required, permission_required
+from django.shortcuts import (get_list_or_404, get_object_or_404,
+ redirect, render)
from django.db import transaction
from django.views.decorators.cache import never_cache
from django.views.generic import DeleteView
-from django.views.generic.simple import direct_to_template
from django.template import Context, loader
-from django.utils import simplejson
+from django.template.defaultfilters import slugify
+from django.utils.timezone import now
-from main.models import Todolist, TodolistPkg, Package, Repo
+from main.models import Package, Repo
+from main.utils import find_unique_slug
from packages.utils import attach_maintainers
-from .utils import get_annotated_todolists
+from .models import Todolist, TodolistPackage
+from .utils import get_annotated_todolists, attach_staging
+
class TodoListForm(forms.ModelForm):
- packages = forms.CharField(required=False,
+ raw = forms.CharField(label='Packages', required=False,
help_text='(one per line)',
widget=forms.Textarea(attrs={'rows': '20', 'cols': '60'}))
- def clean_packages(self):
- package_names = [s.strip() for s in
- self.cleaned_data['packages'].split("\n")]
- package_names = set(package_names)
- packages = Package.objects.filter(pkgname__in=package_names).filter(
- repo__testing=False, repo__staging=False).select_related(
- 'arch', 'repo').order_by('arch')
- return packages
+ def package_names(self):
+ return {s.strip() for s in self.cleaned_data['raw'].split("\n")}
+
+ def packages(self):
+ return Package.objects.normal().filter(
+ pkgname__in=self.package_names(),
+ repo__testing=False, repo__staging=False).order_by('arch')
class Meta:
model = Todolist
- fields = ('name', 'description')
+ fields = ('name', 'description', 'raw')
+
-@permission_required('main.change_todolistpkg')
@never_cache
-def flag(request, list_id, pkg_id):
- todolist = get_object_or_404(Todolist, id=list_id)
- pkg = get_object_or_404(TodolistPkg, id=pkg_id)
- pkg.complete = not pkg.complete
- pkg.save()
+def flag(request, slug, pkg_id):
+ todolist = get_object_or_404(Todolist, slug=slug)
+ tlpkg = get_object_or_404(TodolistPackage, id=pkg_id, removed__isnull=True)
+ # TODO: none of this; require absolute value on submit
+ if tlpkg.status == TodolistPackage.INCOMPLETE:
+ tlpkg.status = TodolistPackage.COMPLETE
+ else:
+ tlpkg.status = TodolistPackage.INCOMPLETE
+ tlpkg.user = request.user
+ tlpkg.save(update_fields=('status', 'user', 'last_modified'))
if request.is_ajax():
- return HttpResponse(
- simplejson.dumps({'complete': pkg.complete}),
- mimetype='application/json')
+ data = {
+ 'status': tlpkg.get_status_display(),
+ 'css_class': tlpkg.status_css_class(),
+ }
+ return HttpResponse(json.dumps(data), content_type='application/json')
return redirect(todolist)
-@login_required
-def view(request, list_id):
- todolist = get_object_or_404(Todolist, id=list_id)
- svn_roots = Repo.objects.order_by().values_list(
- 'svn_root', flat=True).distinct()
+
+def view_redirect(request, old_id):
+ todolist = get_object_or_404(Todolist, old_id=old_id)
+ return redirect(todolist, permanent=True)
+
+
+def view(request, slug):
+ todolist = get_object_or_404(Todolist, slug=slug)
+ svn_roots = Repo.objects.values_list(
+ 'svn_root', flat=True).order_by().distinct()
# we don't hold onto the result, but the objects are the same here,
# so accessing maintainers in the template is now cheap
- attach_maintainers(tp.pkg for tp in todolist.packages)
- return direct_to_template(request, 'todolists/view.html', {
+ attach_maintainers(todolist.packages())
+ attach_staging(todolist.packages(), todolist.pk)
+ arches = {tp.arch for tp in todolist.packages()}
+ repos = {tp.repo for tp in todolist.packages()}
+ return render(request, 'todolists/view.html', {
'list': todolist,
'svn_roots': svn_roots,
+ 'arches': sorted(arches),
+ 'repos': sorted(repos),
})
-# really no need for login_required on this one...
-def list_pkgbases(request, list_id, svn_root):
+
+def list_pkgbases(request, slug, svn_root):
'''Used to make bulk moves of packages a lot easier.'''
- todolist = get_object_or_404(Todolist, id=list_id)
+ todolist = get_object_or_404(Todolist, slug=slug)
repos = get_list_or_404(Repo, svn_root=svn_root)
- pkgbases = set(tp.pkg.pkgbase for tp in todolist.packages
- if tp.pkg.repo in repos)
- return HttpResponse('\n'.join(sorted(pkgbases)),
- mimetype='text/plain')
+ pkgbases = TodolistPackage.objects.values_list(
+ 'pkgbase', flat=True).filter(
+ todolist=todolist, repo__in=repos, removed__isnull=True).order_by(
+ 'pkgbase').distinct()
+ return HttpResponse('\n'.join(pkgbases), content_type='text/plain')
+
-@login_required
def todolist_list(request):
- lists = get_annotated_todolists()
- return direct_to_template(request, 'todolists/list.html', {'lists': lists})
+ incomplete_only = request.user.is_anonymous()
+ lists = get_annotated_todolists(incomplete_only)
+ return render(request, 'todolists/list.html', {'lists': lists})
+
-@permission_required('main.add_todolist')
@never_cache
def add(request):
if request.POST:
@@ -89,16 +111,17 @@ def add(request):
page_dict = {
'title': 'Add Todo List',
+ 'description': '',
'form': form,
'submit_text': 'Create List'
}
- return direct_to_template(request, 'general_form.html', page_dict)
+ return render(request, 'general_form.html', page_dict)
+
# TODO: this calls for transaction management and async emailing
-@permission_required('main.change_todolist')
@never_cache
-def edit(request, list_id):
- todo_list = get_object_or_404(Todolist, id=list_id)
+def edit(request, slug):
+ todo_list = get_object_or_404(Todolist, slug=slug)
if request.POST:
form = TodoListForm(request.POST, instance=todo_list)
if form.is_valid():
@@ -107,14 +130,16 @@ def edit(request, list_id):
return redirect(todo_list)
else:
form = TodoListForm(instance=todo_list,
- initial={ 'packages': '\n'.join(todo_list.package_names) })
+ initial={'packages': todo_list.raw})
page_dict = {
'title': 'Edit Todo List: %s' % todo_list.name,
+ 'description': '',
'form': form,
'submit_text': 'Save List'
}
- return direct_to_template(request, 'general_form.html', page_dict)
+ return render(request, 'general_form.html', page_dict)
+
class DeleteTodolist(DeleteView):
model = Todolist
@@ -122,36 +147,64 @@ class DeleteTodolist(DeleteView):
template_name = 'todolists/todolist_confirm_delete.html'
success_url = '/todo/'
+
@transaction.commit_on_success
def create_todolist_packages(form, creator=None):
- packages = form.cleaned_data['packages']
+ package_names = form.package_names()
+ packages = form.packages()
+ timestamp = now()
if creator:
- # todo list is new
+ # todo list is new, populate creator and slug fields
todolist = form.save(commit=False)
todolist.creator = creator
+ todolist.slug = find_unique_slug(Todolist, todolist.name)
todolist.save()
-
- old_packages = []
else:
# todo list already existed
form.save()
todolist = form.instance
- # first delete any packages not in the new list
- for todo_pkg in todolist.packages:
- if todo_pkg.pkg not in packages:
- todo_pkg.delete()
- # save the old package list so we know what to add
- old_packages = [p.pkg for p in todolist.packages]
+ # first mark removed any packages not in the new list
+ to_remove = set()
+ for todo_pkg in todolist.packages():
+ if todo_pkg.pkg and todo_pkg.pkg not in packages:
+ to_remove.add(todo_pkg.pk)
+ elif todo_pkg.pkgname not in package_names:
+ to_remove.add(todo_pkg.pk)
+
+ TodolistPackage.objects.filter(
+ pk__in=to_remove).update(removed=timestamp)
+ # Add (or mark unremoved) any packages in the new packages list
todo_pkgs = []
for package in packages:
- if package not in old_packages:
- todo_pkg = TodolistPkg.objects.create(list=todolist, pkg=package)
+ # ensure get_or_create uses the fields in our unique constraint
+ defaults = {
+ 'pkg': package,
+ 'pkgbase': package.pkgbase,
+ 'repo': package.repo,
+ }
+ todo_pkg, created = TodolistPackage.objects.get_or_create(
+ todolist=todolist,
+ pkgname=package.pkgname,
+ arch=package.arch,
+ defaults=defaults)
+ if created:
todo_pkgs.append(todo_pkg)
+ else:
+ save = False
+ if todo_pkg.removed is not None:
+ todo_pkg.removed = None
+ save = True
+ if todo_pkg.pkg != package:
+ todo_pkg.pkg = package
+ save = True
+ if save:
+ todo_pkg.save()
return todo_pkgs
+
def send_todolist_emails(todo_list, new_packages):
'''Sends emails to package maintainers notifying them that packages have
been added to a todo list.'''
@@ -179,12 +232,4 @@ def send_todolist_emails(todo_list, new_packages):
[maint],
fail_silently=True)
-def public_list(request):
- todo_lists = Todolist.objects.incomplete()
- # total hackjob, but it makes this a lot less query-intensive.
- all_pkgs = [tp for tl in todo_lists for tp in tl.packages]
- attach_maintainers([tp.pkg for tp in all_pkgs])
- return direct_to_template(request, "todolists/public_list.html",
- {"todo_lists": todo_lists})
-
# vim: set ts=4 sw=4 et: