blob: d3e836daaaaba659cc8435ff8e716ccd12da368d [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001// Copyright 2016 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004
5/**
6 * This file contains JS utilities used by other JS files in Monorail.
7 */
8
9
10/**
11 * Add an indexOf method to all arrays, if this brower's JS implementation
12 * does not already have it.
13 * @param {Object} item The item to find
14 * @return {number} The index of the given item, or -1 if not found.
15 */
16if (Array.prototype.indexOf == undefined) {
17 Array.prototype.indexOf = function(item) {
18 for (let i = 0; i < this.length; ++i) {
19 if (this[i] == item) return i;
20 }
21 return -1;
22 };
23}
24
25
26/**
27 * This function works around a FF HTML layout problem. The table
28 * width is somehow rendered at 100% when the table contains a
29 * display:none element, later, when that element is displayed, the
30 * table renders at the correct width. The work-around is to have the
31 * element initiallye displayed so that the table renders properly,
32 * but then immediately hide the element until it is needed.
33 *
34 * TODO(jrobbins): Find HTML markup that FF can render more
35 * consistently. After that, I can remove this hack.
36 */
37function TKR_forceProperTableWidth() {
38 let e = $('confirmarea');
39 if (e) e.style.display='none';
40}
41
42
43function TKR_parseIssueRef(issueRef) {
44 issueRef = issueRef.trim();
45 if (!issueRef) {
46 return null;
47 }
48
49 let projectName = window.CS_env.projectName;
50 let localId = issueRef;
51 if (issueRef.includes(':')) {
52 const parts = issueRef.split(':', 2);
53 projectName = parts[0];
54 localId = parts[1];
55 }
56
57 return {
58 project_name: projectName,
59 local_id: localId};
60}
61
62
63function _buildFieldsForIssueDelta(issueDelta, valuesByName) {
64 issueDelta.field_vals_add = [];
65 issueDelta.field_vals_remove = [];
66 issueDelta.fields_clear = [];
67
68 valuesByName.forEach((values, key, map) => {
69 if (key.startsWith('op_custom_') && values == 'clear') {
70 const field_id = key.substring('op_custom_'.length);
71 issueDelta.fields_clear.push({field_id: field_id});
72 } else if (key.startsWith('custom_')) {
73 const field_id = key.substring('custom_'.length);
74 values = values.filter(Boolean);
75 if (valuesByName.get('op_' + key) === 'remove') {
76 values.forEach((value) => {
77 issueDelta.field_vals_remove.push({
78 field_ref: {field_id: field_id},
79 value: value});
80 });
81 } else {
82 values.forEach((value) => {
83 issueDelta.field_vals_add.push({
84 field_ref: {field_id: field_id},
85 value: value});
86 });
87 }
88 }
89 });
90}
91
92
93function _classifyPlusMinusItems(values) {
94 let result = {
95 add: [],
96 remove: []};
97 values = new Set(values);
98 values.forEach((value) => {
99 if (!value.startsWith('-') && value) {
100 result.add.push(value);
101 } else if (value.startsWith('-') && value.substring(1)) {
102 result.remove.push(value);
103 }
104 });
105 return result;
106}
107
108
109function TKR_buildIssueDelta(valuesByName) {
110 let issueDelta = {};
111
112 if (valuesByName.has('status')) {
113 issueDelta.status = valuesByName.get('status')[0];
114 }
115 if (valuesByName.has('owner')) {
116 issueDelta.owner_ref = {
117 display_name: valuesByName.get('owner')[0].trim().toLowerCase()};
118 }
119 if (valuesByName.has('cc')) {
120 const cc_usernames = _classifyPlusMinusItems(
121 valuesByName.get('cc')[0].toLowerCase().split(/[,;\s]+/));
122 issueDelta.cc_refs_add = cc_usernames.add.map(
123 (email) => ({display_name: email}));
124 issueDelta.cc_refs_remove = cc_usernames.remove.map(
125 (email) => ({display_name: email}));
126 }
127 if (valuesByName.has('components')) {
128 const components = _classifyPlusMinusItems(
129 valuesByName.get('components')[0].split(/[,;\s]/));
130 issueDelta.comp_refs_add = components.add.map(
131 (path) => ({path: path}));
132 issueDelta.comp_refs_remove = components.remove.map(
133 (path) => ({path: path}));
134 }
135 if (valuesByName.has('label')) {
136 const labels = _classifyPlusMinusItems(valuesByName.get('label'));
137 issueDelta.label_refs_add = labels.add.map(
138 (label) => ({label: label}));
139 issueDelta.label_refs_remove = labels.remove.map(
140 (label) => ({label: label}));
141 }
142 if (valuesByName.has('blocked_on')) {
143 const blockedOn = _classifyPlusMinusItems(valuesByName.get('blocked_on'));
144 issueDelta.blocked_on_refs_add = blockedOn.add.map(TKR_parseIssueRef);
145 issueDelta.blocked_on_refs_add = blockedOn.remove.map(TKR_parseIssueRef);
146 }
147 if (valuesByName.has('blocking')) {
148 const blocking = _classifyPlusMinusItems(valuesByName.get('blocking'));
149 issueDelta.blocking_refs_add = blocking.add.map(TKR_parseIssueRef);
150 issueDelta.blocking_refs_add = blocking.remove.map(TKR_parseIssueRef);
151 }
152 if (valuesByName.has('merge_into')) {
153 issueDelta.merged_into_ref = TKR_parseIssueRef(
154 valuesByName.get('merge_into')[0]);
155 }
156 if (valuesByName.has('summary')) {
157 issueDelta.summary = valuesByName.get('summary')[0];
158 }
159
160 _buildFieldsForIssueDelta(issueDelta, valuesByName);
161
162 return issueDelta;
163}