Associations
This commit is contained in:
@@ -609,4 +609,16 @@
|
||||
<data name="label.reference.external" xml:space="preserve">
|
||||
<value>Ext. reference</value>
|
||||
</data>
|
||||
<data name="label.location" xml:space="preserve">
|
||||
<value>Location</value>
|
||||
</data>
|
||||
<data name="label.group" xml:space="preserve">
|
||||
<value>Group</value>
|
||||
</data>
|
||||
<data name="caption.association.select" xml:space="preserve">
|
||||
<value>Select Association</value>
|
||||
</data>
|
||||
<data name="caption.contact.select" xml:space="preserve">
|
||||
<value>Select Contact</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -47,7 +47,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SbmSessionContext_Web SessionContext { get; }
|
||||
public HashSet<string> DbIdentifiers { get; } = new HashSet<string>();
|
||||
public HashSet<string> RepositoryContexts { get; } = new HashSet<string>();
|
||||
public ISacsDatabase BusMgrDatabase { get; set; }
|
||||
public virtual SbmInstanceConfig InstanceConfig => null;
|
||||
// Control database properties.
|
||||
@@ -125,17 +125,25 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList();
|
||||
}
|
||||
public override SbmSessionContext GetSessionContext(ushort index)
|
||||
public override SbmSessionContext GetSessionContextByIndex(ushort index)
|
||||
{
|
||||
return sessionContexts.GetValue(index, null)?.SessionContext;
|
||||
}
|
||||
public SbmSessionContext GetControlSessionContext(String dbIdentifier)
|
||||
public override List<SbmSessionContext> GetSessionContexts()
|
||||
{
|
||||
return PopulateControlSessionContext(dbIdentifier)?.SessionContext;
|
||||
return new List<SbmSessionContext>(sessionContexts.Values.Select(item => item.SessionContext));
|
||||
}
|
||||
public override HashSet<string> GetDbIdentifiers(SbmSessionContext sessionContext)
|
||||
/// <summary>
|
||||
/// Retrieve the Control Session Context that matches the Repository Context, if defined.
|
||||
/// <para>- Control Session Context will be populated if not previously referenced.</para>
|
||||
/// </summary>
|
||||
public SbmSessionContext GetControlSessionContextByRepositoryContext(String repositoryContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.DbIdentifiers ?? new HashSet<string>();
|
||||
return PopulateControlSessionContext(repositoryContext)?.SessionContext;
|
||||
}
|
||||
public override HashSet<string> GetRepositoryContexts(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.RepositoryContexts ?? new HashSet<string>();
|
||||
}
|
||||
// Databases.
|
||||
public override ISacsDatabase GetControlDatabase()
|
||||
@@ -240,7 +248,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
ushort sessionContextIdx = sessionContextIdx_Next++;
|
||||
SessionContextData sessionContextData = new SessionContextData_Core(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal));
|
||||
sessionContextData.BusMgrDatabase = coreDatabase;
|
||||
sessionContextData.DbIdentifiers.UnionWith(dbConfig.Identifiers);
|
||||
sessionContextData.RepositoryContexts.UnionWith(dbConfig.Identifiers);
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Database: " + coreDatabase.DatabaseName + ". Initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
@@ -253,12 +261,12 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private SessionContextData PopulateControlSessionContext(String dbIdentifier)
|
||||
private SessionContextData PopulateControlSessionContext(String repositoryContext)
|
||||
{
|
||||
if (StringUtil.IsBlank(dbIdentifier)) return null;
|
||||
if (StringUtil.IsBlank(repositoryContext)) return null;
|
||||
|
||||
// Check whether context already exists in cache.
|
||||
SessionContextData sessionContextData = sessionContexts.Values.FirstOrDefault(sc => sc.IsControl && sc.DbIdentifiers.ContainsCI(dbIdentifier));
|
||||
SessionContextData sessionContextData = sessionContexts.Values.FirstOrDefault(sc => sc.IsControl && sc.RepositoryContexts.ContainsCI(repositoryContext));
|
||||
using (DisposableCollection<IDisposable> disposables = new DisposableCollection<IDisposable>())
|
||||
{
|
||||
SbmcInstanceMgr controlInstanceMgr = SbmGlobals_Web.System.CreateControlInstanceMgr();
|
||||
@@ -267,7 +275,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
|
||||
// Check whether context is defined in Control database (and active).
|
||||
SbmcRepository.Params prmRepository = new SbmcRepository.Params();
|
||||
prmRepository.ContextsIncluded.Add(dbIdentifier);
|
||||
prmRepository.ContextsIncluded.Add(repositoryContext);
|
||||
SbmcRepository repository = controlInstanceMgr.GetRepository(prmRepository);
|
||||
disposables.Add(repository);
|
||||
|
||||
@@ -301,14 +309,14 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
else SaLogger.Info($"{SysUtil.Fn} Control Instance refreshed: Context: {repository.Context}. Database: {repository.DatabaseName}.");
|
||||
|
||||
// Refresh properties.
|
||||
sessionContextData.DbIdentifiers.Add(repository.Context);
|
||||
sessionContextData.RepositoryContexts.Add(repository.Context);
|
||||
sessionContextData.BusMgrDatabase = coreDatabase;
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Database: {coreDatabase.DatabaseName}. Initialisation error: {coreDatabase.ErrorStateMessage}");
|
||||
}
|
||||
else
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Attempt to connect to inactive repository. Context: {dbIdentifier}.");
|
||||
SaLogger.Warn($"{SysUtil.Fn} Attempt to connect to inactive repository. Context: {repositoryContext}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
/// <para>SessionContext and UserAccount must be supplied.</para>
|
||||
/// <para>Organisation is optional.</para>
|
||||
/// </summary>
|
||||
public SbmSessionData_Portal(SbmSessionContext sessionContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
public SbmSessionData_Portal(SbmSessionContext sessionContext, String repositoryContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
base(sessionContext)
|
||||
{
|
||||
DbIdentifier = dbIdentifier;
|
||||
RepositoryContext = repositoryContext;
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
Organisation = new OrganisationData_Portal(associationOrganisation, affiliateOrganisation);
|
||||
User = new UserData_Portal(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
@@ -100,7 +100,7 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
// Database context.
|
||||
|
||||
/// <summary>Database context specified on sign-in.</summary>
|
||||
public String DbIdentifier { get; set; }
|
||||
public String RepositoryContext { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security Profile.
|
||||
|
||||
+49
-8
@@ -73,9 +73,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
}
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Target}", affiliateTarget.GetDisplayName());
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.ReferenceExt}", association.RefExt);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Location}", association.Location);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Group}", association.Group);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.DescDetail}", association.DescDetail);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Location}", association.Location);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Role}", association.Role);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.PhoneMain}", association.PhoneMain);
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Email}", association.Email);
|
||||
@@ -83,7 +83,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
// Flags.
|
||||
// Common properties.
|
||||
data.StatusCode = association.StatusCode;
|
||||
data.StatusDesc = association.StatusDesc;
|
||||
data.Field.Value.Add($"{Model_Association.ItemField.Status}", association.StatusDesc);
|
||||
// Cleanse field values.
|
||||
data.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value));
|
||||
// Populate item list values that might be cleared during update after removing blank values to ensure that blank values are published.
|
||||
@@ -99,6 +99,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_AssociationConfig(SbmModel_Portal model) : base(model) { }
|
||||
// Page caption.
|
||||
public String Caption { get; set; }
|
||||
// Configuration.
|
||||
public Model_Association.ListConfigData Config { get; } = new Model_Association.ListConfigData();
|
||||
public Model_Association.ItemConfigData ConfigCust { get; } = new Model_Association.ItemConfigData();
|
||||
@@ -131,6 +133,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
}
|
||||
private void PopulateAssociationConfig(Model_Association model, AjaxResponse_AssociationConfig responseData)
|
||||
{
|
||||
// Page caption.
|
||||
Sbm.AssociationType associationType = model.GetFilterAssociationType();
|
||||
if (associationType == Sbm.AssociationType.Customer)
|
||||
responseData.Caption = Localiser["label.customers"];
|
||||
else if (associationType == Sbm.AssociationType.Supplier)
|
||||
responseData.Caption = Localiser["label.suppliers"];
|
||||
responseData.Caption = StringUtil.OnBlank(responseData.Caption, Localiser["label.associations"]);
|
||||
|
||||
// Configuration.
|
||||
model.PopulateListConfig(responseData.Config);
|
||||
model.PopulateItemConfig(responseData.ConfigCust, null, SessionData_Portal.Organisation.AffiliateId, Sbm.AssociationType.Customer);
|
||||
@@ -138,11 +148,11 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
|
||||
// Reference data - types.
|
||||
List<TypeCodeDesc> associationTypes = Internals.AssociationTypeCodes;
|
||||
foreach (Sbm.AssociationType associationType in EnumUtil.GetValues<Sbm.AssociationType>())
|
||||
foreach (Sbm.AssociationType type in EnumUtil.GetValues<Sbm.AssociationType>())
|
||||
{
|
||||
if (associationType <= 0 || associationType == Sbm.AssociationType.Internal) continue;
|
||||
if (!SessionConsole.AllowAssociationType(associationType)) continue;
|
||||
responseData.AssociationTypes.Add(associationTypes.GetCodeForType(associationType), Localiser.GetAssociationTypeCaption(associationType));
|
||||
if (type <= 0 || type == Sbm.AssociationType.Internal) continue;
|
||||
if (!SessionConsole.AllowAssociationType(type)) continue;
|
||||
responseData.AssociationTypes.Add(associationTypes.GetCodeForType(type), Localiser.GetAssociationTypeCaption(type));
|
||||
}
|
||||
|
||||
// Reference data - statuses.
|
||||
@@ -158,6 +168,15 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_AssociationList(SbmModel_Portal model) : base(model) { }
|
||||
// View mode.
|
||||
public class ModeData
|
||||
{
|
||||
public bool? Maintain { get; set; }
|
||||
public bool? Search { get; set; }
|
||||
public bool? Relationships { get; set; }
|
||||
public bool? PriceSet { get; set; }
|
||||
}
|
||||
public ModeData Mode { get; set; }
|
||||
// Association list.
|
||||
public List<AssociationListData> Associations { get; } = new List<AssociationListData>();
|
||||
}
|
||||
@@ -178,13 +197,35 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
// Populate configuration data.
|
||||
PopulateAssociationConfig(model, responseData);
|
||||
|
||||
// View mode.
|
||||
responseData.Mode = new AjaxResponse_AssociationList.ModeData();
|
||||
switch (model.GetFilterMode())
|
||||
{
|
||||
case Model_Association.AssociationViewMode.Search:
|
||||
responseData.Mode.Search = true;
|
||||
break;
|
||||
case Model_Association.AssociationViewMode.Relationships:
|
||||
responseData.Mode.Relationships = true;
|
||||
break;
|
||||
case Model_Association.AssociationViewMode.PriceSet:
|
||||
responseData.Mode.PriceSet = true;
|
||||
break;
|
||||
default:
|
||||
responseData.Mode.Maintain = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Item filter.
|
||||
SbmAssociation.Params prmAssociation = new SbmAssociation.Params();
|
||||
prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId;
|
||||
prmAssociation.Search = model.Filter.Search;
|
||||
if (SysId.IsValid(StringUtil.ToSysId(model.Filter.OwnerId)))
|
||||
prmAssociation.AffiliateIdOwner = StringUtil.ToSysId(model.Filter.OwnerId);
|
||||
else prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId;
|
||||
if (SysId.IsValid(StringUtil.ToSysId(model.Filter.TargetId)))
|
||||
prmAssociation.AffiliateIdTarget = StringUtil.ToSysId(model.Filter.TargetId);
|
||||
prmAssociation.AssociationType = model.GetFilterAssociationType();
|
||||
if (prmAssociation.AssociationType <= 0)
|
||||
prmAssociation.AssociationType = Sbm.AssociationType.NotInternal;
|
||||
prmAssociation.Search = model.Filter.Search;
|
||||
prmAssociation.StatusCat = SbmAssociation.StatusCat.NotDeleted;
|
||||
prmAssociation.SortColumns.Add(AccountMgr.GetAssociationColumnDfn(SbmAssociation.Column.Target_Name));
|
||||
model.Paging.ItemTotal = (ulong)AccountMgr.GetAssociationCount(prmAssociation);
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
{
|
||||
@@ -33,7 +34,11 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index(Model_Association model)
|
||||
[Route("Association")]
|
||||
[Route("Associations")]
|
||||
[Route("Customers")]
|
||||
[Route("Suppliers")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
@@ -46,7 +51,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
}
|
||||
|
||||
// Association page.
|
||||
Model_Association model = new Model_Association(Localiser);
|
||||
RefreshModel(model);
|
||||
if (Request.Path.Value.MatchCI("/Customers/?$"))
|
||||
model.Filter.AssociationType = Internals.AssociationTypeCodes.GetCodeForType(Sbm.AssociationType.Customer);
|
||||
else if (Request.Path.Value.MatchCI("/Suppliers/?$"))
|
||||
model.Filter.AssociationType = Internals.AssociationTypeCodes.GetCodeForType(Sbm.AssociationType.Supplier);
|
||||
model.PopulateListConfig();
|
||||
model.Paging.PageNo = SessionData_Portal.Profile.Associations.Filter.PageNo;
|
||||
model.Paging.PageLength = SessionData_Portal.Profile.Associations.Filter.PageLength;
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
// Affiliate data.
|
||||
private class AffiliateListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
// Affiliate properties with specific handling.
|
||||
public String Name { get; set; }
|
||||
// Affiliate properties for list with specific handling.
|
||||
public long? AssociationCount { get; set; }
|
||||
// Fields.
|
||||
@@ -50,6 +52,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
private void PopulateAffiliateResponseItemData(Model_Contact model, SbmAffiliate affiliate, AffiliateItemData data)
|
||||
{
|
||||
PopulateAffiliateResponseListData(model, affiliate, data as AffiliateListData);
|
||||
// Affiliate name - prominent property for selecting and editing.
|
||||
data.Name = affiliate.Name;
|
||||
// Affiliate type - populate for list ('Type' property populated with desc) and form (Type Code & Desc).
|
||||
data.TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliate.AffiliateType);
|
||||
data.TypeDesc = Internals.AffiliateTypeCodes.GetDescForType(affiliate.AffiliateType);
|
||||
@@ -84,7 +88,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
data.Field.Value.Add($"{Model_Contact.ItemField.Prospect}", affiliate.Prospect ? "1" : "");
|
||||
// Common properties.
|
||||
data.StatusCode = affiliate.StatusCode;
|
||||
data.StatusDesc = affiliate.StatusDesc;
|
||||
data.Field.Value.Add($"{Model_Contact.ItemField.Status}", affiliate.StatusDesc);
|
||||
// Cleanse field values.
|
||||
data.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value));
|
||||
// Populate item list values that might be cleared during update after removing blank values to ensure that blank values are published.
|
||||
@@ -172,6 +176,13 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_ContactList(SbmModel_Portal model) : base(model) { }
|
||||
// View mode.
|
||||
public class ModeData
|
||||
{
|
||||
public bool? Maintain { get; set; }
|
||||
public bool? Search { get; set; }
|
||||
}
|
||||
public ModeData Mode { get; set; }
|
||||
// Affiliate list.
|
||||
public List<AffiliateListData> Contacts { get; } = new List<AffiliateListData>();
|
||||
}
|
||||
@@ -192,10 +203,20 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
// Populate configuration data.
|
||||
PopulateContactConfig(model, responseData);
|
||||
|
||||
// View mode.
|
||||
responseData.Mode = new AjaxResponse_ContactList.ModeData();
|
||||
Model_Contact.ContactViewMode viewMode = model.GetFilterMode();
|
||||
if (viewMode == Model_Contact.ContactViewMode.Search)
|
||||
responseData.Mode.Search = true;
|
||||
else
|
||||
responseData.Mode.Maintain = true;
|
||||
|
||||
// Item filter.
|
||||
SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params();
|
||||
prmAffiliate.Search = model.Filter.Search;
|
||||
prmAffiliate.AffiliateType = model.GetFilterContactType();
|
||||
if (prmAffiliate.AffiliateType == Sbm.AffiliateType.Any && viewMode == Model_Contact.ContactViewMode.Search)
|
||||
prmAffiliate.AffiliateType = Sbm.AffiliateType.AnyContact;
|
||||
prmAffiliate.StatusCat = SbmAffiliate.StatusCat.NotDeleted;
|
||||
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Name));
|
||||
prmAffiliate.SortColumns.Add(AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.LastName));
|
||||
@@ -228,6 +249,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
columns.Remove(colAddress);
|
||||
if (responseData.Config.Column.Hide.Contains($"{Model_Contact.ItemField.Email}"))
|
||||
columns.Remove(colEmail);
|
||||
if (responseData.Config.Column.Hide.Contains($"{Model_Contact.ItemField.Associations}"))
|
||||
columns.Remove(colAssocCount);
|
||||
|
||||
// Sort Columns.
|
||||
if (!prmAffiliate.SortColumns.Any())
|
||||
@@ -243,9 +266,10 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
|
||||
AffiliateListData affiliateData = new AffiliateListData()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
Name = values.GetString(colName.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
};
|
||||
affiliateData.Field.Value.Add($"{Model_Contact.ItemField.Name}", values.GetString(colName.DataName));
|
||||
affiliateData.Field.Value.Add($"{Model_Contact.ItemField.Name}", affiliateData.Name);
|
||||
affiliateData.Field.Value.Add($"{Model_Contact.ItemField.Type}", Internals.AffiliateTypeCodes.GetDescForType(affiliateType));
|
||||
affiliateData.Field.Value.Add($"{Model_Contact.ItemField.Address}", StringUtil.NullOnBlank(AccountMgr.GetAffiliateDataValue(colAddress, values).AsString()));
|
||||
affiliateData.Field.Value.Add($"{Model_Contact.ItemField.Contact}", StringUtil.NullOnBlank(values.GetString(colContact.DataName)));
|
||||
|
||||
@@ -23,6 +23,7 @@ using System.Web;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Web.Portal.Helpers;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
@@ -79,7 +80,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
/// <para>- Open user session - store details against Sesion Data.</para>
|
||||
/// <para>- Set 'Keep logged in' cookie if required.</para>
|
||||
/// </summary>
|
||||
protected bool SignUserIn(ISbmUserContext_Core userContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
|
||||
protected bool SignUserIn(ISbmUserContext_Core userContext, String repositoryContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
|
||||
{
|
||||
// Validate Security Item and Affiliate, just in case - should have been done before arriving here!
|
||||
if (securityItemUser == null)
|
||||
@@ -150,7 +151,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
}
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(userContext.SessionContext, dbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
|
||||
OpenUserSession(userContext.SessionContext, repositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
|
||||
|
||||
// Configure security profile.
|
||||
SessionData_Portal.SecurityProfile_Core.RefreshProfile(SessionConsole, SecurityConsole, securityItemUser.Id, SecurityConsole.GetRegisteredRights());
|
||||
@@ -180,7 +181,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Start a new user session on sign-in.</summary>
|
||||
protected bool OpenUserSession(SbmSessionContext sessionContext, String dbIdentifier, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
protected bool OpenUserSession(SbmSessionContext sessionContext, String repositoryContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
{
|
||||
// Validate user properties.
|
||||
if (!SysId.IsValid(affiliateUser.Id)) return false;
|
||||
@@ -190,7 +191,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
CloseUserSession();
|
||||
|
||||
// Open session.
|
||||
return SetSessionData(new SbmSessionData_Portal(sessionContext, dbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation));
|
||||
return SetSessionData(new SbmSessionData_Portal(sessionContext, repositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation));
|
||||
}
|
||||
protected void CloseUserSession()
|
||||
{
|
||||
@@ -240,45 +241,48 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(keepLoggedInParams.DbIdentifier, keepLoggedInParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
List<SbmSessionContext> sessionContexts = SbmSessionContextHelper_Portal.GetSessionContextForRepositoryContextUserEmail(keepLoggedInParams.RepositoryContext, keepLoggedInParams.EmailAddress);
|
||||
if (sessionContexts.Any())
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
|
||||
foreach (SbmSessionContext sessionContext in sessionContexts)
|
||||
{
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(keepLoggedInParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
|
||||
using (SbmAssociation associationOrganisation = accountMgrForUser.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
|
||||
using (SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null))
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
|
||||
{
|
||||
if (securityItemUser != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(keepLoggedInParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(keepLoggedInParams.AffiliateIdUser))
|
||||
using (SbmAssociation associationOrganisation = accountMgrForUser.GetAssociationById(keepLoggedInParams.AssociationIdOrganisation))
|
||||
using (SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null))
|
||||
{
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
if (securityItemUser != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, keepLoggedInParams.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
|
||||
return true;
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, keepLoggedInParams.RepositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
|
||||
{
|
||||
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
|
||||
return true;
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
else SaLogger.Warn(logPrefix + "Affiliate is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Affiliate is not active." + logSuffix);
|
||||
else SaLogger.Warn(logPrefix + "Security Item and Affiliate are inconsistent. " + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item and Affiliate are inconsistent. " + logSuffix);
|
||||
else SaLogger.Warn(logPrefix + "Security Item or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but no matching session contexts found." + logSuffix);
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(encryptedParams))
|
||||
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
|
||||
@@ -322,7 +326,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep-logged-in cookie value.
|
||||
private static readonly String ParamName_KeepLoggedIn_DbIdentifier = "dbi";
|
||||
private static readonly String ParamName_KeepLoggedIn_RepositoryContext = "rct";
|
||||
private static readonly String ParamName_KeepLoggedIn_EmailAddress = "ema";
|
||||
private static readonly String ParamName_KeepLoggedIn_SecurityItemId = "sii";
|
||||
private static readonly String ParamName_KeepLoggedIn_AffiliateIdUser = "afiu";
|
||||
@@ -330,7 +334,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
private String GenerateKeepLoggedInCookieValue()
|
||||
{
|
||||
NameValueCollection keepLoggedInParams = new NameValueCollection();
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_DbIdentifier, SessionData_Portal.DbIdentifier);
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_RepositoryContext, SessionData_Portal.RepositoryContext);
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_EmailAddress, SessionData_Portal.User.EmailAddress);
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_SecurityItemId, SysId.ToString(SessionData_Portal.User.SecurityItemId));
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AffiliateIdUser, SysId.ToString(SessionData_Portal.User.AffiliateId));
|
||||
@@ -341,7 +345,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
//-------------------------------------------------------------------
|
||||
public class KeepLoggedInParams
|
||||
{
|
||||
public String DbIdentifier { get; set; }
|
||||
public String RepositoryContext { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public SysId SecurityItemId { get; set; }
|
||||
public SysId AffiliateIdUser { get; set; }
|
||||
@@ -350,8 +354,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (!StringUtil.IsBlank(DbIdentifier))
|
||||
values.Add("DbIdentifier: " + DbIdentifier);
|
||||
if (!StringUtil.IsBlank(RepositoryContext))
|
||||
values.Add("RepositoryContext: " + RepositoryContext);
|
||||
if (!StringUtil.IsBlank(EmailAddress))
|
||||
values.Add("EmailAddress: " + EmailAddress);
|
||||
if (SysId.IsValid(SecurityItemId))
|
||||
@@ -366,7 +370,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
public bool IsValid()
|
||||
{
|
||||
return
|
||||
!StringUtil.IsBlank(DbIdentifier) &&
|
||||
!StringUtil.IsBlank(RepositoryContext) &&
|
||||
!StringUtil.IsBlank(EmailAddress) &&
|
||||
SysId.IsValid(SecurityItemId) &&
|
||||
SysId.IsValid(AffiliateIdUser) &&
|
||||
@@ -379,7 +383,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
|
||||
keepLoggedInParams.DbIdentifier = linkParams.Get(ParamName_KeepLoggedIn_DbIdentifier);
|
||||
keepLoggedInParams.RepositoryContext = linkParams.Get(ParamName_KeepLoggedIn_RepositoryContext);
|
||||
keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress);
|
||||
keepLoggedInParams.SecurityItemId = linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId).ToSysId();
|
||||
keepLoggedInParams.AffiliateIdUser = linkParams.Get(ParamName_KeepLoggedIn_AffiliateIdUser).ToSysId();
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
if (!(SessionData_Portal?.ValidUser ?? false))
|
||||
{
|
||||
// Instance Repository configured on Control database.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Portal.GetControlSessionContext(model.DbIdentifier);
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Portal.GetControlSessionContextByRepositoryContext(model.RepositoryContext);
|
||||
String errorMessage = "";
|
||||
|
||||
if (!OpenUserSession(model, sessionContext, ref errorMessage))
|
||||
@@ -79,15 +79,13 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
|
||||
if (!(SessionData_Portal?.ValidUser ?? false))
|
||||
{
|
||||
// AppSettings configured session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(model.DbIdentifier, model.EmailAddress);
|
||||
if (sessionContextIdxs.IsEmpty())
|
||||
// Session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<SbmSessionContext> sessionContexts = SbmSessionContextHelper_Portal.GetSessionContextForRepositoryContextUserEmail(model.RepositoryContext, model.EmailAddress);
|
||||
if (sessionContexts.IsEmpty())
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
foreach (SbmSessionContext sessionContext in sessionContexts)
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
String errorMessage = "";
|
||||
|
||||
if (OpenUserSession(model, sessionContext, ref errorMessage)) break;
|
||||
|
||||
if (!StringUtil.IsBlank(errorMessage))
|
||||
@@ -99,7 +97,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
|
||||
if (!(SessionData_Portal?.ValidUser ?? false))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Suitable database. Context: {model.DbIdentifier}. Email: {model.EmailAddress}.");
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Suitable database. Context: {model.RepositoryContext}. Email: {model.EmailAddress}.");
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
}
|
||||
|
||||
@@ -177,7 +175,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
}
|
||||
|
||||
// Initialise user session.
|
||||
if (SignUserIn(userContext, model.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
if (SignUserIn(userContext, model.RepositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -409,42 +407,41 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
SbmAffiliate affiliateUser = null;
|
||||
bool validRequestPasswordParams = false;
|
||||
bool validSessionRequired = true;
|
||||
RequestPasswordParams requestPasswordParams = ExtractRequestPasswordLinkParams(model.rpe);
|
||||
if (requestPasswordParams.IsValid())
|
||||
RequestPasswordParams storePasswordParams = ExtractRequestPasswordLinkParams(model.rpe);
|
||||
if (storePasswordParams.IsValid())
|
||||
{
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts for databases with specified Id that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(requestPasswordParams.DbIdentifier, requestPasswordParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
List<SbmSessionContext> sessionContexts = SbmSessionContextHelper_Portal.GetSessionContextForRepositoryContextUserEmail(storePasswordParams.RepositoryContext, storePasswordParams.EmailAddress);
|
||||
foreach (SbmSessionContext sessionContext in sessionContexts)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
sessionContextForUser = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
userContextForUser = new SbmUserContext_Web(sessionContextForUser);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContextForUser))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContextForUser))
|
||||
{
|
||||
// Retrieve user details and validate email address.
|
||||
securityItemUser = securityConsoleForUser.GetSecurityItemById(SaSecurity.ItemType.User, requestPasswordParams.SecurityItemId);
|
||||
affiliateUser = accountMgrForUser.GetAffiliateById(requestPasswordParams.AffiliateId);
|
||||
if (requestPasswordParams.IsValid(securityItemUser, affiliateUser))
|
||||
securityItemUser = securityConsoleForUser.GetSecurityItemById(SaSecurity.ItemType.User, storePasswordParams.SecurityItemId);
|
||||
affiliateUser = accountMgrForUser.GetAffiliateById(storePasswordParams.AffiliateId);
|
||||
if (storePasswordParams.IsValid(securityItemUser, affiliateUser))
|
||||
{
|
||||
sessionContextForUser = sessionContext;
|
||||
userContextForUser = userContext;
|
||||
validRequestPasswordParams = true;
|
||||
validSessionRequired = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} 'Request Password' parameters supplied but invalid. Email: {requestPasswordParams.EmailAddress}. SecurityItemId: {SysId.ToString(requestPasswordParams.SecurityItemId)}. AffiliateId: {SysId.ToString(requestPasswordParams.AffiliateId)}.");
|
||||
SaLogger.Warn($"{SysUtil.Fn} 'Request Password' parameters supplied but invalid. Email: {storePasswordParams.EmailAddress}. SecurityItemId: {SysId.ToString(storePasswordParams.SecurityItemId)}. AffiliateId: {SysId.ToString(storePasswordParams.AffiliateId)}.");
|
||||
if (securityItemUser != null) securityItemUser.Dispose(); securityItemUser = null;
|
||||
if (affiliateUser != null) affiliateUser.Dispose(); affiliateUser = null;
|
||||
sessionContextForUser = null;
|
||||
userContextForUser = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User must have a valid session if security item and affiliate not idenfied via the 'Request Password' paramaters.
|
||||
// User must have a valid session if security item and affiliate not idenfied via the 'Request Password' parameters.
|
||||
if (validSessionRequired && (securityItemUser == null || affiliateUser == null) && !ValidUserSession)
|
||||
return Json(responseData.SetSessionExpired(messageTitle, Localiser["security.msg.warn.sessionExpired"]));
|
||||
|
||||
@@ -541,10 +538,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
if (responseData.HasControlErrors()) return Json(responseData);
|
||||
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(model.DbIdentifier, model.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
List<SbmSessionContext> sessionContexts = SbmSessionContextHelper_Portal.GetSessionContextForRepositoryContextUserEmail(model.RepositoryContext, model.EmailAddress);
|
||||
foreach (SbmSessionContext sessionContext in sessionContexts)
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
|
||||
// Get user security item and affiliate.
|
||||
@@ -600,14 +596,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
emailConsole.ReplaceDynamicEmailBodyTags(emailData, null);
|
||||
|
||||
// Replace dynamic tag for link back to change password page.
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(SessionData_Portal.DbIdentifier, securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(SessionData_Portal.RepositoryContext, securityItemUser.Id, affiliateUser.Id, securityItemUser.EmailAddress, ""));
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes().ToString());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Password request link.
|
||||
private static String ParamName_RequestPasswordEncrypted { get; } = "rpe";
|
||||
private static String ParamName_DbIdentifier { get; } = "dbi";
|
||||
private static String ParamName_RepositoryContext { get; } = "rct";
|
||||
private static String ParamName_EmailAddress { get; } = "ema";
|
||||
private static String ParamName_SecurityItemId { get; } = "sei";
|
||||
private static String ParamName_AffiliateId { get; } = "afi";
|
||||
@@ -615,10 +611,10 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
private static String ParamName_Token { get; } = "tok";
|
||||
// Portal Request Password encryption parameters (key & IV) are defined in the base Controller
|
||||
// so that they can be shared with the Console application.
|
||||
private String GenerateRequestPasswordLink(String dbIdentifier, SysId securityItemId, SysId affiliateId, String emailAddress, String requestPasswordToken)
|
||||
private String GenerateRequestPasswordLink(String repositoryContext, SysId securityItemId, SysId affiliateId, String emailAddress, String requestPasswordToken)
|
||||
{
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
parameters.Add(ParamName_DbIdentifier, dbIdentifier);
|
||||
parameters.Add(ParamName_RepositoryContext, repositoryContext);
|
||||
parameters.Add(ParamName_EmailAddress, emailAddress);
|
||||
parameters.Add(ParamName_SecurityItemId, SysId.ToString(securityItemId));
|
||||
parameters.Add(ParamName_AffiliateId, SysId.ToString(affiliateId));
|
||||
@@ -638,7 +634,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
}
|
||||
private class RequestPasswordParams
|
||||
{
|
||||
public String DbIdentifier { get; set; }
|
||||
public String RepositoryContext { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public SysId SecurityItemId { get; set; }
|
||||
public SysId AffiliateId { get; set; }
|
||||
@@ -648,8 +644,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (!StringUtil.IsBlank(DbIdentifier))
|
||||
values.Add($"DbIdentifier: {DbIdentifier}");
|
||||
if (!StringUtil.IsBlank(RepositoryContext))
|
||||
values.Add($"RepositoryContext: {RepositoryContext}");
|
||||
if (!StringUtil.IsBlank(EmailAddress))
|
||||
values.Add($"Email: {EmailAddress}");
|
||||
if (SysId.IsValid(SecurityItemId))
|
||||
@@ -666,7 +662,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
public bool IsValid()
|
||||
{
|
||||
return
|
||||
!StringUtil.IsBlank(DbIdentifier) &&
|
||||
!StringUtil.IsBlank(RepositoryContext) &&
|
||||
StringUtil.IsBlank(EmailAddress) &&
|
||||
SysId.IsValid(SecurityItemId) &&
|
||||
SysId.IsValid(AffiliateId) &&
|
||||
@@ -690,7 +686,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword_Portal, Base64Key_RequestPassword_Portal);
|
||||
requestPasswordParams.DbIdentifier = linkParams.Get(ParamName_DbIdentifier);
|
||||
requestPasswordParams.RepositoryContext = linkParams.Get(ParamName_RepositoryContext);
|
||||
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
|
||||
requestPasswordParams.SecurityItemId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_SecurityItemId)));
|
||||
requestPasswordParams.AffiliateId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_AffiliateId)));
|
||||
|
||||
@@ -16,6 +16,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sarand.BusinessMgr.Web.Portal.Helpers;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
{
|
||||
@@ -70,32 +71,31 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
|
||||
// Check for encrypted parameters from 'Request Password' email link.
|
||||
// NB Only allowed as a 'GET' request.
|
||||
String encryptedParams = Request.Query[ParamName_RequestPasswordEncrypted];
|
||||
RequestPasswordParams requestPasswordParams = ExtractRequestPasswordLinkParams(encryptedParams);
|
||||
if (requestPasswordParams.IsValid())
|
||||
RequestPasswordParams changePasswordParams = ExtractRequestPasswordLinkParams(encryptedParams);
|
||||
if (changePasswordParams.IsValid())
|
||||
{
|
||||
String logPrefix = $"{SysUtil.Fn} 'Request Password' parameters supplied but ";
|
||||
String logSuffix = requestPasswordParams.GetValidParams().Concat("", " ", ".");
|
||||
String logSuffix = changePasswordParams.GetValidParams().Concat("", " ", ".");
|
||||
// User may be defined on any one of the BusinessMgr databases - need to find out which.
|
||||
// Identify session contexts with a BusMgr database that hosts the specified email address.
|
||||
List<ushort> sessionContextIdxs = SbmSessionContextHelper_Web.GetSessionContextIdxsForContextUserEmail(requestPasswordParams.DbIdentifier, requestPasswordParams.EmailAddress);
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
List<SbmSessionContext> sessionContexts = SbmSessionContextHelper_Portal.GetSessionContextForRepositoryContextUserEmail(changePasswordParams.RepositoryContext, changePasswordParams.EmailAddress);
|
||||
foreach (SbmSessionContext sessionContext in sessionContexts)
|
||||
{
|
||||
// Consoles and Managers must be associated with the specific context.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
|
||||
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
|
||||
{
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(requestPasswordParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(requestPasswordParams.AffiliateId))
|
||||
using (SaSecurityItem securityItemUser = securityConsoleForUser.GetUserByEmail(changePasswordParams.EmailAddress))
|
||||
using (SbmAffiliate affiliateUser = accountMgrForUser.GetAffiliateById(changePasswordParams.AffiliateId))
|
||||
{
|
||||
if (securityItemUser != null && affiliateUser != null)
|
||||
{
|
||||
if (securityItemUser.Id.Equals(requestPasswordParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
if (securityItemUser.Id.Equals(changePasswordParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
if (requestPasswordParams.IsValid(securityItemUser, affiliateUser))
|
||||
if (changePasswordParams.IsValid(securityItemUser, affiliateUser))
|
||||
{
|
||||
model.rpe = encryptedParams;
|
||||
validSessionRequired = false;
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Security;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Helpers
|
||||
{
|
||||
@@ -12,12 +19,104 @@ namespace Sarand.BusinessMgr.Web.Portal.Helpers
|
||||
public class SbmSessionContextHelper_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Control Session Contexts.
|
||||
// Control Session Context.
|
||||
//-------------------------------------------------------------------
|
||||
public static SbmSessionContext GetControlSessionContext(String dbIdentifier)
|
||||
public static SbmSessionContext GetControlSessionContextByRepositoryContext(String repositoryContext)
|
||||
{
|
||||
SbmApplication_Portal app = SbmApplication_Portal.Instance;
|
||||
return app?.GetControlSessionContext(dbIdentifier);
|
||||
return app?.GetControlSessionContextByRepositoryContext(repositoryContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session Contexts.
|
||||
//-------------------------------------------------------------------
|
||||
public static List<SbmSessionContext> GetSessionContextsByRepositoryContext(String repositoryContext)
|
||||
{
|
||||
Dictionary<int, SbmSessionContext> sessionContexts = new Dictionary<int, SbmSessionContext>();
|
||||
SbmApplication_Portal app = SbmApplication_Portal.Instance;
|
||||
|
||||
// Control session context.
|
||||
// - Will be populated if not previously referenced by Repository Context.
|
||||
SbmSessionContext controlSessionContext = app.GetControlSessionContextByRepositoryContext(repositoryContext);
|
||||
if (controlSessionContext != null)
|
||||
sessionContexts[controlSessionContext.Index] = controlSessionContext;
|
||||
|
||||
// Core Session Contexts.
|
||||
foreach (ushort sessionContextIdx in app.GetSessionContextIdxs())
|
||||
{
|
||||
// Retrieve the session context.
|
||||
SbmSessionContext sessionContext = app.GetSessionContextByIndex(sessionContextIdx);
|
||||
if (sessionContext == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve SessionContext for idx: " + sessionContextIdx);
|
||||
continue;
|
||||
}
|
||||
// Verify Repository Context.
|
||||
HashSet<string> repositoryContexts = app.GetRepositoryContexts(sessionContext);
|
||||
if (!repositoryContexts.ContainsCI(repositoryContext))
|
||||
continue;
|
||||
sessionContexts[sessionContext.Index] = sessionContext;
|
||||
}
|
||||
return new List<SbmSessionContext>(sessionContexts.Values);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session Contexts for Repository Context and User Email Address.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Identify the session context(s) that corresponds with the BusinessMgr
|
||||
/// repository by context for the specified user by email address.
|
||||
/// </summary>
|
||||
public static List<SbmSessionContext> GetSessionContextForRepositoryContextUserEmail(String repositoryContext, String emailAddress)
|
||||
{
|
||||
Dictionary<int, SbmSessionContext> sessionContexts = new Dictionary<int, SbmSessionContext>();
|
||||
String alias_SecurityItem = "SecItm";
|
||||
String alias_Affiliate = "Affil";
|
||||
if (StringUtil.IsEmpty(emailAddress)) return new List<SbmSessionContext>(sessionContexts.Values);
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Searching for database. Identifier: {repositoryContext}. Email address: {emailAddress}");
|
||||
|
||||
// Get the session context indices defined by the application.
|
||||
SbmApplication_Web app = SbmGlobals_Web.Application;
|
||||
foreach (SbmSessionContext sessionContext in GetSessionContextsByRepositoryContext(repositoryContext))
|
||||
{
|
||||
// Verify Repository Context.
|
||||
HashSet<string> repositoryContexts = app.GetRepositoryContexts(sessionContext);
|
||||
if (!repositoryContexts.ContainsCI(repositoryContext))
|
||||
continue;
|
||||
|
||||
// Retrieve database.
|
||||
ISacsDatabase db = app.GetBusMgrDatabase(sessionContext);
|
||||
if (db == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Database for idx: " + sessionContext.Index);
|
||||
continue;
|
||||
}
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Database: " + db.DatabaseName);
|
||||
|
||||
// Query to check for Security Item matching the email with associated Affiliate.
|
||||
// NB This is done independently for each database in case there are different
|
||||
// DBMSs involved with different value formatting or syntax rules.
|
||||
DbQuery qry = new DbQuery(db.DbmsType);
|
||||
qry.Tables.Add(SaSecurityDbDfn.GetTableName(SaSecurityDbDfn.TableIdx.SaSecItem), alias_SecurityItem);
|
||||
qry.Columns.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_Id, alias_SecurityItem));
|
||||
qry.Columns.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_Id, alias_SecurityItem));
|
||||
qry.Filters.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress, alias_SecurityItem) + "='" + DbQuery.FormatForCondition(emailAddress) + "'");
|
||||
// Join to the Affiliate table.
|
||||
DbQueryJoin joinAffiliate = new DbQueryJoin(DbJoinType.FullOuter);
|
||||
joinAffiliate.Table = new StringPair(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Affiliate), alias_Affiliate);
|
||||
joinAffiliate.Filters.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_UserId, alias_Affiliate) + "=" + SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_Id, alias_SecurityItem));
|
||||
|
||||
// Execute query.
|
||||
using (DbResultSet resultSet = DbResultSet_DataReader.ExecuteQuery(db, qry.BuildQuery()))
|
||||
{
|
||||
if (resultSet != null && resultSet.NextRecord())
|
||||
{
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Database contains email: " + db.DatabaseName);
|
||||
sessionContexts[sessionContext.Index] = sessionContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new List<SbmSessionContext>(sessionContexts.Values); ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Accounts.Sage.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
@@ -81,13 +82,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
Status,
|
||||
CreatedOn,
|
||||
UpdatedOn,
|
||||
Actions,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier used by form fields to show control specific messages generated by model validation etc.
|
||||
/// <para>- Both page and model should use this method to consistently generate the field name.</para>
|
||||
/// </summary>
|
||||
public String GetFieldName(ItemField field)
|
||||
public static String GetFieldName(ItemField field)
|
||||
{
|
||||
return $"{FieldNamePrefix}{field}";
|
||||
}
|
||||
@@ -95,6 +97,19 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
// List configuration.
|
||||
public class ListConfigData
|
||||
{
|
||||
// Actions.
|
||||
public class ActionData
|
||||
{
|
||||
public class AllowData
|
||||
{
|
||||
public bool? CreateCust { get; set; }
|
||||
public bool? UpdateCust { get; set; }
|
||||
public bool? CreateSupp { get; set; }
|
||||
public bool? UpdateSupp { get; set; }
|
||||
}
|
||||
public AllowData Allow { get; } = new AllowData();
|
||||
}
|
||||
public ActionData Action { get; } = new ActionData();
|
||||
// List columns.
|
||||
public class ColumnData
|
||||
{
|
||||
@@ -120,15 +135,29 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
}
|
||||
public void PopulateListConfig(ListConfigData config)
|
||||
{
|
||||
bool modeIsRelationships = Mode == AssociationPageMode.Relationships;
|
||||
bool modeIsMaintain = Mode == AssociationPageMode.Maintain;
|
||||
Sbm.AssociationType associationType = GetAssociationType();
|
||||
AssociationViewMode pageMode = GetFilterMode();
|
||||
bool modeIsRelationships = pageMode == AssociationViewMode.Relationships;
|
||||
bool modeIsMaintain = pageMode == AssociationViewMode.Maintain;
|
||||
Sbm.AssociationType associationType = GetFilterAssociationType();
|
||||
bool typeIsCustomer = associationType == Sbm.AssociationType.Customer;
|
||||
bool typeIsSupplier = associationType == Sbm.AssociationType.Supplier;
|
||||
bool typeIsMember = associationType == Sbm.AssociationType.Member;
|
||||
|
||||
bool userCanViewFinancials = SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials();
|
||||
|
||||
// Actions.
|
||||
|
||||
if (typeIsCustomer)
|
||||
{
|
||||
config.Action.Allow.CreateCust = true;
|
||||
config.Action.Allow.UpdateCust = true;
|
||||
}
|
||||
if (typeIsSupplier)
|
||||
{
|
||||
config.Action.Allow.CreateSupp = true;
|
||||
config.Action.Allow.UpdateSupp = true;
|
||||
}
|
||||
|
||||
// List columns.
|
||||
|
||||
if (associationType > 0)
|
||||
@@ -192,6 +221,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
if (!typeIsMember)
|
||||
config.Column.Hide.Add($"{ItemField.Terminated}");
|
||||
|
||||
// Actions.
|
||||
if (!modeIsMaintain)
|
||||
config.Column.Hide.Add($"{ItemField.Actions}");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -220,7 +252,19 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
public class ItemConfigData
|
||||
{
|
||||
// Update dialog title.
|
||||
public String Title{ get; set; }
|
||||
public String Title { get; set; }
|
||||
// Pre-select Association type.
|
||||
public class TypeData
|
||||
{
|
||||
public TypeData(string code, String desc)
|
||||
{
|
||||
Code = code;
|
||||
Desc = desc;
|
||||
}
|
||||
public String Code { get; set; }
|
||||
public String Desc { get; set; }
|
||||
}
|
||||
public TypeData Type { get; set; }
|
||||
// Field name prefix.
|
||||
public String Prefix { get; } = Model_Association.FieldNamePrefix;
|
||||
// Control flags.
|
||||
@@ -282,6 +326,15 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
isSupplier ? Localiser["caption.supplier.update"] :
|
||||
Localiser["caption.association.update"];
|
||||
|
||||
// Pre-selected Association type.
|
||||
List<TypeCodeDesc> associationTypes = Internals.AssociationTypeCodes;
|
||||
if (isCustomer)
|
||||
config.Type = new ItemConfigData.TypeData(associationTypes.GetCodeForType(Sbm.AssociationType.Customer), Localiser.GetAssociationTypeCaption(Sbm.AssociationType.Customer));
|
||||
else if (isSupplier)
|
||||
config.Type = new ItemConfigData.TypeData(associationTypes.GetCodeForType(Sbm.AssociationType.Supplier), Localiser.GetAssociationTypeCaption(Sbm.AssociationType.Supplier));
|
||||
else if (isMember)
|
||||
config.Type = new ItemConfigData.TypeData(associationTypes.GetCodeForType(Sbm.AssociationType.Member), Localiser.GetAssociationTypeCaption(Sbm.AssociationType.Member));
|
||||
|
||||
// Allow actions.
|
||||
if (SessionData_Portal.GetOwnerOption_AllowOption(Sbm.OrgOption_AllowOption.UpdateAssociationCode))
|
||||
config.Allow.UpdateCode = true;
|
||||
@@ -345,7 +398,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
// Credit limit.
|
||||
if (!canViewFinancials || !managedByAccounts)
|
||||
config.Field.Hide.Add($"{ItemField.CreditLimit}");
|
||||
else if (managedByAccounts||!canUpdateFinancials)
|
||||
else if (managedByAccounts || !canUpdateFinancials)
|
||||
config.Field.Readonly.Add($"{ItemField.CreditLimit}");
|
||||
|
||||
// Account balance.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
@@ -24,7 +25,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public enum AssociationPageMode
|
||||
public enum AssociationViewMode
|
||||
{
|
||||
Search, Maintain, Relationships, PriceSet,
|
||||
}
|
||||
@@ -38,24 +39,29 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public AssociationPageMode Mode { get; set; } = AssociationPageMode.Maintain;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
// Filter.
|
||||
public class FilterData
|
||||
{
|
||||
public String Mode { get; set; }
|
||||
public string OwnerId { get; set; }
|
||||
public string TargetId { get; set; }
|
||||
public string AssociationType { get; set; }
|
||||
public string Search { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public AssociationViewMode GetFilterMode()
|
||||
{
|
||||
return EnumUtil.ParseEnum(Filter.Mode, AssociationViewMode.Maintain);
|
||||
}
|
||||
public Sbm.AssociationType GetFilterAssociationType()
|
||||
{
|
||||
return (Sbm.AssociationType)Internals.AssociationTypeCodes.GetTypeForCode(Filter.AssociationType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Association properties.
|
||||
// Form.
|
||||
public class AssociationData
|
||||
{
|
||||
public string Exists { get; set; }
|
||||
|
||||
@@ -69,13 +69,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
Status,
|
||||
CreatedOn,
|
||||
UpdatedOn,
|
||||
Actions,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier used by form fields to show control specific messages generated by model validation etc.
|
||||
/// <para>- Both page and model should use this method to consistently generate the field name.</para>
|
||||
/// </summary>
|
||||
public String GetFieldName(ItemField field)
|
||||
public static String GetFieldName(ItemField field)
|
||||
{
|
||||
return $"{FieldNamePrefix}{field}";
|
||||
}
|
||||
@@ -113,6 +114,11 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
/// </summary>
|
||||
public void PopulateListConfig(ListConfigData config)
|
||||
{
|
||||
|
||||
ContactViewMode viewMode = GetFilterMode();
|
||||
bool modeIsMaintain= viewMode == ContactViewMode.Maintain;
|
||||
bool modeIsSearch = viewMode == ContactViewMode.Search;
|
||||
|
||||
Sbm.AffiliateType affiliateType = GetFilterContactType();
|
||||
bool contactGroupsOnly = affiliateType == Sbm.AffiliateType.ContactGroup;
|
||||
|
||||
@@ -176,6 +182,18 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
config.Column.Label.Add($"{ItemField.Id}", Localiser["label.id"]);
|
||||
else
|
||||
config.Column.Hide.Add($"{ItemField.Id}");
|
||||
|
||||
// Associations.
|
||||
if (modeIsSearch)
|
||||
config.Column.Hide.Add($"{ItemField.Associations}");
|
||||
|
||||
// Status.
|
||||
if (modeIsSearch)
|
||||
config.Column.Hide.Add($"{ItemField.Status}");
|
||||
|
||||
// Actions.
|
||||
if (!modeIsMaintain)
|
||||
config.Column.Hide.Add($"{ItemField.Actions}");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -23,6 +23,13 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
/// </summary>
|
||||
public partial class Model_Contact : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public enum ContactViewMode
|
||||
{
|
||||
Search, Maintain,
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Contact(SbmLocaliser localiser) :
|
||||
@@ -34,11 +41,16 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String Mode { get; set; }
|
||||
public string ContactType { get; set; }
|
||||
public string Search { get; set; }
|
||||
public string Email { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public ContactViewMode GetFilterMode()
|
||||
{
|
||||
return EnumUtil.ParseEnum(Filter.Mode, ContactViewMode.Maintain);
|
||||
}
|
||||
public Sbm.AffiliateType GetFilterContactType()
|
||||
{
|
||||
Sbm.AffiliateType affiliateType = (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.ContactType);
|
||||
@@ -47,15 +59,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
return affiliateType;
|
||||
}
|
||||
|
||||
/// <summary>List of Affiliate Types for filter dropdown.</summary>
|
||||
public IEnumerable<SelectListItem> GetAffiliateTypeCodesForFilterSelect()
|
||||
{
|
||||
List<TypeCodeDesc> affiliateTypes = GetCodesOfType(Sbm.SystemCode.AffiliateType);
|
||||
if (!affiliateTypes.Any(item => item.Type == (int)Sbm.AffiliateType.AnyOrganisation))
|
||||
affiliateTypes.Insert(0, new TypeCodeDesc((int)Sbm.AffiliateType.AnyOrganisation, ((short)Sbm.AffiliateType.AnyOrganisation).ToString(), Localiser["label.organisation"]));
|
||||
return new SelectList(affiliateTypes, "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Contact properties.
|
||||
public class ContactData
|
||||
@@ -244,6 +247,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
if (Contact.CompanyNo != null)
|
||||
{
|
||||
String controlName = GetFieldName(ItemField.CompanyNo);
|
||||
Contact.CompanyNo = Contact.CompanyNo.ToUpper();
|
||||
responseData.SetControlValue(controlName, Contact.CompanyNo);
|
||||
if (StringUtil.GetLength(Contact.CompanyNo) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)]);
|
||||
@@ -253,6 +257,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
if (Contact.VatReg != null)
|
||||
{
|
||||
String controlName = GetFieldName(ItemField.VatReg);
|
||||
Contact.VatReg = Contact.VatReg.ToUpper();
|
||||
responseData.SetControlValue(controlName, Contact.VatReg);
|
||||
if (StringUtil.GetLength(Contact.VatReg) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)]);
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
//-------------------------------------------------------------------
|
||||
// Form properties.
|
||||
/// <summary>Database config identifier.</summary>
|
||||
public String DbIdentifier { get; set; }
|
||||
public String RepositoryContext { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public String PasswordCurrent { get; set; }
|
||||
public String Password { get; set; }
|
||||
@@ -48,9 +48,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
{
|
||||
// Database context.
|
||||
String controlName = nameof(DbIdentifier);
|
||||
responseData.SetControlValue(controlName, DbIdentifier);
|
||||
if (StringUtil.IsEmpty(DbIdentifier))
|
||||
String controlName = nameof(RepositoryContext);
|
||||
responseData.SetControlValue(controlName, RepositoryContext);
|
||||
if (StringUtil.IsEmpty(RepositoryContext))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
{
|
||||
// Database context.
|
||||
String controlName = nameof(DbIdentifier);
|
||||
responseData.SetControlValue(controlName, DbIdentifier);
|
||||
if (StringUtil.IsEmpty(DbIdentifier))
|
||||
String controlName = nameof(RepositoryContext);
|
||||
responseData.SetControlValue(controlName, RepositoryContext);
|
||||
if (StringUtil.IsEmpty(RepositoryContext))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -26,6 +29,37 @@ namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
public override ISbmUserContext_Core UserContext_Core { get { return SessionData_Portal; } }
|
||||
public String OrganisationName { get { return SessionData_Portal?.Organisation?.DisplayName ?? ""; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// View reference data.
|
||||
|
||||
/// <summary>
|
||||
/// List of Affiliate Types for filter dropdown.
|
||||
/// <para>- Contact model cannot define this as contact list/dialog may be included in other views with their own model, eg. Association page.</para>
|
||||
/// </summary>
|
||||
public IEnumerable<SelectListItem> GetAffiliateTypeCodesForFilterSelect()
|
||||
{
|
||||
List<TypeCodeDesc> affiliateTypes = GetCodesOfType(Sbm.SystemCode.AffiliateType);
|
||||
if (!affiliateTypes.Any(item => item.Type == (int)Sbm.AffiliateType.AnyOrganisation))
|
||||
affiliateTypes.Insert(0, new TypeCodeDesc((int)Sbm.AffiliateType.AnyOrganisation, ((short)Sbm.AffiliateType.AnyOrganisation).ToString(), Localiser["label.organisation"]));
|
||||
return new SelectList(affiliateTypes, "Code", "Desc");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of Association Types for filter dropdown.
|
||||
/// <para>- Association model cannot define this as association list/dialog may be included in other views with their own model, eg. Commodity page.</para>
|
||||
/// </summary>
|
||||
public IEnumerable<SelectListItem> GetAssociationTypeCodesForFilterSelect()
|
||||
{
|
||||
List<TypeCodeDesc> associationTypes = GetCodesOfType(Sbm.SystemCode.AssociationType);
|
||||
associationTypes.RemoveAll(item => item.Type == (short)Sbm.AssociationType.Internal);
|
||||
foreach (Sbm.AssociationType associationType in EnumUtil.GetValues<Sbm.AssociationType>())
|
||||
{
|
||||
if (!SessionConsole.AllowAssociationType(associationType))
|
||||
associationTypes.RemoveAll(item => item.Type == (short)associationType);
|
||||
}
|
||||
return new SelectList(associationTypes, "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Update="Views\Association\Panel-AssociationList.cshtml">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -121,13 +121,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control row">
|
||||
<div class="sbm-control row">
|
||||
<div class="col">
|
||||
@Html.HiddenFor(model => model.Asset.CategoryId, new { @id = "", @class = "AssetCategoryId" })
|
||||
<input type="text" class="AssetCategory sbm-input" readonly="readonly" />
|
||||
</div>
|
||||
<div class="fixed">
|
||||
<div class="sbc-action AssetCategorySearch"><img src="~/img/action/search24.png" alt="" title="" /></div>
|
||||
<div class="sbm-action AssetCategorySearch"><img src="~/img/action/search24.png" alt="" title="" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
|
||||
@@ -1,120 +1,8 @@
|
||||
@model Model_Association
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Associations - Index */
|
||||
/* Association page */
|
||||
ViewData["Title"] = "Associations";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-assoc.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Associations fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.createCust= '@(Localiser.GetJavascriptText("caption.customer.create"))';
|
||||
sbm.lbl.createSupp= '@(Localiser.GetJavascriptText("caption.supplier.create"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@* Header - Page caption, paging controls, actions. *@
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.associations"]</div></div>
|
||||
<div class="col right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association Category *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
@Html.DropDownListFor(model => model.Filter.AssociationType, Model.GetAssociationTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterAssociationType sbm-select" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@* Item list *@
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Type) width10pc pl-1">@Localiser["label.type"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Code) width10pc pl-1">@Localiser["label.code"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Target) width25pc">@Localiser["label.name"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Address) width25pc d-none d-md-table-cell">@Localiser["label.address"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Association.ItemField.Status) width10pc center">@Localiser["label.status"]</th>
|
||||
<th class="right" style="width:2%;"></th>
|
||||
</tr>
|
||||
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu AssociationList">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
@* Association row template - table is ignored. *@
|
||||
<table>
|
||||
<tr class="sbm-row-item Association">
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Type) pl-1"></td>
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Code) pl-1"></td>
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Target)"></td>
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Address) d-none d-md-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Notes) d-none d-md-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Association.ItemField.Status) center"></td>
|
||||
<td>
|
||||
<div class="right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Association">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<partial name="Panel-AssociationDialog.cshtml" />
|
||||
<partial name="Panel-AssociationMaintain.cshtml" />
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
@model Model_Association
|
||||
@* View is decoupled from Association model as it may be included in other views, eg. Contacts, Commodities etc. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Associations - Association dialog panel */
|
||||
/* Association dialog panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Association/Panel-AssociationDialog")) return;
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -11,35 +14,63 @@
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociationId", @class = "sbm-form" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Association.Id, new { @class = "AssociationId" })
|
||||
<input type="hidden" name="Association.Id" class="AssociationId" />
|
||||
}
|
||||
|
||||
<div id="dlgAssociation" class="sbm-dialog" title="">
|
||||
<div class="spacer2"></div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssociation", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Association.Id, new { @id = "", @class = "AssociationId sbm-input" })
|
||||
@Html.HiddenFor(model => model.Association.Exists, new { @id = "", @class = "AssociationExists sbm-input" })
|
||||
<input type="hidden" name="Association.Id" id="" class="AssociationId sbm-input" />
|
||||
<input type="hidden" name="Association.Exists" id="" class="AssociationExists sbm-input" />
|
||||
|
||||
@* Association Type *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Type)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssociationType"><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Association Type *@
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Type)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssociationType"><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
<select name="Association.Type" id="cbAssociationType" class="AssociationType sbm-select"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.DropDownListFor(model => model.Association.Type, Model.GetAssociationTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbAssociationType", @class = "AssociationType sbm-select sbm-auto-val" })
|
||||
|
||||
</div>
|
||||
<div class="col-sm-1"></div>
|
||||
<div class="col-sm">
|
||||
|
||||
@* Association status *@
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Status)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssociationStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
<select id="cbAssociationStatus" class="AssociationStatus sbm-select sbm-auto-val" name="Association.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Owner contact *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Owner)">
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Owner)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -47,13 +78,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbc-control row">
|
||||
<div class="sbm-control row">
|
||||
<div class="col">
|
||||
@Html.HiddenFor(model => model.Association.ContactIdOwner, new { @id = "", @class = "AssociationOwnerId sbm-input" })
|
||||
<input type="hidden" name="Association.ContactIdOwner" id="" class=" AssociationOwnerId sbm-input" />
|
||||
<input type="text" id="ifAssociationOwner" class="AssociationOwner sbm-input sbm-auto-val" readonly="readonly" />
|
||||
</div>
|
||||
<div class="fixed">
|
||||
@* <div class="sbc-action AssetOwnerSearch"><img src="~/img/action/search24.png" alt="" title="" /></div> *@
|
||||
@* <div class="sbm-action AssociationOwnerSearch"><img src="~/img/action/search24.png" alt="" title="" /></div> *@
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
@@ -62,7 +93,7 @@
|
||||
</div>
|
||||
|
||||
@* Target contact *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Target)">
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Target)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -70,13 +101,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbc-control row">
|
||||
<div class="sbm-control row">
|
||||
<div class="col">
|
||||
@Html.HiddenFor(model => model.Association.ContactIdTarget, new { @id = "", @class = "AssociationTargetId sbm-input" })
|
||||
<input type="hidden" name="Association.ContactIdTarget" id="" class=" AssociationTargetId sbm-input" />
|
||||
<input type="text" id="ifAssociationTarget" class="AssociationTarget sbm-input sbm-auto-val" readonly="readonly" />
|
||||
</div>
|
||||
<div class="fixed">
|
||||
<div class="sbc-action AssetTargetSearch"><img src="~/img/action/search24.png" alt="" title="" /></div>
|
||||
<div class="sbm-action AssocTargetSearch"><img src="~/img/action/search24.png" alt="" title="" /></div>
|
||||
</div>
|
||||
<div class="fixed">
|
||||
<div class="sbm-action AssocTargetEdit"><img src="~/img/action/edit24.png" alt="" title="" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
@@ -88,7 +122,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Association Code *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Code)">
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Code)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -97,7 +131,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Association.Code, new { @id = "ifAssociationCode", @class = "AssociationCode sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code) })
|
||||
<input type="text" name="Association.Code" id="ifAssociationCode" class="AssociationCode sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Code)" />
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
@@ -109,7 +143,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Association ExtRef *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.ReferenceExt)">
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.ReferenceExt)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -118,7 +152,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Association.ReferenceExt, new { @id = "ifAssociationExtRef", @class = "AssociationExtRef sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef) })
|
||||
<input type="text" name="Association.ReferenceExt" id="ifAssociationExtRef" class="AssociationExtRef sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_ExtRef)" />
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
@@ -128,25 +162,52 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Association status *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Status)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssociationStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Association Location *@
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Location)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssociationLocation"><span>@Localiser["label.location"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
<input type="text" name="Association.Location" id="ifAssociationLocation" class="AssociationLocation sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Location)" />
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
<select id="cbAssociationStatus" class="AssociationStatus sbm-select sbm-auto-val" name="Association.StatusCode"></select>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-1"></div>
|
||||
<div class="col-sm">
|
||||
|
||||
@* Association Group *@
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Group)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssociationGroup"><span>@Localiser["label.group"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
<input type="text" name="Association.Group" id="ifAssociationGroup" class="AssociationGroup sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Group)" />
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Association Notes *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Association.ItemField.Notes)">
|
||||
<div class="sbm-form-control @Model_Association.GetFieldName(Model_Association.ItemField.Notes)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -155,7 +216,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.Association.Notes, new { @id = "ifAssociationNotes", @class = "AssociationNotes sbm-textarea sbm-auto-val", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes) })
|
||||
<textarea name="Association.Notes" id="ifAssociationNotes" class="AssociationNotes sbm-textarea sbm-auto-val" rows="3" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Association_Notes)"></textarea>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
@@ -164,4 +225,9 @@
|
||||
|
||||
}
|
||||
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Contact panels. *@
|
||||
<partial name="~/Views/Contact/Panel-ContactSelect.cshtml" />
|
||||
<partial name="~/Views/Contact/Panel-ContactDialog.cshtml" />
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
@* View is decoupled from Association model as it may be included in other views, eg. Contacts, Commodities etc. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Association list panel */
|
||||
/* NB Can potentially appear more than once on a page? */
|
||||
}
|
||||
|
||||
@* Item list *@
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Type) width10pc pl-1">@Localiser["label.type"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Code) width10pc pl-1">@Localiser["label.code"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Target) width25pc">@Localiser["label.name"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Address) width25pc d-none d-md-table-cell">@Localiser["label.address"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Status) width10pc center">@Localiser["label.status"]</th>
|
||||
<th class="@Model_Association.GetFieldName(Model_Association.ItemField.Actions)" style="width:2%;"></th>
|
||||
</tr>
|
||||
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu AssociationList">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
@* Association row template - table is ignored. *@
|
||||
<table>
|
||||
<tr class="sbm-row-item Association">
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Type) pl-1"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Code) pl-1"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Target)"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Address) d-none d-md-table-cell"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Notes) d-none d-md-table-cell"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Status) center"></td>
|
||||
<td class="@Model_Association.GetFieldName(Model_Association.ItemField.Actions)">
|
||||
<div class="right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Association">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,68 @@
|
||||
@* View is decoupled from Association model as it may be included in other views, eg. Contacts, Commodities etc. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Association maintain panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Association/Panel-AssociationMaintain")) return;
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-assoc.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Associations fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.createCust= '@(Localiser.GetJavascriptText("caption.customer.create"))';
|
||||
sbm.lbl.createSupp= '@(Localiser.GetJavascriptText("caption.supplier.create"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmAssociationFilter sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@* Header - Page caption, paging controls, actions. *@
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.associations"]</div></div>
|
||||
<div class="col right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association Category *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
@Html.DropDownList("Filter.AssociationType", Model.GetAssociationTypeCodesForFilterSelect(), @Localiser["label.any"], new { @id = "", @class = "FilterAssociationType sbm-select" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<partial name="Panel-AssociationList.cshtml" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="Panel-AssociationDialog.cshtml" />
|
||||
@@ -0,0 +1,46 @@
|
||||
@* View is decoupled from Association model as it may be included in other views, eg. Associations, Commodities etc. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Association select panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Association/Panel-AssociationSelect")) return;
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-assoc.js");
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
|
||||
<div id="dlgAssociationSelect" class="sbm-dialog sbm-flex sbm-no-padding" title="@Localiser["caption.association.select"]">
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmAssociationFilter sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.Hidden("Filter.Mode", "Search", new { @id = "" })
|
||||
@Html.Hidden("Filter.OwnerId", "", new { @id = "", @class = "FilterOwnerId" })
|
||||
@Html.Hidden("Filter.TargetId", "", new { @id = "", @class = "FilterTargetId" })
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association type *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
@Html.DropDownList("Filter.AssociationType", Model.GetAssociationTypeCodesForFilterSelect(), @Localiser["label.any"], new { @id = "", @class = "FilterAssociationType sbm-select" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Association filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<partial name="Panel-AssociationList.cshtml" />
|
||||
|
||||
</div>
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control">
|
||||
<div class="sbm-control">
|
||||
<select name="model.Code.CodeTypeId" class="CodeType sbm-select" readonly="readonly"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</script>
|
||||
|
||||
@* Results paging *@
|
||||
<div class="sbm-results-paging hidden">
|
||||
<div class="sbm-results-paging" style="display:none;">
|
||||
|
||||
@Html.HiddenFor(model => model.Paging.PageNo, new { @id = "", @class = "PagingPageNo" })
|
||||
@Html.HiddenFor(model => model.Paging.PageLength, new { @id = "", @class = "PagingPageLength" })
|
||||
|
||||
@@ -1,123 +1,8 @@
|
||||
@model Model_Contact
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Contacts - Index */
|
||||
/* Contact page */
|
||||
ViewData["Title"] = "Contacts";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-contact.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Contacts fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.createOrg = '@(Localiser.GetJavascriptText("caption.organisation.create"))';
|
||||
sbm.lbl.createInd = '@(Localiser.GetJavascriptText("caption.individual.create"))';
|
||||
sbm.lbl.createGrp = '@(Localiser.GetJavascriptText("caption.contact.group.create"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@* Header - Page caption, paging controls, actions. *@
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
|
||||
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.contacts"]</div></div>
|
||||
<div class="col right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact type *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
@Html.DropDownListFor(model => model.Filter.ContactType, Model.GetAffiliateTypeCodesForFilterSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@* Item list *@
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Type) width10pc pl-1">@Localiser["label.type"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Name) width25pc pl-1">@Localiser["label.name"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Address) width25pc d-none d-md-table-cell">@Localiser["label.address"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Contact) width10pc d-none d-md-table-cell">@Localiser["label.contact"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Phone) width10pc d-none d-sm-table-cell">@Localiser["label.phone"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Associations) width10pc center">@Localiser["label.associations"]</th>
|
||||
<th class="@Model.GetFieldName(Model_Contact.ItemField.Status) width10pc center">@Localiser["label.status"]</th>
|
||||
<th class="right" style="width:2%;"></th>
|
||||
</tr>
|
||||
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu ContactList">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
@* Item row template - table is ignored. *@
|
||||
<table>
|
||||
<tr class="sbm-row-item Contact">
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Type) pl-1"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Name) pl-1"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Address) d-none d-md-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Contact) d-none d-md-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Phone) d-none d-sm-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Notes) d-none d-md-table-cell"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Associations) center"></td>
|
||||
<td class="@Model.GetFieldName(Model_Contact.ItemField.Status) center"></td>
|
||||
<td>
|
||||
<div class="right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Contact">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="Panel-ContactDialog.cshtml" />
|
||||
<partial name="Panel-ContactMaintain.cshtml" />
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
@model Model_Contact
|
||||
@* View is decoupled from Contact model as it may be included in other views, eg. Associations. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Contacts - Contactdialog panel */
|
||||
/* Contact dialog panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Contact/Panel-ContactDialog")) return;
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -10,23 +13,23 @@
|
||||
</script>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactId", @class = "sbm-form" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Contact.Id, new { @class = "ContactId" })
|
||||
<input type="hidden" name="Contact.Id" class="ContactId" />
|
||||
}
|
||||
<div id="dlgContact" class="sbm-dialog" title="">
|
||||
<div class="spacer2"></div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContact", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Contact.Id, new { @id = "", @class = "ContactId sbm-input" })
|
||||
@Html.HiddenFor(model => model.Contact.Exists, new { @id = "", @class = "ContactExists sbm-input" })
|
||||
@Html.HiddenFor(model => model.Contact.IsIndividual, new { @id = "", @class = "ContactIsIndividual sbm-input" })
|
||||
@Html.HiddenFor(model => model.Contact.IsGroup, new { @id = "", @class = "ContactIsGroup sbm-input" })
|
||||
<input type="hidden" name="Contact.Id" id="" class="ContactId sbm-input" />
|
||||
<input type="hidden" name="Contact.Exists" id="" class="ContactExists sbm-input" />
|
||||
<input type="hidden" name="Contact.IsIndividual" id="" class="ContactIsIndividual sbm-input" />
|
||||
<input type="hidden" name="Contact.IsGroup" id="" class="ContactIsGroup sbm-input" />
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Contact Type *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Type)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Type)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -47,7 +50,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Organisation Abbreviation *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Abbreviation)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Abbreviation)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -56,7 +59,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Abbreviation, new { @id = "ifContactAbbreviation", @class = "ContactAbbreviation sbm-input sbm-auto-val upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev) })
|
||||
<input type="text" name="Contact.Abbreviation" id="ifContactAbbreviation" class="ContactAbbreviation sbm-input sbm-auto-val upper" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -67,7 +70,7 @@
|
||||
</div>
|
||||
|
||||
@* Organisation Name *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Name)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Name)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -76,7 +79,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Name, new { @id = "ifContactName", @class = "ContactName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) })
|
||||
<input type="text" name="Contact.Name" id="ifContactName" class="ContactName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -87,7 +90,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Nature Organisation Nature *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Nature)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Nature)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -96,7 +99,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Nature, new { @id = "ifContactNature", @class = "ContactNature sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature) })
|
||||
<input type="text" name="Contact.Nature" id="ifContactNature" class="ContactNature sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,7 +111,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Organisation Contact *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Contact)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Contact)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -117,7 +120,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Contact, new { @id = "ifContactContact", @class = "ContactContact sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact) })
|
||||
<input type="text" name="Contact.Contact" id="ifContactContact" class="ContactContact sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,7 +134,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Individual Title *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Title)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Title)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -140,7 +143,12 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.DropDownListFor(model => model.Contact.Title, Model.GetCodeTypeCodesForSelect(Sbm.ApplCodeType.ContactTitle), new { @id = "cbContactTitle", @class = "ContactTitle sbm-select sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Title) })
|
||||
<select name="Contact.Title" id="cbContactTitle" class="ContactTitle sbm-select sbm-auto-val">
|
||||
@foreach (var title in Model.GetCodeTypeCodesForSelect(Sbm.ApplCodeType.ContactTitle))
|
||||
{
|
||||
<option value="@title.Value">@title.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,7 +160,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Individual Salutation *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Salutation)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Salutation)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -161,7 +169,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Salutation, new { @id = "ifContactSalutation", @class = "ContactSalutation sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation) })
|
||||
<input type="text" name="Contact.Salutation" id="ifContactSalutation" class="ContactSalutation sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -175,7 +183,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Individual First Name *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.FirstName)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.FirstName)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -184,7 +192,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.FirstName, new { @id = "ifContactFirstName", @class = "ContactFirstName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) })
|
||||
<input type="text" name="Contact.FirstName" id="ifContactFirstName" class="ContactFirstName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -196,7 +204,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Individual Initials *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Initials)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Initials)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -205,7 +213,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Initials, new { @id = "ifContactInitials", @class = "ContactInitials sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials) })
|
||||
<input type="text" name="Contact.Initials" id="ifContactInitials" class="ContactInitials sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,7 +224,7 @@
|
||||
</div>
|
||||
|
||||
@* Individual Last Name *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.LastName)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.LastName)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -225,7 +233,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.LastName, new { @id = "ifContactLastName", @class = "ContactLastName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) })
|
||||
<input type="text" name="Contact.LastName" id="ifContactLastName" class="ContactLastName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,7 +244,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Organisation Main Phone & Individual Home Phone *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneMain)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.PhoneMain)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -245,7 +253,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.PhoneMain, new { @id = "ifContactPhoneMain", @class = "ContactPhoneMain sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain) })
|
||||
<input type="text" name="Contact.PhoneMain" id="ifContactPhoneMain" class="ContactPhoneMain sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -257,7 +265,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Organisation Alt Phone *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneAlt)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.PhoneAlt)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -266,7 +274,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.PhoneAlt, new { @id = "ifContactPhoneAlt", @class = "ContactPhoneAlt sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt) })
|
||||
<input type="text" name="Contact.PhoneAlt" id="ifContactPhoneAlt" class="ContactPhoneAlt sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,7 +282,7 @@
|
||||
</div>
|
||||
|
||||
@* Individual Mobile Phone *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneMobile)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.PhoneMobile)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -283,7 +291,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.PhoneMobile, new { @id = "ifContactPhoneMobile", @class = "ContactPhoneMobile sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile) })
|
||||
<input type="text" name="Contact.PhoneMobile" id="ifContactPhoneMobile" class="ContactPhoneMobile sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -297,7 +305,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Organisation Direct Phone *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneDirect)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.PhoneDirect)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -306,7 +314,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.PhoneDirect, new { @id = "ifContactPhoneDirect", @class = "ContactPhoneDirect sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect) })
|
||||
<input type="text" name="Contact.PhoneDirect" id="ifContactPhoneDirect" class="ContactPhoneDirect sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,7 +326,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Organisation Fax *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.PhoneFax)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.PhoneFax)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -327,7 +335,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.PhoneFax, new { @id = "ifContactPhoneFax", @class = "ContactPhoneFax sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax) })
|
||||
<input type="text" name="Contact.PhoneFax" id="ifContactPhoneFax" class="ContactPhoneFax sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -338,7 +346,7 @@
|
||||
</div>
|
||||
|
||||
@* Contact Email *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Email)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Email)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -347,7 +355,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Email, new { @id = "ifContactEmail", @class = "ContactEmail sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) })
|
||||
<input type="text" name="Contact.Email" id="ifContactEmail" class="ContactEmail sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -355,7 +363,7 @@
|
||||
</div>
|
||||
|
||||
@* Contact Website *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Website)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Website)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -364,7 +372,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.Website, new { @id = "ifContactWebsite", @class = "ContactWebsite sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website) })
|
||||
<input type="text" name="Contact.Website" id="ifContactWebsite" class="ContactWebsite sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -375,7 +383,7 @@
|
||||
<div class="col-sm-6">
|
||||
|
||||
@* Organisation Company Number *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.CompanyNo)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.CompanyNo)">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="sbm-label">
|
||||
@@ -384,7 +392,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.CompanyNo, new { @id = "ifContactCompanyNo", @class = "ContactCompanyNo sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo) })
|
||||
<input type="text" name="Contact.CompanyNo" id="ifContactCompanyNo" class="ContactCompanyNo sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -396,7 +404,7 @@
|
||||
<div class="col-sm">
|
||||
|
||||
@* Organisation VAT registration number *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.VatReg)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.VatReg)">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="sbm-label">
|
||||
@@ -405,7 +413,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Contact.VatReg, new { @id = "ifContactVatReg", @class = "ContactVatReg sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg) })
|
||||
<input type="text" name="Contact.VatReg" id="ifContactVatReg" class="ContactVatReg sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -416,7 +424,7 @@
|
||||
</div>
|
||||
|
||||
@* Contact Options *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Options)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Options)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -424,11 +432,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Prospect)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Prospect)">
|
||||
<div class="sbm-control">
|
||||
<input type="checkbox" name="Contact.Prospect" id="chkContactProspect" class="ContactProspect sbm-checkbox mt-1" value="true" />
|
||||
<input type="checkbox" name="Contact.Prospect" class="sbm-checkbox hidden" value="false" />
|
||||
<span class="sbc-label pointer" onclick="$('#chkContactProspect').click();">@Localiser["label.prospect"]</span>
|
||||
<span class="sbm-label pointer" onclick="$('#chkContactProspect').click();">@Localiser["label.prospect"]</span>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
@@ -437,7 +445,7 @@
|
||||
</div>
|
||||
|
||||
@* Contact Notes *@
|
||||
<div class="sbm-form-control @Model.GetFieldName(Model_Contact.ItemField.Notes)">
|
||||
<div class="sbm-form-control @Model_Contact.GetFieldName(Model_Contact.ItemField.Notes)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
@@ -446,7 +454,7 @@
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.Contact.Notes, new { @id = "ifContactNotes", @class = "ContactNotes sbm-textarea sbm-auto-val", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes) })
|
||||
<textarea name="Contact.Notes" id="ifContactNotes" class="ContactNotes sbm-textarea sbm-auto-val" rows="3" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Notes)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -455,4 +463,9 @@
|
||||
|
||||
}
|
||||
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Association panels. *@
|
||||
<partial name="~/Views/Association/Panel-AssociationSelect.cshtml" />
|
||||
<partial name="~/Views/Association/Panel-AssociationDialog.cshtml" />
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
@* View is decoupled from Contact model as it may be included in other views, eg. Associations. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Contact list panel */
|
||||
/* NB Can potentially appear more than once on a page? */
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
|
||||
@* Item list *@
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Type) width10pc pl-1">@Localiser["label.type"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Name) width25pc pl-1">@Localiser["label.name"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Address) width25pc d-none d-md-table-cell">@Localiser["label.address"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Contact) width10pc d-none d-md-table-cell">@Localiser["label.contact"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Phone) width10pc d-none d-sm-table-cell">@Localiser["label.phone"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Associations) width10pc center">@Localiser["label.associations"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Status) width10pc center">@Localiser["label.status"]</th>
|
||||
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Actions) right" style="width:2%;"></th>
|
||||
</tr>
|
||||
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu ContactList">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
@* Item row template - table is ignored. *@
|
||||
<table>
|
||||
<tr class="sbm-row-item Contact">
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Type) pl-1"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Name) pl-1"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Address) d-none d-md-table-cell"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Contact) d-none d-md-table-cell"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Phone) d-none d-sm-table-cell"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Notes) d-none d-md-table-cell"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Associations) center"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Status) center"></td>
|
||||
<td class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Actions)">
|
||||
<div class="right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@* Burger dropdown item template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Contact">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,73 @@
|
||||
@* View is decoupled from Contact model as it may be included in other views, eg. Associations. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Contact maintain panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Contact/Panel-ContactMaintain")) return;
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-contact.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Contacts fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.createOrg = '@(Localiser.GetJavascriptText("caption.organisation.create"))';
|
||||
sbm.lbl.createInd = '@(Localiser.GetJavascriptText("caption.individual.create"))';
|
||||
sbm.lbl.createGrp = '@(Localiser.GetJavascriptText("caption.contact.group.create"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmContactFilter sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@* Header - Page caption, paging controls, actions. *@
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
|
||||
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["label.contacts"]</div></div>
|
||||
<div class="col right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact type *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
<select name="Filter.ContactType" id="" class="FilterContactType sbm-select">
|
||||
<option value="">@Localiser["label.any"]</option>
|
||||
@foreach (var type in Model.GetAffiliateTypeCodesForFilterSelect())
|
||||
{
|
||||
<option value="@type.Value">@type.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-7 col-sm-8">
|
||||
<input type="text" name="Filter.Search" id="" class="FilterSearch sbm-input" maxlength="32" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<partial name="Panel-ContactList.cshtml" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="Panel-ContactDialog.cshtml" />
|
||||
@@ -0,0 +1,49 @@
|
||||
@* View is decoupled from Contact model as it may be included in other views, eg. Associations. *@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
/* Contact select panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Contact/Panel-ContactSelect")) return;
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-contact.js");
|
||||
}
|
||||
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
|
||||
<div id="dlgContactSelect" class="sbm-dialog sbm-flex sbm-no-padding" title="@Localiser["caption.contact.select"]">
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmContactFilter sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
<input type="hidden" name="Filter.Mode" value="Search" />
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbm-panel-filter">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact type *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
<select name="Filter.ContactType" id="" class="FilterContactType sbm-select">
|
||||
<option value="">@Localiser["label.any"]</option>
|
||||
@foreach (var type in Model.GetAffiliateTypeCodesForFilterSelect())
|
||||
{
|
||||
<option value="@type.Value">@type.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
@* Contact filter - name etc. *@
|
||||
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-8 col-sm-8">
|
||||
<input type="text" name="Filter.Search" id="" class="FilterSearch sbm-input" maxlength="32" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<partial name="Panel-ContactList.cshtml" />
|
||||
|
||||
</div>
|
||||
@@ -15,12 +15,12 @@
|
||||
{
|
||||
|
||||
<div class="spacer4"></div>
|
||||
<div class="sbm-form-control DbIdentifier">
|
||||
<div class="sbm-form-control RepositoryContext">
|
||||
<div class="sbm-label">
|
||||
<label for="ifEmailAddress"><span>@Localiser["label.context"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.DbIdentifier, new { @id = "ifDbIdentifier", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
@Html.TextBoxFor(model => model.RepositoryContext, new { @id = "ifRepositoryContext", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
{
|
||||
|
||||
<div class="spacer2"></div>
|
||||
<div class="sbm-form-control DbIdentifier">
|
||||
<div class="sbm-form-control RepositoryContext">
|
||||
<div class="sbm-label">
|
||||
<label for="ifEmailAddress"><span>@Localiser["label.context"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.DbIdentifier, new { @id = "ifDbIdentifier", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
@Html.TextBoxFor(model => model.RepositoryContext, new { @id = "ifRepositoryContext", @class = "sbm-input", @maxlength = @Sbm.Config.Database.Identifier.MaxLength })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
|
||||
@@ -125,6 +125,8 @@
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Contact');">@Localiser["label.contacts"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Customers');">@Localiser["label.customers"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Suppliers');">@Localiser["label.suppliers"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Association');">@Localiser["label.associations"]</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
:root
|
||||
{
|
||||
--color-OldGold: #d4af37;
|
||||
--color-MintGreen: #98fb98;
|
||||
--color-LimeGreen: #32cd32;
|
||||
--color-KellyGreen: #4cbb17;
|
||||
--color-OliveGreen: #808000;
|
||||
--color-ForestGreen: #228b22;
|
||||
--color-CornflowerBlue: #6495ed;
|
||||
--color-RoyalBlue: #4169e1;
|
||||
--color-NavyBlue: #000080;
|
||||
--color-DarkBlue: #00008B;
|
||||
--color-Indigo: #4b0082;
|
||||
--color-Iris: #5d3fd3;
|
||||
--color-BrightPurple: #bf40bf;
|
||||
--color-DarkPink: #aa336a;
|
||||
}
|
||||
|
||||
body
|
||||
|
||||
@@ -6,14 +6,24 @@
|
||||
|
||||
:root
|
||||
{
|
||||
--color-DataPanel-main: var(--color-OliveGreen);
|
||||
--color-panel-data: var(--color-OliveGreen);
|
||||
}
|
||||
|
||||
.Contacts .sbm-panel-data
|
||||
{
|
||||
--color-panel-data: var(--color-ForestGreen);
|
||||
}
|
||||
|
||||
.Associations .sbm-panel-data
|
||||
{
|
||||
--color-panel-data: var(--color-Iris);
|
||||
}
|
||||
|
||||
.sbm-panel-data
|
||||
{
|
||||
margin: 6px auto;
|
||||
background-color: #f8f8f8;
|
||||
border: solid 1px var(--color-DataPanel-main);
|
||||
border: solid 1px var(--color-panel-data);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -32,8 +42,8 @@
|
||||
padding: 1px 8px 2px 8px;
|
||||
min-height: 24px;
|
||||
color: #f0f0f0;
|
||||
background-color: var(--color-DataPanel-main);
|
||||
border-bottom: solid 1px var(--color-DataPanel-main);
|
||||
background-color: var(--color-panel-data);
|
||||
border-bottom: solid 1px var(--color-panel-data);
|
||||
}
|
||||
|
||||
.sbm-panel-data .sbm-panel-header .sbm-panel-caption
|
||||
@@ -65,13 +75,13 @@
|
||||
|
||||
/* Data panel - Filter */
|
||||
|
||||
.sbm-panel-data .sbm-panel-filter
|
||||
.sbm-panel-filter
|
||||
{
|
||||
padding: 6px 8px;
|
||||
border-bottom: solid 1px var(--color-DataPanel-main);
|
||||
padding: 6px 8px 2px 8px;
|
||||
border-bottom: solid 1px var(--color-panel-data);
|
||||
}
|
||||
|
||||
.sbm-panel-data .sbm-panel-filter .sbm-label
|
||||
.sbm-panel-filter .sbm-label
|
||||
{
|
||||
padding: 2px 8px 0 0;
|
||||
}
|
||||
@@ -126,7 +136,8 @@
|
||||
|
||||
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action
|
||||
{
|
||||
margin: 2px 1px 0 1px;
|
||||
margin: 0px 1px;
|
||||
padding:0;
|
||||
background-color: #e0e0e0;
|
||||
opacity: 50%;
|
||||
box-shadow: 0 0 0 1px #40404080 inset;
|
||||
@@ -393,7 +404,7 @@ table.sbm-item-list tbody tr:hover
|
||||
|
||||
table.sbm-item-list tbody tr.sbm-sel
|
||||
{
|
||||
background-color: palegreen;
|
||||
background-color: #c1f9a2;
|
||||
}
|
||||
|
||||
table.sbm-item-list tbody td
|
||||
|
||||
@@ -99,13 +99,21 @@ body > .container, header > .container, footer > .container
|
||||
{
|
||||
}
|
||||
|
||||
a.navbar-brand
|
||||
.navbar a.navbar-brand
|
||||
{
|
||||
padding-top:0.3rem;
|
||||
padding-bottom:0.1rem;
|
||||
white-space: normal;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.navbar li.nav-item a.nav-link
|
||||
{
|
||||
padding-top: 0.3rem;
|
||||
padding-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
.border-top
|
||||
{
|
||||
border-top: 1px solid #e5e5e5;
|
||||
@@ -333,6 +341,16 @@ a:focus
|
||||
--color-dialog: var(--color-DarkBlue);
|
||||
}
|
||||
|
||||
.ui-dialog.sbm-Contact
|
||||
{
|
||||
--color-dialog: var(--color-ForestGreen);
|
||||
}
|
||||
|
||||
.ui-dialog.sbm-Association
|
||||
{
|
||||
--color-dialog: var(--color-Iris);
|
||||
}
|
||||
|
||||
.sbm-dialog
|
||||
{
|
||||
display: none;
|
||||
@@ -393,10 +411,21 @@ a:focus
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sbm-dialog.ui-dialog-content.sbm-flex
|
||||
{
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sbm-dialog.ui-dialog-content.sbm-no-padding
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-buttonpane
|
||||
{
|
||||
border-color: var(--color-dialog);
|
||||
margin-top: .25em;
|
||||
margin-top: 0;
|
||||
padding: .2em 1em .2em .5em;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,73 +5,100 @@
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let as = sbm.Associations = { data: {}, ajax: {} };
|
||||
let $pnl = as.$pnl = {}, $frm = as.$frm = {}, $dlg = as.$dlg = {};
|
||||
let as = sbm.mdl.Associations = { env: {} };
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.refreshResults = function (delay)
|
||||
as.refreshConfig = function (env, delay)
|
||||
{
|
||||
if (!sbm.awaitingRefreshResponse)
|
||||
{
|
||||
$pnl.bgr.invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
as.ajax.refreshResults = as.ajax.refreshResults || { url: sbm.url.base + 'Association/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: as.doRefreshResults };
|
||||
sbm.doAjaxRequest(as.ajax.refreshResults, delay || 50);
|
||||
sbm.awaitingRefreshResponse = true;
|
||||
env.ajax.refreshConfig = env.ajax.refreshConfig || { url: sbm.url.base + 'Association/Ajax/Config', formSel: env.$frm.filter, callbackFn: function (response) { as.doRefreshConfig(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.refreshConfig, delay || 50);
|
||||
}
|
||||
as.doRefreshResults = function (response)
|
||||
as.doRefreshConfig = function (env, response)
|
||||
{
|
||||
//sbm.debug('doRefreshResults', response);
|
||||
delete sbm.awaitingRefreshResponse;
|
||||
$pnl.msgs.hide().empty();
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
sbm.refreshPaging(response, '#frmAssociationFilter', as.refreshResults);
|
||||
//sbm.debug('doRefreshConfig', env, response);
|
||||
if (!response.success) return;
|
||||
// Config.
|
||||
env.mode = response.mode;
|
||||
env.config = response.config;
|
||||
env.configCust = response.configCust;
|
||||
env.configSupp = response.configSupp;
|
||||
env.data.associationTypes = response.associationTypes;
|
||||
env.data.statuses = response.statuses;
|
||||
env.data.defaultStatusCode = response.defaultStatusCode;
|
||||
}
|
||||
|
||||
// Reference data.
|
||||
as.config = response.config;
|
||||
as.configCust = response.configCust;
|
||||
as.configSupp = response.configSupp;
|
||||
as.data.associationTypes = response.associationTypes;
|
||||
as.data.statuses = response.statuses;
|
||||
as.data.defaultStatusCode = response.defaultStatusCode;
|
||||
//--------------------------------------------------------------
|
||||
as.refreshResults = function (env, delay)
|
||||
{
|
||||
if (!as.awaitingRefreshResponse)
|
||||
{
|
||||
env.$pnl.bgr.invisible();
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
env.$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
env.ajax.refreshResults = env.ajax.refreshResults || { url: sbm.url.base + 'Association/Ajax/List', formSel: env.$frm.filter, callbackFn: function (response) { as.doRefreshResults(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.refreshResults, delay || 50);
|
||||
as.awaitingRefreshResponse = true;
|
||||
}
|
||||
as.doRefreshResults = function (env, response)
|
||||
{
|
||||
//sbm.debug('doRefreshResults', env, response);
|
||||
delete as.awaitingRefreshResponse;
|
||||
env.$pnl.msgs.hide().empty();
|
||||
let $table = $('table', env.$pnl.table).find('tbody tr').remove().end();
|
||||
sbm.refreshPaging(response, env.$frm.filter, function () { as.refreshResults(env); });
|
||||
if (!response.success) return;
|
||||
as.doRefreshConfig(env, response);
|
||||
if (response.caption) env.$pnl.items.find('.sbm-panel-caption').text(response.caption);
|
||||
|
||||
// Menu.
|
||||
$pnl.bgr.invisible();
|
||||
$pnl.mnu.empty();
|
||||
$pnl.mnu.append(as.getFilterMenuOption(sbm.lbl.refresh, function () { as.refreshResults(); }, 'sbm-refresh'));
|
||||
$pnl.mnu.append(as.getFilterMenuOption(sbm.lbl.createCust, function () { as.createItem(as.configCust, sbm.lbl.createCust); }, 'sbm-add'));
|
||||
$pnl.mnu.append(as.getFilterMenuOption(sbm.lbl.createSupp, function () { as.createItem(as.configSupp, sbm.lbl.createSupp); }, 'sbm-add'));
|
||||
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
|
||||
if (env.$pnl.bgr.length)
|
||||
{
|
||||
env.$pnl.bgr.invisible();
|
||||
env.$pnl.mnu.empty();
|
||||
env.$pnl.mnu.append(as.getFilterMenuOption(env, sbm.lbl.refresh, function () { as.refreshResults(env); }, 'sbm-refresh'));
|
||||
if (env.config.action.allow.createCust)
|
||||
env.$pnl.mnu.append(as.getFilterMenuOption(env, sbm.lbl.createCust, function () { as.createItem(env, env.configCust, sbm.lbl.createCust); }, 'sbm-add'));
|
||||
if (env.config.action.allow.createSupp)
|
||||
env.$pnl.mnu.append(as.getFilterMenuOption(env, sbm.lbl.createSupp, function () { as.createItem(env, env.configSupp, sbm.lbl.createSupp); }, 'sbm-add'));
|
||||
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
|
||||
}
|
||||
|
||||
// Items.
|
||||
var items = response.associations || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
return env.$pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(as.populateItem(as.getItemTemplate(), items[itemIdx]));
|
||||
sbm.configureItemTable(as.config, $table);
|
||||
$table.append(as.populateItem(env, as.getItemTemplate(env), items[itemIdx]));
|
||||
sbm.configureItemTable(env.config, $table);
|
||||
}
|
||||
as.populateItem = function ($item, item)
|
||||
as.populateItem = function (env, $item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$item.prop('id', as.getItemId(item));
|
||||
sbm.populateItemValues(as.config, $item, item.field.value);
|
||||
let prefix = as.config.column.prefix;
|
||||
$('.' + prefix + 'Status', $item).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
var $bgr = $('.sbm-burger', $item).hide();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
let cfg = env.config;
|
||||
sbm.populateItemValues(cfg, $item, item.field.value);
|
||||
let prefix = cfg.column.prefix;
|
||||
if (!env.mode.search)
|
||||
{
|
||||
let fnUpd = function () { as.updateItem(item) };
|
||||
$mnu.append(as.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.' + prefix + 'Target', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
$('.' + prefix + 'Status', $item).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
var $bgr = $('.sbm-burger', $item).hide();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
let fnUpd = function () { as.updateItem(env, item.id) };
|
||||
$mnu.append(as.getItemMenuOption(env, sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.' + prefix + 'Target', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
}
|
||||
else if (env.prmSelect)
|
||||
{
|
||||
$item.off('click').on('click', function () { as.selectItemRow(env, $item, item); });
|
||||
$item.off('dblclick').on('dblclick', function () { as.selectItem(env); });
|
||||
}
|
||||
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
as.getItemId = function (item)
|
||||
@@ -80,27 +107,27 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.getFilterDropdownTemplate = function ()
|
||||
as.getFilterDropdownTemplate = function (env)
|
||||
{
|
||||
return $('.sbm-dropdown-menu.AssociationList li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
return $('.sbm-dropdown-menu.AssociationList li.sbm-dropdown-item', env.$pnl.tmpls).clone();
|
||||
}
|
||||
as.getItemTemplate = function ()
|
||||
as.getItemTemplate = function (env)
|
||||
{
|
||||
return $('table tr.sbm-row-item.Association', $pnl.tmpls).clone();
|
||||
return $('table tr.sbm-row-item.Association', env.$pnl.tmpls).clone();
|
||||
}
|
||||
as.getItemDropdownTemplate = function ()
|
||||
as.getItemDropdownTemplate = function (env)
|
||||
{
|
||||
return $('.sbm-dropdown-menu.Association li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
return $('.sbm-dropdown-menu.Association li.sbm-dropdown-item', env.$pnl.tmpls).clone();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.getFilterMenuOption = function (lbl, fn, cls)
|
||||
as.getFilterMenuOption = function (env, lbl, fn, cls)
|
||||
{
|
||||
return as.getMenuOption(as.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
return as.getMenuOption(as.getFilterDropdownTemplate(env), lbl, fn, cls);
|
||||
}
|
||||
as.getItemMenuOption = function (lbl, fn, cls)
|
||||
as.getItemMenuOption = function (env, lbl, fn, cls)
|
||||
{
|
||||
return as.getMenuOption(as.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
return as.getMenuOption(as.getItemDropdownTemplate(env), lbl, fn, cls);
|
||||
}
|
||||
as.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
@@ -108,107 +135,217 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.createItem = function (cfg, title)
|
||||
as.createItem = function (env, cfg, title)
|
||||
{
|
||||
as.clearItem(cfg);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
|
||||
$ctrls.filter('.AssociationType').val('').prop('disabled', false);
|
||||
$ctrls.filter('.AssociationStatus').val(as.data.defaultStatusCode);
|
||||
as.openItemDlg(cfg, title);
|
||||
as.clearItem(env, cfg);
|
||||
let prefix = cfg.field.prefix;
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
|
||||
if (cfg.type) sbm.selectOrAdd($ctrls.filter('.AssociationType'), cfg.type.code, cfg.type.desc)
|
||||
env.$ctrl.targetActions.filter('.AssocTargetSearch').show();
|
||||
$ctrls.filter('.AssociationTarget').off('dblclick').on('dblclick', function () { as.selectTarget(env); });
|
||||
$ctrls.filter('.AssociationStatus').val(env.data.defaultStatusCode);
|
||||
as.openEditDlg(env, cfg, title);
|
||||
}
|
||||
as.clearItem = function (cfg)
|
||||
as.clearItem = function (env, cfg)
|
||||
{
|
||||
sbm.clearItemForm($frm.item);
|
||||
sbm.populateSelectCodeDesc('#cbAssociationType', as.data.associationTypes);
|
||||
sbm.populateSelectCodeDesc('#cbAssociationStatus', as.data.statuses);
|
||||
sbm.clearItemForm(env.$frm.item);
|
||||
let prefix = cfg.field.prefix;
|
||||
sbm.populateSelectCodeDesc('#cbAssociationType', env.data.associationTypes);
|
||||
env.$ctrl.targetActions.hide();
|
||||
sbm.populateSelectCodeDesc('#cbAssociationStatus', env.data.statuses);
|
||||
}
|
||||
as.openItemDlg = function (cfg, title)
|
||||
as.openEditDlg = function (env, cfg, title)
|
||||
{
|
||||
sbm.configureItemControls(cfg, $frm.item);
|
||||
$dlg.item.dialog('option', 'title', title);
|
||||
sbm.openDialog($dlg.item, 640, 600);
|
||||
sbm.configureItemControls(cfg, env.$frm.item);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
|
||||
$ctrls.filter('.AssociationTarget').prop('disabled', false)
|
||||
let $dlg = env.$dlg.item;
|
||||
let btns = {};
|
||||
btns[sbm.lbl.ok] = function () { as.storeItem(env); };
|
||||
btns[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.dialog('option', 'buttons', btns);
|
||||
if (title) $dlg.dialog('option', 'title', title);
|
||||
sbm.openDialog($dlg, 720, 640);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.updateItem = function (item)
|
||||
as.selectTarget = function (env)
|
||||
{
|
||||
$('.AssociationId', $frm.itemId).val(item.id);
|
||||
as.ajax.updateItem = as.ajax.updateItem || { url: sbm.url.base + 'Association/Ajax/GetItem', formId: 'frmAssociationId', callbackFn: as.onUpdateItem };
|
||||
sbm.doAjaxRequest(as.ajax.updateItem, 50);
|
||||
sbm.fn.selectContact({ fnSuccess: function (item) { as.onSelectTarget(env, item); } });
|
||||
}
|
||||
as.onUpdateItem = function (response)
|
||||
as.onSelectTarget = function (env, item)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', response);
|
||||
//sbm.debug('onSelectTarget', env, item);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
|
||||
$ctrls.filter('.AssociationTargetId').val(item.id);
|
||||
$ctrls.filter('.AssociationTarget').val(item.Name);
|
||||
}
|
||||
as.editTarget = function (env)
|
||||
{
|
||||
let cfg = {
|
||||
id: $('.sbm-input', env.$frm.item).filter('.AssociationTargetId').val(),
|
||||
fnSuccess: function (item) { as.onEditTarget(env, item); }
|
||||
};
|
||||
sbm.fn.editContact(cfg);
|
||||
}
|
||||
as.onEditTarget = function (env, item)
|
||||
{
|
||||
//sbm.debug('onEditTarget', env, item);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
|
||||
$ctrls.filter('.AssociationTarget').val(item.name);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.updateItem = function (env, id)
|
||||
{
|
||||
let $frm = env.$frm.itemId;
|
||||
$('.AssociationId', $frm).val(id);
|
||||
env.ajax.updateItem = env.ajax.updateItem || { url: sbm.url.base + 'Association/Ajax/GetItem', formSel: $frm, callbackFn: function (response) { as.onUpdateItem(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.updateItem, 50);
|
||||
}
|
||||
as.onUpdateItem = function (env, response)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', env, response);
|
||||
if (!response.success) return;
|
||||
let cfg = response.config || {};
|
||||
let prefix = cfg.field.prefix;
|
||||
as.clearItem(cfg);
|
||||
as.clearItem(env, cfg);
|
||||
let item = response.association;
|
||||
sbm.populateFormValues(cfg, $frm.item, item.field.value);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
|
||||
let $frm = env.$frm.item;
|
||||
sbm.populateFormValues(cfg, $frm, item.field.value);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm);
|
||||
$ctrls.filter('.AssociationId').val(item.id);
|
||||
$ctrls.filter('.AssociationExists').val(1);
|
||||
let $ctrlType = $ctrls.filter('.AssociationType');
|
||||
sbm.selectOrAdd($ctrlType, item.typeCode, item.typeDesc)
|
||||
//if ($ctrlType.val()) $ctrlType.prop('disabled', true);
|
||||
sbm.selectOrAdd($ctrls.filter('.AssociationType'), item.typeCode, item.typeDesc)
|
||||
$ctrls.filter('.AssociationOwnerId').val(item.ownerId);
|
||||
$ctrls.filter('.AssociationTargetId').val(item.targetId);
|
||||
env.$ctrl.targetActions.filter('.AssocTargetEdit').show();
|
||||
$ctrls.filter('.AssociationTarget').off('dblclick').on('dblclick', function () { as.editTarget(env); });
|
||||
sbm.selectOrAdd($ctrls.filter('.AssociationStatus'), item.statusCode, item.statusDesc)
|
||||
as.openItemDlg(cfg, cfg.title || sbm.dlg.title.updateAssociation);
|
||||
as.openEditDlg(env, cfg, cfg.title || sbm.dlg.title.updateAssociation);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.storeItem = function ()
|
||||
as.storeItem = function (env)
|
||||
{
|
||||
as.ajax.storeItem = as.ajax.storeItem || { url: sbm.url.base + 'Association/Ajax/StoreItem', formId: 'frmAssociation', callbackFn: as.onStoreItem };
|
||||
sbm.doAjaxRequest(as.ajax.storeItem, 50);
|
||||
env.ajax.storeItem = env.ajax.storeItem || { url: sbm.url.base + 'Association/Ajax/StoreItem', formSel: env.$frm.item, callbackFn: function (response) { as.onStoreItem(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.storeItem, 50);
|
||||
}
|
||||
as.onStoreItem = function (response)
|
||||
as.onStoreItem = function (env, response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
//sbm.debug('onStoreItem', env, response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
$pnl.msgs.hide().empty();
|
||||
env.$dlg.item.dialog('close');
|
||||
env.$pnl.msgs.hide().empty();
|
||||
|
||||
var item = response.association;
|
||||
var $item = $('#' + as.getItemId(item), $pnl.table);
|
||||
var $item = $('#' + as.getItemId(item), env.$pnl.table);
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = as.getItemTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
$item = as.getItemTemplate(env);
|
||||
$('table tbody', env.$pnl.table).prepend($item).show();
|
||||
}
|
||||
let cfg = response.config || {};
|
||||
as.populateItem($item, item);
|
||||
as.populateItem(env, $item, item);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/* Params: ownerId, targetId, search. */
|
||||
sbm.fn.listAssociations = function (prm)
|
||||
{
|
||||
let env = as.env.select;
|
||||
//sbm.debug('listAssociations', env, prm);
|
||||
env.prmList = prm;
|
||||
let $frm = env.$frm.filter;
|
||||
$frm.find('.FilterOwnerId').val(prm.ownerId);
|
||||
$frm.find('.FilterTargetId').val(prm.targetId);
|
||||
$frm.find('.FilterContactType').val('');
|
||||
$frm.find('.FilterSearch').val(prm.search || '');
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
let $dlg = env.$dlg.select;
|
||||
let btns = $dlg.dialog('option', 'buttons');
|
||||
btns[sbm.lbl.close] = function () { delete env.prmSelect; delete env.prmList; $(this).dialog('close'); };
|
||||
$dlg.dialog('option', 'buttons', btns);
|
||||
sbm.openDialog($dlg, 1000, 800);
|
||||
if (env.$pnl.items.length) setTimeout(function () { as.refreshResults(env); }, 250);
|
||||
}
|
||||
|
||||
/* Params: type, search. */
|
||||
sbm.fn.selectAssociation = function (prm)
|
||||
{
|
||||
let env = as.env.select;
|
||||
//sbm.debug('listAssociations', env, prm);
|
||||
env.prmSelect = prm;
|
||||
let $frm = env.$frm.filter;
|
||||
$frm.find('.FilterOwnerId,.FilterTargetId').val('');
|
||||
$frm.find('.FilterContactType').val(prm.type || '');
|
||||
$frm.find('.FilterSearch').val(prm.search || '');
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
let $dlg = env.$dlg.select;
|
||||
let btns = $dlg.dialog('option', 'buttons');
|
||||
btns[sbm.lbl.ok] = function () { as.selectItem(env); };
|
||||
btns[sbm.lbl.cancel] = function () { delete env.prmSelect; delete env.prmList; $(this).dialog('close'); };
|
||||
$dlg.dialog('option', 'buttons', btns);
|
||||
sbm.openDialog($dlg, 1000, 800);
|
||||
if (env.$pnl.items.length) setTimeout(function () { as.refreshResults(env); }, 250);
|
||||
}
|
||||
as.selectItemRow = function (env, $item, item)
|
||||
{
|
||||
//sbm.debug('selectItemRow', env, $item, item);
|
||||
env.$pnl.table.find('tr').removeClass('sbm-sel');
|
||||
$item.addClass('sbm-sel');
|
||||
env.prmSelect.item = item;
|
||||
}
|
||||
as.selectItem = function (env)
|
||||
{
|
||||
//sbm.debug('selectItem', env, env.prmSelect.item);
|
||||
env.$dlg.select.dialog('close');
|
||||
env.prmSelect.fnSuccess(env.prmSelect.item);
|
||||
delete env.prmSelect;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
as.initContactEnv = function ($pnlItems)
|
||||
{
|
||||
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
|
||||
|
||||
env.$pnl.items = $($pnlItems);
|
||||
env.$pnl.header = env.$pnl.items.find('.sbm-panel-header');
|
||||
env.$pnl.bgr = env.$pnl.header.find('.sbm-burger');
|
||||
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
|
||||
env.$pnl.table = env.$pnl.items.find('.sbm-panel-item-table');
|
||||
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
|
||||
env.$pnl.tmpls = env.$pnl.items.find('.sbm-panel-item-template');
|
||||
|
||||
env.$frm.filter = env.$pnl.items.find('.frmAssociationFilter');
|
||||
env.$frm.filter.on('input', '.FilterSearch', function () { as.refreshResults(env, 250); }).on('change', '.FilterAssociationType', function () { as.refreshResults(env, 50); });
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.dialogClass += " sbm-Association";
|
||||
env.$dlg.item = $('#dlgAssociation').dialog(opt);
|
||||
env.$frm.itemId = $('#frmAssociationId');
|
||||
env.$frm.item = $('#frmAssociation').on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
env.$ctrl.targetActions = env.$frm.item.find('.AssocTarget .sbm-control .sbm-action');
|
||||
env.$ctrl.targetActions.filter('.AssocTargetSearch').off('click').on('click', function () { as.selectTarget(env); });
|
||||
env.$ctrl.targetActions.filter('.AssocTargetEdit').off('click').on('click', function () { as.editTarget(env); });
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.dialogClass += " sbm-Association";
|
||||
env.$dlg.select = $('#dlgAssociationSelect').dialog(opt);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.Associations');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.bgr = $('.sbm-burger', $pnl.header);
|
||||
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmAssociationFilter');
|
||||
$frm.filter.on('input', '.FilterSearch', function () { as.refreshResults(250); }).on('change', '.FilterAssociationType', function () { as.refreshResults(50); });
|
||||
|
||||
|
||||
$frm.itemId = $('#frmAssociationId');
|
||||
$frm.item = $('#frmAssociation');
|
||||
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.ok] = function () { as.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgAssociation').dialog(opt);
|
||||
|
||||
setTimeout(as.refreshResults, 250);
|
||||
as.env.maint = as.initContactEnv('.sbm-panel.Associations');
|
||||
if (as.env.maint.$pnl.items.length) setTimeout(function () { as.refreshResults(as.env.maint); }, 250);
|
||||
as.env.select = as.initContactEnv('#dlgAssociationSelect');
|
||||
if (as.env.select.$pnl.items.length) setTimeout(function () { as.refreshConfig(as.env.select); }, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -5,79 +5,104 @@
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let co = sbm.Contacts = { data: {}, ajax: {} };
|
||||
let $pnl = co.$pnl = {}, $frm = co.$frm = {}, $dlg = co.$dlg = {};
|
||||
let co = sbm.mdl.Contacts = { env: {} };
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.refreshResults = function (delay)
|
||||
co.refreshConfig = function (env, delay)
|
||||
{
|
||||
if (!sbm.awaitingRefreshResponse)
|
||||
{
|
||||
$pnl.bgr.invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
co.ajax.refreshResults = co.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: co.doRefreshResults };
|
||||
sbm.doAjaxRequest(co.ajax.refreshResults, delay || 50);
|
||||
sbm.awaitingRefreshResponse = true;
|
||||
env.ajax.refreshConfig = env.ajax.refreshConfig || { url: sbm.url.base + 'Contact/Ajax/Config', formSel: env.$frm.itemId, callbackFn: function (response) { co.doRefreshConfig(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.refreshConfig, delay || 50);
|
||||
}
|
||||
co.doRefreshResults = function (response)
|
||||
co.doRefreshConfig = function (env, response)
|
||||
{
|
||||
//sbm.debug('doRefreshResults', response);
|
||||
delete sbm.awaitingRefreshResponse;
|
||||
$pnl.msgs.hide().empty();
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
sbm.refreshPaging(response, '#frmContactFilter', co.refreshResults);
|
||||
//sbm.debug('doRefreshConfig', env, response);
|
||||
if (!response.success) return;
|
||||
// Config.
|
||||
env.mode = response.mode;
|
||||
env.config = response.config;
|
||||
env.configInd = response.configInd;
|
||||
env.configOrg = response.configOrg;
|
||||
env.configGrp = response.configGrp;
|
||||
env.data.organisationTypes = response.organisationTypes;
|
||||
env.data.titles = response.titles;
|
||||
env.data.salutations = response.salutations;
|
||||
env.data.statuses = response.statuses;
|
||||
env.data.defaultStatusCode = response.defaultStatusCode;
|
||||
}
|
||||
|
||||
// Reference data.
|
||||
co.config = response.config;
|
||||
co.configInd = response.configInd;
|
||||
co.configOrg = response.configOrg;
|
||||
co.configGrp = response.configGrp;
|
||||
co.data.organisationTypes = response.organisationTypes;
|
||||
co.data.titles = response.titles;
|
||||
co.data.salutations = response.salutations;
|
||||
co.data.statuses = response.statuses;
|
||||
co.data.defaultStatusCode = response.defaultStatusCode;
|
||||
//--------------------------------------------------------------
|
||||
co.refreshResults = function (env, delay)
|
||||
{
|
||||
if (!co.awaitingRefreshResponse)
|
||||
{
|
||||
env.$pnl.bgr.invisible();
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
env.$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
env.ajax.refreshResults = env.ajax.refreshResults || { url: sbm.url.base + 'Contact/Ajax/List', formSel: env.$frm.filter, callbackFn: function (response) { co.doRefreshResults(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.refreshResults, delay || 50);
|
||||
co.awaitingRefreshResponse = true;
|
||||
}
|
||||
co.doRefreshResults = function (env, response)
|
||||
{
|
||||
//sbm.debug('doRefreshResults', env, response);
|
||||
delete co.awaitingRefreshResponse;
|
||||
env.$pnl.msgs.hide().empty();
|
||||
let $table = $('table', env.$pnl.table).find('tbody tr').remove().end();
|
||||
sbm.refreshPaging(response, env.$frm.filter, function () { co.refreshResults(env); });
|
||||
if (!response.success) return;
|
||||
co.doRefreshConfig(env, response);
|
||||
|
||||
// Menu.
|
||||
$pnl.bgr.invisible();
|
||||
$pnl.mnu.empty();
|
||||
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.refresh, function () { co.refreshResults(); }, 'sbm-refresh'));
|
||||
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createOrg, function () { co.createItem(co.configOrg, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createInd, function () { co.createItem(co.configInd, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.createGrp, function () { co.createItem(co.configGrp, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
|
||||
if (env.$pnl.bgr.length)
|
||||
{
|
||||
env.$pnl.bgr.invisible();
|
||||
env.$pnl.mnu.empty();
|
||||
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.refresh, function () { co.refreshResults(env); }, 'sbm-refresh'));
|
||||
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.createOrg, function () { co.createItem(env, env.configOrg, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.createInd, function () { co.createItem(env, env.configInd, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.createGrp, function () { co.createItem(env, env.configGrp, sbm.dlg.title.createContact); }, 'sbm-add'));
|
||||
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
|
||||
}
|
||||
|
||||
// Items.
|
||||
var items = response.contacts || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
return env.$pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(co.populateItem(co.getItemTemplate(), items[itemIdx]));
|
||||
sbm.configureItemTable(co.config, $table);
|
||||
$table.append(co.populateItem(env, co.getItemTemplate(env), items[itemIdx]));
|
||||
sbm.configureItemTable(env.config, $table);
|
||||
}
|
||||
co.populateItem = function ($item, item)
|
||||
co.populateItem = function (env, $item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$item.prop('id', co.getItemId(item));
|
||||
sbm.populateItemValues(co.config, $item, item.field.value);
|
||||
let prefix = co.config.column.prefix;
|
||||
if (item.associationCount)
|
||||
$('.' + prefix + 'Associations', $item).text(item.associationCount).off('click').on('click', function () { co.onClickAssociationCount(item); }).addClass('sbm-action-text');
|
||||
$('.' + prefix + 'Status', $item).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
var $bgr = $('.sbm-burger', $item).hide();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
let cfg = env.config;
|
||||
if (cfg) sbm.populateItemValues(cfg, $item, item.field.value);
|
||||
if (!env.mode.search)
|
||||
{
|
||||
let fnUpd = function () { co.updateItem(item) };
|
||||
$mnu.append(co.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.' + prefix + 'Name', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
let prefix = cfg.column.prefix;
|
||||
let $assocs = $('.' + prefix + 'Associations', $item).text(item.associationCount || '').off('click');
|
||||
if (item.associationCount)
|
||||
$assocs.on('click', function () { co.onClickAssociationCount(env, item); }).addClass('sbm-action-text');
|
||||
$('.' + prefix + 'Status', $item).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
var $bgr = $('.sbm-burger', $item).hide();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
let fnUpd = function () { co.updateItem(env, item.id) };
|
||||
$mnu.append(co.getItemMenuOption(env, sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.' + prefix + 'Name', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item.off('click').on('click', function () { co.selectItemRow(env, $item, item); });
|
||||
$item.off('dblclick').on('dblclick', function () { co.selectItem(env); });
|
||||
}
|
||||
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
co.getItemId = function (item)
|
||||
@@ -86,27 +111,27 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.getFilterDropdownTemplate = function ()
|
||||
co.getFilterDropdownTemplate = function (env)
|
||||
{
|
||||
return $('.sbm-dropdown-menu.ContactList li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
return $('.sbm-dropdown-menu.ContactList li.sbm-dropdown-item', env.$pnl.tmpls).clone();
|
||||
}
|
||||
co.getItemTemplate = function ()
|
||||
co.getItemTemplate = function (env)
|
||||
{
|
||||
return $('table tr.sbm-row-item.Contact', $pnl.tmpls).clone();
|
||||
return $('table tr.sbm-row-item.Contact', env.$pnl.tmpls).clone();
|
||||
}
|
||||
co.getItemDropdownTemplate = function ()
|
||||
co.getItemDropdownTemplate = function (env)
|
||||
{
|
||||
return $('.sbm-dropdown-menu.Contact li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
return $('.sbm-dropdown-menu.Contact li.sbm-dropdown-item', env.$pnl.tmpls).clone();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.getFilterMenuOption = function (lbl, fn, cls)
|
||||
co.getFilterMenuOption = function (env, lbl, fn, cls)
|
||||
{
|
||||
return co.getMenuOption(co.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
return co.getMenuOption(co.getFilterDropdownTemplate(env), lbl, fn, cls);
|
||||
}
|
||||
co.getItemMenuOption = function (lbl, fn, cls)
|
||||
co.getItemMenuOption = function (env, lbl, fn, cls)
|
||||
{
|
||||
return co.getMenuOption(co.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
return co.getMenuOption(co.getItemDropdownTemplate(env), lbl, fn, cls);
|
||||
}
|
||||
co.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
@@ -114,115 +139,183 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.createItem = function (cfg, title)
|
||||
co.createItem = function (env, cfg, title)
|
||||
{
|
||||
co.clearItem(cfg);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
|
||||
$ctrls.filter('.ContactStatus').val(co.data.defaultStatusCode);
|
||||
co.openItemDlg(cfg, title);
|
||||
co.clearItem(env, cfg);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
|
||||
$ctrls.filter('.ContactStatus').val(env.data.defaultStatusCode);
|
||||
co.openEditDlg(env, cfg, title);
|
||||
}
|
||||
co.clearItem = function (cfg)
|
||||
co.clearItem = function (env, cfg)
|
||||
{
|
||||
//sbm.debug('clearItem', cfg);
|
||||
let frm = $frm.item;
|
||||
sbm.clearItemForm(frm);
|
||||
if (cfg.isIndividual) $('.ContactIsIndividual', frm).val(1);
|
||||
if (cfg.isGroup) $('.ContactIsGroup', frm).val(1);
|
||||
sbm.populateSelectCodeDesc('#cbContactType', co.data.organisationTypes);
|
||||
sbm.populateSelectCodeDesc('#cbContactTitle', co.data.titles);
|
||||
sbm.populateSelectCodeDesc('#cbContactSalutation', co.data.salutations);
|
||||
sbm.populateSelectCodeDesc('#cbContactStatus', co.data.statuses);
|
||||
//sbm.debug('clearItem', env, cfg);
|
||||
let $frm = env.$frm.item;
|
||||
sbm.clearItemForm($frm);
|
||||
if (cfg.isIndividual) $('.ContactIsIndividual', $frm).val(1);
|
||||
if (cfg.isGroup) $('.ContactIsGroup', $frm).val(1);
|
||||
sbm.populateSelectCodeDesc('#cbContactType', env.data.organisationTypes);
|
||||
sbm.populateSelectCodeDesc('#cbContactTitle', env.data.titles);
|
||||
sbm.populateSelectCodeDesc('#cbContactSalutation', env.data.salutations);
|
||||
sbm.populateSelectCodeDesc('#cbContactStatus', env.data.statuses);
|
||||
}
|
||||
co.openItemDlg = function (cfg, title)
|
||||
co.openEditDlg = function (env, cfg, title)
|
||||
{
|
||||
sbm.configureItemControls(cfg, $frm.item);
|
||||
$dlg.item.dialog('option', 'title', title);
|
||||
sbm.openDialog($dlg.item, 640, 600);
|
||||
let $frm = env.$frm.item;
|
||||
sbm.configureItemControls(cfg, $frm);
|
||||
var btns = {};
|
||||
btns[sbm.lbl.ok] = function () { co.storeItem(env); };
|
||||
btns[sbm.lbl.cancel] = function () { delete env.prmEdit; $(this).dialog('close'); };
|
||||
env.$dlg.item.dialog('option', 'buttons', btns);
|
||||
if (title) env.$dlg.item.dialog('option', 'title', title);
|
||||
sbm.openDialog(env.$dlg.item, 640, 600);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.updateItem = function (item)
|
||||
co.updateItem = function (env, id)
|
||||
{
|
||||
$('.ContactId', $frm.itemId).val(item.id);
|
||||
co.ajax.updateItem = co.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formId: 'frmContactId', callbackFn: co.onUpdateItem };
|
||||
sbm.doAjaxRequest(co.ajax.updateItem, 50);
|
||||
let $frm = env.$frm.itemId;
|
||||
$('.ContactId', $frm).val(id);
|
||||
env.ajax.updateItem = env.ajax.updateItem || { url: sbm.url.base + 'Contact/Ajax/GetItem', formSel: $frm, callbackFn: function (response) { co.onUpdateItem(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.updateItem, 50);
|
||||
}
|
||||
co.onUpdateItem = function (response)
|
||||
co.onUpdateItem = function (env, response)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', response);
|
||||
//sbm.debug('onUpdateItem', env, response);
|
||||
if (!response.success) return;
|
||||
let cfg = response.config || {};
|
||||
co.clearItem(cfg);
|
||||
co.clearItem(env, cfg);
|
||||
let item = response.contact;
|
||||
sbm.populateFormValues(cfg, $frm.item, item.field.value);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select,.sbm-checkbox', $frm.item);
|
||||
let $frm = env.$frm.item;
|
||||
sbm.populateFormValues(cfg, $frm, item.field.value);
|
||||
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select,.sbm-checkbox', $frm);
|
||||
$ctrls.filter('.ContactId').val(item.id);
|
||||
$ctrls.filter('.ContactExists').val(1);
|
||||
$ctrls.filter('.ContactType').val(item.typeCode);
|
||||
$ctrls.filter('.ContactProspect').prop('checked', !!item.prospect);
|
||||
$ctrls.filter('.ContactStatus').val(item.statusCode);
|
||||
co.openItemDlg(cfg, sbm.dlg.title.updateContact);
|
||||
co.openEditDlg(env, cfg, sbm.dlg.title.updateContact);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.storeItem = function ()
|
||||
co.storeItem = function (env)
|
||||
{
|
||||
co.ajax.storeItem = co.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formId: 'frmContact', callbackFn: co.onStoreItem };
|
||||
sbm.doAjaxRequest(co.ajax.storeItem, 50);
|
||||
env.ajax.storeItem = env.ajax.storeItem || { url: sbm.url.base + 'Contact/Ajax/StoreItem', formSel: env.$frm.item, callbackFn: function (response) { co.onStoreItem(env, response); } };
|
||||
sbm.doAjaxRequest(env.ajax.storeItem, 50);
|
||||
}
|
||||
co.onStoreItem = function (response)
|
||||
co.onStoreItem = function (env, response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
//sbm.debug('onStoreItem', env, response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
$pnl.msgs.hide().empty();
|
||||
|
||||
env.$dlg.item.dialog('close');
|
||||
var item = response.contact;
|
||||
var $item = $('#' + co.getItemId(item), $pnl.table);
|
||||
if (!$item.length)
|
||||
if (env.prmEdit)
|
||||
{
|
||||
$item = co.getItemTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
co.onContactEdited(env, item);
|
||||
}
|
||||
else if (env.$pnl.table.length)
|
||||
{
|
||||
env.$pnl.msgs.hide().empty();
|
||||
var $item = $('#' + co.getItemId(item), env.$pnl.table);
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = co.getItemTemplate(env);
|
||||
$('table tbody', env.$pnl.table).prepend($item).show();
|
||||
}
|
||||
co.populateItem(env, $item, item);
|
||||
}
|
||||
co.populateItem($item, item);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.onClickAssociationCount = function (item)
|
||||
co.onClickAssociationCount = function (env, item)
|
||||
{
|
||||
sbm.debug('onClickAssociationCount');
|
||||
//sbm.debug('onClickAssociationCount', env, item);
|
||||
if (!item.id) return;
|
||||
//sbm.doPleaseWait();
|
||||
//let frm = $frm.itemId;
|
||||
//$('.ContactId', frm).val(item.id);
|
||||
//frm.prop('action', sbm.url.base + 'Association').submit();
|
||||
sbm.fn.listAssociations({ ownerId: item.id });
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/* Params: type, search, fnSuccess. */
|
||||
sbm.fn.selectContact = function (prm)
|
||||
{
|
||||
//sbm.debug('selectContact', prm);
|
||||
let env = co.env.select;
|
||||
env.prmSelect = prm;
|
||||
env.$frm.filter.find('.FilterContactType').val('');
|
||||
env.$frm.filter.find('.FilterSearch').val(prm.search || '');
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
sbm.openDialog(env.$dlg.select, 1000, 800);
|
||||
if (env.$pnl.items.length) setTimeout(function () { co.refreshResults(env); }, 250);
|
||||
}
|
||||
co.selectItemRow = function (env, $item, item)
|
||||
{
|
||||
//sbm.debug('selectItemRow', env, $item, item);
|
||||
env.$pnl.table.find('tr').removeClass('sbm-sel');
|
||||
$item.addClass('sbm-sel');
|
||||
env.prmSelect.item = item;
|
||||
}
|
||||
co.selectItem = function (env)
|
||||
{
|
||||
//sbm.debug('selectItem', env, env.prmSelect.item);
|
||||
env.$dlg.select.dialog('close');
|
||||
env.prmSelect.fnSuccess(env.prmSelect.item);
|
||||
delete env.prmSelect;
|
||||
}
|
||||
|
||||
/* Params: id, fnSuccess. */
|
||||
sbm.fn.editContact = function (prm)
|
||||
{
|
||||
//sbm.debug('editContact', prm);
|
||||
let env = co.env.select;
|
||||
env.prmEdit = prm;
|
||||
sbm.debug(env, prm);
|
||||
co.updateItem(env, prm.id);
|
||||
}
|
||||
co.onContactEdited = function (env, item)
|
||||
{
|
||||
//sbm.debug('onContactEdited', env, item);
|
||||
env.prmEdit.fnSuccess(item);
|
||||
delete env.prmEdit;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
co.initContactEnv = function ($pnlItems)
|
||||
{
|
||||
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
|
||||
|
||||
env.$pnl.items = $($pnlItems);
|
||||
env.$pnl.header = env.$pnl.items.find('.sbm-panel-header');
|
||||
env.$pnl.bgr = env.$pnl.header.find('.sbm-burger');
|
||||
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
|
||||
env.$pnl.table = env.$pnl.items.find('.sbm-panel-item-table');
|
||||
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
|
||||
env.$pnl.tmpls = env.$pnl.items.find('.sbm-panel-item-template');
|
||||
|
||||
env.$frm.filter = env.$pnl.items.find('.frmContactFilter');
|
||||
env.$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(env, 250); }).on('change', '.FilterContactType', function () { co.refreshResults(env, 50); });
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.dialogClass += " sbm-Contact";
|
||||
env.$dlg.item = $('#dlgContact').dialog(opt);
|
||||
env.$frm.itemId = $('#frmContactId');
|
||||
env.$frm.item = $('#frmContact').on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.dialogClass += " sbm-Contact";
|
||||
opt.buttons[sbm.lbl.ok] = function () { co.selectItem(env); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { delete env.prmSelect; $(this).dialog('close'); };
|
||||
env.$dlg.select = $('#dlgContactSelect').dialog(opt);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.Contacts');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.bgr = $('.sbm-burger', $pnl.header);
|
||||
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmContactFilter', $pnl.items);
|
||||
$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(250); }).on('change', '.FilterContactType', function () { co.refreshResults(50); });
|
||||
|
||||
$frm.itemId = $('#frmContactId');
|
||||
$frm.item = $('#frmContact');
|
||||
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.ok] = function () { co.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgContact').dialog(opt);
|
||||
|
||||
setTimeout(co.refreshResults, 250);
|
||||
co.env.maint = co.initContactEnv('.sbm-panel.Contacts');
|
||||
if (co.env.maint.$pnl.items.length) setTimeout(function () { co.refreshResults(co.env.maint); }, 250);
|
||||
co.env.select = co.initContactEnv('#dlgContactSelect');
|
||||
co.env.select.$frm.filter.find('.FilterContactType option[value="GRP"]').remove();
|
||||
if (co.env.select.$pnl.items.length) setTimeout(function () { co.refreshConfig(co.env.select); }, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
}
|
||||
sbm.refreshPaging = function (response, context, refreshFn)
|
||||
{
|
||||
if (sbm.resultsPaging.fn.refreshPaging)
|
||||
if (sbm.isFn(sbm.resultsPaging.fn.refreshPaging))
|
||||
sbm.resultsPaging.fn.refreshPaging(response.paging, context, refreshFn);
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
//enctype: 'multipart/form-data',
|
||||
data: ajax.formData || $("#" + ajax.formId).serialize(),
|
||||
data: ajax.formData || $(ajax.formSel || "#" + ajax.formId).serialize(),
|
||||
dataType: 'json',
|
||||
success: function (response, status, jqXHR)
|
||||
{
|
||||
@@ -438,8 +438,7 @@
|
||||
}
|
||||
sbm.triggeRefreshSession = function ()
|
||||
{
|
||||
sbm.session = sbm.session || { refresh: {} };
|
||||
let ssr = sbm.session.refresh;
|
||||
let ssr = sbm.session.refresh = sbm.session.refresh || {};
|
||||
win.clearTimeout(ssr.timeout);
|
||||
ssr.timeout = setTimeout(function () { sbm.refreshSession(); }, 150000);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//--------------------------------------------------------------
|
||||
rp.fn.refreshPaging = function (paging, contextSel, refreshFn)
|
||||
{
|
||||
//sbm.debug('refreshPaging', paging, contextSel, refreshFn);
|
||||
let context = rp.fn.getContext(contextSel, refreshFn);
|
||||
rp.fn.init(context);
|
||||
context.paging = paging = paging || {};
|
||||
|
||||
Reference in New Issue
Block a user