Rebuild all the things I burnt, (p1)

Lots of re-implementing going on, using BsonDocuments directly rather
than going through the LINQ layer.
This commit is contained in:
Thomas Hounsell 2016-01-11 21:16:29 +00:00
parent 48e161ca4a
commit 0403a9a1f5
12 changed files with 520 additions and 231 deletions

View File

@ -1,61 +1,100 @@
@using BuildFeed.Code
@using System.Web.Mvc
@using System.Web.Mvc.Html
@using System.Web.Mvc.Html
@using System.Web.Routing
@using BuildFeed.Code
@helper PaginationBlock(int currentPage, int totalPages, string view, RouteValueDictionary rd)
{
string multiView = view + "Page";
if (totalPages > 1)
{
<div class="text-center">
<ul class="pagination">
@if (currentPage == 2)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd.Remove("page");
string multiView = view + "Page";
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, rvd)</li>
}
else if (currentPage > 2)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage - 1;
if (totalPages > 1)
{
<div class="text-center">
<ul class="pagination">
@if (currentPage == 2)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd.Remove("page");
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, rvd)</li>
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&lsaquo;"), view, rvd)</li>
}
else if (currentPage > 2)
{
RouteValueDictionary firstRvd = new RouteValueDictionary(rd);
firstRvd.Remove("page");
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, firstRvd)</li>
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), multiView, rvd)</li>
}
else
{
<li class="disabled"><span>&laquo;</span></li>
}
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage - 1;
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&lsaquo;"), multiView, rvd)</li>
}
else
{
<li class="disabled">
<span>&laquo;</span></li>
<li class="disabled">
<span>&lsaquo;</span>
</li>
}
@{
RouteValueDictionary rvdIndex = new RouteValueDictionary(rd);
rvdIndex.Remove("page");
}
<li @((1 == currentPage) ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink("1", view)</li>
@for (int i = 2; i <= totalPages; i++)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = i;
@{
RouteValueDictionary rvdIndex = new RouteValueDictionary(rd);
rvdIndex.Remove("page");
IEnumerable<int> pages = new int[0];
}
<li @((i == currentPage) ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink(i.ToString(), multiView, rvd)</li>
}
@if (totalPages <= 7)
{
pages = Enumerable.Range(1, totalPages);
}
else if (currentPage <= 4)
{
pages = Enumerable.Range(1, 7);
}
else if (currentPage >= totalPages - 2)
{
pages = Enumerable.Range(totalPages - 6, 7);
}
else
{
pages = Enumerable.Range(currentPage - 3, 7);
}
@foreach (int i in pages)
{
if (i == 1)
{
<li @(1 == currentPage ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink("1", view)</li>
}
else
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = i;
<li @(i == currentPage ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink(i.ToString(), multiView, rvd)</li>
}
}
@if (currentPage < totalPages)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage + 1;
@if (currentPage < totalPages)
{
RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage + 1;
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&raquo;"), multiView, rvd)</li>
}
else
{
<li class="disabled"><span>&raquo;</span></li>
}
</ul>
</div>
}
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&rsaquo;"), multiView, rvd)</li>
RouteValueDictionary lastRvd = new RouteValueDictionary(rd);
lastRvd["page"] = totalPages;
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&raquo;"), multiView, lastRvd)</li>
}
else
{
<li class="disabled">
<span>&rsaquo;</span></li>
<li class="disabled">
<span>&raquo;</span>
</li>
}
</ul>
</div>
}
}

View File

@ -896,12 +896,12 @@
<SubType>Designer</SubType>
</Content>
<Content Include="Views\front\Index.cshtml" />
<Content Include="Views\front\viewGroup.cshtml" />
<Content Include="Views\front\ViewGroup.cshtml" />
<Content Include="Views\front\ViewBuild.cshtml" />
<Content Include="Views\front\viewLab.cshtml" />
<Content Include="Views\front\viewSource.cshtml" />
<Content Include="Views\front\viewYear.cshtml" />
<Content Include="Views\front\viewVersion.cshtml" />
<Content Include="Views\front\ViewLab.cshtml" />
<Content Include="Views\front\ViewSource.cshtml" />
<Content Include="Views\front\ViewYear.cshtml" />
<Content Include="Views\front\ViewVersion.cshtml" />
<Content Include="Views\support\credits.cshtml" />
</ItemGroup>
<ItemGroup>

