blob: 4458a516b19990081d059e987b9c90d8ee17502b [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001/* Copyright 2016 The Chromium Authors. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file or at
5 * https://developers.google.com/open-source/licenses/bsd
6 */
7/* eslint-disable no-var */
8
9/**
10 * This file contains JS functions that implement various navigation
11 * features of Monorail.
12 */
13
14
15/**
16 * Navigate the browser to the given URL.
17 * @param {string} url The URL of the page to browse.
18 * @param {boolean} newWindow Open a new tab or window.
19 */
20function TKR_go(url, newWindow) {
21 if (newWindow) {
22 window.open(url, '_blank');
23 } else {
24 document.location = url;
25 }
26}
27
28
29/**
30 * Tell the browser to scroll to the given anchor on the current page.
31 * @param {string} anchor Name of the <a name="xxx"> anchor on the page.
32 */
33function TKR_goToAnchor(anchor) {
34 document.location.hash = anchor;
35}
36
37
38/**
39 * Get the user-editable colspec form field. This text field is normally
40 * display:none, but it is shown when the user chooses "Edit columns...".
41 * We need a function to get this element because there are multiple form
42 * fields on the page with name="colspec", and an IE misfeature sets their
43 * id attributes as well, which makes document.getElementById() fail.
44 * @return {Element} user editable colspec form field.
45 */
46function TKR_getColspecElement() {
47 const elem = document.getElementById('colspec_field');
48 return elem && elem.firstChild;
49}
50
51
52/**
53 * Get the artifact search form field. This is a visible text field where
54 * the user enters a query for issues. This function
55 * is needed because there is also the project search field on the each page,
56 * and it has name="q". An IE misfeature confuses name="..." with id="...".
57 * @return {Element} artifact query form field, or undefined.
58 */
59function TKR_getArtifactSearchField() {
60 const element = _getSearchBarComponent();
61 if (!element) return $('searchq');
62
63 return element.shadowRoot.querySelector('#searchq');
64}
65
66
67/**
68 * Get the can selector. This function
69 * @return {Element} can input element.
70 */
71function TKR_getArtifactCanField() {
72 const element = _getSearchBarComponent();
73 if (!element) return $('can');
74
75 return element.shadowRoot.querySelector('#can');
76}
77
78
79function _getSearchBarComponent() {
80 const element = document.querySelector('mr-header');
81 if (!element) return;
82
83 return element.shadowRoot.querySelector('mr-search-bar');
84}
85
86
87/**
88 * Build a query string for all the common contextual values that we use.
89 */
90function TKR_formatContextQueryArgs() {
91 let args = '';
92 let colspec = _ctxDefaultColspec;
93 const colSpecElem = TKR_getColspecElement();
94 if (colSpecElem) {
95 colspec = colSpecElem.value;
96 }
97
98 if (_ctxHotlistID != '') args += '&hotlist_id=' + _ctxHotlistID;
99 if (_ctxCan != 2) args += '&can=' + _ctxCan;
100 args += '&q=' + encodeURIComponent(_ctxQuery);
101 if (_ctxSortspec != '') args += '&sort=' + _ctxSortspec;
102 if (_ctxGroupBy != '') args += '&groupby=' + _ctxGroupBy;
103 if (colspec != _ctxDefaultColspec) args += '&colspec=' + colspec;
104 if (_ctxStart != 0) args += '&start=' + _ctxStart;
105 if (_ctxNum != _ctxResultsPerPage) args += '&num=' + _ctxNum;
106 if (!colSpecElem) args += '&mode=grid';
107 return args;
108}
109
110// Fields that should use ":" when filtering.
111const _PRETOKENIZED_FIELDS = [
112 'owner', 'reporter', 'cc', 'commentby', 'component'];
113
114/**
115 * The user wants to narrow their search results by adding a search term
116 * for the given prefix and value. Reload the issue list page with that
117 * additional search term.
118 * @param {string} prefix Field or label prefix, e.g., "Priority".
119 * @param {string} suffix Field or label value, e.g., "High".
120 */
121function TKR_filterTo(prefix, suffix) {
122 let newQuery = TKR_getArtifactSearchField().value;
123 if (newQuery != '') newQuery += ' ';
124
125 let op = '=';
126 for (let i = 0; i < _PRETOKENIZED_FIELDS.length; i++) {
127 if (prefix == _PRETOKENIZED_FIELDS[i]) {
128 op = ':';
129 break;
130 }
131 }
132
133 newQuery += prefix + op + suffix;
134 let url = 'list?can=' + TKR_getArtifactCanField().value + '&q=' + newQuery;
135 if ($('sort') && $('sort').value) url += '&sort=' + $('sort').value;
136 url += '&colspec=' + TKR_getColspecElement().value;
137 TKR_go(url);
138}
139
140
141/**
142 * The user wants to sort their search results by adding a sort spec
143 * for the given column. Reload the issue list page with that
144 * additional sort spec.
145 * @param {string} colname Field or label prefix, e.g., "Priority".
146 * @param {boolean} descending True if the values should be reversed.
147 */
148function TKR_addSort(colname, descending) {
149 let existingSortSpec = '';
150 if ($('sort')) {
151 existingSortSpec = $('sort').value;
152 }
153 const oldSpecs = existingSortSpec.split(/ +/);
154 let sortDirective = colname;
155 if (descending) sortDirective = '-' + colname;
156 const specs = [sortDirective];
157 for (let i = 0; i < oldSpecs.length; i++) {
158 if (oldSpecs[i] != '' && oldSpecs[i] != colname &&
159 oldSpecs[i] != '-' + colname) {
160 specs.push(oldSpecs[i]);
161 }
162 }
163
164 const isHotlist = window.location.href.includes('/hotlists/');
165 let url = isHotlist ? ($('hotlist_name').value + '?') : ('list?');
166 url += ('can='+ TKR_getArtifactCanField().value + '&q=' +
167 TKR_getArtifactSearchField().value);
168 url += '&sort=' + specs.join('+');
169 url += '&colspec=' + TKR_getColspecElement().value;
170 TKR_go(url);
171}
172
173/** Convenience function for sorting in ascending order. */
174function TKR_sortUp(colname) {
175 TKR_addSort(colname, false);
176}
177
178/** Convenience function for sorting in descending order. */
179function TKR_sortDown(colname) {
180 TKR_addSort(colname, true);
181}
182