big refactoring, and more

New routes, new juice flow, the tags on posts
This commit is contained in:
Paul Schneider 2015-10-17 14:45:57 +02:00
commit 1805cb3e17
46 changed files with 1339 additions and 515 deletions

View file

@ -21,38 +21,38 @@ namespace Yavsc.ApiControllers
/// </summary>
public class BlogsController : YavscApiController
{
private const string adminRoleName = "Admin";
/// <summary>
/// Initialize the specified controllerContext.
/// </summary>
/// <param name="controllerContext">Controller context.</param>
protected override void Initialize (System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize (controllerContext);
if (!Roles.RoleExists (adminRoleName)) {
Roles.CreateRole (adminRoleName);
}
}
/// <summary>
/// Tag the specified postid and tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="id">Postid.</param>
/// <param name="tag">Tag.</param>
public void Tag (long postid,string tag) {
BlogManager.GetForEditing (postid);
BlogManager.Tag (postid, tag);
[Authorize,
AcceptVerbs ("POST")]
public void Tag (PostTag model) {
if (ModelState.IsValid) {
BlogManager.GetForEditing (model.PostId);
BlogManager.Tag (model.PostId, model.Tag);
}
}
/// <summary>
/// Tags the specified pattern.
/// </summary>
/// <param name="pattern">Pattern.</param>
[ValidateAjaxAttribute]
public IEnumerable<string> Tags(string pattern)
{
return new string[] { "Artistes", "Accueil", "Mentions juridique", "Admin", "Web" } ;
}
/// <summary>
/// Untag the specified postid and tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="id">Postid.</param>
/// <param name="tag">Tag.</param>
public void Untag (long postid,string tag) {
BlogManager.GetForEditing (postid);
BlogManager.Untag (postid, tag);
[Authorize, ValidateAjaxAttribute, HttpPost]
public void Untag (long id, [FromBody] string tag) {
BlogManager.GetForEditing (id);
BlogManager.Untag (id, tag);
}
/// <summary>
@ -60,8 +60,8 @@ namespace Yavsc.ApiControllers
/// </summary>
/// <param name="user">User.</param>
/// <param name="title">Title.</param>
[Authorize]
public void RemoveTitle(string user, string title) {
[Authorize, ValidateAjaxAttribute, HttpPost]
public void RemoveTitle(string user, string title) {
if (Membership.GetUser ().UserName != user)
if (!Roles.IsUserInRole("Admin"))
throw new AuthorizationDenied (user);
@ -72,7 +72,8 @@ namespace Yavsc.ApiControllers
/// Removes the tag.
/// </summary>
/// <param name="tagid">Tagid.</param>
public void RemoveTag(long tagid) {
[Authorize, ValidateAjaxAttribute, HttpPost]
public void RemoveTag([FromBody] long tagid) {
throw new NotImplementedException ();
}
@ -96,7 +97,7 @@ namespace Yavsc.ApiControllers
/// Posts the file.
/// </summary>
/// <returns>The file.</returns>
[Authorize,HttpPost]
[Authorize, HttpPost]
public async Task<HttpResponseMessage> PostFile(long id) {
if (!(Request.Content.Headers.ContentType.MediaType=="multipart/form-data"))
throw new HttpRequestException ("not a multipart/form-data request");
@ -142,10 +143,10 @@ namespace Yavsc.ApiControllers
/// Searchs the file.
/// </summary>
/// <returns>The file.</returns>
/// <param name="postid">Postid.</param>
/// <param name="id">Postid.</param>
/// <param name="terms">Terms.</param>
[Authorize,HttpGet]
public async Task<HttpResponseMessage> SearchFile(long postid, string terms) {
[HttpGet]
public async Task<HttpResponseMessage> SearchFile(long id, string terms) {
throw new NotImplementedException ();
}
@ -154,8 +155,8 @@ namespace Yavsc.ApiControllers
/// </summary>
/// <param name="id">Identifier.</param>
/// <param name="photo">Photo.</param>
[Authorize,HttpPost]
public void SetPhoto(long id, string photo)
[Authorize, HttpPost, ValidateAjaxAttribute]
public void SetPhoto(long id, [FromBody] string photo)
{
BlogManager.Provider.UpdatePostPhoto (id, photo);
}
@ -164,6 +165,7 @@ namespace Yavsc.ApiControllers
/// Import the specified id.
/// </summary>
/// <param name="id">Identifier.</param>
[Authorize, HttpPost, ValidateAjaxAttribute]
public async Task<HttpResponseMessage> Import(long id) {
if (!(Request.Content.Headers.ContentType.MediaType=="multipart/form-data"))
throw new HttpRequestException ("not a multipart/form-data request");

View file

@ -7,24 +7,53 @@ body {
padding: 0;
margin: 0;
}
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
}
/* When the body has the loading class, we turn
the scrollbar off with overflow:hidden */
body.loading {
overflow: hidden;
}
/* Anytime the body has the loading class, our
modal element will be visible */
body.loading .modal {
display: block;
}
.iconsmall { max-height: 1.3em; max-width: 1.3em; }
.photo { width: 100%; }
.blogbanner { float: left; top:0; }
.subtitle { font-size:small; font-style: italic; }
header {
padding: 0;
margin: 0;
margin-top: 0;
padding-top: 201px;
margin-bottom:2em;
padding-bottom:2em;
display: block;
text-align: center;
background: url("/images/totem-banner.xs.jpg") 0 0 no-repeat fixed;
}
header h1, header a {
background-color: rgba(0,0,0,.5);
margin:0; padding:1em;
}
nav {
@ -34,12 +63,11 @@ nav {
border-radius:1em;
background: url("/images/live-concert-388160_1280.jpg") 50% 10em repeat fixed ;
justify-content: space-around;
min-height:5em;
}
main {
margin: 2em;
padding: 6em 2em 6em 2em;
padding: 2em;
display: block;
border-radius:1em;
background: url("/images/musician-923526_1.nbb.jpg") 50% 20em repeat fixed ;
@ -54,29 +82,26 @@ footer {
clear: both;
font-size: smaller;
justify-content: space-around;
}
footer a {
border-radius:5px;
margin:.5em;
border-radius:1em;
padding:1em;
}
legend {
border-radius:5px;
margin:.5em;
padding:1.5em;
padding:.5em;
background-color: rgba(0,0,32,.5);
}
#copyr { text-align: center; display: block; background-color: rgba(20,20,20,.8); }
footer p { display:inline-block; }
footer img { max-height: 2em; vertical-align: middle; }
footer img { max-height: 3em; vertical-align: middle; }
a img, h1 img, .menuitem img { max-height: 1em; vertical-align: middle; }
#gspacer {
background-color: rgba(20,20,20,.8);
border-radius:5px;
margin:.5em; padding:1em; display: inline-block }
border-radius:1em;
margin:1em; padding:1em; display: inline-block }
fieldset {
background-color: rgba(16,16,64,0.8);
border-radius:5px; border: solid 1px #000060;
@ -85,7 +110,7 @@ fieldset {
main video, main img {
max-width:100%;
max-height:75%;
padding: .5em;
padding: 1em;
}
aside {
@ -97,10 +122,9 @@ aside {
.postpreview {
display: inline-block;
max-width: 40em;
padding: .5em;
margin: .5em;
padding: 1em;
background-color: rgba(0,0,32,0.8);
border-radius:10px;
border-radius:1em;
}
.postpreview video, .postpreview img {
max-width:100%;
@ -108,11 +132,10 @@ aside {
}
.post {
display:block;
margin:1em;
padding:1em;
padding: 1em;
background-color: rgba(0,0,32,0.8);
color: #eee;
border-radius:10px;
border-radius:1em;
}
.hiddenpost { background-color: rgba(16,16,16,0.5); }
.fullwidth { width: 100%; }
@ -129,24 +152,23 @@ textarea.fullwidth { min-height:10em; }
.panel,.bshpanel, aside {
background-color: rgba(20,20,20,.8);
border-radius: 5px;
margin: .5em;
padding: .5em;
border-radius: 1em;
padding: 1em;
}
.spanel {
max-width: 24em;
display: inline-block;
margin: .3em;
padding: .3em;
}
.xspanel {
max-width:13em;
display: inline-block;
margin:.2em;
padding:.2em;
}
.xxspanel {
max-width:7em;
display: inline-block;
margin:.1em;
padding:.1em;
}
.hint {
display: inline;
@ -162,7 +184,7 @@ content: ")";
.usertitleref {
border-radius: 5px;
border-radius: 1em;
background-color:rgba(0,0,32,0.6);
font-family: 'Arial', cursive;
padding: 1em;
@ -180,8 +202,7 @@ label {
border: dashed rgb(020,20,256) 2px;
}
#notifications {
margin: 2em;
padding: 2em;
padding: 1em;
}
.notification {
@ -230,7 +251,6 @@ a {
cursor: pointer;
font-family: 'Arial', cursive;
padding: 1em;
margin:1em;
}
input, select, textarea {
@ -299,22 +319,33 @@ input, select, textarea {
.c3-alt { display:none; }
@media all and (max-width: 640px) {
header {
padding-bottom:1em;
}
header h1, header a , .actionlink, .menuitem, a { padding:.5em;}
nav {
margin: 1em;
margin: 1em;
padding: 1em;
min-height:4em;
background: url("/images/live-concert-388160_1280.s.jpg") 50% 10% repeat fixed ;
}
main {
margin: 1em;
padding: 4em 1em 4em 1em;
margin: 1em;
padding: 1em;
background: url("/images/musician-923526_1.nbb.xs.jpg") 50% 20em repeat fixed ;
}
footer {
background: url("/images/drummer-652345_1280.xs.jpg") 50% 90% repeat fixed ;
padding: 1em;
margin: 1em;
background: url("/images/drummer-652345_1280.s.jpg") 50% 90% repeat fixed ;
}
footer a {
border-radius:.5em;
margin:.5em;
padding:.5em;
}
#notifications {
padding: .5em;
}
.menuitem {
display: block;
}
@ -326,7 +357,6 @@ input, select, textarea {
padding:.3em;
}
.bshpanel { cursor:zoom-in; }
footer { clear:both; }
.c2 { display:initial; }
.c2-alt { display:none; }
@ -336,30 +366,30 @@ input, select, textarea {
@media all and (max-width: 350px) {
header {
padding: 0;
margin: 0;
margin-top: 0;
padding-top: 101px;
margin-bottom:1em;
padding-bottom:1em;
background: url("/images/totem-banner.xxs.jpg") 0 0 no-repeat fixed;
}
header h1, header a { padding:.2em;}
nav {
margin: .5em;
margin: .5em;
padding: .5em;
min-height:3em;
background: url("/images/live-concert-388160_1280.xxs.jpg") 50% 10% repeat fixed ;
}
main {
margin: .5em;
padding: 3em .5em 3em .5em;
margin: .5em;
padding: .5em;
background: url("/images/musician-923526_1.nbb.xxs.jpg") 50% 20em repeat fixed ;
}
footer {
background: url("/images/drummer-652345_1280.xxs.jpg") 50% 90% repeat fixed ;
margin: 0.5em;
padding: 0.5em;
}
footer a {
border-radius:.2em;
margin:.2em;
padding:.2em;
}
.c2 { display:none; }
.c2-alt { display:initial; }
}

View file

@ -1,3 +1,29 @@
2015-10-17 Paul Schneider <paul@pschneider.fr>
* Web.csproj:
* Global.asax.cs:
* yavsc.js:
* App.master:
* style.css:
* Edit.aspx:
* Title.aspx:
* Index.aspx:
* YavscHelpers.cs:
* UserPost.aspx:
* UserPosts.aspx:
* PageLinks.ascx:
* TagControl.ascx:
* PostActions.ascx:
* HomeController.cs:
* AdminController.cs:
* BlogsController.cs:
* GoogleController.cs:
* Estimate.aspx:
* AccountController.cs:
* BlogsController.cs:
* knockout-jqAutocomplete.js:
* knockout-jqAutocomplete.min.js:
2015-10-13 Paul Schneider <paul@pschneider.fr>
* Index.aspx:

View file

@ -388,20 +388,20 @@ namespace Yavsc.Controllers
{
MembershipUser u = Membership.GetUser (id, false);
if (u == null) {
ViewData ["Error"] =
string.Format ("Cet utilisateur n'existe pas ({0})", id);
YavscHelpers.Notify( ViewData,
string.Format ("Cet utilisateur n'existe pas ({0})", id));
} else if (u.ProviderUserKey.ToString () == key) {
if (u.IsApproved) {
ViewData ["Message"] =
string.Format ("Votre compte ({0}) est déjà validé.", id);
YavscHelpers.Notify( ViewData,
string.Format ("Votre compte ({0}) est déjà validé.", id));
} else {
u.IsApproved = true;
Membership.UpdateUser (u);
ViewData ["Message"] =
string.Format ("La création de votre compte ({0}) est validée.", id);
YavscHelpers.Notify( ViewData,
string.Format ("La création de votre compte ({0}) est validée.", id));
}
} else
ViewData ["Error"] = "La clé utilisée pour valider ce compte est incorrecte";
YavscHelpers.Notify( ViewData, "La clé utilisée pour valider ce compte est incorrecte" );
return View ();
}

View file

@ -165,7 +165,7 @@ namespace Yavsc.Controllers
ViewData ["usertoremove"] = username;
if (submitbutton == "Supprimer") {
Membership.DeleteUser (username);
YavscHelpers.Notice(ViewData, string.Format("utilisateur \"{0}\" supprimé",username));
YavscHelpers.Notify(ViewData, string.Format("utilisateur \"{0}\" supprimé",username));
ViewData ["usertoremove"] = null;
}
return View ();
@ -240,7 +240,7 @@ namespace Yavsc.Controllers
public ActionResult DoAddRole (string rolename)
{
Roles.CreateRole(rolename);
YavscHelpers.Notice(ViewData, LocalizedText.role_created+ " : "+rolename);
YavscHelpers.Notify(ViewData, LocalizedText.role_created+ " : "+rolename);
return View ();
}
@ -278,7 +278,7 @@ namespace Yavsc.Controllers
ViewData ["useritems"] = users;
if (ModelState.IsValid) {
Roles.AddUserToRole (model.UserName, adminRoleName);
YavscHelpers.Notice(ViewData, model.UserName + " "+LocalizedText.was_added_to_the_role+" '" + adminRoleName + "'");
YavscHelpers.Notify(ViewData, model.UserName + " "+LocalizedText.was_added_to_the_role+" '" + adminRoleName + "'");
} else {
if (admins.Length > 0) {
if (! admins.Contains (Membership.GetUser ().UserName)) {
@ -290,7 +290,7 @@ namespace Yavsc.Controllers
// No admin, gives the Admin Role to the current user
Roles.AddUserToRole (currentUser, adminRoleName);
admins = new string[] { currentUser };
YavscHelpers.Notice(ViewData, string.Format (
YavscHelpers.Notify(ViewData, string.Format (
LocalizedText.was_added_to_the_empty_role,
currentUser, adminRoleName));
}

View file

@ -36,8 +36,11 @@ namespace Yavsc.Controllers
/// <param name="title">Title.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
public ActionResult Index (int pageIndex = 0, int pageSize = 10)
public ActionResult Index (string title, int pageIndex = 0, int pageSize = 10)
{
if (title != null)
return Title (title, pageIndex, pageSize);
return BlogList (pageIndex, pageSize);
}
/// <summary>
@ -45,7 +48,7 @@ namespace Yavsc.Controllers
/// </summary>
/// <returns>The media.</returns>
/// <param name="id">Identifier.</param>
public ActionResult ChooseMedia(long id)
public ActionResult ChooseMedia(long postid)
{
return View ();
}
@ -76,20 +79,20 @@ namespace Yavsc.Controllers
/// <param name="pageSize">Page size.</param>
///
[HttpGet]
public ActionResult Title (string id, int pageIndex = 0, int pageSize = 10)
public ActionResult Title (string title, int pageIndex = 0, int pageSize = 10)
{
int recordCount;
MembershipUser u = Membership.GetUser ();
string username = u == null ? null : u.UserName;
FindBlogEntryFlags sf = FindBlogEntryFlags.MatchTitle;
BlogEntryCollection c =
BlogManager.FindPost (username, id, sf, pageIndex, pageSize, out recordCount);
var utc = new UTBlogEntryCollection (id);
BlogManager.FindPost (username, title, sf, pageIndex, pageSize, out recordCount);
var utc = new UTBlogEntryCollection (title);
utc.AddRange (c);
ViewData ["RecordCount"] = recordCount;
ViewData ["PageIndex"] = pageIndex;
ViewData ["PageSize"] = pageSize;
return View (utc);
return View ("Title", utc);
}
/// <summary>
@ -100,27 +103,30 @@ namespace Yavsc.Controllers
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
[HttpGet]
public ActionResult UserPosts (string id, int pageIndex = 0, int pageSize = 10)
public ActionResult UserPosts (string user, string title=null, int pageIndex = 0, int pageSize = 10)
{
if (title != null) return UserPost (user, title, pageIndex, pageSize);
int recordcount=0;
MembershipUser u = Membership.GetUser ();
FindBlogEntryFlags sf = FindBlogEntryFlags.MatchUserName;
ViewData ["SiteName"] = sitename;
ViewData ["BlogUser"] = id;
ViewData ["BlogUser"] = user;
string readersName = null;
ViewData ["PageIndex"] = pageIndex;
ViewData ["pageSize"] = pageSize;
// displays invisible items when the logged user is also the author
if (u != null) {
if (u.UserName == id || Roles.IsUserInRole ("Admin"))
if (u.UserName == user || Roles.IsUserInRole ("Admin"))
sf |= FindBlogEntryFlags.MatchInvisible;
readersName = u.UserName;
if (user == null)
user = u.UserName;
}
// find entries
BlogEntryCollection c =
BlogManager.FindPost (readersName, id, sf, pageIndex, pageSize, out recordcount);
BlogManager.FindPost (readersName, user, sf, pageIndex, pageSize, out recordcount);
// Get author's meta data
var pr = ProfileBase.Create (id);
var pr = ProfileBase.Create (user);
if (pr != null) {
Profile bupr = new Profile (pr);
ViewData ["BlogUserProfile"] = bupr;
@ -130,7 +136,7 @@ namespace Yavsc.Controllers
ViewData ["Avatar"] = bupr.avatar;
}
ViewData ["RecordCount"] = recordcount;
UUBlogEntryCollection uuc = new UUBlogEntryCollection (id, c);
UUBlogEntryCollection uuc = new UUBlogEntryCollection (user, c);
return View ("UserPosts", uuc);
}
@ -147,14 +153,14 @@ namespace Yavsc.Controllers
}
/// <summary>
/// Returns the post.
/// Gets the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="id">Identifier.</param>
public ActionResult GetPost (long id)
/// <param name="postid">Postid.</param>
public ActionResult GetPost (long postid)
{
ViewData ["id"] = id;
BlogEntry e = BlogManager.GetForReading (id);
ViewData ["id"] = postid;
BlogEntry e = BlogManager.GetForReading (postid);
UUTBlogEntryCollection c = new UUTBlogEntryCollection (e.Author,e.Title);
c.Add (e);
ViewData ["user"] = c.Author;
@ -306,15 +312,15 @@ namespace Yavsc.Controllers
/// </summary>
/// <param name="id">Identifier.</param>
[Authorize]
public ActionResult Edit (long id)
public ActionResult Edit (long postid)
{
BlogEntry e = BlogManager.GetForEditing (id);
BlogEntry e = BlogManager.GetForEditing (postid);
string user = Membership.GetUser ().UserName;
Profile pr = new Profile (ProfileBase.Create(e.Author));
ViewData ["BlogTitle"] = pr.BlogTitle;
ViewData ["LOGIN"] = user;
ViewData ["Id"] = id;
ViewData ["Id"] = postid;
// Populates the circles combo items
if (e.AllowedCircles == null)
@ -356,21 +362,21 @@ namespace Yavsc.Controllers
/// <param name="returnUrl">Return URL.</param>
/// <param name="confirm">If set to <c>true</c> confirm.</param>
[Authorize]
public ActionResult RemoveTitle (string id, string user, string returnUrl, bool confirm = false)
public ActionResult RemoveTitle (string user, string title, string returnUrl, bool confirm = false)
{
if (returnUrl == null)
if (Request.UrlReferrer != null)
returnUrl = Request.UrlReferrer.AbsoluteUri;
ViewData ["returnUrl"] = returnUrl;
ViewData ["Author"] = user;
ViewData ["Title"] = id;
ViewData ["Title"] = title;
if (Membership.GetUser ().UserName != user)
if (!Roles.IsUserInRole("Admin"))
throw new AuthorizationDenied (user);
if (!confirm)
return View ("RemoveTitle");
BlogManager.RemoveTitle (user, id);
BlogManager.RemoveTitle (user, title);
if (returnUrl == null)
RedirectToAction ("Index", new { user = user });
return Redirect (returnUrl);
@ -384,19 +390,19 @@ namespace Yavsc.Controllers
/// <param name="returnUrl">Return URL.</param>
/// <param name="confirm">If set to <c>true</c> confirm.</param>
[Authorize]
public ActionResult RemovePost (long id, string returnUrl, bool confirm = false)
public ActionResult RemovePost (long postid, string returnUrl, bool confirm = false)
{
// ensures the access control
BlogEntry e = BlogManager.GetForEditing (id);
BlogEntry e = BlogManager.GetForEditing (postid);
if (e == null)
return new HttpNotFoundResult ("post id "+id.ToString());
ViewData ["id"] = id;
return new HttpNotFoundResult ("post id "+postid.ToString());
ViewData ["id"] = postid;
ViewData ["returnUrl"] = string.IsNullOrWhiteSpace(returnUrl)?
Request.UrlReferrer.AbsoluteUri.ToString(): returnUrl;
// TODO: cleaner way to disallow deletion
if (!confirm)
return View ("RemovePost",e);
BlogManager.RemovePost (id);
BlogManager.RemovePost (postid);
if (string.IsNullOrWhiteSpace(returnUrl))
return RedirectToAction ("Index");
return Redirect (returnUrl);

View file

@ -106,7 +106,7 @@ namespace Yavsc.Controllers
AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg);
if (gat == null) {
YavscHelpers.Notice(ViewData, msg);
YavscHelpers.Notify(ViewData, msg);
return View ("Auth");
}
SaveToken (gat);
@ -143,7 +143,7 @@ namespace Yavsc.Controllers
OAuth2 oa = new OAuth2 (AuthGRU);
AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg);
if (gat == null) {
YavscHelpers.Notice(ViewData, msg);
YavscHelpers.Notify(ViewData, msg);
return View ();
}
string returnUrl = (string)Session ["returnUrl"];

View file

@ -121,7 +121,7 @@ namespace Yavsc.Controllers
using (System.Net.Mail.SmtpClient sc = new SmtpClient())
{
sc.Send (msg);
YavscHelpers.Notice(ViewData, LocalizedText.Message_sent);
YavscHelpers.Notify(ViewData, LocalizedText.Message_sent);
return View (new { email=email, reason="", body="" });
}
}

View file

@ -47,17 +47,33 @@ namespace Yavsc
routes.IgnoreRoute ("favicon.png"); // favorite icon
routes.IgnoreRoute ("robots.txt"); // for search engine robots
routes.MapRoute (
"View",
"v/{title}",
"Titles",
"t/{title}",
new { controller = "Blogs", action = "Index",
title=UrlParameter.Optional }
);
routes.MapRoute (
"Blogs",
"b/{user}/{title}",
"b/{user}",
new { controller = "Blogs",
action = "UserPosts",
user="Paul Schneider" }
);
routes.MapRoute (
"BlogByTitle",
"by/{user}/{title}/{id}",
new { controller = "Blogs",
action = "UserPosts",
user="Paul Schneider",
title=UrlParameter.Optional,
id=UrlParameter.Optional }
);
routes.MapRoute (
"BlogById",
"b/{action}/{postid}",
new { controller = "Blogs", action = "Index",
user=UrlParameter.Optional,
title=UrlParameter.Optional }
postid=UrlParameter.Optional }
);
/* routes.MapRoute (
"Artistes",

View file

@ -13,6 +13,7 @@ using System.Web.UI;
using System.Linq.Expressions;
using System.Web.Profile;
using System.Web.Script.Serialization;
using System.Web.Mvc;
namespace Yavsc.Helpers
{
@ -214,14 +215,22 @@ namespace Yavsc.Helpers
return serializer.Serialize(obj);
}
/// <summary>
/// Notice the specified ViewData with message.
/// Notifies
/// </summary>
/// <param name="ViewData">View data.</param>
/// <param name="message">Message.</param>
public static void Notice (System.Web.Mvc.ViewDataDictionary ViewData, string message) {
if (ViewData ["Notifications"] == null)
ViewData ["Notifications"] = new List<string> ();
(ViewData ["Notifications"] as List<string>).Add (message.Replace("\'","\\\'"));
public static void Notify (this HtmlHelper helper, string message) {
Notify (helper.ViewData, message);
}
/// <summary>
/// Notify the specified viewData and message.
/// </summary>
/// <param name="viewData">View data.</param>
/// <param name="message">Message.</param>
public static void Notify(ViewDataDictionary viewData, string message) {
if (viewData ["Notifications"] == null)
viewData ["Notifications"] = new List<string> ();
(viewData ["Notifications"] as List<string>).Add (message.Replace("\'","\\\'"));
}
/// <summary>
/// Files the list.
@ -279,6 +288,53 @@ namespace Yavsc.Helpers
return new System.Web.Mvc.MvcHtmlString (str.ToString ());
}
/// <summary>
/// Renders the page links.
/// </summary>
/// <returns>The page links.</returns>
/// <param name="helper">Helper.</param>
/// <param name="ResultCount">Result count.</param>
/// <param name="PageSize">Page size.</param>
/// <param name="PageIndex">Page index.</param>
public static IHtmlString RenderPageLinks (
this HtmlHelper helper,
int PageIndex, int PageSize, int ResultCount,
string args="?PageIndex={0}",
string pagesLabel="Pages: ", string singlePage="",
string none="néant"
)
{
StringWriter strwr = new StringWriter ();
HtmlTextWriter writer = new HtmlTextWriter(strwr);
if (ResultCount > 0 && ResultCount > PageSize ) {
int pageCount = ((ResultCount-1) / PageSize) + 1;
if ( pageCount > 1 ) {
writer.WriteEncodedText (pagesLabel);
for (int pi = (PageIndex < 5) ? 0 : PageIndex - 5; pi < pageCount && pi < PageIndex + 5; pi++) {
if (PageIndex == pi)
writer.RenderBeginTag ("b");
else {
writer.AddAttribute (HtmlTextWriterAttribute.Href,
string.Format (args, pi));
writer.RenderBeginTag ("a");
}
writer.Write (pi + 1);
writer.RenderEndTag ();
writer.Write ("&nbsp;");
}
}
else {
writer.Write (singlePage);
}
}
if (ResultCount == 0) {
writer.Write (none);
}
return new MvcHtmlString(strwr.ToString());
}
}
}

View file

@ -19,8 +19,9 @@
<script type="text/javascript">
var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</script>
<script src="<%=Url.Content("~/Scripts/yavsc.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/yavsc.scrollnotif.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/yavsc.js")%>">
</script>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
@ -29,34 +30,38 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
<asp:ContentPlaceHolder ID="overHeaderOne" runat="server">
<h1><a href="<%= Url.Content("~/") %>">
<%=ViewState["orgtitle"]%></a>
<span> -
<a href="<%= Url.Content("~/") %>"><%= YavscHelpers.SiteName %></a>
</span></h1>
- <a href="<%= Url.Content("~/") %>"><%= YavscHelpers.SiteName %></a>
</h1>
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder>
<div id="notifications"></div>
<%if (ViewData ["Notifications"]!=null) { %>
<script>
$(document).ready(function(){
<%if (ViewData ["Notifications"]!=null) { %>
<% foreach (string notice in (IEnumerable<string>) ViewData ["Notifications"] ) { %>
Yavsc.notice('<%=notice%>');
<% } %>
<% } %>
$body = $("body");
$(document).on({
ajaxStart: function() { $body.addClass("loading"); },
ajaxStop: function() { $body.removeClass("loading"); }
});
});
</script>
<% } %>
</header>
<nav data-type="background" data-speed="2">
<% if (Membership.GetUser()==null) { %>
<a href="<%= Url.Content("~/Account/Login/?returnUrl=") + Url.Encode( Request.Url.PathAndQuery )%>" class="menuitem" >
<a href="<%= Url.RouteUrl("Default", new { controller = "Account", action = "Login", returnUrl=Request.Url.PathAndQuery}) %>" class="menuitem" accesskey = "C">
<i class="fa fa-sign-in">Connexion</i>
</a>
<% } else { %>
<a href="<%=Url.Content("~/b/"+HttpContext.Current.User.Identity.Name)%>" accesskey = "B" class="menuitem" >
<a href="<%=Url.RouteUrl("Blogs", new { user = HttpContext.Current.User.Identity.Name } )%>" accesskey = "B" class="menuitem" >
<img src="<%=Url.AvatarUrl(HttpContext.Current.User.Identity.Name)%>" alt="vos billets" class="iconsmall" />
<span class="hint">Vos billets</span>
</a>
<a href="<%= Url.Content("~/Account/Profile/" + HttpContext.Current.User.Identity.Name) %>" accesskey="L" class="menuitem">
<a href="<%= Url.RouteUrl("Default", new { controller = "Account", action = "Profile", id = HttpContext.Current.User.Identity.Name} ) %>" accesskey="P" class="menuitem">
<i class="fa fa-user"><%= HttpContext.Current.User.Identity.Name %>
<span class="hint"> &Eacute;dition de votre profile </span></i>
</a>
@ -65,7 +70,7 @@ Yavsc.notice('<%=notice%>');
<span class="hint">&Eacute;dition d'un nouveau billet </span></i>
</a>
<a href="<%= Url.Content( "~/Account/Logout/?returnUrl=")+Url.Encode(Request.Url.PathAndQuery)%>" accesskey = "P" class="menuitem">
<a href="<%= Url.RouteUrl("Default", new { controller = "Account", action = "Logout", returnUrl=Request.Url.PathAndQuery}) %>" accesskey = "C" class="menuitem">
<i class="fa fa-sign-out">Deconnexion</i></a>
<% } %>
</nav>
@ -93,6 +98,6 @@ Yavsc.notice('<%=notice%>');
<div id="gspacer" class="control"><div class="g-plusone" data-annotation="inline" data-width="170"></div>
</div>
</div>
</footer>
</footer><div class="modal"></div>
</body>
</html>

View file

@ -1,41 +0,0 @@
//
// NUnitTestClass.cs
//
// Author:
// Paul Schneider <paul@pschneider.fr>
//
// Copyright (c) 2015 GNU GPL
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using NUnit.Framework;
using System;
namespace Yavsc
{
/// <summary>
/// N unit test class.
/// </summary>
[TestFixture ()]
public class NUnitTestClass
{
/// <summary>
/// Tests the case.
/// </summary>
[Test ()]
public void TestCase ()
{
}
}
}

View file

@ -0,0 +1,189 @@
// knockout-jqAutocomplete 0.4.3 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
;(function(factory) {
if (typeof define === "function" && define.amd) {
// AMD anonymous module
define(["knockout", "jquery", "jquery-ui/autocomplete"], factory);
} else {
// No module loader - put directly in global namespace
factory(window.ko, jQuery);
}
})(function(ko, $) {
var JqAuto = function() {
var self = this,
unwrap = ko.utils.unwrapObservable; //support older KO versions that did not have ko.unwrap
//binding's init function
this.init = function(element, valueAccessor, allBindings, data, context) {
var existingSelect, existingChange,
options = unwrap(valueAccessor()),
config = {},
filter = typeof options.filter === "function" ? options.filter : self.defaultFilter;
//extend with global options
ko.utils.extend(config, self.options);
//override with options passed in binding
ko.utils.extend(config, options.options);
//get source from a function (can be remote call)
if (typeof options.source === "function" && !ko.isObservable(options.source)) {
config.source = function(request, response) {
//provide a wrapper to the normal response callback
var callback = function(data) {
self.processOptions(valueAccessor, null, data, request, response);
};
//call the provided function for retrieving data
options.source.call(context.$data, request.term, callback);
};
}
else {
//process local data
config.source = self.processOptions.bind(self, valueAccessor, filter, options.source);
}
//save any passed in select/change calls
existingSelect = typeof config.select === "function" && config.select;
existingChange = typeof config.change === "function" && config.change;
//handle updating the actual value
config.select = function(event, ui) {
if (ui.item && ui.item.actual) {
options.value(ui.item.actual);
if (ko.isWriteableObservable(options.dataValue)) {
options.dataValue(ui.item.data);
}
}
if (existingSelect) {
existingSelect.apply(this, arguments);
}
};
//user made a change without selecting a value from the list
config.change = function(event, ui) {
if (!ui.item || !ui.item.actual) {
options.value(event.target && event.target.value);
if (ko.isWriteableObservable(options.dataValue)) {
options.dataValue(null);
}
}
if (existingChange) {
existingChange.apply(this, arguments);
}
};
//initialize the widget
var widget = $(element).autocomplete(config).data("ui-autocomplete");
//render a template for the items
if (options.template) {
widget._renderItem = self.renderItem.bind(self, options.template, context);
}
//destroy the widget if KO removes the element
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
if (widget && typeof widget.destroy === "function") {
widget.destroy();
widget = null;
}
});
};
//the binding's update function. keep value in sync with model
this.update = function(element, valueAccessor) {
var propNames, sources,
options = unwrap(valueAccessor()),
value = unwrap(options && options.value);
if (!value && value !== 0) {
value = "";
}
// find the appropriate value for the input
sources = unwrap(options.source);
propNames = self.getPropertyNames(valueAccessor);
// if there is local data, then try to determine the appropriate value for the input
if ($.isArray(sources) && propNames.value) {
value = ko.utils.arrayFirst(sources, function (opt) {
return opt[propNames.value] == value;
}
) || value;
}
if (propNames.input && value && typeof value === "object") {
element.value = value[propNames.input];
}
else {
element.value = value;
}
};
//if dealing with local data, the default filtering function
this.defaultFilter = function(item, term) {
term = term && term.toLowerCase();
return (item || item === 0) && ko.toJSON(item).toLowerCase().indexOf(term) > -1;
};
//filter/map options to be in a format that autocomplete requires
this.processOptions = function(valueAccessor, filter, data, request, response) {
var item, index, length,
items = unwrap(data) || [],
results = [],
props = this.getPropertyNames(valueAccessor);
//filter/map items
for (index = 0, length = items.length; index < length; index++) {
item = items[index];
if (!filter || filter(item, request.term)) {
results.push({
label: props.label ? item[props.label] : item.toString(),
value: props.input ? item[props.input] : item.toString(),
actual: props.value ? item[props.value] : item,
data: item
});
}
}
//call autocomplete callback to display list
response(results);
};
//if specified, use a template to render an item
this.renderItem = function(templateName, context, ul, item) {
var $li = $("<li></li>").appendTo(ul),
itemContext = context.createChildContext(item.data);
//apply the template binding
ko.applyBindingsToNode($li[0], { template: templateName }, itemContext);
//clean up
$li.one("remove", ko.cleanNode.bind(ko, $li[0]));
return $li;
};
//retrieve the property names to use for the label, input, and value
this.getPropertyNames = function(valueAccessor) {
var options = ko.toJS(valueAccessor());
return {
label: options.labelProp || options.valueProp,
input: options.inputProp || options.labelProp || options.valueProp,
value: options.valueProp
};
};
//default global options passed into autocomplete widget
this.options = {
autoFocus: true,
delay: 50
};
};
ko.bindingHandlers.jqAuto = new JqAuto();
});

View file

@ -0,0 +1,2 @@
// knockout-jqAutocomplete 0.4.3 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
!function(a){"function"==typeof define&&define.amd?define(["knockout","jquery","jquery-ui/autocomplete"],a):a(window.ko,jQuery)}(function(a,b){var c=function(){var c=this,d=a.utils.unwrapObservable;this.init=function(e,f,g,h,i){var j,k,l=d(f()),m={},n="function"==typeof l.filter?l.filter:c.defaultFilter;a.utils.extend(m,c.options),a.utils.extend(m,l.options),m.source="function"!=typeof l.source||a.isObservable(l.source)?c.processOptions.bind(c,f,n,l.source):function(a,b){var d=function(d){c.processOptions(f,null,d,a,b)};l.source.call(i.$data,a.term,d)},j="function"==typeof m.select&&m.select,k="function"==typeof m.change&&m.change,m.select=function(b,c){c.item&&c.item.actual&&(l.value(c.item.actual),a.isWriteableObservable(l.dataValue)&&l.dataValue(c.item.data)),j&&j.apply(this,arguments)},m.change=function(b,c){c.item&&c.item.actual||(l.value(b.target&&b.target.value),a.isWriteableObservable(l.dataValue)&&l.dataValue(null)),k&&k.apply(this,arguments)};var o=b(e).autocomplete(m).data("ui-autocomplete");l.template&&(o._renderItem=c.renderItem.bind(c,l.template,i)),a.utils.domNodeDisposal.addDisposeCallback(e,function(){o&&"function"==typeof o.destroy&&(o.destroy(),o=null)})},this.update=function(e,f){var g,h,i=d(f()),j=d(i&&i.value);j||0===j||(j=""),h=d(i.source),g=c.getPropertyNames(f),b.isArray(h)&&g.value&&(j=a.utils.arrayFirst(h,function(a){return a[g.value]==j})||j),e.value=g.input&&j&&"object"==typeof j?j[g.input]:j},this.defaultFilter=function(b,c){return c=c&&c.toLowerCase(),(b||0===b)&&a.toJSON(b).toLowerCase().indexOf(c)>-1},this.processOptions=function(a,b,c,e,f){var g,h,i,j=d(c)||[],k=[],l=this.getPropertyNames(a);for(h=0,i=j.length;i>h;h++)g=j[h],(!b||b(g,e.term))&&k.push({label:l.label?g[l.label]:g.toString(),value:l.input?g[l.input]:g.toString(),actual:l.value?g[l.value]:g,data:g});f(k)},this.renderItem=function(c,d,e,f){var g=b("<li></li>").appendTo(e),h=d.createChildContext(f.data);return a.applyBindingsToNode(g[0],{template:c},h),g.one("remove",a.cleanNode.bind(a,g[0])),g},this.getPropertyNames=function(b){var c=a.toJS(b());return{label:c.labelProp||c.valueProp,input:c.inputProp||c.labelProp||c.valueProp,value:c.valueProp}},this.options={autoFocus:!0,delay:50}};a.bindingHandlers.jqAuto=new c});

View file

@ -1,6 +1,13 @@
var Yavsc = (function(apiBaseUrl){
var self = {};
function dumpprops(obj) {
var str = "";
for(var k in obj)
if (obj.hasOwnProperty(k))
str += k + " = " + obj[k] + "\n";
return (str); }
self.apiBaseUrl = (apiBaseUrl || '/api');
self.showHide = function () {
@ -33,8 +40,11 @@ self.notice = function (msg, msgok) {
self.onAjaxBadInput = function (data)
{
if (!data) { Yavsc.notice('no data'); return; }
if (!data.responseJSON) { Yavsc.notice('no json data:'+data); return; }
if (!Array.isArray(data.responseJSON)) { Yavsc.notice('Bad Input: '+data.responseJSON); return; }
$.each(data.responseJSON, function (key, value) {
var errspanid = "Err_cr_" + value.key.replace("model.","");
var errspanid = "Err_" + value.key;
var errspan = document.getElementById(errspanid);
if (errspan==null)
alert('enoent '+errspanid);
@ -47,9 +57,24 @@ self.notice = function (msg, msgok) {
self.onAjaxError = function (xhr, ajaxOptions, thrownError) {
if (xhr.status!=400)
Yavsc.notice(xhr.status+" : "+xhr.responseText);
else Yavsc.notice(false);
};
return self;
})();
$(document).ready(function(){
var $window = $(window);
$(window).scroll(function() {
var $ns = $('#notifications');
if ($ns.has('*').length>0) {
if ($window.scrollTop()>375) {
$ns.css('position','fixed');
$ns.css('z-index',2);
$ns.css('top',0);
}
else {
$ns.css('position','static');
$ns.css('z-index',1);
}}
});
});

View file

@ -1,37 +0,0 @@
//
// parralax.js
//
// Author:
// Paul Schneider <paul@pschneider.fr>
//
// Copyright (c) 2015 GNU GPL
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
$(document).ready(function(){
var $window = $(window);
$(window).scroll(function() {
var $ns = $('#notifications');
if ($ns.has('*').length>0) {
if ($window.scrollTop()>375) {
$ns.css('position','fixed');
$ns.css('z-index',2);
$ns.css('top',0);
}
else {
$ns.css('position','static');
$ns.css('z-index',1);
}}
});
});

View file

@ -25,25 +25,19 @@
<hr>
<script>
function dumpprops(obj) {
var str = "";
for(var k in obj)
if (obj.hasOwnProperty(k))
str += k + " = " + obj[k] + "\n";
return (str); }
$(document).ready(function(){
$('#hidesource').click(function(){
$('#source').addClass('hidden');
$('#viewsource').removeClass('hidden');
$('#hidesource').addClass('hidden');
});
$('#viewsource').click(function(){
$('#source').removeClass('hidden');
$('#viewsource').addClass('hidden');
$('#hidesource').removeClass('hidden');
});
$('#hidesource').click(function(){
$('#source').addClass('hidden');
$('#viewsource').removeClass('hidden');
$('#hidesource').addClass('hidden');
});
$('#viewsource').click(function(){
$('#source').removeClass('hidden');
$('#viewsource').addClass('hidden');
$('#hidesource').removeClass('hidden');
});
jQuery('.placard').hallo({plugins: {'hallo-image-insert-edit': { lang: 'fr' } } });

View file

@ -4,7 +4,7 @@
<div>
<% foreach (var g in Model.GroupByTitle()) { %>
<h2><%=Html.ActionLink(g.Key, "Title", "Blogs", new { id = g.Key } , new { @class="userref" } )%></h2>
<h2><a href="<%= Url.RouteUrl("Titles", new { title = g.Key }) %>" class="usertitleref"><%=Html.Encode(g.Key)%></a></h2>
<% foreach (var p in g) { %>
<div class="postpreview">
<p><%= Html.Markdown(p.Intro,"/bfiles/"+p.Id+"/") %></p>
@ -12,16 +12,5 @@
</div> <% } %>
<% } %>
</div>
<form runat="server" id="form1" method="GET">
<%
rp1.ResultCount = (int) ViewData["ResultCount"];
rp1.PageSize = (int) ViewData ["PageSize"];
rp1.PageIndex = (int) ViewData["PageIndex"];
rp1.None = Html.Translate("no content");
%>
<yavsc:ResultPages id="rp1" runat="server" >
<None>Aucun résultat</None>
</yavsc:ResultPages>
</form>
<%= Html.RenderPageLinks((int)ViewData["PageIndex"],(int)ViewData["PageSize"],(int)ViewData["ResultCount"])%>
</asp:Content>

View file

@ -0,0 +1,8 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= (int) ViewData["ResultCount"] %>
rp1.PageSize = (int) ViewData ["PageSize"];
rp1.PageIndex = (int) ViewData["PageIndex"];
rp1.None = Html.Translate("no content");

View file

@ -1,15 +1,15 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BasePost>" %>
<aside>
(<%= Model.Posted.ToString("yyyy/MM/dd") %>
- <%= Model.Modified.ToString("yyyy/MM/dd") %> <%= Model.Visible? "":", Invisible!" %>)
(<%= Model.Posted.ToString("D") %>
- <%= Model.Modified.ToString("D") %> <%= Model.Visible? "":", Invisible!" %>)
<% if (Membership.GetUser()!=null) {
if (Membership.GetUser().UserName==Model.Author || Roles.IsUserInRole("Admin"))
{ %>
<i class="fa fa-tag"><%=Html.Translate("DoTag")%></i>
<a href="<%= Url.RouteUrl("Default", new { action = "Edit", controller = "Blogs", id = Model.Id })%>" class="actionlink">
<% if (Model is BlogEntry) { %><%= Html.Partial("TagControl",Model)%><% } %>
<a href="<%= Url.RouteUrl("BlogById", new { action = "Edit", postid = Model.Id })%>" class="actionlink">
<i class="fa fa-pencil"><%=Html.Translate("Edit")%></i>
</a>
<a href="<%= Url.RouteUrl("Default", new { action = "RemovePost", controller = "Blogs", id = Model.Id })%>" class="actionlink">
<a href="<%= Url.RouteUrl("BlogById", new { action = "RemovePost", postid = Model.Id })%>" class="actionlink">
<i class="fa fa-remove"><%=Html.Translate("Remove")%></i></a>
<% }} %>
</aside>

View file

@ -0,0 +1,97 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BlogEntry>" %>
<ul id="tags">
<% if (Model.Tags != null) foreach (string tagname in Model.Tags) { %>
<li><%= tagname %></li>
<% } %>
</ul>
<% if (Membership.GetUser()!=null) { %>
<% if (Membership.GetUser().UserName==Model.Author || Roles.IsUserInRole("Admin"))
{ // grant all permissions: to choose a given set of tags, also create some new tags %>
<span id="viewtagger">
<i class="fa fa-tag menuitem" id="viewtaggerbtn"><%=Html.Translate("DoTag")%></i></span>
<span id="hidetagger" class="hidden">
<i class="fa fa-tag menuitem" id="hidetaggerbtn" ><%=Html.Translate("Hide")%></i>
Note: Ils sont utilisé pour classifier le document. Par exemple, le tag <code>Accueil</code> rend le document
éligible à une place en page d'Accueil.
</span>
<form id="tagger" class="hidden">
<fieldset>
<legend>Associer des tags au billet</legend>
<label for="newtag"><%= Html.Translate("Tag_name")%>: </label>
<span id="Err_tag" class="error"></span>
<input type="text" id="newtag">
<span id="Err_model" class="error"></span>
<input id="sendnewtag" type="submit" class="fa fa-tag" value="<%=Html.Translate("Submit")%>">
</fieldset>
</form>
<script>
$(document).ready(function(){
$('#hidetaggerbtn').click(function(){
$('#tagger').addClass('hidden');
$('#viewtagger').removeClass('hidden');
$('#hidetagger').addClass('hidden');
});
$('#viewtaggerbtn').click(function(){
$('#tagger').removeClass('hidden');
$('#viewtagger').addClass('hidden');
$('#hidetagger').removeClass('hidden');
});
$('#newtag').autocomplete({
minLength: 0,
delay: 200,
source: function( request, response ) {
$.ajax({
url: "/api/Blogs/Tags",
type: "POST",
data: {
pattern: request.term
},
success: function( data ) {
response( data );
}
});
},
select: function( event, ui ) {
console.log( ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
},
close: function() {
$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
}
});
$('#tagger').on('submit', function(e) { e.preventDefault(); });
$('#sendnewtag').click(function(){
var data = {
postid: <%= Model.Id %>,
tag: $('#newtag').val()
}
$.ajax({
url: '/api/Blogs/Tag/',
type: 'POST',
data: data,
success: function() {
$('<li>'+data.tag+'</li>').appendTo('#tags');
$('#newtag').val('');
},
statusCode: {
400: Yavsc.onAjaxBadInput
},
error: Yavsc.onAjaxError
});
});
});
</script>
<% } %>
<% } %>

View file

@ -6,8 +6,8 @@
<asp:Content ContentPlaceHolderID="overHeaderOne" ID="header1" runat="server">
<h1 class="post">
<%=Html.ActionLink(Model.Title, "Title", new{id=Model.Title}, null)%>
- <a href="<%= Url.Content("~/") %>"><%= YavscHelpers.SiteName %></a>
<%=Html.ActionLink(Model.Title, "Title", new{title=Model.Title}, null)%>
- <a href="<%= Url.RouteUrl("Default") %>"><%= YavscHelpers.SiteName %></a>
</h1>
</asp:Content>

View file

@ -30,7 +30,8 @@
<% string username = Membership.GetUser()==null ? null : Membership.GetUser().UserName; %>
<% foreach (var c in (Comment[]) BlogManager.GetComments(be.Id)) { %>
<div class="comment" style="min-height:32px;"> <img style="clear:left;float:left;max-width:32px;max-height:32px;margin:.3em;" src="<%= Url.Content("~/Account/Avatar/"+c.From) %>" alt="<%=c.From%>"/>
<div class="comment" style="min-height:32px;">
<img style="clear:left;float:left;max-width:32px;max-height:32px;margin:.3em;" src="<%= Url.RouteUrl("Blogs", new { user = c.From } ) %>" alt="<%=c.From%>"/>
<%= Html.Markdown(c.CommentText) %>
<% if (Model.Author == username || c.From == username ) { %>
<%= Html.ActionLink("Supprimer","RemoveComment", new { cmtid = c.Id } , new { @class="actionlink" })%>

View file

@ -7,25 +7,26 @@
<asp:Content ContentPlaceHolderID="overHeaderOne" ID="header1" runat="server">
<% if (!string.IsNullOrEmpty((string)ViewData["Avatar"])) { %>
<a href="<%=Url.Content("~/Blog/"+Model.Author)%>" id="avatar">
<a href="<%=Url.RouteUrl( "Blogs", new { user = Model.Author } )%>" id="avatar">
<img src="<%=ViewData["Avatar"]%>" />
</a>
<% } %>
<h1 class="blogtitle">
<a href="<%=Url.Content("~/Blog/"+Model.Author)%>">
<a href="<%=Url.RouteUrl( "Blogs", new { user = Model.Author } )%>">
<%=Html.Encode(ViewData["BlogTitle"])%></a>
- <a href="<%= Url.Content("~/") %>"><%= YavscHelpers.SiteName %></a>
- <a href="<%= Url.RouteUrl( "Default") %>"><%= YavscHelpers.SiteName %></a>
</h1>
</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
<% foreach (BlogEntry e in this.Model) { %>
<div class="postpreview<% if (!e.Visible) { %> hiddenpost<% } %>" >
<h2><%= Html.ActionLink(e.Title,"UserPost", new { user=e.Author, title=e.Title, id = e.Id }, new { @class = "usertitleref" }) %></h2>
<h2><a href="<%= Url.RouteUrl("BlogByTitle", new { user=e.Author, title=e.Title, id = e.Id })%>" class="usertitleref">
<%=Html.Markdown(e.Title)%></a></h2>
<% bool truncated = false; %>
<%= Html.MarkdownToHtmlIntro(out truncated, e.Content,"/bfiles/"+e.Id+"/") %>
<% if (truncated) { %>
<a href="<%= Url.RouteUrl( "View", new { action="Title", title=e.Title}) %>">
<a href="<%= Url.RouteUrl( "BlogByTitle", new { user=e.Author , title=e.Title, id = e.Id}) %>">
<i>Html.Translate("ReadMore")</i></a>
<% } %>
<%= Html.Partial("PostActions",e)%>

View file

@ -3,9 +3,6 @@
<asp:Content ContentPlaceHolderID="head" ID="head1" runat="server" >
<script type="text/javascript" src="<%=Url.Content("~/Scripts/stupidtable.js")%>"></script>
<script>
$(function(){
$("#tbwrts").stupidtable();
});
</script>
</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
@ -352,6 +349,9 @@ function addRow(){
$("#wr_Count").val(1);
$("#wr_UnitaryCost").val(0);
});
$("#tbwrts").stupidtable();
});
</script>

View file

@ -142,7 +142,6 @@
<Folder Include="fonts\" />
<Folder Include="lib\" />
<Folder Include="App_Data\" />
<Folder Include="Test\" />
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\HomeController.cs" />
@ -190,7 +189,6 @@
<Compile Include="Formatters\EstimToPdfFormatter.MSAN.cs" />
<Compile Include="Helpers\TemplateException.cs" />
<Compile Include="Formatters\FormatterException.cs" />
<Compile Include="NUnitTestClass.cs" />
<Compile Include="TestExec.cs" />
<Compile Include="ApiControllers\WorkFlowController.cs" />
<Compile Include="ApiControllers\BasketController.cs" />
@ -432,7 +430,10 @@
<Content Include="Views\Blogs\Title.aspx" />
<Content Include="Views\Blogs\PostActions.ascx" />
<Content Include="Scripts\yavsc.tags.js" />
<Content Include="Scripts\yavsc.scrollnotif.js" />
<Content Include="Views\Blogs\TagControl.ascx" />
<Content Include="Scripts\knockout-jqAutocomplete.js" />
<Content Include="Scripts\knockout-jqAutocomplete.min.js" />
<Content Include="Views\Blogs\PageLinks.ascx" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />