fix: more small timezone-aware fixes (#4489)

* fix: use meeting timezone for agenda_by_(room|type)

* refactor: use timezone.override instead of timezone.activate/deactivate

* fix: add timezone info in create-charter-newrevisiondocevents

* fix: use meeting timezone for recording.html template

* fix: use meeting timezone for slide submission timeslot display

* fix: use meeting timezone for schedule diff template

* fix: use meeting timezone for edit_meeting_timeslots_and_misc_sessions

* fix: use meeting timezone for materials() view

* fix: use meeting timezone for proceedings() view

* refactor: force timestamps to utc in important_dates_for_meeting.ics

Has no effect now, but guarantees consistency with template's assertion
that its timestamps are in UTC.

* fix: use meeting timezone for a couple interim meeting templates

* fix: use meeting timezone for propose_session_slides template

* fix: use meeting timezone for upload_session_*.html

* fix: use meeting timezone for a couple session templates
This commit is contained in:
Jennifer Richards 2022-09-22 12:19:56 -03:00 committed by GitHub
parent 00cf7cf8ca
commit 63a1baf116
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 295 additions and 296 deletions

View file

@ -28,7 +28,7 @@ def warn(string):
# ------------------------------------------------------------------------------
import re
from datetime import datetime as Datetime
import datetime
import django
django.setup()
@ -44,7 +44,7 @@ system_entity = Person.objects.get(name="(System)")
charterdir = Path(settings.CHARTER_PATH)
for file in charterdir.files("charter-ietf-*.txt"):
fname = file.name
ftime = Datetime.fromtimestamp(file.mtime)
ftime = datetime.datetime.fromtimestamp(file.mtime, datetime.timezone.utc)
match = re.search("^(?P<name>[a-z0-9-]+)-(?P<rev>\d\d-\d\d)\.txt$", fname)
if match:
name = match.group("name")

View file

@ -136,12 +136,13 @@ def materials(request, num=None):
if meeting.number.isdigit() and int(meeting.number) > 96:
return redirect('ietf.meeting.views.proceedings', num=meeting.number)
else:
return render(request, "meeting/materials_upload_closed.html", {
'meeting_num': meeting.number,
'begin_date': begin_date,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date
})
with timezone.override(meeting.tz()):
return render(request, "meeting/materials_upload_closed.html", {
'meeting_num': meeting.number,
'begin_date': begin_date,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date
})
past_cutoff_date = date_today() > meeting.get_submission_correction_date()
@ -177,20 +178,21 @@ def materials(request, num=None):
for type_name in ProceedingsMaterialTypeName.objects.all()
]
return render(request, "meeting/materials.html", {
'meeting': meeting,
'proceedings_materials': proceedings_materials,
'plenaries': plenaries,
'ietf': ietf,
'training': training,
'irtf': irtf,
'iab': iab,
'other': other,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date,
'submission_started': now > begin_date,
'old': old,
})
with timezone.override(meeting.tz()):
return render(request, "meeting/materials.html", {
'meeting': meeting,
'proceedings_materials': proceedings_materials,
'plenaries': plenaries,
'ietf': ietf,
'training': training,
'irtf': irtf,
'iab': iab,
'other': other,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date,
'submission_started': now > begin_date,
'old': old,
})
def current_materials(request):
today = date_today()
@ -282,8 +284,7 @@ def materials_editable_groups(request, num=None):
def edit_timeslots(request, num=None):
meeting = get_meeting(num)
timezone.activate(meeting.tz())
try:
with timezone.override(meeting.tz()):
if request.method == 'POST':
# handle AJAX requests
action = request.POST.get('action')
@ -337,8 +338,7 @@ def edit_timeslots(request, num=None):
"ts_with_official_assignments": ts_with_official_assignments,
"ts_with_any_assignments": ts_with_any_assignments,
})
finally:
timezone.deactivate()
class NewScheduleForm(forms.ModelForm):
class Meta:
@ -992,7 +992,7 @@ class RoomNameModelChoiceField(forms.ModelChoiceField):
return obj.name
class TimeSlotForm(forms.Form):
day = forms.TypedChoiceField(coerce=lambda t: datetime.datetime.strptime(t, "%Y-%m-%d").date())
day = forms.TypedChoiceField(coerce=lambda t: datetime.datetime.strptime(t, "%Y-%m-%d").date()) # all dates, no tz
time = forms.TimeField()
duration = CustomDurationField() # this is just to make 1:30 turn into 1.5 hours instead of 1.5 minutes
location = RoomNameModelChoiceField(queryset=Room.objects.all(), required=False, empty_label="(No location)")
@ -1032,8 +1032,8 @@ class TimeSlotForm(forms.Form):
if timeslot:
self.initial = {
'day': timeslot.time.date(),
'time': timeslot.time.time(),
'day': timeslot.local_start_time().date(),
'time': timeslot.local_start_time().time(),
'duration': timeslot.duration,
'location': timeslot.location_id,
'show_location': timeslot.show_location,
@ -1112,238 +1112,239 @@ def edit_meeting_timeslots_and_misc_sessions(request, num=None, owner=None, name
can_edit = has_role(request.user, 'Secretariat')
if request.method == 'GET' and request.GET.get('action') == "edit-timeslot":
timeslot_pk = request.GET.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(timeslot_qs, pk=timeslot_pk)
with timezone.override(meeting.tz()):
if request.method == 'GET' and request.GET.get('action') == "edit-timeslot":
timeslot_pk = request.GET.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(timeslot_qs, pk=timeslot_pk)
assigned_session = add_event_info_to_session_qs(Session.objects.filter(
timeslotassignments__schedule__in=[schedule, schedule.base],
timeslotassignments__timeslot=timeslot,
)).first()
assigned_session = add_event_info_to_session_qs(Session.objects.filter(
timeslotassignments__schedule__in=[schedule, schedule.base],
timeslotassignments__timeslot=timeslot,
)).first()
timeslot.can_cancel = not assigned_session or assigned_session.current_status not in ['canceled', 'canceled', 'resched']
timeslot.can_cancel = not assigned_session or assigned_session.current_status not in ['canceled', 'canceled', 'resched']
return JsonResponse({
'form': render_to_string("meeting/edit_timeslot_form.html", {
'timeslot_form_action': 'edit',
'timeslot_form': TimeSlotForm(meeting, schedule, timeslot=timeslot),
'timeslot': timeslot,
'schedule': schedule,
'meeting': meeting,
'can_edit': can_edit,
}, request=request)
})
return JsonResponse({
'form': render_to_string("meeting/edit_timeslot_form.html", {
'timeslot_form_action': 'edit',
'timeslot_form': TimeSlotForm(meeting, schedule, timeslot=timeslot),
'timeslot': timeslot,
'schedule': schedule,
'meeting': meeting,
'can_edit': can_edit,
}, request=request)
})
scroll = request.POST.get('scroll')
scroll = request.POST.get('scroll')
def redirect_with_scroll():
url = request.get_full_path()
if scroll and scroll.isdecimal():
url += "#scroll={}".format(scroll)
return HttpResponseRedirect(url)
def redirect_with_scroll():
url = request.get_full_path()
if scroll and scroll.isdecimal():
url += "#scroll={}".format(scroll)
return HttpResponseRedirect(url)
add_timeslot_form = None
if request.method == 'POST' and request.POST.get('action') == 'add-timeslot' and can_edit:
add_timeslot_form = TimeSlotForm(meeting, schedule, request.POST)
if add_timeslot_form.is_valid():
c = add_timeslot_form.cleaned_data
add_timeslot_form = None
if request.method == 'POST' and request.POST.get('action') == 'add-timeslot' and can_edit:
add_timeslot_form = TimeSlotForm(meeting, schedule, request.POST)
if add_timeslot_form.is_valid():
c = add_timeslot_form.cleaned_data
timeslot, created = TimeSlot.objects.get_or_create(
meeting=meeting,
type=c['type'],
name=c['name'],
time=meeting.tz().localize(datetime.datetime.combine(c['day'], c['time'])),
duration=c['duration'],
location=c['location'],
show_location=c['show_location'],
)
timeslot, created = TimeSlot.objects.get_or_create(
meeting=meeting,
type=c['type'],
name=c['name'],
time=meeting.tz().localize(datetime.datetime.combine(c['day'], c['time'])),
duration=c['duration'],
location=c['location'],
show_location=c['show_location'],
)
if timeslot.type_id != 'regular':
if not created:
Session.objects.filter(timeslotassignments__timeslot=timeslot).delete()
session = Session.objects.create(
meeting=meeting,
name=c['name'],
short=c['short'],
group=c['group'],
type=c['type'],
purpose=c['purpose'],
agenda_note=c.get('agenda_note') or "",
)
SchedulingEvent.objects.create(
session=session,
status=SessionStatusName.objects.get(slug='sched'),
by=request.user.person,
)
SchedTimeSessAssignment.objects.create(
timeslot=timeslot,
session=session,
schedule=schedule
)
return redirect_with_scroll()
edit_timeslot_form = None
if request.method == 'POST' and request.POST.get('action') == 'edit-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
edit_timeslot_form = TimeSlotForm(meeting, schedule, request.POST, timeslot=timeslot)
if edit_timeslot_form.is_valid() and edit_timeslot_form.active_assignment.schedule_id == schedule.pk:
c = edit_timeslot_form.cleaned_data
timeslot.type = c['type']
timeslot.name = c['name']
timeslot.time = meeting.tz().localize(datetime.datetime.combine(c['day'], c['time']))
timeslot.duration = c['duration']
timeslot.location = c['location']
timeslot.show_location = c['show_location']
timeslot.save()
session = Session.objects.filter(
timeslotassignments__schedule__in=[schedule, schedule.base if schedule else None],
timeslotassignments__timeslot=timeslot,
).select_related('group').first()
if session:
if timeslot.type_id != 'regular':
session.name = c['name']
session.short = c['short']
session.group = c['group']
session.type = c['type']
session.agenda_note = c.get('agenda_note') or ""
session.save()
return redirect_with_scroll()
if request.method == 'POST' and request.POST.get('action') == 'cancel-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
if timeslot.type_id != 'break':
sessions = add_event_info_to_session_qs(
Session.objects.filter(timeslotassignments__schedule=schedule, timeslotassignments__timeslot=timeslot),
).exclude(current_status__in=['canceled', 'resched'])
for session in sessions:
SchedulingEvent.objects.create(
session=session,
status=SessionStatusName.objects.get(slug='canceled'),
by=request.user.person,
)
return redirect_with_scroll()
if request.method == 'POST' and request.POST.get('action') == 'delete-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
if timeslot.type_id != 'regular':
if not created:
Session.objects.filter(timeslotassignments__timeslot=timeslot).delete()
for session in Session.objects.filter(timeslotassignments__schedule=schedule, timeslotassignments__timeslot=timeslot):
for doc in session.materials.all():
doc.set_state(State.objects.get(type=doc.type_id, slug='deleted'))
e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='deleted')
e.desc = "Deleted meeting session"
e.save()
session = Session.objects.create(
session.delete()
timeslot.delete()
return redirect_with_scroll()
sessions_by_pk = {
s.pk: s for s in
add_event_info_to_session_qs(
Session.objects.filter(
meeting=meeting,
name=c['name'],
short=c['short'],
group=c['group'],
type=c['type'],
purpose=c['purpose'],
agenda_note=c.get('agenda_note') or "",
)
).order_by('pk'),
requested_time=True,
requested_by=True,
).filter(
current_status__in=['appr', 'schedw', 'scheda', 'sched', 'canceled', 'canceledpa', 'resched']
).prefetch_related(
'group', 'group', 'group__type',
)
}
SchedulingEvent.objects.create(
session=session,
status=SessionStatusName.objects.get(slug='sched'),
by=request.user.person,
)
assignments_by_timeslot = defaultdict(list)
for a in SchedTimeSessAssignment.objects.filter(schedule__in=[schedule, schedule.base]):
assignments_by_timeslot[a.timeslot_id].append(a)
SchedTimeSessAssignment.objects.create(
timeslot=timeslot,
session=session,
schedule=schedule
)
days = [meeting.date + datetime.timedelta(days=i) for i in range(meeting.days)]
return redirect_with_scroll()
timeslots_by_day_and_room = defaultdict(list)
for t in timeslot_qs:
timeslots_by_day_and_room[(t.time.date(), t.location_id)].append(t)
edit_timeslot_form = None
if request.method == 'POST' and request.POST.get('action') == 'edit-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
# Calculate full time range for display in meeting-local time, always showing at least 8am to 10pm
min_time = min([t.local_start_time().time() for t in timeslot_qs] + [datetime.time(8)])
max_time = max([t.local_end_time().time() for t in timeslot_qs] + [datetime.time(22)])
min_max_delta = datetime.datetime.combine(meeting.date, max_time) - datetime.datetime.combine(meeting.date, min_time)
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
day_grid = []
for d in days:
room_timeslots = []
for r in rooms:
ts = []
for t in timeslots_by_day_and_room.get((d, r.pk), []):
# FIXME: the database (as of 2020) contains spurious
# regular timeslots in rooms not intended for regular
# sessions - once those are gone, this filter can go
# away
if t.type_id == 'regular' and not any(t.slug == 'regular' for t in r.session_types.all()):
continue
edit_timeslot_form = TimeSlotForm(meeting, schedule, request.POST, timeslot=timeslot)
if edit_timeslot_form.is_valid() and edit_timeslot_form.active_assignment.schedule_id == schedule.pk:
t.assigned_sessions = []
for a in assignments_by_timeslot.get(t.pk, []):
s = sessions_by_pk.get(a.session_id)
if s:
t.assigned_sessions.append(s)
c = edit_timeslot_form.cleaned_data
local_start_dt = t.local_start_time()
local_min_dt = local_start_dt.replace(
hour=min_time.hour,
minute=min_time.minute,
second=min_time.second,
microsecond=min_time.microsecond,
)
t.left_offset = 100.0 * (local_start_dt - local_min_dt) / min_max_delta
t.layout_width = min(100.0 * t.duration / min_max_delta, 100 - t.left_offset)
ts.append(t)
timeslot.type = c['type']
timeslot.name = c['name']
timeslot.time = meeting.tz().localize(datetime.datetime.combine(c['day'], c['time']))
timeslot.duration = c['duration']
timeslot.location = c['location']
timeslot.show_location = c['show_location']
timeslot.save()
room_timeslots.append((r, ts))
session = Session.objects.filter(
timeslotassignments__schedule__in=[schedule, schedule.base if schedule else None],
timeslotassignments__timeslot=timeslot,
).select_related('group').first()
day_grid.append({
'day': d,
'room_timeslots': room_timeslots
})
if session:
if timeslot.type_id != 'regular':
session.name = c['name']
session.short = c['short']
session.group = c['group']
session.type = c['type']
session.agenda_note = c.get('agenda_note') or ""
session.save()
return redirect_with_scroll()
if request.method == 'POST' and request.POST.get('action') == 'cancel-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
if timeslot.type_id != 'break':
sessions = add_event_info_to_session_qs(
Session.objects.filter(timeslotassignments__schedule=schedule, timeslotassignments__timeslot=timeslot),
).exclude(current_status__in=['canceled', 'resched'])
for session in sessions:
SchedulingEvent.objects.create(
session=session,
status=SessionStatusName.objects.get(slug='canceled'),
by=request.user.person,
)
return redirect_with_scroll()
if request.method == 'POST' and request.POST.get('action') == 'delete-timeslot' and can_edit:
timeslot_pk = request.POST.get('timeslot')
if not timeslot_pk or not timeslot_pk.isdecimal():
raise Http404
timeslot = get_object_or_404(TimeSlot, pk=timeslot_pk)
if timeslot.type_id != 'regular':
for session in Session.objects.filter(timeslotassignments__schedule=schedule, timeslotassignments__timeslot=timeslot):
for doc in session.materials.all():
doc.set_state(State.objects.get(type=doc.type_id, slug='deleted'))
e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='deleted')
e.desc = "Deleted meeting session"
e.save()
session.delete()
timeslot.delete()
return redirect_with_scroll()
sessions_by_pk = {
s.pk: s for s in
add_event_info_to_session_qs(
Session.objects.filter(
meeting=meeting,
).order_by('pk'),
requested_time=True,
requested_by=True,
).filter(
current_status__in=['appr', 'schedw', 'scheda', 'sched', 'canceled', 'canceledpa', 'resched']
).prefetch_related(
'group', 'group', 'group__type',
)
}
assignments_by_timeslot = defaultdict(list)
for a in SchedTimeSessAssignment.objects.filter(schedule__in=[schedule, schedule.base]):
assignments_by_timeslot[a.timeslot_id].append(a)
days = [meeting.date + datetime.timedelta(days=i) for i in range(meeting.days)]
timeslots_by_day_and_room = defaultdict(list)
for t in timeslot_qs:
timeslots_by_day_and_room[(t.time.date(), t.location_id)].append(t)
# Calculate full time range for display in meeting-local time, always showing at least 8am to 10pm
min_time = min([t.local_start_time().time() for t in timeslot_qs] + [datetime.time(8)])
max_time = max([t.local_end_time().time() for t in timeslot_qs] + [datetime.time(22)])
min_max_delta = datetime.datetime.combine(meeting.date, max_time) - datetime.datetime.combine(meeting.date, min_time)
day_grid = []
for d in days:
room_timeslots = []
for r in rooms:
ts = []
for t in timeslots_by_day_and_room.get((d, r.pk), []):
# FIXME: the database (as of 2020) contains spurious
# regular timeslots in rooms not intended for regular
# sessions - once those are gone, this filter can go
# away
if t.type_id == 'regular' and not any(t.slug == 'regular' for t in r.session_types.all()):
continue
t.assigned_sessions = []
for a in assignments_by_timeslot.get(t.pk, []):
s = sessions_by_pk.get(a.session_id)
if s:
t.assigned_sessions.append(s)
local_start_dt = t.local_start_time()
local_min_dt = local_start_dt.replace(
hour=min_time.hour,
minute=min_time.minute,
second=min_time.second,
microsecond=min_time.microsecond,
)
t.left_offset = 100.0 * (local_start_dt - local_min_dt) / min_max_delta
t.layout_width = min(100.0 * t.duration / min_max_delta, 100 - t.left_offset)
ts.append(t)
room_timeslots.append((r, ts))
day_grid.append({
'day': d,
'room_timeslots': room_timeslots
return render(request, "meeting/edit_meeting_timeslots_and_misc_sessions.html", {
'meeting': meeting,
'schedule': schedule,
'can_edit': can_edit,
'day_grid': day_grid,
'empty_timeslot_form': TimeSlotForm(meeting, schedule),
'add_timeslot_form': add_timeslot_form,
'edit_timeslot_form': edit_timeslot_form,
'scroll': scroll,
'hide_menu': True,
})
return render(request, "meeting/edit_meeting_timeslots_and_misc_sessions.html", {
'meeting': meeting,
'schedule': schedule,
'can_edit': can_edit,
'day_grid': day_grid,
'empty_timeslot_form': TimeSlotForm(meeting, schedule),
'add_timeslot_form': add_timeslot_form,
'edit_timeslot_form': edit_timeslot_form,
'scroll': scroll,
'hide_menu': True,
})
class SchedulePropertiesForm(forms.ModelForm):
class Meta:
@ -1565,8 +1566,7 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
is_current_meeting = (num is None) or (num == get_current_ietf_meeting_num())
display_timezone = 'UTC' if utc else meeting.time_zone
timezone.activate(display_timezone)
try:
with timezone.override(display_timezone):
rendered_page = render(
request,
"meeting/" + base + ext,
@ -1585,8 +1585,6 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
},
content_type=mimetype[ext],
)
finally:
timezone.deactivate()
return rendered_page
@ -1868,13 +1866,14 @@ def agenda_by_room(request, num=None, name=None, owner=None):
schedule__in=[schedule, schedule.base if schedule else None]
).prefetch_related('timeslot', 'timeslot__location', 'session', 'session__group', 'session__group__parent')
ss_by_day = OrderedDict()
for day in assignments.dates('timeslot__time','day'):
ss_by_day[day]=[]
ss_by_day = {}
for ss in assignments.order_by('timeslot__location__functional_name','timeslot__location__name','timeslot__time'):
day = ss.timeslot.time.date()
ss_by_day[day].append(ss)
return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"schedule":schedule,"ss_by_day":ss_by_day})
# sorts by time within each day but days are not in order at this point
day = ss.timeslot.time.astimezone(meeting.tz()).date()
ss_by_day.setdefault(day, []).append(ss)
ss_by_day = OrderedDict((key, ss_by_day[key]) for key in sorted(ss_by_day)) # fix day ordering
with timezone.override(meeting.tz()):
return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"schedule":schedule,"ss_by_day":ss_by_day})
@role_required('Area Director','Secretariat','IAB')
def agenda_by_type(request, num=None, type=None, name=None, owner=None):
@ -1892,7 +1891,8 @@ def agenda_by_type(request, num=None, type=None, name=None, owner=None):
if type:
assignments = assignments.filter(session__type__slug=type)
return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"schedule":schedule,"assignments":assignments})
with timezone.override(meeting.tz()):
return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"schedule":schedule,"assignments":assignments})
@role_required('Area Director','Secretariat','IAB')
def agenda_by_type_ics(request,num=None,type=None):
@ -3779,20 +3779,21 @@ def proceedings(request, num=None):
meeting_sessions.append(s)
ietf_areas.append((area, meeting_sessions, not_meeting_sessions))
return render(request, "meeting/proceedings.html", {
'meeting': meeting,
'plenaries': plenaries, 'ietf': ietf, 'training': training, 'irtf': irtf, 'iab': iab,
'ietf_areas': ietf_areas,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date,
'submission_started': now > begin_date,
'cache_version': cache_version,
'attendance': meeting.get_attendance(),
'meetinghost_logo': {
'max_height': settings.MEETINGHOST_LOGO_MAX_DISPLAY_HEIGHT,
'max_width': settings.MEETINGHOST_LOGO_MAX_DISPLAY_WIDTH,
}
})
with timezone.override(meeting.tz()):
return render(request, "meeting/proceedings.html", {
'meeting': meeting,
'plenaries': plenaries, 'ietf': ietf, 'training': training, 'irtf': irtf, 'iab': iab,
'ietf_areas': ietf_areas,
'cut_off_date': cut_off_date,
'cor_cut_off_date': cor_cut_off_date,
'submission_started': now > begin_date,
'cache_version': cache_version,
'attendance': meeting.get_attendance(),
'meetinghost_logo': {
'max_height': settings.MEETINGHOST_LOGO_MAX_DISPLAY_HEIGHT,
'max_width': settings.MEETINGHOST_LOGO_MAX_DISPLAY_WIDTH,
}
})
@role_required('Secretariat')
def finalize_proceedings(request, num=None):
@ -4099,8 +4100,7 @@ def edit_timeslot(request, num, slot_id):
meeting = get_object_or_404(Meeting, number=num)
if timeslot.meeting != meeting:
raise Http404()
timezone.activate(meeting.tz()) # specifies current_timezone used for rendering and form handling
try:
with timezone.override(meeting.tz()): # specifies current_timezone used for rendering and form handling
if request.method == 'POST':
form = TimeSlotEditForm(instance=timeslot, data=request.POST)
if form.is_valid():
@ -4118,8 +4118,6 @@ def edit_timeslot(request, num, slot_id):
{'timeslot': timeslot, 'form': form, 'sessions': sessions},
status=400 if form.errors else 200,
)
finally:
timezone.deactivate()
@role_required('Secretariat')
@ -4318,7 +4316,7 @@ def approve_proposed_slides(request, slidesubmission_id, num):
}
form = ApproveSlidesForm(show_apply_to_all_checkbox, initial=initial )
return render(request, "meeting/approve_proposed_slides.html",
return render(request, "meeting/approve_proposed_slides.html",
{'submission': submission,
'session_number': session_number,
'existing_doc' : existing_doc,

View file

@ -1,5 +1,5 @@
{% extends "base_site.html" %}
{% load staticfiles %}
{% load staticfiles tz %}
{% block title %}Proceedings{% endblock %}
@ -59,7 +59,7 @@
</tr>
</thead>
{% if sessions %}
<tbody>
<tbody>{% timezone meeting.time_zone %}
{% for session in sessions %}
{% if session.recordings %}
@ -84,7 +84,7 @@
{% endfor %}
</tbody>
{% endtimezone %}</tbody>
{% endif %}
</table>
</div> <!-- inline-group -->

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}
Approve Slides Proposed for {{ submission.session.meeting }} : {{ submission.session.group.acronym }}
{% endblock %}
@ -15,7 +15,7 @@
</h1>
{% if session_number %}
<h2>
Session {{ session_number }} : {{ submission.session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}
Session {{ session_number }} : {{ submission.session.official_timeslotassignment.timeslot.time|timezone:submission.session.meeting.time_zone|date:"D M-d-Y Hi" }}
</h2>
{% endif %}
<p class="alert alert-info my-3">

View file

@ -2,7 +2,7 @@
{# Copyright The IETF Trust 2020, All Rights Reserved #}
{% load origin %}
{% load ietf_filters %}
{% load django_bootstrap5 %}
{% load django_bootstrap5 tz %}
{% block title %}Differences between Meeting Agendas for IETF {{ meeting.number }}{% endblock %}
{% block content %}
{% origin %}
@ -26,7 +26,7 @@
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tbody>{% timezone meeting.time_zone %}
{% for d in diffs %}
<tr>
<td>
@ -40,7 +40,7 @@
</td>
</tr>
{% endfor %}
</tbody>
{% endtimezone %}</tbody>
</table>
{% else %}
No differences in scheduled sessions found.

View file

@ -1,9 +1,9 @@
{% for d in meeting.important_dates %}BEGIN:VEVENT
{% load tz %}{% for d in meeting.important_dates %}BEGIN:VEVENT
UID:ietf-{{ meeting.number }}-{{ d.name_id }}-{{ d.date.isoformat }}
SUMMARY:IETF {{ meeting.number }}: {{ d.name.name }}
CLASS:PUBLIC
DTSTART{% if not d.midnight_cutoff %};VALUE=DATE{% endif %}:{{ d.date|date:"Ymd" }}{% if d.midnight_cutoff %}235900Z{% endif %}
DTSTAMP:{{ meeting.cached_updated|date:"Ymd" }}T{{ meeting.cached_updated|date:"His" }}Z
DTSTAMP:{{ meeting.cached_updated|utc|date:"Ymd" }}T{{ meeting.cached_updated|utc|date:"His" }}Z
TRANSP:TRANSPARENT
DESCRIPTION:{{ d.name.desc }}{% if first and d.name.slug == 'openreg' or first and d.name.slug == 'earlybird' %}\n
Register here: https://www.ietf.org/how/meetings/register/{% endif %}{% if d.name.slug == 'opensched' %}\n

View file

@ -1,4 +1,4 @@
{% load ietf_filters %}
{% load ietf_filters tz %}{% timezone meeting.time_zone %}
---------------------------------------------------------
{{ group.type.verbose_name }} Name: {{ group.name|safe }}
{% if group.type.slug == "wg" or group.type.slug == "directorate" or group.type.slug == "team" %}Area Name: {{ group.parent }}
@ -17,3 +17,4 @@ Remote Participation Information: {{ session.remote_instructions }}
Agenda Note: {{ session.agenda_note }}
{% endfor %}
---------------------------------------------------------
{% endtimezone %}

View file

@ -1,7 +1,7 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load static %}
{% load textfilters %}
{% load textfilters tz %}
{% origin %}
{% with item=session.official_timeslotassignment acronym=session.historic_group.acronym %}
<div role="group" class="btn-group btn-group-sm">
@ -90,8 +90,8 @@
{# iCalendar item #}
<a class="btn btn-outline-primary"
href="{% url 'ietf.meeting.views.agenda_ical' num=meeting.number session_id=session.id %}"
aria-label="icalendar entry for {{ acronym }} session on {{ item.timeslot.utc_start_time|date:'Y-m-d H:i' }} UTC"
title="icalendar entry for {{ acronym }} session on {{ item.timeslot.utc_start_time|date:'Y-m-d H:i' }} UTC">
aria-label="icalendar entry for {{ acronym }} session on {{ item.timeslot.time|utc|date:'Y-m-d H:i' }} UTC"
title="icalendar entry for {{ acronym }} session on {{ item.timeslot.time|utc|date:'Y-m-d H:i' }} UTC">
<i class="bi bi-calendar"></i>
</a>
{% else %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}Propose Slides for {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
{% block content %}
{% origin %}
@ -13,7 +13,7 @@
</h1>
{% if session_number %}
<h2 class="mt-3">
Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}
Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}
</h2>
{% endif %}
<p class="alert alert-info my-3">

View file

@ -2,7 +2,7 @@
{% load origin %}
{% load static %}
{% load textfilters %}
{% load ietf_filters %}
{% load ietf_filters tz %}
{% origin %}
{% if item and item|should_show_agenda_session_buttons %}
{% with slug=item.slug %}
@ -130,8 +130,8 @@
<a class="btn btn-outline-primary"
role="button"
href="{% url 'ietf.meeting.views.agenda_ical' num=meeting.number session_id=session.id %}"
aria-label="icalendar entry for {{ acronym }} session on {{ timeslot.utc_start_time|date:'Y-m-d H:i' }} UTC"
title="icalendar entry for {{ acronym }} session on {{ timeslot.utc_start_time|date:'Y-m-d H:i' }} UTC">
aria-label="icalendar entry for {{ acronym }} session on {{ timeslot.time|utc|date:'Y-m-d H:i' }} UTC"
title="icalendar entry for {{ acronym }} session on {{ timeslot.time|utc|date:'Y-m-d H:i' }} UTC">
<i class="bi bi-calendar"></i>
</a>
{% else %}

View file

@ -6,7 +6,7 @@
{% if sessions|length > 1 %}Session {{ forloop.counter }} :{% endif %}
{% for time in session.times %}
{% if not forloop.first %},{% endif %}
{{ time|dateformat:"l Y-m-d H:i T" }}
{{ time|timezone:session.meeting.time_zone|dateformat:"l Y-m-d H:i T" }}
{% if time.tzinfo.zone != "UTC" %}<span class="small">({{ time|utc|dateformat:"H:i T" }})</span>{% endif %}
{% endfor %}
{% if session.cancelled %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}
{% if agenda_sp %}
Revise
@ -24,7 +24,7 @@
</small>
</h1>
{% if session_number %}
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}</h2>
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}</h2>
{% endif %}
<form enctype="multipart/form-data" method="post" class="my-3">
{% csrf_token %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}
{% if bluesheet_sp %}
Revise
@ -24,7 +24,7 @@
</small>
</h1>
{% if session_number %}
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}</h2>
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}</h2>
{% endif %}
<form enctype="multipart/form-data" method="post" class="my-3">
{% csrf_token %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}
{% if minutes_sp %}
Revise
@ -24,7 +24,7 @@
</small>
</h1>
{% if session_number %}
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}</h2>
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}</h2>
{% endif %}
<form enctype="multipart/form-data" method="post" class="my-3">
{% csrf_token %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static django_bootstrap5 %}
{% load origin static django_bootstrap5 tz %}
{% block title %}
{% if slides_sp %}
Revise
@ -25,7 +25,7 @@
</small>
</h1>
{% if session_number %}
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|date:"D M-d-Y Hi" }}</h2>
<h2>Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}</h2>
{% endif %}
{% if slides_sp %}<h3>{{ slides_sp.document.name }}</h3>{% endif %}
<form class="my-3" enctype="multipart/form-data" method="post">