blob: fe235dbdf073570b49a718c505086b3e3b6a7815 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Class that implements the reranking on the hotlistissues table page."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import logging
12
13from features import features_bizobj
14from features import hotlist_helpers
15from framework import jsonfeed
16from framework import permissions
17from framework import sorting
18from services import features_svc
19from tracker import rerank_helpers
20
21
22class RerankHotlistIssue(jsonfeed.JsonFeed):
23 """Rerank an issue in a hotlist."""
24
25 def AssertBasePermission(self, mr):
26 super(RerankHotlistIssue, self).AssertBasePermission(mr)
27 if mr.target_id and mr.moved_ids and mr.split_above:
28 try:
29 hotlist = self._GetHotlist(mr)
30 except features_svc.NoSuchHotlistException:
31 return
32 edit_perm = permissions.CanEditHotlist(
33 mr.auth.effective_ids, mr.perms, hotlist)
34 if not edit_perm:
35 raise permissions.PermissionException(
36 'User is not allowed to re-rank this hotlist')
37
38 def HandleRequest(self, mr):
39 changed_ranks = self._GetNewRankings(mr)
40
41 if changed_ranks:
42 relations_to_change = dict(
43 (issue_id, rank) for issue_id, rank in changed_ranks)
44
45 self.services.features.UpdateHotlistItemsFields(
46 mr.cnxn, mr.hotlist_id, new_ranks=relations_to_change)
47
48 hotlist_items = self.services.features.GetHotlist(
49 mr.cnxn, mr.hotlist_id).items
50
51 # Note: Cannot use mr.hotlist because hotlist_issues
52 # of mr.hotlist is not updated
53
54 sorting.InvalidateArtValuesKeys(
55 mr.cnxn, [hotlist_item.issue_id for hotlist_item in hotlist_items])
56 (table_data, _) = hotlist_helpers.CreateHotlistTableData(
57 mr, hotlist_items, self.services)
58
59 json_table_data = [{
60 'cells': [{
61 'type': cell.type,
62 'values': [{
63 'item': value.item,
64 'isDerived': value.is_derived,
65 } for value in cell.values],
66 'colIndex': cell.col_index,
67 'align': cell.align,
68 'noWrap': cell.NOWRAP,
69 'nonColLabels': [{
70 'value': label.value,
71 'isDerived': label.is_derived,
72 } for label in cell.non_column_labels],
73 } for cell in table_row.cells],
74 'issueRef': table_row.issue_ref,
75 'idx': table_row.idx,
76 'projectName': table_row.project_name,
77 'projectURL': table_row.project_url,
78 'localID': table_row.local_id,
79 'issueID': table_row.issue_id,
80 'isStarred': table_row.starred,
81 'issueCleanURL': table_row.issue_clean_url,
82 'issueContextURL': table_row.issue_ctx_url,
83 } for table_row in table_data]
84
85 for row, json_row in zip(
86 [table_row for table_row in table_data], json_table_data):
87 if (row.group and row.group.cells):
88 json_row.update({'group': {
89 'rowsInGroup': row.group.rows_in_group,
90 'cells': [{'groupName': cell.group_name,
91 'values': [{
92 # TODO(jojwang): check if this gives error when there
93 # is no value.item
94 'item': value.item if value.item else 'None',
95 } for value in cell.values],
96 } for cell in row.group.cells],
97 }})
98 else:
99 json_row['group'] = 'no'
100
101 return {'table_data': json_table_data}
102 else:
103 return {'table_data': ''}
104
105 def _GetHotlist(self, mr):
106 """Retrieve the current hotlist."""
107 if mr.hotlist_id is None:
108 return None
109 try:
110 hotlist = self.services.features.GetHotlist( mr.cnxn, mr.hotlist_id)
111 except features_svc.NoSuchHotlistException:
112 self.abort(404, 'hotlist not found')
113 return hotlist
114
115 def _GetNewRankings(self, mr):
116 """Compute new issue reference rankings."""
117 missing = False
118 if not (mr.target_id):
119 logging.info('No target_id.')
120 missing = True
121 if not (mr.moved_ids):
122 logging.info('No moved_ids.')
123 missing = True
124 if mr.split_above is None:
125 logging.info('No split_above.')
126 missing = True
127 if missing:
128 return
129
130 untouched_items = [
131 (item.issue_id, item.rank) for item in
132 mr.hotlist.items if item.issue_id not in mr.moved_ids]
133
134 lower, higher = features_bizobj.SplitHotlistIssueRanks(
135 mr.target_id, mr.split_above, untouched_items)
136 return rerank_helpers.GetInsertRankings(lower, higher, mr.moved_ids)