Пример #1
0
def _MakeTableData(issues, starred_iid_set, lower_columns, lower_group_by,
                   users_by_id, cell_factories, related_issues, config,
                   context_for_all_issues, hotlist_id, sort_spec):
    """Returns data from MakeTableData after adding additional information."""
    table_data = table_view_helpers.MakeTableData(
        issues, starred_iid_set, lower_columns, lower_group_by, users_by_id,
        cell_factories, lambda issue: issue.issue_id, related_issues, config,
        context_for_all_issues)

    for row, art in zip(table_data, issues):
        row.issue_id = art.issue_id
        row.local_id = art.local_id
        row.project_name = art.project_name
        row.project_url = framework_helpers.FormatURL(
            None, '/p/%s' % row.project_name)
        row.issue_ref = '%s:%d' % (art.project_name, art.local_id)
        row.issue_clean_url = tracker_helpers.FormatRelativeIssueURL(
            art.project_name, urls.ISSUE_DETAIL, id=art.local_id)
        row.issue_ctx_url = tracker_helpers.FormatRelativeIssueURL(
            art.project_name,
            urls.ISSUE_DETAIL,
            id=art.local_id,
            sort=sort_spec,
            hotlist_id=hotlist_id)

    return table_data
Пример #2
0
  def __init__(self, attach_pb, project_name):
    """Get IssueAttachmentContent PB and make its fields available as attrs.

    Args:
      attach_pb: Attachment part of IssueComment protocol buffer.
      project_name: string Name of the current project.
    """
    super(AttachmentView, self).__init__(attach_pb)
    self.filesizestr = template_helpers.BytesKbOrMb(attach_pb.filesize)
    self.downloadurl = 'attachment?aid=%s' % attach_pb.attachment_id

    self.url = None
    self.thumbnail_url = None
    self.video_url = None
    if IsViewableImage(attach_pb.mimetype, attach_pb.filesize):
      self.url = self.downloadurl + '&inline=1'
      self.thumbnail_url = self.url + '&thumb=1'
    elif IsViewableVideo(attach_pb.mimetype, attach_pb.filesize):
      self.url = self.downloadurl + '&inline=1'
      self.video_url = self.url
    elif IsViewableText(attach_pb.mimetype, attach_pb.filesize):
      self.url = tracker_helpers.FormatRelativeIssueURL(
          project_name, urls.ISSUE_ATTACHMENT_TEXT,
          aid=attach_pb.attachment_id)

    self.iconurl = '/images/paperclip.png'
Пример #3
0
def GetViewURL(attach, download_url, project_name):
    """Return a relative URL to view an attachment in the browser."""
    if IsViewableImage(attach.mimetype, attach.filesize):
        return download_url + '&inline=1'
    elif IsViewableVideo(attach.mimetype, attach.filesize):
        return download_url + '&inline=1'
    elif IsViewableText(attach.mimetype, attach.filesize):
        return tracker_helpers.FormatRelativeIssueURL(
            project_name, urls.ISSUE_ATTACHMENT_TEXT, aid=attach.attachment_id)
    else:
        return None
Пример #4
0
def PrepareForMakeGridData(allowed_results,
                           starred_iid_set,
                           x_attr,
                           grid_col_values,
                           y_attr,
                           grid_row_values,
                           users_by_id,
                           all_label_values,
                           config,
                           related_issues,
                           hotlist_context_dict=None):
    """Return all data needed for EZT to render the body of the grid view."""
    def IssueViewFactory(issue):
        return template_helpers.EZTItem(summary=issue.summary,
                                        local_id=issue.local_id,
                                        issue_id=issue.issue_id,
                                        status=issue.status
                                        or issue.derived_status,
                                        starred=None,
                                        data_idx=0,
                                        project_name=issue.project_name)

    grid_data = MakeGridData(allowed_results,
                             x_attr,
                             grid_col_values,
                             y_attr,
                             grid_row_values,
                             users_by_id,
                             IssueViewFactory,
                             all_label_values,
                             config,
                             related_issues,
                             hotlist_context_dict=hotlist_context_dict)
    issue_dict = {issue.issue_id: issue for issue in allowed_results}
    for grid_row in grid_data:
        for grid_cell in grid_row.cells_in_row:
            for tile in grid_cell.tiles:
                if tile.issue_id in starred_iid_set:
                    tile.starred = ezt.boolean(True)
                issue = issue_dict[tile.issue_id]
                tile.issue_url = tracker_helpers.FormatRelativeIssueURL(
                    issue.project_name, urls.ISSUE_DETAIL, id=tile.local_id)
                tile.issue_ref = issue.project_name + ':' + str(tile.local_id)

    return grid_data
