Rename Meeting.agenda to Meeting.schedule together with a bunch of

related internal things
 - Legacy-Id: 17051
This commit is contained in:
Ole Laursen 2019-11-18 17:22:19 +00:00
parent 4049804920
commit 0555879777
34 changed files with 322 additions and 290 deletions

View file

@ -1,3 +1,4 @@
# Copyright The IETF Trust 2013-2019, All Rights Reserved
import json
from django.shortcuts import get_object_or_404, redirect
@ -7,9 +8,9 @@ from django.http import Http404
from django.views.decorators.http import require_POST
from ietf.ietfauth.utils import role_required, has_role
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_person_by_email, get_schedule_by_name
from ietf.meeting.helpers import get_meeting, get_schedule, schedule_permissions, get_person_by_email, get_schedule_by_name
from ietf.meeting.models import TimeSlot, Session, Schedule, Room, Constraint, SchedTimeSessAssignment, ResourceAssociation
from ietf.meeting.views import edit_timeslots, edit_agenda
from ietf.meeting.views import edit_timeslots, edit_schedule
import debug # pyflakes:ignore
@ -43,8 +44,8 @@ def get_meeting_schedule(num, owner, name):
# should asking if an agenda is read-only require any kind of permission?
def agenda_permission_api(request, num, owner, name):
# should asking if an schedule is read-only require any kind of permission?
def schedule_permission_api(request, num, owner, name):
meeting = get_meeting(num)
person = get_person_by_email(owner)
schedule = get_schedule_by_name(meeting, person, name)
@ -56,7 +57,7 @@ def agenda_permission_api(request, num, owner, name):
owner_href = ""
if schedule is not None:
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
owner_href = request.build_absolute_uri(schedule.owner.json_url())
if has_role(request.user, "Area Director") or secretariat:
@ -256,39 +257,39 @@ def timeslot_sloturl(request, num=None, slotid=None):
return timeslot_delslot(request, meeting, slotid)
#############################################################################
## Agenda List API
## Schedule List API
#############################################################################
AgendaEntryForm = modelform_factory(Schedule, exclude=('meeting','owner'))
EditAgendaEntryForm = modelform_factory(Schedule, exclude=('meeting','owner', 'name'))
ScheduleEntryForm = modelform_factory(Schedule, exclude=('meeting','owner'))
EditScheduleEntryForm = modelform_factory(Schedule, exclude=('meeting','owner', 'name'))
@role_required('Area Director','Secretariat')
def agenda_list(request, mtg):
agendas = mtg.schedule_set.all()
def schedule_list(request, mtg):
schedules = mtg.schedule_set.all()
json_array=[]
for agenda in agendas:
json_array.append(agenda.json_dict(request.build_absolute_uri('/')))
for schedule in schedules:
json_array.append(schedule.json_dict(request.build_absolute_uri('/')))
return HttpResponse(json.dumps(json_array),
content_type="application/json")
# duplicates save-as functionality below.
@role_required('Area Director','Secretariat')
def agenda_add(request, meeting):
newagendaform = AgendaEntryForm(request.POST)
if not newagendaform.is_valid():
def schedule_add(request, meeting):
newscheduleform = ScheduleEntryForm(request.POST)
if not newscheduleform.is_valid():
return HttpResponse(status=404)
newagenda = newagendaform.save(commit=False)
newagenda.meeting = meeting
newagenda.owner = request.user.person
newagenda.save()
newschedule = newscheduleform.save(commit=False)
newschedule.meeting = meeting
newschedule.owner = request.user.person
newschedule.save()
if "HTTP_ACCEPT" in request.META and "application/json" in request.META['HTTP_ACCEPT']:
return redirect(agenda_infourl, meeting.number, newagenda.owner_email(), newagenda.name)
return redirect(schedule_infourl, meeting.number, newschedule.owner_email(), newschedule.name)
else:
return redirect(edit_agenda, meeting.number, newagenda.owner_email(), newagenda.name)
return redirect(edit_schedule, meeting.number, newschedule.owner_email(), newschedule.name)
@require_POST
def agenda_update(request, meeting, schedule):
def schedule_update(request, meeting, schedule):
# forms are completely useless for update actions that want to
# accept a subset of values. (huh? we could use required=False)
@ -297,7 +298,7 @@ def agenda_update(request, meeting, schedule):
if not user.is_authenticated:
return HttpResponse({'error':'no permission'}, status=403)
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
#read_only = not canedit ## not used
# TODO: Secretariat should always get canedit
@ -316,53 +317,53 @@ def agenda_update(request, meeting, schedule):
schedule.save()
# enforce that a non-public schedule can not be the public one.
if meeting.agenda == schedule and not schedule.public:
meeting.agenda = None
if meeting.schedule == schedule and not schedule.public:
meeting.schedule = None
meeting.save()
if "HTTP_ACCEPT" in request.META and "application/json" in request.META['HTTP_ACCEPT']:
return HttpResponse(json.dumps(schedule.json_dict(request.build_absolute_uri('/'))),
content_type="application/json")
else:
return redirect(edit_agenda, meeting.number, schedule.owner_email(), schedule.name)
return redirect(edit_schedule, meeting.number, schedule.owner_email(), schedule.name)
@role_required('Secretariat')
def agenda_del(request, meeting, schedule):
def schedule_del(request, meeting, schedule):
schedule.delete_assignments()
#debug.log("deleting meeting: %s agenda: %s" % (meeting, meeting.agenda))
if meeting.agenda == schedule:
meeting.agenda = None
#debug.log("deleting meeting: %s schedule: %s" % (meeting, meeting.schedule))
if meeting.schedule == schedule:
meeting.schedule = None
meeting.save()
schedule.delete()
return HttpResponse('{"error":"none"}', status = 200)
def agenda_infosurl(request, num=None):
def schedule_infosurl(request, num=None):
meeting = get_meeting(num)
if request.method == 'GET':
return agenda_list(request, meeting)
return schedule_list(request, meeting)
elif request.method == 'POST':
return agenda_add(request, meeting)
return schedule_add(request, meeting)
# unacceptable action
return HttpResponse(status=406)
def agenda_infourl(request, num=None, owner=None, name=None):
def schedule_infourl(request, num=None, owner=None, name=None):
meeting = get_meeting(num)
person = get_person_by_email(owner)
schedule = get_schedule_by_name(meeting, person, name)
if schedule is None:
raise Http404("No meeting information for meeting %s schedule %s available" % (num,name))
#debug.log("results in agenda: %u / %s" % (schedule.id, request.method))
#debug.log("results in schedule: %u / %s" % (schedule.id, request.method))
if request.method == 'GET':
return HttpResponse(json.dumps(schedule.json_dict(request.build_absolute_uri('/'))),
content_type="application/json")
elif request.method == 'POST':
return agenda_update(request, meeting, schedule)
return schedule_update(request, meeting, schedule)
elif request.method == 'DELETE':
return agenda_del(request, meeting, schedule)
return schedule_del(request, meeting, schedule)
else:
return HttpResponse(status=406)
@ -377,22 +378,22 @@ def meeting_get(request, meeting):
@role_required('Secretariat')
def meeting_update(request, meeting):
# at present, only the official agenda can be updated from this interface.
# at present, only the official schedule can be updated from this interface.
#debug.log("1 meeting.agenda: %s / %s / %s" % (meeting.agenda, update_dict, request.body))
if "agenda" in request.POST:
value = request.POST["agenda"]
#debug.log("4 meeting.agenda: %s" % (value))
#debug.log("1 meeting.schedule: %s / %s / %s" % (meeting.schedule, update_dict, request.body))
if "schedule" in request.POST:
value = request.POST["schedule"]
#debug.log("4 meeting.schedule: %s" % (value))
if not value or value == "None": # value == "None" is just weird, better with empty string
meeting.set_official_agenda(None)
meeting.set_official_schedule(None)
else:
schedule = get_schedule(meeting, value)
if not schedule.public:
return HttpResponse(status = 406)
#debug.log("3 meeting.agenda: %s" % (schedule))
meeting.set_official_agenda(schedule)
#debug.log("3 meeting.schedule: %s" % (schedule))
meeting.set_official_schedule(schedule)
#debug.log("2 meeting.agenda: %s" % (meeting.agenda))
#debug.log("2 meeting.schedule: %s" % (meeting.schedule))
meeting.save()
return meeting_get(request, meeting)
@ -442,9 +443,9 @@ def sessions_json(request, num):
# this creates an entirely *NEW* schedtimesessassignment
def assignments_post(request, meeting, schedule):
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
if not canedit:
return HttpResponse(json.dumps({'error':'no permission to modify this agenda'}),
return HttpResponse(json.dumps({'error':'no permission to modify this schedule'}),
status = 403,
content_type="application/json")
@ -491,7 +492,7 @@ def assignments_get(request, num, schedule):
return HttpResponse(json.dumps(sess1_dict, sort_keys=True, indent=2),
content_type="application/json")
# this returns the list of scheduled sessions for the given named agenda
# this returns the list of scheduled sessions for the given named schedule
def assignments_json(request, num, owner, name):
info = get_meeting_schedule(num, owner, name)
# The return values from get_meeting_schedule() are silly, in that it
@ -512,9 +513,9 @@ def assignments_json(request, num, owner, name):
# accepts both POST and PUT in order to implement Postel Doctrine.
def assignment_update(request, meeting, schedule, ss):
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
if not canedit:
return HttpResponse(json.dumps({'error':'no permission to update this agenda'}),
return HttpResponse(json.dumps({'error':'no permission to update this schedule'}),
status = 403,
content_type="application/json")
@ -530,9 +531,9 @@ def assignment_update(request, meeting, schedule, ss):
content_type="application/json")
def assignment_delete(request, meeting, schedule, ss):
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
if not canedit:
return HttpResponse(json.dumps({'error':'no permission to update this agenda'}),
return HttpResponse(json.dumps({'error':'no permission to update this schedule'}),
status = 403,
content_type="application/json")
@ -552,10 +553,10 @@ def assignment_delete(request, meeting, schedule, ss):
content_type="application/json")
def assignment_get(request, meeting, schedule, ss):
cansee,canedit,secretariat = agenda_permissions(meeting, schedule, request.user)
cansee,canedit,secretariat = schedule_permissions(meeting, schedule, request.user)
if not cansee:
return HttpResponse(json.dumps({'error':'no permission to see this agenda'}),
return HttpResponse(json.dumps({'error':'no permission to see this schedule'}),
status = 403,
content_type="application/json")

View file

@ -63,9 +63,9 @@ class MeetingFactory(factory.DjangoModelFactory):
@factory.post_generation
def populate_agenda(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
def populate_schedule(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
'''
Create a default agenda, unless the factory is called
Create a default schedule, unless the factory is called
with populate_agenda=False
'''
if extracted is None:
@ -73,7 +73,7 @@ class MeetingFactory(factory.DjangoModelFactory):
if create and extracted:
for x in range(3):
TimeSlotFactory(meeting=obj)
obj.agenda = ScheduleFactory(meeting=obj)
obj.schedule = ScheduleFactory(meeting=obj)
obj.save()
class SessionFactory(factory.DjangoModelFactory):
@ -96,7 +96,7 @@ class SessionFactory(factory.DjangoModelFactory):
extracted = True
if create and extracted:
ts = obj.meeting.timeslot_set.all()
obj.timeslotassignments.create(timeslot=ts[random.randrange(len(ts))],schedule=obj.meeting.agenda)
obj.timeslotassignments.create(timeslot=ts[random.randrange(len(ts))],schedule=obj.meeting.schedule)
class ScheduleFactory(factory.DjangoModelFactory):
class Meta:
@ -175,4 +175,4 @@ class SlideSubmissionFactory(factory.DjangoModelFactory):
make_file = factory.PostGeneration(
lambda obj, create, extracted, **kwargs: open(obj.staged_filepath(),'a').close()
)
)

View file

@ -187,11 +187,11 @@ class InterimMeetingModelForm(forms.ModelForm):
if kwargs.get('commit', True):
# create schedule with meeting
meeting.save() # pre-save so we have meeting.pk for schedule
if not meeting.agenda:
meeting.agenda = Schedule.objects.create(
if not meeting.schedule:
meeting.schedule = Schedule.objects.create(
meeting=meeting,
owner=Person.objects.get(name='(System)'))
meeting.save() # save with agenda
meeting.save() # save with schedule
# create directories
make_materials_directories(meeting)

View file

@ -138,14 +138,14 @@ def get_ietf_meeting(num=None):
def get_schedule(meeting, name=None):
if name is None:
schedule = meeting.agenda
schedule = meeting.schedule
else:
schedule = get_object_or_404(meeting.schedule_set, name=name)
return schedule
def get_schedule_by_id(meeting, schedid):
if schedid is None:
schedule = meeting.agenda
schedule = meeting.schedule
else:
schedule = get_object_or_404(meeting.schedule_set, id=int(schedid))
return schedule
@ -271,7 +271,7 @@ def convert_draft_to_pdf(doc_name):
pipe("ps2pdf "+psname+" "+outpath)
os.unlink(psname)
def agenda_permissions(meeting, schedule, user):
def schedule_permissions(meeting, schedule, user):
# do this in positive logic.
cansee = False
canedit = False
@ -389,7 +389,7 @@ def create_interim_meeting(group, date, city='', country='', timezone='UTC',
owner=person,
visible=True,
public=True)
meeting.agenda = schedule
meeting.schedule = schedule
meeting.save()
return meeting
@ -622,7 +622,7 @@ def update_interim_session_assignment(form):
SchedTimeSessAssignment.objects.create(
timeslot=slot,
session=session,
schedule=session.meeting.agenda)
schedule=session.meeting.schedule)
def populate_important_dates(meeting):
assert ImportantDate.objects.filter(meeting=meeting).exists() is False

View file

@ -0,0 +1,28 @@
# Copyright The IETF Trust 2019, All Rights Reserved
# -*- coding: utf-8 -*-
# Generated by Django 1.11.26 on 2019-11-18 04:01
from __future__ import unicode_literals
from django.db import migrations
import django.db.models.deletion
import ietf.utils.models
class Migration(migrations.Migration):
dependencies = [
('meeting', '0020_remove_future_break_sessions'),
]
operations = [
migrations.RenameField(
model_name='meeting',
old_name='agenda',
new_name='schedule',
),
migrations.AlterField(
model_name='schedule',
name='meeting',
field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedule_set', to='meeting.Meeting'),
),
]

View file

@ -102,7 +102,7 @@ class Meeting(models.Model):
reg_area = models.CharField(blank=True, max_length=255)
agenda_info_note = models.TextField(blank=True, help_text="Text in this field will be placed at the top of the html agenda page for the meeting. HTML can be used, but will not be validated.")
agenda_warning_note = models.TextField(blank=True, help_text="Text in this field will be placed more prominently at the top of the html agenda page for the meeting. HTML can be used, but will not be validated.")
agenda = ForeignKey('Schedule',null=True,blank=True, related_name='+')
schedule = ForeignKey('Schedule',null=True,blank=True, related_name='+')
session_request_lock_message = models.CharField(blank=True,max_length=255) # locked if not empty
proceedings_final = models.BooleanField(default=False, help_text="Are the proceedings for this meeting complete?")
acknowledgements = models.TextField(blank=True, help_text="Acknowledgements for use in meeting proceedings. Use ReStructuredText markup.")
@ -217,8 +217,8 @@ class Meeting(models.Model):
# unfortunately, using the datetime aware json encoder seems impossible,
# so the dates are formatted as strings here.
agenda_url = ""
if self.agenda:
agenda_url = urljoin(host_scheme, self.agenda.base_url())
if self.schedule:
agenda_url = urljoin(host_scheme, self.schedule.base_url())
return {
'href': urljoin(host_scheme, self.json_url()),
'name': self.number,
@ -290,16 +290,16 @@ class Meeting(models.Model):
pass
return ''
def set_official_agenda(self, agenda):
if self.agenda != agenda:
self.agenda = agenda
def set_official_schedule(self, schedule):
if self.schedule != schedule:
self.schedule = schedule
self.save()
def updated(self):
min_time = datetime.datetime(1970, 1, 1, 0, 0, 0) # should be Meeting.modified, but we don't have that
timeslots_updated = self.timeslot_set.aggregate(Max('modified'))["modified__max"] or min_time
sessions_updated = self.session_set.aggregate(Max('modified'))["modified__max"] or min_time
assignments_updated = (self.agenda.assignments.aggregate(Max('modified'))["modified__max"] or min_time) if self.agenda else min_time
assignments_updated = (self.schedule.assignments.aggregate(Max('modified'))["modified__max"] or min_time) if self.schedule else min_time
ts = max(timeslots_updated, sessions_updated, assignments_updated)
tz = pytz.timezone(settings.PRODUCTION_TIMEZONE)
ts = tz.localize(ts)
@ -459,7 +459,7 @@ class TimeSlot(models.Model):
@property
def session(self):
if not hasattr(self, "_session_cache"):
self._session_cache = self.sessions.filter(timeslotassignments__schedule=self.meeting.agenda).first()
self._session_cache = self.sessions.filter(timeslotassignments__schedule=self.meeting.schedule).first()
return self._session_cache
@property
@ -609,15 +609,15 @@ class TimeSlot(models.Model):
@python_2_unicode_compatible
class Schedule(models.Model):
"""
Each person may have multiple agendas saved.
An Agenda may be made visible, which means that it will show up in
Each person may have multiple schedules saved.
An Schedule may be made visible, which means that it will show up in
public drop down menus, etc. It may also be made public, which means
that someone who knows about it by name/id would be able to reference
it. A non-visible, public agenda might be passed around by the
it. A non-visible, public schedule might be passed around by the
Secretariat to IESG members for review. Only the owner may edit the
agenda, others may copy it
schedule, others may copy it
"""
meeting = ForeignKey(Meeting, null=True)
meeting = ForeignKey(Meeting, null=True, related_name='schedule_set')
name = models.CharField(max_length=16, blank=False)
owner = ForeignKey(Person)
visible = models.BooleanField(default=True, help_text="Make this agenda available to those who know about it.")
@ -666,7 +666,7 @@ class Schedule(models.Model):
@property
def is_official(self):
return (self.meeting.agenda == self)
return (self.meeting.schedule == self)
# returns a dictionary {group -> [schedtimesessassignment+]}
# and it has [] if the session is not placed.
@ -720,7 +720,7 @@ class Schedule(models.Model):
class SchedTimeSessAssignment(models.Model):
"""
This model provides an N:M relationship between Session and TimeSlot.
Each relationship is attached to the named agenda, which is owned by
Each relationship is attached to the named schedule, which is owned by
a specific person/user.
"""
timeslot = ForeignKey('TimeSlot', null=False, blank=False, related_name='sessionassignments')
@ -1032,7 +1032,7 @@ class Session(models.Model):
ss0name = "(%s)" % self.status.name
else:
ss0name = "(unscheduled)"
ss = self.timeslotassignments.filter(schedule=self.meeting.agenda).order_by('timeslot__time')
ss = self.timeslotassignments.filter(schedule=self.meeting.schedule).order_by('timeslot__time')
if ss:
ss0name = ','.join([x.timeslot.time.strftime("%a-%H%M") for x in ss])
return "%s: %s %s %s" % (self.meeting, self.group.acronym, self.name, ss0name)
@ -1065,11 +1065,11 @@ class Session(models.Model):
def reverse_constraints(self):
return Constraint.objects.filter(target=self.group, meeting=self.meeting).order_by('name__name')
def timeslotassignment_for_agenda(self, schedule):
def timeslotassignment_for_schedule(self, schedule):
return self.timeslotassignments.filter(schedule=schedule).first()
def official_timeslotassignment(self):
return self.timeslotassignment_for_agenda(self.meeting.agenda)
return self.timeslotassignment_for_schedule(self.meeting.schedule)
def constraints_dict(self, host_scheme):
constraint_list = []

View file

@ -18,7 +18,7 @@ from ietf.meeting.models import ( Meeting, ResourceAssociation, Constraint, Room
from ietf.name.resources import MeetingTypeNameResource
class MeetingResource(ModelResource):
type = ToOneField(MeetingTypeNameResource, 'type')
agenda = ToOneField('ietf.meeting.resources.ScheduleResource', 'agenda', null=True)
schedule = ToOneField('ietf.meeting.resources.ScheduleResource', 'schedule', null=True)
updated = DateTimeField(attribute='updated')
class Meta:
cache = SimpleCache()
@ -48,7 +48,7 @@ class MeetingResource(ModelResource):
"agenda_warning_note": ALL,
"session_request_lock_message": ALL,
"type": ALL_WITH_RELATIONS,
"agenda": ALL_WITH_RELATIONS,
"schedule": ALL_WITH_RELATIONS,
"proceedings_final": ALL,
}
api.meeting.register(MeetingResource())

View file

@ -37,7 +37,7 @@ def make_interim_meeting(group,date,status='sched'):
SchedTimeSessAssignment.objects.create(
timeslot=slot,
session=session,
schedule=session.meeting.agenda)
schedule=session.meeting.schedule)
# agenda
name = "agenda-%s-%s-%s" % (meeting.number, group.acronym, "01")
rev = '00'
@ -77,8 +77,8 @@ def make_meeting_test_data(meeting=None):
if not meeting:
meeting = Meeting.objects.get(number="72", type="ietf")
schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-agenda", visible=True, public=True)
unofficial_schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-unofficial-agenda", visible=True, public=True)
schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-schedule", visible=True, public=True)
unofficial_schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-unofficial-schedule", visible=True, public=True)
# test room
pname = RoomResourceName.objects.create(name='projector',slug='proj')
@ -156,7 +156,7 @@ def make_meeting_test_data(meeting=None):
scheduled=datetime.datetime.now(),type_id="break")
SchedTimeSessAssignment.objects.create(timeslot=break_slot, session=break_session, schedule=schedule)
meeting.agenda = schedule
meeting.schedule = schedule
meeting.save()
# Convenience for the tests

View file

@ -21,16 +21,16 @@ from ietf.utils.mail import outbox
class ApiTests(TestCase):
def test_update_agenda(self):
def test_update_schedule(self):
meeting = make_meeting_test_data()
schedule = Schedule.objects.get(meeting__number=72,name="test-agenda")
schedule = Schedule.objects.get(meeting__number=72,name="test-schedule")
mars_session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
ames_session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session,schedule__name='test-agenda')
mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session,schedule__name='test-schedule')
mars_slot = mars_scheduled.timeslot
ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda')
ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-schedule')
ames_slot = ames_scheduled.timeslot
def do_unschedule(assignment):
@ -96,16 +96,16 @@ class ApiTests(TestCase):
r = do_extend(schedule,mars_scheduled)
self.assertEqual(r.status_code, 201)
self.assertTrue("error" not in r.json())
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),2)
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-schedule').count(),2)
# Unschedule mars
r = do_unschedule(mars_scheduled)
self.assertEqual(r.status_code, 200)
self.assertNotIn("error", r.json())
# Make sure it got both the original and extended session
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),0)
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-schedule').count(),0)
self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda').timeslot, mars_slot)
self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-schedule').timeslot, mars_slot)
def test_constraints_json(self):
@ -212,9 +212,9 @@ class ApiTests(TestCase):
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.agenda.assignments.filter(session__type_id='session')]))
self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.schedule.assignments.filter(session__type_id='session')]))
schedule = meeting.agenda
schedule = meeting.schedule
url = urlreverse("ietf.meeting.ajax.assignments_json",
kwargs=dict(num=meeting.number,owner=schedule.owner_email(),name=schedule.name))
r = self.client.get(url)
@ -281,45 +281,45 @@ class ApiTests(TestCase):
def test_schedule_json(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.agenda_infourl",
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
name=meeting.agenda.name))
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
r = self.client.get(url)
info = r.json()
self.assertEqual(info["schedule_id"], meeting.agenda.pk)
self.assertEqual(info["schedule_id"], meeting.schedule.pk)
def test_create_new_schedule(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.agenda_infosurl",
url = urlreverse("ietf.meeting.ajax.schedule_infosurl",
kwargs=dict(num=meeting.number))
post_data = {
'name': 'new-agenda',
'name': 'new-schedule',
}
# unauthorized post
self.client.login(username="plain", password="plain+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
self.assertTrue(not meeting.schedule_set.filter(name='new-agenda'))
self.assertTrue(not meeting.schedule_set.filter(name='new-schedule'))
# create new agenda
# create new schedule
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
self.assertTrue(meeting.schedule_set.filter(name='new-agenda'))
self.assertTrue(meeting.schedule_set.filter(name='new-schedule'))
def test_update_schedule(self):
def test_update_meeting_schedule(self):
meeting = make_meeting_test_data()
self.assertTrue(meeting.agenda.visible)
self.assertTrue(meeting.schedule.visible)
url = urlreverse("ietf.meeting.ajax.agenda_infourl",
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
name=meeting.agenda.name))
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
post_data = {
'visible': 'false',
@ -334,21 +334,21 @@ class ApiTests(TestCase):
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
# change agenda
# change schedule
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
changed_schedule = Schedule.objects.get(pk=meeting.agenda.pk)
changed_schedule = Schedule.objects.get(pk=meeting.schedule.pk)
self.assertTrue(not changed_schedule.visible)
self.assertEqual(changed_schedule.name, "new-test-name")
def test_delete_schedule(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.agenda_infourl",
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
name=meeting.agenda.name))
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
# unauthorized delete
self.client.login(username="plain", password="plain+password")
r = self.client.delete(url)
@ -358,16 +358,16 @@ class ApiTests(TestCase):
self.client.login(username="secretary", password="secretary+password")
r = self.client.delete(url)
self.assertEqual(r.status_code, 200)
self.assertTrue(not Schedule.objects.filter(pk=meeting.agenda.pk))
self.assertTrue(not Schedule.objects.filter(pk=meeting.schedule.pk))
def test_set_meeting_agenda(self):
def test_set_meeting_schedule(self):
meeting = make_meeting_test_data()
schedule = meeting.agenda
schedule = meeting.schedule
url = urlreverse("ietf.meeting.ajax.meeting_json",
kwargs=dict(num=meeting.number))
post_data = {
"agenda": "",
"schedule": "",
}
# unauthorized post
self.client.login(username="ad", password="ad+password")
@ -378,18 +378,18 @@ class ApiTests(TestCase):
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 200)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).agenda)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).schedule)
# set agenda - first fail with non-public
# set schedule - first fail with non-public
post_data = {
"agenda": schedule.name,
"schedule": schedule.name,
}
schedule.public = False
schedule.save()
r = self.client.post(url, post_data)
self.assertTrue(r.status_code != 200)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).agenda)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).schedule)
# then go through with public
schedule.public = True
@ -399,7 +399,7 @@ class ApiTests(TestCase):
prior_length= len(outbox)
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 200)
self.assertEqual(Meeting.objects.get(pk=meeting.pk).agenda, schedule)
self.assertEqual(Meeting.objects.get(pk=meeting.pk).schedule, schedule)
self.assertEqual(len(outbox),prior_length)
def test_read_only(self):
@ -407,20 +407,20 @@ class ApiTests(TestCase):
# Secretariat
self.client.login(username="secretary", password="secretary+password")
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.agenda.owner.email_address(), meeting.agenda.name);
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.schedule.owner.email_address(), meeting.schedule.name);
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info['secretariat'], True)
self.assertEqual(urlsplit(info['owner_href'])[2], "/person/%s.json" % meeting.agenda.owner_id)
self.assertEqual(urlsplit(info['owner_href'])[2], "/person/%s.json" % meeting.schedule.owner_id)
self.assertEqual(info['read_only'], True)
self.assertEqual(info['save_perm'], True)
# owner
self.client.login(username=meeting.agenda.owner.user.username,
password=meeting.agenda.owner.user.username+"+password")
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.agenda.owner.email_address(), meeting.agenda.name);
self.client.login(username=meeting.schedule.owner.user.username,
password=meeting.schedule.owner.user.username+"+password")
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.schedule.owner.email_address(), meeting.schedule.name);
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
@ -434,7 +434,7 @@ class ApiTests(TestCase):
scheduled = SchedTimeSessAssignment.objects.filter(
session__meeting=meeting, session__group__acronym="mars").first()
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.agenda.owner_email(), meeting.agenda.name, scheduled.pk)
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.schedule.owner_email(), meeting.schedule.name, scheduled.pk)
post_data = {
"pinned": True
@ -448,11 +448,11 @@ class ApiTests(TestCase):
self.assertTrue(not SchedTimeSessAssignment.objects.get(pk=scheduled.pk).pinned)
# set pinned
meeting.agenda.owner = Person.objects.get(user__username="secretary")
meeting.agenda.save()
meeting.schedule.owner = Person.objects.get(user__username="secretary")
meeting.schedule.save()
# need to rebuild URL, since the agenda owner has changed.
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.agenda.owner_email(), meeting.agenda.name, scheduled.pk)
# need to rebuild URL, since the schedule owner has changed.
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.schedule.owner_email(), meeting.schedule.name, scheduled.pk)
self.client.login(username="secretary", password="secretary+password")
r = self.client.put(url, post_data)

