Implémente un formulaire simple

de réservation d'un préstataire

* p8-av4.xxs.jpg:
* p8-av4.xxs.png: inutile

* NoLogin.master:
* Entity.cs:
* OAuth2.cs:
* ApiClient.cs:
* PeopleApi.cs:
* MapTracks.cs:
* SkillManager.cs:
* Skills.aspx:
* EntityQuery.cs:
* CalendarApi.cs:
* SimpleJsonPostMethod.cs:
* GoogleHelpers.cs:
* EventPub.aspx:
* GoogleController.cs:
* Notification.cs:
* UserSkills.aspx:
* BackOfficeController.cs:
* BackOfficeController.cs:
* Notification.cs:
* MessageWithPayLoad.cs:
* MessageWithPayloadResponse.cs: refabrication

* IContentProvider.cs:
* NpgsqlBlogProvider.cs: xml doc

* NpgsqlContentProvider.cs: implemente un listing des prestataire du
  code APE en base.

* NpgsqlSkillProvider.cs: implemente un listing des domaines de
  compétence du préstataire en base.

* XmlCatalogProvider.cs: Le catalogue de vente implémente mainenant
  l'interface d'un fournisseur de donnée comme les autres.
Il pourrait par exemple vouloir définir des activité et des
  compétences.
Pour l'instant, il n'est pas activé par la configuration, et reste le
  fournisseur du catalogue legacy (voir </FrontOffice/Catalog> ).

* FrontOfficeController.cs: format du code

* Global.asax.cs: Une route customisée pour le Front Office : /do
  (genre, ici, ça bouge.)

* activity.sql: implémente en base de donnée le modèle des activités
  et compétences,
ajoute aussi deux activités : l'edition logicielle et "Artiste"

* style.css: changement de mes images de fond ... tombées du camion de
  Xavier et onlinehome.us

* p8-av4.s.jpg: changement de taille

* AccountController.cs: Met le code MEA à "none" quand il est spécifié
  non disponible.

* BlogsController.cs: fixe un bug de l'edition d'un billet

* FrontOfficeController.cs: implemente le contrôle booking simple

* HomeController.cs: ajoute l'assemblage du catalog dans le listing
  dédié

* YavscAjaxHelper.cs: Implemente un outil de representation JSon des
  objets côté serveur

* parallax.js: deux fois plus de mouvement autout de x dans le
  parallax

* yavsc.rate.js: imlemente un callback JS pour le rating

* Activities.aspx: Des labels au formulaire de déclaration des
  activités

* Activity.ascx: un panneau activité descent

* Booking.aspx: implemente l'UI web du booking simple.

* EavyBooking.aspx: refabrication du booking lourd

* Index.aspx: supprime le panneau du tag Accueil, affiche les
  activités en cours du site (avec au moins un préstataire valide pour
  cette activité)

* Web.config: Implemente une cote utilisateur, par une nouvelle valeur
  de son profile (Rate).

* Yavsc.csproj: refabrique du code API Google, qui part dans le model.

* MarkdownDeep.dll: le tag <p> ne convenait pas, le remplacer par le
  tag <span> non plus.
Maintenant ça devrait être correct, c'est un div, mais que en cas de
  tag englobant non défini.

* BookingQuery.cs: Le booking lourd devient une commande basée sur des
  activités concernée par l'intervention

* ChangeLog: nettoyage

* CatalogProvider.cs: implemente l'interface d'un fournissseur de
  contenu

* PerformerProfile.cs: implemente le profile prestataire

* SimpleBookingQuery.cs: Les besoin sont exprimé sous forme d'un
  tableau de valeur du parametrage de la commande

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

* Profile.cs: implemente un accès à l'id d'enregistrement Google GCM

* SkillEntity.cs: La compétence appartient à un domaine d'activité, on
  lui associe un et un seul code APE

* SkillProvider.cs: Fait chercher les compétences à partir d'un code
  activité

