Skip to content

Instantly share code, notes, and snippets.

@Tempest1000
Last active June 10, 2021 18:56
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Tempest1000/bcfe53eda7c0b6dadda95acb39cf46e7 to your computer and use it in GitHub Desktop.
Save Tempest1000/bcfe53eda7c0b6dadda95acb39cf46e7 to your computer and use it in GitHub Desktop.
<Query Kind="Program">
<Reference Relative="bin\Newtonsoft.Json.dll">D:\Data\LINQ\bin\Newtonsoft.Json.dll</Reference>
</Query>
void Main()
{
// -------------------------
// To use this application you must download a copy of Newtonsoft.Json.dll, which by default is not bundled with LINQPad.
// This DLL can be sourced from the NuGet package manager here: https://www.nuget.org/packages/Newtonsoft.Json
// Note the hardcoded path above, this can be changed to the location of the DLL on your hard drive.
// To do this: F4 > browse > choose Newtonsoft.Json.dll
// The password for JIRA shouldn't be stored in plaintext in the script, so add this value to the LINQPad password manager.
// In the password manager give the password the name "Jira Password".
// -------------------------
// credit to fyllepo
// for creating this fantastic app in PHP
// https://github.com/fyllepo/jira-report-time-logged-by-user/blob/master/index.php
string pathWithEnv = @"%USERPROFILE%\AppData\Local\LINQPad\report.html";
int maxResults = 100;
string jiraUrl = "jira.genco.local";
string jiraProjectKey = "RED5";
string username = "user";
string credentials = string.Format("{0}:{1}", username, Util.GetPassword("Jira Password"));
List<string> filterUsers = new List<string>
{
"John Smith",
"Jane Smith"
};
string responseData = null;
string responseHeaders = null;
int responseStatusCode = 0;
// credit to dhlavaty
// https://gist.github.com/dhlavaty/4433398
using (BetterWebClient webClient = new BetterWebClient())
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(credentials);
string key = System.Convert.ToBase64String(plainTextBytes);
string method = System.Net.WebRequestMethods.Http.Get;
webClient.Proxy = null;
webClient.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/json; charset=utf-8");
webClient.Headers.Add(System.Net.HttpRequestHeader.Authorization, "Basic " + key);
var webRequest = webClient.GetWebRequestX(new Uri(string.Format("http://{0}/rest/api/2/search?jql=project={1}&maxResults={2}", jiraUrl, jiraProjectKey, maxResults)));
webRequest.Method = method;
using (System.Net.WebResponse response = webRequest.GetResponse())
{
ProcessResponse(response, out responseData, out responseHeaders, out responseStatusCode);
}
}
// requires a download of Newtonsoft JSON from https://www.newtonsoft.com/json
// or the NuGet package manager here: https://www.nuget.org/packages/Newtonsoft.Json
// then F4 > browse > choose Newtonsoft.Json.dll
Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(responseData);
var list = new List<JiraInfo>();
foreach (var data in jo["issues"])
{
var field = data["fields"];
var info = new JiraInfo();
info.Key = data["key"].ToString();
if (field["assignee"] != null) {
if (!field["assignee"].Any()) {
info.Assignee = "Unassigned";
}
else
{
info.Assignee = field["assignee"]["displayName"].ToString();
}
}
info.Status = field["status"]["name"].ToString();
info.Priority = field["priority"]["name"].ToString();
info.Summary = field["summary"].ToString();
var timeEstimate = field["timeestimate"].ToString();
var totalTimeSpent = field["aggregatetimespent"].ToString();
var timeEstimateHours = 0m;
var totalTimeSpentHours = 0m;
if (decimal.TryParse(timeEstimate, out decimal timeEstimateHoursParsed))
{
timeEstimateHours = timeEstimateHoursParsed / 3600;
}
if (decimal.TryParse(totalTimeSpent, out decimal totalTimeSpentHoursParsed))
{
totalTimeSpentHours = totalTimeSpentHoursParsed / 3600;
}
info.TimeEstimate = timeEstimateHours.ToString();
info.TotalTimeSpent = totalTimeSpentHours.ToString();
list.Add(info);
}
var html = GenerateHtml(list, filterUsers);
var filePath = Environment.ExpandEnvironmentVariables(pathWithEnv);
File.WriteAllText(filePath, html);
}
// classes
class JiraInfo
{
public string Key { get; set; }
public string Assignee { get; set; }
public string Status { get; set; }
public string Priority { get; set; }
public string Summary { get; set; }
public string TimeEstimate { get; set; }
public string TotalTimeSpent { get; set; }
}
// credit to dhlavaty
// https://gist.github.com/dhlavaty/4433398
class BetterWebClient : System.Net.WebClient
{
public virtual System.Net.WebRequest GetWebRequestX(Uri address)
{
return this.GetWebRequest(address);
}
}
// methods
void ProcessResponse(System.Net.WebResponse response, out string recurlyResponse, out string responseHeaders, out int responseStatusCode)
{
recurlyResponse = responseHeaders = String.Empty;
responseStatusCode = 0;
using (var responseStream = response.GetResponseStream())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream, Encoding.UTF8))
{
recurlyResponse = sr.ReadToEnd();
}
}
responseHeaders = response.Headers.ToString();
var httpWebResponse = response as System.Net.HttpWebResponse;
if (httpWebResponse != null)
{
responseStatusCode = (int)httpWebResponse.StatusCode;
}
}
string GenerateHtml(List<JiraInfo> list, List<string> filterUsers)
{
StringBuilder sb = new StringBuilder();
sb.Append(@"
<!DOCTYPE html>
<html lang=""en"">
<head>
<meta charset=""UTF-8"">
<title>JIRA Export</title>
<link rel=""stylesheet"" href=""https://unpkg.com/purecss@0.6.2/build/pure-min.css"" integrity=""sha384-UQiGfs9ICog+LwheBSRCt1o5cbyKIHbwjWscjemyBMT9YCUMZffs6UqUTd0hObXD"" crossorigin=""anonymous"">
<style>body{font-family:Arial;padding:30px}label{margin-top:50px;width:360px;font-size:22px;font-weight:700;padding-bottom: 10px;}input{margin-top:5px;height:40px;width:400px;font-size:20px;padding-left:15px;text-transform:uppercase;vertical-align:bottom;}button{color:#fff;vertical-align:bottom;height:46px;}.button-success{background:#1cb841;color:#fff;}.button-secondary{background:#42b8dd}.button-small{font-size:85%}.button-xlarge{font-size:125%}</style>
</head>
<body>
<h3>Results</h3>
<table class=""pure-table pure-table-bordered"">
<thead>
<tr>
<th width=""100"">Key</th>
<th>Assignee</th>
<th>Status</th>
<th>Priority</th>
<th>Summary</th>
<th>Time Estimated</th>
<th>Total Time Spent (hrs)</th>
</tr>
</thead>
<tbody>
");
var rows = filterUsers.Any() ? list.Where(x => filterUsers.Contains(x.Assignee)) : list;
foreach(var info in rows)
{
sb.Append(string.Format(@"
<tr>
<td>{0}</td>
<td>{1}</td>
<td>{2}</td>
<td>{3}</td>
<td>{4}</td>
<td>{5}</td>
<td>{6}</td>
</tr>
", info.Key, info.Assignee, info.Status, info.Priority, info.Summary, info.TimeEstimate, info.TotalTimeSpent));
}
sb.Append(@"
</tbody>
</table>
</body>
</html>
");
return sb.ToString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment