Author: gjm
Date: Sun Apr 1 09:27:37 2012
New Revision: 1308057
URL: http://svn.apache.org/viewvc?rev=1308057&view=rev
Log:
Theme code import: Tickets created via ajax requests
Modified:
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/scripts/theme.js
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/theme.py
Modified:
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/scripts/theme.js
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/scripts/theme.js?rev=1308057&r1=1308056&r2=1308057&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/scripts/theme.js
(original)
+++ incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/scripts/theme.js
Sun Apr 1 09:27:37 2012
@@ -4,11 +4,43 @@ $( function () {
// Do not close dropdown menu if user clicks on form controls
$('.dropdown-menu input, .dropdown-menu label, .dropdown-menu select')
.click(function (e) { e.stopPropagation(); });
-
+
+ /* Helper functions */
+
+ // Display message triggered by quick create box
+ function qct_alert(msg) {
+ alert(msg);
+ }
+
+ // Clear input controls inside quick create box
+ function qct_clearui() {
+ $('#qct-fieldset input, #qct-fieldset select').val('');
+ }
+
// Install quick create box click handlers
$('#qct-cancel').click(
+ function () {
+ qct_clearui();
+ }
+ );
+ $('#qct-create').click(
function() {
- $('#qct-box input').val('');
+ var qct_url = $('#qct-create').attr('data-target');
+ $.post(qct_url, $('#qct-form').serialize(),
+ function(ticket_id) {
+ qct_alert('Created ticket ' + ticket_id);
+ })
+ .error(function(jqXHR, textStatus, errorMsg) {
+ var msg = 'Error:' + errorMsg;
+ if (textStatus === 'timeout')
+ msg = 'Request timed out';
+ else if (textStatus === 'error')
+ msg = 'Could not create ticket . Error : ' + errorMsg;
+ else if (textStatus === 'abort')
+ msg = 'Aborted request'
+ qct_alert(msg);
+ });
+ qct_clearui();
}
)
})
Modified:
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bloodhound_theme.html?rev=1308057&r1=1308056&r2=1308057&view=diff
==============================================================================
---
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
(original)
+++
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
Sun Apr 1 09:27:37 2012
@@ -90,28 +90,28 @@
</select>
</py:def>
<py:def function="qct_box()">
-<label for="qct_summary">Summary</label>
-<input class="input-medium" type="text" id="qct_summary"
- placeholder="Ticket summary" />
-<label for="qct_project">Project</label>
-<input class="input-medium disabled" type="text"
+<label for="field-summary">Summary</label>
+<input class="input-medium" type="text" id="field-summary"
+ name="field_summary" placeholder="Ticket summary" />
+<label for="field-project">Project</label>
+<input class="input-medium disabled" id="field-project" type="text"
placeholder="Target project" disabled="" />
<div class="form-horizontal">
-<label class="control-label" for="qct_version">Version</label>
+<label class="control-label" for="field-version">Version</label>
<div class="controls">
<!-- input name="qct_version" class="input-mini" type="text"
placeholder="Version" / -->
${field_select(qct.fields.version, None)}
<p class="help-block">Most recent by default</p>
</div>
-<label class="control-label" for="qct_type">Type</label>
+<label class="control-label" for="field-type">Type</label>
<div class="controls">
<!-- input name="qct_type" class="input-mini" type="text"
placeholder="Type" / -->
${field_select(qct.fields.type, None)}
<p class="help-block">Select ticket type</p>
</div>
-<label class="control-label" for="qct_component">Component</label>
+<label class="control-label" for="field-component">Component</label>
<div class="controls">
<!-- input name="qct_component" class="input-mini" type="text"
placeholder="Component" / -->
@@ -119,18 +119,6 @@
<p class="help-block">Select component</p>
</div>
</div>
-<div class="btn-toolbar">
-<div class="btn-group">
-<button id="qct-create" class="btn btn-primary">
- Create
-</button>
-</div>
-<div class="btn-group">
-<button id="qct-cancel" class="btn btn-danger">
- Cancel
-</button>
-</div>
-</div>
</py:def>
<py:choose test="">
<py:when test="qct">
@@ -154,7 +142,24 @@
</style>
<div class="popover-title"><h3>Create Ticket</h3></div>
<div class="popover-content">
- ${qct_box()}
+<form id="qct-form" name="qct" method="post">
+<div id="qct-fieldset">
+ ${qct_box()}
+</div>
+</form>
+<div class="btn-toolbar">
+<div class="btn-group">
+<button id="qct-create" class="btn btn-primary"
+ data-target="${href.qct()}">
+ Create
+</button>
+</div>
+<div class="btn-group">
+<button id="qct-cancel" class="btn btn-danger">
+ Cancel
+</button>
+</div>
+</div>
</div>
</div>
</div>
Modified: incubator/bloodhound/trunk/bloodhound_theme/bhtheme/theme.py
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_theme/bhtheme/theme.py?rev=1308057&r1=1308056&r2=1308057&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_theme/bhtheme/theme.py (original)
+++ incubator/bloodhound/trunk/bloodhound_theme/bhtheme/theme.py Sun Apr 1
09:27:37 2012
@@ -21,9 +21,10 @@ from genshi.core import Markup, Stream,
from genshi.filters import Transformer
from genshi.input import HTML
from trac.core import *
+from trac.ticket.api import TicketSystem
from trac.ticket.model import Ticket
from trac.ticket.web_ui import TicketModule
-from trac.web.api import Request, IRequestFilter, ITemplateStreamFilter
+from trac.web.api import Request, IRequestFilter, IRequestHandler
from trac.web.chrome import Chrome
from trac.web.main import RequestDispatcher
@@ -72,7 +73,7 @@ class BloodhoundTheme(ThemeBase):
return True
class QuickCreateTicketDialog(Component):
- implements(IRequestFilter)
+ implements(IRequestFilter, IRequestHandler)
# IRequestFilter(Interface):
@@ -96,4 +97,59 @@ class QuickCreateTicketDialog(Component)
data['qct'] = { 'fields' : fields }
return template, data, content_type
+ # IRequestHandler methods
+
+ def match_request(self, req):
+ """Handle requests sent to /qct
+ """
+ return req.path_info == '/qct'
+
+ def process_request(self, req):
+ """Forward new ticket request to `trac.ticket.web_ui.TicketModule`
+ but return plain text suitable for AJAX requests.
+ """
+ try:
+ tm = self.env[TicketModule]
+ if tm is None:
+ raise TracError('Unable to load TicketModule (disabled)?')
+ req.perm.require('TICKET_CREATE')
+ summary = req.args.pop('field_summary', '')
+ desc = ",, ... via ''Bloodhound'' quick create ticket dialog,,"
+ attrs = dict([k[6:], v] for k,v in req.args.iteritems() \
+ if k.startswith('field_'))
+ ticket_id = self.create(req, summary, desc, attrs, False)
+ except Exception, exc:
+ self.log.exception("BH: Quick create ticket failed %s" % (exc,))
+ req.send(str(exc), 'plain/text', 500)
+ else:
+ req.send(str(ticket_id), 'plain/text')
+
+ # Public API
+ def create(self, req, summary, description, attributes = {}, notify=False):
+ """ Create a new ticket, returning the ticket ID.
+
+ PS: Borrowed from XmlRpcPlugin.
+ """
+ t = Ticket(self.env)
+ t['summary'] = summary
+ t['description'] = description
+ t['reporter'] = req.authname
+ for k, v in attributes.iteritems():
+ t[k] = v
+ t['status'] = 'new'
+ t['resolution'] = ''
+ t.insert()
+ # Call ticket change listeners
+ ts = TicketSystem(self.env)
+ for listener in ts.change_listeners:
+ listener.ticket_created(t)
+ if notify:
+ try:
+ tn = TicketNotifyEmail(self.env)
+ tn.notify(t, newticket=True)
+ except Exception, e:
+ self.log.exception("Failure sending notification on creation "
+ "of ticket #%s: %s" % (t.id, e))
+ return t.id
+