Bug & layout fixes

* Index.aspx:
* Title.aspx:
* YavscModel.csproj:
* BlogEntry.cs:
* yavsc.scrollnotif.js:
* AccountController.cs:
* BlogEntryCollection.cs: refactoring

* yavsc.tags.js: Implements a js call
to the tag & untag methods

* PostActions.ascx: a better html structure

* BasePost.cs: refactoring:
allows the "PostActions" user control to use a common base object as
  post reference

* NpgsqlBlogProvider.cs: implements the tag methods on db

* ResultPages.cs: A multi-pages result meta info when one page only

* yavsc.circles.js:
* AccountController.cs: code formatting

* BlogsController.cs: Untag a post

* style.css: yastyle, yet a better one.

* BlogsController.cs: View the Title after edition

* App.master:
* UserPosts.aspx: a nicer html structure

* yavsc.js: Fixes notice & dimiss js

* Login.aspx: refactoring

* Edit.aspx: better html

* UserPost.aspx: A promess to be allowed to tag.

* Web.csproj: Adds yavsc.tags.js and yavsc.scrollnotifs.js to the
  project decription.

* BlogManager.cs: Makes the blog manager expose of the new `UnTag`
  method

* BlogProvider.cs: introduces a method to `untag`

* FindBlogEntryFlags.cs: Find post entry by tag

* LocalizedText.resx:
* LocalizedText.Designer.cs: new translations: - "Tag"
- "Edit"

* LocalizedText.fr.resx:
* LocalizedText.fr.Designer.cs: nouvelles traductions: - "Tag"
- "Edit"

* Profile.cs: a nicer stack trace at buggy usage
This commit is contained in:
Paul Schneider
2015-10-13 22:53:39 +02:00
parent c962998aaa
commit d04a68db01
41 changed files with 896 additions and 272 deletions

View File

@ -1,3 +1,7 @@
2015-10-13 Paul Schneider <paul@pschneider.fr>
* NpgsqlBlogProvider.cs: implements the tag methods on db
2015-10-10 Paul Schneider <paul@pschneider.fr>
* NpgsqlBlogProvider.cs:

View File

@ -7,6 +7,7 @@ using Yavsc.Model.Blogs;
using Yavsc.Model.Circles;
using System.Web.Mvc;
using NpgsqlTypes;
using System.Linq;
namespace Npgsql.Web.Blog
{
@ -19,34 +20,51 @@ namespace Npgsql.Web.Blog
string connectionString;
#region implemented abstract members of BlogProvider
/// <summary>
/// Tag the specified postid and tag.
/// Tag the specified post by identifier
/// using the given tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tag">Tag.</param>
public override long Tag (long postid, string tag)
/// <param name="tagname">Tag name.</param>
public override long Tag (long postid, string tagname)
{
long tid = GetOrCreateTagId (tagname);
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "insert into bltag (blid,tag) values (:postid,:tag) returning _id";
cmd.Parameters.AddWithValue("tag",tag);
cmd.Parameters.AddWithValue("postid",postid);
cmd.CommandText = "INSERT INTO tagged (tagid,postid) VALUES (:tid,:pid)";
cmd.Parameters.AddWithValue("tid",tid);
cmd.Parameters.AddWithValue("pid",postid);
cnx.Open ();
return (long) cmd.ExecuteScalar ();
cmd.ExecuteNonQuery ();
return tid;
}
}
/// <summary>
/// Removes the tag.
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagid">Tagid.</param>
public override void RemoveTag (long tagid)
{
/// <param name="name">Name.</param>
override public void Untag(long postid, string name) {
Untag(postid, GetTagId (name));
}
/// <summary>
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagid">Tagid.</param>
/// <param name="tid">Tid.</param>
override public void Untag(long postid, long tid) {
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "delete from bltag where _id = :tagid";
cmd.Parameters.AddWithValue("tagid",tagid);
cmd.CommandText = "DELETE FROM tagged WHERE postid = :pid AND tagid = :tid";
cmd.Parameters.AddWithValue ("pid", postid);
cmd.Parameters.AddWithValue ("tid", tid);
cnx.Open ();
cmd.ExecuteNonQuery ();
cmd.ExecuteNonQuery ();
}
}
/// <summary>
@ -257,7 +275,7 @@ namespace Npgsql.Web.Blog
}
}
}
if (be!=null) SetCirclesOn (be);
if (be!=null) Populate (be);
return be;
}
@ -334,8 +352,7 @@ namespace Npgsql.Web.Blog
be.Tags = tags.ToArray ();
}
}
SetCirclesOn (bec);
if (bec!=null) Populate (bec);
}
}
return bec;
@ -359,12 +376,104 @@ namespace Npgsql.Web.Blog
be.AllowedCircles = circles.ToArray ();
}
private void SetCirclesOn(BlogEntryCollection bec)
{
foreach (BlogEntry be in bec) {
SetCirclesOn (be);
/// <summary>
/// Removes the tag.
/// </summary>
/// <param name="tagid">Tagid.</param>
public override void DropTag(long tagid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "DELETE from public.tag where _id = :tid";
cmd.Parameters.AddWithValue("tagid",tagid);
cnx.Open ();
cmd.ExecuteNonQuery ();
cnx.Close ();
}
}
private static string SelectTagsSql = "SELECT tag.name, tag._id FROM public.tag WHERE name like :name";
private IEnumerable<string> GetSuggestion (string pattern) {
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = SelectTagsSql;
throw new NotImplementedException ();
}
}
private static string InsertTagSql = "INSERT INTO tag (name) VALUES (:name) returning _id";
private void InsertTag(long postid, long tagid)
{
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = InsertTagSql;
throw new NotImplementedException ();
}
}
private long GetTagId(string tagname)
{
long id = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "SELECT tag._id FROM public.tag WHERE name = :name";
cmd.Parameters.AddWithValue ("name", tagname);
cnx.Open ();
id = (long) cmd.ExecuteScalar ();
}
return id;
}
private long GetOrCreateTagId(string tagname)
{
long id = 0;
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = "SELECT tag._id FROM public.tag WHERE name = :name;\n" +
"IF NOT FOUND THEN INSERT INTO tag (name) values (:name) RETURNING _id; ENDIF;\n";
cmd.Parameters.AddWithValue ("name", tagname);
cnx.Open ();
id = (long) cmd.ExecuteScalar ();
}
return id;
}
private static string SelectPostTagsSql = "SELECT tag.name FROM public.tag, public.tagged\n" +
"WHERE tag._id = tagged.tagid AND tagged.postid = :pid \n";
private void SetTagsOn(BlogEntryCollection bec){
foreach (BlogEntry be in bec) {
SetTagsOn (be);
}
}
private void SetTagsOn(BlogEntry be)
{
List<string> tags = new List<string> ();
using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString))
using (NpgsqlCommand cmdtags = cnx.CreateCommand ()) {
cmdtags.CommandText = SelectPostTagsSql;
cmdtags.Parameters.AddWithValue ("pid", be.Id);
cnx.Open ();
using (NpgsqlDataReader rdr = cmdtags.ExecuteReader ()) {
while (rdr.Read ()) {
tags.Add (rdr.GetString (0));
}
}
}
be.Tags = tags.ToArray ();
}
// Assert(bec!=null);
private void Populate(BlogEntryCollection bec)
{
foreach (BlogEntry be in bec) Populate(be);
}
private void Populate(BlogEntry be)
{
SetTagsOn (be);
SetCirclesOn (be);
}
/// <summary>
/// Post the specified username, title, content and visible.
/// </summary>
@ -487,6 +596,15 @@ namespace Npgsql.Web.Blog
}
cmd.Parameters.AddWithValue ("appname", applicationName);
if (pattern != null) {
if ((searchflags & FindBlogEntryFlags.MatchTag) > 0) {
cmd.CommandText +=
"AND EXISTS (SELECT tag._id FROM public.tag, public.tagged WHERE " +
"public.tag._id = public.tagged.tagid " +
"AND public.tagged.postid = a.post_id " +
"public.tag.name like :tagname) ";
cmd.Parameters.AddWithValue ("tagname", pattern);
}
if ((searchflags & FindBlogEntryFlags.MatchContent) > 0) {
cmd.CommandText += " and bcontent like :bcontent";
cmd.Parameters.AddWithValue ("bcontent", pattern);
@ -532,8 +650,7 @@ namespace Npgsql.Web.Blog
rdr.Close ();
}
}
foreach (BlogEntry be in c)
SetCirclesOn (be);
if (c!=null) Populate (c);
return c;
}
@ -602,8 +719,7 @@ namespace Npgsql.Web.Blog
}
}
}
foreach (BlogEntry be in c)
SetCirclesOn (be);
if (c!=null) Populate (c);
return c;
}
#endregion

