using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Tango.Core.Helpers;
using Tango.Core.IO;
using Tango.TFS;
namespace Tango.BugReporter
{
class Program
{
private static List<Color> _colors = new List<Color>()
{
Colors.Crimson,
Colors.Coral,
Colors.Khaki,
Colors.Wheat,
Colors.PaleGreen,
Colors.PaleTurquoise,
Colors.CadetBlue,
Colors.Lavender,
Colors.SlateBlue,
Colors.LightSteelBlue,
Colors.PowderBlue,
Colors.Silver,
Colors.SlateGray,
};
static void Main(string[] args)
{
String startPath = AssemblyHelper.GetCurrentAssemblyFolder();
ITeamFoundationServiceClient tfs = new TeamFoundationServiceClient("https://twinetfs.visualstudio.com/DefaultCollection", String.Empty, "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa");
var project = tfs.GetProject("Tango").Result;
var allItems = tfs.GetAllWorkItems(project).Result.OrderByDescending(x => x.Type).OrderBy(x => x.Severity).ToList();
var activeItems = allItems.Where(x => x.State == State.Active || x.State == State.New).ToList();
var resolvedItems = allItems.Where(x => x.State == State.Resolved).ToList();
Document document = new Document();
document.Info.Title = "Tango Bug Report";
document.Info.Author = "Twine Solutions LTD";
document.DefaultPageSetup.TopMargin = 5;
document.DefaultPageSetup.RightMargin = 5;
document.DefaultPageSetup.LeftMargin = 5;
Style style = document.Styles["Normal"];
style.Font.Size = 7;
var section = document.AddSection();
section.PageSetup.PageFormat = PageFormat.A4;
var headParagraph = section.AddParagraph();
headParagraph.Format.Alignment = ParagraphAlignment.Left;
headParagraph.Format.Font.Size = 16;
headParagraph.Format.Font.Bold = true;
headParagraph.Format.SpaceBefore = "8mm";
headParagraph.Format.SpaceAfter = "5mm";
headParagraph.Format.RightIndent = "5mm";
headParagraph.Format.Font.Color = Colors.DimGray;
var img = headParagraph.AddImage(Path.Combine(startPath, "twine-logo.jpg"));
headParagraph.AddSpace(5);
var t = headParagraph.AddText(" Twine Solutions VSTS Report");
var pp = section.AddParagraph(String.Format("This report was generated on {0}. Below you can find a daily summery of the Tango project, work items state and urgency.", DateTime.Now.ToShortDateString()));
pp.Format.LeftIndent = "2cm";
AddTable(section, "All Active Items", activeItems);
section.AddPageBreak();
AddTable(section, "Created Today", activeItems.Where(x => x.CreatedDate.Date == DateTime.Now.Date));
section.AddPageBreak();
AddTable(section, "Resolved Today", resolvedItems.Where(x => x.ResolvedDate.Date == DateTime.Now.Date));
section.AddPageBreak();
AddChart(section, ChartType.Column2D, "Items Per Member", activeItems.GroupBy(x => x.AssignedTo), nameof(TeamMember.DisplayName));
section.AddPageBreak();
AddChart(section, ChartType.Bar2D, "Items Per Area", activeItems.GroupBy(x => x.Area.Name), null);
section.AddPageBreak();
foreach (var g in activeItems.GroupBy(x => x.Area.Name))
{
AddTable(section, g.Key + " Items", g);
section.AddPageBreak();
}
var group = activeItems.GroupBy(x => x.AssignedTo);
var file = TemporaryManager.Default.CreateFile();
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfFontEmbedding.None);
pdfRenderer.Document = document;
pdfRenderer.RenderDocument();
pdfRenderer.PdfDocument.Save(file.Path);
ITeamFoundationEmailClient emailClient = new TeamFoundationEmailClient(new System.Net.NetworkCredential("roy@twine-s.com", "Maya2018"));
Email mail = new Email();
mail.Attachments.Add(new Attachment() { FilePath = file.Path, Name = "VSTS-REPORT.pdf" });
mail.From = project.Members.SingleOrDefault(x => x.DisplayName.Contains("Roy"));
mail.To.Add(mail.From);
mail.Subject = "VSTS Daily Report";
mail.Body = "Attached is a daily report containing Tango project work items.";
emailClient.Send(mail).Wait();
file.Delete();
}
private static Chart AddChart<T>(Section section, ChartType chartType, String header, IEnumerable<IGrouping<T, WorkItem>> workItemGroups, String propName)
{
var headParagraph = section.AddParagraph(header);
headParagraph.Format.Alignment = ParagraphAlignment.Left;
headParagraph.Format.Font.Size = 16;
headParagraph.Format.Font.Bold = true;
headParagraph.Format.SpaceBefore = "8mm";
headParagraph.Format.SpaceAfter = "5mm";
Chart chart = section.AddChart(chartType);
chart.Width = section.Document.DefaultPageSetup.PageWidth - 5;
chart.Height = "10cm";
workItemGroups = workItemGroups.OrderByDescending(x => x.Count());
Series series = chart.SeriesCollection.AddSeries();
series.Add(workItemGroups.Select(x => (double)x.Count()).ToArray());
XSeries xseries = chart.XValues.AddXSeries();
if (propName != null)
{
xseries.Add(workItemGroups.Select(x => x.Key.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.Instance).GetValue(x.Key).ToString()).ToArray());
}
else
{
xseries.Add(workItemGroups.Select(x => x.Key.ToString()).ToArray());
}
var elements = series.Elements.Cast<Point>().ToArray();
for (int i = 0; i < elements.Length; i++)
{
elements[i].FillFormat.Color = _colors[i];
}
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.XAxis.Title.Caption = propName;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Color = Colors.White;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
return chart;
}
private static Table AddTable(Section section, String header, IEnumerable<WorkItem> workItems)
{
String startPath = AssemblyHelper.GetCurrentAssemblyFolder();
var headParagraph = section.AddParagraph(header);
headParagraph.Format.Alignment = ParagraphAlignment.Left;
headParagraph.Format.Font.Size = 16;
headParagraph.Format.Font.Bold = true;
headParagraph.Format.SpaceBefore = "8mm";
headParagraph.Format.SpaceAfter = "5mm";
var table = section.AddTable();
table.Borders.Color = Colors.Black;
table.Borders.Width = 0.25;
table.Borders.Left.Width = 0.5;
table.Borders.Right.Width = 0.5;
table.Rows.LeftIndent = 0;
table.BottomPadding = "2mm";
table.TopPadding = "2mm";
table.LeftPadding = "2mm";
table.RightPadding = "2mm";
// Before you can add a row, you must define the columns
table.AddColumn("1cm");
table.AddColumn();
table.AddColumn("4cm");
table.AddColumn();
table.AddColumn();
table.AddColumn();
table.AddColumn("1.5cm");
table.AddColumn("1.5cm");
table.AddColumn("1.5cm");
// Create the header of the table
Row row = table.AddRow();
row.HeadingFormat = true;
row.Shading.Color = Colors.Gainsboro;
row.Cells[0].AddParagraph("Work Item");
row.Cells[1].AddParagraph("Created Date");
row.Cells[2].AddParagraph("Title");
row.Cells[3].AddParagraph("Area");
row.Cells[4].AddParagraph("Created By");
row.Cells[5].AddParagraph("Assigned To");
row.Cells[6].AddParagraph("Severity");
row.Cells[7].AddParagraph("Priority");
row.Cells[8].AddParagraph("State");
foreach (var item in workItems)
{
Row r = table.AddRow();
var image = r.Cells[0].AddImage(Path.Combine(startPath, item.Type == WorkItemType.Bug ? "bug.png" : "task.png"));
image.Width = 15;
image.Height = 15;
r.Cells[1].AddParagraph(item.CreatedDate.ToShortDateString());
var linkParagraph = r.Cells[2].AddParagraph();
var link = linkParagraph.AddHyperlink(String.Format("https://twinetfs.visualstudio.com/DefaultCollection/Tango/_queries?id={0}&_a=edit", item.ID), HyperlinkType.Web);
link.AddFormattedText(item.Title);
r.Cells[3].AddParagraph(item.Area.Name);
r.Cells[4].AddParagraph(item.CreatedBy.DisplayName);
r.Cells[5].AddParagraph(item.AssignedTo.DisplayName);
var p = r.Cells[6].AddParagraph(item.Severity.ToString());
if (item.Severity == Severity.Critical || item.Severity == Severity.High)
{
p.Format.Font.Color = Colors.Red;
}
r.Cells[7].AddParagraph(item.Priority.ToDescription());
r.Cells[8].AddParagraph(item.State.ToString());
}
return table;
}
}
}