datatracker/ietf/static/ietf/js/agenda/agenda_objects.js
Sasha Romijn 4decb23022 Add display of new constraints and joint sessions to agenda builder interface.
The new timerange, time_relation and wg_adjacent constraints, along with the
joint_with_groups option, are now reflected in the special requests field.
This allows them to be taken into account while scheduling sessions.
 - Legacy-Id: 17378
2020-03-03 15:16:58 +00:00

1963 lines
63 KiB
JavaScript

/*
*
* FILE: agenda_objects.js
* Copyright (c) 2013, The IETF Trust. See ../../../LICENSE.
*
* www.credil.org: Project Orlando 2013
* Author: Justin Hornosty ( justin@credil.org )
* Michael Richardson <mcr@sandelman.ca>
*
* Description:
* Contains the objects relating to django's models.
* As much business logic as possible should be here.
* This file should be resuable by other than agenda_edit.js
*
* Display logic should be contained in agenda_listeners.js
*
* Functions:
* - check_delimiter(inp)
* - upperCaseWords(inp)
*
*/
function AgendaGlobals() {
this.group_objs = {};
this.slot_status = {};
this.slot_objs = {};
this.meeting_objs = {};
this.sessions_objs = {};
this.timeslot_bydomid = {};
this.timeslot_byid = {};
this.assignment_promise = undefined;
this.timeslot_promise = undefined;
this.__debug_session_move = false;
}
function createLine(x1,y1, x2,y2){
var length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
var transform = 'rotate('+angle+'deg)';
var line = $('<div>')
.appendTo('#meetings')
.addClass('line')
.css({
'position': '',
'transform': transform
})
.width(length)
.offset({left: x1, top: y1});
return line;
}
function empty_callback(inp){
// console.log('inp:', inp);
}
function get_all_constraints(){
for(s in agenda_globals.meeting_objs){
show_non_conflicting_spots(s)
}
}
function show_all_conflicts(){
console.log("showing all conflicts");
for(sk in agenda_globals.meeting_objs) {
var s = agenda_globals.meeting_objs[sk];
s.display_conflict();
s.display_personconflict();
}
}
// not really used anymore -- just for debugging
function hide_all_conflicts(){
for(sk in agenda_globals.meeting_objs) {
var s = agenda_globals.meeting_objs[sk];
s.hide_conflict();
}
}
function get_all_conflicts(){
var all_constraint_promises = [];
var one_constraint;
var sess1;
//console.log("get_all_conflicts()");
for(var s in agenda_globals.meeting_objs){
sess1 = agenda_globals.meeting_objs[s];
sess1.clear_conflict();
sess1.display_conflict();
one_constraint = sess1.retrieve_constraints_by_session();
all_constraint_promises.push(one_constraint);
}
/* now make a promise that ends when all the conflicts are loaded */
var all_constraints = $.when.apply($,all_constraint_promises);
all_constraints.done(function() {
for(var s in agenda_globals.meeting_objs) {
var sess2 = agenda_globals.meeting_objs[s];
sess2.examine_people_conflicts();
}
});
return all_constraints;
}
var __debug_conflict_calculate = false;
var __verbose_conflict_calculate = false;
function calculate_real_conflict(conflict, vertical_location, room_tag, session_obj) {
if(__debug_conflict_calculate) {
console.log(" conflict check:", conflict.othergroup.acronym, "me:", vertical_location, room_tag);
}
if(session_obj.group.href == conflict.othergroup.href) {
console.log(" session: ",session_obj.session_id, "lists conflict with self");
return;
}
var osessions = conflict.othergroup.all_sessions;
if(__debug_conflict_calculate) {
console.log(" ogroup: ", conflict.othergroup.href, "me: ", session_obj.group.href);
}
if(conflict.othergroup === session_obj.group) {
osessions = conflict.thisgroup.all_sessions;
}
if(osessions != null) {
$.each(osessions, function(index) {
osession = osessions[index];
for(ccn in osession.column_class_list) {
var value = osession.column_class_list[ccn];
if(value != undefined) {
if(__debug_conflict_calculate) {
console.log(" vs: ",index, "session_id:",osession.session_id," at: ",value.column_tag, value.room_tag);
}
if(value.column_tag == vertical_location &&
value.room_tag != room_tag) {
if(__verbose_conflict_calculate || __debug_conflict_calculate) {
console.log("real conflict:",session_obj.title," with: ",conflict.othergroup.acronym, " #session_",session_obj.session_id, value.room_tag, room_tag, value.column_tag, vertical_location);
}
// there is a conflict!
__DEBUG_SHOW_CONSTRAINT = $("#"+value[0]).children()[0];
session_obj.add_conflict(conflict);
}
}
}
});
}
}
var __DEBUG_SHOW_CONSTRAINT = null;
// can become a method now.
function find_and_populate_conflicts(session_obj) {
if(__debug_conflict_calculate) {
console.log("populating conflict:", session_obj.title, session_obj.column_class_list);
}
var room_tag = null;
session_obj.reset_conflicts();
for(ccn in session_obj.column_class_list) {
var vertical_location = session_obj.column_class_list[ccn].column_tag;
var room_tag = session_obj.column_class_list[ccn].room_tag;
if(session_obj.constraints.conflict != null){
$.each(session_obj.constraints.conflict, function(i){
var conflict = session_obj.constraints.conflict[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
if(session_obj.constraints.conflic2 != null){
$.each(session_obj.constraints.conflic2, function(i){
var conflict = session_obj.constraints.conflic2[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
if(session_obj.constraints.conflic3 != null){
$.each(session_obj.constraints.conflic3, function(i){
var conflict = session_obj.constraints.conflic3[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
if(session_obj.theirconstraints.conflict != null){
$.each(session_obj.theirconstraints.conflict, function(i){
var conflict = session_obj.theirconstraints.conflict[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
if(session_obj.theirconstraints.conflic2 != null){
$.each(session_obj.theirconstraints.conflic2, function(i){
var conflict = session_obj.theirconstraints.conflic2[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
if(session_obj.theirconstraints.conflic3 != null){
$.each(session_obj.theirconstraints.conflic3, function(i){
var conflict = session_obj.theirconstraints.conflic3[i];
calculate_real_conflict(conflict, vertical_location, room_tag, session_obj);
});
}
/* bethere constraints are processed in another loop */
}
}
function show_non_conflicting_spots(ss_id){
var conflict_spots = []
$.each(conflict_classes, function(key){
conflict_spots.push(conflict_classes[key].session.slot_status_key);
});
var empty_slots = find_empty_slots();
conflict_spots.forEach(function(val){
empty_slots.forEach(function(s){
if(val == s.key){
}
});
});
}
function find_empty_slots(){
var empty_slots = [];
$.each(slot_status, function(key){
for(var i =0; i<slot_status[key].length; i++){
if(slot_status[key][i].empty == "True" || slot_status[key][i].empty == true){
var pos = { "index" :i, key:key } ;
empty_slots.push(pos);
}
}
});
return empty_slots;
}
// ++++++++++++++++++
// Slot Object
function slot(){
}
/*
check_delimiter(inp), where inp is a string.
returns char.
checks for what we should split a string by.
mainly we are checking for a '/' or '-' character
Maybe there is a js function for this. doing 'a' in "abcd" does not work.
*/
function check_delimiter(inp){
for(var i =0; i<inp.length; i++){
if(inp[i] == '/'){
return '/';
}
else if(inp[i] == '-'){
return '-';
}
}
return ' ';
}
/*
upperCaseWords(inp), where inp is a string.
returns string
turns the first letter of each word in a string to uppercase
a word is something considered be something defined by the function
check_delimiter(). ( '/' , '-' , ' ' )
*/
function upperCaseWords(inp){
var newStr = "";
var split = inp.split(check_delimiter(inp));
for(i=0; i<split.length; i++){
newStr = newStr+split[i][0].toUpperCase();
newStr = newStr+split[i].slice(1,split[i].length);
if(i+1 < split.length){ // so we don't get a extra space
newStr = newStr+" ";
}
}
return newStr;
}
var daysofweek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
// ++++++++++++++++++
// ColumnClass is an object that knows about columns, but also about
// columns + room (so it can identify a single slot, or a column of them)
function ColumnClass(room,date,time) {
this.room = room;
this.date = date;
this.time = time;
this.room_tag = this.room+"_"+this.date+"_"+this.time;
this.th_time = this.date+"-"+this.time;
this.column_tag = ".agenda-column-"+this.th_time;
this.th_tag = ".day_" + this.th_time;
};
// ++++++++++++++++++
// TimeSlot Object
//
// { "timeslot_id":"{{timeslot.id}}",
// "room" :"{{timeslot.location|slugify}}",
// "time" :"{{timeslot.time|date:'Hi' }}",
// "date" :"{{timeslot.time|date:'Y-m-d'}}",
// "domid" :"{{timeslot.js_identifier}}"}
function TimeSlot(){
this.timeslot_id = undefined;
this.room = undefined;
this.time = undefined;
this.date = undefined;
this.domid = undefined;
this.empty = true;
this.assignments = [];
this.following_timeslot_id = undefined;
this.unscheduled_box = false;
}
TimeSlot.prototype.initialize = function(json) {
for(var key in json) {
this[key]=json[key];
}
//console.log("timeslot processing: ", this.timeslot_id,
// this.room, this.date, this.time);
this.column_class=new ColumnClass(this.room, this.date, this.time);
this.day = new Date(this.date);
this.starttime = parseInt(this.time,10);
var t = this.day.getUTCDay();
if(this.room == "Unassigned"){
this.short_string = "Unassigned";
}
else{
this.short_string = daysofweek[t] + ", "+ this.time + ", " + this.room;
}
agenda_globals.timeslot_bydomid[this.domid] = this;
agenda_globals.timeslot_byid[this.timeslot_id] = this;
};
TimeSlot.prototype.title = function() {
return this.room + " "+this.date+" "+this.time;
};
TimeSlot.prototype.slot_title = function() {
return "id#"+this.timeslot_id+" dom:"+this.domid;
};
TimeSlot.prototype.mark_empty = function() {
if(agenda_globals.__debug_session_move) {
console.log("marking slot empty", this.domid);
$("#"+this.domid).html("empty");
}
this.empty = true;
};
TimeSlot.prototype.mark_occupied = function() {
if(agenda_globals.__debug_session_move) {
console.log("marking slot occupied", this.domid);
// if it was empty before, then clear it (might have word "empty" in it)
if(this.empty == true) {
$("#"+this.domid).html("");
}
}
this.empty = false;
};
TimeSlot.prototype.can_extend_right = function() {
if(this.following_timeslot == undefined) {
if(this.following_timeslot_id != undefined) {
this.following_timeslot = agenda_globals.timeslot_byid[this.following_timeslot_id];
}
}
if(this.following_timeslot == undefined) {
console.log("can_extend_right:",this.timeslot_id," no slot to check");
return false;
} else {
console.log("can_extend_right:",
this.slot_title()," for slot: ",
this.following_timeslot.slot_title(),
"is ",this.following_timeslot.empty);
return this.following_timeslot.empty;
}
};
function make_timeslot(json) {
var ts = new TimeSlot();
ts.initialize(json);
return ts;
}
/* feed this an array of timeslots */
function make_timeslots(json, status, jqXHR) {
$.each(json, function(index) {
var thing = json[index];
make_timeslot(thing);
});
}
function load_timeslots(href) {
if(agenda_globals.timeslot_promise == undefined) {
agenda_globals.timeslot_promise = $.Deferred();
var ts_promise = agenda_globals.timeslot_promise;
var ts = $.ajax(href);
ts.success(function(newobj, status, jqXHR) {
make_timeslots(newobj);
ts_promise.resolve(newobj);
console.log("finished timeslot promise");
});
}
return agenda_globals.timeslot_promise;
}
// ++++++++++++++++++
// ScheduledSlot Object
// SchedTimeSessAssignment is the DJANGO name for this object
// It represents a TimeSlot that can be assigned in this schedule.
// { "assignment_id": "{{s.id}}",
// "href: "{{s.href}}",
// "timeslot_id":"{{s.timeslot.id}}",
// "session_id" :"{{s.session.id}}",
// "extendedfrom_id" :refers to another schedtimesessassignment by ss.id
function ScheduledSlot(){
this.extendedfrom = undefined;
this.extendedto = undefined;
this.extendedfrom_id = false;
this.pinned = false;
}
ScheduledSlot.prototype.room = function() {
return this.timeslot.room;
};
ScheduledSlot.prototype.time = function() {
return this.timeslot.time;
};
ScheduledSlot.prototype.date = function() {
return this.timeslot.date;
};
ScheduledSlot.prototype.domid = function() {
return this.timeslot.domid;
};
ScheduledSlot.prototype.column_class = function() {
return this.timeslot.column_class;
};
ScheduledSlot.prototype.short_string = function() {
return this.timeslot.short_string;
};
ScheduledSlot.prototype.saveit = function() {
var myss = this;
stuffjson = new Object();
stuffjson.session_id = this.session_id;
stuffjson.timeslot_id = this.timeslot_id;
if(this.extendedfrom_id != undefined && this.extendedfrom_id != false) {
stuffjson.extendedfrom_id = this.extendedfrom_id;
}
var stuff = JSON.stringify(stuffjson, null, '\t');
var saveit = $.ajax(assignments_post_href,{
"content-type": "application/json",
"type": "POST",
"data": stuff,
});
// should do something on success and failure.
saveit.done(function(result, status, jqXHR) {
myss.initialize(result, "saveit");
var session = myss.session;
if(session != undefined) {
session.placed(myss.timeslot);
}
});
saveit.fail(function(jqXHR, textStatus) {
var xhr = JSON.parse(jqXHR.responseText);
alert("ERROR: " + xhr.error + "\nThe schedule will now reload.");
location.reload(true);
});
// return the promise, in case someone (tests!) needs to know when we are done.
return saveit;
};
ScheduledSlot.prototype.set_pinned = function(state, completefunc) {
var ss = this;
var pinned_struct = { "pinned" : state };
var pinned_update = $.ajax(this.href, {
"content-type": "application/json",
"type": "PUT",
"data": pinned_struct,
});
pinned_update.success(function(result, status, jqXHR) {
if(result.message != "valid") {
alert("Update of pinned failed");
return;
}
ss.pinned = state;
completefunc(this);
});
};
function remove_from_slot_status(domid, ss_id) {
var found_at;
if(agenda_globals.__debug_session_move) {
console.log("remove", domid, agenda_globals.slot_status[domid]);
}
if(agenda_globals.slot_status[domid] != undefined) {
$.each(agenda_globals.slot_status[domid], function(index, value) {
if(agenda_globals.__debug_session_move) {
console.log(" checking", index, value, ss_id);
}
if(value.assignment_id == ss_id) {
found_at = index;
return;
}
});
if(found_at != undefined) {
agenda_globals.slot_status[domid].splice(found_at, 1);
console.log("removed", found_at, agenda_globals.slot_status[domid]);
}
} else {
//console.log(" already empty");
}
};
ScheduledSlot.prototype.deleteit = function() {
var deleteit = $.ajax(this.href, {
"content-type": "application/json",
"type": "DELETE",
});
// now nuke self!
var me = this;
delete agenda_globals.slot_objs[this.assignment_id];
remove_from_slot_status(this.domid(), this.assignment_id);
return deleteit;
};
function update_if_not_undefined(old, newval) {
if(newval != undefined) {
return newval;
} else {
return old;
}
}
ScheduledSlot.prototype.make_unassigned = function() {
this.assignment_id = 0;
this.empty = true;
this.session_id = null;
this.room = "unassigned";
this.time = null;
this.date = null;
this.timeslot = new TimeSlot();
this.timeslot.initialize({"domid":"sortable-list"});
this.timeslot.unscheduled_box = true;
this.timeslot.short_string = "Unscheduled";
agenda_globals.slot_status[this.domid()]=[];
agenda_globals.slot_status[this.domid()].push(this);
agenda_globals.slot_objs[this.assignment_id] = this;
};
ScheduledSlot.prototype.real_initialize = function(json, extra) {
/* do not copy everything over */
this.pinned = update_if_not_undefined(this.pinned, json.pinned);
this.assignment_id = update_if_not_undefined(this.assignment_id, json.assignment_id);
this.session_id = update_if_not_undefined(this.session_id, json.session_id);
this.timeslot_id = update_if_not_undefined(this.timeslot_id, json.timeslot_id);
this.href = update_if_not_undefined(this.href, json.href);
this.extendedfrom_id = update_if_not_undefined(this.extendedfrom_id, json.extendedfrom_id);
//console.log("timeslot_id", this.timeslot_id);
this.timeslot = agenda_globals.timeslot_byid[this.timeslot_id];
if(this.timeslot != undefined && this.session_id != undefined) {
this.timeslot.mark_occupied();
}
if(this.session_id != undefined) {
this.session = agenda_globals.meeting_objs[this.session_id];
}
// translate Python booleans to JS.
if(this.pinned == "True") {
this.pinned = true;
} else {
this.pinned = false;
}
// timeslot should never be null, but if there is old/flaky
// data it could happen, so guard against it.
if(this.timeslot != undefined) {
// do not include in data structures if session_id is nil
// the key so two sessions in the same timeslot
if(agenda_globals.slot_status[this.domid()] == null) {
agenda_globals.slot_status[this.domid()]=[];
}
if(this.session_id != undefined) {
// remove any old duplicate that might exist.
remove_from_slot_status(this.domid(), this.assignment_id);
if(agenda_globals.__debug_session_move) {
console.log(extra, "adding to slot_status", this.domid());
}
agenda_globals.slot_status[this.domid()].push(this);
//console.log("filling slot_objs", this.assignment_id);
}
}
agenda_globals.slot_objs[this.assignment_id] = this;
};
ScheduledSlot.prototype.initialize = ScheduledSlot.prototype.real_initialize;
function load_assignments(ts_promise, session_promise, href) {
if(agenda_globals.assignment_promise == undefined) {
agenda_globals.assignment_promise = $.Deferred();
var ss = $.ajax(href);
var ss_loaded = $.when(ss,ts_promise,session_promise);
ss_loaded.done(function(result, status, jqXHR) {
console.log("finished ss promise");
newobj = result[0]
$.each(newobj, function(index) {
one = newobj[index];
//console.log("ss has:", one);
make_ss(one);
});
agenda_globals.assignment_promise.resolve(newobj);
});
}
return agenda_globals.assignment_promise;
}
ScheduledSlot.prototype.connect_to_timeslot_session = function() {
if(this.timeslot == undefined) {
if(this.timeslot_id != undefined) {
this.timeslot = agenda_globals.timeslot_byid[this.timeslot_id];
} else {
/* must be the unassigned one?! */
this.timeslot = new TimeSlot();
this.timeslot.domid = "sortable-list";
}
}
/* session could be hooked up, but it is now always session() */
};
ScheduledSlot.prototype.session = function() {
if(this.session_id != undefined) {
return agenda_globals.meeting_objs[this.session_id];
} else {
console.log("ss id:", this.assignment_id, "timeslot:", this.timeslot_id, this.timeslot.title(), "has null session");
return undefined;
}
};
ScheduledSlot.prototype.slot_title = function() {
return "id#"+this.assignment_id+" dom:"+this.domid();
};
function make_ss(json) {
var ss = new ScheduledSlot();
ss.initialize(json, "make_ss");
return ss;
}
// ++++++++++++++++++
// Session Objects
//
// initialized by loading a json from /meeting/XX/sessions.json, return JSON that looks like:
//
// {"title" : "{{ s.short_name }}",
// "description":"{{ s.group.name }}",
// "special_request": "{{ s.special_request_token }}",
// "session_id":"{{s.id}}",
// "owner": "{{s.owner.owner}}",
// "area":"{{s.group.parent.acronym|upper}}",
// "duration":"{{s.requested_duration.seconds|durationFormat}}"});
//
function Session() {
this.constraints = {};
this.theirconstraints = {};
this.constraint_load_andthen_list = [];
this.constraints_loaded = false;
this.last_timeslot_id = null;
this.slot_status_key = null;
this.href = false;
this.group = undefined;
this.column_class_list = [];
this.loaded = undefined;
this.area = "noarea";
this.special_request = "";
this.conflicted = false;
this.conflicted_direction = {};
this.theirconflicted = false;
this.double_wide = false;
this.attendees = undefined;
}
function session_obj(json) {
session = new Session();
for(var key in json) {
//console.log("copying", key, "value: ", json[key]);
if(json[key] != undefined && json[key] != "") {
session[key]=json[key];
}
}
// dict will not pass .length > 0 above.
session.group = json.group;
if(session.requested_duration == undefined) {
session.requested_duration = session.duration;
}
// make it a number.
session.attendees = parseInt(session.attendees);
session.ogroup = session.group;
if(session.group != undefined) {
/* it has an inline group object, intern it, and redirect to interned object */
//console.log(session.title, "using embedded group: ",
// session.group.acronym, session.group.href, session.group);
session.group = load_group_from_json(session.group);
session.group_href = session.group.href;
//console.log(session.title, "2 using embedded group: ",
// session.group.acronym, session.group.href, session.group);
} else if(session.group_href != undefined) {
console.log("session ",session.session_id,
"has no embedded group, load by href", session.group_href);
session.group = find_group_by_href(session.group_href, "session_load");
} else {
// bogus
session.group_href = site_base_url+'/group/'+session.title+".json";
}
// keep a list of sessions by name
// this is mostly used for debug purposes only.
if(agenda_globals.sessions_objs[session.title] == undefined) {
agenda_globals.sessions_objs[session.title] = [];
}
agenda_globals.sessions_objs[session.title].push(session); // an array since there can be more than one session/wg
agenda_globals.meeting_objs[session.session_id] = session;
return session;
}
/* feed this an array of sessions */
function make_sessions(json, status, jqXHR) {
$.each(json, function(index) {
var thing = json[index];
session_obj(thing);
});
}
function load_sessions(href) {
if(agenda_globals.session_promise == undefined) {
agenda_globals.session_promise = $.Deferred();
var ss = $.ajax(href);
ss.success(function(newobj, status, jqXHR) {
console.log("finished session promise");
make_sessions(newobj);
agenda_globals.session_promise.resolve(newobj);
});
}
return agenda_globals.session_promise;
}
function count_sessions() {
$.each(agenda_globals.sessions_objs, function(title) {
//console.log("title", title, this);
var lastone = null;
var sessions = agenda_globals.sessions_objs[title];
var num_sessions = sessions.length;
$.each(sessions, function(index) {
//console.log("session", index, this);
this.number = index; // a number
this.maxNum = num_sessions;
this.prev_session = lastone;
this.next_session = null;
if(index < num_sessions) {
this.next_session = sessions[index+1];
}
lastone = this;
});
});
}
// augument to jQuery.getJSON( url, [data], [callback] )
Session.prototype.load_session_obj = function(andthen, arg) {
session = this;
if(this.loaded == undefined) {
start_spin();
this.loaded = $.ajax(this.href);
}
this.loaded.success(function(newobj, status, jqXHR) {
last_json_reply = newobj;
$.extend(session, newobj);
if(andthen != undefined) {
andthen(session, true, arg);
}
stop_spin();
});
this.loaded.error(function(jqXHR, textStatus, errorThrown ) {
console.log("exception: ",textStatus,errorThrown);
if(andthen != undefined) {
andthen(session, false, arg);
}
stop_spin();
});
};
Session.prototype.find_responsible_ad = function() {
var session = this;
//console.log("session",this.title, this.session_id,"looking for ad",this.group.ad_href);
if(this.group && this.group.ad_href) {
find_person_by_href(session.group.ad_href).done(function(ad) {
//console.log("session",session.session_id,"found ", ad);
session.responsible_ad = ad;
});
}
};
Session.prototype.element = function() {
return $("#session_"+this.session_id);
};
Session.prototype.personconflict_element = function() {
return this.element().parent().find(".personconflict");
};
Session.prototype.selectit = function() {
clear_all_selections();
// mark self as selected
if(this.group != undefined) {
$("." + this.group.acronym).addClass("same_group");
}
this.element().removeClass("save_group");
this.element().addClass("selected_group");
};
Session.prototype.unselectit = function() {
clear_all_selections();
};
Session.prototype.on_bucket_list = function() {
this.is_placed = false;
this.column_class_list = [];
this.element().parent("div").addClass("meeting_box_bucket_list");
};
Session.prototype.placed = function(where, forceslot, assignment) {
this.is_placed = true;
// forceslot is set on a move, but unset on initial placement,
// as placed might be called more than once for a double slot session.
if(forceslot || this.slot==undefined) {
this.slot = where;
this.assignment = assignment;
/* we can not mark old slot as empty, because it
might have multiple sessions in it.
we can do the opposite: mark it was not empty when we fill it.
*/
if(where != undefined) {
where.empty = false;
}
}
if(where != undefined) {
this.add_column_class(where.column_class);
}
//console.log("session:",session.title, "column_class", ssid.column_class());
this.element().parent("div").removeClass("meeting_box_bucket_list");
this.pinned = where.pinned;
};
Session.prototype.populate_event = function(js_room_id) {
var eTemplate = this.event_template()
insert_cell(js_room_id, eTemplate, false);
};
Session.prototype.repopulate_event = function(js_room_id) {
var eTemplate = this.event_template()
insert_cell(js_room_id, eTemplate, true);
this.display_conflict();
};
Session.prototype.visible_title = function() {
return this.special_request + this.title;
};
var _conflict_debug = false;
Session.prototype.mark_conflict = function(value) {
this.conflicted = value;
};
Session.prototype.add_conflict = function(conflict) {
this.conflicted = true;
if (this.conflicted_direction==undefined) {
this.conflicted_direction={};
}
this.conflicted_direction[conflict.direction] = true;
if (this.highest_conflict==undefined) {
this.highest_conflict={};
}
if(this.highest_conflict[conflict.direction]==undefined) {
this.highest_conflict[conflict.direction] = conflict;
} else {
var oldhighest = this.highest_conflict[conflict.direction];
this.highest_conflict[conflict.direction] = this.highest_conflict[conflict.direction].conflict_compare(conflict);
if(_conflict_debug) {
console.log("add conflict for", this.title,
oldhighest.conflict_type, ">?", conflict.conflict_type,
"=", this.highest_conflict[conflict.direction].conflict_type);
}
}
if (this.conflict_level==undefined){
this.conflict_level={};
}
this.conflict_level[conflict.direction] = this.highest_conflict[conflict.direction].conflict_type;
};
Session.prototype.clear_conflict = function() {
this.conflicted = false;
};
Session.prototype.clear_all_conflicts = function(old_column_classes) {
var session_obj = this;
this.clear_conflict();
if(old_column_classes != undefined) {
$.each(session_obj.constraints.bethere, function(i) {
var conflict = session_obj.constraints.bethere[i];
var person = conflict.person;
person.clear_session(session_obj, old_column_classes);
});
}
};
Session.prototype.show_conflict = function() {
if(_conflict_debug) {
console.log("showing conflict for", this.title, this.conflict_level['ours'],this.conflict_level['theirs']);
}
var display = { 'conflict':'1' , 'conflic2':'2' , 'conflic3':'3' };
if (this.conflicted) {
if ('ours' in this.conflict_level) {
this.element().find('.ourconflicts').text('->'+display[this.conflict_level.ours]);
}
if ('theirs' in this.conflict_level) {
this.element().find('.theirconflicts').text(display[this.conflict_level.theirs]+'->');
}
}
};
Session.prototype.hide_conflict = function() {
if(_conflict_debug) {
console.log("removing conflict for", this.title);
}
this.element().find('.ourconflicts').text('');
this.element().find('.theirconflicts').text('');
};
Session.prototype.display_conflict = function() {
if(this.conflicted || this.theirconflicted) {
this.show_conflict();
} else {
this.hide_conflict();
}
};
Session.prototype.reset_conflicts = function() {
this.conflict_level = undefined;
this.highest_conflict = undefined;
this.conflicted = false;
this.conflicted_direction = undefined;
this.theirconflict_level = undefined;
this.highest_theirconflict = undefined;
this.theirconflicted = false;
};
Session.prototype.show_personconflict = function() {
if(_conflict_debug) {
console.log("showing person conflict for", this.title, this.conflict_level.ours);
}
this.personconflict_element().removeClass("hidepersonconflict");
this.personconflict_element().addClass("showpersonconflict");
};
Session.prototype.hide_personconflict = function() {
if(_conflict_debug) {
console.log("removing person conflict for", this.title);
}
this.personconflict_element().addClass("hidepersonconflict");
this.personconflict_element().removeClass("showpersonconflict");
};
Session.prototype.display_personconflict = function() {
if(this.person_conflicted) {
this.show_personconflict();
} else {
this.hide_personconflict();
}
};
Session.prototype.add_personconflict = function(conflict) {
this.person_conflicted = true;
};
Session.prototype.examine_people_conflicts = function() {
/*
* the scan for people conflicts has to be done after the fill_in_constraints
* because we don't know which sessions the people will need to attend until
* all the constraints have been examined.
*/
var session_obj = this;
// reset people conflicts.
session_obj.person_conflicted = false;
for(ccn in session_obj.column_class_list) {
var vertical_location = session_obj.column_class_list[ccn].column_tag;
var room_tag = session_obj.column_class_list[ccn].room_tag;
if(session_obj.constraints.bethere != null) {
if(_person_bethere_debug) {
console.log("examining bethere constraints for", session_obj.title);
}
$.each(session_obj.constraints.bethere, function(i) {
var conflict = session_obj.constraints.bethere[i];
find_person_by_href(conflict.person_href).done(function(person) {
conflict.person = person;
if(_person_bethere_debug) {
console.log("examining", person.ascii," bethere constraints for", session_obj.title);
}
if(person.conflicted_time(vertical_location)) {
session_obj.add_personconflict(conflict);
}
});
});
}
}
}
Session.prototype.area_scheme = function() {
return this.area.toUpperCase() + "-scheme";
};
Session.prototype.is_bof = function() {
return this.bof == "True";
}
Session.prototype.wg_scheme = function() {
if(this.is_bof()) {
return "bof_style";
} else {
return "wg_style";
}
};
Session.prototype.add_column_class = function(column_class) {
if(__column_class_debug) {
console.log("adding:",column_class, "to ", this.title);
}
this.column_class_list.push(column_class);
};
var _LAST_MOVED_OLD;
var _LAST_MOVED_NEW;
// timeslot_list is a list of slots where the session has been located.
// bucket_list is a boolean.
Session.prototype.update_column_classes = function(timeslot_list, bucket_list) {
// COLUMN CLASSES MUST BE A LIST because of multiple slot use
console.log("updating column_classes for ", this.title);
var old_column_classes = this.column_class_list;
if(old_column_classes.length == 0) {
console.log("old column class was undefined for session:", session.title);
old_column_classes = [new ColumnClass()];
}
// zero out list.
this.column_class_list = [];
var new_column_tag = "none";
if(bucket_list) {
this.on_bucket_list();
} else {
for(tsn in timeslot_list) {
var ts = timeslot_list[tsn];
console.log("timeslot_list", tsn, ts);
this.add_column_class(ts.column_class);
}
new_column_tag = this.column_class_list[0].column_tag;
}
var old_column_class_name = "none";
if(old_column_classes != undefined &&
old_column_classes[0] != undefined) {
old_colum_class_name = old_column_classes[0].column_tag;
}
console.log("setting column_class for ",this.title," to ",
new_column_tag, "was: ", old_column_class_name);
console.log("unset conflict for ",this.title," is ", this.conflicted);
_LAST_MOVED_OLD = old_column_classes;
_LAST_MOVED_NEW = this.column_class_list;
this.group.del_column_classes(old_column_classes);
this.group.add_column_classes(this.column_class_list);
recalculate_conflicts_for_session(this, old_column_classes, this.column_class_list);
};
// utility/debug function, draws all events.
function update_all_templates() {
for(key in agenda_globals.meeting_objs) {
session = agenda_globals.meeting_objs[key];
var slot = session.slot_status_key;
if(slot != null) {
session.repopulate_event(slot);
}
}
}
Session.prototype.event_template = function() {
// the extra div is present so that the table can have a border which does not
// affect the total height of the box. The border otherwise screws up the height,
// causing things to the right to avoid this box.
var area_mark = "";
if(this.responsible_ad != undefined) {
area_mark = this.responsible_ad.area_mark;
if(area_mark == undefined) {
// This doesn't seem to do the right thing
// area_mark = "ad:" + this.responsible_ad.href;
area_mark = "";
}
}
var bucket_list_style = "meeting_box_bucket_list"
if(this.is_placed) {
bucket_list_style = "";
area_mark = ""; /* no mark for unplaced items: it goes to the wrong place */
}
if(this.double_wide) {
bucket_list_style = bucket_list_style + " meeting_box_double";
}
var pinned = "";
if(this.pinned) {
bucket_list_style = bucket_list_style + " meeting_box_pinned";
pinned="<td class=\"pinned-tack\">P</td>";
}
var groupacronym = "nogroup";
if(this.group != undefined) {
groupacronym = this.group.acronym;
}
//console.log("acronym", groupacronym, this.group.acronym, this.visible_title());
var durationstring="";
if (this.requested_duration!="0.0") {
durationstring = " ("+this.requested_duration+")"
}
// see comment in ietf.ccs, and
// http://stackoverflow.com/questions/5148041/does-firefox-support-position-relative-on-table-elements
return "<div class='meeting_box_container' session_id=\""+this.session_id+"\"><div class=\"meeting_box "+bucket_list_style+"\" ><table class='meeting_event "+
groupacronym +
"' id='session_"+
this.session_id+
"' session_id=\""+this.session_id+"\"" +
"><tr id='meeting_event_title'><td class=\"theirconflicts\"></td><th class='"+
this.wg_scheme()+" "+
this.area_scheme() +" meeting_obj'>"+
this.visible_title()+
"<span>" + durationstring + "</span>" +
"</th><td class=\"ourconflicts\"></td>"+pinned+"</tr></table>"+ area_mark +"</div></div>";
};
function andthen_alert(object, result, arg) {
alert("result: "+result+" on obj: "+object);
};
Session.prototype.generate_info_table = function() {
$("#info_grp").html(name_select_html);
if(this.is_bof()) {
$("#grp_type").html("BOF");
} else {
$("#grp_type").html("WG");
}
$("#info_name_select").val($("#info_name_select_option_"+this.session_id).val());
if(this.description.length > 33) {
$("#info_name").html("<span title=\""+this.description+"\">"+this.description.substring(0,35)+"...</span>");
} else {
$("#info_name").html(this.description);
}
$("#info_area").html("<span class='"+this.area.toUpperCase()+"-scheme'>"+this.area+"</span>");
$("#info_duration").html(this.requested_duration);
if(this.attendees == "None") {
$("#info_capacity").text("size unknown");
} else {
$("#info_capacity").text(this.attendees + " people");
}
if(!read_only) {
$("#info_location").html(generate_select_box()+"<button id='info_location_set'>set</button>");
}
var special_requests_text = '';
if(this.joint_with_groups) {
special_requests_text += 'Joint session with ' + this.joint_with_groups.join(', ') + '. ';
}
if(this.constraints.wg_adjacent) {
for (var target_href in this.constraints.wg_adjacent) {
if (this.constraints.wg_adjacent.hasOwnProperty(target_href)) {
special_requests_text += 'Schedule adjacent with ' + this.constraints.wg_adjacent[target_href].othergroup.acronym + '. ';
}
}
}
if(this.constraints.time_relation) {
special_requests_text += this.constraints.time_relation.time_relation.time_relation_display + '. ';
}
if(this.constraints.timerange) {
special_requests_text += this.constraints.timerange.timerange.timeranges_display + '. ';
}
if("comments" in this && this.comments.length > 0 && this.comments != "None") {
special_requests_text += this.comments;
} else {
special_requests_text += "Special requests: None";
}
$("#special_requests").text(special_requests_text);
this.selectit();
if(this.slot != undefined) {
ss = this.slot;
if(ss.timeslot_id == null){
$("#info_location_select").val(agenda_globals.meeting_objs[ss.assignment_id]);
}else{
$("#info_location_select").val(ss.timeslot_id); // ***
}
$("#info_location_select").val($("#info_location_select_option_"+ss.timeslot_id).val());
}
//console.log("ad for session",this.session_id,"is",this.responsible_ad);
if(this.responsible_ad) {
this.responsible_ad.populate_responsible_ad();
}
$("#info_requestedby").html(this.requested_by +" ("+this.requested_time+")");
listeners();
};
function load_all_groups() {
for(key in agenda_globals.meeting_objs) {
session = agenda_globals.meeting_objs[key];
session.group = find_group_by_href(session.group_href, "load all");
}
}
var __DEBUG_THIS_SLOT;
Session.prototype.retrieve_constraints_by_session = function() {
__DEBUG_THIS_SLOT = this;
//console.log("4 retrieve loaded:", this.title, this.constraints_loaded, "loading:", this.constraints_loading);
if(this.constraints_promise != undefined) {
return this.constraints_promise;
}
var session_obj = this;
var href = meeting_base_url+'/session/'+session_obj.session_id+"/constraints.json";
this.constraints_promise = $.ajax(href);
this.constraints_loading = true;
this.constraints_promise.success(function(newobj, status, jq) {
session_obj.fill_in_constraints(newobj);
session_obj.constraints_loaded = true;
session_obj.constraints_loading = false;
find_and_populate_conflicts(session_obj);
});
return this.constraints_promise;
};
var __verbose_person_conflicts = false;
Session.prototype.calculate_bethere = function() {
var session_obj = this;
if("bethere" in this.constraints) {
$.each(this.constraints["bethere"], function(index) {
var bethere = session_obj.constraints["bethere"][index];
find_person_by_href(bethere.person_href).done(function(person) {
if(__verbose_person_conflicts) {
console.log("person",person.ascii,"attends session",session_obj.group.acronym);
}
person.attend_session(session_obj);
});
});
}
};
Session.prototype.fill_in_constraints = function(constraint_list) {
var session_obj = this;
$.each(constraint_list, function(key){
thing = constraint_list[key];
session_obj.add_constraint_obj(thing);
});
// here we can sort the constraints by group name.
// make a single list. this.constraints is not an array, can not use concat.
this.conflicts = [];
if("conflict" in this.constraints) {
$.each(this.constraints["conflict"], function(index) {
session_obj.conflicts.push(session_obj.constraints["conflict"][index]);
});
}
if("conflic2" in this.constraints) {
$.each(this.constraints["conflic2"], function(index) {
session_obj.conflicts.push(session_obj.constraints["conflic2"][index]);
});
}
if("conflic3" in this.constraints) {
$.each(this.constraints["conflic3"], function(index) {
session_obj.conflicts.push(session_obj.constraints["conflic3"][index]);
});
}
if("conflict" in this.theirconstraints) {
$.each(this.theirconstraints["conflict"], function(index) {
session_obj.conflicts.push(session_obj.theirconstraints["conflict"][index]);
});
}
if("conflic2" in this.theirconstraints) {
$.each(this.theirconstraints["conflic2"], function(index) {
session_obj.conflicts.push(session_obj.theirconstraints["conflic2"][index]);
});
}
if("conflic3" in this.theirconstraints) {
$.each(this.theirconstraints["conflic3"], function(index) {
session_obj.conflicts.push(session_obj.theirconstraints["conflic3"][index]);
});
}
this.calculate_bethere();
this.conflicts = sort_conflict_list(this.conflicts)
};
// ++++++++++++++++++
// Group Objects
function Group() {
this.andthen_list = []; /* should be removed, or replaced with promise */
this.all_sessions = [];
}
Group.prototype.loaded_andthen = function() {
me = this;
$.each(this.andthen_list, function(index, andthen) {
andthen(me);
});
this.andthen_list = [];
};
Group.prototype.load_group_obj = function(andthen) {
//console.log("group ",this.href);
var group_obj = this;
if(!this.loaded && !this.loading) {
this.loading = true;
this.andthen_list.push(andthen);
$.ajax(this.href,
{
success: function(newobj, status, jqXHR) {
if(newobj) {
$.extend(group_obj, newobj);
group_obj.loaded = true;
}
group_obj.loading = false;
group_obj.loaded_andthen();
},
error: function(jqXHR, textStatus, errorThrown ) {
console.log("error loading ",group_obj.href," textStatus: ", textStatus,errorThrown);
group_obj.loading = false;
group_obj.loaded = true; // white lie
group_obj.load_error = true;
}
});
} else {
if(!this.loaded) {
// queue this continuation for later.
this.andthen_list.push(andthen);
} else {
this.loading = false;
andthen(group_obj);
}
}
}
Group.prototype.add_session = function(session) {
if(this.all_sessions == undefined) {
this.all_sessions = [];
}
this.all_sessions.push(session);
};
var __DEBUG_GROUP_COLUMN_CLASSES = false;
Group.prototype.add_column_class = function(column_class) {
if(this.column_class_list == undefined) {
this.column_class_list = [];
}
if(__DEBUG_GROUP_COLUMN_CLASSES) {
console.log("group",this.acronym,"adding column_class",column_class);
}
this.column_class_list.push(column_class);
};
Group.prototype.del_column_class = function(column_class) {
if(__DEBUG_GROUP_COLUMN_CLASSES) {
console.log("group",this.acronym,"del column_class",column_class);
}
for(n in this.column_class_list) {
if(this.column_class_list[n] == column_class) {
this.column_class_list.splice(n,1);
}
}
};
Group.prototype.add_column_classes = function(column_class_list) {
for(ccn in column_class_list) {
cc = column_class_list[ccn];
this.add_column_class(cc);
}
};
Group.prototype.del_column_classes = function(column_class_list) {
for(ccn in column_class_list) {
cc = column_class_list[ccn];
this.del_column_class(cc);
}
};
var __debug_group_load = false;
function create_group_by_href(href) {
if(agenda_globals.group_objs[href] == undefined) {
agenda_globals.group_objs[href]=new Group();
var g = agenda_globals.group_objs[href];
if(__debug_group_load) {
console.log("creating new group for", href);
}
g.loaded = false;
g.loading= false;
}
return agenda_globals.group_objs[href];
}
function load_group_by_href(href) {
var g = agenda_globals.group_objs[href];
if(!g.loaded) {
g.href = href;
if(__debug_group_load) {
console.log("loading group href", href);
}
g.load_group_obj(function() {});
}
return g;
}
// takes a json that has at least a "href" member,
// and finds or creates the object. Any additional
// fields are added to the group object, and the group
// is marked loaded. The resulting group object is returned.
function load_group_from_json(json) {
var g = create_group_by_href(json.href);
for(var key in json) {
if(json[key].length > 0) {
g[key]=json[key];
}
}
g.loaded = true;
g.loading= false;
return g;
}
var group_references = 0;
var group_demand_loads = 0;
function find_group_by_href(href, msg) {
group_references++;
var g=agenda_globals.group_objs[href];
if(g == undefined) {
group_demand_loads++;
if(__debug_group_load) {
console.log("loading",href,"because of",msg);
}
g = create_group_by_href(href);
load_group_by_href(href);
}
//console.log("finding group by ", href, "gives: ", g);
return g;
}
// ++++++++++++++++++
// Constraint Objects
function Constraint() {
// fields: (see ietf.meeting.models Constraint.json_dict)
//
// -constraint_id
// -href
// -name -- really the conflict_type, which will get filled in
// -person/_href
// -source/_href
// -target/_href
// -meeting/_href
//
}
var conflict_classes = {};
function clear_conflict_classes() {
// remove all conflict boxes from before
$(".show_conflict_specific_box").removeClass("show_conflict_specific_box");
$(".show_conflic2_specific_box").removeClass("show_conflic2_specific_box");
$(".show_conflic3_specific_box").removeClass("show_conflic3_specific_box");
// reset all column headings
$(".show_conflict_view_highlight").removeClass("show_conflict_view_highlight");
}
function find_conflict(domid) {
return conflict_classes[domid];
}
Constraint.prototype.column_class_list = function() {
return this.othergroup.column_class_list;
};
Constraint.prototype.conflict1P = function() {
return (this.conflict_type == "conflict")
};
Constraint.prototype.conflict2P = function() {
return (this.conflict_type == "conflic2")
};
Constraint.prototype.conflict3P = function() {
return (this.conflict_type == "conflic3")
};
Constraint.prototype.conflict_groupP = function() {
return (this.conflict_type == "conflict" ||
this.conflict_type == "conflic2" ||
this.conflict_type == "conflic3");
};
Constraint.prototype.conflict_peopleP = function() {
return (this.conflict_type == "bethere")
};
Constraint.prototype.conflict_compare = function(oflict) {
if(this.conflict_peopleP()) {
return oflict;
}
if(this.conflict1P()) {
/* "conflict" is highest, return it. */
return this;
}
if(this.conflict2P() && oflict.conflict3P()) {
/* "conflic2" > "conflic3" */
return this;
}
/* self > 2, so otype would win */
return oflict;
};
// red is arbitrary here... There should be multiple shades of red for
// multiple types of conflicts.
var __CONSTRAINT_DEBUG = null;
var __column_class_debug = false;
// one used to get here by having the conflict boxes enabled/disabled, but they were
// removed from the UI.
// when a session is selected, the conflict boxes are filled in,
// and then they are all clicked in order to highlight everything.
Constraint.prototype.show_conflict_view = function() {
classes=this.column_class_list();
if(classes == undefined) {
classes = []
}
//console.log("show_conflict_view", this);
__CONSTRAINT_DEBUG = this;
if(__column_class_debug) {
console.log("show conflict", this.href, "classes", classes.length, this);
}
// this highlights the column headings of the sessions that conflict.
for(ccn in classes) {
var cc = classes[ccn]; // cc is a ColumnClass now
if(cc != undefined) {
/* this extracts the day from this structure */
var th_tag = cc.th_tag;
if(__column_class_debug) {
console.log("add conflict for column_class", this.session.title, th_tag);
}
$(th_tag).addClass("show_conflict_view_highlight");
} else {
console.log("cc is undefined for ccn:",ccn);
}
}
// this highlights the conflicts themselves
//console.log("make box", this.thisgroup.href);
sessions = this.othergroup.all_sessions
// set class to like: .show_conflict_specific_box
conflict_class = "show_"+this.conflict_type+"_specific_box";
if(sessions) {
$.each(sessions, function(key) {
//console.log("2 make box", key);
this.element().addClass(conflict_class);
});
}
//console.log("viewed", this.thisgroup.href);
};
Constraint.prototype.populate_conflict_classes = function() {
// this is used for the red square highlighting.
var checkbox_id = "conflict_"+this.dom_id;
conflict_classes[checkbox_id] = this;
};
// Made dead by change to how the group view is built out
//Constraint.prototype.build_group_conflict_view = function() {
//
// var display = { 'conflict':'1' , 'conflic2':'2' , 'conflic3':'3' };
//
// // this is used for the red square highlighting.
// var checkbox_id = "conflict_"+this.dom_id;
// conflict_classes[checkbox_id] = this;
//
// build = "<div id='"+this.dom_id+"'>";
// if (this.direction=='theirs') {
// build += display[this.conflict_type]+"->";
// }
// build += this.othergroup_name;
// if (this.direction=='ours') {
// build += "->"+display[this.conflict_type];
// }
// build += "</div>";
//
// return build
//
//};
Constraint.prototype.build_people_conflict_view = function() {
var area_mark = "";
if(this.person != undefined && this.person.area_mark_basic != undefined) {
area_mark = this.person.area_mark_basic;
}
return "<div class='conflict our-"+this.conflict_type+"' id='"+this.dom_id+
"'>"+area_mark+"</div>";
};
Constraint.prototype.build_othername = function() {
if(this.othergroup.load_error) {
console.log("request for unloaded group: ",this.othergroup.href);
var patt = /.*\/group\//; // ugly assumption about href structure.
var base = this.othergroup.href.replace(patt,"")
this.othergroup_name = base.replace(".json","")
} else {
this.othergroup_name = this.othergroup.acronym;
}
};
// subclasses would make some sense here.
Constraint.prototype.conflict_view = function() {
this.dom_id = "constraint_"+this.constraint_id;
if(this.conflict_peopleP()) {
return this.build_people_conflict_view();
}
else {
// This function is currently never called for this case
console.log("!! unexpected conflict_view for", this.href);
//this.build_othername();
//return this.build_group_conflict_view();
}
};
var _constraint_load_debug = false;
// SESSION CONFLICT OBJECTS
// take an object and add attributes so that it becomes a session_conflict_obj.
// note that constraints are duplicated: each session has both incoming and outgoing constraints added.
Session.prototype.add_constraint_obj = function(obj) {
// turn this into a Constraint object
// can not print or JSONify these on ff as this has cyclic references. Chrome can.
//console.log("session: ", this);
//console.log("add_constraint: ",obj.constraint_id, obj.name);
obj2 = new Constraint();
$.extend(obj2, obj);
obj = obj2;
obj.session = this;
var listname = obj.name;
obj.conflict_type = listname;
if(this.constraints[listname]==undefined) {
this.constraints[listname]={};
}
if(this.theirconstraints[listname]==undefined) {
this.theirconstraints[listname]={};
}
if(listname == "bethere") {
//console.log("bethere constraint: ", obj);
var person_href = obj.person_href;
var session = this;
this.constraints[listname][person_href]=obj;
find_person_by_href(person_href).done(function(person) {
if(_constraint_load_debug) {
console.log("recorded bethere constraint: ",person.ascii,"for group",session.group.acronym);
}
obj.person = person;
});
} else {
// must be conflic*, timerange, time_relation or wg_adjacent
var ogroupname;
if(obj.source_href == this.group_href) {
obj.thisgroup = this.group;
obj.othergroup = find_group_by_href(obj.target_href, "constraint src"+obj.href);
obj.direction = 'ours';
if (obj.target_href) {
ogroupname = obj.target_href;
} else {
ogroupname = obj.name;
}
if(this.constraints[listname][ogroupname]) {
console.log("Found multiple instances of",this.group_href,listname,ogroupname);
}
this.constraints[listname][ogroupname] = obj
} else {
obj.thisgroup = this.group;
obj.othergroup = find_group_by_href(obj.source_href, "constraint dst"+obj.href);
obj.direction = 'theirs';
ogroupname = obj.source_href;
if(this.theirconstraints[listname][ogroupname]) {
console.log("Found multiple instances of",ogroupname,listname,this.group_href);
}
this.theirconstraints[listname][ogroupname] = obj
}
}
};
function constraint_compare(a, b)
{
if(a==undefined || a.othergroup == undefined) {
return -1;
}
if(b==undefined || b.othergroup == undefined) {
return 1;
}
return (a.othergroup.href > b.othergroup.href ? 1 : -1);
}
function sort_conflict_list(things) {
var keys = Object.keys(things);
var keys1 = keys.sort(function(a,b) {
return constraint_compare(things[a],things[b]);
});
var newlist = [];
for(i=0; i<keys1.length; i++) {
var key = keys1[i];
newlist[i] = things[key];
}
return newlist;
}
// ++++++++++++++
// Person Objects
function Person() {
// fields: (see ietf.person.models Person.json_dict)
//
//
}
var all_people = {};
// this should be done completely with promises, but
// one can't use the promise returned by $.ajax() directly,
// because the object it returns does not seem to persist.
// So, one has to create a new persistent object.
// This returns a promise that will receive the person object.
function find_person_by_href(href) {
// first, look and see if the a promise for this href
// already.
var deferal;
if(!(href in all_people)) {
deferal = $.Deferred();
all_people[href]= deferal;
var lookup = $.ajax(href);
lookup.success(function(newobj, status, jqXHR) {
person = new Person();
$.extend(person, newobj);
person.loaded = true;
deferal.resolve(person);
});
} else {
deferal = all_people[href];
}
// or should this be deferal.promise()?
return deferal.promise();
}
var area_result;
// this function creates a unique per-area director mark
function mark_area_directors(directorpromises) {
$.each(area_directors, function(areaname) {
var adnum = 1;
$.each(area_directors[areaname], function(key) {
var thisad = adnum;
directorpromises.push(this);
this.done(function(person) {
person.make_area_mark(areaname, thisad);
person.marked = true;
});
adnum++;
});
});
return directorpromises;
}
Person.prototype.make_area_mark = function(areaname, adnum) {
this.area_mark = "<span title=\""+areaname+" "+this.name+"\" class=\" director-rightup\">";
this.area_mark += "<span class=\"personconflict hidepersonconflict\">AD</span>";
this.area_mark += "<span class=\"director-mark-" + areaname.toUpperCase() + " director-mark\">";
this.area_mark += adnum;
this.area_mark += "</span></span>";
this.area_mark_basic = "<span title=\""+areaname+" "+this.name+"\" class=\"director-mark-" + areaname.toUpperCase() + " director-mark director-right\">";
this.area_mark_basic += adnum;
this.area_mark_basic += "</span>";
};
Person.prototype.populate_responsible_ad = function() {
var area_mark = "";
if(this.area_mark != undefined) {
area_mark = this.area_mark_basic;
}
$("#info_responsible").html(this.name + area_mark);
};
var _person_bethere_debug = false;
// this marks a person as needing to attend a session
// in a particular timeslot.
Person.prototype.clear_session = function(session, old_column_classes) {
for(ccn in old_column_class_list) {
var vertical_location = session.column_class_list[ccn].column_tag;
var room_tag = session.column_class_list[ccn].room_tag;
if(_person_bethere_debug) {
console.log("person",this.ascii,"maybe no longer attending session",
session.session_id, "in room",room_tag);
}
// probably should make it dict, to make removal easier
if(this.sessions == undefined) {
continue;
}
if(this.sessions[vertical_location] == undefined) {
continue;
}
if(room_tag in this.sessions[vertical_location]) {
delete this.sessions[vertical_location][room_tag];
if(_person_bethere_debug) {
console.log("person: ",this.ascii,"removed from room",
room_tag, "at", vertical_location);
}
}
}
};
Person.prototype.attend_session = function(session) {
for(ccn in session.column_class_list) {
var vertical_location = session.column_class_list[ccn].column_tag;
var room_tag = session.column_class_list[ccn].room_tag;
if(_person_bethere_debug) {
console.log("person",this.ascii,"maybe attending session", session.session_id, "in room",room_tag);
}
// probably should make it dict, to make removal easier
if(this.sessions == undefined) {
this.sessions = [];
}
if(this.sessions[vertical_location] == undefined) {
this.sessions[vertical_location] = [];
}
if(!(room_tag in this.sessions[vertical_location])) {
this.sessions[vertical_location][room_tag]=true;
if(_person_bethere_debug) {
console.log("person: ",this.ascii,"needs to be in room",
room_tag, "at", vertical_location);
}
}
}
};
Person.prototype.conflicted_time = function(vertical_location) {
var yesno = this.conflicted_time1(vertical_location);
//console.log("person: ",this.ascii,"examining for", vertical_location, "gives",yesno);
return yesno;
}
Person.prototype.conflicted_time1 = function(vertical_location) {
if(this.sessions == undefined) {
return false;
}
if(this.sessions[vertical_location] == undefined) {
return false;
}
var placestobe = Object.keys(this.sessions[vertical_location]);
if(placestobe.length > 1) {
return true;
} else {
return false;
}
};
/*
* Local Variables:
* c-basic-offset:4
* End:
*/