FogBugz » TimeIntervalCommentsPlugin http://fogbugz.stackexchange.com/questions/3316
Clone URL:  
Pushed to one repository · View In Graph Contained in version_0-2-0-0, version_0-2-0-1, and tip

version_0-2-0-0 finished! version 0.2 actually works but only just :) http://our.fogbugz.com/default.asp?2036704

Changeset 991672cdc03b

Parent 9fa408c4fe1c

by Adam Wishneusky

Changes to 3 files · Browse files at 991672cdc03b Showing diff from parent 9fa408c4fe1c Diff from another changeset...

 
39
40
41
42
43
 
 
 
39
40
41
 
 
42
43
@@ -39,5 +39,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers  // by using the '*' as shown below:  // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.4.1")] -[assembly: AssemblyFileVersion("0.1.4.1")] +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
 
 
 
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
 
 
 
 
 
 
 
 
 
 
 
 
160
161
162
163
164
 
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
 
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
 using System;  using System.Collections.Generic;  using System.Text;  using System.Web;    using FogCreek.FogBugz;  using FogCreek.FogBugz.Plugins;  using FogCreek.FogBugz.Plugins.Api;  using FogCreek.FogBugz.Database.Entity;  using FogCreek.FogBugz.Plugins.Entity;  using FogCreek.FogBugz.Plugins.Interfaces;  using FogCreek.FogBugz.UI.Dialog;    namespace TimeIntervalExample  {   public class TimeIntervalExample : Plugin, IPluginTimeIntervalJoin,   IPluginJS, IPluginDatabase, IPluginRawPageDisplay   {   public TimeIntervalExample(CPluginApi api) : base(api) { }     protected const string sPluginId = "Adam+TimeIntervalExample@fogcreek.com";   private const string CommentsTable = "TimeIntervalComment";   private const string IntervalColumn = "ixInterval";   private const string CommentColumn = "sComment";   public const int CommentColumnMaxLength = 255;   private const int PluginSchemaVer = 1;     #region IPluginTimeIntervalJoin Members     public string[] TimeIntervalJoinTables()   {   return new string[] { "TimeIntervalComment" };   }     #endregion     #region IPluginJS Members   + // this js comes down on every page. I put this here instead of in the static js file + // because we need the pluginprefix for this plugin (which is based on when the plugin is + // installed. alternatively, we could just set a variable for it in JS-land and put the + // rest of these functions into the static js file   public CJSInfo JSInfo()   {   string fullAjaxPostUrl = api.Url.PluginRawPageUrl() +   String.Format("&{0}sComment=' + sComment + '&{0}action=postTimeIntervalComment&{0}actionToken={1}&{0}ixInterval=' + ixInterval",   api.PluginPrefix,   api.Security.GetActionToken("postTimeIntervalComment"));   string fullAjaxGetUrl = api.Url.PluginRawPageUrl() +   String.Format("&{0}action=getTimeIntervalComment&{0}actionToken={1}&{0}ixInterval=' + ixInterval",   api.PluginPrefix,   api.Security.GetActionToken("postTimeIntervalComment"));     CJSInfo jsInfo = new CJSInfo();   jsInfo.rgsStaticFiles = new string[] { "js/TimeIntervalExample.js" };   jsInfo.sInlineJS = @"  function postTimeIntervalComment()  {   var sComment = $('form#TimeIntervalExamplePluginForm input[name=comment]').val();   var ixInterval = $('form#TimeIntervalExamplePluginForm input[name=ixInterval]').val();   var url = '" + fullAjaxPostUrl + @";   jQuery.get(url, function(data) { postCallback(data); });  }    function getTimeIntervalComment(ixInterval)  {   var url = '" + fullAjaxGetUrl + @";   jQuery.get(url, function(data) { getCallback(data); });  }";   return jsInfo;   }     #endregion     #region IPluginDatabase Members     public CTable[] DatabaseSchema()   {   var timeIntervalComments = api.Database.NewTable(api.Database.PluginTableName(CommentsTable));   timeIntervalComments.sDesc = "Assigns Comments to TimeIntervals";   timeIntervalComments.AddAutoIncrementPrimaryKey("ixTimeIntervalComment");   timeIntervalComments.AddIntColumn(IntervalColumn, true, 0);   timeIntervalComments.AddVarcharColumn(CommentColumn, CommentColumnMaxLength, false);     return new[] { timeIntervalComments };   }     public int DatabaseSchemaVersion()   {   return PluginSchemaVer;   }     public void DatabaseUpgradeAfter(int ixVersionFrom, int ixVersionTo, CDatabaseUpgradeApi apiUpgrade)   {   if (ixVersionTo == 1)   {   // No action required. Don't create any data in the tables   }   }     public void DatabaseUpgradeBefore(int ixVersionFrom, int ixVersionTo, CDatabaseUpgradeApi apiUpgrade)   {   if (ixVersionTo == 1)   {   // No action required. Don't create any data in the tables   }   }     #endregion     #region IPluginRawPageDisplay Members     public string RawPageDisplay()   {   if (api.Request[api.AddPluginPrefix("action")] != null &&   Convert.ToString(api.Request[api.AddPluginPrefix("action")]) == "postTimeIntervalComment")   {   // make sure the request includes a valid action token   if ((api.Request[api.AddPluginPrefix("actionToken")] == null) ||   !api.Security.ValidateActionToken(api.Request[api.AddPluginPrefix("actionToken")],   "postTimeIntervalComment"))   {   return "failure: action token invalid";   }   else   {   int ixInterval = -1;   string sComment = "";   if (api.Request[api.AddPluginPrefix("ixInterval")] != null &&   Int32.TryParse(Convert.ToString(api.Request[api.AddPluginPrefix("ixInterval")]), out ixInterval))   {   if (api.Request[api.AddPluginPrefix("sComment")] != null)   sComment = api.Request[api.AddPluginPrefix("sComment")].ToString();   return PostComment(ixInterval, sComment);   }   else return "failure: invalid ixInterval";   }     }     else if (api.Request[api.AddPluginPrefix("action")] != null &&   Convert.ToString(api.Request[api.AddPluginPrefix("action")]) == "getTimeIntervalComment")   {   int ixInterval = -1;   if (api.Request[api.AddPluginPrefix("ixInterval")] != null &&   Int32.TryParse(Convert.ToString(api.Request[api.AddPluginPrefix("ixInterval")]), out ixInterval))   return GetComment(ixInterval);   else   return "failure: ixInterval invalid";   }   else return "failure: command not recognized";   }     public PermissionLevel RawPageVisibility()   {   return PermissionLevel.Normal;   }     #endregion     private string PostComment(int ixInterval, string sComment)   { - return "you posted '" + sComment + "' for interval #" + ixInterval; + CTimeIntervalQuery query = api.TimeInterval.NewTimeIntervalQuery(); + query.AddWhere("TimeInterval.ixInterval = @ixInterval"); + query.SetParamInt("@ixInterval", ixInterval); + + CTimeInterval[] rgTimeIntervals = query.List(); + if (rgTimeIntervals.Length > 0) + { + CTimeInterval interval = rgTimeIntervals[0]; + interval.SetPluginField(sPluginId, "sComment", sComment); + interval.Commit(); + } + return "success: '" + sComment + "' recorded for interval #" + ixInterval;   }     private string GetComment(int ixInterval)   { - string sComment = "none"; + string sComment = "";     CTimeIntervalQuery query = api.TimeInterval.NewTimeIntervalQuery();   query.AddWhere("TimeInterval.ixInterval = @ixInterval");   query.SetParamInt("@ixInterval", ixInterval);     CTimeInterval[] rgTimeIntervals = query.List();   if (rgTimeIntervals.Length > 0)   {   object oComment = rgTimeIntervals[0].GetPluginField(sPluginId, "sComment");   if (oComment != null)   sComment = oComment.ToString();   }   return sComment;   }   }  }
 
 
 
 
 
1
2
3
 
24
25
26
 
27
28
29
30
31
32
 
51
52
53
 
54
55
56
 
63
64
65
 
 
66
67
68
 
71
72
73
74
 
75
76
77
 
78
79
80
 
83
84
85
86
 
87
88
89
 
1
2
3
4
5
6
7
 
28
29
30
31
32
 
 
33
34
35
 
54
55
56
57
58
59
60
 
67
68
69
70
71
72
73
74
 
77
78
79
 
80
81
82
 
83
84
85
86
 
89
90
91
 
92
93
94
95
@@ -1,3 +1,7 @@
+// this is the standard fogbugz popup code, managed by the PopupManager object +// I set the html and added js after oSelf.Popup.setHtml which finds the ixInterval that got added to +// the dialog in doTimesheetMagic to the form here. it also calls getTimeIntervalComment to fetch +// the comment for the interval being shown  var TimeIntervalExamplePlugin = new function(){   var oSelf = this;   @@ -24,9 +28,8 @@
  });  }();   +// this code will be called each time the timesheet dialog is displayed  function doTimesheetMagic(){ - // put your jQuery magic here that manipulates the timesheet table - // keep in mind that this code will be called each time the timesheet dialog is displayed   var i = 0;   jQuery("#idTimesheetTable tbody tr").each( function(index)   { @@ -51,6 +54,7 @@
  i++;   });  } +// this lets our code run after the dialog is actually done coming down from the server  var nWaitCount = 0;  function waitForTimesheetReady(){   console.log('lookin for timesheet table...'); @@ -63,6 +67,8 @@
  doTimesheetMagic();   }  } +// this runs when the timesheet dialog is displayed. it can be changed / added to +// to also run when you click the next and previous arrows in the dialog  var oldShow = ClockPopup.show;  ClockPopup.show = function(){   console.log('Calling ClockPopup.show()...'); @@ -71,10 +77,10 @@
  waitForTimesheetReady();   return result;  }; - +// runs after the comment is fetched for an interval  function getCallback(data)  { - if (!data || data.substring(0,7) == 'failure') + if (data.substring(0,7) == 'failure')   {   alert('error');   } @@ -83,7 +89,7 @@
  $('form#TimeIntervalExamplePluginForm input[name=comment]').val(data);   }  } - +// runs after the comment is posted for an interval  function postCallback(data)  {   alert(data);