You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by jo...@apache.org on 2013/06/17 19:38:47 UTC
[4/7] git commit: [#6203] ticket:362 Change bulk edit to a background
task
[#6203] ticket:362 Change bulk edit to a background task
Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/5cb57f2d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/5cb57f2d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/5cb57f2d
Branch: refs/heads/master
Commit: 5cb57f2dbd5d2fc6425f9dd1b1596355cbfc3a1a
Parents: 017f4aa
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Jun 5 09:13:08 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Mon Jun 17 17:19:06 2013 +0000
----------------------------------------------------------------------
ForgeTracker/forgetracker/model/ticket.py | 122 +++++++++++++++++++++++++
ForgeTracker/forgetracker/tasks.py | 7 +-
ForgeTracker/forgetracker/tracker_main.py | 120 +-----------------------
3 files changed, 130 insertions(+), 119 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5cb57f2d/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index ed28a09..6d89ca5 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -26,12 +26,14 @@ import pymongo
from pymongo.errors import OperationFailure
from pylons import tmpl_context as c, app_globals as g
from pprint import pformat
+from paste.deploy.converters import aslist
from ming import schema
from ming.utils import LazyProperty
from ming.orm import Mapper, session
from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
from ming.orm.declarative import MappedClass
+from ming.orm.ormsession import ThreadLocalORMSession
from allura.model import (Artifact, VersionedArtifact, Snapshot,
project_orm_session, BaseAttachment, VotableArtifact, AppConfig, Mailbox, User)
@@ -290,6 +292,126 @@ class Globals(MappedClass):
text = 'Tickets moved from %s to %s' % (moved_from, moved_to)
Notification.post_user(c.user, None, 'flash', text=text)
+ def update_tickets(self, **post_data):
+ from forgetracker.tracker_main import get_change_text, get_label
+ tickets = Ticket.query.find(dict(
+ _id={'$in':[ObjectId(id) for id in aslist(post_data['__ticket_ids'])]},
+ app_config_id=c.app.config._id)).all()
+
+ fields = set(['status'])
+ values = {}
+ for k in fields:
+ v = post_data.get(k)
+ if v: values[k] = v
+ assigned_to = post_data.get('assigned_to')
+ if assigned_to == '-':
+ values['assigned_to_id'] = None
+ elif assigned_to:
+ user = c.project.user_in_project(assigned_to)
+ if user:
+ values['assigned_to_id'] = user._id
+
+ custom_values = {}
+ custom_fields = {}
+ for cf in c.app.globals.custom_fields or []:
+ v = post_data.get(cf.name)
+ if v:
+ custom_values[cf.name] = v
+ custom_fields[cf.name] = cf
+
+ changes = {}
+ changed_tickets = {}
+ for ticket in tickets:
+ message = ''
+ for k, v in sorted(values.iteritems()):
+ if k == 'assigned_to_id':
+ new_user = User.query.get(_id=v)
+ old_user = User.query.get(_id=getattr(ticket, k))
+ if new_user:
+ message += get_change_text(
+ get_label(k),
+ new_user.display_name,
+ old_user.display_name)
+ else:
+ message += get_change_text(
+ get_label(k),
+ v,
+ getattr(ticket, k))
+ setattr(ticket, k, v)
+ for k, v in sorted(custom_values.iteritems()):
+ def cf_val(cf):
+ return ticket.get_custom_user(cf.name) \
+ if cf.type == 'user' \
+ else ticket.custom_fields.get(cf.name)
+ cf = custom_fields[k]
+ old_value = cf_val(cf)
+ ticket.custom_fields[k] = v
+ new_value = cf_val(cf)
+ message += get_change_text(
+ cf.label,
+ new_value,
+ old_value)
+ if message != '':
+ changes[ticket._id] = message
+ changed_tickets[ticket._id] = ticket
+ ticket.discussion_thread.post(message, notify=False)
+ ticket.commit()
+
+ filtered_changes = self.filtered_by_subscription(changed_tickets)
+ users = User.query.find({'_id': {'$in': filtered_changes.keys()}}).all()
+ def changes_iter(user):
+ for t_id in filtered_changes.get(user._id, []):
+ yield (changed_tickets[t_id], changes[t_id])
+ mail = dict(
+ fromaddr = str(c.user._id),
+ reply_to = str(c.user._id),
+ subject = '[%s:%s] Mass edit changes by %s' % (c.project.shortname,
+ c.app.config.options.mount_point,
+ c.user.display_name),
+ )
+ tmpl = g.jinja2_env.get_template('forgetracker:data/mass_report')
+ head = []
+ for f, v in sorted(values.iteritems()):
+ if f == 'assigned_to_id':
+ user = User.query.get(_id=v)
+ v = user.display_name if user else v
+ head.append('- **%s**: %s' % (get_label(f), v))
+ for f, v in sorted(custom_values.iteritems()):
+ cf = custom_fields[f]
+ if cf.type == 'user':
+ user = User.by_username(v)
+ v = user.display_name if user else v
+ head.append('- **%s**: %s' % (cf.label, v))
+ tmpl_context = {'context': c, 'data': {'header': '\n'.join(['Mass edit changing:', ''] + head)}}
+ for user in users:
+ tmpl_context['data'].update({'changes': changes_iter(user)})
+ mail.update(dict(
+ message_id = h.gen_message_id(),
+ text = tmpl.render(tmpl_context),
+ destinations = [str(user._id)]))
+ mail_tasks.sendmail.post(**mail)
+
+ if c.app.config.options.get('TicketMonitoringType') in (
+ 'AllTicketChanges', 'AllPublicTicketChanges'):
+ monitoring_email = c.app.config.options.get('TicketMonitoringEmail')
+ visible_changes = []
+ for t_id, t in changed_tickets.items():
+ if (not t.private or
+ c.app.config.options.get('TicketMonitoringType') ==
+ 'AllTicketChanges'):
+ visible_changes.append(
+ (changed_tickets[t_id], changes[t_id]))
+ if visible_changes:
+ tmpl_context['data'].update({'changes': visible_changes})
+ mail.update(dict(
+ message_id = h.gen_message_id(),
+ text = tmpl.render(tmpl_context),
+ destinations = [monitoring_email]))
+ mail_tasks.sendmail.post(**mail)
+
+ c.app.globals.invalidate_bin_counts()
+ ThreadLocalORMSession.flush_all()
+
def filtered_by_subscription(self, tickets, project_id=None, app_config_id=None):
p_id = project_id if project_id else c.project._id
ac_id = app_config_id if app_config_id else c.app.config._id
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5cb57f2d/ForgeTracker/forgetracker/tasks.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tasks.py b/ForgeTracker/forgetracker/tasks.py
index 6cbd42d..6492d7d 100644
--- a/ForgeTracker/forgetracker/tasks.py
+++ b/ForgeTracker/forgetracker/tasks.py
@@ -18,9 +18,9 @@
import logging
from pylons import tmpl_context as c
+
from allura.lib.decorators import task
from allura.lib import helpers as h
-
from allura import model as M
log = logging.getLogger(__name__)
@@ -37,3 +37,8 @@ def update_bin_counts(app_config_id):
@task
def move_tickets(ticket_ids, destination_tracker_id):
c.app.globals.move_tickets(ticket_ids, destination_tracker_id)
+
+
+@task
+def bulk_edit(**post_data):
+ c.app.globals.update_tickets(**post_data)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5cb57f2d/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index aabf321..ac56a30 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -845,125 +845,9 @@ class RootController(BaseController, FeedController):
app_config_id=c.app.config._id)).all()
for ticket in tickets:
require_access(ticket, 'update')
-
- fields = set(['status'])
- values = {}
- for k in fields:
- v = post_data.get(k)
- if v: values[k] = v
- assigned_to = post_data.get('assigned_to')
- if assigned_to == '-':
- values['assigned_to_id'] = None
- elif assigned_to:
- user = c.project.user_in_project(assigned_to)
- if user:
- values['assigned_to_id'] = user._id
-
- custom_values = {}
- custom_fields = {}
- for cf in c.app.globals.custom_fields or []:
- v = post_data.get(cf.name)
- if v:
- custom_values[cf.name] = v
- custom_fields[cf.name] = cf
-
- changes = {}
- changed_tickets = {}
- for ticket in tickets:
- message = ''
- for k, v in sorted(values.iteritems()):
- if k == 'assigned_to_id':
- new_user = M.User.query.get(_id=v)
- old_user = M.User.query.get(_id=getattr(ticket, k))
- if new_user:
- message += get_change_text(
- get_label(k),
- new_user.display_name,
- old_user.display_name)
- else:
- message += get_change_text(
- get_label(k),
- v,
- getattr(ticket, k))
- setattr(ticket, k, v)
- for k, v in sorted(custom_values.iteritems()):
- def cf_val(cf):
- return ticket.get_custom_user(cf.name) \
- if cf.type == 'user' \
- else ticket.custom_fields.get(cf.name)
- cf = custom_fields[k]
- old_value = cf_val(cf)
- ticket.custom_fields[k] = v
- new_value = cf_val(cf)
- message += get_change_text(
- cf.label,
- new_value,
- old_value)
- if message != '':
- changes[ticket._id] = message
- changed_tickets[ticket._id] = ticket
- ticket.discussion_thread.post(message, notify=False)
- ticket.commit()
-
- filtered_changes = c.app.globals.filtered_by_subscription(changed_tickets)
- users = M.User.query.find({'_id': {'$in': filtered_changes.keys()}}).all()
- def changes_iter(user):
- for t_id in filtered_changes.get(user._id, []):
- yield (changed_tickets[t_id], changes[t_id])
- mail = dict(
- fromaddr = str(c.user._id),
- reply_to = str(c.user._id),
- subject = '[%s:%s] Mass edit changes by %s' % (c.project.shortname,
- c.app.config.options.mount_point,
- c.user.display_name),
- )
- tmpl = jinja2.Environment(
- loader=jinja2.PackageLoader('forgetracker', 'data'),
- auto_reload=asbool(config.get('auto_reload_templates', True)),
- ).get_template('mass_report')
- head = []
- for f, v in sorted(values.iteritems()):
- if f == 'assigned_to_id':
- user = M.User.query.get(_id=v)
- v = user.display_name if user else v
- head.append('- **%s**: %s' % (get_label(f), v))
- for f, v in sorted(custom_values.iteritems()):
- cf = custom_fields[f]
- if cf.type == 'user':
- user = M.User.by_username(v)
- v = user.display_name if user else v
- head.append('- **%s**: %s' % (cf.label, v))
- tmpl_context = {'context': c, 'data': {'header': '\n'.join(['Mass edit changing:', ''] + head)}}
- for user in users:
- tmpl_context['data'].update({'changes': changes_iter(user)})
- mail.update(dict(
- message_id = h.gen_message_id(),
- text = tmpl.render(tmpl_context),
- destinations = [str(user._id)]))
- mail_tasks.sendmail.post(**mail)
-
- if c.app.config.options.get('TicketMonitoringType') in (
- 'AllTicketChanges', 'AllPublicTicketChanges'):
- monitoring_email = c.app.config.options.get('TicketMonitoringEmail')
- visible_changes = []
- for t_id, t in changed_tickets.items():
- if (not t.private or
- c.app.config.options.get('TicketMonitoringType') ==
- 'AllTicketChanges'):
- visible_changes.append(
- (changed_tickets[t_id], changes[t_id]))
- if visible_changes:
- tmpl_context['data'].update({'changes': visible_changes})
- mail.update(dict(
- message_id = h.gen_message_id(),
- text = tmpl.render(tmpl_context),
- destinations = [monitoring_email]))
- mail_tasks.sendmail.post(**mail)
-
- c.app.globals.invalidate_bin_counts()
- ThreadLocalORMSession.flush_all()
+ tasks.bulk_edit.post(**post_data)
count = len(tickets)
- flash('Updated {} ticket{}'.format(count, 's' if count != 1 else ''), 'ok')
+ flash('Update scheduled ({} ticket{})'.format(count, 's' if count != 1 else ''), 'ok')
redirect('edit/' + post_data['__search'])
def tickets_since(self, when=None):