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,11 +1,10 @@
@using BuildFeed.Code @using System.Web.Mvc.Html
@using System.Web.Mvc
@using System.Web.Mvc.Html
@using System.Web.Routing @using System.Web.Routing
@using BuildFeed.Code
@helper PaginationBlock(int currentPage, int totalPages, string view, RouteValueDictionary rd) @helper PaginationBlock(int currentPage, int totalPages, string view, RouteValueDictionary rd)
{ {
string multiView = view + "Page"; string multiView = view + "Page";
if (totalPages > 1) if (totalPages > 1)
{ {
<div class="text-center"> <div class="text-center">
@ -14,33 +13,65 @@
{ {
RouteValueDictionary rvd = new RouteValueDictionary(rd); RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd.Remove("page"); rvd.Remove("page");
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, rvd)</li> <li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, rvd)</li>
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&lsaquo;"), view, rvd)</li>
} }
else if (currentPage > 2) else if (currentPage > 2)
{ {
RouteValueDictionary firstRvd = new RouteValueDictionary(rd);
firstRvd.Remove("page");
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), view, firstRvd)</li>
RouteValueDictionary rvd = new RouteValueDictionary(rd); RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage - 1; rvd["page"] = currentPage - 1;
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&lsaquo;"), multiView, rvd)</li>
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&laquo;"), multiView, rvd)</li>
} }
else else
{ {
<li class="disabled"><span>&laquo;</span></li> <li class="disabled">
<span>&laquo;</span></li>
<li class="disabled">
<span>&lsaquo;</span>
</li>
} }
@{ @{
RouteValueDictionary rvdIndex = new RouteValueDictionary(rd); RouteValueDictionary rvdIndex = new RouteValueDictionary(rd);
rvdIndex.Remove("page"); rvdIndex.Remove("page");
IEnumerable<int> pages = new int[0];
} }
<li @((1 == currentPage) ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink("1", view)</li>
@for (int i = 2; i <= totalPages; i++) @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); RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = i; rvd["page"] = i;
<li @((i == currentPage) ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink(i.ToString(), multiView, rvd)</li> <li @(i == currentPage ? "class=active" : "")>@MvcIntrinsics.Html.ActionLink(i.ToString(), multiView, rvd)</li>
}
} }
@ -49,11 +80,19 @@
RouteValueDictionary rvd = new RouteValueDictionary(rd); RouteValueDictionary rvd = new RouteValueDictionary(rd);
rvd["page"] = currentPage + 1; rvd["page"] = currentPage + 1;
<li>@MvcIntrinsics.Html.ActionLink(HttpUtility.HtmlDecode("&raquo;"), multiView, rvd)</li> <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 else
{ {
<li class="disabled"><span>&raquo;</span></li> <li class="disabled">
<span>&rsaquo;</span></li>
<li class="disabled">
<span>&raquo;</span>
</li>
} }
</ul> </ul>
</div> </div>

View File

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

View File

