diff --git a/NpgsqlBlogProvider/ChangeLog b/NpgsqlBlogProvider/ChangeLog new file mode 100644 index 00000000..06ab4884 --- /dev/null +++ b/NpgsqlBlogProvider/ChangeLog @@ -0,0 +1,4 @@ +2015-10-08 Paul Schneider + + * NpgsqlBlogProvider.cs: implements a blog post photo storage + diff --git a/NpgsqlBlogProvider/NpgsqlBlogProvider.cs b/NpgsqlBlogProvider/NpgsqlBlogProvider.cs index 9f237b10..07057683 100644 --- a/NpgsqlBlogProvider/NpgsqlBlogProvider.cs +++ b/NpgsqlBlogProvider/NpgsqlBlogProvider.cs @@ -236,7 +236,7 @@ namespace Npgsql.Web.Blog BlogEntry be = null; using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { - cmd.CommandText = "select username, title, bcontent, modified, posted, visible from blog " + + cmd.CommandText = "select username, title, bcontent, modified, posted, visible, photo from blog " + "where applicationname = @appname and _id = @id"; cmd.Parameters.AddWithValue ("@appname", applicationName); cmd.Parameters.AddWithValue ("@id", postid); @@ -250,6 +250,7 @@ namespace Npgsql.Web.Blog be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); + be.Photo = rdr.GetString (rdr.GetOrdinal ("photo")); be.Id = postid; } } @@ -285,7 +286,7 @@ namespace Npgsql.Web.Blog UUTBlogEntryCollection bec = new UUTBlogEntryCollection (username,title); using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) { - cmd.CommandText = "select _id,bcontent,modified,posted,visible from blog " + + cmd.CommandText = "select _id,bcontent,modified,posted,visible,photo from blog " + "where applicationname = :appname and username = :username and title = :title"; cmd.Parameters.AddWithValue ("appname", NpgsqlDbType.Varchar, applicationName); cmd.Parameters.AddWithValue ("username", NpgsqlDbType.Varchar ,username); @@ -302,6 +303,7 @@ namespace Npgsql.Web.Blog be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); + be.Photo = rdr.GetString (rdr.GetOrdinal ("photo")); bec.Add (be); } rdr.Close (); @@ -393,6 +395,24 @@ namespace Npgsql.Web.Blog UpdatePostCircles (pid, circles); return pid; } + /// + /// Updates the post photo. + /// + /// Pid. + /// Photo. + public override void UpdatePostPhoto ( long pid, string photo) + { + using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { + cnx.Open (); + using (NpgsqlCommand cmd = cnx.CreateCommand ()) { + cmd.CommandText = "update blog set photo = :photo where _id = :pid"; + cmd.Parameters.AddWithValue ("pid", pid); + cmd.Parameters.AddWithValue ("photo", photo); + cmd.ExecuteNonQuery (); + } + cnx.Close (); + } + } private void UpdatePostCircles( long pid, long[] circles) { diff --git a/web/ApiControllers/BlogsController.cs b/web/ApiControllers/BlogsController.cs index d3697a11..67ad442f 100644 --- a/web/ApiControllers/BlogsController.cs +++ b/web/ApiControllers/BlogsController.cs @@ -125,10 +125,29 @@ namespace Yavsc.ApiControllers } } + /// + /// Searchs the files accociated to the given post id, + /// or related to the given terms. + /// + /// The file. + /// Postid. + /// Terms. [Authorize,HttpGet] public async Task SearchFile(long postid, string terms) { throw new NotImplementedException (); } + + /// + /// Sets the photo. + /// + /// Identifier. + /// Photo. + [Authorize,HttpPost] + public void SetPhoto(long id, string photo) + { + BlogManager.Provider.UpdatePostPhoto (id, photo); + } + /// /// Import the specified id. /// @@ -138,7 +157,7 @@ namespace Yavsc.ApiControllers throw new HttpRequestException ("not a multipart/form-data request"); BlogEntry be = BlogManager.GetPost (id); if (be.Author != Membership.GetUser ().UserName) - throw new AuthorizationDenied ("b"+id); + throw new AuthorizationDenied ("post: "+id); string root = HttpContext.Current.Server.MapPath("~/bfiles/"+id); DirectoryInfo di = new DirectoryInfo (root); if (!di.Exists) di.Create (); @@ -150,7 +169,7 @@ namespace Yavsc.ApiControllers var invalidChars = Path.GetInvalidFileNameChars(); List bodies = new List(); - + foreach (string fkey in provider.BodyPartFileNames.Keys) { string filename = provider.BodyPartFileNames[fkey]; diff --git a/web/App_Themes/style.css b/web/App_Themes/style.css index dc2bbb65..371632f4 100644 --- a/web/App_Themes/style.css +++ b/web/App_Themes/style.css @@ -75,7 +75,7 @@ a.actionlink img, h1 img, .menuitem img { vertical-align: middle; } border-radius:5px; margin:.5em; padding:1em; display: inline-block } fieldset { - background-color: rgba(32,16,16,0.8); + background-color: rgba(16,16,64,0.8); border-radius:5px; border: solid 1px #000060; } @@ -96,7 +96,7 @@ aside { max-width: 40em; padding: .5em; margin: .5em; - background-color: rgba(32,32,32,0.8); + background-color: rgba(0,0,32,0.8); border-radius:10px; } .postpreview video, .postpreview img { @@ -107,7 +107,7 @@ aside { display:block; margin:1em; padding:1em; - background-color: rgba(32,32,32,0.8); + background-color: rgba(0,0,32,0.8); color: #aaa; border-radius:10px; } @@ -125,7 +125,7 @@ textarea.fullwidth { min-height:10em; } } .panel,.bshpanel, aside { - background-color: rgba(32,32,16,0.8); + background-color: rgba(0,0,128,.5); border-radius:5px; margin:.5em; padding: .5em; @@ -167,9 +167,14 @@ label { font-size: medium; } -.message, #message { + #notifications { + padding: .5em; + } + +.notification { font-size: large; background-color: rgba(64,64,0,0.5); + border: solid green 1px; } .dirty { background-color: rgba(128,128,0,0.5); @@ -184,7 +189,6 @@ label { background-color: rgba(256,0,0,0.5); } - .hidden { display:none; } ul.preview li:nth-child(-n+10) { @@ -234,6 +238,9 @@ input, select { max-width: 64px; max-height: 64px; } +#avatar { + float: left; + } .comment { border-radius:25px; @@ -268,8 +275,7 @@ input, select { .c3 { font-size: x-small; font-style: italic; } @media print { body {background-color:white;color:black;} - header,footer,.postcomment,.actionlink,nav - { display:none;} + .control,.actionlink,nav { display:none;} } @media all and (min-width: 640px) { diff --git a/web/ChangeLog b/web/ChangeLog new file mode 100644 index 00000000..65f16d00 --- /dev/null +++ b/web/ChangeLog @@ -0,0 +1,40 @@ +2015-10-08 Paul Schneider + + * BlogsController.cs: implements a method to update the photo + url + + * style.css: yastyle + + * AdminController.cs: refactoring the notification: + Introduces a static `Notice` method, server side, to populate + an array + in `ViewData`, used in the paster page. + + * BlogsController.cs: Controls the photo update + + * YavscHelpers.cs: + * yavsc.circles.js: + * HomeController.cs: + * GoogleController.cs: notification refactoring + + * App.master: - notification refactoring + - html structure in the `nav` + + * hallo.js: event 'hallomodified' now also occurs at image + modifications + + * to-markdown.js: ?Fixes? html images alt text and title to + Markdown + + * yavsc.js: implements the photo in database + + * Edit.aspx: A nicer bill edition, with a photo + + * UserPost.aspx: Displays the photo + + * UserPosts.aspx: Fixes the new usage of `ResultPages` + + * Web.config: totem custo + + * instdbws.sql: adds a `photo` field in the `blog` table + diff --git a/web/Controllers/AdminController.cs b/web/Controllers/AdminController.cs index e6a21af0..2190527b 100644 --- a/web/Controllers/AdminController.cs +++ b/web/Controllers/AdminController.cs @@ -10,6 +10,7 @@ using Yavsc.Model.Admin; using Yavsc.Admin; using System.IO; using Yavsc.Model; +using Yavsc.Helpers; namespace Yavsc.Controllers { @@ -160,8 +161,7 @@ namespace Yavsc.Controllers ViewData ["usertoremove"] = username; if (submitbutton == "Supprimer") { Membership.DeleteUser (username); - ViewData["Message"]= - string.Format("utilisateur \"{0}\" supprimé",username); + YavscHelpers.Notice(ViewData, string.Format("utilisateur \"{0}\" supprimé",username)); ViewData ["usertoremove"] = null; } return View (); @@ -236,7 +236,7 @@ namespace Yavsc.Controllers public ActionResult DoAddRole (string rolename) { Roles.CreateRole(rolename); - ViewData["Message"] = LocalizedText.role_created+ " : "+rolename; + YavscHelpers.Notice(ViewData, LocalizedText.role_created+ " : "+rolename); return View (); } @@ -274,7 +274,7 @@ namespace Yavsc.Controllers ViewData ["useritems"] = users; if (ModelState.IsValid) { Roles.AddUserToRole (model.UserName, adminRoleName); - ViewData ["Message"] = model.UserName + " "+LocalizedText.was_added_to_the_role+" '" + adminRoleName + "'"; + YavscHelpers.Notice(ViewData, model.UserName + " "+LocalizedText.was_added_to_the_role+" '" + adminRoleName + "'"); } else { if (admins.Length > 0) { if (! admins.Contains (Membership.GetUser ().UserName)) { @@ -286,9 +286,9 @@ namespace Yavsc.Controllers // No admin, gives the Admin Role to the current user Roles.AddUserToRole (currentUser, adminRoleName); admins = new string[] { currentUser }; - ViewData ["Message"] += string.Format ( + YavscHelpers.Notice(ViewData, string.Format ( LocalizedText.was_added_to_the_empty_role, - currentUser, adminRoleName); + currentUser, adminRoleName)); } } return View (model); diff --git a/web/Controllers/BlogsController.cs b/web/Controllers/BlogsController.cs index 6ce6d660..42f32b47 100644 --- a/web/Controllers/BlogsController.cs +++ b/web/Controllers/BlogsController.cs @@ -273,6 +273,8 @@ namespace Yavsc.Controllers } else model.Id = BlogManager.Post (model.Author, model.Title, model.Content, model.Visible, model.AllowedCircles); + if (model.Photo != null) + BlogManager.UpdatePostPhoto (model.Id, model.Photo); return RedirectToAction ("UserPosts", new { user = model.Author, title = model.Title }); } ViewData ["AllowedCircles"] = diff --git a/web/Controllers/GoogleController.cs b/web/Controllers/GoogleController.cs index 923c9b15..440fd72e 100644 --- a/web/Controllers/GoogleController.cs +++ b/web/Controllers/GoogleController.cs @@ -17,6 +17,7 @@ using Yavsc.Model.Google; using Yavsc.Model.RolesAndMembers; using Yavsc.Helpers.Google; using Yavsc.Model.Calendar; +using Yavsc.Helpers; namespace Yavsc.Controllers { @@ -100,7 +101,7 @@ namespace Yavsc.Controllers AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg); if (gat == null) { - ViewData ["Message"] = msg; + YavscHelpers.Notice(ViewData, msg); return View ("Auth"); } SaveToken (gat); @@ -137,7 +138,7 @@ namespace Yavsc.Controllers OAuth2 oa = new OAuth2 (AuthGRU); AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg); if (gat == null) { - ViewData ["Message"] = msg; + YavscHelpers.Notice(ViewData, msg); return View (); } string returnUrl = (string)Session ["returnUrl"]; diff --git a/web/Controllers/HomeController.cs b/web/Controllers/HomeController.cs index 3eb0cacb..ac57297e 100644 --- a/web/Controllers/HomeController.cs +++ b/web/Controllers/HomeController.cs @@ -84,16 +84,9 @@ namespace Yavsc.Controllers /// public ActionResult Index () { - /* - * A very bad idea (a redirect permanent as home page): - * - * string startPage = WebConfigurationManager.AppSettings ["StartPage"]; - if (startPage != null) - Redirect (startPage); - */ - ViewData ["Message"] = LocalizedText.Welcome; return View (); } + /// /// Contact the specified email, reason and body. /// @@ -123,8 +116,7 @@ namespace Yavsc.Controllers using (System.Net.Mail.SmtpClient sc = new SmtpClient()) { sc.Send (msg); - ViewData ["Message"] = LocalizedText.Message_sent; - + YavscHelpers.Notice(ViewData, LocalizedText.Message_sent); return View (new { email=email, reason="", body="" }); } } diff --git a/web/Helpers/YavscHelpers.cs b/web/Helpers/YavscHelpers.cs index b64e507b..341d5c1c 100644 --- a/web/Helpers/YavscHelpers.cs +++ b/web/Helpers/YavscHelpers.cs @@ -14,6 +14,7 @@ using Yavsc.Model.Circles; using System.Web.UI; using System.Linq.Expressions; using System.Web.Profile; +using System.Web.Script.Serialization; namespace Yavsc.Helpers { @@ -175,6 +176,23 @@ namespace Yavsc.Helpers if (a == null || a is DBNull) return "/avatars/" + helper.Encode(username)+".png"; return helper.Encode ((string)a); } + + public static string JavaScript(this HtmlHelper html, object obj) + { + return JavaScript (obj); + } + + public static string JavaScript(object obj) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + return serializer.Serialize(obj); + } + + public static void Notice (ViewDataDictionary ViewData, string message) { + if (ViewData ["Notifications"] == null) + ViewData ["Notifications"] = new List (); + (ViewData ["Notifications"] as List).Add (message.Replace("\'","\\\'")); + } } } diff --git a/web/Models/App.master b/web/Models/App.master index b41346c4..b11a9173 100644 --- a/web/Models/App.master +++ b/web/Models/App.master @@ -22,7 +22,6 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>'; -
@@ -34,26 +33,33 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>'; -
<%= (ViewData["Error"]!=null)? Html.Encode(ViewData["Error"]) : "" %>
-
<%= Html.Encode(ViewData["Message"]) %>
+ +
+
+<%if (ViewData ["Notifications"]!=null) { %> + +<% } %>