Add the scripts and dependencies for the agenda page back, and make them work.
- Legacy-Id: 19652
This commit is contained in:
parent
273feec52d
commit
be3a8f71ce
310
ietf/static/js/agenda_filter.js
Normal file
310
ietf/static/js/agenda_filter.js
Normal 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}
|
||||
};
|
||||
})();
|
84
ietf/static/js/agenda_materials.js
Normal file
84
ietf/static/js/agenda_materials.js
Normal 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"));
|
||||
});
|
||||
})
|
||||
})();
|
229
ietf/static/js/agenda_timezone.js
Normal file
229
ietf/static/js/agenda_timezone.js
Normal 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;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
import "moment-timezone/builds/moment-timezone-with-data-10-year-range";
|
3
ietf/static/js/moment.js
Normal file
3
ietf/static/js/moment.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const moment = require("moment");
|
||||
|
||||
global.moment = moment;
|
74
ietf/static/js/timezone.js
Normal file
74
ietf/static/js/timezone.js
Normal 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
|
||||
}
|
||||
})();
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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
38
package-lock.json
generated
|
@ -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",
|
||||
|
|
12
package.json
12
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue