mirror of
https://gitlab.com/buildfeed/BuildFeed.git
synced 2024-03-22 21:10:34 +08:00
Search Overhaul p1
This commit is contained in:
parent
611089a747
commit
b2698e6e42
|
@ -11,6 +11,9 @@ public static void RegisterBundles(BundleCollection bundles)
|
|||
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
|
||||
"~/Scripts/jquery-{version}.js"));
|
||||
|
||||
bundles.Add(new ScriptBundle("~/bundles/jsrender").Include(
|
||||
"~/Scripts/jsrender*"));
|
||||
|
||||
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
|
||||
"~/Scripts/jquery.validate*"));
|
||||
|
||||
|
|
|
@ -162,6 +162,7 @@
|
|||
<Compile Include="Global.asax.cs">
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Models\ApiModel\SearchResult.cs" />
|
||||
<Compile Include="Models\Build.cs" />
|
||||
<Compile Include="Models\ViewModel\LoginUser.cs" />
|
||||
<Compile Include="Models\ViewModel\ChangePassword.cs" />
|
||||
|
@ -184,6 +185,7 @@
|
|||
<None Include="Scripts\jquery-2.1.1.intellisense.js" />
|
||||
<Content Include="googleacffc6da14c53e15.html" />
|
||||
<Content Include="content\tile\large.png" />
|
||||
<Content Include="Scripts\bfs.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.min.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.min.map" />
|
||||
|
@ -224,7 +226,6 @@
|
|||
<Folder Include="App_Data\" />
|
||||
<Folder Include="Areas\admin\Models\" />
|
||||
<Folder Include="Areas\admin\Views\Shared\" />
|
||||
<Folder Include="Models\ApiModel\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using BuildFeed.Models;
|
||||
using BuildFeed.Models.ApiModel;
|
||||
|
||||
namespace BuildFeed.Controllers
|
||||
{
|
||||
|
@ -17,7 +18,56 @@ public IEnumerable<Build> GetBuilds()
|
|||
|
||||
public IEnumerable<string> GetWin10Labs()
|
||||
{
|
||||
return Build.SelectBuildLabs(6, 4);
|
||||
List<string> labs = new List<string>();
|
||||
labs.AddRange(Build.SelectBuildLabs(6, 4));
|
||||
labs.AddRange(Build.SelectBuildLabs(10, 0));
|
||||
return labs.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<SearchResult> GetSearchResult(string query)
|
||||
{
|
||||
List<SearchResult> results = new List<SearchResult>();
|
||||
|
||||
var yearResults = from y in Build.SelectBuildYears()
|
||||
where y.ToString().Contains(query)
|
||||
orderby y descending
|
||||
select new SearchResult()
|
||||
{
|
||||
Url = Url.Route("Year Root", new { controller = "build", action = "year", year = y }),
|
||||
Label = y.ToString().Replace(query, "<strong>" + query + "</strong>"),
|
||||
Group = "Year"
|
||||
};
|
||||
|
||||
results.AddRange(yearResults);
|
||||
|
||||
|
||||
var labResults = from l in Build.SelectBuildLabs()
|
||||
where l.Contains(query)
|
||||
orderby l.IndexOf(query) ascending
|
||||
select new SearchResult()
|
||||
{
|
||||
Url = Url.Route("Lab Root", new { controller = "build", action = "lab", lab = l }),
|
||||
Label = l.Replace(query, "<strong>" + query + "</strong>"),
|
||||
Group = "Lab"
|
||||
};
|
||||
|
||||
results.AddRange(labResults);
|
||||
|
||||
|
||||
var buildResults = from b in Build.Select()
|
||||
where b.FullBuildString.Contains(query)
|
||||
orderby b.FullBuildString.IndexOf(query) ascending,
|
||||
b.BuildTime descending
|
||||
select new SearchResult()
|
||||
{
|
||||
Url = Url.Route("Actions", new { controller = "build", action = "info", id = b.Id }),
|
||||
Label = b.FullBuildString.Replace(query, "<strong>" + query + "</strong>"),
|
||||
Group = "Build"
|
||||
};
|
||||
|
||||
results.AddRange(buildResults);
|
||||
|
||||
return results.Take(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public async Task<ActionResult> added()
|
|||
Title = build.FullBuildString,
|
||||
Link = new RssUrl(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Action("info", new { controller = "Build", id = build.Id }))),
|
||||
Guid = new RssGuid() { IsPermaLink = true, Value = string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Action("info", new { controller = "Build", id = build.Id })) },
|
||||
//PubDate = build.Added
|
||||
PubDate = build.Added
|
||||
}).ToList()
|
||||
}
|
||||
};
|
||||
|
|
14
Models/ApiModel/SearchResult.cs
Normal file
14
Models/ApiModel/SearchResult.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace BuildFeed.Models.ApiModel
|
||||
{
|
||||
public class SearchResult
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Group { get; set; }
|
||||
}
|
||||
}
|
|
@ -2,3 +2,5 @@
|
|||
/// <reference path="jquery-2.1.1.js" />
|
||||
/// <reference path="jquery.validate.unobtrusive.js" />
|
||||
/// <reference path="jquery.validate.js" />
|
||||
/// <reference path="bfs.js" />
|
||||
/// <reference path="jsrender.js" />
|
||||
|
|
15
Scripts/bfs.js
Normal file
15
Scripts/bfs.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
$(function () {
|
||||
$("#search-input").change(function () {
|
||||
var search = $(this);
|
||||
$(this).parent().find(".list-group").remove();
|
||||
$.ajax("/api/GetSearchResult/?query=" + $(this).val()).done(function (data) {
|
||||
var template = $.templates("#result-template");
|
||||
var content = $("<div class='list-group'></div>");
|
||||
|
||||
var item = template.render(data);
|
||||
content.append(item);
|
||||
|
||||
search.after(content);
|
||||
});
|
||||
});
|
||||
});
|
1712
Scripts/jsrender.js
Normal file
1712
Scripts/jsrender.js
Normal file
File diff suppressed because it is too large
Load Diff
6
Scripts/jsrender.min.js
vendored
Normal file
6
Scripts/jsrender.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
8
Scripts/jsrender.min.js.map
Normal file
8
Scripts/jsrender.min.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -103,137 +103,28 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="panel-group" id="filter-list">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#filter-clear">
|
||||
Clear filters
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="filter-clear" class="panel-collapse collapse @(ViewBag.Action == "Index" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li>@Html.ActionLink("Clear Filters", "index", new { page = 1 })</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#filter-version">
|
||||
Filter by version
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="filter-version" class="panel-collapse collapse @(ViewBag.Action == "Version" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
@foreach (BuildFeed.Models.BuildVersion ver in BuildFeed.Models.Build.SelectBuildVersions())
|
||||
{
|
||||
<li><a href="@Url.Action("version", new { minor = ver.Minor, major = ver.Major, page = 1 })">@string.Format("{0}.{1}", ver.Major, ver.Minor)</a></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#filter-lab">
|
||||
Filter by lab
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="filter-lab" class="panel-collapse collapse @(ViewBag.Action == "Lab" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
@foreach (string lab in BuildFeed.Models.Build.SelectBuildLabs())
|
||||
{
|
||||
<li>@Html.ActionLink(lab, "lab", new { lab = lab, page = 1 })</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#filter-year">
|
||||
Filter by year
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="filter-year" class="panel-collapse collapse @(ViewBag.Action == "Year" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
@foreach (int year in BuildFeed.Models.Build.SelectBuildYears())
|
||||
{
|
||||
<li>@Html.ActionLink(year.ToString(), "year", new { year = year, page = 1 })</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#filter-source">
|
||||
Filter by source
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="filter-source" class="panel-collapse collapse @(ViewBag.Action == "Source" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
@foreach (BuildFeed.Models.TypeOfSource s in Enum.GetValues(typeof(BuildFeed.Models.TypeOfSource)).Cast<BuildFeed.Models.TypeOfSource>().OrderBy(d => d.ToString()))
|
||||
{
|
||||
<li><a href="@Url.Action("source", new { source = s })">@Html.DisplayFor(TypeOfSource => s, "Enumeration")</a></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>
|
||||
<a data-toggle="collapse" data-parent="#filter-list" href="#admin-actions">
|
||||
Website Administration
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="admin-actions" class="panel-collapse collapse @(ViewBag.Action == "Source" ? "in" : "")">
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
if (User.Identity.Name == "hounsell")
|
||||
{
|
||||
<li>@Html.ActionLink("Administration", "index", new { controller = "base", area = "admin" })</li>
|
||||
<li> </li>
|
||||
}
|
||||
<li>@Html.ActionLink("Add a build", "create", "build")</li>
|
||||
<li> </li>
|
||||
<li>@Html.ActionLink("Change your password", "password", "support")</li>
|
||||
<li>@Html.ActionLink("Log out", "logout", "support")</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li>@Html.ActionLink("Log in", "login", "support")</li>
|
||||
<li>@Html.ActionLink("Register", "register", "support")</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default panel-search">
|
||||
<div class="panel-body">
|
||||
@Html.TextBox("search-input", "", new { @class = "form-control" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
if (User.Identity.Name == "hounsell")
|
||||
{
|
||||
@Html.ActionLink("Administration", "index", new { controller = "base", area = "admin" }, new { @class = "list-group-item" })
|
||||
}
|
||||
@Html.ActionLink("Add a build", "create", new { controller = "build" }, new { @class = "list-group-item" })
|
||||
@Html.ActionLink("Change your password", "password", new { controller = "support" }, new { @class = "list-group-item" })
|
||||
@Html.ActionLink("Log out", "logout", new { controller = "support" }, new { @class = "list-group-item" })
|
||||
}
|
||||
else
|
||||
{
|
||||
@Html.ActionLink("Log in", "login", new { controller = "support" }, new { @class = "list-group-item" })
|
||||
@Html.ActionLink("Register", "register", new { controller = "support" }, new { @class = "list-group-item" })
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -265,4 +156,16 @@
|
|||
<li class="disabled"><span>»</span></li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
@section scripts
|
||||
{
|
||||
@Scripts.Render("~/bundles/jsrender")
|
||||
<script type="text/javascript" src="~/Scripts/bfs.js"></script>
|
||||
<script id="result-template" type="text/x-jsrender">
|
||||
<a href="{{:Url}}" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">{{:Label}}</h4>
|
||||
<p class="list-group-item-text">{{:Group}}</p>
|
||||
</a>
|
||||
</script>
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
<h2>@Model.FullBuildString</h2>
|
||||
|
||||
|
||||
<div class="form-horizontal form-details">
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.MajorVersion, new { @class = "control-label col-sm-2" })
|
||||
|
@ -154,7 +153,15 @@
|
|||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<a href="/" class="btn btn-default">Return to Listing</a>
|
||||
<a href="/" class="btn btn-info">Return to Listing</a>
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
@Html.ActionLink("Edit", "edit", new { id = Model.Id }, new { @class = "btn btn-default" })
|
||||
}
|
||||
@if (User.Identity.Name == "hounsell")
|
||||
{
|
||||
@Html.ActionLink("Delete", "delete", new { id = Model.Id }, new { @class = "btn btn-danger" })
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootswatch/3.3.0/yeti/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
|
||||
|
|
|
@ -1,105 +1,148 @@
|
|||
body, h1, h2, h3 {
|
||||
body, h1, h2, h3
|
||||
{
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
h1
|
||||
{
|
||||
font-size: 48px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
h1 a
|
||||
{
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
.social-links
|
||||
{
|
||||
margin: 30px 0 6px;
|
||||
}
|
||||
|
||||
.social-links a {
|
||||
.social-links a
|
||||
{
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.build-head {
|
||||
.build-head
|
||||
{
|
||||
margin-bottom: 0.33em;
|
||||
}
|
||||
|
||||
.build-head h3 {
|
||||
.build-head h3
|
||||
{
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.build-head .btn {
|
||||
.build-head .btn
|
||||
{
|
||||
display: inline-block;
|
||||
margin-right: 0.66em;
|
||||
vertical-align: text-bottom;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.build-foot {
|
||||
.build-foot
|
||||
{
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.build-foot .badge {
|
||||
.build-foot .badge
|
||||
{
|
||||
border-radius: 4px;
|
||||
font-weight: normal;
|
||||
color: #666 !important;
|
||||
}
|
||||
|
||||
.build-foot .badge:first-child {
|
||||
.build-foot .badge:first-child
|
||||
{
|
||||
min-width: 90px;
|
||||
}
|
||||
|
||||
li:last-child .build-foot {
|
||||
li:last-child .build-foot
|
||||
{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.fa-sm {
|
||||
.fa-sm
|
||||
{
|
||||
font-size: 0.7em;
|
||||
vertical-align: 1px;
|
||||
margin-right: 0.12em;
|
||||
}
|
||||
|
||||
.field-validation-error {
|
||||
.field-validation-error
|
||||
{
|
||||
color: #ff4136;
|
||||
}
|
||||
|
||||
.form-details label {
|
||||
.form-details label
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.panel-heading h4 {
|
||||
.panel-heading h4
|
||||
{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
.panel-search .list-group
|
||||
{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.panel-search .list-group-item-heading
|
||||
{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.panel-search .list-group-item-heading h4
|
||||
{
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.panel-search .list-group-item-heading strong
|
||||
{
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.pagination
|
||||
{
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.pagination > li > a,
|
||||
.pagination > li > span {
|
||||
.pagination > li > span
|
||||
{
|
||||
padding: 2px 7px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
#page-footer {
|
||||
#page-footer
|
||||
{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.form-horizontal .control-label {
|
||||
.form-horizontal .control-label
|
||||
{
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
label, .control-label, .help-block, .checkbox, .radio {
|
||||
label, .control-label, .help-block, .checkbox, .radio
|
||||
{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.table .btn {
|
||||
.table .btn
|
||||
{
|
||||
padding: 4px 9px;
|
||||
}
|
||||
|
||||
.table-admin > tbody > tr > th,
|
||||
.table-admin > tbody > tr > td
|
||||
{
|
||||
{
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user