From e0be7ef062ae202e9ac2cefa8292b2f2cbba104d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 1/11] Increase the number of blacklisted project names --- diff --git a/pagure/default_config.py b/pagure/default_config.py index 246d8df..79f645c 100644 --- a/pagure/default_config.py +++ b/pagure/default_config.py @@ -198,7 +198,9 @@ APPLICATION_ROOT = '/' # List of blacklisted project names BLACKLISTED_PROJECTS = [ 'static', 'pv', 'releases', 'new', 'api', 'settings', - 'logout', 'login', 'users', 'groups', 'projects', 'ssh_info'] + 'logout', 'login', 'users', 'groups', 'projects', 'ssh_info' + 'issues', 'pull-requests', 'commits', 'tree', 'forks', +] # List of prefix allowed in project names ALLOWED_PREFIX = [] From cab0ee49c5e5c8a5b8b10f9ca8a6c790a6ecd67b Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 2/11] Add a form used when adding a new report --- diff --git a/pagure/forms.py b/pagure/forms.py index 9b12c28..8b46de4 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -502,3 +502,12 @@ class ForkRepoForm(wtf.Form): 'The project namespace', [wtforms.validators.optional()] ) + + +class AddReportForm(wtf.Form): + """ Form to verify that comment is not empty + """ + report_name = wtforms.TextAreaField( + 'Report name*', + [wtforms.validators.Required()] + ) From 2fee4f8847d7a48d1b5f2bee65bcd67184d636dc Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 3/11] Add a reports property to the projects That's the JSON blob that will contain the information about the filtering to do for each report (as well as the name of the report). --- diff --git a/pagure/lib/model.py b/pagure/lib/model.py index dd10e60..cfab888 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -318,6 +318,7 @@ class Project(BASE): nullable=True) _priorities = sa.Column(sa.Text, nullable=True) _milestones = sa.Column(sa.Text, nullable=True) + _reports = sa.Column(sa.Text, nullable=True) date_created = sa.Column(sa.DateTime, nullable=False, default=datetime.datetime.utcnow) @@ -440,6 +441,23 @@ class Project(BASE): self._priorities = json.dumps(priorities) @property + def reports(self): + """ Return the dict stored as string in the database as an actual + dict object. + """ + reports = {} + + if self._reports: + reports = json.loads(self._reports) + + return reports + + @reports.setter + def reports(self, reports): + ''' Ensures the reports are properly saved. ''' + self._reports = json.dumps(reports) + + @property def open_requests(self): ''' Returns the number of open pull-requests for this project. ''' return BASE.metadata.bind.query( From cd66151d662d73b118dc414cb7d4df8c9bd3ca38 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 4/11] Add a method to save the filters applied in a given URL to the database This is the method saving the report with a given name --- diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index c2a9d37..eefd0f1 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -3030,3 +3030,15 @@ def user_watch_list(session, user): watch.remove(project) return sorted(list(watch), key=lambda proj: proj.name) + + +def save_report(session, repo, name, url, username): + """ Save the report of issues based on the given URL of the project. + """ + url_obj = urlparse.urlparse(url) + url = url_obj.geturl().replace(url_obj.query, '') + query = dict(urlparse.parse_qsl(url_obj.query)) + reports = repo.reports + reports[name] = query + repo.reports = reports + session.add(repo) From e156e2f863a1772e7a8649da3587e60e1bd996e5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 5/11] Add the UI endpoint to save a report to the database --- diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 9f2578d..8d61432 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -1122,3 +1122,39 @@ def edit_comment_issue( comment=comment, is_js=is_js, ) + + +@APP.route('//issues/reports', methods=['POST']) +@APP.route('///issues/reports', methods=['POST']) +@APP.route('/fork///issues/reports', methods=['POST']) +@APP.route( + '/fork////issues/reports', methods=['POST']) +@login_required +def save_reports(repo, username=None, namespace=None): + """ Marked for watching or Unwatching + """ + + return_point = flask.url_for( + 'view_issues', repo=repo, username=username, namespace=namespace) + if pagure.is_safe_url(flask.request.referrer): + return_point = flask.request.referrer + + form = pagure.forms.AddReportForm() + if not form.validate_on_submit(): + flask.abort(400) + + name = form.report_name.data + + try: + msg = pagure.lib.save_report( + SESSION, + flask.g.repo, + name=name, + url=flask.request.referrer, + username=flask.g.fas_user.username) + SESSION.commit() + flask.flash(msg) + except pagure.exceptions.PagureException as msg: + flask.flash(msg, 'error') + + return flask.redirect(return_point) From e47caa492733f94f15ea00867ccc3ac785411170 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 6/11] Add the button to save the current view as a report --- diff --git a/pagure/templates/issues.html b/pagure/templates/issues.html index f45d9cd..9a8930c 100644 --- a/pagure/templates/issues.html +++ b/pagure/templates/issues.html @@ -253,6 +253,40 @@ + + + {{ pagination_link('page', g.page, total_page) }} {% endblock %} From 77b2fd676807bc28acf9c8411865c2c749ae8edf Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 7/11] Add the endpoint to view a given report --- diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 8d61432..53095db 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -21,6 +21,7 @@ from collections import defaultdict from math import ceil import pygit2 +import werkzeug.datastructures from sqlalchemy.exc import SQLAlchemyError import chardet @@ -500,6 +501,7 @@ def view_issues(repo, username=None, namespace=None): author=author, priority=priority, total_page=total_page, + add_report_form=pagure.forms.AddReportForm(), ) @@ -1158,3 +1160,21 @@ def save_reports(repo, username=None, namespace=None): flask.flash(msg, 'error') return flask.redirect(return_point) + + +@APP.route('//report/') +@APP.route('///report/') +@APP.route('/fork///report/') +@APP.route('/fork////report/') +@login_required +def view_report(repo, report, username=None, namespace=None): + """ Show the specified report. + """ + reports = flask.g.repo.reports + if report not in reports: + flask.abort(404, 'No such report found') + + flask.request.args = werkzeug.datastructures.ImmutableMultiDict( + reports[report]) + + return view_issues(repo=repo, username=username, namespace=namespace) From a11e8056cab9decb1619b66be2a1b6b623a721df Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 8/11] Add the button in the issue page to load a certain report --- diff --git a/pagure/templates/issues.html b/pagure/templates/issues.html index 9a8930c..cfd0049 100644 --- a/pagure/templates/issues.html +++ b/pagure/templates/issues.html @@ -29,6 +29,24 @@ Roadmap {% endif %} + {% if g.repo.reports %} + + {% endif %} {% if oth_issues %} From cc9dd89cb3cbe13631d06f85283fbfdbb9b499b0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Sep 13 2016 06:47:20 +0000 Subject: [PATCH 9/11] Fix indentation in the repo_master template --- diff --git a/pagure/templates/repo_master.html b/pagure/templates/repo_master.html index e027c29..95abc8c 100644 --- a/pagure/templates/repo_master.html +++ b/pagure/templates/repo_master.html @@ -9,96 +9,98 @@
-

