diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 09af58d67..788639699 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -34,7 +34,7 @@ from ietf.utils.text import xslugify from ietf.person.factories import PersonFactory from ietf.group.factories import GroupFactory, GroupEventFactory from ietf.meeting.factories import ( SessionFactory, SessionPresentationFactory, ScheduleFactory, - MeetingFactory, FloorPlanFactory ) + MeetingFactory, FloorPlanFactory, TimeSlotFactory ) from ietf.doc.factories import DocumentFactory @@ -536,6 +536,17 @@ class EditTests(TestCase): self.assertEqual(r.status_code, 200) self.assertTrue(meeting.room_set.all().first().name in unicontent(r)) + def test_edit_timeslot_type(self): + timeslot = TimeSlotFactory() + url = urlreverse('ietf.meeting.views.edit_timeslot_type', kwargs=dict(num=timeslot.meeting.number,slot_id=timeslot.id)) + login_testing_unauthorized(self,"secretary",url) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + r = self.client.post(url,{'type':'other',}) + self.assertEqual(r.status_code, 302) + timeslot = TimeSlot.objects.get(id=timeslot.id) + self.assertEqual(timeslot.type.slug,'other') + def test_slot_to_the_right(self): meeting = make_meeting_test_data() session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index f2cb32091..2c15b1ffb 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -41,6 +41,7 @@ type_ietf_only_patterns = [ 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'^timeslots/edit$', views.edit_timeslots), + url(r'^timeslot/(?P\d+)/edittype$', views.edit_timeslot_type), url(r'^rooms$', ajax.timeslot_roomsurl), url(r'^room/(?P\d+).json$', ajax.timeslot_roomurl), url(r'^timeslots$', ajax.timeslot_slotsurl), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index ec73d5bf8..1a19c5317 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -6,7 +6,7 @@ import re import tarfile import urllib from tempfile import mkstemp -from collections import OrderedDict, Counter +from collections import OrderedDict, Counter, deque import csv import json import pytz @@ -39,7 +39,7 @@ from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent from ietf.group.models import Group from ietf.group.utils import can_manage_materials from ietf.ietfauth.utils import role_required, has_role -from ietf.meeting.models import Meeting, Session, Schedule, FloorPlan, SessionPresentation +from ietf.meeting.models import Meeting, Session, Schedule, FloorPlan, SessionPresentation, TimeSlot from ietf.meeting.helpers import get_areas, get_person_by_email, get_schedule_by_name from ietf.meeting.helpers import build_all_agenda_slices, get_wg_name_list from ietf.meeting.helpers import get_all_assignments_from_schedule @@ -266,41 +266,29 @@ def agenda_create(request, num=None, owner=None, name=None): @role_required('Secretariat') -@ensure_csrf_cookie def edit_timeslots(request, num=None): meeting = get_meeting(num) - timeslots = meeting.timeslot_set.exclude(location=None).select_related("location", "type") time_slices,date_slices,slots = meeting.build_timeslices() - meeting_base_url = request.build_absolute_uri(meeting.base_url()) - site_base_url = request.build_absolute_uri('/')[:-1] # skip the trailing slash - - rooms = meeting.room_set.order_by("capacity") - - # this import locate here to break cyclic loop. - from ietf.meeting.ajax import timeslot_roomsurl, AddRoomForm, timeslot_slotsurl, AddSlotForm - roomsurl = reverse(timeslot_roomsurl, args=[meeting.number]) - adddayurl = reverse(timeslot_slotsurl, args=[meeting.number]) + ts_list = deque() + rooms = meeting.room_set.order_by("capacity","name","id") + for room in rooms: + for day in time_slices: + for slice in date_slices[day]: + ts_list.append(room.timeslot_set.filter(time=slice[0],duration=datetime.timedelta(seconds=slice[2])).first()) + return render(request, "meeting/timeslot_edit.html", - {"timeslots": timeslots, - "meeting_base_url": meeting_base_url, - "site_base_url": site_base_url, - "rooms":rooms, - "addroom": AddRoomForm(), - "roomsurl": roomsurl, - "addday": AddSlotForm(), - "adddayurl":adddayurl, + {"rooms":rooms, "time_slices":time_slices, "slot_slices": slots, "date_slices":date_slices, "meeting":meeting, - "hide_menu": True, + "ts_list":ts_list, }) - ############################################################################## #@role_required('Area Director','Secretariat') # disable the above security for now, check it below. @@ -2204,3 +2192,26 @@ def important_dates(request, num=None): context={'meetings':meetings} return render(request, 'meeting/important-dates.html', context) + +TimeSlotTypeForm = modelform_factory(TimeSlot, fields=('type',)) + +@role_required('Secretariat') +def edit_timeslot_type(request, num, slot_id): + timeslot = get_object_or_404(TimeSlot,id=slot_id) + meeting = get_object_or_404(Meeting,number=num) + if timeslot.meeting!=meeting: + raise Http404() + if request.method=='POST': + form = TimeSlotTypeForm(instance=timeslot,data=request.POST) + if form.is_valid(): + form.save() + return HttpResponseRedirect(reverse('ietf.meeting.views.edit_timeslots',kwargs={'num':num})) + + else: + form = TimeSlotTypeForm(instance=timeslot) + + sessions = timeslot.sessions.filter(timeslotassignments__schedule=meeting.agenda) + + return render(request, 'meeting/edit_timeslot_type.html', {'timeslot':timeslot,'form':form,'sessions':sessions}) + + diff --git a/ietf/templates/meeting/edit_timeslot_type.html b/ietf/templates/meeting/edit_timeslot_type.html new file mode 100644 index 000000000..ddaec88dc --- /dev/null +++ b/ietf/templates/meeting/edit_timeslot_type.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{# Copyright The IETF Trust 2018, All Rights Reserved #} +{% load origin %} +{% load bootstrap3 %} + +{% block title %}Edit timeslot type for {{timeslot}}{% endblock %} + +{% block content %} + {% origin %} +