View File

@ -1,6 +1,4 @@
using BuildFeed.Code;
using BuildFeed.Models;
using System;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
@ -10,17 +8,19 @@
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using BuildFeed.Code;
using BuildFeed.Models;
namespace BuildFeed.Controllers
{
public class FrontController : LocalController
{
private const int PAGE_SIZE = 96;
private const int PAGE_SIZE = 72;
private readonly Build _bModel;
private readonly MetaItem _mModel;
public FrontController() : base()
public FrontController()
{
_bModel = new Build();
_mModel = new MetaItem();
@ -42,8 +42,8 @@ public async Task<ActionResult> IndexPage(int page)
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(
Convert.ToDouble(await _bModel.SelectAllGroupsCount()) /
Convert.ToDouble(PAGE_SIZE));
Convert.ToDouble(await _bModel.SelectAllGroupsCount()) /
Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
@ -59,7 +59,7 @@ public async Task<ActionResult> IndexPage(int page)
#endif
public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, uint? revision = null)
{
BuildGroup bg = new BuildGroup()
BuildGroup bg = new BuildGroup
{
Major = major,
Minor = minor,
@ -69,9 +69,13 @@ public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, u
var builds = await _bModel.SelectGroup(bg);
return builds.Count() == 1 ?
RedirectToAction(nameof(ViewBuild), new { id = builds.Single().Id }) as ActionResult :
View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds));
return builds.Count() == 1
? RedirectToAction(nameof(ViewBuild), new
{
id = builds.Single()
.Id
}) as ActionResult
: View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds));
}
[Route("build/{id:guid}/", Name = "Build")]
@ -81,7 +85,10 @@ public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, u
public async Task<ActionResult> ViewBuild(Guid id)
{
BuildModel b = await _bModel.SelectById(id);
if (b == null) return new HttpNotFoundResult();
if (b == null)
{
return new HttpNotFoundResult();
}
return View(b);
}
@ -89,8 +96,14 @@ public async Task<ActionResult> ViewBuild(Guid id)
public async Task<ActionResult> ViewBuild(long id)
{
BuildModel b = await _bModel.SelectByLegacyId(id);
if (b == null) return new HttpNotFoundResult();
return RedirectToAction(nameof(ViewBuild), new { id = b.Id });
if (b == null)
{
return new HttpNotFoundResult();
}
return RedirectToAction(nameof(ViewBuild), new
{
id = b.Id
});
}
[Route("twitter/{id:guid}/", Name = "Twitter")]
@ -101,7 +114,10 @@ public async Task<ActionResult> ViewBuild(long id)
public async Task<ActionResult> TwitterCard(Guid id)
{
BuildModel b = await _bModel.SelectById(id);
if (b == null) return new HttpNotFoundResult();
if (b == null)
{
return new HttpNotFoundResult();
}
string path = Path.Combine(Server.MapPath("~/content/card/"), $"{b.Family}.png");
bool backExists = System.IO.File.Exists(path);
@ -123,10 +139,14 @@ public async Task<ActionResult> TwitterCard(Guid id)
gr.FillRectangle(new SolidBrush(Color.FromArgb(0x27, 0x2b, 0x30)), 0, 0, 1120, 600);
}
gp.AddString("BUILDFEED", new FontFamily("Segoe UI"), (int)FontStyle.Bold, 32, new Point(40, 32), StringFormat.GenericTypographic);
gp.AddString($"{DisplayHelpers.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})", new FontFamily("Segoe UI"), 0, 48, new Point(40, 80), StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 280, new Point(32, 96), StringFormat.GenericTypographic);
gp.AddString(b.BuildTime.HasValue ? $"{b.Lab}\r\n{b.BuildTime.Value:yyyy/MM/dd HH:mm}" : $"{b.Lab}", new FontFamily("Segoe UI"), 0, 44, new Point(40, 440), StringFormat.GenericTypographic);
gp.AddString("BUILDFEED", new FontFamily("Segoe UI"), (int) FontStyle.Bold, 32, new Point(40, 32),
StringFormat.GenericTypographic);
gp.AddString($"{DisplayHelpers.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})",
new FontFamily("Segoe UI"), 0, 48, new Point(40, 80), StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 280, new Point(32, 96),
StringFormat.GenericTypographic);
gp.AddString(b.BuildTime.HasValue ? $"{b.Lab}\r\n{b.BuildTime.Value:yyyy/MM/dd HH:mm}" : $"{b.Lab}",
new FontFamily("Segoe UI"), 0, 44, new Point(40, 440), StringFormat.GenericTypographic);
gr.FillPath(Brushes.White, gp);
Response.ContentType = "image/png";
@ -141,8 +161,14 @@ public async Task<ActionResult> TwitterCard(Guid id)
public async Task<ActionResult> TwitterCard(long id)
{
BuildModel b = await _bModel.SelectByLegacyId(id);
if (b == null) return new HttpNotFoundResult();
return RedirectToAction(nameof(TwitterCard), new { id = b.Id });
if (b == null)
{
return new HttpNotFoundResult();
}
return RedirectToAction(nameof(TwitterCard), new
{
id = b.Id
});
}
[Route("lab/{lab}/", Order = 1, Name = "Lab Root")]
@ -158,14 +184,15 @@ public async Task<ActionResult> TwitterCard(long id)
public async Task<ActionResult> ViewLabPage(string lab, int page)
{
ViewBag.MetaItem = await _mModel.SelectById(new MetaItemKey
{
Type = MetaType.Lab,
Value = lab
});
{
Type = MetaType.Lab,
Value = lab
});
var builds = await _bModel.SelectLab(lab, (page - 1) * PAGE_SIZE, PAGE_SIZE);
var builds = await _bModel.SelectLab(lab, PAGE_SIZE, (page - 1) * PAGE_SIZE);
ViewBag.ItemId = builds.First().Lab;
ViewBag.ItemId = builds.FirstOrDefault()
?.Lab;
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectLabCount(lab)) / Convert.ToDouble(PAGE_SIZE));
@ -190,13 +217,13 @@ public async Task<ActionResult> ViewLabPage(string lab, int page)
public async Task<ActionResult> ViewSourcePage(TypeOfSource source, int page)
{
ViewBag.MetaItem = await _mModel.SelectById(new MetaItemKey
{
Type = MetaType.Source,
Value = source.ToString()
});
{
Type = MetaType.Source,
Value = source.ToString()
});
ViewBag.ItemId = DisplayHelpers.GetDisplayTextForEnum(source);
var builds = await _bModel.SelectSource(source, (page - 1) * PAGE_SIZE, PAGE_SIZE);
var builds = await _bModel.SelectSource(source, PAGE_SIZE, (page - 1) * PAGE_SIZE);
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectSourceCount(source)) / Convert.ToDouble(PAGE_SIZE));
@ -222,13 +249,13 @@ public async Task<ActionResult> ViewSourcePage(TypeOfSource source, int page)
public async Task<ActionResult> ViewYearPage(int year, int page)
{
ViewBag.MetaItem = await _mModel.SelectById(new MetaItemKey
{
Type = MetaType.Year,
Value = year.ToString()
});
{
Type = MetaType.Year,
Value = year.ToString()
});
ViewBag.ItemId = year.ToString();
var builds = await _bModel.SelectYear(year, (page - 1) * PAGE_SIZE, PAGE_SIZE);
var builds = await _bModel.SelectYear(year, PAGE_SIZE, (page - 1) * PAGE_SIZE);
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(await _bModel.SelectYearCount(year) / Convert.ToDouble(PAGE_SIZE));
@ -255,13 +282,13 @@ public async Task<ActionResult> ViewVersionPage(uint major, uint minor, int page
{
string valueString = $"{major}.{minor}";
ViewBag.MetaItem = await _mModel.SelectById(new MetaItemKey
{
Type = MetaType.Version,
Value = valueString
});
{
Type = MetaType.Version,
Value = valueString
});
ViewBag.ItemId = valueString;
var builds = await _bModel.SelectVersion(major, minor, (page - 1) * PAGE_SIZE, PAGE_SIZE);
var builds = await _bModel.SelectVersion(major, minor, PAGE_SIZE, (page - 1) * PAGE_SIZE);
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectVersionCount(major, minor)) / Convert.ToDouble(PAGE_SIZE));
@ -277,11 +304,11 @@ public async Task<ActionResult> ViewVersionPage(uint major, uint minor, int page
[Route("add/"), Authorize]
public ActionResult AddBuild()
{
BuildModel b = new BuildModel()
{
SourceType = TypeOfSource.PrivateLeak,
FlightLevel = LevelOfFlight.None
};
BuildModel b = new BuildModel
{
SourceType = TypeOfSource.PrivateLeak,
FlightLevel = LevelOfFlight.None
};
return View("EditBuild", b);
}
@ -309,9 +336,9 @@ public async Task<ActionResult> AddBuild(BuildModel build)
return View("EditBuild", build);
}
return RedirectToAction(nameof(ViewBuild), new
{
id = build.Id
});
{
id = build.Id
});
}
return View("EditBuild", build);
}
@ -345,7 +372,10 @@ public async Task<ActionResult> EditBuild(Guid id, BuildModel build)
return View(build);
}
return RedirectToAction(nameof(ViewBuild), new { id = build.Id });
return RedirectToAction(nameof(ViewBuild), new
{
id = build.Id
});
}
return View(build);
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BuildFeed.Models.ViewModel.Front;
@ -34,17 +33,15 @@ public async Task<FrontBuildGroup[]> SelectAllGroups(int limit = -1, int skip =
new BsonElement($"_id.{nameof(BuildGroup.Minor)}", -1),
new BsonElement($"_id.{nameof(BuildGroup.Build)}", -1),
new BsonElement($"_id.{nameof(BuildGroup.Revision)}", -1)
});
})
.Skip(skip);
if (limit > 0)
{
query = query
.Limit(limit);
query = query.Limit(limit);
}
var grouping = await query
.Skip(skip)
.ToListAsync();
var grouping = await query.ToListAsync();
return (from g in grouping
select new FrontBuildGroup
@ -54,14 +51,14 @@ public async Task<FrontBuildGroup[]> SelectAllGroups(int limit = -1, int skip =
Major = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Major)].AsInt32,
Minor = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Minor)].AsInt32,
Build = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Build)].AsInt32,
Revision = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Revision)].AsInt32
Revision = (uint?) g["_id"].AsBsonDocument[nameof(BuildGroup.Revision)].AsNullableInt32
},
LastBuild = g["date"].ToNullableUniversalTime(),
BuildCount = g["count"].AsInt32
}).ToArray();
}
public async Task<int> SelectAllGroupsCount()
public async Task<long> SelectAllGroupsCount()
{
var grouping = await _buildCollection.Aggregate()
.Group(
@ -80,8 +77,41 @@ public async Task<int> SelectAllGroupsCount()
return grouping.Count;
}
public async Task<List<BuildModel>> SelectGroup(BuildGroup group, int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<List<BuildModel>> SelectGroup(BuildGroup group, int limit = -1, int skip = 0)
{
var query = _buildCollection.Find(
new BsonDocument
{
new BsonElement(nameof(BuildModel.MajorVersion), group.Major),
new BsonElement(nameof(BuildModel.MinorVersion), group.Minor),
new BsonElement(nameof(BuildModel.Number), group.Build),
new BsonElement(nameof(BuildModel.Revision), group.Revision)
})
.Sort(
new BsonDocument
{
new BsonElement(nameof(BuildModel.BuildTime), -1)
})
.Skip(skip);
public async Task<List<BuildModel>> SelectGroupCount(BuildGroup group) { throw new NotImplementedException(); }
if (limit > 0)
{
query = query.Limit(limit);
}
return await query.ToListAsync();
}
public async Task<long> SelectGroupCount(BuildGroup group)
{
return await _buildCollection.CountAsync(
new BsonDocument
{
new BsonElement(nameof(BuildModel.MajorVersion), group.Major),
new BsonElement(nameof(BuildModel.MinorVersion), group.Minor),
new BsonElement(nameof(BuildModel.Number), group.Build),
new BsonElement(nameof(BuildModel.Revision), group.Revision)
});
}
}
}

