#542 add new issues widget to replace pagureissues and githubissues
Merged 6 years ago by abompard. Opened 6 years ago by ryanlerch.
ryanlerch/fedora-hubs team-issues  into  develop

file modified
+1 -3
@@ -57,19 +57,17 @@ 

  

  WIDGETS = [

      'hubs.widgets.badges:Badges',

-     'hubs.widgets.bugzilla:Bugzilla',

      'hubs.widgets.library:Library',

      'hubs.widgets.weeklyactivity:WeeklyActivity',

      'hubs.widgets.feed:Feed',

-     'hubs.widgets.githubissues:GitHubIssues',

      'hubs.widgets.halp:Halp',

      'hubs.widgets.irc:IRC',

+     'hubs.widgets.newestissues:NewestIssues',

      'hubs.widgets.meetings:Meetings',

      'hubs.widgets.mailinglist:MailingList',

      'hubs.widgets.memberships:Memberships',

      'hubs.widgets.my_hubs:MyHubs',

      'hubs.widgets.pullrequests:PullRequests',

-     'hubs.widgets.pagureissues:PagureIssues',

      'hubs.widgets.repositories:Repositories',

      'hubs.widgets.sticky:Sticky',

      'hubs.widgets.issues:Issues',

@@ -56,7 +56,8 @@ 

      def test_move_widget(self):

          hub = Hub(name="testing", hub_type="team")

          self.session.add(hub)

-         widget_names = ["meetings", "badges", "bugzilla", "my_hubs", "sticky"]

+         widget_names = ["meetings", "badges", "newestissues",

+                         "my_hubs", "sticky"]

  

          def get_names():

              return [
@@ -83,23 +84,23 @@ 

          # From middle to middle forwards

          check_move(

              "badges", 3,

-             ["meetings", "bugzilla", "my_hubs", "badges", "sticky"])

+             ["meetings", "newestissues", "my_hubs", "badges", "sticky"])

          # From middle to middle backwards

          check_move(

              "badges", 1,

-             ["meetings", "badges", "bugzilla", "my_hubs", "sticky"])

+             ["meetings", "badges", "newestissues", "my_hubs", "sticky"])

          # From middle to start

          check_move(

              "my_hubs", 0,

-             ["my_hubs", "meetings", "badges", "bugzilla", "sticky"])

+             ["my_hubs", "meetings", "badges", "newestissues", "sticky"])

          # From middle to end

          check_move(

              "badges", 5,

-             ["my_hubs", "meetings", "bugzilla", "sticky", "badges"])

+             ["my_hubs", "meetings", "newestissues", "sticky", "badges"])

          # From start to end

          check_move(

              "my_hubs", 5,

-             ["meetings", "bugzilla", "sticky", "badges", "my_hubs"])

+             ["meetings", "newestissues", "sticky", "badges", "my_hubs"])

  

      def test_move_widget_disabled(self):

          # Make sure moving works even if there are disabled widgets

@@ -200,32 +200,35 @@ 

      def test_post_invalid_config(self):

          hub = Hub.by_name("ralph", "user")

          self.session.add(Widget(

-             hub=hub, plugin="bugzilla", index=0))

+             hub=hub, plugin="newestissues", index=0))

          self.session.commit()

          self.assertEqual(

              Widget.query.filter_by(

-                 hub=hub, plugin="bugzilla").count(), 1)

+                 hub=hub, plugin="newestissues").count(), 1)

+         widget_class = registry["newestissues"]

          data = {

-             "name": "bugzilla",

+             "name": "newestissues",

              "config": {"foo": "bar"},

              'position': 'right',

              }

          user = FakeAuthorization('ralph')

-         with auth_set(app, user):

-             result = self.app.post(

-                 '/api/hubs/%s/widgets/' % hub.id,

-                 content_type="application/json",

-                 data=json.dumps(data))

+         with patch.object(

+                 widget_class, "parameters", [{"name": "required"}]):

+             with auth_set(app, user):

+                 result = self.app.post(

+                     '/api/hubs/%s/widgets/' % hub.id,

+                     content_type="application/json",

+                     data=json.dumps(data))

          self.assertEqual(result.status_code, 200)

          self.assertEqual(

              json.loads(result.get_data(as_text=True)),

              {

                  "status": "ERROR",

-                 "message": "You must provide a value for: username",

+                 "message": "You must provide a value for: required",

               })

          self.assertEqual(

              Widget.query.filter_by(

-                 hub=hub, plugin="bugzilla").count(), 1)