View File

@ -24,27 +24,55 @@ using Yavsc.Model.Blogs;
using Yavsc.Controllers;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.Configuration;
using System.Configuration;
using System.IO;
using System.Web.Http;
namespace TestAPI
namespace Yavsc
{
[TestFixture ()]
public class BlogUnitTest
public class AccountUnitTestCase
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
AccountController accountController;
[TestFixtureSetUp]
public void Init()
public AccountController AccountController {
get {
return accountController;
}
}
string defaultMembershipProvider = null;
[Test]
public virtual void Init()
{
webSource = new XSPWebSource (configurationManager.Address, configurationManager.Port, !root);
var server = new ApplicationServer (webSource, configurationManager.Root) {
Verbose = configurationManager.Verbose,
SingleApplication = !root
};
string basedir = AppDomain.CurrentDomain.BaseDirectory;
string curdir = Directory.GetCurrentDirectory ();
string dummyVirtualPath = "/";
string physicalPath = @"/home/paul/workspace/totem/web/";
WebConfigurationFileMap map = new WebConfigurationFileMap ();
map.VirtualDirectories.Add(dummyVirtualPath, new VirtualDirectoryMapping(physicalPath, true));
Configuration configuration = WebConfigurationManager.OpenMappedWebConfiguration(map, dummyVirtualPath);
accountController = new AccountController ();
string da = (string) configuration.AppSettings.Settings ["DefaultAvatar"].Value;
MembershipSection s = configuration.GetSection ("system.web/membership") as MembershipSection;
defaultMembershipProvider = s.DefaultProvider;
}
[Test ()]
public void Register ()
public virtual void Register ()
{
ViewResult actionResult = accountController.Register (
new Yavsc.Model.RolesAndMembers.RegisterViewModel () {
@ -53,7 +81,7 @@ namespace TestAPI
IsApprouved = true
},
"/testreturnurl") as ViewResult;
Assert.AreEqual (actionResult.ViewName, "RegistrationPending");
Assert.AreSame ("",actionResult.ViewName);
MembershipUser u = Membership.GetUser (UserName, false);
Assert.NotNull (u);
Assert.False (u.IsApproved);
@ -64,8 +92,9 @@ namespace TestAPI
Membership.UpdateUser (u);
Assert.True (u.IsApproved);
}
[TestFixtureTearDown()]
public void Unregister()
public virtual void Unregister()
{
ViewResult actionResult =
accountController.Unregister (UserName, true) as ViewResult;

View File

@ -0,0 +1,52 @@
//
// TagTestCases.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;
using Yavsc.Model.Blogs;
namespace Yavsc
{
[TestFixture ()]
public class BlogUnitTestCase: AccountUnitTestCase
{
[TestFixtureSetUp]
void NeedAPost()
{
Register ();
}
[Test ()]
public void TestCase ()
{
long pid = BlogManager.Post (UserName, "BlogUnitTestCase", "content", true, null);
BlogManager.Tag (pid, "test");
}
[TestFixtureTearDown()]
void Cleanup()
{
Unregister ();
}
}
}

124
TestAPI/Web.config Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
<sectionGroup name="system.web">
<section name="membership" type="System.Web.Configuration.MembershipSection, System.Web" />
<section name="blog" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="thanks" type="Yavsc.ThanksConfigurationSection, Yavsc" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="catalog" type="Yavsc.Model.FrontOffice.Configuration.CatalogProvidersConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="workflow" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="circleProviders" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" />
<section name="userNameManager" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" />
</sectionGroup>
<section name="paypal" type="PayPal.SDKConfigHandler, PayPal" />
</configSections>
<system.data>
<DbProviderFactories>
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories>
</system.data>
<system.web>
<authentication mode="Forms" >
<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<membership defaultProvider="NpgsqlMembershipProvider" userIsOnlineTimeWindow="1">
<providers>
<clear />
<add name="NpgsqlMembershipProvider" type="Npgsql.Web.NpgsqlMembershipProvider, NpgsqlMRPProviders"
connectionStringName="yavsc" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
requiresUniqueEmail="true" passwordFormat="Clear" maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10" applicationName="/" autogenerateschema="false" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="NpgsqlRoleProvider">
<providers>
<clear />
<add name="NpgsqlRoleProvider" connectionStringName="yavsc" applicationName="/" type="Npgsql.Web.NpgsqlRoleProvider, NpgsqlMRPProviders" autogenerateschema="false" />
</providers>
</roleManager>
<userNameManager defaultProvider="NpsqlUserNameProvider">
<providers>
<add name="NpsqlUserNameProvider" connectionStringName="yavsc" applicationName="/" type="Npgsql.Web.RolesAndMembers.NpgsqlUserNameProvider, NpgsqlMRPProviders" autogenerateschema="false">
</add>
</providers>
</userNameManager>
<workflow defaultProvider="ITProvider">
<providers>
<clear />
<add name="ITProvider" type="Yavsc.ITCPNpgsqlProvider, ITContentProvider" applicationName="/" connectionStringName="yavsc" />
</providers>
</workflow>
<profile defaultProvider="NpgsqlProfileProvider">
<providers>
<clear />
<add name="NpgsqlProfileProvider" type="Npgsql.Web.NpgsqlProfileProvider, NpgsqlMRPProviders" connectionStringName="yavsc" applicationName="/" description="ProfileProvider for yavsc" />
</providers>
<properties>
<add name="Name" />
<add name="Phone" />
<add name="Mobile" />
<add name="Avatar" />
<add name="BlogVisible" type="System.Boolean" />
<add name="BlogTitle" />
<add name="WebSite" />
<add name="Address" />
<add name="CityAndState" />
<add name="ZipCode" />
<add name="Country" />
<add name="BankCode" />
<add name="IBAN" />
<add name="BIC" />
<add name="WicketCode" />
<add name="AccountNumber" />
<add name="BankedKey" />
<add name="gtoken" />
<add name="grefreshtoken" />
<add name="gtokentype" />
<add name="gtokenexpir" />
<add name="gcalapi" />
<add name="gcalid" />
<add name="gregid" />
</properties>
</profile>
<blog defaultProvider="NpgsqlBlogProvider">
<providers>
<add name="NpgsqlBlogProvider" connectionStringName="yavsc" applicationName="/" type="Npgsql.Web.Blog.NpgsqlBlogProvider, NpgsqlBlogProvider" />
</providers>
</blog>
</system.web>
<connectionStrings>
<add name="yavsc" connectionString="Server=127.0.0.1;Port=5432;Database=totem;User Id=totemweb;Password=cZeoft2k5_d4;" providerName="Npgsql" />
</connectionStrings>
<appSettings>
<add key="MonoServerDefaultIndexFiles" value="index.html,Index.aspx" />
<add key="WorkflowContentProviderClass" value="yavsc.NpgsqlContentProvider" />
<add key="SmtpServer" value="smtp.free.fr" />
<add key="AdminEMail" value="paulschneider@free.fr" />
<add key="OwnerEMail" value="" />
<add key="Name" value="TOTEM PRODUCTION" />
<add key="DefaultController" value="Home" />
<add key="DefaultAvatar" value="/images/noavatar.png;image/png" />
<add key="RegistrationMessage" value="/RegistrationMail.txt" />
<!-- <add key="ClientValidationEnabled" value="true" /> -->
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="PayPalLogger" value="PayPal.Log.Log4netLogger" />
</appSettings>
</configuration>

View File

@ -1,3 +1,8 @@
2015-10-13 Paul Schneider <paul@pschneider.fr>
* ResultPages.cs: A multi-pages result meta info when one page
only
2015-10-04 Paul Schneider <paul@pschneider.fr>
* ResultPages.cs: .

View File

@ -91,6 +91,21 @@ namespace Yavsc.WebControls
}
}
/// <summary>
/// Gets or sets the Single page message.
/// </summary>
/// <value>The none.</value>
[Bindable (true)]
[DefaultValue("1")]
public string SinglePage {
get {
return (string) ViewState["SinglePage"];
}
set {
ViewState["SinglePage"] = value;
}
}
/// <summary>
/// Gets or sets the none.
/// </summary>
@ -105,7 +120,20 @@ namespace Yavsc.WebControls
ViewState["None"] = value;
}
}
/// <summary>
/// Gets or sets the none.
/// </summary>
/// <value>The none.</value>
[Bindable (true)]
[DefaultValue("Pages: ")]
public string PagesLabel {
get {
return (string) ViewState["PagesLabel"];
}
set {
ViewState["PagesLabel"] = value;
}
}
/// <summary>
/// Gets or sets the current page.
/// </summary>
@ -132,6 +160,7 @@ namespace Yavsc.WebControls
writer.WriteEncodedText (Text);
int pageCount = ((ResultCount-1) / PageSize) + 1;
if ( pageCount > 1 ) {
writer.Write (PagesLabel);
for (int pi = (PageIndex < 5) ? 0 : PageIndex - 5; pi < pageCount && pi < PageIndex + 5; pi++) {
if (PageIndex == pi)
writer.RenderBeginTag ("b");
@ -144,6 +173,9 @@ namespace Yavsc.WebControls
writer.RenderEndTag ();
writer.Write ("&nbsp;");
}
}
else {
writer.Write (SinglePage);
}
}
if (ResultCount == 0) {

View File

@ -39,10 +39,11 @@ namespace Yavsc.ApiControllers
/// Register the specified model.
/// </summary>
/// <param name="model">Model.</param>
[Authorize()]
[Authorize ()]
[ValidateAjaxAttribute]
public HttpResponseMessage Register ([FromBody] RegisterClientModel model)
{
if (ModelState.IsValid) {
if (model.IsApprouved)
if (!Roles.IsUserInRole ("Admin"))
@ -54,32 +55,32 @@ namespace Yavsc.ApiControllers
}
MembershipCreateStatus mcs;
var user = Membership.CreateUser (
model.UserName,
model.Password,
model.Email,
model.Question,
model.Answer,
model.IsApprouved,
out mcs);
model.UserName,
model.Password,
model.Email,
model.Question,
model.Answer,
model.IsApprouved,
out mcs);
switch (mcs) {
case MembershipCreateStatus.DuplicateEmail:
ModelState.AddModelError ("Email", "Cette adresse e-mail correspond " +
"à un compte utilisateur existant");
"à un compte utilisateur existant");
break;
case MembershipCreateStatus.DuplicateUserName:
ModelState.AddModelError ("UserName", "Ce nom d'utilisateur est " +
"déjà enregistré");
"déjà enregistré");
break;
case MembershipCreateStatus.Success:
if (!model.IsApprouved)
Url.SendActivationMessage (user);
ProfileBase prtu = ProfileBase.Create (model.UserName);
prtu.SetPropertyValue("Name",model.Name);
prtu.SetPropertyValue("Address",model.Address);
prtu.SetPropertyValue("CityAndState",model.CityAndState);
prtu.SetPropertyValue("Mobile",model.Mobile);
prtu.SetPropertyValue("Phone",model.Phone);
prtu.SetPropertyValue("ZipCode",model.ZipCode);
prtu.SetPropertyValue ("Name", model.Name);
prtu.SetPropertyValue ("Address", model.Address);
prtu.SetPropertyValue ("CityAndState", model.CityAndState);
prtu.SetPropertyValue ("Mobile", model.Mobile);
prtu.SetPropertyValue ("Phone", model.Phone);
prtu.SetPropertyValue ("ZipCode", model.ZipCode);
break;
default:
break;
@ -88,15 +89,12 @@ namespace Yavsc.ApiControllers
return DefaultResponse ();
}
/// <summary>
/// Resets the password.
/// </summary>
/// <param name="model">Model.</param>
[ValidateAjax]
public void ResetPassword(LostPasswordModel model)
public void ResetPassword (LostPasswordModel model)
{
StringDictionary errors;
MembershipUser user;
@ -108,4 +106,3 @@ namespace Yavsc.ApiControllers
}
}
}

