blob: b9889d6daaa0b625ac2b51e264a78c857fda6949 [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" ""]
179 </td>
180 </tr>
181
182 <tbody class="collapse">
183 [if-any page_perms.EditIssue]
184 <tr class="ifCollapse">
185 <td><a href="#" class="toggleCollapse">More options</a></td>
186 </tr>
187 [end]
188
189 <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>
190 <td class="inplace" colspan="2">
191 <input type="text" name="blocked_on" id="blocked_on" value="[initial_blocked_on]">
192 [if-any errors.blocked_on]
193 <div class="fielderror">[errors.blocked_on]</div>
194 [end]
195 </td>
196 </tr>
197 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end] class="ifExpand"><th><label for="blocking">Blocking:</label></th>
198 <td class="inplace" colspan="2">
199 <input type="text" name="blocking" id="blocking" value="[initial_blocking]" />
200 [if-any errors.blocking]
201 <div class="fielderror">[errors.blocking]</div>
202 [end]
203 </td>
204 </tr>
205
206 <tr [if-any page_perms.EditIssue][else]style="display:none;"[end] class="ifExpand"><th><label for="hotlistsenter">Hotlists:</label></th>
207 <td class="inplace" colspan="2">
208 <input type="text" name="hotlists" autocomplete="off" id="hotlistsenter" value="[initial_hotlists]" />
209 [if-any errors.hotlists]
210 <div class="fielderror">[errors.hotlists]</div>
211 [end]
212 </td>
213 </tr>
214 </tbody>
215
216 [if-any approvals]
217 <tr>
218 <th>Launch Gates:</th>
219 <td colspan="7">
220 [include "launch-gates-widget.ezt"]
221 </td>
222 </tr>
223 [end]
224
225 [for fields][if-any fields.applicable][if-any fields.field_def.is_approval_subfield]
226 <tr is="subfield-row">
227 <th>[fields.field_def.parent_approval_name] [fields.field_name]:</th>
228 <td colspan="2">
229 [if-any fields.is_editable]
230 [include "field-value-widgets.ezt" False "tmpl" False ""]
231 <div class="fielderror" style="display:none" id="error_custom_[fields.field_id]"></div>
232 [else]
233 <input disabled value = "
234 [for fields.values]
235 [fields.values.val]
236 [end]
237 " style="text-align:right; width:12em" class="multivalued customfield" aria-labelledby="[fields.field_id]_label">
238 [end]
239 </td>
240 </tr>
241 [end][end][end]
242
243 [for issue_phase_names]
244 [for fields]
245 [is fields.phase_name issue_phase_names]
246 <tr>
247 <th>[issue_phase_names].[fields.field_name]:</th>
248 <td colspan="2">
249 [if-any fields.is_editable]
250 [include "field-value-widgets.ezt" False "tmpl" False issue_phase_names]
251 <div class="fielderror" style="display:none" id="error_custom_[issue_phase_names]_[fields.field_id]"></div>
252 [else]
253 <input disabled value = "
254 [for fields.values]
255 [fields.values.val]
256 [end]
257 " style="text-align:right; width:12em" class="multivalued customfield" aria-labelledby="[fields.field_id]_label">
258 [end]
259 </td>
260 </th>
261 </tr>
262 [end][end][end]
263
264 [include "../framework/label-validation-row.ezt"]
265 [include "../framework/component-validation-row.ezt"]
266 </table>
267
268 <div style="padding:6px">
269 <input type="submit" id="submit_btn" name="btn" value="Submit issue">
270 <input type="button" id="discard" name="nobtn" value="Discard">
271 </div>
272
273 </td>
274 </tr>
275 </table>
276 </form>
277</div>
278
279[include "../features/filterrules-preview.ezt"]
280
281<div style="margin-top:5em; margin-left: 8px;">
282 Problems submitting issues?
283 <a href="#" id="new-issue-feedback-link">
284 Send feedback
285 </a>
286</div>
287
288<div id="helparea"></div>
289
290<script type="text/javascript" nonce="[nonce]">
291runOnLoad(function() {
292 window.getTSMonClient().recordIssueEntryTiming();
293
294 if ($('launch-gates-table')) {
295 $('launch-gates-table').classList.remove('hidden');
296 }
297
298 if ($("template_name")) {
299 $("template_name").addEventListener("change", function(event) {
300 _switchTemplate(event.target.getAttribute("data-project-name"),
301 event.target.value)
302 });
303 }
304
305 if ($("summary")) {
306 var clearSummaryOnClick = $("summary").getAttribute("data-clear-summary-on-click");
307 if (clearSummaryOnClick) {
308 $("summary").addEventListener("keydown", function(event) {
309 _clearOnFirstEvent('[format "js"][initial_summary][end]');
310 });
311 }
312 $("summary").addEventListener("click", function(event) {
313 if (clearSummaryOnClick) {
314 _clearOnFirstEvent('[format "js"][initial_summary][end]');
315 }
316 checksubmit();
317 });
318 $("summary").addEventListener("focus", function(event) {
319 _acrob(null);
320 _acof(event);
321 });
322 $("summary").addEventListener("keyup", function(event) {
323 checksubmit();
324 return true;
325 });
326 }
327
328 if ($("settings")) {
329 $("settings").addEventListener("focus", function(event) {
330 _acrob(null);
331 });
332 }
333 if ($("statusenter")) {
334 _loadStatusSelect("[projectname]", "statusenter", "[initial_status]");
335 $("statusenter").addEventListener("focus", function(event) {
336 _acrob(null);
337 });
338 }
339 if($("res_fd_message")) {
340 $("res_fd_message").onclick = function(){
341 $("res_fd_banner").classList.add("hidden");
342 };
343 };
344
345 if ($("submit_btn")) {
346 $("submit_btn").addEventListener("focus", function(event) {
347 _acrob(null);
348 });
349 $("submit_btn").addEventListener("click", function(event) {
350 _acrob(null);
351 _trimCommas();
352 userMadeChanges = false;
353 });
354 }
355 if ($("discard")) {
356 $("discard").addEventListener("focus", function(event) {
357 _acrob(null);
358 });
359 $("discard").addEventListener("click", function(event) {
360 _acrob(null);
361 _confirmDiscardEntry(event.target);
362 event.preventDefault();
363 });
364 }
365 if ($("new-issue-feedback-link")) {
366 $("new-issue-feedback-link").addEventListener("click", function(event) {
367 userfeedback.api.startFeedback({
368 'productId': '5208992', // Required.
369 'productVersion': '[app_version]' // Optional.
370 });
371 })
372 }
373
374 window.allowSubmit = true;
375 $("create_issue_form").addEventListener("submit", function() {
376 if (allowSubmit) {
377 allowSubmit = false;
378 $("submit_btn").value = "Creating issue...";
379 $("submit_btn").disabled = "disabled";
380 }
381 else {
382 event.preventDefault();
383 }
384 });
385
386 var _blockIdsToListeners = [[]"blocked_on", "blocking", "hotlistsenter"];
387 for (var i = 0; i < _blockIdsToListeners.length; i++) {
388 var id = _blockIdsToListeners[[]i];
389 if ($(id)) {
390 $(id).addEventListener("focus", function(event) {
391 _acrob(null);
392 _acof(event);
393 });
394 }
395 }
396
397 var _idsToAddDefaultListeners = [[]"ownerenter", "memberenter", "components"];
398 for (var i = 0; i < _idsToAddDefaultListeners.length; i++) {
399 var id = _idsToAddDefaultListeners[[]i];
400 if ($(id)) {
401 $(id).addEventListener("focus", function(event) {
402 _acrob(null);
403 _acof(event);
404 });
405 }
406 }
407
408 var _elementsToAddPresubmit = document.querySelectorAll(
409 "#create_issue_form input, #create_issue_form select");
410 var debounced_presubmit = debounce(TKR_presubmit, 500);
411 for (var i = 0; i < _elementsToAddPresubmit.length; i++) {
412 var el = _elementsToAddPresubmit[[]i];
413 el.addEventListener("keyup", debounced_presubmit);
414 el.addEventListener("change", debounced_presubmit);
415 }
416 debounced_presubmit();
417
418 if ($("attachafile")) {
419 $("attachafile").addEventListener("click", function(event) {
420 _addAttachmentFields("attachmentareadeventry");
421 event.preventDefault();
422 });
423 }
424
425 document.addEventListener('keydown', function(event) {
426 if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
427 event.preventDefault();
428 $('submit_btn').click();
429 }
430 })
431
432 window.onsubmit = function() {
433 TKR_initialFormValues = TKR_currentFormValues();
434 };
435
436 window.onbeforeunload = function() {
437 if (TKR_isDirty()) {
438 // This message is ignored in recent versions of Chrome and Firefox.
439 return "You have unsaved changes. Leave this page and discard them?";
440 }
441 };
442
443 _lfidprefix = 'labelenter';
444 [if-any any_errors]
445 function _clearOnFirstEvent(){}
446 [end]
447
448 [if-any page_perms.EditIssue page_perms.EditIssueStatus page_perms.EditIssueOwner page_perms.EditIssueCc]
449 setTimeout(_forceProperTableWidth, 100);
450 [end]
451
452 [if-any page_perms.EditIssue]
453 _exposeExistingLabelFields();
454 [end]
455
456 var field_error;
457 [if-any errors.custom_fields]
458 [for errors.custom_fields]
459 field_error = document.getElementById('error_custom_' + [errors.custom_fields.field_id]);
460 field_error.textContent = "[errors.custom_fields.message]";
461 field_error.style.display = "";
462 [end]
463 [end]
464
465
466
467function checksubmit() {
468 var restrict_to_known = [if-any restrict_to_known]true[else]false[end];
469 var confirmmsg = document.getElementById('confirmmsg');
470 var cg = document.getElementById('cg');
471 var label_blocksubmitmsg = document.getElementById('blocksubmitmsg');
472 var component_blocksubmitmsg = document.getElementById('component_blocksubmitmsg');
473
474 // Check for templates that require components.
475 var component_required = [if-any component_required]true[else]false[end];
476 var components = document.getElementById('components');
477 if (components && component_required && components.value == "") {
478 component_blocksubmitmsg.textContent = "You must specify a component for this template.";
479 } else {
480 component_blocksubmitmsg.textContent = "";
481 }
482
483 var submit = document.getElementById('submit_btn');
484 var summary = document.getElementById('summary');
485 if ((restrict_to_known && confirmmsg && confirmmsg.textContent) ||
486 (label_blocksubmitmsg && label_blocksubmitmsg.textContent) ||
487 (component_blocksubmitmsg && component_blocksubmitmsg.textContent) ||
488 (cg && cg.value == "") ||
489 (!allowSubmit) ||
490 (!summary.value [if-any must_edit_summary]|| summary.value == '[format "js"][template_summary][end]'[end])) {
491 submit.disabled='disabled';
492 } else {
493 submit.disabled='';
494 }
495}
496checksubmit();
497setInterval(checksubmit, 700); [# catch changes that were not keystrokes, e.g., paste menu item.]
498
499$("star").addEventListener("click", function (event) {
500 _TKR_toggleStarLocal($("star"), "star_input");
501});
502
503 const mrCodeFontToggle = document.createElement('mr-pref-toggle');
504 mrCodeFontToggle.style = 'float:right; margin: 3px;';
505 [if-any code_font]
506 mrCodeFontToggle.initialValue = true;
507 [end]
508 [if-any logged_in_user]
509 mrCodeFontToggle.userDisplayName = "[logged_in_user.email]";
510 [end]
511 mrCodeFontToggle.label = "Code";
512 mrCodeFontToggle.title = "Code font";
513 mrCodeFontToggle.prefName = "code_font";
514 $('mr-code-font-toggle-slot').appendChild(mrCodeFontToggle);
515 mrCodeFontToggle.fetchPrefs();
516 mrCodeFontToggle.addEventListener('font-toggle', function(e) {
517 const checked = e.detail.checked;
518 const ancestor = $('color_control');
519 if (ancestor) {
520 if (checked) {
521 ancestor.classList.add('codefont');
522 } else {
523 ancestor.classList.remove('codefont');
524 }
525 }
526 });
527
528
529});
530</script>
531
532<script type="text/javascript" defer src="/static/third_party/js/keys.js?version=[app_version]" nonce="[nonce]"></script>
533<script type="text/javascript" defer src="/static/third_party/js/skipper.js?version=[app_version]" nonce="[nonce]"></script>
534<script type="text/javascript" defer src="https://support.google.com/inapp/api.js" nonce="[nonce]"></script>
535<script type="text/javascript" nonce="[nonce]">
536runOnLoad(function() {
537 _setupKibblesOnEntryPage('[project_home_url]/issues/list');
538});
539</script>
540
541[end]
542
543[include "field-value-widgets-js.ezt"]
544[include "../framework/footer.ezt"]
545
546<script type="text/javascript" nonce="[nonce]">
547runOnLoad(function() {
548 if (typeof(ClientLogger) === "function") {
549 const l = new ClientLogger("issues");
550 l.logStart("new-issue", "user-time");
551 document.forms.create_issue_form.addEventListener('submit', function() {
552 l.logStart("new-issue", "server-time");
553 });
554 }
555});
556</script>