Merge with master

This commit is contained in:
Niels Hartvig
2017-06-23 10:38:52 +02:00
4 changed files with 151 additions and 63 deletions
@@ -4,13 +4,11 @@
{
foreach (var contributor in Model.Contributors)
{
var author = contributor.Author;
if (author != null)
{
<a href="@author.HtmlUrl" class="contributor" target="_blank" title="@author.Login">
<a href="@contributor.AuthorUrl" class="contributor" target="_blank" title="@contributor.AuthorLogin">
<div class="avatar">
<img alt="@author.Login" src="@author.AvatarUrl&s=112" />
<span class="contrib-count" title="@(contributor.TotalCommits + " " + (contributor.TotalCommits == 1 ? "commit" : "commits"))">
<img alt="@contributor.AuthorLogin" src="@contributor.AuthorAvatarUrl&s=112"
srcset="@contributor.AuthorAvatarUrl&s=224 2x, @contributor.AuthorAvatarUrl&s=336 3x" />
<span class="contrib-count" title="@(contributor.TotalCommits + " " + (contributor.TotalCommits == 1 ? "contribution" : "contributions"))">
@contributor.TotalCommits
</span>
<div class="counts">
@@ -22,7 +20,6 @@
</div>
</div>
</a>
}
}
<div class="loadmore">
<a class="button transparent" href="#" onclick="loadAllGitHubContributors(); return false;">Load more</a>
@@ -9,7 +9,9 @@ using RestSharp;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Web.Mvc;
using Umbraco.Web.PropertyEditors;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Text;
namespace OurUmbraco.Community.Controllers
{
@@ -28,82 +30,138 @@ namespace OurUmbraco.Community.Controllers
"Umbraco.Deploy.ValueConnectors"
};
protected string JsonPath
{
get { return Server.MapPath("~/App_Data/TEMP/GithubContributors.json"); }
}
public List<GitHubCachedGlobalContributorModel> GetCachedContributors()
{
if (!System.IO.File.Exists(JsonPath)) throw new Exception("The JSON file doesn't exist on disk");
List<GitHubCachedGlobalContributorModel> temp = new List<GitHubCachedGlobalContributorModel>();
// Parse the JSON file from disk
foreach (JToken token in Skybrud.Essentials.Json.JsonUtils.LoadJsonArray(JsonPath))
{
temp.Add(token.ToObject<GitHubCachedGlobalContributorModel>());
}
return temp;
}
/// <summary>
/// Gets data for all GitHub contributors for all listed Umbraco repositories,
/// excluding the GitHub IDs of the HQ contributors from the text file list
/// </summary>
/// <returns></returns>
public ActionResult GitHubGetContributorsResult()
public ActionResult GitHubGetContributorsResult(bool force = false)
{
var model = new GitHubContributorsModel();
model.Contributors = new List<GitHubCachedGlobalContributorModel>();
try
{
string configPath = Server.MapPath("~/config/githubhq.txt");
if (!System.IO.File.Exists(configPath))
// If the file exists on disk and hasn't expired (AKA not older than one day), we should just load that
if (force == false && System.IO.File.Exists(JsonPath) && System.IO.File.GetLastWriteTimeUtc(JsonPath) >= DateTime.UtcNow.AddDays(-1))
{
LogHelper.Debug<GitHubContributorController>("Config file was not found: " + configPath);
model.Contributors = GetCachedContributors();
return PartialView("~/Views/Partials/Home/GitHubContributors.cshtml", model);
}
string[] login = System.IO.File.ReadAllLines(configPath).Where(x => x.Trim() != "").Distinct().ToArray();
var contributors = ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem<List<GitHubGlobalContributorModel>>("UmbracoGitHubContributors",
() =>
{
var githubController = new GitHubController();
var gitHubContributors = new List<GitHubContributorModel>();
foreach (var repo in Repositories)
{
var response = githubController.GetAllRepoContributors(repo);
if (response.StatusCode == HttpStatusCode.OK &&
response.ResponseStatus == ResponseStatus.Completed)
{
gitHubContributors.AddRange(response.Data);
}
else
{
LogHelper.Warn<IGitHubContributorsModel>(string.Format("Invalid HTTP response for repository {0}", repo));
}
}
try
{
// Load the contributors via the GitHub API and map to the cached model
var contributors = GetContributors().Select(x => new GitHubCachedGlobalContributorModel(x));
// filter to only include items from the last year (if we ran 4.6.1 we could have used ToUnixTimeSeconds())
var filteredRange = DateTime.UtcNow.AddYears(-1).Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
foreach (var contrib in gitHubContributors)
{
var contribWeeks = contrib.Weeks.Where(x => x.W >= filteredRange).ToList();
contrib.TotalAdditions = contribWeeks.Sum(x=>x.A);
contrib.TotalDeletions = contribWeeks.Sum(x=>x.D);
contrib.Total = contribWeeks.Sum(x => x.C);
}
// Serialize the contributors to raw JSON
string rawJson = JsonConvert.SerializeObject(contributors, Formatting.Indented);
var filteredContributors = gitHubContributors
.Where(g => !login.Contains(g.Author.Login))
.GroupBy(g => g.Author.Id)
.OrderByDescending(c => c.Sum(g => g.Total));
// Save the JSON to disk
System.IO.File.WriteAllText(JsonPath, rawJson, Encoding.UTF8);
model.Contributors = contributors.ToList();
} catch (Exception ex)
{
// Log the error so we can debug it later
LogHelper.Error<GitHubContributorController>("Unable to load GitHub contributors from the GitHub API", ex);
List<GitHubGlobalContributorModel> temp = new List<GitHubGlobalContributorModel>();
// Load the contributors from the cache (if we have any)
model.Contributors = GetCachedContributors();
}
foreach (var group in filteredContributors)
{
var contributor = new GitHubGlobalContributorModel(group);
if (contributor.TotalCommits > 0)
temp.Add(contributor);
}
return temp;
}, TimeSpan.FromDays(1));
model.Contributors = contributors;
}
catch (Exception ex)
} catch (Exception ex)
{
LogHelper.Error<IGitHubContributorsModel>("Could not get GitHub Contributors", ex);
// Log the error so we can debug it later
LogHelper.Error<GitHubContributorController>("Unable to load GitHub contributors from the GitHub API", ex);
}
return PartialView("~/Views/Partials/Home/GitHubContributors.cshtml", model);
}
public List<GitHubGlobalContributorModel> GetContributors()
{
string configPath = Server.MapPath("~/config/githubhq.txt");
if (!System.IO.File.Exists(configPath))
{
LogHelper.Debug<GitHubContributorController>("Config file was not found: " + configPath);
throw new Exception("Config file was not found: " + configPath);
}
string[] login = System.IO.File.ReadAllLines(configPath).Where(x => x.Trim() != "").Distinct().ToArray();
var githubController = new GitHubController();
var gitHubContributors = new List<GitHubContributorModel>();
foreach (var repo in Repositories)
{
var response = githubController.GetAllRepoContributors(repo);
if (response.StatusCode == HttpStatusCode.OK &&
response.ResponseStatus == ResponseStatus.Completed)
{
gitHubContributors.AddRange(response.Data);
}
else
{
LogHelper.Warn<IGitHubContributorsModel>(string.Format("Invalid HTTP response for repository {0}", repo));
}
}
// filter to only include items from the last year (if we ran 4.6.1 we could have used ToUnixTimeSeconds())
var filteredRange = DateTime.UtcNow.AddYears(-1).Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
foreach (var contrib in gitHubContributors)
{
var contribWeeks = contrib.Weeks.Where(x => x.W >= filteredRange).ToList();
contrib.TotalAdditions = contribWeeks.Sum(x => x.A);
contrib.TotalDeletions = contribWeeks.Sum(x => x.D);
contrib.Total = contribWeeks.Sum(x => x.C);
}
var filteredContributors = gitHubContributors
.Where(g => !login.Contains(g.Author.Login))
.GroupBy(g => g.Author.Id)
.OrderByDescending(c => c.Sum(g => g.Total));
List<GitHubGlobalContributorModel> temp = new List<GitHubGlobalContributorModel>();
foreach (var group in filteredContributors)
{
temp.Add(new GitHubGlobalContributorModel(group));
}
return temp;
}
}
}
@@ -4,6 +4,39 @@ using OurUmbraco.Community.Models;
namespace OurUmbraco.Community.Controllers
{
public class GitHubCachedGlobalContributorModel
{
public int AuthorId { get; set; }
public string AuthorLogin { get; set; }
public string AuthorUrl { get; set; }
public string AuthorAvatarUrl { get; set; }
public int TotalCommits { get; set; }
public int TotalAdditions { get; set; }
public int TotalDeletions { get; set; }
public GitHubCachedGlobalContributorModel() { }
public GitHubCachedGlobalContributorModel(GitHubGlobalContributorModel contributor)
{
AuthorId = contributor.Author.Id;
AuthorLogin = contributor.Author.Login;
AuthorUrl = contributor.Author.HtmlUrl;
AuthorAvatarUrl = contributor.Author.AvatarUrl;
TotalCommits = contributor.TotalCommits;
TotalAdditions = contributor.TotalAdditions;
TotalDeletions = contributor.TotalDeletions;
}
}
public class GitHubGlobalContributorModel
{
public List<GitHubContributorModel> Items { get; set; }
@@ -5,6 +5,6 @@ namespace OurUmbraco.Community.Models
{
public class GitHubContributorsModel : IGitHubContributorsModel
{
public List<GitHubGlobalContributorModel> Contributors { get; set; }
public List<GitHubCachedGlobalContributorModel> Contributors { get; set; }
}
}