- - {% if repo.is_fork -%} - - {{ repo.user.user }}/{{ - repo.namespace + '/' if repo.namespace - }}{{ repo.name}} - {%- else -%} - {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }} - {%- endif -%} - - {% if authenticated %} -
- {% if repo.settings.get('issue_tracker', True) - and config.get('ENABLE_TICKETS', True)%} - + + {% if repo.is_fork -%} + + {{ repo.user.user }}/{{ + repo.namespace + '/' if repo.namespace + }}{{ repo.name}} + {%- else -%} + {{ repo.namespace + '/' if repo.namespace }}{{ repo.name }} + {%- endif -%} + + {% if authenticated %} +
+ {% if repo.settings.get('issue_tracker', True) + and config.get('ENABLE_TICKETS', True)%} + New Issue + {% endif %} +
+ {% if not repo.is_fork %} +
+ {{ forkbuttonform.csrf_token }} +
+ + {% endif %} + + - {% endif %} + user=repo.user.user if repo.is_fork else None, + namespace=repo.namespace, + watch=0) }}"> + {%- if is_watching( + repo.name, + repo.user.user if repo.is_fork else None, + repo.namespace) + %} + Stop watching {{ + repo.name }} + {% else %} + Watch {{ + repo.name }} + {% endif -%} - {% if authenticated %} -
+ {{ forkbuttonform.csrf_token }} +
{% endif %}

{% if repo.is_fork and repo.parent %} {% elif repo.is_fork and not repo.parent %}
@@ -109,6 +111,7 @@ {% if repo.description %}{{ repo.description | safe }}{% else %}-{% endif -%} {%- if repo.url %}  |  {{ repo.url }}{% endif %}
+