View file

@ -84,10 +84,10 @@ class ScheduleEditTests(StaticLiveServerTestCase):
def testUnschedule(self):
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=72,session__group__acronym='mars',schedule__name='test-agenda').count(),1)
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=72,session__group__acronym='mars',schedule__name='test-schedule').count(),1)
self.login()
url = self.absreverse('ietf.meeting.views.edit_agenda',kwargs=dict(num='72',name='test-agenda',owner='plain@example.com'))
url = self.absreverse('ietf.meeting.views.edit_schedule',kwargs=dict(num='72',name='test-schedule',owner='plain@example.com'))
self.driver.get(url)
q = PyQuery(self.driver.page_source)
@ -101,7 +101,7 @@ class ScheduleEditTests(StaticLiveServerTestCase):
self.assertTrue(len(q('#sortable-list #session_1'))>0)
time.sleep(0.1) # The API that modifies the database runs async
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=72,session__group__acronym='mars',schedule__name='test-agenda').count(),0)
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=72,session__group__acronym='mars',schedule__name='test-schedule').count(),0)
@skipIf(skip_selenium, skip_message)
class SlideReorderTests(StaticLiveServerTestCase):
@ -173,5 +173,5 @@ class SlideReorderTests(StaticLiveServerTestCase):
# condition_data()
#
# def testOpenSchedule(self):
# url = urlreverse('ietf.meeting.views.edit_agenda', kwargs=dict(num='72',name='test-agenda'))
# url = urlreverse('ietf.meeting.views.edit_schedule', kwargs=dict(num='72',name='test-schedule'))
# r = self.client.get(url)

