Move group material handling code to doc/material/ now that the view of the material is integrated into /doc/, fix a bunch of bugs

- Legacy-Id: 7834
This commit is contained in:
Ole Laursen 2014-06-03 09:42:16 +00:00
parent c94757405d
commit 88cf68d43f
10 changed files with 194 additions and 157 deletions

View file

@ -173,7 +173,7 @@ class DocumentInfo(models.Model):
def meeting_related(self):
return(self.type_id in ("agenda", "minutes", "slides") and (
self.name.split("-")[1] == "interim"
or self.session_set.exists()))
or (self.session_set.exists() if isinstance(self, Document) else self.doc.session_set.exists())))
class Meta:
abstract = True

View file

@ -102,4 +102,5 @@ urlpatterns = patterns('',
(r'^(?P<name>charter-[A-Za-z0-9._+-]+)/', include('ietf.doc.urls_charter')),
(r'^(?P<name>[A-Za-z0-9._+-]+)/conflict-review/', include('ietf.doc.urls_conflict_review')),
(r'^(?P<name>[A-Za-z0-9._+-]+)/status-change/', include('ietf.doc.urls_status_change')),
(r'^(?P<name>[A-Za-z0-9._+-]+)/material/', include('ietf.doc.urls_material')),
)

View file

@ -0,0 +1,6 @@
from django.conf.urls import patterns, url
urlpatterns = patterns('ietf.doc.views_material',
url(r'^(?P<action>state|title|revise)/$', "edit_material", name="material_edit"),
)

168
ietf/doc/views_material.py Normal file
View file

@ -0,0 +1,168 @@
# views for managing group materials (slides, ...)
import re
import os
import datetime
import shutil
from django import forms
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, HttpResponseForbidden, Http404, HttpResponseRedirect
from django.utils.html import mark_safe
from django.utils.text import slugify
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse as urlreverse
import debug # pyflakes:ignore
from ietf.doc.models import Document, DocAlias, DocTypeName, DocEvent, State
from ietf.doc.models import NewRevisionDocEvent, save_document_in_history
from ietf.doc.utils import add_state_change_event
from ietf.group.models import Group
from ietf.group.utils import can_manage_materials
from ietf.ietfauth.utils import has_role
@login_required
def choose_material_type(request, acronym):
group = get_object_or_404(Group, acronym=acronym)
if not group.features.has_materials:
raise Http404
return render(request, 'doc/material/choose_material_type.html', {
'group': group,
'material_types': DocTypeName.objects.filter(slug__in=group.features.material_types),
})
def name_for_material(doc_type, group, title):
return "%s-%s-%s" % (doc_type.slug, group.acronym, slugify(title))
class UploadMaterialForm(forms.Form):
title = forms.CharField(max_length=Document._meta.get_field("title").max_length)
state = forms.ModelChoiceField(State.objects.all(), empty_label=None)
material = forms.FileField(label='File', help_text="PDF or text file (ASCII/UTF-8)")
def __init__(self, doc_type, action, group, doc, *args, **kwargs):
super(UploadMaterialForm, self).__init__(*args, **kwargs)
self.fields["state"].queryset = self.fields["state"].queryset.filter(type=doc_type)
self.doc_type = doc_type
self.action = action
self.group = group
if action == "new":
self.fields["state"].widget = forms.HiddenInput()
self.fields["state"].queryset = self.fields["state"].queryset.filter(slug="active")
self.fields["state"].initial = self.fields["state"].queryset[0].pk
else:
self.fields["title"].initial = doc.title
self.fields["state"].initial = doc.get_state().pk if doc.get_state() else None
if doc.get_state_slug() == "deleted":
self.fields["state"].help_text = "Note: If you wish to revise this document, you may wish to change the state so it's not deleted."
if action == "title":
del self.fields["state"]
del self.fields["material"]
elif action == "state":
del self.fields["title"]
del self.fields["material"]
def clean_title(self):
title = self.cleaned_data["title"]
if self.action == "new":
name = name_for_material(self.doc_type, self.group, title)
existing = Document.objects.filter(type=self.doc_type, name=name)
if existing:
url = urlreverse("material_edit", kwargs={ 'name': existing[0].name, 'action': 'revise' })
raise forms.ValidationError(mark_safe("Can't upload: %s with name %s already exists. The name is derived from the title so you must either choose another title for what you're uploading or <a href=\"%s\">revise the existing %s</a>." % (self.doc_type.name, name, url, name)))
return title
@login_required
def edit_material(request, name=None, acronym=None, action=None, doc_type=None):
# the materials process is not very developed, so at the moment we
# handle everything through the same view/form
if action == "new":
group = get_object_or_404(Group, acronym=acronym)
if not group.features.has_materials:
raise Http404
doc = None
document_type = get_object_or_404(DocTypeName, slug=doc_type)
else:
doc = get_object_or_404(Document, name=name)
group = doc.group
document_type = doc.type
if not can_manage_materials(request.user, group):
return HttpResponseForbidden("You don't have permission to access this view")
if request.method == 'POST':
form = UploadMaterialForm(document_type, action, group, doc, request.POST, request.FILES)
if form.is_valid():
if action == "new":
doc = Document()
doc.type = document_type
doc.group = group
doc.rev = "00"
doc.name = name_for_material(doc.type, doc.group, form.cleaned_data["title"])
prev_rev = None
else:
save_document_in_history(doc)
prev_rev = doc.rev
prev_title = doc.title
prev_state = doc.get_state()
if "title" in form.cleaned_data:
doc.title = form.cleaned_data["title"]
doc.time = datetime.datetime.now()
if "material" in form.fields:
if action != "new":
doc.rev = "%02d" % (int(doc.rev) + 1)
f = form.cleaned_data["material"]
file_ext = os.path.splitext(f.name)[1]
with open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + file_ext), 'wb+') as dest:
for chunk in f.chunks():
dest.write(chunk)
doc.save()
if action == "new":
DocAlias.objects.get_or_create(name=doc.name, document=doc)
if prev_rev != doc.rev:
e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev)
e.time = doc.time
e.by = request.user.person
e.desc = "New version available: <b>%s-%s</b>" % (doc.name, doc.rev)
e.save()
if prev_title != doc.title:
e = DocEvent(doc=doc, by=request.user.person, type='changed_document')
e.desc = u"Changed title to <b>%s</b>" % doc.title
if prev_title:
e.desc += u" from %s" % prev_title
e.time = doc.time
e.save()
if "state" in form.cleaned_data and form.cleaned_data["state"] != prev_state:
doc.set_state(form.cleaned_data["state"])
add_state_change_event(doc, request.user.person, prev_state, form.cleaned_data["state"])
return redirect("doc_view", name=doc.name)
else:
form = UploadMaterialForm(document_type, action, group, doc)
return render(request, 'doc/material/edit_material.html', {
'group': group,
'form': form,
'action': action,
'document_type': document_type,
'doc_name': doc.name if doc else "",
})