+                 hub=hub, plugin="newestissues").count(), 1)

  

  

  class TestAPIHubWidget(APPTest):

@@ -1,54 +0,0 @@ 

- from __future__ import unicode_literals

- 

- from . import WidgetTest

- 

- 

- class TestGithubIssues(WidgetTest):

- 

-     plugin = "githubissues"

-     initial_widget_config = {

-         "org": "fedora-infra",

-         "repo": "fedora-hubs",

-     }

- 

-     def populate(self):

-         super(TestGithubIssues, self).populate()

-         self._add_widget_under_test()

- 

-     def _get_should_invalidate_result(self, msg):

-         func = self.widget.module.get_cached_functions()['GetIssues']

-         return func(self.widget).should_invalidate(msg)

- 

-     def test_should_invalidate_wrong_topic(self):

-         msg = {'topic': 'hubs.widget.update.WRONG.TOPIC'}

-         self.assertFalse(self._get_should_invalidate_result(msg))

- 

-     def test_should_invalidate_good_match(self):

-         msg = {

-             'topic': 'tests.github.issue.opened',

-             'msg': {

-                 'organization': 'fedora-infra',

-                 'repository': 'fedora-hubs',

-             }

-         }

-         self.assertTrue(self._get_should_invalidate_result(msg))

- 

-     def test_should_invalidate_wrong_org(self):

-         msg = {

-             'topic': 'tests.github.issue.opened',

-             'msg': {

-                 'organization': 'not_fedora_infra',

-                 'repository': 'fedora-hubs',

-             }

-         }

-         self.assertFalse(self._get_should_invalidate_result(msg))

- 

-     def test_should_invalidate_wrong_repo(self):

-         msg = {

-             'topic': 'tests.github.issue.opened',

-             'msg': {

-                 'organization': 'fedora-infra',

-                 'repository': 'not-fedora-hubs',

-             }

-         }

-         self.assertFalse(self._get_should_invalidate_result(msg))

hubs/tests/widgets/test_newestissues.py hubs/tests/widgets/test_pagureissues.py
file renamed
+36 -12
@@ -3,26 +3,42 @@ 

  from . import WidgetTest

  

  

- class TestPagureIssues(WidgetTest):

+ class TestNewestIssues(WidgetTest):

  

-     plugin = "pagureissues"

-     initial_widget_config = {

-         "repo": "fedora-hubs",

-     }

+     plugin = "newestissues"

  

      def populate(self):

-         super(TestPagureIssues, self).populate()

+         super(TestNewestIssues, self).populate()

          self._add_widget_under_test()

  

-     def _get_should_invalidate_result(self, msg):

-         func = self.widget.module.get_cached_functions()['GetIssues']

+     def _get_pagure_should_invalidate_result(self, msg):

+         func = self.widget.module.get_cached_functions()['GetPagureIssues']

+         return func(self.widget).should_invalidate(msg)

+ 

+     def _get_github_should_invalidate_result(self, msg):

+         func = self.widget.module.get_cached_functions()['GetGithubIssues']

          return func(self.widget).should_invalidate(msg)

  

      def test_should_invalidate_wrong_topic(self):

          msg = {'topic': 'hubs.widget.update.WRONG.TOPIC'}

-         self.assertFalse(self._get_should_invalidate_result(msg))

+         self.assertFalse(self._get_pagure_should_invalidate_result(msg))

+         self.assertFalse(self._get_github_should_invalidate_result(msg))

+ 

+     def test_github_should_invalidate_good_match(self):

+         self.widget.hub.config["github"] = ["fedora-infra/bodhi"]

+ 

+         msg = {

+             'topic': 'tests.github.issue.opened',

+             'msg': {

+                 'repository': {

+                     'fullname': 'fedora-infra/bodhi',

+                 },

+             }

+         }

+         self.assertTrue(self._get_github_should_invalidate_result(msg))

  

-     def test_should_invalidate_good_match(self):

+     def test_pagure_should_invalidate_good_match(self):

+         self.widget.hub.config["pagure"] = ["fedora-hubs"]

          msg = {

              'topic': 'tests.pagure.issue.new',

              'msg': {
@@ -31,7 +47,7 @@ 

                  },

              },

          }