View File

@ -40,9 +40,19 @@ namespace Yavsc.ApiControllers
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tag">Tag.</param>
public long Tag (long postid,string tag) {
public void Tag (long postid,string tag) {
BlogManager.GetForEditing (postid);
return BlogManager.Tag (postid, tag);
BlogManager.Tag (postid, tag);
}
/// <summary>
/// Untag the specified postid and tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tag">Tag.</param>
public void Untag (long postid,string tag) {
BlogManager.GetForEditing (postid);
BlogManager.Untag (postid, tag);
}
/// <summary>
@ -57,6 +67,7 @@ namespace Yavsc.ApiControllers
throw new AuthorizationDenied (user);
BlogManager.RemoveTitle (user, title);
}
/// <summary>
/// Removes the tag.
/// </summary>
@ -65,6 +76,7 @@ namespace Yavsc.ApiControllers
throw new NotImplementedException ();
}
/// <summary>
/// The allowed media types.
/// </summary>
@ -125,9 +137,9 @@ namespace Yavsc.ApiControllers
}
}
/// <summary>
/// Searchs the files accociated to the given post id,
/// or related to the given terms.
/// Searchs the file.
/// </summary>
/// <returns>The file.</returns>
/// <param name="postid">Postid.</param>
@ -165,7 +177,8 @@ namespace Yavsc.ApiControllers
try
{
// Read the form data.
IEnumerable<HttpContent> data = await Request.Content.ReadAsMultipartAsync(provider) ;
//IEnumerable<HttpContent> data =
await Request.Content.ReadAsMultipartAsync(provider) ;
var invalidChars = Path.GetInvalidFileNameChars();
List<string> bodies = new List<string>();
@ -182,10 +195,7 @@ namespace Yavsc.ApiControllers
FileInfo fp = new FileInfo (Path.Combine(root,filename));
if (fi.Exists) fi.Delete();
fp.MoveTo(fi.FullName);
// Get the mime type
// TODO Get the mime type
using (Process p = new Process ()) {
p.StartInfo.WorkingDirectory = root;
p.StartInfo = new ProcessStartInfo ();

View File

@ -8,13 +8,8 @@ body {
margin: 0;
}
.iconsmall { max-height: 1.3em; max-width: 1.3em; }
input, textarea, checkbox {
color: #FFFFA0;
background-color: black;
}
.photo { width: 100%; }
.blogbanner { float: left; top:0; }
@ -76,7 +71,7 @@ legend {
footer p { display:inline-block; }
footer img { max-height: 2em; vertical-align: middle; }
a.actionlink img, h1 img, .menuitem img { vertical-align: middle; }
a img, h1 img, .menuitem img { max-height: 1em; vertical-align: middle; }
#gspacer {
background-color: rgba(20,20,20,.8);
@ -116,7 +111,7 @@ aside {
margin:1em;
padding:1em;
background-color: rgba(0,0,32,0.8);
color: #aaa;
color: #eee;
border-radius:10px;
}
.hiddenpost { background-color: rgba(16,16,16,0.5); }
@ -167,14 +162,13 @@ content: ")";
.usertitleref {
color: #B0B080;
border-radius: 5px;
background-color:rgba(0,0,32,0.6);
font-family: 'Arial', cursive;
padding: 1em;
}
a:visited {
color: #90B090;
color: #E0E0E0;
}
label {
font-size: medium;
@ -186,7 +180,8 @@ label {
border: dashed rgb(020,20,256) 2px;
}
#notifications {
padding: .5em;
margin: 2em;
padding: 2em;
}
.notification {
@ -227,30 +222,33 @@ a {
}
.actionlink, .menuitem, a {
color: #B0B080;
display:inline-block;
color: white;
border-radius:1em;
border: solid black 1px;
background-color: rgba(20,20,20,.8);
cursor: pointer;
font-family: 'Arial', cursive;
padding: .2em;
display: inline-block;
padding: 1em;
margin:1em;
}
input, select {
color: #B0B080;
input, select, textarea {
color: white;
background-color:rgba(0,0,64,0.8);
border: solid 1px rgb(128,128,128);
border-radius:1em;
background-color:rgba(0,0,32,0.8);
font-family: 'Arial', cursive;
font-family: 'Arial', cursive;
}
.actionlink:hover, fa:hover, .menuitem:hover, a:hover, input:hover {
.actionlink:hover, fa:hover, .menuitem:hover, a:hover {
background-color:rgba(30,0,124,0.9);
border: solid green 1px;
}
input:hover, textarea:hover {
color: white;
background-color:rgba(64,64,64,0.8);
}
.code {
font-family: "monospace";
background-color: rgba(0,0,256,0.1);
@ -273,14 +271,6 @@ input, select {
font-size: smaller;
}
.menuitem {
border-radius:5px;
margin:.5em;
padding:.5em;
display: inline-block;
}
.onhover {
display:none;
position: absolute;
@ -300,7 +290,7 @@ input, select {
.c3 { font-size: x-small; font-style: italic; }
@media print {
body {background-color:white;color:black;}
.control,.actionlink,nav { display:none;}
.control, .actionlink, .menuitem, nav { display:none;}
}
.bshpanel { display:block; }

View File

@ -1,3 +1,38 @@
2015-10-13 Paul Schneider <paul@pschneider.fr>
* Index.aspx:
* Title.aspx:
* yavsc.scrollnotif.js:
* AccountController.cs: refactoring
* yavsc.tags.js: Implements a js call
to the tag & untag methods
* PostActions.ascx: a better html structure
* yavsc.circles.js:
* AccountController.cs: code formatting
* BlogsController.cs: Untag a post
* style.css: yastyle, yet a better one.
* BlogsController.cs: View the Title after edition
* App.master:
* UserPosts.aspx: a nicer html structure
* yavsc.js: Fixes notice & dimiss js
* Login.aspx: refactoring
* Edit.aspx: better html
* UserPost.aspx: A promess to be allowed to tag.
* Web.csproj: Adds yavsc.tags.js and yavsc.scrollnotifs.js to
the project decription.
2015-10-10 Paul Schneider <paul@pschneider.fr>
* Web.csproj:

View File

@ -92,12 +92,15 @@ namespace Yavsc.Controllers
}
/// <summary>
/// Registers the form.
/// Gets the registration form.
/// </summary>
/// <returns>The form.</returns>
public ActionResult RegisterForm()
/// <returns>The register.</returns>
/// <param name="model">Model.</param>
/// <param name="returnUrl">Return URL.</param>
public ActionResult GetRegister(RegisterViewModel model, string returnUrl)
{
return View ("Register");
ViewData ["returnUrl"] = returnUrl;
return View ("Register",model);
}
/// <summary>
@ -109,11 +112,6 @@ namespace Yavsc.Controllers
public ActionResult Register (RegisterViewModel model, string returnUrl)
{
ViewData ["returnUrl"] = returnUrl;
if (Request.RequestType == "GET") {
foreach (string k in ModelState.Keys)
ModelState [k].Errors.Clear ();
return View (model);
}
if (ModelState.IsValid) {
if (model.ConfirmPassword != model.Password) {

View File

@ -71,7 +71,7 @@ namespace Yavsc.Controllers
/// <summary>
/// Title the specified title, pageIndex and pageSize.
/// </summary>
/// <param name="title">Title.</param>
/// <param name="id">Title.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
///
@ -289,7 +289,7 @@ namespace Yavsc.Controllers
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 });
return RedirectToAction ("Title", new { id = model.Title });
}
ViewData ["AllowedCircles"] =
CircleManager.DefaultProvider.List (

View File

@ -19,7 +19,8 @@
<script type="text/javascript">
var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</script>
<script src="/Scripts/yavsc.js"></script>
<script src="<%=Url.Content("~/Scripts/yavsc.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/yavsc.scrollnotif.js")%>"></script>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
@ -46,6 +47,7 @@ Yavsc.notice('<%=notice%>');
</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" >
<i class="fa fa-sign-in">Connexion</i>
</a>

View File

@ -48,6 +48,7 @@ function removeCircle() {
else Yavsc.notice(false);
}}});
}
function modifyCircle() {
Yavsc.notice(false);
var id = $('#id').val();

View File

@ -17,10 +17,12 @@ self.showHide = function () {
$(this).html(this.oldhtml);
}
};
self.dimiss = function () {
self.dimiss = function () {
$(this).parent().remove();
}
self.notice = function (msg, msgok) {
};
self.notice = function (msg, msgok) {
if (!msgok) msgok='Ok';
if (msg) {
var note = $('<div class="notification">'+msg+'<br></div>');
@ -40,12 +42,14 @@ self.showHide = function () {
errspan.innerHTML=value.errors.join("<br/>");
});
}
};
self.onAjaxError = function (xhr, ajaxOptions, thrownError) {
if (xhr.status!=400)
Yavsc.notice(xhr.status+" : "+xhr.responseText);
else Yavsc.notice(false);
}
};
return self;
})();

View File

@ -0,0 +1,37 @@
//
// 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);
}}
});
});