@ -1,6 +1,4 @@
using BuildFeed.Code; using System;
using BuildFeed.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
@ -10,17 +8,19 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Mvc; using System.Web.Mvc;
using BuildFeed.Code;
using BuildFeed.Models;
namespace BuildFeed.Controllers namespace BuildFeed.Controllers
{ {
public class FrontController : LocalController public class FrontController : LocalController
{ {
private const int PAGE_SIZE = 96; private const int PAGE_SIZE = 72;
private readonly Build _bModel; private readonly Build _bModel;
private readonly MetaItem _mModel; private readonly MetaItem _mModel;
public FrontController() : base() public FrontController()
{ {
_bModel = new Build(); _bModel = new Build();
_mModel = new MetaItem(); _mModel = new MetaItem();
@ -59,7 +59,7 @@ public async Task<ActionResult> IndexPage(int page)
#endif #endif
public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, uint? revision = null) public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, uint? revision = null)
{ {
BuildGroup bg = new BuildGroup() BuildGroup bg = new BuildGroup
{ {
Major = major, Major = major,
Minor = minor, Minor = minor,
@ -69,9 +69,13 @@ public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, u
var builds = await _bModel.SelectGroup(bg); var builds = await _bModel.SelectGroup(bg);
return builds.Count() == 1 ? return builds.Count() == 1
RedirectToAction(nameof(ViewBuild), new { id = builds.Single().Id }) as ActionResult : ? RedirectToAction(nameof(ViewBuild), new
View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds)); {
id = builds.Single()
.Id
}) as ActionResult
: View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds));
} }
[Route("build/{id:guid}/", Name = "Build")] [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) public async Task<ActionResult> ViewBuild(Guid id)
{ {
BuildModel b = await _bModel.SelectById(id); BuildModel b = await _bModel.SelectById(id);
if (b == null) return new HttpNotFoundResult(); if (b == null)
{
return new HttpNotFoundResult();
}
return View(b); return View(b);
} }
@ -89,8 +96,14 @@ public async Task<ActionResult> ViewBuild(Guid id)
public async Task<ActionResult> ViewBuild(long id) public async Task<ActionResult> ViewBuild(long id)
{ {
BuildModel b = await _bModel.SelectByLegacyId(id); BuildModel b = await _bModel.SelectByLegacyId(id);
if (b == null) return new HttpNotFoundResult(); if (b == null)
return RedirectToAction(nameof(ViewBuild), new { id = b.Id }); {
return new HttpNotFoundResult();
}
return RedirectToAction(nameof(ViewBuild), new
{
id = b.Id
});
} }
[Route("twitter/{id:guid}/", Name = "Twitter")] [Route("twitter/{id:guid}/", Name = "Twitter")]
@ -101,7 +114,10 @@ public async Task<ActionResult> ViewBuild(long id)
public async Task<ActionResult> TwitterCard(Guid id) public async Task<ActionResult> TwitterCard(Guid id)
{ {
BuildModel b = await _bModel.SelectById(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"); string path = Path.Combine(Server.MapPath("~/content/card/"), $"{b.Family}.png");
bool backExists = System.IO.File.Exists(path); 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); 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("BUILDFEED", new FontFamily("Segoe UI"), (int) FontStyle.Bold, 32, new Point(40, 32),
gp.AddString($"{DisplayHelpers.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})", new FontFamily("Segoe UI"), 0, 48, new Point(40, 80), StringFormat.GenericTypographic); StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 280, new Point(32, 96), StringFormat.GenericTypographic); gp.AddString($"{DisplayHelpers.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})",
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); 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); gr.FillPath(Brushes.White, gp);
Response.ContentType = "image/png"; Response.ContentType = "image/png";
@ -141,8 +161,14 @@ public async Task<ActionResult> TwitterCard(Guid id)
public async Task<ActionResult> TwitterCard(long id) public async Task<ActionResult> TwitterCard(long id)
{ {
BuildModel b = await _bModel.SelectByLegacyId(id); BuildModel b = await _bModel.SelectByLegacyId(id);
if (b == null) return new HttpNotFoundResult(); if (b == null)
return RedirectToAction(nameof(TwitterCard), new { id = b.Id }); {
return new HttpNotFoundResult();
}
return RedirectToAction(nameof(TwitterCard), new
{
id = b.Id
});
} }
[Route("lab/{lab}/", Order = 1, Name = "Lab Root")] [Route("lab/{lab}/", Order = 1, Name = "Lab Root")]
@ -163,9 +189,10 @@ public async Task<ActionResult> ViewLabPage(string lab, int page)
Value = 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.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectLabCount(lab)) / Convert.ToDouble(PAGE_SIZE)); ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectLabCount(lab)) / Convert.ToDouble(PAGE_SIZE));
@ -196,7 +223,7 @@ public async Task<ActionResult> ViewSourcePage(TypeOfSource source, int page)
}); });
ViewBag.ItemId = DisplayHelpers.GetDisplayTextForEnum(source); 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.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectSourceCount(source)) / Convert.ToDouble(PAGE_SIZE)); ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectSourceCount(source)) / Convert.ToDouble(PAGE_SIZE));
@ -228,7 +255,7 @@ public async Task<ActionResult> ViewYearPage(int year, int page)
}); });
ViewBag.ItemId = 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.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(await _bModel.SelectYearCount(year) / Convert.ToDouble(PAGE_SIZE)); ViewBag.PageCount = Math.Ceiling(await _bModel.SelectYearCount(year) / Convert.ToDouble(PAGE_SIZE));
@ -261,7 +288,7 @@ public async Task<ActionResult> ViewVersionPage(uint major, uint minor, int page
}); });
ViewBag.ItemId = 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.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectVersionCount(major, minor)) / Convert.ToDouble(PAGE_SIZE)); ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(await _bModel.SelectVersionCount(major, minor)) / Convert.ToDouble(PAGE_SIZE));
@ -277,7 +304,7 @@ public async Task<ActionResult> ViewVersionPage(uint major, uint minor, int page
[Route("add/"), Authorize] [Route("add/"), Authorize]
public ActionResult AddBuild() public ActionResult AddBuild()
{ {
BuildModel b = new BuildModel() BuildModel b = new BuildModel
{ {
SourceType = TypeOfSource.PrivateLeak, SourceType = TypeOfSource.PrivateLeak,
FlightLevel = LevelOfFlight.None FlightLevel = LevelOfFlight.None
@ -345,7 +372,10 @@ public async Task<ActionResult> EditBuild(Guid id, BuildModel build)
return View(build); return View(build);
} }
return RedirectToAction(nameof(ViewBuild), new { id = build.Id }); return RedirectToAction(nameof(ViewBuild), new
{
id = build.Id
});
} }
return View(build); return View(build);
} }

