Files
yavsc/web/Helpers/YavscHelpers.cs
Paul Schneider d999ae5a8e Thème clair opé, WIP circles
* animate.css: animations css

* links.css: liens avec le fond blanc qui se déroule

* links.css: WIP liens thème sombre

* GitHub.ico: un petit merci à GitHub

* live-concert-fg.png: image de plan rapproché : les fans

* live-concert-scene.jpg: Image de fond : la scene

* splash-image-2.jpg: image de fond : photo colorée, public de
  concert, vient de totemproduction.fr

* links.css: ficher de définitions globales du style des bouttons
  (encore inutilisé)

* yavsc.user.js: WIP implémente le widget "utilisateur", permettant
l'affichage des liens rapides pour tout nom d'ulitisateur, le cas
  échéant, vers l'ajout à un cercle,
vers son blog, vers des methodes choisies d'administateur, vers ses
  réseaux sociaux, voir plus.

* About.aspx: Implémente une page "à propos"

* Test.aspx: Page de test: désolé pour le bruit, elle n'est compilée
  qu'en mode `Debug` (elle n'est pas accessible en production)

* NpgsqlBlogProvider.cs: Corrige la méthode pour enlever un tag à un
  article ...

* NpgsqlBlogProvider.csproj: .

* NpgsqlCircleProvider.cs: liste les cercles auquels appartient un
  utilisateur.

* BasketController.cs:
* NpgsqlContentProvider.cs: Les commandes sont fortement typée.

* README.md: mise à jour des priorités

* style.css: réécriture du thème clair

* style.css: * implémente un classe css `clickme` pour attirer l'oeil
sur le boutton de validation après la modification d'un champ de
  formulaire.
* enlève tous les coins arrondis
* modifie la chasse de caractères (une seule utilisée pour le moment)
*

* style.css: * integre la référence à la feuille de style des
  [animations](https://daneden.github.io/animate.css/)
* corrige des marges, alignements
* supprime ce qui reste de coin arrondi
* néttoye les définitions obsolètes
* définit la classe `username`
* corrige le survol à la suppression de tag

* FrontOfficeController.cs: renomme des methodes, refabriqué pour
  s'adapter aux changements de l'API du workflow,
WIP propose les cercles utilisateurs pour l'ajout des profiles
  préstataires aux cercles.

* HomeController.cs: implémente une page "à propos"

* T.cs: re-autorise le titre vide de page, au cas où ... car ce n'est
  pas un véritable
défaut fonctionnel.

* YavscHelpers.cs: Implemente un outil de presentation des liens
  action traduits. Tous les liens action utilisent maintenant cette
  nouvelle methode,
au profile de celle du framework `HtmlHelpers.ActionLink`

* App.master: corrige l'usage du contrôle utilisateur des cotes dans
  le cadre des cotes de billet.

* AppAdmin.master:
* Index.aspx:
* Service.aspx:
* ProductCategory.aspx: traduction des liens action

* NoLogin.master: * traduction des liens action
* suppression des liens de remerciement dans le bas de page, cette
  information a été déplacée dans la page `/Home/Credits`

* to-markdown.js: transforme maintenant les noeuds Html `div` en
  paragraphes Markdown.

* yavsc.hidefieldset.js: Le script règle la forme de la souris au
  survol du bouton,
le cas échéant.

* yavsc.js: nouvelle fonction javascript pour logger un objet
  arbitraire.

* yavsc.rate.js: Fixe la possibilité de mettre des cotes très basses
  ou très hautes (reste encore un mieux à faire),
Affiche au survol des descriptions optionnelles de la cote.

* Title.aspx:
* UserPost.aspx:
* Edit.aspx:
* Index.aspx:
* Brand.aspx:
* Index.aspx:
* PostActions.ascx:
* TitleNotFound.aspx:
* Booking.aspx:
* Command.aspx:
* ChangePasswordSuccess.aspx: Traduction des liens action

* Login.aspx: * Traduction des liens actionTraduction des liens action

* Profile.aspx: * Traduction des liens actionTraduction des liens
  action
* utilisation de la classe css `mayhide` qui autorise maintenant un
  champ d'entrées de formulaire à être plié/déplié au click sur sa
  légende.

* Admin.aspx: Traduction des liens actionTraduction des liens
  actionTraduction des liens actionTraduction des liens
  actionTraduction des liens actionTraduction des liens action

* Backups.aspx:
* RoleList.aspx:
* UserList.aspx:
* Index.aspx: Traduction des liens actionTraduction des liens action

* Edit.aspx: * refabrication de la structure Html
* Traduction des liens actionTraduction des liens action

* Index.aspx: Simlpification des apperçus de blog

* TagControl.ascx: refabrication pour simplifier l'implémentation du
  contrôle utilisateur des tags

* UserPosts.aspx: Traduction des liens action, et simplification du
  listing de blog

* Basket.aspx: Affiche les articles du panier de commandes avec leur
  vue
dédiée à leur type (les commande sont maintenant fortement typées)

* Catalog.aspx: Traduction des liens action, correctin du lien vers le
  produit
(cassé depuis une vielle refabrication des routes)

* DoAnEstimate.aspx: refabrication de la vue de création du devis:
  renommée depuis `Estimate`

* Performer.ascx: * un message supplementaire à l'absence de
  compétence affichée par un préstataire
* des guillemets autour du commentaire du préstataire sur sa
  compétence
* ajout du préstataire au cercles

* Performers.aspx: Décrit en détail les informations sur la
  disponibilité d'un préstataire,
à la date demandée.

* YourEstimates.aspx: renomage de cette page, pour préciser sa
  fonction : Vos devis.

* Contact.aspx: structure Html de la page de contact

* Credits.aspx: Ajoute les remerciements aux communauté du libre

* Index.aspx: ne fait rien

* Web.config: * import de `System.Transactions`
* mise à jour des credits libres

* WebDeploy.targets: utilise les séparateurs de chemin vers ficher à
  la POSIX, ne change rien pour ma config ... (TODO tester sous
  WoinDose)

* Yavsc.csproj: déploie des pages des scripts Javascript et des images
  et feuilles de style en plus.

* CircleManager.cs: implémente les methodes utilisées à la
  construction du contrôle utilisateur.

* CircleProvider.cs: * doc xml
* extension de interface

* Commande.cs: l'objet `Command` devient abstrait, pour exister (être
  instanciée), une commande doit maintenant hériter de cet objet
  abstrait.

