Author: dammina
Date: Sun Aug 10 05:00:03 2014
New Revision: 1617047

URL: http://svn.apache.org/r1617047
Log:
Changed the feature to a wiki macro

Modified:
    
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/htdocs/js/batchcreate.js
    
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/theme.py

Modified: 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/htdocs/js/batchcreate.js
URL: 
http://svn.apache.org/viewvc/bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/htdocs/js/batchcreate.js?rev=1617047&r1=1617046&r2=1617047&view=diff
==============================================================================
--- 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/htdocs/js/batchcreate.js
 (original)
+++ 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/htdocs/js/batchcreate.js
 Sun Aug 10 05:00:03 2014
@@ -1,25 +1,21 @@
-function emptyTable(product,milestones,components,href,token) {
-
-       var numOfRows = document.getElementById("numOfRows").value;
-       var created_rows = document.getElementById("numOfRows").value;
+function emptyTable(numOfRows,product,milestones,components,href,token) {
+       created_rows=numOfRows;
        form_token = token.split(";")[0].split("=")[1];
        if(numOfRows == ""){
                alert("Enter the ticket batch size.")
        }
        else if(numOfRows != "" && document.getElementById("empty-table") == 
null){
-       var contentDiv = document.getElementById("content");
-       //var headers = 
{"summary":"Summary","description":"Description","product":"Product","status":"Status","priority":"Priority","type":"Types","owner":"Owner","cc":"Cc","milestone":"Milestone","keywords":"Keywords"}
+       var contentDiv = document.getElementById("div-empty-table");
     var headers = 
{"ticket":"","summary":"Summary","description":"Description","product":"Product","priority":"Priority","milestone":"Milestone","component":"Component"}
-       //statuses = ["new", "accepted", "assigned", "closed", "reopened"];
        priorities = ["blocker", "critical", "major", "minor", "trivial"];
        types = ["defect", "enhancement", "task"];
        
        var div = document.createElement("div");
        div.setAttribute("class","span12");
        div.setAttribute("id","empty-table");
-       var h2 = document.createElement("h2");
-       h2.appendChild(document.createTextNode("Batch Create Tickets"));
-       div.appendChild(h2);
+       var h5 = document.createElement("h5");
+       h5.appendChild(document.createTextNode("Batch Create Tickets"));
+       div.appendChild(h5);
        
        var form = document.createElement("form");
        form.setAttribute("id","bct-form");
@@ -85,21 +81,6 @@ function emptyTable(product,milestones,c
                                td_row.appendChild(input_description);
                                tr_rows.appendChild(td_row);
                        }
-                       /*else if (header == "status") {
-                               td_row = document.createElement("td");
-                               input_status = document.createElement("select");
-                               
input_status.setAttribute("id","field-status"+i);
-                               
input_status.setAttribute("class","input-block-level");
-                               
input_status.setAttribute("name","field_status"+i);
-                               for (status in statuses){
-                                       option = 
document.createElement("option");
-                                       
option.setAttribute("value",statuses[status]);
-                                       
option.appendChild(document.createTextNode(statuses[status]));
-                                       input_status.appendChild(option);
-                               }
-                               td_row.appendChild(input_status);
-                               tr_rows.appendChild(td_row);
-                       }*/
                        else if (header == "priority") {
                                td_row = document.createElement("td");
                                input_priority = 
document.createElement("select");
@@ -115,21 +96,6 @@ function emptyTable(product,milestones,c
                                td_row.appendChild(input_priority);
                                tr_rows.appendChild(td_row);
                        }
-                       /*else if (header == "type") {
-                               td_row = document.createElement("td");
-                               input_type = document.createElement("select");
-                               input_type.setAttribute("id","field-type"+i);
-                               
input_type.setAttribute("class","input-block-level");
-                               input_type.setAttribute("name","field_type"+i);
-                               for (type in types){
-                                       option = 
document.createElement("option");
-                                       
option.setAttribute("value",types[type]);
-                                       
option.appendChild(document.createTextNode(types[type]));
-                                       input_type.appendChild(option);
-                               }
-                               td_row.appendChild(input_type);
-                               tr_rows.appendChild(td_row);
-                       }*/
                        else if (header == "product") {
                                td_row = document.createElement("td");
                                field_product = 
document.createElement("select");
@@ -145,26 +111,6 @@ function emptyTable(product,milestones,c
                                td_row.appendChild(field_product);
                                tr_rows.appendChild(td_row);
                        }
-                       /*else if (header == "owner"){
-                               td_row = document.createElement("td");
-                               input_owner = document.createElement("input");
-                               input_owner.setAttribute("type","text");
-                               input_owner.setAttribute("id","field-owner"+i);
-                               
input_owner.setAttribute("class","input-block-level");
-                               
input_owner.setAttribute("name","field_owner"+i);
-                               td_row.appendChild(input_owner);
-                               tr_rows.appendChild(td_row);
-                       }*/
-                       /*else if (header == "cc"){
-                               td_row = document.createElement("td");
-                               input_cc = document.createElement("input");
-                               input_cc.setAttribute("type","text");
-                               input_cc.setAttribute("id","field-cc"+i);
-                               
input_cc.setAttribute("class","input-block-level");
-                               input_cc.setAttribute("name","field_cc"+i);
-                               td_row.appendChild(input_cc);
-                               tr_rows.appendChild(td_row);
-                       }*/
                        else if (header == "milestone"){
                                td_row = document.createElement("td");
                                field_milestone = 
document.createElement("select");
@@ -195,16 +141,6 @@ function emptyTable(product,milestones,c
                                td_row.appendChild(field_component);
                                tr_rows.appendChild(td_row);
                        }
-                       /*else if (header == "keywords"){
-                               td_row = document.createElement("td");
-                               input_keywords = 
document.createElement("input");
-                               input_keywords.setAttribute("type","text");
-                               
input_keywords.setAttribute("id","field-keywords"+i);
-                               
input_keywords.setAttribute("class","input-block-level");
-                               
input_keywords.setAttribute("name","field_keywords"+i);
-                               td_row.appendChild(input_keywords);
-                               tr_rows.appendChild(td_row);
-                       }*/
                }
                tbody.appendChild(tr_rows);
        }
@@ -283,11 +219,6 @@ function submitForm(){
        document.getElementById("bct-form").submit();
 }
 
-function removeBatchCreate(){
-       document.getElementById("bct-button").remove();
-       document.getElementById("numOfRows").remove();
-}
-
 function deleteForm(){
        document.getElementById("empty-table").remove();
 }
@@ -300,15 +231,14 @@ function submit_btn_action() {
         $.post(product_base_url , $('#bct-form').serialize(),
         function(ticket) {
                        deleteForm();
-                       removeBatchCreate();
 
                        var headers = 
{"ticket":"Ticket","summary":"Summary","product":"Product","status":"Status","milestone":"Milestone","component":"Component"}
-                       var contentDiv = document.getElementById("content");
+                       var contentDiv = 
document.getElementById("div-empty-table");
                        var div = document.createElement("div");
                        div.setAttribute("class","span12");
-                       var h2 = document.createElement("h2");
-                       h2.appendChild(document.createTextNode("Created 
Tickets"));
-                       div.appendChild(h2);
+                       var h5 = document.createElement("h5");
+                       h5.appendChild(document.createTextNode("Created 
Tickets"));
+                       div.appendChild(h5);
                        var table = document.createElement("table");
                        table.setAttribute("class","listing tickets table 
table-bordered table-condensed query");
                        table.setAttribute("style","border-radius: 0px 0px 4px 
4px");
@@ -415,21 +345,6 @@ function add_row_btn_action(product,mile
                        td_row.appendChild(input_description);
                        tr_rows.appendChild(td_row);
                }
-               /*else if (header == "status") {
-                       td_row = document.createElement("td");
-                       input_status = document.createElement("select");
-                       input_status.setAttribute("id","field-status"+i);
-                       input_status.setAttribute("class","input-block-level");
-                       input_status.setAttribute("name","field_status"+i);
-                       for (status in statuses){
-                               option = document.createElement("option");
-                               option.setAttribute("value",statuses[status]);
-                               
option.appendChild(document.createTextNode(statuses[status]));
-                               input_status.appendChild(option);
-                       }
-                       td_row.appendChild(input_status);
-                       tr_rows.appendChild(td_row);
-               }*/
                else if (header == "priority") {
                        td_row = document.createElement("td");
                        input_priority = document.createElement("select");
@@ -505,3 +420,74 @@ function remove_row_btn_action(numOfRows
        }
        return cnt;
 }
+
+function display_created_tickets(ticket) {
+       var headers = 
{"ticket":"Ticket","summary":"Summary","product":"Product","status":"Status","milestone":"Milestone","component":"Component"}
+       var contentDiv = document.getElementById("div-created-ticket-table");
+       var div = document.createElement("div");
+       div.setAttribute("class","span12");
+       var h5 = document.createElement("h5");
+       h5.appendChild(document.createTextNode("Created Tickets"));
+       div.appendChild(h5);
+       var table = document.createElement("table");
+       table.setAttribute("class","listing tickets table table-bordered 
table-condensed query");
+       table.setAttribute("style","border-radius: 0px 0px 4px 4px");
+       tr = document.createElement("tr");
+       tr.setAttribute("class","trac-columns");
+                       
+       for (header in headers){
+               th = document.createElement("th");
+               font = document.createElement("font");
+               font.setAttribute("color","#1975D1");
+               font.appendChild(document.createTextNode(headers[header]))
+               th = document.createElement("th");
+               th.appendChild(font);
+               tr.appendChild(th);
+       }
+       table.appendChild(tr);
+       for ( i=0 ; i<Object.keys(ticket.tickets).length ; i++ ){
+               tr = document.createElement("tr");
+               for (j=0;j<6;j++){
+                       if(j==0){
+                               td = document.createElement("td");
+                               a = document.createElement("a");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               a.setAttribute("href",tkt.url);
+                               
a.appendChild(document.createTextNode("#"+tkt.id));
+                               td.appendChild(a);
+                       }
+                       else if(j==1){
+                               td = document.createElement("td");
+                               a = document.createElement("a");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               a.setAttribute("href",tkt.url);
+                               
a.appendChild(document.createTextNode(tkt.summary));
+                               td.appendChild(a);
+                       }
+                       else if(j==2){
+                               td = document.createElement("td");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               
td.appendChild(document.createTextNode(tkt.product));
+                       }
+                       else if(j==3){
+                               td = document.createElement("td");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               
td.appendChild(document.createTextNode(tkt.status));
+                       }
+                       else if(j==4){
+                               td = document.createElement("td");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               
td.appendChild(document.createTextNode(tkt.milestone));
+                       }
+                       else if(j==5){
+                               td = document.createElement("td");
+                               tkt = JSON.parse(ticket.tickets[i]);
+                               
td.appendChild(document.createTextNode(tkt.component));
+                       }
+                       tr.appendChild(td);
+               }
+               table.appendChild(tr);
+       }
+       div.appendChild(table);
+       contentDiv.appendChild(div);     
+ }
\ No newline at end of file

Modified: 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/theme.py
URL: 
http://svn.apache.org/viewvc/bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/theme.py?rev=1617047&r1=1617046&r2=1617047&view=diff
==============================================================================
--- 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/theme.py
 (original)
+++ 
bloodhound/branches/bep_0011_batch_create_tickets/bloodhound_theme/bhtheme/theme.py
 Sun Aug 10 05:00:03 2014
@@ -18,6 +18,7 @@
 #  under the License.
 
 import sys
+import re
 
 from genshi.builder import tag
 from genshi.core import TEXT
@@ -34,6 +35,7 @@ from trac.ticket.notification import Tic
 from trac.ticket.web_ui import TicketModule
 from trac.util.compat import set
 from trac.util.presentation import to_json
+from trac.util.translation import cleandoc_
 from trac.versioncontrol.web_ui.browser import BrowserModule
 from trac.web.api import IRequestFilter, ITemplateStreamFilter
 from trac.web.chrome import (add_stylesheet, add_warning, 
INavigationContributor,
@@ -51,6 +53,7 @@ from bhdashboard import wiki
 from multiproduct.env import ProductEnvironment
 from multiproduct.web_ui import PRODUCT_RE, ProductModule
 from bhtheme.translation import _, add_domain
+from trac.wiki.macros import WikiMacroBase
 
 try:
     from multiproduct.ticket.web_ui import ProductTicketModule
@@ -692,12 +695,20 @@ from pkg_resources import get_distributi
 application_version = get_distribution('BloodhoundTheme').version
 
 
-class BatchCreateTicketDialog(Component):
+class BatchCreateTicketsMacro(WikiMacroBase):
     implements(
         IRequestFilter,
         IRequestHandler,
         ITemplateStreamFilter,
         IPermissionRequestor)
+    _description = cleandoc_(
+        """Batch Create Tickets macro.
+
+    This macro can be used to create batch oftickets at once. Use the 
following syntax.
+    BatchCreateTickets[[10]]
+    You can replace the argument(10 in the above exaple) to change the number 
of tickets that you are going to create.
+
+    """)
 
     bct_fields = ListOption(
         'ticket',
@@ -710,17 +721,85 @@ class BatchCreateTicketDialog(Component)
         import pkg_resources
         locale_dir = pkg_resources.resource_filename(__name__, 'locale')
         add_domain(self.env.path, locale_dir)
-        super(BatchCreateTicketDialog, self).__init__(*args, **kwargs)
+        self.rows = 0
+        self.rqst = None
+        self.file = None
+        super(BatchCreateTicketsMacro, self).__init__(*args, **kwargs)
 
     # IPermissionRequestor methods
     def get_permission_actions(self):
         return ['TICKET_BATCH_CREATE']
 
-    # IRequestFilter(Interface):
+    def expand_macro(self, formatter, name, args):
+        """Set the number of rows for empty ticket table to be generated.
+        Return none as the template will not changed at this point.
+
+        `name` is the actual name of the macro. (here it'll be
+        `'BatchCreateTickets'`),
+        `args` is the text enclosed in parenthesis at the call of the macro.
+          Note that if there are ''no'' parenthesis (like in, e.g.
+          [[BatchCreateTickets]]), then `args` is `None` and its not a valid 
argument.
+          Or if the argument is not a valid type(like in, e.g.
+          [[BatchCreateTickets("Hello")]] "Hello" is a string which can't be 
parsed to an integer)
+          then the bh will raise an error.
+        """
+        self.rows = args
+        if (
+                self.env.product is not None) and (
+                self.file == 'bh_wiki_view.html' or self.file == 
'bh_wiki_edit.html' or self.file is None) and (
+                self.rqst.perm.has_permission('TRAC_ADMIN') or 
self.rqst.perm.has_permission('TICKET_BATCH_CREATE')):
+            add_script(self.rqst, 'theme/js/batchcreate.js')
+            product_id = str(self.env.product.resource.id)
+            product_name = self.env.db_query(
+                "SELECT * FROM bloodhound_product WHERE prefix=%s", 
(product_id,))
+            milestones = self.env.db_query(
+                "SELECT * FROM milestone WHERE product=%s", (product_id,))
+            components = self.env.db_query(
+                "SELECT * FROM component WHERE product=%s", (product_id,))
+            form = tag.form(
+                method="get",
+                style="display:inline",
+                id="batchcreate")
+            div = tag.div(
+                style="display:inline-block;position:relative;left: -30px;",
+                id="div-empty-table")
+            span = tag.span(class_="input-group-btn")
+            style1 = tag.style(
+                id="js-caller",
+                onload="Javascript:emptyTable(" +
+                to_json(str(self.rows)) +
+                "," +
+                to_json(product_name) +
+                "," +
+                to_json(milestones) +
+                "," +
+                to_json(components) +
+                "," +
+                to_json(
+                    self.rqst.href() +
+                    "/bct") +
+                "," +
+                to_json(
+                    str(
+                        self.rqst.environ["HTTP_COOKIE"])) +
+                ")")
+            span.append(style1)
+            div.append(span)
+            form.append(div)
+            try:
+                int(self.rows)
+            except TracError:
+                print "Enter  a valid argument (integer) to the 
BatchCreateTickets macro."
 
+            return form
+        else:
+            return None
+
+    # IRequestFilter(Interface):
     def pre_process_request(self, req, handler):
         """Nothing to do.
         """
+        self.rqst = req
         return handler
 
     def post_process_request(self, req, template, data, content_type):
@@ -805,7 +884,6 @@ class BatchCreateTicketDialog(Component)
             # that information will be used to load the resultant query table
             product, tid, new_tkts = self.batch_create(
                 req, attrs, True)
-            # product, tid = self.batch_create(req, attrs, True)
         except Exception as exc:
             self.log.exception("BH: Batch create tickets failed %s" % (exc,))
             req.send(str(exc), 'plain/text', 500)
@@ -838,7 +916,23 @@ class BatchCreateTicketDialog(Component)
                             'component': new_tkts[i].values['component'],
                             'priority': new_tkts[i].values['priority'],
                             'description': new_tkts[i].values['description']}))
+
             tkt_dict["tickets"] = tkt_list
+
+            """Editing the wiki content"""
+            max_uid = self.env.db_query("SELECT MAX(uid) FROM ticket")
+            max_time = self.env.db_query("SELECT MAX(time) FROM wiki")
+            wiki_content = self.env.db_query(
+                "SELECT * FROM wiki WHERE time==%s", (max_time[0][0],))
+            wiki_string = wiki_content[0][5]
+            pattern = '\[\[BatchCreateTickets\([0-9]+\)\]\]'
+            l = re.search(pattern, wiki_string)
+            l1 = str(wiki_string[l.regs[0][0]:l.regs[0][1]])
+            updated_wiki_content = wiki_string.replace(
+                l1, "[[CreatedTickets(" + str(max_uid[0][0] - num_of_tkts) + 
"," + str(max_uid[0][0]) + ")]]")
+            with self.env.db_transaction as db:
+                db("UPDATE wiki SET text=%s WHERE time=%s",
+                   (updated_wiki_content, max_time[0][0]))
             req.send(to_json(tkt_dict), 'application/json')
 
     def _get_ticket_module(self):
@@ -854,57 +948,7 @@ class BatchCreateTicketDialog(Component)
 
     # Template Stream Filter methods
     def filter_stream(self, req, method, filename, stream, data):
-        if (self.env.product is not None) and (filename == 
'bh_wiki_view.html') and (
-                req.perm.has_permission('TRAC_ADMIN') or 
req.perm.has_permission('TICKET_BATCH_CREATE')):
-            add_script(req, 'theme/js/batchcreate.js')
-            xpath = '//form[@id=modifypage]'
-
-            product_id = str(self.env.product.resource.id)
-
-            product_name = self.env.db_query(
-                "SELECT * FROM bloodhound_product WHERE prefix=%s", 
(product_id,))
-            milestones = self.env.db_query(
-                "SELECT * FROM milestone WHERE product=%s", (product_id,))
-            components = self.env.db_query(
-                "SELECT * FROM component WHERE product=%s", (product_id,))
-            form = tag.form(
-                method="get",
-                style="display:inline",
-                id="batchcreate")
-            div = tag.div(style="display:inline-block;position:relative;")
-            span = tag.span(class_="input-group-btn")
-            input = tag.input(
-                id="numOfRows",
-                type="text",
-                style="width:200px;padding-right:30px;",
-                class_="form-control",
-                placeholder="How many tickets?")
-            button = tag.button(
-                id="bct-button",
-                
style="background-color:transparent;border:0;position:absolute;right:0;top:0;margin-top:
 0px;height:29px;background-color:#5C85FF;color:white",
-                type="button",
-                onclick="Javascript:emptyTable(" +
-                to_json(product_name) +
-                "," +
-                to_json(milestones) +
-                "," +
-                to_json(components) +
-                "," +
-                to_json(
-                    req.href() +
-                    "/bct") +
-                "," +
-                to_json(
-                    str(
-                        req.environ["HTTP_COOKIE"])) +
-                ")")
-            text = tag.text("Batch Create")
-            button.append(text)
-            span.append(input)
-            span.append(button)
-            div.append(span)
-            form.append(div)
-            stream |= Transformer(xpath).append(form)
+        self.file = filename
         return stream
 
     # Public API
@@ -917,6 +961,9 @@ class BatchCreateTicketDialog(Component)
         i = -1
 
         while loop_condition:
+            if num_of_tkts <= 0:
+                loop_condition = False
+                break
             i += 1
             if 'summary' + str(i) not in attributes:
                 continue
@@ -967,7 +1014,100 @@ class BatchCreateTicketDialog(Component)
                         "of ticket #%s: %s" %
                         (t.id, e))
             num_of_tkts -= 1
-            if num_of_tkts <= 0:
-                loop_condition = False
-
         return t['product'], t.id, created_tickets
+
+
+class CreatedTicketsMacro(WikiMacroBase):
+    implements(ITemplateStreamFilter)
+    _description = cleandoc_(
+        """Created Tickets macro.
+
+    This macro can be used to display the data of batch of tickets as a table 
within the wiki text. Use the following syntax.
+    CreatedTickets[[10,12]]
+    Arguments for the macro should be the starting id and the end id of the 
ticket sequence.
+
+    This is originally implemented as a part of the BatchCreateTickets macro. 
Though it can be intentionally use as a separate macro.
+    """)
+
+    def __init__(self, *args, **kwargs):
+        import pkg_resources
+        locale_dir = pkg_resources.resource_filename(__name__, 'locale')
+        add_domain(self.env.path, locale_dir)
+        self.rqst = None
+        self.file = None
+        super(CreatedTicketsMacro, self).__init__(*args, **kwargs)
+
+    # Template Stream Filter methods
+    def filter_stream(self, req, method, filename, stream, data):
+        self.rqst = req
+        self.file = filename
+        return stream
+
+    def expand_macro(self, formatter, name, args):
+        """Set the number of rows for empty ticket table to be generated.
+        Return none as the template will not changed at this point.
+
+        `name` is the actual name of the macro. (here it'll be
+        `'BatchCreateTickets'`),
+        `args` is the text enclosed in parenthesis at the call of the macro.
+          Note that if there are ''no'' parenthesis (like in, e.g.
+          [[BatchCreateTickets]]), then `args` is `None` and its not a valid 
argument.
+          Or if the argument is not a valid type(like in, e.g.
+          [[BatchCreateTickets("Hello")]] "Hello" is a string which can't be 
parsed to an integer)
+          then the bh will raise an error.
+        """
+        if self.file == 'bh_wiki_view.html' or self.file == 
'bh_wiki_edit.html' or self.file is None:
+            start_id = int(args.split(',')[0])
+            end_id = int(args.split(',')[1])
+
+            display_tickets = self.env.db_query(
+                "SELECT id,summary,product,status,milestone,component FROM 
ticket WHERE uid>=%s and uid<=%s",
+                (start_id +
+                 1,
+                 end_id),
+            )
+            display_tickets_list = []
+            display_tickets_dict = {}
+            for i in range(0, end_id - start_id):
+                tres = Neighborhood(
+                    'product',
+                    display_tickets[i][2])(
+                    'ticket',
+                    display_tickets[i][0])
+                href = self.rqst.href
+                display_tickets_list.append(
+                    to_json(
+                        {
+                            'product': display_tickets[i][2],
+                            'id': display_tickets[i][0],
+                            'url': get_resource_url(
+                                self.env,
+                                tres,
+                                href),
+                            'summary': display_tickets[i][1],
+                            'status': display_tickets[i][3],
+                            'milestone': display_tickets[i][4],
+                            'component': display_tickets[i][5]
+                        }))
+            display_tickets_dict["tickets"] = display_tickets_list
+
+            add_script(self.rqst, 'theme/js/batchcreate.js')
+            form = tag.form(
+                method="get",
+                style="display:inline",
+                id="batchcreate")
+            div = tag.div(
+                style="display:inline-block;position:relative;left: -30px;",
+                id="div-created-ticket-table")
+            span = tag.span(class_="input-group-btn")
+            body = tag.body(
+                id="js-caller",
+                onload="Javascript:display_created_tickets(" +
+                to_json(display_tickets_dict) +
+                ")")
+            span.append(body)
+            div.append(span)
+            form.append(div)
+            return form
+        else:
+            return None


Reply via email to