32
web/Scripts/yavsc.tags.js Normal file
View File

@ -0,0 +1,32 @@
var Tags = (function(apiBaseUrl){
var self = {};
self.blogsApiUrl = (apiBaseUrl || '/api') + "/Blogs";
self.tag = function (postid,tagname,callback) {
$.ajax({
url: CirclesApiUrl+"/Tag",
type: "POST",
data: { postid: postid, tag: tagname },
success: function () {
if (callback) callback(postid,tagname);
},
statusCode: {
400: Yavsc.onAjaxBadInput
},
error: Yavsc.onAjaxError});
}
self.untag = function (postid,tagname,callback) {
$.ajax({
url: CirclesApiUrl+"/Untag",
type: "POST",
data: { postid: postid, tag: tagname },
success: function () {
if (callback) callback(postid,tagname);
},
statusCode: {
400: Yavsc.onAjaxBadInput
},
error: Yavsc.onAjaxError});
}
return self;
})();

View File

@ -20,7 +20,7 @@
<input type="submit"/>
<% } %></div>
<div class="panel">
<%= Html.ActionLink("S'enregistrer","RegisterForm",new {returnUrl=ViewData["returnUrl"]}, new { @class="actionlink" }) %>
<%= Html.ActionLink("S'enregistrer","GetRegister",new {returnUrl=ViewData["returnUrl"]}, new { @class="actionlink" }) %>
</div>
<div class="panel">
<a href="<%=Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Login"%>?returnUrl=<%=ViewData["returnUrl"]==null?Request.Url.PathAndQuery:(string)ViewData["returnUrl"]%>" class="actionlink">