-         self.assertTrue(self._get_should_invalidate_result(msg))

+         self.assertTrue(self._get_pagure_should_invalidate_result(msg))

  

      def test_should_invalidate_wrong_repo(self):

          msg = {
@@ -42,4 +58,12 @@ 

                  },

              },

          }

-         self.assertFalse(self._get_should_invalidate_result(msg))

+         self.assertFalse(self._get_pagure_should_invalidate_result(msg))

+ 

+         msg = {

+             'topic': 'tests.github.issue.opened',

+             'msg': {

+                 'fullname': 'not_fedora_infra/fedora-hubs',

+             }

+         }

+         self.assertFalse(self._get_github_should_invalidate_result(msg))

file modified
+24
@@ -58,6 +58,30 @@ 

          )

  

  

+ def github_issues(repo, token=None):

+     log.info("Finding github issues for %r" % (repo))

+     tmpl = "https://api.github.com/repos/{repo}/" + \

+         "issues?per_page=100"

+     url = tmpl.format(repo=repo)

+     if token:

+         token = dict(access_token=token)

+     for result in _github_results(url, token):

+         yield dict(

+             issue_project_url='/'.join(["https://github.com", repo]),

+             issue_url='/'.join(["https://github.com",

+                                 repo, "pull", str(result['number'])]),

+             issue_project_name=repo,

+             issue_id=result['number'],

+             issue_title=result['title'][:40],

+             issue_title_full=result['title'],

+             issue_openedby=result['user']['login'],

+             issue_assignee=result['assignee'],

+             issue_repo=repo,

+             issue_hosting_type="Github",

+             issue_opened_date=arrow.get(result['created_at']).timestamp,

+         )

+ 

+ 

  def _github_results(url, auth):

      link = dict(next=url)

      while 'next' in link:

file modified
+44 -1
@@ -40,5 +40,48 @@ 

                  pr_assignee=request['assignee'],

                  pr_repo=repo,

                  pr_hosting_type="Pagure",

-                 pr_opened_date=arrow.get(int(request['date_created'])),

+                 pr_opened_date=arrow.get(int(request['date_created'])

+                                          ).timestamp,

+             )

+ 

+ 

+ def pagure_issues(repo):

+     url = '/'.join([PAGURE_URL, "api", "0", repo, "issues"])

+     response = requests.get(url)

+     data = response.json()

+ 

+     for issue in data['issues']:

+ 

+         issue_assignee = None

+         if issue['assignee']:

+             issue_assignee = issue['assignee']['name']

+ 

+         issue_project_user = None

+         issue_project_name = repo

+         if 'project' in issue:

+             issue_project_name = issue['project']['name']

+             if issue['project']['parent']:

+                 issue_project_user = issue['project']['user']['username']

+             else:

+                 if '/' in repo:

+                     issue_project_name, issue_project_user = \

+                         repo.split('/', 1)

+                 else:

+                     issue_project_name = repo

+ 

+         yield dict(

+                 issue_project_url="/".join([PAGURE_URL, repo]),

+                 issue_url="/".join([PAGURE_URL, repo,

+                                     "issue", str(issue['id'])]),

+                 issue_project_name=issue_project_name,

+                 issue_project_user=issue_project_user,

+                 issue_id=issue['id'],

+                 issue_title=issue['title'][:45],

+                 issue_title_full=issue['title'],

+                 issue_openedby=issue['user']['name'],

+                 issue_assignee=issue_assignee,

+                 issue_repo=repo,

+                 issue_hosting_type="Pagure",

+                 issue_opened_date=arrow.get(int(issue['date_created'])

+                                             ).timestamp,

              )

@@ -1,85 +0,0 @@ 

- from __future__ import unicode_literals

- 

- import logging

- 

- import pkgwat.api

- 

- from hubs.utils import validators

- from hubs.utils.packages import get_user_packages

- from hubs.widgets.base import Widget

- from hubs.widgets.view import RootWidgetView

- from hubs.widgets.caching import CachedFunction

- 

- 

- log = logging.getLogger('hubs.widgets')

- 

- 

- class Bugzilla(Widget):

- 

-     name = "bugzilla"

-     label = "Bugzilla issues"

-     position = "right"

