@@ -58,6 +58,7 @@ namespace Teknik.Areas.Blog.Controllers | |||
return View(model); | |||
} | |||
#region Posts | |||
// GET: Blogs/Details/5 | |||
[AllowAnonymous] | |||
public ActionResult Post(string username, int id) | |||
@@ -67,12 +68,12 @@ namespace Teknik.Areas.Blog.Controllers | |||
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); | |||
} | |||
// find the post specified | |||
Post post = db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.Blog.User.Username == username && p.PostId == id) && | |||
(p.Published || p.Blog.User.Username == User.Identity.Name) | |||
).First(); | |||
if (post != null) | |||
var posts = (User.IsInRole("Admin")) ? db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.Blog.User.Username == username && p.PostId == id)) | |||
: db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.Blog.User.Username == username && p.PostId == id) && | |||
(p.Published || p.Blog.User.Username == User.Identity.Name)); | |||
if (posts != null && posts.Any()) | |||
{ | |||
PostViewModel model = new PostViewModel(post); | |||
PostViewModel model = new PostViewModel(posts.First()); | |||
ViewBag.Title = model.Title + " - " + username + "'s Blog - " + Config.Title; | |||
return View("~/Areas/Blog/Views/Blog/ViewPost.cshtml", model); | |||
@@ -84,9 +85,9 @@ namespace Teknik.Areas.Blog.Controllers | |||
[AllowAnonymous] | |||
public ActionResult GetPosts(int blogID, int startPostID, int count) | |||
{ | |||
var posts = db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.BlogId == blogID && p.PostId > startPostID) && | |||
(p.Published || p.Blog.User.Username == User.Identity.Name) | |||
).OrderByDescending(p => p.DatePosted).Skip(startPostID).Take(count).ToList(); | |||
var posts = (User.IsInRole("Admin")) ? db.Posts.Include("Blog").Include("Blog.User").Where(p => p.BlogId == blogID).OrderByDescending(p => p.DatePosted).Skip(startPostID).Take(count).ToList() | |||
: db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.BlogId == blogID) && (p.Published || p.Blog.User.Username == User.Identity.Name) | |||
).OrderByDescending(p => p.DatePosted).Skip(startPostID).Take(count).ToList(); | |||
List<PostViewModel> postViews = new List<PostViewModel>(); | |||
if (posts != null) | |||
{ | |||
@@ -103,8 +104,8 @@ namespace Teknik.Areas.Blog.Controllers | |||
public ActionResult GetPostTitle(int postID) | |||
{ | |||
string title = string.Empty; | |||
Post post = (User.IsInRole("Admin")) ? db.Posts.Find(postID) : db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.PostId == postID) && | |||
(p.Published || p.Blog.User.Username == User.Identity.Name)).First(); | |||
Post post = (User.IsInRole("Admin")) ? db.Posts.Find(postID) | |||
: db.Posts.Include("Blog").Include("Blog.User").Where(p => (p.PostId == postID) && (p.Published || p.Blog.User.Username == User.Identity.Name)).First(); | |||
if (post != null) | |||
{ | |||
return Json(new { result = post.Title }); | |||
@@ -143,7 +144,7 @@ namespace Teknik.Areas.Blog.Controllers | |||
db.SaveChanges(); | |||
return Json(new { result = true }); | |||
} | |||
return Json(new { error = "No post found" }); | |||
return Json(new { error = "No post created" }); | |||
} | |||
[HttpPost] | |||
@@ -201,5 +202,90 @@ namespace Teknik.Areas.Blog.Controllers | |||
} | |||
return Json(new { error = "No post found" }); | |||
} | |||
#endregion | |||
#region Comments | |||
[HttpPost] | |||
[AllowAnonymous] | |||
public ActionResult GetComments(int postID, int startCommentID, int count) | |||
{ | |||
var comments = db.BlogComments.Include("Post").Include("Post.Blog").Include("Post.Blog.User").Where(p => (p.PostId == postID)).OrderByDescending(p => p.DatePosted).Skip(startCommentID).Take(count).ToList(); | |||
List<CommentViewModel> commentViews = new List<CommentViewModel>(); | |||
if (comments != null) | |||
{ | |||
foreach (Comment comment in comments) | |||
{ | |||
commentViews.Add(new CommentViewModel(comment)); | |||
} | |||
} | |||
return PartialView("~/Areas/Blog/Views/Blog/Comments.cshtml", commentViews); | |||
} | |||
[HttpPost] | |||
[AllowAnonymous] | |||
public ActionResult GetCommentArticle(int commentID) | |||
{ | |||
Comment comment = db.BlogComments.Include("Post").Include("Post.Blog").Include("Post.Blog.User").Where(p => (p.CommentId == commentID)).First(); | |||
if (comment != null) | |||
{ | |||
return Json(new { result = comment.Article }); | |||
} | |||
return Json(new { error = "No article found" }); | |||
} | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public ActionResult CreateComment(int postID, string article) | |||
{ | |||
if (ModelState.IsValid) | |||
{ | |||
Comment comment = db.BlogComments.Create(); | |||
comment.PostId = postID; | |||
comment.UserId = db.Users.Where(u => u.Username == User.Identity.Name).First().UserId; | |||
comment.Article = article; | |||
comment.DatePosted = DateTime.Now; | |||
db.BlogComments.Add(comment); | |||
db.SaveChanges(); | |||
return Json(new { result = true }); | |||
} | |||
return Json(new { error = "No comment created" }); | |||
} | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public ActionResult EditComment(int commentID, string article) | |||
{ | |||
if (ModelState.IsValid) | |||
{ | |||
Comment comment = db.BlogComments.Find(commentID); | |||
if (comment != null) | |||
{ | |||
comment.Article = article; | |||
db.Entry(comment).State = EntityState.Modified; | |||
db.SaveChanges(); | |||
return Json(new { result = true }); | |||
} | |||
} | |||
return Json(new { error = "No comment found" }); | |||
} | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public ActionResult DeleteComment(int commentID) | |||
{ | |||
if (ModelState.IsValid) | |||
{ | |||
Comment comment = db.BlogComments.Find(commentID); | |||
if (comment != null) | |||
{ | |||
db.BlogComments.Remove(comment); | |||
db.SaveChanges(); | |||
return Json(new { result = true }); | |||
} | |||
} | |||
return Json(new { error = "No comment found" }); | |||
} | |||
#endregion | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Areas.Profile.Models; | |||
namespace Teknik.Areas.Blog.Models | |||
{ | |||
public class Comment | |||
{ | |||
public int CommentId { get; set; } | |||
public int PostId { get; set; } | |||
public Post Post { get; set; } | |||
public int? UserId { get; set; } | |||
public User User { get; set; } | |||
public DateTime DatePosted { get; set; } | |||
public string Article { get; set; } | |||
} | |||
} |
@@ -23,5 +23,7 @@ namespace Teknik.Areas.Blog.Models | |||
public string Article { get; set; } | |||
public List<string> Tags { get; set; } | |||
public List<Comment> Comments { get; set; } | |||
} | |||
} |
@@ -76,14 +76,14 @@ | |||
$.ajax({ | |||
type: "POST", | |||
url: addCommentURL, | |||
data: AddAntiForgeryToken({ postID: postID, service: 'blog', comment: post }), | |||
data: AddAntiForgeryToken({ postID: postID, article: post }), | |||
success: function (html) { | |||
if (html == 'true') { | |||
if (html.result) { | |||
window.location.reload(); | |||
} | |||
else { | |||
$("#top_msg").css('display', 'inline', 'important'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html + '</div>'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html.error + '</div>'); | |||
} | |||
} | |||
}); | |||
@@ -97,10 +97,10 @@ | |||
$.ajax({ | |||
type: "POST", | |||
url: getCommentContentURL, | |||
data: { id: commentID }, | |||
data: { commentID: commentID }, | |||
success: function (html) { | |||
if (html) { | |||
$("#edit_comment_post").val(html); | |||
if (html.result) { | |||
$("#edit_comment_post").val(html.result); | |||
} | |||
} | |||
}); | |||
@@ -115,12 +115,12 @@ | |||
url: editCommentURL, | |||
data: AddAntiForgeryToken({ commentID: postID, post: post }), | |||
success: function (html) { | |||
if (html == 'true') { | |||
if (html.result) { | |||
window.location.reload(); | |||
} | |||
else { | |||
$("#top_msg").css('display', 'inline', 'important'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html + '</div>'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html.error + '</div>'); | |||
} | |||
} | |||
}); | |||
@@ -171,7 +171,7 @@ function loadMoreComments(start, count) { | |||
$.ajax({ | |||
type: "POST", | |||
url: getCommentsURL, | |||
data: { postID: post_id, service: 'blog', postCount: count, startPost: start }, | |||
data: { postID: post_id, count: count, startCommentID: start }, | |||
success: function (html) { | |||
if (html) { | |||
$(".post-comments").append(html); | |||
@@ -274,14 +274,14 @@ function linkCommentDelete(selector) { | |||
$.ajax({ | |||
type: "POST", | |||
url: deleteCommentURL, | |||
data: AddAntiForgeryToken({ postID: post_id }), | |||
data: AddAntiForgeryToken({ commentID: post_id }), | |||
success: function (html) { | |||
if (html == 'true') { | |||
if (html.result) { | |||
window.location.reload(); | |||
} | |||
else { | |||
$("#top_msg").css('display', 'inline', 'important'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html + '</div>'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + html.error + '</div>'); | |||
} | |||
} | |||
}); |
@@ -0,0 +1,31 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Areas.Blog.Models; | |||
using Teknik.Areas.Profile.Models; | |||
namespace Teknik.Areas.Blog.ViewModels | |||
{ | |||
public class CommentViewModel | |||
{ | |||
public int CommentId { get; set; } | |||
public int PostId { get; set; } | |||
public Post Post { get; set; } | |||
public int? UserId { get; set; } | |||
public User User { get; set; } | |||
public DateTime DatePosted { get; set; } | |||
public string Article { get; set; } | |||
public CommentViewModel(Comment comment) | |||
{ | |||
CommentId = comment.CommentId; | |||
PostId = comment.PostId; | |||
Post = comment.Post; | |||
UserId = comment.UserId; | |||
User = comment.User; | |||
DatePosted = comment.DatePosted; | |||
Article = comment.Article; | |||
} | |||
} | |||
} |
@@ -27,6 +27,8 @@ namespace Teknik.Areas.Blog.ViewModels | |||
public List<string> Tags { get; set; } | |||
public List<Comment> Comments { get; set; } | |||
public PostViewModel(Post post) | |||
{ | |||
BlogId = post.BlogId; | |||
@@ -38,11 +40,7 @@ namespace Teknik.Areas.Blog.ViewModels | |||
Title = post.Title; | |||
Tags = post.Tags; | |||
Article = post.Article; | |||
} | |||
public bool CanView(IPrincipal user) | |||
{ | |||
return (Published || Blog.User.Username == user.Identity.Name || user.IsInRole("Admin")); | |||
Comments = post.Comments; | |||
} | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
@model Teknik.Areas.Blog.ViewModels.CommentViewModel | |||
<script> | |||
var converter = new Markdown.getSanitizingConverter(); | |||
// Title Conversion | |||
var old_post = $("#title_@Model.CommentId").text(); | |||
var new_post = converter.makeHtml(old_post); | |||
$("#title_@Model.CommentId").html(new_post); | |||
// Post Conversion | |||
var old_post = $("#comment_@Model.CommentId").text(); | |||
var new_post = converter.makeHtml(old_post); | |||
$("#comment_@Model.CommentId").html(new_post); | |||
</script> | |||
<hr> | |||
<div class="row"> | |||
<div class="col-sm-8 col-sm-offset-2"> | |||
<div class="post-comment"> | |||
<p class="post-comment-meta text-muted"> | |||
<a href="@Url.Action("Index", "Profile", new { area = "Profile", username = Model.Post.Blog.User.Username })">@Model.Post.Blog.User.Username</a> replied at @Model.DatePosted.ToString("H:m:s tt") on @Model.DatePosted.ToString("MMMM dd, yyyy") | |||
@if (Model.Post.Blog.User.Username == User.Identity.Name || User.IsInRole("Admin")) | |||
{ | |||
<br /> | |||
<button type="button" class="btn btn-info edit_comment" id="@Model.CommentId" data-toggle="modal" data-target="#editComment">Edit</button> | |||
<button type="button" class="btn btn-danger delete_comment" id="@Model.CommentId">Delete</button> | |||
} | |||
</p> | |||
<p id="comment_@Model.CommentId">@Model.Article</p> | |||
</div> | |||
</div> | |||
</div> |
@@ -0,0 +1,6 @@ | |||
@model List<Teknik.Areas.Blog.ViewModels.CommentViewModel> | |||
@foreach (var comment in Model) | |||
{ | |||
@Html.Partial("Comment", comment) | |||
} |
@@ -17,8 +17,8 @@ | |||
<h2 class="blog-post-title text-center"><a href="@Url.Action("Post", "Blog", new { area = "Blog", username = Model.Blog.User.Username, id = Model.PostId })" id="title_@Model.PostId">@Model.Title</a></h2> | |||
<p class="blog-post-meta text-center text-muted"> | |||
Posted on @Model.DatePublished.ToString("MMMM dd, yyyy") by <a href="@Url.Action("Index", "Profile", new { area = "Profile", username = Model.Blog.User.Username })">@Model.Blog.User.Username</a> | |||
@if (Model.Blog.User.Username == User.Identity.Name) | |||
{ | |||
@if (Model.Blog.User.Username == User.Identity.Name || User.IsInRole("Admin")) | |||
{ | |||
<br /> | |||
<button type="button" class="btn btn-info edit_post" id="@Model.PostId" data-toggle="modal" data-target="#editPost">Edit</button> | |||
if (Model.Published) |
@@ -17,8 +17,8 @@ | |||
var getCommentsURL = '@Url.Action("GetComments", "Blog", new { area = "Blog" })'; | |||
var getCommentContentURL = '@Url.Action("GetCommentContent", "Blog", new { area = "Blog" })'; | |||
var addCommentURL = '@Url.Action("CreatePost", "Blog", new { area = "Blog" })'; | |||
var editCommentURL = '@Url.Action("EditPost", "Blog", new { area = "Blog" })'; | |||
var addCommentURL = '@Url.Action("CreateComment", "Blog", new { area = "Blog" })'; | |||
var editCommentURL = '@Url.Action("EditComment", "Blog", new { area = "Blog" })'; | |||
var deleteCommentURL = '@Url.Action("DeleteComment", "Blog", new { area = "Blog" })'; | |||
</script> | |||
@@ -15,6 +15,7 @@ namespace Teknik.Models | |||
public DbSet<Role> Roles { get; set; } | |||
public DbSet<Blog> Blogs { get; set; } | |||
public DbSet<Post> Posts { get; set; } | |||
public DbSet<Comment> BlogComments { get; set; } | |||
public DbSet<Contact> Contact { get; set; } | |||
protected override void OnModelCreating(DbModelBuilder modelBuilder) | |||
@@ -24,6 +25,7 @@ namespace Teknik.Models | |||
modelBuilder.Entity<Role>().ToTable("Roles"); | |||
modelBuilder.Entity<Blog>().ToTable("Blogs"); | |||
modelBuilder.Entity<Post>().ToTable("Posts"); | |||
modelBuilder.Entity<Comment>().ToTable("BlogComments"); | |||
modelBuilder.Entity<Contact>().ToTable("Contact"); | |||
base.OnModelCreating(modelBuilder); |
@@ -142,7 +142,9 @@ | |||
<Compile Include="Areas\About\AboutAreaRegistration.cs" /> | |||
<Compile Include="Areas\About\Controllers\AboutController.cs" /> | |||
<Compile Include="Areas\Blog\BlogAreaRegistration.cs" /> | |||
<Compile Include="Areas\Blog\Models\Comment.cs" /> | |||
<Compile Include="Areas\Blog\ViewModels\BlogViewModel.cs" /> | |||
<Compile Include="Areas\Blog\ViewModels\CommentViewModel.cs" /> | |||
<Compile Include="Areas\Blog\ViewModels\PostViewModel.cs" /> | |||
<Compile Include="Areas\Contact\ContactAreaRegistration.cs" /> | |||
<Compile Include="Areas\Contact\Controllers\ContactController.cs" /> | |||
@@ -241,6 +243,8 @@ | |||
<Content Include="Areas\Blog\Views\Blog\Post.cshtml" /> | |||
<Content Include="Areas\Blog\Views\Blog\ViewPost.cshtml" /> | |||
<Content Include="Areas\Profile\Views\Profile\ViewLogin.cshtml" /> | |||
<Content Include="Areas\Blog\Views\Blog\Comments.cshtml" /> | |||
<Content Include="Areas\Blog\Views\Blog\Comment.cshtml" /> | |||
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" /> | |||
<None Include="Scripts\jquery-2.1.4.intellisense.js" /> | |||
<Content Include="Scripts\bootbox\bootbox.min.js" /> |