View File

@ -197,7 +197,7 @@ var data = new FormData($('#frmajax').get()[0]);
</script>
<form id="frmajax">
<fieldset>
<legend>Fichiers attachés</legend>
<legend>Attacher des fichiers</legend>
<input type="file" name="attached" id="postedfile" multiple>
<input type="button" value="attacher les ficher" onclick="submitFile()">
<input type="button" value="importer les documents" onclick="submitImport()">
@ -214,6 +214,11 @@ var data = new FormData($('#frmajax').get()[0]);
<%= Html.ListBox("AllowedCircles") %>
<%= Html.ValidationMessage("AllowedCircles", "*") %>
</fieldset>
<span id="viewsource">
<i class="fa fa-code menuitem"><%=Html.Translate("View_source")%></i></span>
<span id="hidesource" class="hidden">
<i class="fa fa-code menuitem"><%=Html.Translate("Hide_source")%></i>
</span>
<fieldset id="source" class="hidden">
<%=Html.Hidden("Author")%>
<%=Html.Hidden("Id")%>
@ -226,14 +231,10 @@ var data = new FormData($('#frmajax').get()[0]);
<%=Html.TextArea("Content")%>
<%=Html.ValidationMessage("Content")%>
</fieldset>
<i class="af af-check actionlink"><input type="submit" id="validate" value="Valider"></i>
<input type="submit" id="validate" value="Valider" class="fa fa-check menuitem">
<% } %>
<span id="viewsource" class="actionlink">
<i class="fa fa-code">View Source</i></span>
<span id="hidesource" class="actionlink hidden">
<i class="fa fa-code">Hide Source</i>
</span>
<aside>
Id:<%= Html.ActionLink( Model.Id.ToString() , "UserPost", new { user= Model.Author, title=Model.Title, id = Model.Id }, new { @class = "usertitleref actionlink" }) %>
, Posted: <%= Model.Posted.ToString("yyyy/MM/dd") %> - Modified: <%= Model.Modified.ToString("yyyy/MM/dd") %>

View File