-     parameters = [dict(

-             name="username",

-             label="Username",

-             default=None,

-             validator=validators.Username,

-             help="A FAS username.",

-         ), dict(

-             name="max",

-             label="Max number of issues",

-             default=3,

-             validator=validators.Integer,

-             help="The maximum number of issues to display.",

-         )]

- 

- 

- class BaseView(RootWidgetView):

- 

-     def get_context(self, instance, *args, **kwargs):

-         get_issues = GetIssues(instance)

-         return dict(

-             username=instance.config["username"],

-             issues=get_issues() or []

-             )

- 

- 

- class GetIssues(CachedFunction):

-     """Returns data for Bugzilla widget.

- 

-     Queries Bugzilla for issues on the user's packages.

-     """

- 

-     def execute(self):

-         username = self.instance.config["username"]

-         max_num = int(self.instance.config.get("max", 3))

-         owned = get_user_packages(username)

-         issues = []

-         for pkg_name in owned:

-             if len(issues) == max_num:

-                 break

-             try:

-                 pkg_details = pkgwat.api.bugs(pkg_name)

-             except ValueError:

-                 # Usually a JSON decoding error. Fail now and don't cache.

-                 return None

-             for row in pkg_details['rows']:

-                 if len(issues) == max_num:

-                     break

-                 issues.append(

-                     dict(

-                         id=row['id'],

-                         title=row['description'],

-                         pkg_name=pkg_name,

-                     )

-                 )

-         return issues

- 

-     def should_invalidate(self, message):

-         try:

-             component = message['msg']['bug']['component']

-         except KeyError:

-             return False

-         username = self.instance.config["username"]

-         owned = get_user_packages(username)

-         return (component in owned)

@@ -1,17 +0,0 @@ 

- <ul class="list-unstyled mb-0">

-   {% for item in issues %}

-     <li class="media py-2">

-       <div class="align-self-center mr-3">

-         <a href="https://bugzilla.redhat.com/show_bug.cgi?id={{ item['id'] }}" target="_blank">

-         <span class="badge badge-primary">#{{ item['id'] }}</span>

-         </a>

-       </div>

-       <div class="media-body">

-         <h5 class="mt-0">

-           <a href="https://apps.fedoraproject.org/packages/{{ item['pkg_name'] }}" target="_blank">{{ item['pkg_name'] }}</a>:

-           {{ item['title'] }}

-         </h5>

-       </div>

-     </li>

-   {% endfor %}

- </ul>

@@ -1,104 +0,0 @@ 

- from __future__ import unicode_literals

- 

- import requests

- 

- from hubs.utils import validators

- from hubs.widgets.base import Widget

- from hubs.widgets.view import RootWidgetView

- from hubs.widgets.caching import CachedFunction

- 

- 

- # TODO: use a checkbox set to select which repos to use from the hub's

- # configuration.

- 

- 

- class GitHubIssues(Widget):

- 

-     name = "githubissues"

-     label = "Github: Newest Open Tickets"

-     position = "right"

-     parameters = [

-         dict(

-             name="org",

-             label="Username",

-             default=None,

-             validator=validators.GithubOrganization,

-             help="Github Organization or username",

-         ), dict(

-             name="repo",

-             label="Repository",

-             default=None,

-             validator=validators.GithubRepo,

-             help="Github repository",

-         ), dict(

-             name="display_number",

-             label="Number of tickets",

-             default=10,

-             validator=validators.Integer,

-             help="The number of tickets to display.",

-         )]

- 

-     def validate_parameters(self, values):

-         config = {}

-         config["org"] = \

-             validators.GithubOrganization(values["org"])

-         config["repo"] = \

-             validators.GithubRepo('/'.join([values["org"],

-                                            values["repo"]]))

-         config["display_number"] = \

-             validators.Integer(values["display_number"])

-         return config

- 

- 

- class BaseView(RootWidgetView):

- 

-     def get_context(self, instance, *args, **kwargs):

-         get_issues = GetIssues(instance)

-         return dict(

-             org=instance.config["org"],

-             repo=instance.config["repo"],

-             display_number=instance.config["display_number"],

-             all_issues=get_issues(),

-         )

- 

- 

- class GetIssues(CachedFunction):

-     ''' Data for Github Issues widget. Queries github api for issues '''

- 

-     def execute(self):

-         org = self.instance.config["org"]

