diff --git a/web_service/App_Code/moma-dblinq.cs b/web_service/App_Code/moma-dblinq.cs index 610dcd7..c20e300 100644 --- a/web_service/App_Code/moma-dblinq.cs +++ b/web_service/App_Code/moma-dblinq.cs @@ -1,4 +1,4 @@ -#region Auto-generated classes for nhibernate database on 2008-09-03 16:20:12Z +#region Auto-generated classes for nhibernate database on 2008-10-13 17:08:47Z // // ____ _ __ __ _ _ @@ -7,7 +7,7 @@ // | |_| | |_) | | | | __/ || (_| | | // |____/|_.__/|_| |_|\___|\__\__,_|_| // -// Auto-generated from nhibernate on 2008-09-03 16:20:12Z +// Auto-generated from nhibernate on 2008-10-13 17:08:47Z // Please visit http://linq.to/db for more information #endregion @@ -42,6 +42,8 @@ namespace MomaTool.Database.Linq public Table IssueType { get { return GetTable(); } } public Table MomADefinition { get { return GetTable(); } } public Table Report { get { return GetTable(); } } + public Table ReportComment { get { return GetTable(); } } + public Table ReportMetadata { get { return GetTable(); } } } @@ -249,21 +251,6 @@ namespace MomaTool.Database.Linq #region Parents - private System.Data.Linq.EntityRef issueType; - [Association(Storage = "issueType", ThisKey = "IssueTypeID", Name = "fk_issue_issue_type")] - [DebuggerNonUserCode] - public IssueType IssueType - { - get - { - return issueType.Entity; - } - set - { - issueType.Entity = value; - } - } - private System.Data.Linq.EntityRef report; [Association(Storage = "report", ThisKey = "ReportID", Name = "fk_issue_report")] [DebuggerNonUserCode] @@ -279,6 +266,21 @@ namespace MomaTool.Database.Linq } } + private System.Data.Linq.EntityRef issueType; + [Association(Storage = "issueType", ThisKey = "IssueTypeID", Name = "fk_issue_issue_type")] + [DebuggerNonUserCode] + public IssueType IssueType + { + get + { + return issueType.Entity; + } + set + { + issueType.Entity = value; + } + } + #endregion @@ -939,6 +941,28 @@ namespace MomaTool.Database.Linq } } + [Association(Storage = null, OtherKey = "ReportID", Name = "report_metadata_report_id_fkey")] + [DebuggerNonUserCode] + public EntityMSet ReportMetadata + { + get + { + // L212 - child data available only when part of query + return null; + } + } + + [Association(Storage = null, OtherKey = "ReportID", Name = "report_comment_report_id_fkey")] + [DebuggerNonUserCode] + public EntityMSet ReportComment + { + get + { + // L212 - child data available only when part of query + return null; + } + } + #endregion @@ -960,6 +984,339 @@ namespace MomaTool.Database.Linq } + #endregion + + } + + [Table(Name = "public.report_comment")] + public partial class ReportComment : INotifyPropertyChanged + { + #region INotifyPropertyChanged handling + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + #endregion + + #region string Comment + + private string comment; + [DebuggerNonUserCode] + [Column(Storage = "comment", Name = "comment", DbType = "text", CanBeNull = false, Expression = null)] + public string Comment + { + get + { + return comment; + } + set + { + if (value != comment) + { + comment = value; + OnPropertyChanged("Comment"); + } + } + } + + #endregion + + #region System.DateTime CommentDate + + private System.DateTime commentDate; + [DebuggerNonUserCode] + [Column(Storage = "commentDate", Name = "comment_date", DbType = "timestamp without time zone", CanBeNull = false, Expression = null)] + public System.DateTime CommentDate + { + get + { + return commentDate; + } + set + { + if (value != commentDate) + { + commentDate = value; + OnPropertyChanged("CommentDate"); + } + } + } + + #endregion + + #region string CommentER + + private string commentEr; + [DebuggerNonUserCode] + [Column(Storage = "commentEr", Name = "commenter", DbType = "character varying(255)", CanBeNull = false, Expression = null)] + public string CommentER + { + get + { + return commentEr; + } + set + { + if (value != commentEr) + { + commentEr = value; + OnPropertyChanged("CommentER"); + } + } + } + + #endregion + + #region bool EmailEd + + private bool emailEd; + [DebuggerNonUserCode] + [Column(Storage = "emailEd", Name = "emailed", DbType = "boolean", CanBeNull = false, Expression = null)] + public bool EmailEd + { + get + { + return emailEd; + } + set + { + if (value != emailEd) + { + emailEd = value; + OnPropertyChanged("EmailEd"); + } + } + } + + #endregion + + #region int ID + + [AutoGenId] + private int id; + [DebuggerNonUserCode] + [Column(Storage = "id", Name = "id", DbType = "integer(32,0)", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, Expression = "nextval('report_comment_id_seq')")] + public int ID + { + get + { + return id; + } + set + { + if (value != id) + { + id = value; + OnPropertyChanged("ID"); + } + } + } + + #endregion + + #region int ReportID + + private int reportID; + [DebuggerNonUserCode] + [Column(Storage = "reportID", Name = "report_id", DbType = "integer(32,0)", CanBeNull = false, Expression = null)] + public int ReportID + { + get + { + return reportID; + } + set + { + if (value != reportID) + { + reportID = value; + OnPropertyChanged("ReportID"); + } + } + } + + #endregion + + #region Parents + + private System.Data.Linq.EntityRef report; + [Association(Storage = "report", ThisKey = "ReportID", Name = "report_comment_report_id_fkey")] + [DebuggerNonUserCode] + public Report Report + { + get + { + return report.Entity; + } + set + { + report.Entity = value; + } + } + + + #endregion + + } + + [Table(Name = "public.report_metadata")] + public partial class ReportMetadata : INotifyPropertyChanged + { + #region INotifyPropertyChanged handling + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + #endregion + + #region string ApplicationName + + private string applicationName; + [DebuggerNonUserCode] + [Column(Storage = "applicationName", Name = "application_name", DbType = "character varying(200)", Expression = null)] + public string ApplicationName + { + get + { + return applicationName; + } + set + { + if (value != applicationName) + { + applicationName = value; + OnPropertyChanged("ApplicationName"); + } + } + } + + #endregion + + #region string ApplicationType + + private string applicationType; + [DebuggerNonUserCode] + [Column(Storage = "applicationType", Name = "application_type", DbType = "character varying(100)", Expression = null)] + public string ApplicationType + { + get + { + return applicationType; + } + set + { + if (value != applicationType) + { + applicationType = value; + OnPropertyChanged("ApplicationType"); + } + } + } + + #endregion + + #region int ID + + [AutoGenId] + private int id; + [DebuggerNonUserCode] + [Column(Storage = "id", Name = "id", DbType = "integer(32,0)", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, Expression = "nextval('report_metadata_id_seq')")] + public int ID + { + get + { + return id; + } + set + { + if (value != id) + { + id = value; + OnPropertyChanged("ID"); + } + } + } + + #endregion + + #region string Importance + + private string importance; + [DebuggerNonUserCode] + [Column(Storage = "importance", Name = "importance", DbType = "character varying(100)", Expression = null)] + public string Importance + { + get + { + return importance; + } + set + { + if (value != importance) + { + importance = value; + OnPropertyChanged("Importance"); + } + } + } + + #endregion + + #region int ReportID + + private int reportID; + [DebuggerNonUserCode] + [Column(Storage = "reportID", Name = "report_id", DbType = "integer(32,0)", CanBeNull = false, Expression = null)] + public int ReportID + { + get + { + return reportID; + } + set + { + if (value != reportID) + { + reportID = value; + OnPropertyChanged("ReportID"); + } + } + } + + #endregion + + #region Parents + + private System.Data.Linq.EntityRef report; + [Association(Storage = "report", ThisKey = "ReportID", Name = "report_metadata_report_id_fkey")] + [DebuggerNonUserCode] + public Report Report + { + get + { + return report.Entity; + } + set + { + report.Entity = value; + } + } + + #endregion } diff --git a/web_service/MoMA.css b/web_service/MoMA.css index 198ae2b..0f4d043 100644 --- a/web_service/MoMA.css +++ b/web_service/MoMA.css @@ -27,4 +27,21 @@ .content { -} \ No newline at end of file + /* Make this the context box for the main body content */ + position: relative; +} + +.reportview_metadata +{ + float: left; +} + +.reportview_comments +{ + float: right; +} + +.reportview_issues +{ + clear: both; +} diff --git a/web_service/Overview.aspx b/web_service/Overview.aspx index e301896..3d9cd64 100644 --- a/web_service/Overview.aspx +++ b/web_service/Overview.aspx @@ -7,9 +7,9 @@ This view is only available to logged-in users. - +
- + @@ -24,9 +24,9 @@ - +
- + @@ -35,9 +35,9 @@ - +
- +
diff --git a/web_service/Overview.aspx.cs b/web_service/Overview.aspx.cs index 7977b47..d7ee205 100644 --- a/web_service/Overview.aspx.cs +++ b/web_service/Overview.aspx.cs @@ -276,7 +276,7 @@ public partial class Overview : System.Web.UI.Page if (Page.User.Identity.IsAuthenticated) { // ... and we need to find it from inside the LoginView - GridView grid1 = (GridView)LoginView1.FindControl("GridView1"); + GridView grid1 = (GridView)LoginView1.FindControl("Latest20GridView"); string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString; NpgsqlConnection conn = new NpgsqlConnection(connstr); @@ -304,6 +304,16 @@ public partial class Overview : System.Web.UI.Page */ foreach (OverviewData ov in grid1_q) { + /* This works with MS LINQ, but not with DBLINQ - the ToArray() blows up */ +#if NAUGHT + var q = (from iss in db.Issue where iss.ReportID == ov.ID group iss by iss.IssueTypeID into g orderby g.Key select new { issue_type_id = g.Key, Count = g.Count() }).ToArray(); + + ov.Miss = q[miss_id].Count; + ov.Niex = q[niex_id].Count; + ov.Pinv = q[pinv_id].Count; + ov.Todo = q[todo_id].Count; +#endif + ov.Miss = (from issue in db.Issue where issue.ReportID == ov.ID && issue.IssueTypeID == miss_id select issue.ID).ToList().Count; ov.Niex = (from issue in db.Issue where issue.ReportID == ov.ID && issue.IssueTypeID == niex_id select issue.ID).ToList().Count; ov.Pinv = (from issue in db.Issue where issue.ReportID == ov.ID && issue.IssueTypeID == pinv_id select issue.ID).ToList().Count; @@ -314,7 +324,7 @@ public partial class Overview : System.Web.UI.Page grid1.DataSource = grid1_q; grid1.DataBind(); - GridView grid2 = (GridView)LoginView1.FindControl("GridView2"); + GridView grid2 = (GridView)LoginView1.FindControl("MostNeededGridView"); /* FIXME: figure out the LINQ version of the count(distinct)... */ var grid2_q = db.ExecuteQuery(@"select count(distinct(issue.report_id)) as Apps, issue.method_namespace as Namespace, issue.method_class as Class, issue.method_name as Method, issue_type.display_name as Type from issue, issue_type where issue_type.id = issue.issue_type_id group by method_namespace, method_class, method_name, display_name order by Apps desc limit 20;"); @@ -334,7 +344,7 @@ public partial class Overview : System.Web.UI.Page { if (Page.User.Identity.IsAuthenticated) { - ZedGraphWeb zg1 = (ZedGraphWeb)LoginView1.FindControl("ZedGraph1"); + ZedGraphWeb zg1 = (ZedGraphWeb)LoginView1.FindControl("IssuesPerAppGraph"); zg1.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(this.OnRenderGraph1); } } diff --git a/web_service/ReportView.aspx b/web_service/ReportView.aspx index 2681872..2e0e2af 100644 --- a/web_service/ReportView.aspx +++ b/web_service/ReportView.aspx @@ -6,13 +6,59 @@ This view is only available to logged-in users. - - - - - - - + +
+ + +
+
+
+
+ +
+ <%-- + + --%> +
+
+
+ + +
diff --git a/web_service/ReportView.aspx.cs b/web_service/ReportView.aspx.cs index b842312..f54d5a1 100644 --- a/web_service/ReportView.aspx.cs +++ b/web_service/ReportView.aspx.cs @@ -13,40 +13,307 @@ using System.Xml.Linq; using MomaTool.Database.Linq; using Npgsql; +using System.Data.Linq; +using System.Net.Mail; +using System.Text; public partial class ReportView : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { - // GridView1 only available to logged-in users + // Content only available to logged-in users if (Page.User.Identity.IsAuthenticated) { - string id_qs = Request.QueryString["ReportID"]; - int id; - - if (id_qs != null) + if (!Page.IsPostBack) { - id = int.Parse(id_qs); - } - else - { - id = 1; - } - - string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString; - NpgsqlConnection conn = new NpgsqlConnection(connstr); - MoMADB db = new MoMADB(conn); + int id = this.GetID(); + MoMADB db = this.OpenDB(); + Report report = this.GetReport(db, id); + MomADefinition def = this.GetMomaDefinition(db, report.MomADefinitionID); + ReportMetadata report_meta = this.GetMetadata(db, id); - // ... and we need to find it from inside the LoginView - GridView grid = (GridView)LoginView1.FindControl("GridView1"); - grid.DataSource = (from rep in db.Report - where rep.ID == id - select new { - ID = rep.ID, - ReportFileName = rep.ReportFilename, - ReporterName = rep.ReporterName - }); - grid.DataBind(); + // ... and we need to find it from inside the LoginView + Label report_id_label = (Label)LoginView1.FindControl("ReportIDLabel"); + report_id_label.Text = "Report " + report.ID; + + DropDownList importance_ddl = (DropDownList)LoginView1.FindControl("ImportanceDropDownList"); + importance_ddl.SelectedValue = report_meta.Importance; + + TextBox application_content_textbox = (TextBox)LoginView1.FindControl("ApplicationContent"); + application_content_textbox.Text = report_meta.ApplicationName; + + Label author_content_label = (Label)LoginView1.FindControl("AuthorContent"); + author_content_label.Text = report.ReporterName; + + Label email_content_label = (Label)LoginView1.FindControl("EmailContent"); + email_content_label.Text = report.ReporterEmail; + + Label website_content_label = (Label)LoginView1.FindControl("WebsiteContent"); + website_content_label.Text = report.ReporterHomepage; + + Label framework_version_content_label = (Label)LoginView1.FindControl("FrameworkVersionContent"); + // I get NullReferenceException here if I try to use report.MomADefinition.DisplayName + // with dblinq + framework_version_content_label.Text = def.DisplayName; + + TextBox application_type_content_textbox = (TextBox)LoginView1.FindControl("ApplicationTypeContent"); + application_type_content_textbox.Text = report_meta.ApplicationType; + + var issues_q = (from iss in db.Issue + from type in db.IssueType + where iss.ReportID == id && iss.IssueTypeID == type.ID + select new + { + Type = type.LookupName, + Namespace = iss.MethodNamesPace, + ClassName = iss.MethodClass, + Method = iss.MethodName + }); + GridView grid1 = (GridView)LoginView1.FindControl("IssuesGridView"); + grid1.DataSource = issues_q; + grid1.DataBind(); + + // Make the default text go away when the user clicks in the Comments box + // (but ensure that it won't blow away a half-entered comment!) + TextBox new_comment_textbox = (TextBox)LoginView1.FindControl("NewComment"); + new_comment_textbox.Text = "Type your comment here..."; + new_comment_textbox.Attributes.Add("onFocus", "if (this.value == 'Type your comment here...') this.value='';"); + + this.UpdateComments(db, id); + + if (!report.ReporterEmail.Contains("@")) + { + CheckBox send_comment_checkbox = (CheckBox)LoginView1.FindControl("SendCommentCheckBox"); + + /* Hide the email checkbox, as we can't email the submitter anyway... */ + send_comment_checkbox.Visible = false; + send_comment_checkbox.Checked = false; + } + } + } + } + + protected void UpdateButton_Click(object sender, EventArgs e) + { + if (Page.User.Identity.IsAuthenticated) + { + int id = this.GetID(); + MoMADB db = this.OpenDB(); + Report report = this.GetReport(db, id); + ReportMetadata report_meta = this.GetMetadata(db, id); + + DropDownList importance_ddl = (DropDownList)LoginView1.FindControl("ImportanceDropDownList"); + report_meta.Importance = importance_ddl.SelectedValue; + + TextBox application_content_textbox = (TextBox)LoginView1.FindControl("ApplicationContent"); + report_meta.ApplicationName = application_content_textbox.Text; + + TextBox application_type_content_textbox = (TextBox)LoginView1.FindControl("ApplicationTypeContent"); + report_meta.ApplicationType = application_type_content_textbox.Text; + + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + } + } + + Report GetReport(MoMADB db, int id) + { + Report report = (from rep in db.Report + where rep.ID == id + select rep).First(); + + return report; + } + + MomADefinition GetMomaDefinition(MoMADB db, int? def_id) + { + MomADefinition definition = (from def in db.MomADefinition + where def.ID == def_id + select def).First(); + + return definition; + } + + ReportMetadata GetMetadata(MoMADB db, int report_id) + { + // FirstOrDefault() doesn't work in dblinq, and this can fail if noone has created the + // metadata entry yet, so we have to fart about with the array instead + ReportMetadata report_meta; + var report_meta_q = (from rep_meta in db.ReportMetadata + where rep_meta.ReportID == report_id + select rep_meta).ToArray(); + if (report_meta_q.Length == 0) + { + // Need to create a default metadata entry + report_meta = new ReportMetadata(); + report_meta.ReportID = report_id; + report_meta.Importance = "Useful"; + report_meta.ApplicationName = ""; + report_meta.ApplicationType = ""; + + db.ReportMetadata.Add(report_meta); + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + } + else + { + report_meta = report_meta_q[0]; + } + + return report_meta; + } + + ReportComment[] GetComments(MoMADB db, int report_id) + { + ReportComment[] comment_q = (from comm in db.ReportComment + where comm.ReportID == report_id + orderby comm.CommentDate ascending + select comm).ToArray(); + + return comment_q; + } + + MoMADB OpenDB() + { + string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString; + NpgsqlConnection conn = new NpgsqlConnection(connstr); + MoMADB db = new MoMADB(conn); + + return db; + } + + int GetID() + { + string id_qs = Request.QueryString["ReportID"]; + int id; + + if (id_qs != null) + { + id = int.Parse(id_qs); + } + else + { + id = 1; + } + + return id; + } + + void UpdateComments(MoMADB db, int report_id) + { + ReportComment[] comments = this.GetComments(db, report_id); + TextBox comments_textbox = (TextBox)LoginView1.FindControl("Comments"); + comments_textbox.Text = ""; + + foreach (ReportComment comm in comments) + { + comments_textbox.Text += comm.Comment; + comments_textbox.Text += "\n"; + comments_textbox.Text += comm.CommentER; + comments_textbox.Text += " @ "; + comments_textbox.Text += comm.CommentDate; + comments_textbox.Text += "\n\n\n"; + } + + /* FIXME: figure out how to scroll to the end of the textbox */ + } + + protected void ApplicationContent_TextChanged(object sender, EventArgs e) + { + if (Page.User.Identity.IsAuthenticated) + { + int id = this.GetID(); + MoMADB db = this.OpenDB(); + Report report = this.GetReport(db, id); + ReportMetadata report_meta = this.GetMetadata(db, id); + + TextBox application_content_textbox = (TextBox)LoginView1.FindControl("ApplicationContent"); + report_meta.ApplicationName = application_content_textbox.Text; + + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + } + } + protected void ApplicationType_TextChanged(object sender, EventArgs e) + { + if (Page.User.Identity.IsAuthenticated) + { + int id = this.GetID(); + MoMADB db = this.OpenDB(); + Report report = this.GetReport(db, id); + ReportMetadata report_meta = this.GetMetadata(db, id); + + TextBox application_type_content_textbox = (TextBox)LoginView1.FindControl("ApplicationTypeContent"); + report_meta.ApplicationType = application_type_content_textbox.Text; + + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + } + } + protected void Importance_SelectedIndexChanged(object sender, EventArgs e) + { + if (Page.User.Identity.IsAuthenticated) + { + int id = this.GetID(); + MoMADB db = this.OpenDB(); + Report report = this.GetReport(db, id); + ReportMetadata report_meta = this.GetMetadata(db, id); + + DropDownList importance_ddl = (DropDownList)LoginView1.FindControl("ImportanceDropDownList"); + report_meta.Importance = importance_ddl.SelectedValue; + + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + } + } + protected void CommentButton_Click(object sender, EventArgs e) + { + if (Page.User.Identity.IsAuthenticated) + { + int id = this.GetID(); + MoMADB db = this.OpenDB(); + ReportComment comment = new ReportComment(); + CheckBox send_comment_checkbox = (CheckBox)LoginView1.FindControl("SendCommentCheckBox"); + TextBox newcomment_textbox = (TextBox)LoginView1.FindControl("NewComment"); + Label email_content_label = (Label)LoginView1.FindControl("EmailContent"); + + comment.Comment = newcomment_textbox.Text; + comment.ReportID = id; + comment.CommentER = Page.User.Identity.Name; + comment.CommentDate = DateTime.Now; + comment.EmailEd = send_comment_checkbox.Checked; + + db.ReportComment.Add(comment); + db.SubmitChanges(ConflictMode.FailOnFirstConflict); + + if (send_comment_checkbox.Checked) + { + /* Email the comment (we know the address is available, as the checkbox can't be + * checked otherwise) + */ + StringBuilder email_text = new StringBuilder(); + + email_text.AppendFormat("{0} added a comment to your MoMA report:\n\n", Page.User.Identity.Name); + email_text.AppendFormat("{0}", newcomment_textbox.Text); + email_text.AppendFormat("\n\nSee {0} for this report.\n", Page.Request.Url.ToString()); + + string from_addr = Membership.GetUser().Email; + + MailMessage mess = new MailMessage(from_addr, "dick@acm.org"/*email_content_label.Text*/); + mess.Subject = "New comment on MoMA report " + id.ToString(); + mess.Body = email_text.ToString(); + mess.IsBodyHtml = false; + + SmtpClient smtp = new SmtpClient(); + try + { + smtp.Send(mess); + } + catch (SmtpException ex) + { + /* Not sure what we can do here, except inform the commenter that the email didn't + * get sent + */ + } + } + + this.UpdateComments(db, id); + newcomment_textbox.Text = ""; } } }