<%@ LANGUAGE="JSCRIPT" %> <% // // Project information page - shows in the "task pane" of the frame set. // This is part of the Web Schedule Browser. NOTE: This ASP also has the // logic for pause/resume all projects, since doing either ends with this // project status page being displayed. // // 23-Dec-08 rbd New DB caching hack // 14-Feb-09 rbd Relayout for compactness, add new content // 14-Mar-09 rbd Fix loadPlansTable() for all browsers, simplify! // 18-Jan-11 rbd GEM:323 Properly account for Observation.SetCount. // 19-Jan-11 rbd GEM:300 Fix count in "run" column. // 05-Feb-12 rbd Copyright to 2012 // 12-Feb-12 rbd GEM:790 Highlight Projects with running plan(s) // 01-Jan-14 rbd Copyright to 2014, navigation notes. // 31-Jan-14 rbd GEM:1083 No more DBRelay hack :-) // 15-Nov-14 rbd GEM:342 wording of project disabled to paused. // 16-Nov-14 rbd GEM:1202 Add pause/resume all projects logic here // 17-Dec-14 rbd GEM:1266 Light style, factor out the status-specific // styles into new style.css stylesheets. // 30-Jan-14 rbd GEM:927 Everyone gets to see all requests // 07-Jun-16 rbd GEM:1456 Color code completion and fail columns // 16-Jul-18 rbd GEM:1581 mailto: links for Project Contact info or // if none, the user/Observer if have that info. // No GEM - update copyright. // 18-Jul-18 rbd GEM:1581 Oops remove the [ACP user]# from the Contact // name before display and use in email To: address. // 17-Jan-19 rbd GEM:1660 Modern DOCTYPE and HTML declarations // 07-Jan-20 rbd No GEM - Copyright to 2021 // 13-Sep-23 rbd No GEM - Copyright to 2023 // // // Enhance String with a trim() method // String.prototype.trim = function() { return this.replace(/(^\s*)|(\s*$)/g, ""); }; var DB = Scheduler.Database var opCode = ""; // Meaning of 'opid' // "" = just display the Project grid // "pauseall" = pause all projects, refresh tree, and display the Project grid // "resumeall" = resume all projects, refresh tree, and display the Project grid if (Request.Form("op")) { opCode = Request.Form("op").Item.toLowerCase(); // Also used later for tree refresh decision var eR = new Enumerator(DB.Projects); // Cannot use MarkAll functions, need user filtering for(;!eR.atEnd(); eR.moveNext()) { var R = eR.item(); if(!User.IsAdministrator && R.User.Name != User.Name) continue; switch(opCode) { case "pauseall": R.Disabled = true; break; case "resumeall": R.Disabled = false; break; default: break; } R.Update(); } } Response.ExpiresAbsolute = new Date("Jan 1, 2000").getVarDate(); // Expire even with clocdk offsets Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); %> ACP Schedule Browser <% // // Generate the HTML for the table itself at the server end, then note // at the bottom the call to stripe the table (once it has been generated). // var tr = ""; var tre = "\r\n"; var td = "\r\n"; var tdd = "
Current Observing Projects
Click a Project name below to see its Plans
Hovering the mouse will reveal info in many places
Project Observer Plns Imgs Time Run Cmpl Pend Defd Fail Dis
"; var tdg = ""; var tdo = ""; var tdr = ""; var tde = ""; function dispTime(t) { if(t >= 3600) { t /= 3600; return t.toFixed(2) + "h"; } else { t /= 60; return t.toFixed(1) + "min"; } } var eR = new Enumerator(DB.Projects); for(;!eR.atEnd(); eR.moveNext()) { var R = eR.item(); var totPlan = 0; var totImg = 0; var totTime = 0; var totCompl = 0; var totPend = 0; var totDef = 0; var totRun = 0; var totFail = 0; var totDis = 0; var eP = new Enumerator(R.Plans); for(;!eP.atEnd(); eP.moveNext()) { P = eP.item(); totPlan += 1; switch(P.Status) { case 0: totPend += 1; break; case 1: totDef += 1; break; case 2: totRun += 1; break; case 3: totCompl += 1; break; case 4: totFail += 1; break; case 5: totDis += 1; break; } var eO = new Enumerator(P.Observations); for(;!eO.atEnd(); eO.moveNext()) { O = eO.item(); var eI = new Enumerator(O.Images); var iImgs = 0; var iTime = 0; for(;!eI.atEnd(); eI.moveNext()) { I = eI.item(); iImgs += I.RepeatCount; iTime += I.ExposureInterval * I.RepeatCount; } totImg += iImgs * O.SetCount; totTime += iTime * O.SetCount; } } totPend = (totPend / totPlan) * 100; totDef = (totDef / totPlan) * 100; totRun = (totRun / totPlan) * 100; totCompl = (totCompl / totPlan) * 100; totFail = (totFail / totPlan) * 100; totDis = (totDis / totPlan) * 100; Response.Write(tr); var buf = ""; buf += R.Name + ""; if(totRun > 0) buf += "  Running"; Response.Write(td + buf + tde); // // ACP Expert copies the Scheduler User Name and User Email into each of the // Projects it creates. Then for that project it is OK to change these. If the // Contact Name is empty, then we revert to using the project Owner/User's name // and email. Think about this before changing it... ha ha. // var cn = R.ContactName; var em = R.ContactEmail; if(!cn) { cn = R.User.Name; em = R.User.Email; } else { cn = cn.replace(/\[ACP.*/, ""); } if(em && em.toLowerCase() != "your@email.here") { Response.Write(td + "") + "?subject=Scheduler Project: " + encodeURI(R.Name) + "\" title=\"Send email to " + em + "\">" + cn + "" + tde); } else { Response.Write(td + cn + tde); } Response.Write(td + totPlan + tde); Response.Write(td + totImg + tde); Response.Write(td + dispTime(totTime) + tde); if(!R.Disabled) { if(totRun > 0) Response.Write(td + "" + totRun.toFixed(1) + "%" + tde); else Response.Write(td + "0.0%" + tde); if(totCompl == 100) { Response.Write(td + "" + totCompl.toFixed(1) + "%" + tde); } else if(totCompl > 80) { Response.Write(td + "" + totCompl.toFixed(1) + "%" + tde); } else { Response.Write(td + totCompl.toFixed(1) + "%" + tde); } Response.Write(td + totPend.toFixed(1) + "%" + tde); Response.Write(td + totDef.toFixed(1) + "%" + tde); if(totFail > 0) Response.Write(td + "" + totFail.toFixed(1) + "%" + tde); else Response.Write(td + "0.0%" + tde); Response.Write(td + totDis.toFixed(1) + "%" + tde); } else { Response.Write(tdd + "---" + tde); Response.Write(tdd + "---" + tde); Response.Write(tdd + "---" + tde); Response.Write(tdd + "---" + tde); Response.Write(tdd + "---" + tde); Response.Write(tdd + "---" + tde); } Response.Write(tre); } %>