View File

@ -1,19 +1,59 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models
{
public partial class Build
{
public Task<string[]> SelectAllLabs(int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<string[]> SelectAllLabs(int limit = -1, int skip = 0)
{
var query = _buildCollection.Aggregate()
.Group(new BsonDocument("_id", $"${nameof(BuildModel.Lab)}"))
.Sort(new BsonDocument("_id", 1))
.Skip(skip);
public async Task<int> SelectAllLabsCount() { throw new NotImplementedException(); }
if (limit > 0)
{
query = query.Limit(limit);
}
public async Task<List<BuildModel>> SelectLab(string lab, int limit = -1, int skip = 0) { throw new NotImplementedException(); }
var grouping = await query.ToListAsync();
public async Task<int> SelectLabCount(string lab) { throw new NotImplementedException(); }
return (from g in grouping
select g["_id"].AsString).ToArray();
}
public async Task<long> SelectAllLabsCount()
{
var query = _buildCollection.Aggregate()
.Group(new BsonDocument("_id", new BsonDocument(nameof(BuildModel.Lab), $"${nameof(BuildModel.Lab)}")))
.Sort(new BsonDocument("_id", 1));
var grouping = await query.ToListAsync();
return grouping.Count;
}
public async Task<List<BuildModel>> SelectLab(string lab, int limit = -1, int skip = 0)
{
var query = _buildCollection.Find(new BsonDocument(nameof(BuildModel.LabUrl), lab))
.Sort(sortByDate)
.Skip(skip);
if (limit > 0)
{
query = query.Limit(limit);
}
return await query.ToListAsync();
}
public async Task<long> SelectLabCount(string lab)
{
return await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.LabUrl), lab));
}
}
}

