refactor: Remove secr groups app (#5334)
This commit is contained in:
parent
a544cc91f9
commit
abc70ae650
|
@ -1,117 +0,0 @@
|
|||
import re
|
||||
|
||||
from django import forms
|
||||
from django.db.models import Count
|
||||
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.name.models import GroupStateName, GroupTypeName, RoleName
|
||||
from ietf.person.models import Person, Email
|
||||
|
||||
|
||||
# ---------------------------------------------
|
||||
# Select Choices
|
||||
# ---------------------------------------------
|
||||
SEARCH_MEETING_CHOICES = (('',''),('NO','NO'),('YES','YES'))
|
||||
|
||||
# ---------------------------------------------
|
||||
# Functions
|
||||
# ---------------------------------------------
|
||||
def get_person(name):
|
||||
'''
|
||||
This function takes a string which is in the name autocomplete format "name - (id)"
|
||||
and returns a person object
|
||||
'''
|
||||
|
||||
match = re.search(r'\((\d+)\)', name)
|
||||
if not match:
|
||||
return None
|
||||
id = match.group(1)
|
||||
try:
|
||||
person = Person.objects.get(id=id)
|
||||
except (Person.ObjectDoesNoExist, Person.MultipleObjectsReturned):
|
||||
return None
|
||||
return person
|
||||
|
||||
def get_parent_group_choices():
|
||||
area_choices = [(g.id, g.name) for g in Group.objects.filter(type='area',state='active')]
|
||||
other_parents = Group.objects.annotate(children=Count('group')).filter(children__gt=0).order_by('name').exclude(type='area')
|
||||
other_choices = [(g.id, g.name) for g in other_parents]
|
||||
choices = (('Working Group Areas',area_choices),('Other',other_choices))
|
||||
return choices
|
||||
|
||||
# ---------------------------------------------
|
||||
# Forms
|
||||
# ---------------------------------------------
|
||||
|
||||
class DescriptionForm (forms.Form):
|
||||
description = forms.CharField(widget=forms.Textarea(attrs={'rows':'20'}),required=True, strip=False)
|
||||
|
||||
|
||||
|
||||
class RoleForm(forms.Form):
|
||||
name = forms.ModelChoiceField(RoleName.objects.filter(slug__in=('chair','editor','secr','techadv')),empty_label=None)
|
||||
person = forms.CharField(max_length=50,widget=forms.TextInput(attrs={'class':'name-autocomplete'}),help_text="To see a list of people type the first name, or last name, or both.")
|
||||
email = forms.CharField(widget=forms.Select(),help_text="Select an email")
|
||||
group_acronym = forms.CharField(widget=forms.HiddenInput(),required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.group = kwargs.pop('group')
|
||||
super(RoleForm, self).__init__(*args,**kwargs)
|
||||
# this form is re-used in roles app, use different roles in select
|
||||
if self.group.features.custom_group_roles:
|
||||
self.fields['name'].queryset = RoleName.objects.all()
|
||||
|
||||
# check for id within parenthesis to ensure name was selected from the list
|
||||
def clean_person(self):
|
||||
person = self.cleaned_data.get('person', '')
|
||||
m = re.search(r'(\d+)', person)
|
||||
if person and not m:
|
||||
raise forms.ValidationError("You must select an entry from the list!")
|
||||
|
||||
# return person object
|
||||
return get_person(person)
|
||||
|
||||
# check that email exists and return the Email object
|
||||
def clean_email(self):
|
||||
email = self.cleaned_data['email']
|
||||
try:
|
||||
obj = Email.objects.get(address=email)
|
||||
except Email.ObjectDoesNoExist:
|
||||
raise forms.ValidationError("Email address not found!")
|
||||
|
||||
# return email object
|
||||
return obj
|
||||
|
||||
def clean(self):
|
||||
# here we abort if there are any errors with individual fields
|
||||
# One predictable problem is that the user types a name rather then
|
||||
# selecting one from the list, as instructed to do. We need to abort
|
||||
# so the error is displayed before trying to call get_person()
|
||||
if any(self.errors):
|
||||
# Don't bother validating the formset unless each form is valid on its own
|
||||
return
|
||||
super(RoleForm, self).clean()
|
||||
cleaned_data = self.cleaned_data
|
||||
person = cleaned_data['person']
|
||||
email = cleaned_data['email']
|
||||
name = cleaned_data['name']
|
||||
group_acronym = cleaned_data['group_acronym']
|
||||
|
||||
if email.person != person:
|
||||
raise forms.ValidationError('ERROR: The person associated with the chosen email address is different from the chosen person')
|
||||
|
||||
if Role.objects.filter(name=name,group=self.group,person=person,email=email):
|
||||
raise forms.ValidationError('ERROR: This is a duplicate entry')
|
||||
|
||||
if not group_acronym:
|
||||
raise forms.ValidationError('You must select a group.')
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class SearchForm(forms.Form):
|
||||
group_acronym = forms.CharField(max_length=12,required=False)
|
||||
group_name = forms.CharField(max_length=80,required=False)
|
||||
primary_area = forms.ModelChoiceField(queryset=Group.objects.filter(type='area',state='active'),required=False)
|
||||
type = forms.ModelChoiceField(queryset=GroupTypeName.objects.all(),required=False)
|
||||
meeting_scheduled = forms.CharField(widget=forms.Select(choices=SEARCH_MEETING_CHOICES),required=False)
|
||||
state = forms.ModelChoiceField(queryset=GroupStateName.objects.exclude(slug__in=('dormant','unknown')),required=False)
|
|
@ -1,69 +0,0 @@
|
|||
# Copyright The IETF Trust 2013-2020, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from ietf.utils.test_utils import TestCase
|
||||
from ietf.group.models import Group
|
||||
from ietf.secr.groups.forms import get_parent_group_choices
|
||||
from ietf.group.factories import GroupFactory, RoleFactory
|
||||
from ietf.meeting.factories import MeetingFactory
|
||||
from ietf.person.factories import PersonFactory
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
class GroupsTest(TestCase):
|
||||
def test_get_parent_group_choices(self):
|
||||
GroupFactory(type_id='area')
|
||||
choices = get_parent_group_choices()
|
||||
area = Group.objects.filter(type='area',state='active').first()
|
||||
# This is opaque. Can it be rewritten to be more self-documenting?
|
||||
self.assertEqual(choices[0][1][0][0],area.id)
|
||||
|
||||
# ------- Test Search -------- #
|
||||
def test_search(self):
|
||||
"Test Search"
|
||||
MeetingFactory(type_id='ietf')
|
||||
group = GroupFactory()
|
||||
url = reverse('ietf.secr.groups.views.search')
|
||||
post_data = {'group_acronym':group.acronym,'submit':'Search'}
|
||||
self.client.login(username="secretary", password="secretary+password")
|
||||
response = self.client.post(url,post_data,follow=True)
|
||||
self.assertContains(response, group.acronym)
|
||||
|
||||
# ------- Test View -------- #
|
||||
def test_view(self):
|
||||
MeetingFactory(type_id='ietf')
|
||||
group = GroupFactory()
|
||||
url = reverse('ietf.secr.groups.views.view', kwargs={'acronym':group.acronym})
|
||||
self.client.login(username="secretary", password="secretary+password")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
# ------- Test People -------- #
|
||||
def test_people_delete(self):
|
||||
role = RoleFactory(name_id='member')
|
||||
group = role.group
|
||||
id = role.id
|
||||
url = reverse('ietf.secr.groups.views.delete_role', kwargs={'acronym':group.acronym,'id':role.id})
|
||||
target = reverse('ietf.secr.groups.views.people', kwargs={'acronym':group.acronym})
|
||||
self.client.login(username="secretary", password="secretary+password")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.post(url, {'post':'yes'})
|
||||
self.assertRedirects(response, target)
|
||||
self.assertFalse(group.role_set.filter(id=id))
|
||||
|
||||
def test_people_add(self):
|
||||
person = PersonFactory()
|
||||
group = GroupFactory()
|
||||
url = reverse('ietf.secr.groups.views.people', kwargs={'acronym':group.acronym})
|
||||
post_data = {'group_acronym':group.acronym,
|
||||
'name':'chair',
|
||||
'person':'Joe Smith - (%s)' % person.id,
|
||||
'email':person.email_set.all()[0].address,
|
||||
'submit':'Add'}
|
||||
self.client.login(username="secretary", password="secretary+password")
|
||||
response = self.client.post(url,post_data,follow=True)
|
||||
self.assertRedirects(response, url)
|
||||
self.assertContains(response, 'added successfully')
|
|
@ -1,14 +0,0 @@
|
|||
from django.conf import settings
|
||||
|
||||
from ietf.secr.groups import views
|
||||
from ietf.utils.urls import url
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.search),
|
||||
url(r'^blue-dot-report/$', views.blue_dot),
|
||||
#(r'^ajax/get_ads/$', views.get_ads),
|
||||
url(r'^%(acronym)s/$' % settings.URL_REGEXPS, views.view),
|
||||
url(r'^%(acronym)s/delete/(?P<id>\d{1,6})/$' % settings.URL_REGEXPS, views.delete_role),
|
||||
url(r'^%(acronym)s/charter/$' % settings.URL_REGEXPS, views.charter),
|
||||
url(r'^%(acronym)s/people/$' % settings.URL_REGEXPS, views.people),
|
||||
]
|
|
@ -1,301 +0,0 @@
|
|||
from django.contrib import messages
|
||||
from django.conf import settings
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
||||
from ietf.group.models import Group, GroupEvent, Role
|
||||
from ietf.group.utils import save_group_in_history, get_charter_text
|
||||
from ietf.ietfauth.utils import role_required
|
||||
from ietf.person.models import Person
|
||||
from ietf.secr.groups.forms import RoleForm, SearchForm
|
||||
from ietf.secr.utils.meeting import get_current_meeting
|
||||
from ietf.liaisons.views import contacts_from_roles
|
||||
|
||||
# -------------------------------------------------
|
||||
# Helper Functions
|
||||
# -------------------------------------------------
|
||||
|
||||
def add_legacy_fields(group):
|
||||
'''
|
||||
This function takes a Group object as input and adds legacy attributes:
|
||||
start_date,proposed_date,concluded_date,meeting_scheduled
|
||||
'''
|
||||
# it's possible there could be multiple records of a certain type in which case
|
||||
# we just return the latest record
|
||||
query = GroupEvent.objects.filter(group=group, type="changed_state").order_by('time')
|
||||
proposed = query.filter(changestategroupevent__state="proposed")
|
||||
meeting = get_current_meeting()
|
||||
|
||||
if proposed:
|
||||
group.proposed_date = proposed[0].time
|
||||
active = query.filter(changestategroupevent__state="active")
|
||||
if active:
|
||||
group.start_date = active[0].time
|
||||
concluded = query.filter(changestategroupevent__state="conclude")
|
||||
if concluded:
|
||||
group.concluded_date = concluded[0].time
|
||||
|
||||
if group.session_set.filter(meeting__number=meeting.number):
|
||||
group.meeting_scheduled = 'YES'
|
||||
else:
|
||||
group.meeting_scheduled = 'NO'
|
||||
|
||||
group.chairs = group.role_set.filter(name="chair")
|
||||
group.techadvisors = group.role_set.filter(name="techadv")
|
||||
group.editors = group.role_set.filter(name="editor")
|
||||
group.secretaries = group.role_set.filter(name="secr")
|
||||
# Note: liaison_contacts is now a dict instead of a model instance with fields. In
|
||||
# templates, the dict can still be accessed using '.contacts' and .cc_contacts', though.
|
||||
group.liaison_contacts = dict(
|
||||
contacts=contacts_from_roles(group.role_set.filter(name='liaison_contact')),
|
||||
cc_contacts=contacts_from_roles(group.role_set.filter(name='liaison_cc_contact')),
|
||||
)
|
||||
|
||||
#fill_in_charter_info(group)
|
||||
|
||||
#--------------------------------------------------
|
||||
# AJAX Functions
|
||||
# -------------------------------------------------
|
||||
'''
|
||||
def get_ads(request):
|
||||
""" AJAX function which takes a URL parameter, "area" and returns the area directors
|
||||
in the form of a list of dictionaries with "id" and "value" keys(in json format).
|
||||
Used to populate select options.
|
||||
"""
|
||||
|
||||
results=[]
|
||||
area = request.GET.get('area','')
|
||||
qs = AreaDirector.objects.filter(area=area)
|
||||
for item in qs:
|
||||
d = {'id': item.id, 'value': item.person.first_name + ' ' + item.person.last_name}
|
||||
results.append(d)
|
||||
|
||||
return HttpResponse(json.dumps(results), content_type='application/javascript')
|
||||
'''
|
||||
# -------------------------------------------------
|
||||
# Standard View Functions
|
||||
# -------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@role_required('Secretariat')
|
||||
def blue_dot(request):
|
||||
'''
|
||||
This is a report view. It returns a text/plain listing of working group chairs.
|
||||
'''
|
||||
people = Person.objects.filter(role__name__slug='chair',
|
||||
role__group__type='wg',
|
||||
role__group__state__slug__in=('active','bof','proposed')).distinct()
|
||||
chairs = []
|
||||
for person in people:
|
||||
parts = person.name_parts()
|
||||
groups = [ r.group.acronym for r in person.role_set.filter(name__slug='chair',
|
||||
group__type='wg',
|
||||
group__state__slug__in=('active','bof','proposed')) ]
|
||||
entry = {'name':'%s, %s' % (parts[3], parts[1]),
|
||||
'groups': ', '.join(groups)}
|
||||
chairs.append(entry)
|
||||
|
||||
# sort the list
|
||||
sorted_chairs = sorted(chairs, key = lambda a: a['name'])
|
||||
|
||||
return render(request, 'groups/blue_dot_report.txt', { 'chairs':sorted_chairs },
|
||||
content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET,
|
||||
)
|
||||
|
||||
@role_required('Secretariat')
|
||||
def charter(request, acronym):
|
||||
"""
|
||||
View Group Charter
|
||||
|
||||
**Templates:**
|
||||
|
||||
* ``groups/charter.html``
|
||||
|
||||
**Template Variables:**
|
||||
|
||||
* group, charter_text
|
||||
|
||||
"""
|
||||
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
# TODO: get_charter_text() should be updated to return None
|
||||
if group.charter:
|
||||
charter_text = get_charter_text(group)
|
||||
else:
|
||||
charter_text = ''
|
||||
|
||||
return render(request, 'groups/charter.html', {
|
||||
'group': group,
|
||||
'charter_text': charter_text},
|
||||
)
|
||||
|
||||
@role_required('Secretariat')
|
||||
def delete_role(request, acronym, id):
|
||||
"""
|
||||
Handle deleting roles for groups (chair, editor, advisor, secretary)
|
||||
|
||||
**Templates:**
|
||||
|
||||
* none
|
||||
|
||||
Redirects to people page on success.
|
||||
|
||||
"""
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
role = get_object_or_404(Role, id=id)
|
||||
|
||||
if request.method == 'POST' and request.POST['post'] == 'yes':
|
||||
# save group
|
||||
save_group_in_history(group)
|
||||
|
||||
role.delete()
|
||||
messages.success(request, 'The entry was deleted successfully')
|
||||
return redirect('ietf.secr.groups.views.people', acronym=acronym)
|
||||
|
||||
return render(request, 'confirm_delete.html', {'object': role})
|
||||
|
||||
|
||||
@role_required('Secretariat')
|
||||
def people(request, acronym):
|
||||
"""
|
||||
Edit Group Roles (Chairs, Secretary, etc)
|
||||
|
||||
**Templates:**
|
||||
|
||||
* ``groups/people.html``
|
||||
|
||||
**Template Variables:**
|
||||
|
||||
* form, group
|
||||
|
||||
"""
|
||||
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
|
||||
if request.method == 'POST':
|
||||
# we need to pass group for form validation
|
||||
form = RoleForm(request.POST,group=group)
|
||||
if form.is_valid():
|
||||
name = form.cleaned_data['name']
|
||||
person = form.cleaned_data['person']
|
||||
email = form.cleaned_data['email']
|
||||
|
||||
# save group
|
||||
save_group_in_history(group)
|
||||
|
||||
Role.objects.create(name=name,
|
||||
person=person,
|
||||
email=email,
|
||||
group=group)
|
||||
|
||||
if not email.origin or email.origin == person.user.username:
|
||||
email.origin = "role: %s %s" % (group.acronym, name.slug)
|
||||
email.save()
|
||||
|
||||
messages.success(request, 'New %s added successfully!' % name)
|
||||
return redirect('ietf.secr.groups.views.people', acronym=group.acronym)
|
||||
else:
|
||||
form = RoleForm(initial={'name':'chair', 'group_acronym':group.acronym}, group=group)
|
||||
|
||||
return render(request, 'groups/people.html', {
|
||||
'form':form,
|
||||
'group':group},
|
||||
)
|
||||
|
||||
@role_required('Secretariat')
|
||||
def search(request):
|
||||
"""
|
||||
Search IETF Groups
|
||||
|
||||
**Templates:**
|
||||
|
||||
* ``groups/search.html``
|
||||
|
||||
**Template Variables:**
|
||||
|
||||
* form, results
|
||||
|
||||
"""
|
||||
results = []
|
||||
if request.method == 'POST':
|
||||
form = SearchForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
kwargs = {}
|
||||
group_acronym = form.cleaned_data['group_acronym']
|
||||
group_name = form.cleaned_data['group_name']
|
||||
primary_area = form.cleaned_data['primary_area']
|
||||
meeting_scheduled = form.cleaned_data['meeting_scheduled']
|
||||
state = form.cleaned_data['state']
|
||||
type = form.cleaned_data['type']
|
||||
meeting = get_current_meeting()
|
||||
|
||||
# construct search query
|
||||
if group_acronym:
|
||||
kwargs['acronym__istartswith'] = group_acronym
|
||||
if group_name:
|
||||
kwargs['name__istartswith'] = group_name
|
||||
if primary_area:
|
||||
kwargs['parent'] = primary_area
|
||||
if state:
|
||||
kwargs['state'] = state
|
||||
if type:
|
||||
kwargs['type'] = type
|
||||
#else:
|
||||
# kwargs['type__in'] = ('wg','rg','ietf','ag','sdo','team')
|
||||
|
||||
if meeting_scheduled == 'YES':
|
||||
kwargs['session__meeting__number'] = meeting.number
|
||||
# perform query
|
||||
if kwargs:
|
||||
if meeting_scheduled == 'NO':
|
||||
qs = Group.objects.filter(**kwargs).exclude(session__meeting__number=meeting.number).distinct()
|
||||
else:
|
||||
qs = Group.objects.filter(**kwargs).distinct()
|
||||
else:
|
||||
qs = Group.objects.all()
|
||||
results = qs.order_by('acronym')
|
||||
|
||||
# if there's just one result go straight to view
|
||||
if len(results) == 1:
|
||||
return redirect('ietf.secr.groups.views.view', acronym=results[0].acronym)
|
||||
|
||||
# process GET argument to support link from area app
|
||||
elif 'primary_area' in request.GET:
|
||||
area = request.GET.get('primary_area','')
|
||||
results = Group.objects.filter(parent__id=area,type='wg',state__in=('bof','active','proposed')).order_by('name')
|
||||
form = SearchForm({'primary_area':area,'state':'','type':'wg'})
|
||||
else:
|
||||
form = SearchForm(initial={'state':'active'})
|
||||
|
||||
# loop through results and tack on meeting_scheduled because it is no longer an
|
||||
# attribute of the meeting model
|
||||
for result in results:
|
||||
add_legacy_fields(result)
|
||||
|
||||
return render(request, 'groups/search.html', {
|
||||
'results': results,
|
||||
'form': form},
|
||||
)
|
||||
|
||||
@role_required('Secretariat')
|
||||
def view(request, acronym):
|
||||
"""
|
||||
View IETF Group details
|
||||
|
||||
**Templates:**
|
||||
|
||||
* ``groups/view.html``
|
||||
|
||||
**Template Variables:**
|
||||
|
||||
* group
|
||||
|
||||
"""
|
||||
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
|
||||
add_legacy_fields(group)
|
||||
|
||||
return render(request, 'groups/view.html', { 'group': group } )
|
||||
|
|
@ -43,7 +43,6 @@
|
|||
<!-- <li><button type="button" onclick="window.location='../../'">Back</button></li> -->
|
||||
<li><button type="button" onclick="window.location='edit/'">Edit</button></li>
|
||||
<li><button type="button" onclick="window.location='people/'">People</button></li>
|
||||
<li><button type="button" onclick="window.location='{% url 'ietf.secr.groups.views.search' %}?primary_area={{ area.id }}'">Groups</button></li>
|
||||
</ul>
|
||||
</div> <!-- button-group -->
|
||||
</div> <!-- module -->
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
BLUE DOT REPORT
|
||||
|
||||
NAMES ROSTER BADGE
|
||||
--------------------------------------------------------------------------
|
||||
{% for chair in chairs %}{{ chair.name|safe|stringformat:"-33s" }}{{ chair.groups|stringformat:"-36s" }}BLUE
|
||||
{% endfor %}
|
|
@ -1,25 +0,0 @@
|
|||
{% extends "base_site.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Groups - Charter{% endblock %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script src="{% static 'secr/js/utils.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{{ block.super }}
|
||||
» <a href="../../">Groups</a>
|
||||
» <a href="../">{{ group.acronym }}</a>
|
||||
» Charter
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="module group-container">
|
||||
<h2>Groups - Charter</h2>
|
||||
<pre>
|
||||
{% if charter_txt %}{{ charter_text }}{% else %}Charter not found.{% endif %}
|
||||
</pre>
|
||||
</div> <!-- module -->
|
||||
|
||||
{% endblock %}
|
|
@ -1,72 +0,0 @@
|
|||
{% extends "base_site.html" %}
|
||||
{% load staticfiles widget_tweaks %}
|
||||
|
||||
{% block title %}Groups - People{% endblock %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<link rel="stylesheet" href="{% static 'ietf/css/jquery-ui.css' %}">
|
||||
<script src="{% static 'ietf/js/jquery-ui.js' %}"></script>
|
||||
<script src="{% static 'secr/js/utils.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{{ block.super }}
|
||||
» <a href="../../">Groups</a>
|
||||
» <a href="../">{{ group.acronym }}</a>
|
||||
» People
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="module">
|
||||
<h2>People</h2>
|
||||
<table class="full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Role</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Email</th>
|
||||
<th scope="col">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% if group.role_set.all %}
|
||||
<tbody>
|
||||
{% for role in group.role_set.all %}
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
<td>{{ role.name }}</td>
|
||||
<td>{{ role.person }}</td>
|
||||
<td>{{ role.email }}</td>
|
||||
<td><a href="{% url 'ietf.secr.groups.views.delete_role' acronym=group.acronym id=role.id %}">Delete</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
||||
<div class="inline-related">
|
||||
<!-- <hr><br> -->
|
||||
<h3>Add Role</h3>
|
||||
<form id="groups-people" method="post">{% csrf_token %}
|
||||
{{ form.non_field_errors }}
|
||||
{{ form.group_acronym }}
|
||||
<table class="full-width">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ form.name.errors }}{{ form.name|attr:"aria-label:Name" }}</td>
|
||||
<td>{{ form.person.errors }}{{ form.person|attr:"aria-label:Person" }}{% if form.person.help_text %}<br>{{ form.person.help_text }}{% endif %}</td>
|
||||
<td>{{ form.email.errors }}{{ form.email|attr:"aria-label:Email" }}{% if form.email.help_text %}<br>{{ form.email.help_text }}{% endif %}</td>
|
||||
<td><button type="submit" name="submit">Add</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div> <!-- inline-related -->
|
||||
|
||||
<div class="button-group">
|
||||
<ul>
|
||||
<li><button type="button" onclick="window.location='../'">Back</button></li>
|
||||
</ul>
|
||||
</div> <!-- button-group -->
|
||||
|
||||
</div> <!-- module -->
|
||||
|
||||
{% endblock %}
|
|
@ -1,39 +0,0 @@
|
|||
{% extends "base_site.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Groups - Search{% endblock %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
|
||||
<script src="{% static 'secr/js/utils.js' %}"></script>
|
||||
<script src="{% static "ietf/js/list.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{{ block.super }}
|
||||
» Groups
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="module group-container">
|
||||
<h2>Groups - Search</h2>
|
||||
<form enctype="multipart/form-data" method="post">{% csrf_token %}
|
||||
<table class="full-width amstable">
|
||||
<tbody>
|
||||
<!-- [html-validate-disable-block wcag/h63 -- FIXME: as_table renders without scope] -->
|
||||
{{ form.as_table }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% include "includes/buttons_search.html" %}
|
||||
|
||||
</form>
|
||||
|
||||
<div class="inline-related">
|
||||
<h2>Search Results</h2>
|
||||
{% include "includes/group_search_results.html" %}
|
||||
{% if not_found %}{{ not_found }}{% endif %}
|
||||
</div> <!-- inline-group -->
|
||||
</div> <!-- module -->
|
||||
|
||||
{% endblock %}
|
|
@ -1,123 +0,0 @@
|
|||
{% extends "base_site.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Groups - View{% endblock %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script src="{% static 'secr/js/utils.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{{ block.super }}
|
||||
» <a href="../">Groups</a>
|
||||
» {{ group.acronym }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="module group-container">
|
||||
<div id="groups-view-col1">
|
||||
<h2>Groups - View</h2>
|
||||
<table >
|
||||
<tbody>
|
||||
<tr><td>Group Acronym:</td><td>{{ group.acronym }}</td></tr>
|
||||
<tr><td>Group Name:</td><td>{{ group.name }}</td></tr>
|
||||
<tr><td>Status:</td><td>{{ group.state }}</td></tr>
|
||||
<tr><td>Type:</td><td>{{ group.type }}</td></tr>
|
||||
<tr><td>Proposed Date:</td><td>{{ group.proposed_date|date:"Y-m-d" }}</td></tr>
|
||||
<tr><td>Start Date:</td><td>{{ group.start_date|date:"Y-m-d" }}</td></tr>
|
||||
<tr><td>Concluded Date:</td><td>{{ group.concluded_date|date:"Y-m-d" }}</td></tr>
|
||||
{% comment %}
|
||||
Here we need to check that group.area_director and group.area_director.area are defined before referencing.
|
||||
Otherwise the template would raise errors if the group area director record didn't exist or
|
||||
in the case of Area Director = TBD, the area field is NULL
|
||||
{% endcomment %}
|
||||
<tr><td>Primary Area:</td>
|
||||
<td>{% if not group.parent %}(No Data){% else %}
|
||||
<a href="{% url "ietf.secr.areas.views.view" name=group.parent.acronym %}">{{ group.parent }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>Primary Area Director:</td>
|
||||
<td>{% if group.ad_role %}
|
||||
<a href="{% url 'ietf.secr.rolodex.views.view' id=group.ad_role.person.id %}">{{ group.ad_role.person }}</a>
|
||||
{% endif %}
|
||||
</td></tr>
|
||||
<tr><td>Meeting Scheduled:</td><td>{{ group.meeting_scheduled}}</td></tr>
|
||||
<tr><td>Email Address:</td><td>{{ group.list_email }}</td></tr>
|
||||
<tr><td>Email Subscription:</td><td>{{ group.list_subscribe }}</td></tr>
|
||||
<tr><td>Email Archive:</td><td>{{ group.list_archive }}</td></tr>
|
||||
{% if group.liaison_contacts %}
|
||||
<tr><td>Default Liaison Contacts:</td><td>{{ group.liaison_contacts.contacts }}</td></tr>
|
||||
{% endif %}
|
||||
{% if group.features.has_chartering_process %}
|
||||
<tr><td>Charter:</td><td><a href="{% url 'ietf.secr.groups.views.charter' acronym=group.acronym %}">View Charter</a></td></tr>
|
||||
{% else %}
|
||||
<tr><td>Description:</td><td>{{ group.description }}</td></tr>
|
||||
{% endif %}
|
||||
<tr><td>Comments:</td><td>{{ group.comments }}</td></tr>
|
||||
<tr><td>Last Modified Date:</td><td>{{ group.time }}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div> <!-- groups-view-col1 -->
|
||||
<div id="groups-view-col2">
|
||||
<div class="inline-related">
|
||||
<h2>Chairperson(s)</h2>
|
||||
{% if group.chairs %}
|
||||
<table>
|
||||
{% for role in group.chairs %}
|
||||
<tr><td><a href="{% url 'ietf.secr.rolodex.views.view' id=role.person.id %}">{{ role.person }}</a></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div> <!-- inline-related -->
|
||||
|
||||
<div class="inline-related">
|
||||
<h2>Document Editor(s)</h2>
|
||||
{% if group.editors %}
|
||||
<table>
|
||||
{% for role in group.editors %}
|
||||
<tr><td><a href="{% url 'ietf.secr.rolodex.views.view' id=role.person.id %}">{{ role.person }}</a></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div> <!-- inline-related -->
|
||||
|
||||
<div class="inline-related">
|
||||
<h2>Technical Advisor(s)</h2>
|
||||
{% if group.techadvisors %}
|
||||
<table>
|
||||
{% for role in group.techadvisors %}
|
||||
<tr><td><a href="{% url 'ietf.secr.rolodex.views.view' id=role.person.id %}">{{ role.person }}</a></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div> <!-- inline-related -->
|
||||
|
||||
<div class="inline-related">
|
||||
<h2>Secretary(ies)</h2>
|
||||
{% if group.secretaries %}
|
||||
<table>
|
||||
{% for role in group.secretaries %}
|
||||
<tr><td><a href="{% url 'ietf.secr.rolodex.views.view' id=role.person.id %}">{{ role.person }}</a></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div> <!-- inline-related -->
|
||||
|
||||
</div> <!-- groups-view-col2 -->
|
||||
|
||||
<div class="button-group">
|
||||
<ul>
|
||||
<li><button type="button" onclick="window.location='edit/'">Edit</button></li>
|
||||
<li><button type="button" onclick="window.location='people/'">People</button></li>
|
||||
{% comment %}
|
||||
<li><button type="button" onclick="window.location='{% url "sec.ids.views.search" id=group.group_acronym.acronym_id %}'">Drafts</button></li>
|
||||
<li><button type="button" onclick="window.location='{% url "sec.rfcs.views.search" id=group.group_acronym.acronym_id %}'">RFCs</button></li>
|
||||
{% endcomment %}
|
||||
</ul>
|
||||
</div> <!-- button-group -->
|
||||
</div> <!-- module -->
|
||||
|
||||
{% endblock %}
|
|
@ -1,24 +0,0 @@
|
|||
<table id="group-search-results" class="center" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Group Name</th>
|
||||
<th scope="col">Group Acronym</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Meeting Scheduled</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in results %}
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
<td><a href="{% url 'ietf.secr.groups.views.view' acronym=item.acronym %}">{{item.name}}</a></td>
|
||||
<td>{{item.acronym}}</td>
|
||||
<td>{{item.state}}</td>
|
||||
<td>{{item.type}}</td>
|
||||
<td>{{item.meeting_scheduled}}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td><b>No Results</b></td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
|
@ -21,7 +21,6 @@
|
|||
<h2>IDs and WGs Process</h2>
|
||||
<ul>
|
||||
<li> <a href="{% url "ietf.secr.areas.views.list_areas" %}"><b>Areas</b></a></li>
|
||||
<li> <a href="{% url 'ietf.secr.groups.views.search' %}"><b>Groups</b></a></li>
|
||||
<li> <a href="{% url 'ietf.secr.rolodex.views.search' %}"><b>Rolodex</b></a></li>
|
||||
</ul>
|
||||
</td>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
{% if role.group.type.slug == "area" %}
|
||||
<a href="{% url "ietf.secr.areas.views.view" name=role.group.acronym %}">{{ role.group.acronym }}{% if role.group.state.slug == "conclude" %} (concluded){% endif %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'ietf.secr.groups.views.view' acronym=role.group.acronym %}">{{ role.group.acronym }}{% if role.group.state.slug == "conclude" %} (concluded){% endif %}</a>
|
||||
<a href="{% url 'ietf.group.views.group_home' acronym=role.group.acronym %}">{{ role.group.acronym }}{% if role.group.state.slug == "conclude" %} (concluded){% endif %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ role.email }}</td>
|
||||
|
|
|
@ -6,7 +6,6 @@ urlpatterns = [
|
|||
url(r'^announcement/', include('ietf.secr.announcement.urls')),
|
||||
url(r'^areas/', include('ietf.secr.areas.urls')),
|
||||
url(r'^console/', include('ietf.secr.console.urls')),
|
||||
url(r'^groups/', include('ietf.secr.groups.urls')),
|
||||
url(r'^meetings/', include('ietf.secr.meetings.urls')),
|
||||
url(r'^rolodex/', include('ietf.secr.rolodex.urls')),
|
||||
url(r'^sreq/', include('ietf.secr.sreq.urls')),
|
||||
|
|
|
@ -476,7 +476,6 @@ INSTALLED_APPS = [
|
|||
# IETF Secretariat apps
|
||||
'ietf.secr.announcement',
|
||||
'ietf.secr.areas',
|
||||
'ietf.secr.groups',
|
||||
'ietf.secr.meetings',
|
||||
'ietf.secr.rolodex',
|
||||
'ietf.secr.sreq',
|
||||
|
|
Loading…
Reference in a new issue