* improved default browse page
* fixed bug where you couldn't add more categories if none already existed * added ability to delete quotes * added call handler to delete the search index when a quote is deleted
This commit is contained in:
parent
2ac8d0155b
commit
a41335c5ba
@ -0,0 +1,31 @@
|
|||||||
|
using Microsoft.Practices.Unity;
|
||||||
|
using Microsoft.Practices.Unity.InterceptionExtension;
|
||||||
|
using Portoa.Search;
|
||||||
|
using VideoGameQuotes.Api;
|
||||||
|
|
||||||
|
namespace VideoGameQuotes.Web.Configuration {
|
||||||
|
/// <summary>
|
||||||
|
/// Call handler that deletes the search index whenever a quote is deleted
|
||||||
|
/// </summary>
|
||||||
|
public class DeleteSearchIndexCallHandler : ICallHandler {
|
||||||
|
private readonly IUnityContainer container;
|
||||||
|
|
||||||
|
public DeleteSearchIndexCallHandler(IUnityContainer container) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
|
||||||
|
var quoteId = (int)input.Arguments[0];
|
||||||
|
var returnValue = getNext()(input, getNext);
|
||||||
|
if (returnValue.Exception != null) {
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.Resolve<ISearchIndexBuilder<Quote, int>>().DeleteIndex(new Quote { Id = quoteId });
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,12 @@ namespace VideoGameQuotes.Web.Configuration {
|
|||||||
.AddPolicy("UpdateSearchIndexPolicy")
|
.AddPolicy("UpdateSearchIndexPolicy")
|
||||||
.AddCallHandler<UpdateSearchIndexCallHandler>()
|
.AddCallHandler<UpdateSearchIndexCallHandler>()
|
||||||
.AddMatchingRule(new QuoteUpdatedMatchingRule());
|
.AddMatchingRule(new QuoteUpdatedMatchingRule());
|
||||||
|
|
||||||
|
Container
|
||||||
|
.Configure<Interception>()
|
||||||
|
.AddPolicy("DeleteSearchIndexPolicy")
|
||||||
|
.AddCallHandler<DeleteSearchIndexCallHandler>()
|
||||||
|
.AddMatchingRule(new QuoteDeletedMatchingRule());
|
||||||
}
|
}
|
||||||
|
|
||||||
#region lucene-related factories
|
#region lucene-related factories
|
||||||
@ -60,6 +66,7 @@ namespace VideoGameQuotes.Web.Configuration {
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region matching rules
|
||||||
private class QuoteUpdatedMatchingRule : IMatchingRule {
|
private class QuoteUpdatedMatchingRule : IMatchingRule {
|
||||||
private static readonly MethodBase saveMethod = typeof(IRepository<Quote, int>).GetMethod("Save", new[] { typeof(Quote) });
|
private static readonly MethodBase saveMethod = typeof(IRepository<Quote, int>).GetMethod("Save", new[] { typeof(Quote) });
|
||||||
|
|
||||||
@ -67,5 +74,14 @@ namespace VideoGameQuotes.Web.Configuration {
|
|||||||
return member == saveMethod;
|
return member == saveMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class QuoteDeletedMatchingRule : IMatchingRule {
|
||||||
|
private static readonly MethodBase deleteMethod = typeof(IRepository<Quote, int>).GetMethod("Delete", new[] { typeof(int) });
|
||||||
|
|
||||||
|
public bool Matches(MethodBase member) {
|
||||||
|
return member == deleteMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,13 +31,23 @@ namespace VideoGameQuotes.Web.Controllers {
|
|||||||
return this.SerializeToJson(data);
|
return this.SerializeToJson(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost, VerifyUser(Group = UserGroup.Admin)]
|
||||||
|
public ActionResult Delete(int id) {
|
||||||
|
try {
|
||||||
|
quoteService.Delete(id);
|
||||||
|
return Json(this.CreateJsonResponse());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Json(this.CreateJsonErrorResponse(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ActionResult Browse(BrowseModel model, int page = 1) {
|
public ActionResult Browse(BrowseModel model, int page = 1) {
|
||||||
if (page < 1) {
|
if (page < 1) {
|
||||||
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
|
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.IsEmpty) {
|
if (model.IsEmpty) {
|
||||||
return View("DefaultBrowse");
|
return View("DefaultBrowse", quoteService.GetDefaultBrowseModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
model.CurrentUser = currentUserProvider.CurrentUser;
|
model.CurrentUser = currentUserProvider.CurrentUser;
|
||||||
|
@ -75,7 +75,8 @@ namespace VideoGameQuotes.Web {
|
|||||||
|
|
||||||
//these routes don't work with constraints in mono...?
|
//these routes don't work with constraints in mono...?
|
||||||
routes.MapSmartRoute("quote-edit", "quote/edit/{id}", new { controller = "Quote", action = "Edit" });
|
routes.MapSmartRoute("quote-edit", "quote/edit/{id}", new { controller = "Quote", action = "Edit" });
|
||||||
routes.MapSmartRoute("individual-quote-with-text", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" });
|
routes.MapSmartRoute("quote-delete", "quote/delete", new { controller = "Quote", action = "Delete" });
|
||||||
|
routes.MapSmartRoute("single-quote", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" });
|
||||||
|
|
||||||
routes.MapSmartRoute("dismiss-flag", "dismiss-flag", new { controller = "Quote", action = "DismissFlag" });
|
routes.MapSmartRoute("dismiss-flag", "dismiss-flag", new { controller = "Quote", action = "DismissFlag" });
|
||||||
routes.MapSmartRoute("default", "", new { controller = "Home", action = "Index" });
|
routes.MapSmartRoute("default", "", new { controller = "Home", action = "Index" });
|
||||||
|
9
Src/VideoGameQuotes.Web/Models/DefaultBrowseModel.cs
Normal file
9
Src/VideoGameQuotes.Web/Models/DefaultBrowseModel.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace VideoGameQuotes.Web.Models {
|
||||||
|
public class DefaultBrowseModel {
|
||||||
|
public int TotalNumberOfQuotes { get; set; }
|
||||||
|
public int TotalNumberOfGames { get; set; }
|
||||||
|
public int TotalNumberOfSystems { get; set; }
|
||||||
|
public int TotalNumberOfPublishers { get; set; }
|
||||||
|
public int TotalNumberOfCategories { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@ namespace VideoGameQuotes.Web.Services {
|
|||||||
Vote GetVoteOrCreateNew(Quote quote, User voter);
|
Vote GetVoteOrCreateNew(Quote quote, User voter);
|
||||||
IEnumerable<Quote> GetBrowsableQuotes(BrowseModel model, int start, int end, out int totalCount);
|
IEnumerable<Quote> GetBrowsableQuotes(BrowseModel model, int start, int end, out int totalCount);
|
||||||
Quote GetQuoteForDayOfYear(int day);
|
Quote GetQuoteForDayOfYear(int day);
|
||||||
|
DefaultBrowseModel GetDefaultBrowseModel();
|
||||||
|
void Delete(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class QuoteService : IQuoteService {
|
public class QuoteService : IQuoteService {
|
||||||
@ -53,6 +55,22 @@ namespace VideoGameQuotes.Web.Services {
|
|||||||
this.publisherRepository = publisherRepository;
|
this.publisherRepository = publisherRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
public DefaultBrowseModel GetDefaultBrowseModel() {
|
||||||
|
return new DefaultBrowseModel {
|
||||||
|
TotalNumberOfCategories = categoryRepository.Records.Count(),
|
||||||
|
TotalNumberOfSystems = systemRepository.Records.Count(),
|
||||||
|
TotalNumberOfPublishers = publisherRepository.Records.Count(),
|
||||||
|
TotalNumberOfGames = gameRepository.Records.Count(),
|
||||||
|
TotalNumberOfQuotes = quoteRepository.Records.Count()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
public void Delete(int id) {
|
||||||
|
quoteRepository.Delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
[UnitOfWork]
|
[UnitOfWork]
|
||||||
public Game GetGame(int id) {
|
public Game GetGame(int id) {
|
||||||
return gameRepository.FindById(id);
|
return gameRepository.FindById(id);
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Configuration\DeleteSearchIndexCallHandler.cs" />
|
||||||
<Compile Include="Configuration\EnableLogging.cs" />
|
<Compile Include="Configuration\EnableLogging.cs" />
|
||||||
<Compile Include="Configuration\EnableSearchWithLucene.cs" />
|
<Compile Include="Configuration\EnableSearchWithLucene.cs" />
|
||||||
<Compile Include="Configuration\UpdateSearchIndexCallHandler.cs" />
|
<Compile Include="Configuration\UpdateSearchIndexCallHandler.cs" />
|
||||||
@ -115,6 +116,7 @@
|
|||||||
<Compile Include="Controllers\HomeController.cs" />
|
<Compile Include="Controllers\HomeController.cs" />
|
||||||
<Compile Include="Controllers\PublisherController.cs" />
|
<Compile Include="Controllers\PublisherController.cs" />
|
||||||
<Compile Include="Controllers\SystemController.cs" />
|
<Compile Include="Controllers\SystemController.cs" />
|
||||||
|
<Compile Include="Models\DefaultBrowseModel.cs" />
|
||||||
<Compile Include="Models\EditCategoryModel.cs" />
|
<Compile Include="Models\EditCategoryModel.cs" />
|
||||||
<Compile Include="Models\EditGameModel.cs" />
|
<Compile Include="Models\EditGameModel.cs" />
|
||||||
<Compile Include="Models\EditPublisherModel.cs" />
|
<Compile Include="Models\EditPublisherModel.cs" />
|
||||||
@ -210,6 +212,7 @@
|
|||||||
<Content Include="Views\Home\About.aspx" />
|
<Content Include="Views\Home\About.aspx" />
|
||||||
<Content Include="Views\Home\Contact.aspx" />
|
<Content Include="Views\Home\Contact.aspx" />
|
||||||
<Content Include="Views\Home\ContactSuccess.aspx" />
|
<Content Include="Views\Home\ContactSuccess.aspx" />
|
||||||
|
<Content Include="Views\Quote\DeleteSuccess.aspx" />
|
||||||
<Content Include="Views\Shared\CaptchaJavaScript.ascx" />
|
<Content Include="Views\Shared\CaptchaJavaScript.ascx" />
|
||||||
<Content Include="Views\Shared\PagingMenu.ascx" />
|
<Content Include="Views\Shared\PagingMenu.ascx" />
|
||||||
<Content Include="Views\Quote\QuoteFormJavaScript.ascx" />
|
<Content Include="Views\Quote\QuoteFormJavaScript.ascx" />
|
||||||
@ -236,7 +239,9 @@
|
|||||||
<Content Include="Views\Shared\Unknown.aspx" />
|
<Content Include="Views\Shared\Unknown.aspx" />
|
||||||
<Content Include="Views\User\Edit.aspx" />
|
<Content Include="Views\User\Edit.aspx" />
|
||||||
<Content Include="Views\User\InvalidUsername.aspx" />
|
<Content Include="Views\User\InvalidUsername.aspx" />
|
||||||
<Content Include="Web.config" />
|
<Content Include="Web.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
<Content Include="Web.Debug.config">
|
<Content Include="Web.Debug.config">
|
||||||
<DependentUpon>Web.config</DependentUpon>
|
<DependentUpon>Web.config</DependentUpon>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Views/Shared/Site.Master" %>
|
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<VideoGameQuotes.Web.Models.DefaultBrowseModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
|
||||||
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent">Browse</asp:Content>
|
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent">Browse</asp:Content>
|
||||||
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
|
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
|
||||||
<h2>Browse</h2>
|
<p>
|
||||||
|
There are currently <strong><%= Model.TotalNumberOfQuotes %></strong> quotes. Choose wisely.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div id="browse-default-menu">
|
<div id="browse-default-menu">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#" id="browse-game">Games</a></li>
|
<li><a href="#" id="browse-game">Games</a> <small>(<%= Model.TotalNumberOfGames %>)</small></li>
|
||||||
<li><a href="#" id="browse-system">Systems</a></li>
|
<li><a href="#" id="browse-system">Systems</a> <small>(<%= Model.TotalNumberOfSystems %>)</small></li>
|
||||||
<li><a href="#" id="browse-category">Categories</a></li>
|
<li><a href="#" id="browse-category">Categories</a> <small>(<%= Model.TotalNumberOfCategories %>)</small></li>
|
||||||
<li><a href="#" id="browse-publisher">Publishers</a></li>
|
<li><a href="#" id="browse-publisher">Publishers</a> <small>(<%= Model.TotalNumberOfPublishers %>)</small></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
9
Src/VideoGameQuotes.Web/Views/Quote/DeleteSuccess.aspx
Normal file
9
Src/VideoGameQuotes.Web/Views/Quote/DeleteSuccess.aspx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Views/Shared/Site.Master" %>
|
||||||
|
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent">Quote Successfully Deleted</asp:Content>
|
||||||
|
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
|
||||||
|
<h2>Wild Success!</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The quote and all its votes and flags were deleted.
|
||||||
|
</p>
|
||||||
|
</asp:Content>
|
@ -16,8 +16,8 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Anyway, try <%= Html.ActionLink("searching", "Search", "Quote") %> for the quote
|
Anyway, try searching for the quote you were hoping to find using the little search box up
|
||||||
you were hoping to find. Maybe that will make you less of a stain on humanity.
|
there in the top right corner. Maybe that will make you less of a stain on humanity.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -28,11 +28,12 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="quote-links">
|
<p class="quote-links">
|
||||||
<a class="quote-flag-icon" href="#" title="flag this quote as inaccurate, fake, spam, duplicate, etc."></a>
|
<a class="quote-flag-icon quote-flag-link" href="#" title="flag this quote as inaccurate, fake, spam, duplicate, etc."></a>
|
||||||
<a class="quote-permalink" href="<%= Url.Action("Quote", "Quote", new { id = Model.Quote.Id, text = Model.Quote.GetUrlFriendlyText() }) %>" title="permanent link to this quote"></a>
|
<a class="quote-permalink" href="<%= Url.Action("Quote", "Quote", new { id = Model.Quote.Id, text = Model.Quote.GetUrlFriendlyText() }) %>" title="permanent link to this quote"></a>
|
||||||
<% if (Model.User != null && Model.User.Group >= UserGroup.Admin) { %>
|
<% if (Model.User != null && Model.User.Group >= UserGroup.Admin) { %>
|
||||||
<a class="edit-icon" href="<%= Url.Action("Edit", "Quote", new { id = Model.Quote.Id }) %>" title="edit this quote"></a>
|
<a class="edit-icon" href="<%= Url.Action("Edit", "Quote", new { id = Model.Quote.Id }) %>" title="edit this quote"></a>
|
||||||
<small>(<%= Model.Quote.FlagCount %>)</small>
|
<a class="delete-icon delete-quote-link" href="#" title="delete this quote and all its flags and votes"></a>
|
||||||
|
<strong>[<%= Model.Quote.FlagCount %>]</strong>
|
||||||
<% } %>
|
<% } %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user