View file

@ -459,136 +459,3 @@ def customize_workflow(request, group_type, acronym):
'states': states,
'tags': tags,
})
@login_required
def choose_material_type(request, acronym, group_type=None):
group = get_group_or_404(acronym, group_type)
if not group.features.has_materials:
raise Http404
return render(request, 'group/choose_material_type.html', {
'group': group,
'material_types': DocTypeName.objects.filter(slug__in=group.features.material_types),
})
def name_for_material(doc_type, group, title):
return "%s-%s-%s" % (doc_type.slug, group.acronym, slugify(title))
class UploadMaterialForm(forms.Form):
title = forms.CharField(max_length=Document._meta.get_field("title").max_length)
state = forms.ModelChoiceField(State.objects.all(), empty_label=None)
material = forms.FileField(label='File', help_text="PDF or text file (ASCII/UTF-8)")
def __init__(self, doc_type, action, group, doc, *args, **kwargs):
super(UploadMaterialForm, self).__init__(*args, **kwargs)
self.fields["state"].queryset = self.fields["state"].queryset.filter(type=doc_type)
self.doc_type = doc_type
self.action = action
self.group = group
if action == "new":
self.fields["state"].widget = forms.HiddenInput()
self.fields["state"].queryset = self.fields["state"].queryset.filter(slug="active")
self.fields["state"].initial = self.fields["state"].queryset[0].pk
else:
self.fields["title"].initial = doc.title
self.fields["state"].initial = doc.get_state().pk if doc.get_state() else None
if doc.get_state_slug() == "deleted":
self.fields["state"].help_text = "Note: If you wish to revise this document, you may wish to change the state so it's not deleted."
if action == "edit":
del self.fields["material"]
def clean_title(self):
title = self.cleaned_data["title"]
if self.action == "new":
name = name_for_material(self.doc_type, self.group, title)
existing = Document.objects.filter(type=self.doc_type, name=name)
if existing:
url = urlreverse("group_revise_material", kwargs={ 'acronym': self.group.acronym, 'name': existing[0].name })
raise forms.ValidationError(mark_safe("Can't upload: %s with name %s already exists. The name is derived from the title so you must either choose another title for what you're uploading or <a href=\"%s\">revise the existing %s</a>." % (self.doc_type.name, name, url, name)))
return title
@login_required
def edit_material(request, acronym, action="new", name=None, doc_type=None, group_type=None):
group = get_group_or_404(acronym, group_type)
if not group.features.has_materials:
raise Http404
if not can_manage_materials(request.user, group):
return HttpResponseForbidden("You don't have permission to access this view")
existing = None
if name and action != "new":
existing = get_object_or_404(Document, name=name)
document_type = existing.type
else:
document_type = get_object_or_404(DocTypeName, slug=doc_type)
if request.method == 'POST':
form = UploadMaterialForm(document_type, action, group, existing, request.POST, request.FILES)
if form.is_valid():
if action == "new":
d = Document()
d.type = document_type
d.group = group
d.rev = "00"
d.name = name_for_material(d.type, d.group, form.cleaned_data["title"])
else:
d = existing
prev_rev = d.rev
prev_title = d.title
prev_state = d.get_state()
d.title = form.cleaned_data["title"]
d.time = datetime.datetime.now()
if "material" in form.fields:
if action != "new":
d.rev = "%02d" % (int(d.rev) + 1)
f = form.cleaned_data["material"]
file_ext = os.path.splitext(f.name)[1]
with open(os.path.join(d.get_file_path(), d.name + "-" + d.rev + file_ext), 'wb+') as dest:
for chunk in f.chunks():
dest.write(chunk)
d.save()
if action == "new":
DocAlias.objects.get_or_create(name=d.name, document=d)
if not existing or prev_rev != d.rev:
e = NewRevisionDocEvent(type="new_revision", doc=d, rev=d.rev)
e.time = d.time
e.by = request.user.person
e.desc = "New version available: <b>%s-%s</b>" % (d.name, d.rev)
e.save()
if prev_title != d.title:
e = DocEvent(doc=d, by=request.user.person, type='changed_document')
e.desc = u"Changed title to <b>%s</b>" % d.title
if prev_title:
e.desc += u" from %s" % prev_title
e.time = d.time
e.save()
d.set_state(form.cleaned_data["state"])
add_state_change_event(d, request.user.person, prev_state, form.cleaned_data["state"])
return redirect("group_materials", acronym=group.acronym)
else:
form = UploadMaterialForm(document_type, action, group, existing)
return render(request, 'group/edit_material.html', {
'group': group,
'form': form,
'action': action,
})