* WorkFlowManager.cs: implemente l'accès à la liste des préstataires
de telle activité

* YavscModel.csproj: refabrications

* Skills.sql: vient de passer dans activity.Sql

* T.cs: la traduction est faite plus simple à appeler (sans cast vers
  `string`).
This commit is contained in:
Paul Schneider 2015-11-28 18:34:52 +01:00
commit a99232ba2b
68 changed files with 1402 additions and 1534 deletions

View file

@ -262,7 +262,7 @@ namespace Yavsc.Controllers
private void SetMEACodeViewData(Profile model) {
var activities = WorkFlowManager.FindActivity ("%", false);
var items = new List<SelectListItem> ();
items.Add (new SelectListItem () { Selected = model.MEACode == null, Text = LocalizedText.DoNotPublishMyActivity, Value=null });
items.Add (new SelectListItem () { Selected = model.MEACode == null, Text = LocalizedText.DoNotPublishMyActivity, Value="none" });
foreach (var a in activities) {
items.Add(new SelectListItem() { Selected = model.MEACode == a.Id,
Text = string.Format("{1} : {0}",a.Title,a.Id),
@ -271,7 +271,6 @@ namespace Yavsc.Controllers
ViewData ["MEACode"] = items;
}
/// <summary>
/// Profile the specified id, model and AvatarFile.
/// </summary>

View file

@ -5,9 +5,9 @@ using System.Web;
using System.Web.Mvc;
using Yavsc.Admin;
using Yavsc.Model.Calendar;
using Yavsc.Helpers.Google;
using Yavsc.Model.Circles;
using System.Web.Security;
using Yavsc.Model.Google.Api;
namespace Yavsc.Controllers

View file

@ -302,7 +302,7 @@ namespace Yavsc.Controllers
Membership.GetUser ().UserName).Select (x => new SelectListItem {
Value = x.Id.ToString(),
Text = x.Title,
Selected = model.AllowedCircles.Contains (x.Id)
Selected = (model.AllowedCircles==null)? false : model.AllowedCircles.Contains (x.Id)
});
return View ("Edit", model);
}

View file

@ -17,6 +17,10 @@ using System.Configuration;
using Yavsc.Helpers;
using Yavsc.Model.FrontOffice.Catalog;
using Yavsc.Model.Skill;
using System.Web.Profile;
using Yavsc.Model.Google.Api;
using System.Net;
using System.Linq;
namespace Yavsc.Controllers
{
@ -33,6 +37,7 @@ namespace Yavsc.Controllers
{
return View ();
}
/// <summary>
/// Pub the Event
/// </summary>
@ -42,6 +47,7 @@ namespace Yavsc.Controllers
{
return View (model);
}
/// <summary>
/// Estimates released to this client
/// </summary>
@ -53,7 +59,7 @@ namespace Yavsc.Controllers
throw new ConfigurationErrorsException ("no redirection to any login page");
string username = u.UserName;
Estimate [] estims = WorkFlowManager.GetUserEstimates (username);
Estimate[] estims = WorkFlowManager.GetUserEstimates (username);
ViewData ["UserName"] = username;
ViewData ["ResponsibleCount"] =
Array.FindAll (
@ -61,8 +67,8 @@ namespace Yavsc.Controllers
x => x.Responsible == username).Length;
ViewData ["ClientCount"] =
Array.FindAll (
estims,
x => x.Client == username).Length;
estims,
x => x.Client == username).Length;
return View (estims);
}
@ -76,7 +82,7 @@ namespace Yavsc.Controllers
Estimate f = WorkFlowManager.GetEstimate (id);
if (f == null) {
ModelState.AddModelError ("Id", "Wrong Id");
return View (new Estimate () { Id=id } );
return View (new Estimate () { Id = id });
}
return View (f);
}
@ -89,9 +95,9 @@ namespace Yavsc.Controllers
[Authorize]
public ActionResult Estimate (Estimate model, string submit)
{
string username = Membership.GetUser().UserName;
string username = Membership.GetUser ().UserName;
// Obsolete, set in master page
ViewData ["WebApiBase"] = Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative);
ViewData ["WebApiBase"] = Url.Content (Yavsc.WebApiConfig.UrlPrefixRelative);
ViewData ["WABASEWF"] = ViewData ["WebApiBase"] + "/WorkFlow";
if (submit == null) {
if (model.Id > 0) {
@ -107,7 +113,7 @@ namespace Yavsc.Controllers
&& !Roles.IsUserInRole ("FrontOffice"))
throw new UnauthorizedAccessException ("You're not allowed to view this estimate");
} else if (model.Id == 0) {
if (string.IsNullOrWhiteSpace(model.Responsible))
if (string.IsNullOrWhiteSpace (model.Responsible))
model.Responsible = username;
}
} else {
@ -116,7 +122,7 @@ namespace Yavsc.Controllers
if (string.IsNullOrWhiteSpace (model.Responsible))
model.Responsible = username;
if (username != model.Responsible
&& !Roles.IsUserInRole ("FrontOffice"))
&& !Roles.IsUserInRole ("FrontOffice"))
throw new UnauthorizedAccessException ("You're not allowed to modify this estimate");
if (ModelState.IsValid) {
@ -172,7 +178,7 @@ namespace Yavsc.Controllers
throw new Exception ("No catalog");
var brand = cat.GetBrand (brandid);
if (brand == null)
throw new Exception ("Not a brand id: "+brandid);
throw new Exception ("Not a brand id: " + brandid);
var pcat = brand.GetProductCategory (pcid);
if (pcat == null)
throw new Exception ("Not a product category id in this brand: " + pcid);
@ -194,7 +200,7 @@ namespace Yavsc.Controllers
ViewData ["ProdRef"] = pref;
Catalog cat = CatalogManager.GetCatalog ();
if (cat == null) {
YavscHelpers.Notify(ViewData, "Catalog introuvable");
YavscHelpers.Notify (ViewData, "Catalog introuvable");
ViewData ["RefType"] = "Catalog";
return View ("ReferenceNotFound");
}
@ -236,11 +242,11 @@ namespace Yavsc.Controllers
try {
// Add specified product command to the basket,
// saves it in db
new Command(collection,HttpContext.Request.Files);
YavscHelpers.Notify(ViewData, LocalizedText.Item_added_to_basket);
new Command (collection, HttpContext.Request.Files);
YavscHelpers.Notify (ViewData, LocalizedText.Item_added_to_basket);
return View (collection);
} catch (Exception e) {
YavscHelpers.Notify(ViewData,"Exception:" + e.Message);
YavscHelpers.Notify (ViewData, "Exception:" + e.Message);
return View (collection);
}
}
@ -257,7 +263,7 @@ namespace Yavsc.Controllers
/// <summary>
/// Skills the specified model.
/// </summary>
[Authorize(Roles="Admin")]
[Authorize (Roles = "Admin")]
public ActionResult Skills (string search)
{
if (search == null)
@ -266,16 +272,28 @@ namespace Yavsc.Controllers
return View (skills);
}
/// <summary>
/// Performers on this MEA.
/// fr
/// Liste des prestataires dont
/// l'activité principale est celle spécifiée
/// </summary>
/// <param name="id">Identifiant APE de l'activité.</param>
public ActionResult Performers (string id)
{
throw new NotImplementedException ();
}
/// <summary>
/// Activities the specified search and toPower.
/// </summary>
/// <param name="search">Search.</param>
/// <param name="toPower">If set to <c>true</c> to power.</param>
public ActionResult Activities (string search, bool toPower = false)
public ActionResult Activities (string id, bool toPower = false)
{
if (search == null)
search = "%";
var activities = WorkFlowManager.FindActivity(search,!toPower);
if (id == null)
id = "%";
var activities = WorkFlowManager.FindActivity (id, !toPower);
return View (activities);
}
@ -283,21 +301,22 @@ namespace Yavsc.Controllers
/// Activity at the specified id.
/// </summary>
/// <param name="id">Identifier.</param>
public ActionResult Activity(string id)
public ActionResult Activity (string id)
{
return View(WorkFlowManager.GetActivity (id));
return View (WorkFlowManager.GetActivity (id));
}
/// <summary>
/// Display and should
/// offer Ajax edition of
/// user's skills.
/// </summary>
/// <param name="id">the User name.</param>
[Authorize()]
[Authorize ()]
public ActionResult UserSkills (string id)
{
if (id == null)
id = User.Identity.Name ;
if (id == null)
id = User.Identity.Name;
// TODO or not to do, handle a skills profile update,
// actually performed via the Web API :-°
// else if (ModelState.IsValid) {}
@ -308,15 +327,131 @@ namespace Yavsc.Controllers
}
/// <summary>
/// Booking the specified model.
/// Dates the query.
/// </summary>
/// <returns>The query.</returns>
/// <param name="model">Model.</param>
public ActionResult Booking (string id, SimpleBookingQuery model)
[Authorize,HttpPost]
public ActionResult Book (BookingQuery model)
{
if (model.Needs == null)
model.Needs = SkillManager.FindSkill ("%");
model.MAECode = id;
DateTime mindate = DateTime.Now;
if (model.StartDate.Date < mindate.Date) {
ModelState.AddModelError ("StartDate", LocalizedText.FillInAFutureDate);
}
if (model.EndDate < model.StartDate)
ModelState.AddModelError ("EndDate", LocalizedText.StartDateAfterEndDate);
if (ModelState.IsValid) {
var result = new List<PerformerProfile> ();
foreach (string meacode in model.MEACodes) {
foreach (PerformerProfile profile in WorkFlowManager.FindPerformer(meacode)) {
try {
var events = ProfileBase.Create (profile.UserName).GetEvents (model.StartDate, model.EndDate);
if (events.items.Length == 0)
result.Add (profile);
} catch (WebException ex) {
string response;
using (var stream = ex.Response.GetResponseStream ()) {
using (var reader = new StreamReader (stream)) {
response = reader.ReadToEnd ();
stream.Close ();
}
YavscHelpers.Notify (ViewData,
string.Format (
"Google calendar API exception {0} : {1}<br><pre>{2}</pre>",
ex.Status.ToString (),
ex.Message,
response));
}
}
}
}
return View ("Performers", result.ToArray ());
}
return View (model);
}
/// <summary>
/// Booking the specified model.
/// </summary>
/// <param name="MEACode">MEA Code.</param>
/// <param name="model">Model.</param>
public ActionResult Booking (SimpleBookingQuery model)
{
// In order to present this form
// with no need selected and without
// validation error display,
// we only check the need here, not at validation time.
// Although, the need is indeed cruxial requirement,
// but we already have got a MEA code
if (ModelState.IsValid)
if (model.Needs != null) {
var result = new List<PerformerAvailability> ();
foreach (PerformerProfile profile in WorkFlowManager.FindPerformer(model.MEACode)) {
if (profile.HasCalendar ()) {
try {
var events = ProfileBase.Create (profile.UserName)
.GetEvents (
model.PreferedDate.Date,
model.PreferedDate.AddDays (1).Date);
// TODO replace (events.items.Length == 0)
// with a descent computing of dates and times claims, calendar,
// AND performer preferences, perhaps also client preferences
result.Add (profile.CreateAvailability (model.PreferedDate, (events.items.Length == 0)));
} catch (WebException ex) {
HandleWebException (ex, "Google Calendar Api");
}
} else
result.Add (profile.CreateAvailability (model.PreferedDate, false));
}
return View ("Performers", result.ToArray ());
} else {
// A first Get
var needs = SkillManager.FindSkill ("%", model.MEACode);
ViewData ["Needs"] = needs;
model.Needs = needs.Select (
x => string.Format ("{0}:{1}", x.Id, x.Rate)).ToArray ();
}
var activity = WorkFlowManager.GetActivity (model.MEACode);
ViewData ["Activity"] = activity;
ViewData ["Title"] = activity.Title;
ViewData ["Comment"] = activity.Comment;
ViewData ["Photo"] = activity.Photo;
if (model.PreferedDate < DateTime.Now)
model.PreferedDate = DateTime.Now;
return View (model);
}
private void HandleWebException (WebException ex, string context)
{
string response = "";
using (var stream = ex.Response.GetResponseStream ()) {
if (stream.CanRead) {
var reader = new StreamReader (stream);
response = reader.ReadToEnd ();
reader.Close ();
reader.DiscardBufferedData ();
reader.Dispose ();
}
stream.Close ();
stream.Dispose ();
}
YavscHelpers.Notify (ViewData,
string.Format (
"{3} exception {0} : {1}<br><pre>{2}</pre>",
ex.Status.ToString (),
ex.Message,
response,
context
));
}
}
}