Edit timeslot type for {{timeslot}}

+ {% if sessions %} +
+ This timeslot currently has the following sessions assigned to it: + {% for s in sessions %} +
{{s}}
+ {% endfor %} +
+ {% endif %} +
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + Cancel + {% endbuttons %} +
+{% endblock %} diff --git a/ietf/templates/meeting/timeslot_edit.html b/ietf/templates/meeting/timeslot_edit.html index 4d7627563..d75ad70d3 100644 --- a/ietf/templates/meeting/timeslot_edit.html +++ b/ietf/templates/meeting/timeslot_edit.html @@ -1,187 +1,57 @@ {% extends "base.html" %} {# Copyright The IETF Trust 2015, All Rights Reserved #} {% load origin %} -{% load staticfiles %} -{% load ietf_filters %} -{% load humanize %} +{% load agenda_custom_tags %} {% block title %}IETF {{ meeting.number }} Meeting Agenda: Timeslot/Room Availability{% endblock %} -{% load agenda_custom_tags %} -{% block pagehead %} - - - -{% endblock pagehead %} -{% block js %} - - - - - - - - - - - - - - - - - - - - - - - - - - - -{% endblock js %} +{% block morecss %} +.tstable { width: 100%;} +.tstable th { white-space: nowrap;} +.tstable td { white-space: nowrap;} +.capacity { font-size:80%; font-weight: normal;} +.tstable .tstype_unavail {background-color:#666;} +{% endblock %} {% block content %} {% origin %} -
-
-< -
-
- - - -{% for day in time_slices %} - - -{% endfor %} - - - +
-
-
- - {{day|date:'D'}} ({{day}}) - - -
-
-
-
-
+ROOM
-
+DAY
-
+ + + + {% for day in time_slices %} + + {% endfor %} + + + {% for day in time_slices %} {% for slot in slot_slices|lookup:day %} - - {% endfor %} - - {% endfor %} + + - {% for r in rooms %} - - + {% for room in rooms %} + + {% for day in time_slices %} - {% for slot in date_slices|lookup:day %} - + {% for slice in date_slices|lookup:day %} + {% with ts=ts_list.popleft %} + {% if ts %}{{ts.type.slug}}{% endif %} + {% endwith %} {% endfor %} - {% endfor %} {% endfor %}
+ {{day|date:'D'}} ({{day}}) +
-
X
- {{slot.time|date:'Hi'}}-{{slot.end_time|date:'Hi'}} +
+ {{slot.time|date:'Hi'}}-{{slot.end_time|date:'Hi'}} -
-
X
- - - -
-
- {% for resource in r.resources.all %} - - {% if resource.id == "project" %} {{resource.desc}}{% endif %} - {% if resource.id == "proj2" %} {{resource.desc}}{% endif %} - {% if resource.id == "meetecho" %} {{resource.desc}}{% endif %} - {% if resource.id == "boardroom" %} {{resource.desc}}{% endif %} - - {% endfor %} -
-
{{room.name}}{% if room.capacity %} ({{room.capacity}}){% endif %}
-
-
-
{% csrf_token %} - - {{ addroom.as_table }} - -
-
-
-
- - {% csrf_token %} - {{ addday }} - - - - -
-
- -
- Are you sure you want to delete this room? -
- -
- Are you sure you want to delete this entire timeslot? -
- {% endblock %}