-         repo = self.instance.config["repo"]

-         display_number = int(self.instance.config["display_number"])

-         url = '/'.join(['https://api.github.com/repos', org, repo, "issues"])

-         issues = requests.get(url).json()

- 

-         all_issues = []

-         for issue in issues[:display_number]:

-             issue_details = {}

-             issue_details['num'] = issue['number']

-             issue_details['title'] = issue['title']

-             issue_details['openedby'] = issue['user']['login']

- 

-             issue_assignee = None

-             if issue['assignee'] is not None:

-                 issue_assignee = issue['assignee']['login']

- 

-             issue_details['assignee'] = issue_assignee

-             all_issues.append(issue_details)

- 

-         all_issues.reverse()

-         return all_issues

- 

-     def should_invalidate(self, message):

-         if ".github.issue." not in message["topic"]:

-             return False

-         try:

-             org = message['msg']['organization']

-             repo = message['msg']['repository']

-         except KeyError:

-             return False

-         return (

-             org == self.instance.config["org"]

-             and

-             repo == self.instance.config["repo"]

-             )

@@ -1,40 +0,0 @@ 

- <ul class="list-unstyled">

- 

- {% for i in range(display_number) %}

- <li class="media">

-   <div class="align-self-center mr-3">

-     <a href="#" target="_blank">

-       <span class="badge badge-primary">#{{ all_issues[i]['num'] }}</span>

-     </a>

-   </div>

-   <div class="media-body">

-     <h5 class="mt-0">

-         {{ all_issues[i]['title'] }}

-     </h5>

-     <div class="row no-gutters">

-       <div class="col-md-10">

-         <i>Opened by <a href="https://github.com/{{ all_issues[i]['openedby'] }}" target="_blank">{{ all_issues[i]['openedby'] }}</a></i>

-           {% if all_issues[i]['assignee']|string() == "None" %}

-             <br /><i>Unclaimed</i>

-           {% else %}

-              <br /><i>Assigned by <a href="https://github.com/{{ all_issues[i]['assignee'] }}" target="_blank">{{ all_issues[i]['assignee'] }}</a></i>

-           {% endif %}

- 

-       </div>

-       <div class="col-md-2">

-       <a href="https://github.com/{{ org }}/{{ repo }}/issues/{{ all_issues[i]['num'] }}" target="_blank">

-            <button type="button" class="btn btn-secondary btn-sm" aria-label="Left Align">

-              <i class="fa fa-chevron-right" aria-hidden="true"></i>

-            </button>

-          </a>

-       </div>

-     </div>

-   </div>

- </li>

- {% endfor %}

- 

- </ul>

- 

- <div class="row">

-   <a href="https://github.com/{{ org }}/{{ repo }}/issues" target="_blank"><center>All Issues</center></a>

- </div>

@@ -0,0 +1,104 @@ 

+ from __future__ import unicode_literals

+ 

+ from hubs.utils import pagure

+ from hubs.utils.github import github_issues

+ from hubs.utils.fedmsg import get_fedmsg_config

+ from hubs.widgets.base import Widget

+ from hubs.widgets.view import RootWidgetView

+ from hubs.widgets.caching import CachedFunction

+ 

+ fedmsg_config = get_fedmsg_config()

+ 

+ 

+ class NewestIssues(Widget):

+ 

+     name = "newestissues"

+     label = "Newest Open Issues"

+     position = "right"

+     hub_types = ['team']

+ 

+ 

+ class BaseView(RootWidgetView):

+ 

+     def get_context(self, instance, *args, **kwargs):

+         get_pagure_issues = GetPagureIssues(instance)

+         get_github_issues = GetGithubIssues(instance)

+ 

+         all_issues = get_github_issues() + get_pagure_issues()

+ 

+         all_issues = sorted(all_issues,

+                             key=lambda x: x["issue_opened_date"],

+                             reverse=True)

+ 

+         return dict(all_issues=all_issues)

+ 

+ 

+ class GetPagureIssues(CachedFunction):

+     def __init__(self, instance):

+         self.instance = instance

+         self.invalidate()

+ 

+     def execute(self):

+         all_issues = list()

+         for repo in self.instance.hub.config["pagure"]:

+             try:

+                 issues = pagure.pagure_issues(repo)

+             except ValueError:

+                 continue

