5858from ietf .meeting .models import Meeting , Session , Schedule , FloorPlan , SessionPresentation , TimeSlot , SlideSubmission
5959from ietf .meeting .models import SessionStatusName , SchedulingEvent , SchedTimeSessAssignment , Room , TimeSlotTypeName
6060from ietf .meeting .forms import ( CustomDurationField , SwapDaysForm , SwapTimeslotsForm ,
61- TimeSlotCreateForm , TimeSlotEditForm )
61+ TimeSlotCreateForm , TimeSlotEditForm , SessionEditForm )
6262from ietf .meeting .helpers import get_areas , get_person_by_email , get_schedule_by_name
6363from ietf .meeting .helpers import build_all_agenda_slices , get_wg_name_list
6464from ietf .meeting .helpers import get_all_assignments_from_schedule
@@ -500,6 +500,16 @@ def new_meeting_schedule(request, num, owner=None, name=None):
500500
501501@ensure_csrf_cookie
502502def edit_meeting_schedule (request , num = None , owner = None , name = None ):
503+ """Schedule editor
504+
505+ In addition to the URL parameters, accepts a query string parameter 'type'.
506+ If present, only sessions/timeslots with a TimeSlotTypeName with that slug
507+ will be included in the editor. More than one type can be enabled by passing
508+ multiple type parameters.
509+
510+ ?type=regular - shows only regular sessions/timeslots (i.e., old editor behavior)
511+ ?type=regular&type=other - shows both regular and other sessions/timeslots
512+ """
503513 # Need to coordinate this list with types of session requests
504514 # that can be created (see, e.g., SessionQuerySet.requests())
505515 IGNORE_TIMESLOT_TYPES = ('offagenda' , 'reserved' , 'unavail' )
@@ -532,22 +542,31 @@ def timeslot_locked(ts):
532542 "hide_menu" : True
533543 }, status = 403 , content_type = "text/html" )
534544
545+ # See if we were given one or more 'type' query string parameters. If so, filter to that timeslot type.
546+ if 'type' in request .GET :
547+ include_timeslot_types = request .GET .getlist ('type' )
548+ else :
549+ include_timeslot_types = None # disables filtering by type (other than IGNORE_TIMESLOT_TYPES)
550+
535551 assignments = SchedTimeSessAssignment .objects .filter (
536552 schedule__in = [schedule , schedule .base ],
537553 timeslot__location__isnull = False ,
538- # session__type='regular',
539- ).order_by ('timeslot__time' ,'timeslot__name' )
554+ )
555+ if include_timeslot_types is not None :
556+ assignments = assignments .filter (session__type__in = include_timeslot_types )
557+ assignments = assignments .order_by ('timeslot__time' ,'timeslot__name' )
540558
541559 assignments_by_session = defaultdict (list )
542560 for a in assignments :
543561 assignments_by_session [a .session_id ].append (a )
544562
545563 tombstone_states = ['canceled' , 'canceledpa' , 'resched' ]
546564
565+ sessions = Session .objects .filter (meeting = meeting )
566+ if include_timeslot_types is not None :
567+ sessions = sessions .filter (type__in = include_timeslot_types )
547568 sessions = add_event_info_to_session_qs (
548- Session .objects .filter (
549- meeting = meeting ,
550- ).exclude (
569+ sessions .exclude (
551570 type__in = IGNORE_TIMESLOT_TYPES ,
552571 ).order_by ('pk' ),
553572 requested_time = True ,
@@ -559,14 +578,19 @@ def timeslot_locked(ts):
559578 'resources' , 'group' , 'group__parent' , 'group__type' , 'joint_with_groups' , 'purpose' ,
560579 )
561580
562- timeslots_qs = TimeSlot .objects .filter (
563- meeting = meeting ,
564- ).exclude (
581+ timeslots_qs = TimeSlot .objects .filter (meeting = meeting )
582+ if include_timeslot_types is not None :
583+ timeslots_qs = timeslots_qs .filter (type__in = include_timeslot_types )
584+ timeslots_qs = timeslots_qs .exclude (
565585 type__in = IGNORE_TIMESLOT_TYPES ,
566586 ).prefetch_related ('type' ).order_by ('location' , 'time' , 'name' )
567587
568- min_duration = min (t .duration for t in timeslots_qs )
569- max_duration = max (t .duration for t in timeslots_qs )
588+ if timeslots_qs .count () > 0 :
589+ min_duration = min (t .duration for t in timeslots_qs )
590+ max_duration = max (t .duration for t in timeslots_qs )
591+ else :
592+ min_duration = 1
593+ max_duration = 2
570594
571595 def timedelta_to_css_ems (timedelta ):
572596 # we scale the session and slots a bit according to their
@@ -707,7 +731,10 @@ def prepare_timeslots_for_display(timeslots, rooms):
707731
708732 all_days = sorted (all_days ) # changes set to a list
709733 # Note the maximum timeslot count for any room
710- max_timeslots = max (rd ['timeslot_count' ] for rd in room_data .values ())
734+ if len (room_data ) > 0 :
735+ max_timeslots = max (rd ['timeslot_count' ] for rd in room_data .values ())
736+ else :
737+ max_timeslots = 0
711738
712739 # Partition rooms into groups with identical timeslot arrangements.
713740 # Start by discarding any roos that have no timeslots.
@@ -920,7 +947,10 @@ def _json_response(success, status=None, **extra_data):
920947 return _json_response (False , error = "Invalid parameters" )
921948
922949 # Show only rooms that have regular sessions
923- rooms = meeting .room_set .filter (session_types__slug = 'regular' )
950+ if include_timeslot_types is None :
951+ rooms = meeting .room_set .all ()
952+ else :
953+ rooms = meeting .room_set .filter (session_types__slug__in = include_timeslot_types )
924954
925955 # Construct timeslot data for the template to render
926956 days = prepare_timeslots_for_display (timeslots_qs , rooms )
@@ -1583,7 +1613,7 @@ def get_assignments_for_agenda(schedule):
15831613 """Get queryset containing assignments to show on the agenda"""
15841614 return SchedTimeSessAssignment .objects .filter (
15851615 schedule__in = [schedule , schedule .base ],
1586- timeslot__type__private = False ,
1616+ session__on_agenda = True ,
15871617 )
15881618
15891619
@@ -1938,7 +1968,7 @@ def week_view(request, num=None, name=None, owner=None):
19381968
19391969 filtered_assignments = SchedTimeSessAssignment .objects .filter (
19401970 schedule__in = [schedule , schedule .base ],
1941- timeslot__type__private = False ,
1971+ session__on_agenda = True ,
19421972 )
19431973 filtered_assignments = preprocess_assignments_for_agenda (filtered_assignments , meeting )
19441974 AgendaKeywordTagger (assignments = filtered_assignments ).apply ()
@@ -2121,7 +2151,7 @@ def agenda_ical(request, num=None, name=None, acronym=None, session_id=None):
21212151
21222152 assignments = SchedTimeSessAssignment .objects .filter (
21232153 schedule__in = [schedule , schedule .base ],
2124- timeslot__type__private = False ,
2154+ session__on_agenda = True ,
21252155 )
21262156 assignments = preprocess_assignments_for_agenda (assignments , meeting )
21272157 AgendaKeywordTagger (assignments = assignments ).apply ()
@@ -2159,7 +2189,7 @@ def agenda_json(request, num=None):
21592189 parent_acronyms = set ()
21602190 assignments = SchedTimeSessAssignment .objects .filter (
21612191 schedule__in = [meeting .schedule , meeting .schedule .base if meeting .schedule else None ],
2162- timeslot__type__private = False ,
2192+ session__on_agenda = True ,
21632193 ).exclude (
21642194 session__type__in = ['break' , 'reg' ]
21652195 )
@@ -4098,6 +4128,24 @@ def create_timeslot(request, num):
40984128 )
40994129
41004130
4131+ @role_required ('Secretariat' )
4132+ def edit_session (request , session_id ):
4133+ session = get_object_or_404 (Session , pk = session_id )
4134+ if request .method == 'POST' :
4135+ form = SessionEditForm (instance = session , data = request .POST )
4136+ if form .is_valid ():
4137+ form .save ()
4138+ return HttpResponseRedirect (
4139+ reverse ('ietf.meeting.views.edit_meeting_schedule' ,
4140+ kwargs = {'num' : form .instance .meeting .number }))
4141+ else :
4142+ form = SessionEditForm (instance = session )
4143+ return render (
4144+ request ,
4145+ 'meeting/edit_session.html' ,
4146+ {'session' : session , 'form' : form },
4147+ )
4148+
41014149@role_required ('Secretariat' )
41024150def request_minutes (request , num = None ):
41034151 meeting = get_ietf_meeting (num )
0 commit comments