Пример #5
0
def _make_issue_view(default_pn, config, viewable_iids_set, ref_issue):
    viewable = ref_issue.issue_id in viewable_iids_set
    return {
        "id":
        tracker_bizobj.FormatIssueRef(
            (ref_issue.project_name, ref_issue.local_id),
            default_project_name=default_pn),
        "href":
        tracker_helpers.FormatRelativeIssueURL(ref_issue.project_name,
                                               urls.ISSUE_DETAIL,
                                               id=ref_issue.local_id),
        "closed":
        ezt.boolean(
            viewable and
            not tracker_helpers.MeansOpenInProject(ref_issue.status, config)),
        "title":
        ref_issue.summary if viewable else ""
    }
Пример #6
0
def _MakeTableData(
    visible_results, starred_iid_set, lower_columns, lower_group_by,
    users_by_id, cell_factories, related_issues, viewable_iids_set, config):
  """Return a list of list row objects for display by EZT."""
  table_data = table_view_helpers.MakeTableData(
      visible_results, starred_iid_set,
      lower_columns, lower_group_by, users_by_id, cell_factories,
      lambda issue: issue.issue_id, related_issues, viewable_iids_set, config)

  for row, art in zip(table_data, visible_results):
    row.local_id = art.local_id
    row.project_name = art.project_name
    row.issue_ref = '%s:%d' % (art.project_name, art.local_id)
    row.issue_url = tracker_helpers.FormatRelativeIssueURL(
        art.project_name, urls.ISSUE_DETAIL, id=art.local_id)
    row.crbug_url = tracker_helpers.FormatCrBugURL(
        art.project_name, art.local_id)

  return table_data
