keithsalisbury-subtrac 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +1 -1
- data/bin/subtrac +2 -0
- data/lib/subtrac.rb +85 -50
- data/lib/subtrac/config/config.yml +22 -19
- data/lib/subtrac/templates/location.erb +2 -2
- data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +1 -1
- data/lib/subtrac/templates/trac.erb +1 -1
- data/lib/subtrac/templates/vhost.erb +6 -6
- metadata +1 -105
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +0 -419
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +0 -3
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +0 -20
- data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +0 -28
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +0 -168
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +0 -137
- data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +0 -91
- data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +0 -199
- data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +0 -105
- data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +0 -287
- data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +0 -71
- data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +0 -4
- data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +0 -135
- data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +0 -70
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +0 -142
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +0 -231
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +0 -27
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +0 -152
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +0 -160
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +0 -124
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +0 -134
- data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +0 -132
- data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +0 -97
- data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +0 -161
- data/lib/subtrac/trac-plugins/clientsplugin/setup.py +0 -43
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +0 -4
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +0 -273
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +0 -44
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +0 -36
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +0 -32
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +0 -409
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +0 -30
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +0 -53
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +0 -181
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +0 -66
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +0 -47
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +0 -93
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +0 -86
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +0 -20
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +0 -23
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +0 -128
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +0 -40
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +0 -285
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +0 -173
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +0 -164
- data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +0 -69
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +0 -1
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +0 -292
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +0 -172
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +0 -178
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +0 -25
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +0 -6
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +0 -356
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +0 -100
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +0 -84
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +0 -1149
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +0 -119
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +0 -73
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +0 -165
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +0 -28
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +0 -221
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +0 -675
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +0 -150
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +0 -25
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +0 -131
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +0 -84
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +0 -104
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +0 -194
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +0 -62
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +0 -28
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +0 -127
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +0 -129
- data/lib/subtrac/trac-plugins/worklogplugin/setup.py +0 -29
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +0 -1
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +0 -187
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +0 -67
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +0 -12
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +0 -7
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +0 -208
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +0 -1439
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +0 -80
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +0 -336
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +0 -598
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +0 -45
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +0 -70
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +0 -59
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +0 -33
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +0 -153
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +0 -96
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +0 -29
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +0 -31
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +0 -47
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +0 -174
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +0 -73
@@ -1,119 +0,0 @@
|
|
1
|
-
|
2
|
-
//var linkify =
|
3
|
-
//(function(){
|
4
|
-
String.prototype.trim =
|
5
|
-
(function () {return this.replace(/^\s+/, "").replace(/\s+$/, "");});
|
6
|
-
var invalidDate = new Date("invalid").toString()
|
7
|
-
var billingfields= {}
|
8
|
-
var statusfields = []
|
9
|
-
function dateToUnixEpoch(date){
|
10
|
-
return Math.round(date.getTime()/1000) - (60 * date.getTimezoneOffset());
|
11
|
-
}
|
12
|
-
function addBillingField( name /*optional type defaults to "textbox", optional flag status*/ ){
|
13
|
-
var type = arguments.length >= 1 ? arguments[1] : "textbox";
|
14
|
-
var status = arguments.length >= 2 ? arguments[2] : false;
|
15
|
-
var getSet =
|
16
|
-
(function(){
|
17
|
-
var valueProp = "value";
|
18
|
-
|
19
|
-
if(type == "date"){
|
20
|
-
return function (/*optional value*/){
|
21
|
-
if(arguments.length == 0){
|
22
|
-
var d = new Date(this.$()[valueProp]);
|
23
|
-
if(d.toString == invalidDate){
|
24
|
-
alert("You entered an invalid "+name);
|
25
|
-
return null;
|
26
|
-
}
|
27
|
-
return dateToUnixEpoch(d);
|
28
|
-
}
|
29
|
-
else{
|
30
|
-
var val = new Date(arguments[0]);
|
31
|
-
if(val.toString == invalidDate){
|
32
|
-
this.$()[valueProp] = null;
|
33
|
-
return null;
|
34
|
-
}
|
35
|
-
this.$()[valueProp] = val;
|
36
|
-
return val;
|
37
|
-
}
|
38
|
-
}
|
39
|
-
}
|
40
|
-
//FOR EVERYTHING ELSE
|
41
|
-
if(type == "checkbox"){
|
42
|
-
valueProp = "checked";
|
43
|
-
}
|
44
|
-
return function (/*optional value*/){
|
45
|
-
//alert(name+" : "+type+" "+valueProp);
|
46
|
-
if(arguments.length == 0){
|
47
|
-
var val = (this.$())[valueProp];
|
48
|
-
|
49
|
-
if(typeof(val) == "string") val = val.trim();
|
50
|
-
if(val)return val;
|
51
|
-
return null;
|
52
|
-
}
|
53
|
-
else{
|
54
|
-
var val = arguments[0];
|
55
|
-
(this.$())[valueProp] = val;
|
56
|
-
return val
|
57
|
-
}
|
58
|
-
}
|
59
|
-
})()
|
60
|
-
billingfields[name] = {
|
61
|
-
"$" : function(){
|
62
|
-
return document.getElementById(name);
|
63
|
-
},
|
64
|
-
getval : getSet,
|
65
|
-
setval : getSet
|
66
|
-
};
|
67
|
-
if (status){
|
68
|
-
statusfields.push({
|
69
|
-
name:name,
|
70
|
-
"$" : function(){
|
71
|
-
return document.getElementById(name);
|
72
|
-
},
|
73
|
-
getval : getSet,
|
74
|
-
setval : getSet
|
75
|
-
});
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
addBillingField("billable", "checkbox");
|
80
|
-
addBillingField("unbillable", "checkbox");
|
81
|
-
addBillingField("startdate", "date");
|
82
|
-
addBillingField("startbilling", "dateselect");
|
83
|
-
addBillingField("enddate", "date");
|
84
|
-
addBillingField("endbilling", "dateselect");
|
85
|
-
|
86
|
-
|
87
|
-
var linkify = function ( atag, basehref ){
|
88
|
-
var query = "";
|
89
|
-
var haveAdded = false;
|
90
|
-
function addToQuery(str){
|
91
|
-
query += haveAdded ? "&" : "?";
|
92
|
-
query += str;
|
93
|
-
haveAdded = true;
|
94
|
-
}
|
95
|
-
//billable logic
|
96
|
-
addToQuery(billingfields["billable"].getval() || !(billingfields["unbillable"].getval())
|
97
|
-
? "BILLABLE=1" : "BILLABLE=0");
|
98
|
-
addToQuery(billingfields["unbillable"].getval() || !(billingfields["billable"].getval())
|
99
|
-
? "UNBILLABLE=0" : "UNBILLABLE=1");
|
100
|
-
|
101
|
-
for(var i=0, f = null ; f = statusfields[i] ; i++){
|
102
|
-
val = f.name.toUpperCase().replace("_","", "g").replace(" ","","g")+"=";
|
103
|
-
if(f.getval()){
|
104
|
-
val += f.name
|
105
|
-
}
|
106
|
-
addToQuery(val);
|
107
|
-
}
|
108
|
-
|
109
|
-
//startdate the date in the text box or the date in the dropdown or the first time
|
110
|
-
startdate = billingfields["startdate"].getval() || billingfields["startbilling"].getval() || 0;
|
111
|
-
addToQuery("STARTDATE="+startdate);
|
112
|
-
//the date in the enddate text box or the date in the enddate billing box or real close to the end of integer unix epoch time
|
113
|
-
// this will need a patch to continue working past this point
|
114
|
-
enddate = billingfields["enddate"].getval() || billingfields["endbilling"].getval() || 2000000000;
|
115
|
-
addToQuery("ENDDATE="+enddate);
|
116
|
-
|
117
|
-
atag.href = basehref+query;
|
118
|
-
}
|
119
|
-
//})()
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
(function(){
|
2
|
-
function AddEventListener( elem, evt, func, capture){
|
3
|
-
capture = capture || false;
|
4
|
-
if(elem.addEventListener) elem.addEventListener( evt, func, capture);
|
5
|
-
else elem.attachEvent('on'+evt, func);
|
6
|
-
return func;
|
7
|
-
};
|
8
|
-
var InitQuery = function(){
|
9
|
-
function createTableRow( numTds ){
|
10
|
-
var tr = document.createElement('tr');
|
11
|
-
var td = document.createElement('td');
|
12
|
-
td.style.backgroundColor="#EEF";
|
13
|
-
for(var i=0 ; i < numTds ; i++){
|
14
|
-
tr.appendChild(td.cloneNode(true));
|
15
|
-
}
|
16
|
-
return tr;
|
17
|
-
}
|
18
|
-
|
19
|
-
var _tbls = document.getElementsByTagName('table');
|
20
|
-
var tbls = [], tbl, cell;
|
21
|
-
// filter so that we only get ticket listing tables
|
22
|
-
for(var i=0 ; tbl = _tbls[i] ; i++ ){
|
23
|
-
if(tbl.className == 'listing tickets') tbls.push(tbl);
|
24
|
-
}
|
25
|
-
|
26
|
-
// find numerical columns
|
27
|
-
tbl = tbls[0];
|
28
|
-
|
29
|
-
var cells = tbl.tBodies[0].rows[0].cells;
|
30
|
-
var cellIdxs = [], columnNames = {};
|
31
|
-
for(var i=0 ; cell = cells[i] ; i++ ){
|
32
|
-
if(!isNaN(Number(cells[i].textContent))){
|
33
|
-
cellIdxs.push(i);
|
34
|
-
if(tbl && tbl.tHead.rows.length > 0)
|
35
|
-
columnNames[i] = tbl.tHead.rows[0].cells[i].textContent;
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
// total the numerical columns and add a total row to each table
|
40
|
-
var totals, total_totals =[], idx;
|
41
|
-
for(var i=0 ; tbl = tbls[i] ; i++ ){
|
42
|
-
totals = [];
|
43
|
-
for(var k=0 ; row = tbl.tBodies[0].rows[k] ; k++){
|
44
|
-
for(var j=0 ; idx = cellIdxs[j] ; j++){
|
45
|
-
if(totals[idx] == null) totals[idx] = 0;
|
46
|
-
if(total_totals[idx] == null) total_totals[idx] = 0;
|
47
|
-
if(!isNaN(Number(row.cells[idx].textContent)))
|
48
|
-
var val = Number(row.cells[idx].textContent);
|
49
|
-
total_totals[idx] += val
|
50
|
-
totals[idx] += val;
|
51
|
-
}
|
52
|
-
}
|
53
|
-
if(tbl.tBodies[0].rows.length > 0){
|
54
|
-
var tr = createTableRow(tbl.tBodies[0].rows[0].cells.length);
|
55
|
-
for(var j=0 ; idx = cellIdxs[j] ; j++){
|
56
|
-
tr.cells[idx].appendChild(document.createTextNode(totals[idx]));
|
57
|
-
}
|
58
|
-
tbl.tBodies[0].appendChild(tr);
|
59
|
-
}
|
60
|
-
}
|
61
|
-
// If we are grouping by things, we are going to want to add a complete total to the bottom
|
62
|
-
if(tbls.length > 1){
|
63
|
-
var totalHtml = document.createElement('div');
|
64
|
-
totalHtml.style.backgroundColor="#EEF";
|
65
|
-
for(var j=0 ; idx = cellIdxs[j] ; j++){
|
66
|
-
totalHtml.appendChild(document.createTextNode("Total "+columnNames[idx]+": "+total_totals[idx]));
|
67
|
-
totalHtml.appendChild(document.createElement('br'));
|
68
|
-
}
|
69
|
-
tbls[0].parentNode.appendChild(totalHtml);
|
70
|
-
}
|
71
|
-
}
|
72
|
-
AddEventListener(window, 'load', InitQuery)
|
73
|
-
})()
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
(function(){
|
2
|
-
function teAddEventListener(elem, evt, func, capture)
|
3
|
-
{
|
4
|
-
capture = capture || false;
|
5
|
-
if (elem.addEventListener) elem.addEventListener(evt, func, capture);
|
6
|
-
else elem.attachEvent('on'+evt, func);
|
7
|
-
return func;
|
8
|
-
}
|
9
|
-
|
10
|
-
// Function from: http://www.robertnyman.com/index.php?p=256
|
11
|
-
function getElementsByClassName(className, tag, elm)
|
12
|
-
{
|
13
|
-
var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
|
14
|
-
var tag = tag || "*";
|
15
|
-
var elm = elm || document;
|
16
|
-
var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
|
17
|
-
var returnElements = [];
|
18
|
-
var current;
|
19
|
-
var length = elements.length;
|
20
|
-
for (var i=0; i<length; i++)
|
21
|
-
{
|
22
|
-
current = elements[i];
|
23
|
-
if(testClass.test(current.className))
|
24
|
-
{
|
25
|
-
returnElements.push(current);
|
26
|
-
}
|
27
|
-
}
|
28
|
-
return returnElements;
|
29
|
-
}
|
30
|
-
|
31
|
-
|
32
|
-
function FloatToHoursMins(hours)
|
33
|
-
{
|
34
|
-
if (0 == hours) return hours;
|
35
|
-
var neg = false;
|
36
|
-
if(hours < 0){
|
37
|
-
neg = true;
|
38
|
-
hours *= -1;
|
39
|
-
}
|
40
|
-
mins = Math.floor((hours - Math.floor(hours)) * 60);
|
41
|
-
str = neg ? '-' : '';
|
42
|
-
if (hours) str += Math.floor(hours) + 'h';
|
43
|
-
if (mins) str += ' ' + mins + 'm';
|
44
|
-
return str;
|
45
|
-
}
|
46
|
-
|
47
|
-
function IntToYesNo(boolflag)
|
48
|
-
{
|
49
|
-
if (boolflag == '1')
|
50
|
-
return 'Yes';
|
51
|
-
|
52
|
-
if (boolflag == '0')
|
53
|
-
return 'No';
|
54
|
-
|
55
|
-
return boolflag;
|
56
|
-
}
|
57
|
-
|
58
|
-
|
59
|
-
InitBilling = function(){
|
60
|
-
/* // Convert totalhours field to non-editable
|
61
|
-
try
|
62
|
-
{
|
63
|
-
var x = document.getElementById('totalhours');
|
64
|
-
x = x || document.getElementById('field-totalhours');
|
65
|
-
if (x)
|
66
|
-
{
|
67
|
-
var p = x.parentNode;
|
68
|
-
var n = document.createElement('span')
|
69
|
-
n.id = x.id;
|
70
|
-
n.appendChild(document.createTextNode(x.value));
|
71
|
-
p.removeChild(x);
|
72
|
-
p.appendChild(n);
|
73
|
-
}
|
74
|
-
}
|
75
|
-
catch (er) {}
|
76
|
-
*/
|
77
|
-
|
78
|
-
// Display yes/no in the summary
|
79
|
-
// if we fail, then no harm done.
|
80
|
-
try
|
81
|
-
{
|
82
|
-
var b = document.getElementById('h_billable');
|
83
|
-
do{ b = b.nextSibling; }while(b.nodeName != "TD");
|
84
|
-
b.innerHTML = IntToYesNo(b.innerHTML);
|
85
|
-
}
|
86
|
-
catch (er) {}
|
87
|
-
|
88
|
-
/*
|
89
|
-
// Hide the Add Hours in the title table
|
90
|
-
// if we fail, then no harm done.
|
91
|
-
try
|
92
|
-
{
|
93
|
-
var b = document.getElementById('h_hours');
|
94
|
-
b.innerHTML = '';
|
95
|
-
do{ b = b.nextSibling; }while(b.nodeName != "TD");
|
96
|
-
b.innerHTML = '';
|
97
|
-
}
|
98
|
-
catch (er) {}
|
99
|
-
*/
|
100
|
-
|
101
|
-
// Convert hours from float to hours minutes seconds
|
102
|
-
// if we fail, then no harm done.
|
103
|
-
try
|
104
|
-
{
|
105
|
-
fields = Array('estimatedhours', 'totalhours');
|
106
|
-
for (var i=0; i < 2; ++i)
|
107
|
-
{
|
108
|
-
var b = document.getElementById('h_' + fields[i]);
|
109
|
-
while (b)
|
110
|
-
{
|
111
|
-
if (!b.nextSibling) break;
|
112
|
-
b = b.nextSibling;
|
113
|
-
if (b.nodeName == 'TD')
|
114
|
-
{
|
115
|
-
b.innerHTML = FloatToHoursMins(b.innerHTML);
|
116
|
-
break;
|
117
|
-
}
|
118
|
-
}
|
119
|
-
}
|
120
|
-
}
|
121
|
-
catch (er) {}
|
122
|
-
|
123
|
-
// Convert all relevent ticket changes to hours/minutes
|
124
|
-
// if we fail, then no harm done.
|
125
|
-
try {
|
126
|
-
changes = getElementsByClassName('changes', 'ul', document.getElementById('changelog'));
|
127
|
-
var change, li;
|
128
|
-
for (var i=0; change = changes[i]; i++) {
|
129
|
-
for (var j=0, li = change.childNodes[j]; li = change.childNodes[j]; j++) {
|
130
|
-
handleChangeRow(li);
|
131
|
-
}
|
132
|
-
}
|
133
|
-
}
|
134
|
-
catch (er) {}
|
135
|
-
}
|
136
|
-
|
137
|
-
handleChangeRow = function(li){
|
138
|
-
var child, val, vals =[];
|
139
|
-
if (li.nodeName != 'LI') return;
|
140
|
-
// We look for a STRONG childNode
|
141
|
-
// We also need to find any em's following the STRONG
|
142
|
-
for(var i=0 ; child = li.childNodes[i] ; i++){
|
143
|
-
if (child.nodeName == 'STRONG'){
|
144
|
-
field = child.firstChild.nodeValue;
|
145
|
-
if(!(field == 'hours'
|
146
|
-
|| field == 'estimatedhours'
|
147
|
-
|| field == 'totalhours'))
|
148
|
-
return;
|
149
|
-
}
|
150
|
-
if (child.nodeName == 'EM'){
|
151
|
-
vals.push([child, child.firstChild.nodeValue])
|
152
|
-
}
|
153
|
-
}
|
154
|
-
for(var i=0; val = vals[i] ; i++){
|
155
|
-
out = FloatToHoursMins(Number(val[1]))
|
156
|
-
//print(val[0]+'|'+ val[1] )
|
157
|
-
//print("#"+ out)
|
158
|
-
val[0].innerHTML = out
|
159
|
-
}
|
160
|
-
return vals;
|
161
|
-
}
|
162
|
-
|
163
|
-
teAddEventListener(window, 'load', InitBilling)
|
164
|
-
})()
|
165
|
-
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
import re
|
2
|
-
from trac.log import logger_factory
|
3
|
-
from trac.core import *
|
4
|
-
from trac.web import IRequestHandler
|
5
|
-
from trac.util import Markup
|
6
|
-
from trac.web.chrome import add_stylesheet, add_script, \
|
7
|
-
INavigationContributor, ITemplateProvider
|
8
|
-
from trac.web.href import Href
|
9
|
-
|
10
|
-
class QueryWebUiAddon(Component):
|
11
|
-
implements(INavigationContributor)
|
12
|
-
|
13
|
-
def __init__(self):
|
14
|
-
pass
|
15
|
-
|
16
|
-
# INavigationContributor methods
|
17
|
-
def get_active_navigation_item(self, req):
|
18
|
-
|
19
|
-
if re.search('query', req.path_info):
|
20
|
-
return "query-addon"
|
21
|
-
else:
|
22
|
-
return ""
|
23
|
-
|
24
|
-
def get_navigation_items(self, req):
|
25
|
-
src = req.href.chrome("Billing/query.js")
|
26
|
-
if re.search('query', req.path_info):
|
27
|
-
yield 'mainnav', "query-addon", \
|
28
|
-
Markup("""<script language="javascript" type="text/javascript" src="%s"></script>"""%src)
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py
DELETED
@@ -1,221 +0,0 @@
|
|
1
|
-
from trac.core import *
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class CustomReportManager:
|
6
|
-
"""A Class to manage custom reports"""
|
7
|
-
version = 1
|
8
|
-
name = "custom_report_manager_version"
|
9
|
-
env = None
|
10
|
-
log = None
|
11
|
-
TimingAndEstimationKey = "Timing and Estimation Plugin"
|
12
|
-
|
13
|
-
def __init__(self, env, log):
|
14
|
-
self.env = env
|
15
|
-
self.log = log
|
16
|
-
self.upgrade()
|
17
|
-
|
18
|
-
def upgrade(self):
|
19
|
-
# Check to see what version we have
|
20
|
-
db = self.env.get_db_cnx()
|
21
|
-
cursor = db.cursor()
|
22
|
-
cursor.execute("SELECT value FROM system WHERE name=%s", (self.name,))
|
23
|
-
try:
|
24
|
-
version = int(cursor.fetchone()[0])
|
25
|
-
except:
|
26
|
-
version = 0
|
27
|
-
cursor.execute("INSERT INTO system (name,value) VALUES(%s,%s)",
|
28
|
-
(self.name, version))
|
29
|
-
|
30
|
-
if version > self.version:
|
31
|
-
raise TracError("Fatal Error: You appear to be running two plugins with conflicting versions "
|
32
|
-
"of the CustomReportManager class. Please ensure that '%s' is updated to "
|
33
|
-
"version %s of the file reportmanager.py (currently using version %s)."
|
34
|
-
% (__name__, str(version), str(self.version)))
|
35
|
-
|
36
|
-
# Do the staged updates
|
37
|
-
try:
|
38
|
-
if version < 1:
|
39
|
-
cursor.execute("CREATE TABLE custom_report ("
|
40
|
-
"id INTEGER,"
|
41
|
-
"uuid VARCHAR(64),"
|
42
|
-
"maingroup VARCHAR(255),"
|
43
|
-
"subgroup VARCHAR(255),"
|
44
|
-
"version INTEGER,"
|
45
|
-
"ordering INTEGER)")
|
46
|
-
|
47
|
-
#if version < 2:
|
48
|
-
# cursor.execute("...")
|
49
|
-
|
50
|
-
# Updates complete, set the version
|
51
|
-
cursor.execute("UPDATE system SET value=%s WHERE name=%s",
|
52
|
-
(self.version, self.name))
|
53
|
-
db.commit()
|
54
|
-
db.close()
|
55
|
-
|
56
|
-
except Exception, e:
|
57
|
-
self.log.error("CustomReportManager Exception: %s" % (e,));
|
58
|
-
db.rollback()
|
59
|
-
|
60
|
-
def get_report_id_and_version (self, uuid):
|
61
|
-
sql = "SELECT custom_report.id, custom_report.version FROM custom_report "\
|
62
|
-
"JOIN report ON report.id = custom_report.id " \
|
63
|
-
"WHERE uuid=%s"
|
64
|
-
tpl = self.get_first_row(sql, uuid)
|
65
|
-
return tpl or (None, 0)
|
66
|
-
|
67
|
-
def get_new_report_id (self):
|
68
|
-
"""find the next available report id """
|
69
|
-
rtn = self.get_scalar("SELECT MAX(id) FROM report")
|
70
|
-
return (rtn and rtn+1) or 1
|
71
|
-
|
72
|
-
def get_max_ordering(self, maingroup, subgroup):
|
73
|
-
""" Find the maximum ordering value used for this group of the custom_report table"""
|
74
|
-
return self.get_scalar("SELECT MAX(ordering) FROM custom_report WHERE maingroup=%s AND subgroup=%s",
|
75
|
-
0, maingroup, subgroup) or 0
|
76
|
-
|
77
|
-
def _insert_report (self, next_id, title, author, description, query,
|
78
|
-
uuid, maingroup, subgroup, version, ordering):
|
79
|
-
""" Adds a row the custom_report_table """
|
80
|
-
self.log.debug("Inserting new report '%s' with uuid '%s'" % (title,uuid))
|
81
|
-
self.execute_in_trans(("DELETE FROM custom_report WHERE uuid=%s", (uuid,)),
|
82
|
-
("INSERT INTO report (id, title, author, description, query) " \
|
83
|
-
"VALUES (%s, %s, %s, %s, %s)",
|
84
|
-
(next_id, title, author, description, query)),
|
85
|
-
("INSERT INTO custom_report (id, uuid, maingroup, subgroup, version, ordering) " \
|
86
|
-
"VALUES (%s, %s, %s, %s, %s, %s)",
|
87
|
-
(next_id, uuid, maingroup, subgroup, version, ordering)))
|
88
|
-
self.log.debug("Attempting to increment sequence (only works in postgres)")
|
89
|
-
try:
|
90
|
-
self.execute_in_trans(("SELECT nextval('report_id_seq');",[]));
|
91
|
-
self.log.debug("Sequence updated");
|
92
|
-
except:
|
93
|
-
self.log.debug("Sequence failed to update, perhaps you are not running postgres?");
|
94
|
-
|
95
|
-
def _update_report (self, id, title, author, description, query,
|
96
|
-
maingroup, subgroup, version):
|
97
|
-
"""Updates a report and its row in the custom_report table """
|
98
|
-
self.log.debug("Updating report '%s' with to version %s" % (title, version))
|
99
|
-
self.execute_in_trans(("UPDATE report SET title=%s, author=%s, description=%s, query=%s " \
|
100
|
-
"WHERE id=%s", (title, author, description, query, id)),
|
101
|
-
("UPDATE custom_report SET version=%s, maingroup=%s, subgroup=%s "
|
102
|
-
"WHERE id=%s", (version, maingroup, subgroup, id)))
|
103
|
-
|
104
|
-
def add_report(self, title, author, description, query, uuid, version,
|
105
|
-
maingroup, subgroup="", force=False):
|
106
|
-
"""
|
107
|
-
We add/update a report to the system. We will not overwrite unchanged versions
|
108
|
-
unless force is set.
|
109
|
-
"""
|
110
|
-
# First check to see if we can load an existing version of this report
|
111
|
-
(id, currentversion) = self.get_report_id_and_version(uuid)
|
112
|
-
self.log.debug("add_report %s (ver:%s) | id: %s currentversion: %s" % (uuid , version, id, currentversion))
|
113
|
-
try:
|
114
|
-
if not id:
|
115
|
-
next_id = self.get_new_report_id()
|
116
|
-
ordering = self.get_max_ordering(maingroup, subgroup) + 1
|
117
|
-
self._insert_report(next_id, title, author, description, query,
|
118
|
-
uuid, maingroup, subgroup, version, ordering)
|
119
|
-
return True
|
120
|
-
if currentversion < version or force:
|
121
|
-
self._update_report(id, title, author, description, query,
|
122
|
-
maingroup, subgroup, version)
|
123
|
-
return True
|
124
|
-
except Exception, e:
|
125
|
-
self.log.error("CustomReportManager.add_report Exception: %s, %s" % (e,(title, author, uuid, version,
|
126
|
-
maingroup, subgroup, force)));
|
127
|
-
self.log.debug("report %s not upgraded (a better version already exists)" % uuid)
|
128
|
-
return False
|
129
|
-
|
130
|
-
def get_report_by_uuid(self, uuid):
|
131
|
-
sql = "SELECT report.id,report.title FROM custom_report "\
|
132
|
-
"LEFT JOIN report ON custom_report.id=report.id "\
|
133
|
-
"WHERE custom_report.uuid=%s"
|
134
|
-
return self.get_first_row(sql,uuid)
|
135
|
-
|
136
|
-
def get_reports_by_group(self, group):
|
137
|
-
"""Gets all of the reports for a given group"""
|
138
|
-
db = self.env.get_db_cnx()
|
139
|
-
cursor = db.cursor()
|
140
|
-
rv = {}
|
141
|
-
try:
|
142
|
-
cursor.execute("SELECT custom_report.subgroup,report.id,report.title, custom_report.version, custom_report.uuid "
|
143
|
-
"FROM custom_report "
|
144
|
-
"LEFT JOIN report ON custom_report.id=report.id "
|
145
|
-
"WHERE custom_report.maingroup=%s "
|
146
|
-
"ORDER BY custom_report.subgroup,custom_report.ordering", (group,))
|
147
|
-
for subgroup, id, title, version, uuid in cursor:
|
148
|
-
if not rv.has_key(subgroup):
|
149
|
-
rv[subgroup] = { "title": subgroup,
|
150
|
-
"reports": [] }
|
151
|
-
rv[subgroup]["reports"].append( { "id": int(id), "title": title, "version":version, "uuid":uuid } )
|
152
|
-
except:
|
153
|
-
pass
|
154
|
-
return rv
|
155
|
-
|
156
|
-
def get_version_hash_by_group(self, group):
|
157
|
-
"""Gets all of the reports for a given group as a uuid=>version hash"""
|
158
|
-
db = self.env.get_db_cnx()
|
159
|
-
cursor = db.cursor()
|
160
|
-
rv = {}
|
161
|
-
try:
|
162
|
-
cursor.execute("SELECT custom_report.subgroup,report.id,report.title, custom_report.version, custom_report.uuid "
|
163
|
-
"FROM custom_report "
|
164
|
-
"LEFT JOIN report ON custom_report.id=report.id "
|
165
|
-
"WHERE custom_report.maingroup=%s "
|
166
|
-
"ORDER BY custom_report.subgroup,custom_report.ordering", (group,))
|
167
|
-
for subgroup, id, title, version, uuid in cursor:
|
168
|
-
rv[uuid] = version
|
169
|
-
except:
|
170
|
-
pass
|
171
|
-
return rv
|
172
|
-
|
173
|
-
# similar functions are found in dbhelper, but this file should be fairly
|
174
|
-
# stand alone so that it can be copied and pasted around
|
175
|
-
def get_first_row(self, sql,*params):
|
176
|
-
""" Returns the first row of the query results as a tuple of values (or None)"""
|
177
|
-
db = self.env.get_db_cnx()
|
178
|
-
cur = db.cursor()
|
179
|
-
data = None;
|
180
|
-
try:
|
181
|
-
cur.execute(sql, params)
|
182
|
-
data = cur.fetchone();
|
183
|
-
db.commit();
|
184
|
-
except Exception, e:
|
185
|
-
self.log.error('There was a problem executing sql:%s \n \
|
186
|
-
with parameters:%s\nException:%s'%(sql, params, e));
|
187
|
-
db.rollback()
|
188
|
-
try:
|
189
|
-
db.close()
|
190
|
-
except:
|
191
|
-
pass
|
192
|
-
return data;
|
193
|
-
|
194
|
-
def get_scalar(self, sql, col=0, *params):
|
195
|
-
""" Gets a single value (in the specified column) from the result set of the query"""
|
196
|
-
data = self.get_first_row(sql, *params);
|
197
|
-
if data:
|
198
|
-
return data[col]
|
199
|
-
else:
|
200
|
-
return None;
|
201
|
-
|
202
|
-
def execute_in_trans(self, *args):
|
203
|
-
success = True
|
204
|
-
db = self.env.get_db_cnx()
|
205
|
-
cur = db.cursor()
|
206
|
-
try:
|
207
|
-
for sql, params in args:
|
208
|
-
cur.execute(sql, params)
|
209
|
-
db.commit()
|
210
|
-
except Exception, e:
|
211
|
-
self.log.error('There was a problem executing sql:%s \n \
|
212
|
-
with parameters:%s\nException:%s'%(sql, params, e));
|
213
|
-
db.rollback();
|
214
|
-
success = False
|
215
|
-
try:
|
216
|
-
db.close()
|
217
|
-
except:
|
218
|
-
pass
|
219
|
-
return success
|
220
|
-
|
221
|
-
|