diff --git a/Makefile b/Makefile
index ca040be3..e07af982 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ VERSION=1.1
CONFIG=Debug
DESTDIR=build/web/$(CONFIG)
COPYUNCHANGED="false"
+PREPRODHOST=lua.pschneider.fr
all: deploy
@@ -14,7 +15,7 @@ deploy: ddir build
rm -rf $(DESTDIR)/obj
mv $(DESTDIR)/Web.config $(DESTDIR)/Web.config.new
-rsync: rsync-preprod rsync-local
+rsync: rsync-preprod
build:
xbuild /p:Configuration=$(CONFIG) /t:Build Yavsc.sln
@@ -24,7 +25,7 @@ clean:
rm -rf $(DESTDIR)
rsync-preprod: deploy
- rsync -ravu build/web/$(CONFIG)/ root@lua.localdomain:/srv/httpd/luapre
+ rsync -ravu build/web/$(CONFIG)/ root@$(PREPRODHOST):/srv/httpd/luapre
rsync-local:
rsync -ravu build/web/$(CONFIG)/ root@localhost:/srv/www/yavsc
diff --git a/web/Controllers/AccountController.cs b/web/Controllers/AccountController.cs
index 46618769..9a56544a 100644
--- a/web/Controllers/AccountController.cs
+++ b/web/Controllers/AccountController.cs
@@ -46,7 +46,7 @@ namespace Yavsc.Controllers
public static Profile GetProfile (string user)
{
- return new Profile (ProfileBase.Create (user));
+ return new Profile (ProfileBase.Create (user)) ;
}
@@ -216,8 +216,10 @@ namespace Yavsc.Controllers
[HttpGet]
public ActionResult Profile(Profile model)
{
- ViewData ["UserName"] = Membership.GetUser ().UserName;
- model = GetProfile ((string) ViewData ["UserName"]);
+ string username = Membership.GetUser ().UserName;
+ ViewData ["UserName"] = username;
+ model = GetProfile (username);
+ model.RememberMe = FormsAuthentication.GetAuthCookie ( username, true )==null;
return View (model);
}
@@ -280,9 +282,9 @@ namespace Yavsc.Controllers
HttpContext.Profile.SetPropertyValue (
"IBAN", model.IBAN);
HttpContext.Profile.Save ();
- ViewData ["Message"] = "Profile enregistré.";
-
- }
+ FormsAuthentication.SetAuthCookie (username, model.RememberMe);
+ ViewData ["Message"] = "Profile enregistré, cookie modifié.";
+ }
// HttpContext.Profile.SetPropertyValue("Avatar",Avatar);
return View (model);
}
diff --git a/web/Controllers/AdminController.cs b/web/Controllers/AdminController.cs
index 6833a59d..eff21665 100644
--- a/web/Controllers/AdminController.cs
+++ b/web/Controllers/AdminController.cs
@@ -19,10 +19,11 @@ namespace Yavsc.Controllers
///
public class AdminController : Controller
{
+
[Authorize(Roles="Admin")]
- public ActionResult Index(DataAccess model)
+ public ActionResult Index()
{
- return View (model);
+ return View ();
}
[Authorize(Roles="Admin")]
diff --git a/web/Controllers/BlogsController.cs b/web/Controllers/BlogsController.cs
index 4ae6969a..46ab5ab6 100644
--- a/web/Controllers/BlogsController.cs
+++ b/web/Controllers/BlogsController.cs
@@ -48,7 +48,9 @@ namespace Yavsc.Controllers
if (string.IsNullOrEmpty (user)) {
return BlogList (pageIndex, pageSize);
} else {
- MembershipUser u = Membership.GetUser (user, false);
+ MembershipUser u = null;
+ if (Membership.FindUsersByName (user) != null)
+ u= Membership.GetUser (user, false);
if (u == null) {
ModelState.AddModelError ("UserName",
string.Format ("Utilisateur inconu : {0}", user));
@@ -58,6 +60,8 @@ namespace Yavsc.Controllers
return UserPosts (user, pageIndex, pageSize);
return UserPost (user, title);
}
+
+
}
}
diff --git a/web/Controllers/FormInputValue.cs b/web/Controllers/FormInputValue.cs
deleted file mode 100644
index d3cb339a..00000000
--- a/web/Controllers/FormInputValue.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using Yavsc;
-using SalesCatalog;
-using SalesCatalog.Model;
-using System.Web.Routing;
-using System.Threading.Tasks;
-using System.Diagnostics;
-using System.Web.Http;
-using System.Net.Http;
-using System.Web;
-using System.Linq;
-using System.IO;
-using System.Net;
-using WorkFlowProvider;
-using System.Web.Security;
-using Yavsc.Model.WorkFlow;
-using System.Reflection;
-using System.Collections.Generic;
-using Yavsc.Model.RolesAndMembers;
-using Yavsc.Controllers;
-using Yavsc.Formatters;
-using System.Text;
-using System.Web.Profile;
-
-namespace Yavsc.ApiControllers
-{
-
- public class FormInputValue: IValueProvider
- {
- #region IValueProvider implementation
-
- public T GetValue ()
- {
- throw new NotImplementedException ();
- }
-
- #endregion
-
-
- }
-
-
-}
-
diff --git a/web/Controllers/FrontOfficeController.cs b/web/Controllers/FrontOfficeController.cs
index e366e11d..7a7e5e84 100644
--- a/web/Controllers/FrontOfficeController.cs
+++ b/web/Controllers/FrontOfficeController.cs
@@ -30,6 +30,11 @@ namespace Yavsc.Controllers
wfmgr = new WorkFlowManager ();
}
+ public ActionResult Index ()
+ {
+ return View ();
+ }
+
[Authorize]
public ActionResult Estimates ()
{
diff --git a/web/Controllers/GoogleController.cs b/web/Controllers/GoogleController.cs
index 94476329..01548060 100644
--- a/web/Controllers/GoogleController.cs
+++ b/web/Controllers/GoogleController.cs
@@ -22,79 +22,125 @@ namespace Yavsc.Controllers
public class GoogleController : Controller
{
-
+ // datetime format : yyyy-mm-ddTHH:MM:ss
+ // 2015-01-01T10:00:00-07:00
// private string API_KEY="AIzaSyBV_LQHb22nGgjNvFzZwnQHjao3Q7IewRw";
private string getPeopleUri = "https://www.googleapis.com/plus/v1/people";
+ private string getCalListUri = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
+ private string getCalEntriesUri = "https://developers.google.com/google-apps/calendar/v3/reference/events/list";
- private string CLIENT_ID="325408689282-6bekh7p3guj4k0f3301a6frf025cnrk1.apps.googleusercontent.com";
-
- private string CLIENT_SECRET="MaxYcvJJCs2gDGvaELZbzwfL";
+ private string CLIENT_ID = "325408689282-6bekh7p3guj4k0f3301a6frf025cnrk1.apps.googleusercontent.com";
+ private string CLIENT_SECRET = "MaxYcvJJCs2gDGvaELZbzwfL";
- string [] SCOPES = {
- "openid" ,
+ string[] SCOPES = {
+ "openid",
"profile",
"email"
- } ;
+ };
- string tokenUri = "https://accounts.google.com/o/oauth2/token";
- string authUri = "https://accounts.google.com/o/oauth2/auth";
+ string tokenUri = "https://accounts.google.com/o/oauth2/token";
+ string authUri = "https://accounts.google.com/o/oauth2/auth";
- public void Login(string returnUrl)
+ private string SetSessionSate ()
{
- if (string.IsNullOrWhiteSpace (returnUrl))
- returnUrl = "/";
Random rand = new Random ();
- string state = "security_token"+rand.Next (100000).ToString()+rand.Next (100000).ToString();
+ string state = "security_token" + rand.Next (100000).ToString () + rand.Next (100000).ToString ();
Session ["state"] = state;
+ return state;
+ }
+
+ public void Login (string returnUrl)
+ {
+ if (string.IsNullOrWhiteSpace (returnUrl))
+ returnUrl = "/";
Session ["returnUrl"] = returnUrl;
string redirectUri = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Auth";
+ string scope = string.Join ("%20", SCOPES);
- string prms = String.Format("response_type=code&client_id={0}&redirect_uri={1}&scope={2}&state={3}&access_type=offline&include_granted_scopes=false",
- CLIENT_ID, redirectUri, string.Join("%20",SCOPES), state);
-
- WebRequest wr = WebRequest.Create(authUri+"?"+prms);
- wr.Method = "GET";
- // Get the response.
+ string prms = String.Format ("response_type=code&client_id={0}&redirect_uri={1}&scope={2}&state={3}&include_granted_scopes=false",
+ CLIENT_ID, redirectUri, scope, SetSessionSate ());
- WebResponse response = wr.GetResponse();
- string resQuery = response.ResponseUri.Query;
- string cont = HttpUtility.ParseQueryString(resQuery)["continue"];
- Response.Redirect (cont);
+ GetAuthResponse (prms);
+ }
+ private void GetAuthResponse (string prms)
+ {
+ WebRequest wr = WebRequest.Create (authUri + "?" + prms);
+ wr.Method = "GET";
+ WebResponse response = wr.GetResponse ();
+ string resQuery = response.ResponseUri.Query;
+ string cont = HttpUtility.ParseQueryString (resQuery) ["continue"];
+ Response.Redirect (cont);
+ }
+ [Authorize]
+ public void GetCalAuth ()
+ {
+ string redirectUri = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/CalAuth";
+ string scope = string.Join ("%20", SCOPES);
+ scope += "%20https://www.googleapis.com/auth/calendar";
+ string prms = String.Format ("response_type=code&client_id={0}&redirect_uri={1}&scope={2}&state={3}&include_granted_scopes=false&access_type=offline",
+ CLIENT_ID, redirectUri, scope, SetSessionSate ());
+ Session ["calasked"] = true;
+ GetAuthResponse (prms);
}
[HttpGet]
- public ActionResult Auth()
+ [Authorize]
+ public ActionResult CalAuth ()
{
+ string redirectUri = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/CalAuth";
+ AuthToken gat = GetToken (TokenPostDataFromCode(redirectUri, GetCodeFromRequest()));
+ if (gat == null) {
+ return View ("Auth");
+ }
+ SaveToken (gat);
+ HttpContext.Profile.SetPropertyValue ("gcalapi", true);
+ string returnUrl = (string)Session ["returnUrl"];
+ Session ["returnUrl"]=null;
+ return Redirect (returnUrl);
+ }
- string returnUrl = (string) Session ["returnUrl"];
- string redirectUri = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Auth";
+ ///
+ /// Saves the token.
+ /// This calls the Profile.Save() method.
+ /// It should be called immediatly after getting the token from Google, in
+ /// order to save a descent value as expiration date.
+ ///
+ /// Gat.
+ private void SaveToken(AuthToken gat)
+ {
+ HttpContext.Profile.SetPropertyValue ("gtoken", gat.access_token);
+ if (gat.refresh_token!=null)
+ HttpContext.Profile.SetPropertyValue ("grefreshtoken", gat.refresh_token);
+ HttpContext.Profile.SetPropertyValue ("gtokentype", gat.token_type);
+ HttpContext.Profile.SetPropertyValue ("gtokenexpir", DateTime.Now.AddSeconds(gat.expires_in));
+ HttpContext.Profile.Save ();
+ }
+
+ private string GetCodeFromRequest()
+ {
string code = Request.Params ["code"];
string error = Request.Params ["error"];
if (error != null) {
ViewData ["Message"] =
- string.Format(LocalizedText.Google_error,
- LocalizedText.ResourceManager.GetString(error));
- return View();
+ string.Format (LocalizedText.Google_error,
+ LocalizedText.ResourceManager.GetString (error));
+ return null;
}
string state = Request.Params ["state"];
- if (state!=null && string.Compare((string)Session ["state"],state)!=0) {
+ if (state != null && string.Compare ((string)Session ["state"], state) != 0) {
ViewData ["Message"] =
- LocalizedText.ResourceManager.GetString("invalid request state");
- return View();
+ LocalizedText.ResourceManager.GetString ("invalid request state");
+ return null;
}
+ return code;
+ }
- string postdata =
- string.Format(
- "redirect_uri={0}&client_id={1}&client_secret={2}&code={3}&grant_type=authorization_code",
- HttpUtility.UrlEncode(redirectUri),
- HttpUtility.UrlEncode(CLIENT_ID),
- HttpUtility.UrlEncode(CLIENT_SECRET),
- HttpUtility.UrlEncode(code));
-
+ private AuthToken GetToken (string postdata)
+ {
Byte[] bytes = System.Text.Encoding.UTF8.GetBytes (postdata);
HttpWebRequest webreq = WebRequest.CreateHttp (tokenUri);
webreq.Method = "POST";
@@ -103,45 +149,71 @@ namespace Yavsc.Controllers
webreq.ContentLength = bytes.Length;
using (Stream dataStream = webreq.GetRequestStream ()) {
dataStream.Write (bytes, 0, bytes.Length);
- };
+ }
+ AuthToken gat =null;
using (WebResponse response = webreq.GetResponse ()) {
using (Stream responseStream = response.GetResponseStream ()) {
using (StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8)) {
string responseStr = readStream.ReadToEnd ();
- AuthToken gat = JsonConvert.DeserializeObject(responseStr);
- Session ["GoogleAuthToken"] = gat;
- SignIn regmod = new SignIn ();
- HttpWebRequest webreppro = WebRequest.CreateHttp (getPeopleUri+"/me");
- webreppro.ContentType = "application/http";
- webreppro.Headers.Add (HttpRequestHeader.Authorization, gat.token_type + " " + gat.access_token);
- webreppro.Method = "GET";
- using (WebResponse proresp = webreppro.GetResponse ()) {
- using (Stream prresponseStream = proresp.GetResponseStream ()) {
- using (StreamReader readproresp = new StreamReader (prresponseStream, Encoding.UTF8)) {
- string prresponseStr = readproresp.ReadToEnd ();
- People me = JsonConvert.DeserializeObject (prresponseStr);
- // TODO use me.id to retreive an existing user
- string accEmail = me.emails.Where (x => x.type == "account").First().value;
- MembershipUserCollection mbrs = Membership.FindUsersByEmail (accEmail);
- if (mbrs.Count == 1) {
- // TODO check the google id
- // just set this user as logged on
- FormsAuthentication.SetAuthCookie (me.displayName, true);
- Session ["returnUrl"] = null;
- return Redirect (returnUrl);
- }
- // else create the account
- regmod.Email = accEmail;
- regmod.UserName = me.displayName;
- Session ["me"] = me;
- return Auth(regmod);
- }
- }
- }
+ gat = JsonConvert.DeserializeObject (responseStr);
}
}
}
+ return gat;
+ }
+
+ private string TokenPostDataFromCode(string redirectUri, string code)
+ {
+ string postdata =
+ string.Format (
+ "redirect_uri={0}&client_id={1}&client_secret={2}&code={3}&grant_type=authorization_code",
+ HttpUtility.UrlEncode (redirectUri),
+ HttpUtility.UrlEncode (CLIENT_ID),
+ HttpUtility.UrlEncode (CLIENT_SECRET),
+ HttpUtility.UrlEncode (code));
+ return postdata;
+ }
+
+ [HttpGet]
+ public ActionResult Auth ()
+ {
+ string redirectUri = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Auth";
+ AuthToken gat = GetToken (TokenPostDataFromCode( redirectUri, GetCodeFromRequest()));
+ if (gat == null) {
+ return View ();
+ }
+ string returnUrl = (string)Session ["returnUrl"];
+
+ SignIn regmod = new SignIn ();
+ HttpWebRequest webreppro = WebRequest.CreateHttp (getPeopleUri + "/me");
+ webreppro.ContentType = "application/http";
+ webreppro.Headers.Add (HttpRequestHeader.Authorization, gat.token_type + " " + gat.access_token);
+ webreppro.Method = "GET";
+ using (WebResponse proresp = webreppro.GetResponse ()) {
+ using (Stream prresponseStream = proresp.GetResponseStream ()) {
+ using (StreamReader readproresp = new StreamReader (prresponseStream, Encoding.UTF8)) {
+ string prresponseStr = readproresp.ReadToEnd ();
+ People me = JsonConvert.DeserializeObject (prresponseStr);
+ // TODO use me.id to retreive an existing user
+ string accEmail = me.emails.Where (x => x.type == "account").First ().value;
+ MembershipUserCollection mbrs = Membership.FindUsersByEmail (accEmail);
+ if (mbrs.Count == 1) {
+ // TODO check the google id
+ // just set this user as logged on
+ FormsAuthentication.SetAuthCookie (me.displayName, true);
+ Session ["returnUrl"] = null;
+ return Redirect (returnUrl);
+ }
+ // else create the account
+ regmod.Email = accEmail;
+ regmod.UserName = me.displayName;
+ Session ["me"] = me;
+ Session ["GoogleAuthToken"] = gat;
+ return Auth (regmod);
+ }
+ }
+ }
}
///
@@ -149,7 +221,7 @@ namespace Yavsc.Controllers
///
/// Regmod.
[HttpPost]
- public ActionResult Auth(SignIn regmod)
+ public ActionResult Auth (SignIn regmod)
{
if (ModelState.IsValid) {
if (Membership.GetUser (regmod.UserName) != null) {
@@ -188,7 +260,6 @@ namespace Yavsc.Controllers
FormsAuthentication.SetAuthCookie (regmod.UserName, true);
HttpContext.Profile.Initialize (regmod.UserName, true);
- HttpContext.Profile.SetPropertyValue ("gtoken", gat.access_token);
HttpContext.Profile.SetPropertyValue ("Name", me.displayName);
// TODO use image
if (me.image != null) {
@@ -197,11 +268,12 @@ namespace Yavsc.Controllers
if (me.placesLived != null) {
People.Place pplace = me.placesLived.Where (x => x.primary).First ();
if (pplace != null)
- HttpContext.Profile.SetPropertyValue ("Address", pplace.value);
+ HttpContext.Profile.SetPropertyValue ("CityAndState", pplace.value);
}
if (me.url != null)
HttpContext.Profile.SetPropertyValue ("WebSite", me.url);
- HttpContext.Profile.Save ();
+ SaveToken (gat);
+ // already done in SaveToken: HttpContext.Profile.Save ();
return Redirect (returnUrl);
}
ViewData ["returnUrl"] = returnUrl;
@@ -209,10 +281,111 @@ namespace Yavsc.Controllers
return View (regmod);
}
- public void ChooseCalendar()
+ private string GetFreshGoogleCredential (ProfileBase pr)
{
- throw new NotImplementedException();
+ string token = (string) pr.GetPropertyValue ("gtoken");
+ string token_type = (string) pr.GetPropertyValue ("gtokentype");
+ DateTime token_exp = (DateTime) pr.GetPropertyValue ("gtokenexpir");
+ if (token_exp < DateTime.Now) {
+ string refresh_token = (string) pr.GetPropertyValue ("grefreshtoken");
+ AuthToken gat = GetToken(
+ string.Format("grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}",
+ CLIENT_ID, CLIENT_SECRET, refresh_token));
+ token = gat.access_token;
+ pr.SetPropertyValue ("gtoken", token);
+ pr.Save ();
+ // assert gat.token_type == token_type
+ }
+ return token_type + " " + token;
}
- }
-}
+ [Authorize]
+ [HttpGet]
+ public ActionResult ChooseCalendar (string returnUrl)
+ {
+ Session ["ChooseCalReturnUrl"] = returnUrl;
+ bool hasCalAuth = (bool)HttpContext.Profile.GetPropertyValue ("gcalapi");
+ if (!hasCalAuth) {
+ Session["returnUrl"] = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/ChooseCalendar";
+ return RedirectToAction ("GetCalAuth");
+ }
+
+ string cred = GetFreshGoogleCredential (HttpContext.Profile);
+
+ HttpWebRequest webreq = WebRequest.CreateHttp (getCalListUri);
+ webreq.Headers.Add (HttpRequestHeader.Authorization, cred);
+ webreq.Method = "GET";
+ webreq.ContentType = "application/http";
+ using (WebResponse resp = webreq.GetResponse ()) {
+ using (Stream respstream = resp.GetResponseStream ()) {
+ using (StreamReader readresp = new StreamReader (respstream, Encoding.UTF8)) {
+ string responseStr = readresp.ReadToEnd ();
+ CalendarList res = JsonConvert.DeserializeObject (responseStr);
+ ViewData ["json"] = responseStr;
+ return View (res);
+ }
+ }
+ }
+ }
+
+ [HttpPost]
+ [Authorize]
+ public ActionResult SetCalendar (string calchoice)
+ {
+ HttpContext.Profile.SetPropertyValue ("gcalid", calchoice);
+ HttpContext.Profile.Save ();
+
+ string returnUrl = (string) Session ["ChooseCalReturnUrl"];
+ if (returnUrl != null) {
+ Session ["ChooseCalReturnUrl"] = null;
+ return Redirect (returnUrl);
+ }
+ return Redirect ("/");
+ }
+
+ [Authorize]
+ [HttpGet]
+ public ActionResult DateQuery()
+ {
+ return View (new AskForADate ());
+ }
+
+ [Authorize]
+ [HttpPost]
+ public ActionResult DateQuery(AskForADate model)
+ {
+ if (ModelState.IsValid) {
+ if (model.MinDate < DateTime.Now) {
+ ModelState.AddModelError ("MinTime", "This first date must be in the future.");
+ return View (model);
+ }
+ if (model.MinDate > model.MaxDate) {
+ ModelState.AddModelError ("MinTime", "This first date must be lower than the second one.");
+ return View (model);
+ }
+ ProfileBase upr = ProfileBase.Create (model.UserName);
+ if (upr == null) {
+ ModelState.AddModelError ("UserName", "Non existent user");
+ return View (model);
+ }
+
+
+ HttpWebRequest webreq = WebRequest.CreateHttp (getCalEntriesUri);
+ webreq.Headers.Add (HttpRequestHeader.Authorization, GetFreshGoogleCredential(upr));
+ webreq.Method = "GET";
+ webreq.ContentType = "application/http";
+ using (WebResponse resp = webreq.GetResponse ()) {
+ using (Stream respstream = resp.GetResponseStream ()) {
+ using (StreamReader readresp = new StreamReader (respstream, Encoding.UTF8)) {
+ string responseStr = readresp.ReadToEnd ();
+ CalendarList res = JsonConvert.DeserializeObject (responseStr);
+ ViewData ["json"] = responseStr;
+ return View (res);
+ }
+ }
+ }
+ }
+ return View (model);
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/Controllers/IOrderInfo.cs b/web/Controllers/IOrderInfo.cs
index c7cd3673..9af566d6 100644
--- a/web/Controllers/IOrderInfo.cs
+++ b/web/Controllers/IOrderInfo.cs
@@ -30,7 +30,7 @@ namespace Yavsc.ApiControllers
DateTime Creation { get; set; }
string Status { get; set; }
long OrderId { get; set; }
- FormInputValue [] Details { get; set; }
+ Object [] Details { get; set; }
}
}
diff --git a/web/Global.asax.cs b/web/Global.asax.cs
index bacbe529..32f7e0d4 100644
--- a/web/Global.asax.cs
+++ b/web/Global.asax.cs
@@ -25,19 +25,28 @@ namespace Yavsc
"Blog",
"Blog/{user}/{title}",
new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional }
- );
+ ); /*
routes.MapRoute (
"Blogs",
"Blogs/{action}/{user}/{title}",
new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional}
- );
+ );*/ /*
+ routes.MapRoute (
+ "Home",
+ "Home/Index",
+ new { controller = "Blogs", action = "Index", user="paul", title = "Documentation" }
+ );*/
+ /*routes.MapRoute (
+ "Default",
+ "{controller}/{action}/{id}",
+ new { controller = "Home", action = "Index", id = UrlParameter.Optional }
+ );*/
routes.MapRoute (
"Default",
- "{controller}/{action}/{user}",
- new { controller = "Home", action = "Index", user="" }
+ "{controller}/{action}/{user}/{title}",
+ new { controller = "Blogs", action = "Index", user="paul", title = "Documentation"}
);
-
}
protected void Application_Start ()
diff --git a/web/Helpers/T.cs b/web/Helpers/T.cs
index 70fac62c..645c558c 100644
--- a/web/Helpers/T.cs
+++ b/web/Helpers/T.cs
@@ -8,14 +8,16 @@ using System.Web.Mvc.Ajax;
using System.Net.Mail;
using Yavsc;
using System.Globalization;
+using Yavsc.Model;
-namespace Yavsc
+namespace Yavsc.Helpers
{
public class T
{
- public static string GetString(string msgid)
+ public static string GetString(string msg)
{
- return Mono.Unix.Catalog.GetString (msgid);
+ string tr = LocalizedText.ResourceManager.GetString (msg.Replace (" ", "_"));
+ return tr==null?msg:tr;
}
}
}
diff --git a/web/Models/App.master b/web/Models/App.master
index 0b23262f..e766a075 100644
--- a/web/Models/App.master
+++ b/web/Models/App.master
@@ -2,8 +2,9 @@
- <% Page.Title = Page.Title + " - " + YavscHelpers.SiteName; %>
+ <% ViewState["orgtitle"] = T.GetString(Page.Title); %>
+ <% Page.Title = ViewState["orgtitle"] + " - " + YavscHelpers.SiteName; %>
@@ -16,7 +17,9 @@
<% if (ViewData["Error"]!=null) { %>
@@ -29,32 +32,36 @@
<%= Html.Encode(ViewData["Message"]) %>
<% } %>
+
+
+
+
<% if (Membership.GetUser()==null) { %>
- <%= Html.ActionLink( YavscHelpers.SiteName, "Index", "Home" ,null, new { @class="actionlink" } ) %>
+ <%= Html.ActionLink( YavscHelpers.SiteName, "Index", "Home" ,null, new { @class="actionlink" } ) %>
Page d'accueil
- <%= Html.ActionLink("Login", "Login", "Account", new { returnUrl=Request.Url.PathAndQuery }, new { @class="actionlink" } ) %>
+ <%= Html.ActionLink("Login", "Login", "Account", new { returnUrl=Request.Url.PathAndQuery }, new { @class="actionlink" } ) %>
Pour pouvoir poster ou commenter
?returnUrl=<%=ViewData["returnUrl"]%>" class="actionlink">
-
+
S'authentifier avec son compte Google+
<% } else { %>
- <%= Html.ActionLink(HttpContext.Current.User.Identity.Name, "Profile", "Account", null, new { @class="actionlink" }) %>
+ <%= Html.ActionLink(HttpContext.Current.User.Identity.Name, "Profile", "Account", null, new { @class="actionlink" }) %>
Édition de votre profile
- @ <%= Html.ActionLink( YavscHelpers.SiteName, "Index", "Home" ,null, new { @class="actionlink" }) %>
+ @ <%= Html.ActionLink( YavscHelpers.SiteName, "Index", "Home" ,null, new { @class="actionlink" }) %>
Page d'accueil
-
Poster
+
Poster
Édition d'un nouveau billet
- <%= Html.ActionLink( "Deconnexion", "Logout", "Account", new { returnUrl=Request.Url.PathAndQuery }, new { @class="actionlink" }) %>
+ <%= Html.ActionLink( "Deconnexion", "Logout", "Account", new { returnUrl=Request.Url.PathAndQuery }, new { @class="actionlink" }) %>
<% } %>
diff --git a/web/Scripts/GruntFile.js b/web/Scripts/GruntFile.js
new file mode 100644
index 00000000..ca3e653b
--- /dev/null
+++ b/web/Scripts/GruntFile.js
@@ -0,0 +1,29 @@
+module.exports = function(grunt) {
+
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+ meta: {
+ banner : '/*!\n' +
+ ' * <%= pkg.title %> v<%= pkg.version %> - <%= pkg.description %>\n' +
+ ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> - <%= pkg.homepage %>\n' +
+ ' * License: <%= pkg.license %>\n' +
+ ' */\n\n'
+ },
+ uglify: {
+ options : {
+ banner : '<%= meta.banner %>',
+ report: 'gzip'
+ },
+ dist: {
+ files: {
+ 'jquery.timepicker.min.js': ['jquery.timepicker.js']
+ }
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+
+ grunt.registerTask('default', ['uglify']);
+
+};
diff --git a/web/Scripts/jquery.mousewheel.js b/web/Scripts/jquery.mousewheel.js
new file mode 100755
index 00000000..6756fa61
--- /dev/null
+++ b/web/Scripts/jquery.mousewheel.js
@@ -0,0 +1,221 @@
+/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Version: 3.1.12
+ *
+ * Requires: jQuery 1.2.2+
+ */
+
+(function (factory) {
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS style for Browserify
+ module.exports = factory;
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function ($) {
+
+ var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
+ toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
+ ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
+ slice = Array.prototype.slice,
+ nullLowestDeltaTimeout, lowestDelta;
+
+ if ( $.event.fixHooks ) {
+ for ( var i = toFix.length; i; ) {
+ $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
+ }
+ }
+
+ var special = $.event.special.mousewheel = {
+ version: '3.1.12',
+
+ setup: function() {
+ if ( this.addEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.addEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = handler;
+ }
+ // Store the line height and page height for this particular element
+ $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
+ $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
+ },
+
+ teardown: function() {
+ if ( this.removeEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.removeEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = null;
+ }
+ // Clean up the data we added to the element
+ $.removeData(this, 'mousewheel-line-height');
+ $.removeData(this, 'mousewheel-page-height');
+ },
+
+ getLineHeight: function(elem) {
+ var $elem = $(elem),
+ $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
+ if (!$parent.length) {
+ $parent = $('body');
+ }
+ return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
+ },
+
+ getPageHeight: function(elem) {
+ return $(elem).height();
+ },
+
+ settings: {
+ adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
+ normalizeOffset: true // calls getBoundingClientRect for each event
+ }
+ };
+
+ $.fn.extend({
+ mousewheel: function(fn) {
+ return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
+ },
+
+ unmousewheel: function(fn) {
+ return this.unbind('mousewheel', fn);
+ }
+ });
+
+
+ function handler(event) {
+ var orgEvent = event || window.event,
+ args = slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ offsetX = 0,
+ offsetY = 0;
+ event = $.event.fix(orgEvent);
+ event.type = 'mousewheel';
+
+ // Old school scrollwheel delta
+ if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
+ if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
+ if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
+
+ // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
+ if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
+ deltaX = deltaY * -1;
+ deltaY = 0;
+ }
+
+ // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
+ delta = deltaY === 0 ? deltaX : deltaY;
+
+ // New school wheel delta (wheel event)
+ if ( 'deltaY' in orgEvent ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( 'deltaX' in orgEvent ) {
+ deltaX = orgEvent.deltaX;
+ if ( deltaY === 0 ) { delta = deltaX * -1; }
+ }
+
+ // No change actually happened, no reason to go any further
+ if ( deltaY === 0 && deltaX === 0 ) { return; }
+
+ // Need to convert lines and pages to pixels if we aren't already in pixels
+ // There are three delta modes:
+ // * deltaMode 0 is by pixels, nothing to do
+ // * deltaMode 1 is by lines
+ // * deltaMode 2 is by pages
+ if ( orgEvent.deltaMode === 1 ) {
+ var lineHeight = $.data(this, 'mousewheel-line-height');
+ delta *= lineHeight;
+ deltaY *= lineHeight;
+ deltaX *= lineHeight;
+ } else if ( orgEvent.deltaMode === 2 ) {
+ var pageHeight = $.data(this, 'mousewheel-page-height');
+ delta *= pageHeight;
+ deltaY *= pageHeight;
+ deltaX *= pageHeight;
+ }
+
+ // Store lowest absolute delta to normalize the delta values
+ absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
+
+ if ( !lowestDelta || absDelta < lowestDelta ) {
+ lowestDelta = absDelta;
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
+ lowestDelta /= 40;
+ }
+ }
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
+ // Divide all the things by 40!
+ delta /= 40;
+ deltaX /= 40;
+ deltaY /= 40;
+ }
+
+ // Get a whole, normalized value for the deltas
+ delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
+ deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
+ deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
+
+ // Normalise offsetX and offsetY properties
+ if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
+ var boundingRect = this.getBoundingClientRect();
+ offsetX = event.clientX - boundingRect.left;
+ offsetY = event.clientY - boundingRect.top;
+ }
+
+ // Add information to the event object
+ event.deltaX = deltaX;
+ event.deltaY = deltaY;
+ event.deltaFactor = lowestDelta;
+ event.offsetX = offsetX;
+ event.offsetY = offsetY;
+ // Go ahead and set deltaMode to 0 since we converted to pixels
+ // Although this is a little odd since we overwrite the deltaX/Y
+ // properties with normalized deltas.
+ event.deltaMode = 0;
+
+ // Add event and delta to the front of the arguments
+ args.unshift(event, delta, deltaX, deltaY);
+
+ // Clearout lowestDelta after sometime to better
+ // handle multiple device types that give different
+ // a different lowestDelta
+ // Ex: trackpad = 3 and mouse wheel = 120
+ if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
+ nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
+
+ return ($.event.dispatch || $.event.handle).apply(this, args);
+ }
+
+ function nullLowestDelta() {
+ lowestDelta = null;
+ }
+
+ function shouldAdjustOldDeltas(orgEvent, absDelta) {
+ // If this is an older event and the delta is divisable by 120,
+ // then we are assuming that the browser is treating this as an
+ // older mouse wheel event and that we should divide the deltas
+ // by 40 to try and get a more usable deltaFactor.
+ // Side note, this actually impacts the reported scroll distance
+ // in older browsers and can cause scrolling to be slower than native.
+ // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
+ return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
+ }
+
+}));
diff --git a/web/Scripts/jquery.timepicker.js b/web/Scripts/jquery.timepicker.js
new file mode 100644
index 00000000..8f4a900f
--- /dev/null
+++ b/web/Scripts/jquery.timepicker.js
@@ -0,0 +1,1151 @@
+/************************
+jquery-timepicker v1.4.13
+http://jonthornton.github.com/jquery-timepicker/
+
+requires jQuery 1.7+
+************************/
+
+
+(function (factory) {
+ if (typeof exports === "object" && exports &&
+ typeof module === "object" && module && module.exports === exports) {
+ // Browserify. Attach to jQuery module.
+ factory(require("jquery"));
+ } else if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function ($) {
+ var _baseDate = _generateBaseDate();
+ var _ONE_DAY = 86400;
+ var _lang = {
+ am: 'am',
+ pm: 'pm',
+ AM: 'AM',
+ PM: 'PM',
+ decimal: '.',
+ mins: 'mins',
+ hr: 'hr',
+ hrs: 'hrs'
+ };
+
+ var methods =
+ {
+ init: function(options)
+ {
+ return this.each(function()
+ {
+ var self = $(this);
+
+ // pick up settings from data attributes
+ var attributeOptions = [];
+ for (var key in $.fn.timepicker.defaults) {
+ if (self.data(key)) {
+ attributeOptions[key] = self.data(key);
+ }
+ }
+
+ var settings = $.extend({}, $.fn.timepicker.defaults, attributeOptions, options);
+
+ if (settings.lang) {
+ _lang = $.extend(_lang, settings.lang);
+ }
+
+ settings = _parseSettings(settings);
+ self.data('timepicker-settings', settings);
+ self.addClass('ui-timepicker-input');
+
+ if (settings.useSelect) {
+ _render(self);
+ } else {
+ self.prop('autocomplete', 'off');
+ self.on('click.timepicker focus.timepicker', methods.show);
+ self.on('change.timepicker', _formatValue);
+ self.on('keydown.timepicker', _keydownhandler);
+ self.on('keyup.timepicker', _keyuphandler);
+
+ _formatValue.call(self.get(0));
+ }
+ });
+ },
+
+ show: function(e)
+ {
+ var self = $(this);
+ var settings = self.data('timepicker-settings');
+
+ if (e) {
+ if (!settings.showOnFocus) {
+ return true;
+ }
+
+ e.preventDefault();
+ }
+
+ if (settings.useSelect) {
+ self.data('timepicker-list').focus();
+ return;
+ }
+
+ if (_hideKeyboard(self)) {
+ // block the keyboard on mobile devices
+ self.blur();
+ }
+
+ var list = self.data('timepicker-list');
+
+ // check if input is readonly
+ if (self.prop('readonly')) {
+ return;
+ }
+
+ // check if list needs to be rendered
+ if (!list || list.length === 0 || typeof settings.durationTime === 'function') {
+ _render(self);
+ list = self.data('timepicker-list');
+ }
+
+ if (_isVisible(list)) {
+ return;
+ }
+
+ // make sure other pickers are hidden
+ methods.hide();
+
+ // position the dropdown relative to the input
+ list.show();
+ var listOffset = {};
+
+ if (settings.orientation == 'rtl') {
+ // right-align the dropdown
+ listOffset.left = self.offset().left + self.outerWidth() - list.outerWidth() + parseInt(list.css('marginLeft').replace('px', ''), 10);
+ } else {
+ // left-align the dropdown
+ listOffset.left = self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10);
+ }
+
+ if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) {
+ // position the dropdown on top
+ list.addClass('ui-timepicker-positioned-top');
+ listOffset.top = self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10);
+ } else {
+ // put it under the input
+ list.removeClass('ui-timepicker-positioned-top');
+ listOffset.top = self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10);
+ }
+
+ list.offset(listOffset);
+
+ // position scrolling
+ var selected = list.find('.ui-timepicker-selected');
+
+ if (!selected.length) {
+ if (_getTimeValue(self)) {
+ selected = _findRow(self, list, _time2int(_getTimeValue(self)));
+ } else if (settings.scrollDefault) {
+ selected = _findRow(self, list, settings.scrollDefault);
+ }
+ }
+
+ if (selected && selected.length) {
+ var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight();
+ list.scrollTop(topOffset);
+ } else {
+ list.scrollTop(0);
+ }
+
+ // attach close handlers
+ $(document).on('touchstart.ui-timepicker mousedown.ui-timepicker', _closeHandler);
+ if (settings.closeOnWindowScroll) {
+ $(document).on('scroll.ui-timepicker', _closeHandler);
+ }
+
+ self.trigger('showTimepicker');
+
+ return this;
+ },
+
+ hide: function(e)
+ {
+ var self = $(this);
+ var settings = self.data('timepicker-settings');
+
+ if (settings && settings.useSelect) {
+ self.blur();
+ }
+
+ $('.ui-timepicker-wrapper').each(function() {
+ var list = $(this);
+ if (!_isVisible(list)) {
+ return;
+ }
+
+ var self = list.data('timepicker-input');
+ var settings = self.data('timepicker-settings');
+
+ if (settings && settings.selectOnBlur) {
+ _selectValue(self);
+ }
+
+ list.hide();
+ self.trigger('hideTimepicker');
+ });
+
+ return this;
+ },
+
+ option: function(key, value)
+ {
+ return this.each(function(){
+ var self = $(this);
+ var settings = self.data('timepicker-settings');
+ var list = self.data('timepicker-list');
+
+ if (typeof key == 'object') {
+ settings = $.extend(settings, key);
+
+ } else if (typeof key == 'string' && typeof value != 'undefined') {
+ settings[key] = value;
+
+ } else if (typeof key == 'string') {
+ return settings[key];
+ }
+
+ settings = _parseSettings(settings);
+
+ self.data('timepicker-settings', settings);
+
+ if (list) {
+ list.remove();
+ self.data('timepicker-list', false);
+ }
+
+ if (settings.useSelect) {
+ _render(self);
+ }
+ });
+ },
+
+ getSecondsFromMidnight: function()
+ {
+ return _time2int(_getTimeValue(this));
+ },
+
+ getTime: function(relative_date)
+ {
+ var self = this;
+
+ var time_string = _getTimeValue(self);
+ if (!time_string) {
+ return null;
+ }
+
+ if (!relative_date) {
+ relative_date = new Date();
+ }
+ var offset = _time2int(time_string);
+
+ // construct a Date with today's date, and offset's time
+ var time = new Date(relative_date);
+ time.setHours(offset / 3600);
+ time.setMinutes(offset % 3600 / 60);
+ time.setSeconds(offset % 60);
+ time.setMilliseconds(0);
+
+ return time;
+ },
+
+ setTime: function(value)
+ {
+ var self = this;
+ var settings = self.data('timepicker-settings');
+
+ if (settings.forceRoundTime) {
+ var prettyTime = _roundAndFormatTime(value, settings)
+ } else {
+ var prettyTime = _int2time(_time2int(value), settings.timeFormat);
+ }
+
+ _setTimeValue(self, prettyTime);
+ if (self.data('timepicker-list')) {
+ _setSelected(self, self.data('timepicker-list'));
+ }
+
+ return this;
+ },
+
+ remove: function()
+ {
+ var self = this;
+
+ // check if this element is a timepicker
+ if (!self.hasClass('ui-timepicker-input')) {
+ return;
+ }
+
+ var settings = self.data('timepicker-settings');
+ self.removeAttr('autocomplete', 'off');
+ self.removeClass('ui-timepicker-input');
+ self.removeData('timepicker-settings');
+ self.off('.timepicker');
+
+ // timepicker-list won't be present unless the user has interacted with this timepicker
+ if (self.data('timepicker-list')) {
+ self.data('timepicker-list').remove();
+ }
+
+ if (settings.useSelect) {
+ self.show();
+ }
+
+ self.removeData('timepicker-list');
+
+ return this;
+ }
+ };
+
+ // private methods
+
+ function _isVisible(elem)
+ {
+ var el = elem[0];
+ return el.offsetWidth > 0 && el.offsetHeight > 0;
+ }
+
+ function _parseSettings(settings)
+ {
+ if (settings.minTime) {
+ settings.minTime = _time2int(settings.minTime);
+ }
+
+ if (settings.maxTime) {
+ settings.maxTime = _time2int(settings.maxTime);
+ }
+
+ if (settings.durationTime && typeof settings.durationTime !== 'function') {
+ settings.durationTime = _time2int(settings.durationTime);
+ }
+
+ if (settings.scrollDefault == 'now') {
+ settings.scrollDefault = _time2int(new Date());
+ } else if (settings.scrollDefault) {
+ settings.scrollDefault = _time2int(settings.scrollDefault);
+ } else if (settings.minTime) {
+ settings.scrollDefault = settings.minTime;
+ }
+
+ if (settings.scrollDefault) {
+ settings.scrollDefault = _roundTime(settings.scrollDefault, settings);
+ }
+
+ if ($.type(settings.timeFormat) === "string" && settings.timeFormat.match(/[gh]/)) {
+ settings._twelveHourTime = true;
+ }
+
+ if (settings.disableTimeRanges.length > 0) {
+ // convert string times to integers
+ for (var i in settings.disableTimeRanges) {
+ settings.disableTimeRanges[i] = [
+ _time2int(settings.disableTimeRanges[i][0]),
+ _time2int(settings.disableTimeRanges[i][1])
+ ];
+ }
+
+ // sort by starting time
+ settings.disableTimeRanges = settings.disableTimeRanges.sort(function(a, b){
+ return a[0] - b[0];
+ });
+
+ // merge any overlapping ranges
+ for (var i = settings.disableTimeRanges.length-1; i > 0; i--) {
+ if (settings.disableTimeRanges[i][0] <= settings.disableTimeRanges[i-1][1]) {
+ settings.disableTimeRanges[i-1] = [
+ Math.min(settings.disableTimeRanges[i][0], settings.disableTimeRanges[i-1][0]),
+ Math.max(settings.disableTimeRanges[i][1], settings.disableTimeRanges[i-1][1])
+ ];
+ settings.disableTimeRanges.splice(i, 1);
+ }
+ }
+ }
+
+ return settings;
+ }
+
+ function _render(self)
+ {
+ var settings = self.data('timepicker-settings');
+ var list = self.data('timepicker-list');
+
+ if (list && list.length) {
+ list.remove();
+ self.data('timepicker-list', false);
+ }
+
+ if (settings.useSelect) {
+ list = $(' ', { 'class': 'ui-timepicker-select' });
+ var wrapped_list = list;
+ } else {
+ list = $('', { 'class': 'ui-timepicker-list' });
+
+ var wrapped_list = $('
', { 'class': 'ui-timepicker-wrapper', 'tabindex': -1 });
+ wrapped_list.css({'display':'none', 'position': 'absolute' }).append(list);
+ }
+
+ if (settings.noneOption) {
+ if (settings.noneOption === true) {
+ settings.noneOption = (settings.useSelect) ? 'Time...' : 'None';
+ }
+
+ if ($.isArray(settings.noneOption)) {
+ for (var i in settings.noneOption) {
+ if (parseInt(i, 10) == i){
+ var noneElement = _generateNoneElement(settings.noneOption[i], settings.useSelect);
+ list.append(noneElement);
+ }
+ }
+ } else {
+ var noneElement = _generateNoneElement(settings.noneOption, settings.useSelect);
+ list.append(noneElement);
+ }
+ }
+
+ if (settings.className) {
+ wrapped_list.addClass(settings.className);
+ }
+
+ if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
+ wrapped_list.addClass('ui-timepicker-with-duration');
+ wrapped_list.addClass('ui-timepicker-step-'+settings.step);
+ }
+
+ var durStart = settings.minTime;
+ if (typeof settings.durationTime === 'function') {
+ durStart = _time2int(settings.durationTime());
+ } else if (settings.durationTime !== null) {
+ durStart = settings.durationTime;
+ }
+ var start = (settings.minTime !== null) ? settings.minTime : 0;
+ var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1);
+
+ if (end <= start) {
+ // make sure the end time is greater than start time, otherwise there will be no list to show
+ end += _ONE_DAY;
+ }
+
+ if (end === _ONE_DAY-1 && $.type(settings.timeFormat) === "string" && settings.timeFormat.indexOf('H') !== -1) {
+ // show a 24:00 option when using military time
+ end = _ONE_DAY;
+ }
+
+ var dr = settings.disableTimeRanges;
+ var drCur = 0;
+ var drLen = dr.length;
+
+ for (var i=start; i <= end; i += settings.step*60) {
+ var timeInt = i;
+ var timeString = _int2time(timeInt, settings.timeFormat);
+
+ if (settings.useSelect) {
+ var row = $(' ', { 'value': timeString });
+ row.text(timeString);
+ } else {
+ var row = $(' ');
+ row.data('time', (timeInt <= 86400 ? timeInt : timeInt % 86400));
+ row.text(timeString);
+ }
+
+ if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
+ var durationString = _int2duration(i - durStart, settings.step);
+ if (settings.useSelect) {
+ row.text(row.text()+' ('+durationString+')');
+ } else {
+ var duration = $(' ', { 'class': 'ui-timepicker-duration' });
+ duration.text(' ('+durationString+')');
+ row.append(duration);
+ }
+ }
+
+ if (drCur < drLen) {
+ if (timeInt >= dr[drCur][1]) {
+ drCur += 1;
+ }
+
+ if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
+ if (settings.useSelect) {
+ row.prop('disabled', true);
+ } else {
+ row.addClass('ui-timepicker-disabled');
+ }
+ }
+ }
+
+ list.append(row);
+ }
+
+ wrapped_list.data('timepicker-input', self);
+ self.data('timepicker-list', wrapped_list);
+
+ if (settings.useSelect) {
+ if (self.val()) {
+ list.val(_roundAndFormatTime(self.val(), settings));
+ }
+
+ list.on('focus', function(){
+ $(this).data('timepicker-input').trigger('showTimepicker');
+ });
+ list.on('blur', function(){
+ $(this).data('timepicker-input').trigger('hideTimepicker');
+ });
+ list.on('change', function(){
+ _setTimeValue(self, $(this).val(), 'select');
+ });
+
+ _setTimeValue(self, list.val());
+ self.hide().after(list);
+ } else {
+ var appendTo = settings.appendTo;
+ if (typeof appendTo === 'string') {
+ appendTo = $(appendTo);
+ } else if (typeof appendTo === 'function') {
+ appendTo = appendTo(self);
+ }
+ appendTo.append(wrapped_list);
+ _setSelected(self, list);
+
+ list.on('mousedown', 'li', function(e) {
+
+ // hack: temporarily disable the focus handler
+ // to deal with the fact that IE fires 'focus'
+ // events asynchronously
+ self.off('focus.timepicker');
+ self.on('focus.timepicker-ie-hack', function(){
+ self.off('focus.timepicker-ie-hack');
+ self.on('focus.timepicker', methods.show);
+ });
+
+ if (!_hideKeyboard(self)) {
+ self[0].focus();
+ }
+
+ // make sure only the clicked row is selected
+ list.find('li').removeClass('ui-timepicker-selected');
+ $(this).addClass('ui-timepicker-selected');
+
+ if (_selectValue(self)) {
+ self.trigger('hideTimepicker');
+ wrapped_list.hide();
+ }
+ });
+ }
+ }
+
+ function _generateNoneElement(optionValue, useSelect)
+ {
+ var label, className, value;
+
+ if (typeof optionValue == 'object') {
+ label = optionValue.label;
+ className = optionValue.className;
+ value = optionValue.value;
+ } else if (typeof optionValue == 'string') {
+ label = optionValue;
+ } else {
+ $.error('Invalid noneOption value');
+ }
+
+ if (useSelect) {
+ return $(' ', {
+ 'value': value,
+ 'class': className,
+ 'text': label
+ });
+ } else {
+ return $(' ', {
+ 'class': className,
+ 'text': label
+ }).data('time', value);
+ }
+ }
+
+ function _roundTime(seconds, settings)
+ {
+ if (!$.isNumeric(seconds)) {
+ seconds = _time2int(seconds);
+ }
+
+ if (seconds === null) {
+ return null;
+ } else {
+ var offset = seconds % (settings.step*60); // step is in minutes
+
+ if (offset >= settings.step*30) {
+ // if offset is larger than a half step, round up
+ seconds += (settings.step*60) - offset;
+ } else {
+ // round down
+ seconds -= offset;
+ }
+
+ return seconds;
+ }
+ }
+
+ function _roundAndFormatTime(seconds, settings)
+ {
+ seconds = _roundTime(seconds, settings);
+ if (seconds !== null) {
+ return _int2time(seconds, settings.timeFormat);
+ }
+ }
+
+ function _generateBaseDate()
+ {
+ return new Date(1970, 1, 1, 0, 0, 0);
+ }
+
+ // event handler to decide whether to close timepicker
+ function _closeHandler(e)
+ {
+ var target = $(e.target);
+ var input = target.closest('.ui-timepicker-input');
+ if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) {
+ methods.hide();
+ $(document).unbind('.ui-timepicker');
+ }
+ }
+
+ function _hideKeyboard(self)
+ {
+ var settings = self.data('timepicker-settings');
+ return ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && settings.disableTouchKeyboard);
+ }
+
+ function _findRow(self, list, value)
+ {
+ if (!value && value !== 0) {
+ return false;
+ }
+
+ var settings = self.data('timepicker-settings');
+ var out = false;
+ var halfStep = settings.step*30;
+
+ // loop through the menu items
+ list.find('li').each(function(i, obj) {
+ var jObj = $(obj);
+ if (typeof jObj.data('time') != 'number') {
+ return;
+ }
+
+ var offset = jObj.data('time') - value;
+
+ // check if the value is less than half a step from each row
+ if (Math.abs(offset) < halfStep || offset == halfStep) {
+ out = jObj;
+ return false;
+ }
+ });
+
+ return out;
+ }
+
+ function _setSelected(self, list)
+ {
+ list.find('li').removeClass('ui-timepicker-selected');
+
+ var timeValue = _time2int(_getTimeValue(self), self.data('timepicker-settings'));
+ if (timeValue === null) {
+ return;
+ }
+
+ var selected = _findRow(self, list, timeValue);
+ if (selected) {
+
+ var topDelta = selected.offset().top - list.offset().top;
+
+ if (topDelta + selected.outerHeight() > list.outerHeight() || topDelta < 0) {
+ list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight());
+ }
+
+ selected.addClass('ui-timepicker-selected');
+ }
+ }
+
+
+ function _formatValue(e, origin)
+ {
+ if (this.value === '' || origin == 'timepicker') {
+ return;
+ }
+
+ var self = $(this);
+ var list = self.data('timepicker-list');
+
+ if (self.is(':focus') && (!e || e.type != 'change')) {
+ return;
+ }
+
+ var seconds = _time2int(this.value);
+
+ if (seconds === null) {
+ self.trigger('timeFormatError');
+ return;
+ }
+
+ var settings = self.data('timepicker-settings');
+ var rangeError = false;
+ // check that the time in within bounds
+ if (settings.minTime !== null && seconds < settings.minTime) {
+ rangeError = true;
+ } else if (settings.maxTime !== null && seconds > settings.maxTime) {
+ rangeError = true;
+ }
+
+ // check that time isn't within disabled time ranges
+ $.each(settings.disableTimeRanges, function(){
+ if (seconds >= this[0] && seconds < this[1]) {
+ rangeError = true;
+ return false;
+ }
+ });
+
+ if (settings.forceRoundTime) {
+ var offset = seconds % (settings.step*60); // step is in minutes
+
+ if (offset >= settings.step*30) {
+ // if offset is larger than a half step, round up
+ seconds += (settings.step*60) - offset;
+ } else {
+ // round down
+ seconds -= offset;
+ }
+ }
+
+ var prettyTime = _int2time(seconds, settings.timeFormat);
+
+ if (rangeError) {
+ if (_setTimeValue(self, prettyTime, 'error')) {
+ self.trigger('timeRangeError');
+ }
+ } else {
+ _setTimeValue(self, prettyTime);
+ }
+ }
+
+ function _getTimeValue(self)
+ {
+ if (self.is('input')) {
+ return self.val();
+ } else {
+ // use the element's data attributes to store values
+ return self.data('ui-timepicker-value');
+ }
+ }
+
+ function _setTimeValue(self, value, source)
+ {
+ if (self.is('input')) {
+ self.val(value);
+
+ var settings = self.data('timepicker-settings');
+ if (settings.useSelect && source != 'select') {
+ self.data('timepicker-list').val(_roundAndFormatTime(value, settings));
+ }
+ }
+
+ if (self.data('ui-timepicker-value') != value) {
+ self.data('ui-timepicker-value', value);
+ if (source == 'select') {
+ self.trigger('selectTime').trigger('changeTime').trigger('change', 'timepicker');
+ } else if (source != 'error') {
+ self.trigger('changeTime');
+ }
+
+ return true;
+ } else {
+ self.trigger('selectTime');
+ return false;
+ }
+ }
+
+ /*
+ * Keyboard navigation via arrow keys
+ */
+ function _keydownhandler(e)
+ {
+ var self = $(this);
+ var list = self.data('timepicker-list');
+
+ if (!list || !_isVisible(list)) {
+ if (e.keyCode == 40) {
+ // show the list!
+ methods.show.call(self.get(0));
+ list = self.data('timepicker-list');
+ if (!_hideKeyboard(self)) {
+ self.focus();
+ }
+ } else {
+ return true;
+ }
+ }
+
+ switch (e.keyCode) {
+
+ case 13: // return
+ if (_selectValue(self)) {
+ methods.hide.apply(this);
+ }
+
+ e.preventDefault();
+ return false;
+
+ case 38: // up
+ var selected = list.find('.ui-timepicker-selected');
+
+ if (!selected.length) {
+ list.find('li').each(function(i, obj) {
+ if ($(obj).position().top > 0) {
+ selected = $(obj);
+ return false;
+ }
+ });
+ selected.addClass('ui-timepicker-selected');
+
+ } else if (!selected.is(':first-child')) {
+ selected.removeClass('ui-timepicker-selected');
+ selected.prev().addClass('ui-timepicker-selected');
+
+ if (selected.prev().position().top < selected.outerHeight()) {
+ list.scrollTop(list.scrollTop() - selected.outerHeight());
+ }
+ }
+
+ return false;
+
+ case 40: // down
+ selected = list.find('.ui-timepicker-selected');
+
+ if (selected.length === 0) {
+ list.find('li').each(function(i, obj) {
+ if ($(obj).position().top > 0) {
+ selected = $(obj);
+ return false;
+ }
+ });
+
+ selected.addClass('ui-timepicker-selected');
+ } else if (!selected.is(':last-child')) {
+ selected.removeClass('ui-timepicker-selected');
+ selected.next().addClass('ui-timepicker-selected');
+
+ if (selected.next().position().top + 2*selected.outerHeight() > list.outerHeight()) {
+ list.scrollTop(list.scrollTop() + selected.outerHeight());
+ }
+ }
+
+ return false;
+
+ case 27: // escape
+ list.find('li').removeClass('ui-timepicker-selected');
+ methods.hide();
+ break;
+
+ case 9: //tab
+ methods.hide();
+ break;
+
+ default:
+ return true;
+ }
+ }
+
+ /*
+ * Time typeahead
+ */
+ function _keyuphandler(e)
+ {
+ var self = $(this);
+ var list = self.data('timepicker-list');
+
+ if (!list || !_isVisible(list)) {
+ return true;
+ }
+
+ if (!self.data('timepicker-settings').typeaheadHighlight) {
+ list.find('li').removeClass('ui-timepicker-selected');
+ return true;
+ }
+
+ switch (e.keyCode) {
+
+ case 96: // numpad numerals
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 48: // numerals
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 65: // a
+ case 77: // m
+ case 80: // p
+ case 186: // colon
+ case 8: // backspace
+ case 46: // delete
+ _setSelected(self, list);
+ break;
+
+ default:
+ // list.find('li').removeClass('ui-timepicker-selected');
+ return;
+ }
+ }
+
+ function _selectValue(self)
+ {
+ var settings = self.data('timepicker-settings');
+ var list = self.data('timepicker-list');
+ var timeValue = null;
+
+ var cursor = list.find('.ui-timepicker-selected');
+
+ if (cursor.hasClass('ui-timepicker-disabled')) {
+ return false;
+ }
+
+ if (cursor.length) {
+ // selected value found
+ timeValue = cursor.data('time');
+ }
+
+ if (timeValue !== null) {
+ if (typeof timeValue == 'string') {
+ self.val(timeValue);
+ self.trigger('selectTime').trigger('changeTime').trigger('change', 'timepicker');
+ } else {
+ var timeString = _int2time(timeValue, settings.timeFormat);
+ _setTimeValue(self, timeString, 'select');
+ }
+ }
+
+ return true;
+ }
+
+ function _int2duration(seconds, step)
+ {
+ seconds = Math.abs(seconds);
+ var minutes = Math.round(seconds/60),
+ duration = [],
+ hours, mins;
+
+ if (minutes < 60) {
+ // Only show (x mins) under 1 hour
+ duration = [minutes, _lang.mins];
+ } else {
+ hours = Math.floor(minutes/60);
+ mins = minutes%60;
+
+ // Show decimal notation (eg: 1.5 hrs) for 30 minute steps
+ if (step == 30 && mins == 30) {
+ hours += _lang.decimal + 5;
+ }
+
+ duration.push(hours);
+ duration.push(hours == 1 ? _lang.hr : _lang.hrs);
+
+ // Show remainder minutes notation (eg: 1 hr 15 mins) for non-30 minute steps
+ // and only if there are remainder minutes to show
+ if (step != 30 && mins) {
+ duration.push(mins);
+ duration.push(_lang.mins);
+ }
+ }
+
+ return duration.join(' ');
+ }
+
+ function _int2time(seconds, format)
+ {
+ if (seconds === null) {
+ return;
+ }
+
+ var time = new Date(_baseDate.valueOf() + (seconds*1000));
+
+ if (isNaN(time.getTime())) {
+ return;
+ }
+
+ if ($.type(format) === "function") {
+ return format(time);
+ }
+
+ var output = '';
+ var hour, code;
+ for (var i=0; i 11) ? _lang.pm : _lang.am;
+ break;
+
+ case 'A':
+ output += (time.getHours() > 11) ? _lang.pm.toUpperCase() : _lang.am.toUpperCase();
+ break;
+
+ case 'g':
+ hour = time.getHours() % 12;
+ output += (hour === 0) ? '12' : hour;
+ break;
+
+ case 'G':
+ output += time.getHours();
+ break;
+
+ case 'h':
+ hour = time.getHours() % 12;
+
+ if (hour !== 0 && hour < 10) {
+ hour = '0'+hour;
+ }
+
+ output += (hour === 0) ? '12' : hour;
+ break;
+
+ case 'H':
+ hour = time.getHours();
+ if (seconds === _ONE_DAY) hour = 24;
+ output += (hour > 9) ? hour : '0'+hour;
+ break;
+
+ case 'i':
+ var minutes = time.getMinutes();
+ output += (minutes > 9) ? minutes : '0'+minutes;
+ break;
+
+ case 's':
+ seconds = time.getSeconds();
+ output += (seconds > 9) ? seconds : '0'+seconds;
+ break;
+
+ case '\\':
+ // escape character; add the next character and skip ahead
+ i++;
+ output += format.charAt(i);
+ break;
+
+ default:
+ output += code;
+ }
+ }
+
+ return output;
+ }
+
+ function _time2int(timeString, settings)
+ {
+ if (timeString === '') return null;
+ if (!timeString || timeString+0 == timeString) return timeString;
+
+ if (typeof(timeString) == 'object') {
+ return timeString.getHours()*3600 + timeString.getMinutes()*60 + timeString.getSeconds();
+ }
+
+ timeString = timeString.toLowerCase();
+
+ // if the last character is an "a" or "p", add the "m"
+ if (timeString.slice(-1) == 'a' || timeString.slice(-1) == 'p') {
+ timeString += 'm';
+ }
+
+ // try to parse time input
+ var pattern = new RegExp('^([0-2]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?\\s*('+_lang.am+'|'+_lang.pm+')?$');
+ var time = timeString.match(pattern);
+ if (!time) {
+ return null;
+ }
+
+ var hour = parseInt(time[1]*1, 10);
+ var ampm = time[4];
+ var hours = hour;
+
+ if (hour <= 12 && ampm) {
+ if (hour == 12) {
+ hours = (time[4] == _lang.pm) ? 12 : 0;
+ } else {
+ hours = (hour + (time[4] == _lang.pm ? 12 : 0));
+ }
+ }
+
+ var minutes = ( time[2]*1 || 0 );
+ var seconds = ( time[3]*1 || 0 );
+ var timeInt = hours*3600 + minutes*60 + seconds;
+
+ // if no am/pm provided, intelligently guess based on the scrollDefault
+ if (!ampm && settings && settings._twelveHourTime && settings.scrollDefault) {
+ var delta = timeInt - settings.scrollDefault;
+ if (delta < 0 && delta >= _ONE_DAY / -2) {
+ timeInt = (timeInt + (_ONE_DAY / 2)) % _ONE_DAY;
+ }
+ }
+
+ return timeInt
+ }
+
+ function _pad2(n) {
+ return ("0" + n).slice(-2);
+ }
+
+ // Plugin entry
+ $.fn.timepicker = function(method)
+ {
+ if (!this.length) return this;
+ if (methods[method]) {
+ // check if this element is a timepicker
+ if (!this.hasClass('ui-timepicker-input')) {
+ return this;
+ }
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+ }
+ else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
+ else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); }
+ };
+ // Global defaults
+ $.fn.timepicker.defaults = {
+ className: null,
+ minTime: null,
+ maxTime: null,
+ durationTime: null,
+ step: 30,
+ showDuration: false,
+ showOnFocus: true,
+ timeFormat: 'g:ia',
+ scrollDefault: null,
+ selectOnBlur: false,
+ disableTouchKeyboard: false,
+ forceRoundTime: false,
+ appendTo: 'body',
+ orientation: 'ltr',
+ disableTimeRanges: [],
+ closeOnWindowScroll: false,
+ typeaheadHighlight: true,
+ noneOption: false
+ };
+}));
diff --git a/web/Scripts/jquery.timepicker.min.js b/web/Scripts/jquery.timepicker.min.js
new file mode 100644
index 00000000..ac720215
--- /dev/null
+++ b/web/Scripts/jquery.timepicker.min.js
@@ -0,0 +1,7 @@
+/*!
+ * jquery-timepicker v1.4.13 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
+ * Copyright (c) 2014 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
+ * License:
+ */
+
+!function(a){"object"==typeof exports&&exports&&"object"==typeof module&&module&&module.exports===exports?a(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){var b=a[0];return b.offsetWidth>0&&b.offsetHeight>0}function c(b){if(b.minTime&&(b.minTime=u(b.minTime)),b.maxTime&&(b.maxTime=u(b.maxTime)),b.durationTime&&"function"!=typeof b.durationTime&&(b.durationTime=u(b.durationTime)),"now"==b.scrollDefault?b.scrollDefault=u(new Date):b.scrollDefault?b.scrollDefault=u(b.scrollDefault):b.minTime&&(b.scrollDefault=b.minTime),b.scrollDefault&&(b.scrollDefault=f(b.scrollDefault,b)),"string"===a.type(b.timeFormat)&&b.timeFormat.match(/[gh]/)&&(b._twelveHourTime=!0),b.disableTimeRanges.length>0){for(var c in b.disableTimeRanges)b.disableTimeRanges[c]=[u(b.disableTimeRanges[c][0]),u(b.disableTimeRanges[c][1])];b.disableTimeRanges=b.disableTimeRanges.sort(function(a,b){return a[0]-b[0]});for(var c=b.disableTimeRanges.length-1;c>0;c--)b.disableTimeRanges[c][0]<=b.disableTimeRanges[c-1][1]&&(b.disableTimeRanges[c-1]=[Math.min(b.disableTimeRanges[c][0],b.disableTimeRanges[c-1][0]),Math.max(b.disableTimeRanges[c][1],b.disableTimeRanges[c-1][1])],b.disableTimeRanges.splice(c,1))}return b}function d(b){var c=b.data("timepicker-settings"),d=b.data("timepicker-list");if(d&&d.length&&(d.remove(),b.data("timepicker-list",!1)),c.useSelect){d=a(" ",{"class":"ui-timepicker-select"});var f=d}else{d=a("",{"class":"ui-timepicker-list"});var f=a("
",{"class":"ui-timepicker-wrapper",tabindex:-1});f.css({display:"none",position:"absolute"}).append(d)}if(c.noneOption)if(c.noneOption===!0&&(c.noneOption=c.useSelect?"Time...":"None"),a.isArray(c.noneOption)){for(var h in c.noneOption)if(parseInt(h,10)==h){var i=e(c.noneOption[h],c.useSelect);d.append(i)}}else{var i=e(c.noneOption,c.useSelect);d.append(i)}c.className&&f.addClass(c.className),null===c.minTime&&null===c.durationTime||!c.showDuration||(f.addClass("ui-timepicker-with-duration"),f.addClass("ui-timepicker-step-"+c.step));var k=c.minTime;"function"==typeof c.durationTime?k=u(c.durationTime()):null!==c.durationTime&&(k=c.durationTime);var m=null!==c.minTime?c.minTime:0,n=null!==c.maxTime?c.maxTime:m+w-1;m>=n&&(n+=w),n===w-1&&"string"===a.type(c.timeFormat)&&-1!==c.timeFormat.indexOf("H")&&(n=w);for(var p=c.disableTimeRanges,q=0,v=p.length,h=m;n>=h;h+=60*c.step){var x=h,z=t(x,c.timeFormat);if(c.useSelect){var A=a(" ",{value:z});A.text(z)}else{var A=a(" ");A.data("time",86400>=x?x:x%86400),A.text(z)}if((null!==c.minTime||null!==c.durationTime)&&c.showDuration){var B=s(h-k,c.step);if(c.useSelect)A.text(A.text()+" ("+B+")");else{var C=a(" ",{"class":"ui-timepicker-duration"});C.text(" ("+B+")"),A.append(C)}}v>q&&(x>=p[q][1]&&(q+=1),p[q]&&x>=p[q][0]&&x
",{value:f,"class":e,text:d}):a(" ",{"class":e,text:d}).data("time",f)}function f(b,c){if(a.isNumeric(b)||(b=u(b)),null===b)return null;var d=b%(60*c.step);return d>=30*c.step?b+=60*c.step-d:b-=d,b}function g(a,b){return a=f(a,b),null!==a?t(a,b.timeFormat):void 0}function h(){return new Date(1970,1,1,0,0,0)}function i(b){var c=a(b.target),d=c.closest(".ui-timepicker-input");0===d.length&&0===c.closest(".ui-timepicker-wrapper").length&&(y.hide(),a(document).unbind(".ui-timepicker"))}function j(a){var b=a.data("timepicker-settings");return(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&b.disableTouchKeyboard}function k(b,c,d){if(!d&&0!==d)return!1;var e=b.data("timepicker-settings"),f=!1,g=30*e.step;return c.find("li").each(function(b,c){var e=a(c);if("number"==typeof e.data("time")){var h=e.data("time")-d;return Math.abs(h)b.outerHeight()||0>e)&&b.scrollTop(b.scrollTop()+d.position().top-d.outerHeight()),d.addClass("ui-timepicker-selected")}}}function m(b,c){if(""!==this.value&&"timepicker"!=c){var d=a(this);if(d.data("timepicker-list"),!d.is(":focus")||b&&"change"==b.type){var e=u(this.value);if(null===e)return d.trigger("timeFormatError"),void 0;var f=d.data("timepicker-settings"),g=!1;if(null!==f.minTime&&ef.maxTime&&(g=!0),a.each(f.disableTimeRanges,function(){return e>=this[0]&&e=30*f.step?e+=60*f.step-h:e-=h}var i=t(e,f.timeFormat);g?o(d,i,"error")&&d.trigger("timeRangeError"):o(d,i)}}}function n(a){return a.is("input")?a.val():a.data("ui-timepicker-value")}function o(a,b,c){if(a.is("input")){a.val(b);var d=a.data("timepicker-settings");d.useSelect&&"select"!=c&&a.data("timepicker-list").val(g(b,d))}return a.data("ui-timepicker-value")!=b?(a.data("ui-timepicker-value",b),"select"==c?a.trigger("selectTime").trigger("changeTime").trigger("change","timepicker"):"error"!=c&&a.trigger("changeTime"),!0):(a.trigger("selectTime"),!1)}function p(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e)){if(40!=c.keyCode)return!0;y.show.call(d.get(0)),e=d.data("timepicker-list"),j(d)||d.focus()}switch(c.keyCode){case 13:return r(d)&&y.hide.apply(this),c.preventDefault(),!1;case 38:var f=e.find(".ui-timepicker-selected");return f.length?f.is(":first-child")||(f.removeClass("ui-timepicker-selected"),f.prev().addClass("ui-timepicker-selected"),f.prev().position().top0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")),!1;case 40:return f=e.find(".ui-timepicker-selected"),0===f.length?(e.find("li").each(function(b,c){return a(c).position().top>0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")):f.is(":last-child")||(f.removeClass("ui-timepicker-selected"),f.next().addClass("ui-timepicker-selected"),f.next().position().top+2*f.outerHeight()>e.outerHeight()&&e.scrollTop(e.scrollTop()+f.outerHeight())),!1;case 27:e.find("li").removeClass("ui-timepicker-selected"),y.hide();break;case 9:y.hide();break;default:return!0}}function q(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e))return!0;if(!d.data("timepicker-settings").typeaheadHighlight)return e.find("li").removeClass("ui-timepicker-selected"),!0;switch(c.keyCode){case 96:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 65:case 77:case 80:case 186:case 8:case 46:l(d,e);break;default:return}}function r(a){var b=a.data("timepicker-settings"),c=a.data("timepicker-list"),d=null,e=c.find(".ui-timepicker-selected");if(e.hasClass("ui-timepicker-disabled"))return!1;if(e.length&&(d=e.data("time")),null!==d)if("string"==typeof d)a.val(d),a.trigger("selectTime").trigger("changeTime").trigger("change","timepicker");else{var f=t(d,b.timeFormat);o(a,f,"select")}return!0}function s(a,b){a=Math.abs(a);var c,d,e=Math.round(a/60),f=[];return 60>e?f=[e,x.mins]:(c=Math.floor(e/60),d=e%60,30==b&&30==d&&(c+=x.decimal+5),f.push(c),f.push(1==c?x.hr:x.hrs),30!=b&&d&&(f.push(d),f.push(x.mins))),f.join(" ")}function t(b,c){if(null!==b){var d=new Date(v.valueOf()+1e3*b);if(!isNaN(d.getTime())){if("function"===a.type(c))return c(d);for(var e,f,g="",h=0;h11?x.pm:x.am;break;case"A":g+=d.getHours()>11?x.pm.toUpperCase():x.am.toUpperCase();break;case"g":e=d.getHours()%12,g+=0===e?"12":e;break;case"G":g+=d.getHours();break;case"h":e=d.getHours()%12,0!==e&&10>e&&(e="0"+e),g+=0===e?"12":e;break;case"H":e=d.getHours(),b===w&&(e=24),g+=e>9?e:"0"+e;break;case"i":var i=d.getMinutes();g+=i>9?i:"0"+i;break;case"s":b=d.getSeconds(),g+=b>9?b:"0"+b;break;case"\\":h++,g+=c.charAt(h);break;default:g+=f}return g}}}function u(a,b){if(""===a)return null;if(!a||a+0==a)return a;if("object"==typeof a)return 3600*a.getHours()+60*a.getMinutes()+a.getSeconds();a=a.toLowerCase(),("a"==a.slice(-1)||"p"==a.slice(-1))&&(a+="m");var c=new RegExp("^([0-2]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?\\s*("+x.am+"|"+x.pm+")?$"),d=a.match(c);if(!d)return null;var e=parseInt(1*d[1],10),f=d[4],g=e;12>=e&&f&&(g=12==e?d[4]==x.pm?12:0:e+(d[4]==x.pm?12:0));var h=1*d[2]||0,i=1*d[3]||0,j=3600*g+60*h+i;if(!f&&b&&b._twelveHourTime&&b.scrollDefault){var k=j-b.scrollDefault;0>k&&k>=w/-2&&(j=(j+w/2)%w)}return j}var v=h(),w=86400,x={am:"am",pm:"pm",AM:"AM",PM:"PM",decimal:".",mins:"mins",hr:"hr",hrs:"hrs"},y={init:function(b){return this.each(function(){var e=a(this),f=[];for(var g in a.fn.timepicker.defaults)e.data(g)&&(f[g]=e.data(g));var h=a.extend({},a.fn.timepicker.defaults,f,b);h.lang&&(x=a.extend(x,h.lang)),h=c(h),e.data("timepicker-settings",h),e.addClass("ui-timepicker-input"),h.useSelect?d(e):(e.prop("autocomplete","off"),e.on("click.timepicker focus.timepicker",y.show),e.on("change.timepicker",m),e.on("keydown.timepicker",p),e.on("keyup.timepicker",q),m.call(e.get(0)))})},show:function(c){var e=a(this),f=e.data("timepicker-settings");if(c){if(!f.showOnFocus)return!0;c.preventDefault()}if(f.useSelect)return e.data("timepicker-list").focus(),void 0;j(e)&&e.blur();var g=e.data("timepicker-list");if(!e.prop("readonly")&&(g&&0!==g.length&&"function"!=typeof f.durationTime||(d(e),g=e.data("timepicker-list")),!b(g))){y.hide(),g.show();var h={};h.left="rtl"==f.orientation?e.offset().left+e.outerWidth()-g.outerWidth()+parseInt(g.css("marginLeft").replace("px",""),10):e.offset().left+parseInt(g.css("marginLeft").replace("px",""),10),e.offset().top+e.outerHeight(!0)+g.outerHeight()>a(window).height()+a(window).scrollTop()?(g.addClass("ui-timepicker-positioned-top"),h.top=e.offset().top-g.outerHeight()+parseInt(g.css("marginTop").replace("px",""),10)):(g.removeClass("ui-timepicker-positioned-top"),h.top=e.offset().top+e.outerHeight()+parseInt(g.css("marginTop").replace("px",""),10)),g.offset(h);var l=g.find(".ui-timepicker-selected");if(l.length||(n(e)?l=k(e,g,u(n(e))):f.scrollDefault&&(l=k(e,g,f.scrollDefault))),l&&l.length){var m=g.scrollTop()+l.position().top-l.outerHeight();g.scrollTop(m)}else g.scrollTop(0);return a(document).on("touchstart.ui-timepicker mousedown.ui-timepicker",i),f.closeOnWindowScroll&&a(document).on("scroll.ui-timepicker",i),e.trigger("showTimepicker"),this}},hide:function(){var c=a(this),d=c.data("timepicker-settings");return d&&d.useSelect&&c.blur(),a(".ui-timepicker-wrapper").each(function(){var c=a(this);if(b(c)){var d=c.data("timepicker-input"),e=d.data("timepicker-settings");e&&e.selectOnBlur&&r(d),c.hide(),d.trigger("hideTimepicker")}}),this},option:function(b,e){return this.each(function(){var f=a(this),g=f.data("timepicker-settings"),h=f.data("timepicker-list");if("object"==typeof b)g=a.extend(g,b);else if("string"==typeof b&&"undefined"!=typeof e)g[b]=e;else if("string"==typeof b)return g[b];g=c(g),f.data("timepicker-settings",g),h&&(h.remove(),f.data("timepicker-list",!1)),g.useSelect&&d(f)})},getSecondsFromMidnight:function(){return u(n(this))},getTime:function(a){var b=this,c=n(b);if(!c)return null;a||(a=new Date);var d=u(c),e=new Date(a);return e.setHours(d/3600),e.setMinutes(d%3600/60),e.setSeconds(d%60),e.setMilliseconds(0),e},setTime:function(a){var b=this,c=b.data("timepicker-settings");if(c.forceRoundTime)var d=g(a,c);else var d=t(u(a),c.timeFormat);return o(b,d),b.data("timepicker-list")&&l(b,b.data("timepicker-list")),this},remove:function(){var a=this;if(a.hasClass("ui-timepicker-input")){var b=a.data("timepicker-settings");return a.removeAttr("autocomplete","off"),a.removeClass("ui-timepicker-input"),a.removeData("timepicker-settings"),a.off(".timepicker"),a.data("timepicker-list")&&a.data("timepicker-list").remove(),b.useSelect&&a.show(),a.removeData("timepicker-list"),this}}};a.fn.timepicker=function(b){return this.length?y[b]?this.hasClass("ui-timepicker-input")?y[b].apply(this,Array.prototype.slice.call(arguments,1)):this:"object"!=typeof b&&b?(a.error("Method "+b+" does not exist on jQuery.timepicker"),void 0):y.init.apply(this,arguments):this},a.fn.timepicker.defaults={className:null,minTime:null,maxTime:null,durationTime:null,step:30,showDuration:!1,showOnFocus:!0,timeFormat:"g:ia",scrollDefault:null,selectOnBlur:!1,disableTouchKeyboard:!1,forceRoundTime:!1,appendTo:"body",orientation:"ltr",disableTimeRanges:[],closeOnWindowScroll:!1,typeaheadHighlight:!0,noneOption:!1}});
\ No newline at end of file
diff --git a/web/Theme/jquery-ui.css b/web/Theme/jquery-ui.css
new file mode 100644
index 00000000..5465f332
--- /dev/null
+++ b/web/Theme/jquery-ui.css
@@ -0,0 +1,1225 @@
+/*! jQuery UI - v1.11.2 - 2014-12-28
+* http://jqueryui.com
+* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Segoe%20UI%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=333333&bgTextureHeader=gloss_wave&bgImgOpacityHeader=25&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=inset_soft&bgImgOpacityContent=25&borderColorContent=666666&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=555555&bgTextureDefault=glass&bgImgOpacityDefault=20&borderColorDefault=666666&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=0078a3&bgTextureHover=glass&bgImgOpacityHover=40&borderColorHover=59b4d4&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=f58400&bgTextureActive=inset_soft&bgImgOpacityActive=30&borderColorActive=ffaf0f&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=glass&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=flat&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=flat&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+ display: none;
+}
+.ui-helper-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.ui-helper-reset {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ line-height: 1.3;
+ text-decoration: none;
+ font-size: 100%;
+ list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+ content: "";
+ display: table;
+ border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+ clear: both;
+}
+.ui-helper-clearfix {
+ min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+ z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+ cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ display: block;
+ text-indent: -99999px;
+ overflow: hidden;
+ background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.ui-draggable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable {
+ position: relative;
+}
+.ui-resizable-handle {
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+ display: none;
+}
+.ui-resizable-n {
+ cursor: n-resize;
+ height: 7px;
+ width: 100%;
+ top: -5px;
+ left: 0;
+}
+.ui-resizable-s {
+ cursor: s-resize;
+ height: 7px;
+ width: 100%;
+ bottom: -5px;
+ left: 0;
+}
+.ui-resizable-e {
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-w {
+ cursor: w-resize;
+ width: 7px;
+ left: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-se {
+ cursor: se-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ bottom: 1px;
+}
+.ui-resizable-sw {
+ cursor: sw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ bottom: -5px;
+}
+.ui-resizable-nw {
+ cursor: nw-resize;
+ width: 9px;
+ height: 9px;
+ left: -5px;
+ top: -5px;
+}
+.ui-resizable-ne {
+ cursor: ne-resize;
+ width: 9px;
+ height: 9px;
+ right: -5px;
+ top: -5px;
+}
+.ui-selectable {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-selectable-helper {
+ position: absolute;
+ z-index: 100;
+ border: 1px dotted black;
+}
+.ui-sortable-handle {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-accordion .ui-accordion-header {
+ display: block;
+ cursor: pointer;
+ position: relative;
+ margin: 2px 0 0 0;
+ padding: .5em .5em .5em .7em;
+ min-height: 0; /* support: IE7 */
+ font-size: 100%;
+}
+.ui-accordion .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+ padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+ position: absolute;
+ left: .5em;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+ padding: 1em 2.2em;
+ border-top: 0;
+ overflow: auto;
+}
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+}
+.ui-button {
+ display: inline-block;
+ position: relative;
+ padding: 0;
+ line-height: normal;
+ margin-right: .1em;
+ cursor: pointer;
+ vertical-align: middle;
+ text-align: center;
+ overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+ text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+ width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+ width: 2.4em;
+}
+.ui-button-icons-only {
+ width: 3.4em;
+}
+button.ui-button-icons-only {
+ width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+ display: block;
+ line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+ padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+ padding: .4em;
+ text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+ padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+ padding-left: 2.1em;
+ padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+ padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+ position: absolute;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+ left: 50%;
+ margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+ left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+ right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+ margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+ margin-left: 0;
+ margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+.ui-datepicker {
+ width: 17em;
+ padding: .2em .2em 0;
+ display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+ position: relative;
+ padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ position: absolute;
+ top: 2px;
+ width: 1.8em;
+ height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+ right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+ display: block;
+ position: absolute;
+ left: 50%;
+ margin-left: -8px;
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+ margin: 0 2.3em;
+ line-height: 1.8em;
+ text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+ font-size: 1em;
+ margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+ width: 45%;
+}
+.ui-datepicker table {
+ width: 100%;
+ font-size: .9em;
+ border-collapse: collapse;
+ margin: 0 0 .4em;
+}
+.ui-datepicker th {
+ padding: .7em .3em;
+ text-align: center;
+ font-weight: bold;
+ border: 0;
+}
+.ui-datepicker td {
+ border: 0;
+ padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+ display: block;
+ padding: .2em;
+ text-align: right;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+ background-image: none;
+ margin: .7em 0 0 0;
+ padding: 0 .2em;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+ float: right;
+ margin: .5em .2em .4em;
+ cursor: pointer;
+ padding: .2em .6em .3em .6em;
+ width: auto;
+ overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+ float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+ width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+ float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+ width: 95%;
+ margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+ width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+ width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+ width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+ border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+ clear: left;
+}
+.ui-datepicker-row-break {
+ clear: both;
+ width: 100%;
+ font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+ direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+ right: 2px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+ left: 2px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+ right: 1px;
+ left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+ left: 1px;
+ right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+ clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+ float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+ float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+ border-right-width: 0;
+ border-left-width: 1px;
+}
+.ui-dialog {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: .2em;
+ outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+ padding: .4em 1em;
+ position: relative;
+}
+.ui-dialog .ui-dialog-title {
+ float: left;
+ margin: .1em 0;
+ white-space: nowrap;
+ width: 90%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+ position: absolute;
+ right: .3em;
+ top: 50%;
+ width: 20px;
+ margin: -10px 0 0 0;
+ padding: 1px;
+ height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+ position: relative;
+ border: 0;
+ padding: .5em 1em;
+ background: none;
+ overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+ text-align: left;
+ border-width: 1px 0 0 0;
+ background-image: none;
+ margin-top: .5em;
+ padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+ margin: .5em .4em .5em 0;
+ cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+ width: 12px;
+ height: 12px;
+ right: -5px;
+ bottom: -5px;
+ background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+ cursor: move;
+}
+.ui-menu {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ display: block;
+ outline: none;
+}
+.ui-menu .ui-menu {
+ position: absolute;
+}
+.ui-menu .ui-menu-item {
+ position: relative;
+ margin: 0;
+ padding: 3px 1em 3px .4em;
+ cursor: pointer;
+ min-height: 0; /* support: IE7 */
+ /* support: IE10, see #8844 */
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-divider {
+ margin: 5px 0;
+ height: 0;
+ font-size: 0;
+ line-height: 0;
+ border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+ margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+ position: relative;
+}
+.ui-menu-icons .ui-menu-item {
+ padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: .2em;
+ margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+ left: auto;
+ right: 0;
+}
+.ui-progressbar {
+ height: 2em;
+ text-align: left;
+ overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+ margin: -1px;
+ height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+ height: 100%;
+ filter: alpha(opacity=25); /* support: IE8 */
+ opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+ background-image: none;
+}
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ /* Support: IE7 */
+ overflow-x: hidden;
+ padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+.ui-selectmenu-open {
+ display: block;
+}
+.ui-selectmenu-button {
+ display: inline-block;
+ overflow: hidden;
+ position: relative;
+ text-decoration: none;
+ cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+ right: 0.5em;
+ left: auto;
+ margin-top: -8px;
+ position: absolute;
+ top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+ text-align: left;
+ padding: 0.4em 2.1em 0.4em 1em;
+ display: block;
+ line-height: 1.4;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.ui-slider {
+ position: relative;
+ text-align: left;
+}
+.ui-slider .ui-slider-handle {
+ position: absolute;
+ z-index: 2;
+ width: 1.2em;
+ height: 1.2em;
+ cursor: default;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.ui-slider .ui-slider-range {
+ position: absolute;
+ z-index: 1;
+ font-size: .7em;
+ display: block;
+ border: 0;
+ background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+ filter: inherit;
+}
+
+.ui-slider-horizontal {
+ height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+ top: -.3em;
+ margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+ top: 0;
+ height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+ left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+ right: 0;
+}
+
+.ui-slider-vertical {
+ width: .8em;
+ height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -.3em;
+ margin-left: 0;
+ margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+ left: 0;
+ width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+ bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+ top: 0;
+}
+.ui-spinner {
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ padding: 0;
+ vertical-align: middle;
+}
+.ui-spinner-input {
+ border: none;
+ background: none;
+ color: inherit;
+ padding: 0;
+ margin: .2em 0;
+ vertical-align: middle;
+ margin-left: .4em;
+ margin-right: 22px;
+}
+.ui-spinner-button {
+ width: 16px;
+ height: 50%;
+ font-size: .5em;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ position: absolute;
+ cursor: default;
+ display: block;
+ overflow: hidden;
+ right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+ border-top: none;
+ border-bottom: none;
+ border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+ position: absolute;
+ margin-top: -8px;
+ top: 50%;
+ left: 0;
+}
+.ui-spinner-up {
+ top: 0;
+}
+.ui-spinner-down {
+ bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+ /* need to fix icons sprite */
+ background-position: -65px -16px;
+}
+.ui-tabs {
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+ padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+ margin: 0;
+ padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+ list-style: none;
+ float: left;
+ position: relative;
+ top: 0;
+ margin: 1px .2em 0 0;
+ border-bottom-width: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+ float: left;
+ padding: .5em 1em;
+ text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+ cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+ cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 1em 1.4em;
+ background: none;
+}
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+ -webkit-box-shadow: 0 0 5px #aaa;
+ box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+ border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+ font-family: Segoe UI,Arial,sans-serif;
+ font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+ font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: Segoe UI,Arial,sans-serif;
+ font-size: 1em;
+}
+.ui-widget-content {
+ border: 1px solid #666666;
+ background: #000000 url("images/ui-bg_inset-soft_25_000000_1x100.png") 50% bottom repeat-x;
+ color: #ffffff;
+}
+.ui-widget-content a {
+ color: #ffffff;
+}
+.ui-widget-header {
+ border: 1px solid #333333;
+ background: #333333 url("images/ui-bg_gloss-wave_25_333333_500x100.png") 50% 50% repeat-x;
+ color: #ffffff;
+ font-weight: bold;
+}
+.ui-widget-header a {
+ color: #ffffff;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+ border: 1px solid #666666;
+ background: #555555 url("images/ui-bg_glass_20_555555_1x400.png") 50% 50% repeat-x;
+ font-weight: bold;
+ color: #eeeeee;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+ color: #eeeeee;
+ text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+ border: 1px solid #59b4d4;
+ background: #0078a3 url("images/ui-bg_glass_40_0078a3_1x400.png") 50% 50% repeat-x;
+ font-weight: bold;
+ color: #ffffff;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+ color: #ffffff;
+ text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+ border: 1px solid #ffaf0f;
+ background: #f58400 url("images/ui-bg_inset-soft_30_f58400_1x100.png") 50% 50% repeat-x;
+ font-weight: bold;
+ color: #ffffff;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #ffffff;
+ text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+ border: 1px solid #cccccc;
+ background: #eeeeee url("images/ui-bg_highlight-soft_80_eeeeee_1x100.png") 50% top repeat-x;
+ color: #2e7db2;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+ color: #2e7db2;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+ border: 1px solid #ffb73d;
+ background: #ffc73d url("images/ui-bg_glass_40_ffc73d_1x400.png") 50% 50% repeat-x;
+ color: #111111;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+ color: #111111;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+ color: #111111;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+ font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+ opacity: .7;
+ filter:Alpha(Opacity=70); /* support: IE8 */
+ font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+ opacity: .35;
+ filter:Alpha(Opacity=35); /* support: IE8 */
+ background-image: none;
+}
+.ui-state-disabled .ui-icon {
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+ width: 16px;
+ height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+ background-image: url("images/ui-icons_cccccc_256x240.png");
+}
+.ui-widget-header .ui-icon {
+ background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-default .ui-icon {
+ background-image: url("images/ui-icons_cccccc_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+ background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-active .ui-icon {
+ background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+ background-image: url("images/ui-icons_4b8e0b_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+ background-image: url("images/ui-icons_a83300_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 6px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 6px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 6px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 6px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+ background: #5c5c5c url("images/ui-bg_flat_50_5c5c5c_40x100.png") 50% 50% repeat-x;
+ opacity: .8;
+ filter: Alpha(Opacity=80); /* support: IE8 */
+}
+.ui-widget-shadow {
+ margin: -7px 0 0 -7px;
+ padding: 7px;
+ background: #cccccc url("images/ui-bg_flat_30_cccccc_40x100.png") 50% 50% repeat-x;
+ opacity: .6;
+ filter: Alpha(Opacity=60); /* support: IE8 */
+ border-radius: 8px;
+}
diff --git a/web/Theme/jquery-ui.min.css b/web/Theme/jquery-ui.min.css
new file mode 100644
index 00000000..593fdad0
--- /dev/null
+++ b/web/Theme/jquery-ui.min.css
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.11.2 - 2014-12-28
+* http://jqueryui.com
+* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Segoe%20UI%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=333333&bgTextureHeader=gloss_wave&bgImgOpacityHeader=25&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=inset_soft&bgImgOpacityContent=25&borderColorContent=666666&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=555555&bgTextureDefault=glass&bgImgOpacityDefault=20&borderColorDefault=666666&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=0078a3&bgTextureHover=glass&bgImgOpacityHover=40&borderColorHover=59b4d4&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=f58400&bgTextureActive=inset_soft&bgImgOpacityActive=30&borderColorActive=ffaf0f&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=glass&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=flat&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=flat&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Segoe UI,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Segoe UI,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #666;background:#000 url("images/ui-bg_inset-soft_25_000000_1x100.png") 50% bottom repeat-x;color:#fff}.ui-widget-content a{color:#fff}.ui-widget-header{border:1px solid #333;background:#333 url("images/ui-bg_gloss-wave_25_333333_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #666;background:#555 url("images/ui-bg_glass_20_555555_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eee}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#eee;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #59b4d4;background:#0078a3 url("images/ui-bg_glass_40_0078a3_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#fff;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #ffaf0f;background:#f58400 url("images/ui-bg_inset-soft_30_f58400_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #ccc;background:#eee url("images/ui-bg_highlight-soft_80_eeeeee_1x100.png") 50% top repeat-x;color:#2e7db2}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#2e7db2}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #ffb73d;background:#ffc73d url("images/ui-bg_glass_40_ffc73d_1x400.png") 50% 50% repeat-x;color:#111}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#111}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#111}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_4b8e0b_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_a83300_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:6px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:6px}.ui-widget-overlay{background:#5c5c5c url("images/ui-bg_flat_50_5c5c5c_40x100.png") 50% 50% repeat-x;opacity:.8;filter:Alpha(Opacity=80)}.ui-widget-shadow{margin:-7px 0 0 -7px;padding:7px;background:#ccc url("images/ui-bg_flat_30_cccccc_40x100.png") 50% 50% repeat-x;opacity:.6;filter:Alpha(Opacity=60);border-radius:8px}
\ No newline at end of file
diff --git a/web/Theme/jquery.timepicker.css b/web/Theme/jquery.timepicker.css
new file mode 100755
index 00000000..cd75f13f
--- /dev/null
+++ b/web/Theme/jquery.timepicker.css
@@ -0,0 +1,72 @@
+.ui-timepicker-wrapper {
+ overflow-y: auto;
+ height: 150px;
+ width: 6.5em;
+ background: #fff;
+ border: 1px solid #ddd;
+ -webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);
+ -moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);
+ box-shadow:0 5px 10px rgba(0,0,0,0.2);
+ outline: none;
+ z-index: 10001;
+ margin: 0;
+}
+
+.ui-timepicker-wrapper.ui-timepicker-with-duration {
+ width: 13em;
+}
+
+.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,
+.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 {
+ width: 11em;
+}
+
+.ui-timepicker-list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.ui-timepicker-duration {
+ margin-left: 5px; color: #888;
+}
+
+.ui-timepicker-list:hover .ui-timepicker-duration {
+ color: #888;
+}
+
+.ui-timepicker-list li {
+ padding: 3px 0 3px 5px;
+ cursor: pointer;
+ white-space: nowrap;
+ color: #000;
+ list-style: none;
+ margin: 0;
+}
+
+.ui-timepicker-list:hover .ui-timepicker-selected {
+ background: #fff; color: #000;
+}
+
+li.ui-timepicker-selected,
+.ui-timepicker-list li:hover,
+.ui-timepicker-list .ui-timepicker-selected:hover {
+ background: #1980EC; color: #fff;
+}
+
+li.ui-timepicker-selected .ui-timepicker-duration,
+.ui-timepicker-list li:hover .ui-timepicker-duration {
+ color: #ccc;
+}
+
+.ui-timepicker-list li.ui-timepicker-disabled,
+.ui-timepicker-list li.ui-timepicker-disabled:hover,
+.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
+ color: #888;
+ cursor: default;
+}
+
+.ui-timepicker-list li.ui-timepicker-disabled:hover,
+.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
+ background: #f2f2f2;
+}
diff --git a/web/Theme/style.css b/web/Theme/style.css
index e58efe88..72a203b4 100644
--- a/web/Theme/style.css
+++ b/web/Theme/style.css
@@ -14,18 +14,20 @@ main {
margin:.5em;
}
-aside div {
- display: block;
- background-color: rgba(32,16,16,0.5);
- margin: 0.7em;
- float: left;
- margin:.5em;
- }
+aside {background-color: rgba(32,16,16,0.8);
+ padding: 1em; margin: 0.5em;
+ border-radius:25px; border: solid 1px #000060;
+ float: right;
+ }
+
video,img {
max-width:100%;
max-height:75%;
position:relative;
+ top:4px;
}
+.panel { max-width: 17em;
+ max-height:30em; border:solid green 1px;}
footer {
position:fixed;
@@ -87,6 +89,7 @@ label {
.blogtitle {
display:inline;
}
+
.contenu {
padding-left: 20px;
}
@@ -146,7 +149,7 @@ padding-left: 20px;
}
.hidcom {
- display:none; position:fixed; z-index:-1;
+ display:none; position:fixed; z-index:2;
padding:5px; margin:5px;
background-color: rgba(0,0,40,.8);
}
@@ -162,14 +165,12 @@ padding-left: 20px;
}
@media all and (max-width: 640px) {
- aside {
- float: none;
- }
+
footer img {
max-height: 1em;
}
footer a {
font-size: xx-small;
}
- body { margin-bottom:1em; }
+ body { margin-bottom:1em; font-size: smaller; }
}
diff --git a/web/Views/Account/Index.aspx b/web/Views/Account/Index.aspx
index 9212aa60..f98c515f 100644
--- a/web/Views/Account/Index.aspx
+++ b/web/Views/Account/Index.aspx
@@ -1,6 +1,4 @@
-<%@ Page Title="Comptes utilisateur - Index" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %>
-
+<%@ Page Title="Comptes utilisateur" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %>
-
\ No newline at end of file
+Pas de contenu :-(
+
diff --git a/web/Views/Account/Login.aspx b/web/Views/Account/Login.aspx
index dc8a5804..5dafe6ba 100644
--- a/web/Views/Account/Login.aspx
+++ b/web/Views/Account/Login.aspx
@@ -11,7 +11,7 @@
<%= Html.Password( "Password" ) %>
<%= Html.ValidationMessage("Password", "*") %>
-Se souvenir du mot de passe:
+<%= Html.LabelFor(model => model.RememberMe) %>
<%= Html.CheckBox("RememberMe") %>
<%= Html.ValidationMessage("RememberMe", "") %>
<%= Html.Hidden("returnUrl",ViewData["returnUrl"]) %>
diff --git a/web/Views/Account/Profile.aspx b/web/Views/Account/Profile.aspx
index 3f8cd52f..d85baf87 100644
--- a/web/Views/Account/Profile.aspx
+++ b/web/Views/Account/Profile.aspx
@@ -56,10 +56,10 @@ Avatar
<%= Html.ValidationMessage("AvatarFile", "*") %>
- <%= Html.LabelFor(model => model.GoogleCalendar) %>
+ <%= Html.LabelFor(model => model.GoogleCalendar) %>:
-
-
+ <%= Html.Encode(Model.GoogleCalendar) %>
+ <%= Html.ActionLink("Choisir l'agenda","ChooseCalendar","Google",new { returnUrl= Request.Url.AbsolutePath }, new { @class="actionlink" }) %>
diff --git a/web/Views/Admin/Index.aspx b/web/Views/Admin/Index.aspx
index a97e5e3a..43a7cf40 100644
--- a/web/Views/Admin/Index.aspx
+++ b/web/Views/Admin/Index.aspx
@@ -1,4 +1,18 @@
-<%@ Page Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
+<%@ Page Title="Admin" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
+
+
+
<%= Html.ActionLink("Backups","Backups") %>
+
+<%= Html.ActionLink("Restaurations", "Restore") %>
+<%= Html.ActionLink("Create backup","CreateBackup") %>
+<%= Html.ActionLink("Remove user", "RemoveUser") %>
+<%= Html.ActionLink("Remove role", "RemoveRoleQuery") %>
+<%= Html.ActionLink("User list", "UserList") %>
+<%= Html.ActionLink("Role list", "RoleList") %>
+
+
+
+
diff --git a/web/Views/Admin/RemoveUserQuery.aspx b/web/Views/Admin/RemoveUser.aspx
similarity index 100%
rename from web/Views/Admin/RemoveUserQuery.aspx
rename to web/Views/Admin/RemoveUser.aspx
diff --git a/web/Views/Admin/Restore.aspx b/web/Views/Admin/Restore.aspx
index befb74d9..d5be1462 100644
--- a/web/Views/Admin/Restore.aspx
+++ b/web/Views/Admin/Restore.aspx
@@ -1,4 +1,4 @@
-<%@ Page Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
+<%@ Page Title="Restore" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
<%= Html.ValidationSummary("Restore a database backup") %>
<% using (Html.BeginForm("Restore","Admin")) { %>
diff --git a/web/Views/BackOffice/Index.aspx b/web/Views/BackOffice/Index.aspx
new file mode 100644
index 00000000..66563f3f
--- /dev/null
+++ b/web/Views/BackOffice/Index.aspx
@@ -0,0 +1,9 @@
+<%@ Page Title="Back office" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
+
+
+
+
+
+ <%= Html.ActionLink("Catalog","Catalog","FrontOffice" ) %>
+
+
diff --git a/web/Views/Blogs/UserPosts.aspx b/web/Views/Blogs/UserPosts.aspx
index b090830e..86718273 100644
--- a/web/Views/Blogs/UserPosts.aspx
+++ b/web/Views/Blogs/UserPosts.aspx
@@ -1,14 +1,9 @@
<%@ Page Title="Billets utilisateurs" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master"%>
<%@ Register Assembly="Yavsc.WebControls" TagPrefix="yavsc" Namespace="Yavsc.WebControls" %>
-<% Title = ((string) ((Profile)ViewData["BlogUserProfile"]).BlogTitle)+" - "+YavscHelpers.SiteName ; %>
-
-
+
<%
foreach (BlogEntry e in this.Model) { %>
diff --git a/web/Views/FrontOffice/Estimate.aspx b/web/Views/FrontOffice/Estimate.aspx
index 76f33247..9c1433fe 100644
--- a/web/Views/FrontOffice/Estimate.aspx
+++ b/web/Views/FrontOffice/Estimate.aspx
@@ -4,7 +4,6 @@
-
" type="text/css" media="print, projection, screen" />
diff --git a/web/Views/FrontOffice/Index.aspx b/web/Views/FrontOffice/Index.aspx
new file mode 100644
index 00000000..42ce313e
--- /dev/null
+++ b/web/Views/FrontOffice/Index.aspx
@@ -0,0 +1,11 @@
+<%@ Page Title="Front office" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage" %>
+
+
+
+
+
+ <%= Html.ActionLink("Catalog","Catalog" ) %>
+
+ <%= Html.ActionLink("Estimates","Estimates" ) %>
+
+
diff --git a/web/Views/Google/Calendar.aspx b/web/Views/Google/Calendar.aspx
deleted file mode 100644
index 7825a886..00000000
--- a/web/Views/Google/Calendar.aspx
+++ /dev/null
@@ -1,5 +0,0 @@
-<%@ Page Title="Catalog" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %>
-
-
-
-
diff --git a/web/Views/Google/ChooseCalendar.aspx b/web/Views/Google/ChooseCalendar.aspx
new file mode 100644
index 00000000..addaef08
--- /dev/null
+++ b/web/Views/Google/ChooseCalendar.aspx
@@ -0,0 +1,14 @@
+<%@ Page Title="Google calendar usage" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %>
+
+
+
+<% using ( Html.BeginForm("SetCalendar","Google") ) { %>
+<% foreach (CalendarListEntry e in Model.items.Where(x=>x.accessRole=="owner")) { %>
+
+<%=Html.Encode(e.summary)%>
+<%=Html.Encode(e.description)%>
+<% } %>
+
+<% } %>
+
+
diff --git a/web/Views/Google/DateQuery.aspx b/web/Views/Google/DateQuery.aspx
new file mode 100644
index 00000000..a3bb41e0
--- /dev/null
+++ b/web/Views/Google/DateQuery.aspx
@@ -0,0 +1,91 @@
+<%@ Page Title="Date search" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<% using ( Html.BeginForm("DateQuery","Google") ) { %>
+
+ Période de recherche:
+
+ <%= Html.LabelFor(model=>model.MinDate) %>:
+ Le
+à
+
+ <%= Html.ValidationMessageFor(model=>model.MinDate) %>
+
+
+
+<%= Html.LabelFor(model=>model.MaxDate) %>:
+ Le
+ à
+
+ <%= Html.ValidationMessageFor(model=>model.MaxDate) %>
+
+
+
+ Durée minimale :
+
+
+
+
+
+<% } %>
+<%= Html.Encode(ViewData["json"]) %>
+
+
diff --git a/web/Views/Home/Index.aspx b/web/Views/Home/Index.aspx
index eb4731ca..eb1f7069 100644
--- a/web/Views/Home/Index.aspx
+++ b/web/Views/Home/Index.aspx
@@ -5,7 +5,7 @@
« Voir le monde comme un rêve est un bon point de vue. Quand on fait un cauchemar, on se réveille et on se dit que ce n’était qu’un rêve. Il est dit que le monde où nous vivons n’en diffère en rien ».
Ghost Dog, la Voie du samouraï
-<%= Html.ActionLink("Les blogs","Index","Blogs") %>
+<%= Html.ActionLink("Les blogs","Index","Blogs",null, new { @class="actionlink" }) %>
diff --git a/web/Views/Web.config b/web/Views/Web.config
index 9c04945e..381b7060 100644
--- a/web/Views/Web.config
+++ b/web/Views/Web.config
@@ -21,7 +21,6 @@
-
@@ -29,6 +28,7 @@
+
diff --git a/web/Web.config b/web/Web.config
index dd7fab0b..97be9c12 100644
--- a/web/Web.config
+++ b/web/Web.config
@@ -115,6 +115,7 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
+
@@ -132,7 +133,7 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
-
+
@@ -179,6 +180,8 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
+
+
diff --git a/web/Web.csproj b/web/Web.csproj
index 237d381e..a1035a2a 100644
--- a/web/Web.csproj
+++ b/web/Web.csproj
@@ -117,6 +117,7 @@
+
@@ -153,7 +154,6 @@
-
@@ -213,7 +213,6 @@
-
@@ -243,7 +242,6 @@
-
@@ -255,6 +253,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/images/sign-in-with-google-s.png b/web/images/sign-in-with-google-s.png
new file mode 100644
index 00000000..ae68f838
Binary files /dev/null and b/web/images/sign-in-with-google-s.png differ
diff --git a/web/instdbws.sql b/web/instdbws.sql
index 9cad342c..dddcf5de 100644
--- a/web/instdbws.sql
+++ b/web/instdbws.sql
@@ -255,6 +255,7 @@ CREATE TABLE profiledata
gcalid character varying(255),
gtokenexpir timestamp with time zone, -- Google access token expiration date
avatar character varying(512), -- url for an avatar
+ gcalapi boolean NOT NULL DEFAULT false, -- true when user authorized to use its Google calendar
CONSTRAINT fkprofiles2 FOREIGN KEY (uniqueid)
REFERENCES profiles (uniqueid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
@@ -298,6 +299,9 @@ CREATE TABLE profiles
lastactivitydate timestamp with time zone,
lastupdateddate timestamp with time zone,
CONSTRAINT profiles_pkey PRIMARY KEY (uniqueid),
+ CONSTRAINT fk_profileusers FOREIGN KEY (username, applicationname)
+ REFERENCES users (username, applicationname) MATCH SIMPLE
+ ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT pkprofiles UNIQUE (username, applicationname)
)
WITH (
diff --git a/yavscModel/Google/AskForADate.cs b/yavscModel/Google/AskForADate.cs
new file mode 100644
index 00000000..cbb20b52
--- /dev/null
+++ b/yavscModel/Google/AskForADate.cs
@@ -0,0 +1,48 @@
+//
+// AskForADate.cs
+//
+// Author:
+// Paul Schneider
+//
+// Copyright (c) 2014 Paul Schneider
+//
+// 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 .
+using System;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+
+namespace Yavsc.Model.Google
+{
+ public class AskForADate
+ {
+ public AskForADate ()
+ {
+ MinDate = MaxDate = DateTime.Now.AddMinutes (5);
+ }
+
+ [Display(Name="MinDate",ResourceType=typeof(LocalizedText))]
+ [DataType(DataType.Date)]
+ [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
+ public DateTime MinDate { get; set; }
+
+ [Display(Name="MaxDate",ResourceType=typeof(LocalizedText))]
+ [DataType(DataType.Date)]
+ [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
+ public DateTime MaxDate { get; set; }
+
+ [Display(Name="Consultant",ResourceType=typeof(LocalizedText))]
+ public string UserName { get; set; }
+ }
+}
+
diff --git a/yavscModel/Google/AuthToken.cs b/yavscModel/Google/AuthToken.cs
index 7df2e9c9..fd1943bc 100644
--- a/yavscModel/Google/AuthToken.cs
+++ b/yavscModel/Google/AuthToken.cs
@@ -34,24 +34,6 @@ using Yavsc.Model;
namespace Yavsc.Model.Google
{
- /*
- "url": "https://plus.google.com/111395572362177872801",
- "image": {
- "url": "https://lh6.googleusercontent.com/-JqDVMPqafdA/AAAAAAAAAAI/AAAAAAAAADY/FamseW6_nl4/photo.jpg?sz=50",
- "isDefault": false
- },
- "placesLived": [
- {
- "value": "Suresnes, France",
- "primary": true
- }
- ],
- "isPlusUser": true,
- "language": "fr",
- "circledByCount": 0,
- "verified": false
-}
-*/
public class AuthToken {
public string access_token { get; set; }
diff --git a/yavscModel/Google/CalendarList.cs b/yavscModel/Google/CalendarList.cs
new file mode 100644
index 00000000..4e9b8e3c
--- /dev/null
+++ b/yavscModel/Google/CalendarList.cs
@@ -0,0 +1,45 @@
+//
+// CalendarList.cs
+//
+// Author:
+// Paul Schneider
+//
+// Copyright (c) 2014 Paul Schneider
+//
+// 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 .
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Threading;
+using System.Web.Mvc;
+using System.Configuration;
+using System.Threading.Tasks;
+using System.Text;
+using System.Net;
+using System.IO;
+using Yavsc.Model;
+
+namespace Yavsc.Model.Google
+{
+ public class CalendarList {
+ public string kind { get; set;}
+ public string etag { get; set; }
+ public string nextSyncToken { get; set; }
+ public CalendarListEntry[] items { get; set; }
+ }
+
+
+}
diff --git a/yavscModel/Google/CalendarListEntry.cs b/yavscModel/Google/CalendarListEntry.cs
new file mode 100644
index 00000000..81017b8d
--- /dev/null
+++ b/yavscModel/Google/CalendarListEntry.cs
@@ -0,0 +1,65 @@
+//
+// CalendarListEntry.cs
+//
+// Author:
+// Paul Schneider
+//
+// Copyright (c) 2014 Paul Schneider
+//
+// 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 .
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Threading;
+using System.Web.Mvc;
+using System.Configuration;
+using System.Threading.Tasks;
+using System.Text;
+using System.Net;
+using System.IO;
+using Yavsc.Model;
+
+namespace Yavsc.Model.Google
+{
+
+ public class CalendarListEntry {
+ public string kind { get; set;}
+ public string etag { get; set; }
+ public string id { get; set; }
+ public string summary { get; set; }
+ public string description { get; set; }
+ public string timeZone { get; set; }
+ public string colorId { get; set; }
+ public string backgroundColor { get; set; }
+ public string foregroundColor { get; set; }
+ public bool selected { get; set; }
+ public bool primary { get; set; }
+ public string accessRole { get; set; }
+ public class Reminder {
+ public string method { get; set; }
+ public int minutes { get; set; }
+ }
+ public Reminder[] defaultReminders { get; set; }
+ /* "notificationSettings": { "notifications":
+ [ { "type": "eventCreation", "method": "email" },
+ { "type": "eventChange", "method": "email" },
+ { "type": "eventCancellation", "method": "email" },
+ { "type": "eventResponse", "method": "email" } ] }, "primary": true },
+
+*/
+ }
+
+}
diff --git a/yavscModel/Google/People.cs b/yavscModel/Google/People.cs
index 0064c674..74846c46 100644
--- a/yavscModel/Google/People.cs
+++ b/yavscModel/Google/People.cs
@@ -34,6 +34,7 @@ using Yavsc.Model;
namespace Yavsc.Model.Google
{
+
public class People {
public string kind { get; set; }
public string etag { get; set; }
diff --git a/yavscModel/LocalizedText.Designer.cs b/yavscModel/LocalizedText.Designer.cs
index baa89e11..b8218700 100644
--- a/yavscModel/LocalizedText.Designer.cs
+++ b/yavscModel/LocalizedText.Designer.cs
@@ -106,6 +106,12 @@ namespace Yavsc.Model {
}
}
+ public static string Remember_me {
+ get {
+ return ResourceManager.GetString("Remember_me", resourceCulture);
+ }
+ }
+
public static string Title {
get {
return ResourceManager.GetString("Title", resourceCulture);
@@ -136,6 +142,18 @@ namespace Yavsc.Model {
}
}
+ public static string Date_search {
+ get {
+ return ResourceManager.GetString("Date_search", resourceCulture);
+ }
+ }
+
+ public static string Google_calendar {
+ get {
+ return ResourceManager.GetString("Google_calendar", resourceCulture);
+ }
+ }
+
public static string Description {
get {
return ResourceManager.GetString("Description", resourceCulture);
@@ -154,16 +172,34 @@ namespace Yavsc.Model {
}
}
+ public static string MinDate {
+ get {
+ return ResourceManager.GetString("MinDate", resourceCulture);
+ }
+ }
+
public static string Tex_version {
get {
return ResourceManager.GetString("Tex_version", resourceCulture);
}
}
+ public static string Consultant {
+ get {
+ return ResourceManager.GetString("Consultant", resourceCulture);
+ }
+ }
+
public static string Count {
get {
return ResourceManager.GetString("Count", resourceCulture);
}
}
+
+ public static string MaxDate {
+ get {
+ return ResourceManager.GetString("MaxDate", resourceCulture);
+ }
+ }
}
}
diff --git a/yavscModel/LocalizedText.fr.resx b/yavscModel/LocalizedText.fr.resx
index 69136599..d5c48858 100644
--- a/yavscModel/LocalizedText.fr.resx
+++ b/yavscModel/LocalizedText.fr.resx
@@ -33,4 +33,10 @@
Erreur Google : {0}
Accès refusé
Nom d'utilisateur
+ Agenda Google
+ Consultant
+ Date minimale du rendez-vous
+ Date maximale du rendez-vous
+ Recherche d'une date pour rendez-vous
+ Se souvenir du mot de passe
diff --git a/yavscModel/LocalizedText.resx b/yavscModel/LocalizedText.resx
index 8a5c9a34..2c657e91 100644
--- a/yavscModel/LocalizedText.resx
+++ b/yavscModel/LocalizedText.resx
@@ -33,4 +33,10 @@
Google error : {0}
Access denied
User name
-
+ Google calendar
+ Consultant
+ Minimal date for the rendez-vous
+ Maximal date for the rendez-vous
+ Date search for a rendez-vous
+ Remember me
+
diff --git a/yavscModel/RolesAndMemebers/LoginModel.cs b/yavscModel/RolesAndMemebers/LoginModel.cs
index 8ef32144..3d8e0b0e 100644
--- a/yavscModel/RolesAndMemebers/LoginModel.cs
+++ b/yavscModel/RolesAndMemebers/LoginModel.cs
@@ -16,7 +16,7 @@ namespace Yavsc.Model.RolesAndMembers
[RegularExpression("([a-z]|[A-Z]|[-_.~#{}`'\\^])+")]
public string Password { get; set; }
- [Display(Name = "Se souvenir du mot de passe")]
+ [Display(Name = "Remember_me",ResourceType=typeof(LocalizedText))]
public bool RememberMe { get; set; }
}
}
diff --git a/yavscModel/RolesAndMemebers/Profile.cs b/yavscModel/RolesAndMemebers/Profile.cs
index 01d29488..0a128d47 100644
--- a/yavscModel/RolesAndMemebers/Profile.cs
+++ b/yavscModel/RolesAndMemebers/Profile.cs
@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Profile;
using System.Web.Security;
+using System.Web;
namespace Yavsc.Model.RolesAndMembers
{
@@ -78,7 +79,7 @@ namespace Yavsc.Model.RolesAndMembers
[DisplayName ("Clé RIB")]
public int BankedKey { get; set; }
- [Display(Name="Google Calendar")]
+ [Display(Name="Google_calendar",ResourceType=typeof(LocalizedText))]
public string GoogleCalendar { get; set; }
public bool IsBankable { get {
@@ -107,6 +108,8 @@ namespace Yavsc.Model.RolesAndMembers
{
}
+ public bool RememberMe { get; set; }
+
public Profile (ProfileBase profile)
{
object b = profile.GetPropertyValue ("BlogVisible");
@@ -163,6 +166,8 @@ namespace Yavsc.Model.RolesAndMembers
s = profile.GetPropertyValue ("BankedKey");
BankedKey = (s == null) ? 0 : (s is DBNull)? 0 : (int)s;
+ s = profile.GetPropertyValue ("gcalid");
+ GoogleCalendar = (s is DBNull)? null : (string) s;
}
}
}
diff --git a/yavscModel/YavscModel.csproj b/yavscModel/YavscModel.csproj
index 4feebf2d..3ede5ac0 100644
--- a/yavscModel/YavscModel.csproj
+++ b/yavscModel/YavscModel.csproj
@@ -88,6 +88,9 @@
+
+
+