281 lines
12 KiB
HTML
281 lines
12 KiB
HTML
{% extends "base.html" %}
|
|
{# Copyright The IETF Trust 2015, 2020, All Rights Reserved #}
|
|
{% load origin %}
|
|
{% load cache %}
|
|
{% load ietf_filters static classname %}
|
|
|
|
{% block pagehead %}
|
|
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
|
|
<link rel="stylesheet" href="{% static "fullcalendar/core/main.css" %}">
|
|
<link rel="stylesheet" href="{% static "fullcalendar/daygrid/main.css" %}">
|
|
|
|
{% endblock %}
|
|
|
|
{% block bodyAttrs %}data-spy="scroll" data-target="#affix"{% endblock %}
|
|
|
|
{% block title %}Upcoming Meetings{% endblock %}
|
|
|
|
{% block content %}
|
|
{% origin %}
|
|
<div class="row">
|
|
<div class="col-md-10">
|
|
|
|
<h1>Upcoming Meetings
|
|
<span class="regular pull-right">
|
|
<a title="iCalendar subscription for upcoming meetings" href="webcal://{{request.get_host}}{% url 'ietf.meeting.views.upcoming_ical' %}">
|
|
<span class="fa fa-stack-1"><i class="fa fa-fw fa-calendar-o fa-stack-1x"></i><i class="fa fa-fw fa-repeat fa-stack-xs"></i></span>
|
|
</a>
|
|
<a title="iCalendar entry for upcoming meetings" href="{% url 'ietf.meeting.views.upcoming_ical' %}"><span class="fa fa-calendar"></span></a>
|
|
</span>
|
|
</h1>
|
|
|
|
<p>For more on regular IETF meetings see <a href="https://www.ietf.org/meeting/upcoming.html">here</a></p>
|
|
<p>Meeting important dates are not included in upcoming meeting calendars. They have <a href="{% url 'ietf.meeting.views.important_dates' %}">their own calendar</a></p>
|
|
|
|
{% include 'meeting/agenda_filter.html' with filter_categories=filter_categories customize_button_text="Customize the meeting list..." only%}
|
|
|
|
{% if menu_entries %}
|
|
<ul class="nav nav-tabs" role="tablist">
|
|
{% for name, url in menu_entries %}
|
|
<li {% if selected_menu_entry == name.lower %}class="active"{% endif %}>
|
|
<a href="{{ url }}">{{ name }}</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
|
|
{% if menu_actions %}
|
|
<div id="menu-actions" class="buttonlist">
|
|
{% for action in menu_actions %}
|
|
<a class="btn btn-default"
|
|
data-append-filter="{{ action.append_filter }}"
|
|
href="{{ action.url }}">{{ action.label }}</a>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% cache 600 upcoming-meetings entries.count %}
|
|
{% if entries %}
|
|
<table id="upcoming-meeting-table" class="table table-condensed table-striped tablesorter">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Group</th>
|
|
<th>Meeting</th>
|
|
<th class="sorter-false text-right"> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for entry in entries %}
|
|
<tr class="entry"
|
|
{% if entry|classname == 'Session' %}data-filter-keywords="{{ entry.filter_keywords|join:',' }}"{% endif %}>
|
|
{% if entry|classname == 'Meeting' %}
|
|
{% with meeting=entry %}
|
|
<td>{{ meeting.date }} - {{ meeting.end }}</td>
|
|
<td>ietf</td>
|
|
<td><a class="ietf-meeting-link" href="{% url 'ietf.meeting.views.agenda' num=meeting.number %}">IETF {{ meeting.number }}</a></td>
|
|
<td></td>
|
|
{% endwith %}
|
|
{% elif entry|classname == 'Session' %}
|
|
{% with session=entry group=entry.group meeting=entry.meeting%}
|
|
<td>{{ session.official_timeslotassignment.timeslot.utc_start_time | date:"Y-m-d H:i"}} - {{ session.official_timeslotassignment.timeslot.utc_end_time | date:"H:i e" }}</td>
|
|
<td><a href="{% url 'ietf.group.views.group_home' acronym=group.acronym %}">{{ group.acronym }}</a></td>
|
|
<td>
|
|
<a class="interim-meeting-link" href="{% url 'ietf.meeting.views.session_details' num=meeting.number acronym=group.acronym %}"> {{ meeting.number }}</a>
|
|
</td>
|
|
{% if session.current_status == 'canceled' %}
|
|
<td class='text-right'>
|
|
<span class="label label-warning">CANCELLED</span>
|
|
</td>
|
|
{% else %}
|
|
<td class='text-right'>
|
|
{% include "meeting/interim_session_buttons.html" with show_agenda=True %}
|
|
</td>
|
|
{% endif %}
|
|
{% endwith %}
|
|
{% else %}
|
|
<td><span class="label-warning">Unexpected entry type: {{entry|classname}}</span></td>
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
{% endif %}
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<h3>No upcoming meetings</h3>
|
|
{% endif %}
|
|
{% endcache %}
|
|
</div>
|
|
</div>
|
|
<div id="calendar" class="col-md-10" ></div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static "jquery.tablesorter/js/jquery.tablesorter.combined.min.js" %}"></script>
|
|
<script src="{% static 'fullcalendar/core/main.js' %}"></script>
|
|
<script src="{% static 'fullcalendar/daygrid/main.js' %}"></script>
|
|
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
|
|
<script>
|
|
// List of all events with meta-info needed for filtering
|
|
var all_event_list = [{% for entry in entries %}
|
|
{% if entry|classname == 'Meeting' %}
|
|
{% with meeting=entry %}
|
|
{
|
|
title: 'IETF {{ meeting.number }}',
|
|
start: '{{meeting.date}}',
|
|
end: '{{meeting.end}}',
|
|
url: '{% url 'ietf.meeting.views.agenda' num=meeting.number %}'
|
|
}{% if not forloop.last %}, {% endif %}
|
|
{% endwith %}
|
|
{% else %} {# if it's not a Meeting, it's a Session #}
|
|
{% with session=entry %}
|
|
{
|
|
title: '{{session.official_timeslotassignment.timeslot.utc_start_time|date:"H:i"}}-{{session.official_timeslotassignment.timeslot.utc_end_time|date:"H:i"}}',
|
|
group: '{% if session.group %}{{session.group.acronym}}{% endif %}',
|
|
filter_keywords: ["{{ session.filter_keywords|join:'","' }}"],
|
|
start: '{{session.official_timeslotassignment.timeslot.utc_start_time | date:"Y-m-d H:i"}}',
|
|
end: '{{session.official_timeslotassignment.timeslot.utc_end_time | date:"Y-m-d H:i"}}',
|
|
url: '{% url 'ietf.meeting.views.session_details' num=session.meeting.number acronym=session.group.acronym %}'
|
|
}
|
|
{% endwith %}
|
|
{% if not forloop.last %}, {% endif %}
|
|
{% endif %}
|
|
{% endfor %}];
|
|
var filtered_event_list = []; // currently visible list
|
|
var event_calendar; // handle on the calendar object
|
|
|
|
// Test whether an event should be visible given a set of filter parameters
|
|
function calendar_event_visible(filter_params, event) {
|
|
// Visible if filtering is disabled or event has no keywords
|
|
if (!agenda_filter.filtering_is_enabled(filter_params) || !event.filter_keywords) {
|
|
return true;
|
|
}
|
|
|
|
// Visible if shown and not hidden
|
|
return (!agenda_filter.keyword_match(filter_params.hide, event.filter_keywords)
|
|
&& agenda_filter.keyword_match(filter_params.show, event.filter_keywords));
|
|
}
|
|
|
|
// Apply filter_params to the event list and format data for the calendar
|
|
function filter_calendar_events(filter_params, event_list) {
|
|
var calendarEl = document.getElementById('calendar');
|
|
var glue = calendarEl.clientWidth > 720 ? ' ' : '\n';
|
|
var filtered_output = [];
|
|
for (var ii = 0; ii < event_list.length; ii++) {
|
|
var this_event = event_list[ii];
|
|
if (calendar_event_visible(filter_params, this_event)) {
|
|
filtered_output.push({
|
|
title: this_event.title + (this_event.group ? (glue + this_event.group) : ''),
|
|
start: this_event.start,
|
|
end: this_event.end,
|
|
url: this_event.url
|
|
})
|
|
}
|
|
}
|
|
return filtered_output;
|
|
}
|
|
|
|
// Initialize or update the calendar, updating the filtered event list
|
|
function update_calendar(filter_params) {
|
|
filtered_event_list = filter_calendar_events(filter_params, all_event_list);
|
|
if (event_calendar) {
|
|
event_calendar.refetchEvents()
|
|
} else {
|
|
/* Initialize the calendar object.
|
|
* The event source is a function that simply returns the current global list of
|
|
* filtered events.
|
|
*/
|
|
var calendarEl = document.getElementById('calendar')
|
|
event_calendar = new FullCalendar.Calendar(calendarEl, {
|
|
plugins: ['dayGrid'],
|
|
displayEventTime: false,
|
|
events: function (fInfo, success) {success(filtered_event_list)},
|
|
eventRender: function (info) {
|
|
$(info.el).tooltip({ title: info.event.title })
|
|
},
|
|
timeFormat: 'H:mm',
|
|
})
|
|
event_calendar.render()
|
|
}
|
|
}
|
|
|
|
function update_meeting_display(filter_params) {
|
|
var meeting_rows = $("#upcoming-meeting-table tr.entry");
|
|
if (!agenda_filter.filtering_is_enabled(filter_params)) {
|
|
meeting_rows.show();
|
|
return;
|
|
}
|
|
|
|
// hide everything that has keywords
|
|
meeting_rows.filter(function(index, row){
|
|
return !!$(row).attr('data-filter-keywords');
|
|
}).hide();
|
|
|
|
$.each(filter_params['show'], function (i, v) {
|
|
agenda_filter.rows_matching_filter_keyword(meeting_rows, v).show();
|
|
});
|
|
$.each(filter_params['hide'], function (i, v) {
|
|
agenda_filter.rows_matching_filter_keyword(meeting_rows, v).hide();
|
|
});
|
|
}
|
|
|
|
function update_links(filter_params) {
|
|
var filtered_links = $("#menu-actions [data-append-filter='True']");
|
|
var filtering_enabled = agenda_filter.filtering_is_enabled(filter_params);
|
|
filtered_links.each(function(index, elt) {
|
|
var orig_link_href = $(elt).attr("href").split("?")[0];
|
|
if (filtering_enabled) {
|
|
// append new querystring
|
|
$(elt).attr("href", orig_link_href+window.location.search);
|
|
} else {
|
|
// remove querystring
|
|
$(elt).attr("href", orig_link_href);
|
|
}
|
|
});
|
|
}
|
|
|
|
function update_view(filter_params) {
|
|
update_meeting_display(filter_params);
|
|
update_links(filter_params);
|
|
update_calendar(filter_params);
|
|
}
|
|
|
|
// Set up the filtering - the callback will be called when the page loads and on any filter changes
|
|
agenda_filter.set_update_callback(update_view);
|
|
agenda_filter.enable();
|
|
|
|
$(".modal").on("show.bs.modal", function () {
|
|
var i = $(this).find(".frame");
|
|
if ($(i).data("src")) {
|
|
$.get($(i).data("src"), function (data, status, xhr) {
|
|
var t = xhr.getResponseHeader("content-type");
|
|
if (t.indexOf("text/plain") > -1) {
|
|
data = "<pre class='agenda'>" + data + "</pre>";
|
|
} else if(t.indexOf("text/html") > -1) {
|
|
// nothing to do here
|
|
} else {
|
|
data = "<p>Unknown type: " + xhr.getResponseHeader("content-type") + "</p>";
|
|
}
|
|
$(i).html(data);
|
|
});
|
|
}
|
|
var j = $(this).find(".frame2");
|
|
if ($(j).data("src")) {
|
|
$.get($(j).data("src"), function (data, status, xhr) {
|
|
var t = xhr.getResponseHeader("content-type");
|
|
if (t.indexOf("text/plain") > -1) {
|
|
data = "<pre class='agenda'>" + data + "</pre>";
|
|
} else if(t.indexOf("text/html") > -1) {
|
|
// nothing to do here
|
|
} else {
|
|
data = "<p>Unknown type: " + xhr.getResponseHeader("content-type") + "</p>";
|
|
}
|
|
$(j).html(data);
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|