+ 

+             for issue in issues:

+                 all_issues.append(issue)

+ 

+         return all_issues

+ 

+     def should_invalidate(self, message):

+         pagure_repos = self.instance.hub.config["pagure"]

+         if ".pagure.issue." in message["topic"]:

+             try:

+                 repo = message['msg']['project']['name']

+             except KeyError:

+                 print("KeyError")

+                 return False

+             return (repo in pagure_repos)

+         elif message["topic"].endswith('.hubs.hub.updated'):

+             if ("pagure" in message["msg"]["changed_keys"]):

+                 hub_id = message["msg"]["hub_id"]

+                 if hub_id == self.instance.hub.id:

+                     return True

+             else:

+                 return False

+         else:

+             return False

+ 

+ 

+ class GetGithubIssues(CachedFunction):

+     def __init__(self, instance):

+         self.instance = instance

+         self.invalidate()

+ 

+     def execute(self):

+         all_issues = list()

+ 

+         for repo in self.instance.hub.config["github"]:

+             for issue in github_issues(repo, token=None):

+                 all_issues.append(issue)

+ 

+         return all_issues

+ 

+     def should_invalidate(self, message):

+         github_repos = self.instance.hub.config["github"]

+         if ".github.issue." in message["topic"]:

+             try:

+                 repo = message['msg']['repository']['fullname']

+             except KeyError:

+                 return False

+             return (repo in github_repos)

+         elif message["topic"].endswith('.hubs.hub.updated'):

+             if ("github" in message["msg"]["changed_keys"]):

+                 hub_id = message["msg"]["hub_id"]

+                 if hub_id == self.instance.hub.id:

+                     return True

+             else:

+                 return False

+         else:

+             return False

@@ -0,0 +1,28 @@ 

+ <ul class="list-unstyled">

+     {% for issue in all_issues[:10] %}

+       <li class="media py-2">

+         <div class="media-body">

+           <div>

+               <a  href="{{ issue['issue_url'] }}"

+               target="_blank">

+                 <span class="badge badge-secondary">#{{ issue['issue_id'] }}</span>

+                 <span title="{{ issue['issue_title_full'] }}">

+                     {{ issue['issue_title'] }} {% if

+                       issue['issue_title_full'] | length > 40 %} ... {% endif %}

+                   </span>

+             </a>

+             

+   

+           </div>

+           <small>

+             Opened {{issue['issue_opened_date']|humanize}} in 

+             <a href="{{ issue['issue_project_url'] }}"

+                 target="_blank"

+                 title="the {{ issue['issue_project_name'] }} repo">

+             {{ issue['issue_project_name'] }}

+             </a> by {{ issue['issue_openedby'] }}

+           </small>

+         </div>

+       </li>

+     {% endfor %}

+   </ul> 

\ No newline at end of file

@@ -1,96 +0,0 @@ 

- from __future__ import unicode_literals

- 

- import requests

- 

- from hubs.utils import validators, pagure

- from hubs.widgets.base import Widget

- from hubs.widgets.view import RootWidgetView

- from hubs.widgets.caching import CachedFunction

- 

- # TODO: use a checkbox set to select which repos to use from the hub's

- # configuration.

- 

- 

- class PagureIssues(Widget):

- 

-     name = "pagureissues"

-     label = "Pagure: Newest Open Tickets"

-     position = "right"

-     parameters = [

-         dict(

-             name="repo",

-             label="Repository",

-             default=None,

-             validator=validators.PagureRepo,

-             help="Pagure repo name",

-         )]

- 

- 

- class BaseView(RootWidgetView):

- 

-     def get_context(self, instance, *args, **kwargs):

-         get_issues = GetIssues(instance)

-         context = dict(

-             repo=instance.config["repo"],

-             )

-         context.update(get_issues())

-         return context

- 

- 

- class GetIssues(CachedFunction):

-     ''' Data for pagure issues widget

-     Queries Pagure api for issues '''

- 

-     def execute(self):

-         repo = self.instance.config["repo"]

- 

-         url = '/'.join([pagure.PAGURE_URL, "api", "0", repo, "issues"])

-         issue_response = requests.get(url)

-         data = issue_response.json()

-         total = data['total_issues']

- 

-         all_issues = list()

-         for issue in data['issues']:

- 

-             issue_assignee = None

