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 _colors = new List() { 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(Section section, ChartType chartType, String header, IEnumerable> 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().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 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; } } }