View File

@ -3,17 +3,31 @@
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models
{
public partial class Build
{
public Task<TypeOfSource[]> SelectAllSources(int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<TypeOfSource[]> SelectAllSources(int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<int> SelectAllSourcesCount() { throw new NotImplementedException(); }
public async Task<long> SelectAllSourcesCount() { throw new NotImplementedException(); }
public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int limit = -1, int skip = 0)
{
var query = _buildCollection.Find(new BsonDocument(nameof(BuildModel.SourceType), source))
.Sort(sortByOrder)
.Skip(skip);
public async Task<int> SelectSourceCount(TypeOfSource source) { throw new NotImplementedException(); }
if (limit > 0)
{
query = query.Limit(limit);
}
return await query.ToListAsync();
}
public async Task<long> SelectSourceCount(TypeOfSource source) { return await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.SourceType), source)); }
}
}

View File

@ -2,18 +2,84 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models
{
public partial class Build
{
public async Task<BuildVersion[]> SelectAllVersions(int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<BuildVersion[]> SelectAllVersions(int limit = -1, int skip = 0)
{
var query = _buildCollection.Aggregate()
.Group(new BsonDocument(
"_id", new BsonDocument
{
new BsonElement(nameof(BuildVersion.Major), $"${nameof(BuildModel.MajorVersion)}"),
new BsonElement(nameof(BuildVersion.Minor), $"${nameof(BuildModel.MinorVersion)}")
}))
.Sort(new BsonDocument
{
new BsonElement($"_id.{nameof(BuildVersion.Major)}", -1),
new BsonElement($"_id.{nameof(BuildVersion.Minor)}", -1)
})
.Skip(skip);
public async Task<int> SelectAllVersionsCount() { throw new NotImplementedException(); }
if (limit > 0)
{
query = query.Limit(limit);
}
public async Task<List<BuildModel>> SelectVersion(uint major, uint minor, int limit = -1, int skip = 0) { throw new NotImplementedException(); }
var grouping = await query.ToListAsync();
public async Task<int> SelectVersionCount(uint major, uint minor) { throw new NotImplementedException(); }
return (from g in grouping
select new BuildVersion
{
Major = (uint) g["_id"].AsBsonDocument[nameof(BuildVersion.Major)].AsInt32,
Minor = (uint) g["_id"].AsBsonDocument[nameof(BuildVersion.Minor)].AsInt32
}).ToArray();
}
public async Task<long> SelectAllVersionsCount()
{
var query = await _buildCollection.Aggregate()
.Group(new BsonDocument(
"_id", new BsonDocument
{
new BsonElement(nameof(BuildVersion.Major),
$"${nameof(BuildModel.MajorVersion)}"),
new BsonElement(nameof(BuildVersion.Minor),
$"${nameof(BuildModel.MinorVersion)}")
}))
.ToListAsync();
return query.Count;
}
public async Task<List<BuildModel>> SelectVersion(uint major, uint minor, int limit = -1, int skip = 0)
{
var query = _buildCollection.Find(new BsonDocument
{
new BsonElement(nameof(BuildModel.MajorVersion), major),
new BsonElement(nameof(BuildModel.MinorVersion), minor)
})
.Sort(sortByOrder)
.Skip(skip);
if (limit > 0)
{
query = query.Limit(limit);
}
return await query.ToListAsync();
}
public async Task<long> SelectVersionCount(uint major, uint minor)
{
return await _buildCollection.CountAsync(new BsonDocument
{
new BsonElement(nameof(BuildModel.MajorVersion), major),
new BsonElement(nameof(BuildModel.MinorVersion), minor)
});
}
}
}

View File

@ -2,18 +2,63 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models
{
public partial class Build
{
public async Task<int[]> SelectAllYears(int limit = -1, int skip = 0) { throw new NotImplementedException(); }
public async Task<int[]> SelectAllYears(int limit = -1, int skip = 0)
{
var query = _buildCollection.Aggregate()
.Group(new BsonDocument("_id", $"${nameof(BuildModel.BuildTime)}.{nameof(DateTime.Year)}"))
.Sort(new BsonDocument("_id", -1))
.Skip(skip);
public async Task<int> SelectAllYearsCount() { throw new NotImplementedException(); }
if (limit > 0)
{
query = query.Limit(limit);
}
public async Task<List<BuildModel>> SelectYear(int year, int limit = -1, int skip = 0) { throw new NotImplementedException(); }
var grouping = await query.ToListAsync();
public async Task<int> SelectYearCount(int year) { throw new NotImplementedException(); }
return (from g in grouping
select g["_id"].AsInt32).ToArray();
}
public async Task<long> SelectAllYearsCount()
{
var query = await _buildCollection.Aggregate()
.Group(new BsonDocument("_id", $"${nameof(BuildModel.BuildTime)}.{nameof(DateTime.Year)}"))
.ToListAsync();
return query.Count;
}
public async Task<List<BuildModel>> SelectYear(int year, int limit = -1, int skip = 0)
{
var query = _buildCollection.Find(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime,
new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
Builders<BuildModel>.Filter.Lte(b => b.BuildTime,
new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc))))
.Sort(sortByDate)
.Skip(skip);
if (limit > 0)
{
query = query.Limit(limit);
}
return await query.ToListAsync();
}
public async Task<long> SelectYearCount(int year)
{
return await _buildCollection.CountAsync(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime,
new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
Builders<BuildModel>.Filter.Lte(b => b.BuildTime,
new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc))));
}
}
}

