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