зеркало из https://github.com/mono/moma-tool.git
Rewritten all database accessing pages using SqlDataSource and Npgsql.
Moved dblinq versions of pages out of the way. svn path=/trunk/moma-tool/; revision=116933
This commit is contained in:
Родитель
b0386953f0
Коммит
1cb0faf48b
|
@ -0,0 +1,7 @@
|
|||
<%@ Page Language="C#" MasterPageFile="~/MoMA.master" AutoEventWireup="true" CodeFile="APIReport.aspx.cs" Inherits="APIReport" Title="Untitled Page" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
|
||||
</asp:Content>
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="BodyContentPlaceHolder" Runat="Server">
|
||||
</asp:Content>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
public partial class APIReport : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using DbLinq.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
|
||||
public class MomaDataContext
|
||||
{
|
||||
private MoMADB _db;
|
||||
|
||||
public MomaDataContext()
|
||||
{
|
||||
_db = MoMADBSupport.OpenDB();
|
||||
}
|
||||
|
||||
public Table<Issue> Issue { get { return _db.GetTable<Issue>(); } }
|
||||
public Table<IssueType> IssueType { get { return _db.GetTable<IssueType>(); } }
|
||||
public Table<MomADefinition> MomADefinition { get { return _db.GetTable<MomADefinition>(); } }
|
||||
public Table<Report> Report { get { return _db.GetTable<Report>(); } }
|
||||
public Table<ReportComment> ReportComment { get { return _db.GetTable<ReportComment>(); } }
|
||||
public Table<ReportMetadata> ReportMetadata { get { return _db.GetTable<ReportMetadata>(); } }
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
using System.Data.Linq;
|
||||
using Npgsql;
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for MoMADBSupport
|
||||
/// </summary>
|
||||
public class MoMADBSupport
|
||||
{
|
||||
public MoMADBSupport()
|
||||
{
|
||||
}
|
||||
|
||||
public static Report GetReport(MoMADB db, int id)
|
||||
{
|
||||
Report report = (from rep in db.Report
|
||||
where rep.ID == id
|
||||
select rep).First();
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
public static MomADefinition GetMomaDefinition(MoMADB db, int? def_id)
|
||||
{
|
||||
MomADefinition definition = (from def in db.MomADefinition
|
||||
where def.ID == def_id
|
||||
select def).First();
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
public static 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.InsertOnSubmit(report_meta);
|
||||
db.SubmitChanges(ConflictMode.FailOnFirstConflict);
|
||||
}
|
||||
else
|
||||
{
|
||||
report_meta = report_meta_q[0];
|
||||
}
|
||||
|
||||
return report_meta;
|
||||
}
|
||||
|
||||
public static 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;
|
||||
}
|
||||
|
||||
public static MoMADB OpenDB()
|
||||
{
|
||||
string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString;
|
||||
NpgsqlConnection conn = new NpgsqlConnection(connstr);
|
||||
MoMADB db = new MoMADB(conn);
|
||||
|
||||
return db;
|
||||
}
|
||||
}
|
|
@ -33,8 +33,8 @@
|
|||
</asp:MenuItem>
|
||||
<asp:MenuItem NavigateUrl="~/ReportView.aspx" Text="Individual Report"
|
||||
Value="Individual Report"></asp:MenuItem>
|
||||
<asp:MenuItem Text="API Report" Value="API Report"></asp:MenuItem>
|
||||
<asp:MenuItem Text="Submissions Report" Value="Submissions Report">
|
||||
<asp:MenuItem Text="API Report" Value="API Report" NavigateUrl="~/APIReport.aspx"></asp:MenuItem>
|
||||
<asp:MenuItem Text="Submissions Report" Value="Submissions Report" NavigateUrl="~/Submissions.aspx">
|
||||
</asp:MenuItem>
|
||||
</Items>
|
||||
</asp:Menu>
|
||||
|
|
|
@ -9,32 +9,45 @@
|
|||
<LoggedInTemplate>
|
||||
<asp:Label ID="Latest20Label" runat="server" Text="Latest 20 Reports:"></asp:Label>
|
||||
<br />
|
||||
<asp:GridView ID="Latest20GridView" runat="server" AutoGenerateColumns="False">
|
||||
<asp:SqlDataSource ID="Latest20SqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>"
|
||||
SelectCommand="SELECT a.id, a.create_date, a.reporter_name, a.display_name, miss.miss, niex.niex, pinv.pinv, todo.todo, total.total FROM (SELECT rep.id, rep.create_date, rep.reporter_name, prof.display_name FROM report rep, moma_definition prof WHERE rep.moma_definition_id = prof.id) AS a, (SELECT report_id, COUNT(report_id) AS miss FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'MISS' GROUP BY report_id) AS miss, (SELECT report_id, COUNT(report_id) AS niex FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'NIEX' GROUP BY report_id) AS niex, (SELECT report_id, COUNT(report_id) AS pinv FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'PINV' GROUP BY report_id) AS pinv, (SELECT report_id, COUNT(report_id) AS todo FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'TODO' GROUP BY report_id) AS todo, (SELECT report_id, COUNT(report_id) AS total FROM issue GROUP BY report_id) AS total WHERE (a.id = miss.report_id) AND (a.id = niex.report_id) AND (a.id = pinv.report_id) AND (a.id = todo.report_id) AND (a.id = total.report_id) ORDER BY a.create_date DESC LIMIT 20;">
|
||||
</asp:SqlDataSource>
|
||||
<asp:GridView ID="Latest20GridView" runat="server" AutoGenerateColumns="False"
|
||||
DataSourceID="Latest20SqlDataSource">
|
||||
<Columns>
|
||||
<asp:HyperLinkField DataNavigateUrlFields="ID" DataNavigateUrlFormatString="~/ReportView.aspx?ReportID={0}"
|
||||
<asp:HyperLinkField DataNavigateUrlFields="id" DataNavigateUrlFormatString="~/ReportView.aspx?ReportID={0}"
|
||||
HeaderText="Details" Text="View" />
|
||||
<asp:BoundField DataField="CreateDate" HeaderText="Date" />
|
||||
<asp:BoundField DataField="ID" HeaderText="ID" />
|
||||
<asp:BoundField DataField="ReporterName" HeaderText="Name" />
|
||||
<asp:BoundField DataField="Profile" HeaderText="Profile" />
|
||||
<asp:BoundField DataField="Miss" HeaderText="MISS" />
|
||||
<asp:BoundField DataField="Niex" HeaderText="NIEX" />
|
||||
<asp:BoundField DataField="Pinv" HeaderText="PINV" />
|
||||
<asp:BoundField DataField="Todo" HeaderText="TODO" />
|
||||
<asp:BoundField DataField="Total" HeaderText="Total" />
|
||||
<asp:BoundField DataField="create_date" HeaderText="Date" />
|
||||
<asp:BoundField DataField="id" HeaderText="ID" />
|
||||
<asp:BoundField DataField="reporter_name" HeaderText="Name" />
|
||||
<asp:BoundField DataField="display_name" HeaderText="Profile" />
|
||||
<asp:BoundField DataField="miss" HeaderText="MISS" />
|
||||
<asp:BoundField DataField="niex" HeaderText="NIEX" />
|
||||
<asp:BoundField DataField="pinv" HeaderText="PINV" />
|
||||
<asp:BoundField DataField="todo" HeaderText="TODO" />
|
||||
<asp:BoundField DataField="total" HeaderText="Total" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
<asp:Label ID="MostNeededLabel" runat="server" Text="Most needed API:"></asp:Label>
|
||||
<br />
|
||||
<asp:GridView ID="MostNeededGridView" runat="server" AutoGenerateColumns="False">
|
||||
<%--
|
||||
<asp:SqlDataSource ID="MostNeededSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT COUNT(DISTINCT(issue.report_id)) AS Apps, issue.method_namespace, issue.method_class, issue.method_name, issue_type.display_name 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;">
|
||||
</asp:SqlDataSource>
|
||||
<asp:GridView ID="MostNeededGridView" runat="server" AutoGenerateColumns="False" DataSourceID="MostNeededSqlDataSource">
|
||||
<Columns>
|
||||
<asp:BoundField DataField="Namespace" HeaderText="Namespace" />
|
||||
<asp:BoundField DataField="Class" HeaderText="Class" />
|
||||
<asp:BoundField DataField="Method" HeaderText="Method" />
|
||||
<asp:BoundField DataField="Type" HeaderText="Type" />
|
||||
<asp:BoundField DataField="method_namespace" HeaderText="Namespace" />
|
||||
<asp:BoundField DataField="method_class" HeaderText="Class" />
|
||||
<asp:BoundField DataField="method_name" HeaderText="Method" />
|
||||
<asp:BoundField DataField="display_name" HeaderText="Type" />
|
||||
<asp:BoundField DataField="Apps" HeaderText="Apps" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
--%>
|
||||
<asp:SqlDataSource ID="IssuesPerAppSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT COUNT(issue.report_id) AS Count FROM issue GROUP BY issue.report_id;">
|
||||
</asp:SqlDataSource>
|
||||
<asp:Label ID="IssuesPerAppLabel" runat="server" Text="Issues per Application"></asp:Label>
|
||||
<br />
|
||||
<zgw:zedgraphweb ID="IssuesPerAppGraph" runat="server"></zgw:zedgraphweb>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
|
@ -12,326 +11,16 @@ using System.Web.UI.WebControls;
|
|||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
using Npgsql;
|
||||
using System.Drawing;
|
||||
using ZedGraph;
|
||||
using ZedGraph.Web;
|
||||
|
||||
public partial class Overview : System.Web.UI.Page
|
||||
{
|
||||
public class OverviewData
|
||||
{
|
||||
public OverviewData(int id, DateTime create_date, string reporter_name, string profile,
|
||||
int miss, int niex, int pinv, int todo, int total)
|
||||
{
|
||||
this._ID = id;
|
||||
this._CreateDate = create_date;
|
||||
this._ReporterName = reporter_name;
|
||||
this._Profile = profile;
|
||||
this._Miss = miss;
|
||||
this._Niex = niex;
|
||||
this._Pinv = pinv;
|
||||
this._Todo = todo;
|
||||
this._Total = total;
|
||||
}
|
||||
|
||||
/* For some barking reason, DataSource requires this to be a property not a field,
|
||||
* even though the exception states "A field or property with the name 'foo' was
|
||||
* not found on the selected data source.
|
||||
*/
|
||||
private int _ID;
|
||||
public int ID
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ID;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ID = value;
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime _CreateDate;
|
||||
public DateTime CreateDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _CreateDate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_CreateDate = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _ReporterName;
|
||||
public string ReporterName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ReporterName;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ReporterName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Profile;
|
||||
public string Profile
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Profile;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Profile = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Miss;
|
||||
public int Miss
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Miss;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Miss = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Niex;
|
||||
public int Niex
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Niex;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Niex = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Pinv;
|
||||
public int Pinv
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Pinv;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Pinv = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Todo;
|
||||
public int Todo
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Todo;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Todo = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Total;
|
||||
public int Total
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Total;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Total = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OverviewMostNeeded
|
||||
{
|
||||
public OverviewMostNeeded()
|
||||
{
|
||||
this._Namespace = "unknown namespace";
|
||||
this._Class = "unknown class";
|
||||
this._Method = "unknown method";
|
||||
this._Type = "unknown type";
|
||||
this._Apps = 0;
|
||||
}
|
||||
|
||||
public OverviewMostNeeded(string ns, string cls, string meth, string type, int apps)
|
||||
{
|
||||
this._Namespace = ns;
|
||||
this._Class = cls;
|
||||
this._Method = meth;
|
||||
this._Type = type;
|
||||
this._Apps = apps;
|
||||
}
|
||||
|
||||
private string _Namespace;
|
||||
public string Namespace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Namespace;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Namespace = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Class;
|
||||
public string Class
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Class;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Class = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Method;
|
||||
public string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Method;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Method = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Type;
|
||||
public string Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Type = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Apps;
|
||||
public int Apps
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Apps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Apps = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OverviewIssueCount
|
||||
{
|
||||
public OverviewIssueCount()
|
||||
{
|
||||
this._Count = 0;
|
||||
}
|
||||
|
||||
public OverviewIssueCount(int count)
|
||||
{
|
||||
this._Count = count;
|
||||
}
|
||||
|
||||
private int _Count;
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Count;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Count = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
// GridView1 only available to logged-in users
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
// ... and we need to find it from inside the LoginView
|
||||
GridView grid1 = (GridView)LoginView1.FindControl("Latest20GridView");
|
||||
|
||||
string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString;
|
||||
NpgsqlConnection conn = new NpgsqlConnection(connstr);
|
||||
MoMADB db = new MoMADB(conn);
|
||||
//NpgsqlEventLog.Level = LogLevel.Debug;
|
||||
//NpgsqlEventLog.LogName = "c:\\cygwin\\tmp\\npgsql-debug-logx";
|
||||
|
||||
int miss_id = (from type in db.IssueType where type.LookupName == "MISS" select type.ID).ToList()[0];
|
||||
int niex_id = (from type in db.IssueType where type.LookupName == "NIEX" select type.ID).ToList()[0];
|
||||
int pinv_id = (from type in db.IssueType where type.LookupName == "PINV" select type.ID).ToList()[0];
|
||||
int todo_id = (from type in db.IssueType where type.LookupName == "TODO" select type.ID).ToList()[0];
|
||||
|
||||
List<OverviewData> grid1_q = (from rep in db.Report
|
||||
from prof in db.MomADefinition
|
||||
where rep.MomADefinitionID == prof.ID
|
||||
orderby rep.CreateDate descending
|
||||
select new OverviewData(rep.ID, rep.CreateDate,
|
||||
rep.ReporterName, prof.DisplayName,
|
||||
0, 0, 0, 0, 0)
|
||||
).Take(20).ToList();
|
||||
|
||||
/* This ought to be incorporated into the select above, but I can't seem to make
|
||||
* that work with dblinq (not sure whether the problem is dblinq itself, npgsql, or just
|
||||
* me.)
|
||||
*/
|
||||
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;
|
||||
ov.Todo = (from issue in db.Issue where issue.ReportID == ov.ID && issue.IssueTypeID == todo_id select issue.ID).ToList().Count;
|
||||
ov.Total = ov.Miss + ov.Niex + ov.Pinv + ov.Todo;
|
||||
}
|
||||
|
||||
grid1.DataSource = grid1_q;
|
||||
grid1.DataBind();
|
||||
|
||||
GridView grid2 = (GridView)LoginView1.FindControl("MostNeededGridView");
|
||||
|
||||
/* FIXME: figure out the LINQ version of the count(distinct)... */
|
||||
var grid2_q = db.ExecuteQuery<OverviewMostNeeded>(@"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;");
|
||||
|
||||
grid2.DataSource = grid2_q;
|
||||
grid2.DataBind();
|
||||
}
|
||||
//Npgsql.NpgsqlEventLog.Level = Npgsql.LogLevel.Debug;
|
||||
//Npgsql.NpgsqlEventLog.LogName = "c:\\cygwin\\tmp\\npgsql-debug-log";
|
||||
}
|
||||
|
||||
protected override void OnInit(EventArgs e)
|
||||
|
@ -345,42 +34,47 @@ public partial class Overview : System.Web.UI.Page
|
|||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
ZedGraphWeb zg1 = (ZedGraphWeb)LoginView1.FindControl("IssuesPerAppGraph");
|
||||
zg1.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(this.OnRenderGraph1);
|
||||
zg1.RenderGraph += new ZedGraphWebControlEventHandler(this.OnRenderGraph1);
|
||||
}
|
||||
}
|
||||
|
||||
DataView graph_data;
|
||||
|
||||
private void OnRenderGraph1(ZedGraphWeb zgw, Graphics g, MasterPane masterPane)
|
||||
{
|
||||
string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString;
|
||||
NpgsqlConnection conn = new NpgsqlConnection(connstr);
|
||||
MoMADB db = new MoMADB(conn);
|
||||
var issue_count_q = db.ExecuteQuery<OverviewIssueCount>(@"select count(issue.report_id) as Count from issue group by issue.report_id;").ToList();
|
||||
|
||||
GraphPane myPane = masterPane[0];
|
||||
PieItem segment1 = myPane.AddPieSlice(0, Color.FromArgb(0xf5, 0xeb, 0xcb), Color.White, 45f, 0, "1-5");
|
||||
PieItem segment2 = myPane.AddPieSlice(0, Color.FromArgb(0xec, 0xc5, 0x6b), Color.White, 45f, 0, "6-25");
|
||||
PieItem segment3 = myPane.AddPieSlice(0, Color.FromArgb(0xe2, 0x9f, 0x27), Color.White, 45f, 0, "26+");
|
||||
|
||||
segment1.LabelDetail.FontSpec.Size = 20f;
|
||||
segment2.LabelDetail.FontSpec.Size = 20f;
|
||||
segment3.LabelDetail.FontSpec.Size = 20f;
|
||||
|
||||
foreach (OverviewIssueCount count in issue_count_q)
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
if (count.Count < 6)
|
||||
{
|
||||
segment1.Value++;
|
||||
}
|
||||
else if (count.Count < 26)
|
||||
{
|
||||
segment2.Value++;
|
||||
}
|
||||
else
|
||||
{
|
||||
segment3.Value++;
|
||||
}
|
||||
}
|
||||
SqlDataSource ds = (SqlDataSource)LoginView1.FindControl("IssuesPerAppSqlDataSource");
|
||||
graph_data = (DataView)ds.Select(DataSourceSelectArguments.Empty);
|
||||
|
||||
masterPane.AxisChange(g);
|
||||
GraphPane myPane = masterPane[0];
|
||||
PieItem segment1 = myPane.AddPieSlice(0, Color.FromArgb(0xf5, 0xeb, 0xcb), Color.White, 45f, 0, "1-5");
|
||||
PieItem segment2 = myPane.AddPieSlice(0, Color.FromArgb(0xec, 0xc5, 0x6b), Color.White, 45f, 0, "6-25");
|
||||
PieItem segment3 = myPane.AddPieSlice(0, Color.FromArgb(0xe2, 0x9f, 0x27), Color.White, 45f, 0, "26+");
|
||||
|
||||
segment1.LabelDetail.FontSpec.Size = 20f;
|
||||
segment2.LabelDetail.FontSpec.Size = 20f;
|
||||
segment3.LabelDetail.FontSpec.Size = 20f;
|
||||
|
||||
for (int i = 0; i < graph_data.Count; i++)
|
||||
{
|
||||
Int64 view_count = (Int64)graph_data[i]["Count"];
|
||||
|
||||
if (view_count < 6)
|
||||
{
|
||||
segment1.Value++;
|
||||
}
|
||||
else if (view_count < 26)
|
||||
{
|
||||
segment2.Value++;
|
||||
}
|
||||
else
|
||||
{
|
||||
segment3.Value++;
|
||||
}
|
||||
}
|
||||
|
||||
masterPane.AxisChange(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
using Npgsql;
|
||||
using System.Drawing;
|
||||
using ZedGraph;
|
||||
using ZedGraph.Web;
|
||||
|
||||
public partial class Overview : System.Web.UI.Page
|
||||
{
|
||||
public class OverviewData
|
||||
{
|
||||
public OverviewData(int id, DateTime create_date, string reporter_name, string profile,
|
||||
int miss, int niex, int pinv, int todo, int total)
|
||||
{
|
||||
this._ID = id;
|
||||
this._CreateDate = create_date;
|
||||
this._ReporterName = reporter_name;
|
||||
this._Profile = profile;
|
||||
this._Miss = miss;
|
||||
this._Niex = niex;
|
||||
this._Pinv = pinv;
|
||||
this._Todo = todo;
|
||||
this._Total = total;
|
||||
}
|
||||
|
||||
/* For some barking reason, DataSource requires this to be a property not a field,
|
||||
* even though the exception states "A field or property with the name 'foo' was
|
||||
* not found on the selected data source.
|
||||
*/
|
||||
private int _ID;
|
||||
public int ID
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ID;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ID = value;
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime _CreateDate;
|
||||
public DateTime CreateDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _CreateDate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_CreateDate = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _ReporterName;
|
||||
public string ReporterName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ReporterName;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ReporterName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Profile;
|
||||
public string Profile
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Profile;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Profile = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Miss;
|
||||
public int Miss
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Miss;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Miss = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Niex;
|
||||
public int Niex
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Niex;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Niex = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Pinv;
|
||||
public int Pinv
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Pinv;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Pinv = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Todo;
|
||||
public int Todo
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Todo;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Todo = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Total;
|
||||
public int Total
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Total;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Total = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OverviewMostNeeded
|
||||
{
|
||||
public OverviewMostNeeded()
|
||||
{
|
||||
this._Namespace = "unknown namespace";
|
||||
this._Class = "unknown class";
|
||||
this._Method = "unknown method";
|
||||
this._Type = "unknown type";
|
||||
this._Apps = 0;
|
||||
}
|
||||
|
||||
public OverviewMostNeeded(string ns, string cls, string meth, string type, int apps)
|
||||
{
|
||||
this._Namespace = ns;
|
||||
this._Class = cls;
|
||||
this._Method = meth;
|
||||
this._Type = type;
|
||||
this._Apps = apps;
|
||||
}
|
||||
|
||||
private string _Namespace;
|
||||
public string Namespace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Namespace;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Namespace = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Class;
|
||||
public string Class
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Class;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Class = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Method;
|
||||
public string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Method;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Method = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string _Type;
|
||||
public string Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Type;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Type = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _Apps;
|
||||
public int Apps
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Apps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Apps = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OverviewIssueCount
|
||||
{
|
||||
public OverviewIssueCount()
|
||||
{
|
||||
this._Count = 0;
|
||||
}
|
||||
|
||||
public OverviewIssueCount(int count)
|
||||
{
|
||||
this._Count = count;
|
||||
}
|
||||
|
||||
private int _Count;
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Count;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Count = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
// GridView1 only available to logged-in users
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
// ... and we need to find it from inside the LoginView
|
||||
GridView grid1 = (GridView)LoginView1.FindControl("Latest20GridView");
|
||||
|
||||
string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString;
|
||||
NpgsqlConnection conn = new NpgsqlConnection(connstr);
|
||||
MoMADB db = new MoMADB(conn);
|
||||
//NpgsqlEventLog.Level = LogLevel.Debug;
|
||||
//NpgsqlEventLog.LogName = "c:\\cygwin\\tmp\\npgsql-debug-logx";
|
||||
|
||||
int miss_id = (from type in db.IssueType where type.LookupName == "MISS" select type.ID).ToList()[0];
|
||||
int niex_id = (from type in db.IssueType where type.LookupName == "NIEX" select type.ID).ToList()[0];
|
||||
int pinv_id = (from type in db.IssueType where type.LookupName == "PINV" select type.ID).ToList()[0];
|
||||
int todo_id = (from type in db.IssueType where type.LookupName == "TODO" select type.ID).ToList()[0];
|
||||
|
||||
List<OverviewData> grid1_q = (from rep in db.Report
|
||||
from prof in db.MomADefinition
|
||||
where rep.MomADefinitionID == prof.ID
|
||||
orderby rep.CreateDate descending
|
||||
select new OverviewData(rep.ID, rep.CreateDate,
|
||||
rep.ReporterName, prof.DisplayName,
|
||||
0, 0, 0, 0, 0)
|
||||
).Take(20).ToList();
|
||||
|
||||
/* This ought to be incorporated into the select above, but I can't seem to make
|
||||
* that work with dblinq (not sure whether the problem is dblinq itself, npgsql, or just
|
||||
* me.)
|
||||
*/
|
||||
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;
|
||||
ov.Todo = (from issue in db.Issue where issue.ReportID == ov.ID && issue.IssueTypeID == todo_id select issue.ID).ToList().Count;
|
||||
ov.Total = ov.Miss + ov.Niex + ov.Pinv + ov.Todo;
|
||||
}
|
||||
|
||||
grid1.DataSource = grid1_q;
|
||||
grid1.DataBind();
|
||||
|
||||
GridView grid2 = (GridView)LoginView1.FindControl("MostNeededGridView");
|
||||
|
||||
/* FIXME: figure out the LINQ version of the count(distinct)... */
|
||||
var grid2_q = db.ExecuteQuery<OverviewMostNeeded>(@"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;");
|
||||
|
||||
grid2.DataSource = grid2_q;
|
||||
grid2.DataBind();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInit(EventArgs e)
|
||||
{
|
||||
InitializeComponent();
|
||||
base.OnInit(e);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
ZedGraphWeb zg1 = (ZedGraphWeb)LoginView1.FindControl("IssuesPerAppGraph");
|
||||
zg1.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(this.OnRenderGraph1);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRenderGraph1(ZedGraphWeb zgw, Graphics g, MasterPane masterPane)
|
||||
{
|
||||
string connstr = ConfigurationManager.ConnectionStrings["MomaDB"].ConnectionString;
|
||||
NpgsqlConnection conn = new NpgsqlConnection(connstr);
|
||||
MoMADB db = new MoMADB(conn);
|
||||
var issue_count_q = db.ExecuteQuery<OverviewIssueCount>(@"select count(issue.report_id) as Count from issue group by issue.report_id;").ToList();
|
||||
|
||||
GraphPane myPane = masterPane[0];
|
||||
PieItem segment1 = myPane.AddPieSlice(0, Color.FromArgb(0xf5, 0xeb, 0xcb), Color.White, 45f, 0, "1-5");
|
||||
PieItem segment2 = myPane.AddPieSlice(0, Color.FromArgb(0xec, 0xc5, 0x6b), Color.White, 45f, 0, "6-25");
|
||||
PieItem segment3 = myPane.AddPieSlice(0, Color.FromArgb(0xe2, 0x9f, 0x27), Color.White, 45f, 0, "26+");
|
||||
|
||||
segment1.LabelDetail.FontSpec.Size = 20f;
|
||||
segment2.LabelDetail.FontSpec.Size = 20f;
|
||||
segment3.LabelDetail.FontSpec.Size = 20f;
|
||||
|
||||
foreach (OverviewIssueCount count in issue_count_q)
|
||||
{
|
||||
if (count.Count < 6)
|
||||
{
|
||||
segment1.Value++;
|
||||
}
|
||||
else if (count.Count < 26)
|
||||
{
|
||||
segment2.Value++;
|
||||
}
|
||||
else
|
||||
{
|
||||
segment3.Value++;
|
||||
}
|
||||
}
|
||||
|
||||
masterPane.AxisChange(g);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<%@ Page Language="C#" MasterPageFile="~/MoMA.master" AutoEventWireup="true" CodeFile="Overview.aspx.cs" Inherits="Overview" Title="MoMA Studio - Overview" %>
|
||||
<%@ Register TagPrefix="zgw" Namespace="ZedGraph.Web" Assembly="ZedGraph.Web" %>
|
||||
|
||||
<asp:Content ID="BodyContent" ContentPlaceHolderID="BodyContentPlaceHolder" runat="server">
|
||||
<asp:LoginView ID="LoginView1" runat="server">
|
||||
<AnonymousTemplate>
|
||||
This view is only available to logged-in users.
|
||||
</AnonymousTemplate>
|
||||
<LoggedInTemplate>
|
||||
<asp:Label ID="Latest20Label" runat="server" Text="Latest 20 Reports:"></asp:Label>
|
||||
<br />
|
||||
<asp:GridView ID="Latest20GridView" runat="server" AutoGenerateColumns="False">
|
||||
<Columns>
|
||||
<asp:HyperLinkField DataNavigateUrlFields="ID" DataNavigateUrlFormatString="~/ReportView.aspx?ReportID={0}"
|
||||
HeaderText="Details" Text="View" />
|
||||
<asp:BoundField DataField="CreateDate" HeaderText="Date" />
|
||||
<asp:BoundField DataField="ID" HeaderText="ID" />
|
||||
<asp:BoundField DataField="ReporterName" HeaderText="Name" />
|
||||
<asp:BoundField DataField="Profile" HeaderText="Profile" />
|
||||
<asp:BoundField DataField="Miss" HeaderText="MISS" />
|
||||
<asp:BoundField DataField="Niex" HeaderText="NIEX" />
|
||||
<asp:BoundField DataField="Pinv" HeaderText="PINV" />
|
||||
<asp:BoundField DataField="Todo" HeaderText="TODO" />
|
||||
<asp:BoundField DataField="Total" HeaderText="Total" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
<asp:Label ID="MostNeededLabel" runat="server" Text="Most needed API:"></asp:Label>
|
||||
<br />
|
||||
<asp:GridView ID="MostNeededGridView" runat="server" AutoGenerateColumns="False">
|
||||
<Columns>
|
||||
<asp:BoundField DataField="Namespace" HeaderText="Namespace" />
|
||||
<asp:BoundField DataField="Class" HeaderText="Class" />
|
||||
<asp:BoundField DataField="Method" HeaderText="Method" />
|
||||
<asp:BoundField DataField="Type" HeaderText="Type" />
|
||||
<asp:BoundField DataField="Apps" HeaderText="Apps" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
<asp:Label ID="IssuesPerAppLabel" runat="server" Text="Issues per Application"></asp:Label>
|
||||
<br />
|
||||
<zgw:zedgraphweb ID="IssuesPerAppGraph" runat="server"></zgw:zedgraphweb>
|
||||
</LoggedInTemplate>
|
||||
</asp:LoginView>
|
||||
</asp:Content>
|
|
@ -9,55 +9,121 @@
|
|||
<div class="reportview_metadata">
|
||||
<asp:UpdatePanel ID="ReportMetaDataUpdatePanel" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<asp:Label ID="ReportIDLabel" runat="server" Text=""></asp:Label>
|
||||
<br />
|
||||
<asp:Label ID="ApplicationLabel" runat="server" Text="Application:"></asp:Label>
|
||||
<asp:TextBox ID="ApplicationContent" runat="server" AutoPostBack="True"
|
||||
ontextchanged="ApplicationContent_TextChanged"></asp:TextBox><br />
|
||||
<asp:Label ID="ImportanceLabel" runat="server" Text="Importance:"></asp:Label>
|
||||
<asp:DropDownList ID="ImportanceDropDownList" runat="server"
|
||||
AutoPostBack="True"
|
||||
onselectedindexchanged="Importance_SelectedIndexChanged">
|
||||
<asp:ListItem>Important</asp:ListItem>
|
||||
<asp:ListItem>Useful</asp:ListItem>
|
||||
<asp:ListItem>Not useful</asp:ListItem>
|
||||
</asp:DropDownList>
|
||||
<br />
|
||||
<asp:Label ID="AuthorLabel" runat="server" Text="Author:"></asp:Label>
|
||||
<asp:Label ID="AuthorContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="EmailLabel" runat="server" Text="Email:"></asp:Label>
|
||||
<asp:Label ID="EmailContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="WebsiteLabel" runat="server" Text="Website:"></asp:Label>
|
||||
<asp:Label ID="WebsiteContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="FrameworkVersionLabel" runat="server" Text="Framework Version:"></asp:Label>
|
||||
<asp:Label ID="FrameworkVersionContent" runat="server"></asp:Label><br />
|
||||
<asp:Label ID="ApplicationTypeLabel" runat="server" Text="Application Type:"></asp:Label>
|
||||
<asp:TextBox ID="ApplicationTypeContent" runat="server" AutoPostBack="True"
|
||||
ontextchanged="ApplicationType_TextChanged"></asp:TextBox><br />
|
||||
<asp:Button ID="UpdateButton" runat="server" Text="Update" OnClick="UpdateButton_Click" />
|
||||
<asp:SqlDataSource ID="MetadataSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT id FROM report_metadata WHERE report_id = @id;"
|
||||
InsertCommand="INSERT INTO report_metadata (report_id, importance) VALUES (@id, 'Useful');">
|
||||
<SelectParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID"
|
||||
Type="Int32" />
|
||||
</SelectParameters>
|
||||
<InsertParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID" />
|
||||
<asp:FormParameter Name="comment" FormField="NewComment" />
|
||||
<%-- commenter and comment_date set in CommentButton_Click () --%>
|
||||
<asp:Parameter Name="commenter" DefaultValue="" />
|
||||
<asp:Parameter Name="comment_date" DefaultValue="" />
|
||||
<asp:FormParameter Name="emailed" FormField="SendCommentCheckBox" Type="Boolean" />
|
||||
</InsertParameters>
|
||||
</asp:SqlDataSource>
|
||||
<asp:SqlDataSource ID="ReportWithMetadataSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT rep.id, meta.importance, meta.application_name, rep.reporter_name, rep.reporter_email, rep.reporter_homepage, def.display_name, meta.application_type FROM report rep, report_metadata meta, moma_definition def WHERE meta.report_id = rep.id AND rep.moma_definition_id = def.id AND rep.id = @id;"
|
||||
UpdateCommand="UPDATE report_metadata SET application_name = @application_name, importance = @importance, application_type = @application_type WHERE report_id = @id;">
|
||||
<SelectParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID"
|
||||
Type="Int32" />
|
||||
</SelectParameters>
|
||||
<UpdateParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID"
|
||||
Type="Int32" />
|
||||
<asp:Parameter Name="application_name" Type="String" />
|
||||
<asp:Parameter Name="importance" Type="String" />
|
||||
<asp:Parameter Name="application_type" Type="String" />
|
||||
</UpdateParameters>
|
||||
</asp:SqlDataSource>
|
||||
<asp:DetailsView ID="ReportDetailsView" runat="server" AutoGenerateRows="False"
|
||||
DataSourceID="ReportWithMetadataSqlDataSource"
|
||||
ondatabound="ReportDetailsView_DataBound">
|
||||
<Fields>
|
||||
<asp:BoundField DataField="id" HeaderText="Report ID" ReadOnly="True" />
|
||||
<asp:BoundField DataField="application_name" HeaderText="Application" />
|
||||
<asp:TemplateField HeaderText="Importance">
|
||||
<EditItemTemplate>
|
||||
<asp:DropDownList ID="ImportanceDropDownList" runat="server" SelectedValue="<%# Bind('importance') %>">
|
||||
<asp:ListItem>Important</asp:ListItem>
|
||||
<asp:ListItem>Useful</asp:ListItem>
|
||||
<asp:ListItem>Not useful</asp:ListItem>
|
||||
</asp:DropDownList>
|
||||
</EditItemTemplate>
|
||||
<ItemTemplate>
|
||||
<asp:Label ID="ImportanceLabel" runat="server" Text='<%# Bind("importance") %>'></asp:Label>
|
||||
</ItemTemplate>
|
||||
</asp:TemplateField>
|
||||
<asp:BoundField DataField="reporter_name" HeaderText="Author" ReadOnly="True" />
|
||||
<asp:TemplateField HeaderText="Email">
|
||||
<ItemTemplate>
|
||||
<asp:Label ID="EmailContent" runat="server" Text='<%# Bind("reporter_email") %>'></asp:Label>
|
||||
</ItemTemplate>
|
||||
</asp:TemplateField>
|
||||
<asp:BoundField DataField="reporter_homepage" HeaderText="Website"
|
||||
ReadOnly="True" />
|
||||
<asp:BoundField DataField="display_name" HeaderText="Framework Version"
|
||||
ReadOnly="True" />
|
||||
<asp:BoundField DataField="application_type" HeaderText="Application Type" />
|
||||
<asp:CommandField ShowEditButton="True" />
|
||||
</Fields>
|
||||
</asp:DetailsView>
|
||||
</ContentTemplate>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
<div class="reportview_comments">
|
||||
<asp:UpdatePanel ID="CommentUpdatePanel" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<asp:Label ID="CommentsLabel" runat="server" Text="Comments:"></asp:Label><br />
|
||||
<asp:TextBox ID="Comments" runat="server" ReadOnly="True" TextMode="MultiLine"
|
||||
Columns="40" Rows="12"></asp:TextBox><br />
|
||||
<asp:TextBox ID="NewComment" runat="server" Rows="6" TextMode="MultiLine"
|
||||
Columns="40"></asp:TextBox><br />
|
||||
<asp:SqlDataSource ID="CommentsSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT * FROM report_comment WHERE report_id = @id ORDER BY comment_date ASC;"
|
||||
InsertCommand="INSERT INTO report_comment (report_id, comment, commenter, comment_date, emailed) VALUES (@id, @comment, @commenter, @comment_date, @emailed);">
|
||||
<SelectParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID"
|
||||
Type="Int32" />
|
||||
</SelectParameters>
|
||||
<InsertParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID" />
|
||||
<asp:FormParameter Name="comment" FormField="NewComment" />
|
||||
<%-- commenter and comment_date set in CommentButton_Click () --%>
|
||||
<asp:Parameter Name="commenter" DefaultValue="" />
|
||||
<asp:Parameter Name="comment_date" DefaultValue="" />
|
||||
<asp:FormParameter Name="emailed" FormField="SendCommentCheckBox" Type="Boolean" />
|
||||
</InsertParameters>
|
||||
</asp:SqlDataSource>
|
||||
<asp:Label ID="CommentsLabel" runat="server" Text="Comments:"></asp:Label><br />
|
||||
<asp:TextBox ID="Comments" runat="server" ReadOnly="True" TextMode="MultiLine" Columns="40"
|
||||
Rows="12"></asp:TextBox><br />
|
||||
<asp:TextBox ID="NewComment" runat="server" Rows="6" TextMode="MultiLine" Columns="40"></asp:TextBox><br />
|
||||
<asp:CheckBox ID="SendCommentCheckBox" runat="server" Checked="True" Text="Send comment to submitter" /><br />
|
||||
<asp:Button ID="CommentButton" runat="server" Text="Add Comment"
|
||||
onclick="CommentButton_Click" />
|
||||
<asp:Button ID="CommentButton" runat="server" Text="Add Comment" OnClick="CommentButton_Click" />
|
||||
</ContentTemplate>
|
||||
<%--<Triggers>
|
||||
<asp:AsyncPostBackTrigger ControlID="CommentButton" EventName="Click" />
|
||||
</Triggers>--%>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
<div class="reportview_issues">
|
||||
<asp:GridView ID="IssuesGridView" runat="server">
|
||||
</asp:GridView>
|
||||
<asp:UpdatePanel ID="IssuesUpdatePanel" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<asp:SqlDataSource ID="IssuesSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT type.lookup_name, iss.method_namespace, iss.method_class, iss.method_name FROM issue_type type, issue iss WHERE iss.report_id = @id AND iss.issue_type_id = type.id;">
|
||||
<SelectParameters>
|
||||
<asp:QueryStringParameter DefaultValue="1" Name="id" QueryStringField="ReportID"
|
||||
Type="Int32" />
|
||||
</SelectParameters>
|
||||
</asp:SqlDataSource>
|
||||
<asp:GridView ID="IssuesGridView" runat="server" AllowPaging="True" AllowSorting="True"
|
||||
AutoGenerateColumns="False" DataSourceID="IssuesSqlDataSource">
|
||||
<Columns>
|
||||
<asp:BoundField DataField="lookup_name" HeaderText="Type" SortExpression="lookup_name" />
|
||||
<asp:BoundField DataField="method_namespace" HeaderText="Namespace" SortExpression="method_namespace" />
|
||||
<asp:BoundField DataField="method_class" HeaderText="Classname" SortExpression="method_class" />
|
||||
<asp:BoundField DataField="method_name" HeaderText="Method" SortExpression="method_name" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
</ContentTemplate>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
</LoggedInTemplate>
|
||||
</asp:LoginView>
|
||||
|
|
|
@ -11,9 +11,6 @@ using System.Web.UI.WebControls;
|
|||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
using Npgsql;
|
||||
using System.Data.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
|
||||
|
@ -21,163 +18,57 @@ public partial class ReportView : System.Web.UI.Page
|
|||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
//Npgsql.NpgsqlEventLog.Level = Npgsql.LogLevel.Debug;
|
||||
//Npgsql.NpgsqlEventLog.LogName = "c:\\cygwin\\tmp\\npgsql-debug-log";
|
||||
|
||||
// Content only available to logged-in users
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
SqlDataSource ds = (SqlDataSource)LoginView1.FindControl("MetadataSqlDataSource");
|
||||
DataView metadata_data = (DataView)ds.Select(DataSourceSelectArguments.Empty);
|
||||
|
||||
if (metadata_data.Count == 0)
|
||||
{
|
||||
/* Need to create this metadata entry */
|
||||
int id = this.GetID();
|
||||
ds.InsertParameters["id"].DefaultValue = id.ToString();
|
||||
ds.Insert();
|
||||
}
|
||||
|
||||
if (!Page.IsPostBack)
|
||||
{
|
||||
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
|
||||
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;
|
||||
}
|
||||
this.UpdateComments();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateButton_Click(object sender, EventArgs e)
|
||||
void UpdateComments()
|
||||
{
|
||||
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);
|
||||
SqlDataSource ds = (SqlDataSource)LoginView1.FindControl("CommentsSqlDataSource");
|
||||
DataView comments_data = (DataView)ds.Select(DataSourceSelectArguments.Empty);
|
||||
TextBox comments_textbox = (TextBox)LoginView1.FindControl("Comments");
|
||||
comments_textbox.Text = "";
|
||||
|
||||
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];
|
||||
for (int i = 0; i < comments_data.Count; i++)
|
||||
{
|
||||
comments_textbox.Text += comments_data[i]["comment"];
|
||||
comments_textbox.Text += "\n";
|
||||
comments_textbox.Text += comments_data[i]["commenter"];
|
||||
comments_textbox.Text += " @ ";
|
||||
comments_textbox.Text += comments_data[i]["comment_date"];
|
||||
comments_textbox.Text += "\n\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/* FIXME: figure out how to scroll to the end of the textbox */
|
||||
}
|
||||
|
||||
int GetID()
|
||||
|
@ -197,89 +88,22 @@ public partial class ReportView : System.Web.UI.Page
|
|||
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);
|
||||
SqlDataSource ds = (SqlDataSource)LoginView1.FindControl("CommentsSqlDataSource");
|
||||
ds.InsertParameters["id"].DefaultValue = id.ToString();
|
||||
ds.InsertParameters["comment"].DefaultValue = newcomment_textbox.Text;
|
||||
ds.InsertParameters["commenter"].DefaultValue = Page.User.Identity.Name;
|
||||
ds.InsertParameters["comment_date"].DefaultValue = DateTime.Now.ToString("o"); // ISO format
|
||||
ds.InsertParameters["emailed"].DefaultValue = send_comment_checkbox.Checked.ToString();
|
||||
ds.Insert();
|
||||
|
||||
if (send_comment_checkbox.Checked)
|
||||
{
|
||||
|
@ -294,26 +118,57 @@ public partial class ReportView : System.Web.UI.Page
|
|||
|
||||
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);
|
||||
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
|
||||
*/
|
||||
}
|
||||
}
|
||||
catch (SmtpException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
/* Not sure what we can do here, except inform the commenter that the email didn't
|
||||
* get sent
|
||||
/* MailMessage.ctor() can throw if the email address are malformed - again, not
|
||||
* sure what can be done here
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
this.UpdateComments(db, id);
|
||||
/* This reads the entire set of comments - someone else might have added a comment to
|
||||
* this report simultaneously
|
||||
*/
|
||||
this.UpdateComments();
|
||||
newcomment_textbox.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void ReportDetailsView_DataBound(object sender, EventArgs e)
|
||||
{
|
||||
DetailsView dv = (DetailsView)sender;
|
||||
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
Label email_content_label = (Label)dv.FindControl("EmailContent");
|
||||
|
||||
if (!email_content_label.Text.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using MomaTool.Database.Linq;
|
||||
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)
|
||||
{
|
||||
// Content only available to logged-in users
|
||||
if (Page.User.Identity.IsAuthenticated)
|
||||
{
|
||||
if (!Page.IsPostBack)
|
||||
{
|
||||
int id = this.GetID();
|
||||
MoMADB db = MoMADBSupport.OpenDB();
|
||||
Report report = MoMADBSupport.GetReport(db, id);
|
||||
MomADefinition def = MoMADBSupport.GetMomaDefinition(db, report.MomADefinitionID);
|
||||
ReportMetadata report_meta = MoMADBSupport.GetMetadata(db, id);
|
||||
|
||||
// ... 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;
|
||||
|
||||
/* Make this filterable to just show issues that still exist in svn */
|
||||
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 = MoMADBSupport.OpenDB();
|
||||
Report report = MoMADBSupport.GetReport(db, id);
|
||||
ReportMetadata report_meta = MoMADBSupport.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);
|
||||
}
|
||||
}
|
||||
|
||||
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 = MoMADBSupport.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 = MoMADBSupport.OpenDB();
|
||||
Report report = MoMADBSupport.GetReport(db, id);
|
||||
ReportMetadata report_meta = MoMADBSupport.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 = MoMADBSupport.OpenDB();
|
||||
Report report = MoMADBSupport.GetReport(db, id);
|
||||
ReportMetadata report_meta = MoMADBSupport.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 = MoMADBSupport.OpenDB();
|
||||
Report report = MoMADBSupport.GetReport(db, id);
|
||||
ReportMetadata report_meta = MoMADBSupport.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 = MoMADBSupport.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.InsertOnSubmit(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;
|
||||
|
||||
try
|
||||
{
|
||||
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
|
||||
*/
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
/* MailMessage.ctor() can throw if the email address are malformed - again, not
|
||||
* sure what can be done here
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* This reads the entire set of comments - someone else might have added a comment to
|
||||
* this report simultaneously
|
||||
*/
|
||||
this.UpdateComments(db, id);
|
||||
newcomment_textbox.Text = "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<%@ Page Language="C#" MasterPageFile="~/MoMA.master" AutoEventWireup="true" CodeFile="ReportView.aspx.cs" Inherits="ReportView" Title="MoMA Studio - View Report" %>
|
||||
|
||||
<asp:Content ID="BodyContent" ContentPlaceHolderID="BodyContentPlaceHolder" runat="Server">
|
||||
<asp:LoginView ID="LoginView1" runat="server">
|
||||
<AnonymousTemplate>
|
||||
This view is only available to logged-in users.
|
||||
</AnonymousTemplate>
|
||||
<LoggedInTemplate>
|
||||
<div class="reportview_metadata">
|
||||
<asp:UpdatePanel ID="ReportMetaDataUpdatePanel" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<asp:Label ID="ReportIDLabel" runat="server" Text=""></asp:Label>
|
||||
<br />
|
||||
<asp:Label ID="ApplicationLabel" runat="server" Text="Application:"></asp:Label>
|
||||
<asp:TextBox ID="ApplicationContent" runat="server" AutoPostBack="True"
|
||||
ontextchanged="ApplicationContent_TextChanged"></asp:TextBox><br />
|
||||
<asp:Label ID="ImportanceLabel" runat="server" Text="Importance:"></asp:Label>
|
||||
<asp:DropDownList ID="ImportanceDropDownList" runat="server"
|
||||
AutoPostBack="True"
|
||||
onselectedindexchanged="Importance_SelectedIndexChanged">
|
||||
<asp:ListItem>Important</asp:ListItem>
|
||||
<asp:ListItem>Useful</asp:ListItem>
|
||||
<asp:ListItem>Not useful</asp:ListItem>
|
||||
</asp:DropDownList>
|
||||
<br />
|
||||
<asp:Label ID="AuthorLabel" runat="server" Text="Author:"></asp:Label>
|
||||
<asp:Label ID="AuthorContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="EmailLabel" runat="server" Text="Email:"></asp:Label>
|
||||
<asp:Label ID="EmailContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="WebsiteLabel" runat="server" Text="Website:"></asp:Label>
|
||||
<asp:Label ID="WebsiteContent" runat="server" Text=""></asp:Label><br />
|
||||
<asp:Label ID="FrameworkVersionLabel" runat="server" Text="Framework Version:"></asp:Label>
|
||||
<asp:Label ID="FrameworkVersionContent" runat="server"></asp:Label><br />
|
||||
<asp:Label ID="ApplicationTypeLabel" runat="server" Text="Application Type:"></asp:Label>
|
||||
<asp:TextBox ID="ApplicationTypeContent" runat="server" AutoPostBack="True"
|
||||
ontextchanged="ApplicationType_TextChanged"></asp:TextBox><br />
|
||||
<asp:Button ID="UpdateButton" runat="server" Text="Update" OnClick="UpdateButton_Click" />
|
||||
</ContentTemplate>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
<div class="reportview_comments">
|
||||
<asp:UpdatePanel ID="CommentUpdatePanel" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<asp:Label ID="CommentsLabel" runat="server" Text="Comments:"></asp:Label><br />
|
||||
<asp:TextBox ID="Comments" runat="server" ReadOnly="True" TextMode="MultiLine"
|
||||
Columns="40" Rows="12"></asp:TextBox><br />
|
||||
<asp:TextBox ID="NewComment" runat="server" Rows="6" TextMode="MultiLine"
|
||||
Columns="40"></asp:TextBox><br />
|
||||
<asp:CheckBox ID="SendCommentCheckBox" runat="server" Checked="True" Text="Send comment to submitter" /><br />
|
||||
<asp:Button ID="CommentButton" runat="server" Text="Add Comment"
|
||||
onclick="CommentButton_Click" />
|
||||
</ContentTemplate>
|
||||
<%--<Triggers>
|
||||
<asp:AsyncPostBackTrigger ControlID="CommentButton" EventName="Click" />
|
||||
</Triggers>--%>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
<div class="reportview_issues">
|
||||
<asp:GridView ID="IssuesGridView" runat="server">
|
||||
</asp:GridView>
|
||||
</div>
|
||||
</LoggedInTemplate>
|
||||
</asp:LoginView>
|
||||
</asp:Content>
|
|
@ -0,0 +1,48 @@
|
|||
<%@ Page Language="C#" MasterPageFile="~/MoMA.master" AutoEventWireup="true" CodeFile="Submissions.aspx.cs" Inherits="Submissions" Title="MoMA Studio - View Submissions" %>
|
||||
|
||||
<asp:Content ID="BodyContent" ContentPlaceHolderID="BodyContentPlaceHolder" Runat="Server">
|
||||
<asp:LoginView ID="LoginView1" runat="server">
|
||||
<AnonymousTemplate>
|
||||
This view is only available to logged-in users.
|
||||
</AnonymousTemplate>
|
||||
<LoggedInTemplate>
|
||||
<asp:UpdatePanel ID="ReportsGridUpdatePanel" runat="server">
|
||||
<ContentTemplate>
|
||||
<asp:SqlDataSource ID="SubmissionsSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:MomaDB %>"
|
||||
ProviderName="<%$ ConnectionStrings:MomaDB.ProviderName %>" SelectCommand="SELECT a.id, a.report_date, a.application_name, a.application_type, a.reporter_name, a.reporter_organization, a.display_name, miss.miss, niex.niex, pinv.pinv, todo.todo, total.total FROM (SELECT rep.id, rep.report_date, meta.application_name, meta.application_type, rep.reporter_name, rep.reporter_organization, def.display_name FROM moma_definition def, report rep LEFT JOIN report_metadata meta ON rep.id = meta.report_id WHERE rep.moma_definition_id = def.id) AS a, (SELECT report_id, COUNT(report_id) AS miss FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'MISS' GROUP BY report_id) AS miss, (SELECT report_id, COUNT(report_id) as niex FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'NIEX' GROUP BY report_id) AS niex, (SELECT report_id, COUNT(report_id) as pinv FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'PINV' GROUP BY report_id) AS pinv, (SELECT report_id, COUNT(report_id) AS todo FROM issue, issue_type WHERE issue.issue_type_id = issue_type.id AND issue_type.lookup_name = 'TODO' GROUP BY report_id) AS todo, (SELECT report_id, COUNT(report_id) AS total FROM issue GROUP BY report_id) AS total WHERE (a.id = miss.report_id) AND (a.id = niex.report_id) AND (a.id = pinv.report_id) AND (a.id = todo.report_id) AND (a.id = total.report_id);">
|
||||
</asp:SqlDataSource>
|
||||
<asp:GridView ID="ReportsGridView" runat="server" DataSourceID="SubmissionsSqlDataSource"
|
||||
AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False">
|
||||
<Columns>
|
||||
<asp:HyperLinkField DataNavigateUrlFields="id" DataNavigateUrlFormatString="~/ReportView.aspx?ReportID={0}"
|
||||
HeaderText="ID" Text="View" SortExpression="id" />
|
||||
<asp:BoundField DataField="report_date" HeaderText="Date"
|
||||
SortExpression="report_date" />
|
||||
<asp:BoundField DataField="application_name" HeaderText="Application Name"
|
||||
SortExpression="application_name" />
|
||||
<asp:BoundField DataField="application_type" HeaderText="Application Type"
|
||||
SortExpression="application_type" />
|
||||
<asp:BoundField DataField="reporter_name" HeaderText="Reporter"
|
||||
SortExpression="reporter_name" />
|
||||
<asp:BoundField DataField="reporter_organization" HeaderText="Organization"
|
||||
SortExpression="reporter_organization" />
|
||||
<asp:BoundField DataField="display_name" HeaderText="Profile"
|
||||
SortExpression="display_name" />
|
||||
<asp:BoundField DataField="miss" HeaderText="MISS"
|
||||
SortExpression="miss" />
|
||||
<asp:BoundField DataField="niex" HeaderText="NIEX"
|
||||
SortExpression="niex" />
|
||||
<asp:BoundField DataField="pinv" HeaderText="PINV"
|
||||
SortExpression="pinv" />
|
||||
<asp:BoundField DataField="todo" HeaderText="TODO"
|
||||
SortExpression="todo" />
|
||||
<asp:BoundField DataField="total" HeaderText="Total"
|
||||
SortExpression="total" />
|
||||
</Columns>
|
||||
</asp:GridView>
|
||||
</ContentTemplate>
|
||||
</asp:UpdatePanel>
|
||||
</LoggedInTemplate>
|
||||
</asp:LoginView>
|
||||
</asp:Content>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Xml.Linq;
|
||||
|
||||
public partial class Submissions : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
</configSections>
|
||||
<appSettings/>
|
||||
<connectionStrings>
|
||||
<add name="MomaDB" connectionString="Server=hagbard.apathetic.discordia.org.uk;Database=nhibernate;User ID=dick;Password=test;CommandTimeout=600"/>
|
||||
<add name="MomaDB" connectionString="Server=hagbard.apathetic.discordia.org.uk;Database=nhibernate;User ID=dick;Password=test;CommandTimeout=600" providerName="Npgsql"/>
|
||||
<add name="AspSQLProvider" connectionString="Server=hagbard.apathetic.discordia.org.uk;Database=nhibernate_users;User ID=dick;Password=test"/>
|
||||
</connectionStrings>
|
||||
<system.web>
|
||||
|
@ -39,7 +39,8 @@
|
|||
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
|
||||
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
|
||||
<add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></assemblies>
|
||||
<add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
|
||||
</assemblies>
|
||||
</compilation>
|
||||
<!--
|
||||
The <authentication> section enables configuration
|
||||
|
@ -158,4 +159,9 @@
|
|||
</smtp>
|
||||
</mailSettings>
|
||||
</system.net>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql, Version=1.99.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
</configuration>
|
||||
|
|
Загрузка…
Ссылка в новой задаче