@ -8,16 +8,7 @@
<% foreach (var p in g) { %>
<div class="postpreview">
<p><%= Html.Markdown(p.Intro,"/bfiles/"+p.Id+"/") %></p>
<aside>
(Posté le <%=p.Posted.ToString("D") %>)
<% if (Membership.GetUser()!=null)
if ((Membership.GetUser().UserName==g.Key)
|| (Roles.IsUserInRole ("Admin")))
{ %>
<%= Html.ActionLink("Editer","Edit", new { id = p.Id }, new { @class="actionlink" }) %>
<%= Html.ActionLink("Supprimer","RemovePost", new { id = p.Id }, new { @class="actionlink" } ) %>
<% } %> </aside>
<%= Html.Partial("PostActions",p)%>
</div> <% } %>
<% } %>
</div>

View File

@ -0,0 +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!" %>)
<% 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">
<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">
<i class="fa fa-remove"><%=Html.Translate("Remove")%></i></a>
<% }} %>
</aside>

View File

@ -16,30 +16,19 @@
<div class="post<% if (!e.Visible) { %> hiddenpost<% } %>" >
<% if (e.Photo!=null) { %><img src="<%=e.Photo%>" alt="" class="photo"><% } %>
<%= Html.Markdown(e.Content,"/bfiles/"+e.Id+"/") %>
<aside class="hidden">(<%= e.Posted.ToString("yyyy/MM/dd") %>
- <%= e.Modified.ToString("yyyy/MM/dd") %> <%= e.Visible? "":", Invisible!" %>)
<% if (Membership.GetUser()!=null)
if (Membership.GetUser().UserName==e.Author || Roles.IsUserInRole("Admin") )
{ %>
<%= Html.ActionLink("Editer","Edit", new { id = e.Id }, new { @class="actionlink" }) %>
<%= Html.ActionLink("Supprimer","RemovePost", new { id = e.Id }, new { @class="actionlink" } ) %>
<% } %>
</aside>
<%= Html.Partial("PostActions",e)%>
</div>
<% } %>
<aside>
<form runat="server" id="form1" method="GET">
<%
if (((int) ViewData["RecordCount"]) > ((int) ViewData["PageSize"])) {
rp1.ResultCount = (int) ViewData["RecordCount"];
rp1.PageIndex = (int) ViewData["PageIndex"];
rp1.PageSize = (int) ViewData["PageSize"];
%>
%><aside><form runat="server" id="form1">
<yavsc:ResultPages id="rp1" Action = "?pageIndex={0}" runat="server">
<None><i>Pas de contenu</i></None>
</yavsc:ResultPages>
</form>
</aside>
<% } %>
</asp:Content>

View File

@ -35,14 +35,15 @@
<% if (Model.Author == username || c.From == username ) { %>
<%= Html.ActionLink("Supprimer","RemoveComment", new { cmtid = c.Id } , new { @class="actionlink" })%>
<% } %>
</div><% } %>
<% if (Membership.GetUser()!=null) {
if (Membership.GetUser().UserName==be.Author)
{ %> <div class="control">
<%= Html.ActionLink("Editer","Edit", new { id = be.Id }, new { @class="actionlink" }) %>
<%= Html.ActionLink("Supprimer","RemovePost", new { id = be.Id }, new { @class="actionlink" } ) %>
<i class="fa fa-tag">Tagger</i>
</div> <% } %>
<aside class="control">

View File

@ -25,19 +25,10 @@
<% bool truncated = false; %>
<%= Html.MarkdownToHtmlIntro(out truncated, e.Content,"/bfiles/"+e.Id+"/") %>
<% if (truncated) { %>
<i><%= Html.ActionLink( "lire la suite" ,"UserPost", new { user=e.Author, title=e.Title, id = e.Id }, new { @class = "usertitleref" }) %></i>
<a href="<%= Url.RouteUrl( "View", new { action="Title", title=e.Title}) %>">
<i>Html.Translate("ReadMore")</i></a>
<% } %>
<aside>(<%= e.Posted.ToString("yyyy/MM/dd") %>
- <%= e.Modified.ToString("yyyy/MM/dd") %> <%= e.Visible? "":", Invisible!" %>)
<% if (Membership.GetUser()!=null)
if (Membership.GetUser().UserName==e.Author)
{ %>
<%= Html.ActionLink("Editer","Edit", new { id = e.Id }, new { @class="actionlink" }) %>
<%= Html.ActionLink("Supprimer","RemovePost", new { id = e.Id }, new { @class="actionlink" } ) %>
<% } %>
</aside>
<%= Html.Partial("PostActions",e)%>
</div>
<% } %>
<aside>

View File

@ -141,6 +141,8 @@
<Folder Include="bfiles\" />
<Folder Include="fonts\" />
<Folder Include="lib\" />
<Folder Include="App_Data\" />
<Folder Include="Test\" />
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\HomeController.cs" />
@ -150,7 +152,6 @@
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\BlogsController.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Test\TestByteA.cs" />
<Compile Include="Controllers\FrontOfficeController.cs" />
<Compile Include="Controllers\BackOfficeController.cs" />
<Compile Include="Admin\Export.cs" />
@ -429,6 +430,9 @@
<Content Include="images\musician-923526_1.nbb.xs.jpg" />
<Content Include="images\musician-923526_1.nbb.xxs.jpg" />
<Content Include="Views\Blogs\Title.aspx" />
<Content Include="Views\Blogs\PostActions.ascx" />
<Content Include="Scripts\yavsc.tags.js" />
<Content Include="Scripts\yavsc.scrollnotif.js" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
@ -493,7 +497,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="instdbws.sql" />
<EmbeddedResource Include="App_Data\instdbws.sql" />
</ItemGroup>
<ItemGroup>
<WebReferences Include="Web References" />

View File

