OLD | NEW |
(Empty) | |
| 1 [define category_css]css/ph_detail.css[end] |
| 2 [include "../framework/master-header.ezt" "showtabs"] |
| 3 |
| 4 [# Note: base permission for this page is EditIssue] |
| 5 |
| 6 [if-any read_only][include "../framework/read-only-rejection.ezt"] |
| 7 [else] |
| 8 |
| 9 <div style="margin-top: 0; padding: 3px;" class="closed"> |
| 10 <form action="bulkedit.do" method="POST" style="margin: 0; padding: 0" enctype=
"multipart/form-data" |
| 11 id="bulk_form"> |
| 12 |
| 13 <input type="hidden" name="can" value=[can] > |
| 14 <input type="hidden" name="start" value=[start] > |
| 15 <input type="hidden" name="num" value=[num] > |
| 16 <input type="hidden" name="q" value="[query]"> |
| 17 <input type="hidden" id="sort" name="sort" value="[sortspec]"> |
| 18 <input type="hidden" name="groupby" value="[groupby]"> |
| 19 <input type="hidden" name="colspec" value="[colspec]"> |
| 20 <input type="hidden" name="x" value="[grid_x_attr]"> |
| 21 <input type="hidden" name="y" value="[grid_y_attr]"> |
| 22 <input type="hidden" name="mode" value="[if-any grid_mode]grid[end]"> |
| 23 <input type="hidden" name="cells" value="[grid_cell_mode]"> |
| 24 |
| 25 <input type="hidden" name="ids" |
| 26 value="[for issues][issues.local_id][if-index issues last][else], [end][
end]"> |
| 27 <input type="hidden" name="token" value="[form_token]"> |
| 28 <table cellpadding="0" cellspacing="0" border="0"> |
| 29 <tr><td> |
| 30 |
| 31 <table cellspacing="0" cellpadding="3" border="0" class="rowmajor vt"> |
| 32 <tr><th>Issues:</th> |
| 33 <td colspan="2"> |
| 34 [for issues] |
| 35 <a href="detail?id=[issues.local_id]" title="[issues.summary]" |
| 36 [if-any issues.closed]class=closed_ref[end] |
| 37 >[if-any issues.closed] [end][issues.local_id][if-any issues.closed
] [end]</a>[if-index issues last][else], [end] |
| 38 [end] |
| 39 </td> |
| 40 </tr> |
| 41 |
| 42 <tr> |
| 43 <th>Comment:</th> |
| 44 <td colspan="2"> |
| 45 <textarea cols="75" rows="6" name="comment" id="comment" class="issue_text"
>[initial_comment]</textarea> |
| 46 [if-any errors.comment] |
| 47 <div class="fielderror">[errors.comment]</div> |
| 48 [end] |
| 49 </td> |
| 50 </tr> |
| 51 |
| 52 <tr><th width="10%">Status:</th><td colspan="2"> |
| 53 [include "issue-bulk-operator-part.ezt" "statusenter" ""] |
| 54 <input id="statusenter" autocomplete="off" style="width: 12em" |
| 55 name="status" value="[initial_status]"> |
| 56 <span id="merge_area" style="margin-left:2em;"> |
| 57 Merge into issue: |
| 58 <input type="text" id="merge_into" name="merge_into" style="width
: 5em" |
| 59 value="[is initial_merge_into "0"][else][initial_merge_int
o][end]"> |
| 60 </span> |
| 61 [if-any errors.merge_into_id] |
| 62 <div class="fielderror">[errors.merge_into_id]</div> |
| 63 [end] |
| 64 </td> |
| 65 </tr> |
| 66 <tr><th width="10%">Owner:</th><td colspan="2"> |
| 67 [include "issue-bulk-operator-part.ezt" "ownerenter" ""] |
| 68 <input id="ownerenter" type="text" autocomplete="off" style="width: 12e
m" |
| 69 name="owner" value="[initial_owner]"> |
| 70 [if-any errors.owner] |
| 71 <div class="fielderror">[errors.owner]</div> |
| 72 [end] |
| 73 </td> |
| 74 </tr> |
| 75 <tr><th>Cc:</th><td colspan="2"> |
| 76 [include "issue-bulk-operator-part.ezt" "memberenter" "multi"] |
| 77 <input type="text" multiple id="memberenter" autocomplete="off" style="
width: 30em" |
| 78 name="cc" value="[initial_cc]"> |
| 79 [if-any errors.cc] |
| 80 <div class="fielderror">[errors.cc]</div> |
| 81 [end] |
| 82 </td> |
| 83 </tr> |
| 84 |
| 85 <tr><th>Components:</th><td colspan="2"> |
| 86 [include "issue-bulk-operator-part.ezt" "componententer" "multi"] |
| 87 <input type="text" id="componententer" style="width:30em" |
| 88 name="components" value="[initial_components]"> |
| 89 [if-any errors.components] |
| 90 <div class="fielderror">[errors.components]</div> |
| 91 [end] |
| 92 </td></tr> |
| 93 |
| 94 <tbody class="collapse"> |
| 95 [# Show some field editing elements immediately, others can be revealed.] |
| 96 [define any_fields_to_reveal]No[end] |
| 97 [for fields] |
| 98 [if-any fields.applicable] |
| 99 [# TODO(jrobbins): determine applicability dynamically and update field
s in JS] |
| 100 <tr [if-any fields.display][else]class="ifExpand"[define any_fields_to_
reveal]Yes[end][end]> |
| 101 <th>[fields.field_name]:</th> |
| 102 <td colspan="2"> |
| 103 [define widget_id]custom_[fields.field_id][end] |
| 104 [define multi][if-any fields.field_def.is_multivalued_bool]multi[en
d][end] |
| 105 [include "issue-bulk-operator-part.ezt" widget_id multi] |
| 106 [include "field-value-widgets.ezt" False] |
| 107 <div class="fielderror" style="display:none" id="error_custom_[fiel
ds.field_id]"></div> |
| 108 </td> |
| 109 <tr> |
| 110 [end] |
| 111 [end] |
| 112 [is any_fields_to_reveal "Yes"] |
| 113 <tr class="ifCollapse"> |
| 114 <td colspan="2"><a href="#" class="toggleCollapse">Show all fields</a><
t/td> |
| 115 </tr> |
| 116 [end] |
| 117 </tbody> |
| 118 |
| 119 <tr><th>Labels:</th> |
| 120 <td colspan="2" class="labelediting"> |
| 121 <div id="enterrow1"> |
| 122 <input type="text" class="labelinput" id="label0" size="20" autocomplet
e="off" |
| 123 name="label" value="[label0]"> |
| 124 <input type="text" class="labelinput" id="label1" size="20" autocomplet
e="off" |
| 125 name="label" value="[label1]"> |
| 126 <input type="text" class="labelinput" id="label2" size="20" autocomplet
e="off" |
| 127 data-show-id="enterrow2" data-hide-id="addrow1" |
| 128 name="label" value="[label2]"> <span id="addrow1" class="fakelin
k" data-instead="enterrow2">Add a row</span> |
| 129 </div> |
| 130 <div id="enterrow2" style="display:none"> |
| 131 <input type="text" class="labelinput" id="label3" size="20" autocomplet
e="off" |
| 132 name="label" value="[label3]"> |
| 133 <input type="text" class="labelinput" id="label4" size="20" autocomplet
e="off" |
| 134 name="label" value="[label4]"> |
| 135 <input type="text" class="labelinput" id="label5" size="20" autocomplet
e="off" |
| 136 data-show-id="enterrow3" data-hide-id="addrow2" |
| 137 name="label" value="[label5]"> <span id="addrow2" class="fakelin
k" data-instead="enterrow3">Add a row</span> |
| 138 </div> |
| 139 <div id="enterrow3" style="display:none"> |
| 140 <input type="text" class="labelinput" id="label6" size="20" autocomplet
e="off" |
| 141 name="label" value="[label6]"> |
| 142 <input type="text" class="labelinput" id="label7" size="20" autocomplet
e="off" |
| 143 name="label" value="[label7]"> |
| 144 <input type="text" class="labelinput" id="label8" size="20" autocomplet
e="off" |
| 145 data-show-id="enterrow4" data-hide-id="addrow3" |
| 146 name="label" value="[label8]"> <span id="addrow3" class="fakelin
k" data-instead="enterrow4">Add a row</span> |
| 147 </div> |
| 148 <div id="enterrow4" style="display:none"> |
| 149 <input type="text" class="labelinput" id="label9" size="20" autocomplet
e="off" |
| 150 name="label" value="[label9]"> |
| 151 <input type="text" class="labelinput" id="label10" size="20" autocomple
te="off" |
| 152 name="label" value="[label10]"> |
| 153 <input type="text" class="labelinput" id="label11" size="20" autocomple
te="off" |
| 154 data-show-id="enterrow5" data-hide-id="addrow4" |
| 155 name="label" value="[label11]"> <span id="addrow4" class="fakeli
nk" data-instead="enterrow5">Add a row</span> |
| 156 </div> |
| 157 <div id="enterrow5" style="display:none"> |
| 158 <input type="text" class="labelinput" id="label12" size="20" autocomple
te="off" |
| 159 name="label" value="[label12]"> |
| 160 <input type="text" class="labelinput" id="label13" size="20" autocomple
te="off" |
| 161 name="label" value="[label13]"> |
| 162 <input type="text" class="labelinput" id="label14" size="20" autocomple
te="off" |
| 163 data-show-id="enterrow6" data-hide-id="addrow5" |
| 164 name="label" value="[label14]"> <span id="addrow5" class="fakeli
nk" data-instead="enterrow6">Add a row</span> |
| 165 </div> |
| 166 <div id="enterrow6" style="display:none"> |
| 167 <input type="text" class="labelinput" id="label15" size="20" autocomple
te="off" |
| 168 name="label" value="[label15]"> |
| 169 <input type="text" class="labelinput" id="label16" size="20" autocomple
te="off" |
| 170 name="label" value="[label16]"> |
| 171 <input type="text" class="labelinput" id="label17" size="20" autocomple
te="off" |
| 172 data-show-id="enterrow7" data-hide-id="addrow6" |
| 173 name="label" value="[label17]"> <span id="addrow6" class="fakeli
nk" data-instead="enterrow7">Add a row</span> |
| 174 </div> |
| 175 <div id="enterrow7" style="display:none"> |
| 176 <input type="text" class="labelinput" id="label18" size="20" autocomple
te="off" |
| 177 name="label" value="[label18]"> |
| 178 <input type="text" class="labelinput" id="label19" size="20" autocomple
te="off" |
| 179 name="label" value="[label19]"> |
| 180 <input type="text" class="labelinput" id="label20" size="20" autocomple
te="off" |
| 181 data-show-id="enterrow8" data-hide-id="addrow7" |
| 182 name="label" value="[label20]"> <span id="addrow7" class="fakeli
nk" data-instead="enterrow8">Add a row</span> |
| 183 </div> |
| 184 <div id="enterrow8" style="display:none"> |
| 185 <input type="text" class="labelinput" id="label21" size="20" autocomple
te="off" |
| 186 name="label" value="[label21]"> |
| 187 <input type="text" class="labelinput" id="label22" size="20" autocomple
te="off" |
| 188 name="label" value="[label22]"> |
| 189 <input type="text" class="labelinput" id="label23" size="20" autocomple
te="off" |
| 190 name="label" value="[label23]"> |
| 191 </div> |
| 192 </td> |
| 193 </tr> |
| 194 |
| 195 [if-any page_perms.DeleteIssue] |
| 196 <tr><th width="10%">Move to project:</th><td colspan="2"> |
| 197 <input id="move_toenter" type="text" autocomplete="off" style="width: 1
2em" |
| 198 name="move_to"> |
| 199 [if-any errors.move_to] |
| 200 <div class="fielderror">[errors.move_to]</div> |
| 201 [end] |
| 202 </td> |
| 203 </tr> |
| 204 [end] |
| 205 |
| 206 [if-any show_captcha] |
| 207 <tr><th style="white-space:nowrap">Human Verification:</th> |
| 208 <td colspan="2"> |
| 209 [include "../framework/captcha-field.ezt"] |
| 210 </td> |
| 211 </tr> |
| 212 [end] |
| 213 |
| 214 <tr> |
| 215 <td colspan="3"><span id="confirmarea" class="novel" style="padding-top:5px;
margin:0"> |
| 216 <span id="confirmmsg"></span> |
| 217 [# TODO(jrobbins): <a href="TODO" target="_new">Learn more</a>] |
| 218 </span> |
| 219 </td> |
| 220 </tr> |
| 221 </table> |
| 222 |
| 223 |
| 224 |
| 225 [# TODO(jrobbins): <a class="ifClosed toggleHidden" href="#">More options</a
>] |
| 226 [# <a class="ifOpened" href="#" class="toggleHidden" style="background:#ccc;
padding: 4px;">Hide options</a>] |
| 227 [# <div class="ifOpened" style="background:#ccc; padding: 8px"><a href="#a
utmatically-generated">Bookmarkable link to these values</a></div>] |
| 228 [# <br><br>] |
| 229 |
| 230 |
| 231 |
| 232 |
| 233 <div style="padding:6px"> |
| 234 <input type="submit" id="submit_btn" name="btn" value="Update [num_issues] Iss
ue[is num_issues "1"][else]s[end]"> |
| 235 <input type="button" id="discard" name="nobtn" value="Discard"> |
| 236 |
| 237 <input type="checkbox" checked="checked" name="send_email" id="send_email" sty
le="margin-left:1em"> |
| 238 <label for="send_email" title="Send issue change notifications to interested u
sers">Send email</label> |
| 239 |
| 240 </div> |
| 241 |
| 242 |
| 243 |
| 244 [if-any show_progress] |
| 245 <div>Note: Updating [num_issues] issues will take approximately [num_seconds] s
econds.</div> |
| 246 <div id="progress"> |
| 247 </div> |
| 248 [end] |
| 249 |
| 250 </td> |
| 251 <td> |
| 252 <div class="tip"> |
| 253 <b>Usage:</b> This form allows you to update several issues at one |
| 254 time.<br><br> |
| 255 The same comment will be applied to all issues.<br><br> |
| 256 |
| 257 If specified, the status or owner you enter will be applied to all |
| 258 issues.<br><br> |
| 259 |
| 260 You may append or remove values in multi-valued fields by choosing the
+= or -= operators. |
| 261 To remove labels, preceed the label with a leading dash. (You may also
use a leading dash |
| 262 to remove individual items when using the += operator.) |
| 263 </div> |
| 264 </td> |
| 265 </tr> |
| 266 </table> |
| 267 |
| 268 |
| 269 </form> |
| 270 </div> |
| 271 |
| 272 [include "../framework/footer-script.ezt"] |
| 273 |
| 274 <script type="text/javascript" nonce="[nonce]"> |
| 275 runOnLoad(function() { |
| 276 document.getElementById('comment').select(); |
| 277 _lfidprefix = 'label'; |
| 278 _fetchOptions("[projectname]", "issueOptions", |
| 279 CS_env.token, [project.cached_content_timestamp]); |
| 280 _fetchUserProjects(false); |
| 281 setTimeout(_forceProperTableWidth, 100); |
| 282 |
| 283 _exposeExistingLabelFields(); |
| 284 _onload(); |
| 285 |
| 286 checksubmit(); |
| 287 setInterval(checksubmit, 700); [# catch changes that were not keystrokes, e.g.
, paste menu item.] |
| 288 |
| 289 |
| 290 |
| 291 function checksubmit() { |
| 292 var submit = document.getElementById('submit_btn'); |
| 293 var cg = document.getElementById('cg'); |
| 294 if (cg != undefined) { submit.disabled='disabled'; } |
| 295 |
| 296 submit.disabled='disabled'; |
| 297 var restrict_to_known = [if-any restrict_to_known]true[else]false[end]; |
| 298 var confirmmsg = document.getElementById('confirmmsg'); |
| 299 var statusenter = $('statusenter'); |
| 300 var merge_area = $('merge_area'); |
| 301 var statuses_offer_merge = [[] [for statuses_offer_merge]"[statuses_offer_merg
e]"[if-index statuses_offer_merge last][else],[end][end] ]; |
| 302 if (restrict_to_known && confirmmsg && confirmmsg.innerText.length > 0) { |
| 303 return; |
| 304 } |
| 305 if (cg == undefined || cg.value.length > 1) { |
| 306 submit.disabled=''; |
| 307 } |
| 308 |
| 309 if (statusenter) { |
| 310 var offer_merge = 'none'; |
| 311 for (var i = 0; i < statuses_offer_merge.length; i++) { |
| 312 if (statusenter.value == statuses_offer_merge[[]i]) offer_merge = ''; |
| 313 } |
| 314 merge_area.style.display = offer_merge; |
| 315 } |
| 316 } |
| 317 |
| 318 |
| 319 function disableFormElement(el) { |
| 320 el.readOnly = 'yes'; |
| 321 el.style.background = '#eee'; |
| 322 [# TODO(jrobbins): disable auto-complete ] |
| 323 } |
| 324 |
| 325 |
| 326 function bulkOnSubmit() { |
| 327 var inputs = document.getElementsByTagName('input'); |
| 328 for (var i = 0; i < inputs.length; i++) { |
| 329 disableFormElement(inputs[[]i]); |
| 330 } |
| 331 disableFormElement(document.getElementById('comment')); |
| 332 [if-any show_progress] |
| 333 var progress = document.getElementById('progress'); |
| 334 progress.innerText = 'Processing...'; |
| 335 [end] |
| 336 } |
| 337 |
| 338 |
| 339 function _checkAutoClear(inputEl, selectID) { |
| 340 var val = inputEl.value; |
| 341 var sel = document.getElementById(selectID); |
| 342 if (val.match(/^--+$/)) { |
| 343 sel.value = 'clear'; |
| 344 inputEl.value = ''; |
| 345 } else if (val) { |
| 346 sel.value = 'set'; |
| 347 } |
| 348 } |
| 349 |
| 350 |
| 351 function _ignoreWidgetIfOpIsClear(selectEl, inputID) { |
| 352 if (selectEl.value == 'clear') { |
| 353 document.getElementById(inputID).value = ''; |
| 354 } |
| 355 } |
| 356 |
| 357 $("bulk_form").addEventListener("submit", bulkOnSubmit); |
| 358 |
| 359 if ($("comment")) { |
| 360 $("comment").addEventListener("keyup", function(event) { |
| 361 _dirty(); |
| 362 return true; |
| 363 }); |
| 364 } |
| 365 if ($("statusenter")) { |
| 366 $("statusenter").addEventListener("focus", function(event) { |
| 367 _acof(event); |
| 368 }); |
| 369 $("statusenter").addEventListener("keyup", function(event) { |
| 370 _dirty(); |
| 371 _checkAutoClear(event.target, "op_statusenter"); |
| 372 return _confirmNovelStatus(event.target); |
| 373 }); |
| 374 } |
| 375 if ($("ownerenter")) { |
| 376 $("ownerenter").addEventListener("focus", function(event) { |
| 377 _acof(event); |
| 378 }); |
| 379 $("ownerenter").addEventListener("keyup", function(event) { |
| 380 _dirty(); |
| 381 _checkAutoClear(event.target, "op_ownerenter"); |
| 382 return true; |
| 383 }); |
| 384 } |
| 385 if ($("memberenter")) { |
| 386 $("memberenter").addEventListener("focus", function(event) { |
| 387 _acof(event); |
| 388 }); |
| 389 $("memberenter").addEventListener("keyup", function(event) { |
| 390 _dirty(); |
| 391 return true; |
| 392 }); |
| 393 } |
| 394 if ($("componententer")) { |
| 395 $("componententer").addEventListener("focus", function(event) { |
| 396 _acof(event); |
| 397 }); |
| 398 $("componententer").addEventListener("keyup", function(event) { |
| 399 _dirty(); |
| 400 return true; |
| 401 }); |
| 402 } |
| 403 |
| 404 if ($("move_toenter")) { |
| 405 $("move_toenter").addEventListener("focus", function(event) { |
| 406 _acof(event); |
| 407 }); |
| 408 $("move_toenter").addEventListener("keyup", function(event) { |
| 409 _dirty(); |
| 410 return true; |
| 411 }); |
| 412 } |
| 413 |
| 414 if ($("submit_btn")) { |
| 415 $("submit_btn").addEventListener("focus", function(event) { |
| 416 _acrob(null); |
| 417 }); |
| 418 $("submit_btn").addEventListener("mousedown", function(event) { |
| 419 _acrob(null); |
| 420 }); |
| 421 $("submit_btn").addEventListener("click", function(event) { |
| 422 _trimCommas(); |
| 423 }); |
| 424 } |
| 425 if ($("discard")) { |
| 426 $("discard").addEventListener("click", function(event) { |
| 427 _confirmDiscardEntry(this); |
| 428 event.preventDefault(); |
| 429 }); |
| 430 } |
| 431 |
| 432 var labelInputs = document.getElementsByClassName("labelinput"); |
| 433 for (var i = 0; i < labelInputs.length; ++i) { |
| 434 var labelInput = labelInputs[[]i]; |
| 435 labelInput.addEventListener("keyup", function (event) { |
| 436 _dirty(); |
| 437 if (event.target.getAttribute("data-show-id") && |
| 438 event.target.getAttribute("data-hide-id") && |
| 439 event.target.value) { |
| 440 _showID(event.target.getAttribute("data-show-id")); |
| 441 _hideID(event.target.getAttribute("data-hide-id")); |
| 442 } |
| 443 return _vallab(event.target); |
| 444 }); |
| 445 labelInput.addEventListener("blur", function (event) { |
| 446 return _vallab(event.target); |
| 447 }); |
| 448 labelInput.addEventListener("focus", function (event) { |
| 449 return _acof(event); |
| 450 }); |
| 451 } |
| 452 |
| 453 var addRowLinks = document.getElementsByClassName("fakelink"); |
| 454 for (var i = 0; i < addRowLinks.length; ++i) { |
| 455 var rowLink = addRowLinks[[]i]; |
| 456 rowLink.addEventListener("click", function (event) { |
| 457 _acrob(null); |
| 458 var insteadID = event.target.getAttribute("data-instead"); |
| 459 if (insteadID) |
| 460 _showInstead(insteadID, this); |
| 461 }); |
| 462 } |
| 463 |
| 464 }); |
| 465 </script> |
| 466 |
| 467 [end] |
| 468 |
| 469 [include "field-value-widgets-js.ezt"] |
| 470 [include "../framework/master-footer.ezt"] |
OLD | NEW |