diff --git a/djangoproject/core/models.py b/djangoproject/core/models.py
index 5bd51165..11656824 100644
--- a/djangoproject/core/models.py
+++ b/djangoproject/core/models.py
@@ -303,6 +303,7 @@ def to_json(self):
return json.dumps({
'id': self.id,
'name': self.name,
+ 'description': self.description,
'homeURL': self.homeURL,
'trackerURL': self.trackerURL,
'image3x1': self.image3x1.url if self.image3x1 else None,
diff --git a/djangoproject/core/services/bitcoin_frespo_services.py b/djangoproject/core/services/bitcoin_frespo_services.py
index ed4326e4..ad26f073 100644
--- a/djangoproject/core/services/bitcoin_frespo_services.py
+++ b/djangoproject/core/services/bitcoin_frespo_services.py
@@ -107,7 +107,7 @@ def _notify_payment_finished_if_applicable(payment_id):
break
if is_finished:
payment.offer.paid()
- watches = watch_services.find_issue_watches(payment.offer.issue)
+ watches = watch_services.find_issue_and_project_watches(payment.offer.issue)
mail_services.notify_payment_parties_and_watchers_paymentconfirmed(payment, watches)
ActionLog.log_pay(payment)
msg = 'payment_id=%s, value=%s, issue=%s' % (
diff --git a/djangoproject/core/services/issue_services.py b/djangoproject/core/services/issue_services.py
index 28f04454..67a5cf0c 100644
--- a/djangoproject/core/services/issue_services.py
+++ b/djangoproject/core/services/issue_services.py
@@ -82,7 +82,7 @@ def sponsor_existing_issue(issue_id, dict, user):
issue.is_public_suggestion = False
issue.save()
issue.update_redundant_fields()
- watches = watch_services.find_issue_watches(issue)
+ watches = watch_services.find_issue_and_project_watches(issue)
notifyWatchers_offeradded(offer, watches)
msg = "offer: " + str(offer.price) + "\n
" +\
"issue key: " + offer.issue.key + "\n
" +\
@@ -107,7 +107,7 @@ def change_existing_offer(offer_id, offerdict, user):
offer.issue.update_redundant_fields()
old_offer = offer.clone()
offer.changeOffer(offerdict)
- watches = watch_services.find_issue_watches(offer.issue)
+ watches = watch_services.find_issue_and_project_watches(offer.issue)
notifyWatchers_offerchanged(old_offer, offer, watches)
return offer
@@ -126,7 +126,7 @@ def add_solution_to_existing_issue(issue_id, comment_content, accepting_payments
if(comment_content):
comment = IssueComment.newComment(issue, user, comment_content)
comment.save()
- watches = watch_services.find_issue_watches(solution.issue)
+ watches = watch_services.find_issue_and_project_watches(solution.issue)
notifyWatchers_workbegun(solution, comment, watches)
if(accepting_payments):
notifyWatchers_acceptingpayments(solution, watches)
@@ -143,7 +143,7 @@ def abort_existing_solution(solution_id, comment_content, user):
if(comment_content):
comment = IssueComment.newComment(solution.issue, user, comment_content)
comment.save()
- watches = watch_services.find_issue_watches(solution.issue)
+ watches = watch_services.find_issue_and_project_watches(solution.issue)
notifyWatchers_workstopped(solution, comment, watches)
return solution, comment
@@ -159,7 +159,7 @@ def revoke_existing_offer(offer_id, comment_content, user):
if(comment_content):
comment = IssueComment.newComment(offer.issue, user, comment_content)
comment.save()
- watches = watch_services.find_issue_watches(offer.issue)
+ watches = watch_services.find_issue_and_project_watches(offer.issue)
notifyWatchers_offerrevoked(offer, comment, watches)
return offer, comment
@@ -174,7 +174,7 @@ def resolve_existing_solution(solution_id, comment_content, user):
if(comment_content):
comment = IssueComment.newComment(solution.issue, user, comment_content)
comment.save()
- watches = watch_services.find_issue_watches(solution.issue)
+ watches = watch_services.find_issue_and_project_watches(solution.issue)
notifyWatchers_workdone(solution, comment, watches)
return solution, comment
diff --git a/djangoproject/core/services/mail_services.py b/djangoproject/core/services/mail_services.py
index baaea918..4c28fc36 100644
--- a/djangoproject/core/services/mail_services.py
+++ b/djangoproject/core/services/mail_services.py
@@ -1,3 +1,4 @@
+import json
import logging
from django.core.mail import EmailMultiAlternatives
@@ -66,6 +67,26 @@ def send_func(watch):
_notify_watchers(send_func, watches)
+def notifyWatchers_project_edited(user, project, old_json, watches):
+ old_dic = json.loads(old_json)
+ changed_description = old_dic['description'] != project.description
+ changed_image = old_dic['image3x1'] != project.image3x1.url
+ def send_func(watch):
+ if watch.user.id != user.id:
+ _send_mail_to_user(user=watch.user,
+ subject=user.getUserInfo().screenName + " edited project [%s]" % project.name,
+ templateName='email/project_edited.html',
+ contextData={"project": project,
+ "user": user,
+ "you": watch.user,
+ "SITE_HOME": settings.SITE_HOME,
+ "changed_description": changed_description,
+ "changed_image": changed_image,
+ "old_dic": old_dic},
+ whentrue='receiveEmail_issue_work')
+ _notify_watchers(send_func, watches)
+
+
def notifyWatchers_acceptingpayments(solution, watches):
def send_func(watch):
if(watch.user.id != solution.programmer.id):
diff --git a/djangoproject/core/services/paypal_services.py b/djangoproject/core/services/paypal_services.py
index 69489e2d..a05283ad 100644
--- a/djangoproject/core/services/paypal_services.py
+++ b/djangoproject/core/services/paypal_services.py
@@ -34,7 +34,7 @@ def process_ipn_return(paykey, status, tracking_id):
payment.confirm_ipn()
payment.offer.paid()
payment.offer.issue.touch()
- watches = watch_services.find_issue_watches(payment.offer.issue)
+ watches = watch_services.find_issue_and_project_watches(payment.offer.issue)
notify_payment_parties_and_watchers_paymentconfirmed(payment, watches)
notify_admin_payment_confirmed(payment)
ActionLog.log_pay(payment)
diff --git a/djangoproject/core/services/watch_services.py b/djangoproject/core/services/watch_services.py
index 87f834bf..b20b9167 100644
--- a/djangoproject/core/services/watch_services.py
+++ b/djangoproject/core/services/watch_services.py
@@ -8,6 +8,20 @@ def find_issue_watches(issue):
return Watch.objects.filter(entity='ISSUE', objid=issue.id)
+def find_project_watches(project):
+ return Watch.objects.filter(entity='PROJECT', objid=project.id)
+
+
+def find_issue_and_project_watches(issue):
+ iwatches = Watch.objects.filter(entity='ISSUE', objid=issue.id)
+ watches = []
+ watches.extend(iwatches)
+ user_ids = set([w.user.id for w in watches])
+ pwatches = Watch.objects.filter(entity='PROJECT', objid=issue.project.id)
+ watches.extend([w for w in pwatches if not w.user.id in user_ids])
+ return watches
+
+
def watch_issue(user, issue_id, reason):
watch = _findWatchOrNone(user, 'ISSUE', issue_id)
if not watch:
diff --git a/djangoproject/core/views/project_views.py b/djangoproject/core/views/project_views.py
index 6d2c8b2a..1a5bc9ee 100644
--- a/djangoproject/core/views/project_views.py
+++ b/djangoproject/core/views/project_views.py
@@ -2,7 +2,7 @@
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from core.models import Project, ActionLog
-from core.services import stats_services, issue_services, watch_services
+from core.services import stats_services, issue_services, watch_services, mail_services
from core.views import template_folder
from django.contrib.auth.decorators import login_required
@@ -49,6 +49,8 @@ def edit(request):
project.image3x1 = request.FILES['image3x1']
project.description = request.POST.get('description')
project.save()
+ watches = watch_services.find_project_watches(project)
+ mail_services.notifyWatchers_project_edited(request.user, project, old_json, watches)
ActionLog.log_edit_project(project=project, user=request.user, old_json=old_json)
return redirect('core.views.project_views.view', project_id=project.id)
diff --git a/djangoproject/templates/email/project_edited.html b/djangoproject/templates/email/project_edited.html
new file mode 100644
index 00000000..c9261492
--- /dev/null
+++ b/djangoproject/templates/email/project_edited.html
@@ -0,0 +1,27 @@
+{% extends "email/base.html" %}
+{% block mainContent%}
+Hello {{ you.getUserInfo.screenName }}
+
+ {{ user.getUserInfo.screenName }}
+
+has edited the
+{{ project.name }}
+project. Details below
+
+Old project settings
+