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