View file

@ -15,9 +15,12 @@ using Newtonsoft.Json;
using Yavsc.Model;
using Yavsc.Model.Google;
using Yavsc.Model.RolesAndMembers;
using Yavsc.Helpers.Google;
using Yavsc.Model.Calendar;
using Yavsc.Helpers;
using Yavsc.Model.WorkFlow;
using Yavsc.Model.FrontOffice;
using Yavsc.Model.Google.Api;
using Yavsc.Model.Skill;
namespace Yavsc.Controllers
{
@ -303,44 +306,10 @@ namespace Yavsc.Controllers
return View (model);
}
/// <summary>
/// Dates the query.
/// </summary>
/// <returns>The query.</returns>
/// <param name="model">Model.</param>
[Authorize,HttpPost]
public ActionResult Book (BookingQuery model)
public ActionResult Book (SimpleBookingQuery model)
{
DateTime mindate = DateTime.Now;
if (model.StartDate.Date < mindate.Date){
ModelState.AddModelError ("StartDate", LocalizedText.FillInAFutureDate);
}
if (model.EndDate < model.StartDate)
ModelState.AddModelError ("EndDate", LocalizedText.StartDateAfterEndDate);
if (ModelState.IsValid) {
foreach (string rolename in model.Roles) {
foreach (string username in Roles.GetUsersInRole(rolename)) {
try {
var pr = ProfileBase.Create(username);
var events = pr.GetEvents(model.StartDate,model.EndDate);
} catch (WebException ex) {
string response;
using (var stream = ex.Response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
response = reader.ReadToEnd();
}
YavscHelpers.Notify (ViewData,
string.Format(
"Google calendar API exception {0} : {1}<br><pre>{2}</pre>",
ex.Status.ToString(),
ex.Message,
response));
}
}
}
}
return View (model);
}
}

View file

@ -15,6 +15,8 @@ using Yavsc;
using System.Web.Mvc;
using Yavsc.Model.Blogs;
using Yavsc.Model.WorkFlow;
using Yavsc.WebControls;
using SalesCatalog.XmlImplementation;
namespace Yavsc.Controllers
{
@ -47,10 +49,13 @@ namespace Yavsc.Controllers
{
Assembly[] aslist = {
GetType ().Assembly,
typeof(BlogsController).Assembly,
typeof(ITCPNpgsqlProvider).Assembly,
typeof(NpgsqlMembershipProvider).Assembly,
typeof(NpgsqlContentProvider).Assembly,
typeof(NpgsqlBlogProvider).Assembly
typeof(NpgsqlBlogProvider).Assembly,
typeof(InputUserName).Assembly,
typeof(XmlCatalog).Assembly
};
List <AssemblyName> asnlist = new List<AssemblyName> ();