View File

@ -11,6 +11,17 @@ namespace BuildFeed.Models
public partial class Build
{
private const string BUILD_COLLECTION_NAME = "builds";
private static readonly BsonDocument sortByDate = new BsonDocument(nameof(BuildModel.BuildTime), -1);
private static readonly BsonDocument sortByOrder = new BsonDocument
{
new BsonElement(nameof(BuildModel.MajorVersion), -1),
new BsonElement(nameof(BuildModel.MinorVersion), -1),
new BsonElement(nameof(BuildModel.Number), -1),
new BsonElement(nameof(BuildModel.Revision), -1),
new BsonElement(nameof(BuildModel.BuildTime), -1)
};
private readonly IMongoCollection<BuildModel> _buildCollection;
private readonly IMongoDatabase _buildDatabase;
private readonly MongoClient _dbClient;
@ -19,9 +30,9 @@ public Build()
{
_dbClient = new MongoClient
(new MongoClientSettings
{
Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port)
});
{
Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port)
});
_buildDatabase = _dbClient.GetDatabase(MongoConfig.Database);
_buildCollection = _buildDatabase.GetCollection<BuildModel>(BUILD_COLLECTION_NAME);
@ -32,26 +43,21 @@ public async Task SetupIndexes()
var indexes = await (await _buildCollection.Indexes.ListAsync()).ToListAsync();
if (indexes.All(i => i["name"] != "_idx_group"))
{
await _buildCollection.Indexes.CreateOneAsync
(Builders<BuildModel>.IndexKeys.Combine
(
Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.Number),
Builders<BuildModel>.IndexKeys.Descending(b => b.Revision)
), new CreateIndexOptions
{
Name = "_idx_group"
});
await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Combine(Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.Number),
Builders<BuildModel>.IndexKeys.Descending(b => b.Revision)), new CreateIndexOptions
{
Name = "_idx_group"
});
}
if (indexes.All(i => i["name"] != "_idx_legacy"))
{
await _buildCollection.Indexes.CreateOneAsync
(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId), new CreateIndexOptions
{
Name = "_idx_legacy"
});
await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId), new CreateIndexOptions
{
Name = "_idx_legacy"
});
}
}

