├── CHANGELOG.md ├── README.md └── Scrum ├── .gitignore ├── LICENSE ├── Scrum.php ├── files └── scrumboard.css ├── lang ├── strings_english.txt ├── strings_german.txt ├── strings_persian.txt └── strings_polish.txt └── pages ├── board.php └── config_page.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Scrum plugin Revision History 2 | 3 | ### v0.3 - 2014-11-10 4 | - Configuration page 5 | - Fall back to default color for undefined severity/resolution 6 | - Board column headers can now be localized 7 | - Fix bug in 'time left' calculation and improve display 8 | 9 | ### v0.2 - 2014-03-12 10 | - Translations 11 | - Scrum Board layout improvements 12 | - Sort versions on Scrum Board by date order descending 13 | - Remember the filter's version and category 14 | - Fix bug count to include statuses defined in board columns 15 | 16 | ### v0.1 - 2011-09-03 17 | - Initial release 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scrum Board plugin for MantisBT 2 | 3 | Copyright (c) 2011 - 2012 John Reese - http://noswap.com 4 | Copyright (c) 2012 - 2014 MantisBT Team - mantisbt-dev@lists.sourceforge.net 5 | 6 | Released under the [MIT license](http://opensource.org/licenses/MIT) 7 | 8 | See the [Changelog](https://github.com/mantisbt-plugins/scrum/blob/config/CHANGELOG.md). 9 | 10 | 11 | ## Description 12 | 13 | Adds a Scrum board based on Status, Category, and Target Version 14 | to MantisBT. 15 | 16 | 17 | ## Requirements 18 | 19 | The plugin requires [MantisBT](http://www.mantisbt.org/) version 1.2.6 or higher. 20 | 21 | If the [Source Integration plugin](https://github.com/mantisbt-plugins/source-integration) 22 | (version 0.16 or higher) is installed, the cards will display the number of 23 | changesets attached to each issue. 24 | 25 | 26 | ## Installation 27 | 28 | 1. Download or clone a copy of the [plugin's code](https://github.com/mantisbt-plugins/scrum). 29 | 2. Copy the plugin (the `Scrum/` directory) into your Mantis 30 | installation's `plugins/` directory. 31 | 3. While logged into your Mantis installation as an administrator, go to 32 | *Manage -> Manage Plugins*. 33 | 4. In the *Available Plugins* list, you'll find the *Scrum* plugin; 34 | click the **Install** link. 35 | 36 | 37 | ## Usage 38 | 39 | A new *Scrum Board* item is added to MantisBT's Main menu. 40 | 41 | It will display issues for the currently selected Project as Scrum Cards, 42 | which can be filtered by *Target Version* and *Category*, with the cards 43 | distributed in columns based on their Status. 44 | 45 | ### Configuration 46 | 47 | To change the Scrum Board's layout, go to the configuration page, where you 48 | can define: 49 | 50 | - *Board Columns*: specifies which Status goes into which column; 51 | - *Name* is a language-independent code for the Board Column (refer to the 52 | language files for the actual display value) 53 | - *Status* is a comma-delimited list of Statuses from the Status Enumeration 54 | (*status_enum_string*) to include in the Column 55 | - *Board Severity Colors* and *Board Resolution Colors* respectively 56 | define which color to use for display of each severity and resolution code. 57 | It is a comma-delimited list of elements with the form *Code:Color*, the 58 | code being the key from the corresponding Enumeration (Severity and 59 | Resolution). 60 | - *Sprint Length* specifies the duration of a sprint (in days) 61 | - *Always show Status* when checked, the Status name will be displayed in 62 | the Scrum Board's columns even if there are no cards with this Status 63 | (unchecked by default). 64 | - *Token Expiry* determines how long the plugin will remember the filter 65 | criteria on the Scrum Board. 66 | 67 | 68 | ## Support 69 | 70 | Problems or questions dealing with use and installation should be 71 | directed to the [#mantisbt](irc://freenode.net/mantisbt) IRC channel 72 | on Freenode. 73 | 74 | The latest source code can found on 75 | [Github](https://github.com/mantisbt-plugins/scrum). 76 | 77 | We encourage you to submit Bug reports and enhancements requests on the 78 | [Github issues tracker](https://github.com/mantisbt-plugins/scrum/issues). 79 | If you would like to propose a patch, do not hesitate to submit a new 80 | [Pull Request](https://github.com/mantisbt-plugins/scrum/compare/). 81 | -------------------------------------------------------------------------------- /Scrum/.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | -------------------------------------------------------------------------------- /Scrum/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 John Reese 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Scrum/Scrum.php: -------------------------------------------------------------------------------- 1 | name = plugin_lang_get("title"); 19 | $this->description = plugin_lang_get("description"); 20 | $this->page = 'config_page'; 21 | 22 | $this->version = "0.3"; 23 | $this->requires = array( 24 | "MantisCore" => "1.2.6", 25 | ); 26 | $this->uses = array( 27 | "Source" => "0.16", 28 | ); 29 | 30 | $this->author = "John Reese"; 31 | $this->contact = "john@noswap.com"; 32 | $this->url = "https://github.com/mantisbt-plugins/scrum"; 33 | } 34 | 35 | public function config() 36 | { 37 | return array( 38 | #$g_status_enum_string = '10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved,90:closed'; 39 | "board_columns" => array( 40 | "new" => array(10, 20, 30), 41 | "confirmed" => array(40, 50), 42 | "resolved" => array(80), 43 | ), 44 | 45 | #$g_severity_enum_string = '10:feature,20:trivial,30:text,40:tweak,50:minor,60:major,70:crash,80:block'; 46 | "board_severity_colors" => array( 47 | 10 => "green", 48 | 20 => "green", 49 | 30 => "green", 50 | 40 => "green", 51 | 50 => "gray", 52 | 60 => "gray", 53 | 70 => "orange", 54 | 80 => "red", 55 | ), 56 | 57 | #$g_resolution_enum_string = '10:open,20:fixed,30:reopened,40:unable to duplicate,50:not fixable,60:duplicate,70:not a bug,80:suspended,90:wont fix'; 58 | "board_resolution_colors" => array( 59 | 10 => "orange", 60 | 20 => "green", 61 | 30 => "red", 62 | 40 => "gray", 63 | 50 => "gray", 64 | 60 => "gray", 65 | 70 => "gray", 66 | 80 => "gray", 67 | 90 => "gray", 68 | ), 69 | 70 | "token_expiry" => 30 * ScrumPlugin::DURATION_DAY, 71 | "sprint_length" => 14 * ScrumPlugin::DURATION_DAY, 72 | "show_empty_status" => OFF, 73 | ); 74 | } 75 | 76 | public function hooks() 77 | { 78 | return array( 79 | "EVENT_MENU_MAIN" => "menu", 80 | ); 81 | } 82 | 83 | public function menu($event) 84 | { 85 | $links = array(); 86 | $links[] = '' . plugin_lang_get("board") . ''; 87 | 88 | return $links; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Scrum/files/scrumboard.css: -------------------------------------------------------------------------------- 1 | div.scrumbar { 2 | width: 49.5%; 3 | border: 1px dotted gray; 4 | padding: 0; 5 | } 6 | 7 | div.scrumbar#resolved_percent { 8 | float: left; 9 | } 10 | 11 | div.scrumbar#timeleft_percent { 12 | float: right; 13 | } 14 | 15 | div.scrumbar span { 16 | float: left; 17 | padding: 0.5em 1em; 18 | text-align: center; 19 | } 20 | 21 | div.scrumbar span.bar { 22 | padding: 0.5em 0em; 23 | background: #d2f5b0; 24 | } 25 | 26 | td.scrumcolumn { 27 | padding: 4px; 28 | vertical-align: top; 29 | } 30 | 31 | td.scrumcolumn hr { 32 | clear: both; 33 | border: 0; 34 | border-bottom: 1px dotted #aaa; 35 | height: 6px; 36 | } 37 | 38 | div.scrumblock { 39 | float: left; 40 | width: 230px; 41 | margin: 4px; 42 | 43 | background: #FAF3AA; 44 | border: 1px solid black; 45 | 46 | text-align: center; 47 | overflow: hidden; 48 | } 49 | 50 | div.scrumblock p { 51 | margin: 3px; 52 | } 53 | 54 | div.scrumblock p.bugid { 55 | float: left; 56 | color: blue; 57 | } 58 | 59 | div.scrumblock p.commits { 60 | float: right; 61 | color: black; 62 | } 63 | 64 | div.scrumblock p.category { 65 | font-weight: bold; 66 | } 67 | 68 | div.scrumblock p.summary { 69 | clear: both; 70 | width: 100%; 71 | height: 5em; 72 | border-top: 1px solid #e7df8a; 73 | border-bottom: 1px solid #e7df8a; 74 | padding-top: 3px; 75 | text-align: left; 76 | overflow: hidden; 77 | } 78 | 79 | div.scrumblock span.project { 80 | font-weight: bold; 81 | } 82 | 83 | div.scrumblock p.priority { 84 | float: left; 85 | vertical-align: top; 86 | } 87 | 88 | div.scrumblock p.severity { 89 | float: left; 90 | width: 1.2em; 91 | height: 1.2em; 92 | } 93 | 94 | div.scrumblock p.resolution { 95 | float: right; 96 | width: 1.2em; 97 | height: 1.2em; 98 | } 99 | 100 | div.scrumblock p.handler { 101 | padding-top: 3px; 102 | } 103 | 104 | -------------------------------------------------------------------------------- /Scrum/lang/strings_english.txt: -------------------------------------------------------------------------------- 1 | '; 28 | $s_plugin_Scrum_reference_enum = 'Reference enumeration (%s):
%s'; 29 | $s_plugin_Scrum_board_severity_colors_label = 'Board Severity Colors'; 30 | $s_plugin_Scrum_board_resolution_colors_label = 'Board Resolution Colors'; 31 | $s_plugin_Scrum_color = 'Color'; 32 | $s_plugin_Scrum_colors_info = 'Define the colors assigned to each %s, as a comma-delimited list of elements with the form <Code:Color>.
Note: undefined codes will display in white on the Cards. You can either use standard CSS color names or hex values.'; 33 | $s_plugin_Scrum_sprint_length_label = 'Sprint Length'; 34 | $s_plugin_Scrum_sprint_length_info = 'The duration of the Sprint in days'; 35 | $s_plugin_Scrum_show_empty_status_label = 'Always show Status'; 36 | $s_plugin_Scrum_show_empty_status_info = 'If checked, the Status is displayed even if does not contain any Cards'; 37 | $s_plugin_Scrum_token_expiry_label = 'Token Expiry'; 38 | $s_plugin_Scrum_token_expiry_info = 'Number of days to remember the filter criteria selection on the Scrum Board'; 39 | $s_plugin_Scrum_action_update = 'Update'; 40 | -------------------------------------------------------------------------------- /Scrum/lang/strings_german.txt: -------------------------------------------------------------------------------- 1 | status][] = $bug; 156 | 157 | $source_count[$bug_id] = $use_source 158 | ? count( SourceChangeset::load_by_bug( $bug_id ) ) 159 | : '' ; 160 | if( $bug->status >= $resolved_threshold ) { 161 | $resolved_count++; 162 | } 163 | } 164 | 165 | $bug_count = count( $bug_ids ); 166 | if( $bug_count > 0 ) { 167 | $resolved_percent = floor( 100 * $resolved_count / $bug_count ); 168 | 169 | $bug_percentage_by_column = array(); 170 | foreach( $columns as $column => $statuses ) { 171 | $bug_count_for_column = 0; 172 | 173 | foreach( $statuses as $l_status ) { 174 | if( array_key_exists( $l_status, $bugs ) ) { 175 | $bug_count_for_column += count( $bugs[$l_status] ); 176 | } 177 | } 178 | 179 | $bug_percentage_by_column[$column] = $bug_count_for_column / $bug_count * 100; 180 | } 181 | } else { 182 | $resolved_percent = 0; 183 | $bug_percentage_by_column = 100 / count( $columns ); 184 | } 185 | 186 | if( $target_version ) { 187 | foreach( $project_ids as $project_id ) { 188 | $version_id = version_get_id( $target_version, $project_id, true ); 189 | if( $version_id !== false ) { 190 | break; 191 | } 192 | } 193 | 194 | $version = version_get( $version_id ); 195 | $time_diff = max( 0, $version->date_order - time() ); 196 | $timeleft_percent = 100 - min( 100, 100 * $time_diff / $sprint_length ); 197 | 198 | if( $time_diff >= ( 2 * ScrumPlugin::DURATION_WEEK ) ) { 199 | $timeleft_string = sprintf( 200 | plugin_lang_get( 'time_weeks' ), 201 | floor( $time_diff / ScrumPlugin::DURATION_WEEK ) 202 | ); 203 | } elseif( $time_diff >= ( 2 * ScrumPlugin::DURATION_DAY ) ) { 204 | $timeleft_string = sprintf( 205 | plugin_lang_get( 'time_days' ), 206 | floor( $time_diff / ScrumPlugin::DURATION_DAY ) 207 | ); 208 | } elseif( $time_diff > ScrumPlugin::DURATION_HOUR ) { 209 | $timeleft_string = sprintf( 210 | plugin_lang_get( 'time_hours' ), 211 | floor( $time_diff / ScrumPlugin::DURATION_HOUR ) 212 | ); 213 | } elseif( $time_diff > 0 ) { 214 | $timeleft_string = plugin_lang_get( 'time_1hour' ); 215 | } else { 216 | $timeleft_string = plugin_lang_get( 'time_up' ); 217 | } 218 | } 219 | 220 | html_page_top( plugin_lang_get( 'board' ) ); 221 | ?> 222 | 223 | 224 | 225 |
226 | 227 | 228 | 229 | 230 | 258 | 259 | 260 | 261 | 262 | 286 | 287 | 288 | 289 | 290 | $statuses ): ?> 291 | 292 | 293 | 294 | 295 | 296 | 297 | $statuses ) { 302 | ?> 303 | 376 | 379 | 380 | 381 |
231 | 232 |
233 | 234 | 235 | 244 | 245 | 254 | 255 | 256 |
257 |
263 |
264 | 50 ): ?> 265 | 266 | 267 |   268 | 269 |
270 | 271 | 272 |
273 | 50 ): ?> 274 | 275 | 276 |   277 | 278 |
279 | 280 |
281 | 282 | 283 |
284 | 285 |
307 | 315 |
316 | 324 |

