mirror of
https://gitlab.com/buildfeed/BuildFeed.git
synced 2024-03-22 21:10:34 +08:00
Some UI Tweaks; Build Model refactoring
This commit is contained in:
parent
bdb7aa88af
commit
881b30c707
|
@ -768,7 +768,17 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Models\ApiModel\NewBuild.cs" />
|
<Compile Include="Models\ApiModel\NewBuild.cs" />
|
||||||
<Compile Include="Models\ApiModel\SearchResult.cs" />
|
<Compile Include="Models\ApiModel\SearchResult.cs" />
|
||||||
<Compile Include="Models\Build.cs" />
|
<Compile Include="Models\Build\Build-Source.cs" />
|
||||||
|
<Compile Include="Models\Build\Build-Year.cs" />
|
||||||
|
<Compile Include="Models\Build\Build-Lab.cs" />
|
||||||
|
<Compile Include="Models\Build\Build-Version.cs" />
|
||||||
|
<Compile Include="Models\Build\Build-Group.cs" />
|
||||||
|
<Compile Include="Models\Build\Build.cs" />
|
||||||
|
<Compile Include="Models\Build\BuildGroup.cs" />
|
||||||
|
<Compile Include="Models\Build\BuildModel.cs" />
|
||||||
|
<Compile Include="Models\Build\BuildVersion.cs" />
|
||||||
|
<Compile Include="Models\Build\LevelOfFlight.cs" />
|
||||||
|
<Compile Include="Models\Build\TypeOfSource.cs" />
|
||||||
<Compile Include="Models\MetaItem.cs" />
|
<Compile Include="Models\MetaItem.cs" />
|
||||||
<Compile Include="Models\ViewModel\Front\FrontBuildGroup.cs" />
|
<Compile Include="Models\ViewModel\Front\FrontBuildGroup.cs" />
|
||||||
<Compile Include="Models\ViewModel\LoginUser.cs" />
|
<Compile Include="Models\ViewModel\LoginUser.cs" />
|
||||||
|
|
|
@ -28,8 +28,8 @@ public async Task<BuildModel[]> GetBuilds(int limit = 20, int skip = 0)
|
||||||
public async Task<IEnumerable<string>> GetWin10Labs()
|
public async Task<IEnumerable<string>> GetWin10Labs()
|
||||||
{
|
{
|
||||||
List<string> labs = new List<string>();
|
List<string> labs = new List<string>();
|
||||||
labs.AddRange(await bModel.SelectBuildLabs(6, 4));
|
labs.AddRange(await bModel.SelectLabs(6, 4));
|
||||||
labs.AddRange(await bModel.SelectBuildLabs(10, 0));
|
labs.AddRange(await bModel.SelectLabs(10, 0));
|
||||||
|
|
||||||
return labs
|
return labs
|
||||||
.GroupBy(l => l)
|
.GroupBy(l => l)
|
||||||
|
@ -88,7 +88,7 @@ orderby s.Text.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascendi
|
||||||
results.AddRange(sourceResults);
|
results.AddRange(sourceResults);
|
||||||
|
|
||||||
|
|
||||||
var versionResults = from v in await bModel.SelectBuildVersions()
|
var versionResults = from v in await bModel.SelectVersions()
|
||||||
where $"{v.Major}.{v.Minor}".StartsWith(id)
|
where $"{v.Major}.{v.Minor}".StartsWith(id)
|
||||||
orderby v.Major descending, v.Minor descending
|
orderby v.Major descending, v.Minor descending
|
||||||
select new SearchResult()
|
select new SearchResult()
|
||||||
|
@ -102,7 +102,7 @@ orderby s.Text.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascendi
|
||||||
results.AddRange(versionResults);
|
results.AddRange(versionResults);
|
||||||
|
|
||||||
|
|
||||||
var yearResults = from y in await bModel.SelectBuildYears()
|
var yearResults = from y in await bModel.SelectYears()
|
||||||
where y.ToString().Contains(id)
|
where y.ToString().Contains(id)
|
||||||
orderby y descending
|
orderby y descending
|
||||||
select new SearchResult()
|
select new SearchResult()
|
||||||
|
|
|
@ -137,7 +137,7 @@ public ActionResult thanks_register()
|
||||||
[Route("rss")]
|
[Route("rss")]
|
||||||
public async Task<ActionResult> rss()
|
public async Task<ActionResult> rss()
|
||||||
{
|
{
|
||||||
ViewBag.Labs = await bModel.SelectBuildLabs();
|
ViewBag.Labs = await bModel.SelectLabs();
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ public async Task<ActionResult> sitemap()
|
||||||
{
|
{
|
||||||
UrlParams = new RouteValueDictionary(new
|
UrlParams = new RouteValueDictionary(new
|
||||||
{
|
{
|
||||||
controller = "build",
|
controller = "front",
|
||||||
action = "index",
|
action = "indexPage",
|
||||||
page = 1
|
page = 1
|
||||||
}),
|
}),
|
||||||
Pages = (builds.Count() + (frontController.PAGE_SIZE - 1)) / frontController.PAGE_SIZE
|
Pages = (builds.Count() + (frontController.PAGE_SIZE - 1)) / frontController.PAGE_SIZE
|
||||||
|
@ -394,9 +394,6 @@ orderby bl.Count() descending
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("credits/")]
|
[Route("credits/")]
|
||||||
public ActionResult credits()
|
public ActionResult credits() => View();
|
||||||
{
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,599 +0,0 @@
|
||||||
using BuildFeed.Local;
|
|
||||||
using BuildFeed.Models.ApiModel;
|
|
||||||
using BuildFeed.Models.ViewModel.Front;
|
|
||||||
using MongoDB.Bson;
|
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web.Mvc;
|
|
||||||
using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
|
|
||||||
|
|
||||||
namespace BuildFeed.Models
|
|
||||||
{
|
|
||||||
[DataObject]
|
|
||||||
public class BuildModel
|
|
||||||
{
|
|
||||||
[Key, BsonId]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
public long? LegacyId { get; set; }
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "MajorVersion")]
|
|
||||||
public byte MajorVersion { get; set; }
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "MinorVersion")]
|
|
||||||
public byte MinorVersion { get; set; }
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Number")]
|
|
||||||
public ushort Number { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Revision")]
|
|
||||||
[DisplayFormat(ConvertEmptyStringToNull = true)]
|
|
||||||
public ushort? Revision { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Lab")]
|
|
||||||
public string Lab { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "BuildTime")]
|
|
||||||
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:yyMMdd-HHmm}")]
|
|
||||||
public DateTime? BuildTime { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Added")]
|
|
||||||
public DateTime Added { get; set; }
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Modified")]
|
|
||||||
public DateTime Modified { get; set; }
|
|
||||||
|
|
||||||
[@Required]
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "SourceType")]
|
|
||||||
[EnumDataType(typeof(TypeOfSource))]
|
|
||||||
public TypeOfSource SourceType { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "SourceDetails")]
|
|
||||||
[AllowHtml]
|
|
||||||
public string SourceDetails { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "LeakDate")]
|
|
||||||
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
|
|
||||||
public DateTime? LeakDate { get; set; }
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightLevel")]
|
|
||||||
[EnumDataType(typeof(LevelOfFlight))]
|
|
||||||
public LevelOfFlight FlightLevel { get; set; }
|
|
||||||
|
|
||||||
public string LabUrl { get; set; }
|
|
||||||
|
|
||||||
public bool IsLeaked
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (SourceType)
|
|
||||||
{
|
|
||||||
case TypeOfSource.PublicRelease:
|
|
||||||
case TypeOfSource.InternalLeak:
|
|
||||||
case TypeOfSource.UpdateGDR:
|
|
||||||
case TypeOfSource.UpdateLDR:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FullBuildString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.AppendFormat("{0}.{1}.{2}", MajorVersion, MinorVersion, Number);
|
|
||||||
|
|
||||||
if (Revision.HasValue)
|
|
||||||
{
|
|
||||||
sb.AppendFormat(".{0}", Revision);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Lab))
|
|
||||||
{
|
|
||||||
sb.AppendFormat(".{0}", Lab);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuildTime.HasValue)
|
|
||||||
{
|
|
||||||
sb.AppendFormat(".{0:yyMMdd-HHmm}", BuildTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateLabUrl() => (Lab ?? "").Replace('/', '-').ToLower();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Build
|
|
||||||
{
|
|
||||||
private const string _buildCollectionName = "builds";
|
|
||||||
|
|
||||||
private MongoClient _dbClient;
|
|
||||||
private IMongoCollection<BuildModel> _buildCollection;
|
|
||||||
|
|
||||||
public Build()
|
|
||||||
{
|
|
||||||
_dbClient = new MongoClient(new MongoClientSettings()
|
|
||||||
{
|
|
||||||
Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port)
|
|
||||||
});
|
|
||||||
|
|
||||||
_buildCollection = _dbClient.GetDatabase(MongoConfig.Database).GetCollection<BuildModel>(_buildCollectionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
|
||||||
public async Task<List<BuildModel>> Select()
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument()).ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
|
||||||
public async Task<List<BuildModel>> SelectLatest(int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument())
|
|
||||||
.SortByDescending(b => b.Added)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
|
||||||
public async Task<List<BuildModel>> SelectLatestLeaked(int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.LeakDate != null)
|
|
||||||
.SortByDescending(b => b.LeakDate)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<FrontBuildGroup>> SelectBuildGroups(int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Aggregate()
|
|
||||||
.Group(b => new BuildGroup()
|
|
||||||
{
|
|
||||||
Major = b.MajorVersion,
|
|
||||||
Minor = b.MinorVersion,
|
|
||||||
Build = b.Number,
|
|
||||||
Revision = b.Revision
|
|
||||||
},
|
|
||||||
bg => new FrontBuildGroup()
|
|
||||||
{
|
|
||||||
Key = bg.Key,
|
|
||||||
BuildCount = bg.Count(),
|
|
||||||
LastBuild = bg.Max(b => b.BuildTime)
|
|
||||||
})
|
|
||||||
.SortByDescending(b => b.Key.Major)
|
|
||||||
.ThenByDescending(b => b.Key.Minor)
|
|
||||||
.ThenByDescending(b => b.Key.Build)
|
|
||||||
.ThenByDescending(b => b.Key.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
|
||||||
public async Task<int> SelectBuildGroupsCount()
|
|
||||||
{
|
|
||||||
var pipeline = _buildCollection.Aggregate()
|
|
||||||
.Group(b => new BuildGroup()
|
|
||||||
{
|
|
||||||
Major = b.MajorVersion,
|
|
||||||
Minor = b.MinorVersion,
|
|
||||||
Build = b.Number,
|
|
||||||
Revision = b.Revision
|
|
||||||
},
|
|
||||||
bg => new BsonDocument());
|
|
||||||
|
|
||||||
return (await pipeline.ToListAsync()).Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<Tuple<BuildGroup, List<BuildModel>>> SelectSingleBuildGroup(BuildGroup bGroup)
|
|
||||||
{
|
|
||||||
var pipeline = _buildCollection.Aggregate()
|
|
||||||
.Match(b => b.MajorVersion == bGroup.Major)
|
|
||||||
.Match(b => b.MinorVersion == bGroup.Minor)
|
|
||||||
.Match(b => b.Number == bGroup.Build)
|
|
||||||
.Match(b => b.Revision == bGroup.Revision)
|
|
||||||
.SortByDescending(b => b.BuildTime);
|
|
||||||
|
|
||||||
return new Tuple<BuildGroup, List<BuildModel>>(bGroup, await pipeline.ToListAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<BuildModel> SelectById(Guid id)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(f => f.Id == id).SingleOrDefaultAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<BuildModel> SelectByLegacyId(long id)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(f => f.LegacyId == id).SingleOrDefaultAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectInBuildOrder()
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument())
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectInBuildOrder(int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument())
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectInVersionOrder()
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument())
|
|
||||||
.SortByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.ThenByDescending(b => b.BuildTime)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectInVersionOrder(int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(new BsonDocument())
|
|
||||||
.SortByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.ThenByDescending(b => b.BuildTime)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectFlight(LevelOfFlight flight, int limit, int skip)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.FlightLevel == flight)
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectLab(string lab, int skip, int limit)
|
|
||||||
{
|
|
||||||
string labUrl = lab.Replace('/', '-').ToLower();
|
|
||||||
return await _buildCollection.Find(b => b.Lab != null && b.LabUrl == labUrl)
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<long> SelectLabCount(string lab)
|
|
||||||
{
|
|
||||||
string labUrl = lab.Replace('/', '-').ToLower();
|
|
||||||
return await _buildCollection.Find(b => b.Lab != null && b.LabUrl == labUrl)
|
|
||||||
.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int skip, int limit)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.SourceType == source)
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<long> SelectSourceCount(TypeOfSource source)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.SourceType == source)
|
|
||||||
.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectYear(int year, int skip, int limit)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.BuildTime != null &&
|
|
||||||
(b.BuildTime > new DateTime(year, 1, 1, 0, 0, 0)) &&
|
|
||||||
(b.BuildTime < new DateTime(year, 12, 31, 23, 59, 59)))
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<long> SelectYearCount(int year)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.BuildTime != null &&
|
|
||||||
(b.BuildTime > new DateTime(year, 1, 1, 0, 0, 0)) &&
|
|
||||||
(b.BuildTime < new DateTime(year, 12, 31, 23, 59, 59)))
|
|
||||||
.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildModel>> SelectVersion(int major, int minor, int skip, int limit)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.MajorVersion == major && b.MinorVersion == minor)
|
|
||||||
.SortByDescending(b => b.BuildTime)
|
|
||||||
.ThenByDescending(b => b.MajorVersion)
|
|
||||||
.ThenByDescending(b => b.MinorVersion)
|
|
||||||
.ThenByDescending(b => b.Number)
|
|
||||||
.ThenByDescending(b => b.Revision)
|
|
||||||
.Skip(skip)
|
|
||||||
.Limit(limit)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<long> SelectVersionCount(int major, int minor)
|
|
||||||
{
|
|
||||||
return await _buildCollection.Find(b => b.MajorVersion == major && b.MinorVersion == minor)
|
|
||||||
.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<BuildVersion>> SelectBuildVersions()
|
|
||||||
{
|
|
||||||
var result = await _buildCollection.Aggregate()
|
|
||||||
.Group(b => new BuildVersion()
|
|
||||||
{
|
|
||||||
Major = b.MajorVersion,
|
|
||||||
Minor = b.MinorVersion,
|
|
||||||
},
|
|
||||||
// incoming bullshit hack
|
|
||||||
bg => new Tuple<BuildVersion>(bg.Key))
|
|
||||||
.SortByDescending(b => b.Item1.Major)
|
|
||||||
.ThenByDescending(b => b.Item1.Minor)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// work ourselves out of aforementioned bullshit hack
|
|
||||||
return result.Select(b => b.Item1).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<int>> SelectBuildYears()
|
|
||||||
{
|
|
||||||
var result = await _buildCollection.Aggregate()
|
|
||||||
.Match(b => b.BuildTime != null)
|
|
||||||
.Group(b => ((DateTime)b.BuildTime).Year,
|
|
||||||
// incoming bullshit hack
|
|
||||||
bg => new Tuple<int>(bg.Key))
|
|
||||||
.SortByDescending(b => b.Item1)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// work ourselves out of aforementioned bullshit hack
|
|
||||||
return result.Select(b => b.Item1).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<string>> SearchBuildLabs(string query)
|
|
||||||
{
|
|
||||||
var result = await _buildCollection.Aggregate()
|
|
||||||
.Match(b => b.Lab != null)
|
|
||||||
.Match(b => b.Lab != "")
|
|
||||||
.Match(b => b.Lab.ToLower().Contains(query.ToLower()))
|
|
||||||
.Group(b => b.Lab.ToLower(),
|
|
||||||
// incoming bullshit hack
|
|
||||||
bg => new Tuple<string>(bg.Key))
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// work ourselves out of aforementioned bullshit hack
|
|
||||||
return result.Select(b => b.Item1).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<string>> SelectBuildLabs()
|
|
||||||
{
|
|
||||||
var result = await _buildCollection.Aggregate()
|
|
||||||
.Match(b => b.Lab != null)
|
|
||||||
.Match(b => b.Lab != "")
|
|
||||||
.Group(b => b.Lab.ToLower(),
|
|
||||||
// incoming bullshit hack
|
|
||||||
bg => new Tuple<string>(bg.Key))
|
|
||||||
.SortBy(b => b.Item1)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// work ourselves out of aforementioned bullshit hack
|
|
||||||
return result.Select(b => b.Item1).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
|
||||||
public async Task<List<string>> SelectBuildLabs(byte major, byte minor)
|
|
||||||
{
|
|
||||||
var result = await _buildCollection.Aggregate()
|
|
||||||
.Match(b => b.MajorVersion == major)
|
|
||||||
.Match(b => b.MinorVersion == minor)
|
|
||||||
.Match(b => b.Lab != null)
|
|
||||||
.Match(b => b.Lab != "")
|
|
||||||
.Group(b => b.Lab.ToLower(),
|
|
||||||
// incoming bullshit hack
|
|
||||||
bg => new Tuple<string>(bg.Key))
|
|
||||||
.SortBy(b => b.Item1)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// work ourselves out of aforementioned bullshit hack
|
|
||||||
return result.Select(b => b.Item1).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Insert, true)]
|
|
||||||
public async Task Insert(BuildModel item)
|
|
||||||
{
|
|
||||||
item.Id = Guid.NewGuid();
|
|
||||||
item.LabUrl = item.GenerateLabUrl();
|
|
||||||
await _buildCollection.InsertOneAsync(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Insert, false)]
|
|
||||||
public async Task InsertAll(IEnumerable<BuildModel> items)
|
|
||||||
{
|
|
||||||
foreach(var item in items)
|
|
||||||
{
|
|
||||||
item.Id = Guid.NewGuid();
|
|
||||||
item.LabUrl = item.GenerateLabUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _buildCollection.InsertManyAsync(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Update, true)]
|
|
||||||
public async Task Update(BuildModel item)
|
|
||||||
{
|
|
||||||
BuildModel old = await SelectById(item.Id);
|
|
||||||
item.Added = old.Added;
|
|
||||||
item.Modified = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
|
|
||||||
item.LabUrl = item.GenerateLabUrl();
|
|
||||||
|
|
||||||
await _buildCollection.ReplaceOneAsync(f => f.Id == item.Id, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataObjectMethod(DataObjectMethodType.Delete, true)]
|
|
||||||
public async Task DeleteById(Guid id)
|
|
||||||
{
|
|
||||||
await _buildCollection.DeleteOneAsync(f => f.Id == id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TypeOfSource
|
|
||||||
{
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "PublicRelease")]
|
|
||||||
PublicRelease = 0,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "InternalLeak")]
|
|
||||||
InternalLeak = 1,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "UpdateGDR")]
|
|
||||||
UpdateGDR = 2,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "UpdateLDR")]
|
|
||||||
UpdateLDR = 3,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "AppPackage")]
|
|
||||||
AppPackage = 4,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "BuildTools")]
|
|
||||||
BuildTools = 5,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Documentation")]
|
|
||||||
Documentation = 6,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "Logging")]
|
|
||||||
Logging = 7,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "PrivateLeak")]
|
|
||||||
PrivateLeak = 8
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum LevelOfFlight
|
|
||||||
{
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightNone")]
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightWIS")]
|
|
||||||
WIS = 1,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightWIF")]
|
|
||||||
WIF = 2,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightOSG")]
|
|
||||||
OSG = 3,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightMSIT")]
|
|
||||||
MSIT = 4,
|
|
||||||
|
|
||||||
[Display(ResourceType = typeof(Model), Name = "FlightCanary")]
|
|
||||||
Canary = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BuildVersion
|
|
||||||
{
|
|
||||||
public byte Major { get; set; }
|
|
||||||
public byte Minor { get; set; }
|
|
||||||
|
|
||||||
public BuildVersion()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public BuildVersion(byte major, byte minor)
|
|
||||||
{
|
|
||||||
Major = major;
|
|
||||||
Minor = minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Major}.{Minor}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BuildGroup
|
|
||||||
{
|
|
||||||
public byte Major { get; set; }
|
|
||||||
public byte Minor { get; set; }
|
|
||||||
public ushort Build { get; set; }
|
|
||||||
public ushort? Revision { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Revision.HasValue ?
|
|
||||||
$"{Major}.{Minor}.{Build}.{Revision.Value}" :
|
|
||||||
$"{Major}.{Minor}.{Build}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
69
BuildFeed/Models/Build/Build-Group.cs
Normal file
69
BuildFeed/Models/Build/Build-Group.cs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
using BuildFeed.Models.ViewModel.Front;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<FrontBuildGroup>> SelectBuildGroups(int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Aggregate()
|
||||||
|
.Group(b => new BuildGroup()
|
||||||
|
{
|
||||||
|
Major = b.MajorVersion,
|
||||||
|
Minor = b.MinorVersion,
|
||||||
|
Build = b.Number,
|
||||||
|
Revision = b.Revision
|
||||||
|
},
|
||||||
|
bg => new FrontBuildGroup()
|
||||||
|
{
|
||||||
|
Key = bg.Key,
|
||||||
|
BuildCount = bg.Count(),
|
||||||
|
LastBuild = bg.Max(b => b.BuildTime)
|
||||||
|
})
|
||||||
|
.SortByDescending(b => b.Key.Major)
|
||||||
|
.ThenByDescending(b => b.Key.Minor)
|
||||||
|
.ThenByDescending(b => b.Key.Build)
|
||||||
|
.ThenByDescending(b => b.Key.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
||||||
|
public async Task<int> SelectBuildGroupsCount()
|
||||||
|
{
|
||||||
|
var pipeline = _buildCollection.Aggregate()
|
||||||
|
.Group(b => new BuildGroup()
|
||||||
|
{
|
||||||
|
Major = b.MajorVersion,
|
||||||
|
Minor = b.MinorVersion,
|
||||||
|
Build = b.Number,
|
||||||
|
Revision = b.Revision
|
||||||
|
},
|
||||||
|
bg => new BsonDocument());
|
||||||
|
|
||||||
|
return (await pipeline.ToListAsync()).Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<Tuple<BuildGroup, List<BuildModel>>> SelectSingleBuildGroup(BuildGroup bGroup)
|
||||||
|
{
|
||||||
|
var pipeline = _buildCollection.Aggregate()
|
||||||
|
.Match(b => b.MajorVersion == bGroup.Major)
|
||||||
|
.Match(b => b.MinorVersion == bGroup.Minor)
|
||||||
|
.Match(b => b.Number == bGroup.Build)
|
||||||
|
.Match(b => b.Revision == bGroup.Revision)
|
||||||
|
.SortByDescending(b => b.BuildTime);
|
||||||
|
|
||||||
|
return new Tuple<BuildGroup, List<BuildModel>>(bGroup, await pipeline.ToListAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
BuildFeed/Models/Build/Build-Lab.cs
Normal file
86
BuildFeed/Models/Build/Build-Lab.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectLab(string lab, int skip, int limit)
|
||||||
|
{
|
||||||
|
string labUrl = lab.Replace('/', '-').ToLower();
|
||||||
|
return await _buildCollection.Find(b => b.Lab != null && b.LabUrl == labUrl)
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<string>> SelectLabs()
|
||||||
|
{
|
||||||
|
var result = await _buildCollection.Aggregate()
|
||||||
|
.Match(b => b.Lab != null)
|
||||||
|
.Match(b => b.Lab != "")
|
||||||
|
.Group(b => b.Lab.ToLower(),
|
||||||
|
// incoming bullshit hack
|
||||||
|
bg => new Tuple<string>(bg.Key))
|
||||||
|
.SortBy(b => b.Item1)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// work ourselves out of aforementioned bullshit hack
|
||||||
|
return result.Select(b => b.Item1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<string>> SelectLabs(byte major, byte minor)
|
||||||
|
{
|
||||||
|
var result = await _buildCollection.Aggregate()
|
||||||
|
.Match(b => b.MajorVersion == major)
|
||||||
|
.Match(b => b.MinorVersion == minor)
|
||||||
|
.Match(b => b.Lab != null)
|
||||||
|
.Match(b => b.Lab != "")
|
||||||
|
.Group(b => b.Lab.ToLower(),
|
||||||
|
// incoming bullshit hack
|
||||||
|
bg => new Tuple<string>(bg.Key))
|
||||||
|
.SortBy(b => b.Item1)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// work ourselves out of aforementioned bullshit hack
|
||||||
|
return result.Select(b => b.Item1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<long> SelectLabCount(string lab)
|
||||||
|
{
|
||||||
|
string labUrl = lab.Replace('/', '-').ToLower();
|
||||||
|
return await _buildCollection.Find(b => b.Lab != null && b.LabUrl == labUrl)
|
||||||
|
.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<string>> SearchBuildLabs(string query)
|
||||||
|
{
|
||||||
|
var result = await _buildCollection.Aggregate()
|
||||||
|
.Match(b => b.Lab != null)
|
||||||
|
.Match(b => b.Lab != "")
|
||||||
|
.Match(b => b.Lab.ToLower().Contains(query.ToLower()))
|
||||||
|
.Group(b => b.Lab.ToLower(),
|
||||||
|
// incoming bullshit hack
|
||||||
|
bg => new Tuple<string>(bg.Key))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// work ourselves out of aforementioned bullshit hack
|
||||||
|
return result.Select(b => b.Item1).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
BuildFeed/Models/Build/Build-Source.cs
Normal file
32
BuildFeed/Models/Build/Build-Source.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int skip, int limit)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.SourceType == source)
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<long> SelectSourceCount(TypeOfSource source)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.SourceType == source)
|
||||||
|
.CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
BuildFeed/Models/Build/Build-Version.cs
Normal file
79
BuildFeed/Models/Build/Build-Version.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectInVersionOrder()
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument())
|
||||||
|
.SortByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.ThenByDescending(b => b.BuildTime)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectInVersionOrder(int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument())
|
||||||
|
.SortByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.ThenByDescending(b => b.BuildTime)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectVersion(int major, int minor, int skip, int limit)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.MajorVersion == major && b.MinorVersion == minor)
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildVersion>> SelectVersions()
|
||||||
|
{
|
||||||
|
var result = await _buildCollection.Aggregate()
|
||||||
|
.Group(b => new BuildVersion()
|
||||||
|
{
|
||||||
|
Major = b.MajorVersion,
|
||||||
|
Minor = b.MinorVersion,
|
||||||
|
},
|
||||||
|
// incoming bullshit hack
|
||||||
|
bg => new Tuple<BuildVersion>(bg.Key))
|
||||||
|
.SortByDescending(b => b.Item1.Major)
|
||||||
|
.ThenByDescending(b => b.Item1.Minor)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// work ourselves out of aforementioned bullshit hack
|
||||||
|
return result.Select(b => b.Item1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<long> SelectVersionCount(int major, int minor)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.MajorVersion == major && b.MinorVersion == minor)
|
||||||
|
.CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
BuildFeed/Models/Build/Build-Year.cs
Normal file
52
BuildFeed/Models/Build/Build-Year.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectYear(int year, int skip, int limit)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.BuildTime != null &&
|
||||||
|
(b.BuildTime > new DateTime(year, 1, 1, 0, 0, 0)) &&
|
||||||
|
(b.BuildTime < new DateTime(year, 12, 31, 23, 59, 59)))
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<int>> SelectYears()
|
||||||
|
{
|
||||||
|
var result = await _buildCollection.Aggregate()
|
||||||
|
.Match(b => b.BuildTime != null)
|
||||||
|
.Group(b => ((DateTime)b.BuildTime).Year,
|
||||||
|
// incoming bullshit hack
|
||||||
|
bg => new Tuple<int>(bg.Key))
|
||||||
|
.SortByDescending(b => b.Item1)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// work ourselves out of aforementioned bullshit hack
|
||||||
|
return result.Select(b => b.Item1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<long> SelectYearCount(int year)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.BuildTime != null &&
|
||||||
|
(b.BuildTime > new DateTime(year, 1, 1, 0, 0, 0)) &&
|
||||||
|
(b.BuildTime < new DateTime(year, 12, 31, 23, 59, 59)))
|
||||||
|
.CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
146
BuildFeed/Models/Build/Build.cs
Normal file
146
BuildFeed/Models/Build/Build.cs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
using BuildFeed.Models.ViewModel.Front;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial class Build
|
||||||
|
{
|
||||||
|
private const string _buildCollectionName = "builds";
|
||||||
|
|
||||||
|
private MongoClient _dbClient;
|
||||||
|
private IMongoCollection<BuildModel> _buildCollection;
|
||||||
|
|
||||||
|
public Build()
|
||||||
|
{
|
||||||
|
_dbClient = new MongoClient(new MongoClientSettings()
|
||||||
|
{
|
||||||
|
Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port)
|
||||||
|
});
|
||||||
|
|
||||||
|
_buildCollection = _dbClient.GetDatabase(MongoConfig.Database).GetCollection<BuildModel>(_buildCollectionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
||||||
|
public async Task<List<BuildModel>> Select()
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument()).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
||||||
|
public async Task<List<BuildModel>> SelectLatest(int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument())
|
||||||
|
.SortByDescending(b => b.Added)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, true)]
|
||||||
|
public async Task<List<BuildModel>> SelectLatestLeaked(int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.LeakDate != null)
|
||||||
|
.SortByDescending(b => b.LeakDate)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<BuildModel> SelectById(Guid id)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(f => f.Id == id).SingleOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<BuildModel> SelectByLegacyId(long id)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(f => f.LegacyId == id).SingleOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectInBuildOrder()
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument())
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectInBuildOrder(int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(new BsonDocument())
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
|
public async Task<List<BuildModel>> SelectFlight(LevelOfFlight flight, int limit, int skip)
|
||||||
|
{
|
||||||
|
return await _buildCollection.Find(b => b.FlightLevel == flight)
|
||||||
|
.SortByDescending(b => b.BuildTime)
|
||||||
|
.ThenByDescending(b => b.MajorVersion)
|
||||||
|
.ThenByDescending(b => b.MinorVersion)
|
||||||
|
.ThenByDescending(b => b.Number)
|
||||||
|
.ThenByDescending(b => b.Revision)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(limit)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Insert, true)]
|
||||||
|
public async Task Insert(BuildModel item)
|
||||||
|
{
|
||||||
|
item.Id = Guid.NewGuid();
|
||||||
|
item.LabUrl = item.GenerateLabUrl();
|
||||||
|
await _buildCollection.InsertOneAsync(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Insert, false)]
|
||||||
|
public async Task InsertAll(IEnumerable<BuildModel> items)
|
||||||
|
{
|
||||||
|
foreach(var item in items)
|
||||||
|
{
|
||||||
|
item.Id = Guid.NewGuid();
|
||||||
|
item.LabUrl = item.GenerateLabUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _buildCollection.InsertManyAsync(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Update, true)]
|
||||||
|
public async Task Update(BuildModel item)
|
||||||
|
{
|
||||||
|
BuildModel old = await SelectById(item.Id);
|
||||||
|
item.Added = old.Added;
|
||||||
|
item.Modified = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
|
||||||
|
item.LabUrl = item.GenerateLabUrl();
|
||||||
|
|
||||||
|
await _buildCollection.ReplaceOneAsync(f => f.Id == item.Id, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataObjectMethod(DataObjectMethodType.Delete, true)]
|
||||||
|
public async Task DeleteById(Guid id)
|
||||||
|
{
|
||||||
|
await _buildCollection.DeleteOneAsync(f => f.Id == id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
BuildFeed/Models/Build/BuildGroup.cs
Normal file
14
BuildFeed/Models/Build/BuildGroup.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public class BuildGroup
|
||||||
|
{
|
||||||
|
public byte Major { get; set; }
|
||||||
|
public byte Minor { get; set; }
|
||||||
|
public ushort Build { get; set; }
|
||||||
|
public ushort? Revision { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() => Revision.HasValue ?
|
||||||
|
$"{Major}.{Minor}.{Build}.{Revision.Value}" :
|
||||||
|
$"{Major}.{Minor}.{Build}";
|
||||||
|
}
|
||||||
|
}
|
116
BuildFeed/Models/Build/BuildModel.cs
Normal file
116
BuildFeed/Models/Build/BuildModel.cs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
using BuildFeed.Local;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
[DataObject]
|
||||||
|
public class BuildModel
|
||||||
|
{
|
||||||
|
[Key, BsonId]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public long? LegacyId { get; set; }
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "MajorVersion")]
|
||||||
|
public byte MajorVersion { get; set; }
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "MinorVersion")]
|
||||||
|
public byte MinorVersion { get; set; }
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Number")]
|
||||||
|
public ushort Number { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Revision")]
|
||||||
|
[DisplayFormat(ConvertEmptyStringToNull = true)]
|
||||||
|
public ushort? Revision { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Lab")]
|
||||||
|
public string Lab { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "BuildTime")]
|
||||||
|
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:yyMMdd-HHmm}")]
|
||||||
|
public DateTime? BuildTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Added")]
|
||||||
|
public DateTime Added { get; set; }
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Modified")]
|
||||||
|
public DateTime Modified { get; set; }
|
||||||
|
|
||||||
|
[@Required]
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "SourceType")]
|
||||||
|
[EnumDataType(typeof(TypeOfSource))]
|
||||||
|
public TypeOfSource SourceType { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "SourceDetails")]
|
||||||
|
[AllowHtml]
|
||||||
|
public string SourceDetails { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "LeakDate")]
|
||||||
|
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
|
||||||
|
public DateTime? LeakDate { get; set; }
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightLevel")]
|
||||||
|
[EnumDataType(typeof(LevelOfFlight))]
|
||||||
|
public LevelOfFlight FlightLevel { get; set; }
|
||||||
|
|
||||||
|
public string LabUrl { get; set; }
|
||||||
|
|
||||||
|
public bool IsLeaked
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (SourceType)
|
||||||
|
{
|
||||||
|
case TypeOfSource.PublicRelease:
|
||||||
|
case TypeOfSource.InternalLeak:
|
||||||
|
case TypeOfSource.UpdateGDR:
|
||||||
|
case TypeOfSource.UpdateLDR:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FullBuildString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("{0}.{1}.{2}", MajorVersion, MinorVersion, Number);
|
||||||
|
|
||||||
|
if (Revision.HasValue)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(".{0}", Revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(Lab))
|
||||||
|
{
|
||||||
|
sb.AppendFormat(".{0}", Lab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BuildTime.HasValue)
|
||||||
|
{
|
||||||
|
sb.AppendFormat(".{0:yyMMdd-HHmm}", BuildTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateLabUrl() => (Lab ?? "").Replace('/', '-').ToLower();
|
||||||
|
}
|
||||||
|
}
|
21
BuildFeed/Models/Build/BuildVersion.cs
Normal file
21
BuildFeed/Models/Build/BuildVersion.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
|
||||||
|
public class BuildVersion
|
||||||
|
{
|
||||||
|
public byte Major { get; set; }
|
||||||
|
public byte Minor { get; set; }
|
||||||
|
|
||||||
|
public BuildVersion()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildVersion(byte major, byte minor)
|
||||||
|
{
|
||||||
|
Major = major;
|
||||||
|
Minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => $"{Major}.{Minor}";
|
||||||
|
}
|
||||||
|
}
|
26
BuildFeed/Models/Build/LevelOfFlight.cs
Normal file
26
BuildFeed/Models/Build/LevelOfFlight.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using BuildFeed.Local;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public enum LevelOfFlight
|
||||||
|
{
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightNone")]
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightWIS")]
|
||||||
|
WIS = 1,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightWIF")]
|
||||||
|
WIF = 2,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightOSG")]
|
||||||
|
OSG = 3,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightMSIT")]
|
||||||
|
MSIT = 4,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "FlightCanary")]
|
||||||
|
Canary = 5
|
||||||
|
}
|
||||||
|
}
|
35
BuildFeed/Models/Build/TypeOfSource.cs
Normal file
35
BuildFeed/Models/Build/TypeOfSource.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using BuildFeed.Local;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace BuildFeed.Models
|
||||||
|
{
|
||||||
|
public enum TypeOfSource
|
||||||
|
{
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "PublicRelease")]
|
||||||
|
PublicRelease = 0,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "InternalLeak")]
|
||||||
|
InternalLeak = 1,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "UpdateGDR")]
|
||||||
|
UpdateGDR = 2,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "UpdateLDR")]
|
||||||
|
UpdateLDR = 3,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "AppPackage")]
|
||||||
|
AppPackage = 4,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "BuildTools")]
|
||||||
|
BuildTools = 5,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Documentation")]
|
||||||
|
Documentation = 6,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "Logging")]
|
||||||
|
Logging = 7,
|
||||||
|
|
||||||
|
[Display(ResourceType = typeof(Model), Name = "PrivateLeak")]
|
||||||
|
PrivateLeak = 8
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,7 +74,7 @@ public async Task<MetaItemModel> SelectById(MetaItemKey id)
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
public async Task<IEnumerable<string>> SelectUnusedLabs()
|
public async Task<IEnumerable<string>> SelectUnusedLabs()
|
||||||
{
|
{
|
||||||
var labs = await bModel.SelectBuildLabs();
|
var labs = await bModel.SelectLabs();
|
||||||
|
|
||||||
var usedLabs = await _metaCollection.Find(f => f.Id.Type == MetaType.Lab).ToListAsync();
|
var usedLabs = await _metaCollection.Find(f => f.Id.Type == MetaType.Lab).ToListAsync();
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ where usedLabs.All(ul => ul.Id.Value != l)
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
public async Task<IEnumerable<string>> SelectUnusedVersions()
|
public async Task<IEnumerable<string>> SelectUnusedVersions()
|
||||||
{
|
{
|
||||||
var versions = await bModel.SelectBuildVersions();
|
var versions = await bModel.SelectVersions();
|
||||||
|
|
||||||
var usedVersions = await _metaCollection.Find(f => f.Id.Type == MetaType.Version).ToListAsync();
|
var usedVersions = await _metaCollection.Find(f => f.Id.Type == MetaType.Version).ToListAsync();
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ where usedVersions.All(ul => ul.Id.Value != v.ToString())
|
||||||
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
[DataObjectMethod(DataObjectMethodType.Select, false)]
|
||||||
public async Task<IEnumerable<string>> SelectUnusedYears()
|
public async Task<IEnumerable<string>> SelectUnusedYears()
|
||||||
{
|
{
|
||||||
var years = await bModel.SelectBuildYears();
|
var years = await bModel.SelectYears();
|
||||||
|
|
||||||
var usedYears = await _metaCollection.Find(f => f.Id.Type == MetaType.Year).ToListAsync();
|
var usedYears = await _metaCollection.Find(f => f.Id.Type == MetaType.Year).ToListAsync();
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<meta name="twitter:description" content="@metaDesc" />
|
<meta name="twitter:description" content="@metaDesc" />
|
||||||
}
|
}
|
||||||
|
|
||||||
<h1 dir="ltr">@Model.FullBuildString</h1>
|
<h1 dir="ltr" class="eager-wrapping">@Model.FullBuildString</h1>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@foreach (var item in Model.Actions)
|
@foreach (var item in Model.Actions)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,14 @@ h1
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media(max-width: 480px)
|
||||||
|
{
|
||||||
|
h1
|
||||||
|
{
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#page-content
|
#page-content
|
||||||
{
|
{
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
|
@ -45,6 +53,12 @@ h1
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.eager-wrapping
|
||||||
|
{
|
||||||
|
-ms-word-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
.label-build-status
|
.label-build-status
|
||||||
{
|
{
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user