diff --git a/SaBusMgrCoreWeb/Web/App/SbmSessionData_Web.cs b/SaBusMgrCoreWeb/Web/App/SbmSessionData_Web.cs index e978b95..4e8b265 100644 --- a/SaBusMgrCoreWeb/Web/App/SbmSessionData_Web.cs +++ b/SaBusMgrCoreWeb/Web/App/SbmSessionData_Web.cs @@ -1,4 +1,5 @@ -using Sarand.BusinessMgr.Net.Standard.Base.App; +using Newtonsoft.Json; +using Sarand.BusinessMgr.Net.Standard.Base.App; using Sarand.BusinessMgr.Net.Standard.Base.Bus; using Sarand.BusinessMgr.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Bus; @@ -26,23 +27,11 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App securityProfile = new SbmSecurityProfile(this, false); } - //------------------------------------------------------------------- - // User Context. - public SbmUserContext UserContext - { - get - { - SbmUserContext userContext = new SbmUserContext_Web(SessionContext); - return userContext; - } - } - //------------------------------------------------------------------- // Security Profile. private readonly SbmSecurityProfile securityProfile; public ISbmSecurityProfile SecurityProfile { get { return securityProfile; } } - //------------------------------------------------------------------- // ToDo: Organisation configuration. public String GetOrganisationOption(Sbm.OrganisationOption option, String context) { return null; } @@ -61,32 +50,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App public Sbm.CommodityType GetOwnerOption_CommodityType(Sbm.OrgOption_CommodityType commodityTypeContext) { return Sbm.CommodityType.Unknown; } public SysId GetOwnerOption_StockLocation(Sbm.OrgOption_StockLocation eLoc) { return null; } - //------------------------------------------------------------------- - // Contacts. - public class ContactsData - { - public class FilterData - { - public uint PageNo { get; set; } = 1; - public ushort PageLength { get; set; } = 16; - } - public FilterData Filter { get; } = new FilterData(); - } - public ContactsData Contacts { get; } = new ContactsData(); - - //------------------------------------------------------------------- - // Commodities. - public class CommoditiesData - { - public class FilterData - { - public uint PageNo { get; set; } = 1; - public ushort PageLength { get; set; } = 16; - } - public FilterData Filter { get; } = new FilterData(); - } - public CommoditiesData Commodities { get; } = new CommoditiesData(); - //------------------------------------------------------------------- } //======================================================================= diff --git a/SaBusMgrCoreWeb/Web/App/SbmStartup_Web.cs b/SaBusMgrCoreWeb/Web/App/SbmStartup_Web.cs index fb78abd..682a1b7 100644 --- a/SaBusMgrCoreWeb/Web/App/SbmStartup_Web.cs +++ b/SaBusMgrCoreWeb/Web/App/SbmStartup_Web.cs @@ -109,7 +109,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App .AddViewLocalization( LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = resourcesPath; }) - .AddDataAnnotationsLocalization(); + .AddDataAnnotationsLocalization() + // Ignore null values during object serisliation. + .AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; }); // Configure localisation middleware. config.services.Configure diff --git a/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs b/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs index 45e088f..2a50682 100644 --- a/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs +++ b/SaBusMgrCoreWeb/Web/Controllers/SbmController_Base.cs @@ -11,6 +11,7 @@ using Sarand.BusinessMgr.Net.Core.Web.Models; using Sarand.BusinessMgr.Net.Standard.Base.App; using Sarand.BusinessMgr.Net.Standard.Base.Bus; using Sarand.BusinessMgr.Net.Standard.Base.Consoles; +using Sarand.BusinessMgr.Net.Standard.Base.Core; using Sarand.BusinessMgr.Net.Standard.Base.Mgr; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.CodeTypes; @@ -69,8 +70,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers public bool DebugMode { get; } = SacsSystem.DebugMode; protected SbmApplication_Web App { get { return SbmGlobals_Web.Application; } } public SbmAppConfig AppConfig { get { return App.AppConfig; } } - public SbmSessionContext SessionContext { get { return UserContext?.SessionContext ?? null; } } - public SbmUserContext UserContext { get { return SessionData.UserContext; } } + public SbmSessionContext SessionContext { get { return SessionData?.SessionContext ?? null; } } + public ISbmUserContext UserContext { get { return SessionData; } } protected SbmLocaliser Localiser { get; } /// /// Indicate whether session data should be stored by action. @@ -386,10 +387,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers public class AjaxResponse_Base { // Response status. - public bool Success { get; set; } = false; - public bool Error { get; set; } = false; - public bool SessionExpired { get; protected set; } = false; - public bool GoHome { get; protected set; } = false; + public bool? Success { get; set; } = null; + public bool? Error { get; set; } = null; + public bool? SessionExpired { get; protected set; } = null; + public bool? GoHome { get; protected set; } = null; public AjaxResponse_Base SetSessionExpired(String title, String text) { SessionExpired = true; @@ -432,15 +433,22 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers } //--------------------------------------------------------------- + /// + /// Common item response data properties. + /// - Null values are ignored by the JSON serialiser. + /// - Return null for false boolean values where possible. + /// - Return null for blank string values where possible. + /// public class ItemData { public String Id { get; set; } - public String Notes { get; set; } + private String notes; + public String Notes { get { return StringUtil.OnEmpty(notes, null); } set { notes = StringUtil.EmptyOnNull(value).Trim(); } } public String StatusCode { get; set; } public String StatusDesc { get; set; } - public Boolean Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)); } } - public Boolean Active { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Active)); } } - public Boolean Deleted { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Deleted)); } } + public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } } + public bool? Active { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Active)) ? true : (bool?)null; } } + public bool? Deleted { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Deleted)) ? true : (bool?)null; } } public String CreatedOn { get; set; } public String CreatedOnFmt { get; set; } public String UpdatedOn { get; set; } @@ -462,7 +470,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers public String Error { get; set; } } private readonly Dictionary controlValues = new Dictionary(); - public List ControlValues { get { return controlValues.Values.ToList(); } } + public List ControlValues { get { return controlValues.Count > 0 ? controlValues.Values.ToList() : null; } } public void SetControlValue(String controlName, String value, String error = null) { if (controlValues.ContainsKey(controlName)) @@ -509,7 +517,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers public String Message { get; set; } } public NotificationData Notification { get; private set; } - public bool HasNotification { get { return Notification != null; } } public AjaxResponse_Data SetNotification(String title, String message) { Notification = new NotificationData() { Title = title, Message = message }; diff --git a/SaBusMgrCoreWeb/Web/Models/SbmModel_Base.cs b/SaBusMgrCoreWeb/Web/Models/SbmModel_Base.cs index 1cca47e..cd1de65 100644 --- a/SaBusMgrCoreWeb/Web/Models/SbmModel_Base.cs +++ b/SaBusMgrCoreWeb/Web/Models/SbmModel_Base.cs @@ -63,7 +63,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models //------------------------------------------------------------------- // Business components. // NB Keep these accessors protected to avoid them being called by teh model binding logic before the session data is ready. - protected SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(SessionData_Web.UserContext); return internals; } } + protected SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(SessionData_Web); return internals; } } // Managers. protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } } protected SbmAssetMgr AssetMgr { get { return Internals.AssetMgr; } } diff --git a/SaBusMgrStandardBase/Base/App/SbmSessionData.cs b/SaBusMgrStandardBase/Base/App/SbmSessionData.cs index c8a75d2..d8323d9 100644 --- a/SaBusMgrStandardBase/Base/App/SbmSessionData.cs +++ b/SaBusMgrStandardBase/Base/App/SbmSessionData.cs @@ -86,7 +86,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App KeepLoggedIn = affiliateUser.KeepLoggedIn_Portal; else Debugger.Break(); } - this.supervisedOrganisations = supervisedOrganisations; + this.supervisedOrganisations = supervisedOrganisations ?? new List(); } protected UserData(UserData userData) { @@ -132,20 +132,14 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App } protected abstract UserData CreateUserData(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations); + [JsonProperty("User")] + protected UserData userData; + [JsonIgnore] /// User account details. - private UserData userData; public ISbmUserContext.IUserData User { get { return userData; } } public bool ValidUser { get { return SysId.IsValid(userData.SecurityItemId) && SysId.IsValid(userData.AffiliateId); } } public bool KeepLoggedIn { get { return userData.KeepLoggedIn; } } - /// User - JSON deserialisation route. - protected void SetUser(UserData user) - { - if (this.userData != null && userData.UserAccountSupplied) - throw new NotSupportedException("Session User cannot be replaced."); - this.userData = user; - } - //------------------------------------------------------------------- // Organisation. public class OrganisationData : ISbmUserContext.IOrganisationData @@ -165,7 +159,9 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App public String DisplayName { get; protected set; } public String InterfaceContext { get; } } + [JsonProperty("Organisation")] protected OrganisationData organisationData; + [JsonIgnore] public ISbmUserContext.IOrganisationData Organisation { get { return organisationData; } } //------------------------------------------------------------------- diff --git a/SaBusMgrStandardBase/Base/Bus/SbmCommodity.cs b/SaBusMgrStandardBase/Base/Bus/SbmCommodity.cs index e0713a8..1476d46 100644 --- a/SaBusMgrStandardBase/Base/Bus/SbmCommodity.cs +++ b/SaBusMgrStandardBase/Base/Bus/SbmCommodity.cs @@ -1806,8 +1806,6 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Bus // Commodity Ids. public List IncludedIds { get; } = new List(); public List ExcludedIds { get; } = new List(); - /// Organisation - if not available via Session Config. ie. must be populated for Web/Console sessions. - public SysId AffiliateIdOrganisation {get; set; } // Commodity. public Sbm.CommodityType CommodityType { get; set; } public bool StockItemsOnly { get; set; } = false; diff --git a/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs b/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs index a9b006e..522b02c 100644 --- a/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs +++ b/SaBusMgrStandardBase/Base/Mgr/SbmAccountMgr_Affiliate.cs @@ -175,7 +175,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr return false; } // Validate the affiliate names. - if (errField.Name != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Name, "name", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Name), SbmAffiliate.IsIndividual(data.AffiliateType))) + if (errField.Name != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Name, "name", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Affiliate_Name), !SbmAffiliate.IsIndividual(data.AffiliateType))) { errField.Name = SacsHierarchyItem.ValidValue.Invalid; return false; diff --git a/SaBusMgrStandardBase/Base/Mgr/SbmCommodityMgr_Commodity.cs b/SaBusMgrStandardBase/Base/Mgr/SbmCommodityMgr_Commodity.cs index b967b40..afa0d7b 100644 --- a/SaBusMgrStandardBase/Base/Mgr/SbmCommodityMgr_Commodity.cs +++ b/SaBusMgrStandardBase/Base/Mgr/SbmCommodityMgr_Commodity.cs @@ -402,7 +402,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Mgr errField.Code = SacsHierarchyItem.ValidValue.Invalid; return false; } - if (errField.DescBrief != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.DescBrief, "description brief", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Commodity_DescBrief))) + if (errField.DescBrief != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.DescBrief, "description brief", (long)SbmDbDfn.GetColTextLen(SbmDbDfn.ColumnIdx.Commodity_DescBrief), true)) { errField.DescBrief = SacsHierarchyItem.ValidValue.Invalid; return false; diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs b/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs index e2f9e20..b1193b5 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/SbmAccountMgr_Dbas-Affiliate.cs @@ -283,7 +283,10 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr dbAffiliate._Website = affiliate.Website; // Ogranisation. dbAffiliate._AffIdParent = affiliate.AffiliateIdParent.ToInt(); - dbAffiliate._Name = affiliate.Name; + if (!affiliate.IsIndividual()) + dbAffiliate._Name = affiliate.Name; + else + dbAffiliate._Name = affiliate.GetDisplayName(); dbAffiliate._Abbrev = affiliate.Abbr; dbAffiliate._Nature = affiliate.Nature; dbAffiliate._Contact = affiliate.Contact; diff --git a/SaBusMgrStandardDbas/Dbas/Mgr/SbmCommodityMgr_Dbas-Commodity.cs b/SaBusMgrStandardDbas/Dbas/Mgr/SbmCommodityMgr_Dbas-Commodity.cs index 94a8d4a..288029e 100644 --- a/SaBusMgrStandardDbas/Dbas/Mgr/SbmCommodityMgr_Dbas-Commodity.cs +++ b/SaBusMgrStandardDbas/Dbas/Mgr/SbmCommodityMgr_Dbas-Commodity.cs @@ -65,6 +65,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr return new List() { new StringPair("Id",SysId.ToString(commodity.Id)), + new StringPair("Code",commodity.Code), new StringPair("DescBrief",commodity.DescBrief), new StringPair("Status",commodity.StatusCode) }; @@ -2295,16 +2296,11 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr //--------------------------------------------------------------- // Organisation. - if (SysId.IsValid(prm.AffiliateIdOrganisation)) - filter.Add(colCommodity_AffIdOwner + "=" + SysId.ToString(prm.AffiliateIdOrganisation)); - else + // Must filter by organisation if insufficient alternative filetrs. + if (!prm.IncludedIds.HasValidIds() && !prm.PriceSetIdsIncluded.HasValidIds() && !SysId.IsValid(prm.AssociationIdCustomer) && !SysId.IsValid(prm.AssociationIdCommodityCustomer)) { - // Must filter by organisation if insufficient alternative filetrs. - if (!prm.IncludedIds.HasValidIds() && !prm.PriceSetIdsIncluded.HasValidIds() && !SysId.IsValid(prm.AssociationIdCustomer) && !SysId.IsValid(prm.AssociationIdCommodityCustomer)) - { - if (!SysId.IsValid(AffiliateId_Owner)) throw new NotSupportedException("Commodity query filter - Organisation Id must be specified"); - filter.Add(colCommodity_AffIdOwner + "=" + SysId.ToString(AffiliateId_Owner)); - } + if (!SysId.IsValid(AffiliateId_Owner)) throw new NotSupportedException("Commodity query filter - Organisation Id must be specified"); + filter.Add(colCommodity_AffIdOwner + "=" + SysId.ToLong(AffiliateId_Owner)); } //--------------------------------------------------------------- diff --git a/SaBusMgrTest_Portal/Test/Net/Core/Web/Portal/App/SbmSessionData_Portal_Test.cs b/SaBusMgrTest_Portal/Test/Net/Core/Web/Portal/App/SbmSessionData_Portal_Test.cs index 50047b7..3dccd0f 100644 --- a/SaBusMgrTest_Portal/Test/Net/Core/Web/Portal/App/SbmSessionData_Portal_Test.cs +++ b/SaBusMgrTest_Portal/Test/Net/Core/Web/Portal/App/SbmSessionData_Portal_Test.cs @@ -58,6 +58,8 @@ namespace Sarand.BusinessMgr.Test.Net.Core.Web.Portal.App SbmAffiliate affiliateOrganisation = accountMgr.GetAffiliateById(affiliateIdOrganisation); Assert.IsNotNull(affiliateOrganisation); + // Profile. + // Populate User Session. SbmSessionData_Portal sessionData = new SbmSessionData_Portal(SessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation); @@ -80,6 +82,7 @@ namespace Sarand.BusinessMgr.Test.Net.Core.Web.Portal.App Assert.AreEqual(affiliateOrganisation.Id, sessionData.Organisation.AffiliateId); Assert.AreEqual(associationOrganisation.Id, sessionData.Organisation.AssociationId); + // Serialise data. String sessionDataJson = JsonConvert.SerializeObject(sessionData); Assert.IsNotNull(sessionDataJson); diff --git a/SaBusinessMgrCoreWebPortal/Localisation/SbmPortalProperties.resx b/SaBusinessMgrCoreWebPortal/Localisation/SbmPortalProperties.resx index 61f3556..34d88b8 100644 --- a/SaBusinessMgrCoreWebPortal/Localisation/SbmPortalProperties.resx +++ b/SaBusinessMgrCoreWebPortal/Localisation/SbmPortalProperties.resx @@ -192,9 +192,18 @@ Create + + Create Individual + + + Create Organisation + Description + + Edit + Email @@ -216,6 +225,12 @@ Name + + First name + + + Last name + Next @@ -300,6 +315,18 @@ System error encountered. + + Item created. + + + Item deleted. + + + Item removed. + + + Item updated. + Unfortunately, something has gone wrong.\n\nYou will be returned to the home page. diff --git a/SaBusinessMgrCoreWebPortal/Portal/App/SbmSessionData_Portal.cs b/SaBusinessMgrCoreWebPortal/Portal/App/SbmSessionData_Portal.cs index c0a8601..a712dd8 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/App/SbmSessionData_Portal.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/App/SbmSessionData_Portal.cs @@ -35,12 +35,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App //------------------------------------------------------------------- // Contact details. - private class UserData_Online : UserData + private class UserData_Portal : UserData { - public UserData_Online(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations) : + public UserData_Portal(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations) : base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations) { } - public UserData_Online(UserData userData) : + public UserData_Portal(UserData userData) : base(userData) { } public new bool Refresh(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations) @@ -50,10 +50,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App } protected override UserData CreateUserData(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations) { - return new UserData_Online(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations); + return new UserData_Portal(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations); } /// User - JSON deserialisation route. - //public new UserData User { get { return base.User; } set { SetUser(new UserData_Online(value)); } } + //public new UserData User { get { return base.User; } set { SetUser(new UserData_Portal(value)); } } /// /// Update the user's contact details against the session. @@ -61,7 +61,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App /// public bool RefreshUser(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) { - UserData_Online user = User as UserData_Online; + UserData_Portal user = User as UserData_Portal; if (user != null) return user.Refresh(securityItemUser, affiliateUser, supervisedOrganisations); organisationData = new OrganisationData(associationOrganisation, affiliateOrganisation); @@ -69,66 +69,62 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App } //------------------------------------------------------------------- - // User Profile. - // Protected constructors & setters for JSON deserialisation. + /// + /// User Profile. + /// - Filter settings. + /// public class UserProfileData { public UserProfileData() { } - // Sports. - public class SportData + + // Common filter. + public class FilterData { - [JsonConstructor] - public SportData(SysId sportId, SaStatus status) + /// Id for currently selected Association. + public SysId AssociationId { get; set; } + } + /// + /// Common filter properties. + /// + public FilterData Filter { get; private set; } = new FilterData(); + + // Contacts filter. + public class ContactsData + { + public class FilterData { - SportId = sportId; - Status = status; + public uint PageNo { get; set; } = 1; + public ushort PageLength { get; set; } = 16; } - public SysId SportId { get; protected set; } - public SaStatus Status { get; protected set; } + public FilterData Filter { get; } = new FilterData(); } - private class SportData_Online : SportData + /// + /// Contacts filter properties. + /// + public ContactsData Contacts { get; } = new ContactsData(); + + // Commodities filter. + public class CommoditiesData { - // Internal class to allow values to be updated. - public SportData_Online(SysId sportId, SaStatus status) : base(sportId, status) { } - public SportData_Online(SportData sportData) : base(sportData.SportId, sportData.Status) { } - public void SetSportId(SysId sportId) { SportId = sportId; } - public void SetStatus(SaStatus status) { Status = status; } - } - [JsonIgnore] - private readonly List sports = new List(); - [JsonIgnore] - public int SportCount { get { return sports.Count; } } - public List Sports { get { return new List(sports); } protected set { sports.Clear(); sports.AddRange(value.Select(item => new SportData_Online(item))); } } - public void AddSport(SysId sportId, SaStatus status) - { - if (!SysId.IsValid(sportId)) throw new NotSupportedException("Session Profile Sport must have a valid Id"); - SportData_Online sport = this.sports.Find(item => item.SportId == sportId); - if (sport != null) + public class FilterData { - sport.SetStatus(status); + public uint PageNo { get; set; } = 1; + public ushort PageLength { get; set; } = 16; } - else - this.sports.Add(new SportData_Online(sportId, status)); - } - public void ClearSports() - { - this.sports.Clear(); + public FilterData Filter { get; } = new FilterData(); } + /// + /// Commodities filter properties. + /// + public CommoditiesData Commodities { get; } = new CommoditiesData(); } public UserProfileData Profile { get; protected set; } = new UserProfileData(); //------------------------------------------------------------------- - // Filter properties. - public class FilterData - { - /// Id for currently selected Association. - public SysId AssociationId { get; set; } - } - public FilterData Filter { get; private set; } = new FilterData(); //------------------------------------------------------------------- - // Online application encryption IV value - for consistent encryption during session. - public String Base64IV_OnlineApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Portal.Base64Key_OnlineApp); + // Portal application encryption IV value - for consistent encryption during session. + public String Base64IV_PortalApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Portal.Base64Key_OnlineApp); //------------------------------------------------------------------- } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController-Ajax.cs index 850a452..68cf21a 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController-Ajax.cs @@ -97,7 +97,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Item filter. SbmCommodity.Params prmCommodity = new SbmCommodity.Params(); - prmCommodity.AffiliateIdOrganisation = SessionData.Organisation.AffiliateId; prmCommodity.Search = model.Filter.CommoditySearch; prmCommodity.CommodityType = model.GetFilterCommodityType(); prmCommodity.StatusCat = SbmCommodity.StatusCat.NotDeleted; @@ -134,7 +133,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodityType), TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodityType), Code = values.GetString(colCode.DataName), - Desc= values.GetString(colDescBrief.DataName), + Desc = values.GetString(colDescBrief.DataName), Notes = values.GetString(colNotes.DataName), StatusCode = values.GetString(colStatus.DataName), StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)), @@ -150,8 +149,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Refresh paging info. if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Commodities.Count; - SessionData.Commodities.Filter.PageNo = model.Paging.PageNo; - SessionData.Commodities.Filter.PageLength = model.Paging.PageLength; + SessionData_Portal.Profile.Commodities.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Commodities.Filter.PageLength = model.Paging.PageLength; responseData.SetPaging(model); // Complete response. @@ -179,9 +178,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers String messageTitle = Localiser["commodity.caption.commodity"]; AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model); - // Validate session. - if (!ValidUserSession) - return GetAjaxResult_InvalidSession(responseData); + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); // Identify item. SysId commodityId = model.CommodityId.ToSysId(); @@ -217,17 +217,31 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers String messageTitle = Localiser["commodity.caption.commodity"]; AjaxResponse_Commodity responseData = new AjaxResponse_Commodity(model); - // Validate session. - if (!ValidUserSession) - return GetAjaxResult_InvalidSession(responseData); + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); // Validate item properties. model.ValidateCommodityData(responseData); if (responseData.HasControlErrors()) return Json(responseData); - // Retrieve existing item. + // Validate item Id against 'Exists' flag. SysId commodityId = model.CommodityId.ToSysId(); + bool commodityExists = StringUtil.ToBool(model.CommodityExists); + if (commodityExists && !SysId.IsValid(commodityId)) + { + SaLogger.Warn(fn + " Id not specified for existing Commodity."); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + if (!commodityExists && SysId.IsValid(commodityId)) + { + SaLogger.Warn(fn + " Id specified for new Commodity: '" + model.CommodityId + "'"); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + + // Retrieve existing item. SbmCommodity commodity = CommodityMgr.GetCommodityById(commodityId); if (commodity == null && SysId.IsValid(commodityId)) { @@ -244,13 +258,17 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers } // Populate item properties. + if (model.CommodityType != null) + commodity.CommodityType = model.GetCommodityType(); if (model.CommodityCode != null) commodity.Code = model.CommodityCode; + if (model.CommodityDesc != null) + commodity.DescBrief = model.CommodityDesc; // Common properties. if (model.CommodityNotes != null) commodity.Notes = model.CommodityNotes; - if (model.CommodityStatus != null) - commodity.Status = model.GetCommodityStatus(); + if (model.CommodityStatusCode != null) + commodity.Status = model.CommodityStatus; // Store item. if (!SysId.IsValid(commodity.Id)) @@ -260,6 +278,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers SaLogger.Warn(fn + " Failed to insert commodity: " + CommodityMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + CommodityMgr.ErrorStateMessage)); } + responseData.SetNotification(messageTitle, Localiser["msg.item.created"]); } else { @@ -268,6 +287,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers SaLogger.Warn(fn + " Failed to update commodity [Id:" + SysId.ToString(commodity.Id) + "]: " + CommodityMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + CommodityMgr.ErrorStateMessage)); } + responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]); } // Construct response. diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController.cs index 119273f..c7dbed2 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/CommodityController.cs @@ -42,8 +42,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Commodity page. Model_Commodity model = new Model_Commodity(Localiser); - model.Paging.PageNo = SessionData.Commodities.Filter.PageNo; - model.Paging.PageLength = SessionData.Commodities.Filter.PageLength; + model.Paging.PageNo = SessionData_Portal.Profile.Commodities.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Commodities.Filter.PageLength; return View(model); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController-Ajax.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController-Ajax.cs index 7cb9a41..83bd3af 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController-Ajax.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController-Ajax.cs @@ -36,6 +36,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers public String DisplayName { get; set; } public String TypeCode { get; set; } public String TypeDesc { get; set; } + public bool? Individual { get; set; } // Address. public String AddressSummary { get; set; } } @@ -78,6 +79,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers data.DisplayName = affiliate.GetDisplayName(); data.TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliate.AffiliateType); data.TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliate.AffiliateType); + data.Individual = affiliate.AffiliateType == Sbm.AffiliateType.Individual ? true : (bool?)null; // Common properties. data.Notes = affiliate.Notes; data.StatusCode = affiliate.StatusCode; @@ -153,8 +155,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Item filter. SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params(); - prmAffiliate.Search = model.Filter.AffiliateSearch; - prmAffiliate.AffiliateType = model.GetFilterAffiliateType(); + prmAffiliate.Search = model.Filter.ContactSearch; + prmAffiliate.AffiliateType = model.GetFilterContactType(); prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted; prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name)); prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.LastName)); @@ -193,6 +195,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers DisplayName = values.GetString(colName.DataName), TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliateType), TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliateType), + Individual = affiliateType == Sbm.AffiliateType.Individual ? true : (bool?)null, AddressSummary = AccountMgr.GetAffiliateDataValue(colAddress, values).AsString(), Notes = values.GetString(colNotes.DataName), StatusCode = values.GetString(colStatus.DataName), @@ -209,8 +212,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Refresh paging info. if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Affiliates.Count; - SessionData.Contacts.Filter.PageNo = model.Paging.PageNo; - SessionData.Contacts.Filter.PageLength = model.Paging.PageLength; + SessionData_Portal.Profile.Contacts.Filter.PageNo = model.Paging.PageNo; + SessionData_Portal.Profile.Contacts.Filter.PageLength = model.Paging.PageLength; responseData.SetPaging(model); // Complete response. @@ -235,12 +238,13 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers public IActionResult Ajax_GetItem(Model_Contact model) { String fn = GetType().Name + ".Ajax_GetItem"; - String messageTitle = Localiser["affiliate.caption.affiliate"]; + String messageTitle = Localiser["contact.caption.contact"]; AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model); - // Validate session. - if (!ValidUserSession) - return GetAjaxResult_InvalidSession(responseData); + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); // Identify item. SysId affiliateId = model.AffiliateId.ToSysId(); @@ -273,20 +277,34 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers public IActionResult Ajax_StoreItem(Model_Contact model) { String fn = GetType().Name + ".Ajax_StoreItem"; - String messageTitle = Localiser["affiliate.caption.affiliate"]; + String messageTitle = Localiser["contact.caption.contact"]; AjaxResponse_Affiliate responseData = new AjaxResponse_Affiliate(model); - // Validate session. - if (!ValidUserSession) - return GetAjaxResult_InvalidSession(responseData); + // Validate session and referrer. + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + if (!ValidReferer) return Forbid(); + RefreshModel(model); // Validate item properties. model.ValidateAffiliateData(responseData); if (responseData.HasControlErrors()) return Json(responseData); - // Retrieve existing item. + // Validate item Id against 'Exists' flag. SysId affiliateId = model.AffiliateId.ToSysId(); + bool contactExists = StringUtil.ToBool(model.ContactExists); + if (contactExists && !SysId.IsValid(affiliateId)) + { + SaLogger.Warn(fn + " Id not specified for existing Affiliate."); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + if (!contactExists && SysId.IsValid(affiliateId)) + { + SaLogger.Warn(fn + " Id specified for new Affiliate: '" + model.AffiliateId + "'"); + return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); + } + + // Retrieve existing item. SbmAffiliate affiliate = AccountMgr.GetAffiliateById(affiliateId); if (affiliate == null && SysId.IsValid(affiliateId)) { @@ -296,16 +314,33 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Create new item if required. if (affiliate == null) - affiliate = AccountMgr.CreateAffiliate(model.GetAffiliateType()); + { + affiliate = AccountMgr.CreateAffiliate(model.GetContactType()); + } + else + { + if (model.ContactType != null) + affiliate.AffiliateType = model.GetContactType(); + } // Populate item properties. - if (model.AffiliateName != null) - affiliate.Name = model.AffiliateName; + if (affiliate.IsIndividual()) + { + if (model.ContactFirstName != null) + affiliate.FirstName = model.ContactFirstName; + if (model.ContactLastName != null) + affiliate.LastName = model.ContactLastName; + } + else + { + if (model.ContactName != null) + affiliate.Name = model.ContactName; + } // Common properties. - if (model.AffiliateNotes != null) - affiliate.Notes = model.AffiliateNotes; - if (model.AffiliateStatus != null) - affiliate.Status = model.GetAffiliateStatus(); + if (model.ContactNotes != null) + affiliate.Notes = model.ContactNotes; + if (model.ContactStatusCode != null) + affiliate.Status = model.ContactStatus; // Store item. if (!SysId.IsValid(affiliate.Id)) @@ -315,6 +350,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers SaLogger.Warn(fn + " Failed to insert affiliate: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage)); } + responseData.SetNotification(messageTitle, Localiser["msg.item.created"]); } else { @@ -323,6 +359,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers SaLogger.Warn(fn + " Failed to update affiliate [Id:" + SysId.ToString(affiliate.Id) + "]: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage)); } + responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]); } // Construct response. diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController.cs index a47c67f..c1ce1fb 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/ContactController.cs @@ -42,8 +42,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers // Contact page. Model_Contact model = new Model_Contact(Localiser); - model.Paging.PageNo = SessionData.Contacts.Filter.PageNo; - model.Paging.PageLength = SessionData.Contacts.Filter.PageLength; + model.Paging.PageNo = SessionData_Portal.Profile.Contacts.Filter.PageNo; + model.Paging.PageLength = SessionData_Portal.Profile.Contacts.Filter.PageLength; return View(model); } diff --git a/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs b/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs index aa13310..a60a355 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Controllers/SbmController_Portal.cs @@ -272,7 +272,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers public static String Base64Key_OnlineApp { get; } = SacsEncryptionHelper.EncodePlainKey("{SaBusMgr=Portal-App#Encryption}", SacsEncryptionHelper.KeyLength); protected String EncryptOnlineParams(NameValueCollection parameters) { - return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Portal.Base64IV_OnlineApp, Base64Key_OnlineApp)); + return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Portal.Base64IV_PortalApp, Base64Key_OnlineApp)); } public static String EncryptOnlineParams(SbmController_Portal controller, NameValueCollection parameters) { @@ -280,7 +280,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers } protected NameValueCollection ExtractOnlineParams(String encryptedParams) { - return DecryptParameters(encryptedParams, SessionData_Portal.Base64IV_OnlineApp, Base64Key_OnlineApp); + return DecryptParameters(encryptedParams, SessionData_Portal.Base64IV_PortalApp, Base64Key_OnlineApp); } //------------------------------------------------------------------- diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Commodity.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Commodity.cs index 6fd72c4..2b65dd3 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Commodity.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Commodity.cs @@ -41,6 +41,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models //------------------------------------------------------------------- // Commodity properties. public String CommodityId { get; set; } + public String CommodityExists { get; set; } public String CommodityType{ get; set; } public Sbm.CommodityType GetCommodityType() { @@ -50,11 +51,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models public String CommodityDesc { get; set; } // Common properties. public String CommodityNotes { get; set; } - public String CommodityStatus { get; set; } - public SaStatus GetCommodityStatus() - { - return SacsSystem.GetStatusForCode(CommodityStatus); - } + public String CommodityStatusCode { get; set; } + public SaStatus CommodityStatus { get { return SacsSystem.GetStatusForCode(CommodityStatusCode); } } //------------------------------------------------------------------- // Validation. @@ -98,12 +96,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models } // Commodity status. - if (CommodityStatus != null) + if (CommodityStatusCode != null) { - if (StringUtil.IsEmpty(CommodityStatus)) - responseData.SetControlError(nameof(CommodityStatus), Localiser["msg.validation.mandatory.value"]); - else if (!SbmCommodity.ValidStatuses.Contains(GetCommodityStatus())) - responseData.SetControlError(nameof(CommodityStatus), Localiser["msg.validation.invalid.value"]); + if (StringUtil.IsEmpty(CommodityStatusCode)) + responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.mandatory.value"]); + else if (!SbmCommodity.ValidStatuses.Contains(CommodityStatus)) + responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Contact.cs b/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Contact.cs index 4bc1c8c..12e33d9 100644 --- a/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Contact.cs +++ b/SaBusinessMgrCoreWebPortal/Portal/Models/Model_Contact.cs @@ -29,31 +29,38 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models // Filter properties. public class FilterData { - public String AffiliateSearch { get; set; } - public String AffiliateType { get; set; } + public String ContactSearch { get; set; } + public String ContactType { get; set; } } public FilterData Filter { get; } = new FilterData(); - public Sbm.AffiliateType GetFilterAffiliateType() + public Sbm.AffiliateType GetFilterContactType() { - return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.AffiliateType); + return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.ContactType); } //------------------------------------------------------------------- - // Affiliate properties. + // Contact properties. public String AffiliateId { get; set; } - public String AffiliateType{ get; set; } - public Sbm.AffiliateType GetAffiliateType() + public String ContactExists { get; set; } + public String ContactType { get; set; } + public String ContactIndividual { get; set; } + public Sbm.AffiliateType GetContactType() { - return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(AffiliateType); + if (ContactType != null) + return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(ContactType); + if (StringUtil.ToBool(ContactIndividual)) + return Sbm.AffiliateType.Individual; + return Sbm.AffiliateType.Unknown; } - public String AffiliateName { get; set; } + // Organisation. + public String ContactName { get; set; } + // Individual. + public String ContactFirstName { get; set; } + public String ContactLastName { get; set; } // Common properties. - public String AffiliateNotes { get; set; } - public String AffiliateStatus { get; set; } - public SaStatus GetAffiliateStatus() - { - return SacsSystem.GetStatusForCode(AffiliateStatus); - } + public String ContactNotes { get; set; } + public String ContactStatusCode { get; set; } + public SaStatus ContactStatus { get { return SacsSystem.GetStatusForCode(ContactStatusCode); } } //------------------------------------------------------------------- // Validation. @@ -62,37 +69,58 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models public bool ValidateAffiliateData(SbmController_Base.AjaxResponse_Data responseData) { // Affiliate Type. - if (AffiliateType != null) + if (ContactType != null) { - if (StringUtil.IsEmpty(AffiliateType)) - responseData.SetControlError(nameof(AffiliateType), Localiser["msg.validation.mandatory.value"]); + if (StringUtil.IsEmpty(ContactType)) + responseData.SetControlError(nameof(ContactType), Localiser["msg.validation.mandatory.value"]); + } + bool individual = GetContactType() == Sbm.AffiliateType.Individual; + + // Organisation Name. + if (ContactName != null) + { + responseData.SetControlValue(nameof(ContactName), ContactName); + if (StringUtil.IsEmpty(ContactName) && !individual) + responseData.SetControlError(nameof(ContactName), Localiser["msg.validation.mandatory.value"]); + if (StringUtil.GetLength(ContactName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)) + responseData.SetControlError(nameof(ContactName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)]); } - // Affiliate Name. - if (AffiliateName != null) + // Individual First Name. + if (ContactFirstName != null) { - responseData.SetControlValue(nameof(AffiliateName), AffiliateName); - if (StringUtil.IsEmpty(AffiliateName)) - responseData.SetControlError(nameof(AffiliateName), Localiser["msg.validation.mandatory.value"]); - if (StringUtil.GetLength(AffiliateName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)) - responseData.SetControlError(nameof(AffiliateName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)]); + responseData.SetControlValue(nameof(ContactFirstName), ContactFirstName); + if (StringUtil.IsEmpty(ContactFirstName) && individual) + responseData.SetControlError(nameof(ContactFirstName), Localiser["msg.validation.mandatory.value"]); + if (StringUtil.GetLength(ContactFirstName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)) + responseData.SetControlError(nameof(ContactFirstName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)]); + } + + // Individual Last Name. + if (ContactLastName != null) + { + responseData.SetControlValue(nameof(ContactLastName), ContactLastName); + if (StringUtil.IsEmpty(ContactLastName) && individual) + responseData.SetControlError(nameof(ContactLastName), Localiser["msg.validation.mandatory.value"]); + if (StringUtil.GetLength(ContactLastName) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)) + responseData.SetControlError(nameof(ContactLastName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)]); } // Affiliate Notes. - if (AffiliateNotes != null) + if (ContactNotes != null) { - responseData.SetControlValue(nameof(AffiliateNotes), AffiliateNotes); - if (!StringUtil.IsEmpty(AffiliateNotes) && StringUtil.GetLength(AffiliateNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)) - responseData.SetControlError(nameof(AffiliateNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)]); + responseData.SetControlValue(nameof(ContactNotes), ContactNotes); + if (!StringUtil.IsEmpty(ContactNotes) && StringUtil.GetLength(ContactNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)) + responseData.SetControlError(nameof(ContactNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)]); } // Affiliate status. - if (AffiliateStatus != null) + if (ContactStatusCode != null) { - if (StringUtil.IsEmpty(AffiliateStatus)) - responseData.SetControlError(nameof(AffiliateStatus), Localiser["msg.validation.mandatory.value"]); - else if (!SbmAffiliate.ValidStatuses.Contains(GetAffiliateStatus())) - responseData.SetControlError(nameof(AffiliateStatus), Localiser["msg.validation.invalid.value"]); + if (StringUtil.IsEmpty(ContactStatusCode)) + responseData.SetControlError(nameof(ContactStatusCode), Localiser["msg.validation.mandatory.value"]); + else if (!SbmAffiliate.ValidStatuses.Contains(ContactStatus)) + responseData.SetControlError(nameof(ContactStatusCode), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaBusinessMgrCoreWebPortal/Views/Commodity/Index.cshtml b/SaBusinessMgrCoreWebPortal/Views/Commodity/Index.cshtml index 637e46c..c33be72 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Commodity/Index.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Commodity/Index.cshtml @@ -5,11 +5,12 @@ ViewData["Title"] = "Commodities"; } -
+
@@ -31,29 +32,43 @@
-
@(Localiser[
-
@(Localiser[
-
-
-
- -
- @* Commodity filter - name etc. *@ -
-
@Localiser["label.search"]
-
- @Html.TextBoxFor(model => model.Filter.CommoditySearch, new { @id = "", @class = "FilterCommodity", @maxlength = "32" }) -
-
- @* Commodity Category *@ -
-
@Localiser["label.type"]
-
- @Html.DropDownListFor(model => model.Filter.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" }) + @* Burger menu *@ +
+
+ @* Commodity filter - name etc. *@ +
+
@Localiser["label.search"]
+
+ @Html.TextBoxFor(model => model.Filter.CommoditySearch, new { @id = "", @class = "FilterCommodity", @maxlength = "32" }) +
+
+ @* Commodity Category *@ +
+
@Localiser["label.type"]
+
+ @Html.DropDownListFor(model => model.Filter.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" }) +
+
+
+ + @* Filter element templates *@ +
+ @* Burger dropdown item template - ul is ignored *@ +
    +
  • XXX
  • +
+
+ + } @@ -77,7 +92,7 @@
@* Commodity caption *@ -
+
-
@* Burger menu *@ diff --git a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityDialog.cshtml b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityDialog.cshtml index b531571..d61a3d2 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityDialog.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Commodity/Panel-CommodityDialog.cshtml @@ -8,20 +8,23 @@ sbm.dlg.title.createCommodity = '@Localiser.GetJavascriptText("commodity.caption.commodity.create")'; sbm.dlg.title.updateCommodity = '@Localiser.GetJavascriptText("commodity.caption.commodity.update")'; + @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityId", @class = "sbm-form" })) { @Html.HiddenFor(model => model.CommodityId, new { @class = "CommodityId" }) } +
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodity", @class = "sbm-form", @onSubmit = "return false;" })) { @Html.HiddenFor(model => model.CommodityId, new { @id = "", @class = "CommodityId" }) + @Html.HiddenFor(model => model.CommodityExists, new { @id = "", @class = "CommodityExists" }); @* Commodity Type *@
- +
@Html.DropDownListFor(model => model.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbCommodityType", @class = "CommodityType sbm-select" }) @@ -29,10 +32,10 @@
- @* Commodity Codeription *@ + @* Commodity Code *@
- +
@Html.TextBoxFor(model => model.CommodityCode, new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) }) @@ -43,7 +46,7 @@ @* Commodity Description *@
- +
@Html.TextBoxFor(model => model.CommodityDesc, new { @id = "ifCommodityDesc", @class = "CommodityDesc sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief) }) @@ -51,13 +54,24 @@
+ @* Commodity status *@ +
+
+ +
+
+ +
+
+
+ @* Commodity Notes *@
- +
- @Html.TextAreaFor(model => model.CommodityNotes, new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) }) + @Html.TextAreaFor(model => model.CommodityNotes, new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) })
diff --git a/SaBusinessMgrCoreWebPortal/Views/Contact/Index.cshtml b/SaBusinessMgrCoreWebPortal/Views/Contact/Index.cshtml index e8462b2..931269c 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Contact/Index.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Contact/Index.cshtml @@ -1,15 +1,18 @@ @model Model_Contact @inject SbmLocaliser Localiser @{ - /* Affiliates - Index */ - ViewData["Title"] = "Affiliates"; + /* Contacts - Index */ + ViewData["Title"] = "Contacts"; } -
+
@@ -19,7 +22,7 @@
@* Filter Panel *@ - @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAffiliateFilter", @class = "sbm-form", @onSubmit = "return false;" })) + @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactFilter", @class = "sbm-form", @onSubmit = "return false;" })) {
@* Header - Page caption, paging controls, actions. *@ @@ -31,29 +34,43 @@
-
@(Localiser[
-
@(Localiser[
-
-
-
-
-
- @* Affiliate filter - name etc. *@ -
-
@Localiser["label.search"]
-
- @Html.TextBoxFor(model => model.Filter.AffiliateSearch, new { @id = "", @class = "FilterAffiliate", @maxlength = "32" }) -
-
- @* Affiliate Category *@ -
-
@Localiser["label.type"]
-
- @Html.DropDownListFor(model => model.Filter.AffiliateType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterAffiliateType sbm-select" }) + @* Burger menu *@ +
+
+ @* Contact filter - name etc. *@ +
+
@Localiser["label.search"]
+
+ @Html.TextBoxFor(model => model.Filter.ContactSearch, new { @id = "", @class = "FilterContact", @maxlength = "32" }) +
+
+ @* Contact type *@ +
+
@Localiser["label.type"]
+
+ @Html.DropDownListFor(model => model.Filter.ContactType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" }) +
+
+
+ + @* Filter element templates *@ +
+ @* Burger dropdown item template - ul is ignored *@ +
    +
  • XXX
  • +
+
+ +
}
@@ -71,47 +88,47 @@
@* element templates *@ -
- @* Affiliate item template *@ -
-
-
- @* Affiliate caption *@ -
-
-
- @* Burger menu *@ - -
+
+ @* Contact item template *@ +
+
+
+ @* Contact caption *@ +
-
-
-
-
@Localiser["label.associations"]: 
-
-
-
-
-
-
-
-
+
+ @* Burger menu *@ + +
+
+
+
+
+
@Localiser["label.associations"]: 
+
+
+
+
+
+
+
- @* Burger dropdown item template - ul is ignored *@ -
    -
  • XXX
  • -
+ @* Burger dropdown item template - ul is ignored *@ +
    +
  • XXX
  • +
+
- + diff --git a/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-AffiliateDialog.cshtml b/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-AffiliateDialog.cshtml deleted file mode 100644 index 60bbd48..0000000 --- a/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-AffiliateDialog.cshtml +++ /dev/null @@ -1,56 +0,0 @@ -@model Model_Contact -@inject SbmLocaliser Localiser -@{ - /* Affiliates - Affiliate dialog panel */ -} - - -@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAffiliateId", @class = "sbm-form" })) -{ - @Html.HiddenFor(model => model.AffiliateId, new { @class = "AffiliateId" }) -} -
- - @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAffiliate", @class = "sbm-form", @onSubmit = "return false;" })) - { - @Html.HiddenFor(model => model.AffiliateId, new { @id = "", @class = "AffiliateId" }) - - @* Affiliate Type *@ -
-
- -
-
- @Html.DropDownListFor(model => model.AffiliateType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbAffiliateType", @class = "AffiliateType sbm-select" }) -
-
-
- - @* Affiliate Organisation Name *@ -
-
- -
-
- @Html.TextBoxFor(model => model.AffiliateName, new { @id = "ifAffiliateName", @class = "AffiliateName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) }) -
-
-
- - @* Affiliate Notes *@ -
-
- -
-
- @Html.TextAreaFor(model => model.AffiliateNotes, new { @id = "ifAffiliateNotes", @class = "AffiliateNotes sbm-textarea", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes) }) -
-
-
- - } - -
diff --git a/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-ContactDialog.cshtml b/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-ContactDialog.cshtml new file mode 100644 index 0000000..30474de --- /dev/null +++ b/SaBusinessMgrCoreWebPortal/Views/Contact/Panel-ContactDialog.cshtml @@ -0,0 +1,80 @@ +@model Model_Contact +@inject SbmLocaliser Localiser +@{ + /* Contacts - Contactdialog panel */ +} + + +@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactId", @class = "sbm-form" })) +{ + @Html.HiddenFor(model => model.AffiliateId, new { @class = "AffiliateId" }) +} +
+ + @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContact", @class = "sbm-form", @onSubmit = "return false;" })) + { + @Html.HiddenFor(model => model.AffiliateId, new { @id = "", @class = "AffiliateId" }); + @Html.HiddenFor(model => model.ContactExists, new { @id = "", @class = "ContactExists" }); + @Html.HiddenFor(model => model.ContactIndividual, new { @id = "", @class = "ContactIndividual" }); + + @* Contact Type *@ +
+
+ +
+
+ @Html.DropDownListFor(model => model.ContactType, Model.GetAffiliateTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbContactType", @class = "ContactType sbm-select" }) +
+
+
+ + @* Contact Organisation Name *@ +
+
+ +
+
+ @Html.TextBoxFor(model => model.ContactName, new { @id = "ifContactName", @class = "ContactName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) }) +
+
+
+ + @* Contact Individual First Name *@ +
+
+ +
+
+ @Html.TextBoxFor(model => model.ContactFirstName, new { @id = "ifContactFirstName", @class = "ContactFirstName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) }) +
+
+
+ + @* Contact Individual Last Name *@ +
+
+ +
+
+ @Html.TextBoxFor(model => model.ContactLastName, new { @id = "ifContactLastName", @class = "ContactLastName sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) }) +
+
+
+ + @* Contact Notes *@ +
+
+ +
+
+ @Html.TextAreaFor(model => model.ContactNotes, new { @id = "ifContactNotes", @class = "ContactNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes) }) +
+
+
+ + } + +
diff --git a/SaBusinessMgrCoreWebPortal/Views/Security/ChangePassword.cshtml b/SaBusinessMgrCoreWebPortal/Views/Security/ChangePassword.cshtml index c74ac9c..8408ead 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Security/ChangePassword.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Security/ChangePassword.cshtml @@ -20,7 +20,7 @@ /* Current password - required when setting password within user session. */
-
+
@Html.PasswordFor(model => model.PasswordCurrent, new { @id = "ifPasswordCurrent", @class = "sbm-input", @maxlength = Model.PasswordMaxLength })
@@ -35,7 +35,7 @@
-
+
@Html.PasswordFor(model => model.Password, new { @id = "ifPassword", @class = "sbm-input", @maxlength = Model.PasswordMaxLength })
@@ -48,7 +48,7 @@
-
+
@Html.PasswordFor(model => model.PasswordConfirm, new { @id = "ifPasswordConfirm", @class = "sbm-input", @maxlength = Model.PasswordMaxLength })
diff --git a/SaBusinessMgrCoreWebPortal/Views/Security/RequestPassword.cshtml b/SaBusinessMgrCoreWebPortal/Views/Security/RequestPassword.cshtml index 73a4c47..9424b30 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Security/RequestPassword.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Security/RequestPassword.cshtml @@ -17,7 +17,7 @@
- +
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sbm-input lower", @maxlength = "128" }) diff --git a/SaBusinessMgrCoreWebPortal/Views/Security/Signin.cshtml b/SaBusinessMgrCoreWebPortal/Views/Security/Signin.cshtml index f891f2d..a9bc483 100644 --- a/SaBusinessMgrCoreWebPortal/Views/Security/Signin.cshtml +++ b/SaBusinessMgrCoreWebPortal/Views/Security/Signin.cshtml @@ -20,7 +20,7 @@
- +
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sbm-input lower", @maxlength = @emailAddressLen }) @@ -33,7 +33,7 @@
- +
diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css index 5dbecb7..f8b1ca9 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css +++ b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-data.css @@ -38,14 +38,15 @@ .sbm-panel-filter .sbm-header .sbm-action { - margin: 2px 0 0 8px; - border-radius: 4px; + margin: 2px 4px 0 8px; + padding: 2px 4px; + border-radius: 3px; } .sbm-panel-filter .sbm-header .sbm-action:hover { - background-color: #b0b0b0; - box-shadow: 0 0 4px 2px #80808080; + background-color: #e0e0e0; + /*box-shadow: 0 0 4px 2px #80808080;*/ } .sbm-panel-filter .sbm-content @@ -85,7 +86,7 @@ .sbm-results-paging .sbm-paging-info { - font-size: .8rem; + font-size: .67rem; } .sbm-panel-filter .sbm-header .sbm-results-paging .sbm-action @@ -157,7 +158,7 @@ .sbm-panel-item > .sbm-header .sbm-action { - border-radius: 4px; + border-radius: 3px; } .sbm-panel-item > .sbm-header .sbm-caption .sbm-action:hover @@ -167,13 +168,14 @@ .sbm-panel-item > .sbm-header .sbm-actions .sbm-action { - margin: 2px 0 0 8px; + margin: 2px 4px 0 8px; + padding: 2px 4px; } .sbm-panel-item > .sbm-header .sbm-actions .sbm-action:hover { - background-color: #c0c0c0; - box-shadow: 0 0 4px 2px #c0c0c080; + background-color: #e0e0e0; + /*box-shadow: 0 0 4px 2px #c0c0c080;*/ } .sbm-panel-item > .sbm-content diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css index 5a990ba..230774b 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css +++ b/SaBusinessMgrCoreWebPortal/wwwroot/css/sbm-main.css @@ -94,6 +94,10 @@ body /* Header */ +#sbm-page-header +{ +} + a.navbar-brand { white-space: normal; @@ -122,7 +126,15 @@ button.accept-policy line-height: inherit; } +/* Footer */ + +#sbm-page-footer, #sbm-page-footer div +{ + font-size: .8rem; +} + /* Page caption */ + .sbm-page-caption { margin: 0; diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js index 552956d..6783bfc 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-commodity.js @@ -6,122 +6,136 @@ { "use strict"; sbm.itemIdPrefix = 'Itm_'; - var $results; + let $pnl = sbm.$pnl; + let $frm = sbm.$frm; + let $dlg = sbm.$dlg; //-------------------------------------------------------------- sbm.refreshResults = function (delay) { if (!sbm.awaitingRefreshResponse) { - var $items = $('.sbm-panel-item-list', $results).fadeOut(200).empty(); - var $msgs = $('.sbm-panel-messages', $results).hide().empty().append($('
' + sbm.msg.dataQuerying + '
')).fadeIn(200); + $('.sbm-burger', $pnl.filter).hide(); + $('.sbm-panel-item-list', $pnl.results).fadeOut(200).empty(); + $('.sbm-panel-messages', $pnl.results).hide().empty().append($('
' + sbm.msg.dataQuerying + '
')).fadeIn(200); } sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Commodity/Ajax/List', formId: 'frmCommodityFilter', callbackFn: sbm.doRefreshResults }; sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50); sbm.awaitingRefreshResponse = true; } + sbm.getFilterDropdownTemplate = function () + { + return $('.sbm-panel-item-template .sbm-dropdown-menu.CommodityFilter li.sbm-dropdown-item', $pnl.filter).clone(); + } sbm.getItemTemplate = function () { - return $('.sbm-panel-item-template .sbm-panel-item.Commodity', $results); + return $('.sbm-panel-item-template .sbm-panel-item.Commodity', $pnl.results).clone(); } - sbm.getDropdownItemTemplate = function () + sbm.getItemDropdownTemplate = function () { - return $('.sbm-panel-item-template .sbm-dropdown-menu.Commodity li.sbm-dropdown-item', $results); + return $('.sbm-panel-item-template .sbm-dropdown-menu.Commodity li.sbm-dropdown-item', $pnl.results).clone(); } sbm.doRefreshResults = function (response) { - sbm.debug('doRefreshResults', response); + //sbm.debug('doRefreshResults', response); delete sbm.awaitingRefreshResponse; sbm.refreshControlValues(response.controlValues); - var $msgs = $('.sbm-panel-messages', $results).hide().empty(); - var $items = $('.sbm-panel-item-list', $results).hide().empty(); - var $tmpl = sbm.getItemTemplate(); + var $msgs = $('.sbm-panel-messages', $pnl.results).hide().empty(); + var $items = $('.sbm-panel-item-list', $pnl.results).hide().empty(); sbm.refreshPaging(response, '#frmCommodityFilter', sbm.refreshResults); if (!response.success) return; // Reference data - Statuses. if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode; if (response.statuses) sbm.populateSelectCodeDesc('#cbCommodityStatus', response.statuses); + // Menu. + var $bgr = $('.sbm-burger', $pnl.filter).hide(); + var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty(); + $mnu.append(sbm.getFilterMenuOption(sbm.lbl.refresh, function () { sbm.refreshResults(); })); + $mnu.append(sbm.getFilterMenuOption(sbm.lbl.create, function () { sbm.createItem(); })); + $bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length); // Items. - var items = response.commodies; + var items = response.commodities; if (!items.length) return $msgs.append($('
' + sbm.msg.dataNoneFound + '
')).fadeIn(500); for (let itemIdx = 0; itemIdx < items.length; itemIdx++) - { - let item = items[itemIdx]; - let $item = $tmpl.clone(); - sbm.populateItem($item, item); - $items.append($item); - } + $items.append(sbm.populateItem(sbm.getItemTemplate(), items[itemIdx])); $items.fadeIn(50); } sbm.populateItem = function ($item, item) { if (!item) return; $item.prop('id', sbm.itemIdPrefix + item.id); - $('.CommodityName', $item).text(item.displayName); + $('.CommodityCode', $item).text(item.code); + $('.CommodityDesc', $item).text(item.desc); $('.CommodityType', $item).text(item.typeDesc); $('.CommodityAssociationCount', $item).on('click', function () { sbm.onClickAssociationCount(item.id); }).toggle(item.associationCount).find('.AssociationCount').text(item.associationCount); $('.CommodityAddress', $item).text(item.addressSummary); $('.CommodityNotes', $item).text(item.notes); $('.StatusDesc', $item).text(item.statusDesc).addClass('sbm-status-' + item.statusCode.toLowerCase()); $('.sbm-caption .sbm-action').toggleClass('sbm-action', !item.deleted); + let $mnu = $('ul.sbm-dropdown-menu', $item); if (!item.deleted) { - let $mnu = $('ul.sbm-dropdown-menu', $item); - $mnu.append(sbm.getDropdownItemTemplate().clone().find('div.sbm-label').text(sbm.lbl.edit).end().on('click', function () { sbm.updateItem(item.id) })); - if (item.awaiting) - $mnu.append(sbm.getDropdownItemTemplate().clone().find('div.sbm-label').text(sbm.lbl.activate).end().on('click', function () { sbm.activateItem(item.id) })); + $mnu.append(sbm.getItemMenuOption(sbm.lbl.edit, function () { sbm.updateItem(item.id) })); $('.sbm-header .sbm-action.sbm-item-update', $item).off('click').on('click', function () { sbm.updateItem(item.id) }); $item.off('dblclick').on('dblclick', function () { sbm.updateItem(item.id) }); } - $('.sbm-burger', $item).toggle(!!$('.sbm-burger .sbm-dropdown-menu .sbm-dropdown-item', $item).length); - $('.sbm-panel-messages', $results).hide().empty(); + $('.sbm-burger', $item).toggle(!!$('.sbm-dropdown-item', $mnu).length); + $('.sbm-panel-messages', $pnl.results).hide().empty(); return $item; } + //-------------------------------------------------------------- + sbm.getFilterMenuOption = function (lbl, fn) + { + return sbm.getMenuOption(sbm.getFilterDropdownTemplate(), lbl, fn); + } + sbm.getItemMenuOption = function (lbl, fn) + { + return sbm.getMenuOption(sbm.getItemDropdownTemplate(), lbl, fn); + } + sbm.getMenuOption = function ($opt, lbl, fn) + { + return $opt.find('div.sbm-label').text(lbl).end().on('click', fn); + } + //-------------------------------------------------------------- sbm.createItem = function () { - let $frm = sbm.$frm.commodity; - $('.CommodityId,input[type="text"],textarea,select', $frm).val(''); - $('.CommodityStatus', $frm).val(sbm.data.defaultStatusCode); + let frm = $frm.commodity; + $('.CommodityId,.CommodityExists,input[type="text"],textarea,select', frm).val(''); + $('.CommodityStatus', frm).val(sbm.data.defaultStatusCode); sbm.clearControlErrors(); sbm.$dlg.commodity.dialog('option', 'title', sbm.dlg.title.createCommodity); sbm.openDialog(sbm.$dlg.commodity, 600, 600); } - sbm.doCreateItem = function () - { - sbm.storeItem(); - } //-------------------------------------------------------------- sbm.updateItem = function (id) { - $('.CommodityId', sbm.$frm.commodityId).val(id); + $('.CommodityId', $frm.commodityId).val(id); sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Commodity/Ajax/GetItem', formId: 'frmCommodityId', callbackFn: sbm.onUpdateItem }; sbm.doAjaxRequest(sbm.ajax.updateItem, 50); } sbm.onUpdateItem = function (response) { - //sbm.debug('onUpdateItem', response); - let $frm = sbm.$frm.commodity; - $('.CommodityId,input[type="text"],textarea,select', $frm).val(''); + sbm.debug('onUpdateItem', response); + let frm = $frm.commodity; + $('.CommodityId,input[type="text"],textarea,select', frm).val(''); if (!response.success) return; let item = response.commodity; - $('.CommodityId', $frm).val(item.id); - $('.CommodityType', $frm).val(item.typeCode); - $('.CommodityName', $frm).val(item.name); - $('.CommodityNotes', $frm).val(item.notes); - $('.CommodityStatus', $frm).val(item.statusCode); + $('.CommodityId', frm).val(item.id); + $('.CommodityExists', frm).val(1); + $('.CommodityType', frm).val(item.typeCode); + $('.CommodityCode', frm).val(item.code); + $('.CommodityDesc', frm).val(item.desc); + $('.CommodityNotes', frm).val(item.notes); + $('.CommodityStatus', frm).val(item.statusCode); sbm.clearControlErrors(); sbm.$dlg.commodity.dialog('option', 'title', sbm.dlg.title.updateCommodity); sbm.openDialog(sbm.$dlg.commodity, 600, 600); } - sbm.doUpdateItem = function () - { - sbm.storeItem(); - } //-------------------------------------------------------------- sbm.storeItem = function () @@ -140,39 +154,30 @@ var $item = $('#' + sbm.itemIdPrefix + item.id); if (!$item.length) { - $item = $('.sbm-panel-item-template .sbm-panel-item.Commodity', $results).clone(); - $('.sbm-panel-item-list', $results).prepend($item).show(); + $item = sbm.getItemTemplate(); + $('.sbm-panel-item-list', $pnl.results).prepend($item).show(); } $item.replaceWith(sbm.populateItem(sbm.getItemTemplate(), item)); } - //-------------------------------------------------------------- - sbm.onClickAssociationCount = function (id) - { - if (!(id * 1)) return; - sbm.doPleaseWait(); - let $frm = $('#frmCommodityId'); - $('.CommodityId', $frm).val(id); - $frm.prop('action', sbm.url.base + 'Association').submit(); - } - //-------------------------------------------------------------- $(function () { - $('.sbm-panel-filter .sbm-action.sbm-item-create').on('click', function () { sbm.createItem(); }); - $('.sbm-panel-filter .sbm-action.sbm-results-refresh').on('click', function () { sbm.refreshResults(); }); + $pnl.commodities = $('.sbm-panel.Commodities'); + $pnl.filter = $('.sbm-panel-filter', $pnl.commodities); + $pnl.results = $('.sbm-panel-results', $pnl.commodities); + $('.sbm-input, .sbm-textarea').on('input', function () { sbm.clearControlError(this); }); $('.sbm-select').on('change', function () { sbm.clearControlError(this); }); - sbm.$frm.filter = $('#frmCommodityFilter'); - $('.FilterCommodity', sbm.$frm.filter).on('input', function () { sbm.refreshResults(250); }); - $('.FilterCommodityCategory,.FilterCommodityStatusCategory', sbm.$frm.filter).on('change', function () { sbm.refreshResults(50); }); - sbm.$frm.commodityId = $('#frmCommodityId'); - sbm.$frm.commodity = $('#frmCommodity'); - $results = $('.sbm-panel-results'); + $frm.filter = $('#frmCommodityFilter'); + $('.FilterCommodity', $frm.filter).on('input', function () { sbm.refreshResults(250); }); + $('.FilterCommodityType,.FilterCommodityStatusCategory', $frm.filter).on('change', function () { sbm.refreshResults(50); }); + $frm.commodityId = $('#frmCommodityId'); + $frm.commodity = $('#frmCommodity'); var opt = sbm.dlgOpts(); - opt.buttons[sbm.dlg.btn.ok] = function () { sbm.doCreateItem(); }; + opt.buttons[sbm.dlg.btn.ok] = function () { sbm.storeItem(); }; opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); }; sbm.$dlg.commodity = $('#dlgCommodity').dialog(opt); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js index e0658e5..5d5f8df 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-contact.js @@ -6,127 +6,152 @@ { "use strict"; sbm.itemIdPrefix = 'Itm_'; - var $results; + let $pnl = sbm.$pnl; + let $frm = sbm.$frm; + let $dlg = sbm.$dlg; //-------------------------------------------------------------- sbm.refreshResults = function (delay) { if (!sbm.awaitingRefreshResponse) { - var $items = $('.sbm-panel-item-list', $results).fadeOut(200).empty(); - var $msgs = $('.sbm-panel-messages', $results).hide().empty().append($('
' + sbm.msg.dataQuerying + '
')).fadeIn(200); + $('.sbm-burger', $pnl.filter).hide(); + $('.sbm-panel-item-list', $pnl.results).fadeOut(200).empty(); + $('.sbm-panel-messages', $pnl.results).hide().empty().append($('
' + sbm.msg.dataQuerying + '
')).fadeIn(200); } - sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formId: 'frmAffiliateFilter', callbackFn: sbm.doRefreshResults }; + sbm.ajax.refreshResults = sbm.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formId: 'frmContactFilter', callbackFn: sbm.doRefreshResults }; sbm.doAjaxRequest(sbm.ajax.refreshResults, delay || 50); sbm.awaitingRefreshResponse = true; } + sbm.getFilterDropdownTemplate = function () + { + return $('.sbm-panel-item-template .sbm-dropdown-menu.ContactFilter li.sbm-dropdown-item', $pnl.filter).clone(); + } sbm.getItemTemplate = function () { - return $('.sbm-panel-item-template .sbm-panel-item.Affiliate', $results); + return $('.sbm-panel-item-template .sbm-panel-item.Contact', $pnl.results).clone(); } - sbm.getDropdownItemTemplate = function () + sbm.getItemDropdownTemplate = function () { - return $('.sbm-panel-item-template .sbm-dropdown-menu.Affiliate li.sbm-dropdown-item', $results); + return $('.sbm-panel-item-template .sbm-dropdown-menu.Contact li.sbm-dropdown-item', $pnl.results).clone(); } sbm.doRefreshResults = function (response) { - sbm.debug('doRefreshResults', response); + //sbm.debug('doRefreshResults', response); delete sbm.awaitingRefreshResponse; sbm.refreshControlValues(response.controlValues); - var $msgs = $('.sbm-panel-messages', $results).hide().empty(); - var $items = $('.sbm-panel-item-list', $results).hide().empty(); - var $tmpl = sbm.getItemTemplate(); - sbm.refreshPaging(response, '#frmAffiliateFilter', sbm.refreshResults); + var $msgs = $('.sbm-panel-messages', $pnl.results).hide().empty(); + var $items = $('.sbm-panel-item-list', $pnl.results).hide().empty(); + sbm.refreshPaging(response, '#frmContactFilter', sbm.refreshResults); if (!response.success) return; // Reference data - Statuses. if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode; if (response.statuses) - sbm.populateSelectCodeDesc('#cbAffiliateStatus', response.statuses); + sbm.populateSelectCodeDesc('#cbContactStatus', response.statuses); + // Menu. + var $bgr = $('.sbm-burger', $pnl.filter).hide(); + var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty(); + $mnu.append(sbm.getFilterMenuOption(sbm.lbl.refresh, function () { sbm.refreshResults(); })); + $mnu.append(sbm.getFilterMenuOption(sbm.lbl.createOrg, function () { sbm.createItem(); })); + $mnu.append(sbm.getFilterMenuOption(sbm.lbl.createInd, function () { sbm.createItem(1); })); + $bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length); // Items. var items = response.affiliates; if (!items.length) return $msgs.append($('
' + sbm.msg.dataNoneFound + '
')).fadeIn(500); for (let itemIdx = 0; itemIdx < items.length; itemIdx++) - { - let item = items[itemIdx]; - let $item = $tmpl.clone(); - sbm.populateItem($item, item); - $items.append($item); - } + $items.append(sbm.populateItem(sbm.getItemTemplate(), items[itemIdx])); $items.fadeIn(50); } sbm.populateItem = function ($item, item) { if (!item) return; $item.prop('id', sbm.itemIdPrefix + item.id); - $('.AffiliateName', $item).text(item.displayName); - $('.AffiliateType', $item).text(item.typeDesc); - $('.AffiliateAssociationCount', $item).on('click', function () { sbm.onClickAssociationCount(item.id); }).toggle(item.associationCount).find('.AssociationCount').text(item.associationCount); - $('.AffiliateAddress', $item).text(item.addressSummary); - $('.AffiliateNotes', $item).text(item.notes); + $('.ContactName', $item).text(item.displayName); + $('.ContactType', $item).text(item.typeDesc); + $('.ContactAssociationCount', $item).on('click', function () { sbm.onClickAssociationCount(item.id); }).toggle(item.associationCount).find('.AssociationCount').text(item.associationCount); + $('.ContactAddress', $item).text(item.addressSummary); + $('.ContactNotes', $item).text(item.notes); $('.StatusDesc', $item).text(item.statusDesc).addClass('sbm-status-' + item.statusCode.toLowerCase()); $('.sbm-caption .sbm-action').toggleClass('sbm-action', !item.deleted); + let $mnu = $('ul.sbm-dropdown-menu', $item).empty(); if (!item.deleted) { - let $mnu = $('ul.sbm-dropdown-menu', $item); - $mnu.append(sbm.getDropdownItemTemplate().clone().find('div.sbm-label').text(sbm.lbl.edit).end().on('click', function () { sbm.updateItem(item.id) })); - if (item.awaiting) - $mnu.append(sbm.getDropdownItemTemplate().clone().find('div.sbm-label').text(sbm.lbl.activate).end().on('click', function () { sbm.activateItem(item.id) })); + $mnu.append(sbm.getItemMenuOption(sbm.lbl.edit, function () { sbm.updateItem(item.id) })); $('.sbm-header .sbm-action.sbm-item-update', $item).off('click').on('click', function () { sbm.updateItem(item.id) }); $item.off('dblclick').on('dblclick', function () { sbm.updateItem(item.id) }); } - $('.sbm-burger', $item).toggle(!!$('.sbm-burger .sbm-dropdown-menu .sbm-dropdown-item', $item).length); - $('.sbm-panel-messages', $results).hide().empty(); + $('.sbm-burger', $item).toggle(!!$('.sbm-dropdown-item', $mnu).length); + $('.sbm-panel-messages', $pnl.results).hide().empty(); return $item; } //-------------------------------------------------------------- - sbm.createItem = function () + sbm.getFilterMenuOption = function (lbl, fn) { - let $frm = sbm.$frm.affiliate; - $('.AffiliateId,input[type="text"],textarea,select', $frm).val(''); - $('.AffiliateStatus', $frm).val(sbm.data.defaultStatusCode); - sbm.clearControlErrors(); - sbm.$dlg.affiliate.dialog('option', 'title', sbm.dlg.title.createAffiliate); - sbm.openDialog(sbm.$dlg.affiliate, 600, 600); + return sbm.getMenuOption(sbm.getFilterDropdownTemplate(), lbl, fn); } - sbm.doCreateItem = function () + sbm.getItemMenuOption = function (lbl, fn) { - sbm.storeItem(); + return sbm.getMenuOption(sbm.getItemDropdownTemplate(), lbl, fn); + } + sbm.getMenuOption = function ($opt, lbl, fn) + { + return $opt.find('div.sbm-label').text(lbl).end().on('click', fn); + } + + //-------------------------------------------------------------- + sbm.createItem = function (ind) + { + let frm = $frm.contact; + sbm.clearControlErrors(frm); + $('.AffiliateId,.ContactExists,input[type="text"],textarea,select', frm).val(''); + $('.ContactIndividual', frm).val(!!ind ? 1 : null); + $('.ContactStatus', frm).val(sbm.data.defaultStatusCode); + sbm.toggleContactControls(ind); + $dlg.contact.dialog('option', 'title', sbm.dlg.title.createContact); + sbm.openDialog($dlg.contact, 600, 600); + } + sbm.toggleContactControls = function (ind) + { + let frm = $frm.contact; + $('.sbm-form-control.ContactType,.sbm-form-control.ContactName', frm).toggle(!ind).find('input,select').prop('disabled', !!ind); + $('.sbm-form-control.ContactFirstName,.sbm-form-control.ContactLastName', frm).toggle(!!ind).find('input,select').prop('disabled', !ind); } //-------------------------------------------------------------- sbm.updateItem = function (id) { - $('.AffiliateId', sbm.$frm.affiliateId).val(id); - sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formId: 'frmAffiliateId', callbackFn: sbm.onUpdateItem }; + $('.AffiliateId', $frm.contactId).val(id); + sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formId: 'frmContactId', callbackFn: sbm.onUpdateItem }; sbm.doAjaxRequest(sbm.ajax.updateItem, 50); } sbm.onUpdateItem = function (response) { //sbm.debug('onUpdateItem', response); - let $frm = sbm.$frm.affiliate; - $('.AffiliateId,input[type="text"],textarea,select', $frm).val(''); + let frm = $frm.contact; + $('.AffiliateId,input[type="text"],textarea,select', frm).val(''); if (!response.success) return; let item = response.affiliate; - $('.AffiliateId', $frm).val(item.id); - $('.AffiliateType', $frm).val(item.typeCode); - $('.AffiliateName', $frm).val(item.name); - $('.AffiliateNotes', $frm).val(item.notes); - $('.AffiliateStatus', $frm).val(item.statusCode); + sbm.toggleContactControls(item.individual); + $('.AffiliateId', frm).val(item.id); + $('.ContactExists', frm).val(1); + $('.ContactIndividual', frm).val(!!item.individual ? 1 : null); + $('.ContactType', frm).val(item.typeCode); + $('.ContactName', frm).val(item.name); + $('.ContactFirstName', frm).val(item.firstName); + $('.ContactLastName', frm).val(item.lastName); + $('.ContactNotes', frm).val(item.notes); + $('.ContactStatus', frm).val(item.statusCode); sbm.clearControlErrors(); - sbm.$dlg.affiliate.dialog('option', 'title', sbm.dlg.title.updateAffiliate); - sbm.openDialog(sbm.$dlg.affiliate, 600, 600); - } - sbm.doUpdateItem = function () - { - sbm.storeItem(); + $dlg.contact.dialog('option', 'title', sbm.dlg.title.updateContact); + sbm.openDialog($dlg.contact, 600, 600); } //-------------------------------------------------------------- sbm.storeItem = function () { - sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formId: 'frmAffiliate', callbackFn: sbm.onStoreItem }; + sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formId: 'frmContact', callbackFn: sbm.onStoreItem }; sbm.doAjaxRequest(sbm.ajax.storeItem, 50); } sbm.onStoreItem = function (response) @@ -134,14 +159,14 @@ //sbm.debug('onStoreItem', response); sbm.refreshControlValues(response.controlValues); if (!response.success) return; - sbm.$dlg.affiliate.dialog('close'); + $dlg.contact.dialog('close'); var item = response.affiliate; var $item = $('#' + sbm.itemIdPrefix + item.id); if (!$item.length) { - $item = $('.sbm-panel-item-template .sbm-panel-item.Affiliate', $results).clone(); - $('.sbm-panel-item-list', $results).prepend($item).show(); + $item = sbm.getItemTemplate(); + $('.sbm-panel-item-list', $pnl.results).prepend($item).show(); } $item.replaceWith(sbm.populateItem(sbm.getItemTemplate(), item)); } @@ -151,30 +176,31 @@ { if (!(id * 1)) return; sbm.doPleaseWait(); - let $frm = $('#frmAffiliateId'); - $('.AffiliateId', $frm).val(id); - $frm.prop('action', sbm.url.base + 'Association').submit(); + let frm = $frm.contactId; + $('.AffiliateId', frm).val(id); + frm.prop('action', sbm.url.base + 'Association').submit(); } //-------------------------------------------------------------- $(function () { - $('.sbm-panel-filter .sbm-action.sbm-item-create').on('click', function () { sbm.createItem(); }); - $('.sbm-panel-filter .sbm-action.sbm-results-refresh').on('click', function () { sbm.refreshResults(); }); + $pnl.contacts = $('.sbm-panel.Contacts'); + $pnl.filter = $('.sbm-panel-filter', $pnl.contacts); + $pnl.results = $('.sbm-panel-results', $pnl.contacts); + $('.sbm-input, .sbm-textarea').on('input', function () { sbm.clearControlError(this); }); $('.sbm-select').on('change', function () { sbm.clearControlError(this); }); - sbm.$frm.filter = $('#frmAffiliateFilter'); - $('.FilterAffiliate', sbm.$frm.filter).on('input', function () { sbm.refreshResults(250); }); - $('.FilterAffiliateCategory,.FilterAffiliateStatusCategory', sbm.$frm.filter).on('change', function () { sbm.refreshResults(50); }); - sbm.$frm.affiliateId = $('#frmAffiliateId'); - sbm.$frm.affiliate = $('#frmAffiliate'); - $results = $('.sbm-panel-results'); + $frm.filter = $('#frmContactFilter'); + $('.FilterContact', $frm.filter).on('input', function () { sbm.refreshResults(250); }); + $('.FilterContactType', $frm.filter).on('change', function () { sbm.refreshResults(50); }); + $frm.contactId = $('#frmContactId'); + $frm.contact = $('#frmContact'); var opt = sbm.dlgOpts(); - opt.buttons[sbm.dlg.btn.ok] = function () { sbm.doCreateItem(); }; + opt.buttons[sbm.dlg.btn.ok] = function () { sbm.storeItem(); }; opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); }; - sbm.$dlg.affiliate = $('#dlgAffiliate').dialog(opt); + $dlg.contact = $('#dlgContact').dialog(opt); setTimeout(sbm.refreshResults, 250); }); diff --git a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-main.js b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-main.js index 20f343e..a65ee16 100644 --- a/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-main.js +++ b/SaBusinessMgrCoreWebPortal/wwwroot/js/sbm-main.js @@ -264,7 +264,7 @@ //sbm.debug(sbm.topMargin($bdy)); var fbr = $bdy[0].getBoundingClientRect(); var fn = function () { $hdr.delay(2000).animate({ backgroundColor: '#f0f0f0' }, 1000); }; - $not.css({ 'top': Math.max(0, fbr.top - sbm.topMargin($bdy)), 'right': $win.width() - fbr.right }).slideDown(500, fn); + $not.css({ 'top': Math.max(0, fbr.top /*- sbm.topMargin($bdy)*/), 'right': $win.width() - fbr.right }).slideDown(500, fn); sbm.toNotification = setTimeout(sbm.hideNotification, 6000); } sbm.hideNotification = function ()