Files
Facilitor/APPL/RES/res_plan_room.inc
Erik Groener b46fdb89e0 UWVA#61386 Extra release 2019.2 voor UWV
svn path=/Website/branches/v2019.2/; revision=45885
2020-02-18 15:56:54 +00:00

577 lines
21 KiB
PHP
Raw Blame History

<% /*
$Revision$
$Id$
File: res_plan_room.inc
Description: Het echte genereren van het planbordje voor ruimtes
via functie make_plan_room() die een kale HTML-table oplevert
Context: Indirect ajax in read_load_plan_room.asp
of rechtstreeks in res_search_plan_room.asp
Notes: Zie res_load_cat.asp voor de catering en res_plan_obj.inc voor ruimtes
*/
FCLTHeader.Requires({js: [rooturl+"/appl/res/res_plan.js", "date.js"]});
// params: res_van, res_tot (en vis)
// Wijzigt(!) plan_rooms_info en voegt overal een will_fit aan toe
function set_will_fit(plan_rooms_info, plan_bezet_info, params)
{
var any_nofit = false;
for (var i_room in plan_rooms_info)
{
var is_nofit = false;
var room = plan_rooms_info[i_room];
var ar = plan_bezet_info[room.res_ruimte_key];
var df = params.res_van.getHours() + params.res_van.getMinutes()/60;
var dt = params.res_tot.getHours() + params.res_tot.getMinutes()/60;
if (df < room.begintijd || dt > room.eindtijd)
{
is_nofit = true; // Buiten openingstijden
}
else if (room.begintijdblok && room.eindtijdblok && df < room.eindtijdblok && dt > room.begintijdblok)
{
is_nofit = true; // Tijdens lunch
}
if (!is_nofit)
{
for (var ci=0; ar != null && ci<ar.length; ci++)
{
if (ar[ci].rsv_ruimte_key == params.rsv_ruimte_key)
{ // we zijn het zelf
is_selected = true;
}
else
{
// We willen graag de max(preposttime) van de catalogus waarin we nu reserveren, en de existing_rsv catalogus
var this_prepost_time = Math.max(room.prepost_time, (ar[ci].rsv_preposttime || 0));
// this_pre_time = Max van this_prepost_time en existing_rsv.activity.post_time
room.pre_time = (ar[ci].act_post_time ? Math.max(this_prepost_time, ar[ci].act_post_time) : this_prepost_time);
room.post_time = Math.max(this_prepost_time, params.act_post_time);
if (params.res_van.getTime() - room.pre_time *60*60*1000 < ar[ci].res_tot.getTime()
&& params.res_tot.getTime() + room.post_time*60*60*1000 > ar[ci].res_van.getTime())
is_nofit = true; // Overlap!
}
}
}
room.will_fit = !is_nofit;
room.existing_res = ar;
any_nofit |= is_nofit;
}
return any_nofit;
}
// Converts plan_bezet_info[x].res_opstel_tijd into .pre_opstel_tijd and .post_opstel_tijd
// taking into account the "opstelling" of the previous and next reservations.
function addPrePostOpstelTijd(plan_rooms_info, plan_bezet_info, params)
{
var room;
var all_rsv;
var curr_rsv;
var this_rsv;
var prev_rsv;
var next_rsv;
var checkPrevNext;
for (var i_room in plan_rooms_info)
{
room = plan_rooms_info[i_room];
all_rsv = plan_bezet_info[room.res_ruimte_key];
if (all_rsv == null) continue;
// Efficiency check, het sorteren is veruit het zwaarst, dus voorkomen waar mogelijk.
checkPrevNext = false;
for (var x = 0; all_rsv != null && x < all_rsv.length; x++)
{
curr_rsv = all_rsv[x];
if ("res_opstel_tijd" in curr_rsv && curr_rsv.res_opstel_tijd > 0 && curr_rsv.fo_status != 3 &&
(!("prepost_time" in room) || curr_rsv.res_opstel_tijd > room.prepost_time) &&
(!("rsv_preposttime" in curr_rsv) || curr_rsv.res_opstel_tijd > curr_rsv.rsv_preposttime))
{
checkPrevNext = true;
break;
}
}
if (!checkPrevNext) continue;
all_rsv.sort(function(a, b) { return new Date(a.res_van) - new Date(b.res_van) });
for (var x = 0; all_rsv != null && x < all_rsv.length; x++)
{
this_rsv = all_rsv[x];
if (!("res_opstel_tijd" in this_rsv)) continue;
// Hier weegt de res_opstel_tijd toch niet mee
if (!this_rsv.res_opstel_tijd || this_rsv.fo_status == 3 ||
(room.prepost_time && this_rsv.res_opstel_tijd <= room.prepost_time) ||
(this_rsv.rsv_preposttime && this_rsv.res_opstel_tijd <= this_rsv.rsv_preposttime))
{
delete this_rsv.res_opstel_tijd;
continue;
}
prev_rsv = null;
next_rsv = null;
// Verschillende ruimtes hebben nooit dezelfde res_ruimte_opstelling_key
if (x > 0 && ("na_koppel" in this_rsv) == ("na_koppel" in all_rsv[x-1]))
prev_rsv = all_rsv[x-1];
if (x+1 < all_rsv.length && ("na_koppel" in this_rsv) == ("na_koppel" in all_rsv[x+1]))
next_rsv = all_rsv[x+1];
if (prev_rsv == null || !("res_opstel_key" in prev_rsv) || this_rsv.res_opstel_key != prev_rsv.res_opstel_key)
this_rsv.pre_opstel_tijd = this_rsv.res_opstel_tijd;
if (next_rsv == null || !("res_opstel_key" in next_rsv) || this_rsv.res_opstel_key != next_rsv.res_opstel_key)
this_rsv.post_opstel_tijd = this_rsv.res_opstel_tijd;
delete this_rsv.res_opstel_tijd;
}
}
}
// De echte planningblokjes van een regel
function make_plan_regel(room, ar, params, nr_days, hour_px)
{
var vanmidnight = params.res_van.midnight().getTime(); // E<>n keer uitrekenen
var vanofs = params.res_van.getTimezoneOffset();
var html = []; // het resultaat
var begintijd_mask = null;
var eindtijd_mask = null;
if (room.begintijd > S("res_t1"))
begintijd_mask = "<div class='begintijd' style='width:"+((room.begintijd-S("res_t1"))*hour_px)+"px'>&nbsp;</div>";
if (room.eindtijd < S("res_t2"))
{
var start_px = (room.eindtijd - S("res_t1")) * hour_px+1;
var width_px = (S("res_t2") - room.eindtijd) * hour_px;
eindtijd_mask = "<div class='eindtijd' style='left:"+start_px+"px;width:"+width_px+"px'>&nbsp;</div>";
}
var is_nofit = false; // zouden we hier passen?
for (dagen = 0; dagen < nr_days; dagen++)
{
html.push('<td class="plantd reserv"><div class="tddiv">' + (begintijd_mask?begintijd_mask:"") + (eindtijd_mask?eindtijd_mask:""));
if (room.begintijdblok && room.eindtijdblok)
{
var px_start = (room.begintijdblok - S("res_t1")) * hour_px;
var px_end = (room.eindtijdblok - S("res_t1")) * hour_px;
var px_width = px_end - px_start;
var div = "<div class='gepland res_blok res_lunchblok' style='left:"+px_start+"px;width:"+px_width+"px;'>&nbsp;</div>";
html.push("\n" + div);
}
for (ci = 0; ar && ci < ar.length; ci++)
{
var h_start = (ar[ci].res_van.getTime() - vanmidnight) /1000/60/60 - 24*dagen;
var h_end = (ar[ci].res_tot.getTime() - vanmidnight) /1000/60/60 - 24*dagen;
// Correctie voor zomer-/wintertijd
var arvanofs = ar[ci].res_van.getTimezoneOffset();
var artotofs = ar[ci].res_tot.getTimezoneOffset();
if (vanofs > arvanofs)
h_start ++;
else if (vanofs < arvanofs)
h_start --;
if (vanofs > artotofs)
h_end ++;
else if (vanofs < artotofs)
h_end --;
if (h_start>24 || h_end < 0)
continue;
not_available = false;
// if we filter on host key we do not want to show the other reservations
// where our host is not the host.
var contact_key = ar[ci].contact_key || ar[ci].host_key;
if ((params.host_key != -1 && params.host_key != ar[ci].host_key) ||
(params.contact_key != -1 && params.contact_key != contact_key) ||
(params.urole=='fe' && !user.isCollega(contact_key)))
{
not_available = true; // FE en niet een eigen reservering
}
if (ar[ci].extern) // uitzondering
not_available = false;
if ((params.host_key > 0 && not_available) ||
(params.contact_key > 0 && not_available) ||
ar[ci].na_koppel == 1)
statClass = "res_nietvrij";
else
{
var eigen_res = user.isCollega(contact_key);
statClass = { 1 : (eigen_res ? "res_optie_eigen" : "res_optie"),
2 : (eigen_res ? "res_definitief_eigen" : "res_definitief"),
3 : "res_blok",
4 : "res_vervallen"}[ar[ci].fo_status];
}
if (ar[ci].rsv_ruimte_key && ar[ci].rsv_ruimte_key == params.rsv_ruimte_key)
statClass += " res_current";
var theClass = statClass + " gepland" + (room.extern_id != null? " extern" : "");
var iconDiv = "";
if (ar[ci].na_koppel == 1 || params.forSelectRoom || params.urole=='fe')
{
// Geen catering indicatie
}
else
{
// Voeg indicatie iconen toe
if (ar[ci].aantalM > 0) // Res heeft meldingen
iconDiv += I("fa-wrench");
if (ar[ci].aantalD > 0) // Res heeft voorzieningen
iconDiv += I("fa-television");
if (ar[ci].aantalA > 0) // Res heeft catering
iconDiv += I("fa-cutlery");
if (iconDiv != "")
iconDiv = "<div class=\"resIcon\">" + iconDiv + "</div>";
}
if (ar[ci].dirtlevel & res.dirtlevel.ruimte.notavailable)
theClass += " res_fatal";
if (h_start<S("res_t1"))
{
h_start = S("res_t1") - S("res_h");
if (dagen > 0)
theClass += " continueleft";
else
theClass += " overflowleft";
}
px_start = (h_start-S("res_t1"))*hour_px;
var contright = false;
if (h_end>S("res_t2"))
{
h_end = S("res_t2") + S("res_h");
if (dagen < nr_days-1)
{
theClass += " continueright";
contright = true;
}
else
theClass += " overflowright";
}
px_end = (h_end-S("res_t1"))*hour_px;
px_width = px_end - px_start;
var theStyleLeft = ""; // voor cleaning blokje afmeting
var theStyleRight = "";
// We willen graag de max(preposttime) van de catalogus waarin we nu reserveren, en de existing_rsv catalogus
var this_prepost_time = Math.max(room.prepost_time, (ar[ci].rsv_preposttime || 0));
// Perhaps cleaning time, alleen optie en definitief
// this_post_time >= this_prepost_time (always)
var this_pre_time = Math.max(this_prepost_time, (ar[ci].pre_opstel_tijd || 0));
var this_post_time = Math.max(this_prepost_time, (ar[ci].post_opstel_tijd || 0), (ar[ci].act_post_time || 0));
var preclean = 0;
var postclean = 0;
if ((this_pre_time || this_post_time) && (ar[ci].fo_status == 1 || ar[ci].fo_status == 2))
{
theClass += " res_cleaning";
// maximaal kwartier 'doorschieten' links/rechts
preclean = Math.min(this_pre_time, h_start - S("res_t1") + 0.25);
postclean = Math.min(this_post_time, S("res_t2") - h_end + 0.25);
if ( Math.round(hour_px * postclean - 1) > 0 )
theStyleRight = "border-right-width:"+Math.round(hour_px * postclean - 1)+"px;"
if ( preclean > 0 )
{
var precleanpx = Math.round(hour_px * preclean - 1);
if (precleanpx > 0)
theStyleLeft = "border-left-width:"+precleanpx+"px;"
if (px_start >= 0)
{
px_start -= precleanpx; // border is 1px minder, maar wel altijd een kwartier
px_width += 1; // border is 1px minder
}
}
}
if (!preclean)
theClass += " res_nopre";
if (!postclean)
theClass += " res_nopost";
var res_flag = "";
if (ar[ci].flag_status > 0)
{
res_flag = "<div style=\"float:left\">" + I("fa-circle fa-fw respl resflag"+ar[ci].flag_status) + "</div>";
}
if (ar[ci].extern_api)
theClass += " res_extern";
if (!ar[ci].na_koppel && !ar[ci].extern_api && !not_available && !params.forSelectRoom)
theClass += " click";
var div = "<div class='"+theClass+"'";
if (ar[ci].rsv_ruimte_key)
div += " rsv_key='" + ar[ci].rsv_ruimte_key + "'"
if (ar[ci].extern)
{
var txt = L("lcl_reservation") + ": " + ar[ci].extern.res_nr // TODO: lcl_reservering_extern?
+ " " + toTimeString(ar[ci].res_van)
+ "-" + toTimeString(ar[ci].res_tot)
+ "\n" + ar[ci].extern.omschrijving;
div += " title='" + safe.htmlattr(txt) + "'";
if (ar[ci].extern.deepurl)
div += " deepurl='" + safe.htmlattr(ar[ci].extern.deepurl) + "'";
}
/*
var safetxt = "";
if (hour_px >= 24) // dan is de omschrijving opgehaald
{
if (px_width > 60) // totale balk 60 pixels
var txt = 'ar[ci].Omschrijving'; // 'ar[ci].omschrijving'
else
var txt = '...';
// TODO: een class die niet wrapt
safetxt = "<span style='color:white;white-space: nowrap;text-overflow: ellipsis;'>" + safe.htmlattr(txt) + "</span>";
}
*/
div += " style='z-index:"+ci+";left:"+px_start+"px;width:"+px_width+"px;"+theStyleLeft+theStyleRight+"'>"
+res_flag+iconDiv+"</div>";
html.push("\n"+div);
}
html.push("</div></td>")
if (dagen < nr_days - 1)
{ if (contright) {
html.push('<td class="between"><div class="' + statClass + '">&nbsp;</div></td>');
} else {
html.push('<td class="between">&nbsp;</td>');
}
}
else
{
html.push('<td class="post"><div>&nbsp;</div></td>');
}
}
return html.join("");
}
function make_plan_room(plan_rooms_info, plan_bezet_info, params)
{
var nnregels = 0;
__Log("start make_plan_room");
if (params.srtact)
lcl.set_dialect(params.srtact, "RES_SRTACTIVITEIT_KEY");
// Iterate through all reservable rooms (vertically) and show schedule for them (horizontally)
var res_ruimte_key, free;
if (plan_rooms_info.length == 0)
{
Response.Write("<table style='width:500px'><tr><td>" + L("lcl_res_none_inplanbord") + "</td></tr></table>");
return; // quick exit
}
var nr_days = Math.round(1 + (params.res_tot.midnight() - params.res_van.midnight()) / 24 / 60 / 60 / 1000);
// Bereken dynamisch breedte blokjes
var hour_px = res.hour_px(width_px - 400, nr_days);
var onclick = "";
var onmouse = "";
if (!params.forSelectRoom && authparams.PRSwritelevel < 9 && authparams.ALGwritelevel < 9)
{
var dt = params.res_van.midnight().getTime();
onclick = "onclick=\"room_table_click(event,new Date("+dt+"), " + hour_px + ", "+safe.jsfloat(S("res_t1"))+",'"+params.urole+"',"+params.act+")\"";
onmouse = "onmousemove=\"room_table_mouse(event,new Date("+dt+"), " + hour_px + ", "+safe.jsfloat(S("res_t1"))+")\"";
onmouse += " onmouseout=$('#timetip').hide();"
}
if (!params.forSelectRoom)
{
addPrePostOpstelTijd(plan_rooms_info, plan_bezet_info, params);
}
var xfunc = user.func_enabled2("CAD", { isOptional: true });
var cad_button = (xfunc && xfunc.canRead("WEB_CADUSE"));
%>
<script type='text/javascript'>
function openFG(evt, res_ruimte_key, titel)
{
var url = '../cad/ShowRoom.asp?res_ruimte_key='+res_ruimte_key;
FcltMgr.openModalDetail(url, titel );
FcltMgr.stopPropagation(evt);
}
</script>
<div id='timetip'></div>
<table id="<%=params.id%>" cellspacing="0" hour_px="<%=hour_px%>"
class="compressed planbord planbord<%=hour_px%> multiday"
<%=onclick%>
<%=onmouse%>
><thead>
<tr style='height:36px;vertical-align:top;'>
<td><label><!--silence--></label></td>
<td align='right' class="capaciteit"><label><!--silence--></label></td>
<% Response.Write(res.build_planbord_tijdbalk(params.res_van, nr_days, hour_px, S("res_t1"), S("res_t2"), params.fnStep)); %>
</tr></thead><tbody>
<%
var any_nofit = false;
if (params.forSelectRoom)
{
any_nofit = set_will_fit(plan_rooms_info, plan_bezet_info, params);
}
for (i_room in plan_rooms_info)
{
var room = plan_rooms_info[i_room];
var bezet_info = plan_bezet_info[room.res_ruimte_key];
// no_fit is al bepaald met set_will_fit
var cls = ""
if (params.forSelectRoom)
{
if (params.res_ruimte_key==room.res_ruimte_key)
{
cls = " selected";
}
else
{
if (!room.will_fit)
cls = " res_nofit";
}
}
if (room.extern_id != null)
{
cls += " extern";
}
%>
<tr class='<%=cls%>'
<% if (room.deepurl)
{
Response.Write(" deepurl='"+safe.htmlattr(room.deepurl)+"'");
Response.Write(" disc_key='"+params.disc_key+"'");
}
%>
id='<%=room.res_ruimte_key%>'>
<td class='label'
OnMouseOver="showOpmerking('#remark<%=room.res_ruimte_key%>', event);"
OnMouseOut="$('#remark<%=room.res_ruimte_key%>').hide();"
<% if (params.forSelectRoom && room.extern_id == null)
Response.Write(" onClick='selectRoom(this);' style='cursor:pointer'"); %>
><nobr>
<%
if (cad_button && !params.extern)
Response.Write("<i class='fa fa-fw fa-map-marker plancad' title='"+L("lcl_prs_wp_fgraph")+"' onclick='openFG(event,"+room.res_ruimte_key+",\"" +safe.jsstring(room.res_ruimte_nr) + "\")'></i>");
var capc_txt = ''+room.bMin+((room.bMin!=room.bMax)?"-"+room.bMax:"")+" pers."
var safe_tooltip = room.omschrijving;
if (room.image)
{
if (!room.image_url)
room.image_url = S("res_image_path") + room.image;
safe_tooltip += "<br><br><img class='resplanfoto' style='height:100px' theSrc='"+safe.htmlattr(room.image_url)+"'>"
}
%>
<label><%=safe.html(room.res_ruimte_nr)%></label></nobr>
<div class="res_remark" style='z-index:9999;text-align:center' id="remark<%=room.res_ruimte_key%>">
<%=safe_tooltip%>
</div>
</td>
<td class="capaciteit"><nobr><%=capc_txt%></nobr></td>
<%
nnregels ++;
Response.Write(make_plan_regel(room, bezet_info, params, nr_days, hour_px));
%> </tr>
<%
}
%>
<tr><td></td>
<td></td>
<% Response.Write(res.build_planbord_tijdbalk(params.res_van, nr_days, hour_px, S("res_t1"), S("res_t2"))); %>
</tr>
</tbody>
</table>
<% if (!params.noclicker) { %>
<script>
$(function () {
$("div.res_nopre, div.res_nopost").each(function()
{
var MARGIN = 2;
var color = $(this).css("backgroundColor");
var pix = $(this).width() - MARGIN;
$(this).css("background", "linear-gradient(to right, transparent 0px, "+color+" "+MARGIN+"px, "+color+" "+pix+"px, transparent 100%)");
});
$("div.resIcon").each(function() {
var $parent = $(this).parents("div");
// Bereken width van iconDiv
var thisContentWidth = 0;
$(this).children().each(function() {
thisContentWidth += $(this).width();
});
if (thisContentWidth > $parent.width())
{
// Kijken of we wat aan kunnen passen (uitdijen)
if (thisContentWidth <= $parent.outerWidth())
{
$(this).css("width", $parent.outerWidth());
$(this).css("left", (-1 * parseFloat($parent.css("borderLeftWidth"))));
}
else // Of maar weg moeten halen
$(this).remove();
}
});
$("table#<%=params.id%>").on("mouseover", "td div.gepland", function (e)
{
var obj = e.currentTarget;
rsv_title(obj);
});
$("table#<%=params.id%>").on("click", "td div.click", function (e)
{
var obj = e.currentTarget;
rsv_click(obj, '<%=params.urole%>');
});
});
</script>
<% } %>
<%
if (any_nofit)
{
%><div class="resplanbordlimited" onclick="$('table#<%=params.id%>').toggleClass('compressed');$(this).toggle();$(this).next().toggle();FcltMgr.resized()">
<a><%=L("lcl_res_show_full_room_catalogus")%></a></div>
<div class="resplanbordlimited" style='display:none' onclick="$('table#<%=params.id%>').toggleClass('compressed');$(this).toggle();$(this).prev().toggle();FcltMgr.resized()">
<a><%=L("lcl_res_show_half_room_catalogus")%></a></div>
<div class="mapcontainer"></div><%
}
__Log("done make_plan_room");
return nnregels;
}
%>