reporting quotes works

This commit is contained in:
tmont 2011-02-15 01:18:23 +00:00
parent 2496edaf89
commit 5c14400d48
8 changed files with 117 additions and 7 deletions

View File

@ -36,8 +36,14 @@ namespace VideoGameQuotes.Api {
categories.Clear(); categories.Clear();
} }
public virtual Quote AddFlag(QuoteFlag flag) { public virtual Quote AddFlag(string comment, QuoteFlagType type, User user) {
flags.Add(flag); flags.Add(new QuoteFlag {
Comment = comment,
Type = type,
User = user,
Quote = this
});
return this; return this;
} }

View File

@ -1,8 +1,9 @@
namespace VideoGameQuotes.Api { namespace VideoGameQuotes.Api {
public enum QuoteFlagType { public enum QuoteFlagType {
Other = 0,
Inaccurate = 1, Inaccurate = 1,
Spam = 2, Duplicate = 2,
Fake = 3, Spam = 3,
Other = 4 Fake = 4
} }
} }

View File

@ -22,6 +22,22 @@ namespace VideoGameQuotes.Web.Controllers {
this.currentUserProvider = currentUserProvider; this.currentUserProvider = currentUserProvider;
} }
[HttpPost, IsValidUser]
public JsonResult Report(ReportModel model) {
if (!ModelState.IsValid) {
return Json(this.CreateJsonErrorResponse("Invalid request"));
}
try {
var quote = quoteService.GetQuote(model.QuoteId);
quote.AddFlag(model.Comment, model.FlagType, currentUserProvider.CurrentUser);
quoteService.SaveQuote(quote);
return Json(this.CreateJsonResponse());
} catch {
return Json(this.CreateJsonErrorResponse("Unable to create your report"));
}
}
[HttpPost, IsValidUser] [HttpPost, IsValidUser]
public JsonResult Vote(VoteModel model) { public JsonResult Vote(VoteModel model) {
if (!ModelState.IsValid) { if (!ModelState.IsValid) {

View File

@ -39,7 +39,7 @@ namespace VideoGameQuotes.Web {
routes.MapRoute("home", "{action}", new { controller = "Home", action = "Index" }, new { action = "about|contact" }); routes.MapRoute("home", "{action}", new { controller = "Home", action = "Index" }, new { action = "about|contact" });
routes.MapRoute("best", "best/{start}-{end}/", new { controller = "Quote", action = "Best" }, new { start = @"\d+", end = @"\d+" }); routes.MapRoute("best", "best/{start}-{end}/", new { controller = "Quote", action = "Best" }, new { start = @"\d+", end = @"\d+" });
routes.MapRoute("quote", "{action}", new { controller = "Quote" }, new { action = "submit|search|recent|random|best|browse|vote" }); routes.MapRoute("quote", "{action}", new { controller = "Quote" }, new { action = "submit|search|recent|random|best|browse|vote|report" });
routes.MapRoute("individual-quote", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" }, new { id = @"\d+" }); routes.MapRoute("individual-quote", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" }, new { id = @"\d+" });
routes.MapRoute("create-category", "category/create", new { controller = "Quote", action = "CreateCategory" }); routes.MapRoute("create-category", "category/create", new { controller = "Quote", action = "CreateCategory" });

View File

@ -0,0 +1,11 @@
using Portoa.Validation.DataAnnotations;
using VideoGameQuotes.Api;
namespace VideoGameQuotes.Web.Models {
public class ReportModel {
[GreaterThanZero]
public int QuoteId { get; set; }
public QuoteFlagType FlagType { get; set; }
public string Comment { get; set; }
}
}

View File

@ -88,6 +88,7 @@
<Compile Include="Models\PagedQuoteCollectionModel.cs" /> <Compile Include="Models\PagedQuoteCollectionModel.cs" />
<Compile Include="Models\QuoteCollectionModel.cs" /> <Compile Include="Models\QuoteCollectionModel.cs" />
<Compile Include="Models\QuoteModel.cs" /> <Compile Include="Models\QuoteModel.cs" />
<Compile Include="Models\ReportModel.cs" />
<Compile Include="Models\VoteModel.cs" /> <Compile Include="Models\VoteModel.cs" />
<Compile Include="Validation\NonEmptyText.cs" /> <Compile Include="Validation\NonEmptyText.cs" />
<Compile Include="Security\IsValidUserAttribute.cs" /> <Compile Include="Security\IsValidUserAttribute.cs" />

View File

@ -33,3 +33,7 @@
.quote-report-link { .quote-report-link {
float: right; float: right;
} }
.report-dialog {
width: 400px;
}

View File

@ -1,5 +1,17 @@
(function($, window, undefined){ (function($, window, undefined){
$.fn.center = function () {
this.css("top", ($(window).height() - this.height()) / 2 + $(window).scrollTop() + "px");
this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px");
return this;
}
$(document).ready(function() { $(document).ready(function() {
var getQuoteId = function($container) {
return $container.find("input.quote-id").val();
};
var voting = false; var voting = false;
$(".vote-for, .vote-against").live("click", function() { $(".vote-for, .vote-against").live("click", function() {
if (voting) { if (voting) {
@ -11,7 +23,7 @@
var $votingLink = $(this); var $votingLink = $(this);
var $container = $votingLink.parents(".quote-container"); var $container = $votingLink.parents(".quote-container");
var direction = $votingLink.hasClass("vote-for") ? 1 : 0; var direction = $votingLink.hasClass("vote-for") ? 1 : 0;
var quoteId = $container.find("input.quote-id").val(); var quoteId = getQuoteId($container);
$.ajax("/vote", { $.ajax("/vote", {
type: "POST", type: "POST",
data: { data: {
@ -56,5 +68,64 @@
return false; return false;
}); });
//report link
$(".quote-report-link").click(function() {
if ($(".report-dialog").length > 0) {
return false;
}
var $link = $(this);
var $container = $link.parents(".quote-container");
var quoteId = getQuoteId($container);
var $row = $("<tr/>");
var flagTypes = [ [1, "Inaccurate"], [2, "Duplicate"], [3, "Spam"], [4, "Fake"], [0, "Other"] ];
for (var i = 0; i < flagTypes.length; i++) {
var html = "<td><input type=\"radio\" name=\"flagType\" value=\""
+ flagTypes[i][0] + "\" id=\"flag-type-" +flagTypes[i][0] + "\"/>"
+ "<label for=\"flag-type-" + flagTypes[i][0] + "\">" + flagTypes[i][1] + "</label></td>";
$row.append($(html));
}
var $dialog = $("<div/>").addClass("dialog report-dialog");
var $submit = $("<input/>")
.attr("type", "button")
.attr("value", "Submit Report")
.click(function() {
$.ajax("/report", {
type: "POST",
data: { QuoteId: quoteId, Comment: $dialog.find("textarea").val(), FlagType: $dialog.find("input[name='flagType']:checked").val() },
complete: function() { $dialog.remove(); },
success: function(data, status, $xhr) {
if (data.Error !== null) {
alert(data.Error);
return;
}
}
});
});
var $cancel = $("<input/>")
.attr("type", "button")
.attr("value", "Cancel")
.click(function() { $dialog.remove(); });
$dialog
.append($("<p/>").text("Flag as:"))
.append($("<table/>").append($row))
.append($("<p/>").text("Comment"))
.append($("<textarea/>"))
.append($("<div/>").css("text-align", "center").append($submit).append($cancel));
//"other" should be checked by default
$dialog.find("#flag-type-0").attr("checked", "checked");
$("body").append($dialog);
$dialog.center();
return false;
});
}); });
}(jQuery, window)); }(jQuery, window));