Portal signin via Control Instance
This commit is contained in:
@@ -300,7 +300,7 @@
|
||||
<data name="label.signout" xml:space="preserve">
|
||||
<value>Sign-out</value>
|
||||
</data>
|
||||
<data name="label.Suppliers" xml:space="preserve">
|
||||
<data name="label.suppliers" xml:space="preserve">
|
||||
<value>Suppliers</value>
|
||||
</data>
|
||||
<data name="label.type" xml:space="preserve">
|
||||
@@ -417,4 +417,103 @@
|
||||
<data name="security.msg.warn.sessionExpired" xml:space="preserve">
|
||||
<value>Your session has expired.</value>
|
||||
</data>
|
||||
<data name="caption.asset.category.create" xml:space="preserve">
|
||||
<value>Create Asset Category</value>
|
||||
</data>
|
||||
<data name="caption.asset.create" xml:space="preserve">
|
||||
<value>Create Asset</value>
|
||||
</data>
|
||||
<data name="caption.asset.category.update" xml:space="preserve">
|
||||
<value>Update Asset Category</value>
|
||||
</data>
|
||||
<data name="caption.asset.update" xml:space="preserve">
|
||||
<value>Update Asset</value>
|
||||
</data>
|
||||
<data name="caption.asset.categories" xml:space="preserve">
|
||||
<value>Asset Categories</value>
|
||||
</data>
|
||||
<data name="caption.asset.category" xml:space="preserve">
|
||||
<value>Asset Category</value>
|
||||
</data>
|
||||
<data name="label.assets" xml:space="preserve">
|
||||
<value>Assets</value>
|
||||
</data>
|
||||
<data name="label.asset" xml:space="preserve">
|
||||
<value>Asset</value>
|
||||
</data>
|
||||
<data name="label.status" xml:space="preserve">
|
||||
<value>Status</value>
|
||||
</data>
|
||||
<data name="label.save" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="label.serial" xml:space="preserve">
|
||||
<value>Serial</value>
|
||||
</data>
|
||||
<data name="label.item.selected" xml:space="preserve">
|
||||
<value>Selected item</value>
|
||||
</data>
|
||||
<data name="label.items.available" xml:space="preserve">
|
||||
<value>Available items</value>
|
||||
</data>
|
||||
<data name="caption.category.select" xml:space="preserve">
|
||||
<value>Select Category</value>
|
||||
</data>
|
||||
<data name="label.caption" xml:space="preserve">
|
||||
<value>Caption</value>
|
||||
</data>
|
||||
<data name="caption.vehicle.classes" xml:space="preserve">
|
||||
<value>Vehicle Classes</value>
|
||||
</data>
|
||||
<data name="caption.vehicle.class" xml:space="preserve">
|
||||
<value>Vehicle Class</value>
|
||||
</data>
|
||||
<data name="caption.vehicle.class.create" xml:space="preserve">
|
||||
<value>Create Vehicle Class</value>
|
||||
</data>
|
||||
<data name="caption.vehicle.class.update" xml:space="preserve">
|
||||
<value>Update Vehicle Class</value>
|
||||
</data>
|
||||
<data name="label.make" xml:space="preserve">
|
||||
<value>Make</value>
|
||||
</data>
|
||||
<data name="label.model" xml:space="preserve">
|
||||
<value>Model</value>
|
||||
</data>
|
||||
<data name="label.derivative" xml:space="preserve">
|
||||
<value>Derivative</value>
|
||||
</data>
|
||||
<data name="label.vehicle" xml:space="preserve">
|
||||
<value>Vehicle</value>
|
||||
</data>
|
||||
<data name="label.vehicles" xml:space="preserve">
|
||||
<value>Vehicles</value>
|
||||
</data>
|
||||
<data name="caption.code.types" xml:space="preserve">
|
||||
<value>Code Types</value>
|
||||
</data>
|
||||
<data name="caption.code.type" xml:space="preserve">
|
||||
<value>Code Type</value>
|
||||
</data>
|
||||
<data name="label.codes" xml:space="preserve">
|
||||
<value>Codes</value>
|
||||
</data>
|
||||
<data name="caption.code.type.create" xml:space="preserve">
|
||||
<value>Create Code Type</value>
|
||||
</data>
|
||||
<data name="caption.code.type.update" xml:space="preserve">
|
||||
<value>Update Code Type</value>
|
||||
</data>
|
||||
<data name="caption.code.create" xml:space="preserve">
|
||||
<value>Create Code</value>
|
||||
</data>
|
||||
<data name="caption.code.update" xml:space="preserve">
|
||||
<value>Update Code</value>
|
||||
</data>
|
||||
<data name="label.sequence" xml:space="preserve">
|
||||
<value>Sequence</value>
|
||||
</data>
|
||||
<data name="label.code.type" xml:space="preserve">
|
||||
<value>Code type</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -7,7 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class Program
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Control.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Helpers;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.IO;
|
||||
@@ -16,165 +23,270 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmApplication_Portal : SbmApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private PropertySet properties;
|
||||
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
|
||||
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
|
||||
private ISacsDatabase controlDatabase = null;
|
||||
// Session contexts.
|
||||
private static ushort sessionContextIdx_Next = 100;
|
||||
private class SessionContextData
|
||||
{
|
||||
public SessionContextData(SbmSessionContext_Web sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SbmSessionContext_Web SessionContext { get; }
|
||||
public List<string> DbIdentifiers { get; } = new List<string>();
|
||||
public ISacsDatabase BusMgrDatabase { get; set; }
|
||||
}
|
||||
private readonly Dictionary<int, SessionContextData> sessionContexts = new Dictionary<int, SessionContextData>();
|
||||
//=======================================================================
|
||||
public class SbmApplication_Portal : SbmApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private PropertySet properties;
|
||||
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
|
||||
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
|
||||
private ISacsDatabase controlDatabase = null;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmApplication_Portal(IConfiguration configuration) : base()
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
{
|
||||
properties = new PropertySet();
|
||||
SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Web(properties)));
|
||||
Configuration = configuration;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
// Session contexts.
|
||||
private static ushort sessionContextIdx_Next = 100;
|
||||
private class SessionContextData
|
||||
{
|
||||
public SessionContextData(SbmSessionContext_Web sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SbmSessionContext_Web SessionContext { get; }
|
||||
public HashSet<string> DbIdentifiers { get; } = new HashSet<string>();
|
||||
public ISacsDatabase BusMgrDatabase { get; set; }
|
||||
public virtual SbmInstanceConfig InstanceConfig => null;
|
||||
// Control database properties.
|
||||
public bool IsControl { get { return SysId.IsValid(ControlOwnerId) && SysId.IsValid(ControlRepositoryId); } }
|
||||
public SysId ControlOwnerId { get; protected set; }
|
||||
public SysId ControlRepositoryId { get; protected set; }
|
||||
}
|
||||
private class SessionContextData_Control : SessionContextData
|
||||
{
|
||||
public SessionContextData_Control(SbmSessionContext_Web sessionContext, SysId controlOwnerId, SysId controlRepositoryId) : base(sessionContext)
|
||||
{
|
||||
this.ControlOwnerId = controlOwnerId;
|
||||
this.ControlRepositoryId = controlRepositoryId;
|
||||
}
|
||||
private SbmInstanceConfig instanceConfig = null;
|
||||
public override SbmInstanceConfig InstanceConfig
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instanceConfig == null)
|
||||
instanceConfig = new SbmInstanceConfig_Web(ControlOwnerId, ControlRepositoryId);
|
||||
return instanceConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
private readonly Dictionary<int, SessionContextData> sessionContexts = new Dictionary<int, SessionContextData>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmApplication_Portal(IConfiguration configuration) : base()
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
{
|
||||
properties = new PropertySet();
|
||||
SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Web(properties)));
|
||||
Configuration = configuration;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error($"{GetType().Name}.CTR {ExceptionUtil.GetErrorStateMessage(exc)}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
if (Instance != null)
|
||||
SaLogger.Error($"{SysUtil.Fn} Application instance already established.");
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Application Configuration.
|
||||
public override SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
// Session Configuration.
|
||||
public override String SessionCookieName { get { return Sbm.Config.Portal.Session.Cookie.Name; } }
|
||||
public override List<ushort> GetSessionContextIdxs()
|
||||
{
|
||||
return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList();
|
||||
}
|
||||
public override SbmSessionContext GetSessionContext(ushort index)
|
||||
{
|
||||
return sessionContexts.GetValue(index, null)?.SessionContext ?? null;
|
||||
}
|
||||
public override ISacsDatabase GetControlDatabase()
|
||||
{
|
||||
return controlDatabase;
|
||||
}
|
||||
public override ISacsDatabase GetTemplateDatabase()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override List<string> GetDbIdentifiers(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.DbIdentifiers ?? new List<string>();
|
||||
}
|
||||
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
|
||||
}
|
||||
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static SbmApplication_Portal Instance { get; private set; }
|
||||
// Application Configuration.
|
||||
public override SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
// Session Configuration.
|
||||
public override String SessionCookieName { get { return Sbm.Config.Portal.Session.Cookie.Name; } }
|
||||
// Session Contexts - available BusMgr instances.
|
||||
public override List<ushort> GetSessionContextIdxs()
|
||||
{
|
||||
return sessionContexts.Values.Select(item => item.SessionContext.Index).ToList();
|
||||
}
|
||||
public override SbmSessionContext GetSessionContext(ushort index)
|
||||
{
|
||||
return sessionContexts.GetValue(index, null)?.SessionContext;
|
||||
}
|
||||
public SbmSessionContext GetControlSessionContext(String dbIdentifier)
|
||||
{
|
||||
return PopulateControlSessionContext(dbIdentifier)?.SessionContext;
|
||||
}
|
||||
public override HashSet<string> GetDbIdentifiers(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.DbIdentifiers ?? new HashSet<string>();
|
||||
}
|
||||
// Databases.
|
||||
public override ISacsDatabase GetControlDatabase()
|
||||
{
|
||||
return controlDatabase;
|
||||
}
|
||||
public override ISacsDatabase GetTemplateDatabase()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
|
||||
}
|
||||
// Email configuration.
|
||||
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
/// <summary>Initialise environment - from Startup.</summary>
|
||||
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
InitEnvironment(env);
|
||||
}
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sbm-Web-Onl";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
//-------------------------------------------------------------------
|
||||
// Create Consoles.
|
||||
public override SbmEmailConsole CreateEmailConsole(ISbmUserContext_Core userContext)
|
||||
{
|
||||
return new SbmEmailConsole_Portal(EmailConfig);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SbmSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SbmConfiguration = builder.Build();
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
/// <summary>Initialise environment - from Startup.</summary>
|
||||
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
InitEnvironment(env);
|
||||
}
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sbm-Web-Onl";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
|
||||
// Application configuration.
|
||||
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("EmailConfigs"));
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SbmSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SbmConfiguration = builder.Build();
|
||||
|
||||
// Application instance.
|
||||
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sbm.InstanceType.Dev;
|
||||
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sbm.InstanceType.QC;
|
||||
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sbm.InstanceType.UAT;
|
||||
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sbm.InstanceType.UAT;
|
||||
// Application configuration.
|
||||
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("EmailConfigs"));
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
|
||||
// Initialise hard-coded logging path.
|
||||
if (StringUtil.IsEmpty(LoggingRootFolder))
|
||||
{
|
||||
if (SbmSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
||||
LoggingRootFolder = @"D:\Sbmonite\Logs\" + (Development ? "Dev" : "Test");
|
||||
}
|
||||
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
||||
SaLogger.LogFolder = LoggingRootFolder;
|
||||
LogApplicationStart($"{SysUtil.Fn}");
|
||||
// Application instance.
|
||||
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sbm.InstanceType.Dev;
|
||||
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sbm.InstanceType.QC;
|
||||
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sbm.InstanceType.UAT;
|
||||
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sbm.InstanceType.UAT;
|
||||
|
||||
// Initialise hard-coded logging path.
|
||||
if (StringUtil.IsEmpty(LoggingRootFolder))
|
||||
{
|
||||
if (SbmSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
||||
LoggingRootFolder = @"D:\Sbmonite\Logs\" + (Development ? "Dev" : "Test");
|
||||
}
|
||||
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
||||
SaLogger.LogFolder = LoggingRootFolder;
|
||||
LogApplicationStart($"{SysUtil.Fn}");
|
||||
|
||||
// Control database connection.
|
||||
SacsDatabaseConsole.OdbcConfig odbcConfig = new SacsDatabaseConsole.OdbcConfig();
|
||||
odbcConfig.location = AppConfig.ControlDatabase.Location;
|
||||
odbcConfig.user = AppConfig.ControlDatabase.User;
|
||||
odbcConfig.pword = AppConfig.ControlDatabase.Password;
|
||||
controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
||||
if (controlDatabase.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
|
||||
odbcConfig.location = AppConfig.ControlDatabase.Location;
|
||||
odbcConfig.user = AppConfig.ControlDatabase.User;
|
||||
odbcConfig.pword = AppConfig.ControlDatabase.Password;
|
||||
controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
||||
if (controlDatabase.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
|
||||
|
||||
// Configure BusMgr database connections.
|
||||
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
|
||||
{
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = dbConfig.Location;
|
||||
config.user = dbConfig.User;
|
||||
config.pword = dbConfig.Password;
|
||||
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
if (!coreDatabase.HasErrorState())
|
||||
{
|
||||
// Session context.
|
||||
ushort sessionContextIdx = sessionContextIdx_Next++;
|
||||
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal));
|
||||
sessionContextData.BusMgrDatabase = coreDatabase;
|
||||
sessionContextData.DbIdentifiers.AddRange(dbConfig.Identifiers);
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Database: " + coreDatabase.DatabaseName + ". Initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error($"{SysUtil.Fn} " + ExceptionUtil.GetLogMessage(exc));
|
||||
}
|
||||
}
|
||||
// Configure BusMgr database connections.
|
||||
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
|
||||
{
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = dbConfig.Location;
|
||||
config.user = dbConfig.User;
|
||||
config.pword = dbConfig.Password;
|
||||
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
if (!coreDatabase.HasErrorState())
|
||||
{
|
||||
// Session context.
|
||||
ushort sessionContextIdx = sessionContextIdx_Next++;
|
||||
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal));
|
||||
sessionContextData.BusMgrDatabase = coreDatabase;
|
||||
sessionContextData.DbIdentifiers.UnionWith(dbConfig.Identifiers);
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Database: " + coreDatabase.DatabaseName + ". Initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error($"{SysUtil.Fn} " + ExceptionUtil.GetLogMessage(exc));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
//-------------------------------------------------------------------
|
||||
private SessionContextData PopulateControlSessionContext(String dbIdentifier)
|
||||
{
|
||||
if (StringUtil.IsBlank(dbIdentifier)) return null;
|
||||
|
||||
// Check whether context already exists in cache.
|
||||
SessionContextData sessionContextData = sessionContexts.Values.FirstOrDefault(sc => sc.IsControl && sc.DbIdentifiers.ContainsCI(dbIdentifier));
|
||||
using (DisposableCollection<IDisposable> disposables = new DisposableCollection<IDisposable>())
|
||||
{
|
||||
SbmcInstanceMgr controlInstanceMgr = SbmGlobals_Web.System.CreateControlInstanceMgr();
|
||||
if (controlInstanceMgr == null) return null;
|
||||
disposables.Add(controlInstanceMgr);
|
||||
|
||||
// Check whether context is defined in Control database (and active).
|
||||
SbmcRepository.Params prmRepository = new SbmcRepository.Params();
|
||||
prmRepository.ContextsIncluded.Add(dbIdentifier);
|
||||
SbmcRepository repository = controlInstanceMgr.GetRepository(prmRepository);
|
||||
disposables.Add(repository);
|
||||
|
||||
// Retrieve Repository Owner.
|
||||
SbmcOwner owner = controlInstanceMgr.GetOwnerById(repository?.OwnerId);
|
||||
disposables.Add(owner);
|
||||
|
||||
// Validate configuration.
|
||||
if (repository != null && owner != null)
|
||||
{
|
||||
if (owner.IsStatusActive && repository.IsStatusActive)
|
||||
{
|
||||
// Configure Core database.
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = $"MsSql:{repository.ServerName}\\{repository.InstanceName}.{repository.DatabaseName}";
|
||||
config.user = repository.UserName;
|
||||
config.pword = repository.Password;
|
||||
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
|
||||
if (!coreDatabase.HasErrorState())
|
||||
{
|
||||
// Create Session Context if not not currently populated.
|
||||
if (sessionContextData == null)
|
||||
{
|
||||
// New Session context.
|
||||
ushort sessionContextIdx = sessionContextIdx_Next++;
|
||||
sessionContextData = new SessionContextData_Control(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal), owner.Id, repository.Id);
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
SaLogger.Info($"{SysUtil.Fn} Control Instance initialised: Context: {repository.Context}. Database: {repository.DatabaseName}.");
|
||||
}
|
||||
else SaLogger.Info($"{SysUtil.Fn} Control Instance refreshed: Context: {repository.Context}. Database: {repository.DatabaseName}.");
|
||||
|
||||
// Refresh properties.
|
||||
sessionContextData.DbIdentifiers.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}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return sessionContextData;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web
|
||||
namespace Sarand.BusinessMgr.Web
|
||||
{
|
||||
// <summary>
|
||||
/// Dummy classes to group shared resources - named as per '.resx' file in root namespace.
|
||||
@@ -19,7 +19,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web
|
||||
// Ref. Project Properties - Application.
|
||||
}
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmLocaliser_Portal : SbmLocaliser
|
||||
|
||||
@@ -1,73 +1,99 @@
|
||||
using Newtonsoft.Json;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers;
|
||||
using Sarand.BusinessMgr.Web.Portal.Controllers;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Security;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmSessionData_Portal : SbmSessionData_Web
|
||||
public class SbmSessionData_Portal : SbmSessionData_Web, ISbmUserContext_Core
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
[JsonConstructor]
|
||||
private SbmSessionData_Portal(long sessionIdx, int itemIdx, SbmSessionContext sessionContext) :
|
||||
base(sessionIdx, itemIdx, sessionContext)
|
||||
{}
|
||||
{
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
Organisation = new OrganisationData_Portal(null, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// SessionData construction.
|
||||
/// <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) :
|
||||
base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation)
|
||||
base(sessionContext)
|
||||
{
|
||||
DbIdentifier = dbIdentifier;
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
Organisation = new OrganisationData_Portal(associationOrganisation, affiliateOrganisation);
|
||||
User = new UserData_Portal(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Contact details.
|
||||
private class UserData_Portal : UserData
|
||||
{
|
||||
public UserData_Portal(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations) :
|
||||
base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations)
|
||||
{ }
|
||||
public UserData_Portal(UserData userData) :
|
||||
base(userData)
|
||||
{ }
|
||||
public new bool Refresh(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations)
|
||||
{
|
||||
return base.Refresh(securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
}
|
||||
}
|
||||
protected override UserData CreateUserData(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations)
|
||||
{
|
||||
return new UserData_Portal(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
}
|
||||
/// <summary>User - JSON deserialisation route.</summary>
|
||||
//public new UserData User { get { return base.User; } set { SetUser(new UserData_Portal(value)); } }
|
||||
// Properties.
|
||||
|
||||
/// <summary>
|
||||
/// Update the user's contact details against the session.
|
||||
/// <para>- User identity must match that already against the session.</para>
|
||||
/// </summary>
|
||||
public bool RefreshUser(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
// User properties.
|
||||
[JsonIgnore]
|
||||
/// <summary>User Security Item Id.</summary>
|
||||
public SysId UserSecurityItemId { get { return User?.SecurityItemId; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>User Affiliate Id.</summary>
|
||||
public SysId UserAffiliateId { get { return User?.AffiliateId; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>User display name.</summary>
|
||||
public override String UserDisplayName { get { return User?.DisplayName; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>User email address.</summary>
|
||||
public override String UserEmailAddress { get { return User?.EmailAddress; } }
|
||||
[JsonIgnore]
|
||||
public override bool ValidUser { get { return SysId.IsValid(UserSecurityItemId) && SysId.IsValid(UserAffiliateId); } }
|
||||
[JsonIgnore]
|
||||
public override bool KeepLoggedIn { get { return User.KeepLoggedIn; } }
|
||||
|
||||
// Organisation properties.
|
||||
[JsonIgnore]
|
||||
/// <summary>Organisation Affiliate Id.</summary>
|
||||
public SysId OrganisationAffiliateId { get { return Organisation?.AffiliateId; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>Organisation Affiliate Type.</summary>
|
||||
public Sbm.AffiliateType OrganisationAffiliateType { get { return Organisation?.AffiliateType ?? Sbm.AffiliateType.Unknown; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>Organisation 'Internal' Association Id.</summary>
|
||||
public SysId OrganisationAssociationId { get { return Organisation?.AssociationId; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>Organisation display name.</summary>
|
||||
public String OrganisationDisplayName { get { return Organisation?.DisplayName; } }
|
||||
[JsonIgnore]
|
||||
/// <summary>Organisation Interface context - to qualify interfaces belonging to the organisation.</summary>
|
||||
public String OrganisationInterfaceContext { get { return Organisation?.InterfaceContext; } }
|
||||
|
||||
|
||||
// Database properties.
|
||||
[JsonIgnore]
|
||||
public override DbUpdateInfo DbUpdateInfo
|
||||
{
|
||||
UserData_Portal user = User as UserData_Portal;
|
||||
if (user != null)
|
||||
return user.Refresh(securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
organisationData = new OrganisationData(associationOrganisation, affiliateOrganisation);
|
||||
return false;
|
||||
get
|
||||
{
|
||||
return new DbUpdateInfo(User?.AffiliateId, StringUtil.OnEmpty(User.DisplayName, User.EmailAddress), SbmSystem.ComputerName);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -76,6 +102,111 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
/// <summary>Database context specified on sign-in.</summary>
|
||||
public String DbIdentifier { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security Profile.
|
||||
private readonly SbmSecurityProfile securityProfile;
|
||||
public ISbmSecurityProfile_Core SecurityProfile_Core { get { return securityProfile; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation.
|
||||
public class OrganisationData_Portal
|
||||
{
|
||||
private OrganisationData_Portal() { }
|
||||
public OrganisationData_Portal(SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
{
|
||||
AffiliateId = affiliateOrganisation?.Id ?? null;
|
||||
AffiliateType = affiliateOrganisation?.AffiliateType ?? Sbm.AffiliateType.Unknown;
|
||||
AssociationId = associationOrganisation?.Id ?? null;
|
||||
DisplayName = affiliateOrganisation?.GetDisplayName() ?? "";
|
||||
InterfaceContext = SbmAccountMgr.GetInterfaceContext(AffiliateId);
|
||||
}
|
||||
public SysId AffiliateId { get; protected set; }
|
||||
public Sbm.AffiliateType AffiliateType { get; protected set; }
|
||||
public SysId AssociationId { get; protected set; }
|
||||
public String DisplayName { get; protected set; }
|
||||
public String InterfaceContext { get; }
|
||||
}
|
||||
public OrganisationData_Portal Organisation { get; private set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User details.
|
||||
public class UserData_Portal : UserData
|
||||
{
|
||||
[JsonConstructor]
|
||||
private UserData_Portal() { }
|
||||
public UserData_Portal(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations) :
|
||||
base(sessionContext)
|
||||
{
|
||||
if (securityItemUser != null)
|
||||
{
|
||||
SecurityItemId = securityItemUser.Id;
|
||||
}
|
||||
if (affiliateUser != null)
|
||||
{
|
||||
AffiliateId = affiliateUser.Id;
|
||||
Refresh(securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
if (sessionContext.Application == Sbm.Application.WebControl)
|
||||
KeepLoggedIn = affiliateUser.KeepLoggedIn_Control;
|
||||
else if (sessionContext.Application == Sbm.Application.WebPortal)
|
||||
KeepLoggedIn = affiliateUser.KeepLoggedIn_Portal;
|
||||
else Debugger.Break();
|
||||
}
|
||||
this.supervisedOrganisations = supervisedOrganisations ?? new List<SysIdString>();
|
||||
}
|
||||
public UserData_Portal(UserData userData) :
|
||||
base(userData)
|
||||
{
|
||||
UserData_Portal userData_Portal = userData as UserData_Portal;
|
||||
if (userData_Portal != null)
|
||||
{
|
||||
SecurityItemId = userData_Portal.SecurityItemId;
|
||||
AffiliateId = userData_Portal.AffiliateId;
|
||||
supervisedOrganisations = userData_Portal.supervisedOrganisations;
|
||||
}
|
||||
}
|
||||
// Properties.
|
||||
public SysId SecurityItemId { get; protected set; }
|
||||
public SysId AffiliateId { get; protected set; }
|
||||
public bool KeepLoggedIn { get; private set; }
|
||||
/// <summary>User managed associations - Id and display name.</summary>
|
||||
public List<SysIdString> SupervisedOrganisations { get { return new List<SysIdString>(supervisedOrganisations); } }
|
||||
protected List<SysIdString> supervisedOrganisations { get; } = new List<SysIdString>();
|
||||
// Utilities.
|
||||
public bool Refresh(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations)
|
||||
{
|
||||
base.Refresh();
|
||||
// Check that user matches the session.
|
||||
if (!SysId.IsValid(SecurityItemId) || !SysId.IsValid(securityItemUser?.Id ?? null) || !SecurityItemId.Equals(securityItemUser.Id)) return false;
|
||||
if (!SysId.IsValid(AffiliateId) || !SysId.IsValid(affiliateUser?.Id ?? null) || !AffiliateId.Equals(affiliateUser.Id)) return false;
|
||||
// Refresh properties.
|
||||
EmailAddress = securityItemUser.EmailAddress;
|
||||
Title = affiliateUser.Title;
|
||||
FirstName = affiliateUser.FirstName;
|
||||
LastName = affiliateUser.LastName;
|
||||
DisplayName = affiliateUser.GetDisplayName();
|
||||
this.supervisedOrganisations.Clear();
|
||||
this.supervisedOrganisations.AddRange(supervisedOrganisations);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Portal User details.</summary>
|
||||
public UserData_Portal User { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Update the user's contact details against the session.
|
||||
/// <para>- User identity must match that already against the session.</para>
|
||||
/// </summary>
|
||||
public bool RefreshUser(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
{
|
||||
if (User != null && User.Refresh(securityItemUser, affiliateUser, supervisedOrganisations))
|
||||
{
|
||||
Organisation = new OrganisationData_Portal(associationOrganisation, affiliateOrganisation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// User Profile.
|
||||
@@ -137,11 +268,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
}
|
||||
public UserProfileData Profile { get; protected set; } = new UserProfileData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Portal application encryption IV value - for consistent encryption during session.
|
||||
public String Base64IV_PortalApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Portal.Base64Key_OnlineApp);
|
||||
public String Base64IV_PortalApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Portal.Base64Key_PortalApp);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.App
|
||||
namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmStartup_Portal : SbmStartup_Web
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Control.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmEmailConsole_Portal : SbmEmailConsole_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmEmailConsole_Portal(SbmEmailConfig emailConfig) :
|
||||
base(emailConfig)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class AssetCategoryController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// AssetCategory data.
|
||||
private class AssetCategoryListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String TypeDesc { get; set; }
|
||||
public String Code { get; set; }
|
||||
public String DescBrief { get; set; }
|
||||
public long? AssetCount { get; set; }
|
||||
}
|
||||
private class AssetCategoryItemData : AssetCategoryListData
|
||||
{
|
||||
public String TypeCode { get; set; }
|
||||
}
|
||||
private void PopulateAssetCategoryResponseListData(SbmModel_Portal model, AssetCategoryListData data, SbmAssetCategory assetCategory)
|
||||
{
|
||||
data.Id = SysId.ToString(assetCategory.Id);
|
||||
data.TypeDesc = Internals.AssetTypeCodes.GetDescForType(assetCategory.AssetType);
|
||||
data.Code = assetCategory.Code;
|
||||
data.DescBrief = assetCategory.DescBrief;
|
||||
data.StatusCode = assetCategory.StatusCode;
|
||||
data.StatusDesc = assetCategory.StatusDesc;
|
||||
}
|
||||
private void PopulateAssetCategoryResponseItemData(SbmModel_Portal model, AssetCategoryItemData data, SbmAssetCategory assetCategory)
|
||||
{
|
||||
PopulateAssetCategoryResponseListData(model, data, assetCategory);
|
||||
data.TypeCode = Internals.AssetTypeCodes.GetCodeForType(assetCategory.AssetType);
|
||||
data.Notes = assetCategory.Notes;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get AssetCategory List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_AssetCategoryList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_AssetCategoryList(SbmModel_Portal model) : base(model) { }
|
||||
// AssetCategory list.
|
||||
public List<AssetCategoryListData> AssetCategories { get; } = new List<AssetCategoryListData>();
|
||||
// Reference data.
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
|
||||
public String StatusCodeDefault { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/AssetCategory/Ajax/GetList")]
|
||||
[Route("Assets/AssetCategory/Ajax/GetAssetCategories")]
|
||||
[Route("Assets/AssetCategory/Ajax/GetAssetCategoryList")]
|
||||
public IActionResult Ajax_GetAssetCategoryList(Model_AssetCategory model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetAssetCategoryList";
|
||||
String messageTitle = Localiser["caption.asset.categories"];
|
||||
AjaxResponse_AssetCategoryList responseData = new AjaxResponse_AssetCategoryList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Reference data - statuses.
|
||||
foreach (SaStatus status in SbmAssetCategory.ValidStatuses)
|
||||
{
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
if (status != SaStatus.Deleted)
|
||||
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
}
|
||||
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmAssetCategory.DefaultStatus);
|
||||
|
||||
// Item filter.
|
||||
SbmAssetCategory.Params prmAssetCategory = new SbmAssetCategory.Params();
|
||||
prmAssetCategory.Search = model.Filter.Search;
|
||||
prmAssetCategory.StatusCat = model.Filter.GetStatusCat();
|
||||
model.Paging.ItemTotal = (ulong)AssetMgr.GetAssetCategoryCount(prmAssetCategory);
|
||||
model.PopulatePagingTo(prmAssetCategory.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.Id);
|
||||
ColumnDfn colType = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.AssetType_Desc);
|
||||
ColumnDfn colCode = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.Code);
|
||||
ColumnDfn colDescBrief = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.DescBrief);
|
||||
ColumnDfn colAssetCount = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.AssetCount);
|
||||
ColumnDfn colStatus = AssetMgr.GetAssetCategoryColumnDfn(SbmAssetCategory.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colType, colCode, colDescBrief,
|
||||
colAssetCount, colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = AssetMgr.ExecuteAssetCategoryQuery(columns, prmAssetCategory))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
Sbm.AssetType assetType = (Sbm.AssetType)values.GetLong(colType.DataName);
|
||||
AssetCategoryListData assetCategoryData = new AssetCategoryListData()
|
||||
{
|
||||
Id = values.GetLong(colId.DataName).ToString(),
|
||||
TypeDesc = Localiser.GetAssetTypeCaption(assetType),
|
||||
Code = values.GetString(colCode.DataName),
|
||||
DescBrief = values.GetString(colDescBrief.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
long assetCount = values.GetLong(colAssetCount.DataName);
|
||||
if (assetCount > 0)
|
||||
assetCategoryData.AssetCount = assetCount;
|
||||
responseData.AssetCategories.Add(assetCategoryData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.AssetCategories.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get AssetCategory ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_AssetCategory : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_AssetCategory(SbmModel_Portal model) : base(model) { }
|
||||
// AssetCategory details.
|
||||
public AssetCategoryItemData assetCategory { get; } = new AssetCategoryItemData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/AssetCategory/Ajax/GetItem")]
|
||||
[Route("Assets/AssetCategory/Ajax/GetAssetCategory")]
|
||||
public IActionResult Ajax_GetAssetCategory(Model_AssetCategory model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetAssetCategory";
|
||||
String messageTitle = Localiser["caption.asset.category"];
|
||||
AjaxResponse_AssetCategory responseData = new AjaxResponse_AssetCategory(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId assetCategoryId = model.AssetCategory.Id.ToSysId();
|
||||
if (!SysId.IsValid(assetCategoryId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SbmAssetCategory assetCategory = AssetMgr.GetAssetCategoryById(assetCategoryId);
|
||||
disposables.Add(assetCategory);
|
||||
if (assetCategory == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve assetCategory for Id: '" + assetCategoryId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateAssetCategoryResponseItemData(model, responseData.assetCategory, assetCategory);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store AssetCategory ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/AssetCategory/Ajax/StoreItem")]
|
||||
[Route("Assets/AssetCategory/Ajax/StoreAssetCategory")]
|
||||
public IActionResult Ajax_StoreAssetCategory(Model_AssetCategory model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreAssetCategory";
|
||||
String messageTitle = Localiser["caption.asset.category"];
|
||||
AjaxResponse_AssetCategory responseData = new AjaxResponse_AssetCategory(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate item Id.
|
||||
SysId assetCategoryId = model.AssetCategory.Id.ToSysId();
|
||||
if (StringUtil.ToBool(model.AssetCategory.Exists) && !SysId.IsValid(assetCategoryId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} AssetCategory Id not supplied for existing item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!StringUtil.ToBool(model.AssetCategory.Exists) && SysId.IsValid(assetCategoryId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} AssetCategory Id supplied for new item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateAssetCategoryData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SbmAssetCategory assetCategory = AssetMgr.GetAssetCategoryById(assetCategoryId);
|
||||
disposables.Add(assetCategory);
|
||||
if (assetCategory == null && SysId.IsValid(assetCategoryId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Asset Category for Id: '" + model.AssetCategory.Id + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (assetCategory == null)
|
||||
{
|
||||
if (model.AssetCategory.AssetType == 0)
|
||||
{
|
||||
// Should be picked up by model validation unless form doesn't include Asset Type.
|
||||
SaLogger.Warn($"{SysUtil.Fn} Asset Type not specified for new Asset Category.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
assetCategory = AssetMgr.CreateAssetCategory(model.AssetCategory.AssetType);
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.AssetCategory.Code != null)
|
||||
assetCategory.Code = model.AssetCategory.Code;
|
||||
if (model.AssetCategory.DescBrief != null)
|
||||
assetCategory.DescBrief = model.AssetCategory.DescBrief;
|
||||
if (model.AssetCategory.StatusCode != null)
|
||||
assetCategory.Status = model.AssetCategory.GetStatus();
|
||||
if (model.AssetCategory.Notes != null)
|
||||
assetCategory.Notes = model.AssetCategory.Notes;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(assetCategory.Id))
|
||||
{
|
||||
if (!AssetMgr.InsertAssetCategory(assetCategory, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset Category: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AssetMgr.UpdateAssetCategory(assetCategory, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset Category [Id:" + SysId.ToString(assetCategory.Id) + "]: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateAssetCategoryResponseItemData(model, responseData.assetCategory, assetCategory);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class AssetCategoryController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public AssetCategoryController(SbmLocaliser localiser, ILogger<AssetCategoryController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Assets/AssetCategory")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// AssetCategory page.
|
||||
Model_AssetCategory model = new Model_AssetCategory(Localiser);
|
||||
return View("Views/Assets/AssetCategory/Index.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class AssetController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// Asset data.
|
||||
private class AssetListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String CategoryDesc { get; set; }
|
||||
public String SerialNumber { get; set; }
|
||||
public String DescBrief { get; set; }
|
||||
}
|
||||
private class AssetItemData : AssetListData
|
||||
{
|
||||
public String CategoryId { get; set; }
|
||||
public String RefExt { get; set; }
|
||||
public String ItemCaption { get; set; }
|
||||
public String PurchaseOn_Form { get; set; }
|
||||
public String AssocIdSupplier { get; set; }
|
||||
public String SupplierCaption { get; set; }
|
||||
public String PurchaseInvoiceRef { get; set; }
|
||||
}
|
||||
private void PopulateAssetResponseListData(SbmModel_Portal model, AssetListData data, SbmAssetCategory assetCategory, SbmAsset asset)
|
||||
{
|
||||
data.Id = SysId.ToString(asset.Id);
|
||||
data.CategoryDesc = assetCategory.DescBrief;
|
||||
data.SerialNumber = asset.SerialNumber;
|
||||
data.DescBrief = asset.DescBrief;
|
||||
data.StatusCode = asset.StatusCode;
|
||||
data.StatusDesc = asset.StatusDesc;
|
||||
}
|
||||
private void PopulateAssetResponseItemData(SbmModel_Portal model, AssetItemData data, SbmAssetCategory assetCategory, SbmAsset asset)
|
||||
{
|
||||
PopulateAssetResponseListData(model, data, assetCategory, asset);
|
||||
data.CategoryId = SysId.ToString(asset.AssetCategoryId);
|
||||
data.RefExt = asset.RefExt;
|
||||
data.ItemCaption = null;
|
||||
data.PurchaseOn_Form = null;
|
||||
data.AssocIdSupplier = SysId.ToString(asset.AssocIdSupplier);
|
||||
data.SupplierCaption = null;
|
||||
data.PurchaseInvoiceRef = null;
|
||||
data.Notes = asset.Notes;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Asset List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_AssetList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_AssetList(SbmModel_Portal model) : base(model) { }
|
||||
// Asset list.
|
||||
public List<AssetListData> Assets { get; } = new List<AssetListData>();
|
||||
// Reference data.
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
|
||||
public String StatusCodeDefault { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/Asset/Ajax/GetList")]
|
||||
[Route("Assets/Asset/Ajax/GetAssets")]
|
||||
[Route("Assets/Asset/Ajax/GetAssetList")]
|
||||
public IActionResult Ajax_GetAssetList(Model_Asset model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetAssetList";
|
||||
String messageTitle = Localiser["label.assets"];
|
||||
AjaxResponse_AssetList responseData = new AjaxResponse_AssetList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Reference data - statuses.
|
||||
foreach (SaStatus status in SbmAsset.ValidStatuses)
|
||||
{
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
if (status != SaStatus.Deleted)
|
||||
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
}
|
||||
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmAsset.DefaultStatus);
|
||||
|
||||
// Item filter.
|
||||
SbmAsset.Params prmAsset = new SbmAsset.Params();
|
||||
prmAsset.Search = model.Filter.Search;
|
||||
prmAsset.StatusCat = model.Filter.GetStatusCat();
|
||||
model.Paging.ItemTotal = (ulong)AssetMgr.GetAssetCount(prmAsset);
|
||||
model.PopulatePagingTo(prmAsset.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Id);
|
||||
ColumnDfn colCategoryDesc = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Category_DescBrief);
|
||||
ColumnDfn colSerial = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.SerialNumber);
|
||||
ColumnDfn colDescBrief = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.DescBrief);
|
||||
ColumnDfn colStatus = AssetMgr.GetAssetColumnDfn(SbmAsset.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colCategoryDesc, colSerial, colDescBrief,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = AssetMgr.ExecuteAssetQuery(columns, prmAsset))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
AssetListData assetData = new AssetListData()
|
||||
{
|
||||
Id = values.GetLong(colId.DataName).ToString(),
|
||||
CategoryDesc = values.GetString(colCategoryDesc.DataName),
|
||||
SerialNumber = values.GetString(colSerial.DataName),
|
||||
DescBrief = values.GetString(colDescBrief.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Assets.Add(assetData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.Assets.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Asset ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_Asset : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_Asset(SbmModel_Portal model) : base(model) { }
|
||||
// Asset details.
|
||||
public AssetItemData asset { get; } = new AssetItemData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/Asset/Ajax/GetItem")]
|
||||
[Route("Assets/Asset/Ajax/GetAsset")]
|
||||
public IActionResult Ajax_GetAsset(Model_Asset model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetAsset";
|
||||
String messageTitle = Localiser["label.asset"];
|
||||
AjaxResponse_Asset responseData = new AjaxResponse_Asset(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId assetId = model.Asset.Id.ToSysId();
|
||||
if (!SysId.IsValid(assetId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SbmAsset asset = AssetMgr.GetAssetById(assetId);
|
||||
disposables.Add(asset);
|
||||
if (asset == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve asset for Id: '" + assetId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve category.
|
||||
SbmAssetCategory assetCategory = AssetMgr.GetAssetCategoryById(asset.AssetCategoryId);
|
||||
disposables.Add(assetCategory);
|
||||
if (assetCategory == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve asset category for Id: '" + asset.AssetCategoryId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateAssetResponseItemData(model, responseData.asset, assetCategory, asset);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Asset ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/Asset/Ajax/StoreItem")]
|
||||
[Route("Assets/Asset/Ajax/StoreAsset")]
|
||||
public IActionResult Ajax_StoreAsset(Model_Asset model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreAsset";
|
||||
String messageTitle = Localiser["label.asset"];
|
||||
AjaxResponse_Asset responseData = new AjaxResponse_Asset(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate item Id.
|
||||
SysId assetId = model.Asset.Id.ToSysId();
|
||||
if (StringUtil.ToBool(model.Asset.Exists) && !SysId.IsValid(assetId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Asset Id not supplied for existing item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!StringUtil.ToBool(model.Asset.Exists) && SysId.IsValid(assetId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Asset Id supplied for new item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateAssetData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SbmAsset asset = AssetMgr.GetAssetById(assetId);
|
||||
disposables.Add(asset);
|
||||
if (asset == null && SysId.IsValid(assetId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Asset for Id: '" + model.Asset.Id + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve category.
|
||||
SbmAssetCategory assetCategory = null;
|
||||
if (asset != null)
|
||||
{
|
||||
assetCategory = AssetMgr.GetAssetCategoryById(asset.AssetCategoryId);
|
||||
disposables.Add(assetCategory);
|
||||
if (assetCategory == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Asset Category for existing Asset. Id: '" + asset.AssetCategoryId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assetCategory = AssetMgr.GetAssetCategoryById(model.Asset.CategoryId.ToSysId());
|
||||
disposables.Add(assetCategory);
|
||||
if (assetCategory == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Asset Category for new Asset. Id: '" + model.Asset.CategoryId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (asset == null)
|
||||
{
|
||||
if (assetCategory == null || !SysId.IsValid(assetCategory.Id))
|
||||
{
|
||||
// Should be picked up by model validation unless form doesn't include Asset Category.
|
||||
SaLogger.Warn($"{SysUtil.Fn} Asset Category not specified for new Asset.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
asset = AssetMgr.CreateAsset(assetCategory.Id);
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.Asset.SerialNumber != null)
|
||||
asset.SerialNumber = model.Asset.SerialNumber;
|
||||
if (model.Asset.DescBrief != null)
|
||||
asset.DescBrief = model.Asset.DescBrief;
|
||||
if (model.Asset.StatusCode != null)
|
||||
asset.Status = model.Asset.GetStatus();
|
||||
if (model.Asset.Notes != null)
|
||||
asset.Notes = model.Asset.Notes;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(asset.Id))
|
||||
{
|
||||
if (!AssetMgr.InsertAsset(asset, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AssetMgr.UpdateAsset(asset, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset [Id:" + SysId.ToString(asset.Id) + "]: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateAssetResponseItemData(model, responseData.asset, assetCategory, asset);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class AssetController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public AssetController(SbmLocaliser localiser, ILogger<AssetController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Assets/Asset")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Asset page.
|
||||
Model_Asset model = new Model_Asset(Localiser);
|
||||
return View("Views/Assets/Asset/Index.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class VehicleClassController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// VehicleClass data.
|
||||
private class VehicleClassListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String MakeDesc { get; set; }
|
||||
public String Model { get; set; }
|
||||
public String Derivative { get; set; }
|
||||
public String DescBrief { get; set; }
|
||||
public long? VehicleCount { get; set; }
|
||||
}
|
||||
private class VehicleClassItemData : VehicleClassListData
|
||||
{
|
||||
public String MakeCode { get; set; }
|
||||
}
|
||||
private void PopulateVehicleClassResponseListData(SbmModel_Portal model, VehicleClassListData data, SbmVehicleClass vehicleClass)
|
||||
{
|
||||
data.Id = SysId.ToString(vehicleClass.Id);
|
||||
data.MakeDesc = GetMakeDesc(vehicleClass.MakeCode);
|
||||
data.Model = vehicleClass.Model;
|
||||
data.Derivative = vehicleClass.Derivative;
|
||||
data.DescBrief = vehicleClass.DescBrief;
|
||||
data.StatusCode = vehicleClass.StatusCode;
|
||||
data.StatusDesc = vehicleClass.StatusDesc;
|
||||
}
|
||||
private String GetMakeDesc(String makeCode)
|
||||
{
|
||||
return Internals.GetCodesForCodeType(Sbm.ApplCodeType.VehicleMake, false).FirstOrDefault(vm => vm.Code.EqualsCI(makeCode))?.Description ?? makeCode;
|
||||
}
|
||||
private void PopulateVehicleClassResponseItemData(SbmModel_Portal model, VehicleClassItemData data, SbmVehicleClass vehicleClass)
|
||||
{
|
||||
PopulateVehicleClassResponseListData(model, data, vehicleClass);
|
||||
data.MakeCode = vehicleClass.MakeCode;
|
||||
data.Notes = vehicleClass.Notes;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get VehicleClass List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_VehicleClassList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_VehicleClassList(SbmModel_Portal model) : base(model) { }
|
||||
// VehicleClass list.
|
||||
public List<VehicleClassListData> VehicleClasses { get; } = new List<VehicleClassListData>();
|
||||
// Reference data.
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
|
||||
public String StatusCodeDefault { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/VehicleClass/Ajax/GetList")]
|
||||
[Route("Assets/VehicleClass/Ajax/GetVehicleClasses")]
|
||||
[Route("Assets/VehicleClass/Ajax/GetVehicleClassList")]
|
||||
public IActionResult Ajax_GetVehicleClassList(Model_VehicleClass model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetVehicleClassList";
|
||||
String messageTitle = Localiser["caption.vehicle.classes"];
|
||||
AjaxResponse_VehicleClassList responseData = new AjaxResponse_VehicleClassList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Reference data - statuses.
|
||||
foreach (SaStatus status in SbmVehicleClass.ValidStatuses)
|
||||
{
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
if (status != SaStatus.Deleted)
|
||||
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
}
|
||||
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SbmVehicleClass.DefaultStatus);
|
||||
|
||||
// Item filter.
|
||||
SbmVehicleClass.Params prmVehicleClass = new SbmVehicleClass.Params();
|
||||
prmVehicleClass.Search = model.Filter.Search;
|
||||
prmVehicleClass.StatusCat = model.Filter.GetStatusCat();
|
||||
model.Paging.ItemTotal = (ulong)AssetMgr.GetVehicleClassCount(prmVehicleClass);
|
||||
model.PopulatePagingTo(prmVehicleClass.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.Id);
|
||||
ColumnDfn colMakeCode = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.MakeCode);
|
||||
ColumnDfn colModel = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.Model);
|
||||
ColumnDfn colDerivative = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.Derivative);
|
||||
ColumnDfn colDescBrief = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.DescBrief);
|
||||
ColumnDfn colVehicleCount = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.VehicleCount);
|
||||
ColumnDfn colStatus = AssetMgr.GetVehicleClassColumnDfn(SbmVehicleClass.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colMakeCode, colModel, colDerivative, colDescBrief,
|
||||
colVehicleCount, colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = AssetMgr.ExecuteVehicleClassQuery(columns, prmVehicleClass))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
VehicleClassListData vehicleClassData = new VehicleClassListData()
|
||||
{
|
||||
Id = values.GetLong(colId.DataName).ToString(),
|
||||
MakeDesc = GetMakeDesc(values.GetString(colMakeCode.DataName)),
|
||||
Model = values.GetString(colModel.DataName),
|
||||
Derivative = values.GetString(colDerivative.DataName),
|
||||
DescBrief = values.GetString(colDescBrief.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
long vehicleCount = values.GetLong(colVehicleCount.DataName);
|
||||
if (vehicleCount > 0)
|
||||
vehicleClassData.VehicleCount = vehicleCount;
|
||||
responseData.VehicleClasses.Add(vehicleClassData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.VehicleClasses.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get VehicleClass ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_VehicleClass : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_VehicleClass(SbmModel_Portal model) : base(model) { }
|
||||
// VehicleClass details.
|
||||
public VehicleClassItemData vehicleClass { get; } = new VehicleClassItemData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/VehicleClass/Ajax/GetItem")]
|
||||
[Route("Assets/VehicleClass/Ajax/GetVehicleClass")]
|
||||
public IActionResult Ajax_GetVehicleClass(Model_VehicleClass model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetVehicleClass";
|
||||
String messageTitle = Localiser["caption.vehicle.class"];
|
||||
AjaxResponse_VehicleClass responseData = new AjaxResponse_VehicleClass(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId vehicleClassId = model.VehicleClass.Id.ToSysId();
|
||||
if (!SysId.IsValid(vehicleClassId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SbmVehicleClass vehicleClass = AssetMgr.GetVehicleClassById(vehicleClassId);
|
||||
disposables.Add(vehicleClass);
|
||||
if (vehicleClass == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve vehicleClass for Id: '" + vehicleClassId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateVehicleClassResponseItemData(model, responseData.vehicleClass, vehicleClass);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store VehicleClass ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Assets/VehicleClass/Ajax/StoreItem")]
|
||||
[Route("Assets/VehicleClass/Ajax/StoreVehicleClass")]
|
||||
public IActionResult Ajax_StoreVehicleClass(Model_VehicleClass model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreVehicleClass";
|
||||
String messageTitle = Localiser["caption.vehicle.class"];
|
||||
AjaxResponse_VehicleClass responseData = new AjaxResponse_VehicleClass(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate item Id.
|
||||
SysId vehicleClassId = model.VehicleClass.Id.ToSysId();
|
||||
if (StringUtil.ToBool(model.VehicleClass.Exists) && !SysId.IsValid(vehicleClassId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} VehicleClass Id not supplied for existing item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!StringUtil.ToBool(model.VehicleClass.Exists) && SysId.IsValid(vehicleClassId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} VehicleClass Id supplied for new item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateVehicleClassData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SbmVehicleClass vehicleClass = AssetMgr.GetVehicleClassById(vehicleClassId);
|
||||
disposables.Add(vehicleClass);
|
||||
if (vehicleClass == null && SysId.IsValid(vehicleClassId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Vehicle Class for Id: '" + model.VehicleClass.Id + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (vehicleClass == null)
|
||||
{
|
||||
vehicleClass = AssetMgr.CreateVehicleClass();
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.VehicleClass.MakeCode != null)
|
||||
vehicleClass.MakeCode = model.VehicleClass.MakeCode;
|
||||
if (model.VehicleClass.Model != null)
|
||||
vehicleClass.Model = model.VehicleClass.Model;
|
||||
if (model.VehicleClass.Derivative != null)
|
||||
vehicleClass.Derivative = model.VehicleClass.Derivative;
|
||||
if (model.VehicleClass.DescBrief != null)
|
||||
vehicleClass.DescBrief = model.VehicleClass.DescBrief;
|
||||
if (model.VehicleClass.StatusCode != null)
|
||||
vehicleClass.Status = model.VehicleClass.GetStatus();
|
||||
if (model.VehicleClass.Notes != null)
|
||||
vehicleClass.Notes = model.VehicleClass.Notes;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(vehicleClass.Id))
|
||||
{
|
||||
if (!AssetMgr.InsertVehicleClass(vehicleClass, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Vehicle Class: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AssetMgr.UpdateVehicleClass(vehicleClass, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update Vehicle Class [Id:" + SysId.ToString(vehicleClass.Id) + "]: " + AssetMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateVehicleClassResponseItemData(model, responseData.vehicleClass, vehicleClass);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class VehicleClassController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public VehicleClassController(SbmLocaliser localiser, ILogger<VehicleClassController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Assets/VehicleClass")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// VehicleClass page.
|
||||
Model_VehicleClass model = new Model_VehicleClass(Localiser);
|
||||
return View("Views/Assets/VehicleClass/Index.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
@@ -22,7 +22,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Portal Association Controller - Ajax actions.
|
||||
@@ -114,7 +114,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
|
||||
// Item filter.
|
||||
SbmAssociation.Params prmAssociation = new SbmAssociation.Params();
|
||||
prmAssociation.AffiliateIdOwner = SessionData.Organisation.AffiliateId;
|
||||
prmAssociation.AffiliateIdOwner = SessionData_Portal.Organisation.AffiliateId;
|
||||
prmAssociation.Search = model.Filter.AssociationSearch;
|
||||
prmAssociation.AssociationType = model.GetFilterAssociationType();
|
||||
prmAssociation.StatusCat = SbmAssociation.StatusCat.NotDeleted;
|
||||
@@ -276,7 +276,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
// Create new item if required.
|
||||
if (association == null)
|
||||
{
|
||||
association = AccountMgr.CreateAssociation(SessionData.Organisation.AffiliateId, model.GetAssociationType(), model.AffiliateIdTarget.ToSysId());
|
||||
association = AccountMgr.CreateAssociation(SessionData_Portal.Organisation.AffiliateId, model.GetAssociationType(), model.AffiliateIdTarget.ToSysId());
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
@@ -368,7 +368,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!AccountMgr.InsertAssociation(association, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert association: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
|
||||
}
|
||||
@@ -377,7 +377,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!AccountMgr.UpdateAssociation(association, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update association [Id:" + SysId.ToString(association.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -16,7 +16,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class AssociationController : SbmController_Portal
|
||||
@@ -36,7 +36,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Association page.
|
||||
Model_Association model = new Model_Association(Localiser);
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NPOI.OpenXmlFormats.Dml.Diagram;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Codes;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.CodeTypes;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class CodeController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// Code data.
|
||||
private class CodeListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String TypeCode { get; set; }
|
||||
public String TypeName { get; set; }
|
||||
public String Code { get; set; }
|
||||
public String Description { get; set; }
|
||||
}
|
||||
private class CodeItemData : CodeListData
|
||||
{
|
||||
public String CodeTypeId { get; set; }
|
||||
public ushort? Sequence { get; set; }
|
||||
public String DataValue { get; set; }
|
||||
}
|
||||
private void PopulateCodeResponseListData(SbmModel_Portal model, CodeListData data, SaCodeType codeType, SaCode code)
|
||||
{
|
||||
data.Id = SysId.ToString(code.Id);
|
||||
data.TypeCode = codeType.Code;
|
||||
data.TypeName = codeType.Name;
|
||||
data.Code = code.Code;
|
||||
data.Description = code.Description;
|
||||
data.StatusCode = code.StatusCode;
|
||||
data.StatusDesc = code.StatusDesc;
|
||||
}
|
||||
private void PopulateCodeResponseItemData(SbmModel_Portal model, CodeItemData data, SaCodeType codeType, SaCode code)
|
||||
{
|
||||
PopulateCodeResponseListData(model, data, codeType, code);
|
||||
data.CodeTypeId = SysId.ToString(code.CodeTypeId);
|
||||
if (code.Sequence > 0)
|
||||
data.Sequence = code.Sequence;
|
||||
data.DataValue = code.DataValue;
|
||||
data.Notes = code.Notes;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Code List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_CodeList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_CodeList(SbmModel_Portal model) : base(model) { }
|
||||
// Code list.
|
||||
public List<CodeListData> Codes { get; } = new List<CodeListData>();
|
||||
// Reference data.
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
|
||||
public String StatusCodeDefault { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/Code/Ajax/GetList")]
|
||||
[Route("Codes/Code/Ajax/GetCodes")]
|
||||
[Route("Codes/Code/Ajax/GetCodeList")]
|
||||
public IActionResult Ajax_GetCodeList(Model_Code model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetCodeList";
|
||||
String messageTitle = Localiser["label.codes"];
|
||||
AjaxResponse_CodeList responseData = new AjaxResponse_CodeList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Reference data - statuses.
|
||||
foreach (SaStatus status in SaCode.ValidStatuses)
|
||||
{
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
if (status != SaStatus.Deleted)
|
||||
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
}
|
||||
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SaCode.DefaultStatus);
|
||||
|
||||
// Item filter.
|
||||
SaCode.Params prmCode = new SaCode.Params();
|
||||
if (!StringUtil.IsBlank(model.Filter.CodeTypeCode))
|
||||
prmCode.CodeTypeCodes.Add(model.Filter.CodeTypeCode);
|
||||
prmCode.Search = model.Filter.Search;
|
||||
prmCode.StatusCat = model.Filter.GetStatusCat();
|
||||
model.Paging.ItemTotal = (ulong)CodeTypeConsole.GetCodeCount(prmCode);
|
||||
model.PopulatePagingTo(prmCode.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.Id);
|
||||
ColumnDfn colTypeCode = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.CodeType_Code);
|
||||
ColumnDfn colTypeName = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.CodeType_Name);
|
||||
ColumnDfn colCode = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.Code);
|
||||
ColumnDfn colDesc = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.Description);
|
||||
ColumnDfn colStatus = CodeTypeConsole.GetCodeColumnDfn(SaCode.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colTypeCode, colTypeName, colCode, colDesc,
|
||||
colStatus
|
||||
};
|
||||
prmCode.SortColumns.Add(colTypeName);
|
||||
prmCode.SortColumns.Add(colDesc);
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = CodeTypeConsole.ExecuteCodeQuery(columns, prmCode))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
CodeListData codeData = new CodeListData()
|
||||
{
|
||||
Id = values.GetLong(colId.DataName).ToString(),
|
||||
TypeCode = values.GetString(colTypeCode.DataName),
|
||||
TypeName = values.GetString(colTypeName.DataName),
|
||||
Code = values.GetString(colCode.DataName),
|
||||
Description = values.GetString(colDesc.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Codes.Add(codeData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.Codes.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Code ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_Code : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_Code(SbmModel_Portal model) : base(model) { }
|
||||
// Code details.
|
||||
public CodeItemData code { get; } = new CodeItemData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/Code/Ajax/GetItem")]
|
||||
[Route("Codes/Code/Ajax/GetCode")]
|
||||
public IActionResult Ajax_GetCode(Model_Code model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetCode";
|
||||
String messageTitle = Localiser["label.code"];
|
||||
AjaxResponse_Code responseData = new AjaxResponse_Code(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId codeId = model.Code.Id.ToSysId();
|
||||
if (!SysId.IsValid(codeId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaCode code = CodeTypeConsole.GetCodeById(codeId);
|
||||
disposables.Add(code);
|
||||
if (code == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve code for Id: '" + codeId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve code type.
|
||||
SaCodeType codeType = CodeTypeConsole.GetCodeTypeById(code.CodeTypeId);
|
||||
disposables.Add(codeType);
|
||||
if (codeType == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve code type for Id: '" + code.CodeTypeId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateCodeResponseItemData(model, responseData.code, codeType, code);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Code ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/Code/Ajax/StoreItem")]
|
||||
[Route("Codes/Code/Ajax/StoreCode")]
|
||||
public IActionResult Ajax_StoreCode(Model_Code model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreCode";
|
||||
String messageTitle = Localiser["label.code"];
|
||||
AjaxResponse_Code responseData = new AjaxResponse_Code(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate item Id.
|
||||
SysId codeId = model.Code.Id.ToSysId();
|
||||
if (StringUtil.ToBool(model.Code.Exists) && !SysId.IsValid(codeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Code Id not supplied for existing item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!StringUtil.ToBool(model.Code.Exists) && SysId.IsValid(codeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Code Id supplied for new item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateCodeData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SaCode code = CodeTypeConsole.GetCodeById(codeId);
|
||||
disposables.Add(code);
|
||||
if (code == null && SysId.IsValid(codeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Code Type for Id: '" + model.Code.Id + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve code type.
|
||||
SaCodeType codeType = null;
|
||||
if (code != null)
|
||||
{
|
||||
codeType = CodeTypeConsole.GetCodeTypeById(code.CodeTypeId);
|
||||
disposables.Add(codeType);
|
||||
if (codeType == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Code Type for existing Code. Id: '" + code.CodeTypeId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
codeType = CodeTypeConsole.GetCodeTypeById(model.Code.CodeTypeId.ToSysId());
|
||||
disposables.Add(codeType);
|
||||
if (codeType == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Code Type for new Code. Id: '" + model.Code.CodeTypeId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (code == null)
|
||||
{
|
||||
if (codeType == null || !SysId.IsValid(codeType.Id))
|
||||
{
|
||||
// Should be picked up by model validation unless form doesn't include Code Type.
|
||||
SaLogger.Warn($"{SysUtil.Fn} Code Type not specified for new Code.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
code = CodeTypeConsole.CreateCode(codeType.Id, model.Code.Code);
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.Code.Description != null)
|
||||
code.Description = model.Code.Description;
|
||||
if (model.Code.StatusCode != null)
|
||||
code.Status = model.Code.GetStatus();
|
||||
if (model.Code.Notes != null)
|
||||
code.Notes = model.Code.Notes;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(code.Id))
|
||||
{
|
||||
if (!CodeTypeConsole.InsertCode(code, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Code: " + CodeTypeConsole.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CodeTypeConsole.UpdateCode(code, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update Code [Id:" + SysId.ToString(code.Id) + "]: " + CodeTypeConsole.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateCodeResponseItemData(model, responseData.code, codeType, code);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Codes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class CodeController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public CodeController(SbmLocaliser localiser, ILogger<CodeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Codes/Code")]
|
||||
public IActionResult Index(Model_Code model)
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Prepare model.
|
||||
RefreshModel(model);
|
||||
model.PopulateCodeTypes();
|
||||
|
||||
// Code page.
|
||||
return View("Views/Codes/Code/Index.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Codes;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.CodeTypes;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class CodeTypeController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// CodeType data.
|
||||
private class CodeTypeListData : AjaxResponse_Data.ItemData_Base
|
||||
{
|
||||
public String Code { get; set; }
|
||||
public String Name { get; set; }
|
||||
public long? CodeCount { get; set; }
|
||||
}
|
||||
private class CodeTypeItemData : CodeTypeListData
|
||||
{
|
||||
public bool? AutoAssignCode { get; set; }
|
||||
}
|
||||
private void PopulateCodeTypeResponseListData(SbmModel_Portal model, CodeTypeListData data, SaCodeType codeType)
|
||||
{
|
||||
data.Id = SysId.ToString(codeType.Id);
|
||||
data.Code = codeType.Code;
|
||||
data.Name = codeType.Name;
|
||||
data.StatusCode = codeType.StatusCode;
|
||||
data.StatusDesc = codeType.StatusDesc;
|
||||
}
|
||||
private void PopulateCodeTypeResponseItemData(SbmModel_Portal model, CodeTypeItemData data, SaCodeType codeType)
|
||||
{
|
||||
PopulateCodeTypeResponseListData(model, data, codeType);
|
||||
if (codeType.AutoAssignCode)
|
||||
data.AutoAssignCode = true;
|
||||
data.Notes = codeType.Notes;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get CodeType List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_CodeTypeList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_CodeTypeList(SbmModel_Portal model) : base(model) { }
|
||||
// CodeTYpe list.
|
||||
public List<CodeTypeListData> CodeTypes { get; } = new List<CodeTypeListData>();
|
||||
// Reference data.
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public List<CodeDesc> StatusesCreate { get; } = new List<CodeDesc>();
|
||||
public String StatusCodeDefault { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/CodeType/Ajax/GetList")]
|
||||
[Route("Codes/CodeType/Ajax/GetCodeTypes")]
|
||||
[Route("Codes/CodeType/Ajax/GetCodeTypeList")]
|
||||
public IActionResult Ajax_GetCodeTypeList(Model_CodeType model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetCodeTypeList";
|
||||
String messageTitle = Localiser["caption.code.types"];
|
||||
AjaxResponse_CodeTypeList responseData = new AjaxResponse_CodeTypeList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Reference data - statuses.
|
||||
foreach (SaStatus status in SaCodeType.ValidStatuses)
|
||||
{
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
if (status != SaStatus.Deleted)
|
||||
responseData.StatusesCreate.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
}
|
||||
responseData.StatusCodeDefault = SacsSystem.GetStatusCode(SaCodeType.DefaultStatus);
|
||||
|
||||
// Item filter.
|
||||
SaCodeType.Params prmCodeType = new SaCodeType.Params();
|
||||
prmCodeType.Search = model.Filter.Search;
|
||||
prmCodeType.StatusCat = model.Filter.GetStatusCat();
|
||||
model.Paging.ItemTotal = (ulong)CodeTypeConsole.GetCodeTypeCount(prmCodeType);
|
||||
model.PopulatePagingTo(prmCodeType.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Id);
|
||||
ColumnDfn colCode = CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Code);
|
||||
ColumnDfn colName = CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Name);
|
||||
ColumnDfn colCodeCount = CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Codes_Count);
|
||||
ColumnDfn colStatus = CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colCode, colName,
|
||||
colCodeCount, colStatus
|
||||
};
|
||||
prmCodeType.SortColumns.Add(colName);
|
||||
prmCodeType.SortColumns.Add(colCode);
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = CodeTypeConsole.ExecuteCodeTypeQuery(columns, prmCodeType))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
CodeTypeListData codeTypeData = new CodeTypeListData()
|
||||
{
|
||||
Id = values.GetLong(colId.DataName).ToString(),
|
||||
Code = values.GetString(colCode.DataName),
|
||||
Name = values.GetString(colName.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
long codeCount = values.GetLong(colCodeCount.DataName);
|
||||
if (codeCount > 0)
|
||||
codeTypeData.CodeCount = codeCount;
|
||||
responseData.CodeTypes.Add(codeTypeData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.CodeTypes.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get CodeType ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_CodeType : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_CodeType(SbmModel_Portal model) : base(model) { }
|
||||
// CodeType details.
|
||||
public CodeTypeItemData codeType { get; } = new CodeTypeItemData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/CodeType/Ajax/GetItem")]
|
||||
[Route("Codes/CodeType/Ajax/GetCodeType")]
|
||||
public IActionResult Ajax_GetCodeType(Model_CodeType model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetCodeType";
|
||||
String messageTitle = Localiser["caption.asset.category"];
|
||||
AjaxResponse_CodeType responseData = new AjaxResponse_CodeType(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId codeTypeId = model.CodeType.Id.ToSysId();
|
||||
if (!SysId.IsValid(codeTypeId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaCodeType codeType = CodeTypeConsole.GetCodeTypeById(codeTypeId);
|
||||
disposables.Add(codeType);
|
||||
if (codeType == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Code Type for Id: {codeTypeId}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateCodeTypeResponseItemData(model, responseData.codeType, codeType);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store CodeType ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Codes/CodeType/Ajax/StoreItem")]
|
||||
[Route("Codes/CodeType/Ajax/StoreCodeType")]
|
||||
public IActionResult Ajax_StoreCodeType(Model_CodeType model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreCodeType";
|
||||
String messageTitle = Localiser["caption.asset.category"];
|
||||
AjaxResponse_CodeType responseData = new AjaxResponse_CodeType(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate item Id.
|
||||
SysId codeTypeId = model.CodeType.Id.ToSysId();
|
||||
if (StringUtil.ToBool(model.CodeType.Exists) && !SysId.IsValid(codeTypeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} CodeType Id not supplied for existing item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!StringUtil.ToBool(model.CodeType.Exists) && SysId.IsValid(codeTypeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} CodeType Id supplied for new item.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateCodeTypeData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SaCodeType codeType = CodeTypeConsole.GetCodeTypeById(codeTypeId);
|
||||
disposables.Add(codeType);
|
||||
if (codeType == null && SysId.IsValid(codeTypeId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Asset Category for Id: {model.CodeType.Id}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (codeType != null && model.CodeType.Code != null && !model.CodeType.Code.Equals(codeType.Code))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Inconsistent code returned for Code Type Id: {model.CodeType.Id}. Expected: {codeType.Code}. Found: {model.CodeType.Code}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (codeType == null)
|
||||
{
|
||||
if (StringUtil.IsBlank(model.CodeType.Code))
|
||||
{
|
||||
// Should be picked up by model validation unless form doesn't include Code Type code.
|
||||
SaLogger.Warn($"{SysUtil.Fn} Code not specified for new Code Type.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
codeType = CodeTypeConsole.CreateCodeType(model.CodeType.Code);
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.CodeType.Name != null)
|
||||
codeType.Name = model.CodeType.Name;
|
||||
if (model.CodeType.MaxCodeLength != null)
|
||||
codeType.MaxCodeLen = (byte)StringUtil.ToShort(model.CodeType.MaxCodeLength);
|
||||
if (model.CodeType.StatusCode != null)
|
||||
codeType.Status = model.CodeType.GetStatus();
|
||||
if (model.CodeType.Notes != null)
|
||||
codeType.Notes = model.CodeType.Notes;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(codeType.Id))
|
||||
{
|
||||
if (!CodeTypeConsole.InsertCodeType(codeType, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to insert Asset Category: {CodeTypeConsole.ErrorStateMessage}");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CodeTypeConsole.UpdateCodeType(codeType, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update Asset Category [Id: {SysId.ToString(codeType.Id)}]: {CodeTypeConsole.ErrorStateMessage}");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateCodeTypeResponseItemData(model, responseData.codeType, codeType);
|
||||
responseData.Success = true;
|
||||
}
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Assets;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Codes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class CodeTypeController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public CodeTypeController(SbmLocaliser localiser, ILogger<CodeTypeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Codes/CodeType")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Code Type page.
|
||||
Model_CodeType model = new Model_CodeType(Localiser);
|
||||
return View("Views/Codes/CodeType/Index.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
@@ -21,13 +21,14 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Portal Commodity Controller - Ajax actions.
|
||||
//=======================================================================
|
||||
partial class CommodityController
|
||||
//=======================================================================
|
||||
// Portal Commodity Controller - Ajax actions.
|
||||
//=======================================================================
|
||||
partial class CommodityController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity data.
|
||||
@@ -252,7 +253,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
// Create new item if required.
|
||||
if (commodity == null)
|
||||
{
|
||||
commodity = CommodityMgr.CreateCommodity(SessionData.Organisation.AffiliateId, model.GetCommodityType(), model.CommodityCode);
|
||||
commodity = CommodityMgr.CreateCommodity(model.GetCommodityType(), model.CommodityCode);
|
||||
if (model.CommodityCode != null)
|
||||
commodity.Code = model.CommodityCode;
|
||||
}
|
||||
@@ -276,7 +277,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!CommodityMgr.InsertCommodity(commodity, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert commodity: " + CommodityMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + CommodityMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
|
||||
}
|
||||
@@ -285,7 +286,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!CommodityMgr.UpdateCommodity(commodity, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update commodity [Id:" + SysId.ToString(commodity.Id) + "]: " + CommodityMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + CommodityMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -15,11 +14,12 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class CommodityController : SbmController_Portal
|
||||
//=======================================================================
|
||||
public partial class CommodityController : SbmController_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
@@ -35,10 +35,15 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Commodity page.
|
||||
Model_Commodity model = new Model_Commodity(Localiser);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
@@ -22,7 +22,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Portal Contact Controller - Ajax actions.
|
||||
@@ -348,7 +348,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!AccountMgr.InsertAffiliate(affiliate, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert affiliate: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.created"]);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
if (!AccountMgr.UpdateAffiliate(affiliate, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update affiliate [Id:" + SysId.ToString(affiliate.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
|
||||
}
|
||||
responseData.SetNotification(messageTitle, Localiser["msg.item.updated"]);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -16,7 +16,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class ContactController : SbmController_Portal
|
||||
@@ -35,10 +35,15 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Contact page.
|
||||
Model_Contact model = new Model_Contact(Localiser);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -16,7 +16,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class HomeController : SbmController_Portal
|
||||
@@ -35,73 +35,18 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Check for 'Keep Logged In' cookie.
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (!ValidUserSession && AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
{
|
||||
// Extract parameters and validate that they are populated.
|
||||
String encryptedParams = GetRequestCookie(CookieName_KeepLoggedIn);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logPrefix = $"{SysUtil.Fn} 'Keep Logged In' cookie found but ";
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (keepLoggedInParams.IsValid())
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// 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(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 != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
{
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, keepLoggedInParams.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
|
||||
{
|
||||
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
|
||||
break;
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "failed to sign user in: " + errorMessage + "." + 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 or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(encryptedParams))
|
||||
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
|
||||
}
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Home page.
|
||||
Model_Home model = new Model_Home(Localiser);
|
||||
// Home page.
|
||||
Model_Home model = new Model_Home(Localiser);
|
||||
model.ProhibitCache = false;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Newtonsoft.Json;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
@@ -16,44 +17,67 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
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;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmController_Portal : SbmController_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SbmSysParamCache sysParamCache = null;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SbmController_Portal(SbmLocaliser localiser, Microsoft.Extensions.Logging.ILogger<SbmController_Portal> logger) : base(localiser)
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (sysParamCache != null) sysParamCache.Dispose();
|
||||
sysParamCache = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session data.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Online session data</summary>
|
||||
|
||||
/// <summary>Portal session data</summary>
|
||||
protected SbmSessionData_Portal SessionData_Portal { get { return SessionData as SbmSessionData_Portal; } }
|
||||
public override ISbmUserContext_Core UserContext_Core { get { return SessionData_Portal; } }
|
||||
/// <summary>
|
||||
/// Session data deserialisation.
|
||||
/// </summary>
|
||||
protected override SbmSessionData_Web DeserializeSessionData(String sessionDataJson)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<SbmSessionData_Portal>(sessionDataJson, SbmSessionDataJsonSerializerSettings);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User Session.
|
||||
// Properties.
|
||||
|
||||
// Business components.
|
||||
protected SbmSysParamCache SysParamCache { get { if (sysParamCache == null) sysParamCache = new SbmSysParamCache(UserContext_Core, SessionData_Portal.User.AffiliateId); return sysParamCache; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User Session.
|
||||
|
||||
/// <summary>
|
||||
/// Sign the account in.
|
||||
/// <para>- Record login time and clear invalid login data.</para>
|
||||
/// <para>- Open user session - store details against Sesion Data.</para>
|
||||
/// <para>- Set 'Keep logged in' cookie if required.</para>
|
||||
/// </summary>
|
||||
protected bool SignUserIn(ISbmUserContext 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 dbIdentifier, 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)
|
||||
@@ -138,7 +162,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
protected bool RefreshSessionProfileContact(SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation)
|
||||
{
|
||||
SbmSessionData_Portal sessionData = SessionData_Portal;
|
||||
SysId affiliateIdUser = sessionData?.User.AffiliateId ?? null;
|
||||
SysId affiliateIdUser = sessionData?.User?.AffiliateId ?? null;
|
||||
if (!SysId.IsValid(affiliateIdUser)) return false;
|
||||
if (!SysId.IsValid(affiliateUser?.Id ?? null)) return false;
|
||||
if (!affiliateIdUser.Equals(affiliateUser.Id)) return false;
|
||||
@@ -168,25 +192,112 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
ClearSessionData();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Action execution events.
|
||||
//-------------------------------------------------------------------
|
||||
public override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||
{
|
||||
// ToDo Store system params.
|
||||
if (sysParamCache != null)
|
||||
{
|
||||
if (sysParamCache.Modified)
|
||||
{
|
||||
sysParamCache.Store();
|
||||
SaLogger.Info($"{SysUtil.Fn} User params stored.");
|
||||
}
|
||||
}
|
||||
base.OnActionExecuted(filterContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep Logged In.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Check for 'Keep Logged In' cookie and auto-login user if details are valid.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected bool AutoLoginUser()
|
||||
{
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (ValidUserSession) return true;
|
||||
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed) return false;
|
||||
|
||||
// Extract parameters and validate that they are populated.
|
||||
String encryptedParams = GetRequestCookie(KeepLoggedIn.CookieName);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logPrefix = $"{SysUtil.Fn} 'Keep Logged In' cookie found but ";
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (keepLoggedInParams.IsValid())
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// 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(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 != null && affiliateUser != null && associationOrganisation != null && affiliateOrganisation != null)
|
||||
{
|
||||
if (securityItemUser.Id.Equals(keepLoggedInParams.SecurityItemId) && affiliateUser.UserId.Equals(securityItemUser.Id))
|
||||
{
|
||||
if (affiliateUser.IsStatusCurrent)
|
||||
{
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, keepLoggedInParams.DbIdentifier, 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 + "Affiliate is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item and Affiliate are inconsistent. " + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(logPrefix + "Security Item or Affiliate not found. " + logSuffix);
|
||||
}
|
||||
}
|
||||
if (ValidUserSession)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(encryptedParams))
|
||||
SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but with incomplete details." + logSuffix);
|
||||
ClearKeepLoggedInCookie();
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Keep-Logged-In cookie.</summary>
|
||||
protected void SetKeepLoggedInCookie()
|
||||
{
|
||||
String keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
|
||||
int cookieExpiresDays = Math.Max(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
|
||||
SetResponseCookie(CookieName_KeepLoggedIn, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
|
||||
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie set. Value: {keepLoggedInCookieValue}");
|
||||
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
|
||||
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie set. Name: {KeepLoggedIn.CookieName}. Value: {keepLoggedInCookieValue}");
|
||||
}
|
||||
|
||||
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
|
||||
public void ClearKeepLoggedInCookie()
|
||||
{
|
||||
if (StringUtil.IsEmpty(GetRequestCookie(CookieName_KeepLoggedIn))) return;
|
||||
if (StringUtil.IsEmpty(GetRequestCookie(KeepLoggedIn.CookieName))) return;
|
||||
// Clear cookie by setting expiry date in the past.
|
||||
SetResponseCookie(CookieName_KeepLoggedIn, "", DateTime.Today.AddDays(-7), true);
|
||||
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie cleared.");
|
||||
SetResponseCookie(KeepLoggedIn.CookieName, "", DateTime.Today.AddDays(-7), true);
|
||||
SaLogger.Info($"{SysUtil.Fn} 'Keep Logged In' cookie cleared. Name: {KeepLoggedIn.CookieName}.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -195,11 +306,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
// to ensure that cookie value can be decrypted even if application restarts in the meantime.
|
||||
// - Generating IV from same key results in different value each time.
|
||||
// - IV Must be regenerated if key is changed: uncomment 'Generated' variable and copy resulting value to IV variable.
|
||||
// NB - 'Keep Logged In' is termed 'Remember Me' in the Online application.
|
||||
public static String CookieName_KeepLoggedIn = "SBMRM";
|
||||
public static String Base64Key_KeepLoggedIn = SacsEncryptionHelper.EncodePlainKey("<=SaBusMgr^P0rt4L{KeepLoggedIn}~", SacsEncryptionHelper.KeyLength);
|
||||
//public static String Base64IV_KeepLoggedIn_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_KeepLoggedIn);
|
||||
public static String Base64IV_KeepLoggedIn = "UU2UJ2p2tXBihMyUEi9nJg==";
|
||||
// NB - 'Keep Logged In' is termed 'Remember Me' in the Portal application.
|
||||
public static class KeepLoggedIn
|
||||
{
|
||||
public static String CookieName = "sbprm";
|
||||
public static String Base64Key = SacsEncryptionHelper.EncodePlainKey("<=SaBusMgr^P0rt4L{KeepLoggedIn}~", SacsEncryptionHelper.KeyLength);
|
||||
//private static String KeepLoggedIn.Base64IV_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(KeepLoggedIn.Base64Key);
|
||||
public static String Base64IV = "m47AMcMgACp3aoQVc0Y92A==";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep-logged-in cookie value.
|
||||
@@ -216,7 +330,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_SecurityItemId, SysId.ToString(SessionData_Portal.User.SecurityItemId));
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AffiliateIdUser, SysId.ToString(SessionData_Portal.User.AffiliateId));
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_AssociationIdOrganisation, SysId.ToString(SessionData_Portal.Organisation.AssociationId));
|
||||
return EncryptParameters(keepLoggedInParams, Base64IV_KeepLoggedIn, Base64Key_KeepLoggedIn);
|
||||
return EncryptParameters(keepLoggedInParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -248,7 +362,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
{
|
||||
return
|
||||
!StringUtil.IsBlank(DbIdentifier) &&
|
||||
StringUtil.IsBlank(EmailAddress) &&
|
||||
!StringUtil.IsBlank(EmailAddress) &&
|
||||
SysId.IsValid(SecurityItemId) &&
|
||||
SysId.IsValid(AffiliateIdUser) &&
|
||||
SysId.IsValid(AssociationIdOrganisation);
|
||||
@@ -259,7 +373,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
KeepLoggedInParams keepLoggedInParams = new KeepLoggedInParams();
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_KeepLoggedIn, Base64Key_KeepLoggedIn);
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
|
||||
keepLoggedInParams.DbIdentifier = linkParams.Get(ParamName_KeepLoggedIn_DbIdentifier);
|
||||
keepLoggedInParams.EmailAddress = linkParams.Get(ParamName_KeepLoggedIn_EmailAddress);
|
||||
keepLoggedInParams.SecurityItemId = linkParams.Get(ParamName_KeepLoggedIn_SecurityItemId).ToSysId();
|
||||
@@ -274,18 +388,18 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
// Parameter encryption, eg. for images.
|
||||
//-------------------------------------------------------------------
|
||||
// Encryption key is the same for all users but a different IV value is generated for each session so that the links/parameters cannot be shared.
|
||||
public static String Base64Key_OnlineApp { get; } = SacsEncryptionHelper.EncodePlainKey("{SaBusMgr=Portal-App#Encryption}", SacsEncryptionHelper.KeyLength);
|
||||
protected String EncryptOnlineParams(NameValueCollection parameters)
|
||||
public static String Base64Key_PortalApp { get; } = SacsEncryptionHelper.EncodePlainKey("{SaBusMgr=Portal-App#Encryption}", SacsEncryptionHelper.KeyLength);
|
||||
protected String EncryptPortalParams(NameValueCollection parameters)
|
||||
{
|
||||
return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Portal.Base64IV_PortalApp, Base64Key_OnlineApp));
|
||||
return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Portal.Base64IV_PortalApp, Base64Key_PortalApp));
|
||||
}
|
||||
public static String EncryptOnlineParams(SbmController_Portal controller, NameValueCollection parameters)
|
||||
public static String EncryptPortalParams(SbmController_Portal controller, NameValueCollection parameters)
|
||||
{
|
||||
return controller.EncryptOnlineParams(parameters);
|
||||
return controller.EncryptPortalParams(parameters);
|
||||
}
|
||||
protected NameValueCollection ExtractOnlineParams(String encryptedParams)
|
||||
protected NameValueCollection ExtractPortalParams(String encryptedParams)
|
||||
{
|
||||
return DecryptParameters(encryptedParams, SessionData_Portal.Base64IV_PortalApp, Base64Key_OnlineApp);
|
||||
return DecryptParameters(encryptedParams, SessionData_Portal.Base64IV_PortalApp, Base64Key_PortalApp);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.App;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
@@ -23,8 +25,12 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using static Sarand.Net.Standard.Base.Bus.SaErrorStateItem;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Helpers;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Portal Security Controller - Ajax actions.
|
||||
@@ -54,95 +60,129 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
model.ValidateSignInData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
using (DisposableCollection<IDisposable> disposableItems = new DisposableCollection<IDisposable>())
|
||||
|
||||
using (DisposableCollection<IDisposable> disposables = new DisposableCollection<IDisposable>())
|
||||
{
|
||||
|
||||
// Identify 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())
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
if (!(SessionData_Portal?.ValidUser ?? false))
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
ISacsDatabase busMgrDatabase = App.GetBusMgrDatabase(sessionContext);
|
||||
if (busMgrDatabase == null) continue;
|
||||
|
||||
// Account manager.
|
||||
SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext);
|
||||
disposableItems.Add(securityConsoleForUser);
|
||||
SbmAccountMgr accountMgrForUser = SbmGlobals_Web.System.CreateAccountMgr(userContext);
|
||||
disposableItems.Add(accountMgrForUser);
|
||||
|
||||
// User's security item.
|
||||
SaSecurityItem securityItemUser = GetSecurityItemForSignin(securityConsoleForUser, model);
|
||||
disposableItems.Add(securityItemUser);
|
||||
if (securityItemUser == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
continue;
|
||||
}
|
||||
if (!securityItemUser.PasswordMatches(model.Password))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Supplied password doesn't match Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// User's affiliate.
|
||||
SbmAffiliate affiliateUser = GetAffiliateForSignin(accountMgrForUser, model, securityItemUser);
|
||||
disposableItems.Add(affiliateUser);
|
||||
if (affiliateUser == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Affiliate for signin. Database: {busMgrDatabase.DatabaseName}. UserId: {SysId.ToString(securityItemUser.Id)}.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// User's supervised organisations.
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
if (supervisedOrganisations.IsEmpty())
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} User has no supervised organisations. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
continue;
|
||||
}
|
||||
userContext.RefreshUser(securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
|
||||
// User's organisation association.
|
||||
SbmAssociation associationOrganisation = GetOrganisationAssociationForSignIn(accountMgrForUser, model, userContext);
|
||||
disposableItems.Add(associationOrganisation);
|
||||
if (associationOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Organisation Association. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// User's organisation affiliate.
|
||||
SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null);
|
||||
disposableItems.Add(affiliateOrganisation);
|
||||
if (affiliateOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Affiliate for organisation. Database: {busMgrDatabase.DatabaseName}. Id: " + SysId.ToString(associationOrganisation?.Id ?? null));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initialise user session.
|
||||
// Instance Repository configured on Control database.
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Portal.GetControlSessionContext(model.DbIdentifier);
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userContext, model.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
break;
|
||||
else return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
|
||||
if (!OpenUserSession(model, sessionContext, ref errorMessage))
|
||||
{
|
||||
if (!StringUtil.IsBlank(errorMessage))
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
foreach (ushort sessionContextIdx in sessionContextIdxs)
|
||||
{
|
||||
SbmSessionContext sessionContext = SbmSessionContextHelper_Web.GetSessionContext(sessionContextIdx);
|
||||
String errorMessage = "";
|
||||
|
||||
if (OpenUserSession(model, sessionContext, ref errorMessage)) break;
|
||||
|
||||
if (!StringUtil.IsBlank(errorMessage))
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!(SessionData_Portal?.ValidUserSession ?? false))
|
||||
|
||||
if (!(SessionData_Portal?.ValidUser ?? false))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Suitable database. Email: {model.EmailAddress}.");
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Suitable database. Context: {model.DbIdentifier}. Email: {model.EmailAddress}.");
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = SessionData_Portal?.ValidUserSession ?? false;
|
||||
responseData.Success = SessionData_Portal?.ValidUser ?? false;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
private bool OpenUserSession(Model_Security model, SbmSessionContext sessionContext, ref String errorMessage)
|
||||
{
|
||||
if (sessionContext == null) return false;
|
||||
|
||||
SbmUserContext_Web userContext = new SbmUserContext_Web(sessionContext);
|
||||
ISacsDatabase busMgrDatabase = App.GetBusMgrDatabase(sessionContext);
|
||||
if (busMgrDatabase == null) return false;
|
||||
|
||||
using (DisposableCollection<IDisposable> disposables = new DisposableCollection<IDisposable>())
|
||||
{
|
||||
|
||||
// Account manager.
|
||||
SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext);
|
||||
disposables.Add(securityConsoleForUser);
|
||||
SbmAccountMgr accountMgrForUser = SbmGlobals_Web.System.CreateAccountMgr(userContext);
|
||||
disposables.Add(accountMgrForUser);
|
||||
|
||||
// User's security item.
|
||||
SaSecurityItem securityItemUser = GetSecurityItemForSignin(securityConsoleForUser, model);
|
||||
disposables.Add(securityItemUser);
|
||||
if (securityItemUser == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
return false;
|
||||
}
|
||||
if (!securityItemUser.PasswordMatches(model.Password))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Supplied password doesn't match Security Item. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// User's affiliate.
|
||||
SbmAffiliate affiliateUser = GetAffiliateForSignin(accountMgrForUser, model, securityItemUser);
|
||||
disposables.Add(affiliateUser);
|
||||
if (affiliateUser == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Affiliate for signin. Database: {busMgrDatabase.DatabaseName}. UserId: {SysId.ToString(securityItemUser.Id)}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// User's supervised organisations.
|
||||
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
|
||||
if (supervisedOrganisations.IsEmpty())
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} User has no supervised organisations. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
return false;
|
||||
}
|
||||
userContext.RefreshUser(securityItemUser, affiliateUser, supervisedOrganisations);
|
||||
|
||||
// User's organisation association.
|
||||
SbmAssociation associationOrganisation = GetOrganisationAssociationForSignIn(accountMgrForUser, model, userContext);
|
||||
disposables.Add(associationOrganisation);
|
||||
if (associationOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to identify Organisation Association. Database: {busMgrDatabase.DatabaseName}. Email: {model.EmailAddress}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// User's organisation affiliate.
|
||||
SbmAffiliate affiliateOrganisation = accountMgrForUser.GetAffiliateById(associationOrganisation?.AffiliateIdOwner ?? null);
|
||||
disposables.Add(affiliateOrganisation);
|
||||
if (affiliateOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Affiliate for organisation. Database: {busMgrDatabase.DatabaseName}. Id: " + SysId.ToString(associationOrganisation?.Id ?? null));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialise user session.
|
||||
if (SignUserIn(userContext, model.DbIdentifier, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private SaSecurityItem GetSecurityItemForSignin(SaSecurityConsole securityConsoleForUser, Model_Security model)
|
||||
{
|
||||
@@ -203,10 +243,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
private SbmAssociation GetOrganisationAssociationForSignIn(SbmAccountMgr accountMgrForUser, Model_Security model, SbmUserContext userContext)
|
||||
{
|
||||
// Previously selected organisation is stored in user params (SysParam table).
|
||||
SbmSysParamCache sysParamCache = new SbmSysParamCache(userContext);
|
||||
SbmSysParamCache sysParamCache = new SbmSysParamCache(userContext, userContext.UserAffiliateId);
|
||||
SysId affiliateIdOrganisation = StringUtil.ToSysId(sysParamCache.GetUserParamValue(SbmSysParamCache.ParamName_SelectedCompany));
|
||||
SbmAssociation associationOrganisation = null;
|
||||
foreach (SysIdString supervisedOrganisation in userContext.User.SupervisedOrganisations)
|
||||
foreach (SysIdString supervisedOrganisation in userContext.SupervisedOrganisations)
|
||||
{
|
||||
SbmAssociation associationOrganisationCandidate = accountMgrForUser.GetAssociationByOwnerTypeTarget(supervisedOrganisation.Id, Sbm.AssociationType.Internal, supervisedOrganisation.Id);
|
||||
if (associationOrganisationCandidate == null)
|
||||
@@ -253,16 +293,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
AjaxResponse_KeepLoggedIn responseData = new AjaxResponse_KeepLoggedIn();
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer)
|
||||
return Forbid();
|
||||
if (!ValidUserSession)
|
||||
return Json(responseData.SetGoHome());
|
||||
if (!ValidReferer) return Forbid();
|
||||
if (!ValidUserSession) return Json(responseData.SetGoHome());
|
||||
|
||||
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
return Json(responseData);
|
||||
|
||||
// Resend the cookie to extend the expiry date if it is currently populated.
|
||||
if (!StringUtil.IsEmpty(GetRequestCookie(CookieName_KeepLoggedIn)))
|
||||
if (!StringUtil.IsEmpty(GetRequestCookie(KeepLoggedIn.CookieName)))
|
||||
SetKeepLoggedInCookie();
|
||||
|
||||
// Construct response.
|
||||
@@ -302,7 +340,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
}
|
||||
|
||||
// Clear user session.
|
||||
String emailAddress = SessionData.User.EmailAddress;
|
||||
String emailAddress = SessionData.UserEmailAddress;
|
||||
CloseUserSession();
|
||||
SaLogger.Info($"{SysUtil.Fn} User session closed for {emailAddress}.", true);
|
||||
|
||||
@@ -552,10 +590,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
responseData.SuccessMsg = Localiser["security.msg.request.password.email.sent"];
|
||||
return Json(responseData);
|
||||
}
|
||||
private void PopulateRequestPasswordEmailBody(SbmEmailConsole emailConsole, ISbmUserContext userContext, SaEmailData emailData, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser)
|
||||
private void PopulateRequestPasswordEmailBody(SbmEmailConsole emailConsole, ISbmUserContext_Core userContext, SaEmailData emailData, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser)
|
||||
{
|
||||
// Will need to handle culture (language/country) as and when introduced.
|
||||
emailData.MessageBody = SbmResourceHelper.GetTextResource(SbmResourceHelper.TextResource.Email_RequestPassword_Html);
|
||||
emailData.MessageBody = SbmResourceHelper.GetResourceText(SbmResourceHelper.TextResource.Email_RequestPassword_Html);
|
||||
emailData.HtmlBody = true;
|
||||
|
||||
// Replace dynamic tags.
|
||||
@@ -575,11 +613,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
private static String ParamName_AffiliateId { get; } = "afi";
|
||||
private static String ParamName_ExpiresAt { get; } = "exp";
|
||||
private static String ParamName_Token { get; } = "tok";
|
||||
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
|
||||
// IV Must be regenerated if key is changed.
|
||||
private static String Base64Key_RequestPassword { get; } = SacsEncryptionHelper.EncodePlainKey("[-SaBusMgr+<Request=Password>!^]", SacsEncryptionHelper.KeyLength);
|
||||
//private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword);
|
||||
private static String Base64IV_RequestPassword { get; } = "iALRIxzrZIfrB4boNFRXfA==";
|
||||
// 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)
|
||||
{
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
@@ -591,7 +626,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
parameters.Add(ParamName_Token, requestPasswordToken);
|
||||
String link =
|
||||
GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/ChangePassword?" +
|
||||
ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(EncryptParameters(parameters, Base64IV_RequestPassword, Base64Key_RequestPassword));
|
||||
ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(EncryptParameters(parameters, Base64IV_RequestPassword_Portal, Base64Key_RequestPassword_Portal));
|
||||
return link;
|
||||
}
|
||||
private int GetRequestPasswordEmailLinkExpiresMinutes()
|
||||
@@ -654,7 +689,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
RequestPasswordParams requestPasswordParams = new RequestPasswordParams();
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword, Base64Key_RequestPassword);
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword_Portal, Base64Key_RequestPassword_Portal);
|
||||
requestPasswordParams.DbIdentifier = linkParams.Get(ParamName_DbIdentifier);
|
||||
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
|
||||
requestPasswordParams.SecurityItemId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_SecurityItemId)));
|
||||
|
||||
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -17,7 +17,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Controllers
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Online Security Controller.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Helpers
|
||||
{
|
||||
//=======================================================================
|
||||
// Portal Session Context utility functions.
|
||||
//=======================================================================
|
||||
public class SbmSessionContextHelper_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Control Session Contexts.
|
||||
//-------------------------------------------------------------------
|
||||
public static SbmSessionContext GetControlSessionContext(String dbIdentifier)
|
||||
{
|
||||
SbmApplication_Portal app = SbmApplication_Portal.Instance;
|
||||
return app?.GetControlSessionContext(dbIdentifier);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Assets
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Asset : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Asset(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String Search { get; set; }
|
||||
public String StatusCat { get; set; }
|
||||
public SbmAsset.StatusCat GetStatusCat()
|
||||
{
|
||||
return EnumUtil.ParseEnum(StatusCat, SbmAsset.StatusCat.NotDeleted);
|
||||
}
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public class AssetData
|
||||
{
|
||||
public String Exists { get; set; }
|
||||
public String Id { get; set; }
|
||||
public String CategoryId { get; set; }
|
||||
public String SerialNumber{ get; set; }
|
||||
public String DescBrief { get; set; }
|
||||
public String Notes { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public SaStatus GetStatus() { return SacsSystem.GetStatusForCode(StatusCode); }
|
||||
}
|
||||
public AssetData Asset { get; } = new AssetData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Asset.
|
||||
public bool ValidateAssetData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Asset Category.
|
||||
if (Asset.CategoryId != null)
|
||||
{
|
||||
String controlName = "AssetCategory";
|
||||
if (StringUtil.IsBlank(Asset.CategoryId))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!AssetMgr.AssetCategoryExistsById(Asset.CategoryId.ToSysId()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
// Serial Number.
|
||||
if (Asset.SerialNumber != null)
|
||||
{
|
||||
String controlName = "AssetSerialNumber";
|
||||
Asset.SerialNumber = Asset.SerialNumber.ToUpper();
|
||||
responseData.SetControlValue(controlName, Asset.SerialNumber);
|
||||
if (StringUtil.IsBlank(Asset.SerialNumber))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(Asset.SerialNumber) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_SerialNumber))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_SerialNumber)]);
|
||||
}
|
||||
|
||||
// Description.
|
||||
if (Asset.DescBrief != null)
|
||||
{
|
||||
String controlName = "AssetDescription";
|
||||
responseData.SetControlValue(controlName, Asset.DescBrief);
|
||||
if (StringUtil.GetLength(Asset.DescBrief) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_DescBrief))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_DescBrief)]);
|
||||
}
|
||||
|
||||
// Notes.
|
||||
if (Asset.Notes!= null)
|
||||
{
|
||||
String controlName = "AssetNotes";
|
||||
responseData.SetControlValue(controlName, Asset.Notes);
|
||||
if (StringUtil.GetLength(Asset.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_Notes))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_Notes)]);
|
||||
}
|
||||
|
||||
// Asset status.
|
||||
if (Asset.StatusCode != null)
|
||||
{
|
||||
String controlName = "AssetStatus";
|
||||
if (StringUtil.IsBlank(Asset.StatusCode))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SbmAsset.ValidStatuses.Contains(Asset.GetStatus()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Assets
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_AssetCategory : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_AssetCategory(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String Search { get; set; }
|
||||
public String StatusCat { get; set; }
|
||||
public SbmAssetCategory.StatusCat GetStatusCat()
|
||||
{
|
||||
return EnumUtil.ParseEnum(StatusCat, SbmAssetCategory.StatusCat.NotDeleted);
|
||||
}
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public class AssetCategoryData
|
||||
{
|
||||
public String Exists { get; set; }
|
||||
public String Id { get; set; }
|
||||
public String TypeCode { get; set; }
|
||||
public Sbm.AssetType AssetType { get; set; }
|
||||
public String Code { get; set; }
|
||||
public String DescBrief { get; set; }
|
||||
public String Notes { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public SaStatus GetStatus() { return SacsSystem.GetStatusForCode(StatusCode); }
|
||||
}
|
||||
public AssetCategoryData AssetCategory { get; } = new AssetCategoryData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// AssetCategory.
|
||||
public bool ValidateAssetCategoryData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// AssetCategory type.
|
||||
if (AssetCategory.TypeCode != null)
|
||||
{
|
||||
String controlName = "AssetCategoryType";
|
||||
AssetCategory.AssetType = (Sbm.AssetType)Internals.AssetTypeCodes.GetTypeForCode(AssetCategory.TypeCode);
|
||||
responseData.SetControlValue(controlName, AssetCategory.TypeCode);
|
||||
if (StringUtil.IsBlank(AssetCategory.TypeCode))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (AssetCategory.AssetType == 0)
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
// AssetCategory Code.
|
||||
if (AssetCategory.Code != null)
|
||||
{
|
||||
String controlName = "AssetCategoryCode";
|
||||
AssetCategory.Code = AssetCategory.Code.ToUpper();
|
||||
responseData.SetControlValue(controlName, AssetCategory.Code);
|
||||
if (StringUtil.IsBlank(AssetCategory.Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(AssetCategory.Code) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Code)]);
|
||||
}
|
||||
|
||||
// AssetCategory DescBrief.
|
||||
if (AssetCategory.DescBrief != null)
|
||||
{
|
||||
String controlName = "AssetCategoryDescription";
|
||||
responseData.SetControlValue(controlName, AssetCategory.DescBrief);
|
||||
if (StringUtil.IsBlank(AssetCategory.DescBrief))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(AssetCategory.DescBrief) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_DescBrief))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_DescBrief)]);
|
||||
}
|
||||
|
||||
// Notes.
|
||||
if (AssetCategory.Notes != null)
|
||||
{
|
||||
String controlName = "AssetCategoryNotes";
|
||||
responseData.SetControlValue(controlName, AssetCategory.Notes);
|
||||
if (StringUtil.GetLength(AssetCategory.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Notes))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Notes)]);
|
||||
}
|
||||
|
||||
// AssetCategory status.
|
||||
if (AssetCategory.StatusCode != null)
|
||||
{
|
||||
String controlName = "AssetCategoryStatus";
|
||||
if (StringUtil.IsBlank(AssetCategory.StatusCode))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SbmAssetCategory.ValidStatuses.Contains(AssetCategory.GetStatus()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Assets
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_VehicleClass : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_VehicleClass(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public string Search { get; set; }
|
||||
public string StatusCat { get; set; }
|
||||
public SbmVehicleClass.StatusCat GetStatusCat()
|
||||
{
|
||||
return EnumUtil.ParseEnum(StatusCat, SbmVehicleClass.StatusCat.NotDeleted);
|
||||
}
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public class VehicleClassData
|
||||
{
|
||||
public string Exists { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string MakeCode { get; set; }
|
||||
public string Model { get; set; }
|
||||
public string Derivative { get; set; }
|
||||
public string DescBrief { get; set; }
|
||||
public string VehicleTypeCode { get; set; }
|
||||
public Sbm.VehicleType VehicleType { get; set; } = Sbm.VehicleType.Unknown;
|
||||
public string VehicleCategoryCode { get; set; }
|
||||
public string FuelTypeCode { get; set; }
|
||||
public Sbm.VehicleFuelType FuelType { get; set; } = Sbm.VehicleFuelType.Unknown;
|
||||
public string OdometerUnitsCode { get; set; }
|
||||
public Sbm.VehicleOdometerUnits OdometerUnits { get; set; } = Sbm.VehicleOdometerUnits.Unknown;
|
||||
public string Notes { get; set; }
|
||||
public string StatusCode { get; set; }
|
||||
public SaStatus GetStatus() { return SacsSystem.GetStatusForCode(StatusCode); }
|
||||
}
|
||||
public VehicleClassData VehicleClass { get; } = new VehicleClassData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// VehicleClass.
|
||||
public bool ValidateVehicleClassData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Make.
|
||||
if (VehicleClass.MakeCode != null)
|
||||
{
|
||||
string controlName = "VehicleClassMake";
|
||||
responseData.SetControlValue(controlName, VehicleClass.MakeCode);
|
||||
if (VehicleClass.MakeCode.IsBlank())
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Model.
|
||||
if (VehicleClass.Model != null)
|
||||
{
|
||||
string controlName = "VehicleClassModel";
|
||||
VehicleClass.Model = VehicleClass.Model.ToUpper();
|
||||
responseData.SetControlValue(controlName, VehicleClass.Model);
|
||||
if (VehicleClass.Model.IsBlank())
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(VehicleClass.Model) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Model))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Model)]);
|
||||
}
|
||||
|
||||
// VehicleClass DescBrief.
|
||||
if (VehicleClass.DescBrief != null)
|
||||
{
|
||||
string controlName = "VehicleClassDescription";
|
||||
responseData.SetControlValue(controlName, VehicleClass.DescBrief);
|
||||
if (VehicleClass.DescBrief.IsBlank())
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(VehicleClass.DescBrief) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_DescBrief))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_DescBrief)]);
|
||||
}
|
||||
|
||||
// Notes.
|
||||
if (VehicleClass.Notes != null)
|
||||
{
|
||||
string controlName = "VehicleClassNotes";
|
||||
responseData.SetControlValue(controlName, VehicleClass.Notes);
|
||||
if (StringUtil.GetLength(VehicleClass.Notes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Notes))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Notes)]);
|
||||
}
|
||||
|
||||
// VehicleClass status.
|
||||
if (VehicleClass.StatusCode != null)
|
||||
{
|
||||
string controlName = "VehicleClassStatus";
|
||||
if (VehicleClass.StatusCode.IsBlank())
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SbmVehicleClass.ValidStatuses.Contains(VehicleClass.GetStatus()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.CodeTypes;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Code : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Code(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Page preparation data.
|
||||
// Only populated when page is first presented from main code controller.
|
||||
public void PopulateCodeTypes()
|
||||
{
|
||||
if (CodeTypes != null) return;
|
||||
SaCodeType.Params prmCodeType = new SaCodeType.Params();
|
||||
prmCodeType.SortColumns.Add(CodeTypeConsole.GetCodeTypeColumnDfn(SaCodeType.Column.Name));
|
||||
CodeTypes = new List<SaCodeType>(CodeTypeConsole.GetCodeTypeList(prmCodeType));
|
||||
}
|
||||
public List<SaCodeType> CodeTypes { get; private set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String CodeTypeCode { get; set; }
|
||||
public String Search { get; set; }
|
||||
public String StatusCat { get; set; }
|
||||
public SaCode.StatusCat GetStatusCat()
|
||||
{
|
||||
return EnumUtil.ParseEnum(StatusCat, SaCode.StatusCat.Any);
|
||||
}
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public class CodeData
|
||||
{
|
||||
public String Exists { get; set; }
|
||||
public String Id { get; set; }
|
||||
public String CodeTypeId { get; set; }
|
||||
public String Code{ get; set; }
|
||||
public String Description { get; set; }
|
||||
public String Sequence { get; set; }
|
||||
public String Notes { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public SaStatus GetStatus() { return SacsSystem.GetStatusForCode(StatusCode); }
|
||||
}
|
||||
public CodeData Code { get; } = new CodeData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Code.
|
||||
public bool ValidateCodeData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Code Type.
|
||||
if (Code.CodeTypeId != null)
|
||||
{
|
||||
String controlName = "CodeType";
|
||||
if (StringUtil.IsBlank(Code.CodeTypeId))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!CodeTypeConsole.CodeTypeExistsById(Code.CodeTypeId.ToSysId()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
// Code.
|
||||
if (Code.Code != null)
|
||||
{
|
||||
String controlName = "CodeCode";
|
||||
responseData.SetControlValue(controlName, Code.Code);
|
||||
if (StringUtil.IsBlank(Code.Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(Code.Code) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Code)]);
|
||||
}
|
||||
|
||||
// Description.
|
||||
if (Code.Description != null)
|
||||
{
|
||||
String controlName = "CodeDescription";
|
||||
responseData.SetControlValue(controlName, Code.Description);
|
||||
if (StringUtil.IsBlank(Code.Description))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(Code.Description) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Description))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Description)]);
|
||||
}
|
||||
|
||||
// Notes.
|
||||
if (Code.Notes!= null)
|
||||
{
|
||||
String controlName = "CodeNotes";
|
||||
responseData.SetControlValue(controlName, Code.Notes);
|
||||
if (StringUtil.GetLength(Code.Notes) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Notes))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Notes)]);
|
||||
}
|
||||
|
||||
// Code status.
|
||||
if (Code.StatusCode != null)
|
||||
{
|
||||
String controlName = "CodeStatus";
|
||||
if (StringUtil.IsBlank(Code.StatusCode))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaCode.ValidStatuses.Contains(Code.GetStatus()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.Models;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.CodeTypes;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Codes
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_CodeType : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_CodeType(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String Search { get; set; }
|
||||
public String StatusCat { get; set; }
|
||||
public SaCodeType.StatusCat GetStatusCat()
|
||||
{
|
||||
return EnumUtil.ParseEnum(StatusCat, SaCodeType.StatusCat.ActiveOnly);
|
||||
}
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public class CodeTypeData
|
||||
{
|
||||
public String Exists { get; set; }
|
||||
public String Id { get; set; }
|
||||
public String Code { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String AutoAssignCode { get; set; }
|
||||
public String MaxCodeLength { get; set; }
|
||||
public String Notes { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public SaStatus GetStatus() { return SacsSystem.GetStatusForCode(StatusCode); }
|
||||
}
|
||||
public CodeTypeData CodeType { get; } = new CodeTypeData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// CodeType.
|
||||
public bool ValidateCodeTypeData(SbmController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposables = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Code.
|
||||
if (CodeType.Code != null)
|
||||
{
|
||||
String controlName = "CodeTypeCode";
|
||||
responseData.SetControlValue(controlName, CodeType.Code);
|
||||
if (StringUtil.IsBlank(CodeType.Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(CodeType.Code) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code)]);
|
||||
else
|
||||
{
|
||||
SaCodeType.Params prmCodeType = new SaCodeType.Params();
|
||||
if (StringUtil.ToBool(CodeType.Exists) && SysId.IsValid(CodeType.Id.ToSysId()))
|
||||
prmCodeType.IdsExcluded.Add(CodeType.Id.ToSysId());
|
||||
prmCodeType.Code = CodeType.Code;
|
||||
if (CodeTypeConsole.GetCodeTypeCount(prmCodeType) > 0)
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Name.
|
||||
if (CodeType.Name != null)
|
||||
{
|
||||
String controlName = "CodeTypeName";
|
||||
responseData.SetControlValue(controlName, CodeType.Name);
|
||||
if (StringUtil.IsBlank(CodeType.Name))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(CodeType.Name) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Name))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Name)]);
|
||||
}
|
||||
|
||||
// Notes.
|
||||
if (CodeType.Notes != null)
|
||||
{
|
||||
String controlName = "CodeTypeNotes";
|
||||
responseData.SetControlValue(controlName, CodeType.Notes);
|
||||
if (StringUtil.GetLength(CodeType.Notes) > GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Notes))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Notes)]);
|
||||
}
|
||||
|
||||
// CodeType status.
|
||||
if (CodeType.StatusCode != null)
|
||||
{
|
||||
String controlName = "CodeTypeStatus";
|
||||
if (StringUtil.IsBlank(CodeType.StatusCode))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaCodeType.ValidStatuses.Contains(CodeType.GetStatus()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Commodity : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Commodity(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sbm-commodity.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public string CommoditySearch { get; set; }
|
||||
public string CommodityType { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public Sbm.CommodityType GetFilterCommodityType()
|
||||
{
|
||||
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity properties.
|
||||
public string CommodityId { get; set; }
|
||||
public string CommodityExists { get; set; }
|
||||
public string CommodityType { get; set; }
|
||||
public Sbm.CommodityType GetCommodityType()
|
||||
{
|
||||
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(CommodityType);
|
||||
}
|
||||
public string CommodityCode { get; set; }
|
||||
public string CommodityDesc { get; set; }
|
||||
// Common properties.
|
||||
public string CommodityNotes { get; set; }
|
||||
public string CommodityStatusCode { get; set; }
|
||||
public SaStatus CommodityStatus { get { return SacsSystem.GetStatusForCode(CommodityStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity validation.
|
||||
public bool ValidateCommodityData(Sacs.Web.Components.SaController.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Commodity Type.
|
||||
if (CommodityType != null)
|
||||
{
|
||||
if (CommodityType.IsEmpty())
|
||||
responseData.SetControlError(nameof(CommodityType), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Commodity Code.
|
||||
if (CommodityCode != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityCode), CommodityCode);
|
||||
if (CommodityCode.IsEmpty())
|
||||
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.GetLength(CommodityCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code))
|
||||
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code)]);
|
||||
}
|
||||
|
||||
// Commodity Desc.
|
||||
if (CommodityDesc != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityDesc), CommodityDesc);
|
||||
if (CommodityDesc.IsEmpty())
|
||||
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.GetLength(CommodityDesc) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief))
|
||||
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief)]);
|
||||
}
|
||||
|
||||
// Commodity Notes.
|
||||
if (CommodityNotes != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityNotes), CommodityNotes);
|
||||
if (!CommodityNotes.IsEmpty() && StringUtil.GetLength(CommodityNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes))
|
||||
responseData.SetControlError(nameof(CommodityNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes)]);
|
||||
}
|
||||
|
||||
// Commodity status.
|
||||
if (CommodityStatusCode != null)
|
||||
{
|
||||
if (CommodityStatusCode.IsEmpty())
|
||||
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SbmCommodity.ValidStatuses.Contains(CommodityStatus))
|
||||
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class ErrorViewModel : SbmModel_Portal
|
||||
|
||||
@@ -12,7 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Association : SbmModel_Portal
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
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;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Commodity : SbmModel_Portal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Commodity(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sbm-commodity.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Filter properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String CommoditySearch { get; set; }
|
||||
public String CommodityType { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public Sbm.CommodityType GetFilterCommodityType()
|
||||
{
|
||||
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity properties.
|
||||
public String CommodityId { get; set; }
|
||||
public String CommodityExists { get; set; }
|
||||
public String CommodityType{ get; set; }
|
||||
public Sbm.CommodityType GetCommodityType()
|
||||
{
|
||||
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(CommodityType);
|
||||
}
|
||||
public String CommodityCode { get; set; }
|
||||
public String CommodityDesc { get; set; }
|
||||
// Common properties.
|
||||
public String CommodityNotes { get; set; }
|
||||
public String CommodityStatusCode { get; set; }
|
||||
public SaStatus CommodityStatus { get { return SacsSystem.GetStatusForCode(CommodityStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Commodity validation.
|
||||
public bool ValidateCommodityData(SbmController_Web.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Commodity Type.
|
||||
if (CommodityType != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(CommodityType))
|
||||
responseData.SetControlError(nameof(CommodityType), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Commodity Code.
|
||||
if (CommodityCode != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityCode), CommodityCode);
|
||||
if (StringUtil.IsEmpty(CommodityCode))
|
||||
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.GetLength(CommodityCode) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code))
|
||||
responseData.SetControlError(nameof(CommodityCode), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code)]);
|
||||
}
|
||||
|
||||
// Commodity Desc.
|
||||
if (CommodityDesc != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityDesc), CommodityDesc);
|
||||
if (StringUtil.IsEmpty(CommodityDesc))
|
||||
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.GetLength(CommodityDesc) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief))
|
||||
responseData.SetControlError(nameof(CommodityDesc), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief)]);
|
||||
}
|
||||
|
||||
// Commodity Notes.
|
||||
if (CommodityNotes != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(CommodityNotes), CommodityNotes);
|
||||
if (!StringUtil.IsEmpty(CommodityNotes) && StringUtil.GetLength(CommodityNotes) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes))
|
||||
responseData.SetControlError(nameof(CommodityNotes), Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes)]);
|
||||
}
|
||||
|
||||
// Commodity status.
|
||||
if (CommodityStatusCode != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(CommodityStatusCode))
|
||||
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SbmCommodity.ValidStatuses.Contains(CommodityStatus))
|
||||
responseData.SetControlError(nameof(CommodityStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -12,7 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Contact : SbmModel_Portal
|
||||
|
||||
@@ -9,7 +9,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Home : SbmModel_Portal
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Security : SbmModel_Portal
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
namespace Sarand.BusinessMgr.Web.Portal.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmModel_Portal : SbmModel_Base
|
||||
@@ -19,7 +22,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public String OrganisationName { get { return SessionData?.Organisation?.DisplayName ?? ""; } }
|
||||
public SbmSessionData_Portal SessionData_Portal { get { return SessionData as SbmSessionData_Portal; } }
|
||||
public override ISbmUserContext_Core UserContext_Core { get { return SessionData_Portal; } }
|
||||
public String OrganisationName { get { return SessionData_Portal?.Organisation?.DisplayName ?? ""; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<RootNamespace>Sarand.BusinessMgr.Net.Core.Web</RootNamespace>
|
||||
<AssemblyName>Sarand.BusinessMgr.Net.Core.Web</AssemblyName>
|
||||
<RootNamespace>Sarand.BusinessMgr.Web</RootNamespace>
|
||||
<AssemblyName>Sarand.BusinessMgr.Web</AssemblyName>
|
||||
<Description>SaBusinessMgrCoreWebPortal</Description>
|
||||
<PackageId>SaBusinessMgrCoreWebPortal</PackageId>
|
||||
<Authors>Sarand</Authors>
|
||||
@@ -28,6 +28,10 @@
|
||||
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\**\*.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Machine.Sarand110.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
@@ -37,7 +41,17 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Portal\Controllers\Vehicles\" />
|
||||
<Folder Include="Views\Assets\Asset\" />
|
||||
<Folder Include="Views\Assets\Vehicle\" />
|
||||
<Folder Include="Views\Vehicles\" />
|
||||
<Folder Include="Views\Transactions\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Localisation\SbmPortalProperties.resx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
@* Assets - Asset *@
|
||||
@model Model_Asset
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Assets";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-asset.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Assets">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.asset.create"))';
|
||||
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.asset.update"))';
|
||||
sbm.lbl.selectCategory = '@(Localiser.GetJavascriptText("caption.category.select"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="col center"><div class="sbm-panel-caption">@Localiser["label.assets"]</div></div>
|
||||
<div class="fixed">
|
||||
@* 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 pb4">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbm-panel-item-table">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2">@Localiser["label.category"]</th>
|
||||
<th class="">@Localiser["label.serial"]</th>
|
||||
<th class="">@Localiser["label.description"]</th>
|
||||
<th class="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">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu AssetFilter">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
@* Asset row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbm-row-item Asset">
|
||||
<td><div class="AssetCategory pl-1"></div></td>
|
||||
<td><div class="AssetSerial"></div></td>
|
||||
<td><div class="AssetDescription"></div></td>
|
||||
<td><div class="AssetStatusDesc center"></div></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>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Asset">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetId", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Asset.Id, new { @id = "", @class = "AssetId" })
|
||||
}
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCategories", @onSubmit = "return false;" }))
|
||||
{
|
||||
}
|
||||
<div id="dlgAsset" class="sbm-dialog">
|
||||
<div class="spacer2"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAsset", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Asset.Exists, new { @id = "", @class = "AssetExists" })
|
||||
@Html.HiddenFor(model => model.Asset.Id, new { @id = "", @class = "AssetId" })
|
||||
|
||||
@* Type *@
|
||||
<div class="sbm-form-control AssetCategory">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for=""><span>@Localiser["label.category"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-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>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Serial Number*@
|
||||
<div class="sbm-form-control AssetSerialNumber">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetSerialNumber"><span>@Localiser["label.serial"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Asset.SerialNumber, new { @id = "ifAssetSerialNumber", @class = "AssetSerialNumber sbm-input upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_SerialNumber) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Description *@
|
||||
<div class="sbm-form-control AssetDescription">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetDescription"><span>@Localiser["label.description"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Asset.DescBrief, new { @id = "ifAssetDescription", @class = "AssetDescription sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_DescBrief) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Status *@
|
||||
<div class="sbm-form-control AssetStatus">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssetStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbAssetStatus" class="sbm-select AssetStatus" name="Asset.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Notes *@
|
||||
<div class="sbm-form-control AssetNotes">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetNotes"><span>@Localiser["label.notes"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.Asset.Notes, new { @id = "ifAssetNotes", @class = "AssetNotes sbm-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAsset_Notes) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Select Item dialog and script *@
|
||||
<partial name="~/Views/Common/SelectItem.cshtml" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,202 @@
|
||||
@* Assets - Asset Category *@
|
||||
@model Model_AssetCategory
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Asset Categories";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-asset-cat.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel AssetCategories">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.asset.category.create"))';
|
||||
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.asset.category.update"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetCategoryFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="col center"><div class="sbm-panel-caption">@Localiser["caption.asset.categories"]</div></div>
|
||||
<div class="fixed">
|
||||
@* 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 pb4">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbm-panel-item-table">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2">@Localiser["label.type"]</th>
|
||||
<th class="">@Localiser["label.code"]</th>
|
||||
<th class="">@Localiser["label.description"]</th>
|
||||
<th class="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">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu AssetCategoryFilter">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
@* AssetCategory row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbm-row-item AssetCategory">
|
||||
<td><div class="AssetCategoryType pl-1"></div></td>
|
||||
<td><div class="AssetCategoryCode"></div></td>
|
||||
<td><div class="AssetCategoryDescription"></div></td>
|
||||
<td><div class="AssetCategoryStatusDesc center"></div></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>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu AssetCategory">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetCategoryId", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.AssetCategory.Id, new { @id = "", @class = "AssetCategoryId" })
|
||||
}
|
||||
<div id="dlgAssetCategory" class="sbm-dialog">
|
||||
<div class="spacer2"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmAssetCategory", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.AssetCategory.Exists, new { @id = "", @class = "AssetCategoryExists" })
|
||||
@Html.HiddenFor(model => model.AssetCategory.Id, new { @id = "", @class = "AssetCategoryId" })
|
||||
|
||||
@* Type *@
|
||||
<div class="sbm-form-control AssetCategoryType">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetCategoryType"><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.DropDownListFor(model => model.AssetCategory.TypeCode, Model.GetAssetTypeCodesForSelect(), Localiser["label.select"], new { @id = "ifAssetCategoryType", @class = "AssetCategoryType sbm-select" })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Contact Code *@
|
||||
<div class="sbm-form-control AssetCategoryCode">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetCategoryCode"><span>@Localiser["label.code"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.AssetCategory.Code, new { @id = "ifAssetCategoryCode", @class = "AssetCategoryCode sbm-input upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Code) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Description *@
|
||||
<div class="sbm-form-control AssetCategoryDescription">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetCategoryDescription"><span>@Localiser["label.description"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.AssetCategory.DescBrief, new { @id = "ifAssetCategoryDescription", @class = "AssetCategoryDescription sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_DescBrief) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Status *@
|
||||
<div class="sbm-form-control AssetCategoryStatus">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbAssetCategoryStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbAssetCategoryStatus" class="sbm-select AssetCategoryStatus" name="AssetCategory.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Notes *@
|
||||
<div class="sbm-form-control AssetCategoryNotes">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifAssetCategoryNotes"><span>@Localiser["label.notes"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.AssetCategory.Notes, new { @id = "ifAssetCategoryNotes", @class = "AssetCategoryNotes sbm-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaAssetCategory_Notes) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,202 @@
|
||||
@* Vehicles - Vehicle Class *@
|
||||
@model Model_VehicleClass
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Vehicle Classes";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-veh-cls.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel VehicleClasses">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.vehicle.class.create"))';
|
||||
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.vehicle.class.update"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmVehicleClassFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="col center"><div class="sbm-panel-caption">@Localiser["caption.vehicle.classes"]</div></div>
|
||||
<div class="fixed">
|
||||
@* 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 pb4">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbm-panel-item-table">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2">@Localiser["label.make"]</th>
|
||||
<th class="">@Localiser["label.model"]</th>
|
||||
<th class="">@Localiser["label.derivative"]</th>
|
||||
<th class="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">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu VehicleClassFilter">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
@* VehicleClass row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbm-row-item VehicleClass">
|
||||
<td><div class="VehicleClassMake pl-1"></div></td>
|
||||
<td><div class="VehicleClassModel"></div></td>
|
||||
<td><div class="VehicleClassDerivative"></div></td>
|
||||
<td><div class="VehicleClassStatusDesc center"></div></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>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu VehicleClass">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmVehicleClassId", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.VehicleClass.Id, new { @id = "", @class = "VehicleClassId" })
|
||||
}
|
||||
<div id="dlgVehicleClass" class="sbm-dialog">
|
||||
<div class="spacer2"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmVehicleClass", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.VehicleClass.Exists, new { @id = "", @class = "VehicleClassExists" })
|
||||
@Html.HiddenFor(model => model.VehicleClass.Id, new { @id = "", @class = "VehicleClassId" })
|
||||
|
||||
@* Make *@
|
||||
<div class="sbm-form-control VehicleClassMake">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbVehicleClassMake"><span>@Localiser["label.make"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbVehicleClassMake" name="VehicleClass.MakeCode" class="VehicleClassMake sbm-select"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Contact Model *@
|
||||
<div class="sbm-form-control VehicleClassModel">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifVehicleClassModel"><span>@Localiser["label.model"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.VehicleClass.Model, new { @id = "ifVehicleClassModel", @class = "VehicleClassModel sbm-input upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Model) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Derivative *@
|
||||
<div class="sbm-form-control VehicleClassDerivative">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifVehicleClassDerivative"><span>@Localiser["label.description"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.VehicleClass.DescBrief, new { @id = "ifVehicleClassDerivative", @class = "VehicleClassDerivative sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_DescBrief) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Status *@
|
||||
<div class="sbm-form-control VehicleClassStatus">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbVehicleClassStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbVehicleClassStatus" class="sbm-select VehicleClassStatus" name="VehicleClass.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Notes *@
|
||||
<div class="sbm-form-control VehicleClassNotes">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifVehicleClassNotes"><span>@Localiser["label.notes"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.VehicleClass.Notes, new { @id = "ifVehicleClassNotes", @class = "VehicleClassNotes sbm-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.SaVehicleClass_Notes) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -8,9 +8,6 @@
|
||||
<div class="sbm-panel Associations">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
|
||||
sbm.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
|
||||
sbm.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
</script>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
@* Codes - Code *@
|
||||
@model Model_Code
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Codes";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-cod.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel Codes fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.code.create"))';
|
||||
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.code.update"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="col center"><div class="sbm-panel-caption">@Localiser["label.codes"]</div></div>
|
||||
<div class="fixed">
|
||||
@* 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 pb4">
|
||||
<div class="col-md-6 row">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.code.type"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.DropDownListFor(model => model.Filter.CodeTypeCode, Model.GetCodeTypesForSelect(), new { @id = "", @class = "FilterCodeTypeCode", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 row">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2" style="width:35%">@Localiser["label.type"]</th>
|
||||
<th class="" style="width:15%">@Localiser["label.code"]</th>
|
||||
<th class="" style="width:35%">@Localiser["label.description"]</th>
|
||||
<th class="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>
|
||||
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbm-panel-item-template">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu CodeFilter">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
@* Code row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbm-row-item Code">
|
||||
<td><div class="CodeType pl-1"></div></td>
|
||||
<td><div class="CodeCode "></div></td>
|
||||
<td><div class="CodeDesc"></div></td>
|
||||
<td><div class="CodeStatusDesc center"></div></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>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu Code">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeId", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Code.Id, new { @id = "", @class = "CodeId" })
|
||||
}
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCategories", @onSubmit = "return false;" }))
|
||||
{
|
||||
}
|
||||
<div id="dlgCode" class="sbm-dialog">
|
||||
<div class="spacer2"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCode", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.Code.Exists, new { @id = "", @class = "CodeExists" })
|
||||
@Html.HiddenFor(model => model.Code.Id, new { @id = "", @class = "CodeId" })
|
||||
|
||||
@* Type *@
|
||||
<div class="sbm-form-control CodeType">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for=""><span>@Localiser["label.type"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control">
|
||||
<select name="model.Code.CodeTypeId" class="CodeType sbm-select" readonly="readonly"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Code *@
|
||||
<div class="sbm-form-control CodeCode">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeCode"><span>@Localiser["label.code"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Code.Code, new { @id = "ifCodeCode", @class = "CodeCode sbm-input", @maxlength = 3 })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Sequence *@
|
||||
<div class="sbm-form-control CodeSequence">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeSequence"><span>@Localiser["label.sequence"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Code.Sequence, new { @id = "ifCodeSequence", @class = "CodeSequence sbm-input", @maxlength = 3 })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Description *@
|
||||
<div class="sbm-form-control CodeDescription">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeDescription"><span>@Localiser["label.description"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.Code.Description, new { @id = "ifCodeDescription", @class = "CodeDescription sbm-input", @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Description) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Status *@
|
||||
<div class="sbm-form-control CodeStatus">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbCodeStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbCodeStatus" class="sbm-select CodeStatus" name="Code.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Notes *@
|
||||
<div class="sbm-form-control CodeNotes">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeNotes"><span>@Localiser["label.notes"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.Code.Notes, new { @id = "ifCodeNotes", @class = "CodeNotes sbm-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCode_Notes) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Select Item dialog and script *@
|
||||
<partial name="~/Views/Common/SelectItem.cshtml" />
|
||||
|
||||
<script>
|
||||
sbm.data.codeTypes = [@foreach (var codeType in Model.CodeTypes)
|
||||
{
|
||||
<text>{code:'@(Localiser.GetJavascriptText(codeType.Code))',name:'@(Localiser.GetJavascriptText(codeType.Name))'},</text>
|
||||
}];
|
||||
</script>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,185 @@
|
||||
@* Codes - Code Type *@
|
||||
@model Model_CodeType
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Code Types";
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-cod-typ.js");
|
||||
}
|
||||
|
||||
<div class="sbm-panel CodeTypes fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.dlg.title.createItem = '@(Localiser.GetJavascriptText("caption.code.type.create"))';
|
||||
sbm.dlg.title.updateItem = '@(Localiser.GetJavascriptText("caption.code.type.update"))';
|
||||
</script>
|
||||
|
||||
<div class="sbm-panel-data sbm-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeTypeFilter", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbm-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
<partial name="~/Views/Common/ResultsPaging.cshtml" />
|
||||
</div>
|
||||
<div class="col center"><div class="sbm-panel-caption">@Localiser["caption.code.types"]</div></div>
|
||||
<div class="fixed">
|
||||
@* 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 pb4">
|
||||
<div class="col-sm-5 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbm-panel-item-table sbm-flex">
|
||||
<table class="sbm-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2">@Localiser["label.code"]</th>
|
||||
<th class="">@Localiser["label.name"]</th>
|
||||
<th class="center">@Localiser["label.codes"]</th>
|
||||
<th class="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">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu CodeTypeFilter">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
@* CodeType row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbm-row-item CodeType">
|
||||
<td><div class="CodeTypeCode pl-1"></div></td>
|
||||
<td><div class="CodeTypeName"></div></td>
|
||||
<td class="center"><div class="CodeTypeCodes"></div></td>
|
||||
<td><div class="CodeTypeStatusDesc center"></div></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>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbm-dropdown-menu CodeType">
|
||||
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeTypeId", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.CodeType.Id, new { @id = "", @class = "CodeTypeId" })
|
||||
}
|
||||
<div id="dlgCodeType" class="sbm-dialog">
|
||||
<div class="spacer2"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCodeType", @class = "sbm-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.CodeType.Exists, new { @id = "", @class = "CodeTypeExists" })
|
||||
@Html.HiddenFor(model => model.CodeType.Id, new { @id = "", @class = "CodeTypeId" })
|
||||
|
||||
@* Code *@
|
||||
<div class="sbm-form-control CodeTypeCode">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeTypeCode"><span>@Localiser["label.code"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.CodeType.Code, new { @id = "ifCodeTypeCode", @class = "CodeTypeCode sbm-input", @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Code) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Name *@
|
||||
<div class="sbm-form-control CodeTypeName">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeTypeName"><span>@Localiser["label.name"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
@Html.TextBoxFor(model => model.CodeType.Name, new { @id = "ifCodeTypeName", @class = "CodeTypeName sbm-input", @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Name) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Status *@
|
||||
<div class="sbm-form-control CodeTypeStatus">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="cbCodeTypeStatus"><span>@Localiser["label.status"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbm-control">
|
||||
<select id="cbCodeTypeStatus" class="sbm-select CodeTypeStatus" name="CodeType.StatusCode"></select>
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Notes *@
|
||||
<div class="sbm-form-control CodeTypeNotes">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbm-label">
|
||||
<label for="ifCodeTypeNotes"><span>@Localiser["label.notes"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sbm-control">
|
||||
@Html.TextAreaFor(model => model.CodeType.Notes, new { @id = "ifCodeTypeNotes", @class = "CodeTypeNotes sbm-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SaCodeTypeDbDfn.ColumnIdx.SaCodeType_Notes) })
|
||||
</div>
|
||||
<div class="sbm-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -8,9 +8,6 @@
|
||||
<div class="sbm-panel Commodities">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
|
||||
sbm.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
|
||||
sbm.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
</script>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-resultsPaging.js");
|
||||
}
|
||||
|
||||
<script src="~/js/sbm-resultsPaging.js?@Model.HrefVersion"></script>
|
||||
<script type="text/javascript">
|
||||
sbm.resultsPaging.msg.pageInfo = '@Localiser.GetJavascriptText("label.page.info","{0}","{1}")';
|
||||
sbm.resultsPaging = sbm.resultsPaging || { fn: {}, msg: {}, contexts: [] };
|
||||
sbm.resultsPaging.msg.pageInfo = '@Localiser.GetJavascriptText("label.page.info", "{0}", "{1}")';
|
||||
</script>
|
||||
|
||||
@* Results paging *@
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
@model SbmModel_Portal
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Common/SelectItem")) return;
|
||||
// Scripts.
|
||||
Model.AdditionalFiles_JS.Add("js/sbm-sel-itm.js");
|
||||
}
|
||||
|
||||
<link rel="stylesheet" href="~/css/sbm-sel-itm.css?@Model.HrefVersion" />
|
||||
|
||||
<div id="dlgSelectItem" class="sbm-dialog sbm-form">
|
||||
|
||||
<div class="container-fluid h-100">
|
||||
|
||||
@* Selected Item *@
|
||||
<div class="SelectedItem">
|
||||
<div class="row">
|
||||
<div class="col-sm-12"><div class="sbm-label">@Localiser["label.item.selected"]:</div></div>
|
||||
<div class="col-sm-12"><div class="SelectedItemName"></div></div>
|
||||
</div>
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Item Filter *@
|
||||
<div class="ItemFilter sbm-form">
|
||||
<div class="row">
|
||||
<div class="col right"><div class="sbm-label">@Localiser["label.search"]</div></div>
|
||||
<div class="fixed"><input type="search" id="ifItemFilter" class="sbm-input" autocomplete="off" onkeyup="sbm.data.selectItem.fn.displayItems();" /></div>
|
||||
</div>
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@* Available items *@
|
||||
<div class="row">
|
||||
<div class="col"><div class="sbm-label bottom">@Localiser["label.items.available"]:</div></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-12 sbm-selectItem-items AvailableItems"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="sbm-panel-item-template">
|
||||
<div class="sbm-panel-item Item">
|
||||
<div class="ItemName"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -8,9 +8,6 @@
|
||||
<div class="sbm-panel Contacts">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbm.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
|
||||
sbm.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
|
||||
sbm.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
sbm.lbl.createOrg = '@(Localiser.GetJavascriptText("label.create.organisation"))';
|
||||
sbm.lbl.createInd = '@(Localiser.GetJavascriptText("label.create.individual"))';
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,108 @@
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
ViewData["Title"] = "Home Page";
|
||||
bool showTestPage = false;
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Welcome</h1>
|
||||
</div>
|
||||
@if (!showTestPage)
|
||||
{
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Welcome</h1>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<style>
|
||||
.abc-panel-item-table
|
||||
{
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
background-color: white;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
table.abc-item-list
|
||||
{
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
table.abc-item-list thead tr
|
||||
{
|
||||
}
|
||||
|
||||
table.abc-item-list thead th
|
||||
{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 4px 2px 2px 2px;
|
||||
z-index: 1;
|
||||
background-color: #f8f8f8;
|
||||
border-bottom: 1px solid #d0d0d0;
|
||||
}
|
||||
|
||||
table.abc-item-list tbody th
|
||||
{
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<div style="height:100%;background-color:lightcyan;">
|
||||
<div style="display:flex;flex-direction:column;height:100%;padding:4px 8px;">
|
||||
<div style="flex:0;padding:4px 8px;background-color:lightgreen;border:1px solid green;">Upper</div>
|
||||
<div class="abc-panel-item-table" style="background-color:#f0e0e0;border:1px solid red;">
|
||||
<table class="abc-item-list">
|
||||
<thead>
|
||||
<tr><th>Row</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>1</td></tr>
|
||||
<tr><td>2</td></tr>
|
||||
<tr><td>3</td></tr>
|
||||
<tr><td>4</td></tr>
|
||||
<tr><td>5</td></tr>
|
||||
<tr><td>6</td></tr>
|
||||
<tr><td>7</td></tr>
|
||||
<tr><td>8</td></tr>
|
||||
<tr><td>9</td></tr>
|
||||
<tr><td>10</td></tr>
|
||||
<tr><td>11</td></tr>
|
||||
<tr><td>12</td></tr>
|
||||
<tr><td>13</td></tr>
|
||||
<tr><td>14</td></tr>
|
||||
<tr><td>15</td></tr>
|
||||
<tr><td>16</td></tr>
|
||||
<tr><td>17</td></tr>
|
||||
<tr><td>18</td></tr>
|
||||
<tr><td>19</td></tr>
|
||||
<tr><td>20</td></tr>
|
||||
<tr><td>1</td></tr>
|
||||
<tr><td>2</td></tr>
|
||||
<tr><td>3</td></tr>
|
||||
<tr><td>4</td></tr>
|
||||
<tr><td>5</td></tr>
|
||||
<tr><td>6</td></tr>
|
||||
<tr><td>7</td></tr>
|
||||
<tr><td>8</td></tr>
|
||||
<tr><td>9</td></tr>
|
||||
<tr><td>10</td></tr>
|
||||
<tr><td>11</td></tr>
|
||||
<tr><td>12</td></tr>
|
||||
<tr><td>13</td></tr>
|
||||
<tr><td>14</td></tr>
|
||||
<tr><td>15</td></tr>
|
||||
<tr><td>16</td></tr>
|
||||
<tr><td>17</td></tr>
|
||||
<tr><td>18</td></tr>
|
||||
<tr><td>19</td></tr>
|
||||
<tr><td>20</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style="flex:0;padding:4px 8px;background-color:lightblue;border:1px solid blue;">Lower</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -54,26 +54,30 @@
|
||||
}
|
||||
|
||||
@* Scripts *@
|
||||
<script>
|
||||
var sbm = sbm || { page: {}, url: {}, links: {}, data: {}, form: {}, ajax: {}, msg: {}, lbl: {}, dlg: { title: {}, btn: {} }, $frm: {}, $dlg: {}, $pnl: {} };
|
||||
<script type="text/javascript">
|
||||
var sbm = sbm || { page: {}, mdl: {}, fn: {}, url: {}, links: {}, data: {}, form: {}, ajax: {}, msg: {}, lbl: {}, dlg: { title: {}, btn: {} }, $frm: {}, $dlg: {}, $pnl: {}, session: {}, kli: {} };
|
||||
sbm.url.base = '@Model.RedirectLocation.Base';
|
||||
sbm.url.home = '@Model.RedirectLocation.Home';
|
||||
sbm.url.sessionExpired = '@Model.RedirectLocation.Home_SessionExpired';
|
||||
sbm.form.calendarDateFormat = '@(Model.CalendarDateFormat)';
|
||||
sbm.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
|
||||
sbm.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
|
||||
sbm.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
sbm.lbl.calendar = '@Localiser.GetJavascriptText("label.calendar")';
|
||||
sbm.dlg.title.alert = '@Localiser.GetJavascriptText("dialog.title.alert")';
|
||||
sbm.dlg.title.confirm = '@Localiser.GetJavascriptText("dialog.title.confirm")';
|
||||
sbm.dlg.title.progress = '@Localiser.GetJavascriptText("dialog.title.progress")';
|
||||
sbm.dlg.title.signOut = '@Localiser.GetJavascriptText("label.signout")';
|
||||
sbm.dlg.btn.yes = '@Localiser["label.yes"]';
|
||||
sbm.dlg.btn.no = '@Localiser["label.no"]';
|
||||
sbm.dlg.btn.ok = '@Localiser["label.ok"]';
|
||||
sbm.dlg.btn.close = '@Localiser["label.close"]';
|
||||
sbm.dlg.btn.cancel = '@Localiser["label.cancel"]';
|
||||
sbm.lbl.yes = '@Localiser["label.yes"]';
|
||||
sbm.lbl.no = '@Localiser["label.no"]';
|
||||
sbm.lbl.ok = '@Localiser["label.ok"]';
|
||||
sbm.lbl.close = '@Localiser["label.close"]';
|
||||
sbm.lbl.save = '@Localiser["label.save"]';
|
||||
sbm.lbl.cancel = '@Localiser["label.cancel"]';
|
||||
sbm.lbl.availableCharacter = '@Localiser.GetJavascriptText("label.characters.one")';
|
||||
sbm.lbl.availableCharacters = '@Localiser.GetJavascriptText("label.characters.count", "{0}")';
|
||||
sbm.lbl.noneSelected = '@Localiser.GetJavascriptText("label.selected.none")';
|
||||
sbm.lbl.numberSelected = '@Localiser.GetJavascriptText("label.selected.count", "{0}")';
|
||||
sbm.dlg.title.alert = '@Localiser.GetJavascriptText("dialog.title.alert")';
|
||||
sbm.dlg.title.confirm = '@Localiser.GetJavascriptText("dialog.title.confirm")';
|
||||
sbm.dlg.title.progress = '@Localiser.GetJavascriptText("dialog.title.progress")';
|
||||
sbm.dlg.title.signOut = '@Localiser.GetJavascriptText("label.signout")';
|
||||
sbm.msg.itemRemoveConfirm = '@Localiser.GetJavascriptText("msg.confirm.item.remove")';
|
||||
sbm.msg.signOutConfirm = '@Localiser.GetJavascriptText("security.msg.signout.confirm")';
|
||||
sbm.msg.somethingGoneWrong = '@Localiser.GetJavascriptText("msg.something.gone.wrong")';
|
||||
@@ -117,14 +121,34 @@
|
||||
{
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Localiser["label.reference"]
|
||||
@Localiser["label.contacts"]
|
||||
</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('Commodity');">@Localiser["label.commodities"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Association');">@Localiser["label.associations"]</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Localiser["label.commodities"]
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Commodity');">@Localiser["label.commodities"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Assets/AssetCategory');">@Localiser["caption.asset.categories"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Assets/Asset');">@Localiser["label.assets"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Assets/VehicleClass');">@Localiser["caption.vehicle.classes"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Assets/Vehicle');">@Localiser["label.vehicles"]</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Localiser["label.reference"]
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Codes/CodeType');">@Localiser["caption.code.types"]</div>
|
||||
<div class="dropdown-item text-dark sbm-action" onclick="sbm.goToPage('Codes/Code');">@Localiser["label.codes"]</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Localiser["label.security"]
|
||||
@@ -144,7 +168,7 @@
|
||||
|
||||
@* Page body *@
|
||||
<div id="sbm-page-body" class="container">
|
||||
<main role="main" class="pb-3">
|
||||
<main role="main" class="pb-3 fullheight">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
@using Sarand.BusinessMgr.Net.Core.Web.App
|
||||
@using Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
@using Sarand.BusinessMgr.Net.Core.Web.Portal.Models
|
||||
@using Sarand.BusinessMgr.Web.Portal.Models
|
||||
@using Sarand.BusinessMgr.Web.Portal.Models.Commodities
|
||||
@using Sarand.BusinessMgr.Web.Portal.Models.Codes
|
||||
@using Sarand.BusinessMgr.Web.Portal.Models.Assets
|
||||
@using Sarand.Net.Standard.Base.CodeTypes
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"Environments": [ "Development" ],
|
||||
"Instance": "Dev",
|
||||
"ControlDatabase": {
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Control",
|
||||
"Location": "MsSql:.\\SQL2016.SaBusinessMgr_Control",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
@@ -26,6 +26,18 @@
|
||||
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_BPE",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
{
|
||||
"Identifiers": [ "MIMO" ],
|
||||
"Location": "MsSql:.\\SQL2016.SaBusinessMgr_Mimo",
|
||||
"User": "sapphire",
|
||||
"Password": "sarand"
|
||||
},
|
||||
{
|
||||
"Identifiers": [ "Firtree-X" ],
|
||||
"Location": "MsSql:Sarand110\\SQL2016.SaBusinessMgr_Firtree",
|
||||
"User": "firtree",
|
||||
"Password": "sarand"
|
||||
}
|
||||
],
|
||||
"Email": {
|
||||
|
||||
@@ -200,6 +200,11 @@ td.action
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fullheight
|
||||
{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.inlineblock, .inlineBlock, .iblock, .inlineb, .ib
|
||||
{
|
||||
display: inline-block;
|
||||
|
||||
@@ -2,75 +2,111 @@
|
||||
BusMgr Portal - Data stylesheet.
|
||||
*/
|
||||
|
||||
/* Filter panel */
|
||||
|
||||
.sbm-panel-filter
|
||||
:root
|
||||
{
|
||||
margin: 8px auto;
|
||||
--color-OliveGreen: #808000;
|
||||
--color-DataPanel-main: var(--color-OliveGreen);
|
||||
}
|
||||
|
||||
/* Data panel */
|
||||
|
||||
.sbm-panel-data
|
||||
{
|
||||
margin: 6px auto;
|
||||
background-color: #f8f8f8;
|
||||
border: solid 1px #979797;
|
||||
border: solid 1px var(--color-DataPanel-main);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (min-width: 576px)
|
||||
.sbm-layout-flex .sbm-panel-data.sbm-flex
|
||||
{
|
||||
.sbm-panel-filter
|
||||
{
|
||||
}
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header
|
||||
/* Data panel - Header */
|
||||
|
||||
.sbm-panel-data .sbm-panel-header
|
||||
{
|
||||
padding: 1px 8px 2px 8px;
|
||||
min-height: 24px;
|
||||
color: #f0f0f0;
|
||||
background-color: #979797;
|
||||
border-bottom: solid 1px #979797;
|
||||
background-color: var(--color-DataPanel-main);
|
||||
border-bottom: solid 1px var(--color-DataPanel-main);
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header .sbm-caption
|
||||
.sbm-panel-data .sbm-panel-header .sbm-panel-caption
|
||||
{
|
||||
margin-top: 4px;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header .sbm-action
|
||||
/* Data panel - Actions */
|
||||
|
||||
.sbm-panel-data ul.nav.sbm-burger
|
||||
{
|
||||
margin: 2px 4px 0 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.sbm-panel-data .sbm-panel-header .sbm-action
|
||||
{
|
||||
margin: 2px 0 0 8px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header .sbm-action:hover
|
||||
.sbm-panel-data .sbm-panel-header .sbm-action:hover
|
||||
{
|
||||
background-color: #e0e0e0;
|
||||
/*box-shadow: 0 0 4px 2px #80808080;*/
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-content
|
||||
/* Data panel - Filter */
|
||||
|
||||
.sbm-panel-data .sbm-panel-filter
|
||||
{
|
||||
margin: 4px 8px;
|
||||
padding: 4px 8px;
|
||||
padding: 6px 8px;
|
||||
border-bottom: solid 1px var(--color-DataPanel-main);
|
||||
}
|
||||
|
||||
.sbm-panel-data .sbm-panel-filter .sbm-label
|
||||
{
|
||||
padding: 2px 8px 0 0;
|
||||
}
|
||||
|
||||
/* Data panel - Content */
|
||||
|
||||
.sbm-panel-data .sbm-content
|
||||
{
|
||||
margin: 4px 4px;
|
||||
padding: 4px 4px;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-content .sbm-label
|
||||
.sbm-panel-data .sbm-content .sbm-label
|
||||
{
|
||||
padding-top: 2px;
|
||||
padding-top: 6px;
|
||||
padding-right: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-content input[type="text"],
|
||||
.sbm-panel-filter .sbm-content select
|
||||
.sbm-panel-data .sbm-panel-content .sbm-value
|
||||
{
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.sbm-panel-data .sbm-content input[type="text"],
|
||||
.sbm-panel-data .sbm-content select
|
||||
{
|
||||
min-width: 75%;
|
||||
max-width: 90%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-content .sbm-button
|
||||
.sbm-panel-data .sbm-content .sbm-button
|
||||
{
|
||||
min-width: auto;
|
||||
margin-left: 4px;
|
||||
@@ -89,41 +125,281 @@
|
||||
font-size: .67rem;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header .sbm-results-paging .sbm-action
|
||||
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action
|
||||
{
|
||||
margin: 2px 1px 0 1px;
|
||||
background-color: #b0b0b0;
|
||||
box-shadow: 0 0 0 1px #40404080 inset;
|
||||
}
|
||||
|
||||
.sbm-panel-filter .sbm-header .sbm-results-paging .sbm-action:hover
|
||||
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action:hover
|
||||
{
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
|
||||
/* Panel header - Burger */
|
||||
|
||||
ul.nav.sbm-burger
|
||||
{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger .dropdown
|
||||
{
|
||||
margin: 2px 0 2px 0;
|
||||
padding: 2px 2px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger .dropdown:hover
|
||||
{
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger.navbar-light .dropdown:hover
|
||||
{
|
||||
background-color: #f8f8f8;
|
||||
border-color: #606060;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger.navbar-dark .dropdown:hover
|
||||
{
|
||||
border-color: #c0c0c0;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger .sbm-ellipsis-dot
|
||||
{
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
margin: 0 1px 3px 1px;
|
||||
background-color: #808080;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu
|
||||
{
|
||||
padding: 4px 8px 4px 4px;
|
||||
border-radius: 2px 2px 4px 8px;
|
||||
box-shadow: 0 0 8px 2px #80808080;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item
|
||||
{
|
||||
margin: 2px 4px 2px 0;
|
||||
padding: 2px 4px 2px 30px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-refresh
|
||||
{
|
||||
background-image: url('../img/action/refresh24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-info
|
||||
{
|
||||
background-image: url('../img/action/info24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-add
|
||||
{
|
||||
background-image: url('../img/action/add24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-edit
|
||||
{
|
||||
background-image: url('../img/action/edit24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-remove
|
||||
{
|
||||
background-image: url('../img/action/delete24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-experience
|
||||
{
|
||||
background-image: url('../img/action/trophy24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-user
|
||||
{
|
||||
background-image: url('../img/action/user24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-users
|
||||
{
|
||||
background-image: url('../img/action/users24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-mail
|
||||
{
|
||||
background-image: url('../img/action/mail24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-location
|
||||
{
|
||||
background-image: url('../img/action/location-24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-image
|
||||
{
|
||||
background-image: url('../img/action/image-24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-process
|
||||
{
|
||||
background-image: url('../img/action/process24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-upload
|
||||
{
|
||||
background-image: url('../img/action/upload24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-download
|
||||
{
|
||||
background-image: url('../img/action/download24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-network
|
||||
{
|
||||
background-image: url('../img/action/network-24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-close
|
||||
{
|
||||
background-image: url('../img/action/prev24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-itemlock
|
||||
{
|
||||
background-image: url('../img/action/lock24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item.sbm-unlock
|
||||
{
|
||||
background-image: url('../img/action/unlock24.png');
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item:hover
|
||||
{
|
||||
background-color: #f8f8f8;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item .sbm-label
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0 0 0 4px;
|
||||
}
|
||||
|
||||
ul.nav.sbm-burger ul.sbm-dropdown-menu li.sbm-action.sbm-dropdown-item:hover .sbm-label
|
||||
{
|
||||
background-color: #f8f8f8;
|
||||
box-shadow: 0 0 2px 1px #80808080;
|
||||
}
|
||||
|
||||
/* Data Items panel */
|
||||
|
||||
.sbm-panel-results
|
||||
{
|
||||
}
|
||||
|
||||
@media (min-width: 576px)
|
||||
{
|
||||
.sbm-panel-results
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Messages */
|
||||
|
||||
.sbm-panel-results .sbm-panel-messages .sbm-message
|
||||
.sbm-panel-messages
|
||||
{
|
||||
margin-top: 8px;
|
||||
padding-left: 24px;
|
||||
margin: 8px 16px;
|
||||
padding: 2px 12px 2px 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sbm-panel-messages .sbm-message
|
||||
{
|
||||
margin: 4px 0;
|
||||
padding-left: 24px;
|
||||
background-position: left top;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.sbm-panel-results .sbm-panel-messages .sbm-message.sbm-error
|
||||
.sbm-panel-messages .sbm-message.sbm-error
|
||||
{
|
||||
color: #e3120b;
|
||||
background-image: url("../img/icon/error-18.png");
|
||||
}
|
||||
|
||||
/* Item List table */
|
||||
|
||||
.sbm-panel-item-table
|
||||
{
|
||||
width: 100%;
|
||||
min-height: 240px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sbm-layout-flow .sbm-panel-item-table
|
||||
{
|
||||
}
|
||||
|
||||
.sbm-layout-flex .sbm-panel-item-table.sbm-flex
|
||||
{
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
table.sbm-item-list
|
||||
{
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
table.sbm-item-list thead tr
|
||||
{
|
||||
}
|
||||
|
||||
table.sbm-item-list thead th
|
||||
{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 4px 2px 2px 2px;
|
||||
z-index: 1;
|
||||
background-color: #f8f8f8;
|
||||
border-bottom: 1px solid #d0d0d0;
|
||||
}
|
||||
|
||||
table.sbm-item-list tbody th
|
||||
{
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
table.sbm-item-list tbody tr:hover
|
||||
{
|
||||
background-color: lightyellow;
|
||||
}
|
||||
|
||||
table.sbm-item-list tbody tr.sbm-sel
|
||||
{
|
||||
background-color: palegreen;
|
||||
}
|
||||
|
||||
table.sbm-item-list tbody td
|
||||
{
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
/* Item */
|
||||
|
||||
.sbm-panel-item-template
|
||||
@@ -189,13 +465,6 @@
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
@media (min-width: 576px)
|
||||
{
|
||||
.sbm-panel-filter
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Item statuses */
|
||||
|
||||
.sbm-status-awa
|
||||
@@ -203,7 +472,7 @@
|
||||
color: darkorange;
|
||||
}
|
||||
|
||||
.sbm-status-atv
|
||||
.sbm-status-atv, .sbm-status-cur
|
||||
{
|
||||
color: green;
|
||||
}
|
||||
|
||||
@@ -178,15 +178,17 @@
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.sbm-form .sbm-input:read-only, .sbm-form .sbm-textarea:read-only
|
||||
.sbm-form .sbm-input:read-only, .sbm-form .sbm-textarea:read-only, .sbm-form .sbm-select:disabled
|
||||
{
|
||||
background-color: #f8f8f8;
|
||||
color: #404040;
|
||||
opacity: 1;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.sbm-form .sbm-form-control.sbm-error .sbm-input, .sbm-form .sbm-form-control.sbm-error .sbm-textarea, .sbm-form .sbm-form-control.sbm-error .sbm-select
|
||||
{
|
||||
color: #DC143C;
|
||||
border-color: #DC143C;
|
||||
color: #606060; /*#DC143C;*/
|
||||
border-color: #606060; /*#DC143C;*/
|
||||
}
|
||||
|
||||
/* Control messages */
|
||||
@@ -203,6 +205,7 @@
|
||||
|
||||
.sbm-form .sbm-form-control.sbm-error .sbm-message
|
||||
{
|
||||
min-height: 18px;
|
||||
display: block;
|
||||
color: #e3120b;
|
||||
background-image: url("../img/icon/error-18.png");
|
||||
|
||||
@@ -28,7 +28,7 @@ html
|
||||
{
|
||||
html
|
||||
{
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,38 @@ body
|
||||
font-family: Arial, Verdana, Helvetica, Lucida, sans-serif;
|
||||
}
|
||||
|
||||
body > .container
|
||||
@media screen and (max-height: 399px)
|
||||
{
|
||||
#sbm-page-body
|
||||
{
|
||||
min-height: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-height: 400px)
|
||||
{
|
||||
html
|
||||
{
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
body.sbm-layout-flex
|
||||
{
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
body.sbm-layout-flex #sbm-page-body
|
||||
{
|
||||
flex: 1;
|
||||
min-height:0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
|
||||
body > .container, header > .container, footer > .container
|
||||
{
|
||||
padding: 0 0.5%;
|
||||
}
|
||||
@@ -66,32 +97,6 @@ body > .container
|
||||
}
|
||||
}
|
||||
|
||||
/* Sticky footer styles */
|
||||
|
||||
html
|
||||
{
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
/* Margin bottom by footer height */
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.footer
|
||||
{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 0 2%;
|
||||
white-space: nowrap;
|
||||
/* Set the fixed height of the footer here */
|
||||
height: 60px;
|
||||
line-height: 60px; /* Vertically center the text there */
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
#sbm-page-header
|
||||
@@ -126,8 +131,20 @@ button.accept-policy
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/* Information */
|
||||
|
||||
.sbm-para
|
||||
{
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
#sbm-page-footer
|
||||
{
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#sbm-page-footer, #sbm-page-footer div
|
||||
{
|
||||
font-size: .8rem;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Item Selection stylesheet.
|
||||
*/
|
||||
|
||||
/* Panels */
|
||||
|
||||
#dlgSelectItem .SelectedItemName
|
||||
{
|
||||
min-height: 1.5rem;
|
||||
padding: 2px 4px;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #b0b0b0;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#dlgSelectItem .ItemFilter .sbm-label
|
||||
{
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#dlgSelectItem .sbm-button
|
||||
{
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#dlgSelectItem .sbm-selectItem-items
|
||||
{
|
||||
margin-bottom: 8px;
|
||||
padding: 2px 0;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #b0b0b0;
|
||||
border-top-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#dlgSelectItem.sbm-form button.sbm-button
|
||||
{
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#dlgSelectItem .sbm-panel-item.Item
|
||||
{
|
||||
margin: 2px 4px;
|
||||
padding: 2px 4px;
|
||||
background-color: #fff;
|
||||
border: 2px solid #d8d8ff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#dlgSelectItem .sbm-panel-item.Item.sel
|
||||
{
|
||||
background-color: #ececff;
|
||||
border-color: #8a8aff;
|
||||
}
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,206 @@
|
||||
|
||||
/*
|
||||
* SBM - Portal - Assets - Asset Category.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ac = sbm.AssetCat = { data: {}, ajax: {} };
|
||||
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.refreshResults = function (delay)
|
||||
{
|
||||
if (!ac.awaitingRefreshResponse)
|
||||
{
|
||||
$('.sbm-burger', $pnl.header).invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
ac.ajax.assetCategories = ac.ajax.assetCategories || { url: sbm.url.base + 'Assets/AssetCategory/Ajax/GetAssetCategories', formId: $frm.filter.prop('id'), callbackFn: ac.handleAssetCategories };
|
||||
sbm.doAjaxRequest(ac.ajax.assetCategories, delay || 50);
|
||||
ac.awaitingRefreshResponse = true;
|
||||
}
|
||||
ac.handleAssetCategories = function (response)
|
||||
{
|
||||
//sbm.debug('handleAssetCategories', response);
|
||||
delete ac.awaitingRefreshResponse;
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
$pnl.msgs.hide().empty();
|
||||
sbm.refreshPaging(response, '#frmAssetCategoryFilter', ac.refreshResults);
|
||||
if (!response.success) return;
|
||||
|
||||
// Reference data - Statuses.
|
||||
if (response.statuses) sbm.data.statuses = response.statuses;
|
||||
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
|
||||
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
|
||||
|
||||
// Menu.
|
||||
var $bgr = $('.sbm-burger', $pnl.header).invisible();
|
||||
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.assetCategories || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
|
||||
}
|
||||
ac.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$pnl.msgs.hide().empty();
|
||||
$item.prop('id', ac.getItemId(item));
|
||||
$('.AssetCategoryType', $item).text(item.typeDesc);
|
||||
$('.AssetCategoryCode', $item).text(item.code);
|
||||
$('.AssetCategoryDescription', $item).text(item.descBrief);
|
||||
$('.AssetCategoryStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
let fnUpd = function () { ac.updateItem($item, item) };
|
||||
var $bgr = $('.sbm-burger', $item).invisible();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.AssetCategoryCode', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
ac.getItemId = function (item)
|
||||
{
|
||||
return 'Itm_' + (item || {}).id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.AssetCategoryFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemRowTemplate = function ()
|
||||
{
|
||||
return $('table tr.sbm-row-item.AssetCategory', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.AssetCategory li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getFilterMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getItemMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.createItem = function ()
|
||||
{
|
||||
ac.clearItem();
|
||||
sbm.populateSelectCodeDesc('#cbAssetCategoryStatus', sbm.data.statusesCreate);
|
||||
$('#cbAssetCategoryStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
|
||||
ac.openAssetCategoryDlg();
|
||||
}
|
||||
ac.openAssetCategoryDlg = function ()
|
||||
{
|
||||
sbm.openDialog($dlg.item, 600, 600);
|
||||
}
|
||||
ac.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.item;
|
||||
$('.AssetCategoryExists,.AssetCategoryId,input[type="text"],textarea,select', frm).val('');
|
||||
sbm.populateSelectCodeDesc('#cbAssetCategoryStatus', sbm.data.statuses);
|
||||
$('.AssetCategoryType,.AssetCategoryStatus', frm).prop('disabled', false);
|
||||
sbm.clearControlErrors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.updateItem = function ($item, item)
|
||||
{
|
||||
ac.clearItem();
|
||||
$('.AssetCategoryId', $frm.itemId).val(item.id);
|
||||
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Assets/AssetCategory/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
|
||||
}
|
||||
ac.onUpdateItem = function (response)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', response);
|
||||
let frm = $frm.item;
|
||||
ac.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.assetCategory;
|
||||
$('.AssetCategoryExists', frm).val(1);
|
||||
$('.AssetCategoryId', frm).val(item.id);
|
||||
$('.AssetCategoryType', frm).val(item.typeCode).prop('disabled', true);
|
||||
$('.AssetCategoryCode', frm).val(item.code);
|
||||
$('.AssetCategoryDescription', frm).val(item.descBrief);
|
||||
$('.AssetCategoryNotes', frm).val(item.notes);
|
||||
$('.AssetCategoryStatus', frm).val(item.statusCode).prop('disabled', true);
|
||||
sbm.clearControlErrors();
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
|
||||
ac.openAssetCategoryDlg();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.storeItem = function ()
|
||||
{
|
||||
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Assets/AssetCategory/Ajax/StoreItem', formId: 'frmAssetCategory', callbackFn: ac.onStoreItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
|
||||
}
|
||||
ac.onStoreItem = function (response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
|
||||
var item = response.assetCategory;
|
||||
var $item = $('#' + ac.getItemId(item));
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = ac.getItemRowTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
}
|
||||
ac.populateItem($item, item);
|
||||
// Force repopulation of sprts.
|
||||
delete ac.data.assetCategories;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.AssetCategories');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmAssetCategoryFilter');
|
||||
$('.FilterSearch', $frm.filter).on('input', function () { ac.refreshResults(250); });
|
||||
|
||||
$frm.itemId = $('#frmAssetCategoryId');
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgAssetCategory').dialog(opt);
|
||||
$frm.item = $('#frmAssetCategory');
|
||||
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
setTimeout(ac.refreshResults, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,230 @@
|
||||
|
||||
/*
|
||||
* SBM - Portal - Assets - Asset.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ac = sbm.AssetCat = { data: {}, ajax: {} };
|
||||
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.refreshResults = function (delay)
|
||||
{
|
||||
if (!ac.awaitingRefreshResponse)
|
||||
{
|
||||
$('.sbm-burger', $pnl.header).invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
ac.ajax.assets = ac.ajax.assets || { url: sbm.url.base + 'Assets/Asset/Ajax/GetAssets', formId: $frm.filter.prop('id'), callbackFn: ac.handleAssets };
|
||||
sbm.doAjaxRequest(ac.ajax.assets, delay || 50);
|
||||
ac.awaitingRefreshResponse = true;
|
||||
}
|
||||
ac.handleAssets = function (response)
|
||||
{
|
||||
sbm.debug('handleAssets', response);
|
||||
delete ac.awaitingRefreshResponse;
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
$pnl.msgs.hide().empty();
|
||||
sbm.refreshPaging(response, '#frmAssetFilter', ac.refreshResults);
|
||||
if (!response.success) return;
|
||||
|
||||
// Reference data - Statuses.
|
||||
if (response.statuses) sbm.data.statuses = response.statuses;
|
||||
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
|
||||
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
|
||||
|
||||
// Menu.
|
||||
var $bgr = $('.sbm-burger', $pnl.header).invisible();
|
||||
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.assets || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
|
||||
}
|
||||
ac.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$pnl.msgs.hide().empty();
|
||||
$item.prop('id', ac.getItemId(item));
|
||||
$('.AssetCategory', $item).text(item.categoryDesc);
|
||||
$('.AssetSerial', $item).text(item.serialNumber);
|
||||
$('.AssetDescription', $item).text(item.descBrief);
|
||||
$('.AssetStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
let fnUpd = function () { ac.updateItem($item, item) };
|
||||
var $bgr = $('.sbm-burger', $item).invisible();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.AssetSerial', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
ac.getItemId = function (item)
|
||||
{
|
||||
return 'Itm_' + (item || {}).id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.AssetFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemRowTemplate = function ()
|
||||
{
|
||||
return $('table tr.sbm-row-item.Asset', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.Asset li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getFilterMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getItemMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.createItem = function ()
|
||||
{
|
||||
ac.clearItem();
|
||||
sbm.populateSelectCodeDesc('#cbAssetStatus', sbm.data.statusesCreate);
|
||||
$('#cbAssetStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
|
||||
ac.openAssetDlg();
|
||||
}
|
||||
ac.openAssetDlg = function ()
|
||||
{
|
||||
sbm.openDialog($dlg.item, 600, 600);
|
||||
}
|
||||
ac.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.item;
|
||||
$('.AssetExists,.AssetId,input[type="text"],textarea,select', frm).val('');
|
||||
sbm.populateSelectCodeDesc('#cbAssetStatus', sbm.data.statuses);
|
||||
$('.AssetStatus', frm).prop('disabled', false);
|
||||
sbm.clearControlErrors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.updateItem = function ($item, item)
|
||||
{
|
||||
ac.clearItem();
|
||||
$('.AssetId', $frm.itemId).val(item.id);
|
||||
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Assets/Asset/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
|
||||
}
|
||||
ac.onUpdateItem = function (response)
|
||||
{
|
||||
sbm.debug('onUpdateItem', response);
|
||||
let frm = $frm.item;
|
||||
ac.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.asset;
|
||||
$('.AssetExists', frm).val(1);
|
||||
$('.AssetId', frm).val(item.id);
|
||||
$('.AssetCategoryId', frm).val(item.categoryId);
|
||||
$('.AssetCategory', frm).val(item.categoryDesc);
|
||||
$('.AssetSerialNumber', frm).val(item.serialNumber);
|
||||
$('.AssetDescription', frm).val(item.descBrief);
|
||||
$('.AssetNotes', frm).val(item.notes);
|
||||
$('.AssetStatus', frm).val(item.statusCode).prop('disabled', true);
|
||||
sbm.clearControlErrors();
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
|
||||
ac.openAssetDlg();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.selectCategory = function ()
|
||||
{
|
||||
let fnHandleCategories = function (response)
|
||||
{
|
||||
//sbm.debug('fnHandleCategories', response)
|
||||
if (!response.success) return;
|
||||
let cfg = { caption: sbm.lbl.selectCategory, items: [], itemId: $('.AssetCategoryId', $frm.item).val(), fnCallback: fnItemSelected };
|
||||
(response.assetCategories || []).forEach((ac, i) => { cfg.items.push({ id: ac.id, name: ac.descBrief }) });
|
||||
sbm.fn.selectItem(cfg);
|
||||
}
|
||||
let fnItemSelected = function (item)
|
||||
{
|
||||
//sbm.debug('fnCallback', item);
|
||||
$('.AssetCategoryId', $frm.item).val(item.id);
|
||||
$('.AssetCategory', $frm.item).val(item.name);
|
||||
}
|
||||
ac.ajax.categories = ac.ajax.categories || { url: sbm.url.base + 'Assets/AssetCategory/Ajax/GetAssetCategories', formId: $frm.categories.prop('id'), callbackFn: fnHandleCategories };
|
||||
sbm.doAjaxRequest(ac.ajax.categories, 50);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.storeItem = function ()
|
||||
{
|
||||
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Assets/Asset/Ajax/StoreItem', formId: 'frmAsset', callbackFn: ac.onStoreItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
|
||||
}
|
||||
ac.onStoreItem = function (response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
|
||||
var item = response.asset;
|
||||
var $item = $('#' + ac.getItemId(item));
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = ac.getItemRowTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
}
|
||||
ac.populateItem($item, item);
|
||||
// Force repopulation of sprts.
|
||||
delete ac.data.assets;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.Assets');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmAssetFilter');
|
||||
$('.FilterSearch', $frm.filter).on('input', function () { ac.refreshResults(250); });
|
||||
|
||||
$frm.itemId = $('#frmAssetId');
|
||||
$frm.categories = $('#frmCategories');
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgAsset').dialog(opt);
|
||||
$frm.item = $('#frmAsset');
|
||||
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
$($frm.item).on('dblclick', '.sbm-input.AssetCategory', ac.selectCategory).on('click', '.sbm-action.AssetCategorySearch', ac.selectCategory);
|
||||
|
||||
setTimeout(ac.refreshResults, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -177,8 +177,8 @@
|
||||
$frm.association = $('#frmAssociation');
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.dlg.btn.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
sbm.$dlg.association = $('#dlgAssociation').dialog(opt);
|
||||
|
||||
setTimeout(sbm.refreshResults, 250);
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
|
||||
/*
|
||||
* SBM - Portal - Codes - Code Type.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ac = sbm.CodeCat = { data: {}, ajax: {} };
|
||||
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.refreshResults = function (delay)
|
||||
{
|
||||
if (!ac.awaitingRefreshResponse)
|
||||
{
|
||||
$('.sbm-burger', $pnl.header).invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
ac.ajax.codeTypes = ac.ajax.codeTypes || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetCodeTypes', formId: $frm.filter.prop('id'), callbackFn: ac.handleCodeTypes };
|
||||
sbm.doAjaxRequest(ac.ajax.codeTypes, delay || 50);
|
||||
ac.awaitingRefreshResponse = true;
|
||||
}
|
||||
ac.handleCodeTypes = function (response)
|
||||
{
|
||||
//sbm.debug('handleCodeTypes', response);
|
||||
delete ac.awaitingRefreshResponse;
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
$pnl.msgs.hide().empty();
|
||||
sbm.refreshPaging(response, '#frmCodeTypeFilter', ac.refreshResults);
|
||||
if (!response.success) return;
|
||||
|
||||
// Reference data - Statuses.
|
||||
if (response.statuses) sbm.data.statuses = response.statuses;
|
||||
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
|
||||
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
|
||||
|
||||
// Menu.
|
||||
var $bgr = $('.sbm-burger', $pnl.header).invisible();
|
||||
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.codeTypes || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
|
||||
}
|
||||
ac.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$pnl.msgs.hide().empty();
|
||||
$item.prop('id', ac.getItemId(item));
|
||||
$('.CodeTypeCode', $item).text(item.code);
|
||||
$('.CodeTypeName', $item).text(item.name);
|
||||
$('.CodeTypeCodes', $item).text(item.codeCount);
|
||||
$('.CodeTypeStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
let fnUpd = function () { ac.updateItem($item, item) };
|
||||
var $bgr = $('.sbm-burger', $item).invisible();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.CodeTypeName', $item).on('click', fnUpd).addClass('sbm-action-text');
|
||||
$('.CodeTypeCodes', $item).on('click', function () { sbm.navigateTo('Codes/Code?Filter.CodeTypeCode='+item.code);return false; }).on('dblclick', function () { return false; }).addClass('sbm-action-text');
|
||||
$item.on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
ac.getItemId = function (item)
|
||||
{
|
||||
return 'Itm_' + (item || {}).id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.CodeTypeFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemRowTemplate = function ()
|
||||
{
|
||||
return $('table tr.sbm-row-item.CodeType', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.CodeType li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getFilterMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getItemMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.createItem = function ()
|
||||
{
|
||||
ac.clearItem();
|
||||
sbm.populateSelectCodeDesc('#cbCodeTypeStatus', sbm.data.statusesCreate);
|
||||
$('#cbCodeTypeStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
|
||||
ac.openCodeTypeDlg();
|
||||
}
|
||||
ac.openCodeTypeDlg = function ()
|
||||
{
|
||||
sbm.openDialog($dlg.item, 600, 600);
|
||||
}
|
||||
ac.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.item;
|
||||
$('.CodeTypeExists,.CodeTypeId,input[type="text"],textarea,select', frm).val('');
|
||||
sbm.populateSelectCodeDesc('#cbCodeTypeStatus', sbm.data.statuses);
|
||||
$('.CodeTypeCode', frm).prop('readonly', false);
|
||||
sbm.clearControlErrors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.updateItem = function ($item, item)
|
||||
{
|
||||
ac.clearItem();
|
||||
$('.CodeTypeId', $frm.itemId).val(item.id);
|
||||
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
|
||||
}
|
||||
ac.onUpdateItem = function (response)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', response);
|
||||
let frm = $frm.item;
|
||||
ac.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.codeType;
|
||||
$('.CodeTypeExists', frm).val(1);
|
||||
$('.CodeTypeId', frm).val(item.id);
|
||||
$('.CodeTypeCode', frm).val(item.code).prop('readonly', true);
|
||||
$('.CodeTypeName', frm).val(item.name);
|
||||
$('.CodeTypeNotes', frm).val(item.notes);
|
||||
$('.CodeTypeStatus', frm).val(item.statusCode);
|
||||
sbm.clearControlErrors();
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
|
||||
ac.openCodeTypeDlg();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.storeItem = function ()
|
||||
{
|
||||
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Codes/CodeType/Ajax/StoreItem', formId: 'frmCodeType', callbackFn: ac.onStoreItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
|
||||
}
|
||||
ac.onStoreItem = function (response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
|
||||
var item = response.codeType;
|
||||
var $item = $('#' + ac.getItemId(item));
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = ac.getItemRowTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
}
|
||||
ac.populateItem($item, item);
|
||||
// Force repopulation of sprts.
|
||||
delete ac.data.codeTypes;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.CodeTypes');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmCodeTypeFilter');
|
||||
$('.FilterSearch', $frm.filter).on('input', function () { ac.refreshResults(250); });
|
||||
|
||||
$frm.itemId = $('#frmCodeTypeId');
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgCodeType').dialog(opt);
|
||||
$frm.item = $('#frmCodeType');
|
||||
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
setTimeout(ac.refreshResults, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,231 @@
|
||||
|
||||
/*
|
||||
* SBM - Portal - Codes - Code.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ac = sbm.CodeCat = { data: {}, ajax: {} };
|
||||
let $pnl = ac.$pnl = {}, $frm = ac.$frm = {}, $dlg = ac.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.refreshResults = function (delay)
|
||||
{
|
||||
if (!ac.awaitingRefreshResponse)
|
||||
{
|
||||
$('.sbm-burger', $pnl.header).invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
ac.ajax.codes = ac.ajax.codes || { url: sbm.url.base + 'Codes/Code/Ajax/GetCodes', formId: $frm.filter.prop('id'), callbackFn: ac.handleCodes };
|
||||
sbm.doAjaxRequest(ac.ajax.codes, delay || 50);
|
||||
ac.awaitingRefreshResponse = true;
|
||||
}
|
||||
ac.handleCodes = function (response)
|
||||
{
|
||||
sbm.debug('handleCodes', response);
|
||||
delete ac.awaitingRefreshResponse;
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
$pnl.msgs.hide().empty();
|
||||
sbm.refreshPaging(response, '#frmCodeFilter', ac.refreshResults);
|
||||
if (!response.success) return;
|
||||
|
||||
// Reference data - Statuses.
|
||||
if (response.statuses) sbm.data.statuses = response.statuses;
|
||||
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
|
||||
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
|
||||
|
||||
// Menu.
|
||||
var $bgr = $('.sbm-burger', $pnl.header).invisible();
|
||||
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.refresh, function () { ac.refreshResults(); }, 'sbm-refresh'));
|
||||
$mnu.append(ac.getFilterMenuOption(sbm.lbl.create, function () { ac.createItem(); }, 'sbm-add'));
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.codes || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(ac.populateItem(ac.getItemRowTemplate(), items[itemIdx]));
|
||||
//for (let i = 1; i < 101; i++) $table.append($('<tr><td>'+i+'</td></tr>'));
|
||||
}
|
||||
ac.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$pnl.msgs.hide().empty();
|
||||
$item.prop('id', ac.getItemId(item));
|
||||
$('.CodeType', $item).text(item.typeName);
|
||||
$('.CodeCode', $item).text(item.code);
|
||||
$('.CodeDesc', $item).text(item.description);
|
||||
$('.CodeStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
let fnUpd = function () { ac.updateItem($item, item) };
|
||||
var $bgr = $('.sbm-burger', $item).invisible();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
$mnu.append(ac.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.CodeDesc', $item).on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
ac.getItemId = function (item)
|
||||
{
|
||||
return 'Itm_' + (item || {}).id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.CodeFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemRowTemplate = function ()
|
||||
{
|
||||
return $('table tr.sbm-row-item.Code', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getItemDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.Code li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
ac.getFilterMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getItemMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return ac.getMenuOption(ac.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
ac.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.createItem = function ()
|
||||
{
|
||||
ac.clearItem();
|
||||
sbm.populateSelectCodeDesc('#cbCodeStatus', sbm.data.statusesCreate);
|
||||
$('#cbCodeStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
|
||||
ac.openCodeDlg();
|
||||
}
|
||||
ac.openCodeDlg = function ()
|
||||
{
|
||||
sbm.openDialog($dlg.item, 600, 600);
|
||||
}
|
||||
ac.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.item;
|
||||
$('.CodeExists,.CodeId,input[type="text"],textarea,select', frm).val('');
|
||||
sbm.populateSelectCodeDesc('#cbCodeStatus', sbm.data.statuses);
|
||||
$('.CodeStatus', frm).prop('disabled', false);
|
||||
sbm.clearControlErrors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.updateItem = function ($item, item)
|
||||
{
|
||||
ac.clearItem();
|
||||
$('.CodeId', $frm.itemId).val(item.id);
|
||||
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Codes/Code/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: ac.onUpdateItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
|
||||
}
|
||||
ac.onUpdateItem = function (response)
|
||||
{
|
||||
sbm.debug('onUpdateItem', response);
|
||||
let frm = $frm.item;
|
||||
ac.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.code;
|
||||
$('.CodeExists', frm).val(1);
|
||||
$('.CodeId', frm).val(item.id);
|
||||
$('.CodeCategoryId', frm).val(item.categoryId);
|
||||
$('.CodeCategory', frm).val(item.categoryDesc);
|
||||
$('.CodeSerialNumber', frm).val(item.serialNumber);
|
||||
$('.CodeDescription', frm).val(item.descBrief);
|
||||
$('.CodeNotes', frm).val(item.notes);
|
||||
$('.CodeStatus', frm).val(item.statusCode).prop('disabled', true);
|
||||
sbm.clearControlErrors();
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
|
||||
ac.openCodeDlg();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.selectCategory = function ()
|
||||
{
|
||||
let fnHandleCategories = function (response)
|
||||
{
|
||||
//sbm.debug('fnHandleCategories', response)
|
||||
if (!response.success) return;
|
||||
let cfg = { caption: sbm.lbl.selectCategory, items: [], itemId: $('.CodeCategoryId', $frm.item).val(), fnCallback: fnItemSelected };
|
||||
(response.codeCategories || []).forEach((ac, i) => { cfg.items.push({ id: ac.id, name: ac.descBrief }) });
|
||||
sbm.fn.selectItem(cfg);
|
||||
}
|
||||
let fnItemSelected = function (item)
|
||||
{
|
||||
//sbm.debug('fnCallback', item);
|
||||
$('.CodeCategoryId', $frm.item).val(item.id);
|
||||
$('.CodeCategory', $frm.item).val(item.name);
|
||||
}
|
||||
ac.ajax.categories = ac.ajax.categories || { url: sbm.url.base + 'Codes/CodeCategory/Ajax/GetCodeCategories', formId: $frm.categories.prop('id'), callbackFn: fnHandleCategories };
|
||||
sbm.doAjaxRequest(ac.ajax.categories, 50);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ac.storeItem = function ()
|
||||
{
|
||||
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Codes/Code/Ajax/StoreItem', formId: 'frmCode', callbackFn: ac.onStoreItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
|
||||
}
|
||||
ac.onStoreItem = function (response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
|
||||
var item = response.code;
|
||||
var $item = $('#' + ac.getItemId(item));
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = ac.getItemRowTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
}
|
||||
ac.populateItem($item, item);
|
||||
// Force repopulation of sprts.
|
||||
delete ac.data.codes;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.Codes');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmCodeFilter');
|
||||
$frm.filter.on('input', '.FilterSearch', function () { ac.refreshResults(250); }).on('change', '.FilterCodeTypeCode', function () { ac.refreshResults(250); });
|
||||
|
||||
$frm.itemId = $('#frmCodeId');
|
||||
$frm.categories = $('#frmCategories');
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.save] = function () { ac.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgCode').dialog(opt);
|
||||
$frm.item = $('#frmCode');
|
||||
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
$($frm.item).on('dblclick', '.sbm-input.CodeCategory', ac.selectCategory).on('click', '.sbm-action.CodeCategorySearch', ac.selectCategory);
|
||||
|
||||
setTimeout(ac.refreshResults, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -177,8 +177,8 @@
|
||||
$frm.commodity = $('#frmCommodity');
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.dlg.btn.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
sbm.$dlg.commodity = $('#dlgCommodity').dialog(opt);
|
||||
|
||||
setTimeout(sbm.refreshResults, 250);
|
||||
|
||||
@@ -198,8 +198,8 @@
|
||||
$frm.contact = $('#frmContact');
|
||||
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.dlg.btn.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
opt.buttons[sbm.lbl.ok] = function () { sbm.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.contact = $('#dlgContact').dialog(opt);
|
||||
|
||||
setTimeout(sbm.refreshResults, 250);
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
{
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
sbm.getTime = function ()
|
||||
{
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
sbm.zeroPad = function (num, count)
|
||||
{
|
||||
var val = num + '';
|
||||
@@ -52,12 +56,12 @@
|
||||
if (file.filename) return filename.split('.').pop();
|
||||
return "";
|
||||
}
|
||||
sbm.formatFileSize = function (size)
|
||||
sbm.formatFileSize = function (size, decimals = 0)
|
||||
{
|
||||
if (size / 10 ** 9 > 1) return Math.floor(size / 10 ** 9) + 'Gb';
|
||||
if (size / 10 ** 6 > 1) return Math.floor(size / 10 ** 6) + 'Mb';
|
||||
if (size / 10 ** 3 > 1) return Math.floor(size / 10 ** 3) + 'Kb';
|
||||
return size + 'bytes';
|
||||
if (size / 10 ** 9 > 1) return (size / 10.0 ** 9).toFixed(decimals) + ' Gb';
|
||||
if (size / 10 ** 6 > 1) return (size / 10.0 ** 6).toFixed(decimals) + ' Mb';
|
||||
if (size / 10 ** 3 > 1) return (size / 10.0 ** 3).toFixed(decimals) + ' Kb';
|
||||
return size + ' bytes';
|
||||
}
|
||||
sbm.escapeRegExp = function (val)
|
||||
{
|
||||
@@ -70,6 +74,21 @@
|
||||
}
|
||||
sbm.debug = sbm.debugMode ? win.console.log.bind(win.console) : function () { };
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sbm.compareCI = function (a, b)
|
||||
{
|
||||
var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
if (comparison === 0)
|
||||
return a.localeCompare(b);
|
||||
return comparison;
|
||||
}
|
||||
sbm.arraySortCI = function ()
|
||||
{
|
||||
if (!this) return this;
|
||||
this.sort(function (a, b) { return sbm.compareCI(a, b); });
|
||||
return this;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sbm.setOddDataRowClass = function (rowSel, cName)
|
||||
{
|
||||
@@ -78,35 +97,49 @@
|
||||
return index % 2 == 1 ? (cName || "other") : "";
|
||||
});
|
||||
}
|
||||
sbm.populateSelect = function ($sel, values, code, desc)
|
||||
{
|
||||
code = code || 'code';
|
||||
desc = desc || 'desc';
|
||||
$sel = $($sel).empty();
|
||||
for (const value of values || [])
|
||||
$sel.append($('<option>').prop('value', value[code]).text(value[desc]));
|
||||
}
|
||||
sbm.populateSelectCodeDesc = function ($sel, values)
|
||||
{
|
||||
$sel = $($sel).empty();
|
||||
for (const value of values)
|
||||
$sel.append($('<option>').prop('value', value.code).text(value.desc));
|
||||
sbm.populateSelect($sel, values);
|
||||
}
|
||||
sbm.checkTextAreaMaxLength = function (ctrl, len)
|
||||
{
|
||||
if (ctrl == null || ctrl.value == null) return;
|
||||
if (ctrl.value.length > len) ctrl.value = ctrl.value.substring(0, len);
|
||||
}
|
||||
sbm.setAvailableCharsLabel = function ($if, max, $lbl)
|
||||
sbm.setAvailableCharsInfo = function ($if, max, $info)
|
||||
{
|
||||
var avail = Math.max(0, max - $if.val().length);
|
||||
$lbl.text(avail == 1 ? sbm.lbl.availableCharacter : sbm.lbl.availableCharacters.replace(/\{0\}/g, avail));
|
||||
let info = '';
|
||||
if (max > 0)
|
||||
{
|
||||
let avail = Math.max(0, max - $if.val().length);
|
||||
info = (avail == 1 ? sbm.lbl.charAvailable : sbm.lbl.charsAvailable.replace(/\{0\}/g, avail));
|
||||
}
|
||||
($info || $('.sbm-info', $if.closest('.sbm-form-control'))).text(info);
|
||||
}
|
||||
sbm.setCharsAvailableLabel = function ($if, max)
|
||||
{
|
||||
var avail = Math.max(0, max - $if.val().length);
|
||||
$('.sbm-select-chars-available', $if.closest('.sbm-form-control')).text(avail == 1 ? sbm.lbl.availableCharacter : sbm.lbl.availableCharacters.replace(/\{0\}/g, avail));
|
||||
}
|
||||
sbm.setItemsSelectedLabel = function ($sel)
|
||||
sbm.setItemsSelectedInfo = function ($sel, $info)
|
||||
{
|
||||
var sel = $(':selected', $sel).length;
|
||||
$('.sbm-select-items-selected', $sel.closest('.sbm-form-control')).text(sel == 0 ? sbm.lbl.noneSelected : sbm.lbl.numberSelected.replace(/\{0\}/g, sel));
|
||||
($info || $('.sbm-info', $sel.closest('.sbm-form-control'))).text(sel == 0 ? sbm.lbl.noneSelected : sbm.lbl.numberSelected.replace(/\{0\}/g, sel));
|
||||
}
|
||||
sbm.initCalendars = function (sel)
|
||||
sbm.initCalendars = function (sel, opt)
|
||||
{
|
||||
return $(sel).datepicker();
|
||||
return $(sel).datepicker(opt || {});
|
||||
}
|
||||
sbm.allowClearCalendar = function (sel)
|
||||
{
|
||||
$(sel).datepicker().on('keyup', function (e)
|
||||
{
|
||||
if (e.key == 'Backspace' || e.key == 'Delete')
|
||||
$(this).datepicker('setDate', null).datepicker('hide').trigger('change');
|
||||
});
|
||||
}
|
||||
sbm.refreshPaging = function (response, context, refreshFn)
|
||||
{
|
||||
@@ -119,7 +152,7 @@
|
||||
sbm.navigateTo = function (action)
|
||||
{
|
||||
sbm.doPleaseWait();
|
||||
$('#frmNavigate').prop('action', sbm.url.base + action).submit();
|
||||
$('#frmNavigate').prop('action', sbm.url.base + action).trigger('submit');
|
||||
}
|
||||
sbm.goToPage = function (action)
|
||||
{
|
||||
@@ -127,17 +160,6 @@
|
||||
location = sbm.url.base + action;
|
||||
}
|
||||
|
||||
// Account action.
|
||||
sbm.onAccountAction = function (select)
|
||||
{
|
||||
var action = $(select).val();
|
||||
$(select).val("");
|
||||
if (action == "Profile")
|
||||
sbm.navigateTo("Profile");
|
||||
else if (action == "Organisations")
|
||||
sbm.navigateTo("Organisations");
|
||||
}
|
||||
|
||||
// Security.
|
||||
sbm.redirectHome = function ()
|
||||
{
|
||||
@@ -171,12 +193,12 @@
|
||||
}
|
||||
sbm.dlgOpts = function ()
|
||||
{
|
||||
return { autoOpen: false, modal: true, show: 'clip', hide: 'clip', minWidth: 320, maxWidth: 480, width: 'auto', resizable: false, draggable: false, closeOnEscape: false, dialogClass: "dialog-no-close", buttons: {} };
|
||||
return { autoOpen: false, modal: true, show: 'clip', hide: 'clip', minWidth: 320, maxWidth: 480, width: 'auto', resizable: false, draggable: false, closeOnEscape: false, dialogClass: "no-close", buttons: {} };
|
||||
}
|
||||
sbm.dlgOptsClose = function ()
|
||||
{
|
||||
var opts = sbm.dlgOpts();
|
||||
opts.buttons[sbm.dlg.btn.close] = function () { $(this).dialog('close'); };
|
||||
opts.buttons[sbm.lbl.close] = function () { $(this).dialog('close'); };
|
||||
return opts;
|
||||
}
|
||||
sbm.doAlert = function (title, msg, onOk)
|
||||
@@ -189,11 +211,12 @@
|
||||
if (!sbm.isDef(sbm.$dlg.alert))
|
||||
{
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.dlg.btn.ok] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
sbm.$dlg.alert = $('<div id="dlgAlert"><div id="dlgAlertMsg"></div></div>').dialog(opt);
|
||||
}
|
||||
$('#dlgAlertMsg', sbm.$dlg.alert).html(msg);
|
||||
sbm.$dlg.alert.dialog('option', { title: title || sbm.dlg.title.alert });
|
||||
$('#dlgAlertMsg', sbm.$dlg.alert).html(msg.replace(/\\n/g, '<br>'));
|
||||
let btns = [];
|
||||
btns[sbm.lbl.ok] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
sbm.$dlg.alert.dialog('option', { title: title || sbm.dlg.title.alert, buttons: btns });
|
||||
sbm.openDialog(sbm.$dlg.alert);
|
||||
}
|
||||
sbm.doConfirm = function (title, msg, onOk, onCancel)
|
||||
@@ -208,11 +231,11 @@
|
||||
var opt = sbm.dlgOpts();
|
||||
sbm.$dlg.confirm = $('<div id="dlgConfirm"><div class="spacer2"></div><div id="dlgConfirmMsg"></div></div>').dialog(opt);
|
||||
}
|
||||
var buttons = sbm.$dlg.confirm.dialog('option', 'buttons');
|
||||
buttons[sbm.dlg.btn.yes] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
buttons[sbm.dlg.btn.no] = function () { $(this).dialog('close'); if (onCancel) onCancel(); };
|
||||
sbm.$dlg.confirm.dialog('option', { title: title || sbm.dlg.title.confirm, 'buttons': buttons });
|
||||
$('#dlgConfirmMsg').html(msg);
|
||||
var btns = [];
|
||||
btns[sbm.lbl.yes] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
btns[sbm.lbl.no] = function () { $(this).dialog('close'); if (onCancel) onCancel(); };
|
||||
sbm.$dlg.confirm.dialog('option', { title: title || sbm.dlg.title.confirm, buttons: btns });
|
||||
$('#dlgConfirmMsg').html(msg.replace(/\\n/g, '<br>'));
|
||||
sbm.openDialog(sbm.$dlg.confirm);
|
||||
}
|
||||
sbm.confirmItemRemove = function (fn)
|
||||
@@ -234,7 +257,7 @@
|
||||
opt.hide = { effect: 'fade', duration: 200 };
|
||||
sbm.$dlg.progress = $('<div id="dlgProgress"><div id="dlgProgressMsg"></div></div>').dialog(opt);
|
||||
}
|
||||
$('#dlgProgressMsg').html(msg);
|
||||
$('#dlgProgressMsg').html(msg.replace(/\\n/g, '<br>'));
|
||||
sbm.$dlg.progress.dialog('option', { title: title || sbm.dlg.title.progress });
|
||||
if (delay > 0) sbm.toShowProgress = setTimeout(function () { sbm.$dlg.progress.dialog('open'); }, delay);
|
||||
else sbm.$dlg.progress.dialog('open');
|
||||
@@ -479,22 +502,25 @@
|
||||
sbm.onWinResizePage = function () { };
|
||||
sbm.onWinResize = function ()
|
||||
{
|
||||
var winH = $(win).height();
|
||||
var $pageBody = $('#sbm-page-body');
|
||||
var $hdr = $('#sbm-page-header');
|
||||
var $ftr = $('#sbm-page-footer');
|
||||
if (sbm.isAutoHeight())
|
||||
$pageBody.height('auto');
|
||||
else
|
||||
$pageBody.innerHeight(Math.min(1200, winH - $hdr.outerHeight() - $ftr.outerHeight(true)));
|
||||
$ftr.css('visibility', 'visible');
|
||||
$('body').toggleClass('sbm-layout-flex', !sbm.isAutoHeight()).toggleClass('sbm-layout-flow', sbm.isAutoHeight());
|
||||
sbm.onWinResizePage();
|
||||
}
|
||||
setTimeout(sbm.onWinResize, 50);
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$(win).on('resize', function () { sbm.onWinResize(); });
|
||||
|
||||
$('.sbm-button-cta,.sbm-button-action,.sbm-action-link,.sbm-social-icon.sbm-action').prop('tabindex', 0);
|
||||
|
||||
$.fn.visible = function () { return this.css('visibility', 'visible'); };
|
||||
$.fn.invisible = function () { return this.css('visibility', 'hidden'); };
|
||||
$.fn.toggleVisibility = function ()
|
||||
{
|
||||
return this.css('visibility', function (i, visibility) { return (visibility == 'visible') ? 'hidden' : 'visible'; });
|
||||
};
|
||||
|
||||
if (sbm.keepLoggedIn)
|
||||
sbm.configureKeepLoggedIn();
|
||||
else if (!sbm.awaitingLogin)
|
||||
|
||||
@@ -71,12 +71,13 @@
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$(':input:enabled:visible:first').focus();
|
||||
$(':input:enabled:visible:first').trigger('focus');
|
||||
$('#ifEmailAddress,#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm').on('input', function () { sbm.clearControlError(this); });
|
||||
$('#frmChangePassword #ifPassword').on('keyup', sbm.doScorePassword);
|
||||
sbm.$prgPasswordStrength = $('#frmChangePassword #prgPasswordStrength').progressbar({ 'max': 5 });
|
||||
$('#ifEmailAddress,#ifPassword', $('#frmSignIn')).on('keypress', function (e) { if (e.which == 13) sbm.doSignin(); });
|
||||
$('#frmSignIn #pbSignIn').on('click', function () { sbm.doSignin(); });
|
||||
sbm.$frm.signIn = $('#frmSignIn');
|
||||
sbm.$frm.signIn.on('keypress', '#ifEmailAddress,#ifPassword,#chkKeepMeSignedIn', function (e) { if (e.which == 13 && $('#ifEmailAddress', sbm.$frm.signIn).val() && $('#ifPassword', sbm.$frm.signIn).val()) sbm.doSignin(); });
|
||||
sbm.$frm.signIn.on('click', '#pbSignIn', function () { sbm.doSignin(); }).on('keypress', '#pbSignIn', function (e) { if (e.which == 13) sbm.doSignin(); });;
|
||||
$('#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm', $('#frmChangePassword')).on('keypress', function (e) { if (e.which == 13) sbm.doChangePassword(); });
|
||||
$('#frmChangePassword #pbChangePassword').on('click', function () { sbm.doChangePassword(); });
|
||||
$('#ifEmailAddress', $('#frmRequestPassword')).on('keypress', function (e) { if (e.which == 13) sbm.doRequestPassword(); });
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Portal - Item selection.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let si = sbm.data.selectItem = sbm.data.selectItem || { items: {}, fn: {}, $dlg: {}, itemIdPrefix: 'Itm_' };
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/*
|
||||
* Item selection config:
|
||||
* - caption - dialog title.
|
||||
* - items - list of objects: { id, name }
|
||||
* - itemId - currently selected item.
|
||||
* - fnCallback - method to call on completion to store selected item.
|
||||
*/
|
||||
sbm.fn.selectItem = function (cfg)
|
||||
{
|
||||
si.cfg = cfg;
|
||||
si.itemId = cfg.itemId;
|
||||
si.fn.showSelectItem();
|
||||
}
|
||||
si.fn.showSelectItem = function ()
|
||||
{
|
||||
$('.SelectedItemName', si.$dlg).text(si.fn.getItemName(si.itemId));
|
||||
$('#ifItemFilter', si.$dlg).val('');
|
||||
si.fn.displayItems();
|
||||
sbm.openDialog(si.$dlg.dialog('option', { title: si.cfg.caption || 'Select Item' }), 480, 640);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
si.fn.compareItems = function (a, b)
|
||||
{
|
||||
var comparison = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
|
||||
if (comparison === 0)
|
||||
return a.name.localeCompare(b.name);
|
||||
return comparison;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
si.fn.displayItems = function ()
|
||||
{
|
||||
let filter = $('#ifItemFilter', si.$dlg).val();
|
||||
let reFilter = new RegExp(sbm.escapeRegExp((filter || '').trim()), 'i');
|
||||
let $itemsAvail = $('.sbm-selectItem-items.AvailableItems').empty();
|
||||
let $itemTmpl = $('.sbm-panel-item-template .sbm-panel-item.Item');
|
||||
let items = [...si.cfg.items];
|
||||
items.sort(si.fn.compareItems);
|
||||
for (let rgnIdx = 0; rgnIdx < items.length; rgnIdx++)
|
||||
{
|
||||
let item = items[rgnIdx];
|
||||
let id = item.id;
|
||||
if (filter && !item.name.match(reFilter)) continue;
|
||||
let $item = $itemTmpl.clone();
|
||||
$item.prop('id', si.itemIdPrefix + id).on('click', function () { si.fn.onClickItem(id); }).on('dblclick', function () { si.fn.onDblClickItem(id); }).find('.ItemName').text(item.name).end();
|
||||
if (id == si.itemId) $item.addClass('sel');
|
||||
$itemsAvail.append($item);
|
||||
}
|
||||
}
|
||||
si.fn.getItem = function (id)
|
||||
{
|
||||
for (let rgnIdx = 0; rgnIdx < si.cfg.items.length; rgnIdx++)
|
||||
{
|
||||
let item = si.cfg.items[rgnIdx];
|
||||
if (item.id == id) return item;
|
||||
}
|
||||
}
|
||||
si.fn.getItemName = function (id)
|
||||
{
|
||||
let item = si.fn.getItem(id);
|
||||
return item ? item.name : '';
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
si.fn.onClickItem = function (id)
|
||||
{
|
||||
$('.SelectedItemName', si.$dlg).text(si.fn.getItemName(si.itemId = id));
|
||||
$('.sbm-panel-item.Item').removeClass('sel');
|
||||
$('.sbm-panel-item.Item#' + si.itemIdPrefix + id).addClass('sel');
|
||||
}
|
||||
si.fn.onDblClickItem = function (id)
|
||||
{
|
||||
si.itemId = id;
|
||||
si.fn.storeSelectItem();
|
||||
}
|
||||
si.fn.storeSelectItem = function ()
|
||||
{
|
||||
if (!si.itemId) return;
|
||||
let item = si.fn.getItem(si.itemId);
|
||||
if (!item) return;
|
||||
if (si.cfg.fnCallback) si.cfg.fnCallback(item);
|
||||
si.$dlg.dialog('close');
|
||||
si.fn.cleanUp();
|
||||
}
|
||||
si.fn.cleanUp = function ()
|
||||
{
|
||||
delete si.cfg;
|
||||
delete si.itemId;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
si.fn.onDlgSize = function ()
|
||||
{
|
||||
let $pnl = $('.sbm-selectItem-items.AvailableItems');
|
||||
$pnl.outerHeight(Math.floor(si.$dlg.innerHeight() - $pnl.position().top - ($pnl.outerHeight(true) - $pnl.innerHeight())));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.open = function (evt, ui) { si.fn.onDlgSize(); };
|
||||
opt.resize = function (evt, ui) { si.fn.onDlgSize(); };
|
||||
opt.buttons[sbm.lbl.ok] = function () { si.fn.storeSelectItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { si.fn.cleanUp(); $(this).dialog('close'); };
|
||||
si.$dlg = $('#dlgSelectItem').dialog(opt);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,207 @@
|
||||
|
||||
/*
|
||||
* SBM - Portal - Assets - Vehicle Class.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let vc = sbm.VehicleClass = { data: {}, ajax: {} };
|
||||
let $pnl = vc.$pnl = {}, $frm = vc.$frm = {}, $dlg = vc.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
vc.refreshResults = function (delay)
|
||||
{
|
||||
if (!vc.awaitingRefreshResponse)
|
||||
{
|
||||
$('.sbm-burger', $pnl.header).invisible();
|
||||
$pnl.table.find('tbody tr').remove();
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
vc.ajax.vehicleClasses = vc.ajax.vehicleClasses || { url: sbm.url.base + 'Assets/VehicleClass/Ajax/GetVehicleClasses', formId: $frm.filter.prop('id'), callbackFn: vc.handleVehicleClasses };
|
||||
sbm.doAjaxRequest(vc.ajax.vehicleClasses, delay || 50);
|
||||
vc.awaitingRefreshResponse = true;
|
||||
}
|
||||
vc.handleVehicleClasses = function (response)
|
||||
{
|
||||
sbm.debug('handleVehicleClasses', response);
|
||||
delete vc.awaitingRefreshResponse;
|
||||
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
|
||||
$pnl.msgs.hide().empty();
|
||||
sbm.refreshPaging(response, '#frmVehicleClassFilter', vc.refreshResults);
|
||||
if (!response.success) return;
|
||||
|
||||
// Reference data - Statuses.
|
||||
if (response.statuses) sbm.data.statuses = response.statuses;
|
||||
if (response.statusesCreate) sbm.data.statusesCreate = response.statusesCreate;
|
||||
if (response.statusCodeDefault) sbm.data.statusCodeDefault = response.statusCodeDefault;
|
||||
|
||||
// Menu.
|
||||
var $bgr = $('.sbm-burger', $pnl.header).invisible();
|
||||
var $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(vc.getFilterMenuOption(sbm.lbl.refresh, function () { vc.refreshResults(); }, 'sbm-refresh'));
|
||||
$mnu.append(vc.getFilterMenuOption(sbm.lbl.create, function () { vc.createItem(); }, 'sbm-add'));
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.vehicleClasses || [];
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(vc.populateItem(vc.getItemRowTemplate(), items[itemIdx]));
|
||||
}
|
||||
vc.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$pnl.msgs.hide().empty();
|
||||
$item.prop('id', vc.getItemId(item));
|
||||
$('.VehicleClassMake', $item).text(item.makeDesc);
|
||||
$('.VehicleClassModel', $item).text(item.model);
|
||||
$('.VehicleClassDerivative', $item).text(item.derivative);
|
||||
$('.VehicleClassDescription', $item).text(item.descBrief);
|
||||
$('.VehicleClassStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sbm-status-\S+/g) || []).join(' '); }).addClass('sbm-status-' + item.statusCode.toLowerCase());
|
||||
// Actions.
|
||||
let fnUpd = function () { vc.updateItem($item, item) };
|
||||
var $bgr = $('.sbm-burger', $item).invisible();
|
||||
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
|
||||
if (!item.deleted)
|
||||
{
|
||||
$mnu.append(vc.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
|
||||
$('.VehicleClassMake,.VehicleClassModel', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
|
||||
$item.off('dblclick').on('dblclick', fnUpd);
|
||||
}
|
||||
$bgr.toggleVisibility(!!$('.sbm-dropdown-item', $mnu).length);
|
||||
return $item;
|
||||
}
|
||||
vc.getItemId = function (item)
|
||||
{
|
||||
return 'Itm_' + (item || {}).id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
vc.getFilterDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.VehicleClassFilter li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
vc.getItemRowTemplate = function ()
|
||||
{
|
||||
return $('table tr.sbm-row-item.VehicleClass', $pnl.tmpls).clone();
|
||||
}
|
||||
vc.getItemDropdownTemplate = function ()
|
||||
{
|
||||
return $('.sbm-dropdown-menu.VehicleClass li.sbm-dropdown-item', $pnl.tmpls).clone();
|
||||
}
|
||||
vc.getFilterMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return vc.getMenuOption(vc.getFilterDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
vc.getItemMenuOption = function (lbl, fn, cls)
|
||||
{
|
||||
return vc.getMenuOption(vc.getItemDropdownTemplate(), lbl, fn, cls);
|
||||
}
|
||||
vc.getMenuOption = function ($opt, lbl, fn, cls)
|
||||
{
|
||||
return $opt.find('div.sbm-label').text(lbl).end().on('click', fn).addClass(cls);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
vc.createItem = function ()
|
||||
{
|
||||
vc.clearItem();
|
||||
sbm.populateSelectCodeDesc('#cbVehicleClassStatus', sbm.data.statusesCreate);
|
||||
$('#cbVehicleClassStatus').val(sbm.data.statusCodeDefault).prop('readonly', false);
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.createItem);
|
||||
vc.openVehicleClassDlg();
|
||||
}
|
||||
vc.openVehicleClassDlg = function ()
|
||||
{
|
||||
sbm.openDialog($dlg.item, 600, 600);
|
||||
}
|
||||
vc.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.item;
|
||||
$('.VehicleClassExists,.VehicleClassId,input[type="text"],textarea,select', frm).val('');
|
||||
sbm.populateSelectCodeDesc('#cbVehicleClassStatus', sbm.data.statuses);
|
||||
$('.VehicleClassType,.VehicleClassStatus', frm).prop('disabled', false);
|
||||
sbm.clearControlErrors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
vc.updateItem = function ($item, item)
|
||||
{
|
||||
vc.clearItem();
|
||||
$('.VehicleClassId', $frm.itemId).val(item.id);
|
||||
sbm.ajax.updateItem = sbm.ajax.updateItem || { url: sbm.url.base + 'Assets/VehicleClass/Ajax/GetItem', formId: $frm.itemId.prop('id'), callbackFn: vc.onUpdateItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.updateItem, 50);
|
||||
}
|
||||
vc.onUpdateItem = function (response)
|
||||
{
|
||||
//sbm.debug('onUpdateItem', response);
|
||||
let frm = $frm.item;
|
||||
vc.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.vehicleClass;
|
||||
$('.VehicleClassExists', frm).val(1);
|
||||
$('.VehicleClassId', frm).val(item.id);
|
||||
$('.VehicleClassType', frm).val(item.typeCode).prop('disabled', true);
|
||||
$('.VehicleClassCode', frm).val(item.code);
|
||||
$('.VehicleClassDescription', frm).val(item.descBrief);
|
||||
$('.VehicleClassNotes', frm).val(item.notes);
|
||||
$('.VehicleClassStatus', frm).val(item.statusCode).prop('disabled', true);
|
||||
sbm.clearControlErrors();
|
||||
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateItem);
|
||||
vc.openVehicleClassDlg();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
vc.storeItem = function ()
|
||||
{
|
||||
sbm.ajax.storeItem = sbm.ajax.storeItem || { url: sbm.url.base + 'Assets/VehicleClass/Ajax/StoreItem', formId: 'frmVehicleClass', callbackFn: vc.onStoreItem };
|
||||
sbm.doAjaxRequest(sbm.ajax.storeItem, 50);
|
||||
}
|
||||
vc.onStoreItem = function (response)
|
||||
{
|
||||
//sbm.debug('onStoreItem', response);
|
||||
sbm.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.item.dialog('close');
|
||||
|
||||
var item = response.vehicleClass;
|
||||
var $item = $('#' + vc.getItemId(item));
|
||||
if (!$item.length)
|
||||
{
|
||||
$item = vc.getItemRowTemplate();
|
||||
$('table tbody', $pnl.table).prepend($item).show();
|
||||
}
|
||||
vc.populateItem($item, item);
|
||||
// Force repopulation of sprts.
|
||||
delete vc.data.vehicleClasses;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbm-panel.VehicleClasses');
|
||||
$pnl.header = $('.sbm-panel-header', $pnl.items);
|
||||
$pnl.filter = $('.sbm-panel-filter', $pnl.items);
|
||||
$pnl.msgs = $('.sbm-panel-messages', $pnl.items);
|
||||
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
|
||||
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
|
||||
|
||||
$frm.filter = $('#frmVehicleClassFilter');
|
||||
$('.FilterSearch', $frm.filter).on('input', function () { vc.refreshResults(250); });
|
||||
|
||||
$frm.itemId = $('#frmVehicleClassId');
|
||||
var opt = sbm.dlgOpts();
|
||||
opt.buttons[sbm.lbl.save] = function () { vc.storeItem(); };
|
||||
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.item = $('#dlgVehicleClass').dialog(opt);
|
||||
$frm.item = $('#frmVehicleClass');
|
||||
$($frm.item).on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
|
||||
|
||||
setTimeout(vc.refreshResults, 250);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
Reference in New Issue
Block a user