diff --git a/include/ajax.reports.php b/include/ajax.reports.php index 8b09100225f0d875c93476253a7eab4ae81873b4..1dd3247f9eb76cc8407bcd389ddccde13094145b 100644 --- a/include/ajax.reports.php +++ b/include/ajax.reports.php @@ -35,8 +35,12 @@ class OverviewReportAjaxAPI extends AjaxController { } function getData() { - $start = $this->get('start', strtotime('last month')); - $stop = $this->get('stop', time()); + $start = $this->get('start', 'last month'); + $stop = $this->get('stop', 'now'); + if (substr($stop, 0, 1) == '+') + $stop = $start . $stop; + $start = 'FROM_UNIXTIME('.strtotime($start).')'; + $stop = 'FROM_UNIXTIME('.strtotime($stop).')'; $groups = array( "dept" => array( @@ -67,45 +71,41 @@ class OverviewReportAjaxAPI extends AjaxController { $info = $groups[$group]; # XXX: Die if $group not in $groups - $res = db_query( - 'SELECT ' . $info['fields'] . ',' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.status=\'open\') AS Open,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND (A1.staff_id > 0 OR A1.team_id > 0)' - .' AND A1.status=\'open\') AS Assigned,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND (A1.staff_id = 0 AND A1.team_id = 0)' - .' AND A1.status=\'open\') AS Unassigned,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.isanswered = 0' - .' AND A1.status=\'open\') AS Unanswered,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.isoverdue = 1' - .' AND A1.status=\'open\') AS Overdue,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.status=\'closed\') AS Closed,' - .'(SELECT COUNT(A1.ticket_id) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.reopened is not null) AS Reopened,' - .'(SELECT FORMAT(AVG(DATEDIFF(A1.closed, A1.created)),1) FROM '.TICKET_TABLE - .' A1 WHERE A1.'.$info['pk'].' = T1.'.$info['pk'] - .' AND A1.status=\'closed\') AS ServiceTime' - .' FROM ' . $info['table'] . ' T1' + $queries=array( + array(7, 'SELECT '.$info['fields'].', + COUNT(*)-COUNT(NULLIF(A1.state, "created")) AS Opened, + COUNT(*)-COUNT(NULLIF(A1.state, "assigned")) AS Assigned, + COUNT(*)-COUNT(NULLIF(A1.state, "overdue")) AS Overdue, + COUNT(*)-COUNT(NULLIF(A1.state, "closed")) AS Closed, + COUNT(*)-COUNT(NULLIF(A1.state, "reopened")) AS Reopened, + FORMAT(AVG(DATEDIFF(T2.closed, T2.created)),1) AS ServiceTime, + FORMAT(AVG(DATEDIFF(B2.created, B1.created)),1) AS ResponseTime + FROM '.$info['table'].' T1 LEFT JOIN '.TICKET_TABLE.' T2 USING ('.$info['pk'].') + LEFT JOIN '.TICKET_EVENT_TABLE.' A1 USING (ticket_id) + LEFT JOIN '.TICKET_THREAD_TABLE.' B1 ON (B1.ticket_id = T2.ticket_id + AND B1.thread_type="M") + LEFT JOIN '.TICKET_THREAD_TABLE.' B2 ON (B2.pid = B1.id) + WHERE A1.timestamp BETWEEN '.$start.' AND '.$stop.' + OR B1.created BETWEEN '.$start.' AND '.$stop.' + OR T1.created BETWEEN '.$start.' AND '.$stop.' + GROUP BY '.$info['fields'].' + ORDER BY '.$info['fields']) ); $rows = array(); - while ($row = db_fetch_row($res)) { - $rows[] = $row; + foreach ($queries as $q) { + list($c, $sql) = $q; + $res = db_query($sql); + $i = 0; + while ($row = db_fetch_row($res)) { + if (count($rows) <= $i) + $rows[] = array_slice($row, 0, count($row) - $c); + $rows[$i] = array_merge($rows[$i], array_slice($row, -$c)); + $i++; + } } return array("columns" => array_merge($info['headers'], - array('Open','Assigned','Unassigned','Unanswered', - 'Overdue','Closed','Reopened','Service Time')), + array('Open','Assigned','Overdue','Closed','Reopened', + 'Service Time','Response Time')), "data" => $rows); } diff --git a/scp/css/dashboard.css b/scp/css/dashboard.css index 8d4e77facc4a85994759840bce8c5696ef95a0a4..43ec338890ac6bcce9d7647f85841657d362fe88 100644 --- a/scp/css/dashboard.css +++ b/scp/css/dashboard.css @@ -30,7 +30,7 @@ span.label { #table-here tr :not(:first-child) { text-align: right; padding-right: 2.3em; - width: 10%; + width: 12%; } #table-here tr :not(:first-child) div { position: relative; diff --git a/scp/dashboard.php b/scp/dashboard.php index 34070aa55a4eede3294db04234d178aa28a9affa..8756ca1ea86522eb77c8a7b8ee381f3928de27f9 100644 --- a/scp/dashboard.php +++ b/scp/dashboard.php @@ -55,7 +55,10 @@ require(STAFFINC_DIR.'header.inc.php'); <div style="position:absolute;right:0;top:0" id="line-chart-legend"></div> </div> -<h2>Current statistics</h2> +<hr/> +<h2>Statistics</h2> +<p>Statistics of tickets organized by department, help topic, and staff +member.</p> <ul class="nav nav-tabs" id="tabular-navigation"></ul> <div id="table-here"></div> diff --git a/scp/js/dashboard.inc.js b/scp/js/dashboard.inc.js index 0141204d52bc2f762ab4d9112939b62c95fca8e7..6411d302ec23e673ed40f308961dc1a1e9190ee3 100644 --- a/scp/js/dashboard.inc.js +++ b/scp/js/dashboard.inc.js @@ -1,5 +1,6 @@ (function ($) { - function refresh() { + var current_tab; + function refresh(e) { $('#line-chart-here').empty(); $('#line-chart-legend').empty(); var r = new Raphael('line-chart-here'), @@ -100,6 +101,7 @@ }); } }); + if (this.start) build_table.apply(this); return false; } $(function() { $('tabular-navigation').tab(); }); @@ -120,38 +122,41 @@ .append(json[key]))); first=false; } - build_table.apply($('#tabular-navigation li:first-child a')) + build_table.apply($('#tabular-navigation li:first-child a')[0]) } }); }); - function build_table(e) { - $('#table-here').empty(); - $(this).tab('show'); - var group = $(this).attr('table-group') + var start, stop; + function build_table() { + if (this.tagName == 'A') { + current_tab = $(this).tab('show'); + } + else if (this.start) { + start = this.start.value || 'last month'; + stop = this.period.value || 'now'; + } + var group = current_tab.attr('table-group'); $.ajax({ method: 'GET', dataType: 'json', url: 'ajax.php/report/overview/table', - data: {group: group}, + data: {group: group, start: start, stop: stop}, success: function(json) { - var q = $('<table>').attr({class:'table table-condensed table-striped'}); - var h = $('<tr>').appendTo($('<thead>').appendTo(q)); - var pagesize = 25; - var min = [], max = [], range = []; + var q = $('<table>').attr({'class':'table table-condensed table-striped'}), + h = $('<tr>').appendTo($('<thead>').appendTo(q)), + pagesize = 25, + max = []; for (var c in json.columns) { h.append($('<th>').append(json.columns[c])); - min.push(1e8); max.push(0); + max.push(0); } for (y in json.data) { row = json.data[y]; for (x in row) { - min[x] = Math.min(min[x], parseFloat(row[x]||0)); max[x] = Math.max(max[x], parseFloat(row[x]||0)); } } - for (i=1; i<min.length; i++) - range[i] = max[i] - min[i] for (var i in json.data) { if (i % pagesize === 0) b = $('<tbody>').attr({'page':i/pagesize+1}).appendTo(q); @@ -171,7 +176,7 @@ } tr.append($('<td>') .append($('<div>').append( - $('<div>').css(val && range[j] ? { + $('<div>').css(val ? { 'background-color': color, 'width': size, 'height': size, @@ -183,7 +188,12 @@ } } } - $('#table-here').append(q); + if (json.data.length == 0) { + $('<tbody>').attr('page','1').append($('<tr>').append( + $('<td>').attr('colspan','8').append( + 'No data for this timeframe found'))).appendTo(q); + } + $('#table-here').empty().append(q); // ----------------------> Pagination <--------------------- function goabs(e) { @@ -248,5 +258,5 @@ return false; } $(refresh); - $('#timeframe-form').submit(refresh); + $(function() { $('#timeframe-form').submit(refresh); }); })(window.jQuery);