From 3fcc812dd01d75136707ad9d42c894d6872f74bb Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Jan 04 2016 18:42:10 +0000 Subject: Added watch functionality. --- diff --git a/alembic/versions/2f6afca270a2_added_watch_column_to_user_projects.py b/alembic/versions/2f6afca270a2_added_watch_column_to_user_projects.py new file mode 100644 index 0000000..33b6b40 --- /dev/null +++ b/alembic/versions/2f6afca270a2_added_watch_column_to_user_projects.py @@ -0,0 +1,41 @@ +"""Added watch column to user_projects + +Revision ID: 2f6afca270a2 +Revises: 1cd0a853c697 +Create Date: 2015-12-15 20:50:24.651970 + +""" + +# revision identifiers, used by Alembic. +revision = '2f6afca270a2' +down_revision = '1cd0a853c697' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ''' Add the column watch to the table user_projects. + ''' + op.add_column( + 'user_projects', + sa.Column( + 'watch', + sa.Boolean, + nullable=True, + default=True + ) + ) + + op.execute('''UPDATE "user_projects" SET watch=1;''') + + op.alter_column( + 'user_projects', + column_name='watch', + nullable=False, + existing_nullable=True) + +def downgrade(): + ''' Remove the column watch from the table user_projects. + ''' + op.drop_column('user_projects', 'watch') diff --git a/pagure/__init__.py b/pagure/__init__.py index 5ac1710..98cee18 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -394,6 +394,21 @@ def get_remote_repo_path(remote_git, branch_from, loop=False): return repopath +def check_watching(repo): + '''Checks the logged in user watching the project + ''' + if not authenticated(): + return False + + watch = False + username = flask.g.fas_user.username + for user in repo.project_users: + if user.user.user == username: + watch = user.watch + break + + return watch + # Import the application import pagure.ui.app diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index a1e5a06..b49ce95 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -704,6 +704,33 @@ def edit_issue_tags(session, project, old_tag, new_tag, ticketfolder, user): return msgs +def update_watch_status(session, project, user, watch): + ''' Update the user status for watching a project. ''' + user_obj = __get_user(session, user) + + if not user_obj: + return pagure.exceptions.PagureException( + 'No user with username: %s' % user) + + project_user = None + for project_user in project.project_users: + if project_user.user.user == user: + break + + if not project_user: + project_user = model.ProjectUser( + project_id=project.id, + user_id=user_obj.id, + watch=watch + ) + else: + project_user.watch = watch + + session.add(project_user) + session.flush() + + return 'Status updated' + def add_user_to_project(session, project, new_user, user): ''' Add a specified user to a specified project. ''' new_user_obj = __get_user(session, new_user) @@ -2606,3 +2633,18 @@ def get_pull_request_of_user(session, username): ) return query.all() + + +def get_users_unwatched(session, project_id): + '''Get all the users not watching the project. + ''' + query = session.query( + model.ProjectUser + ) + query = query.filter( + model.ProjectUser.project_id == project_id + ).filter( + model.ProjectUser.watch == False + ) + + return query.all() \ No newline at end of file diff --git a/pagure/lib/model.py b/pagure/lib/model.py index f95c302..32599a9 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -300,6 +300,10 @@ class Project(BASE): backref='co_projects' ) + project_users = relation( + 'ProjectUser' + ) + groups = relation( "PagureGroup", secondary="projects_groups", @@ -402,7 +406,6 @@ class Project(BASE): Issue.private == False ).count() - def to_json(self, public=False, api=False): ''' Return a representation of the project as JSON. ''' @@ -444,6 +447,10 @@ class ProjectUser(BASE): sa.ForeignKey('users.id', onupdate='CASCADE'), nullable=False, index=True) + watch = sa.Column( + sa.Boolean, + nullable=False) + user = relation('User') class Issue(BASE): diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index 9fd2a93..658b764 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -74,6 +74,18 @@ def _clean_emails(emails, user): return emails +def _clean_emails_unwatched_users(emails, project_id): + if project_id: + from pagure import SESSION + users = pagure.lib.get_users_unwatched(SESSION, project_id) + + if users: + for user in users: + if user.default_email in emails: + emails.remove(user.default_email) + return emails + + def _get_emails_for_issue(issue): ''' Return the list of emails to send notification to when notifying about the specified issue. @@ -115,6 +127,11 @@ def _get_emails_for_issue(issue): 'FROM_EMAIL', 'pagure@fedoraproject.org')) ) + # Drop the user's email who are not watching. + if issue.project: + emails = _clean_emails_unwatched_users( + emails, issue.project.id) + return emails diff --git a/pagure/static/pagure.css b/pagure/static/pagure.css index 3001f24..ea566f5 100644 --- a/pagure/static/pagure.css +++ b/pagure/static/pagure.css @@ -87,6 +87,9 @@ table.list thead th a, [id=fork_button]:hover, [id=settings_button]:hover, [id=profile_button]:hover, +[id=watch_button]:hover, +#watch_button.clicked, +.watch-menu ul li:hover, .fgradient{ color: white; background: #426ead; /* Old browsers */ @@ -142,6 +145,7 @@ header p { margin:0; } + header h1 span { float: right; color: rgba(255, 255, 255, .5); @@ -759,13 +763,15 @@ header.repo.forked > p { display: inline-block; } -#request_pull,#fork_button, #settings_button, #profile_button { +#request_pull,#fork_button, #settings_button, #profile_button, #watch_button { border-radius: 10px; } #fork_button a, #settings_button a, -#profile_button a { +#profile_button a, +#watch_button a, +.watch-menu ul li a { background-position: 8px 50%; background-repeat: no-repeat; margin-top: .2em; @@ -782,6 +788,10 @@ header.repo.forked > p { background-image: url(images/fork_button.png); } +#watch_button a { + +} + #settings_button a { background-image: url(images/settings_button.png); } @@ -797,7 +807,10 @@ header.repo.forked > p { #request_pull a, #fork_button:hover a, #settings_button:hover a, -#profile_button:hover a { +#profile_button:hover a, +#watch_button:hover a, +#watch_button.clicked a, +.watch-menu ul li:hover a { color: white; } @@ -805,10 +818,16 @@ header.repo.forked > p { background-image: url(images/fork_button_hover.png); } + +#watch_button:hover a { + +} + #settings_button:hover a { background-image: url(images/settings_button_hover.png); } + #profile_button:hover a { background-image: url(images/profile_button_hover.png); } @@ -827,6 +846,7 @@ header.repo.forked > p { margin: .4em 0 0; } + .commit_message_body { display: block; font-weight: normal; @@ -856,6 +876,7 @@ header.repo.forked > p { } .issues_pbar > span { + background-color: #8bf08b; } @@ -1014,3 +1035,41 @@ span.CONFLICTS { font-family: monospace; font-size: 120%; } + +#watch_button:hover { + cursor: pointer; +} + +.watch-menu { + display: none; + position: absolute; +} + +.watch-menu ul li { + display: block; + padding: 10px; + background: #eeeeee; +} + +.watch-menu ul li a { + color: #4D4D4D !important; +} + +.watch-menu ul li:hover a { + color: #ffffff !important; + cursor: pointer; +} + +.watch-menu ul li a { + background: none; +} + +/* +.watch-menu ul li.selected span { + width: 15px; + height: 9px; + background: url("./images/ui-icons_454545_256x240.png"); + background-position: -66px -149px; + content: ''; + display: inline-block; +}*/ \ No newline at end of file diff --git a/pagure/templates/repo_master.html b/pagure/templates/repo_master.html index 861f9dd..8a4086b 100644 --- a/pagure/templates/repo_master.html +++ b/pagure/templates/repo_master.html @@ -90,6 +90,23 @@