Пример #7
0
  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
    if mr.local_id is None:
      self.abort(404, 'no issue specified')
    with work_env.WorkEnv(mr, self.services) as we:
      # Signed in users could edit the issue, so it must be fresh.
      use_cache = not mr.auth.user_id
      issue = we.GetIssueByLocalID(
          mr.project_id, mr.local_id, use_cache=use_cache)

      # We give no explanation of missing issues on the peek page.
      if issue.deleted:
        self.abort(404, 'issue not found')

      star_cnxn = sql.MonorailConnection()
      star_promise = framework_helpers.Promise(
          we.IsIssueStarred, issue, cnxn=star_cnxn)

      config = we.GetProjectConfig(mr.project_id)
      comments = we.ListIssueComments(issue)

    descriptions, visible_comments, cmnt_pagination = PaginateComments(
        mr, issue, comments, config, self.services)

    with mr.profiler.Phase('making user proxies'):
      involved_user_ids = tracker_bizobj.UsersInvolvedInIssues([issue])
      group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups(
          mr.cnxn, involved_user_ids)
      comment_user_ids = tracker_bizobj.UsersInvolvedInCommentList(
          descriptions + visible_comments)
      users_by_id = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, involved_user_ids,
          comment_user_ids, group_ids=group_ids)
      framework_views.RevealAllEmailsToMembers(mr.auth, mr.project, users_by_id)

    (issue_view, description_views,
     comment_views) = self._MakeIssueAndCommentViews(
         mr, issue, users_by_id, descriptions, visible_comments, config,
         issue_reporters=[], comment_reporters=[])

    with mr.profiler.Phase('getting starring info'):
      starred = star_promise.WaitAndGetValue()
      star_cnxn.Close()
      permit_edit = permissions.CanEditIssue(
          mr.auth.effective_ids, mr.perms, mr.project, issue)

    mr.ComputeColSpec(config)
    restrict_to_known = config.restrict_to_known

    page_perms = self.MakePagePerms(
        mr, issue,
        permissions.CREATE_ISSUE,
        permissions.SET_STAR,
        permissions.EDIT_ISSUE,
        permissions.EDIT_ISSUE_SUMMARY,
        permissions.EDIT_ISSUE_STATUS,
        permissions.EDIT_ISSUE_OWNER,
        permissions.EDIT_ISSUE_CC,
        permissions.DELETE_ISSUE,
        permissions.ADD_ISSUE_COMMENT,
        permissions.DELETE_OWN,
        permissions.DELETE_ANY,
        permissions.VIEW_INBOUND_MESSAGES)
    page_perms.EditIssue = ezt.boolean(permit_edit)

    prevent_restriction_removal = (
        mr.project.only_owners_remove_restrictions and
        not framework_bizobj.UserOwnsProject(
            mr.project, mr.auth.effective_ids))

    cmd_slots, default_slot_num = self.services.features.GetRecentCommands(
        mr.cnxn, mr.auth.user_id, mr.project_id)
    cmd_slot_views = [
        template_helpers.EZTItem(
            slot_num=slot_num, command=command, comment=comment)
        for slot_num, command, comment in cmd_slots]

    previous_locations = self.GetPreviousLocations(mr, issue)

    return {
        'issue_tab_mode': 'issueDetail',
        'issue': issue_view,
        'description': description_views,
        'comments': comment_views,
        'labels': issue.labels,
        'num_detail_rows': len(comment_views) + 4,
        'noisy': ezt.boolean(tracker_helpers.IsNoisy(
            len(comment_views), issue.star_count)),

        'cmnt_pagination': cmnt_pagination,
        'colspec': mr.col_spec,
        'searchtip': 'You can jump to any issue by number',
        'starred': ezt.boolean(starred),

        'pagegen': str(int(time.time() * 1000000)),

        'restrict_to_known': ezt.boolean(restrict_to_known),
        'prevent_restriction_removal': ezt.boolean(
            prevent_restriction_removal),

        'statuses_offer_merge': config.statuses_offer_merge,
        'page_perms': page_perms,
        'cmd_slots': cmd_slot_views,
        'default_slot_num': default_slot_num,
        'quick_edit_submit_url': tracker_helpers.FormatRelativeIssueURL(
            issue.project_name, urls.ISSUE_PEEK + '.do', id=issue.local_id),
        'previous_locations': previous_locations,
        # for template issue-meta-part shared by issuedetail servlet
        'user_remaining_hotlists': [],
        'user_issue_hotlists': [],
        'involved_users_issue_hotlists': [],
        'remaining_issue_hotlists': [],
        }
