Add the scripts and dependencies for the agenda page back, and make them work.

- Legacy-Id: 19652
This commit is contained in:
Lars Eggert 2021-11-12 13:41:31 +00:00
parent 273feec52d
commit be3a8f71ce
13 changed files with 768 additions and 26 deletions

View file

@ -0,0 +1,310 @@
window.agenda_filter; // public interface
window.agenda_filter_for_testing; // methods to be accessed for automated testing
// closure to create private scope
(function () {
'use strict'
/* n.b., const refers to the opts object itself, not its contents.
* Use camelCase for easy translation into element.dataset keys,
* which are automatically camel-cased from the data attribute name.
* (e.g., data-always-show -> elt.dataset.alwaysShow) */
const opts = {
alwaysShow: false,
updateCallback: null // function(filter_params)
};
/* Remove from list, if present */
function remove_list_item (list, item) {
var item_index = list.indexOf(item);
if (item_index !== -1) {
list.splice(item_index, 1)
}
}
/* Add to list if not present, remove if present
*
* Returns true if added to the list, otherwise false.
*/
function toggle_list_item (list, item) {
var item_index = list.indexOf(item);
if (item_index === -1) {
list.push(item)
return true;
} else {
list.splice(item_index, 1)
return false;
}
}
function parse_query_params (qs) {
var params = {}
qs = decodeURI(qs).replace(/^\?/, '').toLowerCase()
if (qs) {
var param_strs = qs.split('&')
for (var ii = 0; ii < param_strs.length; ii++) {
var toks = param_strs[ii].split('=', 2)
params[toks[0]] = toks[1] || true
}
}
return params
}
/* filt = 'show' or 'hide' */
function get_filter_from_qparams (qparams, filt) {
if (!qparams[filt] || (qparams[filt] === true)) {
return [];
}
var result = [];
var qp = qparams[filt].split(',');
for (var ii = 0; ii < qp.length; ii++) {
result.push(qp[ii].trim());
}
return result;
}
function get_filter_params (qparams) {
var enabled = opts.alwaysShow || qparams.show || qparams.hide;
return {
enabled: enabled,
show: get_filter_from_qparams(qparams, 'show'),
hide: get_filter_from_qparams(qparams, 'hide')
}
}
function get_keywords(elt) {
var keywords = $(elt).attr('data-filter-keywords');
if (keywords) {
return keywords.toLowerCase().split(',');
}
return [];
}
function get_item(elt) {
return $(elt).attr('data-filter-item');
}
// utility method - is there a match between two lists of keywords?
function keyword_match(list1, list2) {
for (var ii = 0; ii < list1.length; ii++) {
if (list2.indexOf(list1[ii]) !== -1) {
return true;
}
}
return false;
}
// Find the items corresponding to a keyword
function get_items_with_keyword (keyword) {
var items = [];
$('.view button.pickview').filter(function(index, elt) {
return keyword_match(get_keywords(elt), [keyword]);
}).each(function (index, elt) {
items.push(get_item($(elt)));
});
return items;
}
function filtering_is_enabled (filter_params) {
return filter_params.enabled;
}
// Update the filter / customization UI to match the current filter parameters
function update_filter_ui (filter_params) {
var buttons = $('.pickview');
if (!filtering_is_enabled(filter_params)) {
// Not filtering - set to default and exit
buttons.removeClass('active');
return;
}
update_href_querystrings(filter_params_as_querystring(filter_params))
// show the customizer - it will stay visible even if filtering is disabled
const customizer = $('#customize');
if (customizer.hasClass('collapse')) {
customizer.collapse('show')
}
// Update button state to match visibility
buttons.each(function (index, elt) {
elt = $(elt);
var keywords = get_keywords(elt);
keywords.push(get_item(elt)); // treat item as one of its keywords
var hidden = keyword_match(filter_params.hide, keywords);
var shown = keyword_match(filter_params.show, keywords);
if (shown && !hidden) {
elt.addClass('active');
} else {
elt.removeClass('active');
}
});
}
/* Update state of the view to match the filters
*
* Calling the individual update_* functions outside of this method will likely cause
* various parts of the page to get out of sync.
*/
function update_view () {
var filter_params = get_filter_params(parse_query_params(window.location.search))
update_filter_ui(filter_params)
if (opts.updateCallback) {
opts.updateCallback(filter_params)
}
}
/* Trigger an update so the user will see the page appropriate for given filter_params
*
* Updates the URL to match filter_params, then updates the history / display to match
* (if supported) or loads the new URL.
*/
function update_filters (filter_params) {
var new_url = replace_querystring(
window.location.href,
filter_params_as_querystring(filter_params)
)
update_href_querystrings(filter_params_as_querystring(filter_params))
if (window.history && window.history.replaceState) {
// Keep current origin, replace search string, no page reload
history.replaceState({}, document.title, new_url)
update_view()
} else {
// No window.history.replaceState support, page reload required
window.location = new_url
}
}
/**
* Update the querystring in the href filterable agenda links
*/
function update_href_querystrings(querystring) {
Array.from(
document.getElementsByClassName('agenda-link filterable')
).forEach(
(elt) => elt.href = replace_querystring(elt.href, querystring)
)
}
function filter_params_as_querystring(filter_params) {
var qparams = []
if (filter_params.show.length > 0) {
qparams.push('show=' + filter_params.show.join())
}
if (filter_params.hide.length > 0) {
qparams.push('hide=' + filter_params.hide.join())
}
if (qparams.length > 0) {
return '?' + qparams.join('&')
}
return ''
}
function replace_querystring(url, new_querystring) {
return url.replace(/(\?.*)?(#.*)?$/, new_querystring + window.location.hash)
}
/* Helper for pick group/type button handlers - toggles the appropriate parameter entry
* elt - the jquery element that was clicked
*/
function handle_pick_button (elt) {
var fp = get_filter_params(parse_query_params(window.location.search));
var item = get_item(elt);
/* Normally toggle in and out of the 'show' list. If this item is active because
* one of its keywords is active, invert the sense and toggle in and out of the
* 'hide' list instead. */
var inverted = keyword_match(fp.show, get_keywords(elt));
var just_showed_item = false;
if (inverted) {
toggle_list_item(fp.hide, item);
remove_list_item(fp.show, item);
} else {
just_showed_item = toggle_list_item(fp.show, item);
remove_list_item(fp.hide, item);
}
/* If we just showed an item, remove its children from the
* show/hide lists to keep things consistent. This way, selecting
* an area will enable all items in the row as one would expect. */
if (just_showed_item) {
var children = get_items_with_keyword(item);
$.each(children, function(index, child) {
remove_list_item(fp.show, child);
remove_list_item(fp.hide, child);
});
}
// If the show list is empty, clear the hide list because there is nothing to hide
if (fp.show.length === 0) {
fp.hide = [];
}
return fp;
}
function is_disabled(elt) {
return elt.hasClass('disabled');
}
function register_handlers() {
$('.pickview').on("click", function () {
if (is_disabled($(this))) { return; }
var fp = handle_pick_button($(this));
update_filters(fp);
});
}
/**
* Read options from the template
*/
function read_template_options() {
const opts_elt = document.getElementById('agenda-filter-options');
opts.keys().forEach((opt) => {
if (opt in opts_elt.dataset) {
opts[opt] = opts_elt.dataset[opt];
}
});
}
/* Entry point to filtering code when page loads
*
* This must be called if you are using the HTML template to provide a customization
* button UI. Do not call if you only want to use the parameter parsing routines.
*/
function enable () {
// ready handler fires immediately if document is already "ready"
$(document).ready(function () {
register_handlers();
update_view();
})
}
// utility method - filter a jquery set to those matching a keyword
function rows_matching_filter_keyword(rows, kw) {
return rows.filter(function(index, element) {
var row_kws = get_keywords(element);
return keyword_match(row_kws, [kw.toLowerCase()]);
});
}
// Make private functions available for unit testing
agenda_filter_for_testing = {
parse_query_params: parse_query_params,
toggle_list_item: toggle_list_item
};
// Make public interface methods accessible
agenda_filter = {
enable: enable,
filtering_is_enabled: filtering_is_enabled,
get_filter_params: get_filter_params,
keyword_match: keyword_match,
parse_query_params: parse_query_params,
rows_matching_filter_keyword: rows_matching_filter_keyword,
set_update_callback: function (cb) {opts.updateCallback = cb}
};
})();

View file

@ -0,0 +1,84 @@
// Copyright The IETF Trust 2021, All Rights Reserved
/*
Javascript support for the materials modal rendered by session_agenda_include.html
Requires jquery be loaded
*/
var agenda_materials; // public interface
(function() {
'use strict';
/**
* Retrieve and display materials for a session
*
* If output_elt exists and has a "data-src" attribute, retrieves the document
* from that URL and displays under output_elt. Handles text/plain, text/markdown,
* and text/html.
*
* @param output_elt Element, probably a div, to hold the output
*/
function retrieve_session_materials(output_elt) {
if (!output_elt) {return;}
output_elt = $(output_elt);
var data_src = output_elt.attr("data-src");
if (!data_src) {
output_elt.html("<p>Error: missing data-src attribute</p>");
} else {
output_elt.html("<p>Loading " + data_src + "...</p>");
var outer_xhr = $.ajax({url:data_src,headers:{'Accept':'text/plain;q=0.8,text/html;q=0.9'}})
outer_xhr.done(function(data, status, xhr) {
var t = xhr.getResponseHeader("content-type");
if (!t) {
data = "<p>Error retrieving " + data_src
+ ": Missing content-type in response header</p>";
} else if (t.indexOf("text/plain") > -1) {
data = "<pre class='agenda'>" + data + "</pre>";
} else if (t.indexOf("text/markdown") > -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>";
}
output_elt.html(data);
}).fail(function() {
output_elt.html("<p>Error retrieving " + data_src
+ ": (" + outer_xhr.status.toString() + ") "
+ outer_xhr.statusText + "</p>");
})
}
}
/**
* Retrieve contents of a session materials modal
*
* Expects output_elt to exist and have a "data-src" attribute. Retrieves the
* contents of that URL, then attempts to populate the .agenda-frame and
* .minutes-frame elements.
*
* @param output_elt Element, probably a div, to hold the output
*/
function retrieve_session_modal(output_elt) {
if (!output_elt) {return;}
output_elt = $(output_elt);
var data_src = output_elt.attr("data-src");
if (!data_src) {
output_elt.html("<p>Error: missing data-src attribute</p>");
} else {
output_elt.html("<p>Loading...</p>");
$.get(data_src).done(function(data) {
output_elt.html(data);
retrieve_session_materials(output_elt.find(".agenda-frame"));
retrieve_session_materials(output_elt.find(".minutes-frame"));
});
}
}
$(document).ready(function() {
$(".modal").on("show.bs.modal", function () {
retrieve_session_modal($(this).find(".session-materials"));
});
})
})();

View file

@ -0,0 +1,229 @@
// Copyright The IETF Trust 2021, All Rights Reserved
/*
Timezone support specific to the agenda page
To properly handle timezones other than local, needs a method to retrieve
the current timezone. Set this by passing a method taking no parameters and
returning the current timezone to the set_current_tz_cb() method.
This should be done before calling anything else in the file.
*/
var meeting_timezone;
var local_timezone = moment.tz.guess();
// get_current_tz_cb must be overwritten using set_current_tz_cb
window.get_current_tz_cb = function () {
throw new Error('Tried to get current timezone before callback registered. Use set_current_tz_cb().')
};
// Initialize moments
window.initialize_moments = function () {
var times=$('span.time')
$.each(times, function(i, item) {
item.start_ts = moment.unix(this.getAttribute("data-start-time")).utc();
item.end_ts = moment.unix(this.getAttribute("data-end-time")).utc();
if (this.hasAttribute("weekday")) {
item.format=2;
} else {
item.format=1;
}
if (this.hasAttribute("format")) {
item.format = +this.getAttribute("format");
}
});
var times=$('[data-slot-start-ts]')
$.each(times, function(i, item) {
item.slot_start_ts = moment.unix(this.getAttribute("data-slot-start-ts")).utc();
item.slot_end_ts = moment.unix(this.getAttribute("data-slot-end-ts")).utc();
});
}
window.format_time = function (t, tz, fmt) {
var out;
var mtz = meeting_timezone;
if (mtz == "") {
mtz = "UTC";
}
switch (fmt) {
case 0:
out = t.tz(tz).format('dddd, ') + '<span class="hidden-xs">' +
t.tz(tz).format('MMMM Do YYYY, ') + '</span>' +
t.tz(tz).format('HH:mm') + '<span class="hidden-xs">' +
t.tz(tz).format(' Z z') + '</span>';
break;
case 1:
// Note, this code does not work if the meeting crosses the
// year boundary.
out = t.tz(tz).format("HH:mm");
if (+t.tz(tz).dayOfYear() < +t.tz(mtz).dayOfYear()) {
out = out + " (-1)";
} else if (+t.tz(tz).dayOfYear() > +t.tz(mtz).dayOfYear()) {
out = out + " (+1)";
}
break;
case 2:
out = t.tz(mtz).format("dddd, ").toUpperCase() +
t.tz(tz).format("HH:mm");
if (+t.tz(tz).dayOfYear() < +t.tz(mtz).dayOfYear()) {
out = out + " (-1)";
} else if (+t.tz(tz).dayOfYear() > +t.tz(mtz).dayOfYear()) {
out = out + " (+1)";
}
break;
case 3:
out = t.utc().format("YYYY-MM-DD");
break;
case 4:
out = t.tz(tz).format("YYYY-MM-DD HH:mm");
break;
case 5:
out = t.tz(tz).format("HH:mm");
break;
}
return out;
}
// Format tooltip notice
window.format_tooltip_notice = function (start, end) {
var notice = "";
if (end.isBefore()) {
notice = "Event ended " + end.fromNow();
} else if (start.isAfter()) {
notice = "Event will start " + start.fromNow();
} else {
notice = "Event started " + start.fromNow() + " and will end " +
end.fromNow();
}
return '<span class="tooltipnotice">' + notice + '</span>';
}
// Format tooltip table
window.format_tooltip_table = function (start, end) {
var current_timezone = get_current_tz_cb();
var out = '<table><tr><th>Timezone</th><th>Start</th><th>End</th></tr>';
if (meeting_timezone !== "") {
out += '<tr><td class="timehead">Meeting timezone:</td><td>' +
format_time(start, meeting_timezone, 0) + '</td><td>' +
format_time(end, meeting_timezone, 0) + '</td></tr>';
}
out += '<tr><td class="timehead">Local timezone:</td><td>' +
format_time(start, local_timezone, 0) + '</td><td>' +
format_time(end, local_timezone, 0) + '</td></tr>';
if (current_timezone !== 'UTC') {
out += '<tr><td class="timehead">Selected Timezone:</td><td>' +
format_time(start, current_timezone, 0) + '</td><td>' +
format_time(end, current_timezone, 0) + '</td></tr>';
}
out += '<tr><td class="timehead">UTC:</td><td>' +
format_time(start, 'UTC', 0) + '</td><td>' +
format_time(end, 'UTC', 0) + '</td></tr>';
out += '</table>' + format_tooltip_notice(start, end);
return out;
}
// Format tooltip for item
window.format_tooltip = function (start, end) {
return '<div class="timetooltiptext">' +
format_tooltip_table(start, end) +
'</div>';
}
// Add tooltips
window.add_tooltips = function () {
$('span.time').each(function () {
var tooltip = $(format_tooltip(this.start_ts, this.end_ts));
tooltip[0].start_ts = this.start_ts;
tooltip[0].end_ts = this.end_ts;
tooltip[0].ustart_ts = moment(this.start_ts).add(-2, 'hours');
tooltip[0].uend_ts = moment(this.end_ts).add(2, 'hours');
$(this).parent().append(tooltip);
});
}
// Update times on the agenda based on the selected timezone
window.update_times = function (newtz) {
$('span.current-tz').html(newtz);
$('span.time').each(function () {
if (this.format == 4) {
var tz = this.start_ts.tz(newtz).format(" z");
if (this.start_ts.tz(newtz).dayOfYear() ==
this.end_ts.tz(newtz).dayOfYear()) {
$(this).html(format_time(this.start_ts, newtz, this.format) +
'-' + format_time(this.end_ts, newtz, 5) + tz);
} else {
$(this).html(format_time(this.start_ts, newtz, this.format) +
'-' +
format_time(this.end_ts, newtz, this.format) + tz);
}
} else {
$(this).html(format_time(this.start_ts, newtz, this.format) + '-' +
format_time(this.end_ts, newtz, this.format));
}
});
update_tooltips_all();
update_clock();
}
// Highlight ongoing based on the current time
window.highlight_ongoing = function () {
$("div#now").remove("#now");
$('.ongoing').removeClass("ongoing");
var agenda_rows=$('[data-slot-start-ts]')
agenda_rows = agenda_rows.filter(function() {
return moment().isBetween(this.slot_start_ts, this.slot_end_ts);
});
agenda_rows.addClass("ongoing");
agenda_rows.first().children("th, td").
prepend($('<div id="now" class="anchor-target"></div>'));
}
// Update tooltips
window.update_tooltips = function () {
var tooltips=$('.timetooltiptext');
tooltips.filter(function() {
return moment().isBetween(this.ustart_ts, this.uend_ts);
}).each(function () {
$(this).html(format_tooltip_table(this.start_ts, this.end_ts));
});
}
// Update all tooltips
window.update_tooltips_all = function () {
var tooltips=$('.timetooltiptext');
tooltips.each(function () {
$(this).html(format_tooltip_table(this.start_ts, this.end_ts));
});
}
// Update clock
window.update_clock = function () {
$('#current-time').html(format_time(moment(), get_current_tz_cb(), 0));
}
$.urlParam = function(name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results == null) {
return null;
} else {
return results[1] || 0;
}
}
window.init_timers = function () {
var fast_timer = 60000 / (speedup > 600 ? 600 : speedup);
update_clock();
highlight_ongoing();
setInterval(function() { update_clock(); }, fast_timer);
setInterval(function() { highlight_ongoing(); }, fast_timer);
setInterval(function() { update_tooltips(); }, fast_timer);
setInterval(function() { update_tooltips_all(); }, 3600000 / speedup);
}
// set method used to find current time zone
window.set_current_tz_cb = function (fn) {
get_current_tz_cb = fn;
}

View file

@ -0,0 +1 @@
import "moment-timezone/builds/moment-timezone-with-data-10-year-range";

3
ietf/static/js/moment.js Normal file
View file

@ -0,0 +1,3 @@
const moment = require("moment");
global.moment = moment;

View file

@ -0,0 +1,74 @@
// Copyright The IETF Trust 2021, All Rights Reserved
/*
Timezone selection handling. Relies on the moment.js library.
To use, create one (or more) select inputs with class "tz-select". When the initialize()
method is called, the options in the select will be replaced with the recognized time zone
names. Time zone can be changed via the select input or by calling the use() method with
the name of a time zone (or 'local' to guess the user's local timezone).
*/
window.ietf_timezone; // public interface
(function () {
'use strict';
// Callback for timezone change - called after current_timezone is updated
var timezone_change_callback;
var current_timezone;
// Select timezone to use. Arg is name of a timezone or 'local' to guess local tz.
function use_timezone (newtz) {
// Guess local timezone if necessary
if (newtz.toLowerCase() === 'local') {
newtz = moment.tz.guess()
}
if (current_timezone !== newtz) {
current_timezone = newtz
// Update values of tz-select inputs but do not trigger change event
$('select.tz-select').val(newtz)
if (timezone_change_callback) {
timezone_change_callback(newtz)
}
}
}
/* Initialize timezone system
*
* This will set the timezone to the value of 'current'. Set up the tz_change callback
* before initializing.
*/
function timezone_init (current) {
var tz_names = moment.tz.names()
var select = $('select.tz-select')
select.empty()
$.each(tz_names, function (i, item) {
if (current === item) {
select.append($('<option/>', {
selected: 'selected', html: item, value: item
}))
} else {
select.append($('<option/>', {
html: item, value: item
}))
}
})
select.on("change", function () {use_timezone(this.value)});
/* When navigating back/forward, the browser may change the select input's
* value after the window load event. It does not fire the change event on
* the input when it does this. The pageshow event occurs after such an update,
* so trigger the change event ourselves to be sure the UI stays consistent
* with the timezone select input. */
window.addEventListener('pageshow', function(){select.trigger("change"); })
use_timezone(current);
}
// Expose public interface
ietf_timezone = {
get_current_tz: function() {return current_timezone},
initialize: timezone_init,
set_tz_change_callback: function(cb) {timezone_change_callback=cb},
use: use_timezone
}
})();

View file

@ -346,7 +346,7 @@
{% block js %}
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/agenda_filter.js' %}"></script>
<script>
// Update the agenda display with specified filters
function update_agenda_display(filter_params) {
@ -435,13 +435,12 @@
}
</script>
<script src="{% static 'moment/min/moment.min.js' %}"></script>
<script src="{% static 'moment-timezone/builds/moment-timezone-with-data-10-year-range.min.js' %}"></script>
<script src="{% static 'ietf/js/agenda/timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_materials.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_timezone.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda_materials.js' %}"></script>
<script src="{% static 'ietf/js/agenda_timezone.js' %}"></script>
<script>
{% if settings.DEBUG and settings.DEBUG_AGENDA %}
speedup = +$.urlParam('speedup');
if (speedup < 1) {

View file

@ -374,11 +374,11 @@
{% endblock %}
{% block js %}
<script src="{% static 'moment/min/moment.min.js' %}"></script>
<script src="{% static 'moment-timezone/builds/moment-timezone-with-data-10-year-range.min.js' %}"></script>
<script src="{% static 'ietf/js/agenda/timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda_timezone.js' %}"></script>
<script src="{% static 'ietf/js/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_personalize.js' %}"></script>
<script>

View file

@ -30,8 +30,8 @@
{% block title %}{{ schedule.name }}: IETF {{ meeting.number }} meeting agenda{% endblock %}
{% block js %}
<script type="text/javascript" src="{% static 'moment/min/moment.min.js' %}"></script>
<script type="text/javascript" src="{% static 'moment-timezone/builds/moment-timezone-with-data-10-year-range.min.js' %}"></script>
<script type="text/javascript" src="{% static 'ietf/js/moment.js' %}"></script>
<script type="text/javascript" src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script type="text/javascript" src="{% static 'ietf/js/edit-meeting-schedule.js' %}"></script>
{% endblock js %}

View file

@ -178,11 +178,11 @@
<script src="{% static "ietf/js/datatables.js" %}"></script>
<script src="{% static 'fullcalendar/core/main.js' %}"></script>
<script src="{% static 'fullcalendar/daygrid/main.js' %}"></script>
<script src="{% static 'moment/min/moment.min.js' %}"></script>
<script src="{% static 'moment-timezone/builds/moment-timezone-with-data-10-year-range.min.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/agenda/agenda_materials.js' %}"></script>
<script src="{% static 'ietf/js/agenda/timezone.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script src="{% static 'ietf/js/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/agenda_materials.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script>
// List of all events with meta-info needed for filtering
var all_event_list = [{% for entry in entries %}

View file

@ -2,9 +2,9 @@
{% load origin %}{% origin %}
{% load static %}
<html> <head>
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
<script src="{% static 'moment/min/moment.min.js' %}"></script>
<script src="{% static 'moment-timezone/builds/moment-timezone-with-data-10-year-range.min.js' %}"></script>
<script src="{% static 'ietf/js/agenda_filter.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script type="text/javascript">
var all_items = {{ items|safe }};

38
package-lock.json generated
View file

@ -1,5 +1,5 @@
{
"name": "7.39.1.dev3-bs5",
"name": "7.39.1.dev4-bs5",
"lockfileVersion": 2,
"requires": true,
"packages": {
@ -12,7 +12,9 @@
"datatables.net": "^1.11.3",
"datatables.net-bs5": "^1.11.3",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1"
"js-cookie": "^3.0.1",
"moment": "^2.29.1",
"moment-timezone": "^0.5.34"
},
"devDependencies": {
"@parcel/transformer-sass": "^2.0.1",
@ -5810,6 +5812,25 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/moment-timezone": {
"version": "0.5.34",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz",
"integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==",
"dependencies": {
"moment": ">= 2.9.0"
},
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -13191,6 +13212,19 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"moment-timezone": {
"version": "0.5.34",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz",
"integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==",
"requires": {
"moment": ">= 2.9.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View file

@ -7,7 +7,9 @@
"datatables.net": "^1.11.3",
"datatables.net-bs5": "^1.11.3",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1"
"js-cookie": "^3.0.1",
"moment": "^2.29.1",
"moment-timezone": "^0.5.34"
},
"devDependencies": {
"@parcel/transformer-sass": "^2.0.1",
@ -20,6 +22,12 @@
"ietf/static/js/datatables.js",
"ietf/static/js/document_timeline.js",
"ietf/static/js/d3.js",
"ietf/static/js/moment.js",
"ietf/static/js/agenda_filter.js",
"ietf/static/js/agenda_materials.js",
"ietf/static/js/agenda_timezone.js",
"ietf/static/js/timezone.js",
"ietf/static/js/moment-timezone-with-data-10-year-range.js",
"ietf/static/css/ietf.scss",
"ietf/static/css/datatables.scss",
"ietf/static/images/ietflogo-small-transparent.png",
@ -32,4 +40,4 @@
"distDir": "ietf/static/dist/ietf"
}
}
}
}