325 | 326 |

severity, $sevcolors ) 332 | ? $sevcolors[$bug->severity] 333 | : 'white' ; 334 | $rescolor = array_key_exists( $bug->resolution, $rescolors ) 335 | ? $rescolors[$bug->resolution] 336 | : 'white' ; 337 | ?> 338 |
339 |

priority ) ?>

340 |

341 |

id] ?>

342 |

project_id != $current_project ) { 344 | $project_name = project_get_name( $bug->project_id ); 345 | echo '' . $project_name . ' - '; 346 | } 347 | echo category_full_name( $bug->category_id, false ) ?> 348 |

349 |

350 | id ) 352 | . ': ' 353 | . bug_format_summary( $bug->id, 0 ); 354 | ?> 355 | 356 |

357 |

360 |

361 |

364 |

365 |

handler_id > 0 ? user_get_name( $bug->handler_id ) : '' 367 | ?>

368 |
369 | 375 |
382 | 383 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | > 26 | 30 | 54 | 55 | 56 | 57 | 58 | > 59 | 65 | 81 | 82 | 83 | 84 | 85 | > 86 | 92 | 108 | 109 | 110 | 111 | 112 | > 113 | 117 | 121 | 122 | 123 | 124 | 125 | > 126 | 130 | 134 | 135 | 136 | 137 | 138 | > 139 | 143 | 147 | 148 | 149 | 150 | 151 | 152 | 153 |
27 |
28 | 29 |
31 | 32 | 33 | 34 | 35 | 36 | $t_value ) { 40 | echo ''; 41 | echo ''; 42 | echo ''; 43 | echo ''; 44 | } 45 | ?> 46 |
47 | 53 |
60 |
61 | 63 | 64 |
66 |
74 | 80 |
87 |
88 | 90 | 91 |
93 |
101 | 107 |
114 |
115 | 116 |
118 | 120 |
127 |
128 | 129 |
131 | > 133 |
140 |
141 | 142 |
144 | 146 |
"/>
154 |
155 | 156 |