* LocalizedText.resx:
* LocalizedText.fr.resx:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs: traductions

* IContentProvider.cs: doc xml

* SiteSkills.aspx: renomage de cette page, pour préciser sa fonction :
  les compétences sur ce site.
2015-12-09 13:26:02 +01:00

509 lines
16 KiB
C#

using System;
using System.Web;
using System.Configuration;
using System.Web.Security;
using System.IO;
using System.Web.Configuration;
using System.Net.Mail;
using Yavsc.Model.RolesAndMembers;
using System.Collections.Generic;
using System.Collections.Specialized;
using Yavsc.Model.Circles;
using System.Web.UI;
using System.Linq.Expressions;
using System.Web.Profile;
using System.Web.Script.Serialization;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using Yavsc.Model.Messaging;
using System.Linq;
using System.Reflection;
using System.Web.Routing;
namespace Yavsc.Helpers
{
/// <summary>
/// Yavsc helpers.
/// </summary>
public static class YavscHelpers
{
private static string siteName = null;
/// <summary>
/// Gets the name of the site.
/// </summary>
/// <value>The name of the site.</value>
public static string SiteName {
get {
if (siteName == null)
siteName = WebConfigurationManager.AppSettings ["Name"];
return siteName;
}
}
// Administrator email
private static string admail =
WebConfigurationManager.AppSettings ["AdminEmail"];
/// <summary>
/// Gets the Administrator email.
/// </summary>
/// <value>The admail.</value>
public static string Admail {
get {
return admail;
}
}
/// <summary>
/// Sends the activation message.
/// </summary>
/// <param name="helper">Helper.</param>
/// <param name="user">User.</param>
public static void SendActivationMessage(this System.Web.Http.Routing.UrlHelper helper, MembershipUser user)
{
SendActivationMessage (helper.Route("Default", new { controller="Account",
action = "Validate",
key=user.ProviderUserKey.ToString(), id = user.UserName } )
, WebConfigurationManager.AppSettings ["RegistrationMessage"],
user);
}
/// <summary>
/// Sends the activation message.
/// </summary>
/// <param name="helper">Helper.</param>
/// <param name="user">User.</param>
public static void SendActivationMessage(this System.Web.Mvc.UrlHelper helper, MembershipUser user)
{
SendActivationMessage (
string.Format("{2}://{3}/Account/Validate/{1}?key={0}",
user.ProviderUserKey.ToString(), user.UserName ,
helper.RequestContext.HttpContext.Request.Url.Scheme,
helper.RequestContext.HttpContext.Request.Url.Authority
)
, WebConfigurationManager.AppSettings ["RegistrationMessage"],
user);
}
/// <summary>
/// Sends the activation message.
/// </summary>
/// <param name="validationUrl">Validation URL.</param>
/// <param name="registrationMessage">Registration message.</param>
/// <param name="user">User.</param>
public static void SendActivationMessage(string validationUrl, string registrationMessage, MembershipUser user) {
FileInfo fi = new FileInfo (
HttpContext.Current.Server.MapPath (registrationMessage));
if (!fi.Exists) {
throw new Exception(
string.Format (
"Erreur inattendue (pas de corps de message " +
"à envoyer pour le message de confirmation ({0}))",
registrationMessage));
}
using (StreamReader sr = fi.OpenText ()) {
string body = sr.ReadToEnd ();
body = body.Replace ("<%SiteName%>", YavscHelpers.SiteName);
body = body.Replace ("<%UserName%>", user.UserName);
body = body.Replace ("<%UserActivatonUrl%>", validationUrl);
using (MailMessage msg = new MailMessage (
Admail, user.Email,
string.Format ("Validation de votre compte {0}", YavscHelpers.SiteName),
body)) {
using (SmtpClient sc = new SmtpClient ()) {
sc.Send (msg);
}
}
}
}
/// <summary>
/// Validates the password reset.
/// </summary>
/// <param name="model">Model.</param>
/// <param name="errors">Errors.</param>
/// <param name="user">User.</param>
public static void ValidatePasswordReset(LostPasswordModel model, out StringDictionary errors, out MembershipUser user)
{
MembershipUserCollection users = null;
errors = new StringDictionary ();
user = null;
if (!string.IsNullOrEmpty (model.UserName)) {
users =
Membership.FindUsersByName (model.UserName);
if (users.Count < 1) {
errors.Add ("UserName", "User name not found");
return ;
}
if (users.Count != 1) {
errors.Add ("UserName", "Found more than one user!(sic)");
return ;
}
}
if (!string.IsNullOrEmpty (model.Email)) {
users =
Membership.FindUsersByEmail (model.Email);
if (users.Count < 1) {
errors.Add ( "Email", "Email not found");
return ;
}
if (users.Count != 1) {
errors.Add ("Email", "Found more than one user!(sic)");
return ;
}
}
if (users==null)
return;
// Assert users.Count == 1
foreach (MembershipUser u in users) user = u;
}
/// <summary>
/// Avatars the URL.
/// </summary>
/// <returns>The URL.</returns>
/// <param name="helper">Helper.</param>
/// <param name="username">Username.</param>
public static string AvatarUrl (this System.Web.Mvc.UrlHelper helper, string username) {
if (username == null) return null;
ProfileBase pr = ProfileBase.Create (username);
object avpath = null;
if (pr != null) avpath = pr.GetPropertyValue("Avatar");
if (avpath == null || avpath is DBNull)
return DefaultAvatar==null?"/bfiles/"+username+".png":DefaultAvatar;
string avatarLocation = avpath as string;
if (avatarLocation.StartsWith ("~/")) {
avatarLocation = helper.RouteUrl("Default", avatarLocation);
}
return avatarLocation;
}
private static string avatarDir = "~/avatars";
private static string defaultAvatar = null;
private static string defaultAvatarMimetype = null;
public static string DefaultAvatar {
get {
if (defaultAvatar == null)
GetAvatarConfig ();
return defaultAvatar;
}
}
public static string AvatarDir {
get {
return avatarDir;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="Yavsc.Controllers.BlogsController"/> class.
/// </summary>
private static void GetAvatarConfig ()
{
string[] defaultAvatarSpec = ConfigurationManager.AppSettings.Get ("DefaultAvatar").Split (';');
if (defaultAvatarSpec.Length != 2)
throw new ConfigurationErrorsException ("the DefaultAvatar spec should be found as <fileName>;<mime-type> ");
defaultAvatar = defaultAvatarSpec [0];
defaultAvatarMimetype = defaultAvatarSpec [1];
}
/// <summary>
/// Javas the script.
/// </summary>
/// <returns>The script.</returns>
/// <param name="html">Html.</param>
/// <param name="obj">Object.</param>
public static string JavaScript(this System.Web.Mvc.HtmlHelper html, object obj)
{
return JavaScript (obj);
}
/// <summary>
/// Javas the script.
/// </summary>
/// <returns>The script.</returns>
/// <param name="obj">Object.</param>
public static string JavaScript(object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static void Notify(ViewDataDictionary ViewData, string message, string click_action=null, string clickActionName="Ok") {
Notify(ViewData, new Notification { body = YavscAjaxHelper.QuoteJavascriptString(message),
click_action = click_action, click_action_name = YavscAjaxHelper.QuoteJavascriptString(clickActionName)} ) ;
}
public static void Notify(ViewDataDictionary ViewData, Notification note) {
if (ViewData ["Notifications"] == null)
ViewData ["Notifications"] = new List<Notification> ();
(ViewData ["Notifications"] as List<Notification>).Add (
note ) ;
}
/// <summary>
/// Files the list.
/// </summary>
/// <returns>The list.</returns>
/// <param name="html">Html.</param>
/// <param name="path">Path.</param>
/// <param name="patterns">Patterns.</param>
public static IHtmlString FileList(this System.Web.Mvc.HtmlHelper html, string path, string [] patterns = null) {
StringWriter str = new StringWriter();
HtmlTextWriter writter = new HtmlTextWriter (str);
DirectoryInfo di = new DirectoryInfo (HttpContext.Current.Server.MapPath(path));
if (!di.Exists)
return new System.Web.Mvc.MvcHtmlString ("");
var files = new List<FileInfo> ();
if (patterns == null)
patterns = new string[] { "*" };
var url = new System.Web.Mvc.UrlHelper(html.ViewContext.RequestContext,
html.RouteCollection);
foreach (string pattern in patterns)
files.AddRange(
di.EnumerateFiles (
pattern,
SearchOption.TopDirectoryOnly));
writter.RenderBeginTag ("table");
writter.RenderBeginTag ("tr");
writter.RenderBeginTag ("td");
writter.Write (html.Translate ("Name"));
writter.RenderEndTag ();
writter.RenderBeginTag ("td");
writter.Write (html.Translate ("Created"));
writter.RenderEndTag ();
writter.RenderBeginTag ("td");
writter.Write (html.Translate ("Modified"));
writter.RenderEndTag ();
writter.RenderEndTag ();
foreach (FileInfo fi in files) {
writter.RenderBeginTag ("tr");
writter.RenderBeginTag ("td");
writter.AddAttribute ("href", url.Content(path+"/"+fi.Name));
writter.RenderBeginTag ("a");
writter.Write (fi.Name);
writter.RenderEndTag ();
writter.RenderEndTag ();
writter.RenderBeginTag ("td");
writter.Write (fi.LastWriteTime.ToString ("U"));
writter.RenderEndTag ();
writter.RenderBeginTag ("td");
writter.Write (fi.CreationTime.ToString("U"));
writter.RenderEndTag ();
writter.RenderEndTag ();
}
writter.RenderEndTag ();
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="PageIndex">Page index.</param>
/// <param name="PageSize">Page size.</param>
/// <param name="ResultCount">Result count.</param>
/// <param name="args">Arguments.</param>
/// <param name="pagesLabel">Pages label.</param>
/// <param name="singlePage">Single page.</param>
/// <param name="none">None.</param>
/// <param name="cssClass">Css class.</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", string cssClass = "pagelink"
)
{
StringWriter strwr = new StringWriter ();
HtmlTextWriter writer = new HtmlTextWriter(strwr);
if (PageSize <= 0)
PageSize = 0;
if (ResultCount > 0 && ResultCount > PageSize ) {
int pageCount = ((ResultCount-1) / PageSize) + 1;
if ( pageCount > 1 ) {
if (cssClass!=null)
writer.AddAttribute ("class", cssClass);
writer.RenderBeginTag ("div");
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;");
}
writer.RenderEndTag ();
}
else {
writer.Write (singlePage);
}
}
if (ResultCount == 0) {
writer.WriteEncodedText(none);
}
return new MvcHtmlString(strwr.ToString());
}
/// <summary>
/// The available themes.
/// </summary>
public static string[] AvailableThemes = {
"clear", "dark", "blue", "green"
};
/// <summary>
/// Themes the CSS links.
/// </summary>
/// <returns>The CSS links.</returns>
/// <param name="html">Html.</param>
/// <param name="theme">Theme.</param>
/// <param name="baseName">Base name.</param>
public static IHtmlString ThemeCSSLinks (
this System.Web.Mvc.HtmlHelper html, string theme, string baseName) {
if (!AvailableThemes.Contains (theme))
throw new ArgumentException ("The given theme is not configured: " +
theme);
if (string.IsNullOrWhiteSpace(baseName))
throw new ArgumentException ("Specify a base name");
StringWriter strwr = new StringWriter ();
HtmlTextWriter writer = new HtmlTextWriter(strwr);
// refer to the global style
writer.AddAttribute ("rel", "stylesheet");
writer.AddAttribute ("href",
string.Format(
"/App_Themes/{1}.css",
theme,baseName));
writer.RenderBeginTag ("link");
// refer to the themed style
writer.AddAttribute ("rel", "stylesheet");
writer.AddAttribute ("title", theme);
writer.AddAttribute ("href",
string.Format(
"/App_Themes/{0}/{1}.css",
theme,baseName));
writer.RenderBeginTag ("link");
// refer to alternate styles
foreach (string atheme in AvailableThemes) {
if (atheme != theme) {
writer.AddAttribute ("rel", "alternate stylesheet");
writer.AddAttribute ("title", atheme);
writer.AddAttribute ("href",
string.Format (
"/App_Themes/{0}/{1}.css",
atheme, baseName));
writer.RenderBeginTag ("link");
}
}
return new MvcHtmlString(strwr.ToString());
}
private static object defaultHtmlAttributes =
new { @class="actionlink" };
/// <summary>
/// Translateds the action link.
/// </summary>
/// <returns>The action link.</returns>
/// <param name="helper">Helper.</param>
/// <param name="actionName">Action name.</param>
/// <param name="htmlAttributes">Html attributes.</param>
public static IHtmlString TranslatedActionLink (this HtmlHelper helper,
string actionLabel, object htmlAttributes = null) {
return TranslatedActionLink (helper, actionLabel, actionLabel, htmlAttributes);
}
/// <summary>
/// Translateds the action link.
/// </summary>
/// <returns>The action link.</returns>
/// <param name="helper">Helper.</param>
/// <param name="actionName">Action name.</param>
/// <param name="method">Method.</param>
/// <param name="htmlAttributes">Html attributes.</param>
public static IHtmlString TranslatedActionLink (this HtmlHelper helper,
string actionLabel, string method, object htmlAttributes = null) {
return TranslatedActionLink (helper,
actionLabel, method, null, htmlAttributes = null);
}
/// <summary>
/// Translateds the action link.
/// </summary>
/// <returns>The action link.</returns>
/// <param name="helper">Helper.</param>
/// <param name="actionName">Action name.</param>
/// <param name="method">Method.</param>
/// <param name="controller">Controller.</param>
/// <param name="htmlAttributes">Html attributes.</param>
public static IHtmlString TranslatedActionLink (this HtmlHelper helper,
string actionLabel, string method, string controller, object htmlAttributes = null) {
return TranslatedActionLink (helper, actionLabel, method, controller,
new { controller = controller, action = actionLabel }, htmlAttributes);
}
/// <summary>
/// Translateds the action link.
/// </summary>
/// <returns>The action link.</returns>
/// <param name="helper">Helper.</param>
/// <param name="actionName">Action name.</param>
/// <param name="method">Method.</param>
/// <param name="controller">Controller.</param>
/// <param name="routes">Routes.</param>
/// <param name="htmlAttributes">Html attributes.</param>
public static IHtmlString TranslatedActionLink (this HtmlHelper helper,
string actionLabel, string actionName, string controller, object routes, object htmlAttributes = null) {
if (htmlAttributes == null)
htmlAttributes = defaultHtmlAttributes;
IHtmlString text = T.Translate (helper, actionLabel);
StringWriter strwr = new StringWriter ();
HtmlTextWriter writer = new HtmlTextWriter(strwr);
foreach (var ppt in htmlAttributes.GetType().GetProperties(BindingFlags.GetProperty|
BindingFlags.Public)) {
writer.AddAttribute(ppt.Name, ppt.GetValue(htmlAttributes).ToString())
;
}
writer.AddAttribute ("href",
UrlHelper.GenerateUrl (
"Default", actionName, controller,
( routes == null ) ? null : new RouteValueDictionary ( routes ) ,
helper.RouteCollection,
helper.ViewContext.RequestContext,
false));
writer.RenderBeginTag ("a");
writer.Write (text);
writer.RenderEndTag ();
return new MvcHtmlString(strwr.ToString());
}
public static IHtmlString TranslatedActionLink (this HtmlHelper helper,
string actionName, string method, object routes, object htmlAttributes = null) {
string controllerName = helper.ViewContext.Controller.GetType ().Name;
if (controllerName.EndsWith ("Controller"))
controllerName = controllerName.Substring (0,controllerName.Length - 10);
return TranslatedActionLink (helper, actionName, method,
controllerName, routes, htmlAttributes);
}
}
}