@ -0,0 +1,137 @@
//
// BasePost.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 System;
using System.Configuration;
using System.Collections.Generic;
using Yavsc.Model.Blogs;
using System.Linq;
using Yavsc.Model.Circles;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace Yavsc.Model.Blogs
{
/// <summary>
/// Base post.
/// </summary>
public class BasePost {
/// <summary>
/// The identifier.
/// </summary>
long id;
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
[DisplayName("Identifiant numérique de billet")]
public long Id {
get {
return id;
}
set {
id = value;
}
}
/// <summary>
/// The posted.
/// </summary>
private DateTime posted;
/// <summary>
/// Gets or sets the posted.
/// </summary>
/// <value>The posted.</value>
[DisplayName("Date de creation")]
public DateTime Posted {
get {
return posted;
}
set {
posted = value;
}
}
/// <summary>
/// The modified.
/// </summary>
private DateTime modified;
/// <summary>
/// Gets or sets the modified.
/// </summary>
/// <value>The modified.</value>
[DisplayName("Date de modification")]
public DateTime Modified {
get {
return modified;
}
set {
modified = value;
}
}
private string title;
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[DisplayName("Titre du billet")]
[StringLength(512)]
[RegularExpression("^[^:%&?]*$",ErrorMessage = "Les caratères suivants sont invalides pour un titre: :%&?")]
[Required(ErrorMessage = "S'il vous plait, saisissez un titre")]
public string Title {
get {
return title;
}
set {
title = value;
}
}
private string author;
/// <summary>
/// Gets or sets the name of the user.
/// </summary>
/// <value>The name of the user.</value>
[StringLength(255)]
[DisplayName("Auteur")]
public string Author {
get {
return author;
}
set {
author = value;
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="Yavsc.Model.Blogs.BlogEntry"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
public bool Visible { get; set ; }
}
}

View File

@ -10,23 +10,7 @@ namespace Yavsc.Model.Blogs
/// <summary>
/// Blog entry.
/// </summary>
public class BlogEntry {
long id;
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
[DisplayName("Identifiant numérique de billet")]
public long Id {
get {
return id;
}
set {
id = value;
}
}
public class BlogEntry : BasePost {
/// <summary>
/// Gets or sets the photo.
@ -37,24 +21,7 @@ namespace Yavsc.Model.Blogs
set;
}
string title;
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[DisplayName("Titre du billet")]
[StringLength(512)]
[RegularExpression("^[^:%&?]*$",ErrorMessage = "Les caratères suivants sont invalides pour un titre: :%&?")]
[Required(ErrorMessage = "S'il vous plait, saisissez un titre")]
public string Title {
get {
return title;
}
set {
title = value;
}
}
string content;
@ -73,65 +40,6 @@ namespace Yavsc.Model.Blogs
}
}
string userName;
/// <summary>
/// Gets or sets the name of the user.
/// </summary>
/// <value>The name of the user.</value>
[StringLength(255)]
[DisplayName("Auteur")]
public string Author {
get {
return userName;
}
set {
userName = value;
}
}
/// <summary>
/// The posted.
/// </summary>
public DateTime posted;
/// <summary>
/// Gets or sets the posted.
/// </summary>
/// <value>The posted.</value>
[DisplayName("Date de creation")]
public DateTime Posted {
get {
return posted;
}
set {
posted = value;
}
}
/// <summary>
/// The modified.
/// </summary>
public DateTime modified;
/// <summary>
/// Gets or sets the modified.
/// </summary>
/// <value>The modified.</value>
[DisplayName("Date de modification")]
public DateTime Modified {
get {
return modified;
}
set {
modified = value;
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="Yavsc.Model.Blogs.BlogEntry"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
public bool Visible { get; set ; }
/// <summary>
/// Gets or sets the circles allowed to read this ticket.
/// An empty collection specifies a public post.

View File

@ -76,22 +76,13 @@ namespace Yavsc.Model.Blogs
}
return res;
}
/// <summary>
/// Base post info.
/// </summary>
public class BasePostInfo {
/// <summary>
/// The identifier.
/// </summary>
public long Id;
/// <summary>
/// The posted.
/// </summary>
public DateTime Posted;
/// <summary>
/// The modified.
/// </summary>
public DateTime Modified;
public class BasePostInfo: BasePost {
/// <summary>
/// The intro.

View File

@ -183,9 +183,9 @@ namespace Yavsc.Model.Blogs
/// <param name="postid">Postid.</param>
/// <param name="tag">Tag.</param>
/// <returns>The tag identifier</returns>
public static long Tag (long postid, string tag)
public static void Tag (long postid, string tag)
{
return Provider.Tag (postid, tag);
Provider.Tag (postid, tag);
}
/// <summary>
@ -215,6 +215,16 @@ namespace Yavsc.Model.Blogs
return e;
}
/// <summary>
/// Untag the specified postid and tagname.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagname">Tagname.</param>
public static void Untag (long postid, string tagname)
{
Provider.Untag (postid, tagname);
}
private static bool CanView (BlogEntry e, MembershipUser u = null)
{
if (e.AllowedCircles != null && e.AllowedCircles.Length > 0) {

View File

@ -143,14 +143,26 @@ namespace Yavsc.Model.Blogs
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tag">Tag.</param>
public abstract long Tag (long postid,string tag);
public abstract long Tag (long postid, string tag);
/// <summary>
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="tagid">Tagid.</param>
public abstract void Untag (long postid, long tagid);
/// <summary>
/// Uns the tag.
/// </summary>
/// <param name="postid">Postid.</param>
/// <param name="name">Name.</param>
public abstract void Untag (long postid, string name);
/// <summary>
/// Removes the tag.
/// </summary>
/// <param name="tagid">Tagid.</param>
public abstract void RemoveTag (long tagid);
public abstract void DropTag (long tagid);
/// <summary>
/// Updates the post photo.
/// </summary>

View File

@ -23,7 +23,11 @@ namespace Yavsc.Model.Blogs
/// <summary>
/// The match invisible.
/// </summary>
MatchInvisible = 8
MatchInvisible = 8,
/// <summary>
/// The match tag.
/// </summary>
MatchTag = 16,
}
}

View File

@ -1,3 +1,31 @@
2015-10-13 Paul Schneider <paul@pschneider.fr>
* BasePost.cs: refactoring:
allows the "PostActions" user control to use a common base
object as post reference
* YavscModel.csproj:
* BlogEntry.cs:
* BlogEntryCollection.cs: refactoring
* BlogManager.cs: Makes the blog manager expose of the new
`UnTag` method
* BlogProvider.cs: introduces a method to `untag`
* FindBlogEntryFlags.cs: Find post entry by tag
* LocalizedText.resx:
* LocalizedText.Designer.cs: new translations: - "Tag"
- "Edit"
* LocalizedText.fr.resx:
* LocalizedText.fr.Designer.cs: nouvelles traductions: - "Tag"
- "Edit"
* Profile.cs: a nicer stack trace at buggy usage
2015-10-10 Paul Schneider <paul@pschneider.fr>
* YavscModel.csproj:

View File

@ -190,6 +190,18 @@ namespace Yavsc.Model {
}
}
public static string View_source {
get {
return ResourceManager.GetString("View_source", resourceCulture);
}
}
public static string Hide_source {
get {
return ResourceManager.GetString("Hide_source", resourceCulture);
}
}
public static string access_denied {
get {
return ResourceManager.GetString("access_denied", resourceCulture);
@ -238,6 +250,12 @@ namespace Yavsc.Model {
}
}
public static string DoTag {
get {
return ResourceManager.GetString("DoTag", resourceCulture);
}
}
public static string Not_Approuved {
get {
return ResourceManager.GetString("Not_Approuved", resourceCulture);
@ -364,6 +382,12 @@ namespace Yavsc.Model {
}
}
public static string ReadMore {
get {
return ResourceManager.GetString("ReadMore", resourceCulture);
}
}
public static string Item_added_to_basket {
get {
return ResourceManager.GetString("Item_added_to_basket", resourceCulture);
@ -376,6 +400,12 @@ namespace Yavsc.Model {
}
}
public static string Edit {
get {
return ResourceManager.GetString("Edit", resourceCulture);
}
}
public static string InternalServerError {
get {
return ResourceManager.GetString("InternalServerError", resourceCulture);

View File

@ -124,6 +124,12 @@ namespace Yavsc.Model {
}
}
public static string View_source {
get {
return ResourceManager.GetString("View_source", resourceCulture);
}
}
public static string Ciffer {
get {
return ResourceManager.GetString("Ciffer", resourceCulture);
@ -184,15 +190,21 @@ namespace Yavsc.Model {
}
}
public static string Hide_source {
get {
return ResourceManager.GetString("Hide_source", resourceCulture);
}
}
public static string access_denied {
get {
return ResourceManager.GetString("access_denied", resourceCulture);
}
}
public static string was_added_to_the_role {
public static string DoTag {
get {
return ResourceManager.GetString("was_added_to_the_role", resourceCulture);
return ResourceManager.GetString("DoTag", resourceCulture);
}
}
@ -352,6 +364,12 @@ namespace Yavsc.Model {
}
}
public static string ReadMore {
get {
return ResourceManager.GetString("ReadMore", resourceCulture);
}
}
public static string Item_added_to_basket {
get {
return ResourceManager.GetString("Item_added_to_basket", resourceCulture);
@ -364,6 +382,12 @@ namespace Yavsc.Model {
}
}
public static string Edit {
get {
return ResourceManager.GetString("Edit", resourceCulture);
}
}
public static string InternalServerError {
get {
return ResourceManager.GetString("InternalServerError", resourceCulture);
@ -375,5 +399,11 @@ namespace Yavsc.Model {
return ResourceManager.GetString("entries", resourceCulture);
}
}
public static string was_added_to_the_role {
get {
return ResourceManager.GetString("was_added_to_the_role", resourceCulture);
}
}
}
}

View File

@ -25,12 +25,15 @@
<data name="DocTemplateException"><value>Une erreur est survenue à la génération de votre document</value></data>
<data name="Description"><value>Description</value></data>
<data name="DisplayName"><value>Nom affiché</value></data>
<data name="DoTag"><value>Tagger</value></data>
<data name="entries"><value>entrées</value></data>
<data name="Edit"><value>Éditer</value></data>
<data name="EndDate"><value>Date de fin</value></data>
<data name="Estimate_not_found"><value>Devis non trouvé</value></data>
<data name="EventWebPage"><value>Page web de l'événement</value></data>
<data name="Google_calendar"><value>Agenda Google</value></data>
<data name="Google_error"><value>Erreur Google : {0}</value></data>
<data name="Hide_source"><value>Cacher le texte source du billet</value></data>
<data name="Home"><value>Accueil</value></data>
<data name="ImgLocator"><value>URI de l'image</value></data>
<data name="ImportException"><value>Exception à l'import</value></data>
@ -52,6 +55,7 @@
<data name="Preview"><value>Prévisualiser</value><comment>Prévisualiser le document</comment></data>
<data name="Profile_edition"><value>Édition du profile</value></data>
<data name="Product_reference"><value>Référence produit</value></data>
<data name="ReadMore"><value>Lire la suite ...</value></data>
<data name="ProviderId"><value>Identifiant du fournisseur</value></data>
<data name="ProviderName"><value>Nom du fournisseur</value></data>
<data name="Register"><value>Enregistez-vous</value></data>
@ -64,6 +68,7 @@
<data name="Unitary_cost"><value>Coût unitaire</value></data>
<data name="User List"><value>Liste des utilisateurs</value><comment></comment></data>
<data name="User_name"><value>Nom d'utilisateur</value></data>
<data name="View_source"><value>Voir le texte source du billet</value></data>
<data name="was_added_to_the_role"><value>a été ajouté au rôle</value></data>
<data name="was_added_to_the_empty_role"><value>Il n'y avait pas 'utilisateur dans le rôle '{1}'. Vous ({0}) avez été ajouté au rôle '{1}'.</value></data>
<data name="Welcome"><value>Bienvenue</value><comment></comment></data>

View File

@ -25,12 +25,15 @@
<data name="Description"><value>Description</value></data>
<data name="DisplayName"><value>Display Name</value></data>
<data name="DocTemplateException"><value>Exception occured when rendering your document</value></data>
<data name="DoTag"><value>Tag</value></data>
<data name="DuplicateEmail"><value>This email adress is already used ({0}).</value></data>
<data name="DuplicateUserName"><value>This user name is already used ({0}).</value></data>
<data name="Edit"><value>Edit</value></data>
<data name="EndDate"><value>End date</value></data>
<data name="Estimate_not_found"><value>Estimate not found</value></data>
<data name="EventWebPage"><value>Event Web page</value></data>
<data name="Home"><value>Home</value></data>
<data name="Hide_source"><value>Hide the bill source text</value></data>
<data name="entries"><value>entries</value></data>
<data name="Google_calendar"><value>Google calendar</value></data>
<data name="Google_error"><value>Google error : {0}</value></data>
@ -57,6 +60,7 @@
<data name="ProviderId"><value>Provider identifier</value></data>
<data name="ProviderName"><value>Provider name</value></data>
<data name="Product_reference"><value>Product_reference</value></data>
<data name="ReadMore"><value>Read more ...</value></data>
<data name="Register"><value>Register</value></data>
<data name="Remember_me"><value>Remember me</value></data>
<data name="Remove"><value>Remove</value></data>
@ -67,6 +71,7 @@
<data name="Unitary_cost"><value>Unitary_cost</value></data>
<data name="User_List"><value>User List</value><comment></comment></data>
<data name="User_name"><value>User name</value></data>
<data name="View_source"><value>View source</value></data>
<data name="was_added_to_the_role"><value>was added to the role</value></data>
<data name="was_added_to_the_empty_role"><value>There was no user in the '{1}' role. You ({0}) was just added as firt user in the '{1}' role.</value></data>
<data name="Welcome"><value>Welcome</value><comment></comment></data>

View File

@ -237,6 +237,9 @@ namespace Yavsc.Model.RolesAndMembers
/// <param name="profile">Profile.</param>
public Profile (ProfileBase profile)
{
if (profile == null)
throw new Exception ("No profile");
object b = profile.GetPropertyValue ("BlogVisible");
BlogVisible = (b == null) ? true : (b is DBNull)? true : (bool)b;

View File

@ -172,6 +172,7 @@
<Compile Include="Circles\CircleBase.cs" />
<Compile Include="Blogs\MarkdownHelper.cs" />
<Compile Include="Blogs\UTBlogEntryCollection.cs" />
<Compile Include="Blogs\BasePost.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>