You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bloodhound.apache.org by gj...@apache.org on 2012/04/01 11:27:37 UTC

svn commit: r1308057 - in /incubator/bloodhound/trunk/bloodhound_theme/bhtheme: htdocs/scripts/theme.js templates/bloodhound_theme.html theme.py

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
+
 



Re: svn commit: r1308057 - in /incubator/bloodhound/trunk/bloodhound_theme/bhtheme: htdocs/scripts/theme.js templates/bloodhound_theme.html theme.py

Posted by Gary <ga...@wandisco.com>.
Hi,

Sorry about that, clearly I wasn't thinking straight. I must remember to 
take more care over decisions I make when I am that tired. In retrospect 
I should at least have discussed the idea of putting all the code in so 
quickly and it was also very silly not to make time to talk about it 
after the event. Clearly it would also be a lot more helpful to everyone 
if code is committed as it was created instead of waiting so long.

The two code drops are in the form of two plugins that are effectively 
separate from the work existing in the repositories before this point 
and so the changes are isolated to two new directories: 
trunk/bloodhound_dashboard and trunk/bloodhound_theme. They are not 
complete interpretations of the designs that have been discussed with 
Joe in the mailing list and published in the wiki, but they do go a long 
way to providing a substantial base for that work.

All this means that there is no strict dependency on this new code at 
this point and so I was going to discuss this morning whether we should 
change the installer to also install these plugins.

At this point, there is still a change required that will allow us to 
use the ThemeEngine plugin that the theme work relies on. That could be 
done as a modification to our working branch of the core trac code found 
in trunk/trac, stopping a infinite recursion created by certain plugins. 
It didn't occur to me to include this in the code drop as it represents 
a change to existing code.

Cheers,
     Gary


On 04/01/2012 11:13 AM, Greg Stein wrote:
> Okay. This seems to be the last of committed revisions under the
> "Theme code import". And now that I look, there is also a "Dashboard
> code import" set of revisions.
>
> This is wrong.
>
> Where are these revisions coming from? Why were these revisions not
> developed as part of the community *here* ?
>
> Why are we just seeing these revisions now? Where is any commentary
> about this *DROP* of a multitude of revisions?
>
> There is a big drop of revision around "theme" and "dashboard". But I
> see no discussion about this change on the dev@ list.
>
> ....
>
> The issue here is not "oh, slow down awesome contributions", but more:
> what is going on? this is a big change; has it been discussed?; are
> other people on board?
>
> The secondary issue is: where were these imported from? It said
> "(Theme|Dashboard) code import". This project should be developed
> *here*. Discussion and design should occur *here*. Individual
> revisions to the project should occur *here*. Batches of changes
> occurring elsewhere and then "imported" here is not the way this
> community can prosper.
>
> Changes need to be managed individually, in order for the community to
> evaluate them. Batches are ungood.
>
> -g
>
> On Apr 1, 2012 5:28 AM,<gj...@apache.org>  wrote:
>> 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
>> +
>>
>>
>>


Re: svn commit: r1308057 - in /incubator/bloodhound/trunk/bloodhound_theme/bhtheme: htdocs/scripts/theme.js templates/bloodhound_theme.html theme.py

Posted by Greg Stein <gs...@gmail.com>.
Okay. This seems to be the last of committed revisions under the
"Theme code import". And now that I look, there is also a "Dashboard
code import" set of revisions.

This is wrong.

Where are these revisions coming from? Why were these revisions not
developed as part of the community *here* ?

Why are we just seeing these revisions now? Where is any commentary
about this *DROP* of a multitude of revisions?

There is a big drop of revision around "theme" and "dashboard". But I
see no discussion about this change on the dev@ list.

....

The issue here is not "oh, slow down awesome contributions", but more:
what is going on? this is a big change; has it been discussed?; are
other people on board?

The secondary issue is: where were these imported from? It said
"(Theme|Dashboard) code import". This project should be developed
*here*. Discussion and design should occur *here*. Individual
revisions to the project should occur *here*. Batches of changes
occurring elsewhere and then "imported" here is not the way this
community can prosper.

Changes need to be managed individually, in order for the community to
evaluate them. Batches are ungood.

-g

On Apr 1, 2012 5:28 AM, <gj...@apache.org> wrote:
>
> 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
> +
>
>
>