View file

@ -96,7 +96,7 @@ class MeetingTests(TestCase):
def test_meeting_agenda(self):
meeting = make_meeting_test_data()
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule=meeting.agenda)
slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule=meeting.schedule)
#
self.write_materials_files(meeting, session)
#
@ -475,7 +475,7 @@ class MeetingTests(TestCase):
# Create an extra session
t2 = TimeSlotFactory.create(meeting=meeting, time=datetime.datetime.combine(meeting.date, datetime.time(11, 30)))
s2 = SessionFactory.create(meeting=meeting, group=s1.group, add_to_schedule=False)
SchedTimeSessAssignment.objects.create(timeslot=t2, session=s2, schedule=meeting.agenda)
SchedTimeSessAssignment.objects.create(timeslot=t2, session=s2, schedule=meeting.schedule)
#
url = urlreverse('ietf.meeting.views.ical_agenda', kwargs={'num':meeting.number, 'acronym':s1.group.acronym, })
r = self.client.get(url)
@ -537,14 +537,14 @@ class MeetingTests(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 302)
def test_edit_agenda_properties(self):
def test_edit_schedule_properties(self):
self.client.login(username='secretary',password='secretary+password')
url = urlreverse('ietf.meeting.views.edit_agenda_properties',kwargs={'owner':'does@notexist.example','name':'doesnotexist','num':00})
url = urlreverse('ietf.meeting.views.edit_schedule_properties',kwargs={'owner':'does@notexist.example','name':'doesnotexist','num':00})
response = self.client.get(url)
self.assertEqual(response.status_code,404)
self.client.logout()
schedule = ScheduleFactory(meeting__type_id='ietf',visible=False,public=False)
url = urlreverse('ietf.meeting.views.edit_agenda_properties',kwargs={'owner':schedule.owner.email(),'name':schedule.name,'num':schedule.meeting.number})
url = urlreverse('ietf.meeting.views.edit_schedule_properties',kwargs={'owner':schedule.owner.email(),'name':schedule.name,'num':schedule.meeting.number})
response = self.client.get(url)
self.assertEqual(response.status_code,302)
self.client.login(username='secretary',password='secretary+password')
@ -590,27 +590,27 @@ class EditTests(TestCase):
fg_group_colors[area_upper] = "#333"
bg_group_colors[area_upper] = "#aaa"
def test_edit_agenda(self):
def test_edit_schedule(self):
meeting = make_meeting_test_data()
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number)))
r = self.client.get(urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number)))
self.assertContains(r, "load_assignments")
def test_save_agenda_as_and_read_permissions(self):
meeting = make_meeting_test_data()
# try to get non-existing agenda
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
url = urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name="foo"))
r = self.client.get(url)
self.assertEqual(r.status_code, 404)
# save as new name (requires valid existing agenda)
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
name=meeting.agenda.name))
url = urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
self.client.login(username="ad", password="ad+password")
r = self.client.post(url, {
'savename': "foo",
@ -622,7 +622,7 @@ class EditTests(TestCase):
# get
schedule = meeting.get_schedule_by_name("foo")
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
url = urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number,
owner=schedule.owner_email(),
name="foo"))
r = self.client.get(url)
@ -655,9 +655,9 @@ class EditTests(TestCase):
meeting = make_meeting_test_data()
# save as new name (requires valid existing agenda)
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
owner=meeting.agenda.owner_email(),
name=meeting.agenda.name))
url = urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
self.client.login(username="ad", password="ad+password")
r = self.client.post(url, {
'savename': "/no/this/should/not/work/it/is/too/long",
@ -706,12 +706,12 @@ class EditTests(TestCase):
def test_slot_to_the_right(self):
meeting = make_meeting_test_data()
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
mars_scheduled = session.timeslotassignments.get(schedule__name='test-agenda')
mars_slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
mars_scheduled = session.timeslotassignments.get(schedule__name='test-schedule')
mars_slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule__name='test-schedule')
mars_ends = mars_slot.time + mars_slot.duration
session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session,sessionassignments__schedule__name='test-schedule')
ames_slot_qs.update(time=mars_ends + datetime.timedelta(seconds=11 * 60))
self.assertTrue(not mars_slot.slot_to_the_right)
@ -784,8 +784,8 @@ class EditScheduleListTests(TestCase):
self.mtg = MeetingFactory(type_id='ietf')
ScheduleFactory(meeting=self.mtg,name='Empty-Schedule')
def test_list_agendas(self):
url = urlreverse('ietf.meeting.views.list_agendas',kwargs={'num':self.mtg.number})
def test_list_schedules(self):
url = urlreverse('ietf.meeting.views.list_schedules',kwargs={'num':self.mtg.number})
login_testing_unauthorized(self,"secretary",url)
r = self.client.get(url)
self.assertTrue(r.status_code, 200)
@ -793,8 +793,8 @@ class EditScheduleListTests(TestCase):
def test_delete_schedule(self):
url = urlreverse('ietf.meeting.views.delete_schedule',
kwargs={'num':self.mtg.number,
'owner':self.mtg.agenda.owner.email_address(),
'name':self.mtg.agenda.name,
'owner':self.mtg.schedule.owner.email_address(),
'name':self.mtg.schedule.name,
})
login_testing_unauthorized(self,"secretary",url)
r = self.client.get(url)
@ -802,7 +802,7 @@ class EditScheduleListTests(TestCase):
r = self.client.post(url,{'save':1})
self.assertTrue(r.status_code, 403)
self.assertEqual(self.mtg.schedule_set.count(),2)
self.mtg.agenda=None
self.mtg.schedule=None
self.mtg.save()
r = self.client.get(url)
self.assertTrue(r.status_code, 200)
@ -811,7 +811,7 @@ class EditScheduleListTests(TestCase):
self.assertEqual(self.mtg.schedule_set.count(),1)
def test_make_schedule_official(self):
schedule = self.mtg.schedule_set.exclude(id=self.mtg.agenda.id).first()
schedule = self.mtg.schedule_set.exclude(id=self.mtg.schedule.id).first()
url = urlreverse('ietf.meeting.views.make_schedule_official',
kwargs={'num':self.mtg.number,
'owner':schedule.owner.email_address(),
@ -823,7 +823,7 @@ class EditScheduleListTests(TestCase):
r = self.client.post(url,{'save':1})
self.assertTrue(r.status_code, 302)
mtg = Meeting.objects.get(number=self.mtg.number)
self.assertEqual(mtg.agenda,schedule)
self.assertEqual(mtg.schedule,schedule)
# -------------------------------------------------
# Interim Meeting Tests
@ -1594,7 +1594,7 @@ class InterimTests(TestCase):
# Create an extra session
t2 = TimeSlotFactory.create(meeting=meeting, time=datetime.datetime.combine(meeting.date, datetime.time(11, 30)))
s2 = SessionFactory.create(meeting=meeting, group=s1.group, add_to_schedule=False)
SchedTimeSessAssignment.objects.create(timeslot=t2, session=s2, schedule=meeting.agenda)
SchedTimeSessAssignment.objects.create(timeslot=t2, session=s2, schedule=meeting.schedule)
#
url = urlreverse('ietf.meeting.views.ical_agenda', kwargs={'num':meeting.number, 'acronym':s1.group.acronym, })
r = self.client.get(url)

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2007, All Rights Reserved
# Copyright The IETF Trust 2007-2019, All Rights Reserved
from django.conf.urls import include
from django.views.generic import RedirectView
@ -24,8 +24,8 @@ safe_for_all_meeting_types = [
type_ietf_only_patterns = [
url(r'^agenda/%(owner)s/%(schedule_name)s/edit$' % settings.URL_REGEXPS, views.edit_agenda),
url(r'^agenda/%(owner)s/%(schedule_name)s/details$' % settings.URL_REGEXPS, views.edit_agenda_properties),
url(r'^agenda/%(owner)s/%(schedule_name)s/edit$' % settings.URL_REGEXPS, views.edit_schedule),
url(r'^agenda/%(owner)s/%(schedule_name)s/details$' % settings.URL_REGEXPS, views.edit_schedule_properties),
url(r'^agenda/%(owner)s/%(schedule_name)s/delete$' % settings.URL_REGEXPS, views.delete_schedule),
url(r'^agenda/%(owner)s/%(schedule_name)s/make_official$' % settings.URL_REGEXPS, views.make_schedule_official),
url(r'^agenda/%(owner)s/%(schedule_name)s(\.(?P<ext>.html))?/?$' % settings.URL_REGEXPS, views.agenda),
@ -34,16 +34,16 @@ type_ietf_only_patterns = [
url(r'^agenda/%(owner)s/%(schedule_name)s/by-room/?$' % settings.URL_REGEXPS, views.agenda_by_room),
url(r'^agenda/%(owner)s/%(schedule_name)s/by-type/?$' % settings.URL_REGEXPS, views.agenda_by_type),
url(r'^agenda/%(owner)s/%(schedule_name)s/by-type/(?P<type>[a-z]+)$' % settings.URL_REGEXPS, views.agenda_by_type),
url(r'^agenda/%(owner)s/%(schedule_name)s/permissions$' % settings.URL_REGEXPS, ajax.agenda_permission_api),
url(r'^agenda/%(owner)s/%(schedule_name)s/permissions$' % settings.URL_REGEXPS, ajax.schedule_permission_api),
url(r'^agenda/%(owner)s/%(schedule_name)s/session/(?P<assignment_id>\d+).json$' % settings.URL_REGEXPS, ajax.assignment_json),
url(r'^agenda/%(owner)s/%(schedule_name)s/sessions.json$' % settings.URL_REGEXPS, ajax.assignments_json),
url(r'^agenda/%(owner)s/%(schedule_name)s.json$' % settings.URL_REGEXPS, ajax.agenda_infourl),
url(r'^agenda/%(owner)s/%(schedule_name)s.json$' % settings.URL_REGEXPS, ajax.schedule_infourl),
url(r'^agenda/by-room$', views.agenda_by_room),
url(r'^agenda/by-type$', views.agenda_by_type),
url(r'^agenda/by-type/(?P<type>[a-z]+)$', views.agenda_by_type),
url(r'^agenda/by-type/(?P<type>[a-z]+)/ics$', views.agenda_by_type_ics),
url(r'^agendas/list$', views.list_agendas),
url(r'^agendas/edit$', RedirectView.as_view(pattern_name='ietf.meeting.views.list_agendas', permanent=True)),
url(r'^agendas/list$', views.list_schedules),
url(r'^agendas/edit$', RedirectView.as_view(pattern_name='ietf.meeting.views.list_schedules', permanent=True)),
url(r'^timeslots/edit$', views.edit_timeslots),
url(r'^timeslot/(?P<slot_id>\d+)/edittype$', views.edit_timeslot_type),
url(r'^rooms$', ajax.timeslot_roomsurl),
@ -51,8 +51,8 @@ type_ietf_only_patterns = [
url(r'^timeslots$', ajax.timeslot_slotsurl),
url(r'^timeslots.json$', ajax.timeslot_slotsurl),
url(r'^timeslot/(?P<slotid>\d+).json$', ajax.timeslot_sloturl),
url(r'^agendas$', ajax.agenda_infosurl),
url(r'^agendas.json$', ajax.agenda_infosurl),
url(r'^agendas$', ajax.schedule_infosurl),
url(r'^agendas.json$', ajax.schedule_infosurl),
url(r'^agenda/(?P<acronym>[-a-z0-9]+)-drafts.pdf$', views.session_draft_pdf),
url(r'^agenda/(?P<acronym>[-a-z0-9]+)-drafts.tgz$', views.session_draft_tarfile),
url(r'^sessions.json', ajax.sessions_json),
@ -73,7 +73,7 @@ type_ietf_only_patterns_id_optional = [
url(r'^agenda(?P<utc>-utc)?(?P<ext>.html)?/?$', views.agenda),
url(r'^agenda(?P<ext>.txt)$', views.agenda),
url(r'^agenda(?P<ext>.csv)$', views.agenda),
url(r'^agenda/edit$', views.edit_agenda),
url(r'^agenda/edit$', views.edit_schedule),
url(r'^requests$', views.meeting_requests),
url(r'^agenda/agenda\.ics$', views.ical_agenda),
url(r'^agenda\.ics$', views.ical_agenda),

View file

@ -23,7 +23,7 @@ from ietf.secr.proceedings.proc_utils import import_audio_files
def group_sessions(sessions):
def sort_key(session):
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.schedule)
if official_sessions:
return official_sessions.first().timeslot.time
elif session.meeting.date:
@ -77,7 +77,7 @@ def sort_sessions(sessions):
# (or the time of the session request if the session isn't scheduled).
def time_sort_key(session):
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.schedule)
if official_sessions:
return official_sessions.first().timeslot.time
else:

View file

@ -57,7 +57,7 @@ from ietf.meeting.helpers import build_all_agenda_slices, get_wg_name_list
from ietf.meeting.helpers import get_all_assignments_from_schedule
from ietf.meeting.helpers import get_modified_from_assignments
from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_ietf_meeting
from ietf.meeting.helpers import get_meeting, get_schedule, schedule_permissions, get_ietf_meeting
from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file
from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session_date
from ietf.meeting.helpers import can_view_interim_request, can_approve_interim_request
@ -133,7 +133,7 @@ def materials(request, num=None):
schedule = get_schedule(meeting, None)
sessions = ( Session.objects
.filter(meeting__number=meeting.number, timeslotassignments__schedule=schedule)
.select_related('meeting__agenda','status','group__state','group__parent', )
.select_related('meeting__schedule','status','group__state','group__parent', )
)
for session in sessions:
session.past_cutoff_date = past_cutoff_date
@ -244,7 +244,7 @@ class SaveAsForm(forms.Form):
savename = forms.CharField(max_length=16)
@role_required('Area Director','Secretariat')
def agenda_create(request, num=None, owner=None, name=None):
def schedule_create(request, num=None, owner=None, name=None):
meeting = get_meeting(num)
person = get_person_by_email(owner)
schedule = get_schedule_by_name(meeting, person, name)
@ -252,29 +252,29 @@ def agenda_create(request, num=None, owner=None, name=None):
if schedule is None:
# here we have to return some ajax to display an error.
messages.error("Error: No meeting information for meeting %s owner %s schedule %s available" % (num, owner, name)) # pylint: disable=no-value-for-parameter
return redirect(edit_agenda, num=num, owner=owner, name=name)
return redirect(edit_schedule, num=num, owner=owner, name=name)
# authorization was enforced by the @group_require decorator above.
saveasform = SaveAsForm(request.POST)
if not saveasform.is_valid():
messages.info(request, "This name is not valid. Please choose another one.")
return redirect(edit_agenda, num=num, owner=owner, name=name)
return redirect(edit_schedule, num=num, owner=owner, name=name)
savedname = saveasform.cleaned_data['savename']
if not ascii_alphanumeric(savedname):
messages.info(request, "This name contains illegal characters. Please choose another one.")
return redirect(edit_agenda, num=num, owner=owner, name=name)
return redirect(edit_schedule, num=num, owner=owner, name=name)
# create the new schedule, and copy the assignments
try:
sched = meeting.schedule_set.get(name=savedname, owner=request.user.person)
if sched:
return redirect(edit_agenda, num=meeting.number, owner=sched.owner_email(), name=sched.name)
return redirect(edit_schedule, num=meeting.number, owner=sched.owner_email(), name=sched.name)
else:
messages.info(request, "Agenda creation failed. Please try again.")
return redirect(edit_agenda, num=num, owner=owner, name=name)
messages.info(request, "Schedule creation failed. Please try again.")
return redirect(edit_schedule, num=num, owner=owner, name=name)
except Schedule.DoesNotExist:
pass
@ -313,7 +313,7 @@ def agenda_create(request, num=None, owner=None, name=None):
# now redirect to this new schedule.
return redirect(edit_agenda, meeting.number, newschedule.owner_email(), newschedule.name)
return redirect(edit_schedule, meeting.number, newschedule.owner_email(), newschedule.name)
@role_required('Secretariat')
@ -344,16 +344,16 @@ def edit_timeslots(request, num=None):
#@role_required('Area Director','Secretariat')
# disable the above security for now, check it below.
@ensure_csrf_cookie
def edit_agenda(request, num=None, owner=None, name=None):
def edit_schedule(request, num=None, owner=None, name=None):
if request.method == 'POST':
return agenda_create(request, num, owner, name)
return schedule_create(request, num, owner, name)
user = request.user
meeting = get_meeting(num)
person = get_person_by_email(owner)
if name is None:
schedule = meeting.agenda
schedule = meeting.schedule
else:
schedule = get_schedule_by_name(meeting, person, name)
if schedule is None:
@ -364,13 +364,13 @@ def edit_agenda(request, num=None, owner=None, name=None):
rooms = meeting.room_set.filter(session_types__slug='session').distinct().order_by("capacity")
saveas = SaveAsForm()
saveasurl=reverse(edit_agenda,
saveasurl=reverse(edit_schedule,
args=[meeting.number, schedule.owner_email(), schedule.name])
can_see, can_edit,secretariat = agenda_permissions(meeting, schedule, user)
can_see, can_edit,secretariat = schedule_permissions(meeting, schedule, user)
if not can_see:
return render(request, "meeting/private_agenda.html",
return render(request, "meeting/private_schedule.html",
{"schedule":schedule,
"meeting": meeting,
"meeting_base_url":meeting_base_url,
@ -413,32 +413,32 @@ def edit_agenda(request, num=None, owner=None, name=None):
})
##############################################################################
# show the properties associated with an agenda (visible, public)
# show the properties associated with a schedule (visible, public)
#
AgendaPropertiesForm = modelform_factory(Schedule, fields=('name','visible', 'public'))
SchedulePropertiesForm = modelform_factory(Schedule, fields=('name','visible', 'public'))
# The meeing urls.py won't allow empy num, owmer, or name values
@role_required('Area Director','Secretariat')
def edit_agenda_properties(request, num=None, owner=None, name=None):
def edit_schedule_properties(request, num=None, owner=None, name=None):
meeting = get_meeting(num)
person = get_person_by_email(owner)
schedule = get_schedule_by_name(meeting, person, name)
if schedule is None:
raise Http404("No meeting information for meeting %s owner %s schedule %s available" % (num, owner, name))
cansee, canedit, secretariat = agenda_permissions(meeting, schedule, request.user)
cansee, canedit, secretariat = schedule_permissions(meeting, schedule, request.user)
if not (canedit or has_role(request.user,'Secretariat')):
return HttpResponseForbidden("You may not edit this agenda")
return HttpResponseForbidden("You may not edit this schedule")
else:
if request.method == 'POST':
form = AgendaPropertiesForm(instance=schedule,data=request.POST)
form = SchedulePropertiesForm(instance=schedule,data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num': num}))
return HttpResponseRedirect(reverse('ietf.meeting.views.list_schedules',kwargs={'num': num}))
else:
form = AgendaPropertiesForm(instance=schedule)
form = SchedulePropertiesForm(instance=schedule)
return render(request, "meeting/properties_edit.html",
{"schedule":schedule,
"form":form,
@ -446,11 +446,11 @@ def edit_agenda_properties(request, num=None, owner=None, name=None):
})
##############################################################################
# show list of agendas.
# show list of schedules.
#
@role_required('Area Director','Secretariat')
def list_agendas(request, num=None ):
def list_schedules(request, num=None ):
meeting = get_meeting(num)
user = request.user
@ -463,7 +463,7 @@ def list_agendas(request, num=None ):
schedules = sorted(list(schedules),key=lambda x:not x.is_official)
return render(request, "meeting/agenda_list.html",
return render(request, "meeting/schedule_list.html",
{"meeting": meeting,
"schedules": schedules,
})
@ -484,7 +484,7 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
assert num is None or num.isdigit()
meeting = get_ietf_meeting(num)
if not meeting or (meeting.number.isdigit() and int(meeting.number) <= 64 and (not meeting.agenda or not meeting.agenda.assignments.exists())):
if not meeting or (meeting.number.isdigit() and int(meeting.number) <= 64 and (not meeting.schedule or not meeting.schedule.assignments.exists())):
if ext == '.html' or (meeting and meeting.number.isdigit() and 0 < int(meeting.number) <= 64):
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s' % num )
else:
@ -946,7 +946,7 @@ def json_agenda(request, num=None ):
sessions = []
locations = set()
parent_acronyms = set()
assignments = meeting.agenda.assignments.exclude(session__type__in=['lead','offagenda','break','reg'])
assignments = meeting.schedule.assignments.exclude(session__type__in=['lead','offagenda','break','reg'])
# Update the assignments with historic information, i.e., valid at the
# time of the meeting
assignments = preprocess_assignments_for_agenda(assignments, meeting)
@ -1076,7 +1076,7 @@ def get_sessions(num, acronym):
sessions = Session.objects.filter(meeting=meeting,short=acronym,type__in=['session','plenary','other'])
def sort_key(session):
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.schedule)
if official_sessions:
return official_sessions.first().timeslot.time
else:
@ -1094,7 +1094,7 @@ def session_details(request, num, acronym ):
for session in sessions:
session.type_counter = Counter()
ss = session.timeslotassignments.filter(schedule=meeting.agenda).order_by('timeslot__time')
ss = session.timeslotassignments.filter(schedule=meeting.schedule).order_by('timeslot__time')
if ss:
session.time = ', '.join(x.timeslot.time.strftime("%A %b-%d-%Y %H%M") for x in ss)
if session.status.slug == 'canceled':
@ -1704,9 +1704,9 @@ def make_schedule_official(request, num, owner, name):
schedule.public = True
schedule.visible = True
schedule.save()
meeting.agenda = schedule
meeting.schedule = schedule
meeting.save()
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num':num}))
return HttpResponseRedirect(reverse('ietf.meeting.views.list_schedules',kwargs={'num':num}))
if not schedule.public:
messages.warning(request,"This schedule will be made public as it is made official.")
@ -1731,15 +1731,15 @@ def delete_schedule(request, num, owner, name):
if schedule.name=='Empty-Schedule':
return HttpResponseForbidden('You may not delete the default empty schedule')
if schedule == meeting.agenda:
return HttpResponseForbidden('You may not delete the official agenda for %s'%meeting)
if schedule == meeting.schedule:
return HttpResponseForbidden('You may not delete the official schedule for %s'%meeting)
if not ( has_role(request.user, 'Secretariat') or person.user == request.user ):
return HttpResponseForbidden("You may not delete other user's schedules")
if request.method == 'POST':
schedule.delete()
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num':num}))
return HttpResponseRedirect(reverse('ietf.meeting.views.list_schedules',kwargs={'num':num}))
return render(request, "meeting/delete_schedule.html",
{ 'schedule' : schedule,
@ -2143,7 +2143,7 @@ def upcoming_ical(request):
assignments = []
for meeting in meetings:
items = meeting.agenda.assignments.order_by(
items = meeting.schedule.assignments.order_by(
'session__type__slug', 'timeslot__time')
assignments.extend(items)
@ -2175,7 +2175,7 @@ def upcoming_ical(request):
def floor_plan(request, num=None, floor=None, ):
meeting = get_meeting(num)
schedule = meeting.agenda
schedule = meeting.schedule
floors = FloorPlan.objects.filter(meeting=meeting).order_by('order')
if floor:
floors = [ f for f in floors if xslugify(f.name) == floor ]
@ -2189,7 +2189,7 @@ def proceedings(request, num=None):
meeting = get_meeting(num)
if (meeting.number.isdigit() and int(meeting.number) <= 64) or not meeting.agenda or not meeting.agenda.assignments.exists():
if (meeting.number.isdigit() and int(meeting.number) <= 64) or not meeting.schedule or not meeting.schedule.assignments.exists():
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s' % num )
begin_date = meeting.get_submission_start_date()
@ -2220,7 +2220,7 @@ def finalize_proceedings(request, num=None):
meeting = get_meeting(num)
if (meeting.number.isdigit() and int(meeting.number) <= 64) or not meeting.agenda or not meeting.agenda.assignments.exists() or meeting.proceedings_final:
if (meeting.number.isdigit() and int(meeting.number) <= 64) or not meeting.schedule or not meeting.schedule.assignments.exists() or meeting.proceedings_final:
raise Http404
if request.method=='POST':
@ -2404,7 +2404,7 @@ def edit_timeslot_type(request, num, slot_id):
else:
form = TimeSlotTypeForm(instance=timeslot)
sessions = timeslot.sessions.filter(timeslotassignments__schedule=meeting.agenda)
sessions = timeslot.sessions.filter(timeslotassignments__schedule=meeting.schedule)
return render(request, 'meeting/edit_timeslot_type.html', {'timeslot':timeslot,'form':form,'sessions':sessions})
@ -2425,7 +2425,7 @@ def request_minutes(request, num=None):
return HttpResponseRedirect(reverse('ietf.meeting.views.materials',kwargs={'num':num}))
else:
needs_minutes = set()
for a in meeting.agenda.assignments.filter(session__group__type_id__in=('wg','rg','ag')).exclude(session__status='canceled'):
for a in meeting.schedule.assignments.filter(session__group__type_id__in=('wg','rg','ag')).exclude(session__status='canceled'):
if not a.session.all_meeting_minutes():
group = a.session.group
if group.parent and group.parent.type_id in ('area','irtf'):

View file

@ -1,3 +1,4 @@
# Copyright The IETF Trust 2013-2019, All Rights Reserved
import re
from django import forms
@ -102,7 +103,7 @@ class MeetingModelForm(forms.ModelForm):
idsubmit_cutoff_warning_days = ietf.utils.fields.DurationField()
class Meta:
model = Meeting
exclude = ('type', 'agenda', 'session_request_lock_message')
exclude = ('type', 'schedule', 'session_request_lock_message')
def __init__(self,*args,**kwargs):

View file

@ -93,7 +93,7 @@ class SecrMeetingTestCase(TestCase):
self.assertEqual(Meeting.objects.count(),count + 1)
new_meeting = Meeting.objects.get(number=number)
self.assertTrue(new_meeting.agenda)
self.assertTrue(new_meeting.schedule)
self.assertEqual(new_meeting.attendees, None)
def test_edit_meeting(self):
@ -151,9 +151,9 @@ class SecrMeetingTestCase(TestCase):
meeting = make_meeting_test_data()
mars_group = Group.objects.get(acronym='mars')
ames_group = Group.objects.get(acronym='ames')
ames_stsa = meeting.agenda.assignments.get(session__group=ames_group)
ames_stsa = meeting.schedule.assignments.get(session__group=ames_group)
assert ames_stsa.session.status_id == 'schedw'
mars_stsa = meeting.agenda.assignments.get(session__group=mars_group)
mars_stsa = meeting.schedule.assignments.get(session__group=mars_group)
mars_stsa.session.status = SessionStatusName.objects.get(slug='appr')
mars_stsa.session.save()
url = reverse('ietf.secr.meetings.views.notifications',kwargs={'meeting_id':72})
@ -169,7 +169,7 @@ class SecrMeetingTestCase(TestCase):
person = Person.objects.get(name="(System)")
GroupEvent.objects.create(group=mars_group,time=now,type='sent_notification',
by=person,desc='sent scheduled notification for %s' % meeting)
ss = meeting.agenda.assignments.get(session__group=ames_group)
ss = meeting.schedule.assignments.get(session__group=ames_group)
ss.modified = then
ss.save()
self.client.login(username="secretary", password="secretary+password")
@ -184,14 +184,14 @@ class SecrMeetingTestCase(TestCase):
response = self.client.post(url)
self.assertEqual(response.status_code, 302)
self.assertEqual(len(outbox), mailbox_before + 1)
ames_stsa = meeting.agenda.assignments.get(session__group=ames_group)
ames_stsa = meeting.schedule.assignments.get(session__group=ames_group)
assert ames_stsa.session.status_id == 'sched'
mars_stsa = meeting.agenda.assignments.get(session__group=mars_group)
mars_stsa = meeting.schedule.assignments.get(session__group=mars_group)
assert mars_stsa.session.status_id == 'sched'
def test_meetings_rooms(self):
meeting = make_meeting_test_data()
url = reverse('ietf.secr.meetings.views.rooms',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.rooms',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
@ -200,7 +200,7 @@ class SecrMeetingTestCase(TestCase):
# test delete
# first unschedule sessions so we can delete
SchedTimeSessAssignment.objects.filter(schedule=meeting.agenda).delete()
SchedTimeSessAssignment.objects.filter(schedule=meeting.schedule).delete()
SchedTimeSessAssignment.objects.filter(schedule=meeting.unofficial_schedule).delete()
self.client.login(username="secretary", password="secretary+password")
post_dict = {
@ -217,7 +217,7 @@ class SecrMeetingTestCase(TestCase):
def test_meetings_times(self):
make_meeting_test_data()
url = reverse('ietf.secr.meetings.views.times',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.times',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
@ -237,12 +237,12 @@ class SecrMeetingTestCase(TestCase):
expected_deletion_count = qs.filter(time=qs.first().time).count()
url = reverse('ietf.secr.meetings.views.times_delete',kwargs={
'meeting_id':meeting.number,
'schedule_name':meeting.agenda.name,
'schedule_name':meeting.schedule.name,
'time':qs.first().time.strftime("%Y:%m:%d:%H:%M")
})
redirect_url = reverse('ietf.secr.meetings.views.times',kwargs={
'meeting_id':meeting.number,
'schedule_name':meeting.agenda.name
'schedule_name':meeting.schedule.name
})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
@ -257,7 +257,7 @@ class SecrMeetingTestCase(TestCase):
timeslot = TimeSlot.objects.filter(meeting=meeting,type='session').first()
url = reverse('ietf.secr.meetings.views.times_edit',kwargs={
'meeting_id':72,
'schedule_name':'test-agenda',
'schedule_name':'test-schedule',
'time':timeslot.time.strftime("%Y:%m:%d:%H:%M")
})
self.client.login(username="secretary", password="secretary+password")
@ -272,7 +272,7 @@ class SecrMeetingTestCase(TestCase):
def test_meetings_nonsession(self):
make_meeting_test_data()
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
@ -281,7 +281,7 @@ class SecrMeetingTestCase(TestCase):
meeting = make_meeting_test_data()
room = meeting.room_set.first()
group = Group.objects.get(acronym='secretariat')
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
self.client.login(username="secretary", password="secretary+password")
response = self.client.post(url, {
'day':'1',
@ -302,7 +302,7 @@ class SecrMeetingTestCase(TestCase):
def test_meetings_nonsession_add_invalid(self):
make_meeting_test_data()
group = Group.objects.get(acronym='secretariat')
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
self.client.login(username="secretary", password="secretary+password")
response = self.client.post(url, {
'day':'1',
@ -320,8 +320,8 @@ class SecrMeetingTestCase(TestCase):
meeting = make_meeting_test_data()
session = meeting.session_set.exclude(name='').first() # get first non-session session
timeslot = session.official_timeslotassignment().timeslot
url = reverse('ietf.secr.meetings.views.non_session_edit',kwargs={'meeting_id':72,'schedule_name':meeting.agenda.name,'slot_id':timeslot.pk})
redirect_url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-agenda'})
url = reverse('ietf.secr.meetings.views.non_session_edit',kwargs={'meeting_id':72,'schedule_name':meeting.schedule.name,'slot_id':timeslot.pk})
redirect_url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':72,'schedule_name':'test-schedule'})
new_time = timeslot.time + datetime.timedelta(days=1)
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
@ -342,34 +342,34 @@ class SecrMeetingTestCase(TestCase):
def test_meetings_non_session_delete(self):
meeting = make_meeting_test_data()
slot = meeting.agenda.assignments.filter(timeslot__type='reg').first().timeslot
url = reverse('ietf.secr.meetings.views.non_session_delete', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name,'slot_id':slot.id})
target = reverse('ietf.secr.meetings.views.non_session', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name})
slot = meeting.schedule.assignments.filter(timeslot__type='reg').first().timeslot
url = reverse('ietf.secr.meetings.views.non_session_delete', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name,'slot_id':slot.id})
target = reverse('ietf.secr.meetings.views.non_session', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name})
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(meeting.agenda.assignments.filter(timeslot=slot))
self.assertFalse(meeting.schedule.assignments.filter(timeslot=slot))
def test_meetings_non_session_cancel(self):
meeting = make_meeting_test_data()
slot = meeting.agenda.assignments.filter(timeslot__type='reg').first().timeslot
url = reverse('ietf.secr.meetings.views.non_session_cancel', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name,'slot_id':slot.id})
redirect_url = reverse('ietf.secr.meetings.views.non_session', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name})
slot = meeting.schedule.assignments.filter(timeslot__type='reg').first().timeslot
url = reverse('ietf.secr.meetings.views.non_session_cancel', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name,'slot_id':slot.id})
redirect_url = reverse('ietf.secr.meetings.views.non_session', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name})
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, redirect_url)
session = slot.sessionassignments.filter(schedule=meeting.agenda).first().session
session = slot.sessionassignments.filter(schedule=meeting.schedule).first().session
self.assertEqual(session.status_id, 'canceled')
def test_meetings_session_edit(self):
meeting = make_meeting_test_data()
session = Session.objects.filter(meeting=meeting,group__acronym='mars').first()
url = reverse('ietf.secr.meetings.views.session_edit', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name,'session_id':session.id})
redirect_url = reverse('ietf.secr.meetings.views.sessions', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name})
url = reverse('ietf.secr.meetings.views.session_edit', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name,'session_id':session.id})
redirect_url = reverse('ietf.secr.meetings.views.sessions', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.schedule.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)

View file

@ -40,7 +40,7 @@ def assign(session,timeslot,meeting,schedule=None):
Robust function to assign a session to a timeslot. Much simplyfied 2014-03-26.
'''
if schedule == None:
schedule = meeting.agenda
schedule = meeting.schedule
SchedTimeSessAssignment.objects.create(schedule=schedule,
session=session,
timeslot=timeslot)
@ -122,7 +122,7 @@ def is_combined(session,meeting,schedule=None):
Check to see if this session is using two combined timeslots
'''
if schedule == None:
schedule = meeting.agenda
schedule = meeting.schedule
if session.timeslotassignments.filter(schedule=schedule).count() > 1:
return True
else:
@ -230,7 +230,7 @@ def add(request):
owner = Person.objects.get(name='(System)'),
visible = True,
public = True)
meeting.agenda = schedule
meeting.schedule = schedule
# we want to carry session request lock status over from previous meeting
previous_meeting = get_meeting( int(meeting.number) - 1 )
@ -300,7 +300,7 @@ def blue_sheet_generate(request, meeting_id):
# TODO: Why aren't 'ag' in here as well?
groups = Group.objects.filter(
type__in=['wg','rg'],
session__timeslotassignments__schedule=meeting.agenda).order_by('acronym')
session__timeslotassignments__schedule=meeting.schedule).order_by('acronym')
create_blue_sheets(meeting, groups)
messages.success(request, 'Blue Sheets generated')
@ -560,7 +560,7 @@ def notifications(request, meeting_id):
meeting = get_object_or_404(Meeting, number=meeting_id)
last_notice = GroupEvent.objects.filter(type='sent_notification').first()
groups = set()
for ss in meeting.agenda.assignments.filter(timeslot__type='session'):
for ss in meeting.schedule.assignments.filter(timeslot__type='session'):
last_notice = ss.session.group.latest_event(type='sent_notification')
if last_notice and ss.modified > last_notice.time:
groups.add(ss.session.group)
@ -569,7 +569,7 @@ def notifications(request, meeting_id):
if request.method == "POST":
# ensure session state is scheduled
for ss in meeting.agenda.assignments.all():
for ss in meeting.schedule.assignments.all():
session = ss.session
if session.status.slug in ["schedw", "appr"]:
session.status_id = "sched"
@ -848,7 +848,7 @@ def view(request, meeting_id):
'''
meeting = get_object_or_404(Meeting, number=meeting_id)
return render(request, 'meetings/view.html', {
'meeting': meeting},
)

View file

@ -34,7 +34,7 @@ VIDEO_TITLE_RE = re.compile(r'IETF(?P<number>[\d]+)-(?P<name>.*)-(?P<date>\d{8})
def _get_session(number,name,date,time):
'''Lookup session using data from video title'''
meeting = Meeting.objects.get(number=number)
schedule = meeting.agenda
schedule = meeting.schedule
timeslot_time = datetime.datetime.strptime(date + time,'%Y%m%d%H%M')
try:
assignment = SchedTimeSessAssignment.objects.get(
@ -73,7 +73,7 @@ def import_audio_files(meeting):
timeslot = get_timeslot_for_filename(filename)
if timeslot:
sessionassignments = timeslot.sessionassignments.filter(
schedule=timeslot.meeting.agenda,
schedule=timeslot.meeting.schedule,
session__status='sched',
).exclude(session__agenda_note__icontains='canceled').order_by('timeslot__time')
if not sessionassignments:
@ -103,7 +103,7 @@ def get_timeslot_for_filename(filename):
meeting=meeting,
location__name=room_mapping[match.groupdict()['room']],
time=time,
sessionassignments__schedule=meeting.agenda,
sessionassignments__schedule=meeting.schedule,
).exclude(sessions__status_id='canceled').distinct()
return slots.get()
except (ObjectDoesNotExist, KeyError):

View file

@ -134,7 +134,7 @@ class RecordingTestCase(TestCase):
ames_session.status = scheduled
ames_session.save()
timeslot = mars_session.official_timeslotassignment().timeslot
SchedTimeSessAssignment.objects.create(timeslot=timeslot,session=ames_session,schedule=meeting.agenda)
SchedTimeSessAssignment.objects.create(timeslot=timeslot,session=ames_session,schedule=meeting.schedule)
self.create_audio_file_for_timeslot(timeslot)
import_audio_files(meeting)
doc = mars_session.materials.filter(type='recording').first()

View file

@ -232,7 +232,7 @@ def recording(request, meeting_num):
session.
'''
meeting = get_object_or_404(Meeting, number=meeting_num)
assignments = meeting.agenda.assignments.exclude(session__type__in=('reg','break')).order_by('session__group__acronym')
assignments = meeting.schedule.assignments.exclude(session__type__in=('reg','break')).order_by('session__group__acronym')
sessions = [ x.session for x in assignments ]
if request.method == 'POST':

View file

@ -327,7 +327,7 @@ def edit(request, *args, **kwargs):
def session_save(session):
session.save()
if session.status_id == "schedw" and session.meeting.agenda != None:
if session.status_id == "schedw" and session.meeting.schedule != None:
# send an email to iesg-secretariat to alert to change
pass

View file

@ -37,18 +37,18 @@
<li><button onclick="window.location='{% url "ietf.secr.meetings.views.edit_meeting" meeting_id=meeting.number %}'">Edit</button></li>
<li><button onclick="window.location='{% url "ietf.secr.meetings.views.notifications" meeting_id=meeting.number %}'">Notifications</button></li>
<li><button onclick="window.location='{% url "ietf.secr.meetings.views.blue_sheet" meeting_id=meeting.number %}'">Blue Sheets</button></li>
<li><button onclick="window.location='{% url "ietf.meeting.views.list_agendas" num=meeting.number %}'">Agenda List</button></li>
<li><button onclick="window.location='{% url "ietf.meeting.views.list_schedules" num=meeting.number %}'">Agenda List</button></li>
<li>
<form id="id_schedule_selector">
<select name="forma" onchange="location = this.options[this.selectedIndex].value;">
<option value="">Select a schedule...</option>
{% for sched in meeting.schedule_set.all %}
<option value="{{ sched.name }}">{{ sched.name }}{% if sched == meeting.agenda %} (official){% endif %}</option>
<option value="{{ sched.name }}">{{ sched.name }}{% if sched == meeting.schedule %} (official){% endif %}</option>
{% endfor %}
</select>
</form>
</li>
<li><button onclick="window.location='{% url "ietf.secr.meetings.views.rooms" meeting_id=meeting.number schedule_name=meeting.agenda.name %}'">Official Schedule</button></li>
<li><button onclick="window.location='{% url "ietf.secr.meetings.views.rooms" meeting_id=meeting.number schedule_name=meeting.schedule.name %}'">Official Schedule</button></li>
</ul>
</div> <!-- button-group -->

View file

@ -14,8 +14,8 @@
<tr class="{% cycle 'row1' 'row2' %}">
<td align="left" style="white-space: nowrap">{{ meeting.date }}</td>
<td><a href="https://datatracker.ietf.org/wg/{{ meeting.group.acronym }}">{{ meeting.group.acronym }}</a></td>
{% if meeting.agenda %}
<td width="70" align="center"><a href="{{ meeting.agenda.get_absolute_url }}">Agenda</a></td>
{% if meeting.schedule %}
<td width="70" align="center"><a href="{{ meeting.schedule.get_absolute_url }}">Agenda</a></td>
{% else %}
<td width="70" align="center">Agenda</td>
{% endif %}

View file

@ -1,3 +1,5 @@
# Copyright The IETF Trust 2013-2019, All Rights Reserved
import os
from django.conf import settings
@ -49,7 +51,7 @@ def get_session(timeslot, schedule=None):
'''
# todo, doesn't account for shared timeslot
if not schedule:
schedule = timeslot.meeting.agenda
schedule = timeslot.meeting.schedule
qs = timeslot.sessions.filter(timeslotassignments__schedule=schedule) #.exclude(states__slug='deleted')
if qs:
return qs[0]
@ -63,7 +65,7 @@ def get_timeslot(session, schedule=None):
schedule to use the meeting "official" schedule.
'''
if not schedule:
schedule = session.meeting.agenda
schedule = session.meeting.schedule
ss = session.timeslotassignments.filter(schedule=schedule)
if ss:
return ss[0].timeslot

View file

@ -33,7 +33,7 @@ li.daylistentry { margin-left:2em; font-weight: 400; }
<ul class="typelist">
{% for type in type_list %}
<li class="typelistentry {% cycle 'even' 'odd' %}">
<h2>{{type.grouper|title}}</h2> {% if schedule == meeting.agenda %}<a id="ical-link" class="btn btn-primary" href="{% url "ietf.meeting.views.agenda_by_type_ics" num=meeting.number type=type.grouper %}">Download to Calendar</a>{% endif %}
<h2>{{type.grouper|title}}</h2> {% if schedule == meeting.schedule %}<a id="ical-link" class="btn btn-primary" href="{% url "ietf.meeting.views.agenda_by_type_ics" num=meeting.number type=type.grouper %}">Download to Calendar</a>{% endif %}
<ul class="daylist">
{% regroup type.list by timeslot.time|date:"l Y-M-d" as daylist %}
{% for day in daylist %}

View file

@ -19,7 +19,7 @@
{# Null Form #}
{% buttons %}
<input class="btn btn-primary" type="submit" value="Delete schedule" name="save">
<a href="{% url 'ietf.meeting.views.list_agendas' num=meeting.number %}" class="btn btn-default">Cancel</a>
<a href="{% url 'ietf.meeting.views.list_schedules' num=meeting.number %}" class="btn btn-default">Cancel</a>
{% endbuttons %}
</form>

View file

@ -1,10 +1,10 @@
{% load ietf_filters %}{% if is_change %}MEETING DETAILS HAVE CHANGED. SEE LATEST DETAILS BELOW.
{% endif %}The {{ group.name }} ({{ group.acronym }}) {% if group.type.slug == "rg" %}Research Group{% elif group.state.slug == "active" %}Working Group{% elif group.state.slug == 'bof' %}BOF{% endif %} will hold
{% if meeting.session_set.count == 1 %}a{% if meeting.city %}n {% else %} virtual {% endif %}interim meeting on {{ meeting.date }} from {{ meeting.agenda.assignments.first.timeslot.time | date:"H:i" }} to {{ meeting.agenda.assignments.first.timeslot.end_time | date:"H:i" }} {{ meeting.time_zone }}.
{% if meeting.session_set.count == 1 %}a{% if meeting.city %}n {% else %} virtual {% endif %}interim meeting on {{ meeting.date }} from {{ meeting.schedule.assignments.first.timeslot.time | date:"H:i" }} to {{ meeting.schedule.assignments.first.timeslot.end_time | date:"H:i" }} {{ meeting.time_zone }}.
{% else %}a multi-day {% if not meeting.city %}virtual {% endif %}interim meeting.
{% for assignment in meeting.agenda.assignments.all %}Session {{ forloop.counter }}:
{% for assignment in meeting.schedule.assignments.all %}Session {{ forloop.counter }}:
{{ assignment.timeslot.time | date:"Y-m-d" }} {{ assignment.timeslot.time | date:"H:i" }} to {{ assignment.timeslot.end_time | date:"H:i" }} {{ meeting.time_zone }}
{% endfor %}{% endif %}
{% if meeting.city %}Meeting Location:

View file

@ -26,7 +26,7 @@
<dd>{{ meeting.country }}</dd>
<dt>Timezone</dt>
<dd>{{ meeting.time_zone }}</dd>
{% for assignment in meeting.agenda.assignments.all %}
{% for assignment in meeting.schedule.assignments.all %}
<br>
<dt>Date</dt>
<dd>{{ assignment.timeslot.time|date:"Y-m-d" }}

View file

@ -117,7 +117,7 @@ promiselist.push(ss_promise);
<div id="unassigned-items">
<div id="all_agendas" class="events_bar_buttons">
<a href="{% url "ietf.meeting.views.list_agendas" meeting.number %}">
<a href="{% url "ietf.meeting.views.list_schedules" meeting.number %}">
<button class="styled_button">all agendas</button>
</a>
</div>

View file

@ -20,7 +20,7 @@
{# Null Form #}
{% buttons %}
<input class="btn btn-primary" type="submit" value="Make this schedule official" name="save">
<a href="{% url 'ietf.meeting.views.list_agendas' num=meeting.number %}" class="btn btn-default">Cancel</a>
<a href="{% url 'ietf.meeting.views.list_schedules' num=meeting.number %}" class="btn btn-default">Cancel</a>
{% endbuttons %}
</form>

View file

@ -5,7 +5,7 @@
{% origin %}
{% if schedule != meeting.agenda %}
{% if schedule != meeting.schedule %}
<h3 class="alert alert-danger text-center">
This is schedule {{schedule.owner.email}}/{{ schedule.name }}, not the official schedule.
</h3>
@ -34,7 +34,7 @@
<li {% if selected == "agenda-utc" %}class="active"{% endif %}>
<a href="{% url 'ietf.meeting.views.agenda' num=schedule.meeting.number utc='-utc' %}">UTC Agenda</a></li>
{% if user|has_role:"Secretariat,Area Director,IAB" %}
{% if schedule != meeting.agenda %}
{% if schedule != meeting.schedule %}
<li {% if selected == "by-room" %}class="active"{% endif %}>
<a href="{% url 'ietf.meeting.views.agenda_by_room' num=schedule.meeting.number name=schedule.name owner=schedule.owner.email %}">by Room</a></li>
<li {% if selected == "by-type" %}class="active"{% endif %}>

View file

@ -15,7 +15,7 @@
<div id="read_only">
<p>You do not have access this agenda. It belongs to {{ schedule.owner }}.</p>
<p><a href="{% url "ietf.meeting.views.list_agendas" meeting.number %}">List your meetings</a>.</p>
<p><a href="{% url "ietf.meeting.views.list_schedules" meeting.number %}">List your meetings</a>.</p>
<div class="wrapper custom_text_stuff"></div>
</div>

View file

@ -25,7 +25,7 @@
{% bootstrap_form form %}
{% buttons %}
<input class="btn btn-primary" type="submit" value="Save" name="save">
<a href="{% url 'ietf.meeting.views.list_agendas' num=meeting.number %}" class="btn btn-default">Cancel</a>
<a href="{% url 'ietf.meeting.views.list_schedules' num=meeting.number %}" class="btn btn-default">Cancel</a>
{% endbuttons %}
</form>

View file

@ -30,14 +30,14 @@
<th class="col-md-1">Public</th>
<th class="col-md-1"></th>
</tr>
{% for agenda in class.list %}
{% for schedule in class.list %}
<tr>
<td><a href="{% url "ietf.meeting.views.edit_agenda" agenda.meeting.number agenda.owner_email agenda.name %}">
{{ agenda.name }}</a></td>
<td>{{ agenda.owner }}</td>
<td>{{ agenda.visible_token }}</td>
<td>{{ agenda.public_token }}</td>
<td><a class="btn btn-default" href="{% url "ietf.meeting.views.edit_agenda_properties" agenda.meeting.number agenda.owner_email agenda.name %}">
<td><a href="{% url "ietf.meeting.views.edit_schedule" schedule.meeting.number schedule.owner_email schedule.name %}">
{{ schedule.name }}</a></td>
<td>{{ schedule.owner }}</td>
<td>{{ schedule.visible_token }}</td>
<td>{{ schedule.public_token }}</td>
<td><a class="btn btn-default" href="{% url "ietf.meeting.views.edit_schedule_properties" schedule.meeting.number schedule.owner_email schedule.name %}">
EDIT</a></td>
</tr>
{% endfor %}