View file

@ -299,7 +299,7 @@ def construct_group_menu_context(request, group, selected, group_type, others):
actions.append((u"Add or edit milestones", urlreverse("group_edit_milestones", kwargs=kwargs)))
if group.features.has_materials and can_manage_materials(request.user, group):
actions.append((u"Upload material", urlreverse("group_choose_material_type", kwargs=kwargs)))
actions.append((u"Upload material", urlreverse("ietf.doc.views_material.choose_material_type", kwargs=kwargs)))
if group.type_id in ("rg", "wg") and group.state_id != "conclude" and can_manage:
actions.append((u"Edit group", urlreverse("group_edit", kwargs=kwargs)))

View file

@ -7,7 +7,9 @@ urlpatterns = patterns('',
(r'^chartering/$', 'ietf.group.info.chartering_groups'),
(r'^chartering/create/(?P<group_type>(wg|rg))/$', 'ietf.group.edit.edit', {'action': "charter"}, "group_create"),
(r'^concluded/$', 'ietf.group.info.concluded_groups'),
# FIXME: the things below are duplicated in urls_info.py, need to unify these at some point
# FIXME: the things below are duplicated in urls_info.py while we
# figure out whether to serve everything from /group/<acronym>,
# need to unify these at some point
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', 'ietf.group.info.group_home', None, "group_home"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/$', 'ietf.group.info.group_documents', None, "group_docs"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', 'ietf.group.info.group_about', None, 'group_charter'),
@ -25,10 +27,8 @@ urlpatterns = patterns('',
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/about/(?P<group_type>.)?$', 'ietf.group.info.group_about', None, 'group_about'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/$', 'ietf.group.info.materials', None, "group_materials"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/$', 'ietf.group.edit.choose_material_type', None, "group_choose_material_type"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/(?P<doc_type>[\w-]+)/$', 'ietf.group.edit.edit_material', { 'action': "new" }, "group_new_material"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/(?P<name>[^/]+)/edit/$', 'ietf.group.edit.edit_material', { 'action': "edit" }, "group_edit_material"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/(?P<name>[^/]+)/revise/$', 'ietf.group.edit.edit_material', { 'action': "revise" }, "group_revise_material"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/$', 'ietf.doc.views_material.choose_material_type'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/materials/new/(?P<doc_type>[\w-]+)/$', 'ietf.doc.views_material.edit_material', { 'action': "new" }, "group_new_material"),
)