-             if issue['assignee']:

-                 issue_assignee = issue['assignee']['name']

- 

-             issue_project_user = None

-             if 'project' in issue:

-                 issue_project_name = issue['project']['name']

-                 if issue['project']['parent']:

-                     issue_project_user = issue['project']['user']['username']

-                 else:

-                     if '/' in repo:

-                         issue_project_name, issue_project_user = \

-                             repo.split('/', 1)

-                     else:

-                         issue_project_name = repo

- 

-             all_issues.append(

-                 dict(

-                     issue_project_name=issue_project_name,

-                     issue_project_user=issue_project_user,

-                     issue_id=issue['id'],

-                     issue_title=issue['title'][:45],

-                     issue_title_full=issue['title'],

-                     issue_openedby=issue['user']['name'],

-                     issue_assignee=issue_assignee,

-                 )

-             )

- 

-         all_issues.reverse()

-         return dict(

-             total=total,

-             all_issues=all_issues,

-         )

- 

-     def should_invalidate(self, message):

-         if ".pagure.issue." not in message["topic"]:

-             return False

-         try:

-             repo = message['msg']['project']['name']

-         except KeyError:

-             return False

-         return (repo == self.instance.config['repo'])

@@ -1,49 +0,0 @@ 

- <a class="btn btn-success" target="_blank"

-     href="https://pagure.io/{{ repo }}/issues">

-   All Issues

- </a>

- <hr/>

- 

- <ul class="list-unstyled">

-   {% for issue in all_issues[:10] %}

-     <li class="media py-2">

-       <div class="align-self-center mr-3">

-         <a  href="https://pagure.io/{{ repo }}/issue/{{ issue['issue_id'] }}"

-             target="_blank">

-           {{ issue['issue_project_name'] }}

-         <span class="badge badge-primary">#{{ issue['issue_id'] }}</span>

-         </a>

-       </div>

-       <div class="media-body">

-         <h5 class="mt-0">

-           <span title="{{ issue['issue_title_full'] }}">

-             {{ issue['issue_title'] }} {% if

-               issue['issue_title_full'] | length > 45 %} ... {% endif %}

-           </span>

-         </h5>

- 	<small>

-         Opened by:

-           <a href="https://pagure.io/user/{{ issue['issue_openedby'] }}"

-               target="_blank">

-             {{ issue['issue_openedby'] }}

-           </a>

-         --

-         {% if issue['issue_assignee'] %}

-           Assigned to:

-           <a href="https://pagure.io/user/{{issue['issue_assignee'] }}"

-               target="_blank">

-             {{issue['issue_assignee'] }}

-           </a>

-         {% else %}

-           <span class="text-muted">Unassigned</span>

-         {% endif %}

- 	</small>

-       </div>

-     </li>

-   {% endfor %}

-   {% if all_issues | length > 10 %}

-   <li>

-     And {{ all_issues | length - 10 }} more ...

-   </li>

-   {% endif %}

- </ul>

file modified
+7 -1
@@ -23,6 +23,8 @@ 

      "hubs.widgets.meetings:Meetings",

      "hubs.widgets.feed:Feed",

      "hubs.widgets.memberships:Memberships",

+     "hubs.widgets.newestissues:NewestIssues",

+ 

      ])

  

  
@@ -194,7 +196,8 @@ 

      hub.config["mailing_list"] = 'design-team@lists.fedoraproject.org'

      hub.config["chat_domain"] = 'irc.freenode.net'

      hub.config["chat_channel"] = '#fedora-design'

-     hub.config["pagure"] = ['design']

+     hub.config["pagure"] = ['design', "fedora-badges"]

+     hub.config["github"] = ['fedora-infra/bodhi']

      hub.config["calendar"] = 'design'

  

      widget = hubs.models.Widget(plugin='memberships', index=1)
@@ -203,6 +206,9 @@ 

      widget = hubs.models.Widget(plugin='meetings', index=2)

      hub.widgets.append(widget)

  

+     widget = hubs.models.Widget(plugin='newestissues', index=3)

+     hub.widgets.append(widget)

+ 

      widget = hubs.models.Widget(plugin='feed', index=1, left=True)

      hub.widgets.append(widget)

  

This adds a new widget called issues that replaces the
githubissues and pagureissues widgets. It consolodates these into a
single widget that draws the repos from the team hub config

