* 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")
|
||||
.AddCallHandler<UpdateSearchIndexCallHandler>()
|
||||
.AddMatchingRule(new QuoteUpdatedMatchingRule());
|
||||
|
||||
Container
|
||||
.Configure<Interception>()
|
||||
.AddPolicy("DeleteSearchIndexPolicy")
|
||||
.AddCallHandler<DeleteSearchIndexCallHandler>()
|
||||
.AddMatchingRule(new QuoteDeletedMatchingRule());
|
||||
}
|
||||
|
||||
#region lucene-related factories
|
||||
@ -60,6 +66,7 @@ namespace VideoGameQuotes.Web.Configuration {
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region matching rules
|
||||
private class QuoteUpdatedMatchingRule : IMatchingRule {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[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) {
|
||||
if (page < 1) {
|
||||
return new StatusOverrideResult(View("BadPaging")) { StatusCode = HttpStatusCode.BadRequest };
|
||||
}
|
||||
|
||||
if (model.IsEmpty) {
|
||||
return View("DefaultBrowse");
|
||||
return View("DefaultBrowse", quoteService.GetDefaultBrowseModel());
|
||||
}
|
||||
|
||||
model.CurrentUser = currentUserProvider.CurrentUser;
|
||||
|
@ -75,7 +75,8 @@ namespace VideoGameQuotes.Web {
|
||||
|
||||
//these routes don't work with constraints in mono...?
|
||||
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("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);
|
||||
IEnumerable<Quote> GetBrowsableQuotes(BrowseModel model, int start, int end, out int totalCount);
|
||||
Quote GetQuoteForDayOfYear(int day);
|
||||
DefaultBrowseModel GetDefaultBrowseModel();
|
||||
void Delete(int id);
|
||||
}
|
||||
|
||||
public class QuoteService : IQuoteService {
|
||||
@ -53,6 +55,22 @@ namespace VideoGameQuotes.Web.Services {
|
||||
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]
|
||||
public Game GetGame(int id) {
|
||||
return gameRepository.FindById(id);
|
||||
|
@ -105,6 +105,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Configuration\DeleteSearchIndexCallHandler.cs" />
|
||||
<Compile Include="Configuration\EnableLogging.cs" />
|
||||
<Compile Include="Configuration\EnableSearchWithLucene.cs" />
|
||||
<Compile Include="Configuration\UpdateSearchIndexCallHandler.cs" />
|
||||
@ -115,6 +116,7 @@
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Controllers\PublisherController.cs" />
|
||||
<Compile Include="Controllers\SystemController.cs" />
|
||||
<Compile Include="Models\DefaultBrowseModel.cs" />
|
||||
<Compile Include="Models\EditCategoryModel.cs" />
|
||||
<Compile Include="Models\EditGameModel.cs" />
|
||||
<Compile Include="Models\EditPublisherModel.cs" />
|
||||
@ -210,6 +212,7 @@
|
||||
<Content Include="Views\Home\About.aspx" />
|
||||
<Content Include="Views\Home\Contact.aspx" />
|
||||
<Content Include="Views\Home\ContactSuccess.aspx" />
|
||||
<Content Include="Views\Quote\DeleteSuccess.aspx" />
|
||||
<Content Include="Views\Shared\CaptchaJavaScript.ascx" />
|
||||
<Content Include="Views\Shared\PagingMenu.ascx" />
|
||||
<Content Include="Views\Quote\QuoteFormJavaScript.ascx" />
|
||||
@ -236,7 +239,9 @@
|
||||
<Content Include="Views\Shared\Unknown.aspx" />
|
||||
<Content Include="Views\User\Edit.aspx" />
|
||||
<Content Include="Views\User\InvalidUsername.aspx" />
|
||||
<Content Include="Web.config" />
|
||||
<Content Include="Web.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</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="Main" ContentPlaceHolderID="MainContent">
|
||||
<h2>Browse</h2>
|
||||
<p>
|
||||
There are currently <strong><%= Model.TotalNumberOfQuotes %></strong> quotes. Choose wisely.
|
||||
</p>
|
||||
|
||||
<div id="browse-default-menu">
|
||||
<ul>
|
||||
<li><a href="#" id="browse-game">Games</a></li>
|
||||
<li><a href="#" id="browse-system">Systems</a></li>
|
||||
<li><a href="#" id="browse-category">Categories</a></li>
|
||||
<li><a href="#" id="browse-publisher">Publishers</a></li>
|
||||
<li><a href="#" id="browse-game">Games</a> <small>(<%= Model.TotalNumberOfGames %>)</small></li>
|
||||
<li><a href="#" id="browse-system">Systems</a> <small>(<%= Model.TotalNumberOfSystems %>)</small></li>
|
||||
<li><a href="#" id="browse-category">Categories</a> <small>(<%= Model.TotalNumberOfCategories %>)</small></li>
|
||||
<li><a href="#" id="browse-publisher">Publishers</a> <small>(<%= Model.TotalNumberOfPublishers %>)</small></li>
|
||||
</ul>
|
||||
</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>
|
||||
Anyway, try <%= Html.ActionLink("searching", "Search", "Quote") %> for the quote
|
||||
you were hoping to find. Maybe that will make you less of a stain on humanity.
|
||||
Anyway, try searching for the quote you were hoping to find using the little search box up
|
||||
there in the top right corner. Maybe that will make you less of a stain on humanity.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -28,11 +28,12 @@
|
||||
</p>
|
||||
|
||||
<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>
|
||||
<% 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>
|
||||
<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>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user