-
+
{{ session.group.acronym }}
{% if session.purpose_id != "regular" and session.purpose_id != "none" %}
diff --git a/ietf/secr/templates/sreq/session_approval_notification.txt b/ietf/templates/meeting/session_approval_notification.txt
similarity index 56%
rename from ietf/secr/templates/sreq/session_approval_notification.txt
rename to ietf/templates/meeting/session_approval_notification.txt
index 7bb63aa3fa..74eca09bd8 100644
--- a/ietf/secr/templates/sreq/session_approval_notification.txt
+++ b/ietf/templates/meeting/session_approval_notification.txt
@@ -1,3 +1,4 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
Dear {{ group.parent }} Director(s):
{{ header }} meeting session request has just been
@@ -5,11 +6,11 @@ submitted by {{ requester }}.
The third session requires your approval.
To approve the session go to the session request view here:
-{{ settings.IDTRACKER_BASE_URL }}{% url "ietf.secr.sreq.views.view" acronym=group.acronym %}
+{{ settings.IDTRACKER_BASE_URL }}{% url "ietf.meeting.views_session_request.view_request" acronym=group.acronym %}
and click "Approve Third Session".
Regards,
The IETF Secretariat.
-{% include "includes/session_info.txt" %}
+{% include "meeting/session_request_info.txt" %}
diff --git a/ietf/templates/meeting/session_buttons_include.html b/ietf/templates/meeting/session_buttons_include.html
index bb5144b45d..b1fd92ba5b 100644
--- a/ietf/templates/meeting/session_buttons_include.html
+++ b/ietf/templates/meeting/session_buttons_include.html
@@ -2,7 +2,8 @@
{% load origin %}
{% load static %}
{% load textfilters tz %}
-{% load ietf_filters %}
+{% load ietf_filters session_filters %}
+
{% origin %}
{% if item and item|should_show_agenda_session_buttons %}
{% with slug=item.slug session=item.session timeslot=item.timeslot %}
@@ -126,10 +127,10 @@
{% else %}
{# chat logs #}
- {% if meeting.has_chat_logs %}
+ {% if meeting.has_chat_logs and session.chatlog %}
@@ -303,10 +304,10 @@
{% else %}
{# chat logs #}
- {% if meeting.has_chat_logs %}
+ {% if meeting.has_chat_logs and session.chatlog %}
+ href="/doc/{{ session.chatlog.document.name }}">
Chat logs
diff --git a/ietf/secr/templates/sreq/session_cancel_notification.txt b/ietf/templates/meeting/session_cancel_notification.txt
similarity index 71%
rename from ietf/secr/templates/sreq/session_cancel_notification.txt
rename to ietf/templates/meeting/session_cancel_notification.txt
index 8aee6c89db..3de67fc8f4 100644
--- a/ietf/secr/templates/sreq/session_cancel_notification.txt
+++ b/ietf/templates/meeting/session_cancel_notification.txt
@@ -1,3 +1,4 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
{% autoescape off %}{% load ams_filters %}
A request to cancel a meeting session has just been submitted by {{ requester }}.{% endautoescape %}
diff --git a/ietf/templates/meeting/session_details.html b/ietf/templates/meeting/session_details.html
index 571715b4b4..a4d9ba1090 100644
--- a/ietf/templates/meeting/session_details.html
+++ b/ietf/templates/meeting/session_details.html
@@ -1,5 +1,5 @@
{% extends "base.html" %}
-{# Copyright The IETF Trust 2015, All Rights Reserved #}
+{# Copyright The IETF Trust 2015-2026, All Rights Reserved #}
{% load origin ietf_filters static %}
{% block title %}{{ meeting }} : {{ group.acronym }}{% endblock %}
{% block morecss %}
@@ -31,93 +31,58 @@ Scheduled Sessions
{% include 'meeting/session_details_panel.html' with sessions=scheduled_sessions %}
Unscheduled Sessions
{% include 'meeting/session_details_panel.html' with sessions=unscheduled_sessions %}
- {% if pending_suggestions %}
-
+ {% for s in pending_suggestions %}
+ {% if forloop.first %}
{% if can_manage_materials %}
Proposed slides awaiting your approval
{% else %}
Your proposed slides awaiting chair approval
{% endif %}
-
- {% for s in pending_suggestions %}
- {% if can_manage_materials %}
-
-
- {{ s.submitter }} - {{ s.title }} ({{ s.time }})
-
-
- {% else %}
-
- {{ s.title }} ({{ s.time }})
-
- {% endif %}
- {% endfor %}
+
{% endif %}
+ {% endfor %}
+ {% if user|has_role:"Secretariat" %}
+
{% endif %}
+ {% comment %}
+ The existence of an element with id canManageMaterialsFlag is checked in
+ session_details.js to determine whether it should init the sortable tables.
+ Not the most elegant approach, but it works.
+ {% endcomment %}
+ {% if can_manage_materials %}
{% endif %}
{% endblock %}
{% block js %}
-
{% if can_manage_materials %}
-
{% endif %}
+
{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_details_form.html b/ietf/templates/meeting/session_details_form.html
index 6b59e7dacd..9cd1b6e85c 100644
--- a/ietf/templates/meeting/session_details_form.html
+++ b/ietf/templates/meeting/session_details_form.html
@@ -1,42 +1,48 @@
-{# Copyright The IETF Trust 2007-2020, All Rights Reserved #}
+{# Copyright The IETF Trust 2007-2025, All Rights Reserved #}
+{% load django_bootstrap5 %}
+
\ No newline at end of file
+ {{ form.attendees.as_hidden }}
+ {{ form.comments.as_hidden }}
+ {{ form.id.as_hidden }}
+ {{ form.on_agenda.as_hidden }}
+ {{ form.DELETE.as_hidden }}
+ {{ form.remote_instructions.as_hidden }}
+ {{ form.short.as_hidden }}
+ {{ form.agenda_note.as_hidden }}
+
diff --git a/ietf/templates/meeting/session_details_panel.html b/ietf/templates/meeting/session_details_panel.html
index a0f5884b9d..7c52ac0b4a 100644
--- a/ietf/templates/meeting/session_details_panel.html
+++ b/ietf/templates/meeting/session_details_panel.html
@@ -109,7 +109,7 @@ Agenda, Minutes, and Bluesheets
{% endif %}
{% if not session.type_counter.minutes %}
- Import minutes from notes.ietf.org
+ Import minutes from notes.ietf.org
Upload minutes
@@ -310,7 +310,7 @@ Notes and recordings
{% endif %}
+
+ {% if can_manage_materials %}
+
+ Link additional recordings to session
+
+ {% endif %}
+
{% endwith %}{% endwith %}
{% endfor %}
diff --git a/ietf/secr/templates/sreq/not_meeting_notification.txt b/ietf/templates/meeting/session_not_meeting_notification.txt
similarity index 83%
rename from ietf/secr/templates/sreq/not_meeting_notification.txt
rename to ietf/templates/meeting/session_not_meeting_notification.txt
index 1120f8480c..0e5c940708 100644
--- a/ietf/secr/templates/sreq/not_meeting_notification.txt
+++ b/ietf/templates/meeting/session_not_meeting_notification.txt
@@ -1,3 +1,4 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
{% load ams_filters %}
{{ login|smart_login }} {{ group.acronym }} working group, indicated that the {{ group.acronym }} working group does not plan to hold a session at IETF {{ meeting.number }}.
diff --git a/ietf/templates/meeting/session_request_confirm.html b/ietf/templates/meeting/session_request_confirm.html
new file mode 100644
index 0000000000..09043d3d0c
--- /dev/null
+++ b/ietf/templates/meeting/session_request_confirm.html
@@ -0,0 +1,38 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static ietf_filters django_bootstrap5 %}
+{% block title %}Confirm Session Request{% endblock %}
+
+{% block content %}
+ Confirm Session Request - IETF {{ meeting.number }}
+
+
+
+
+
+
+
+ {% include "meeting/session_request_view_table.html" %}
+
+
+
+
+
+{% endblock %}
+
+{% block js %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_form.html b/ietf/templates/meeting/session_request_form.html
new file mode 100644
index 0000000000..ecf5cb7268
--- /dev/null
+++ b/ietf/templates/meeting/session_request_form.html
@@ -0,0 +1,206 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static ietf_filters django_bootstrap5 %}
+{% block title %}{% if is_create %}New {% else %}Edit {% endif %}Session Request{% endblock %}
+{% block morecss %}{{ block.super }}
+ .hidden {display: none !important;}
+ div.form-group {display: inline;}
+{% endblock %}
+{% block content %}
+ {% if is_create %}New {% else %}Edit {% endif %}Session Request
+
+ {% if is_create %}
+
+ {% endif %}
+
+
+
+
+
+{% endblock %}
+{% block js %}
+
+ {{ form.media }}
+{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_info.txt b/ietf/templates/meeting/session_request_info.txt
new file mode 100644
index 0000000000..2e96efb31f
--- /dev/null
+++ b/ietf/templates/meeting/session_request_info.txt
@@ -0,0 +1,26 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% load ams_filters %}
+---------------------------------------------------------
+Working Group Name: {{ group.name }}
+Area Name: {{ group.parent }}
+Session Requester: {{ login }}
+{% if session.joint_with_groups %}{{ session.joint_for_session_display }} joint with: {{ session.joint_with_groups }}{% endif %}
+
+Number of Sessions: {{ session.num_session }}
+Length of Session(s): {% for session_length in session_lengths %}{{ session_length.total_seconds|display_duration }}{% if not forloop.last %}, {% endif %}{% endfor %}
+Number of Attendees: {{ session.attendees }}
+Conflicts to Avoid:
+{% for line in session.outbound_conflicts %} {{line}}
+{% endfor %}{% if session.session_time_relation_display %} {{ session.session_time_relation_display }}{% endif %}
+{% if session.adjacent_with_wg %} Adjacent with WG: {{ session.adjacent_with_wg }}{% endif %}
+{% if session.timeranges_display %} Can't meet: {{ session.timeranges_display|join:", " }}{% endif %}
+
+Participants who must be present:
+{% for person in session.bethere %} {{ person.ascii_name }}
+{% endfor %}
+Resources Requested:
+{% for resource in session.resources %} {{ resource.desc }}
+{% endfor %}
+Special Requests:
+ {{ session.comments }}
+---------------------------------------------------------
diff --git a/ietf/templates/meeting/session_request_list.html b/ietf/templates/meeting/session_request_list.html
new file mode 100644
index 0000000000..789b7006e5
--- /dev/null
+++ b/ietf/templates/meeting/session_request_list.html
@@ -0,0 +1,65 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static %}
+{% load ietf_filters %}
+{% load django_bootstrap5 %}
+{% block title %}Session Requests{% endblock %}
+{% block content %}
+ Session Requests IETF {{ meeting.number }}
+
+
+
+
+
+
+
The list below includes those working groups that you currently chair which do not already have a session scheduled. You can click on an acronym to complete a request for a new session at the upcoming IETF meeting. Click "Group will not meet" to send a notification that the group does not plan to meet.
+
+ {% for group in unscheduled_groups %}
+
+ {{ group.acronym }}
+ {% if group.not_meeting %}
+ (Currently, this group does not plan to hold a session at IETF {{ meeting.number }})
+ {% endif %}
+
+ {% empty %}
+ NONE
+ {% endfor %}
+
+
+
+
+
+
+
+
+
The list below includes those working groups for which you or your co-chair has requested sessions at the upcoming IETF meeting. You can click on an acronym to initiate changes to a session, or cancel a session.
+
+
+
+
+{% endblock %}
+
+{% block footer-extras %}
+ {% include "includes/sessions_footer.html" %}
+{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_locked.html b/ietf/templates/meeting/session_request_locked.html
new file mode 100644
index 0000000000..15c023ce33
--- /dev/null
+++ b/ietf/templates/meeting/session_request_locked.html
@@ -0,0 +1,21 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static ietf_filters django_bootstrap5 %}
+{% block title %}Session Request{% endblock %}
+
+{% block content %}
+ Session Request - IETF {{ meeting.number }}
+
+ View list of timeslot requests
+
+
+
+
+
{{ message }}
+
+
+ Back
+
+
+
+{% endblock %}
diff --git a/ietf/secr/templates/sreq/session_request_notification.txt b/ietf/templates/meeting/session_request_notification.txt
similarity index 56%
rename from ietf/secr/templates/sreq/session_request_notification.txt
rename to ietf/templates/meeting/session_request_notification.txt
index 75f2cbbae4..49dbbfc42c 100644
--- a/ietf/secr/templates/sreq/session_request_notification.txt
+++ b/ietf/templates/meeting/session_request_notification.txt
@@ -1,5 +1,6 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
{% autoescape off %}{% load ams_filters %}
{% filter wordwrap:78 %}{{ header }} meeting session request has just been submitted by {{ requester }}.{% endfilter %}
-{% include "includes/session_info.txt" %}{% endautoescape %}
+{% include "meeting/session_request_info.txt" %}{% endautoescape %}
diff --git a/ietf/templates/meeting/session_request_status.html b/ietf/templates/meeting/session_request_status.html
new file mode 100644
index 0000000000..65e98d6d23
--- /dev/null
+++ b/ietf/templates/meeting/session_request_status.html
@@ -0,0 +1,28 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static %}
+{% load ietf_filters %}
+{% load django_bootstrap5 %}
+{% block title %}Session Request Status{% endblock %}
+{% block content %}
+ Session Request Status
+
+
+
+
+
Enter the message that you would like displayed to the WG Chair when this tool is locked.
+
+
+
+
+{% endblock %}
diff --git a/ietf/templates/meeting/session_request_view.html b/ietf/templates/meeting/session_request_view.html
new file mode 100644
index 0000000000..3db16f56cb
--- /dev/null
+++ b/ietf/templates/meeting/session_request_view.html
@@ -0,0 +1,59 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static ietf_filters django_bootstrap5 %}
+{% block title %}Session Request{% endblock %}
+
+{% block content %}
+ Session Request - IETF {{ meeting.number }}
+
+
+
+
+
+
+
+ {% include "meeting/session_request_view_table.html" %}
+
+
+
+
Activities Log
+
+
+
+
+ Date
+ Time
+ Action
+ Name
+
+
+
+ {% for entry in activities %}
+
+ {{ entry.act_date }}
+ {{ entry.act_time }}
+ {{ entry.activity }}
+ {{ entry.act_by }}
+
+ {% endfor %}
+
+
+
+
+
+
Edit
+ {% if show_approve_button %}
+
Approve Third Session
+ {% endif %}
+
Cancel this Request
+
Back
+
+
+
+{% endblock %}
+
+{% block js %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_view_formset.html b/ietf/templates/meeting/session_request_view_formset.html
new file mode 100644
index 0000000000..72811b8c2c
--- /dev/null
+++ b/ietf/templates/meeting/session_request_view_formset.html
@@ -0,0 +1,49 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% load ams_filters %}{# keep this in sync with sessions_request_view_session_set.html #}
+{% for sess_form in formset %}
+ {% if sess_form.cleaned_data and not sess_form.cleaned_data.DELETE %}
+
+
+ Session {{ forloop.counter }}
+
+
+
+
Length
+
{{ sess_form.cleaned_data.requested_duration.total_seconds|display_duration }}
+
+ {% if sess_form.cleaned_data.name %}
+
+
Name
+
{{ sess_form.cleaned_data.name }}
+
+ {% endif %}
+ {% if sess_form.cleaned_data.purpose.slug != 'regular' %}
+
+
Purpose
+
+ {{ sess_form.cleaned_data.purpose }}
+ {% if sess_form.cleaned_data.purpose.timeslot_types|length > 1 %}({{ sess_form.cleaned_data.type }}
+ ){% endif %}
+
+
+
+
Onsite tool?
+
{{ sess_form.cleaned_data.has_onsite_tool|yesno }}
+
+ {% endif %}
+
+
+
+ {% if group.features.acts_like_wg and forloop.counter == 2 and not is_virtual %}
+
+
+ Time between sessions
+
+
+ {% if session.session_time_relation_display %}{{ session.session_time_relation_display }}{% else %}No
+ preference{% endif %}
+
+
+ {% endif %}
+ {% endif %}
+{% endfor %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_view_session_set.html b/ietf/templates/meeting/session_request_view_session_set.html
new file mode 100644
index 0000000000..0b8412b04f
--- /dev/null
+++ b/ietf/templates/meeting/session_request_view_session_set.html
@@ -0,0 +1,47 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% load ams_filters %}{# keep this in sync with sessions_request_view_formset.html #}
+{% for sess in session_set %}
+
+
+ Session {{ forloop.counter }}
+
+
+
+
Length
+
{{ sess.requested_duration.total_seconds|display_duration }}
+
+ {% if sess.name %}
+
+
Name
+
{{ sess.name }}
+
+ {% endif %}
+ {% if sess.purpose.slug != 'regular' %}
+
+
Purpose
+
+ {{ sess.purpose }}
+ {% if sess.purpose.timeslot_types|length > 1 %}({{ sess.type }}){% endif %}
+
+
+
+
Onsite tool?
+
{{ sess.has_onsite_tool|yesno }}
+
+ {% endif %}
+
+
+
+{% if group.features.acts_like_wg and forloop.counter == 2 and not is_virtual %}
+
+
+ Time between sessions
+
+
+ {% if session.session_time_relation_display %}{{ session.session_time_relation_display }}{% else %}No
+ preference{% endif %}
+
+
+{% endif %}
+
+{% endfor %}
\ No newline at end of file
diff --git a/ietf/templates/meeting/session_request_view_table.html b/ietf/templates/meeting/session_request_view_table.html
new file mode 100644
index 0000000000..a5cb85c252
--- /dev/null
+++ b/ietf/templates/meeting/session_request_view_table.html
@@ -0,0 +1,146 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% load ams_filters %}
+
+
+
+ Working Group Name
+
+
+ {{ group.name }} ({{ group.acronym }})
+
+
+
+
+
+ Area Name
+
+
+ {{ group.parent }}
+
+
+
+
+
+ Number of Sessions Requested
+
+
+ {% if session.third_session %}3{% else %}{{ session.num_session }}{% endif %}
+
+
+
+{% if form %}
+ {% include 'meeting/session_request_view_formset.html' with formset=form.session_forms group=group session=session only %}
+{% else %}
+ {% include 'meeting/session_request_view_session_set.html' with session_set=sessions group=group session=session only %}
+{% endif %}
+
+
+
+
+ Number of Attendees
+
+
+ {{ session.attendees }}
+
+
+
+
+
+ Conflicts to Avoid
+
+
+ {% if session_conflicts.outbound %}
+ {% for conflict in session_conflicts.outbound %}
+
+
+ {{ conflict.name|title }}
+
+
+ {{ conflict.groups }}
+
+
+ {% endfor %}
+ {% else %}
None {% endif %}
+
+
+
+
+
+ Other WGs that included {{ group }} in their conflict list
+
+
+ {% if session_conflicts.inbound %}{{ session_conflicts.inbound }}{% else %}None so far {% endif %}
+
+
+
+{% if not is_virtual %}
+
+
+ Resources requested
+
+
+ {% if session.resources %}
{% for resource in session.resources %}{{ resource.desc }} {% endfor %} {% else %}
None so far {% endif %}
+
+
+{% endif %}
+
+
+
+ Participants who must be present
+
+
+ {% if session.bethere %}
{% for person in session.bethere %}{{ person }} {% endfor %} {% else %}
None {% endif %}
+
+
+
+
+
+ Can not meet on
+
+
+ {% if session.timeranges_display %}{{ session.timeranges_display|join:', ' }}{% else %}No constraints{% endif %}
+
+
+
+{% if not is_virtual %}
+
+
+ Adjacent with WG
+
+
+ {{ session.adjacent_with_wg|default:'No preference' }}
+
+
+
+
+ Joint session
+
+
+ {% if session.joint_with_groups %}
+ {{ session.joint_for_session_display }} with: {{ session.joint_with_groups }}
+ {% else %}
+ Not a joint session
+ {% endif %}
+
+
+{% endif %}
+
+
+
+ Special Requests
+
+
+ {{ session.comments }}
+
+
+
+{% if form and form.notifications_optional %}
+
+
+ {{ form.send_notifications.label}}
+
+
+ {% if form.cleaned_data.send_notifications %}Yes{% else %}No{% endif %}
+
+
+{% endif %}
diff --git a/ietf/templates/meeting/timeslot_edit.html b/ietf/templates/meeting/timeslot_edit.html
index 11691ba6dd..3259dba9da 100644
--- a/ietf/templates/meeting/timeslot_edit.html
+++ b/ietf/templates/meeting/timeslot_edit.html
@@ -11,20 +11,22 @@
{% endcomment %}
.timeslot-edit { overflow: auto; height: max(30rem, calc(100vh - 25rem));}
.tstable { width: 100%; border-collapse: separate; } {# "separate" to ensure sticky cells keep their borders #}
-.tstable thead { position: sticky; top: 0; z-index: 3; background-color: white;}
-.tstable th:first-child, .tstable td:first-child {
- background-color: white; {# needs to match the lighter of the striped-table colors! #}
-position: sticky;
-left: 0;
- z-index: 2; {# render above other cells / borders but below thead (z-index 3, above) #}
-}
-.tstable tbody > tr:nth-of-type(odd) > th:first-child {
- background-color: rgb(249, 249, 249); {# needs to match the darker of the striped-table colors! #}
-}
-.tstable th { white-space: nowrap;}
-.tstable td { white-space: nowrap;}
-.capacity { font-size:80%; font-weight: normal;}
-a.new-timeslot-link { color: lightgray; font-size: large;}
+ .tstable tr th:first-child { min-width: 25rem; max-width: 25rem; overflow: hidden; }
+ .tstable thead { position: sticky; top: 0; z-index: 3; background-color: white;}
+ .tstable thead th span.day { position: sticky; left: 25.5rem; }
+ .tstable th:first-child, .tstable td:first-child {
+ background-color: white; {# needs to match the lighter of the striped-table colors! #}
+ position: sticky;
+ left: 0;
+ z-index: 2; {# render above other cells / borders but below thead (z-index 3, above) #}
+ }
+ .tstable tbody > tr:nth-of-type(odd) > th:first-child {
+ background-color: rgb(249, 249, 249); {# needs to match the darker of the striped-table colors! #}
+ }
+ .tstable th { white-space: nowrap;}
+ .tstable td { white-space: nowrap;}
+ .capacity { font-size:80%; font-weight: normal;}
+ a.new-timeslot-link { color: lightgray; font-size: large;}
{% endblock %}
{% block content %}
{% origin %}
@@ -84,12 +86,14 @@
{% for day in time_slices %}
- {{ day|date:'D' }} ({{ day }})
-
-
+
+ {{ day|date:'D' }} ({{ day }})
+
+
+
{% endfor %}
{% endif %}
diff --git a/ietf/templates/meeting/upcoming.ics b/ietf/templates/meeting/upcoming.ics
deleted file mode 100644
index 5eca7ec81d..0000000000
--- a/ietf/templates/meeting/upcoming.ics
+++ /dev/null
@@ -1,32 +0,0 @@
-{% load humanize tz %}{% autoescape off %}{% load ietf_filters textfilters %}BEGIN:VCALENDAR
-VERSION:2.0
-METHOD:PUBLISH
-PRODID:-//IETF//datatracker.ietf.org ical upcoming//EN
-{{vtimezones}}{% for item in assignments %}BEGIN:VEVENT
-UID:ietf-{{item.session.meeting.number}}-{{item.timeslot.pk}}
-SUMMARY:{% if item.session.name %}{{item.session.group.acronym|lower}} - {{item.session.name|ics_esc}}{% else %}{{item.session.group.acronym|lower}} - {{item.session.group.name}}{%endif%}
-{% if item.schedule.meeting.city %}LOCATION:{{item.schedule.meeting.city}},{{item.schedule.meeting.country}}
-{% endif %}STATUS:{{item.session.ical_status}}
-CLASS:PUBLIC
-DTSTART{% ics_date_time item.timeslot.local_start_time item.schedule.meeting.time_zone %}
-DTEND{% ics_date_time item.timeslot.local_end_time item.schedule.meeting.time_zone %}
-DTSTAMP{% ics_date_time item.timeslot.modified|utc 'utc' %}{% if item.session.agenda %}
-URL:{{item.session.agenda.get_href}}{% endif %}
-DESCRIPTION:{% if item.timeslot.name %}{{item.timeslot.name|ics_esc}}\n{% endif %}{% if item.session.agenda_note %}
- Note: {{item.session.agenda_note|ics_esc}}\n{% endif %}{% for material in item.session.materials.all %}
- \n{{material.type}}{% if material.type.name != "Agenda" %}
- ({{material.title|ics_esc}}){% endif %}:
- {{material.get_href}}\n{% endfor %}{% if item.session.remote_instructions %}
- Remote instructions: {{ item.session.remote_instructions }}\n{% endif %}
-END:VEVENT
-{% endfor %}{% for meeting in ietfs %}BEGIN:VEVENT
-UID:ietf-{{ meeting.number }}
-SUMMARY:IETF {{ meeting.number }}{% if meeting.city %}
-LOCATION:{{ meeting.city }},{{ meeting.country }}{% endif %}
-CLASS:PUBLIC
-DTSTART;VALUE=DATE{% if meeting.time_zone %};TZID={{ meeting.time_zone|ics_esc }}{% endif %}:{{ meeting.date|date:"Ymd" }}
-DTEND;VALUE=DATE{% if meeting.time_zone %};TZID={{ meeting.time_zone|ics_esc }}{% endif %}:{{ meeting.end_date|next_day|date:"Ymd" }}
-DTSTAMP{% ics_date_time meeting.cached_updated|utc 'utc' %}
-URL:{{ request.scheme }}://{{ request.get_host }}{% url 'agenda' num=meeting.number %}
-END:VEVENT
-{% endfor %}END:VCALENDAR{% endautoescape %}
diff --git a/ietf/templates/meeting/upload_session_minutes.html b/ietf/templates/meeting/upload_session_minutes.html
index 30eadda277..324440681f 100644
--- a/ietf/templates/meeting/upload_session_minutes.html
+++ b/ietf/templates/meeting/upload_session_minutes.html
@@ -26,6 +26,11 @@
{% if session_number %}
Session {{ session_number }} : {{ session.official_timeslotassignment.timeslot.time|timezone:session.meeting.time_zone|date:"D M-d-Y Hi" }}
{% endif %}
+ {% if future %}
+
+ Caution: Session has not ended yet
+
+ {% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/person/merge_request_email.txt b/ietf/templates/person/merge_request_email.txt
new file mode 100644
index 0000000000..0a695f036c
--- /dev/null
+++ b/ietf/templates/person/merge_request_email.txt
@@ -0,0 +1,23 @@
+Hello,
+
+We have identified multiple IETF Datatracker accounts that may represent a single person:
+
+https://datatracker.ietf.org/person/{{ source_account }}
+
+and
+
+https://datatracker.ietf.org/person/{{ target_account }}
+
+If this is so then it is important that we merge the accounts.
+
+This email is being sent to the primary emails associated with each Datatracker account.
+
+Please respond to this message individually from the email account(s) you control so we can take the appropriate action.
+
+If these should be merged, please identify which account you would like to keep the login credentials from.
+
+If you are associated with but no longer have access to one of the email accounts, then please let us know and we will follow up to determine how to proceed.
+
+
+{{ sender_name }}
+IETF Support
\ No newline at end of file
diff --git a/ietf/templates/person/merge_submit.html b/ietf/templates/person/merge_submit.html
new file mode 100644
index 0000000000..30e1999f81
--- /dev/null
+++ b/ietf/templates/person/merge_submit.html
@@ -0,0 +1,57 @@
+{# Copyright The IETF Trust 2025, All Rights Reserved #}
+{% extends "base.html" %}
+{% load static %}
+{% load django_bootstrap5 %}
+{% block title %}Merge Persons{% endblock %}
+{% block content %}
+ Merge Person Records
+
+ This tool will merge two Person records into one. If both records have logins and you want to retain the one on the left, use the Swap button to swap source and target records.
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/ietf/templates/person/profile.html b/ietf/templates/person/profile.html
index 1424f037a1..a78a90412f 100644
--- a/ietf/templates/person/profile.html
+++ b/ietf/templates/person/profile.html
@@ -50,7 +50,11 @@ Roles