From dff6670c01543053ad63710fd8e958e6da77a2f9 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 20 2017 13:37:52 +0000 Subject: Add a default_priority field to the projects This field must be one of the priorities associated with the project and will be used as the default priority of the new tickets created. Fixes https://pagure.io/pagure/issue/2691 Signed-off-by: Pierre-Yves Chibon --- diff --git a/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py b/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py new file mode 100644 index 0000000..650a0c9 --- /dev/null +++ b/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py @@ -0,0 +1,28 @@ +"""Add default_priority to projects + +Revision ID: e4dbfcd20f42 +Revises: 21292448a775 +Create Date: 2017-10-20 13:34:01.323657 + +""" + +# revision identifiers, used by Alembic. +revision = 'e4dbfcd20f42' +down_revision = '21292448a775' + + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ''' Add default_priority column to projects table''' + + op.add_column( + 'projects', + sa.Column('default_priority', sa.Text, nullable=True) + ) + +def downgrade(): + ''' Revert the default_priority column added''' + op.drop_column('projects', 'default_priority') diff --git a/pagure/forms.py b/pagure/forms.py index e784597..a07b8f3 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -664,6 +664,26 @@ class DefaultBranchForm(PagureForm): ] +class DefaultPriorityForm(PagureForm): + """Form to change the default priority for a repository""" + priority = wtforms.SelectField( + 'default_priority', + [wtforms.validators.optional()], + choices=[] + ) + + def __init__(self, *args, **kwargs): + """ Calls the default constructor with the normal argument but + uses the list of collection provided to fill the choices of the + drop-down list. + """ + super(DefaultPriorityForm, self).__init__(*args, **kwargs) + if 'priorities' in kwargs: + self.priority.choices = [ + (priority, priority) for priority in kwargs['priorities'] + ] + + class EditCommentForm(PagureForm): """ Form to verify that comment is not empty """ diff --git a/pagure/lib/model.py b/pagure/lib/model.py index 81f2390..5df8631 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -374,6 +374,7 @@ class Project(BASE): ), nullable=True) _priorities = sa.Column(sa.Text, nullable=True) + default_priority = sa.Column(sa.Text, nullable=True) _milestones = sa.Column(sa.Text, nullable=True) _quick_replies = sa.Column(sa.Text, nullable=True) _reports = sa.Column(sa.Text, nullable=True) diff --git a/pagure/templates/settings.html b/pagure/templates/settings.html index 0eafd21..aa2ea17 100644 --- a/pagure/templates/settings.html +++ b/pagure/templates/settings.html @@ -590,6 +590,7 @@ and repo.settings.get('issue_tracker', True) %}
+
Priorities
@@ -657,6 +658,47 @@
+ + {% if repo.priorities %} +
+ Default Priority +
+
+

+ The default priority will be set to all issues created after + it has been set. +

