<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!-- Copyright (c) 2002-2010 Rally Software Development Corp. All rights reserved. --> <html> <head> <title>Super Customizable Release Chart</title> <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"> <meta name="Name" content="Mashup: Super Customizable Release Chart"/> <meta name="Version" content="2010.2"/> <meta name="Vendor" content="Rally Software"/> <link rel="stylesheet" type="text/css" href="/slm/css/rally/core.css" charset="utf-8"/> <link rel="stylesheet" type="text/css" href="/slm/css/slm.css" charset="utf-8"/> <script type="text/javascript" src="/slm/js-lib/dojo/1.3.1/dojo/dojo.js"></script> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript" src="/slm/js/help.js"></script> <script type="text/javascript" src="/slm/js/slm.js"></script> <script type="text/javascript" src="/slm/js-lib/ejsc/2.0.1/EJSChart.js"></script> <script type="text/javascript" src="/slm/mashup/1.21/js/batch-toolkit.js"></script> <script type="text/javascript" src="/slm/mashup/1.21/js/utilities.js"></script> <script type="text/javascript" src="/slm/mashup/1.21/js/dropdown.js"></script> <script type="text/javascript"> var MASHUP_TYPE = RALLY.Mashup.RELEASE; var SETTINGS_COOKIE_NAME = 'mu_super_customizable_release_settings'; </script> <script type="text/javascript"> /* Copyright (c) 2002-2010 Rally Software Development Corp. All rights reserved. SuperCustomizableUtilities.js */ var DEFINED_STATE = (typeof DEFINED_STATE === "undefined") ? "Defined" : DEFINED_STATE; function addDaysToDate(a, b) { return(a.getTime() + RALLY.Mashup.Utilities.convertDaysToMilliseconds(b)) } function isValidChartDate(b, c, a) { return(RALLY.Mashup.Utilities.isWorkDay(b) && b >= c && b <= a) ? true : false } function initTodayBurndownObj(a) { return{CardEstimateTotal:0,TaskEstimateTotal:0,CardToDoTotal:0,CreationDate:a} } function formatDateValue(a) { return(a < 10) ? "0" + a : a } function calcNumberOfWorkDays(e, a) { var b = 0; var d = RALLY.Mashup.Utilities.convertIsoDateOnly(e); var c = RALLY.Mashup.Utilities.convertIsoDateOnly(a); while (d <= c) { if (RALLY.Mashup.Utilities.isWorkDay(d)) { b = b + 1 } d.setTime(addDaysToDate(d, 1)) } return b } function findDateForDay(f, c) { var e,b,a,d; a = RALLY.Mashup.Utilities.convertIsoDateOnly(f); d = Math.round(c); if (d <= 0) { return a } e = RALLY.Mashup.Utilities.convertIsoDateOnly(f); b = 0; while (b < d) { if (RALLY.Mashup.Utilities.isWorkDay(e)) { b = b + 1; if (b === d) { return e } } e.setTime(addDaysToDate(e, 1)) } return null } function getBeforeState(a) { if (a.length > 4 && a[0] !== DEFINED_STATE) { return a[0] } else { return null } } function getAfterState(a) { if (a.length <= 4) { return null } else { if (a.length === 5) { if (a[0] === DEFINED_STATE) { return a[4] } else { return null } } else { return a[5] } } } function initDataTuple(b, a) { newTuple = []; newTuple.CardEstimateTotal = 0; newTuple.TaskEstimateTotal = 0; newTuple.CardToDoTotal = 0; b[a] = newTuple } function incrementDataTuple(c, a, b) { if (typeof b !== "undefined") { c[a]["CardEstimateTotal"] += b.CardEstimateTotal } if (typeof b !== "undefined") { c[a]["TaskEstimateTotal"] += b.TaskEstimateTotal } if (typeof b !== "undefined") { c[a]["CardToDoTotal"] += b.CardToDoTotal } } function findFirstIndexForDate(d, b) { var a; for (var c = 0; c < d.length; c++) { if (typeof d[c] !== "undefined") { a = RALLY.Mashup.Utilities.convertIsoDateOnly(d[c]["CreationDate"]); if (a.valueOf() == b.valueOf()) { return c } } } return -1 } function addTodayToBurndownData(d, b, a, c) { var e = b.getMonth() + 1; var f = b.getFullYear() + "-" + formatDateValue(e) + "-" + formatDateValue(b.getDate()) + "T" + formatDateValue(b.getHours()) + ":" + formatDateValue(b.getMinutes()) + ":" + formatDateValue(b.getSeconds()) + ".000Z"; if (typeof d.definedData === "undefined") { d = {definedData:[initTodayBurndownObj(f)],inprogressData:[initTodayBurndownObj(f)],completedData:[initTodayBurndownObj(f)],acceptedData:[initTodayBurndownObj(f)]} } else { d.definedData.push(initTodayBurndownObj(f)); d.inprogressData.push(initTodayBurndownObj(f)); d.completedData.push(initTodayBurndownObj(f)); d.acceptedData.push(initTodayBurndownObj(f)) } if (a !== null) { if (typeof d[a + "Data"] === "undefined") { d[a + "Data"] = [initTodayBurndownObj(f)] } else { d[a + "Data"].push(initTodayBurndownObj(f)) } } if (c !== null) { if (typeof d[c + "Data"] === "undefined") { d[c + "Data"] = [initTodayBurndownObj(f)] } else { d[c + "Data"].push(initTodayBurndownObj(f)) } } return d } function sumTodayValues(k, j, m, d) { var l = ["HierarchicalRequirement","Defect","DefectSuite"]; var b = ["PlanEstimate","TaskEstimateTotal","TaskRemainingTotal"]; var g = {PlanEstimate:"CardEstimateTotal",TaskEstimateTotal:"TaskEstimateTotal",TaskRemainingTotal:"CardToDoTotal"}; var e = {Defined:"defined","In-Progress":"inprogress",Completed:"completed",Accepted:"accepted"}; var f,a; if (m !== null) { e[m] = m } if (d !== null) { e[d] = d } for (var h = 0; h < l.length; h++) { f = j[l[h]]; for (var c = 0; c < f.length; c++) { a = e[f[c].ScheduleState]; if (typeof a !== "undefined") { k[a + "Data"][k[a + "Data"].length - 1][g[b[0]]] += f[c][b[0]]; k[a + "Data"][k[a + "Data"].length - 1][g[b[1]]] += f[c][b[1]]; k[a + "Data"][k[a + "Data"].length - 1][g[b[2]]] += f[c][b[2]] } } } return k } function aggregateFlowDataPerDay(v, f, e, s, c) { var q = []; var p = []; var y = []; var x = []; var m = []; var w = []; var j = []; var t = RALLY.Mashup.Utilities.convertIsoDateOnly(f); var d = RALLY.Mashup.Utilities.convertIsoDateOnly(e); var h = 0; var k,l,g,n; var u,b,r,o; g = RALLY.Mashup.Utilities.convertIsoDateOnly(v.definedData[0].CreationDate); b = calcNumberOfWorkDays(f, v.definedData[0].CreationDate.slice(0, 10)); if (RALLY.Mashup.Utilities.isWorkDay(g) && g >= t) { b = b - 1 } k = new Date(t.getTime()); h = 0; while (k <= g) { if (RALLY.Mashup.Utilities.isWorkDay(k)) { j[h] = new Date(k.getTime()); h = h + 1 } k.setTime(addDaysToDate(k, 1)) } k = new Date(g.getTime()); k.setTime(addDaysToDate(k, -1)); h = b - 1; for (u = 0; u < v.definedData.length; u++) { l = RALLY.Mashup.Utilities.convertIsoDateOnly(v.definedData[u].CreationDate); if (l > k) { k = l; if (isValidChartDate(l, t, d)) { h = h + 1; r = h; j[h] = k; initDataTuple(q, h); initDataTuple(p, h); initDataTuple(y, h); initDataTuple(x, h); initDataTuple(m, h); initDataTuple(w, h); beforeCnt = 0; afterCnt = 0 } } if (isValidChartDate(k, t, d)) { if (s !== null) { o = findFirstIndexForDate(v[s + "Data"], k); if (o >= 0) { incrementDataTuple(m, h, v[s + "Data"][o + beforeCnt]); beforeCnt += 1 } } j[h] = k; incrementDataTuple(q, h, v.definedData[u]); incrementDataTuple(p, h, v.inprogressData[u]); incrementDataTuple(y, h, v.completedData[u]); incrementDataTuple(x, h, v.acceptedData[u]); if (c !== null) { o = findFirstIndexForDate(v[c + "Data"], k); if (o >= 0) { incrementDataTuple(w, h, v[c + "Data"][o + afterCnt]); afterCnt += 1 } } } } n = j[r]; k = new Date(n.getTime()); k.setTime(addDaysToDate(k, 1)); h = r + 1; while (k <= d) { if (RALLY.Mashup.Utilities.isWorkDay(k)) { j[h] = new Date(k.getTime()); h = h + 1 } k.setTime(addDaysToDate(k, 1)) } var a = {firstDataDay:b,lastDataDay:r,dates:j,definedPerDay:q,inprogressPerDay:p,completedPerDay:y,acceptedPerDay:x}; if (s !== null) { a[s + "PerDay"] = m } if (c !== null) { a[c + "PerDay"] = w } return a } ; /* Copyright (c) 2002-2010 Rally Software Development Corp. All rights reserved. SuperCustomizableChart.js */ var RALLY = RALLY || {}; RALLY.Mashup = RALLY.Mashup || {}; RALLY.Mashup.SuperCustomizableChart = function(g, r, E, h, f, V, B, e, s, ah, P) { var y = "Defined"; var z = "In-Progress"; var J = "Completed"; var O = "Accepted"; var w = 3; var M = this; var F = {}; var j; var ab,af,ae,ac,Z,ad,L; var N = {ChartType:"stacked-bar",Units:"story",BeforeStateName:null,AfterStateName:null,BeforeVisible:false,DefinedVisible:true,InProgressVisible:true,CompletedVisible:true,AcceptedVisible:true,AfterVisible:false,BeforeColor:"#EF3F35",DefinedColor:"#E57E3A",InProgressColor:"#5C9ACB",CompletedColor:"#B2E3B6",AcceptedColor:"#6AB17D",AfterColor:"#3A874F",BeforeTrend:false,DefinedTrend:false,InProgressTrend:false,CompletedTrend:false,AcceptedTrend:false,AfterTrend:false,BurndownIdealVisible:false,BurndownIdealColor:"#BBBBBB",BurnupIdealVisible:false,BurnupIdealColor:"#BBBBBB",TableVisible:false,LeftAxisLabelVisible:true,BottomAxisLabelVisible:true,RightAxisLabelVisible:true,LeftAxisVisible:true,BottomAxisVisible:true,RightAxisVisible:true,scopeUp:false,scopeDown:true}; var ai = []; function K() { if (typeof P !== "undefined") { P() } } function ak(al) { if (typeof N.scopeUp !== "undefined") { al.projectScopeUp = N.scopeUp } if (typeof N.scopeDown !== "undefined") { al.projectScopeDown = N.scopeDown } } function m(am) { for (var al in am) { if (am.hasOwnProperty(al)) { N[al] = am[al] } } } function b() { if (V === RALLY.Mashup.ITERATION) { return"StartDate" } else { return"ReleaseStartDate" } } function U() { if (V === RALLY.Mashup.ITERATION) { return"EndDate" } else { return"ReleaseDate" } } function T(ao, an) { var al = (V === RALLY.Mashup.ITERATION) ? "iterationCumulativeFlowData" : "releaseCumulativeFlowData"; var am,ap; if (an === null || an.length === 0) { am = '( CardState = "' + ao + '" )' } else { am = "(" + an + ' AND ( CardState = "' + ao + '" ))' } ap = {key:"FlowData",type:al,fetch:"CreationDate,CardEstimateTotal,TaskEstimateTotal,CardToDoTotal",query:am,order:"CreationDate,ObjectID",project:null}; ak(ap); return ap } function X(al) { return(al.getMonth() + 1) + "/" + al.getDate() } function A(aq, an, al, ao, ap) { var ar = []; for (var am = al; am <= ao; am++) { ar.push([am,an[am][ap],X(aq[am])]) } return ar } function t(ar, aq, al, am, ap) { if (typeof ap === "undefined" || ap === null) { ap = "left" } var an = new EJSC.BarSeries(new EJSC.ArrayDataHandler(aq), {y_axis:ap,padding:{x_axis_min:w,x_axis_max:w,y_axis_min:w,y_axis_max:w}}); an.title = ar; an.color = al; an.opacity = 100; an.lineWidth = 1; j.addSeries(an); if (am && aq.length > 1) { var ao = new EJSC.TrendSeries(an, "linear"); ao.lineWidth = 1; ao.color = an.color; ao.opacity = 100; j.addSeries(ao) } return an } function d(am, ao, an) { var al; if (N[am + "Visible"]) { if (N.ChartType === "burndown" && am === "BurnupIdeal") { al = new EJSC.LineSeries(new EJSC.ArrayDataHandler(an), {y_axis:"right"}) } else { al = new EJSC.LineSeries(new EJSC.ArrayDataHandler(an)) } al.title = ao; al.color = N[am + "Color"]; al.lineWidth = 3; al.opacity = 100; j.addSeries(al); return al } else { return null } } function S(aq, ap, al, am) { var an = new EJSC.LineSeries(new EJSC.ArrayDataHandler(ap)); an.title = aq; an.color = al; an.lineWidth = 3; an.opacity = 100; j.addSeries(an); if (am && ap.length > 1) { var ao = new EJSC.TrendSeries(an, "linear"); ao.lineWidth = 1; ao.color = an.color; ao.opacity = 100; j.addSeries(ao) } return an } function D(ao, an, al) { var am = new EJSC.AreaSeries(new EJSC.ArrayDataHandler(an)); am.title = ao; am.color = al; am.lineWidth = 2; am.opacity = 100; j.addSeries(am); return am } function I(al, ar, aq, am, an) { var ao = new EJSC.BarSeries(new EJSC.ArrayDataHandler(aq), {groupedBars:false}); ao.title = ar; ao.color = am; ao.lineWidth = 1; ao.opacity = 100; al.addSeries(ao); if (an && aq.length > 1) { var ap = new EJSC.TrendSeries(ao, "linear"); ap.lineWidth = 1; ap.color = ao.color; ap.opacity = 100; j.addSeries(ap) } return ao } function C(aA, aq, am, an, ao, au) { var ay = []; var ax = []; var al = []; var aw = []; var az = []; var av = 0; var at; var ar; ay[0] = Array.init(aq, 0); if (N.BeforeStateName !== null && N.BeforeVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], aA); ax[av] = N.BeforeStateName; al[av] = N.BeforeColor; aw[av] = N.BeforeTrend } if (N.DefinedVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], aq); ax[av] = "Defined"; al[av] = N.DefinedColor; aw[av] = N.DefinedTrend } if (N.InProgressVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], am); ax[av] = "In-Progress"; al[av] = N.InProgressColor; aw[av] = N.InProgressTrend } if (N.CompletedVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], an); ax[av] = "Completed"; al[av] = N.CompletedColor; aw[av] = N.CompletedTrend } if (N.AcceptedVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], ao); ax[av] = "Accepted"; al[av] = N.AcceptedColor; aw[av] = N.AcceptedTrend } if (N.AfterStateName !== null && N.AfterVisible) { av = av + 1; ay[av] = addArray(ay[av - 1], au); ax[av] = N.AfterStateName; al[av] = N.AfterColor; aw[av] = N.AfterTrend } for (ar = av; ar > 0; ar--) { at = D(ax[ar], ay[ar], al[ar]); az[ar] = at } for (ar = av; ar > 0; ar--) { if (aw[ar] && ay[ar].length > 1) { var ap = new EJSC.TrendSeries(az[ar], "linear"); ap.lineWidth = 1; ap.color = az[ar].color; ap.opacity = 100; j.addSeries(ap) } } return ay } function R(ao, am, aq, al, an, ap) { L = j.addSeries(new EJSC.StackedBarSeries({intervalOffset:0.7,padding:{x_axis_min:w,x_axis_max:w,y_axis_min:w,y_axis_max:w}})); if (N.AfterStateName !== null && N.AfterVisible) { ad = I(L, N.AfterStateName, ap, N.AfterColor, N.AfterTrend) } if (N.AcceptedVisible) { ac = I(L, O, an, N.AcceptedColor, N.AcceptedTrend) } if (N.CompletedVisible) { ae = I(L, J, al, N.CompletedColor, N.CompletedTrend) } if (N.InProgressVisible) { af = I(L, z, aq, N.InProgressColor, N.InProgressTrend) } if (N.DefinedVisible) { ab = I(L, y, am, N.DefinedColor, N.DefinedTrend) } if (N.BeforeStateName !== null && N.BeforeVisible) { Z = I(L, N.BeforeStateName, ao, N.BeforeColor, N.BeforeTrend) } } function W(ao, am, aq, al, an, ap) { L = j.addSeries(new EJSC.StackedBarSeries({intervalOffset:0.7,padding:{x_axis_min:w,x_axis_max:w,y_axis_min:w,y_axis_max:w}})); if (N.BeforeStateName !== null && N.BeforeVisible) { Z = I(L, N.BeforeStateName, ao, N.BeforeColor, N.BeforeTrend) } if (N.DefinedVisible) { ab = I(L, y, am, N.DefinedColor, N.DefinedTrend) } if (N.InProgressVisible) { af = I(L, z, aq, N.InProgressColor, N.InProgressTrend) } if (N.CompletedVisible) { ae = I(L, J, al, N.CompletedColor, N.CompletedTrend) } if (N.AcceptedVisible) { ac = t(O, an, N.AcceptedColor, N.AcceptedTrend, "right") } if (N.AfterStateName !== null && N.AfterVisible) { ad = t(N.AfterStateName, ap, N.AfterColor, N.AfterTrend, "right") } } function x(ao, am, aq, al, an, ap) { if (N.BeforeStateName !== null && N.BeforeVisible) { Z = t(N.BeforeStateName, ao, N.BeforeColor, N.BeforeTrend) } if (N.DefinedVisible) { ab = t(y, am, N.DefinedColor, N.DefinedTrend) } if (N.InProgressVisible) { af = t(z, aq, N.InProgressColor, N.InProgressTrend) } if (N.CompletedVisible) { ae = t(J, al, N.CompletedColor, N.CompletedTrend) } if (N.AcceptedVisible) { ac = t(O, an, N.AcceptedColor, N.AcceptedTrend) } if (N.AfterStateName !== null && N.AfterVisible) { ad = t(N.AfterStateName, ap, N.AfterColor, N.AfterTrend) } } function H(ao, am, aq, al, an, ap) { if (N.BeforeStateName !== null && N.BeforeVisible) { Z = S(N.BeforeStateName, ao, N.BeforeColor, N.BeforeTrend) } if (N.DefinedVisible) { ab = S(y, am, N.DefinedColor, N.DefinedTrend) } if (N.InProgressVisible) { af = S(z, aq, N.InProgressColor, N.InProgressTrend) } if (N.CompletedVisible) { ae = S(J, al, N.CompletedColor, N.CompletedTrend) } if (N.AcceptedVisible) { ac = S(O, an, N.AcceptedColor, N.AcceptedTrend) } if (N.AfterStateName !== null && N.AfterVisible) { ad = S(N.AfterStateName, ap, N.AfterColor, N.AfterTrend) } } function aa(al) { var an = al.toUTCString().slice(5); var am = an.toString().split(/ /); return am[1] + " " + am[0] + ", " + am[2] } function Q(al) { return Math.round(al * 100) / 100 } function p(am) { var an = new google.visualization.DataTable(); var au,al,ap; var ar,aq,ao; ar = aj(); if (N.ChartType === "burndown") { aq = "CardEstimateTotal" } else { aq = ar } an.addColumn("string", "Date"); if (N.BeforeStateName !== null) { an.addColumn("number", N.BeforeStateName) } an.addColumn("number", y); an.addColumn("number", z); an.addColumn("number", J); an.addColumn("number", O); if (N.AfterStateName !== null) { an.addColumn("number", N.AfterStateName) } ap = am.lastDataDay - am.firstDataDay + 1; an.addRows(ap); au = 0; for (ao = am.firstDataDay; ao <= am.lastDataDay; ao++) { al = 0; an.setCell(au, al++, aa(am.dates[ao])); if (N.BeforeStateName !== null) { an.setCell(au, al++, Q(am[N.BeforeStateName + "PerDay"][ao][ar])) } an.setCell(au, al++, Q(am.definedPerDay[ao][ar])); an.setCell(au, al++, Q(am.inprogressPerDay[ao][ar])); an.setCell(au, al++, Q(am.completedPerDay[ao][ar])); an.setCell(au, al++, Q(am.acceptedPerDay[ao][aq])); if (N.AfterStateName !== null) { an.setCell(au, al++, Q(am[N.AfterStateName + "PerDay"][ao][aq])) } au = au + 1 } document.getElementById(s).style.visibility = "visible"; var at = new google.visualization.Table(document.getElementById(s)); at.draw(an, {allowHtml:true,showRowNumber:false}) } function aj() { if (N.Units === "story") { return"CardEstimateTotal" } else { if (N.Units === "task") { return"TaskEstimateTotal" } else { return"CardToDoTotal" } } } function n(an, am, ao) { var al; al = an.definedPerDay[ao][am] + an.inprogressPerDay[ao][am] + an.completedPerDay[ao][am] + an.acceptedPerDay[ao][am]; if (N.BeforeStateName !== null) { al = al + an[N.BeforeStateName + "PerDay"][ao][am] } if (N.AfterStateName !== null) { al = al + an[N.AfterStateName + "PerDay"][ao][am] } return al } function l(am, an) { var al; al = am.acceptedPerDay[an]["CardEstimateTotal"]; if (N.AfterStateName !== null) { al = al + am[N.AfterStateName + "PerDay"][an]["CardEstimateTotal"] } return al } function q(an, ao) { var al,am; am = aj(); al = an.definedPerDay[ao][am] + an.inprogressPerDay[ao][am] + an.completedPerDay[ao][am]; if (N.BeforeStateName !== null) { al = al + an[N.BeforeStateName + "PerDay"][ao][am] } return al } function ag(am) { var al; if (N.ChartType === "burndown") { al = "TaskEstimateTotal" } else { al = aj() } return n(am, al, am.firstDataDay) } function k(am) { var al; if (N.ChartType === "burndown") { al = "CardEstimateTotal" } else { al = aj() } return n(am, al, am.firstDataDay) } function c(ao, an) { var ap = 0,am = 0; for (var al = ao.firstDataDay; al <= ao.lastDataDay; al++) { if (N.ChartType === "burndown") { ap = Math.max(ap, q(ao, al)); am = Math.max(am, l(ao, al)) } else { ap = Math.max(ap, n(ao, an, al)); am = ap } } if (ap < 0.01) { ap = 1 } if (am < 0.01) { am = 1 } return[ap,am] } function Y(an) { var aH = null,aI = null; var aD,aw,ay,am; var at,aF; var aq,ap,az,ax; var ar = an.dates.length - 1; var av,aC,aG,al; var ao = 300; av = aj(); if (N.ChartType === "burndown") { aC = "CardEstimateTotal" } else { aC = av } aD = A(an.dates, an.definedPerDay, an.firstDataDay, an.lastDataDay, av); aw = A(an.dates, an.inprogressPerDay, an.firstDataDay, an.lastDataDay, av); ay = A(an.dates, an.completedPerDay, an.firstDataDay, an.lastDataDay, av); am = A(an.dates, an.acceptedPerDay, an.firstDataDay, an.lastDataDay, aC); if (N.BeforeStateName !== null) { aH = A(an.dates, an[N.BeforeStateName + "PerDay"], an.firstDataDay, an.lastDataDay, av) } if (N.AfterStateName !== null) { aI = A(an.dates, an[N.AfterStateName + "PerDay"], an.firstDataDay, an.lastDataDay, aC) } at = ag(an); aF = k(an); aG = c(an, av); var aE = X(an.dates[an.dates.length - 1]); var aB = [ [0,at,an.dates[0]], [ar,0,aE] ]; var aA = [ [0,0,an.dates[0]], [ar,aF,aE] ]; az = "Ideal Burndown To Do"; ax = "Ideal Burn-up Accepted"; document.getElementById(e).style.visibility = "visible"; var au = function() { EJSC.Formatter.__extendTo(this); this.format = function(aJ) { if (Math.round(aJ) !== aJ) { return"" } if (aJ >= 0 && aJ < an.dates.length) { return X(an.dates[aJ]) } else { return X(findDateForDay(h, aJ)) } } }; if (typeof j !== "undefined") { j.remove() } j = new EJSC.Chart(e, {show_legend:false,allow_zoom:false,show_titlebar:false,axis_bottom:{caption:"",caption_class:"AxisCaption",label_class:"AxisTickLabel",size:0,min_extreme:0,max_extreme:ar,extremes_ticks:true,major_ticks:{opacity:100,min_interval:3,show:true,thickness:1},visible:N.BottomAxisVisible},axis_left:{caption:"",caption_class:"AxisCaption",label_class:"AxisTickLabel",size:0,min_extreme:0,formatter:new EJSC.NumberFormatter({variable_decimals:1}),visible:N.LeftAxisVisible},axis_right:{caption:"",caption_class:"AxisCaption",label_class:"AxisTickLabel",size:0,min_extreme:0,grid:{show:false},formatter:new EJSC.NumberFormatter({variable_decimals:1}),visible:N.RightAxisVisible}}); if (N.ChartType === "stacked-bar" || N.ChartType === "grouped-bar" || N.ChartType === "burndown") { j.axis_bottom.setExtremes(-0.35, ar + 0.35) } j.axis_left.setExtremes(0, Math.round(Math.max(at, aG[0]))); if (N.ChartType === "burndown") { j.axis_right.setExtremes(0, Math.round(Math.max(aF, aG[1]))) } al = parseInt(document.getElementById(e).style.width, 10); if (isNaN(al)) { al = 0 } if (N.BottomAxisLabelVisible) { j.axis_bottom.caption = "Date"; if (al > ao) { } } if (N.LeftAxisLabelVisible) { if (al > ao) { j.axis_left.size = Math.round(al * 0.06) } if (N.Units === "story") { j.axis_left.caption = "Plan Estimates" } else { if (N.Units === "task") { j.axis_left.caption = "Task Estimates" } else { j.axis_left.caption = "Task To Do" } } } if (N.ChartType === "burndown") { if (al > ao) { j.axis_right.size = Math.round(al * 0.07) } if (N.RightAxisLabelVisible) { j.axis_right.caption = "Plan Estimate" } } j.axis_bottom.formatter = new au(); j.onShowHint = function(aJ, aK, aL, aN, aM) { if (aK.title.indexOf("Trend") >= 0) { return"[series_title]<br/>Value: " + Math.round(aJ.y * 100) / 100 } else { if (aK.title.indexOf("Ideal") >= 0) { return"[series_title]<br/>Date: [x]<br/>Value: " + Math.round(aJ.y * 100) / 100 } else { return"[series_title]<br/>Date: [label]<br/>" + v(aK.title) + ": " + Math.round(aJ.y * 100) / 100 } } }; if (N.ChartType === "stacked-bar") { R(aH, aD, aw, ay, am, aI) } else { if (N.ChartType === "grouped-bar") { x(aH, aD, aw, ay, am, aI) } else { if (N.ChartType === "area") { C(aH, aD, aw, ay, am, aI) } else { if (N.ChartType === "burndown") { W(aH, aD, aw, ay, am, aI) } else { H(aH, aD, aw, ay, am, aI) } } } } aq = d("BurndownIdeal", az, aB); ap = d("BurnupIdeal", ax, aA); if (N.TableVisible && s !== null) { p(an) } } function v(al) { if (N.ChartType === "burndown" && al.indexOf("Accepted") >= 0) { if (V === RALLY.Mashup.ITERATION) { return ai.IterationEstimateUnitName } else { return ai.ReleaseEstimateUnitName } } else { if (N.Units === "story") { if (V === RALLY.Mashup.ITERATION) { return ai.IterationEstimateUnitName } else { return ai.ReleaseEstimateUnitName } } else { return ai.TaskUnitName } } } function G(al) { function ap() { if (V === RALLY.Mashup.ITERATION) { return"Iteration.StartDate" } else { return"Release.ReleaseStartDate" } } function an() { if (V === RALLY.Mashup.ITERATION) { return"Iteration.EndDate" } else { return"Release.ReleaseDate" } } function ao() { if (V === RALLY.Mashup.ITERATION) { return"Iteration.Name" } else { return"Release.Name" } } var am = {key:al,type:al,query:"((( " + ap() + " = " + h + ") AND (" + an() + " = " + f + ")) AND (" + ao() + ' = "' + E + '"))',fetch:"PlanEstimate,TaskEstimateTotal,TaskRemainingTotal,ScheduleState"}; if (ah !== null) { am.project = "/project/" + ah } ak(am); return am } function a(aq, an, am, ao) { var al = []; aq = addTodayToBurndownData(aq, an, am, ao); var ap = function(ar) { aq = sumTodayValues(aq, ar, am, ao); i() }; al[0] = G("HierarchicalRequirement"); al[1] = G("Defect"); al[2] = G("DefectSuite"); BATCH_TOOLKIT.findAll(al, ap) } function i() { var am; var al = new Date(); if (s !== null) { document.getElementById(s).style.visibility = "hidden" } if (typeof F.definedData === "undefined" || (F.definedData.length + F.inprogressData.length + F.completedData.length + F.acceptedData.length) === 0 || al < RALLY.Mashup.Utilities.convertIsoDateOnly(h)) { document.getElementById(e).style.visibility = "visible"; document.getElementById(e).innerHTML = "No Data"; K() } else { am = aggregateFlowDataPerDay(F, h, f, N.BeforeStateName, N.AfterStateName); Y(am); K() } } function o(am) { var az = [],at = [],aq = {},ax; if (r !== null) { ax = r.split(","); for (var ar = 0; ar < ax.length; ar++) { aq = {}; aq.ObjectID = ax[ar]; at[ar] = aq } } else { at = am.timeboxOids } if (at.length === 0) { return } var aw = (V === RALLY.Mashup.ITERATION) ? "IterationObjectID" : "ReleaseObjectID"; if (N.BeforeStateName !== null) { var av = T(N.BeforeStateName, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(av, ay) } else { ay(az) } ai = am.estimateUnit[0]; function ay(aA) { if (N.BeforeStateName !== null) { F[N.BeforeStateName + "Data"] = aA.FlowData } var aB = T(y, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(aB, ap) } function ap(aA) { F.definedData = aA.FlowData; av = T(z, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(av, al) } function al(aA) { F.inprogressData = aA.FlowData; av = T(J, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(av, au) } function au(aA) { F.completedData = aA.FlowData; av = T(O, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(av, ao) } function ao(aA) { F.acceptedData = aA.FlowData; if (N.AfterStateName !== null) { var aB = T(N.AfterStateName, RALLY.Mashup.Utilities.buildOrQueryString(at, aw, "ObjectID")); g.findAll(aB, an) } else { an(az) } } function an(aC) { if (N.AfterStateName !== null) { F[N.AfterStateName + "Data"] = aC.FlowData } var aA = RALLY.Mashup.Utilities.convertIsoDateOnly(h); var aD = RALLY.Mashup.Utilities.convertIsoDateOnly(f); aD.setHours(23, 59, 0, 0); var aB = new Date(); if (isValidChartDate(aB, aA, aD) && V !== RALLY.Mashup.Program) { a(F, aB, N.BeforeStateName, N.AfterStateName) } else { i() } } } function u() { var an = b(); var ao = U(); var am = []; var al = "((( " + an + " = " + h + ") AND (" + ao + " = " + f + ')) AND (Name = "' + E + '"))'; am[0] = {key:"timeboxOids",type:V,fetch:"ObjectID,Name,project," + an + "," + ao,query:al,order:ao + " desc,ObjectID"}; ak(am[0]); am[1] = {key:"estimateUnit",type:"WorkspaceConfiguration",fetch:"TaskUnitName,IterationEstimateUnitName,ReleaseEstimateUnitName"}; ak(am[1]); if (ah !== null) { am[0].project = "/project/" + ah } g.findAll(am, o) } this.display = function() { u() }; this.redisplay = function(al) { m(al); i() }; if (B !== null) { m(B) } return M }; /* Copyright (c) 2002-2010 Rally Software Development Corp. All rights reserved. */ dojo.addOnLoad(initPage); google.load("visualization", "1", {packages:["table"]}); var COLORS = { 'red' : '#E92D34', 'orange' : '#F39731', 'yellow' : '#F4CA13', 'green' : '#6AB17D', 'blue' : '#5E70DE', 'indigo' : "#4B0082", 'violet' : "#EE82EE", 'light_green' : '#B2E3B6', 'gray' : '#BBBBBB' }; var DEFINED_STATE = 'Defined'; var INPROGRESS_STATE = 'In-Progress'; var COMPLETED_STATE = 'Completed'; var ACCEPTED_STATE = 'Accepted'; var CHARTCOLORS = { DEFINED_STATE : "orange", INPROGRESS_STATE : "blue", COMPLETED_STATE : "light_green", ACCEPTED_STATE : "green", 'BurndownIdeal' : "gray", 'BurnupIdeal' : "gray" }; var BATCH_TOOLKIT, DROPDOWN, BURNDOWN_CHART; var NUM_SETTINGS = 31; var SETTINGS_COOKIE_DEFAULT = 't~f~f~f~f~f~t~f~f~t~t~t~t~f~f~f~f~orange~blue~light_green~green~f~f~red~f~f~indigo~f~gray~f~gray'; var NUM_CHART_TYPES = 5; var theChart; var dSeries, iSeries, cSeries, aSeries, bSeries, fSeries, theStack; Array.init = function (template_array, initial) { var a = [], i; for (i = 0; i < template_array.length; i += 1) { a[i] = [template_array[i][0], initial, template_array[i][2]]; } return a; }; function addArray(first, second) { var i; var sum = []; for (i = 0; i < first.length; i += 1) { sum.push([first[i][0], first[i][1] + second[i][1], first[i][2]]); } return sum; } function getControlPanelElement(name) { return document.getElementById(name); } function getState(element) { if (element.checked) { return "~t"; } else { return "~f"; } } function getValue(element) { return "~" + element.value; } function buildConfig() { var config = {}; var beforeState = getBeforeState(SCHEDULE_STATES); var afterState = getAfterState(SCHEDULE_STATES); if (getControlPanelElement('input0').checked) { config.ChartType = 'stacked-bar'; } else if (getControlPanelElement('input1').checked) { config.ChartType = 'grouped-bar'; } else if (getControlPanelElement('input2').checked) { config.ChartType = 'line'; } else if (getControlPanelElement('input3').checked) { config.ChartType = 'area'; } else { config.ChartType = 'burndown'; } if (getControlPanelElement('rbStory').checked) { config.Units = 'story'; } else if (getControlPanelElement('rbTask').checked) { config.Units = 'task'; } else if (getControlPanelElement('rbToDo').checked) { config.Units = 'todo'; } config.BeforeStateName = beforeState; config.AfterStateName = afterState; config[DEFINED_STATE + 'Visible'] = getControlPanelElement('cbDefined').checked; config['InProgressVisible'] = getControlPanelElement('cbIn-Progress').checked; config[COMPLETED_STATE + 'Visible'] = getControlPanelElement('cbCompleted').checked; config[ACCEPTED_STATE + 'Visible'] = getControlPanelElement('cbAccepted').checked; config[DEFINED_STATE + 'Color'] = COLORS[getControlPanelElement('selDefined').value]; config['InProgressColor'] = COLORS[getControlPanelElement('selIn-Progress').value]; config[COMPLETED_STATE + 'Color'] = COLORS[getControlPanelElement('selCompleted').value]; config[ACCEPTED_STATE + 'Color'] = COLORS[getControlPanelElement('selAccepted').value]; config[DEFINED_STATE + 'Trend'] = getControlPanelElement('cbDefinedTrend').checked; config['InProgressTrend'] = getControlPanelElement('cbIn-ProgressTrend').checked; config[COMPLETED_STATE + 'Trend'] = getControlPanelElement('cbCompletedTrend').checked; config[ACCEPTED_STATE + 'Trend'] = getControlPanelElement('cbAcceptedTrend').checked; if (beforeState !== null) { config.BeforeVisible = getControlPanelElement('cb' + beforeState).checked; config.BeforeColor = COLORS[getControlPanelElement('sel' + beforeState).value]; config.BeforeTrend = getControlPanelElement('cb' + beforeState + 'Trend').checked; } if (afterState !== null) { config.AfterVisible = getControlPanelElement('cb' + afterState).checked; config.AfterColor = COLORS[getControlPanelElement('sel' + afterState).value]; config.AfterTrend = getControlPanelElement('cb' + afterState + 'Trend').checked; } config.BurndownIdealVisible = getControlPanelElement('cbBurndownIdeal').checked; config.BurndownIdealColor = COLORS[getControlPanelElement('selBurndownIdeal').value]; config.BurnupIdealVisible = getControlPanelElement('cbBurnupIdeal').checked; config.BurnupIdealColor = COLORS[getControlPanelElement('selBurnupIdeal').value]; config.TableVisible = getControlPanelElement('cbTable').checked; if (config.ChartType === 'burndown') { config.RightAxisLabelVisible = true; } return config; } function getControlStates() { var initialVal = getControlPanelElement('input0').checked ? 't' : 'f'; var beforeState = getBeforeState(SCHEDULE_STATES); var afterState = getAfterState(SCHEDULE_STATES); var cookieVal = initialVal + getState(getControlPanelElement('input1')) + getState(getControlPanelElement('input2')) + getState(getControlPanelElement('input3')) + getState(getControlPanelElement('input4')) + getState(getControlPanelElement('cbTable')) + getState(getControlPanelElement('rbStory')) + getState(getControlPanelElement('rbTask')) + getState(getControlPanelElement('rbToDo')) + getState(getControlPanelElement('cbDefined')) + getState(getControlPanelElement('cbIn-Progress')) + getState(getControlPanelElement('cbCompleted')) + getState(getControlPanelElement('cbAccepted')) + getState(getControlPanelElement('cbDefinedTrend')) + getState(getControlPanelElement('cbIn-ProgressTrend')) + getState(getControlPanelElement('cbCompletedTrend')) + getState(getControlPanelElement('cbAcceptedTrend')) + getValue(getControlPanelElement('selDefined')) + getValue(getControlPanelElement('selIn-Progress')) + getValue(getControlPanelElement('selCompleted')) + getValue(getControlPanelElement('selAccepted')); if (beforeState !== null) { cookieVal = cookieVal + getState(getControlPanelElement('cb' + beforeState)); cookieVal = cookieVal + getState(getControlPanelElement('cb' + beforeState + 'Trend')); cookieVal = cookieVal + getValue(getControlPanelElement('sel' + beforeState)); } else { cookieVal = cookieVal + '~f~f~gray'; } if (afterState !== null) { cookieVal = cookieVal + getState(getControlPanelElement('cb' + afterState)); cookieVal = cookieVal + getState(getControlPanelElement('cb' + afterState + 'Trend')); cookieVal = cookieVal + getValue(getControlPanelElement('sel' + afterState)); } else { cookieVal = cookieVal + '~f~f~gray'; } cookieVal = cookieVal + getState(getControlPanelElement('cbBurndownIdeal')); cookieVal = cookieVal + getValue(getControlPanelElement('selBurndownIdeal')); cookieVal = cookieVal + getState(getControlPanelElement('cbBurnupIdeal')); cookieVal = cookieVal + getValue(getControlPanelElement('selBurnupIdeal')); return cookieVal; } function updateColor(name, colorIndex) { CHARTCOLORS[colorIndex] = getControlPanelElement('sel' + name).value; getControlPanelElement('sq' + name).style.background = COLORS[CHARTCOLORS[colorIndex]]; } function updateColors() { var beforeState = getBeforeState(SCHEDULE_STATES); var afterState = getAfterState(SCHEDULE_STATES); updateColor('Accepted', ACCEPTED_STATE); updateColor('Completed', COMPLETED_STATE); updateColor('In-Progress', INPROGRESS_STATE); updateColor('Defined', DEFINED_STATE); updateColor('BurndownIdeal', 'BurndownIdeal'); updateColor('BurnupIdeal', 'BurnupIdeal'); if (beforeState !== null) { updateColor(beforeState, beforeState); } if (afterState !== null) { updateColor(afterState, afterState); } } function updateUnitRadioButtons() { if (getControlPanelElement('input4').checked) { getControlPanelElement('rbStory').disabled = true; getControlPanelElement('rbTask').disabled = true; getControlPanelElement('rbToDo').checked = true; getControlPanelElement('rbToDo').disabled = true; } else { getControlPanelElement('rbStory').disabled = false; getControlPanelElement('rbTask').disabled = false; getControlPanelElement('rbToDo').disabled = false; } } function onColorChange(e) { RALLY.Mashup.Utilities.updateMashupCookie(SETTINGS_COOKIE_NAME, getControlStates(), 30); updateColors(); RALLY.Mashup.Utilities.showWait('chart_div'); BURNDOWN_CHART.redisplay(buildConfig()); } function onDatasetChange(e) { RALLY.Mashup.Utilities.updateMashupCookie(SETTINGS_COOKIE_NAME, getControlStates(), 30); updateTrendIdealChkBoxes(); RALLY.Mashup.Utilities.showWait('chart_div'); BURNDOWN_CHART.redisplay(buildConfig()); } function addCheckBox(row, id) { var cell = document.createElement("TD"); var checkBox = document.createElement("input"); checkBox.type = "checkbox"; checkBox.id = id; if (document.addEventListener) { // For most browsers checkBox.addEventListener('change', onDatasetChange, false); } else if (document.attachEvent) { // For IE checkBox.attachEvent('onclick', onDatasetChange); } cell.width = 25; cell.appendChild(checkBox); row.appendChild(cell); } function addLabel(row, labeltext) { var label; var cell = document.createElement("TD"); if (labeltext !== null && labeltext.length > 0) { label = document.createElement("label"); label.appendChild(document.createTextNode(labeltext)); cell.appendChild(label); } row.appendChild(cell); } function addLegendSquare(row, id) { var cell = document.createElement("TD"); cell.id = id; cell.height = 5; cell.width = 20; cell.border = 1; row.appendChild(cell); } function addSelectList(row, id) { var option; var cell = document.createElement("TD"); var selectList = document.createElement("select"); selectList.id = id; if (document.addEventListener) { // For most browsers selectList.addEventListener('change', onColorChange, false); } else if (document.attachEvent) { // For IE selectList.attachEvent('onchange', onColorChange); } for (var colorName in COLORS) { if (COLORS.hasOwnProperty(colorName)) { option = document.createElement('option'); option.text = colorName; option.value = colorName; //option.style.background=COLORS[colorName]; try { selectList.add(option, null); // standards compliant; doesn't work in IE } catch(ex) { selectList.add(option); // IE only } } } cell.appendChild(selectList); row.appendChild(cell); } function addHeader(tablebody) { var cell, label; var row = document.createElement("TR"); cell = document.createElement("TH"); row.appendChild(cell); cell = document.createElement("TH"); row.appendChild(cell); cell = document.createElement("TH"); row.appendChild(cell); cell = document.createElement("TH"); row.appendChild(cell); cell = document.createElement("TH"); label = document.createElement("label"); label.appendChild(document.createTextNode("Trend")); cell.appendChild(label); row.appendChild(cell); tablebody.appendChild(row); } function addDatasetControlPanel(results) { var tablebody, table, row, cell, checkBox, selectList, option; SCHEDULE_STATES = results.storyStates; table = document.createElement("TABLE"); table.cellSpacing = 5; tablebody = document.createElement("TBODY"); addHeader(tablebody); for (var i = 0; i < SCHEDULE_STATES.length; i++) { row = document.createElement("TR"); addCheckBox(row, "cb" + SCHEDULE_STATES[i]); addLegendSquare(row, "sq" + SCHEDULE_STATES[i]); addLabel(row, SCHEDULE_STATES[i]); addSelectList(row, "sel" + SCHEDULE_STATES[i]); addCheckBox(row, "cb" + SCHEDULE_STATES[i] + "Trend", null); tablebody.appendChild(row); } table.appendChild(tablebody); document.getElementById('datasetPanel').appendChild(table); addIdealControlPanel(); } function addIdealControlPanel() { var tablebody, table, row, cell, label; table = document.createElement("TABLE"); table.cellSpacing = 5; tablebody = document.createElement("TBODY"); row = document.createElement("TR"); cell = document.createElement("TH"); label = document.createElement("label"); label.appendChild(document.createTextNode("Ideal Lines")); cell.appendChild(label); cell.colSpan = 3; cell.align = "left"; row.appendChild(cell); tablebody.appendChild(row); row = document.createElement("TR"); addCheckBox(row, "cbBurndownIdeal"); addLegendSquare(row, "sqBurndownIdeal"); addLabel(row, "Burndown To Do"); addSelectList(row, "selBurndownIdeal"); tablebody.appendChild(row); row = document.createElement("TR"); addCheckBox(row, "cbBurnupIdeal"); addLegendSquare(row, "sqBurnupIdeal"); addLabel(row, "Burn-up Accepted"); addSelectList(row, "selBurnupIdeal"); tablebody.appendChild(row); table.appendChild(tablebody); document.getElementById('idealPanel').appendChild(table); } function setControlStates(cookieVal) { var stuff = cookieVal.split(/~/); var beforeState = getBeforeState(SCHEDULE_STATES); var afterState = getAfterState(SCHEDULE_STATES); if (stuff.length != NUM_SETTINGS) { stuff = SETTINGS_COOKIE_DEFAULT.split(/~/); } getControlPanelElement('input0').checked = (stuff[0] === 't') ? true : false; getControlPanelElement('input1').checked = (stuff[1] === 't') ? true : false; getControlPanelElement('input2').checked = (stuff[2] === 't') ? true : false; getControlPanelElement('input3').checked = (stuff[3] === 't') ? true : false; getControlPanelElement('input4').checked = (stuff[4] === 't') ? true : false; getControlPanelElement('cbTable').checked = (stuff[5] === 't') ? true : false; getControlPanelElement('rbStory').checked = (stuff[6] === 't') ? true : false; getControlPanelElement('rbTask').checked = (stuff[7] === 't') ? true : false; getControlPanelElement('rbToDo').checked = (stuff[8] === 't') ? true : false; getControlPanelElement('cbDefined').checked = (stuff[9] === 't') ? true : false; getControlPanelElement('cbIn-Progress').checked = (stuff[10] === 't') ? true : false; getControlPanelElement('cbCompleted').checked = (stuff[11] === 't') ? true : false; getControlPanelElement('cbAccepted').checked = (stuff[12] === 't') ? true : false; getControlPanelElement('cbDefinedTrend').checked = (stuff[13] === 't') ? true : false; getControlPanelElement('cbIn-ProgressTrend').checked = (stuff[14] === 't') ? true : false; getControlPanelElement('cbCompletedTrend').checked = (stuff[15] === 't') ? true : false; getControlPanelElement('cbAcceptedTrend').checked = (stuff[16] === 't') ? true : false; getControlPanelElement('selDefined').value = stuff[17]; getControlPanelElement('sqDefined').style.background = COLORS[stuff[17]]; getControlPanelElement('selIn-Progress').value = stuff[18]; getControlPanelElement('sqIn-Progress').style.background = COLORS[stuff[18]]; getControlPanelElement('selCompleted').value = stuff[19]; getControlPanelElement('sqCompleted').style.background = COLORS[stuff[19]]; getControlPanelElement('selAccepted').value = stuff[20]; getControlPanelElement('sqAccepted').style.background = COLORS[stuff[20]]; if (beforeState !== null) { getControlPanelElement('cb' + beforeState).checked = (stuff[21] === 't') ? true : false; getControlPanelElement('cb' + beforeState + 'Trend').checked = (stuff[22] === 't') ? true : false; getControlPanelElement('sel' + beforeState).value = stuff[23]; getControlPanelElement('sq' + beforeState).style.background = COLORS[stuff[23]]; } if (afterState !== null) { getControlPanelElement('cb' + afterState).checked = (stuff[24] === 't') ? true : false; getControlPanelElement('cb' + afterState + 'Trend').checked = (stuff[25] === 't') ? true : false; getControlPanelElement('sel' + afterState).value = stuff[26]; getControlPanelElement('sq' + afterState).style.background = COLORS[stuff[26]]; } getControlPanelElement('cbBurndownIdeal').checked = (stuff[27] === 't') ? true : false; getControlPanelElement('selBurndownIdeal').value = stuff[28]; getControlPanelElement('sqBurndownIdeal').style.background = COLORS[stuff[28]]; getControlPanelElement('cbBurnupIdeal').checked = (stuff[29] === 't') ? true : false; getControlPanelElement('selBurnupIdeal').value = stuff[30]; getControlPanelElement('sqBurnupIdeal').style.background = COLORS[stuff[30]]; updateTrendIdealChkBoxes(); } function updateTrendIdealChkBoxes() { var beforeState = getBeforeState(SCHEDULE_STATES); var afterState = getAfterState(SCHEDULE_STATES); setRelatedCheckbox(getControlPanelElement('cbDefinedTrend'), getControlPanelElement('cbDefined')); setRelatedCheckbox(getControlPanelElement('cbIn-ProgressTrend'), getControlPanelElement('cbIn-Progress')); setRelatedCheckbox(getControlPanelElement('cbCompletedTrend'), getControlPanelElement('cbCompleted')); setRelatedCheckbox(getControlPanelElement('cbAcceptedTrend'), getControlPanelElement('cbAccepted')); if (beforeState !== null) { setRelatedCheckbox(getControlPanelElement('cb' + beforeState + 'Trend'), getControlPanelElement('cb' + beforeState)); } if (afterState !== null) { setRelatedCheckbox(getControlPanelElement('cb' + afterState + 'Trend'), getControlPanelElement('cb' + afterState)); } } function setRelatedCheckbox(checkboxToSet, masterCheckbox) { if (masterCheckbox.checked) { checkboxToSet.disabled = false; } else { checkboxToSet.disabled = true; } } function createChart() { if (!RALLY.Mashup.Utilities.cookieExists(SETTINGS_COOKIE_NAME)) { RALLY.Mashup.Utilities.updateMashupCookie(SETTINGS_COOKIE_NAME, SETTINGS_COOKIE_DEFAULT, 30); } setControlStates(RALLY.Mashup.Utilities.readMashupCookie(SETTINGS_COOKIE_NAME)); document.getElementById('table_div').style.visibility = "hidden"; RALLY.Mashup.Utilities.showWait('chart_div'); BURNDOWN_CHART = new RALLY.Mashup.SuperCustomizableChart(BATCH_TOOLKIT, DROPDOWN.getSelectedOids(), DROPDOWN.getSelectedName(), DROPDOWN.getSelectedStart(), DROPDOWN.getSelectedEnd(), MASHUP_TYPE, buildConfig(), 'chart_div', 'table_div', null); BURNDOWN_CHART.display(); } function runScheduleStateQuery() { var queryObject = { key: 'storyStates', type: 'Hierarchical Requirement', attribute: 'Schedule State' }; BATCH_TOOLKIT.findAll(queryObject, addDatasetControlPanel); } function addEventListeners() { var i; if (document.addEventListener) { // For most browsers getControlPanelElement('cbTable').addEventListener('change', onDatasetChange, false); getControlPanelElement('rbStory').addEventListener('change', onDatasetChange, false); getControlPanelElement('rbTask').addEventListener('change', onDatasetChange, false); getControlPanelElement('rbToDo').addEventListener('change', onDatasetChange, false); for (i = 0; i < NUM_CHART_TYPES; i++) { getControlPanelElement('input' + i).addEventListener('change', nowClear, false); getControlPanelElement('span' + i).addEventListener('mouseup', nowCheck, false); } document.onmouseup = nowClear; } else if (document.attachEvent) { // For IE getControlPanelElement('cbTable').attachEvent('onclick', onDatasetChange); getControlPanelElement('rbStory').attachEvent('onclick', onDatasetChange); getControlPanelElement('rbTask').attachEvent('onclick', onDatasetChange); getControlPanelElement('rbToDo').attachEvent('onclick', onDatasetChange); for (i = 0; i < NUM_CHART_TYPES; i++) { getControlPanelElement('input' + i).attachEvent('onclick', nowClear); getControlPanelElement('span' + i).attachEvent('onclick', nowCheck); } document.attachEvent('onmouseup', nowClear); } } function getTarget(e) { e = e || window.event; if (typeof e.target !== 'undefined') { return e.target; } else if (typeof e.srcElement !== 'undefined') { return e.srcElement; } else { return null; } } function nowClear(e) { var t = getTarget(e); if (t.nodeName.toLowerCase() === "span") { for (var i = 0; i < NUM_CHART_TYPES; i++) { if (getControlPanelElement('input' + i).checked) { getControlPanelElement('span' + i).style.backgroundPosition = "0 -49px"; } else { getControlPanelElement('span' + i).style.backgroundPosition = "0 -0"; } } } } function nowCheck(e) { var t = getTarget(e); for (var i = 0; i < NUM_CHART_TYPES; i++) { if (t.id === "span" + i) { getControlPanelElement('input' + i).checked = true; getControlPanelElement('span' + i).style.backgroundPosition = "0 -49px"; } else { getControlPanelElement('span' + i).style.backgroundPosition = "0 -0"; } } updateUnitRadioButtons(); onDatasetChange(); } function initChartTypeButtons() { for (var i = 0; i < NUM_CHART_TYPES; i++) { if (getControlPanelElement('input' + i).checked) { getControlPanelElement('span' + i).style.backgroundPosition = "0 -49px"; } } } function initPage() { BATCH_TOOLKIT = new RALLY.Mashup.BatchToolkit('__WORKSPACE_OID__', '__PROJECT_OID__', '__PROJECT_SCOPING_UP__', '__PROJECT_SCOPING_DOWN__'); runScheduleStateQuery(); RALLY.Mashup.Utilities.showHelpIcon(165); RALLY.Mashup.Utilities.showPrintButton(); initChartTypeButtons(); addEventListeners(); DROPDOWN = new RALLY.Mashup.Dropdown(BATCH_TOOLKIT, MASHUP_TYPE, 'timeboxList', 'timeboxLabel', 'mu_super_customizable_' + MASHUP_TYPE.toLowerCase()); DROPDOWN.invoke(createChart); } </script> <style type="text/css"> body { background: white; } .lbl { text-align: left; font-size: 14px; } .AxisCaption { font-size: 12px; font-style: normal; } .AxisTickLabel { font-size: 10px; font-style: normal; } </style> <style type="text/css"> span.stackedbar { width: 36px; height: 49px; padding: 0 5px 0 0; background: url(/slm/mashup/1.21/images/stackedbar.gif) no-repeat; display: block; clear: left; float: left; } </style> <style type="text/css"> span.bar { width: 36px; height: 49px; padding: 0 5px 0 0; background: url(/slm/mashup/1.21/images/bar.gif) no-repeat; display: block; clear: left; float: left; } </style> <style type="text/css"> span.line { width: 36px; height: 49px; padding: 0 5px 0 0; background: url(/slm/mashup/1.21/images/line.gif) no-repeat; display: block; clear: left; float: left; } </style> <style type="text/css"> span.area { width: 36px; height: 49px; padding: 0 5px 0 0; background: url(/slm/mashup/1.21/images/area.gif) no-repeat; display: block; clear: left; float: left; } </style> <style type="text/css"> span.burndown { width: 36px; height: 49px; padding: 0 5px 0 0; background: url(/slm/mashup/1.21/images/burndown.gif) no-repeat; display: block; clear: left; float: left; } </style> <style type="text/css"> input.nodisplay { display: none; } </style> </head> <body> <div style="float:right" id="help"></div> <div style="float:left" id="title" class="titlebar">Super Customizable Release Chart</div> <table> <tr> <td style="text-align: left; width: 99%;"> <td style="text-align: right; width: 1%;"> <img id="do" onmouseover="RALLY.Mashup.Utilities.showcbButton();" onmouseout="hidecbMenu('buttons',event);" style="vertical-align: middle;" src="/slm/images/menu_actions.gif"/> <div style="position:relative;top:5px" align="left"> <div id="buttons" class="do-menu" style="left:0px;" onmouseover="document.body.style.cursor='pointer';" onmouseout="document.body.style.cursor='default';hidecbMenu('buttons',event);"> <a id="print" onclick="RALLY.Mashup.Utilities.printPage()">Print...</a> </div> </div> </td> </tr> </table> <div style="clear:both"></div> <table> <tr> <td id="timeboxLabel" class="lbl">Release Name</td> <td><select id="timeboxList"></select></td> </tr> </table> <table cellspacing="10" border="1"> <tr> <td valign="top"> <fieldset> <legend>Chart Type</legend> <table> <tr> <th width=80 align="left">Stacked Bar</th> <th width=80 align="left">Bar</th> </tr> <tr> <td width=80> <span id="span0" class="stackedbar"/> <input type="radio" class="nodisplay" id="input0" name="ctGroup" checked="checked"> </td> <td width=80> <span id="span1" class="bar"/> <input type="radio" class="nodisplay" id="input1" name="ctGroup"> </td> </tr> <tr> <th width=80 align="left">Line</th> <th width=80 align="left">Area</th> <th width=80 align="left">Burndown</th> </tr> <tr> <td width=80> <span id="span2" class="line"/> <input type="radio" class="nodisplay" id="input2" name="ctGroup"> </td> <td width=80> <span id="span3" class="area"/> <input type="radio" class="nodisplay" id="input3" name="ctGroup"> </td> <td width=80> <span id="span4" class="burndown"/> <input type="radio" class="nodisplay" id="input4" name="ctGroup"> </td> </tr> </table> </fieldset> <fieldset> <legend>Data Options</legend> <div id="datasetPanel"> </div> <p> <hr> <div id="idealPanel"> </div> </p> <p> <hr> Units <input type="radio" name="unit_type_group" id="rbStory" value="story" checked="checked"/> <label for="rbStory">Story</label> <input type="radio" name="unit_type_group" id="rbTask" value="task"/> <label for="rbTask">Task</label> <input type="radio" name="unit_type_group" id="rbToDo" value="todo"/> <label for="rbToDo">To Do</label> </p> <p> <hr> <input type="checkbox" name="cbTable" id="cbTable"/> <label for="cbTable">Show Data Table</label> <br/> </p> </fieldset> </td> <td> <table> <tr> <td class="lbl"> <div id="info_msg"></div> </td> </tr> <tr> <td> <div id="chart_div" style="width:600px; height:400px;"></div> </td> </tr> </table> </td> </tr> </table> <br/> <div id="table_div"></div> </body> </html>