View File

@ -1,25 +1,24 @@
var bfsAjax;
var bfsTimeout;
$(function () {
$("#page-navigation-search").click(function (event) {
$(function() {
$("#page-navigation-search").click(function(event) {
event.preventDefault();
$("#search-modal").modal('show');
$("#search-modal").modal("show");
});
$("#search-input").keyup(function () {
var search = $(this);
$("#search-input").keyup(function() {
$(this).parent().find(".list-group").remove();
if (typeof bfsTimeout != 'undefined') {
if (typeof bfsTimeout != "undefined") {
clearTimeout(bfsTimeout);
}
if (typeof bfsAjax != 'undefined' && bfsAjax.readyState != 4) {
if (typeof bfsAjax != "undefined" && bfsAjax.readyState != 4) {
bfsAjax.abort();
}
bfsTimeout = setTimeout(function (object) {
bfsAjax = $.ajax("/api/GetSearchResult/" + $("#search-input").val() + '/').done(function (data) {
bfsTimeout = setTimeout(function(object) {
bfsAjax = $.ajax("/api/GetSearchResult/" + $("#search-input").val() + "/").done(function(data) {
var template = $.templates("#result-template");
var content = $("<div class='list-group'></div>");
@ -28,14 +27,14 @@ $(function () {
$("#search-results").html(content);
$("#search-results a.list-group-item").click(function () {
ga('send', 'pageview', '/api/GetSearchResult/' + $("#search-input").val() + '/');
$("#search-results a.list-group-item").click(function() {
ga("send", "pageview", "/api/GetSearchResult/" + $("#search-input").val() + "/");
});
});
}, 200);
});
$("#lang-switcher a").click(function (event) {
$("#lang-switcher a").click(function(event) {
event.preventDefault();
var lang = $(this).data("lang");
document.cookie = "lang=" + lang + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";

View File

@ -42,7 +42,7 @@
</div>
}
</div>
@PaginationHelpers.PaginationBlock((int)ViewBag.PageNumber, (int)ViewBag.PageCount, "index", ViewContext.RouteData.Values)
@PaginationHelpers.PaginationBlock((int)ViewBag.PageNumber, (int)ViewBag.PageCount, "Index", ViewContext.RouteData.Values)
@section scripts
{
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5431719a661cbfd0" async="async"></script>

View File

@ -1,79 +1,99 @@
@model IEnumerable<BuildFeed.Models.BuildModel>
@using Humanizer;
@using BuildFeed.Local
@using BuildFeed.Models
@using Humanizer
@model IEnumerable<BuildFeed.Models.BuildModel>
@{
ViewBag.Title = string.Format("{0}{1} | {2}", string.Format(BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId), ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName);
ViewBag.Title = string.Format("{0}{1} | {2}", string.Format(Front.BuildsFrom, ViewBag.ItemId), ViewBag.PageNumber == 1 ? "" : string.Format(Common.PageTitleSegment, ViewBag.PageNumber), Common.SiteName);
}
@section head
{
@if (ViewBag.MetaItem != null)
{
<meta name="description" content="@ViewBag.MetaItem.MetaDescription" />
<meta property="og:description" content="@ViewBag.MetaItem.MetaDescription" />
<meta name="description" content="@ViewBag.MetaItem.MetaDescription"/>
<meta property="og:description" content="@ViewBag.MetaItem.MetaDescription"/>
}
else
{
string metaDesc = string.Format(BuildFeed.Local.Front.YearMetaGeneric, ViewBag.ItemId);
<meta name="description" content="@metaDesc" />
<meta property="og:description" content="@metaDesc" />
string metaDesc = string.Format(Front.YearMetaGeneric, ViewBag.ItemId);
<meta name="description" content="@metaDesc"/>
<meta property="og:description" content="@metaDesc"/>
}
@if (ViewBag.PageNumber != 1)
{
<meta name="robots" content="noindex, follow" />
<meta name="robots" content="noindex, follow"/>
}
}
<h1>@string.Format(BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId)</h1>
@if (ViewBag.MetaItem != null && !string.IsNullOrWhiteSpace(ViewBag.MetaItem.PageContent))
{
<h3>@BuildFeed.Local.Front.About</h3>
@Html.Raw(ViewBag.MetaItem.PageContent)
}
<h3>@BuildFeed.Local.Front.Share</h3>
<div class="addthis_sharing_toolbox"></div>
<h3>@BuildFeed.Local.Front.Listing</h3>
<div class="row">
@foreach (var build in Model)
{
<div class="col-md-2 col-sm-3 col-xs-6 build-group">
<h3 class="build-group-title no-wrapping" title="@build.Lab"><a href="@Url.Action("viewBuild", new {id = build.Id})">@string.Format("{0}.{1}.{2}.{3}", build.MajorVersion, build.MinorVersion, build.Number, build.Revision)</a></h3>
@if (User.Identity.IsAuthenticated)
{
<p>
<a href="@Url.Action("editBuild", new { id = build.Id })" class="btn btn-primary btn-xs">@BuildFeed.Local.Front.Edit</a>
@if (Roles.IsUserInRole("Administrators"))
{
<a href="@Url.Action("DeleteBuild", new { id = build.Id })" class="btn btn-danger btn-xs">@BuildFeed.Local.Front.Delete</a>
}
</p>
}
<p class="build-group-p">
@if (!string.IsNullOrEmpty(build.Lab))
{
<div class="no-wrapping" title="@build.Lab"><i class="fa fa-code-fork fa-fw"></i> @build.Lab</div>
}
@if (build.BuildTime.HasValue)
{
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-calendar fa-fw"></i> @build.BuildTime.Value.ToLongDateWithoutDay()</span><br />
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-clock-o fa-fw"></i> @build.BuildTime.Value.ToShortTimeString()</span><br />
}
</p>
<p>
@if (build.IsLeaked)
{
<span class="label label-success label-build-status">@BuildFeed.Local.Front.Public</span>
}
else
{
<span class="label label-danger label-build-status">@BuildFeed.Local.Front.Private</span>
}
</p>
</div>
}
</div>
@PaginationHelpers.PaginationBlock((int)ViewBag.PageNumber, (int)ViewBag.PageCount, "viewYear", ViewContext.RouteData.Values)
@section scripts
<h1>@string.Format(Front.BuildsFrom, ViewBag.ItemId)</h1>
@if (ViewBag.MetaItem != null && !string.IsNullOrWhiteSpace(ViewBag.MetaItem.PageContent))
{
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5431719a661cbfd0" async="async"></script>
}
<h3>@Front.About</h3>
@Html.Raw(ViewBag.MetaItem.PageContent)
}
<h3>@Front.Share</h3>
<div class="addthis_sharing_toolbox"></div>
<h3>@Front.Listing</h3>
<div class="row">
@foreach (BuildModel build in Model)
{
<div class="col-md-2 col-sm-3 col-xs-6 build-group">
<h3 class="build-group-title no-wrapping" title="@build.Lab">
<a href="@Url.Action("ViewBuild", new
{
id = build.Id
})">
@($"{build.MajorVersion}.{build.MinorVersion}.{build.Number}.{build.Revision}")
</a>
</h3>
@if (User.Identity.IsAuthenticated)
{
<p>
<a href="@Url.Action("EditBuild", new
{
id = build.Id
})" class="btn btn-primary btn-xs">
@Front.Edit</a>
@if (Roles.IsUserInRole("Administrators"))
{
<a href="@Url.Action("DeleteBuild", new
{
id = build.Id
})" class="btn btn-danger btn-xs">
@Front.Delete</a>
}
</p>
}
<p class="build-group-p">
@if (!string.IsNullOrEmpty(build.Lab))
{
<div class="no-wrapping" title="@build.Lab">
<i class="fa fa-code-fork fa-fw"></i> @build.Lab</div>
}
@if (build.BuildTime.HasValue)
{
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-calendar fa-fw"></i> @build.BuildTime.Value.ToLongDateWithoutDay()</span>
<br/>
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-clock-o fa-fw"></i> @build.BuildTime.Value.ToShortTimeString()</span>
<br/>
}
</p>
<p>
@if (build.IsLeaked)
{
<span class="label label-success label-build-status">@Front.Public</span>
}
else
{
<span class="label label-danger label-build-status">@Front.Private</span>
}
</p>
</div>
}
</div>
@PaginationHelpers.PaginationBlock((int) ViewBag.PageNumber, (int) ViewBag.PageCount, "viewYear", ViewContext.RouteData.Values)
@section scripts
{
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5431719a661cbfd0" async="async"></script>
}