datatracker/ietf/templates/meeting/room-view.html
Ole Laursen c78ffbcd18 Introduce support for setting a base schedule on a schedule. All
assignments on the base schedule are shown in the pages for the
schedule, read-only.

This allows managing things like breaks and misc sessions separately
from the regular WG sessions.

Base schedules are not allowed to be the base of other base schedules
(the hierarchy can only be one level deep) to simplify the mental
model and the code.

Add link for creating new schedules instead of relying on copying
Empty-Schedule and change the meeting creation code to no longer
create the special Empty-Schedule. Instead a "base" schedule is
created and a first schedule with the name and permissions of the user
creating the meeting, using "base" as base.

Speed up a couple of the Secretariat/AD agenda views by adding
prefetches.
 - Legacy-Id: 18355
2020-08-11 17:34:32 +00:00

613 lines
22 KiB
HTML

{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}{% origin %}
{% load staticfiles %}
<html> <head>
<link rel="stylesheet" href="{% static 'ietf/bootstrap/css/bootstrap.min.css' %}"> {% comment %} This sets box-sizing: border-box {% endcomment %}
<link rel="stylesheet" href="{% static 'ietf/bootstrap/css/bootstrap-theme.min.css' %}">
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'ietf/bootstrap/js/bootstrap.min.js' %}"></script>
<script type="text/javascript">
{% autoescape off %}
var room_names = [{% for room in rooms %}"{{room.name}}"{% if not forloop.last %},{% endif %}{% endfor %}];
var room_functional_names = [{% for room in rooms %}"{{room.functional_name}}"{% if not forloop.last %},{% endif %}{% endfor %}];
var room_typelabels = [{% for room in rooms %}"{% for type in room.session_types.all %}{{type.name}}{% if not forloop.last %}, {% endif %}{% endfor %}"{% if not forloop.last %},{% endif %}{% endfor %}];
var items = new Array();
{% for slot in unavailable %}
if (room_names.indexOf("{{slot.get_hidden_location}}") >= 0 )
{
items.push({room_index:room_names.indexOf("{{slot.get_hidden_location}}"),day:{{slot.day}}, delta_from_beginning:{{slot.delta_from_beginning}},time:"{{slot.time|date:"Hi"}}-{{slot.end_time|date:"Hi"}}", verbose_time:"{{slot.time|date:"D M d Hi"}}-{{slot.end_time|date:"Hi"}}",duration:{{slot.duration.total_seconds}}, type:"{{slot.type}}", name:"Unavailable", dayname:"{{ slot.time|date:"l"|upper }}, {{ slot.time|date:"F j, Y" }}" });
}
{% endfor %}
{% for ss in assignments %}
if (room_names.indexOf("{{ss.timeslot.get_hidden_location}}") >= 0 )
{
items.push({room_index:room_names.indexOf("{{ss.timeslot.get_hidden_location}}"),day:{{ss.day}}, delta_from_beginning:{{ss.delta_from_beginning}},time:"{{ss.timeslot.time|date:"Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}", verbose_time:"{{ss.timeslot.time|date:"D M d Hi"}}-{{ss.timeslot.end_time|date:"Hi"}}",duration:{{ss.timeslot.duration.total_seconds}}, type:"{{ss.timeslot.type}}", {% if ss.session.name %}name:"{{ss.session.name|escapejs}}",{% if ss.session.group.acronym %} wg:"{{ss.session.group.acronym}}",{%endif%}{% else %}{% if ss.timeslot.type.name == "Break" %}name:"{{ss.timeslot.name|escapejs}}", area:"break", wg:"break",{% elif ss.timeslot.type_id == "unavail" %}name:"Unavailable",{% else %}name:"{{ss.session.group.name|escapejs}}{%if ss.session.group.state.name == "BOF"%} BOF{%endif%}",wg:"{{ss.session.group.acronym}}",state:"{{ss.session.group.state}}",area:"{{ss.session.group.parent.acronym}}",{% endif %}{% endif %} dayname:"{{ ss.timeslot.time|date:"l"|upper }}, {{ ss.timeslot.time|date:"F j, Y" }}"{% if ss.session.agenda %}, agenda:"{{ss.session.agenda.get_href}}"{% endif %}, from_base_schedule: {% if ss.schedule_id != meeting.schedule_id %}true{% else %}false{% endif %} });
}
{% endfor %}
{% endautoescape %}
var start_map = items.map(function(el,i) {
return { room_index:el.room_index, start_time:el.delta_from_beginning, index:i};
});
start_map.sort(function(a,b) {
if ( a.room_index != b.room_index) {
return (a.room_index - b.room_index);
}
return a.start_time - b.start_time;
});
var end_map = items.map(function(el,i) {
return { room_index:el.room_index, end_time:el.delta_from_beginning+el.duration, index:i};
});
end_map.sort(function(a,b) {
if ( a.room_index != b.room_index) {
return (a.room_index - b.room_index);
}
return a.end_time - b.end_time;
});
var si = 0;
var ei = 0;
var overlap = 0;
var max_lanes = 0;
var next_lane = [];
var start_overlap = si;
while (si < items.length ) {
var start_room_change = false;
while ( !start_room_change && si < items.length && start_map[si].start_time < end_map[ei].end_time )
{
overlap++;
if (next_lane.length>0)
{
items[start_map[si].index].lane = next_lane.shift();
}
else
{
items[start_map[si].index].lane = max_lanes;
max_lanes++;
}
start_room_change = ( si+1 == items.length || start_map[si].room_index != start_map[si+1].room_index );
si++;
}
var end_room_change = false;
while ( ei < items.length && !end_room_change && ( start_room_change || si == items.length || start_map[si].start_time >= end_map[ei].end_time ) )
{
next_lane.push(items[end_map[ei].index].lane);
overlap--;
end_room_change = ( ei+1 == items.length || end_map[ei].room_index != end_map[ei+1].room_index );
ei++;
}
if ( overlap == 0 )
{
for (var i=start_overlap; i<si; i++)
{
items[start_map[i].index].lanes = max_lanes;
}
max_lanes = 0;
next_lane=[];
start_overlap = si;
}
}
var fg = {
'app': "#008",
'art': "#808",
'gen': "#080",
'int': "#088",
'ops': "#800",
'rai': "#808",
'rtg': "#880",
'sec': "#488",
'tsv': "#484",
'irtf': "#448",
'break': "#000"
};
var bg = {
'app': "#eef",
'art': "#fef",
'gen': "#efe",
'int': "#eff",
'ops': "#fee",
'rai': "#fef",
'rtg': "#ffe",
'sec': "#dff",
'tsv': "#dfd",
'irtf': "#ddf",
'break': "#fff"
};
var divlist = [];
var lastfrag;
var lastheight;
var lastwidth;
var padding = 2;
var border = 1;
setInterval(animate,50);
function draw_calendar()
{
window.setTimeout(draw_calendar,1000);
var width = document.body.clientWidth;
var height = document.body.clientHeight;
if (lastheight == height &&
lastwidth == width &&
lastfrag == window.location.hash)
{
return;
}
var i;
var text="";
var day_start = 23*60+59;
var day_end = 0;
/* Find our boundaries */
for (i = 0; i < items.length; i++)
{
{
var start_time = parseInt(items[i].time.substr(0,2),10) * 60 +
parseInt(items[i].time.substr(2,2),10);
var end_time = start_time + (items[i].duration / 60)
if (start_time < day_start) { day_start = start_time; }
if (end_time > day_end) { day_end = end_time; }
}
}
var timelabel_width = width * 0.020;
var header_height = height * 0.05;
var header_offset = $('#daytabs').outerHeight(true)+$('#mtgheader').outerHeight(true);
console.log($('#mtgheader').outerHeight(true))
var num_days = {{days|length}};
var num_minutes = day_end - day_start;
var minute_height = (height - header_height - header_offset)/num_minutes;
var body = document.body;
var daydiv;
{% for day in days %}
daydiv = document.getElementById("day{{forloop.counter0}}")
while (daydiv.childNodes.length) { daydiv.removeChild(daydiv.childNodes[0]); }
{% endfor %}
var room_width = (width - timelabel_width) {% if rooms.count %}/ {{ rooms.count }}{% endif %};
for (var day=0; day<num_days; day++)
{
for (var ri=0; ri<room_names.length; ri++)
{
var e = document.createElement("div");
e.style.border="solid";
e.style.borderWidth=border;
e.style.background="#2647f0";
e.style.color="#fff";
e.style.borderColor="#000 #fff";
e.style.borderColor="#2647f0 #2647f0 #000 #2647f0";
e.style.display="block";
e.style.overflow="hidden";
e.style.position="absolute";
e.style.top=header_offset;
e.style.left = timelabel_width+ri*room_width;
e.style.width=room_width;
e.style.height=header_height;
e.style.margin=0;
e.style.padding=padding;
e.style.fontFamily="sans-serif";
e.style.fontSize=header_height * 0.25;
e.style.textAlign="center";
var div = document.createElement("div");
div.appendChild(document.createTextNode(room_names[ri]));
if (room_functional_names[ri].length>0)
{
div.appendChild(document.createElement("br"));
div.appendChild(document.createTextNode(room_functional_names[ri]));
}
if (room_typelabels[ri].length>0)
{
div.title=room_names[ri]+"\n"+room_functional_names[ri]+"\n"+room_typelabels[ri];
}
e.appendChild(div);
document.getElementById("day"+day).appendChild(e);
//-----------------------------------------------------------------
// Draw column border
//-----------------------------------------------------------------
e = document.createElement("div");
e.style.border="solid";
e.style.borderWidth=border;
e.style.color="#000";
e.style.borderColor="#fff #000";
e.style.display="block";
e.style.overflow="hidden";
e.style.position="absolute";
e.style.top=header_height+header_offset;
e.style.left=timelabel_width + ri*room_width;
e.style.width=room_width ;
e.style.height=height - header_height - header_offset;
e.style.margin=0;
e.style.padding=padding;
document.getElementById("day"+day).appendChild(e);
}
//-----------------------------------------------------------------
// Draw hour lines
//-----------------------------------------------------------------
for (var time = day_start - (day_start%60) + 60; time < day_end ; time += 60)
{
e = document.createElement("div");
e.style.borderTopStyle="solid";
e.style.boderTopWidth="2px";
e.style.borderColor="#f8f8f8";
e.style.overflow="hidden";
e.style.position="absolute";
e.style.top=header_height + header_offset + (time - day_start) * minute_height;
e.style.left=timelabel_width;
e.style.width=width-timelabel_width;
e.style.height=0;
e.style.zIndex="-1";
e.style.margin=0;
e.style.padding=padding;
document.getElementById("day"+day).appendChild(e);
e = document.createElement("div");
e.style.overflow="hidden";
e.style.position="absolute";
e.style.top=header_height + header_offset - (header_height*0.125) + (time - day_start) * minute_height;
e.style.left=0;
e.style.width=timelabel_width;
e.style.height=header_height * 0.5;
e.style.zIndex="-1";
e.style.margin=0;
e.style.padding=padding;
e.style.fontFamily="sans-serif";
e.style.fontSize=header_height * 0.25;
e.style.textAlign="right";
e.style.color="#e0e0e0";
var label = time/60+"00";
if (label.length < 4 )
{
label = "0"+label;
}
e.appendChild(document.createTextNode(label));
document.getElementById("day"+day).appendChild(e);
}
}
//-----------------------------------------------------------------
// Draw a block for each meeting
//-----------------------------------------------------------------
var resize_func = function(div,t,l,w,h,to_fit)
{ return function(){resize(div,t,l,w,h,to_fit);} }
var maximize_func = function (e) { return function(){maximize(e);}}
for (i = 0; i < items.length; i++)
{
{
var start_time = parseInt(items[i].time.substr(0,2),10) * 60 +
parseInt(items[i].time.substr(2,2),10);
var end_time = start_time + (items[i].duration / 60);
var sess_width = room_width / items[i].lanes;
var sess_height = ((end_time - start_time) * minute_height) ;
var room_left = timelabel_width + items[i].room_index * room_width;
var sess_left = room_left + sess_width * items[i].lane;
var sess_top = ((start_time - day_start) * minute_height) + header_height + header_offset;
sess_width = sess_width;
var e = document.createElement("div");
e.style.border="solid";
e.style.borderWidth=border;
if (fg[items[i].area])
{
e.style.background=bg[items[i].area];
e.style.color=fg[items[i].area];
e.style.borderColor=fg[items[i].area];
}
else
{
e.style.background="#e0e0e0";
e.style.color="#000000";
e.style.borderColor="#000000";
}
e.style.display="block";
e.style.overflow="hidden";
e.style.position="absolute";
e.style.top=sess_top;
e.style.left=sess_left;
e.style.width=sess_width;
e.style.height=sess_height;
e.style.margin=0;
e.style.padding=padding;
e.style.fontFamily="sans-serif";
e.style.fontSize="8pt";
if (items[i].from_base_schedule)
e.style.opacity = 0.5;
e.id=i;
e.onmouseover=resize_func(e,sess_top,room_left,
room_width,
sess_height, true);
e.onmouseout=resize_func(e,sess_top,sess_left,sess_width,sess_height,false);
if (items[i].agenda)
{
e.onclick=maximize_func(e);
e.style.cursor="pointer";
}
var div = document.createElement("div");
div.appendChild(document.createTextNode(items[i].verbose_time));
div.appendChild(document.createElement("br"));
var label = items[i].name;
if (label.length == 0) { label = "Free Slot"; }
if (items[i].wg && fg[items[i].area])
{
label = label + " (" + items[i].wg + ")";
}
var bold = document.createElement("span");
bold.appendChild(document.createTextNode(label));
bold.style.fontWeight="bold";
div.appendChild(bold);
e.appendChild(div);
document.getElementById("day"+items[i].day).appendChild(e);
}
}
lastheight = height;
lastwidth = width;
lastfrag = window.location.hash;
}
function resize(div,t2,l2,w2,h2,to_fit)
{
// Move the element to the front
var parent = div.parentElement;
parent.removeChild(div);
parent.appendChild(div);
div.t2 = t2;
div.l2 = l2;
div.w2 = w2;
div.h2 = h2;
div.to_fit = to_fit;
div.percent = 0;
divlist.push(div);
}
function animate()
{
var i;
for (i = divlist.length - 1; i >= 0; i--)
{
var div = divlist[i];
if (div.percent < 100)
{
div.percent += 5;
var t1 = parseFloat(div.style.top.replace("px",""));
var l1 = parseFloat(div.style.left.replace("px",""));
var w1 = parseFloat(div.style.width.replace("px",""));
var h1 = parseFloat(div.style.height.replace("px",""));
div.style.top = wavg(t1,div.t2,div.percent);
div.style.left = wavg(l1,div.l2,div.percent);
div.style.width = wavg(w1,div.w2,div.percent);
div.style.height = wavg(h1,div.h2,div.percent);
if (t1 == div.t2 && l1 == div.l2 &&
w1 == div.w2 && h1 == div.h2) { div.percent = 100; }
}
else
{
if (div.to_fit)
{
var tmp = div.style.height;
div.style.removeProperty("height");
if (div.h2 < div.clientHeight)
{
div.h2 = div.clientHeight;
div.percent = 0;
}
else
{
divlist.remove(i);
if (div.callback)
{
var tmp = div.callback;
div.callback = undefined;
tmp();
}
}
div.style.height = tmp;
}
else
{
divlist.remove(i);
if (div.callback)
{
var tmp = div.callback;
div.callback = undefined;
tmp();
}
}
}
}
}
function finish_maximize(e)
{
if (!items[e.id].agenda)
{
return;
}
e.insertBefore(document.createElement("br"),e.firstChild);
var minimize_func = function (e) { return function(){minimize(e);} }
var img = document.createElement("img");
img.src = "{% static 'ietf/images/agenda-weekview/close.png' %}";
img.style.cssFloat="right";
img.onclick = minimize_func(e);
img.style.cursor="pointer";
e.insertBefore(img,e.firstChild);
var h = document.createElement("span");
h.appendChild(document.createTextNode(items[e.id].dayname));
h.style.fontWeight="bold";
e.insertBefore(h,e.firstChild);
e.style.fontSize="10pt";
var tmp = e.style.height;
e.style.removeProperty("height");
var used_height = e.clientHeight;
e.style.height = tmp;
var frame = document.createElement("iframe");
frame.setAttribute("src",items[e.id].agenda);
frame.style.position = "absolute";
frame.style.left = 8;
frame.style.width = e.clientWidth - 16 ;
frame.style.top = used_height + 8;
frame.style.height = e.clientHeight - used_height - 16 ;
frame.style.background = "#fff";
frame.style.overflow="auto";
frame.id="agenda";
frame.style.border = e.style.border;
frame.style.borderWidth = border;
frame.style.padding = padding;
frame.style.borderColor = e.style.borderColor;
e.appendChild(frame);
}
function finish_minimize(e)
{
e.onmouseover = e.oldmouseover;
e.onmouseout = e.oldmouseout;
e.oldmouseover = undefined;
e.oldmouseout = undefined;
e.style.cursor="pointer";
}
function maximize(e)
{
if (e.onmouseover)
{
e.oldmouseover = e.onmouseover;
e.oldmouseout = e.onmouseout;
e.onmouseover = undefined;
e.onmouseout = undefined;
e.style.cursor="auto";
var callback_func = function (e) { return function(){finish_maximize(e);}}
e.callback = callback_func(e);
resize(e,0,0,
document.body.clientWidth,
document.body.clientHeight);
}
}
function minimize(e)
{
var agenda = document.getElementById("agenda");
if (agenda)
{
e.removeChild(agenda);
}
var callback_func = function (e) { return function(){finish_minimize(e);}}
e.callback = callback_func(e);
e.oldmouseout();
e.removeChild(e.firstChild);
e.removeChild(e.firstChild);
e.removeChild(e.firstChild);
e.style.fontSize="8pt";
}
function wavg(x1,x2,percent)
{
if (percent == 100) { return x2; }
var res = x2 * (percent / 100) + x1 * ((100 - percent) / 100);
return res;
}
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
</script>
</head>
<body onload="draw_calendar()" onresize="draw_calendar()" id="body">
<div id="mtgheader" style="overflow:auto">{% include "meeting/meeting_heading.html" with updated=schedule.meeting.updated selected="room-view" title_extra="Room Grid" %}</div>
<div id="daycontainer" role="tabpanel">
<ul id="daytabs" class="nav nav-tabs" role="tablist">
{% for day in days %}
<li {% if forloop.first %}class="active"{% endif %} role="presentation"><a href="#day{{forloop.counter0}}" id="day{{forloop.counter0}}-tab" role="tab" data-toggle="tab" area-controls="day{{forloop.counter0}}">{{day|date:"D M d"}}</a></li>
{% endfor %}
</ul>
<div class="tab-content">
{% for day in days %}
<div role="tab-panel" class="tab-pane{% if forloop.first %} active{% endif %}" id="day{{forloop.counter0}}">Error loading calendar for {{day|date:"D M d"}}</div>
{% endfor %}
</div>
<div>
<script>
// Javascript to enable link to tabs
var url = document.location.toString();
if (url.match('#')) {
$('.nav-tabs a[href="#' + url.split('#')[1] + '"]').tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash;
})
</script>
</body></html>