Пример #8
0
    def __init__(self, issue, users_by_id, config):
        """Store relevant values for later display by EZT.

    Args:
      issue: An Issue protocol buffer.
      users_by_id: dict {user_id: UserViews} for all users mentioned in issue.
      config: ProjectIssueConfig for this issue.
    """
        super(IssueView, self).__init__(issue)

        # The users involved in this issue must be present in users_by_id if
        # this IssueView is to be used on the issue detail or peek pages. But,
        # they can be absent from users_by_id if the IssueView is used as a
        # tile in the grid view.
        self.owner = users_by_id.get(issue.owner_id)
        self.derived_owner = users_by_id.get(issue.derived_owner_id)
        self.cc = [users_by_id.get(cc_id) for cc_id in issue.cc_ids if cc_id]
        self.derived_cc = [
            users_by_id.get(cc_id) for cc_id in issue.derived_cc_ids if cc_id
        ]
        self.status = framework_views.StatusView(issue.status, config)
        self.derived_status = framework_views.StatusView(
            issue.derived_status, config)
        # If we don't have a config available, we don't need to access is_open, so
        # let it be True.
        self.is_open = ezt.boolean(
            not config or tracker_helpers.MeansOpenInProject(
                tracker_bizobj.GetStatus(issue), config))

        self.components = sorted([
            ComponentValueView(component_id, config, False)
            for component_id in issue.component_ids
            if tracker_bizobj.FindComponentDefByID(component_id, config)
        ] + [
            ComponentValueView(component_id, config, True)
            for component_id in issue.derived_component_ids
            if tracker_bizobj.FindComponentDefByID(component_id, config)
        ],
                                 key=lambda cvv: cvv.path)

        self.fields = MakeAllFieldValueViews(config, issue.labels,
                                             issue.derived_labels,
                                             issue.field_values, users_by_id)

        labels, derived_labels = tracker_bizobj.ExplicitAndDerivedNonMaskedLabels(
            issue, config)
        self.labels = [
            framework_views.LabelView(label, config) for label in labels
        ]
        self.derived_labels = [
            framework_views.LabelView(label, config)
            for label in derived_labels
        ]
        self.restrictions = _RestrictionsView(issue)

        # TODO(jrobbins): sort by order of labels in project config

        self.short_summary = issue.summary[:tracker_constants.
                                           SHORT_SUMMARY_LENGTH]

        if issue.closed_timestamp:
            self.closed = timestr.FormatAbsoluteDate(issue.closed_timestamp)
        else:
            self.closed = ''

        self.blocked_on = []
        self.has_dangling = ezt.boolean(self.dangling_blocked_on_refs)
        self.blocking = []

        self.detail_relative_url = tracker_helpers.FormatRelativeIssueURL(
            issue.project_name, urls.ISSUE_DETAIL, id=issue.local_id)
        self.crbug_url = tracker_helpers.FormatCrBugURL(
            issue.project_name, issue.local_id)
