Turn charter page for non-chartering groups into about page, fix a bunch of potentially broken links due to the split between group-type prefixed URLs and /group/ ones

- Legacy-Id: 7805
This commit is contained in:
Ole Laursen 2014-05-30 15:59:02 +00:00
parent 544cd702bb
commit 976d0b9d68
19 changed files with 60 additions and 49 deletions

View file

@ -7,10 +7,9 @@ import shutil
from django import forms
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponseForbidden, Http404
from django.http import HttpResponse, HttpResponseForbidden, Http404, HttpResponseRedirect
from django.utils.html import mark_safe
from django.utils.text import slugify
from django.http import Http404, HttpResponse
from django.contrib.auth.decorators import login_required
import debug # pyflakes:ignore
@ -304,7 +303,7 @@ def edit(request, group_type=None, acronym=None, action="edit"):
if action=="charter":
return redirect('charter_submit', name=group.charter.name, option="initcharter")
return redirect('group_charter', group_type=group.type_id, acronym=group.acronym)
return HttpResponseRedirect(group.about_url())
else: # form.is_valid()
if not new_group:
init = dict(name=group.name,
@ -337,11 +336,11 @@ class ConcludeForm(forms.Form):
instructions = forms.CharField(widget=forms.Textarea(attrs={'rows': 30}), required=True)
@login_required
def conclude(request, group_type, acronym):
def conclude(request, acronym, group_type=None):
"""Request the closing of group, prompting for instructions."""
group = get_group_or_404(acronym, group_type)
if not can_manage_group_type(request.user, group_type):
if not can_manage_group_type(request.user, group.type_id):
return HttpResponseForbidden("You don't have permission to access this view")
if request.method == 'POST':
@ -356,13 +355,15 @@ def conclude(request, group_type, acronym):
e.desc = "Requested closing group"
e.save()
return redirect('group_charter', group_type=group.type_id, acronym=group.acronym)
return redirect(group.features.about_page, group_type=group_type, acronym=group.acronym)
else:
form = ConcludeForm()
return render(request, 'group/conclude.html',
dict(form=form, group=group))
return render(request, 'group/conclude.html', {
'form': form,
'group': group,
'group_type': group_type,
})
@login_required
def customize_workflow(request, group_type, acronym):

View file

@ -7,7 +7,8 @@ class GroupFeatures(object):
has_documents = False # i.e. drafts/RFCs
has_materials = False
customize_workflow = False
default_tab = "group_charter"
about_page = "group_about"
default_tab = about_page
material_types = ["slides"]
def __init__(self, group):
@ -19,3 +20,6 @@ class GroupFeatures(object):
self.default_tab = "group_docs"
elif group.type_id in ("team",):
self.has_materials = True
if self.has_chartering_process:
about_page = "group_charter"

View file

@ -22,7 +22,7 @@ class GroupChangesFeed(Feed):
def link(self, obj):
if not obj:
raise FeedDoesNotExist
return urlreverse('group_charter', kwargs=dict(group_type=obj.type_id, acronym=obj.acronym))
return group.about_url()
def description(self, obj):
return self.title(obj)
@ -40,7 +40,7 @@ class GroupChangesFeed(Feed):
if isinstance(obj, DocEvent):
return urlreverse("doc_view", kwargs={'name': obj.doc_id })
elif isinstance(obj, GroupEvent):
return urlreverse('group_charter', kwargs=dict(group_type=obj.group.type_id, acronym=obj.group.acronym))
return group.about_url()
def item_pubdate(self, obj):
return obj.time

View file

@ -272,7 +272,10 @@ def construct_group_menu_context(request, group, selected, group_type, others):
entries = []
if group.features.has_documents:
entries.append(("Documents", urlreverse("ietf.group.info.group_documents", kwargs=kwargs)))
entries.append(("Charter", urlreverse("ietf.group.info.group_charter", kwargs=kwargs)))
if group.features.has_chartering_process:
entries.append(("Charter", urlreverse("group_charter", kwargs=kwargs)))
else:
entries.append(("About", urlreverse("group_about", kwargs=kwargs)))
if group.features.has_materials and get_group_materials(group).exists():
entries.append(("Materials", urlreverse("ietf.group.info.materials", kwargs=kwargs)))
entries.append(("History", urlreverse("ietf.group.info.history", kwargs=kwargs)))
@ -400,7 +403,7 @@ def group_documents_txt(request, acronym, group_type=None):
return HttpResponse(u"\n".join(rows), content_type='text/plain; charset=UTF-8')
def group_charter(request, acronym, group_type=None):
def group_about(request, acronym, group_type=None):
group = get_group_or_404(acronym, group_type)
fill_in_charter_info(group)
@ -408,27 +411,14 @@ def group_charter(request, acronym, group_type=None):
e = group.latest_event(type__in=("changed_state", "requested_close",))
requested_close = group.state_id != "conclude" and e and e.type == "requested_close"
verbose_group_types = {
"wg": "Working Group",
"rg": "Research Group",
"team": "Team",
}
can_manage = can_manage_group_type(request.user, group.type_id)
if group.features.has_chartering_process:
description = group.charter_text
else:
description = group.description or "No description yet."
return render(request, 'group/group_charter.html',
construct_group_menu_context(request, group, "charter", group_type, {
return render(request, 'group/group_about.html',
construct_group_menu_context(request, group, "charter" if group.features.has_chartering_process else "about", group_type, {
"milestones_in_review": group.groupmilestone_set.filter(state="review"),
"milestone_reviewer": milestone_reviewer_for_group_type(group_type),
"requested_close": requested_close,
"verbose_group_type": verbose_group_types.get(group.type_id, "Group"),
"can_manage": can_manage,
"description": description,
}))

View file

@ -22,7 +22,7 @@ def email_secretariat(request, group, subject, text):
"group/email_secretariat.txt",
dict(text=text,
group=group,
group_url=settings.IDTRACKER_BASE_URL + urlreverse('group_charter', kwargs=dict(group_type=group.type_id, acronym=group.acronym)),
group_url=settings.IDTRACKER_BASE_URL + group.about_url(),
charter_url=settings.IDTRACKER_BASE_URL + urlreverse('doc_view', kwargs=dict(name=group.charter.name)),
)
)
@ -31,7 +31,7 @@ def email_milestones_changed(request, group, changes):
def wrap_up_email(to, text):
text = wrap(strip_tags(text), 70)
text += "\n\n"
text += u"URL: %s" % (settings.IDTRACKER_BASE_URL + urlreverse("group_charter", kwargs=dict(group_type=group.type_id, acronym=group.acronym)))
text += u"URL: %s" % (settings.IDTRACKER_BASE_URL + group.about_url())
send_mail_text(request, to, None,
u"Milestones changed for %s %s" % (group.acronym, group.type.name),
@ -121,7 +121,7 @@ def email_milestones_due(group, early_warning_days):
milestones=milestones,
today=today,
early_warning_days=early_warning_days,
url=settings.IDTRACKER_BASE_URL + urlreverse("group_charter", kwargs=dict(group_type=group.type_id, acronym=group.acronym))
url=settings.IDTRACKER_BASE_URL + group.about_url(),
))
def groups_needing_milestones_due_reminder(early_warning_days):
@ -146,7 +146,7 @@ def email_milestones_overdue(group):
"group/reminder_milestones_overdue.txt",
dict(group=group,
milestones=milestones,
url=settings.IDTRACKER_BASE_URL + urlreverse("group_charter", kwargs=dict(group_type=group.type_id, acronym=group.acronym))
url=settings.IDTRACKER_BASE_URL + group.about_url(),
))
def groups_needing_milestones_overdue_reminder(grace_period=30):

View file

@ -5,7 +5,7 @@ import calendar
import json
from django import forms
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseBadRequest
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseBadRequest, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
@ -311,7 +311,7 @@ def edit_milestones(request, acronym, group_type=None, milestone_set="current"):
if milestone_set == "charter":
return redirect('doc_view', name=group.charter.canonical_name())
else:
return redirect('group_charter', group_type=group.type_id, acronym=group.acronym)
return HttpResponseRedirect(group.about_url())
else:
for m in milestones:
forms.append(MilestoneForm(instance=m, needs_review=needs_review))

View file

@ -36,6 +36,14 @@ class GroupInfo(models.Model):
res += " %s (%s)" % (self.type, self.acronym)
return res
def about_url(self):
# bridge gap between group-type prefixed URLs and /group/ ones
from django.core.urlresolvers import reverse as urlreverse
kwargs = { 'acronym': self.acronym }
if self.type_id in ("wg", "rg"):
kwargs["group_type"] = self.type_id
return urlreverse(self.features.about_page, kwargs=kwargs)
class Meta:
abstract = True

View file

@ -183,7 +183,7 @@ class GroupPagesTests(TestCase):
due=datetime.date.today() + datetime.timedelta(days=100))
milestone.docs.add(draft)
url = urlreverse('ietf.group.info.group_charter', kwargs=dict(group_type=group.type_id, acronym=group.acronym))
url = group.about_url()
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
self.assertTrue(group.name in r.content)

