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.
Files changed (113) hide show
  1. data/VERSION.yml +1 -1
  2. data/bin/subtrac +2 -0
  3. data/lib/subtrac.rb +85 -50
  4. data/lib/subtrac/config/config.yml +22 -19
  5. data/lib/subtrac/templates/location.erb +2 -2
  6. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +1 -1
  7. data/lib/subtrac/templates/trac.erb +1 -1
  8. data/lib/subtrac/templates/vhost.erb +6 -6
  9. metadata +1 -105
  10. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
  11. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +0 -419
  12. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +0 -3
  13. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +0 -20
  14. data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
  15. data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +0 -28
  16. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +0 -168
  17. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +0 -137
  18. data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +0 -91
  19. data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +0 -199
  20. data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +0 -105
  21. data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +0 -287
  22. data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +0 -71
  23. data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +0 -4
  24. data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +0 -135
  25. data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +0 -70
  26. data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +0 -142
  27. data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +0 -231
  28. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +0 -27
  29. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +0 -152
  30. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +0 -160
  31. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +0 -124
  32. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +0 -134
  33. data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +0 -132
  34. data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +0 -97
  35. data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +0 -161
  36. data/lib/subtrac/trac-plugins/clientsplugin/setup.py +0 -43
  37. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +0 -4
  38. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +0 -273
  39. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +0 -44
  40. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +0 -36
  41. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +0 -32
  42. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +0 -409
  43. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +0 -30
  44. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +0 -53
  45. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +0 -181
  46. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +0 -66
  47. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +0 -47
  48. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +0 -93
  49. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +0 -86
  50. data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +0 -20
  51. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +0 -23
  52. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +0 -128
  53. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +0 -40
  54. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +0 -285
  55. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +0 -173
  56. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
  57. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +0 -164
  58. data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +0 -69
  59. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +0 -1
  60. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +0 -292
  61. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +0 -172
  62. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +0 -178
  63. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +0 -25
  64. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +0 -6
  65. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +0 -356
  66. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +0 -100
  67. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +0 -84
  68. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +0 -1149
  69. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +0 -119
  70. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +0 -73
  71. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +0 -165
  72. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +0 -28
  73. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +0 -221
  74. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +0 -675
  75. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +0 -150
  76. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +0 -25
  77. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +0 -131
  78. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +0 -84
  79. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +0 -104
  80. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +0 -194
  81. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +0 -62
  82. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +0 -28
  83. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +0 -127
  84. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +0 -129
  85. data/lib/subtrac/trac-plugins/worklogplugin/setup.py +0 -29
  86. data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +0 -1
  87. data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +0 -187
  88. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +0 -40
  89. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +0 -67
  90. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +0 -12
  91. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +0 -7
  92. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +0 -40
  93. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +0 -208
  94. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +0 -1439
  95. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
  96. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
  97. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +0 -80
  98. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
  99. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
  100. data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +0 -336
  101. data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +0 -598
  102. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +0 -45
  103. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +0 -70
  104. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +0 -40
  105. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +0 -59
  106. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +0 -33
  107. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +0 -153
  108. data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +0 -96
  109. data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +0 -29
  110. data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +0 -31
  111. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +0 -47
  112. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +0 -174
  113. 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
- //})()
@@ -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
- })()
@@ -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
-
@@ -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)
@@ -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
-