Пример #9
0
  def __init__(
      self, issue, users_by_id, config, open_related=None,
      closed_related=None, all_related=None):
    """Store relevant values for later display by EZT.

    Args:
      issue: An Issue protocol buffer.
      users_by_id: dict {user_id: UserViews} for all users mentioned in issue.
      config: ProjectIssueConfig for this issue.
      open_related: dict of visible open issues that are related to this issue.
      closed_related: dict {issue_id: issue} of visible closed issues that
          are related to this issue.
      all_related: dict {issue_id: issue} of all blocked-on, blocking,
          or merged-into issues referenced from this issue, regardless of
          perms.
    """
    super(IssueView, self).__init__(issue)

    # The users involved in this issue must be present in users_by_id if
    # this IssueView is to be used on the issue detail or peek pages. But,
    # they can be absent from users_by_id if the IssueView is used as a
    # tile in the grid view.
    self.owner = users_by_id.get(issue.owner_id)
    self.derived_owner = users_by_id.get(issue.derived_owner_id)
    self.cc = [users_by_id.get(cc_id) for cc_id in issue.cc_ids
               if cc_id]
    self.derived_cc = [users_by_id.get(cc_id)
                       for cc_id in issue.derived_cc_ids
                       if cc_id]
    self.status = framework_views.StatusView(issue.status, config)
    self.derived_status = framework_views.StatusView(
        issue.derived_status, config)
    # If we don't have a config available, we don't need to access is_open, so
    # let it be True.
    self.is_open = ezt.boolean(
        not config or
        tracker_helpers.MeansOpenInProject(
            tracker_bizobj.GetStatus(issue), config))

    self.components = sorted(
        [ComponentValueView(component_id, config, False)
         for component_id in issue.component_ids
         if tracker_bizobj.FindComponentDefByID(component_id, config)] +
        [ComponentValueView(component_id, config, True)
         for component_id in issue.derived_component_ids
         if tracker_bizobj.FindComponentDefByID(component_id, config)],
        key=lambda cvv: cvv.path)

    self.fields = [
        MakeFieldValueView(
            fd, config, issue.labels, issue.derived_labels, issue.field_values,
            users_by_id)
        # TODO(jrobbins): field-level view restrictions, display options
        for fd in config.field_defs
        if not fd.is_deleted]
    self.fields = sorted(
        self.fields, key=lambda f: (f.applicable_type, f.field_name))

    field_names = [fd.field_name.lower() for fd in config.field_defs
                   if not fd.is_deleted]  # TODO(jrobbins): restricts
    self.labels = [
        framework_views.LabelView(label, config)
        for label in tracker_bizobj.NonMaskedLabels(issue.labels, field_names)]
    self.derived_labels = [
        framework_views.LabelView(label, config)
        for label in issue.derived_labels
        if not tracker_bizobj.LabelIsMaskedByField(label, field_names)]
    self.restrictions = _RestrictionsView(issue)

    # TODO(jrobbins): sort by order of labels in project config

    self.short_summary = issue.summary[:tracker_constants.SHORT_SUMMARY_LENGTH]

    if issue.closed_timestamp:
      self.closed = timestr.FormatAbsoluteDate(issue.closed_timestamp)
    else:
      self.closed = ''

    blocked_on_iids = issue.blocked_on_iids
    blocking_iids = issue.blocking_iids

    # Note that merged_into_str and blocked_on_str includes all issue
    # references, even those referring to issues that the user can't view,
    # so open_related and closed_related cannot be used.
    if all_related is not None:
      all_blocked_on_refs = [
          (all_related[ref_iid].project_name, all_related[ref_iid].local_id)
          for ref_iid in issue.blocked_on_iids]
      all_blocked_on_refs.extend([
          (r.project, r.issue_id) for r in issue.dangling_blocked_on_refs])
      self.blocked_on_str = ', '.join(
          tracker_bizobj.FormatIssueRef(
              ref, default_project_name=issue.project_name)
          for ref in all_blocked_on_refs)
      all_blocking_refs = [
          (all_related[ref_iid].project_name, all_related[ref_iid].local_id)
          for ref_iid in issue.blocking_iids]
      all_blocking_refs.extend([
          (r.project, r.issue_id) for r in issue.dangling_blocking_refs])
      self.blocking_str = ', '.join(
          tracker_bizobj.FormatIssueRef(
              ref, default_project_name=issue.project_name)
          for ref in all_blocking_refs)
      if issue.merged_into:
        merged_issue = all_related[issue.merged_into]
        merged_into_ref = merged_issue.project_name, merged_issue.local_id
      else:
        merged_into_ref = None
      self.merged_into_str = tracker_bizobj.FormatIssueRef(
          merged_into_ref, default_project_name=issue.project_name)

    self.blocked_on = []
    self.has_dangling = ezt.boolean(self.dangling_blocked_on_refs)
    self.blocking = []
    current_project_name = issue.project_name

    if open_related is not None and closed_related is not None:
      self.merged_into = IssueRefView(
          current_project_name, issue.merged_into,
          open_related, closed_related)

      self.blocked_on = [
          IssueRefView(current_project_name, iid, open_related, closed_related)
          for iid in blocked_on_iids]
      self.blocked_on.extend(
          [DanglingIssueRefView(ref.project, ref.issue_id)
           for ref in issue.dangling_blocked_on_refs])
      self.blocked_on = [irv for irv in self.blocked_on if irv.visible]
      # TODO(jrobbins): sort by irv project_name and local_id

      self.blocking = [
          IssueRefView(current_project_name, iid, open_related, closed_related)
          for iid in blocking_iids]
      self.blocking.extend(
          [DanglingIssueRefView(ref.project, ref.issue_id)
           for ref in issue.dangling_blocking_refs])
      self.blocking = [irv for irv in self.blocking if irv.visible]
      # TODO(jrobbins): sort by irv project_name and local_id

    self.multiple_blocked_on = ezt.boolean(len(self.blocked_on) >= 2)
    self.detail_relative_url = tracker_helpers.FormatRelativeIssueURL(
        issue.project_name, urls.ISSUE_DETAIL, id=issue.local_id)