+
+ +
+ {{ tag_form.csrf_token }} +
+
+
+ Default priority +
+
+
+ {{ priority_form.priority(class_="c-select") }} +
+ +
+
+ +
+
+
+
+ {% endif %} + diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index d79c370..e7751f5 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -1035,6 +1035,9 @@ def view_settings(repo, username=None, namespace=None): branches = repo_obj.listall_branches() branches_form = pagure.forms.DefaultBranchForm(branches=branches) + priority_form = pagure.forms.DefaultPriorityForm( + priorities=repo.priorities.values()) + if form.validate_on_submit(): settings = {} for key in flask.request.form: @@ -1068,6 +1071,7 @@ def view_settings(repo, username=None, namespace=None): if flask.request.method == 'GET' and branchname: branches_form.branches.data = branchname + priority_form.priorities.data = repo.default_priority return flask.render_template( 'settings.html', @@ -1079,6 +1083,7 @@ def view_settings(repo, username=None, namespace=None): form=form, tag_form=tag_form, branches_form=branches_form, + priority_form=priority_form, tags=tags, plugins=plugins, branchname=branchname, @@ -1281,6 +1286,57 @@ def update_priorities(repo, username=None, namespace=None): namespace=repo.namespace)) +@APP.route('//update/default_priority', methods=['POST']) +@APP.route('///update/default_priority', methods=['POST']) +@APP.route('/fork///update/default_priority', methods=['POST']) +@APP.route( + '/fork////update/default_priority', + methods=['POST']) +@login_required +def default_priority(repo, username=None, namespace=None): + """ Update the default priority of a project. + """ + if admin_session_timedout(): + flask.flash('Action canceled, try it again', 'error') + url = flask.url_for( + 'view_settings', username=username, repo=repo, + namespace=namespace) + return flask.redirect( + flask.url_for('auth_login', next=url)) + + repo = flask.g.repo + + if not repo.settings.get('issue_tracker', True): + flask.abort(404, 'No issue tracker found for this project') + + if not flask.g.repo_admin: + flask.abort( + 403, + 'You are not allowed to change the settings for this project') + + form = pagure.forms.DefaultPriorityForm( + priorities=repo.priorities.values()) + + if form.validate_on_submit(): + priority = form.priority.data or None + if priority in repo.priorities.values() or priority is None: + repo.default_priority = priority + try: + SESSION.add(repo) + SESSION.commit() + if priority: + flask.flash('Default priority set to %s' % priority) + else: + flask.flash('Default priority reset') + except SQLAlchemyError as err: # pragma: no cover + SESSION.rollback() + flask.flash(str(err), 'error') + + return flask.redirect(flask.url_for( + 'view_settings', username=username, repo=repo.name, + namespace=repo.namespace)) + + @APP.route('//update/milestones', methods=['POST']) @APP.route('///update/milestones', methods=['POST']) @APP.route('/fork///update/milestones', methods=['POST']) diff --git a/tests/test_pagure_flask_ui_priorities.py b/tests/test_pagure_flask_ui_priorities.py index 762e9a8..493c8f0 100644 --- a/tests/test_pagure_flask_ui_priorities.py +++ b/tests/test_pagure_flask_ui_priorities.py @@ -20,7 +20,7 @@ import tempfile import os import pygit2 -from mock import patch +from mock import patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) @@ -444,6 +444,140 @@ class PagureFlaskPrioritiestests(tests.Modeltests): repo = pagure.lib._get_project(self.session, 'test') self.assertEqual(repo.priorities, {}) + @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) + @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) + def test_default_priority(self): + """ Test updating the default priority of a repo. """ + tests.create_projects(self.session) + tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True) + + # Check the default priorities + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.priorities, {}) + self.assertEqual(repo.default_priority, None) + + user = tests.FakeUser() + user.username = 'pingou' + with tests.user_set(pagure.APP, user): + + csrf_token = self.get_csrf() + + # Set some priorities + data = { + 'priority_weigth': [1, 2, 3], + 'priority_title': ['High', 'Normal', 'Low'], + 'csrf_token': csrf_token, + } + output = self.app.post( + '/test/update/priorities', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the ordering + self.assertTrue( + output.data.find('High') < output.data.find('Normal')) + self.assertTrue( + output.data.find('Normal') < output.data.find('Low')) + # Check the result of the action -- Priority recorded + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual( + repo.priorities, + {u'': u'', u'1': u'High', u'2': u'Normal', u'3': u'Low'} + ) + + # Try setting the default priority -- no csrf + data = {'priority': 'High'} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, None) + + # Try setting the default priority + data = {'priority': 'High', 'csrf_token': csrf_token} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + self.assertIn( + '\n Default priority set ' + 'to High', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, 'High') + + # Try setting a wrong default priority + data = {'priority': 'Smooth', 'csrf_token': csrf_token} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, 'High') + + # reset the default priority + data = {'csrf_token': csrf_token, 'priority': ''} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + self.assertIn( + '\n Default priority reset', + output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, None) + + # Check the behavior if the project disabled the issue tracker + settings = repo.settings + settings['issue_tracker'] = False + repo.settings = settings + self.session.add(repo) + self.session.commit() + + output = self.app.post( + '/test/update/default_priority', data=data) + self.assertEqual(output.status_code, 404) + + # Check for an invalid project + output = self.app.post( + '/foo/update/default_priority', data=data) + self.assertEqual(output.status_code, 404) + + # Check for a non-admin user + settings = repo.settings + settings['issue_tracker'] = True + repo.settings = settings + self.session.add(repo) + self.session.commit() + + user.username = 'ralph' + with tests.user_set(pagure.APP, user): + output = self.app.post( + '/test/update/default_priority', data=data) + self.assertEqual(output.status_code, 403) + if __name__ == '__main__': unittest.main(verbosity=2)