Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/tracker/issueexport.py b/tracker/issueexport.py
index 91620c4..6fe7018 100644
--- a/tracker/issueexport.py
+++ b/tracker/issueexport.py
@@ -1,7 +1,6 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 """Servlet to export a range of issues in JSON format.
 """
@@ -9,16 +8,12 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import logging
 import time
 
-import ezt
-
 from businesslogic import work_env
 from features import savedqueries_helpers
-from framework import flaskservlet
-from framework import permissions
 from framework import jsonfeed
+from framework import permissions
 from framework import servlet
 from tracker import tracker_bizobj
 
@@ -27,7 +22,7 @@
   """IssueExportControls let's an admin choose how to export issues."""
 
   _PAGE_TEMPLATE = 'tracker/issue-export-page.ezt'
-  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ISSUES
+  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ISSUES
 
   def AssertBasePermission(self, mr):
     """Make sure that the logged in user has permission to view this page."""
@@ -70,11 +65,10 @@
         'saved_queries': saved_query_views,
     }
 
-  # def GetIssueExport(self, **kwargs):
-  #   return self.handler(**kwargs)
+  def GetIssueExport(self, **kwargs):
+    return self.handler(**kwargs)
 
 
-# TODO: convert to FLaskJsonFeed while conver to flask
 class IssueExportJSON(jsonfeed.JsonFeed):
   """IssueExport shows a range of issues in JSON format."""
 
@@ -154,7 +148,7 @@
     }
     return json_data
 
-  def _MakeAmendmentJSON(self, amendment, email_dict):
+  def _MakeAmendmentJSON(self, amendment, email_dict, comp_dict):
     amendment_json = {
         'field': amendment.field.name,
     }
@@ -170,6 +164,24 @@
       amendment_json.update(
           {'removed_emails': [email_dict.get(user_id)
                               for user_id in amendment.removed_user_ids]})
+    if amendment.added_component_ids:
+      amendment_json.update(
+          {
+              'added_components':
+                  [
+                      comp_dict.get(component_id).path.lower()
+                      for component_id in amendment.added_component_ids
+                  ]
+          })
+    if amendment.removed_component_ids:
+      amendment_json.update(
+          {
+              'removed_components':
+                  [
+                      comp_dict.get(component_id).path.lower()
+                      for component_id in amendment.removed_component_ids
+                  ]
+          })
     return amendment_json
 
   def _MakeAttachmentJSON(self, attachment):
@@ -183,11 +195,13 @@
     }
     return attachment_json
 
-  def _MakeCommentJSON(self, comment, email_dict):
+  def _MakeCommentJSON(self, comment, email_dict, comp_dict):
     if comment.deleted_by:
       return None
-    amendments = [self._MakeAmendmentJSON(a, email_dict)
-                  for a in comment.amendments]
+    amendments = [
+        self._MakeAmendmentJSON(a, email_dict, comp_dict)
+        for a in comment.amendments
+    ]
     attachments = [self._MakeAttachmentJSON(a)
                    for a in comment.attachments]
     comment_json = {
@@ -242,10 +256,13 @@
     descriptions = [c for c in comment_list if c.is_description]
     for i, d in enumerate(descriptions):
       d.description_num = str(i+1)
-    comments = [self._MakeCommentJSON(c, email_dict) for c in comment_list]
     phase_dict = {phase.phase_id: phase.name for phase in issue.phases}
     config = self.services.config.GetProjectConfig(
         mr.cnxn, mr.project.project_id)
+    comp_dict = {comp.component_id: comp for comp in config.component_defs}
+    comments = [
+        self._MakeCommentJSON(c, email_dict, comp_dict) for c in comment_list
+    ]
     fd_dict = {fd.field_id: fd for fd in config.field_defs}
     issue_json = {
         'local_id': issue.local_id,
@@ -283,8 +300,8 @@
         issue_json['merged_into'] = merge.local_id
     return issue_json
 
-  # def GetIssueExportJSON(self, **kwargs):
-  #   return self.handler(**kwargs)
+  def GetIssueExportJSON(self, **kwargs):
+    return self.handler(**kwargs)
 
-  # def PostIssueExportJSON(self, **kwargs):
-  #   return self.handler(**kwargs)
+  def PostIssueExportJSON(self, **kwargs):
+    return self.handler(**kwargs)