From c217c5d25277b9b564a33c5c4876ebe4cbbfd777 Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Jan 02 2016 18:39:33 +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/lib/__init__.py b/pagure/lib/__init__.py index a1e5a06..ae1c365 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -703,6 +703,41 @@ def edit_issue_tags(session, project, old_tag, new_tag, ticketfolder, user): return msgs +def get_project_user(session, project_id, user_id): + query = session.query( + model.ProjectUser + ) + query = query.filter( + model.ProjectUser.project_id == project_id + ).filter( + model.ProjectUser.user_id == user_id + ) + + return query.first() + +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 'Wrong username/Not logged in.' + + project_user_obj = get_project_user(session, project.id, user_obj.id) + + if not project_user_obj: + project_user = model.ProjectUser( + project_id=project.id, + user_id=user_obj.id, + watch=watch + ) + else: + project_user_obj.watch = watch + project_user = project_user_obj + + 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. ''' @@ -1454,6 +1489,18 @@ def get_project(session, name, user=None): return query.first() +def get_project_by_id(session, project_id): + '''Get a project from the database + ''' + query = session.query( + model.Project + ).filter( + model.Project.id == project_id + ) + + return query.first() + + def search_issues( session, repo, issueid=None, issueuid=None, status=None, closed=False, tags=None, assignee=None, author=None, private=None, @@ -2606,3 +2653,34 @@ def get_pull_request_of_user(session, username): ) return query.all() + + +def check_watching(session, username, repo_id): + '''Checks the logged in user watching the project + ''' + user = search_user(session, username=username) + + if not user: + return False + + user_project = get_project_user(session, repo_id, user.id) + + if not user_project: + return False + + return user_project.watch + + +def get_users_not_watching(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..43fa7f9 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -444,6 +444,9 @@ class ProjectUser(BASE): sa.ForeignKey('users.id', onupdate='CASCADE'), nullable=False, index=True) + watch = sa.Column( + sa.Boolean, + nullable=False) class Issue(BASE): diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index 9fd2a93..e8bdd54 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_not_watching(emails, project_id): + if project_id: + from pagure import SESSION + users = pagure.lib.get_users_not_watching(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_not_watching( + emails, issue.project.id) + return emails diff --git a/pagure/static/pagure.css b/pagure/static/pagure.css index 3001f24..50f07f4 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; @@ -847,7 +867,8 @@ header.repo.forked > p { } .addrem_bar > span { - display: block; + dis + play: block; background-color: #dbffdb; } @@ -856,6 +877,7 @@ header.repo.forked > p { } .issues_pbar > span { + background-color: #8bf08b; } @@ -1014,3 +1036,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..01a5468 100644 --- a/pagure/templates/repo_master.html +++ b/pagure/templates/repo_master.html @@ -90,6 +90,23 @@