* displaying a quote looks slightly prettier, although still hideous
* implemented recent quotes page
This commit is contained in:
parent
d917480c78
commit
a5f96076dc
@ -64,6 +64,15 @@ namespace VideoGameQuotes.Api {
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual VoteDirection? VotedFor(User user) {
|
||||
var vote = Votes.Where(v => v.Voter == user).SingleOrDefault();
|
||||
if (vote == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return vote.Direction;
|
||||
}
|
||||
|
||||
public virtual int UpVotes { get { return Votes.Count(vote => vote.Direction == VoteDirection.Up); } }
|
||||
public virtual int DownVotes { get { return Votes.Count(vote => vote.Direction == VoteDirection.Down); } }
|
||||
public virtual int NetVotes { get { return Votes.Sum(vote => (int)vote); } }
|
||||
|
@ -6,7 +6,6 @@ using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Portoa.Persistence;
|
||||
using Portoa.Web.Controllers;
|
||||
using Portoa.Web.ErrorHandling;
|
||||
using Portoa.Web.Results;
|
||||
using VideoGameQuotes.Api;
|
||||
using VideoGameQuotes.Web.Models;
|
||||
@ -23,6 +22,12 @@ namespace VideoGameQuotes.Web.Controllers {
|
||||
this.currentUserProvider = currentUserProvider;
|
||||
}
|
||||
|
||||
public ActionResult Recent() {
|
||||
//get last 10 submitted quotes
|
||||
var quotes = quoteService.GetMostRecentQuotes(10);
|
||||
return View(new QuoteCollectionModel { Quotes = quotes, User = currentUserProvider.CurrentUser });
|
||||
}
|
||||
|
||||
[IsValidUser]
|
||||
public ActionResult Submit() {
|
||||
var model = new QuoteSubmitModel();
|
||||
@ -140,7 +145,12 @@ namespace VideoGameQuotes.Web.Controllers {
|
||||
|
||||
public ActionResult Quote(int id) {
|
||||
try {
|
||||
return View(quoteService.GetQuote(id));
|
||||
var model = new QuoteModel {
|
||||
Quote = quoteService.GetQuote(id),
|
||||
User = currentUserProvider.CurrentUser
|
||||
};
|
||||
|
||||
return View(model);
|
||||
} catch (EntityNotFoundException) {
|
||||
return new StatusOverrideResult(View("QuoteNotFound")) { StatusCode = HttpStatusCode.NotFound };
|
||||
}
|
||||
@ -156,6 +166,5 @@ namespace VideoGameQuotes.Web.Controllers {
|
||||
return Json(this.CreateJsonErrorResponse(e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -41,6 +41,8 @@ namespace VideoGameQuotes.Web {
|
||||
routes.MapRoute("contact", "contact", new { controller = "Home", action = "Contact" });
|
||||
routes.MapRoute("submit", "submit", new { controller = "Quote", action = "Submit" });
|
||||
routes.MapRoute("search", "search", new { controller = "Quote", action = "Search" });
|
||||
routes.MapRoute("recent", "recent", new { controller = "Quote", action = "Recent" });
|
||||
routes.MapRoute("random", "random", new { controller = "Quote", action = "Random" });
|
||||
routes.MapRoute("create-category", "category/create", new { controller = "Quote", action = "CreateCategory" });
|
||||
routes.MapRoute("individual-quote", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" }, new { id = @"\d+" });
|
||||
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
|
||||
|
23
Src/VideoGameQuotes.Web/Models/QuoteModel.cs
Normal file
23
Src/VideoGameQuotes.Web/Models/QuoteModel.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using VideoGameQuotes.Api;
|
||||
|
||||
namespace VideoGameQuotes.Web.Models {
|
||||
|
||||
public class QuoteCollectionModel {
|
||||
public IEnumerable<Quote> Quotes { get; set; }
|
||||
public User User { get; set; }
|
||||
}
|
||||
|
||||
public class QuoteModel {
|
||||
public Quote Quote { get; set; }
|
||||
public User User { get; set; }
|
||||
|
||||
public bool VotedUp {
|
||||
get { return Quote.VotedFor(User) == VoteDirection.Up; }
|
||||
}
|
||||
|
||||
public bool VotedDown {
|
||||
get { return Quote.VotedFor(User) == VoteDirection.Down; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Portoa.Persistence;
|
||||
using VideoGameQuotes.Api;
|
||||
|
||||
@ -16,6 +17,7 @@ namespace VideoGameQuotes.Web.Services {
|
||||
GamingSystem GetSystem(int systemId);
|
||||
Category GetCategory(int categoryId);
|
||||
Category SaveCategory(Category category);
|
||||
IEnumerable<Quote> GetMostRecentQuotes(int limit);
|
||||
}
|
||||
|
||||
public class QuoteService : IQuoteService {
|
||||
@ -92,5 +94,13 @@ namespace VideoGameQuotes.Web.Services {
|
||||
public Category SaveCategory(Category category) {
|
||||
return categoryRepository.Save(category);
|
||||
}
|
||||
|
||||
[UnitOfWork]
|
||||
public IEnumerable<Quote> GetMostRecentQuotes(int limit) {
|
||||
return quoteRepository
|
||||
.Records
|
||||
.OrderByDescending(quote => quote.Created)
|
||||
.Take(limit);
|
||||
}
|
||||
}
|
||||
}
|
@ -85,6 +85,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Models\QuoteModel.cs" />
|
||||
<Compile Include="Validation\NonEmptyText.cs" />
|
||||
<Compile Include="Security\IsValidUserAttribute.cs" />
|
||||
<Compile Include="Controllers\QuoteController.cs" />
|
||||
@ -108,6 +109,7 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="media\css\global.css" />
|
||||
<Content Include="media\css\quote.css" />
|
||||
<Content Include="media\css\reset.css" />
|
||||
<Content Include="media\images\favicon.png" />
|
||||
<Content Include="media\images\search.png" />
|
||||
@ -116,12 +118,14 @@
|
||||
<Content Include="Views\Home\ContactSuccess.aspx" />
|
||||
<Content Include="Views\Quote\Quote.aspx" />
|
||||
<Content Include="Views\Quote\QuoteNotFound.aspx" />
|
||||
<Content Include="Views\Quote\Recent.aspx" />
|
||||
<Content Include="Views\Quote\Submit.aspx" />
|
||||
<Content Include="Views\Shared\ExceptionView.ascx" />
|
||||
<Content Include="Views\Shared\Forbidden.aspx" />
|
||||
<Content Include="Views\Shared\NotFound.aspx" />
|
||||
<Content Include="Views\Shared\NotFoundContent.ascx" />
|
||||
<Content Include="Views\Shared\RecursiveExceptionView.ascx" />
|
||||
<Content Include="Views\Shared\SingleQuote.ascx" />
|
||||
<Content Include="Views\Shared\Unknown.aspx" />
|
||||
<Content Include="Web.config" />
|
||||
<Content Include="Web.Debug.config">
|
||||
|
@ -1,24 +1,5 @@
|
||||
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<VideoGameQuotes.Api.Quote>" MasterPageFile="~/Views/Shared/Site.Master" %>
|
||||
<%@ Import Namespace="VideoGameQuotes.Api" %>
|
||||
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent"><%: Model.Game.Name %></asp:Content>
|
||||
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<VideoGameQuotes.Web.Models.QuoteModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
|
||||
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent"><%: Model.Quote.Game.Name %></asp:Content>
|
||||
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
|
||||
<div class="quote">
|
||||
<span class="vote-for" title="I like this quote"><a href="#" id="vote-for">↑</a></span>
|
||||
<span class="vote-against" title="I dislike this quote"><a href="#" id="vote-against">↓</a></span>
|
||||
<span class="quote-report-link" title="report this quote as inaccurate, fake, spam, duplicate, etc."><a href="#" id="quote-report-link">report</a></span>
|
||||
|
||||
<p class="quote-text">
|
||||
<%: Model.Text %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="quote-details">
|
||||
<dl>
|
||||
<dt>Game</dt>
|
||||
<dd><%= Html.ActionLink(Model.Game.Name, "Index", "Quote", new { game = Model.Game.Id }, null) %></dd>
|
||||
<dt>Added</dt>
|
||||
<dd><%: Model.GetHumanReadableTimeSinceCreated() %></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</asp:Content>
|
||||
<asp:Content runat="server" ID="DeferrableScripts" ContentPlaceHolderID="DeferrableScripts"></asp:Content>
|
||||
<% Html.RenderPartial("SingleQuote", Model); %>
|
||||
</asp:Content>
|
10
Src/VideoGameQuotes.Web/Views/Quote/Recent.aspx
Normal file
10
Src/VideoGameQuotes.Web/Views/Quote/Recent.aspx
Normal file
@ -0,0 +1,10 @@
|
||||
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<VideoGameQuotes.Web.Models.QuoteCollectionModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
|
||||
<%@ Import Namespace="VideoGameQuotes.Web.Models" %>
|
||||
<asp:Content runat="server" ID="Title" ContentPlaceHolderID="TitleContent">Recently Submitted Quotes</asp:Content>
|
||||
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
|
||||
<%
|
||||
foreach (var quote in Model.Quotes) {
|
||||
Html.RenderPartial("SingleQuote", new QuoteModel { Quote = quote, User = Model.User });
|
||||
}
|
||||
%>
|
||||
</asp:Content>
|
37
Src/VideoGameQuotes.Web/Views/Shared/SingleQuote.ascx
Normal file
37
Src/VideoGameQuotes.Web/Views/Shared/SingleQuote.ascx
Normal file
@ -0,0 +1,37 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<VideoGameQuotes.Web.Models.QuoteModel>" %>
|
||||
<%@ Import Namespace="VideoGameQuotes.Api" %>
|
||||
|
||||
<div class="quote-container">
|
||||
<div class="quote-data clearfix">
|
||||
<div class="quote-score-container">
|
||||
<div class="vote-container">
|
||||
<% if (!Model.VotedUp) { %>
|
||||
<span class="vote-for" title="I like this quote">▲</span>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="quote-score" title="+<%= Model.Quote.UpVotes %>, -<%= Model.Quote.DownVotes %>"><%= Model.Quote.NetVotes %></div>
|
||||
<div class="vote-container">
|
||||
<% if (!Model.VotedDown) { %>
|
||||
<span class="vote-against" title="I hate this quote">▼</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="quote-text">
|
||||
<%: Model.Quote.Text %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="clearfix">
|
||||
<a class="quote-report-link" href="#" title="report this quote as inaccurate, fake, spam, duplicate, etc.">report</a>
|
||||
</div>
|
||||
|
||||
<div class="quote-details">
|
||||
<dl>
|
||||
<dt>Game</dt>
|
||||
<dd><%= Html.ActionLink(Model.Quote.Game.Name, "Index", "Quote", new { game = Model.Quote.Game.Id }, null) %></dd>
|
||||
<dt>Added</dt>
|
||||
<dd><%: Model.Quote.GetHumanReadableTimeSinceCreated() %></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
@ -8,6 +8,7 @@
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="/media/css/reset.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/media/css/global.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/media/css/quote.css" />
|
||||
<link rel="shortcut icon" type="image/png" href="/media/images/favicon.png" />
|
||||
</head>
|
||||
|
||||
|
@ -42,6 +42,9 @@ ul.menu {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
ul.menu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.validation-summary-errors {
|
||||
color: #000000;
|
||||
@ -117,7 +120,6 @@ ul.menu {
|
||||
}
|
||||
|
||||
#main-menu li {
|
||||
float: left;
|
||||
margin-right: 2px;
|
||||
}
|
||||
#main-menu li a {
|
||||
@ -140,6 +142,7 @@ ul.menu {
|
||||
color: #669966;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
#main a:hover {
|
||||
border-bottom: 2px solid #000000;
|
||||
|
35
Src/VideoGameQuotes.Web/media/css/quote.css
Normal file
35
Src/VideoGameQuotes.Web/media/css/quote.css
Normal file
@ -0,0 +1,35 @@
|
||||
.quote-container {
|
||||
width: 500px;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.quote-container .quote-data .quote-score-container {
|
||||
float: left;
|
||||
font-family: Georgia, serif;
|
||||
padding: 5px;
|
||||
color: #FFFFFF;
|
||||
background-color: #6699FF;
|
||||
}
|
||||
.quote-score {
|
||||
cursor: help;
|
||||
}
|
||||
.quote-score, .vote-container {
|
||||
text-align: center;
|
||||
}
|
||||
.vote-for, .vote-against {
|
||||
cursor: pointer;
|
||||
}
|
||||
.vote-for:hover, .vote-against:hover {
|
||||
color: #FFFF99;
|
||||
}
|
||||
|
||||
.quote-container .quote-data .quote-text {
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.quote-report-link {
|
||||
float: right;
|
||||
}
|
Loading…
Reference in New Issue
Block a user