rebased onto 4963c36

6 years ago

rebased, and updated this PR with changes from the comments in #538

  • two cached funtions, one for pagure and one for github
  • not use token for github

also, fixed the tests on thsi one too (forgot to do this earlier...)

What about PR #501 ? It looks like duplicate effort, no?

@abompard for me they are a different IMHO. the user issues widget shows tickets for a user to action, and ones they have filed.

This one is more designed for a team hub to just show the most recent ones filed.

/me hopes this makes sense...

@abompard what do you think we should do with this one? should we just ship it for the teams hub fro 1.0? and change the issues widget that works on user and streams later?

we also need to remove pagureissues and github issues widgets at some point too IMHO. there is the bugzilla widget as well, that i think can be removed as well.

I agree with all that. Let's ship this one and when the issues widget gains team support we'll be able to migrate the few teams that we have created and that may have added this one on their hub.

Let's remove the others too.

thanks @abompard

any review items on this one, or can we merge?

It has to be rebased first, and the widget name conflicts with shaily's issues widget so you need to use another one.

rebased onto 3d7ec93

6 years ago

rebased and renamed. This now also removes the bugzilla widget too.

Elsewhere you've converted that to a timestamp (using the timestamp attribute), I think it's safer to do it here too because of the serializing that will happen before caching.

Same comment as above about timestamp.

It's not about this PR but here there's a conversion to timestamp missing too, it caused a traceback when I tried to display the pullrequests widget.

thanks @abompard! just fixed the three timestamp issues up there.

rebased onto a851195

6 years ago

The hubs.tests.utils.test_views:ViewUtilsTest.test_move_widget now fails because it was using the "bugzilla" widget. I think you can just replace the bugzilla widget name with your new widget, that should work.

There's also a test named test_post_invalid_config in TestAPIHubWidgets that uses the bugzilla widget. This one is trickier to fix because we don't have any widget left with required parameters, so we have to mock it. I suggest the following patch:

diff --git a/hubs/tests/views/test_api_hub_widget.py b/hubs/tests/views/test_api_hub_widget.py
index 8016d835..7c7bd2ca 100644
--- a/hubs/tests/views/test_api_hub_widget.py
+++ b/hubs/tests/views/test_api_hub_widget.py
@@ -200,32 +200,35 @@ class TestAPIHubWidgets(APPTest):
     def test_post_invalid_config(self):
         hub = Hub.by_name("ralph", "user")
         self.session.add(Widget(
-            hub=hub, plugin="bugzilla", index=0))
+            hub=hub, plugin="newestissues", index=0))
         self.session.commit()
         self.assertEqual(
             Widget.query.filter_by(
-                hub=hub, plugin="bugzilla").count(), 1)
+                hub=hub, plugin="newestissues").count(), 1)
+        widget_class = registry["newestissues"]
         data = {
-            "name": "bugzilla",
+            "name": "newestissues",
             "config": {"foo": "bar"},
             'position': 'right',
             }
         user = FakeAuthorization('ralph')
-        with auth_set(app, user):
-            result = self.app.post(
-                '/api/hubs/%s/widgets/' % hub.id,
-                content_type="application/json",
-                data=json.dumps(data))
+        with patch.object(
+                widget_class, "parameters", [{"name": "required"}]):
+            with auth_set(app, user):
+                result = self.app.post(
+                    '/api/hubs/%s/widgets/' % hub.id,
+                    content_type="application/json",
+                    data=json.dumps(data))
         self.assertEqual(result.status_code, 200)
         self.assertEqual(
             json.loads(result.get_data(as_text=True)),
             {
                 "status": "ERROR",
-                "message": "You must provide a value for: username",
+                "message": "You must provide a value for: required",
              })
         self.assertEqual(
             Widget.query.filter_by(
-                hub=hub, plugin="bugzilla").count(), 1)
+                hub=hub, plugin="newestissues").count(), 1)


 class TestAPIHubWidget(APPTest):

@abompard thanks for the patch! applied and fixed!

rebased onto e103644

6 years ago

Almost there! Flake8 says:

./hubs/tests/utils/test_views.py:59:80: E501 line too long (82 > 79 characters)

@abompard thanks! fixed the linting issue, and rebased!

rebased onto 6e44e33

6 years ago

Pull-Request has been merged by abompard

6 years ago