blob: f3b69db5de7311e220d2ce1dca3156286910bddd [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001[define title]New Issue[end]
2[define category_css]css/ph_detail.css[end]
3[include "../framework/header.ezt" "hidetabs"]
4
5[# Note: base permission for this page is CreateIssue]
6
7[if-any read_only][include "../framework/read-only-rejection.ezt"]
8[else]
9
10<div id="color_control" style="margin-top: 0; padding: 3px;" class="closed [if-any code_font]codefont[end]">
11 <form action="entry.do" method="POST" style="margin: 0; padding: 0" enctype="multipart/form-data" id="create_issue_form">
12 <input type="hidden" name="token" value="[form_token]">
13 <input type="hidden" name="template_name" value="[template_name]">
14 <input type="hidden" name="star" id="star_input" value="1">
15 <table cellpadding="0" cellspacing="0" border="0" role="presentation">
16 <tr><td>
17
18 <table cellspacing="0" cellpadding="3" border="0" class="rowmajor vt" role="presentation">
19 [if-any offer_templates]
20 <tr><th><label for="template_name">Template:</label></th>
21 <td colspan="2">
22 <select name="template_name" id="template_name" data-project-name="[projectname]" ignore-dirty>
23 [for config.template_names]
24 <option role="option" value="[format "url"][config.template_names][end]" [is config.template_names template_name]selected=selected[end]>[config.template_names]</option>
25 [end]
26 </select>
27 <span id="mr-code-font-toggle-slot"></span>
28 </td>
29 </tr>
30 [else]
31 <tr>
32 <td colspan="3">
33 <span id="mr-code-font-toggle-slot"></span>
34 </td>
35 </tr>
36 [end]
37
38 <tr><th><label for="summary">Summary:</label></th>
39 <td colspan="2" class="inplace">
40 <input type="text" id="summary" name="summary" value="[initial_summary]" required data-clear-summary-on-click="[clear_summary_on_click]"
41 [if-any any_errors][else]autofocus[end]>
42 [if-any errors.summary]
43 <div class="fielderror">[errors.summary]</div>
44 [end]
45
46 [if-any any_errors][else]
47 <script type="text/javascript" nonce="[nonce]">
48 document.getElementById('summary').select();
49 </script>
50 [end]
51 </td>
52 </tr>
53
54 <tr><th rowspan="3"><label for="comment">Description:</label></th>
55 <td colspan="2">
56 <textarea style="width:100%" cols="80" rows="15" name="comment" id="comment" class="issue_text" required>[initial_description]
57</textarea> [# We want 1 final newline but 0 trailing spaces in the textarea]
58 [if-any errors.comment]
59 <div class="fielderror">[errors.comment]</div>
60 [end]
61 </td>
62 </tr>
63
64 <tr><td colspan="2">
65 [include "../features/cues-conduct.ezt"]
66 <div id="attachmentareadeventry"></div>
67 </td></tr>
68
69 <tr>
70 <td style="width: 12em">
71 [if-any allow_attachments]
72 <span id="attachprompt"><img width="16" height="16" src="/static/images/paperclip.png" border="0" alt="A paperclip">
73 <a href="#" id="attachafile">Attach a file</a></span>
74 <div id="attachmaxsize" style="margin-left:1.2em; display:none">Max. attachments: [max_attach_size]</div>
75 [if-any errors.attachments]
76 <div class="fielderror">[errors.attachments]</div>
77 [end]
78 [else]
79 <div style="color:#666">Issue attachment storage quota exceeded.</div>
80 [end]
81 </td>
82 <td id="star_cell" style="vertical-align: initial">
83 [# Note: if the user is permitted to enter an issue, they are permitted to star it.]
84 <a class="star" id="star" style="color:cornflowerblue;">&#9733;</a>
85 Notify me of issue changes, if enabled in <a id="settings" target="new" href="/hosting/settings">settings</a>
86 </td>
87 </tr>
88
89 <tr [if-any page_perms.EditIssue page_perms.EditIssueStatus][else]style="display:none;"[end]><th width="10%"><label for="statusenter">Status:</label></th>
90 <td colspan="2" class="inplace">
91 <select id="statusenter" name="status">
92 <option style="display: none" value="[initial_status]"></option>
93 </select>
94 </label>
95 </td>
96 </tr>
97 <tr [if-any page_perms.EditIssue page_perms.EditIssueOwner][else]style="display:none;"[end]><th width="10%"><label for="ownerenter">Owner:</label></th>
98 <td colspan="2">
99 <input type="text" id="ownerenter" autocomplete="off"
100 style="width:16em"
101 name="owner" value="[initial_owner]" aria-autocomplete="list" role="combobox">
102 <span class="availability_[owner_avail_state]" id="owner_avail_state"
103 style="padding-left:1em; [if-any owner_avail_message_short][else]display:none[end]">
104 &#9608;
105 <span id="owner_availability">[owner_avail_message_short]</span>
106 </span>
107 </div>
108 [if-any errors.owner]
109 <div class="fielderror">[errors.owner]</div>
110 [end]
111 </td>
112 </tr>
113
114 <tr [if-any page_perms.EditIssue page_perms.EditIssueCc][else]style="display:none;"[end]><th><label for="memberenter">Cc:</label></th>
115 <td colspan="2" class="inplace">
116 <input type="text" multiple id="memberenter" autocomplete="off" name="cc" value="[initial_cc]" aria-autocomplete="list" role="combobox">
117 [if-any errors.cc]
118 <div class="fielderror">[errors.cc]</div>
119 [end]
120 </td>
121 </tr>
122
123 [# TODO(jrobbins): page_perms.EditIssueComponent]
124 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end]><th><label for="components">Components:</label></th>
125 <td colspan="2" class="inplace">
126 <input type="text" id="components" autocomplete="off" name="components" value="[initial_components]" aria-autocomplete="list" role="combobox">
127 [if-any errors.components]
128 <div class="fielderror">[errors.components]</div>
129 [end]
130 </td>
131 </tr>
132
133 [if-any uneditable_fields]
134 <tr id="res_fd_banner"><th></th>
135 <td colspan="2" class="inplace" style="text-align:left; border-radius:25px">
136 <span style="background:var(--chops-orange-50); padding:5px; margin-top:10px; padding-left:10px; padding-right:10px; border-radius:25px">
137 <span style="padding-right:7px">
138 Info: Disabled inputs occur when you are not allowed to edit that restricted field.
139 </span>
140 <i id="res_fd_message" class="material-icons inline-icon" style="font-weight:bold; font-size:14px; vertical-align: text-bottom; cursor: pointer">
141 close</i>
142 </span>
143 </td>
144 </tr>
145 [end]
146
147 <tbody [if-any page_perms.EditIssue][else]style="display:none;"[end] class="collapse">
148 [define any_fields_to_reveal]No[end]
149 [for fields]
150 [if-any fields.applicable][if-any fields.field_def.is_approval_subfield][else][if-any fields.field_def.is_phase_field][else]
151 [# TODO(jrobbins): determine applicability dynamically and update fields in JS]
152 <tr [if-any fields.display][else]class="ifExpand"[define any_fields_to_reveal]Yes[end][end]>
153 <th id="[fields.field_id]_label">[fields.field_name]:</th>
154 <td colspan="2">
155 [if-any fields.is_editable]
156 [include "field-value-widgets.ezt" fields.field_def.is_multivalued_bool "" fields.field_def.is_required_bool ""]
157 <div class="fielderror" style="display:none" id="error_custom_[fields.field_id]"></div>
158 [else]
159 <input disabled value = "
160 [for fields.values]
161 [fields.values.val]
162 [end]
163 " style="text-align:right; width:12em" class="multivalued customfield" aria-labelledby="[fields.field_id]_label">
164 [end]
165 </td>
166 <tr>
167 [end][end][end]
168 [end]
169 [is any_fields_to_reveal "Yes"]
170 <tr class="ifCollapse">
171 <td colspan="2"><a href="#" class="toggleCollapse">Show all fields</a><t/td>
172 </tr>
173 [end]
174 </tbody>
175
176 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end]><th>Labels:</th>[# aria-labels added in label-fields.ezt]
177 <td colspan="2" class="labelediting">
178 [include "label-fields.ezt" "just-two" ""]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100179 [if-any errors.labels]
180 <div class="fielderror">[errors.labels]</div>
181 [end]
Copybara854996b2021-09-07 19:36:02 +0000182 </td>
183 </tr>
184
185 <tbody class="collapse">
186 [if-any page_perms.EditIssue]
187 <tr class="ifCollapse">
188 <td><a href="#" class="toggleCollapse">More options</a></td>
189 </tr>
190 [end]
191
192 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end] class="ifExpand"><th style="white-space:nowrap"><label for="blocked_on">Blocked on:</label></th>
193 <td class="inplace" colspan="2">
194 <input type="text" name="blocked_on" id="blocked_on" value="[initial_blocked_on]">
195 [if-any errors.blocked_on]
196 <div class="fielderror">[errors.blocked_on]</div>
197 [end]
198 </td>
199 </tr>
200 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end] class="ifExpand"><th><label for="blocking">Blocking:</label></th>
201 <td class="inplace" colspan="2">
202 <input type="text" name="blocking" id="blocking" value="[initial_blocking]" />
203 [if-any errors.blocking]
204 <div class="fielderror">[errors.blocking]</div>
205 [end]
206 </td>
207 </tr>
208
209 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end] class="ifExpand"><th><label for="hotlistsenter">Hotlists:</label></th>
210 <td class="inplace" colspan="2">
211 <input type="text" name="hotlists" autocomplete="off" id="hotlistsenter" value="[initial_hotlists]" />
212 [if-any errors.hotlists]
213 <div class="fielderror">[errors.hotlists]</div>
214 [end]
215 </td>
216 </tr>
217 </tbody>
218
219 [if-any approvals]
220 <tr>
221 <th>Launch Gates:</th>
222 <td colspan="7">
223 [include "launch-gates-widget.ezt"]
224 </td>
225 </tr>
226 [end]
227
228 [for fields][if-any fields.applicable][if-any fields.field_def.is_approval_subfield]
229 <tr is="subfield-row">
230 <th>[fields.field_def.parent_approval_name] [fields.field_name]:</th>
231 <td colspan="2">
232 [if-any fields.is_editable]
233 [include "field-value-widgets.ezt" False "tmpl" False ""]
234 <div class="fielderror" style="display:none" id="error_custom_[fields.field_id]"></div>
235 [else]
236 <input disabled value = "
237 [for fields.values]
238 [fields.values.val]
239 [end]
240 " style="text-align:right; width:12em" class="multivalued customfield" aria-labelledby="[fields.field_id]_label">
241 [end]
242 </td>
243 </tr>
244 [end][end][end]
245
246 [for issue_phase_names]
247 [for fields]
248 [is fields.phase_name issue_phase_names]
249 <tr>
250 <th>[issue_phase_names].[fields.field_name]:</th>
251 <td colspan="2">
252 [if-any fields.is_editable]
253 [include "field-value-widgets.ezt" False "tmpl" False issue_phase_names]
254 <div class="fielderror" style="display:none" id="error_custom_[issue_phase_names]_[fields.field_id]"></div>
255 [else]
256 <input disabled value = "
257 [for fields.values]
258 [fields.values.val]
259 [end]
260 " style="text-align:right; width:12em" class="multivalued customfield" aria-labelledby="[fields.field_id]_label">
261 [end]
262 </td>
263 </th>
264 </tr>
265 [end][end][end]
266
267 [include "../framework/label-validation-row.ezt"]
268 [include "../framework/component-validation-row.ezt"]
269 </table>
270
271 <div style="padding:6px">
272 <input type="submit" id="submit_btn" name="btn" value="Submit issue">
273 <input type="button" id="discard" name="nobtn" value="Discard">
274 </div>
275
276 </td>
277 </tr>
278 </table>
279 </form>
280</div>
281
282[include "../features/filterrules-preview.ezt"]
283
284<div style="margin-top:5em; margin-left: 8px;">
285 Problems submitting issues?
286 <a href="#" id="new-issue-feedback-link">
287 Send feedback
288 </a>
289</div>
290
291<div id="helparea"></div>
292
293<script type="text/javascript" nonce="[nonce]">
294runOnLoad(function() {
295 window.getTSMonClient().recordIssueEntryTiming();
296
297 if ($('launch-gates-table')) {
298 $('launch-gates-table').classList.remove('hidden');
299 }
300
301 if ($("template_name")) {
302 $("template_name").addEventListener("change", function(event) {
303 _switchTemplate(event.target.getAttribute("data-project-name"),
304 event.target.value)
305 });
306 }
307
308 if ($("summary")) {
309 var clearSummaryOnClick = $("summary").getAttribute("data-clear-summary-on-click");
310 if (clearSummaryOnClick) {
311 $("summary").addEventListener("keydown", function(event) {
312 _clearOnFirstEvent('[format "js"][initial_summary][end]');
313 });
314 }
315 $("summary").addEventListener("click", function(event) {
316 if (clearSummaryOnClick) {
317 _clearOnFirstEvent('[format "js"][initial_summary][end]');
318 }
319 checksubmit();
320 });
321 $("summary").addEventListener("focus", function(event) {
322 _acrob(null);
323 _acof(event);
324 });
325 $("summary").addEventListener("keyup", function(event) {
326 checksubmit();
327 return true;
328 });
329 }
330
331 if ($("settings")) {
332 $("settings").addEventListener("focus", function(event) {
333 _acrob(null);
334 });
335 }
336 if ($("statusenter")) {
337 _loadStatusSelect("[projectname]", "statusenter", "[initial_status]");
338 $("statusenter").addEventListener("focus", function(event) {
339 _acrob(null);
340 });
341 }
342 if($("res_fd_message")) {
343 $("res_fd_message").onclick = function(){
344 $("res_fd_banner").classList.add("hidden");
345 };
346 };
347
348 if ($("submit_btn")) {
349 $("submit_btn").addEventListener("focus", function(event) {
350 _acrob(null);
351 });
352 $("submit_btn").addEventListener("click", function(event) {
353 _acrob(null);
354 _trimCommas();
355 userMadeChanges = false;
356 });
357 }
358 if ($("discard")) {
359 $("discard").addEventListener("focus", function(event) {
360 _acrob(null);
361 });
362 $("discard").addEventListener("click", function(event) {
363 _acrob(null);
364 _confirmDiscardEntry(event.target);
365 event.preventDefault();
366 });
367 }
368 if ($("new-issue-feedback-link")) {
369 $("new-issue-feedback-link").addEventListener("click", function(event) {
370 userfeedback.api.startFeedback({
371 'productId': '5208992', // Required.
372 'productVersion': '[app_version]' // Optional.
373 });
374 })
375 }
376
377 window.allowSubmit = true;
378 $("create_issue_form").addEventListener("submit", function() {
379 if (allowSubmit) {
380 allowSubmit = false;
381 $("submit_btn").value = "Creating issue...";
382 $("submit_btn").disabled = "disabled";
383 }
384 else {
385 event.preventDefault();
386 }
387 });
388
389 var _blockIdsToListeners = [[]"blocked_on", "blocking", "hotlistsenter"];
390 for (var i = 0; i < _blockIdsToListeners.length; i++) {
391 var id = _blockIdsToListeners[[]i];
392 if ($(id)) {
393 $(id).addEventListener("focus", function(event) {
394 _acrob(null);
395 _acof(event);
396 });
397 }
398 }
399
400 var _idsToAddDefaultListeners = [[]"ownerenter", "memberenter", "components"];
401 for (var i = 0; i < _idsToAddDefaultListeners.length; i++) {
402 var id = _idsToAddDefaultListeners[[]i];
403 if ($(id)) {
404 $(id).addEventListener("focus", function(event) {
405 _acrob(null);
406 _acof(event);
407 });
408 }
409 }
410
411 var _elementsToAddPresubmit = document.querySelectorAll(
412 "#create_issue_form input, #create_issue_form select");
413 var debounced_presubmit = debounce(TKR_presubmit, 500);
414 for (var i = 0; i < _elementsToAddPresubmit.length; i++) {
415 var el = _elementsToAddPresubmit[[]i];
416 el.addEventListener("keyup", debounced_presubmit);
417 el.addEventListener("change", debounced_presubmit);
418 }
419 debounced_presubmit();
420
421 if ($("attachafile")) {
422 $("attachafile").addEventListener("click", function(event) {
423 _addAttachmentFields("attachmentareadeventry");
424 event.preventDefault();
425 });
426 }
427
428 document.addEventListener('keydown', function(event) {
429 if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
430 event.preventDefault();
431 $('submit_btn').click();
432 }
433 })
434
435 window.onsubmit = function() {
436 TKR_initialFormValues = TKR_currentFormValues();
437 };
438
439 window.onbeforeunload = function() {
440 if (TKR_isDirty()) {
441 // This message is ignored in recent versions of Chrome and Firefox.
442 return "You have unsaved changes. Leave this page and discard them?";
443 }
444 };
445
446 _lfidprefix = 'labelenter';
447 [if-any any_errors]
448 function _clearOnFirstEvent(){}
449 [end]
450
451 [if-any page_perms.EditIssue page_perms.EditIssueStatus page_perms.EditIssueOwner page_perms.EditIssueCc]
452 setTimeout(_forceProperTableWidth, 100);
453 [end]
454
455 [if-any page_perms.EditIssue]
456 _exposeExistingLabelFields();
457 [end]
458
459 var field_error;
460 [if-any errors.custom_fields]
461 [for errors.custom_fields]
462 field_error = document.getElementById('error_custom_' + [errors.custom_fields.field_id]);
463 field_error.textContent = "[errors.custom_fields.message]";
464 field_error.style.display = "";
465 [end]
466 [end]
467
468
469
470function checksubmit() {
471 var restrict_to_known = [if-any restrict_to_known]true[else]false[end];
472 var confirmmsg = document.getElementById('confirmmsg');
473 var cg = document.getElementById('cg');
474 var label_blocksubmitmsg = document.getElementById('blocksubmitmsg');
475 var component_blocksubmitmsg = document.getElementById('component_blocksubmitmsg');
476
477 // Check for templates that require components.
478 var component_required = [if-any component_required]true[else]false[end];
479 var components = document.getElementById('components');
480 if (components && component_required && components.value == "") {
481 component_blocksubmitmsg.textContent = "You must specify a component for this template.";
482 } else {
483 component_blocksubmitmsg.textContent = "";
484 }
485
486 var submit = document.getElementById('submit_btn');
487 var summary = document.getElementById('summary');
488 if ((restrict_to_known && confirmmsg && confirmmsg.textContent) ||
489 (label_blocksubmitmsg && label_blocksubmitmsg.textContent) ||
490 (component_blocksubmitmsg && component_blocksubmitmsg.textContent) ||
491 (cg && cg.value == "") ||
492 (!allowSubmit) ||
493 (!summary.value [if-any must_edit_summary]|| summary.value == '[format "js"][template_summary][end]'[end])) {
494 submit.disabled='disabled';
495 } else {
496 submit.disabled='';
497 }
498}
499checksubmit();
500setInterval(checksubmit, 700); [# catch changes that were not keystrokes, e.g., paste menu item.]
501
502$("star").addEventListener("click", function (event) {
503 _TKR_toggleStarLocal($("star"), "star_input");
504});
505
506 const mrCodeFontToggle = document.createElement('mr-pref-toggle');
507 mrCodeFontToggle.style = 'float:right; margin: 3px;';
508 [if-any code_font]
509 mrCodeFontToggle.initialValue = true;
510 [end]
511 [if-any logged_in_user]
512 mrCodeFontToggle.userDisplayName = "[logged_in_user.email]";
513 [end]
514 mrCodeFontToggle.label = "Code";
515 mrCodeFontToggle.title = "Code font";
516 mrCodeFontToggle.prefName = "code_font";
517 $('mr-code-font-toggle-slot').appendChild(mrCodeFontToggle);
518 mrCodeFontToggle.fetchPrefs();
519 mrCodeFontToggle.addEventListener('font-toggle', function(e) {
520 const checked = e.detail.checked;
521 const ancestor = $('color_control');
522 if (ancestor) {
523 if (checked) {
524 ancestor.classList.add('codefont');
525 } else {
526 ancestor.classList.remove('codefont');
527 }
528 }
529 });
530
531
532});
533</script>
534
535<script type="text/javascript" defer src="/static/third_party/js/keys.js?version=[app_version]" nonce="[nonce]"></script>
536<script type="text/javascript" defer src="/static/third_party/js/skipper.js?version=[app_version]" nonce="[nonce]"></script>
537<script type="text/javascript" defer src="https://support.google.com/inapp/api.js" nonce="[nonce]"></script>
538<script type="text/javascript" nonce="[nonce]">
539runOnLoad(function() {
540 _setupKibblesOnEntryPage('[project_home_url]/issues/list');
541});
542</script>
543
544[end]
545
546[include "field-value-widgets-js.ezt"]
547[include "../framework/footer.ezt"]
548
549<script type="text/javascript" nonce="[nonce]">
550runOnLoad(function() {
551 if (typeof(ClientLogger) === "function") {
552 const l = new ClientLogger("issues");
553 l.logStart("new-issue", "user-time");
554 document.forms.create_issue_form.addEventListener('submit', function() {
555 l.logStart("new-issue", "server-time");
556 });
557 }
558});
559</script>