Files
ayanova7/source/ri/ri/util/util.cs

4251 lines
177 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using CSLA.Security;
using GZTW.AyaNova.BLL;
using System.Text;
using System.Drawing;
using System.Reflection;
using System.Collections;
namespace ri.util
{
public static class ay
{
#region VERSION
public static string Version = "v7.6";
#endregion version
#region caching helpers
/// <summary>
/// cache something, defaults to 2 minutes
/// </summary>
/// <param name="key"></param>
/// <param name="o"></param>
/// <param name="minutes"></param>
public static void cacheData(string key, object o, int minutes = 2)
{
System.Web.HttpContext.Current.Cache.Insert(key,
o,
null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(minutes));
}
public static object getCacheData(string key)
{
return System.Web.HttpContext.Current.Cache[key];
}
public static object clearCacheData(string key)
{
return System.Web.HttpContext.Current.Cache.Remove(key);
}
#endregion caching helpers
#region global values
#region IntegrationSimple data
private static Guid RIIntegrationID { get { return new Guid("{F3E11847-B148-4CDC-88A7-BDB144EE5743}"); } }
//public static Guid RIIntegrationID { get { return new Guid("{6946040C-1B50-4eab-BE08-A0E93DB7449F}"); } }
private static RIIntegrationData mRIIntegrationData = null;
public static RIIntegrationData IntegrationData
{
get
{
if (mRIIntegrationData == null)
{
mRIIntegrationData = new RIIntegrationData();
mRIIntegrationData.XMLData = RIIntegration.AIString;
}
return mRIIntegrationData;
}
}
public static void SaveIntegrationData()
{
//trigger is dirty
RIIntegration.SyncCheckPoint = DBUtil.CurrentWorkingDateTime.ToString();//case 1163
RIIntegration.AIString = IntegrationData.XMLData;
mRIIntegration = (IntegrationSimple)RIIntegration.Save();
// HttpContext.Current.Cache.Remove("IntegrationData");
}
private static IntegrationSimple RIIntegration
{
get
{
//It's in memory?
if (mRIIntegration != null)
return mRIIntegration;
////It's in the cache?
//if (HttpContext.Current.Cache["IntegrationData"] != null)
//{
// mRIIntegration = (IntegrationSimple)HttpContext.Current.Cache["IntegrationData"];
// return mRIIntegration;
//}
//check if there is an integration for wbi already
if (!IntegrationSimple.IntegrationExists(RIIntegrationID))
{
IntegrationSimple i = IntegrationSimple.NewItem(RIIntegrationID);
i.AppVersion = Version;
i.Name = "AyaNova RI";
i.AIString = new RIIntegrationData().XMLData;
mRIIntegration = (IntegrationSimple)i.Save();
}
else
{
//try
//{
mRIIntegration = IntegrationSimple.GetItem(RIIntegrationID);
//}
//catch
//{
// //Added as insurance code, on my dev station but no where else getting a serialization exception
// //claiming that it can't find wbi v4.0.0.0 when we've been beyond that for some time without error and deployed
// //4.0.2 doesn't get this error
// IntegrationSimple.DeleteItem(RIIntegrationID);
// IntegrationSimple i = IntegrationSimple.NewItem(RIIntegrationID);
// i.AppVersion = Version;
// i.Name = "AyaNova RI";
// i.AIString = new RIIntegrationData();
// mRIIntegration = (IntegrationSimple)i.Save();
//}
}
////Convert for case 613
//if (!(mRIIntegration.AIObject is RIIntegrationData))
//{
// //convert to new (v4 case 613 integrationdata object from old
// //single guid that stored workorder report id
// Guid mWorkorderReportID = (Guid)mRIIntegration.AIObject;
// mRIIntegration.AIObject = new RIIntegrationData();
// ((RIIntegrationData)mRIIntegration.AIObject).ClientWorkorderReportID = mWorkorderReportID;
// mRIIntegration = (IntegrationSimple)mRIIntegration.Save();
//}
//We have a current integration object so put it in the cache...
//HttpContext.Current.Cache.Insert("IntegrationData", mRIIntegration,
// null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
//...and return it
return mRIIntegration;
}
}
private static IntegrationSimple mRIIntegration=null;
#endregion integration data
//public static bool _DEBUG_MODE = true;
//#ffffe0 faded paper look (light orangy yellow)
public static string ColorInactiveGray = "#e2e2e2";//light gray
/// <summary>
/// Get the current user record
/// </summary>
public static User CurrentUser
{
get
{
return User.GetItem((((BusinessPrincipal)Thread.CurrentPrincipal).ID));
}
}
/// <summary>
/// Get the current user record
/// </summary>
public static Guid CurrentUserID
{
get
{
return (((BusinessPrincipal)Thread.CurrentPrincipal).ID);
}
}
#endregion
#region Form Parsers
/// <summary>
/// string to Guid, guid empty on empty string
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static Guid parseGuid(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "parseGuid");
#endif
string s=string.Empty;
string autoFieldName=fieldName + "_ayauto";
//first check if user entered a - or a [space]- or just wiped out entry indicating no selection
if (f.AllKeys.Contains(autoFieldName))
{
s = f[autoFieldName];
if (s == "-" || s == " -" || string.IsNullOrWhiteSpace(s) || s == PickListFactory.JQUICompliantEmptySelectionCharacter)
return Guid.Empty;
}
s = f[fieldName];
if (string.IsNullOrEmpty(s)) return Guid.Empty;
return new Guid(s);
}
/// <summary>
/// string to bool, false on empty string
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static bool parseBool(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "parseBool");
#endif
string s = f[fieldName];
return parseBool(s);
}
public static bool parseBool(string s)
{
//The following is necessary because for some bizarre reason checkboxes are created by
//mvc in pairs with a hidden false so you get "true,false" on true and "false" on false
if (s.Contains(','))
s = s.Split(',')[0];
if (string.IsNullOrEmpty(s)) return false;
return bool.Parse(s);
}
/// <summary>
/// string to decimal, false on empty string
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static decimal parseDecimal(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "parseDecimal");
#endif
return parseDecimalDirect(f[fieldName]);
}
/// <summary>
/// Directly parse a decimal containing string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static decimal parseDecimalDirect(string s)
{
decimal d = 0;
if (string.IsNullOrEmpty(s)) return d;
if (!decimal.TryParse(s.ToString(), out d))
decimal.TryParse(s.ToString(),
NumberStyles.Currency,
System.Threading.Thread.CurrentThread.CurrentCulture, out d);
return d;
}
/// <summary>
/// string to decimal, false on empty string
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static long parseLong(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "parseLong");
#endif
long d = 0;
string s = f[fieldName];
if (string.IsNullOrEmpty(s)) return d;
if (!long.TryParse(s.ToString(), out d))
long.TryParse(s.ToString(),
NumberStyles.Currency,
System.Threading.Thread.CurrentThread.CurrentCulture, out d);
return d;
}
/// <summary>
///
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static int ParseInt(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseInt");
#endif
return parseIntDirect(f[fieldName]);
}
/// <summary>
/// Directly parse a int containing string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static int parseIntDirect(string s)
{
int d = 0;
if (string.IsNullOrEmpty(s)) return d;
int.TryParse(s.ToString(), out d);
return d;
}
/// <summary>
///
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static long ParseLong(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseLong");
#endif
long d = 0;
string s = f[fieldName];
if (string.IsNullOrEmpty(s)) return d;
long.TryParse(s.ToString(), out d);
return d;
}
//Attempts to parse a string based on current thread culture
//if that fails then tries the invariant culture (to catch US users who have accidentally
//set their web browser to some other language or international users
//browsing through a US site for the most part as it won't work
//for other circumstances, so supporting most common scenario)
//if it can't figure it out at all then it will return an empty dbnull date
//the ideal fix is of course to convert dates to the invariant culture when they are
//first entered into AyaNova in custom fields where this is mostly used
public static object ParseDateToDbValue(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseDateToDbValue");
#endif
string s = f[fieldName];
if (string.IsNullOrEmpty(s)) return System.DBNull.Value;
DateTime dt = new DateTime();
if (!DateTime.TryParse(s.ToString(), out dt))
if (!DateTime.TryParse(s.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
return System.DBNull.Value;
return dt;
}
/// <summary>
/// Parse date / date/time string and returns a datetime object
/// or DateTime.minvalue if unparseable.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static DateTime ParseDateTimeToDateTime(string s)
{
DateTime dt = new DateTime();
if (DateTime.TryParse(s, out dt))
{
return dt;
}
else
{
if (DateTime.TryParse(s.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
return dt;
}
return DateTime.MinValue;
}
/// <summary>
/// Convert string with linefeeds only (\n) but no carriage returns (\r) to
/// CR/LF combination instead (\r\n).
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ParseMultiLineText(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseMultiLineText");
#endif
string s = f[fieldName];
if (string.IsNullOrEmpty(s)) return string.Empty;
//Only do the conversion if there are not existing \r
if (!s.Contains("\r\n"))
return s.Replace("\n", "\r\n");
return s;
}
/// <summary>
/// Parses a text based autocomplete dropdown like the address fields
/// handles if item is new or selected from the drop down existing item
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static string ParseTextAutoComplete(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseTextAutoComplete");
#endif
string fieldNameAuto = fieldName + "_ayauto";
//give priority to fieldNameAuto as this is the actual value typed in
if (string.IsNullOrWhiteSpace(f[fieldNameAuto]))
{
if (string.IsNullOrWhiteSpace(f[fieldName]))
{
return string.Empty;
}
else
{
return f[fieldName];
}
}
else
{
return f[fieldNameAuto];
}
}
/// <summary>
///
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static void ParseScheduleMarkerSourceType(string fieldName, FormCollection f, ScheduleMarker sm)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseScheduleMarkerSourceType");
#endif
string s = f[fieldName];
if (string.IsNullOrEmpty(s) || !s.Contains(",")) return;
string[] sval = s.Split(',');
sm.SourceID = new Guid(sval[1]);
switch (sval[0])
{
case "GLOBAL":
sm.ScheduleMarkerSourceType = ScheduleMarkerSourceTypes.Global;
break;
case "ZONE":
sm.ScheduleMarkerSourceType = ScheduleMarkerSourceTypes.DispatchZone;
break;
case "REGION":
sm.ScheduleMarkerSourceType = ScheduleMarkerSourceTypes.Regional;
break;
case "GROUP":
sm.ScheduleMarkerSourceType = ScheduleMarkerSourceTypes.ScheduleableUserGroup;
break;
case "USER":
sm.ScheduleMarkerSourceType = ScheduleMarkerSourceTypes.User;
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="fieldName"></param>
/// <param name="f"></param>
/// <returns></returns>
public static int ParseColor(string fieldName, FormCollection f)
{
#if(DEBUG)
diagCheckKey(fieldName, f, "ParseColor");
#endif
int d = 0;
string s = f[fieldName];
if (string.IsNullOrEmpty(s)) return d;
d = argbFromHexColor(s);
return d;
}
#if(DEBUG)
/// <summary>
/// Used for development to catch form design errors where the
/// field to be parsed was copied and pasted but the string name
/// of the field was not changed from it's copied value
/// </summary>
/// <param name="collection"></param>
/// <param name="key"></param>
/// <returns></returns>
private static void diagCheckKey(string keyName, System.Collections.Specialized.NameValueCollection f, string methodName)
{
if (f.Get(keyName) == null)
if (!f.AllKeys.Contains(keyName))
throw new System.ArgumentOutOfRangeException("Coding error in Util->" + methodName + ": fieldname \"" + keyName + "\" does not exist. Copy and Paste error? Check field name in controller UPDATE method!");
}
#endif
#endregion
#region Localizer
/// <summary>
/// Get the localized text based on the current users language
/// from the web app cache
///
/// If the cache doesn't contain a localizedtexttable object for the language
/// requested, populate it first
///
/// (caches for 30 minutes from last access)
/// </summary>
/// <param name="Key"></param>
/// <returns></returns>
static public string lt(string Key)
{
if (string.IsNullOrEmpty(Key)) return "LT_KEY_NOT_FOUND: " + Key;
return LocaleTextTable.GetLocalizedText(Key).Replace("&", "&amp;");
}
static public LocalizedTextTable LocaleTextTable
{
get
{
//try and get it from the cache first
if (string.IsNullOrEmpty(((BusinessPrincipal)Thread.CurrentPrincipal).Language)) return null;
string language = ((BusinessPrincipal)Thread.CurrentPrincipal).Language;
LocalizedTextTable l = (LocalizedTextTable)HttpContext.Current.Cache["LT_" + language];
if (l == null)
{
//Not in cache so load it into cache
l = LocalizedTextTable.Load(language);
HttpContext.Current.Cache.Insert("LT_" + language, l,
null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
}
return l;
}
}
/// <summary>
/// Takes a broken rule text and xforms it into the localized version
/// applying all formatting as required
/// </summary>
/// <param name="BrokenRuleString"></param>
/// <returns></returns>
internal static string BrokenRuleLocalizer(string BrokenRuleString)
{
if (BrokenRuleString == null) return null;
if (BrokenRuleString == "") return "";
//Localize and format the string
//this string comes to us as a set of comma delimited localized text key strings
//i.e. "Error.Object.RequiredFieldEmpty,Client.Label.Name"
//the first key translates often to a string with format characters in it such as
//"{0} is not a valid value for the {1} field
//The second and following keys are the values to be inserted in those format positions
//This code makes an object array of all the second and following localized text strings
//and then passes that to the string.format function along with the first string
string[] sarray = BrokenRuleString.Split(',');
object[] sitems = new object[sarray.GetLength(0) - 1];
for (int x = 1; x < sarray.GetLength(0); x++)
{
sitems[x - 1] = lt(sarray[x]);
}
return string.Format(lt(sarray[0]), sitems);
}
#endregion
#region common dialog prompts
public static string PromptForSave()
{
return lt("UI.Label.SavePrompt");
}
public static string PromptForBrokenRulesCancelSave()
{
return lt("UI.Label.UnsaveableDueToBrokenRulesPrompt");
}
public static string PromptForDelete()
{
return lt("UI.Label.DeletePrompt");
}
public static string PromptForDeleteWorkorder()
{
return lt("UI.Label.DeleteWorkorderPrompt");
}
public static string PromptFromLocaleKey(string LocaleKey)
{
return lt(LocaleKey);
}
public static string PromptForAdministratorOnly()
{
return lt("Error.Security.AdministratorOnlyMessage");
}
public static string PromptForRestricted()
{
return lt("Error.Trial.Restricted");
}
//User outside client region warning message, put it here because it's called from both schedule form and workorder form
public static string PromptForSchedTechOutsideRegionWarning(Guid UserID, Guid ClientID)
{
string ret = string.Empty;
if (AyaBizUtils.Lite) return ret;
if (UserID == Guid.Empty) return ret;
if (ClientID == Guid.Empty) return ret;
if (!AyaBizUtils.InClientRegion(ClientID, UserID))
{
return lt("WorkorderItemScheduledUser.Label.Warn.OutOfRegion");
}
return ret;
}
#region Record History
public static string RecordHistoryText(Guid Creator, Guid Modifier, string CreatedDate, string ModifiedDate)
{
StringBuilder sb = new StringBuilder();
sb.Append(lt("UI.RecordHistory.Creator"));
sb.Append(": ");
sb.Append(GetName(Creator));
sb.Append("\\r");
sb.Append(lt("UI.RecordHistory.Created"));
sb.Append(": ");
sb.Append(CreatedDate);
sb.Append("\\r");
sb.Append("\\r");
//sb.Append("<br /><br />");
sb.Append(lt("UI.RecordHistory.Modifier"));
sb.Append(": ");
sb.Append(GetName(Modifier));
sb.Append("\\r");
//sb.Append("<br />");
sb.Append(lt("UI.RecordHistory.Modified"));
sb.Append(": ");
sb.Append(ModifiedDate);
sb.Append("\\r");
//sb.Append("<br />");
return sb.ToString();
}
/// <summary>
/// Build up a name string from passed in user record id
/// </summary>
/// <param name="UserID"></param>
/// <returns></returns>
private static string GetName(Guid UserID)
{
UserPickList upl = UserPickList.GetListOfOneSpecificUser(UserID);
if (upl.Count == 0) return "-";
return upl[0].Name.Replace("'","").Replace("\"","");//case 2070 strip out apostrophes and quotes
}
#endregion Record history
#endregion
#region Rights helpers
/// <summary>
/// Get rights to object and set viewbag rights values
/// </summary>
/// <param name="viewBag"></param>
/// <param name="rot"></param>
public static void setViewBagRights(dynamic viewBag, RootObjectTypes rot)
{
int n = AyaBizUtils.Right(rot);
viewBag.ayCanView = n > (int)SecurityLevelTypes.NoAccess;
viewBag.ayCanEdit = n > (int)SecurityLevelTypes.ReadOnly;
viewBag.ayReadOnly = !viewBag.ayCanEdit;
viewBag.ayCanDelete = n > (int)SecurityLevelTypes.ReadWrite;
}
/// <summary>
/// force viewbag rights settings to chosen security level
/// </summary>
/// <param name="viewBag"></param>
/// <param name="sLevel"></param>
public static void setViewBagRights(dynamic viewBag, SecurityLevelTypes sLevel)
{
viewBag.ayCanView = sLevel > SecurityLevelTypes.NoAccess;
viewBag.ayCanEdit = sLevel > SecurityLevelTypes.ReadOnly;
viewBag.ayReadOnly = !viewBag.ayCanEdit;
viewBag.ayCanDelete = sLevel > SecurityLevelTypes.ReadWrite;
}
#endregion rights helpers
#region Form error handler and helpers
private static string genErr(string field, ayBrokenRules fe)
{
if (null == fe || !fe.FieldErrors.ContainsKey(field)) return "";
//TODO: make this a red error blob with tooltip of actual errors
return "<p class=\"text-danger\">* " + fe.FieldErrors[field] + "</p>\r\n";
}
/// <summary>
/// Return a validation error html fragment if there is an error for the field specified
/// else nothing
/// </summary>
/// <param name="field"></param>
/// <param name="fe"></param>
/// <returns></returns>
public static MvcHtmlString err(string field, ayBrokenRules fe)
{
return new MvcHtmlString(genErr(field, fe));
}
private static TempDataDictionary tempData = null;
public static bool hasGeneralError
{
get
{
if (null == tempData) return false;
return tempData["lastError"] != null;
}
}
public static void setGeneralError(TempDataDictionary TempData, Exception ex)
{
while (ex.InnerException != null)
ex = ex.InnerException;
setGeneralError(TempData,exceptionToHumanString(ex));
}
public static void setGeneralError(TempDataDictionary TempData, string msg)
{
tempData = TempData;
if (null != tempData["lastError"])
tempData["lastError"] += "\r\n" + msg;
else
tempData["lastError"] = msg;
}
public static MvcHtmlString getGeneralError()
{
string s = tempData["lastError"].ToString();
tempData.Remove("lastError");
return new MvcHtmlString("<strong>" + s + "</strong>");
}
public static string exceptionToHumanString(Exception ex)
{
//clear out the target invocation exception, it's always useless
if (ex is System.Reflection.TargetInvocationException && ex.InnerException != null)
ex = ex.InnerException;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendLine("An error was detected:");
if (ex.InnerException == null)
{
sb.AppendLine(ex.Message);
sb.AppendLine(ex.StackTrace);
}
else
{
sb.AppendLine("Outer exception:");
sb.AppendLine(ex.Message);
sb.AppendLine(ex.StackTrace);
int n = 0;
while (ex.InnerException != null)
{
ex = ex.InnerException;
n++;
sb.AppendLine("============================================");
sb.AppendLine("Inner exception :" + n.ToString());
sb.AppendLine(ex.Message);
sb.AppendLine(ex.StackTrace);
}
}
return sb.ToString();
}
#region SQL error
/// <summary>
/// translates obscure sql errors into html compatible, human readable form,
/// and returns or throws the exception if it's not a sql error
/// </summary>
/// <param name="ex"></param>
static public string GetSQLError(Exception ex)
{
if (ex.InnerException == null) throw ex;
string sErrorMessage = "";
if (ex.InnerException is FirebirdSql.Data.FirebirdClient.FbException)
{//TODO: this is forcing a dependancy on the firebird sql driver
//Move this down to the database level
FirebirdSql.Data.FirebirdClient.FbException fex = (FirebirdSql.Data.FirebirdClient.FbException)ex.InnerException;
switch (fex.ErrorCode)
{
case 335544466:
sErrorMessage = lt("Error.DB.ForeignKeyViolation") + "\r\n\r\n----------------------------------------\r\n" + fex.Message;
break;
default://rethrow it, it's nothing we can handle here
throw fex;
}
}
else if (ex.InnerException is System.Data.SqlClient.SqlException)
{
System.Data.SqlClient.SqlException sex = (System.Data.SqlClient.SqlException)ex.InnerException;
switch (sex.Number)
{
case 547:
sErrorMessage = lt("Error.DB.ForeignKeyViolation") + "\r\n\r\n----------------------------------------\r\n" + sex.Message;
break;
default://rethrow it, it's nothing we can handle here
throw sex;
}
}
else
throw ex.InnerException;
return StringWebify(sErrorMessage);
}
#endregion
#endregion
#region Form control generators
#region Private builders
static private string formGroupStart(string name)
{
return "\r\n<div id=\"" + name + "_group" + "\" class=\"form-group col-md-6 col-lg-3\">\r\n";
}
static private string formGroupEnd()
{
return "</div>\r\n";
}
static private string inputGroupStart()
{
return "<div class=\"input-group\">\r\n";
}
static private string inputGroupEnd()
{
return "\r\n</div>\r\n";
}
static private string clearableIGButton(string clearableInputFieldName, string clearableInputFieldType)
{
return "<span onclick=\"ayClearInput('" +
clearableInputFieldName +
"', '" + clearableInputFieldType +
"')\" class=\"input-group-addon ay-ig-button\"><span class=\"glyphicon glyphicon-remove\"></span></span>";
}
static private string getAllIGButton(string fieldName)
{
//fetch all button
return "<span onclick=\"ayGetAll('" +
fieldName +
"')\" class=\"input-group-addon ay-ig-button\"><span class=\"glyphicon glyphicon-cloud-download\"></span></span>";
}
static private string genLabel(string LocalizedTextKey, string LabelFor)
{
// <label for="name">{{aytxt('userName')}}</label>
return "<label for=\"" + LabelFor + "\">" + ay.lt(LocalizedTextKey) + "</label>\r\n";
}
static private string genLabel(string LocalizedTextKey, string LabelFor, string LinkUrl)
{
string lwrLink = LinkUrl.ToLowerInvariant();
bool isTel = lwrLink.StartsWith("tel:");
bool isEmail = (!isTel && lwrLink.StartsWith("mailto:"));
//Since http is the default it's considered http only if no other
//known protocol is recognized first
bool isHttp = (!isTel && !isEmail);
string targ = string.Empty;
if (isHttp)
targ = " target=\"_blank\"";
return "<label for=\"" + LabelFor + "\">" + ay.lt(LocalizedTextKey) + "</label><a class=\"btn btn-sm\" href=\"" + LinkUrl + "\"" + targ + " role=\"button\"><span class=\"ay-action-link glyphicon glyphicon-flash\"></span></a>\r\n";
}
static private string genTextEditor(string name, string value, dynamic viewBag, int maxLength, bool required)
{
// <input class="form-control" type="text" id="name" name="name" required>
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
string clearStart = string.Empty;
string clearEnd = string.Empty;
string ro = "";
//maxlength
//default for a text input is 255
string max = "maxlength=\"255\"";
if (maxLength > 0)
{
max = "maxlength=\"" + maxLength.ToString() + "\"";
}
if (isReadOnly)
{
ro = " readonly";
max = string.Empty;
}
else
{
clearStart = inputGroupStart();
clearEnd = clearableIGButton(name, "text") + inputGroupEnd();
}
return clearStart + "<input class=\"form-control\" " + max + " type=\"text\" id=\"" + name + "\" name=\"" + name + "\" value=\"" + value + "\"" + req + ro + ">\r\n" + clearEnd;
}
static private string genSelect(string name, Dictionary<string, string> items, string selectedValue, dynamic viewBag, bool required)
{
//<!-- The second value will be selected initially -->
//<select required name="select">
// <option value="value1">Value 1</option>
// <option value="value2" selected>Value 2</option>
// <option value="value3">Value 3</option>
//</select>
//As of today it appears the required attribute for selects is in the html5 spec but not supported by major browsers but it *is* in the spec so...
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
if (isReadOnly)
{
//read only so just generate a read only text edit instead
return genTextEditor(name, items[selectedValue], viewBag, 0, false);
}
else
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<select class=\"form-control\" " + req + " name=\"" + name + "\" id=\"" + name + "\">");
if (items != null)//items will be null in case of dynamically filled selects
{
foreach (KeyValuePair<string, string> i in items)
{
//Key is the hidden internal value and value is the visible value confusingly.
sb.Append("<option value=\"" + i.Key + "\"");
if (i.Key == selectedValue)
sb.Append(" selected");
sb.AppendLine(">" + i.Value + "</option>");
}
}
sb.AppendLine("</select>");
return sb.ToString();
}
}
static private string genNumberEditor(string name, string value, bool floatingPoint, dynamic viewBag, bool required)
{
// <input class="form-control" type="number" id="name" name="name" required>
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
string steps = "";
if (floatingPoint)
steps = " step=\"any\"";
//Note: this is what it was originally but up down arrows would then only do steps of .01
//steps = " step=\"0.01\"";
return (isReadOnly ? "" : inputGroupStart()) + "<input class=\"form-control\" type=\"number\" id=\"" + name +
"\" name=\"" + name + "\" value=\"" + value + "\"" + req + steps + (isReadOnly ? " readonly" : "") + ">\r\n" +
(isReadOnly ? "" : clearableIGButton(name, "text") + inputGroupEnd());//bugbug? Should this be "number" instead of "text" or doesn't it matter?
}
//For now this is just a numeric input since there is no html 5 currency entry and
//it would be fuckery to put the localized currency symbol in so instead just treat as a number
static private string genCurrencyEditor(string name, string value, dynamic viewBag, bool required)
{
// <input class="form-control" type="number" id="name" name="name" required>
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
return (isReadOnly ? "" : inputGroupStart()) + "<input class=\"form-control\" type=\"number\" step=\"any\" id=\"" + name +
"\" name=\"" + name + "\" value=\"" + value + "\"" + req + (isReadOnly ? " readonly" : "") + ">\r\n" +
(isReadOnly ? "" : clearableIGButton(name, "text") + inputGroupEnd());//bugbug? Should this be "number" instead of "text" or doesn't it matter?
}
static private string genColorEditor(string name, string value, dynamic viewBag, bool required)
{
// <input class="form-control" type="color" id="name" name="name" required>
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
return ("<input class=\"form-control\" type=\"color\" id=\"" + name +
"\" name=\"" + name + "\" value=\"" + value + "\"" + req + (isReadOnly ? " readonly" : "") + ">\r\n");
}
static private string genTextAreaEditor(string name, string value, dynamic viewBag, int maxLength, bool required)
{
// <input class="form-control" type="text" id="name" name="name" required>
string req = "";
if (required) req = " required=\"\"";
//maxlength
//default for a textarea is 65535
string max = "maxlength=\"65535\"";
if (maxLength > 0)
{
max = "maxlength=\"" + maxLength.ToString() + "\"";
}
bool isReadOnly = FieldIsReadOnly(name, viewBag);
if (isReadOnly)
max = string.Empty;
return (isReadOnly ? "" : inputGroupStart()) +
"<textarea rows=\"4\" cols=\"80\" class=\"form-control\" " + max + " id=\"" + name + "\" name=\"" + name + "\"" + req +
(isReadOnly ? " readonly" : "") + ">" + value +
"</textarea>\r\n" +
(isReadOnly ? "" : clearableIGButton(name, "textarea") + inputGroupEnd());
}
static private string genCheckBox(string name, bool value, dynamic viewBag)
{
string sChecked = "";
if (value)
{
sChecked = "checked";
}
bool isReadOnly = FieldIsReadOnly(name, viewBag);
//Note extra hidden input to deal with false values of checkbox
//http://stackoverflow.com/questions/7600817/how-to-submit-unchecked-checkbox-also
return "<input class=\"form-control\" type=\"checkbox\" " + sChecked + " name=\"" + name + "\" id=\"" + name + "\" value=\"true\"" + (isReadOnly ? " disabled=\"disabled\"" : "") + "/><input type=\"hidden\" name=\"" + name + "\" value=\"false\" />\r\n";
}
/// <summary>
/// Guid value version
/// </summary>
/// <param name="FieldName"></param>
/// <param name="value"></param>
/// <param name="viewBag"></param>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="activeOnly"></param>
/// <param name="regional"></param>
/// <param name="placeholder"></param>
/// <returns></returns>
private static string genAutocomplete(string FieldName, Guid value, dynamic viewBag, UrlHelper url, string listKey, bool activeOnly, bool regional, string placeholder)
{ //inspired by:
//http://dzapart.blogspot.ca/2013/04/auto-complete-controll-with-aspnet-mvc.html
//Generate this:
//<input data-action="/AyaNovaRI/ayList/GetList" data-active-only="True" data-autocomplete="True" data-list-type="region"
//data-regional="True" data-value-name="RegionID" id="RegionID_ayauto" name="RegionID_ayauto" type="text" value="Region: ALL REGIONS" />
Guid id = new Guid(value.ToString());
string visibleValue = PickListFactory.GetItemName(id, listKey);
bool isReadOnly = FieldIsReadOnly(FieldName, viewBag);
if (isReadOnly)
{
//read only so just generate a read only text edit instead
return genTextEditor(FieldName, visibleValue, viewBag,0, false);
}
else
{
string hidden = "<input type=\"hidden\" id=\"" + FieldName + "\" name=\"" + FieldName + "\" value=\"" + value.ToString() + "\" />\r\n";
string vis = inputGroupStart() +
getAllIGButton(FieldName) +
"<input class=\"form-control\" data-action=\"" + url.Action("GetList", "ayList") + "\" data-active-only=\"" + activeOnly.ToString() + "\" data-autocomplete=\"True\" data-list-type=\"" +
listKey + "\" data-regional=\"" + regional.ToString() + "\" data-value-name=\"" + FieldName + "\" id=\"" + FieldName + "_ayauto\" name=\"" + FieldName + "_ayauto\" type=\"text\" " +
" value=\"" + visibleValue + "\"/>" +
clearableIGButton(FieldName, "auto") + inputGroupEnd();
var builder = new System.Text.StringBuilder();
builder.AppendLine(hidden);
builder.AppendLine(vis);
return builder.ToString();
}
}
/// <summary>
/// string value version
/// </summary>
/// <param name="FieldName"></param>
/// <param name="value"></param>
/// <param name="viewBag"></param>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="activeOnly"></param>
/// <param name="regional"></param>
/// <param name="placeholder"></param>
/// <returns></returns>
private static string genAutocomplete(string FieldName, string value, dynamic viewBag, UrlHelper url, string listKey, bool activeOnly, bool regional, string placeholder)
{ //inspired by:
//http://dzapart.blogspot.ca/2013/04/auto-complete-controll-with-aspnet-mvc.html
//Generate this:
//<input data-action="/AyaNovaRI/ayList/GetList" data-active-only="True" data-autocomplete="True" data-list-type="region"
//data-regional="True" data-value-name="RegionID" id="RegionID_ayauto" name="RegionID_ayauto" type="text" value="Region: ALL REGIONS" />
bool isReadOnly = FieldIsReadOnly(FieldName, viewBag);
if (isReadOnly)
{
//read only so just generate a read only text edit instead
return genTextEditor(FieldName, value, viewBag,0, false);
}
else
{
//visible value *is* the value which is a string in this case
string hidden = "<input type=\"hidden\" id=\"" + FieldName + "\" name=\"" + FieldName + "\" value=\"" + value.ToString() + "\" />\r\n";
string vis = inputGroupStart() +
"<input class=\"form-control\" data-action=\"" + url.Action("GetList", "ayList") + "\" data-active-only=\"" + activeOnly.ToString() + "\" data-autocomplete=\"True\" data-list-type=\"" +
listKey + "\" data-regional=\"" + regional.ToString() + "\" data-value-name=\"" + FieldName + "\" id=\"" + FieldName + "_ayauto\" name=\"" + FieldName + "_ayauto\" type=\"text\" " +
" value=\"" + value + "\"/>" +
clearableIGButton(FieldName, "auto") + inputGroupEnd();
var builder = new System.Text.StringBuilder();
builder.AppendLine(hidden);
builder.AppendLine(vis);
return builder.ToString();
}
}
static private string genDateTimeEditor(string name, string value, dynamic viewBag, bool required)
{
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
return "<input class=\"form-control\" type=\"datetime-local\" step=\"any\" id=\"" + name + "\" name=\"" + name + "\"" + value + req + (isReadOnly ? " readonly" : "") + ">\r\n";
}
static private string genDateEditor(string name, string value, dynamic viewBag, bool required)
{
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
return "<input class=\"form-control\" type=\"date\" step=\"any\" id=\"" + name + "\" name=\"" + name + "\"" + value + req + (isReadOnly ? " readonly" : "") + ">\r\n";
}
static private string genTimeEditor(string name, string value, dynamic viewBag, bool required)
{
string req = "";
if (required) req = " required=\"\"";
bool isReadOnly = FieldIsReadOnly(name, viewBag);
return "<input class=\"form-control\" type=\"time\" step=\"1\" id=\"" + name + "\" name=\"" + name + "\"" + value + req + (isReadOnly ? " readonly" : "") + ">\r\n";
}
static private string genMultiSelect(string name, string title, Dictionary<string, string> items, string selectedValues, dynamic viewBag)
{
//example html generated, the last two options are selected
//<fieldset>
// <legend>What is Your Favorite Pet?</legend>
// <input type="checkbox" name="animal" value="Cat" />Cats <br />
// <input type="checkbox" name="animal" value="Dog" checked/>Dogs<br />
// <input type="checkbox" name="animal" value="Bird" checked/>Birds<br />
// <input type="submit" value="Submit now" />
//</fieldset>
//<div class="checkbox">
// <label>
// <input type="checkbox" value="">
// Option one is this and that&mdash;be sure to include why it's great
// </label>
//</div>
bool isReadOnly = FieldIsReadOnly(name, viewBag);
if (isReadOnly)
{
//read only so just generate a read only text edit instead
//BUGBUG: Copied from genSelect, is this relevant or will work?... Or even matter?
return genTextEditor(name, selectedValues, viewBag,0, false);
}
else
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<fieldset>");
sb.AppendLine("<legend>" + title + "</legend>");
sb.AppendLine("<div id=\"" + name + "_AYITEMS" + "\" class=\"ay-scroll\">");
foreach (KeyValuePair<string, string> i in items)
{
//Key is the hidden internal value and value is the visible value confusingly.
sb.AppendLine("<div class=\"checkbox\">");
sb.AppendLine("<label>");
sb.AppendLine("<input type=\"checkbox\" name=\"" + name + "\" value=\"" + i.Key + "\"");//class=\"form-control\"
if (selectedValues.Contains(i.Key))
sb.Append(" checked");
sb.AppendLine("/>" + i.Value);//+ "<br />"
sb.AppendLine("</label>");
sb.AppendLine("</div>");
}
sb.AppendLine("</div>");
sb.AppendLine("</fieldset>");
return sb.ToString();
}
}
static private string genStaticTextEditor(string name, string value)
{
// <input class="form-control" type="text" id="name" name="name" readonly>
return "<input class=\"form-control\" type=\"text\" id=\"" + name + "\" name=\"" + name + "\" value=\"" + value + "\" readonly>\r\n";
}
static private string genDisplayText(string value)
{
return "<h4>" + value + "</h4>\r\n";
}
/// <summary>
/// Check for individual field exceptions for general form read only status
/// </summary>
/// <param name="name"></param>
/// <param name="viewBag"></param>
/// <returns></returns>
private static bool FieldIsReadOnly(string name, dynamic viewBag)
{
if (viewBag == null || viewBag.ayReadOnly == null)
return true;
bool isReadOnly = viewBag.ayReadOnly;
//check for an exception to read only for this field
if (isReadOnly)
{
if (viewBag.allowedFields != null)
{
if (
((System.Collections.Generic.List<string>)viewBag.allowedFields).Contains(name)
)
isReadOnly = false;
}
}
//check for an exception for read/write for this field
if (!isReadOnly)
{
if (viewBag.restrictedFields != null)
{
if (
((System.Collections.Generic.List<string>)viewBag.restrictedFields).Contains(name)
)
isReadOnly = true;
}
}
return isReadOnly;
}
#endregion private builders
#region misc dev test stuff
/// <summary>
/// Generate a test widget to display form screen sizes
/// as known to bootstrap
/// </summary>
/// <returns></returns>
static public MvcHtmlString testSizeDisplayWidget()
{
return new MvcHtmlString("<div class=\"container\"> \r\n" +
" <div class=\"visible-lg\"> \r\n" +
" <span class=\"label label-default\">lg</span> \r\n" +
" </div> \r\n" +
" <div class=\"visible-md\"> \r\n" +
" <span class=\"label label-default\">md</span> \r\n" +
" </div> \r\n" +
" <div class=\"visible-sm\"> \r\n" +
" <span class=\"label label-default\">sm</span> \r\n" +
" </div> \r\n" +
" <div class=\"visible-xs\"> \r\n" +
" <span class=\"label label-default\">xs</span> \r\n" +
" </div> \r\n" +
"</div> \r\n" +
"<hr> ");
}
#endregion misc
#region Text
//non maxlength "default" version
static public MvcHtmlString edTextGroup(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return (edTextGroup(LocalizedTextKey,FieldName, Value, viewBag, 0, required));
}
//maxlength version
static public MvcHtmlString edTextGroup(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, int maxLength, bool required = false)
{ //ayBrokenRules err,
return new MvcHtmlString(edTextGroupAsString(LocalizedTextKey, FieldName, Value, string.Empty, viewBag, maxLength, required));
}
//non maxlength linkurl "default" version
static public MvcHtmlString edTextGroup(string LocalizedTextKey, string FieldName, string Value, string LinkUrl, dynamic viewBag, bool required = false)
{
return edTextGroup(LocalizedTextKey, FieldName, Value, LinkUrl, viewBag, 0, required);
}
//maxlength linkurl version
static public MvcHtmlString edTextGroup(string LocalizedTextKey, string FieldName, string Value, string LinkUrl, dynamic viewBag, int maxLength, bool required = false)
{
return new MvcHtmlString(edTextGroupAsString(LocalizedTextKey, FieldName, Value, LinkUrl, viewBag, maxLength, required));
}
static private string edTextGroupAsString(string LocalizedTextKey, string FieldName, string Value, string LinkUrl, dynamic viewBag, int maxLength, bool required = false)
{
if (string.IsNullOrWhiteSpace(LinkUrl))
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genTextEditor(FieldName, Value, viewBag, maxLength, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
else
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName, LinkUrl) +
genTextEditor(FieldName, Value, viewBag, maxLength, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
}
//Read only / display only text box and label
static public MvcHtmlString displayTextGroup(string LocalizedTextKey, string FieldName, string Value, string LinkUrl = "")
{
return new MvcHtmlString(displayTextGroupAsString(LocalizedTextKey, FieldName, Value, LinkUrl));
}
static private string displayTextGroupAsString(string LocalizedTextKey, string FieldName, string Value, string LinkUrl)
{
if (string.IsNullOrWhiteSpace(LinkUrl))
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genDisplayText(Value) +
formGroupEnd();
}
else
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName, LinkUrl) +
genDisplayText(Value) +
formGroupEnd();
}
}
#endregion text
#region Select
/// <summary>
/// Create a select input form edit group including Bootstrap grid layout classes and label
/// (accepts an enum as the selected value)
/// </summary>
/// <param name="LocalizedTextKey">title lt key</param>
/// <param name="FieldName"></param>
/// <param name="Items">string,string dictionary of items</param>
/// <param name="SelectedEnum">enum value</param>
/// <param name="err"></param>
/// <param name="required">bool may not work</param>
/// <returns></returns>
static public MvcHtmlString edSelectGroup(string LocalizedTextKey, string FieldName, Dictionary<string, string> Items, Enum SelectedEnum, dynamic viewBag, bool required = false)
{
string SelectedValue = Convert.ToInt32(SelectedEnum).ToString();
return new MvcHtmlString(edSelectGroupAsString(LocalizedTextKey, FieldName, Items, SelectedValue, viewBag, required));
}
/// <summary>
/// Create a select input form edit group including Bootstrap grid layout classes and label
/// </summary>
/// <param name="LocalizedTextKey">title lt key</param>
/// <param name="FieldName"></param>
/// <param name="Items">string,string dictionary of items</param>
/// <param name="SelectedValue">string selected value</param>
/// <param name="err"></param>
/// <param name="required">bool may not work</param>
/// <returns></returns>
static public MvcHtmlString edSelectGroup(string LocalizedTextKey, string FieldName, Dictionary<string, string> Items, string SelectedValue, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edSelectGroupAsString(LocalizedTextKey, FieldName, Items, SelectedValue, viewBag, required));
}
/// <summary>
/// For dynamically filled selects
/// </summary>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="viewBag"></param>
/// <param name="required"></param>
/// <returns></returns>
static public MvcHtmlString edEmptySelectGroup(string LocalizedTextKey, string FieldName, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edSelectGroupAsString(LocalizedTextKey, FieldName, null, string.Empty, viewBag, required));
}
static private string edSelectGroupAsString(string LocalizedTextKey, string FieldName, Dictionary<string, string> Items, string SelectedValue, dynamic viewBag, bool required = false)
{
string title = "";
if (!string.IsNullOrWhiteSpace(LocalizedTextKey))
{
title = genLabel(LocalizedTextKey, FieldName);
}
return formGroupStart(FieldName) +
title +
genSelect(FieldName, Items, SelectedValue, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion select
#region TextArea
static public MvcHtmlString edTextAreaGroup(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return edTextAreaGroup(LocalizedTextKey, FieldName, Value, viewBag, 0, required);
}
static public MvcHtmlString edTextAreaGroup(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, int maxLength, bool required = false)
{
return new MvcHtmlString(
formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genTextAreaEditor(FieldName, Value, viewBag, maxLength, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd());
}
#endregion textarea
#region Checkbox
/// <summary>
/// Create a checkbox input form edit group including Boostrap grid layout classes and label
/// </summary>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="err"></param>
/// <returns></returns>
static public MvcHtmlString edCheckGroup(string LocalizedTextKey, string FieldName, bool Value, dynamic viewBag)
{
return new MvcHtmlString(edCheckGroupAsString(LocalizedTextKey, FieldName, Value, string.Empty, viewBag));
}
static public MvcHtmlString edCheckGroup(string LocalizedTextKey, string FieldName, bool Value, string LinkUrl, dynamic viewBag)
{
return new MvcHtmlString(edCheckGroupAsString(LocalizedTextKey, FieldName, Value, LinkUrl, viewBag));
}
static public string edCheckGroupAsString(string LocalizedTextKey, string FieldName, bool Value, string LinkUrl, dynamic viewBag)
{
if (string.IsNullOrWhiteSpace(LinkUrl))
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genCheckBox(FieldName, Value, viewBag) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
else
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName, LinkUrl) +
genCheckBox(FieldName, Value, viewBag) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
}
/// <summary>
/// Gen checkbox without the form group stuff
/// For checkboxes on their own
/// </summary>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="viewBag"></param>
/// <returns></returns>
static public MvcHtmlString edCheckBox(string FieldName, bool Value, dynamic viewBag, bool addFormControlClass)
{
string s = genCheckBox(FieldName, Value, viewBag);
if (!addFormControlClass)
s = s.Replace("form-control", "");
return new MvcHtmlString(s);
}
#endregion checkbox
#region Autocomplete
/// <summary>
/// Autocomplete: Easy override default to regional=true and activeonly=true
/// </summary>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="err"></param>
/// <param name="placeholderstring"></param>
/// <returns></returns>
static public MvcHtmlString edAutocomplete(string LocalizedTextKey, string FieldName, Guid Value,
UrlHelper url, string listKey, dynamic viewBag, string placeholderstring = null)
{
//NOTE: SEE GZTW.AyaNova.BLL.PickListAutoComplete WHERE THESE QUERIES ARE FULFILLED
return edAutocomplete(LocalizedTextKey, FieldName, Value, url, listKey, true, true, placeholderstring, viewBag);
}
/// <summary>
/// Autocomplete: Easy override default to regional=FALSE and activeonly=true
/// </summary>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="err"></param>
/// <param name="placeholderstring"></param>
/// <returns></returns>
static public MvcHtmlString edAutocompleteNoRegion(string LocalizedTextKey, string FieldName, Guid Value,
UrlHelper url, string listKey, dynamic viewBag, string placeholderstring = null)
{
//NOTE: SEE GZTW.AyaNova.BLL.PickListAutoComplete WHERE THESE QUERIES ARE FULFILLED
return edAutocomplete(LocalizedTextKey, FieldName, Value, url, listKey, true, false, placeholderstring, viewBag);
}
/// <summary>
/// string value version for things like address field autocomplete
/// </summary>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="err"></param>
/// <param name="placeholderstring"></param>
/// <returns></returns>
static public MvcHtmlString edAutocomplete(string LocalizedTextKey, string FieldName, string Value,
UrlHelper url, string listKey, dynamic viewBag, string placeholderstring = null)
{
return edAutocomplete(LocalizedTextKey, FieldName, Value, url, listKey, true, true, placeholderstring, viewBag);
}
/// <summary>
/// Gen autocomplete specify any available property
/// </summary>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="activeOnly"></param>
/// <param name="regional"></param>
/// <param name="placeholderstring"></param>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="err"></param>
/// <returns></returns>
static public MvcHtmlString edAutocomplete(string LocalizedTextKey, string FieldName, Guid Value,
UrlHelper url, string listKey, bool activeOnly, bool regional, string placeholderstring, dynamic viewBag)
{
return new MvcHtmlString(
formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genAutocomplete(FieldName, Value, viewBag, url, listKey, activeOnly, regional, placeholderstring) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd());
}
/// <summary>
/// string version
/// </summary>
/// <param name="LocalizedTextKey"></param>
/// <param name="FieldName"></param>
/// <param name="Value"></param>
/// <param name="url"></param>
/// <param name="listKey"></param>
/// <param name="activeOnly"></param>
/// <param name="regional"></param>
/// <param name="placeholderstring"></param>
/// <param name="err"></param>
/// <returns></returns>
static public MvcHtmlString edAutocomplete(string LocalizedTextKey, string FieldName, string Value,
UrlHelper url, string listKey, bool activeOnly, bool regional, string placeholderstring, dynamic viewBag)
{
return new MvcHtmlString(
formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genAutocomplete(FieldName, Value, viewBag, url, listKey, activeOnly, regional, placeholderstring) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd());
}
#endregion autocomplete
#region Date and time
static public MvcHtmlString edDateTimeGroup(string LocalizedTextKey, string FieldName, object Value, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edDateTimeGroupAsString(LocalizedTextKey, FieldName, Value, viewBag, required));
}
static public string edDateTimeGroupAsString(string LocalizedTextKey, string FieldName, object Value, dynamic viewBag, bool required = false)
{
string defaultValue = makeDateTimeValue(Value);
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genDateTimeEditor(FieldName, defaultValue, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
//make date time value as a string that html 5 input controls recognize
static private string makeDateTimeValue(object Value)
{
DateTime dt = parseObjectIntoDateTimeValue(Value);
if (dt == DateTime.MinValue) return "";
return ("value=\"" + isoDatetime(dt) + "\"");
}
#endregion Date and time
#region Date
static public MvcHtmlString edDateGroup(string LocalizedTextKey, string FieldName, object Value, ayBrokenRules err, bool required = false)
{
return new MvcHtmlString(edDateGroupAsString(LocalizedTextKey, FieldName, Value, err, required));
}
static public string edDateGroupAsString(string LocalizedTextKey, string FieldName, object Value, dynamic viewBag, bool required = false)
{
//"2011-09-29"
string format = "yyyy-MM-dd";
string defaultValue = "";
if (Value is DateTime)
defaultValue = "value=\"" + ((DateTime)Value).ToString(format) + "\"";
else
{
if (Value != null && Value.ToString() != "")
{
DateTime dt = new DateTime();
if (DateTime.TryParse(Value.ToString(), out dt))
{
defaultValue = "value=\"" + dt.ToString(format) + "\"";
}
else
{
if (DateTime.TryParse(Value.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
defaultValue = "value=\"" + dt.ToString(format) + "\"";
}
}
}
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genDateEditor(FieldName, defaultValue, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion Date
#region Time
static public MvcHtmlString edTimeGroup(string LocalizedTextKey, string FieldName, object Value, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edTimeGroupAsString(LocalizedTextKey, FieldName, Value, viewBag, required));
}
static public string edTimeGroupAsString(string LocalizedTextKey, string FieldName, object Value, dynamic viewBag, bool required = false)
{
//"12:00"
string timeFormat = "HH:MM:ss";
string defaultValue = "";
if (Value is DateTime)
defaultValue = "value=\"" + ((DateTime)Value).ToString(timeFormat) + "\"";
else
{
if (Value != null && Value.ToString() != "")
{
DateTime dt = new DateTime();
if (DateTime.TryParse(Value.ToString(), out dt))
{
defaultValue = "value=\"" + dt.ToString(timeFormat) + "\"";
}
else
{
if (DateTime.TryParse(Value.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
defaultValue = "value=\"" + dt.ToString(timeFormat) + "\"";
}
}
}
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genTimeEditor(FieldName, defaultValue, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion time
#region Number
static public MvcHtmlString edNumberGroup(string LocalizedNumberKey, string FieldName, string Value, bool floatingPoint, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edNumberGroupAsString(LocalizedNumberKey, FieldName, Value, floatingPoint, viewBag, required));
}
static private string edNumberGroupAsString(string LocalizedNumberKey, string FieldName, string Value, bool floatingPoint, dynamic viewBag, bool required = false)
{
return formGroupStart(FieldName) +
genLabel(LocalizedNumberKey, FieldName) +
genNumberEditor(FieldName, Value, floatingPoint, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion number
#region Currency
//For now this is just a numeric input since there is no html 5 currency entry and
//it would be fuckery to put the localized currency symbol in so instead just treat as a number
//so this is all duplicate of the number code but I've specified currency for future consideration
//in case we do need to add a currency type input with symbol which will save having to edit every form in
//future.
static public MvcHtmlString edCurrencyGroup(string LocalizedCurrencyKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edCurrencyGroupAsString(LocalizedCurrencyKey, FieldName, Value, viewBag, required));
}
static private string edCurrencyGroupAsString(string LocalizedCurrencyKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return formGroupStart(FieldName) +
genLabel(LocalizedCurrencyKey, FieldName) +
genCurrencyEditor(FieldName, Value, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion currency
#region Color
static public MvcHtmlString edColorGroup(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edColorGroupAsString(LocalizedTextKey, FieldName, Value, viewBag, required));
}
static private string edColorGroupAsString(string LocalizedTextKey, string FieldName, string Value, dynamic viewBag, bool required = false)
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genColorEditor(FieldName, Value, viewBag, required) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion
#region Hidden fields generator and helpers
static public string hidden(string FieldName, string Value)
{
return "<input type=\"hidden\" name=\"" + FieldName + "\" value=\"" + Value + "\" />";
}
//given an object generate a set of hidden field values for it's public properties
static public MvcHtmlString hiddenObject(object o)
{
StringBuilder sb = new StringBuilder();
string objectName = o.GetType().Name + "_";
foreach (PropertyInfo propertyInfo in o.GetType().GetProperties())
{
object fieldValue = null;
if (propertyInfo.CanRead)
fieldValue = propertyInfo.GetValue(o, null);
//gen a hidden field
sb.AppendLine(hidden(objectName + propertyInfo.Name, fieldValue.ToString()));
}
return new MvcHtmlString(sb.ToString());
}
//Populate object from FormCollection hidden fields that match names in passed in object
//since we only need to support a limited set of types no need for a universal converter here
static public void populateObjectFromHiddenFields(object o, FormCollection fc)
{
string objectName = o.GetType().Name + "_";
foreach (var key in fc.AllKeys)
{
PropertyInfo pi = o.GetType().GetProperty(key.Replace(objectName, ""));
if (pi != null)
{
Type tProp = pi.PropertyType;
if (tProp == typeof(Guid))
pi.SetValue(o, Guid.Parse(fc[key]), null);
else if (tProp == typeof(bool))
pi.SetValue(o, bool.Parse(fc[key]), null);
else if (tProp == typeof(int))
pi.SetValue(o, int.Parse(fc[key]), null);
else if (tProp == typeof(string))
pi.SetValue(o, fc[key], null);
else
throw new System.NotSupportedException("RI->Util->populateObjectFromHiddenFields: object type of " + tProp.ToString() + " is not supported!");
}
}
}
#endregion hidden
#region MultiSelect
/// <summary>
/// Create a multiple select input form edit group including Bootstrap grid layout classes and label
/// </summary>
/// <param name="LocalizedTextKey">title lt key</param>
/// <param name="FieldName"></param>
/// <param name="Items">string,string dictionary of items</param>
/// <param name="SelectedValues">comma delimited array of selected values</param>
/// <param name="err"></param>
/// <param name="required">Not currently implemented / doesn't apply</param>
/// <returns></returns>
static public MvcHtmlString edMultiSelectGroup(string LocalizedTextKey, string FieldName, Dictionary<string, string> Items, string SelectedValues, dynamic viewBag, bool required = false)
{
return new MvcHtmlString(edMultiSelectGroupAsString(LocalizedTextKey, FieldName, Items, SelectedValues, viewBag, required));
}
static private string edMultiSelectGroupAsString(string LocalizedTextKey, string FieldName, Dictionary<string, string> Items, string SelectedValues, dynamic viewBag, bool required = false)
{
//string title = "";
//if (!string.IsNullOrWhiteSpace(LocalizedTextKey))
//{
// title = genLabel(LocalizedTextKey, FieldName);
//}
return formGroupStart(FieldName) +
//title +
genMultiSelect(FieldName, ay.lt(LocalizedTextKey), Items, SelectedValues, viewBag) +
ay.genErr(FieldName, viewBag.err) +
formGroupEnd();
}
#endregion MultiSelect
#region STATIC TEXT CONTROLS
static public MvcHtmlString edStaticTextGroup(string LocalizedTextKey, string FieldName, string Value)
{ //ayBrokenRules err,
return new MvcHtmlString(edStaticTextGroupAsString(LocalizedTextKey, FieldName, Value));
}
static private string edStaticTextGroupAsString(string LocalizedTextKey, string FieldName, string Value)
{
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genStaticTextEditor(FieldName, Value) +
formGroupEnd();
}
static public MvcHtmlString edStaticCheckMarkGroup(string LocalizedTextKey)
{ //ayBrokenRules err,
return new MvcHtmlString(edStaticCheckMarkGroupAsString(LocalizedTextKey));
}
static private string edStaticCheckMarkGroupAsString(string LocalizedTextKey)
{
string FieldName = Guid.NewGuid().ToString("N");
return formGroupStart(FieldName) +
genLabel(LocalizedTextKey, FieldName) +
genDisplayText(CheckMarkUp) +
formGroupEnd();
}
#endregion
#region STANDARD FORM BUTTON
/// <summary>
/// Class attributes to apply to all buttons in RI
/// </summary>
static public string standardButtonClasses(string additionalClassesString = "")
{
if (!string.IsNullOrWhiteSpace(additionalClassesString))
{
return additionalClassesString.Trim() + " btn btn-lg btn-block";
}
return "btn btn-lg btn-block";
}
#endregion SFB
#region SAVE / BACK / DELETE BUTTONS
static public MvcHtmlString saveBackButtonGroup(dynamic ViewBag, bool forceSaveEnabled = false, bool forceSaveAvailable = false)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<hr />");
//case 2040
//sb.AppendLine("<div class=\"form-group col-md-6 col-lg-3\">");
sb.AppendLine("<div class=\"form-group col-xs-12\">");
#if(DEBUG)
if (ViewBag.ayReadOnly == null)
throw new System.MissingMemberException("util->saveBackButtonGroup: You forgot to set a value for ViewBag.ayreadonly and rights");
#endif
bool isReadOnly = ViewBag.ayReadOnly;
if (ViewBag.allowedFields != null)
isReadOnly = false;
if (!isReadOnly || forceSaveAvailable)
{
string sDisabled = string.Empty;
if (!forceSaveEnabled)
sDisabled = "disabled=\"disabled\"";
//case 2040
////save button
//sb.AppendLine("<button type=\"submit\" class=\"btn btn-success btn-md col-md-4 btn-block \" " + sDisabled + ">");
//sb.AppendLine("<span class=\"icon-Save ay-icon-large\"></span></button>");
////back button
//sb.AppendLine("<a href=\"XXX\" class=\"ayBackLink btn btn-primary btn-md col-md-4 col-md-offset-4 btn-block\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
//save button
sb.AppendLine("<button type=\"submit\" class=\""+ standardButtonClasses("btn-success")+"\" " + sDisabled + ">");
sb.AppendLine("<span class=\"icon-Save ay-icon-large\"></span></button>");
//back button
sb.AppendLine("<a href=\"XXX\" class=\"" + standardButtonClasses("ayBackLink btn-primary") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
}
else
{
//back button only, same, no offset
//case 2040
//sb.AppendLine("<a href=\"XXX\" class=\"ayBackLink btn btn-primary btn-md col-md-4 btn-block\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
sb.AppendLine("<a href=\"XXX\" class=\"" + standardButtonClasses("ayBackLink btn-primary") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
}
sb.AppendLine("</div>");
return new MvcHtmlString(sb.ToString());
}
static public MvcHtmlString listAddBackButtonGroup(dynamic ViewBag)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(listTopAddBackButtonGroupString(ViewBag));
sb.AppendLine("<div class=\"ay-display-list\"><ul class=\"list-group\" id=\"ayalist\"></ul></div>");
sb.AppendLine(listBottomAddBackButtonGroupString(ViewBag));
return new MvcHtmlString(sb.ToString());
}
static public MvcHtmlString listTopAddBackButtonGroup(dynamic ViewBag)
{
return new MvcHtmlString(listTopAddBackButtonGroupString(ViewBag));
}
static public MvcHtmlString listBottomAddBackButtonGroup(dynamic ViewBag)
{
return new MvcHtmlString(listBottomAddBackButtonGroupString(ViewBag));
}
static private string listTopAddBackButtonGroupString(dynamic ViewBag)
{
#if(DEBUG)
if (ViewBag.ayReadOnly == null)
{
throw new System.ArgumentNullException("Util->listTopAddBackButtonGroupString:ViewBag rights is null!!");
}
#endif
StringBuilder sb = new StringBuilder();
//back button only, same, no offset
sb.AppendLine("<a href=\"XXX\" role=\"button\" class=\"" + standardButtonClasses("ayBackLink btn-info") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
string newItemText = string.Empty;
//was a custom text specified?
if (ViewBag.newItemText!=null)
newItemText = ViewBag.newItemText;
else
newItemText = lt("UI.Command.Add");
if (!ViewBag.ayReadOnly)
sb.AppendLine("<a href=\"" + ViewBag.newItemUrl + "\" role=\"button\" class=\"" + standardButtonClasses("btn-success") + "\"><span class=\"icon-Add\"></span>&nbsp;" +
newItemText +
"</a>");
return sb.ToString();
//return new MvcHtmlString(sb.ToString());
}
static private string listBottomAddBackButtonGroupString(dynamic ViewBag)
{
StringBuilder sb = new StringBuilder();
string newItemText = string.Empty;
//was a custom text specified?
if (ViewBag.newItemText != null)
newItemText = ViewBag.newItemText;
else
newItemText = lt("UI.Command.Add");
if (!ViewBag.ayReadOnly)
sb.AppendLine("<a href=\"" + ViewBag.newItemUrl + "\" role=\"button\" class=\"" + standardButtonClasses("btn-success") + "\"><span class=\"icon-Add\"></span>&nbsp;" +
newItemText +
"</a>");
sb.AppendLine("<a href=\"XXX\" role=\"button\" class=\"" + standardButtonClasses("ayBackLink btn-info") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
return sb.ToString();
}
static public MvcHtmlString listNewButton(dynamic ViewBag)
{
if (!ViewBag.ayReadOnly)
{
return new MvcHtmlString("<a href=\"" + ViewBag.newItemUrl + "\" role=\"button\" class=\"" + standardButtonClasses("btn-success") + "\"><span class=\"icon-Add\"></span>&nbsp;" + lt("UI.Toolbar.New") + "</a>");
}
else
{
return new MvcHtmlString("");
}
}
static public MvcHtmlString listBackButton()
{
return new MvcHtmlString("<a href=\"XXX\" role=\"button\" class=\"" + standardButtonClasses("ayBackLink btn-info") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
}
static public MvcHtmlString formBackButton()
{
return new MvcHtmlString("<a href=\"XXX\" role=\"button\" class=\"" + standardButtonClasses("ayBackLink btn-info") + "\"><span class=\"glyphicon glyphicon-menu-left ay-icon-large\"></span></a>");
}
static public MvcHtmlString formSaveButton(dynamic ViewBag, bool forceSaveEnabled = false)
{
StringBuilder sb = new StringBuilder();
if (!ViewBag.ayReadOnly)
{
string sDisabled = string.Empty;
if (!forceSaveEnabled)
sDisabled = "disabled=\"disabled\"";
//save button
sb.AppendLine("<button type=\"submit\" class=\"" + standardButtonClasses("btn-success") + "\" " + sDisabled + ">");
sb.AppendLine("<span class=\"icon-Save ay-icon-large\"></span></button>");
}
else
{
return new MvcHtmlString("");
}
//sb.AppendLine("</div>");
return new MvcHtmlString(sb.ToString());
}
static public MvcHtmlString formDeleteButton(string DeleteUrl, UrlHelper url)
{
string actualDeleteUrl = genBaseSiteUrl(url) + DeleteUrl;
return new MvcHtmlString("<a href=\"" + actualDeleteUrl + "\" role=\"button\" class=\"" + standardButtonClasses("ay-set-ret-url btn-warning") + "\"><span class=\"icon-Delete ay-icon-large\"></span></a>");
}
#endregion save back delete buttons
#region Workorder specific components and helpers
static public MvcHtmlString woItemBadgeButton(string LocalizedTextKey, string sUrl, int nCount, Guid woItemId, UrlHelper url)
{
return woItemBadgeButton(LocalizedTextKey, string.Empty, sUrl, nCount, woItemId, url);
}
//handles empty badge conditions to save
//code on page
static public MvcHtmlString woItemBadgeButton(string LocalizedTextKey, string AdditionalDisplayText, string sUrl, int nCount, Guid woItemId, UrlHelper url)
{
string fullUrl = genBaseSiteUrl(url) + sUrl + woItemId.ToString();
if (sUrl == "#")
fullUrl = sUrl;
string sDisplayText = lt(LocalizedTextKey) + AdditionalDisplayText;
StringBuilder sb = new StringBuilder();
sb.Append("<a href=\"");
sb.Append(fullUrl);
sb.Append("\" role=\"button\" class=\"" + standardButtonClasses("btn-default ay-text-left") + "\" style=\"white-space: normal;\">");
sb.Append(sDisplayText);
if (nCount > 0)
{
sb.Append(
"&nbsp;&nbsp;<span class=\"badge\">" +
nCount.ToString() +
"</span>"
);
}
sb.Append("</a>");
return new MvcHtmlString(sb.ToString());
}
//button for the workorder item "header" itself
static public MvcHtmlString woItemHeaderButton(WorkorderItem wi, UrlHelper url)
{
string fullUrl = genBaseSiteUrl(url) + "WorkorderItem/Edit/" + wi.ID.ToString();
bool bHasText = false;
StringBuilder sb = new StringBuilder();
sb.Append("<a href=\"");
sb.Append(fullUrl);
sb.Append("\" role=\"button\" class=\"" + standardButtonClasses("btn-default ay-text-left") + "\">");
//============
sb.AppendLine("<div class=\"ay-display-list\">");
if (!string.IsNullOrWhiteSpace(wi.Summary))
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.Summary"), wi.Summary));
}
if (wi.WorkorderStatusID != Guid.Empty)
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.WorkorderStatusID"), NameFetcher.GetName(RootObjectTypes.WorkorderStatus, wi.WorkorderStatusID)));
}
if (wi.TypeID != Guid.Empty)
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.TypeID"), NameFetcher.GetName(RootObjectTypes.WorkorderItemType, wi.TypeID)));
}
if (wi.PriorityID != Guid.Empty)
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.PriorityID"), NameFetcher.GetName(RootObjectTypes.Priority, wi.PriorityID)));
}
if (wi.HasRequestDate)
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.RequestDate"), wi.RequestDate));
}
if (wi.WarrantyService)
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.WarrantyService"), CheckMarkUp));
}
if (!string.IsNullOrWhiteSpace(wi.TechNotes))
{
bHasText = true;
sb.Append(AyDisplayListItemWrapper(lt("WorkorderItem.Label.TechNotes"), AyaBizUtils.TruncateStringWithEllipses(wi.TechNotes, 40)));
}
if (!bHasText)
{
//no text so show the title instead
sb.AppendLine(lt("O.WorkorderItem"));
}
sb.AppendLine("</div>");
//============
sb.Append("</a>");
return new MvcHtmlString(sb.ToString());
}
//returns contract icon fragment or empty if none
static public MvcHtmlString woContractIcon(Workorder w)
{
Guid cid = w.ContractIDResolved();
if (cid == Guid.Empty)
{
return new MvcHtmlString("");
}
else
{
return new MvcHtmlString("&nbsp;&nbsp;<span class=\"ay-icon-large icon-Contract\"></span>");
}
}
//returns popup notes icon fragment or empty if none
static public MvcHtmlString woPopupNotesIcon(Workorder w)
{
if (!w.uiHasPopupNotes)
{
return new MvcHtmlString("");
}
else
{
return new MvcHtmlString("&nbsp;&nbsp;<span class=\"ay-icon-large ay-highlight glyphicon glyphicon-info-sign\"></span>");
}
}
static public string woContactFields(Client c)
{
if (c == null) return string.Empty;
System.Text.StringBuilder b = new System.Text.StringBuilder();
b.Append(AyaBizUtils.SS(lt("Client.Label.Phone1") + ": ", c.Phone1, "\r\n"));
b.Append(AyaBizUtils.SS(lt("Client.Label.Phone2") + ": ", c.Phone2, "\r\n"));
b.Append(AyaBizUtils.SS(lt("Client.Label.Phone3") + ": ", c.Phone3, "\r\n"));
b.Append(AyaBizUtils.SS(lt("Client.Label.Phone4") + ": ", c.Phone4, "\r\n"));
b.Append(AyaBizUtils.SS(lt("Client.Label.Phone5") + ": ", c.Phone5, "\r\n"));
b.Append(AyaBizUtils.SS(lt("Client.Label.Email") + ": ", c.Email, "\r\n"));
return b.ToString();
}
static public string woContractDisplay(Workorder w)
{
if (!w.uiHasContract) return "";
Contract c = w.ContractResolved();
//Page.Title = Util.LocaleText("O.Contract") + " - " + c.Name;
//lblHeader.Text = Util.StringWebify(c.Name);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(lt("Contract.Label.DiscountParts"));
sb.Append(": ");
sb.Append(c.DiscountParts.ToString("p"));
sb.Append("\r\n\r\n");
sb.Append(lt("Contract.Label.Notes"));
sb.Append("\r\n");
sb.Append(c.Notes);
sb.Append("\r\n\r\n");
sb.Append(lt("Contract.Label.ContractRatesOnly"));
sb.Append(": ");
sb.Append(c.ContractRatesOnly.ToString());
sb.Append("\r\n\r\n");
if (c.Rates.Count > 1)
{
RatePickList rp = RatePickList.GetListWithContract(c.ID);
sb.Append(lt("ContractRate.Label.List"));
sb.Append("\r\n");
foreach (ContractRate r in c.Rates)
{
RatePickList.RatePickListInfo i = rp[r.RateID];
sb.Append(i.Name);
sb.Append(" - ");
sb.Append(i.Charge.ToString("c"));
sb.Append("\r\n");
}
}
return sb.ToString();
}
static public MvcHtmlString woInventoryDisplay(PartInventoryList list)
{
if (list==null || list.Count < 1) return new MvcHtmlString(string.Empty);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
string title = lt("PartByWarehouseInventory.Label.List");
//string partassembly = lt("O.PartAssembly");
//string partcategory = lt("O.PartCategory");
string partserials = lt("Common.Label.SerialNumber");
string partwarehouse = lt("O.PartWarehouse");
//string part = lt("O.Part");
string onhand = lt("PartByWarehouseInventory.Label.QuantityOnHand");
string onorder = lt("PartByWarehouseInventory.Label.QuantityOnOrder");
sb.AppendLine("<div class=\"row\">");
//collapse button / title
sb.AppendLine(
"<a class=\"" + standardButtonClasses("btn-primary") + "\" role=\"button\" data-toggle=\"collapse\" href=\"#collapseInv\" aria-expanded=\"false\" aria-controls=\"collapseExample\"> \r\n" +
title +
"</a>");
sb.AppendLine("<div class=\"collapse\" id=\"collapseInv\">");
sb.AppendLine("<div class=\"table-responsive\">");
sb.AppendLine("<table class=\"table table-striped table-condensed\"> ");//
sb.AppendLine("<thead>");
sb.AppendLine("<tr>");
sb.AppendLine("<th>" + partwarehouse + "</th>");
sb.AppendLine("<th>" + onhand + "</th>");
sb.AppendLine("<th>" + onorder + "</th>");
sb.AppendLine("<th>" + partserials + "</th>");
sb.AppendLine("</tr>");
sb.AppendLine("</thead>");
sb.AppendLine("<tbody>");
//--------------------------
//rows
foreach (PartInventoryList.PartInventoryListInfo i in list)
{
sb.AppendLine("<tr>");
sb.AppendLine("<td>" + i.LT_O_PartWarehouse + "</td>");
sb.AppendLine("<td>" + i.LT_PartByWarehouseInventory_Label_QuantityOnHand.ToString("g27") + "</td>");
sb.AppendLine("<td>" + i.LT_PartByWarehouseInventory_Label_QuantityOnOrder.ToString("g27") + "</td>");
sb.AppendLine("<td>");
if (i.LT_PartSerial_Label_List != null && i.LT_PartSerial_Label_List.Count > 0)
{
foreach (PartSerialPickList.PartSerialPickListInfo pi in i.LT_PartSerial_Label_List)
sb.Append(pi.SerialNumber + ", ");
sb.Length = sb.Length - 2;
}
sb.AppendLine("</td>");
sb.AppendLine("</tr>");
}
//--------------------------
sb.AppendLine("</tbody>");
sb.AppendLine("</table>");
sb.AppendLine("</div>");//table-responsive
sb.AppendLine("</div>");//collapse
sb.AppendLine("</div>");//row
//<a class="btn btn-primary" role="button" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
// Link with href
//</a>
////<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
//// Button with data-target
////</button>
//<div class="collapse" id="collapseExample">
//<div class="table-responsive">
// <table class="table table-condensed">
// <thead>
// <tr>
// <th>#</th>
// <th>First Name</th>
// <th>Last Name</th>
// <th>Username</th>
// </tr>
//</thead>
//<tbody>
// <tr>
// <th scope="row">1</th>
// <td>Mark</td>
// <td>Otto</td>
// <td>@mdo</td>
// </tr>
// <tr>
// <th scope="row">2</th>
// <td>Jacob</td>
// <td>Thornton</td>
// <td>@fat</td>
// </tr>
// <tr>
// <th scope="row">3</th>
// <td colspan="2">Larry the Bird</td>
// <td>@twitter</td>
// </tr>
//</tbody>
// </table>
//</div>
//</div>
return new MvcHtmlString(sb.ToString());
}
#endregion workorder specific
#endregion control generators
#region PAGE LAYOUT AND STYLE HELPERS
//static public MvcHtmlString WrapInMvcHtmlString(string value)
//{
// return new MvcHtmlString(value);
//}
//convenience method to wrap each item in a list with the
//appropriate markup.
//using this method ensures easier change in future
//and saves code
static private string AyDisplayListItemWrapper(string sTitle, object oValue, bool isMultiLineValue = false, string typeHint = null)
{
System.Text.StringBuilder sb = new StringBuilder();
//turn the object oValue into a suitable string
string sValue = string.Empty;
if (oValue is System.String)
{
sValue = oValue as string;
}
else if (oValue is GridNameValueCellItem)
{
sValue = ((GridNameValueCellItem)oValue).Display;
}
else if (oValue == null)
{
sValue = string.Empty;
}
else if (oValue is System.DBNull)
{
sValue = string.Empty;
}
else if (oValue is decimal)
{
if (typeHint == null)//standard decimal
{
sValue = ((Decimal)oValue).ToString("n2");
}
else
{
//NOTE: initially the only type hint possible is currency but keeping it open in case there is anythign else down the road
//currency
System.Diagnostics.Debug.Assert(typeHint == "$");
sValue = ((Decimal)oValue).ToString("C");
}
}
else if (oValue is Enum)
{
sValue = EnumDescConverter.GetEnumDescription(oValue as Enum);
}
else
{
//it's a date or number or enum or something
if (oValue is DateTime)
{
sValue = parseObjectIntoDateTimeValueString(oValue);
}
else
{
//what are you?
string s = oValue.GetType().ToString();
throw new System.Exception("Util->AyDisplayListItemWrapper: unknown type:" + s);
}
}
sb.Append("<h4>");
sb.Append(sTitle);
sb.AppendLine("</h4>");
if (isMultiLineValue)
{
sb.Append("<pre>");
sb.Append(sValue);
sb.AppendLine("</pre>");
}
else
{
sb.Append("<p>");
sb.Append(sValue);
sb.AppendLine("</p>");
}
return sb.ToString();
}
//Method for on pages
static public MvcHtmlString AyPageDisplayListItemWrapper(string sLocaleKeyTitle, object oValue, bool bShow, bool isMultiLineValue = false, string typeHint = null)
{
if (bShow)
{
return new MvcHtmlString(AyDisplayListItemWrapper(lt(sLocaleKeyTitle), oValue, isMultiLineValue, typeHint));
}
return new MvcHtmlString("");
}
static public MvcHtmlString AyPageDisplayListItemWrapperNotLocalized(string sTitle, object oValue, bool bShow, bool isMultiLineValue = false, string typeHint = null)
{
if (bShow)
{
return new MvcHtmlString(AyDisplayListItemWrapper(sTitle, oValue, isMultiLineValue, typeHint));
}
return new MvcHtmlString("");
}
//format for page javascript in forms that load data
//via ajax dynamically
static public MvcHtmlString AyJSDisplayListItemWrapper(string sLocaleKeyTitle, object oValue, bool bShow, bool isMultiLineValue = false, string typeHint = null)
{
if (bShow)
{
string ret = AyDisplayListItemWrapper(lt(sLocaleKeyTitle), oValue, isMultiLineValue, typeHint);
ret = ret.Replace("<h4>", "'<h4>");
ret = ret.Replace("</h4>", "</h4>'+");
if (!isMultiLineValue)
{
ret = ret.Replace("<p>", "'<p>'+");
ret = ret.Replace("</p>", "+'</p>'+");
}
else
{
ret = ret.Replace("<pre>", "'<pre>'+");
ret = ret.Replace("</pre>", "+'</pre>'+");
}
return new MvcHtmlString(ret);
}
return new MvcHtmlString("");
}
#endregion layout and style helpers
#region AYANOVA SMALL DATA LISTS
//***********************************************************************
// THESE ARE ALL LISTS THAT ARE SO SMALL THEY DON'T REQUIRE AUTOCOMPLETE
// (autocomplete are in ayListController.cs)
//***********************************************************************
static public void AddEmptyItem(Dictionary<string, string> dd)
{
dd.Add(Guid.Empty.ToString(), PickListFactory.JQUICompliantEmptySelectionCharacter);
}
static public Dictionary<string, string> DateRangeList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add("*", ay.lt("UI.Grid.RowFilterDropDownAllItem"));
dd.Add("[YESTERDAY]", ay.lt("UI.Label.DateRange.Yesterday"));
dd.Add("[TODAY]", ay.lt("UI.Label.DateRange.Today"));
dd.Add("[TOMORROW]", ay.lt("UI.Label.DateRange.Tomorrow"));
dd.Add("[LAST WEEK]", ay.lt("UI.Label.DateRange.LastWeek"));
dd.Add("[THIS WEEK]", ay.lt("UI.Label.DateRange.ThisWeek"));
dd.Add("[NEXT WEEK]", ay.lt("UI.Label.DateRange.NextWeek"));
dd.Add("[LAST MONTH]", ay.lt("UI.Label.DateRange.LastMonth"));
dd.Add("[THIS MONTH]", ay.lt("UI.Label.DateRange.ThisMonth"));
dd.Add("[NEXT MONTH]", ay.lt("UI.Label.DateRange.NextMonth"));
dd.Add("[14DAYWINDOW]", ay.lt("UI.Label.DateRange.14DayWindow"));
//case 2067 new ranges
dd.Add("[PAST]", ay.lt("UI.Label.DateRange.Past"));
dd.Add("[FUTURE]", ay.lt("UI.Label.DateRange.Future"));
dd.Add("[LASTYEAR]", ay.lt("UI.Label.DateRange.LastYear"));
dd.Add("[THISYEAR]", ay.lt("UI.Label.DateRange.ThisYear"));
dd.Add("[INTHELAST3MONTHS]", ay.lt("UI.Label.DateRange.InTheLastThreeMonths"));
dd.Add("[INTHELAST6MONTHS]", ay.lt("UI.Label.DateRange.InTheLastSixMonths"));
dd.Add("[INTHELASTYEAR]", ay.lt("UI.Label.DateRange.InTheLastYear"));
return dd;
}
static public Dictionary<string, string> DayOfWeekList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add(((int)AyaDayOfWeek.AnyDayOfWeek).ToString(), ay.lt("UI.Label.Day.Any"));
dd.Add(((int)AyaDayOfWeek.Monday).ToString(), ay.lt("UI.Label.Day.Monday"));
dd.Add(((int)AyaDayOfWeek.Tuesday).ToString(), ay.lt("UI.Label.Day.Tuesday"));
dd.Add(((int)AyaDayOfWeek.Wednesday).ToString(), ay.lt("UI.Label.Day.Wednesday"));
dd.Add(((int)AyaDayOfWeek.Thursday).ToString(), ay.lt("UI.Label.Day.Thursday"));
dd.Add(((int)AyaDayOfWeek.Friday).ToString(), ay.lt("UI.Label.Day.Friday"));
dd.Add(((int)AyaDayOfWeek.Saturday).ToString(), ay.lt("UI.Label.Day.Saturday"));
dd.Add(((int)AyaDayOfWeek.Sunday).ToString(), ay.lt("UI.Label.Day.Sunday"));
return dd;
}
static public Dictionary<string, string> PMGenerateTimeSpanList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add(((int)AyaUnitsOfTime.Hours).ToString(), ay.lt("UI.Label.TimeSpan.Hours"));
dd.Add(((int)AyaUnitsOfTime.Days).ToString(), ay.lt("UI.Label.TimeSpan.Days"));
dd.Add(((int)AyaUnitsOfTime.Months).ToString(), ay.lt("UI.Label.TimeSpan.Months"));
dd.Add(((int)AyaUnitsOfTime.Years).ToString(), ay.lt("UI.Label.TimeSpan.Years"));
return dd;
}
static public Dictionary<string, string> PMThresholdTimeSpanList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add(((int)AyaUnitsOfTime.Minutes).ToString(), ay.lt("UI.Label.TimeSpan.Minutes"));
dd.Add(((int)AyaUnitsOfTime.Hours).ToString(), ay.lt("UI.Label.TimeSpan.Hours"));
dd.Add(((int)AyaUnitsOfTime.Days).ToString(), ay.lt("UI.Label.TimeSpan.Days"));
dd.Add(((int)AyaUnitsOfTime.Months).ToString(), ay.lt("UI.Label.TimeSpan.Months"));
dd.Add(((int)AyaUnitsOfTime.Years).ToString(), ay.lt("UI.Label.TimeSpan.Years"));
return dd;
}
static public Dictionary<string, string> RecordCountList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add("-1", ay.lt("UI.Grid.RowFilterDropDownAllItem"));
dd.Add("25", "25");
dd.Add("100", "100");
dd.Add("500", "500");
dd.Add("1000", "1000");
return dd;
}
//this is to substitute for a tri-state checkbox which is not an easy thing in html 5 as it's not natively supported fully anywhere
static public Dictionary<string, string> TrueFalseNullList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add(PickListFactory.JQUICompliantEmptySelectionCharacter, ay.lt("UI.Grid.RowFilterDropDownAllItem"));
dd.Add(true.ToString(), true.ToString());
dd.Add(false.ToString(), false.ToString());
return dd;
}
static public Dictionary<string, string> QuoteStatusList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add("0", PickListFactory.JQUICompliantEmptySelectionCharacter);
dd.Add("1", ay.lt("WorkorderQuoteStatusTypes.Label.InProgress"));
dd.Add("2", ay.lt("WorkorderQuoteStatusTypes.Label.Submitted"));
dd.Add("3", ay.lt("WorkorderQuoteStatusTypes.Label.Awarded"));
dd.Add("4", ay.lt("WorkorderQuoteStatusTypes.Label.NotAwarded"));
dd.Add("5", ay.lt("WorkorderQuoteStatusTypes.Label.New"));
dd.Add("6", ay.lt("WorkorderQuoteStatusTypes.Label.NotAwarded2"));
return dd;
}
static public Dictionary<string, string> CSRPriorityList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
//case 2083 empty is not a valid selection
//dd.Add("-1", PickListFactory.JQUICompliantEmptySelectionCharacter);
dd.Add("0", ay.lt("ClientServiceRequestPriority.NotUrgent"));
dd.Add("1", ay.lt("ClientServiceRequestPriority.ASAP"));
dd.Add("2", ay.lt("ClientServiceRequestPriority.Emergency"));
return dd;
}
static public Dictionary<string, string> CSRStatusList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add("-1", PickListFactory.JQUICompliantEmptySelectionCharacter);
dd.Add("0", ay.lt("ClientServiceRequestStatus.Open"));
dd.Add("1", ay.lt("ClientServiceRequestStatus.Accepted"));
dd.Add("2", ay.lt("ClientServiceRequestStatus.Declined"));
dd.Add("3", ay.lt("ClientServiceRequestStatus.Closed"));
return dd;
}
static public Dictionary<string, string> LoanItemRateList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
dd.Add("0", ay.lt("LoanItem.Label.RateNone"));
dd.Add("1", ay.lt("LoanItem.Label.RateHour"));
dd.Add("2", ay.lt("LoanItem.Label.RateHalfDay"));
dd.Add("3", ay.lt("LoanItem.Label.RateDay"));
dd.Add("4", ay.lt("LoanItem.Label.RateWeek"));
dd.Add("5", ay.lt("LoanItem.Label.RateMonth"));
dd.Add("6", ay.lt("LoanItem.Label.RateYear"));
return dd;
}
static public Dictionary<string, string> ClientNoteTypeList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
AddEmptyItem(dd);
GenericNVList l = GenericNVList.GetList("ACLIENTNOTETYPE", "AID", "ANAME", true, false, false);
for (int x = 0; x < l.Count; x++)
{
dd.Add(((System.Collections.DictionaryEntry)l.BindableList[x]).Key.ToString(),
((System.Collections.DictionaryEntry)l.BindableList[x]).Value.ToString());
}
return dd;
}
static public Dictionary<string, string> ScheduleMarkerSourceTypesList(ScheduleMarker sm)
{
Dictionary<string, string> dd = new Dictionary<string, string>();
if (sm.FollowID == Guid.Empty)
{
//Load combo boxes with initial values
//Global object
dd.Add("GLOBAL," + ScheduleMarker.ScheduleMarkerGlobalSourceID.ToString(), ay.lt("O.Global"));
//Regions...
//NVCHANGED
GenericNVList l = GenericNVList.GetList("aRegion", "aID", "aName", true, false, true);
//Loop through the items in the list and put them
//into the valuelist
for (int x = 0; x < l.Count; x++)
{
dd.Add(
"REGION," + ((DictionaryEntry)l.BindableList[x]).Key.ToString(),
ay.lt("O.Region") + " - " + ((DictionaryEntry)l.BindableList[x]).Value.ToString()
);
}
}
//***************************************************************
//Scheduleable users....
ScheduleableUserNameDisplayFormats fmt = AyaBizUtils.GlobalSettings.DefaultScheduleableUserNameDisplayFormat;
UserListScheduleable uList = UserListScheduleable.GetList();
foreach (UserListScheduleable.UserListScheduleableInfo ui in uList)
{
if (ui.Active == true || ui.ID == sm.SourceID)
{
dd.Add("USER," + ui.ID.ToString(), ay.lt("O.User") + " - " + ui.Name(fmt));
}
}
//*****************************************************************************
if (sm.FollowID == Guid.Empty)
{
//***************************************************************
//Dispatch zones
DispatchZonePickList DispatchZoneList = DispatchZonePickList.GetList(true);
foreach (DispatchZonePickList.DispatchZonePickListInfo di in DispatchZoneList)
{
if (di.Active == true || di.ID == sm.SourceID)
{
dd.Add("ZONE," + di.ID.ToString(), ay.lt("O.DispatchZone") + " - " + di.Name);
}
}
//*****************************************************************************
//***************************************************************
//Scheduleable user GROUPS....
ScheduleableUserGroupPickList GroupList = ScheduleableUserGroupPickList.GetList();
foreach (ScheduleableUserGroupPickList.ScheduleableUserGroupPickListInfo gi in GroupList)
{
if (gi.Active == true || gi.ID == sm.SourceID)
{
dd.Add("GROUP," + gi.ID.ToString(), ay.lt("O.ScheduleableUserGroup") + " - " + gi.Name);
}
}
//*****************************************************************************
}
return dd;
}
/// <summary>
/// Takes a schedule marker and returns a string representing what the selected value
/// should be so it can be defaulted properly in the UI when a form openss.
///
/// (this is required because the list of items is mixed so there are different types in it
/// represented by a prefix before the Guid, i.e. "ZONE,{SOME GUID VALUE HERE}")
/// </summary>
/// <param name="sm"></param>
/// <returns></returns>
static public string ScheduleMarkerSourceTypeSelectedValue(ScheduleMarker sm)
{
switch (sm.ScheduleMarkerSourceType)
{
case ScheduleMarkerSourceTypes.DispatchZone:
return "ZONE," + sm.SourceID.ToString();
case ScheduleMarkerSourceTypes.Global:
return "GLOBAL," + sm.SourceID.ToString();
case ScheduleMarkerSourceTypes.Regional:
return "REGION," + sm.SourceID.ToString();
case ScheduleMarkerSourceTypes.ScheduleableUserGroup:
return "GROUP," + sm.SourceID.ToString();
case ScheduleMarkerSourceTypes.User:
return "USER," + sm.SourceID.ToString();
default://actually error condition, should throw but instead will return something recognizable in case debugging remotely but not crashable to avoid crashing some poor bastards system when they are just trying to get shit done
return "ScheduleMarkerSourceTypeSelectedValue() NO MATCH OF TYPE," + sm.SourceID.ToString();
}
}
static public Dictionary<string, string> AllUsersList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
UserPickList uList = UserPickList.GetList(false);
ScheduleableUserNameDisplayFormats fmt = AyaBizUtils.GlobalSettings.DefaultScheduleableUserNameDisplayFormat;
foreach (UserPickList.UserPickListInfo ui in uList)
{
if (ui.Active == true)
{
dd.Add(ui.ID.ToString(), ui.Name);
}
}
return dd;
}
static public Dictionary<string, string> AllInternalStaffOnlyList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
UserPickList uList = UserPickList.GetInternalStaffOnlyList(false);
ScheduleableUserNameDisplayFormats fmt = AyaBizUtils.GlobalSettings.DefaultScheduleableUserNameDisplayFormat;
foreach (UserPickList.UserPickListInfo ui in uList)
{
if (ui.Active == true)
{
dd.Add(ui.ID.ToString(), ui.Name);
}
}
return dd;
}
static public Dictionary<string, string> WorkordersForClientPickList(Guid clientId, Guid skipWorkorderId)
{
Dictionary<string, string> dd = new Dictionary<string, string>();
//this is required because the forms that use this are select once only
//and not tied to any existing data so if there is nothing to change *from*
//then the dirty checking code won't allow save
//this ensures there is always a change of selection triggered
AddEmptyItem(dd);
WorkorderPickList PickList = WorkorderPickList.GetListByClient(clientId);
foreach (WorkorderPickList.WorkorderPickListInfo pfo in PickList)
{
if (pfo.ID != skipWorkorderId)
{
dd.Add(pfo.ID.ToString(), pfo.ServiceNumber + " - " + pfo.ServiceDate.ToString() + " \"" + pfo.Summary + "\"");
}
}
return dd;
}
/// <summary>
/// Generic picklist
/// </summary>
/// <param name="tableName"></param>
/// <param name="emptyOk"></param>
/// <returns></returns>
static public Dictionary<string, string> PickListOf(string tableName, bool emptyOk = true)
{
Dictionary<string, string> dd = new Dictionary<string, string>();
if (emptyOk)
AddEmptyItem(dd);
GenericNVList l = GenericNVList.GetList(tableName, "AID", "ANAME", true, false, false);
for (int x = 0; x < l.Count; x++)
{
dd.Add(((System.Collections.DictionaryEntry)l.BindableList[x]).Key.ToString(),
((System.Collections.DictionaryEntry)l.BindableList[x]).Value.ToString());
}
return dd;
}
/// <summary>
/// List for client portal workorder report selection
/// </summary>
/// <returns></returns>
static public Dictionary<string, string> ClientPortalServiceWorkorderReportList()
{
Dictionary<string, string> dd = new Dictionary<string, string>();
AddEmptyItem(dd);
ReportPickList r = ReportPickList.GetList(WorkorderServiceList.ReportKey,
WorkorderServiceDetailedReportData.ReportKey, false);
foreach (ReportPickList.ReportPickListInfo i in r)
{
if (i.Active)
dd.Add(i.ID.ToString(), i.Name);
}
return dd;
}
#endregion select ayanova lists
#region Formatting and converters
/// <summary>
/// Convert carriage returns to html breaks
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string StringWebify(string input)
{
if (string.IsNullOrEmpty(input)) return "";
return input.Replace("\r\n", "<br/>")
.Replace("\r", "<br/>")
.Replace("\n", "<br/>");
}
/// <summary>
/// Web color from ARGB integer value
/// </summary>
/// <param name="argb"></param>
/// <returns></returns>
public static string hexColorFromARGB(int argb)
{
return ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(argb));
}
/// <summary>
/// given a picklist and a status returns the hex color required to show it
/// </summary>
/// <param name="pl"></param>
/// <param name="statId"></param>
/// <returns></returns>
public static string hexColorFromWorkorderStatusId(WorkorderStatusPickList pl, Guid statId)
{
if (pl.Contains(statId))
{
return hexColorFromARGB(pl[statId].Color);
}
else
{
return "#FFFFFF";
}
}
/// <summary>
/// Web hex color to ARGB integer value
/// </summary>
/// <param name="hexcolor"></param>
/// <returns></returns>
public static int argbFromHexColor(string hexcolor)
{
return System.Drawing.ColorTranslator.FromHtml(hexcolor).ToArgb();
}
/// <summary>
/// Date a date time object and return
/// an ISO 8601 string compatible with most javascript objects and
/// html components that deal with date time
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
static public string isoDatetime(DateTime dt)
{
return dt.ToString("s");
}
//take an ayanova object and return a string representatin
static public string parseObjectIntoDateTimeValueString(object Value, string formatString = "g")
{
DateTime dt = parseObjectIntoDateTimeValue(Value);
if (dt == DateTime.MinValue)
{
return "-";
}
else
{
return dt.ToString(formatString);
}
}
//Take an AyaNova object containing some form of date and try to make
//it into a valid C# dateTime
static public DateTime parseObjectIntoDateTimeValue(object Value)
{
if (Value is DateTime)
return (DateTime)Value;
else
{
if (Value != null && Value.ToString() != "")
{
DateTime dt = new DateTime();
if (DateTime.TryParse(Value.ToString(), out dt))
{
return dt;
}
else
{
if (DateTime.TryParse(Value.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
return dt;
}
}
}
return DateTime.MinValue;
}
static public bool dateTimeObjectHasValue(object Value)
{
if (Value is DateTime)
{
return ((DateTime)Value)!=DateTime.MinValue;
}
else
{
if (Value != null && Value.ToString() != "")
{
DateTime dt = new DateTime();
if (DateTime.TryParse(Value.ToString(), out dt))
{
return dt != DateTime.MinValue;
}
else
{
if (DateTime.TryParse(Value.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.None, out dt))
return dt != DateTime.MinValue;;
}
}
}
return false;
}
#endregion
#region Form custom field helpers
static public bool customFieldsAvailable(string sObject)
{
ObjectCustomFields ocf = ObjectCustomFields.GetItems(sObject);
if (ocf.Count == 0) return false;
foreach (ObjectCustomField f in ocf)
if (f.Visible)
return true;
return false;
}
//generate a custom fields editor form from the defined saved settings
static public MvcHtmlString edCustomFields(object bizObject, string sObjectName, dynamic viewBag)
{
StringBuilder sb = new StringBuilder();
ObjectCustomFields ocf = ObjectCustomFields.GetItems(sObjectName);
int controlCount = 0;
bool hasCustomFields = false;
bool needsClosingTag = false;
foreach (ObjectCustomField f in ocf)
{
if (f.Visible)
{
hasCustomFields = true;
needsClosingTag = true;
//do we need to start a new row?
if (controlCount == 0)
sb.AppendLine("<div class=\"row\">");
//get the value from the biz object
object o = (object)bizObject.GetType().GetProperty(f.FieldName).GetValue(bizObject, null);
if (o == null) o = "";
string sVal = o.ToString();
string sTitleKey = sObjectName + ".Label." + f.FieldName;
//Make an input group
switch (f.FieldType)
{
case FormFieldDataTypes.Text:
sb.AppendLine(edTextGroupAsString(sTitleKey, f.FieldName, sVal, string.Empty, viewBag, 500));
controlCount++;
break;
case FormFieldDataTypes.TrueFalse:
sb.AppendLine(edCheckGroupAsString(sTitleKey, f.FieldName, parseBool(sVal), string.Empty, viewBag));
controlCount++;
break;
case FormFieldDataTypes.DateTime:
sb.AppendLine(edDateTimeGroupAsString(sTitleKey, f.FieldName, sVal, viewBag, false));
controlCount++;
break;
case FormFieldDataTypes.Currency:
//TODO:wtf do I do with this? Put a $ in front of it?
sb.AppendLine(edCurrencyGroupAsString(sTitleKey, f.FieldName, sVal, viewBag, false));
controlCount++;
break;
case FormFieldDataTypes.DateOnly:
sb.AppendLine(edDateGroupAsString(sTitleKey, f.FieldName, sVal, viewBag, false));
controlCount++;
break;
case FormFieldDataTypes.Number:
sb.AppendLine(edNumberGroupAsString(sTitleKey, f.FieldName, sVal, true, viewBag, false));
controlCount++;
break;
case FormFieldDataTypes.TimeOnly:
sb.AppendLine(edTimeGroupAsString(sTitleKey, f.FieldName, sVal, viewBag, false));
controlCount++;
break;
}
if (controlCount == 3)
{
controlCount = 0;
needsClosingTag = false;
sb.AppendLine("</div>");
}
}
}//end of foreach
if (hasCustomFields && needsClosingTag)
sb.AppendLine("</div>");
return new MvcHtmlString(sb.ToString());
}
//Populate custom fields in biz object from FormCollection
static public void getCustomFields(object bizObject, string sObjectName, FormCollection fc)
{
ObjectCustomFields ocf = ObjectCustomFields.GetItems(sObjectName);
foreach (ObjectCustomField f in ocf)
{
if (f.Visible)
{
string sData = fc[f.FieldName];
if (sData.Length > 500) sData = sData.Substring(0, 500);
//BUGBUG: issue here with bools?
// sData "true,false" string
//Needs a special handler for bools and maybe other things, need to roundtrip every type between ri wbi and windows to be sure
if (sData == "true,false")
sData = true.ToString();
bizObject.GetType().GetProperty(f.FieldName).SetValue(bizObject, sData, null);
}
}
}
#endregion
#region Form address helpers
static public Dictionary<string, string> LatitudeList()
{
Dictionary<string, string> l = new Dictionary<string, string>(2);
l.Add(((int)LatitudeHemisphere.North).ToString(), lt("UI.Label.North"));
l.Add(((int)LatitudeHemisphere.South).ToString(), lt("UI.Label.South"));
return l;
}
static public Dictionary<string, string> LongitudeList()
{
Dictionary<string, string> l = new Dictionary<string, string>(2);
l.Add(((int)LongitudeHemisphere.West).ToString(), lt("UI.Label.West"));
l.Add(((int)LongitudeHemisphere.East).ToString(), lt("UI.Label.East"));
return l;
}
/// <summary>
/// Take address info and device type and return an url that will hopefully open the native map app
/// or at least google maps web page centered on the address
/// </summary>
/// <param name="deviceType"></param>
/// <param name="streetAddress"></param>
/// <param name="addressLocality"></param>
/// <param name="addressRegion"></param>
/// <param name="postal"></param>
/// <param name="country"></param>
/// <returns></returns>
private static string genAddressUrl(string userAgentString, string street, string city, string stateprov, string postal, string country)
{
//inspired by http://www.habaneroconsulting.com/insights/Translating-schemaorgs-postalAddress-microdata-into-useful-links-for-mobile#.VEafEiLF8bk
if (string.IsNullOrWhiteSpace(street) &&
string.IsNullOrWhiteSpace(city) &&
string.IsNullOrWhiteSpace(stateprov) &&
string.IsNullOrWhiteSpace(postal) &&
string.IsNullOrWhiteSpace(country))
return string.Empty;
string deviceType = Platform(userAgentString);
string ret;
string path;
switch (deviceType)
{
case "ios":
// "xxxhttp://maps.google.com?saddr=Current Location&daddr={streetAddress} {addressLocality} {addressRegion} {postalCode} {addressCountry}"
path = "http://maps.google.com?";
ret = "saddr=Current Location&daddr=" + AyaBizUtils.SS("", street) + AyaBizUtils.SS(" ", city) + AyaBizUtils.SS(" ", stateprov) + AyaBizUtils.SS(" ", postal) + AyaBizUtils.SS(" ", country);
break;
case "android":
// "geo:{streetAddress} {addressLocality} {addressRegion} {postalCode} {addressCountry}"
path = "geo:0,0?=";
ret = AyaBizUtils.SS("", street) + AyaBizUtils.SS(" ", city) + AyaBizUtils.SS(" ", stateprov) + AyaBizUtils.SS(" ", postal) + AyaBizUtils.SS(" ", country);
break;
case "windowsphone":
// "maps:{streetAddress} {addressLocality} {addressRegion} {postalCode} {addressCountry}"
path = "maps:";
ret = AyaBizUtils.SS("", street) + AyaBizUtils.SS(" ", city) + AyaBizUtils.SS(" ", stateprov) + AyaBizUtils.SS(" ", postal) + AyaBizUtils.SS(" ", country);
break;
case "blackberry":
// "xxxjavascript:blackberry.launch.newMap({'address':{'address1':'{streetAddress}','city':'{addressLocality}','country':'{addressCountry}','stateProvince':'{addressRegion}','zipPostal':'{postalCode}'}});"
//this is backwards intentionally so that the javascript doesn't get url encoded
ret = "";
path = "javascript:blackberry.launch.newMap({'address':{'address1':'" + street + "','city':'" + city + "','country':'" + country + "','stateProvince':'" + stateprov + "','zipPostal':'" + postal + "'}});";
break;
case "default":
default:
// "xxxhttp://maps.google.com?q={streetAddress} {addressLocality} {addressRegion} {postalCode} {addressCountry}"
path = "http://maps.google.com?";
ret = "q=" + AyaBizUtils.SS("", street) + AyaBizUtils.SS(" ", city) + AyaBizUtils.SS(" ", stateprov) + AyaBizUtils.SS(" ", postal) + AyaBizUtils.SS(" ", country);
break;
}
string final = path + HttpUtility.UrlPathEncode(ret);//ret;//
return final;
}
/// <summary>
/// Returns a platform specific actionable url link for addresses
/// </summary>
/// <param name="userAgentString"></param>
/// <param name="street"></param>
/// <param name="city"></param>
/// <param name="stateprov"></param>
/// <param name="postal"></param>
/// <param name="country"></param>
/// <returns></returns>
static public string edAddressLink(string userAgentString, string street, string city, string stateprov, string postal, string country)
{
//"</label><a class=\"btn btn-sm\" href=\"" + LinkUrl + "\"" + targ + " role=\"button\"><span class=\"glyphicon glyphicon-flash\"></span></a>
string addrUrl = genAddressUrl(userAgentString, street, city, stateprov, postal, country);
if (string.IsNullOrWhiteSpace(addrUrl)) return string.Empty;//new MvcHtmlString(string.Empty);
return "<a class=\"btn btn-xs\" href=\"" + addrUrl + "\" target=\"_blank\" role=\"button\"><span class=\"ay-action-link glyphicon glyphicon-flash\"></span></a>";
//return new MvcHtmlString("<a class=\"btn btn-sm\" href=\"" + MvcHtmlString.Create(addrUrl) + "\" target=\"_blank\" role=\"button\"><span class=\"ay-action-link glyphicon glyphicon-flash\"></span></a>");
}
#endregion form address helpers
#region Form dynamic menu
static public MvcHtmlString genCustomMenu(ayMenu m)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<li class=\"dropdown\">");
sb.AppendLine("<a href=\"\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">");
if (!string.IsNullOrWhiteSpace(m.icon))
sb.AppendLine(" <span class=\"ay-menu-icon " + m.icon + "\">&nbsp;</span>");
//TODO: hide this when small
sb.AppendLine("<span class=\"hidden-md hidden-sm\">");
sb.AppendLine(lt(m.title));
sb.AppendLine("</span>");
sb.AppendLine("<b class=\"caret\"></b>");
sb.AppendLine("</a>");
sb.AppendLine(" <ul class=\"dropdown-menu\">");
foreach (ayMenuItem i in m.menuItems)
{
string hrefClass = string.Empty;
if (!string.IsNullOrWhiteSpace(i.hrefClass))
hrefClass = " class=\"" + i.hrefClass + "\" ";
switch (i.type)
{
case "header":
sb.AppendLine("<li class=\"dropdown-header\">");
sb.AppendLine(lt(i.title));
sb.AppendLine("</li>");
break;
case "divider":
sb.AppendLine("<li class=\"divider\" </li>");
break;
case "navitem":
sb.AppendLine("<li>");
//<a data-ayconfirmprompt="Are you sure you want to delete this record permanently?" href="/AyaNovaRI/Project/Delete/3eb5328c-2f9e-4317-88aa-e2b44e03659e">Delete</a>
string confirmPrompt = string.Empty;
if (i.prompt != string.Empty)
confirmPrompt = " data-ayconfirmprompt=\"" + i.prompt + "\" ";
sb.AppendLine("<a href=\"" + i.action + "\"" + hrefClass + confirmPrompt + ">");
if (!string.IsNullOrWhiteSpace(i.icon))
sb.AppendLine(" <span class=\"ay-menu-icon " + i.icon + "\">&nbsp;</span>");
sb.AppendLine(lt(i.title));
sb.AppendLine("</a>");
sb.AppendLine("</li>");
break;
case "scriptitem":
sb.AppendLine("<li>");
//case 2069 added href to force hover cursor correct
sb.AppendLine("<a href=\"#\" onclick=\"" + i.action + "\"" + hrefClass + ">");
if (!string.IsNullOrWhiteSpace(i.icon))
sb.AppendLine(" <span class=\"ay-menu-icon " + i.icon + "\">&nbsp;</span>");
sb.AppendLine(lt(i.title));
sb.AppendLine("</a>");
sb.AppendLine("</li>");
break;
}
}
sb.AppendLine("</ul>");
sb.AppendLine("</li>");
return new MvcHtmlString(sb.ToString());
}
#endregion
#region Schedule helpers
#region User selection list
public static MvcHtmlString getSchedUsersDropDown()
{
return new MvcHtmlString(getSchedUsersDropDownAsString());
}
public static string getSchedUsersDropDownAsString()
{
Guid defaultSchedUserId = Guid.Empty;
if (User.CurrentUserType == UserTypes.Schedulable)
defaultSchedUserId = User.CurrentThreadUserID;
StringBuilder sb = new StringBuilder();
ScheduleableUserNameDisplayFormats fmt = AyaBizUtils.GlobalSettings.DefaultScheduleableUserNameDisplayFormat;
UserListScheduleable uls = UserListScheduleable.GetList();
bool selectedSet = false;
sb.AppendLine("<div id=\"ayUsersDiv\"><h2><select name=\"ayUsers\" onchange=\"ayRefetch()\" id=\"ayUsers\">");
foreach (UserListScheduleable.UserListScheduleableInfo i in uls)
{
if (i.Active)
{
if (i.ID == defaultSchedUserId)
{
selectedSet = true;
sb.AppendLine("<option selected=\"selected\" value=\"" + i.ID.ToString() + "\">" + i.Name(fmt) + "</option>");
}
else
{
sb.AppendLine("<option value=\"" + i.ID.ToString() + "\">" + i.Name(fmt) + "</option>");
}
}
}
if (!selectedSet)
{
sb.AppendLine("<option selected=\"selected\" value=\"" + Guid.Empty.ToString() + "\">" + ay.lt("Dashboard.Label.NotAssigned") + "</option>");
}
else
{
sb.AppendLine("<option value=\"" + Guid.Empty.ToString() + "\">" + ay.lt("Dashboard.Label.NotAssigned") + "</option>");
}
sb.AppendLine("</select></h2></div>");
return sb.ToString();
}
#endregion user selection list
#region Get events
public static List<ayEvent> getScheduleEvents(string start, string end, Guid activeUserId)
{
List<ayEvent> events = new List<ayEvent>();
DateTime dtStart = ay.ParseDateTimeToDateTime(start);
DateTime dtEnd = ay.ParseDateTimeToDateTime(end);
AppointmentList apl = AppointmentList.GetList(dtStart, dtEnd, activeUserId);
UserListScheduleable uls = UserListScheduleable.GetList();
foreach (AppointmentList.AppointmentListInfo i in apl)
{
switch (i.SourceObjectType)
{
case RootObjectTypes.WorkorderItemScheduledUser:
{
#region populate woitems
if (activeUserId == i.AppliesToObjectID)
{
ayEvent e = new ayEvent();
//comma delimited identifiers: WO for workorder, workorder id, workorder item id, workorderitemscheduleduserid
e.id = "WO," + i.WorkorderID.ToString() + "," + i.WorkorderItemID + "," + i.SourceObjectID;
e.woId = i.WorkorderID;
e.woItemId = i.WorkorderItemID;
e.woItemScheduledUserId = i.SourceObjectID;
e.title = i.Subject;
e.start = isoDatetime(i.StartDateTime);
e.end = isoDatetime(i.EndDateTime);
e.showFlag = false;
if (i.ShowPriorityFlag)
{
e.showFlag = true;
e.flagColor = hexColorFromARGB(i.PriorityARGB);
}
if (i.BackColorARGB != 0)
e.statusColor = hexColorFromARGB(i.BackColorARGB);
e.isWo = true;
//<!-- Parameters : LinkText, ActionName, Controller, RouteValues, HtmlAttributes -->
// UrlHelper.GenerateUrl("workorderroute","indexaction","workorderctrl",new {id:e.id});
//e.url=System.Web.Mvc.Html.LinkExtensions.ActionLink((string)post.Title, "Details", "Posts", new { id = post.id },null)
events.Add(e);
}
#endregion
}
break;
case RootObjectTypes.ScheduleMarker:
{
#region populate ScheduleMarker
if (shouldCreateScheduleMarker(activeUserId, i, uls))
{
ayEvent e = new ayEvent();
e.showFlag = false;//always false since it applies to wo only
//comma delimited identifier: SM for schedule marker, schedulemarkerID
e.id = "SM," + i.SourceObjectID.ToString();
e.scheduleMarkerId = i.SourceObjectID;
e.title = i.Subject;
e.start = isoDatetime(i.StartDateTime);
e.end = isoDatetime(i.EndDateTime);
e.statusColor = hexColorFromARGB(i.BackColorARGB);
e.isWo = false;
events.Add(e);
}
#endregion populate sched marker
}//case schedulemarker
break;
}
}
return events;
}
private static bool shouldCreateScheduleMarker(Guid activeUserId, AppointmentList.AppointmentListInfo i, UserListScheduleable uls)
{
//Don't process for unassigned user
if (activeUserId == Guid.Empty) return false;
//Could be a bunch by region , global , dispatchzone, schedusergroup
//or could be a single by one user ID
switch (i.AppliesToObjectType)
{
case RootObjectTypes.User:
{
if (i.AppliesToObjectID == activeUserId)
return true;
}
break;
case RootObjectTypes.Region:
{
if (uls[activeUserId].RegionID == i.AppliesToObjectID)
return true;
}
break;
case RootObjectTypes.DispatchZone:
{
if (uls[activeUserId].DispatchZoneID == i.AppliesToObjectID)
return true;
}
break;
case RootObjectTypes.ScheduleableUserGroup:
{
ScheduleableUserGroupUsersList ScheduleMarkerGroup = ScheduleableUserGroupUsersList.GetList(i.AppliesToObjectID);
if (ScheduleMarkerGroup.Contains(activeUserId))//Case 835
return true;
}
break;
case RootObjectTypes.Global:
{
return true;
}
}
return false;
}
#endregion getevents
#region Update event
public static string updateEvent(string id, string newStart, string newEnd)
{
//Fullcalendar gives the dates in UTC with a Z at the end so remove the Z
newStart = newStart.Replace("Z", "");
newEnd = newEnd.Replace("Z", "");
if (id.StartsWith("WO"))
{
//comma delimited identifiers: WO for workorder, workorder id, workorder item id, workorderitemscheduleduserid
//e.id = "WO," + i.WorkorderID.ToString() + "," + i.WorkorderItemID + "," + i.SourceObjectID;
try
{
string[] s = id.Split(',');
Guid woId = Guid.Parse(s[1]);
Guid woItemId = Guid.Parse(s[2]);
Guid woScheduleUserId = Guid.Parse(s[3]);
Workorder w = Workorder.GetItem(woId);
WorkorderItemScheduledUser wisu = w.WorkorderItems[woItemId].ScheduledUsers[woScheduleUserId.ToString()];
wisu.StartDate = ParseDateTimeToDateTime(newStart);
wisu.StopDate = ParseDateTimeToDateTime(newEnd);
if (w.IsSavable)
w.Save();
else
{
return w.GetBrokenRulesString();
}
}
catch (Exception ex)
{
return ay.exceptionToHumanString(ex);
}
return string.Empty;
}
else
{
//comma delimited identifier: SM for schedule marker, schedulemarkerID
//e.id = "SM," + i.SourceObjectID.ToString();
try
{
string[] s = id.Split(',');
Guid smId = Guid.Parse(s[1]);
ScheduleMarker sm = ScheduleMarker.GetItem(smId);
sm.StartDate = ParseDateTimeToDateTime(newStart);
sm.StopDate = ParseDateTimeToDateTime(newEnd);
if (sm.IsSavable)
sm.Save();
else
{
return sm.GetBrokenRulesString();
}
}
catch (Exception ex)
{
return ay.exceptionToHumanString(ex);
}
return string.Empty;
}
}
#endregion update event
#endregion schedule helpers
#region URL helpers
public static string UrlOf(RootObjectTypes aytype, Guid Id, UrlHelper url)
{
return UrlOf(new TypeAndID(aytype, Id), url, TypeAndID.Empty);
}
public static string UrlOf(TypeAndID tid, UrlHelper url)
{
return UrlOf(tid, url, TypeAndID.Empty);
}
public static string UrlOf(RootObjectTypes aytype, Guid Id, UrlHelper url, RootObjectTypes ancestorType, Guid ancestorId)
{
return UrlOf(new TypeAndID(aytype, Id), url, new TypeAndID(ancestorType,ancestorId));
}
public static string UrlOf(TypeAndID tid, UrlHelper url, TypeAndID ancestorTid)
{
string baseSiteURL = genBaseSiteUrl(url);
switch (tid.RootObjectType)
{
case RootObjectTypes.Client:
return baseSiteURL + "Client/edit/" + tid.ID.ToString();
case RootObjectTypes.ClientServiceRequest:
return baseSiteURL + "ClientServiceRequest/view/" + tid.ID.ToString();
case RootObjectTypes.Contract:
return baseSiteURL + "Contract/edit/" + tid.ID.ToString();
case RootObjectTypes.HeadOffice:
return baseSiteURL + "HeadOffice/edit/" + tid.ID.ToString();
case RootObjectTypes.Part:
return baseSiteURL + "Part/edit/" + tid.ID.ToString();
case RootObjectTypes.Unit:
return baseSiteURL + "Unit/edit/" + tid.ID.ToString();
case RootObjectTypes.UnitModel:
return baseSiteURL + "UnitModel/edit/" + tid.ID.ToString();
//case RootObjectTypes.Vendor:
// return baseSiteURL + "Vendor/edit/" + tid.ID.ToString();
case RootObjectTypes.Workorder:
return baseSiteURL + "Workorder/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderService:
{
return baseSiteURL + "Workorder/edit/" + WorkorderIDFetcher.GetWorkorderByRelative(RootObjectTypes.WorkorderService, tid.ID).ToString();
}
case RootObjectTypes.WorkorderQuote:
{
return baseSiteURL + "Workorder/edit/" + WorkorderIDFetcher.GetWorkorderByRelative(RootObjectTypes.WorkorderQuote, tid.ID).ToString();
}
case RootObjectTypes.WorkorderPreventiveMaintenance:
{
return baseSiteURL + "Workorder/edit/" + WorkorderIDFetcher.GetWorkorderByRelative(RootObjectTypes.WorkorderPreventiveMaintenance, tid.ID).ToString();
}
case RootObjectTypes.WorkorderItem:
return baseSiteURL + "Workorder/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemLabor:
return baseSiteURL + "Labor/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemTravel:
return baseSiteURL + "Travel/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemScheduledUser:
return baseSiteURL + "ScheduledUser/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemOutsideService:
return baseSiteURL + "outservice/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemPartRequest:
return baseSiteURL + "partrequest/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemPart:
return baseSiteURL + "wopart/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemLoan:
return baseSiteURL + "LoanItem/edit/" + tid.ID.ToString();
case RootObjectTypes.WorkorderItemMiscExpense:
return baseSiteURL + "Expense/edit/" + tid.ID.ToString();
case RootObjectTypes.ServiceBank:
throw new System.NotSupportedException("UTIL->UrlOf->SERVICE BANK NOT SUPPORTED IN THIS METHOD, USE Util->ServiceBankUrl() method instead");
//No edit for this object, so url is different to view
// return baseSiteURL + "ServiceBank?id=" + tid.ID.ToString()+ "&aytype=" + ((int)tid.RootObjectType).ToString();;
case RootObjectTypes.UnitMeterReading:
//No edit for this object, so url is different to view
//return baseSiteURL + "MeterReading?id=" + tid.ID.ToString();
throw new System.NotSupportedException("UTIL->UrlOf->METER READING NOT SUPPORTED IN THIS METHOD, USE Util->MeterReadingUrl() method instead");
case RootObjectTypes.WikiPage:
{
if (ancestorTid.IsEmpty)
{
throw new System.NotSupportedException("UTIL->UrlOf->WIKIPAGE EMPTY ancestorTid!");
}
return WikiUrl(ancestorTid.RootObjectType, ancestorTid.ID, url);
}
case RootObjectTypes.AyaFile:
throw new System.NotSupportedException("UTIL->UrlOf->AyaFile NOT SUPPORTED IN THIS METHOD, USE Util->WikiFileUrl() method instead");
case RootObjectTypes.ScheduleMarker:
return baseSiteURL + "ScheduleMarker/edit?id=" + tid.ID.ToString();
//these are up in the air because they may or may not have their own controller
//see workordercontroller edit code for way it would be done if not own controller or
//do this if own controller:
//case RootObjectTypes.WorkorderServiceTemplate:
// return baseSiteURL + "ServiceTemplate/edit/" + tid.ID.ToString();
//case RootObjectTypes.WorkorderQuoteTemplate:
// return baseSiteURL + "QuoteTemplate/edit/" + tid.ID.ToString();
//case RootObjectTypes.WorkorderPreventiveMaintenanceTemplate:
// return baseSiteURL + "PMTemplate/edit/" + tid.ID.ToString();
default:
//throw new System.ArgumentOutOfRangeException("The type of: \"" + tid.RootObjectType.ToString() + "\" was not recognized");
return "";//not implemented
}
}
public static string WikiUrl(RootObjectTypes aytype, Guid Id, UrlHelper url, bool edit = false)
{
if (edit)
return genBaseSiteUrl(url) + "WikiPage/edit?id=" + Id.ToString() + "&aytype=" + ((int)aytype).ToString();
else
return genBaseSiteUrl(url) + "WikiPage?id=" + Id.ToString() + "&aytype=" + ((int)aytype).ToString();
}
public static string WikiFileUrl(RootObjectTypes aytype, Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "WikiFile?id=" + Id.ToString() + "&aytype=" + ((int)aytype).ToString();
}
public static string ServiceBankUrl(RootObjectTypes aytype, Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "ServiceBank?id=" + Id.ToString() + "&aytype=" + ((int)aytype).ToString();
}
public static string MeterReadingUrl(Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "MeterReading?id=" + Id.ToString();
}
public static string genBaseSiteUrl(UrlHelper url)
{
return url.Content("~/");
}
public static string ClientUserWikiUrl(RootObjectTypes aytype, Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "Customer/WikiPage?id=" + Id.ToString() + "&aytype=" + ((int)aytype).ToString();
}
public static string ClientUserWOReportUrl(Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "Customer/WOReport?id=" + Id.ToString() + "&ayf=" + url.RequestContext.HttpContext.Request.RawUrl;
}
public static string ClientUserCSRUrl(Guid Id, UrlHelper url)
{
return genBaseSiteUrl(url) + "Customer/CSREdit?CSRId=" + Id.ToString();// +"&ClientId=" + Guid.Empty.ToString();
}
#endregion url helpers
#region Browser info helpers
/// <summary>
/// Return a platform string based on the user agent info
/// </summary>
/// <param name="userAgentString"></param>
/// <returns></returns>
public static string Platform(string userAgentString)
{
if (string.IsNullOrWhiteSpace(userAgentString))
return "default";
string u = userAgentString.ToLowerInvariant();
if (u.Contains("ipad"))
return "ios";
if (u.Contains("ipod"))
return "ios";
if (u.Contains("iphone"))
return "ios";
if (u.Contains("android"))
return "android";
if (u.Contains("blackberry"))
return "blackberry";
if (u.Contains("windows phone"))
return "windowsphone";
return "default";
}
#endregion
#region LOCATION AND URL HISTORY HELPERS
//public static void setOldFromUrl(dynamic ViewBag, FormCollection f)
//{
// if (f["ayRetUrl"] != null)
// {
// ViewBag.ayOldFromUrl = f["ayRetUrl"];
// return;
// }
// ViewBag.ayOldFromUrl = null;
// return;
//}
//public static void setNewFromUrl(dynamic ViewBag)
//{
// if (ViewBag.ayOldFromUrl != null)
// ViewBag.ayFromUrl = ViewBag.ayOldFromUrl;
// else
// ViewBag.ayFromUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
//}
//public static void setRetUrl(dynamic ViewBag, string ret, UrlHelper url)
//{
// //genBaseSiteUrl(url)
// if (string.IsNullOrWhiteSpace(ret))
// {
// ret = System.Web.HttpContext.Current.Request.UrlReferrer.ToString();
// //ret = ret.Replace(genBaseSiteUrl(url), "");
// ret=url.Encode(ret);
// }
// ViewBag.ret = ret;
//}
#endregion
#region JAVASCRIPT FORM SNIPPETS
static public MvcHtmlString jsAreYouSure()
{
return new MvcHtmlString(
"\r\n<script> \r\n" +
" $(document).ready(function () { \r\n" +
" $('form').areYouSure(); \r\n" +
//--------------
" $('form').on('dirty.areYouSure', function() { \r\n" +
" $(this).find('button[type=\"submit\"]').removeAttr('disabled'); \r\n" +
" }); \r\n" +
" $('form').on('clean.areYouSure', function() { \r\n" +
" $(this).find('button[type=\"submit\"]').attr('disabled', 'disabled'); \r\n" +
" }); \r\n" +
//---------------
" }); \r\n" +
"</script> "
);
}
#endregion
#region ICON HELPERS
public static string IconOf(RootObjectTypes aytype, string withClass = "")
{
//default icon is glyphicon glyphicon-warning-sign
//to indicate there is no provided icon for that object
string ico = string.Empty;
if (!string.IsNullOrWhiteSpace(withClass))
withClass = " " + withClass + " ";
switch (aytype)
{
case RootObjectTypes.Part:
ico = "icon-Part";
break;
case RootObjectTypes.Rate:
ico = "icon-Rate";
break;
case RootObjectTypes.Notification:
ico = "icon-Notification";
break;
case RootObjectTypes.PartSerial:
ico = "icon-PartSerial";
break;
case RootObjectTypes.Report:
ico = "icon-Report";
break;
case RootObjectTypes.PartWarehouse:
ico = "icon-PartWarehouse";
break;
case RootObjectTypes.UnitMeterReading:
ico = "icon-UnitMeterReading";
break;
case RootObjectTypes.Priority:
ico = "icon-Priority";
break;
case RootObjectTypes.WorkorderStatus:
ico = "icon-WorkorderStatus";
break;
case RootObjectTypes.Workorder:
case RootObjectTypes.WorkorderService:
ico = "icon-Workorder";
break;
case RootObjectTypes.ServiceBank:
ico = "icon-ServiceBank";
break;
case RootObjectTypes.Project:
ico = "icon-Project";
break;
case RootObjectTypes.WorkorderServiceTemplate:
ico = "icon-WorkorderServiceTemplate";
break;
case RootObjectTypes.WorkorderQuote:
ico = "icon-WorkorderQuote";
break;
case RootObjectTypes.WorkorderPreventiveMaintenance:
ico = "icon-WorkorderPreventiveMaintenance";
break;
case RootObjectTypes.AyaFile:
ico = "icon-WikiFile";
break;
case RootObjectTypes.WikiPage:
ico = "icon-WikiPage";
break;
case RootObjectTypes.PartInventoryAdjustment:
ico = "icon-PartInventoryAdjustment";
break;
case RootObjectTypes.WorkorderItemPartRequest:
ico = "icon-WorkorderItemPartRequest";
break;
case RootObjectTypes.PartByWarehouseInventory:
ico = "icon-PartByWarehouseInventory";
break;
case RootObjectTypes.WorkorderItemMiscExpense:
ico = "icon-WorkorderItemMiscExpense";
break;
case RootObjectTypes.Contract:
ico = "icon-Contract";
break;
case RootObjectTypes.ClientNote:
ico = "icon-ClientNote";
break;
case RootObjectTypes.ClientServiceRequest:
ico = "icon-ClientServiceRequest";
break;
case RootObjectTypes.Region:
ico = "icon-Region";
break;
case RootObjectTypes.Memo:
ico = "icon-Memo";
break;
case RootObjectTypes.User:
ico = "icon-User";
break;
case RootObjectTypes.Vendor:
ico = "icon-Vendor";
break;
case RootObjectTypes.WorkorderItemUnit:
ico = "icon-WorkorderItemUnit";
break;
case RootObjectTypes.UnitModel:
ico = "icon-UnitModel";
break;
case RootObjectTypes.Unit:
ico = "icon-WorkorderItemUnit";
break;
case RootObjectTypes.Client:
ico = "icon-Client";
break;
case RootObjectTypes.HeadOffice:
ico = "icon-HeadOffice";
break;
case RootObjectTypes.WorkorderItemOutsideService:
ico = "icon-WorkorderItemOutsideService";
break;
case RootObjectTypes.WorkorderItemLoan:
ico = "icon-WorkorderItemLoan";
break;
case RootObjectTypes.WorkorderItemLabor:
ico = "icon-WorkorderItemLabor";
break;
case RootObjectTypes.WorkorderItemTask:
ico = "icon-WorkorderItemTask";
break;
case RootObjectTypes.ScheduleMarker:
ico = "icon-ScheduleMarker";
break;
case RootObjectTypes.FollowUp:
ico = "icon-FollowUp";
break;
case RootObjectTypes.Schedule:
ico = "icon-Schedule";
break;
case RootObjectTypes.WorkorderItemScheduledUser:
ico = "icon-WorkorderItemScheduledUser";
break;
case RootObjectTypes.WorkorderItem:
ico = "icon-WorkorderItem";
break;
default:
//missing icon warning icon
ico = "glyphicon glyphicon-warning-sign";
break;
}
return "<span class=\"" + withClass + ico + "\"></span>";
}
/// <summary>
/// HTML code for a checkmark symbol
/// </summary>
public static string CheckMarkUp
{
get
{
return "&#10004;";
}
}
#endregion icon helpers
#region REPORTING HELPERS
//Given report key, return list of available reports as markup
static public MvcHtmlString ReportListMarkup(string ReportKeySummary, string ReportKeyDetailed)
{
// <div class="list-group">
// <button type="button" class="list-group-item">Cras justo odio</button>
// <button type="button" class="list-group-item">Dapibus ac facilisis in</button>
// <button type="button" class="list-group-item">Morbi leo risus</button>
// <button type="button" class="list-group-item">Porta ac consectetur ac</button>
// <button type="button" class="list-group-item">Vestibulum at eros</button>
//</div>
System.Text.StringBuilder sb = new StringBuilder();
sb.AppendLine("<ul class=\"list-group\">");
ReportPickList rpl = ReportPickList.GetList(ReportKeySummary, ReportKeyDetailed, true);
foreach (ReportPickList.ReportPickListInfo i in rpl)
{
if (i.Active)
{
string sValue = string.Empty;
if (i.IsSummary)
sValue = "PRINTSUMMARY," + i.ID.ToString();
else
sValue = "PRINTDETAILED," + i.ID.ToString();
sb.AppendLine("<li class=\"list-group-item\">");
sb.AppendLine("<div class=\"list-group-item-heading\">");
sb.Append("<h4>");
sb.Append(i.Name);
sb.Append("</h4>");
sb.AppendLine("</div>");
sb.Append("<button type=\"submit\" class=\"" + standardButtonClasses("btn-success") + "\" type=\"submit\" name=\"btnRpt\" value=\"" + sValue + "\">");
sb.AppendLine("<span class=\"icon-Report ay-icon-large\"></span>");
sb.AppendLine("</button>");
sb.AppendLine("</li>");
}
}
sb.AppendLine("</ul>");
return new MvcHtmlString(sb.ToString());
}
static public string cacheReport(string ReportID, string Key, object Data, UrlHelper url, string overrideFrom="")
{
string cacheKey = GZTW.AyaNova.BLL.User.CurrentThreadUserID.ToString();
//cache for 6 minutes
//on reportview.aspx it has javascript to return the page
//automatically in 5 minutes so user should never see an error about no data source
cacheData(cacheKey, Data, 6);
string ayf = overrideFrom;
if(string.IsNullOrWhiteSpace(ayf))
ayf=url.RequestContext.HttpContext.Request.RawUrl;
string toUrl = genBaseSiteUrl(url) + "ReportView.aspx?rpt=" + ReportID + "&src=" + cacheKey + "&ayf="+ayf;
return toUrl;
}
#endregion reporting
#region Client portal utils
/// <summary>
/// PUt custom content into viewbag for display to client portal pages
/// </summary>
/// <param name="ViewBag"></param>
public static void SetViewBagCustomClientContent(dynamic ViewBag)
{
string sHeader = fetchCustomContent("CustomClientHeader");
string sFooter = fetchCustomContent("CustomClientFooter");
string sStartHeaderDiv = "<div class=\"customer-header\">";
string sStartFooterDiv = "<div class=\"customer-footer\">";
string sEndDiv = "</div>";
if (sHeader != "NA" && !string.IsNullOrWhiteSpace(sHeader))
ViewBag.CustomClientHeader = new MvcHtmlString(sStartHeaderDiv + sHeader + sEndDiv);
else
ViewBag.CustomClientHeader = "";// new MvcHtmlString(string.Empty);
if (sFooter != "NA" && !string.IsNullOrWhiteSpace(sFooter))
ViewBag.CustomClientFooter = new MvcHtmlString(sStartFooterDiv + sFooter + sEndDiv);
else
ViewBag.CustomClientFooter = "";// new MvcHtmlString(string.Empty);
}
/// <summary>
/// convenience util
/// return string inside MvcHtmlString
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static MvcHtmlString StringToHtmlString(string s)
{
return new MvcHtmlString(s);
}
/// <summary>
/// Cached Custom content
/// Valid items are "CustomClientFooter", "CustomClientHeader"
/// </summary>
private static string fetchCustomContent(string sContentType)
{
if (getCacheData(sContentType) == null)
{
string sContent = "NA";
string sFilePath = System.Web.HttpContext.Current.Server.MapPath("~/Customize/" + sContentType + "Content.txt");
//Check for existance of file
if (System.IO.File.Exists(sFilePath))
{
try
{
sContent = System.IO.File.ReadAllText(sFilePath);
}
catch { }
}
cacheData(sContentType, sContent, 30);
//HttpContext.Current.Cache.Insert(sContentType, sContent, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
}
string sRet = (string)getCacheData(sContentType);
if (sRet == "NA") return "";
else
return sRet;
}
/// <summary>
/// Given an ID return what type of customer account it is
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public static string IdIsClientHeadOfficeOrNone(Guid id)
{
if (Client.Exists(id, string.Empty))
return "CLIENT";
if (HeadOffice.Exists(id, string.Empty))
return "HEADOFFICE";
return "NONE";
}
#endregion client utils
//eoc
}
#region form menu class
public class ayMenuItem
{
/// <summary>
/// Types are "header", "navitem", "scriptitem", "divider", "promptnavitem"
/// </summary>
public string type { get; set; }
public string title { get; set; }
public string icon { get; set; }
public string action { get; set; }
public string prompt { get; set; }
public string hrefClass { get; set; }
public ayMenuItem(string Type, string Title, string Action, string Icon = "", string Prompt = "", string HrefClass = "")
{
type = Type;
title = Title;
icon = Icon;
action = Action;
prompt = Prompt;
hrefClass = HrefClass;
}
}
public class ayMenu
{
public string title { get; set; }
public string icon { get; set; }
public List<ayMenuItem> menuItems { get; set; }
public ayMenu()
{
menuItems = new List<ayMenuItem>();
}
}
#endregion form menu class
#region form error class
public class ayBrokenRules
{
public Dictionary<string, string> FieldErrors { get; set; }
public ayBrokenRules(CSLA.BusinessBase Obj)
{
FieldErrors = new Dictionary<string, string>();
CSLA.BrokenRules.RulesCollection rules = Obj.GetBrokenRulesCollection();
foreach (CSLA.BrokenRules.Rule r in rules)
{
string errText = ay.BrokenRuleLocalizer(r.Description);
//iterate the rules, for each rule add form field name as key and
//as value the localized rule to the dictionary if it doesn't exist or apppend if it does
if (FieldErrors.ContainsKey(r.Property))
FieldErrors[r.Property] = FieldErrors[r.Property] + "\r\n" + errText;
else
FieldErrors.Add(r.Property, errText);
}
//build general form error html here for top of form display since not all can do tooltips
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (KeyValuePair<string, string> kv in FieldErrors)
{
//todo: this needs to be fixed up
//to show proper field names localized and error
sb.AppendLine(kv.Value);
}
}
//eoc
}
#endregion form error class
#region ayEvent class for schedule
public class ayEvent
{
public string id;
public string title;
public string start;
public string end;
public bool isWo;
public bool showFlag;
public string flagColor;
public string statusColor;
public Guid woId;
public Guid woItemId;
public Guid woItemScheduledUserId;
public Guid scheduleMarkerId;
}
#endregion ayEvent class
}//end of namespace