3
function show_progress( ) {
4
global $db, $series, $specs;
6
$query = $db->prepare( 'SELECT count(*) as count, spec, status FROM status WHERE series = :series GROUP BY spec, status' );
7
$query->execute( array( ':series' => $series['series'] ) );
8
$spec_statuses = $query->fetchAll( );
10
foreach( $spec_statuses as $status ) {
11
$data['num'] = $status['count'];
12
$data['percent'] = $status['count'] / $specs[$status['spec']]['item_count'] * 100;
13
$progress[$status['spec']][$status['status']] = $data;
16
echo '<table class="progress">';
18
echo '<th>Specification</th>';
19
echo '<th>Actions</th>';
20
echo '<th>Progress</th>';
24
foreach( $progress as $spec => $statuses ) {
25
$green = $statuses['DONE']['percent'];
26
$yellow = $green + $statuses['INPROGRESS']['percent'];
28
if( $statuses['DONE']['num'] == null ) {
29
$statuses['DONE']['num'] = '0';
31
$content = $statuses['DONE']['num'] . ' of ' . $specs[$spec]['item_count'] . ' (' . round( (int) $green ) . '%)';
33
echo '<tr class="spec">';
34
echo '<td class="title"><a href="#tab-details/spec=' . $spec . '">' . $specs[$spec]['name'] . '</a></td>';
35
echo '<td class="actions">';
36
echo '<a href="' . $specs[$spec]['url'] . '">Edit</a> ';
37
if( strlen( $specs[$spec]['whiteboard'] ) > 0 ) {
38
echo '<a class="whiteboard" href="#">Whiteboard</a>';
41
echo '<td class="progress_bar">' . progress_bar( $content, $green, $yellow ) . '</td>';
44
if( strlen( $specs[$spec]['whiteboard'] ) > 0 ) {
45
echo '<tr class="whiteboard">';
46
echo '<td colspan="3">' . $specs[$spec]['whiteboard'] . '</td>';
50
$green_total += $statuses['DONE']['num'];
51
$yellow_total += $statuses['INPROGRESS']['num'];
52
$total += $specs[$spec]['item_count'];
55
$green_total_percent = $green_total / $total * 100;
56
$yellow_total_percent = ( $green_total + $yellow_total ) / $total * 100;
58
echo '<tr class="total">';
59
echo '<td class="title" colspan="2">Total</td>';
60
$content = $green_total . ' of ' . $total . ' (' . floor( $green_total_percent ) . '%)';
61
echo '<td class="progress_bar">' . progress_bar( $content, $green_total_percent, $yellow_total_percent ) . '</td>';
68
function work_items_list_new( ) {
69
global $db, $series, $specs, $users;
72
echo '<div id="wi_filters" class="toolbar show-on-js">';
73
// Filter by text search
74
echo '<div id="filter-text" class="filter filter-text" data-shorthand="text">Text <input type="text" name="filter-text" />';
75
echo '<a href="" class="clear">X</a></div>';
77
echo '<div id="filter-assignee" data-column="assignee" class="filter filter-dropdown filter-dropdown-multi" data-shorthand="a">Assignee ';
78
echo '<ul><li><span class="filter-title" data-default="Everybody">Everybody</span><ul class="items">';
79
// TODO: Only show users that have work items in the current series
80
foreach( $users as $nick => $name ) {
81
echo '<li><a href="#" data-value="' . $nick . '">' . $name . '</a></li>';
83
echo '</ul></li></ul>';
84
echo '<a href="" class="clear">X</a></div>';
85
// Filter by specification
86
echo '<div id="filter-specification" data-column="specification" class="filter filter-dropdown filter-dropdown-multi" data-shorthand="spec">Specification ';
87
echo '<ul><li><span class="filter-title" data-default="All specifications">All specifications</span><ul class="items">';
88
foreach( $specs as $spec ) {
89
echo '<li><a href="#" data-value="' . $spec['spec'] . '">' . $spec['short_name'] . '</a></li>';
91
echo '</ul></li></ul>';
92
echo '<a href="" class="clear">X</a></div>';
94
echo '<div id="filter-status" data-column="status" class="filter filter-dropdown filter-dropdown-multi" data-shorthand="s">Status ';
95
echo '<ul><li><span class="filter-title" data-default="All statuses">All statuses</span><ul class="items">';
96
echo '<li><a href="#" data-value="todo">To Do</a></li>';
97
echo '<li><a href="#" data-value="inprogress">In Progress</a></li>';
98
echo '<li><a href="#" data-value="blocked">Blocked</a></li>';
99
echo '<li><a href="#" data-value="done">Done</a></li>';
100
echo '<li><a href="#" data-value="postponed">Postponed</a></li>';
101
echo '</ul></li></ul>';
102
echo '<a href="" class="clear">X</a></div>';
104
echo '<a class="action" id="filter-clear" href="#">Clear filters and sort</a>';
106
echo '<div id="permalink_container">';
107
echo '<span class="action">Permalink</span>';
108
echo '<a id="permalink" href="#tab-details">Work item details</a>';
112
echo '<table id="workitems">';
115
echo '<th data-column="assignee" class="assignee" title="Sort by assignee"><span>Assignee</span></th>';
116
echo '<th data-column="item" class="item" title="Sort by work item status"><span>Work item</span></th>';
117
echo '<th data-column="specification" class="specification" title="Sort by specification" colspan="2"><span>Specification</span></th>';
122
$query = $db->prepare( 'SELECT * FROM status WHERE series = :series ORDER BY nick, FIELD( status, "TODO", "INPROGRESS", "BLOCKED", "DONE", "POSTPONED" ), spec ASC' );
123
$query->execute( array( ':series' => $series['series'] ) );
124
$items = $query->fetchAll( );
126
foreach( $items as $item ) {
127
$data_status = strtolower( $item['status'] );
128
// Add row with data attributes for sorting
129
echo '<tr data-status="' . $data_status . '" data-assignee="' . $item['nick'] . '" data-specification="' . $item['spec'] . '" data-item="' . htmlentities( strip_tags( $item['description'] ) ) . '">';
130
echo '<td data-column="assignee" class="assignee"><a href="#tab-details">' . get_user_name( $item['nick'] ) . '</a></td>';
131
echo '<td data-column="item" class="item item-' . $data_status . '"><span>' . $item['description'] . '</span></td>';
132
echo '<td data-column="specification" class="specification"><a href="#tab-details">' . $specs[$item['spec']]['short_name'] . '</a></td>';
133
echo '<td class="specification-link"><a class="action" href="' . $specs[$item['spec']]['url'] . '">Edit</a></td>';
141
function show_burndown( ) {
143
* Show the burndown chart
148
$day_count = day_difference( $series['date_start'], $series['date_end'] );
149
$previous_date = $series['date_start'];
151
/* This controls the padding between bars and is in percentage of the full chart width */
154
$query = $db->prepare( 'SELECT max(items_total) as max FROM history WHERE series = :series AND date >= :date_start AND date <= :date_end' );
155
$query->execute( array( ':series' => $series['series'], ':date_start' => $series['date_start'], ':date_end' => $series['date_end'] ) );
156
$result = $query->fetch( );
157
$max = $result['max'];
159
$padding = ( $day_count - 1 ) * $bar_padding;
160
$bar_width = ( 100 - $padding ) / $day_count;
162
echo '<div class="toolbar show-on-js">';
163
echo '<a class="action" href="#" id="highlight_events" title="Click to toggle highlights">Highlight events</a>';
166
echo '<div id="burndown_chart" class="no-js">';
168
echo '<div id="burndown_bars">';
170
$query = $db->prepare( 'SELECT * FROM history WHERE series = :series AND date >= :date_start AND date <= :date_end ORDER BY date ASC' );
171
$query->execute( array( ':series' => $series['series'], ':date_start' => $series['date_start'], ':date_end' => $series['date_end'] ) );
172
$dates = $query->fetchAll( );
174
foreach( $dates as $date ) {
175
// If we have empty record days, print invisible bars for them
176
if( day_difference( $date['date'], $previous_date ) > 1 ) {
177
for( $i = 1; $i < day_difference( $date['date'], $previous_date ); $i++ ) {
179
echo '<div class="bar_wrapper" style="width: ' . $bar_width . '%; padding-right: ' . $bar_padding . '%;">';
180
echo '<div class="bar" style="background-color: rgba( 0, 0, 0, 0 ); height: 100%; width: 100%;"></div>';
185
$height = $date['items_total'] / $max * 100;
186
$done_percentage = floor( $date['items_done'] / $date['items_total'] * 100 );
188
echo '<div class="bar_wrapper" style="width: ' . $bar_width . '%; padding-right: ' . $bar_padding . '%;" title="' . $date['date'] . ': ' . $date['items_done'] . ' of ' . $date['items_total'] . ' (' . $done_percentage . '%)">';
189
echo progress_bar_percent( null, $date['items_total'], $date['items_done'], $date['items_inprogress'], array( 'direction' => 'bottom', 'height' => $height ) );
192
$previous_date = $date['date'];
198
$query = $db->prepare( 'SELECT * FROM events WHERE series = :series' );
199
$query->execute( array( ':series' => $series['series'] ) );
200
$events = $query->fetchAll( );
202
foreach( $events as $event ) {
203
$days = day_difference( $event['date'], $series['date_start'] );
204
$padding_left = ( $days - 1 ) * $bar_padding;
205
$days_left = $days * $bar_width;
206
$margin_left = $padding_left + $days_left;
208
if( $event['date'] < gmdate( 'Y-m-d' ) ) {
215
echo '<div class="event ' . $class . '" style="left: ' . $margin_left . '%;">';
216
echo '<span title="' . $event['date'] . ' / ' . $event['event'] . '">' . $event['date'] . ' / ' . $event['event'] . '</span>';
220
// Burndown line for non-JS users
221
echo '<div class="burndown_line_nojs hide-on-js"></div>';
226
function show_timeline( ) {
227
global $db, $series, $specs;
231
$query = $db->prepare( 'SELECT * FROM status WHERE series = :series AND status = :status ORDER BY date_done DESC, description ASC' );
232
$query->execute( array( ':series' => $series['series'], ':status' => 'DONE' ) );
233
$done_items = $query->fetchAll( );
235
if( is_array( $done_items ) ) {
236
echo '<ul class="timeline">';
237
foreach( $done_items as $item ) {
238
$month = substr( $item['date_done'], 5, 2 );
239
if( $old_group != $month && $old_group != 'Earlier' ) {
240
if( $item['date_done'] < $series['date_start'] ) {
241
echo '<li class="group-title">Earlier</li>';
242
$old_group = 'Earlier';
244
$date = new DateTime( $item['date_done'] );
245
echo '<li class="group-title">' . $date->format( 'F Y' ) . '</li>';
250
echo '<li class="done">';
251
if( $old_group != 'Earlier' ) {
252
if( substr( $item['date_done'], 8, 2 ) != $old_day ) {
253
echo '<span class="date">' . (int) substr( $item['date_done'], 8, 2 ) . '</span> ';
255
echo '<span class="date"></span>';
257
$old_day = substr( $item['date_done'], 8, 2 );
259
echo $item['description'];
260
echo ' <span class="assignee">completed by <a href="#tab-details/' . $item['nick'] . '">' . get_user_name( $item['nick'] ) . '</a></span>';
261
echo ' <span class="specification">in ' . $specs[$item['spec']]['short_name'] . '</span>';
b'\\ No newline at end of file'