Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5b0abd1ae | |||
| 81ba5bd022 | |||
| 96a3ca71a7 | |||
| a8e253553a | |||
| 91280b18f6 | |||
| fbb8ef1ba0 | |||
| 3f46d94a93 | |||
| 161fcc7f01 | |||
| 5e2cb68299 | |||
| e6a5b59ac6 | |||
| 2ffa61564c | |||
| a1d48afeca | |||
| a51e57737b | |||
| 1c8fcef754 | |||
| ab4ca0015e | |||
| f9014d649b | |||
| adf67fd89f | |||
| 805709a91b | |||
| 40a6aaa1a8 | |||
| 5e51dad445 | |||
| f2d9cc0c0b | |||
| a40f8f9a28 | |||
| 355c4184ef | |||
| 50bdd7647a | |||
| 47c85e633b | |||
| f82cda981c | |||
| aded9ec437 | |||
| bdcad7665f | |||
| 850b61fc4f | |||
| 1ea05d8107 | |||
| 60b7347586 | |||
| b35d45bf31 | |||
| e3c52baf3a | |||
| 0cef4124db | |||
| 87847769ce | |||
| 49c50046c9 | |||
| c93e4d1e2d | |||
| 686e3deb6c |
@@ -62,7 +62,7 @@ function GetSearchFilters(cssClass) {
|
||||
}
|
||||
|
||||
var forumId = $('#selectCategory').val();
|
||||
if(forumId !== undefined) {
|
||||
if(forumId) {
|
||||
forumId = forumId.replace(/([A-Za-z])\w+/g, "");
|
||||
}
|
||||
|
||||
@@ -365,7 +365,8 @@ $('#search-options input[type=checkbox]').click(function () {
|
||||
newUri = updateQueryString("order", orderValue, window.location.href);
|
||||
}
|
||||
} else {
|
||||
newUri = updateQueryString(this.name, this.checked, window.location.href);
|
||||
newUri = updateQueryString(this.name, this.checked, window.location.href);
|
||||
newUri = updateQueryString("page", 1, newUri);
|
||||
}
|
||||
console.log(newUri);
|
||||
window.location = newUri;
|
||||
|
||||
@@ -1,174 +1,174 @@
|
||||
body.packages {
|
||||
nav {
|
||||
|
||||
h3 {
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
opacity: .7;
|
||||
margin: .5rem 0 .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
h3 {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&.open, &.active {
|
||||
h3, a {
|
||||
opacity: 1;
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.active > ul {
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.packages-content {
|
||||
|
||||
.search-big {
|
||||
margin-bottom: 0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 1em 0 10px;
|
||||
font-size: 2.1rem;
|
||||
}
|
||||
|
||||
.package {
|
||||
margin-bottom: 15px;
|
||||
padding: 20px;
|
||||
transition: all .1s linear;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #e9e9e9;
|
||||
|
||||
&:hover {
|
||||
@include box-shadow(2);
|
||||
|
||||
.icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
border: none;
|
||||
border-bottom: 1px solid whitesmoke;
|
||||
width: 100%;
|
||||
|
||||
body.packages {
|
||||
nav {
|
||||
|
||||
h3 {
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
opacity: .7;
|
||||
margin: .5rem 0 .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
h3 {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&.open, &.active {
|
||||
h3, a {
|
||||
opacity: 1;
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.active > ul {
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.packages-content {
|
||||
|
||||
.search-big {
|
||||
margin-bottom: 0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 1em 0 10px;
|
||||
font-size: 2.1rem;
|
||||
}
|
||||
|
||||
.package {
|
||||
margin-bottom: 15px;
|
||||
padding: 20px;
|
||||
transition: all .1s linear;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #e9e9e9;
|
||||
|
||||
&:hover {
|
||||
@include box-shadow(2);
|
||||
|
||||
.icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
border: none;
|
||||
border-bottom: 1px solid whitesmoke;
|
||||
width: 100%;
|
||||
|
||||
.row{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: .5rem;
|
||||
font-weight: 600;
|
||||
|
||||
a {
|
||||
color: $color-headline;
|
||||
|
||||
&:hover {
|
||||
color: $color-our;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
|
||||
@media (min-width: $md) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.col-xs-2 {
|
||||
vertical-align: middle !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.other {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.stats {
|
||||
left: calc(16.666666666666664% + 15px);
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Monaco, Courier, monospace;
|
||||
font-size: .75rem;
|
||||
|
||||
i {
|
||||
margin-left: 3px;
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
span {
|
||||
&:first-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: .9rem;
|
||||
color: $color-text;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.package-badge {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: -3px;
|
||||
|
||||
|
||||
@media (min-width: $md) {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.karma , .downloads {
|
||||
color: #000;
|
||||
|
||||
span {
|
||||
transform: translate(0, 2px);
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&.liked {
|
||||
.karma {
|
||||
i {
|
||||
color: $color-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 1rem;
|
||||
line-height: 1.3;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: .8rem;
|
||||
margin-top: 3px;
|
||||
max-height: 28px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: .5rem;
|
||||
font-weight: 600;
|
||||
|
||||
a {
|
||||
color: $color-headline;
|
||||
|
||||
&:hover {
|
||||
color: $color-our;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
|
||||
@media (min-width: $md) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.col-xs-2 {
|
||||
vertical-align: middle !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.other {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.stats {
|
||||
left: calc(16.666666666666664% + 15px);
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Monaco, Courier, monospace;
|
||||
font-size: .75rem;
|
||||
|
||||
i {
|
||||
margin-left: 3px;
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
span {
|
||||
&:first-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: .9rem;
|
||||
color: $color-text;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.package-badge {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: -3px;
|
||||
|
||||
|
||||
@media (min-width: $md) {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.karma , .downloads {
|
||||
color: #000;
|
||||
|
||||
span {
|
||||
transform: translate(0, 2px);
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&.liked {
|
||||
.karma {
|
||||
i {
|
||||
color: $color-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 1rem;
|
||||
line-height: 1.3;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: .8rem;
|
||||
margin-top: 3px;
|
||||
max-height: 28px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,10 @@ section.forum {
|
||||
max-width: 112px;
|
||||
height: auto;
|
||||
|
||||
.package-forum-activity & {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@media (min-width: $md) {
|
||||
width: 58px;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
Html.RequiresCss("~/assets/css/style.min.css", 0);
|
||||
Html.RequiresCss("https://fonts.googleapis.com/css?family=Asap:400,700,400italic,700italic", 0);
|
||||
Html.RequiresCss("https://cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.5/jquery.fancybox.min.css", 0);
|
||||
Html.RequiresCss("https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.20/jquery.fancybox.min.css", 0);
|
||||
|
||||
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.13.1/jquery.validate.min.js");
|
||||
@@ -23,7 +23,7 @@
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/pagedown/1.0/Markdown.Editor.js");
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/pagedown/1.0/Markdown.Sanitizer.js");
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.8.1/mustache.min.js");
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.5/jquery.fancybox.min.js");
|
||||
Html.RequiresJs("https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.20/jquery.fancybox.min.js");
|
||||
|
||||
Html.RequiresJs("~/assets/js/jquery.ajaxfileupload.js");
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||
|
||||
@Html.Partial("~/Views/Partials/Community/JsValues.cshtml")
|
||||
|
||||
|
||||
@@ -140,7 +140,6 @@ else
|
||||
<div class="col-md-12">
|
||||
<h1 class="text-center">GitHub Contributions</h1>
|
||||
<p>
|
||||
Contributions to Umbraco GitHub repositories
|
||||
<small class="link-list">
|
||||
Contributions to default branches for
|
||||
<a href="https://github.com/umbraco/Umbraco-CMS" target="_blank" title="Umbraco-CMS">Umbraco-CMS</a>,
|
||||
@@ -153,7 +152,7 @@ else
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<small>GitHub contributors</small>
|
||||
<small>Contributions the last 12 months (number indicating accepted commits)</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 flex forum-thread" id="github-contributors">
|
||||
@@ -161,7 +160,7 @@ else
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 goto-forum">
|
||||
<a class="button green" href="https://github.com/umbraco" target="_blank">Contribute to Umbraco on GitHub →</a>
|
||||
<a class="button green" href="https://our.umbraco.org/contribute">Contribute to Umbraco →</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
@inherits OurUmbraco.Our.Models.OurUmbracoTemplatePage
|
||||
|
||||
@{
|
||||
// Save query string for use in pagination links
|
||||
var queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString());
|
||||
|
||||
const int pagesToShowLeft = 4;
|
||||
int page;
|
||||
if (!int.TryParse(Request["page"], out page))
|
||||
@@ -40,9 +43,9 @@
|
||||
TimeSpan.FromSeconds(4));
|
||||
}
|
||||
|
||||
var totalCountKey = "OurForumForumThreadCount[" + cat + "]";
|
||||
var totalCountKey = "OurForumForumThreadCount[" + cat + unsolved + noreplies + "]";
|
||||
var totalTopics = (int)cache.GetCacheItem(totalCountKey,
|
||||
() => topicService.GetAllTopicsCount(cat),
|
||||
() => topicService.GetAllTopicsCount(cat, unsolved, noreplies),
|
||||
TimeSpan.FromMinutes(1));
|
||||
|
||||
var pages = (totalTopics / pageSize) + 1;
|
||||
@@ -168,19 +171,22 @@
|
||||
<nav class="pagination" role="navigation">
|
||||
@if (page > 1)
|
||||
{
|
||||
<a class="prev" href="?page=@(page - 1)">Prev</a>
|
||||
queryString["page"] = (page - 1).ToString();
|
||||
<a class="prev" href="?@queryString">Prev</a>
|
||||
<span>…</span>
|
||||
}
|
||||
|
||||
@for (var i = (page - 1 > 0 ? page - 1 : 1); i < (page + (pagesToShowLeft - (page - 1 > 0 ? 1 : 0))) && i <= pages; i++)
|
||||
{
|
||||
<a class="@Umbraco.If(i == page, "active")" href="?page=@i">@i</a>
|
||||
queryString["page"] = i.ToString();
|
||||
<a class="@Umbraco.If(i == page, "active")" href="?@queryString">@i</a>
|
||||
}
|
||||
|
||||
@if (page < (pages - 3))
|
||||
@if (page < pages)
|
||||
{
|
||||
queryString["page"] = (page + 1).ToString();
|
||||
<span>…</span>
|
||||
<a class="next" href="?page=@(page + 1)">Next</a>
|
||||
<a class="next" href="?@queryString">Next</a>
|
||||
}
|
||||
</nav>
|
||||
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
{
|
||||
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" />
|
||||
<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>
|
||||
@@ -22,7 +20,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
}
|
||||
<div class="loadmore">
|
||||
<a class="button transparent" href="#" onclick="loadAllGitHubContributors(); return false;">Load more</a>
|
||||
|
||||
@@ -185,7 +185,9 @@
|
||||
defaultScreenshot = childContent.GetPropertyValue("defaultScreenshotPath", false, "/css/img/package2.png");
|
||||
}
|
||||
}
|
||||
<img src="@Utils.GetScreenshotPath(defaultScreenshot)?bgcolor=fff&width=50&height=50&format=png" />
|
||||
<img src="@Utils.GetScreenshotPath(defaultScreenshot)?bgcolor=fff&width=50&height=50&format=png"
|
||||
srcset="@Utils.GetScreenshotPath(defaultScreenshot)?bgcolor=fff&width=100&height=100&format=png 2x,
|
||||
@Utils.GetScreenshotPath(defaultScreenshot)?bgcolor=fff&width=150&height=150&format=png 3x" />
|
||||
</div>
|
||||
<div class="col-xs-10 col-md-6">
|
||||
<div class="forum-thread-text">
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
@foreach (var image in screenshots)
|
||||
{
|
||||
<a class="fancybox" rel="gallery1" href="@Utils.GetScreenshotPath(image.Path)" title="">
|
||||
<a class="fancybox" data-fancybox="package-gallery" href="@Utils.GetScreenshotPath(image.Path)" title="">
|
||||
<img src="@Utils.GetScreenshotPath(image.Path)?bgcolor=fff&height=154&width=281&format=png" alt=""/>
|
||||
</a>
|
||||
}
|
||||
@@ -236,7 +236,7 @@
|
||||
<a href="@forum.Url" class="forum-thread">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-10 col-md-0">
|
||||
<div class="col-xs-12 col-md-12">
|
||||
<div class="forum-thread-text">
|
||||
<h3>@forum.Name</h3>
|
||||
<p>@forum.forumDescription</p>
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
(function () {
|
||||
$(".fancybox")
|
||||
.fancybox({
|
||||
openEffect: 'none',
|
||||
closeEffect: 'none',
|
||||
padding: 0
|
||||
// options
|
||||
loop: true,
|
||||
arrows: true,
|
||||
infobar: false
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -32,4 +32,5 @@ UmbCardiff
|
||||
meet-umbraco-the-umbraco-meetup
|
||||
umBristol
|
||||
Oslo-Umbraco-Meetup
|
||||
Orange-County-Umbraco-Web-Technologies
|
||||
Orange-County-Umbraco-Web-Technologies
|
||||
umbLeeds
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
<configuration>
|
||||
<sources>
|
||||
<add url="https://github.com/umbraco/UmbracoDocs/archive/master.zip" folder="" />
|
||||
<!-- Comma separated list of branches we will pull documentation from -->
|
||||
<allowedBranches>master</allowedBranches>
|
||||
</sources>
|
||||
</configuration>
|
||||
|
||||
@@ -308,7 +308,7 @@
|
||||
</buildProviders>
|
||||
</compilation>
|
||||
<authentication mode="Forms">
|
||||
<forms name="yourAuthCookie" loginUrl="login.aspx" protection="All" path="/" slidingExpiration="true" timeout="525600" />
|
||||
<forms requireSSL="true" name="yourAuthCookie" loginUrl="login.aspx" protection="All" path="/" slidingExpiration="true" timeout="525600" />
|
||||
</authentication>
|
||||
<authorization>
|
||||
<allow users="?" />
|
||||
@@ -506,6 +506,10 @@
|
||||
</conditions>
|
||||
<action type="Redirect" url="{C:1}" redirectType="Permanent" appendQueryString="true" />
|
||||
</rule>
|
||||
<rule name="DocsProductsToAddons" patternSyntax="Wildcard" stopProcessing="true">
|
||||
<match url="documentation/products/*" />
|
||||
<action type="Redirect" url="/documentation/Add-ons/{R:1}" redirectType="Permanent" appendQueryString="true" />
|
||||
</rule>
|
||||
<!-- WIKI -->
|
||||
<rule name="RedirectWikiEvents" patternSyntax="Wildcard">
|
||||
<match url="wiki/reference/api-cheatsheet/using-applicationbase-to-register-events/*" />
|
||||
@@ -691,4 +695,4 @@
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
</location>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -9,6 +9,9 @@ using RestSharp;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace OurUmbraco.Community.Controllers
|
||||
{
|
||||
@@ -27,68 +30,144 @@ 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));
|
||||
|
||||
var filteredContributors = gitHubContributors
|
||||
.Where(g => !login.Contains(g.Author.Login))
|
||||
.GroupBy(g => g.Author.Id)
|
||||
.OrderByDescending(c => c.Sum(g => g.Total));
|
||||
// Serialize the contributors to raw JSON
|
||||
string rawJson = JsonConvert.SerializeObject(contributors, Formatting.Indented);
|
||||
|
||||
List<GitHubGlobalContributorModel> temp = new List<GitHubGlobalContributorModel>();
|
||||
// Save the JSON to disk
|
||||
System.IO.File.WriteAllText(JsonPath, rawJson, Encoding.UTF8);
|
||||
|
||||
foreach (var group in filteredContributors)
|
||||
{
|
||||
temp.Add(new GitHubGlobalContributorModel(group));
|
||||
}
|
||||
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);
|
||||
|
||||
return temp;
|
||||
// Load the contributors from the cache (if we have any)
|
||||
model.Contributors = GetCachedContributors();
|
||||
}
|
||||
|
||||
}, TimeSpan.FromDays(1));
|
||||
|
||||
|
||||
model.Contributors = contributors;
|
||||
}
|
||||
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)
|
||||
{
|
||||
var contributor = new GitHubGlobalContributorModel(group);
|
||||
if (contributor.TotalCommits > 0)
|
||||
{
|
||||
temp.Add(contributor);
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
@@ -60,7 +60,8 @@ namespace OurUmbraco.Community.Controllers
|
||||
x.CreatedBy.UserIdentifier.ScreenName.ToLowerInvariant().ContainsAny(usernameFilter) ==
|
||||
false
|
||||
&& x.UserMentions.Any(m => m.ScreenName.ContainsAny(usernameFilter)) == false
|
||||
&& x.Text.ToLowerInvariant().ContainsAny(wordFilter) == false)
|
||||
&& x.Text.ToLowerInvariant().ContainsAny(wordFilter) == false
|
||||
&& x.Text.StartsWith("RT ") == false)
|
||||
.Take(numberOfResults)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ namespace OurUmbraco.Community.Models
|
||||
{
|
||||
public class GitHubContributorsModel : IGitHubContributorsModel
|
||||
{
|
||||
public List<GitHubGlobalContributorModel> Contributors { get; set; }
|
||||
public List<GitHubCachedGlobalContributorModel> Contributors { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Net;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using System.Xml;
|
||||
using Examine;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Logging;
|
||||
using ZipFile = System.IO.Compression.ZipFile;
|
||||
@@ -122,10 +119,36 @@ namespace OurUmbraco.Documentation.Busineslogic.GithubSourcePull
|
||||
public void Process(string url, string foldername)
|
||||
{
|
||||
var zip = Download(url, foldername);
|
||||
RemoveExistingDocumentation(RootFolder);
|
||||
var unzippedPath = string.Empty;
|
||||
var branchAllowed = false;
|
||||
|
||||
using (var zipFile = ZipFile.OpenRead(zip))
|
||||
{
|
||||
var directory = zipFile.Entries.FirstOrDefault();
|
||||
|
||||
if (directory != null)
|
||||
{
|
||||
var branch = directory.FullName.Replace("/", string.Empty).Replace("UmbracoDocs-", string.Empty);
|
||||
branchAllowed = IsBranchWhiteListed(branch);
|
||||
|
||||
if (branchAllowed)
|
||||
{
|
||||
unzippedPath = RootFolder + Path.DirectorySeparatorChar +
|
||||
directory.FullName.Replace('/', Path.DirectorySeparatorChar);
|
||||
if (Directory.Exists(unzippedPath))
|
||||
//delete the directory we're trying to unzip to
|
||||
RemoveUnzippedFiles(unzippedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (branchAllowed == false)
|
||||
return;
|
||||
|
||||
ZipFile.ExtractToDirectory(zip, RootFolder);
|
||||
|
||||
var unzippedPath = RootFolder + "\\UmbracoDocs-StarterkitLessons\\";
|
||||
RemoveUnzippedFiles(RootFolder, ignoreDirectories: new List<string> { unzippedPath });
|
||||
|
||||
foreach (var directory in new DirectoryInfo(unzippedPath).GetDirectories())
|
||||
Directory.Move(directory.FullName, RootFolder + "\\" + directory.Name);
|
||||
foreach (var file in new DirectoryInfo(unzippedPath).GetFiles())
|
||||
@@ -139,6 +162,25 @@ namespace OurUmbraco.Documentation.Busineslogic.GithubSourcePull
|
||||
ExamineManager.Instance.IndexProviderCollection["documentationIndexer"].RebuildIndex();
|
||||
}
|
||||
|
||||
private bool IsBranchWhiteListed(string branch)
|
||||
{
|
||||
var xmlNodeList = Configuration.SelectNodes("//allowedBranches");
|
||||
if (xmlNodeList == null || xmlNodeList.Count <= 0)
|
||||
return false;
|
||||
|
||||
var node = xmlNodeList[0];
|
||||
if (string.IsNullOrWhiteSpace(node.InnerText))
|
||||
return false;
|
||||
|
||||
var allowedBranches = node.InnerText.Split(',');
|
||||
var isBranchWhitelisted = allowedBranches.Any(allowedBranch => allowedBranch.Equals(branch, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
if (isBranchWhitelisted == false)
|
||||
LogHelper.Warn<ZipDownloader>(string.Format("The branch {0} is not allowed in githubpull.config, will not process documentation any further", branch));
|
||||
|
||||
return isBranchWhitelisted;
|
||||
}
|
||||
|
||||
public void BuildSitemap(string foldername)
|
||||
{
|
||||
var folder = new DirectoryInfo(Path.Combine(RootFolder, foldername));
|
||||
@@ -158,7 +200,7 @@ namespace OurUmbraco.Documentation.Busineslogic.GithubSourcePull
|
||||
public List<SiteMapItem> directories { get; set; }
|
||||
|
||||
//public string url => $"http://localhost:24292/documentation{this.path}/?altTemplate=Lesson";
|
||||
|
||||
|
||||
public string url
|
||||
{
|
||||
get
|
||||
@@ -181,7 +223,7 @@ namespace OurUmbraco.Documentation.Busineslogic.GithubSourcePull
|
||||
directories = list,
|
||||
hasChildren = dir.GetDirectories().Any()
|
||||
};
|
||||
|
||||
|
||||
foreach (var child in dir.GetDirectories().Where(x => x.Name != "images"))
|
||||
{
|
||||
list.Add(GetFolderStructure(child, rootPath, level + 1));
|
||||
@@ -452,21 +494,35 @@ namespace OurUmbraco.Documentation.Busineslogic.GithubSourcePull
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private static void RemoveExistingDocumentation(string folder)
|
||||
|
||||
private static void RemoveUnzippedFiles(string folder, List<string> ignoreDirectories = null)
|
||||
{
|
||||
if (Directory.Exists(folder))
|
||||
{
|
||||
foreach (var directory in Directory.GetDirectories(folder))
|
||||
Retry.Do(() => Directory.Delete(directory, true), TimeSpan.FromSeconds(1), 5);
|
||||
{
|
||||
if (ignoreDirectories == null || ignoreDirectories.Any() == false)
|
||||
{
|
||||
//there are no ignores, so proceed to delete it
|
||||
Retry.Do(() => Directory.Delete(directory, true), TimeSpan.FromSeconds(1), 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ignoreDirectory in ignoreDirectories)
|
||||
{
|
||||
if (ignoreDirectory.TrimEnd('\\').Equals(directory.TrimEnd('\\'),
|
||||
StringComparison.InvariantCultureIgnoreCase) == false)
|
||||
{
|
||||
//path is NOT in the ignore list, so proceed to delete it
|
||||
Retry.Do(() => Directory.Delete(directory, true), TimeSpan.FromSeconds(1), 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mdfile in Directory.GetFiles(folder, "*.md"))
|
||||
Retry.Do(() => File.Delete(mdfile), TimeSpan.FromSeconds(1), 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Events _events = new Events();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using MarkdownDeep;
|
||||
|
||||
@@ -85,7 +86,7 @@ namespace OurUmbraco.Documentation.Busineslogic
|
||||
//Need to ensure we dont append the image links as they 404 if we add altTemplate
|
||||
if (AppendAltLessonLink && rawUrl.StartsWith("images/") == false)
|
||||
{
|
||||
return mdUrlTag.Replace(rawUrl, $"{rawUrl.EnsureNoDotsInUrl()}?altTemplate=Lesson");
|
||||
return mdUrlTag.Replace(rawUrl, string.Format("{0}?altTemplate=Lesson", rawUrl.EnsureNoDotsInUrl()));
|
||||
}
|
||||
|
||||
return mdUrlTag.Replace(rawUrl, rawUrl.EnsureNoDotsInUrl());
|
||||
|
||||
@@ -123,7 +123,7 @@ FETCH NEXT @count ROWS ONLY";
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <returns></returns>
|
||||
public int GetAllTopicsCount(int category = -1)
|
||||
public int GetAllTopicsCount(int category = -1, bool unsolved = false, bool noreplies = false)
|
||||
{
|
||||
const string sql1 = @"SELECT COUNT(*) as forumTopicCount
|
||||
FROM forumTopics
|
||||
@@ -135,6 +135,18 @@ LEFT OUTER JOIN umbracoNode u2 ON (forumTopics.memberId = u2.id AND u2.nodeObjec
|
||||
|
||||
var sql = (category > 0 ? sqlic : sqlix);
|
||||
|
||||
if (unsolved)
|
||||
if (sql.Contains("WHERE"))
|
||||
sql = sql + " AND answer = 0";
|
||||
else
|
||||
sql = sql + " WHERE answer = 0";
|
||||
|
||||
if (noreplies)
|
||||
if (sql.Contains("WHERE"))
|
||||
sql = sql + " AND replies = 0";
|
||||
else
|
||||
sql = sql + " WHERE replies = 0";
|
||||
|
||||
return _databaseContext.Database.ExecuteScalar<int>(sql, new { category = category });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user