View file

@ -22,14 +22,14 @@
<tr>
<td>Title:</td>
<td>
<a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "status_change_change_state" name=doc.name %}"{% endif %}>{{ doc.title }}</a>
<a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="title" name=doc.name %}"{% endif %}>{{ doc.title }}</a>
</td>
</tr>
<tr>
<td>State:</td>
<td>
<a title="{{ doc.get_state.desc }}"{% if not snapshot and can_manage_material %} class="editlink" href="{% url "status_change_change_state" name=doc.name %}"{% endif %}>{{ doc.get_state.name }}</a>
<a title="{{ doc.get_state.desc }}"{% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="state" %}"{% endif %}>{{ doc.get_state.name }}</a>
</td>
</tr>
@ -51,9 +51,7 @@
{% if not snapshot and can_manage_material %}
<tr><td colspan="2">
<a class="button" href="{% url "group_edit_material" acronym=group.acronym name=d.name %}">Change title/state</a>
<a class="button" href="{% url "group_revise_material" acronym=group.acronym name=d.name %}">Revise content</a>
<a class="button" href="{% url "material_edit" name=doc.name action="revise" %}">Upload New Revision</a>
</td><tr/>
{% endif %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Upload Material for Group {{ group.acronym }}{% endblock %}
{% block title %}{% if action == "new" or action == "revise" %}Upload{% else %}Edit{% endif %} {{ document_type.name }} for Group {{ group.acronym }}{% endblock %}
{% block morecss %}
{{ block.super }}
@ -12,7 +12,7 @@ form.upload-material .submit-row td { padding-top: 1em; text-align: right; }
{% block content %}
{% load ietf_filters %}
<h1>Upload Material for Group {{ group.acronym }}</h1>
<h1>{% if action == "new" or action == "revise" %}Upload{% else %}Edit{% endif %} {{ document_type.name }} for Group {{ group.acronym }}</h1>
{% if action == "new" %}
<p>
@ -20,19 +20,16 @@ form.upload-material .submit-row td { padding-top: 1em; text-align: right; }
<a href="{% url "group_materials" acronym=group.acronym %}">{{ group.acronym }}</a>.
The file will appear under the materials tab in the group pages.
</p>
{% elif action == "edit" %}
<p>
Below you can edit the details of the material for the group
<a href="{% url "group_materials" acronym=group.acronym %}">{{ group.acronym }}</a>.
</p>
<h3>Upload</h3>
{% elif action == "revise" %}
<p>
Below you can upload a new revision of the material for the group
Below you can upload a new revision of {{ doc_name }} for the group
<a href="{% url "group_materials" acronym=group.acronym %}">{{ group.acronym }}</a>.
</p>
{% endif %}
<h3>Upload</h3>
<h3>Upload New Revision</h3>
{% endif %}
<form class="upload-material" method="post" enctype="multipart/form-data">{% csrf_token %}
<table>
@ -40,8 +37,8 @@ form.upload-material .submit-row td { padding-top: 1em; text-align: right; }
<tr class="submit-row">
<td colspan="2">
<a class="button" href="{% url "group_materials" acronym=group.acronym %}">Cancel</a>
<input class="submit button" type="submit" value="{% if action == "edit" %}Save{% else %}Upload{% endif %}" />
<a class="button" href="{% if doc_name %}{% url "doc_view" name=doc_name %}{% else %}{% url "group_materials" acronym=group.acronym %}{% endif %}">Cancel</a>
<input class="submit button" type="submit" value="{% if action == "new" or action == "revise" %}Upload{% else %}Save{% endif %}" />
</td>
</tr>
</table>