View File

@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BuildFeed.Models.ViewModel.Front; 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.Minor)}", -1),
new BsonElement($"_id.{nameof(BuildGroup.Build)}", -1), new BsonElement($"_id.{nameof(BuildGroup.Build)}", -1),
new BsonElement($"_id.{nameof(BuildGroup.Revision)}", -1) new BsonElement($"_id.{nameof(BuildGroup.Revision)}", -1)
}); })
.Skip(skip);
if (limit > 0) if (limit > 0)
{ {
query = query query = query.Limit(limit);
.Limit(limit);
} }
var grouping = await query var grouping = await query.ToListAsync();
.Skip(skip)
.ToListAsync();
return (from g in grouping return (from g in grouping
select new FrontBuildGroup 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, Major = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Major)].AsInt32,
Minor = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Minor)].AsInt32, Minor = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Minor)].AsInt32,
Build = (uint) g["_id"].AsBsonDocument[nameof(BuildGroup.Build)].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(), LastBuild = g["date"].ToNullableUniversalTime(),
BuildCount = g["count"].AsInt32 BuildCount = g["count"].AsInt32
}).ToArray(); }).ToArray();
} }
public async Task<int> SelectAllGroupsCount() public async Task<long> SelectAllGroupsCount()
{ {
var grouping = await _buildCollection.Aggregate() var grouping = await _buildCollection.Aggregate()
.Group( .Group(
@ -80,8 +77,41 @@ public async Task<int> SelectAllGroupsCount()
return grouping.Count; 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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models namespace BuildFeed.Models
{ {
public partial class Build 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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models namespace BuildFeed.Models
{ {
public partial class Build 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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models namespace BuildFeed.Models
{ {
public partial class Build 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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using MongoDB.Bson;
using MongoDB.Driver;
namespace BuildFeed.Models namespace BuildFeed.Models
{ {
public partial class Build 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 public partial class Build
{ {
private const string BUILD_COLLECTION_NAME = "builds"; 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 IMongoCollection<BuildModel> _buildCollection;
private readonly IMongoDatabase _buildDatabase; private readonly IMongoDatabase _buildDatabase;
private readonly MongoClient _dbClient; private readonly MongoClient _dbClient;
@ -32,14 +43,10 @@ public async Task SetupIndexes()
var indexes = await (await _buildCollection.Indexes.ListAsync()).ToListAsync(); var indexes = await (await _buildCollection.Indexes.ListAsync()).ToListAsync();
if (indexes.All(i => i["name"] != "_idx_group")) if (indexes.All(i => i["name"] != "_idx_group"))
{ {
await _buildCollection.Indexes.CreateOneAsync await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Combine(Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion),
(Builders<BuildModel>.IndexKeys.Combine
(
Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion), Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.Number), Builders<BuildModel>.IndexKeys.Descending(b => b.Number),
Builders<BuildModel>.IndexKeys.Descending(b => b.Revision) Builders<BuildModel>.IndexKeys.Descending(b => b.Revision)), new CreateIndexOptions
), new CreateIndexOptions
{ {
Name = "_idx_group" Name = "_idx_group"
}); });
@ -47,8 +54,7 @@ await _buildCollection.Indexes.CreateOneAsync
if (indexes.All(i => i["name"] != "_idx_legacy")) if (indexes.All(i => i["name"] != "_idx_legacy"))
{ {
await _buildCollection.Indexes.CreateOneAsync await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId), new CreateIndexOptions
(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId), new CreateIndexOptions
{ {
Name = "_idx_legacy" Name = "_idx_legacy"
}); });

View File

@ -4,22 +4,21 @@ var bfsTimeout;
$(function() { $(function() {
$("#page-navigation-search").click(function(event) { $("#page-navigation-search").click(function(event) {
event.preventDefault(); event.preventDefault();
$("#search-modal").modal('show'); $("#search-modal").modal("show");
}); });
$("#search-input").keyup(function() { $("#search-input").keyup(function() {
var search = $(this);
$(this).parent().find(".list-group").remove(); $(this).parent().find(".list-group").remove();
if (typeof bfsTimeout != 'undefined') { if (typeof bfsTimeout != "undefined") {
clearTimeout(bfsTimeout); clearTimeout(bfsTimeout);
} }
if (typeof bfsAjax != 'undefined' && bfsAjax.readyState != 4) { if (typeof bfsAjax != "undefined" && bfsAjax.readyState != 4) {
bfsAjax.abort(); bfsAjax.abort();
} }
bfsTimeout = setTimeout(function(object) { bfsTimeout = setTimeout(function(object) {
bfsAjax = $.ajax("/api/GetSearchResult/" + $("#search-input").val() + '/').done(function (data) { bfsAjax = $.ajax("/api/GetSearchResult/" + $("#search-input").val() + "/").done(function(data) {
var template = $.templates("#result-template"); var template = $.templates("#result-template");
var content = $("<div class='list-group'></div>"); var content = $("<div class='list-group'></div>");
@ -29,7 +28,7 @@ $(function () {
$("#search-results").html(content); $("#search-results").html(content);
$("#search-results a.list-group-item").click(function() { $("#search-results a.list-group-item").click(function() {
ga('send', 'pageview', '/api/GetSearchResult/' + $("#search-input").val() + '/'); ga("send", "pageview", "/api/GetSearchResult/" + $("#search-input").val() + "/");
}); });
}); });
}, 200); }, 200);

View File

@ -42,7 +42,7 @@
</div> </div>
} }
</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 @section scripts
{ {
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5431719a661cbfd0" async="async"></script> <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5431719a661cbfd0" async="async"></script>

View File

@ -1,7 +1,9 @@
@model IEnumerable<BuildFeed.Models.BuildModel> @using BuildFeed.Local
@using Humanizer; @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 @section head
@ -13,7 +15,7 @@
} }
else else
{ {
string metaDesc = string.Format(BuildFeed.Local.Front.YearMetaGeneric, ViewBag.ItemId); string metaDesc = string.Format(Front.YearMetaGeneric, ViewBag.ItemId);
<meta name="description" content="@metaDesc"/> <meta name="description" content="@metaDesc"/>
<meta property="og:description" content="@metaDesc"/> <meta property="og:description" content="@metaDesc"/>
} }
@ -24,49 +26,67 @@
} }
} }
<h1>@string.Format(BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId)</h1> <h1>@string.Format(Front.BuildsFrom, ViewBag.ItemId)</h1>
@if (ViewBag.MetaItem != null && !string.IsNullOrWhiteSpace(ViewBag.MetaItem.PageContent)) @if (ViewBag.MetaItem != null && !string.IsNullOrWhiteSpace(ViewBag.MetaItem.PageContent))
{ {
<h3>@BuildFeed.Local.Front.About</h3> <h3>@Front.About</h3>
@Html.Raw(ViewBag.MetaItem.PageContent) @Html.Raw(ViewBag.MetaItem.PageContent)
} }
<h3>@BuildFeed.Local.Front.Share</h3> <h3>@Front.Share</h3>
<div class="addthis_sharing_toolbox"></div> <div class="addthis_sharing_toolbox"></div>
<h3>@BuildFeed.Local.Front.Listing</h3> <h3>@Front.Listing</h3>
<div class="row"> <div class="row">
@foreach (var build in Model) @foreach (BuildModel build in Model)
{ {
<div class="col-md-2 col-sm-3 col-xs-6 build-group"> <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> <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) @if (User.Identity.IsAuthenticated)
{ {
<p> <p>
<a href="@Url.Action("editBuild", new { id = build.Id })" class="btn btn-primary btn-xs">@BuildFeed.Local.Front.Edit</a> <a href="@Url.Action("EditBuild", new
{
id = build.Id
})" class="btn btn-primary btn-xs">
@Front.Edit</a>
@if (Roles.IsUserInRole("Administrators")) @if (Roles.IsUserInRole("Administrators"))
{ {
<a href="@Url.Action("DeleteBuild", new { id = build.Id })" class="btn btn-danger btn-xs">@BuildFeed.Local.Front.Delete</a> <a href="@Url.Action("DeleteBuild", new
{
id = build.Id
})" class="btn btn-danger btn-xs">
@Front.Delete</a>
} }
</p> </p>
} }
<p class="build-group-p"> <p class="build-group-p">
@if (!string.IsNullOrEmpty(build.Lab)) @if (!string.IsNullOrEmpty(build.Lab))
{ {
<div class="no-wrapping" title="@build.Lab"><i class="fa fa-code-fork fa-fw"></i> @build.Lab</div> <div class="no-wrapping" title="@build.Lab">
<i class="fa fa-code-fork fa-fw"></i> @build.Lab</div>
} }
@if (build.BuildTime.HasValue) @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-calendar fa-fw"></i> @build.BuildTime.Value.ToLongDateWithoutDay()</span>
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-clock-o fa-fw"></i> @build.BuildTime.Value.ToShortTimeString()</span><br /> <br/>
<span title="@build.BuildTime.Value.Humanize()"><i class="fa fa-clock-o fa-fw"></i> @build.BuildTime.Value.ToShortTimeString()</span>
<br/>
} }
</p> </p>
<p> <p>
@if (build.IsLeaked) @if (build.IsLeaked)
{ {
<span class="label label-success label-build-status">@BuildFeed.Local.Front.Public</span> <span class="label label-success label-build-status">@Front.Public</span>
} }
else else
{ {
<span class="label label-danger label-build-status">@BuildFeed.Local.Front.Private</span> <span class="label label-danger label-build-status">@Front.Private</span>
} }
</p> </p>
</div> </div>