View file

@ -10,7 +10,7 @@ urlpatterns = patterns('',
# FIXME: the things below are duplicated in urls_info.py, 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_charter', None, 'group_charter'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', 'ietf.group.info.group_about', None, 'group_charter'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/history/$', 'ietf.group.info.history'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/dot/$', 'ietf.group.info.dependencies_dot'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/pdf/$', 'ietf.group.info.dependencies_pdf'),
@ -23,6 +23,7 @@ urlpatterns = patterns('',
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/ajax/searchdocs/$', 'ietf.group.milestones.ajax_search_docs', None, "group_ajax_search_docs"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/workflow/$', 'ietf.group.edit.customize_workflow'),
(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"),

View file

@ -21,7 +21,7 @@ urlpatterns = patterns('',
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/txt/$', info.group_documents_txt),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', info.group_home, None, "group_home"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/documents/$', info.group_documents, None, "group_docs"),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', info.group_charter, None, 'group_charter'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/charter/$', info.group_about, None, 'group_charter'),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/history/$', info.history),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/dot/$', info.dependencies_dot),
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/deps/pdf/$', info.dependencies_pdf),

View file

@ -25,7 +25,7 @@
{% if snapshot %}Snapshot of{% endif %}
{% if doc.get_state_slug != "approved" %}Proposed{% endif %}
Charter for "{{ group.name }}"
(<a {% if group.type_id == "wg" or group.type_id == "rg" %}href="{% url "ietf.group.info.group_charter" group_type=group.type_id acronym=group.acronym %}"{% endif %}>{{ group.acronym }}</a>) {{ group.type.name }}
(<a href="{{ group.about_url }}">{{ group.acronym }}</a>) {{ group.type.name }}
</div>
<table id="metatable" width="100%">

View file

@ -25,7 +25,7 @@
{% for g in groups %}
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
<td class="acronym">
<a href="{% url "group_charter" group_type=g.type_id acronym=g.acronym %}">{{ g.acronym }}</a>
<a href="{{ g.about_url }}">{{ g.acronym }}</a>
</td>
<td class="title">
<a {%comment%}href="{% url "doc_view" name=g.charter.name %}"{%endcomment%}>{{ g.name }}</a>

View file

@ -33,7 +33,7 @@
{% for g in t.chartering_groups %}
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
<td class="acronym">
<a href="{% url "group_charter" group_type=g.type_id acronym=g.acronym %}">{{ g.acronym }}</a>
<a href="{{ g.about_url }}">{{ g.acronym }}</a>
</td>
<td class="title">
<a href="{% url "doc_view" name=g.charter.name %}">{{ g.name }}</a>

View file

@ -29,7 +29,7 @@ form.conclude .actions {
{{ form.as_table }}
<tr>
<td colspan="2" class="actions">
<a class="button" href="{% url "group_charter" group_type=group.type_id acronym=group.acronym %}">Cancel</a>
<a class="button" href="{{ group.about_url }}">Cancel</a>
<input class="button" type="submit" value="Send request"/>
</td>
</tr>

View file

@ -25,7 +25,7 @@
{% for g in t.concluded_groups %}
<tr>
<td>
<a href="{% url "group_charter" group_type=g.type_id acronym=g.acronym %}">{{ g.acronym }}</a>
<a href="{{ group.about_url }}">{{ g.acronym }}</a>
</td>
<td>{{ g.name }}
<span class="active-period">({% if g.start_date %}{{ g.start_date|date:"M. Y" }}{% else %}?{% endif %}

View file

@ -34,7 +34,7 @@
<h1>Customize Workflow for {{ group.acronym }} {{ group.type.name }}</h1>
<p>Below you can customize the draft states and tags used in the
<a href="{% url "group_charter" group_type=group.type_id acronym=group.acronym %}">{{ group.acronym }} {{ group.type.name }}</a>. Note that some states are
<a href="{{ group.about_url }}">{{ group.acronym }} {{ group.type.name }}</a>. Note that some states are
mandatory for group operation and cannot be deactivated.</p>
{% if group.type_id == "wg" %}

View file

@ -69,7 +69,7 @@ so. New accounts can be <a href="{% url "create_account" %}">created here</a>.</
<td></td>
<td class="actions">
{% if action == "edit" %}
<a class="button" href="{% url "group_charter" group_type=group.type_id acronym=group.acronym %}">Cancel</a>
<a class="button" href="{{ group.about_url }}">Cancel</a>
<input class="button" type="submit" value="Save"/>
{% else %}
{% if action == "charter" %}

View file

@ -42,7 +42,7 @@ tr.milestone.add { font-style: italic; }
<noscript>This page depends on Javascript being enabled to work properly.</noscript>
<p>Links:
<a href="{% url "group_charter" group_type=group.type_id acronym=group.acronym %}">{{ group.acronym }} {{ group.type.name }}</a>
<a href="{{ g.about_url }}">{{ group.acronym }} {{ group.type.name }}</a>
- <a href="{% url "doc_view" name=group.charter.canonical_name %}">{{ group.charter.canonical_name }}</a>
</p>
@ -90,7 +90,7 @@ this list</a> to the milestones currently in use for the {{ group.acronym }} {{
</table>
<div class="actions">
<a class="button" href="{% if milestone_set == "charter" %}{% url "doc_view" name=group.charter.canonical_name %}{% else %}{% url "group_charter" group_type=group.type_id acronym=group.acronym %}{% endif %}">Cancel</a>
<a class="button" href="{% if milestone_set == "charter" %}{% url "doc_view" name=group.charter.canonical_name %}{% else %}{{ group.about_url }}{% endif %}">Cancel</a>
<input class="button" type="submit" data-labelsave="Save" data-labelreview="Review changes" value="Save" style="display:none"/>
<input type="hidden" name="action" value="save">
</div>

View file

@ -99,9 +99,16 @@ is occasionally incorrect.</span>
{% endif %}
{% endwith %}
<h2>Charter for {% if group.state_id == "proposed" %}Proposed{% endif %} {{ verbose_group_type }}</h2>
{% if group.features.has_chartering_process %}
<h2>Charter for {% if group.state_id == "proposed" %}Proposed{% endif %} {{ group.type.desc.title }}</h2>
<p>{{ group.charter_text|linebreaks }}</p>
{% else %}
<h2>About</h2>
<p>{{ group.description|default:"No description yet."|linebreaks }}</p>
{% endif %}
<p>{{ description|linebreaks }}</p>
{% if group.features.has_milestones %}
<h2>{% if group.state_id == "proposed" %}Proposed{% endif %} Milestones</h2>