3.0.0.3 Control Repository Schema & Logs.
This commit is contained in:
@@ -15,7 +15,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
//-------------------------------------------------------------------
|
||||
public static class Version
|
||||
{
|
||||
private static String version { get; } = "3.0.0.2";
|
||||
private static String version { get; } = "3.0.0.3";
|
||||
// Retrieve version.
|
||||
public static String GetFullVersion() { return version; }
|
||||
public static String GetAppVersion()
|
||||
@@ -40,6 +40,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
// 3.0.0 Jul-2021 Initial demo test version.
|
||||
// 02-Feb-25 Initial live deployment.
|
||||
// 3.0.0.1 08-Feb-25 Demo repository registration.
|
||||
// 3.0.0.2 08-Feb-25 Production SMTP config.
|
||||
// 3.0.0.3 10-Feb-25 Osie feedback #1. Control Repository Schema, Logs.
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -113,6 +113,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
{
|
||||
WebControl,
|
||||
WebPortal,
|
||||
WebDemo,
|
||||
}
|
||||
public enum InstanceType
|
||||
{
|
||||
@@ -125,6 +126,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
{
|
||||
Unknown,
|
||||
Control,
|
||||
BusMgr,
|
||||
Template,
|
||||
Demo,
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.App
|
||||
// Properties.
|
||||
public Sbm.Application Application { get; private set; }
|
||||
|
||||
public bool IsDemoRepository() { return Application == Sbm.Application.WebDemo; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -112,8 +112,8 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
|
||||
private SbmInternals Internals { get { return mbr.InternalsSupplied; } }
|
||||
public ISbmUserOrganisationContext UserContext { get { return Internals.UserContext; } }
|
||||
public SbmSessionContext SessionContext { get { return Internals.SessionContext; } }
|
||||
public SbmInstanceConfig InstanceConfig { get { if (instanceConfig == null) instanceConfig = SbmGlobals.Application.GetInstanceConfig(SessionContext); return instanceConfig; } }
|
||||
public SbmOrganisationConfig OrganisationConfig { get { if (organisationConfig == null) organisationConfig = SbmGlobals.Application.GetOrganisationConfig(UserContext); return organisationConfig; } }
|
||||
public SbmInstanceConfig InstanceConfig { get { if (instanceConfig == null) { instanceConfig = SbmGlobals.Application.GetInstanceConfig(SessionContext); } return instanceConfig; } }
|
||||
public SbmOrganisationConfig OrganisationConfig { get { if (organisationConfig == null) { organisationConfig = SbmGlobals.Application.GetOrganisationConfig(UserContext); } return organisationConfig; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C r e a t e C o n s o l e
|
||||
@@ -224,6 +224,17 @@ namespace Sarand.BusinessMgr.Net.Standard.Base.Consoles
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Demo Repository restrictions.
|
||||
|
||||
/// <summary>
|
||||
/// Demo application should not display Individual Contacts for User Accounts other than that logged in.
|
||||
/// </summary>
|
||||
public bool HideOtherUserContacts()
|
||||
{
|
||||
return SessionContext.IsDemoRepository();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Application Configuration. - AllowOption.
|
||||
public virtual bool AllowOption(Sbm.ConfigOption option)
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Create Affiliate.
|
||||
// Create Item.
|
||||
public override SbmAffiliate CreateAffiliate(Sbm.AffiliateType affiliateType)
|
||||
{
|
||||
return new SbmAffiliate_Dbas(null, affiliateType, 0);
|
||||
@@ -169,7 +169,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Affiliate.
|
||||
// Get Item.
|
||||
public override SbmAffiliate GetAffiliate(SbmAffiliate.Params prm)
|
||||
{
|
||||
return GetAffiliate(GetAffiliateQueryFilter(prm).Concat(" AND ", "(", ")"));
|
||||
@@ -206,6 +206,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Affiliate properties.
|
||||
public override String GetAffiliateName(SysId affiliateId)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -280,7 +281,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validate item properties.
|
||||
// Validate Item properties.
|
||||
public override bool IsValidAffiliateData(SbmAffiliate.Data data, SbmAffiliate.ErrField errField)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -666,16 +667,27 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
public override List<string> GetAffiliateQueryFilter(SbmAffiliate.Params prm)
|
||||
{
|
||||
List<String> filter = new List<String>();
|
||||
|
||||
// Item Id.
|
||||
String colAffiliate_Id = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Id, aliasAffiliate);
|
||||
String colAffiliate_Type = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Type, aliasAffiliate);
|
||||
String colAffiliate_UserId = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_UserId, aliasAffiliate);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Demo application restrictions - when user logged in.
|
||||
if (SysId.IsValid(UserContext.UserAffiliateId) && SessionConsole.HideOtherUserContacts())
|
||||
{
|
||||
// Exclude Individual contacts with User Id other than the logged in user.
|
||||
// NB Keep logic in line with corresponding Affiliate method (SbmAccountMgr_Dbas.GetAssociationQueryFilter).
|
||||
filter.Add($"{colAffiliate_Id} Not In (Select Id From {SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Affiliate)} Where Id!={UserContext.UserAffiliateId} And Type={(int)Sbm.AffiliateType.Individual} And UserId>0)");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Item Id.
|
||||
if (prm.IdsIncluded.HasValidIds())
|
||||
filter.Add($"{colAffiliate_Id} IN ({prm.IdsIncluded.Concat(",")})");
|
||||
if (prm.IdsExcluded.HasValidIds())
|
||||
filter.Add($"{colAffiliate_Id} NOT IN ({prm.IdsExcluded.Concat(",")})");
|
||||
|
||||
// Type.
|
||||
String colAffiliate_Type = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_Type, aliasAffiliate);
|
||||
// Affiliate type - Individual.
|
||||
if (prm.AffiliateType == Sbm.AffiliateType.AnyOrganisation)
|
||||
filter.Add($"{colAffiliate_Type} Not In ({(int)Sbm.AffiliateType.Individual}, {(int)Sbm.AffiliateType.ContactGroup})");
|
||||
@@ -687,9 +699,11 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
filter.Add($"{colAffiliate_Type}={(int)prm.AffiliateType}");
|
||||
|
||||
// Parent Id.
|
||||
String colAffiliate_AffIdParent = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_AffIdParent, aliasAffiliate);
|
||||
if (SysId.IsValid(prm.AffiliateIdParent))
|
||||
{
|
||||
String colAffiliate_AffIdParent = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_AffIdParent, aliasAffiliate);
|
||||
filter.Add($"{colAffiliate_AffIdParent}={SysId.ToString(prm.AffiliateIdParent)}");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Common columns.
|
||||
@@ -725,7 +739,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
searchValueFilter.Add(colAffiliate_Notes + " LIKE '%" + searchValue + "%'");
|
||||
searchFilter.Add(searchValueFilter.Concat(" OR ", "(", ")"));
|
||||
}
|
||||
filter.AddRange(searchFilter);
|
||||
if (searchFilter.Any()) filter.AddRange(searchFilter);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
@@ -894,7 +908,6 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// User Id.
|
||||
String colAffiliate_UserId = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Affiliate_UserId, aliasAffiliate);
|
||||
if (SysId.IsValid(prm.UserId))
|
||||
filter.Add($"{colAffiliate_UserId}={SysId.ToString(prm.UserId)}");
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Association.
|
||||
// Get Item.
|
||||
public override SbmAssociation GetAssociation(SbmAssociation.Params prm)
|
||||
{
|
||||
return GetAssociation(GetAssociationQueryFilter(prm).Concat(" AND ", "(", ")"));
|
||||
@@ -77,6 +77,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Item properties.
|
||||
public override SysId GetAssociationAffIdTarget(SysId associationId)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -127,7 +128,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validate Association.
|
||||
// Validate Item.
|
||||
public override bool IsValidAssociationData(SbmAssociation.Data data, SbmAssociation.ErrField errField)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -145,7 +146,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Insert Association.
|
||||
// Insert Item.
|
||||
public override bool InsertAssociation(SbmAssociation association, DbUpdateInfo dbUpdateInfo)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -175,7 +176,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Update Association.
|
||||
// Update Item.
|
||||
public override bool UpdateAssociation(SbmAssociation association, DbUpdateInfo dbUpdateInfo)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -213,7 +214,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Delete Association.
|
||||
// Delete Item.
|
||||
public override bool AssociationCanBeDeleted(SbmAssociation association)
|
||||
{
|
||||
ClearErrorState();
|
||||
@@ -511,7 +512,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Column definitions.
|
||||
// Item Column definitions.
|
||||
private static readonly String aliasAssociation = "aAssoc";
|
||||
// Association Owner contact.
|
||||
private static string aliasAssociation_Affiliate_Owner = "Asn_AffOwn";
|
||||
@@ -556,7 +557,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
col.MaxLength = (int)Internals.GetColTextLen(dbCol);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// Getting prmAssociation column definition.
|
||||
// Item column definition.
|
||||
public override ColumnDfn GetAssociationColumnDfn(SbmAssociation.Column column, string caption = "", int width = 0)
|
||||
{
|
||||
ColumnDfn columnDfn = new ColumnDfn((int)column, caption, width);
|
||||
@@ -1120,10 +1121,21 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
public override List<string> GetAssociationQueryFilter(SbmAssociation.Params prm)
|
||||
{
|
||||
List<String> filter = new List<String>();
|
||||
String colAssociation_Id = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_Id, aliasAssociation);
|
||||
String colAssociation_AffIdOwner = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdOwner, aliasAssociation);
|
||||
String colAssociation_AffIdTarget = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdTarget, aliasAssociation);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Demo application restrictions - when user logged in.
|
||||
if (SysId.IsValid(UserContext.UserAffiliateId) && SessionConsole.HideOtherUserContacts())
|
||||
{
|
||||
// Exclude Individual contacts with User Id other than the logged in user.
|
||||
// NB Keep logic in line with corresponding Affiliate method (SbmAccountMgr_Dbas.GetAffiliateQueryFilter).
|
||||
filter.Add($"{colAssociation_AffIdTarget} Not In (Select Id From {SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Affiliate)} Where Id!={UserContext.UserAffiliateId} And Type={(int)Sbm.AffiliateType.Individual} And UserId>0)");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Association Id.
|
||||
String colAssociation_Id = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_Id, aliasAssociation);
|
||||
if (prm.IdsIncluded.HasValidIds())
|
||||
filter.Add($"{colAssociation_Id} IN ({prm.IdsIncluded.Concat(",")})");
|
||||
if (prm.IdsExcluded.HasValidIds())
|
||||
@@ -1138,12 +1150,10 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Owner affiliate.
|
||||
String colAssociation_AffIdOwner = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdOwner, aliasAssociation);
|
||||
if (SysId.IsValid(prm.AffiliateIdOwner))
|
||||
filter.Add($"{colAssociation_AffIdOwner}={prm.AffiliateIdOwner}");
|
||||
|
||||
// Target Affiliate.
|
||||
String colAssociation_AffIdTarget = SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Association_AffIdTarget, aliasAssociation);
|
||||
if (SysId.IsValid(prm.AffiliateIdTarget))
|
||||
filter.Add($"{colAssociation_AffIdTarget}={prm.AffiliateIdTarget}");
|
||||
|
||||
@@ -1151,7 +1161,7 @@ namespace Sarand.BusinessMgr.Net.Standard.Dbas.Mgr
|
||||
// Contact Group.
|
||||
if (SysId.IsValid(prm.AffiliateIdContactGroup))
|
||||
{
|
||||
//Association must also be a member of this contact group.
|
||||
// Association must also be a member of this contact group.
|
||||
String aliasAssocContactGroup = "aAssConGrp";
|
||||
DbQuery queryAssocContactGroup = new DbQuery(Database.DbmsType);
|
||||
queryAssocContactGroup.Tables.Add(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Association), aliasAssocContactGroup);
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
{
|
||||
// Session configuration.
|
||||
string repositoryContext = "Mimo";
|
||||
SbmSessionContext sessionContext = CreateCoreInstanceConsole(repositoryContext);
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
SbmInternals internals = new SbmInternals(GetSessionData(sessionContext, repositoryContext));
|
||||
disposables.Add(internals);
|
||||
@@ -55,7 +55,7 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
{
|
||||
// Session configuration.
|
||||
string repositoryContext = "Mimo";
|
||||
SbmSessionContext sessionContext = CreateCoreInstanceConsole(repositoryContext);
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
SbmInternals internals = new SbmInternals(GetSessionData(sessionContext, repositoryContext));
|
||||
disposables.Add(internals);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Components;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
|
||||
using Sarand.BusinessMgr.Web.Portal.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Security;
|
||||
using Sarand.Net.Standard.Dbas.Base;
|
||||
|
||||
namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
{
|
||||
//=======================================================================
|
||||
[TestClass]
|
||||
public class SbmApplication_DemoRepository_Tester : SbmApplication_Tester_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public void Test_SessionData_Demo()
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Demo Session configuration.
|
||||
string repositoryContext = Sbm.RepositoryContext_Demo;
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
|
||||
// Session data.
|
||||
SbmSessionData_Portal sessionData = new SbmSessionData_Portal(sessionContext, repositoryContext, null, null, null, null);
|
||||
Assert.IsNotNull(sessionData);
|
||||
Assert.IsTrue(sessionData.SessionContext.IsDemoRepository());
|
||||
|
||||
// Serialise data.
|
||||
string sessionDataJson = JsonConvert.SerializeObject(sessionData, SbmController_Web.SessionDataJsonSerializerSettings);
|
||||
Assert.IsNotNull(sessionDataJson);
|
||||
|
||||
// Deserialise data.
|
||||
SbmSessionData_Portal sessionDataDeserialized = JsonConvert.DeserializeObject<SbmSessionData_Portal>(sessionDataJson, SbmController_Web.SessionDataJsonDeserializerSettings);
|
||||
Assert.IsNotNull(sessionDataDeserialized);
|
||||
Assert.IsTrue(sessionDataDeserialized.SessionContext.IsDemoRepository());
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public void Test_SessionData_NonDemo()
|
||||
{
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Non-Demo Session configuration.
|
||||
string repositoryContext = "Mimo";
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
|
||||
// Session data.
|
||||
SbmSessionData_Portal sessionData = new SbmSessionData_Portal(sessionContext, repositoryContext, null, null, null, null);
|
||||
Assert.IsNotNull(sessionData);
|
||||
Assert.IsFalse(sessionData.SessionContext.IsDemoRepository());
|
||||
|
||||
// Serialise data.
|
||||
string sessionDataJson = JsonConvert.SerializeObject(sessionData, SbmController_Web.SessionDataJsonSerializerSettings);
|
||||
Assert.IsNotNull(sessionDataJson);
|
||||
|
||||
// Deserialise data.
|
||||
SbmSessionData_Portal sessionDataDeserialized = JsonConvert.DeserializeObject<SbmSessionData_Portal>(sessionDataJson, SbmController_Web.SessionDataJsonDeserializerSettings);
|
||||
Assert.IsNotNull(sessionDataDeserialized);
|
||||
Assert.IsFalse(sessionDataDeserialized.SessionContext.IsDemoRepository());
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -39,12 +39,16 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
{
|
||||
// Session configuration.
|
||||
string repositoryContext = "Mimo";
|
||||
SbmSessionContext sessionContext = CreateCoreInstanceConsole(repositoryContext);
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
ISacsDatabase busMgrDatabase = AppPortal.GetBusMgrDatabase(sessionContext);
|
||||
|
||||
// Session data.
|
||||
SbmSessionData_Portal sessionData = new SbmSessionData_Portal(sessionContext, repositoryContext, null, null, null, null);
|
||||
Assert.IsNotNull(sessionData);
|
||||
|
||||
// Internals.
|
||||
SbmInternals internals = new SbmInternals(GetSessionData(sessionContext, repositoryContext));
|
||||
SbmInternals internals = new SbmInternals(sessionData);
|
||||
disposables.Add(internals);
|
||||
SaSecurityConsole securityConsole = internals.SecurityConsole;
|
||||
Assert.IsNotNull(securityConsole);
|
||||
@@ -76,9 +80,8 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
Assert.IsNotNull(affiliateOrganisation);
|
||||
|
||||
|
||||
// Populate User Session.
|
||||
SbmSessionData_Portal sessionData = new SbmSessionData_Portal(sessionContext, repositoryContext, securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
|
||||
Assert.IsNotNull(sessionData);
|
||||
// Populate Session data.
|
||||
sessionData.Refresh(securityItemUser, affiliateUser, associationOrganisation, affiliateOrganisation);
|
||||
|
||||
// Validate user session.
|
||||
Assert.IsNotNull(sessionData.User);
|
||||
@@ -167,7 +170,7 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
|
||||
// Session configuration.
|
||||
string repositoryContext = "Mimo";
|
||||
SbmSessionContext sessionContext = CreateCoreInstanceConsole(repositoryContext);
|
||||
SbmSessionContext sessionContext = GetCoreSessionContext(repositoryContext);
|
||||
Assert.IsNotNull(sessionContext);
|
||||
ISacsDatabase busMgrDatabase = AppPortal.GetBusMgrDatabase(sessionContext);
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Sarand.BusinessMgr.Test.Web.Portal.App
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session Context.
|
||||
protected SbmSessionContext CreateCoreInstanceConsole(String instanceContext)
|
||||
protected SbmSessionContext GetCoreSessionContext(String instanceContext)
|
||||
{
|
||||
return AppPortal.GetControlSessionContextByRepositoryContext(instanceContext);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,31 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
}
|
||||
public UserProfileData Profile { get; protected set; } = new UserProfileData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// System.
|
||||
public class SystemData
|
||||
{
|
||||
// Databases.
|
||||
public class DatabaseData
|
||||
{
|
||||
}
|
||||
public DatabaseData Database { get; private set; } = new DatabaseData();
|
||||
|
||||
// Logs.
|
||||
public class LogsData
|
||||
{
|
||||
public class FilterData
|
||||
{
|
||||
public String Folder { get; set; }
|
||||
public String Year { get; set; }
|
||||
public String Month { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; private set; } = new FilterData();
|
||||
}
|
||||
public LogsData Logs { get; private set; } = new LogsData();
|
||||
}
|
||||
public SystemData System { get; private set; } = new SystemData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Control application encryption IV value - for consistent encryption during session.
|
||||
public String Base64IV_ControlApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SbmController_Control.Base64Key_ControlApp);
|
||||
|
||||
+8
-8
@@ -17,7 +17,7 @@ using System.Linq;
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
partial class CoreDatabaseController
|
||||
partial class RepositoryDatabaseController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
@@ -35,21 +35,21 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
//-------------------------------------------------------------------
|
||||
// Get Core Database Table list ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_CoreDatabaseTableList : AjaxResponse_Data
|
||||
private class AjaxResponse_RepositoryTableList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_CoreDatabaseTableList(SbmModel_Control model) : base(model) { }
|
||||
// CoreDatabase list.
|
||||
public AjaxResponse_RepositoryTableList(SbmModel_Control model) : base(model) { }
|
||||
// Table list.
|
||||
public List<TableListData> Tables { get; } = new List<TableListData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Instance/CoreDatabase/Ajax/GetTableList")]
|
||||
[Route("Instance/CoreDatabase/Ajax/GetTables")]
|
||||
public IActionResult Ajax_GetTableList(Model_CoreDatabase model)
|
||||
[Route("Instance/Repository/Ajax/GetTableList")]
|
||||
[Route("Instance/Repository/Ajax/GetTables")]
|
||||
public IActionResult Ajax_GetTableList(Model_RepositoryDatabase model)
|
||||
{
|
||||
String messageTitle = Localiser["label.database"];
|
||||
AjaxResponse_CoreDatabaseTableList responseData = new AjaxResponse_CoreDatabaseTableList(model);
|
||||
AjaxResponse_RepositoryTableList responseData = new AjaxResponse_RepositoryTableList(model);
|
||||
|
||||
// Validate session and referrer.
|
||||
if (!ValidReferer) return Forbid();
|
||||
+29
-5
@@ -3,25 +3,26 @@ using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.Instance;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
{
|
||||
//======================================================================
|
||||
public partial class CoreDatabaseController : SbmController_Control
|
||||
public partial class RepositoryDatabaseController : SbmController_Control
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public CoreDatabaseController(SbmLocaliser localiser, ILogger<CoreDatabaseController> logger) :
|
||||
public RepositoryDatabaseController(SbmLocaliser localiser, ILogger<RepositoryDatabaseController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Instance/CoreDatabase")]
|
||||
public IActionResult Index(Model_CoreDatabase model)
|
||||
[Route("Instance/Repository/Database/Tables")]
|
||||
public IActionResult DatabaseTables(Model_RepositoryDatabase model)
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
@@ -38,7 +39,30 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
model.Filter.Context = SessionData_Control.Profile.Filter.InstanceContext;
|
||||
|
||||
// Core Database view.
|
||||
return View("Views/Instance/CoreDatabase/Index.cshtml", model);
|
||||
return View("Views/Instance/Repository/Database/Tables.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[Route("Instance/Repository/Database/Schema")]
|
||||
public IActionResult Schema()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Refresh model.
|
||||
Model_System model = new Model_System(Localiser);
|
||||
RefreshModel(model);
|
||||
model.DatabaseFilter.Instance = SessionData_Control.Profile.Filter.InstanceContext;
|
||||
|
||||
// Core Database view.
|
||||
return View("Views/Instance/Repository/Database/Schema.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
+25
-6
@@ -72,7 +72,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
Sbm.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseFilter.Instance), Sbm.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Database instance must be specified."));
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
ISacsDatabase db = GetDatabase(databaseInstance, model.DatabaseFilter.Context);
|
||||
if (db == null)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Database unavailable for instance '{databaseInstance}'."));
|
||||
|
||||
@@ -123,12 +123,14 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
/// <summary>
|
||||
/// Get database by type.
|
||||
/// </summary>
|
||||
private ISacsDatabase GetDatabase(Sbm.Database databaseInstance)
|
||||
private ISacsDatabase GetDatabase(Sbm.Database databaseInstance, String context)
|
||||
{
|
||||
switch (databaseInstance)
|
||||
{
|
||||
case Sbm.Database.Control:
|
||||
return App.GetControlDatabase();
|
||||
case Sbm.Database.BusMgr:
|
||||
return GetDatabaseByContext(context);
|
||||
case Sbm.Database.Template:
|
||||
return GetDatabaseByContext(Sbm.RepositoryContext_Template);
|
||||
case Sbm.Database.Demo:
|
||||
@@ -169,6 +171,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
public AjaxResponse_ValidateDatabaseSchema(SbmModel_Control model) : base(model) { }
|
||||
// Database instance.
|
||||
public String Instance { get; set; }
|
||||
public String Context { get; set; }
|
||||
// Schema validation list.
|
||||
public List<DbSchemaItemResponseData> Items { get; } = new List<DbSchemaItemResponseData>();
|
||||
}
|
||||
@@ -194,13 +197,21 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
responseData.Instance = databaseInstance.ToString();
|
||||
|
||||
// Context.
|
||||
if (databaseInstance == Sbm.Database.BusMgr)
|
||||
{
|
||||
if (StringUtil.IsBlank(model.DatabaseFilter.Context))
|
||||
return Json(responseData.SetMessage(messageTitle, "BusMgr Database context must be specified"));
|
||||
responseData.Context = model.DatabaseFilter.Context;
|
||||
}
|
||||
|
||||
// Database connection.
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
ISacsDatabase db = GetDatabase(databaseInstance, model.DatabaseFilter.Context);
|
||||
if (db == null)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Unrecognised database instance specified: '{model.DatabaseFilter.Instance}'."));
|
||||
|
||||
// Retrieve XML database schema definition.
|
||||
Dictionary<String, String> xmlSchemas = GetSmlSchema(databaseInstance);
|
||||
Dictionary<String, String> xmlSchemas = GetSmlSchemas(databaseInstance);
|
||||
if (!xmlSchemas.Any())
|
||||
return Json(responseData.SetMessage(messageTitle, "Failed to extract XML schema definitions."));
|
||||
|
||||
@@ -253,7 +264,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
private Dictionary<String, String> GetSmlSchema(Sbm.Database databaseInstance)
|
||||
private Dictionary<String, String> GetSmlSchemas(Sbm.Database databaseInstance)
|
||||
{
|
||||
Dictionary<String, String> schemas = new Dictionary<String, String>();
|
||||
switch (databaseInstance)
|
||||
@@ -264,6 +275,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
schemas.Add("SbmDbDfn_Control.xml", SacsResourceHelper.GetManifestResourceAsText(assembly, "", "SbmDbDfn_Control.xml"));
|
||||
break;
|
||||
}
|
||||
case Sbm.Database.BusMgr:
|
||||
case Sbm.Database.Template:
|
||||
case Sbm.Database.Demo:
|
||||
{
|
||||
@@ -436,8 +448,15 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
|
||||
// Context.
|
||||
if (databaseInstance == Sbm.Database.BusMgr)
|
||||
{
|
||||
if (StringUtil.IsBlank(model.DatabaseFilter.Context))
|
||||
return Json(responseData.SetMessage(messageTitle, "BusMgr Database context must be specified"));
|
||||
}
|
||||
|
||||
// Database connection.
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
ISacsDatabase db = GetDatabase(databaseInstance, model.DatabaseFilter.Context);
|
||||
|
||||
// Table definition.
|
||||
DbDfnTable tableDfn = db.GetTableDfn(model.DatabaseTable.Name, true);
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Data;
|
||||
using Sarand.Net.Standard.Dbas.Proc;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.System;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using System.Linq;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.Net.Standard.Dbas.Base;
|
||||
using Sarand.BusinessMgr.Web.Control.Consoles;
|
||||
using System.Reflection;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Dbas.Utils.SbmDbDfnGenerator;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
using Sarand.Net.Standard.Base.IO;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
{
|
||||
//======================================================================
|
||||
// System Controller - Ajax - Logs.
|
||||
//======================================================================
|
||||
partial class SystemController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Database data.
|
||||
private class LogFolderData
|
||||
{
|
||||
public String Name { get; set; }
|
||||
}
|
||||
private class LogFileData
|
||||
{
|
||||
public String Name { get; set; }
|
||||
public String UpdateFmt { get; set; }
|
||||
public long Size { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFolderList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFolderList(SbmModel_Control model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Folders { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of folders under the root folder.
|
||||
/// <para>- These should correspond to applications (control, busmgr, api etc).</para>
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetFolderList")]
|
||||
[Route("System/Ajax/Logs/GetFolders")]
|
||||
public IActionResult Ajax_GetLogFolderList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFolderList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogFolderList responseData = new AjaxResponse_LogFolderList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify folders in root log folder.
|
||||
String rootLogFolder = model.LoggingRootFolder;
|
||||
foreach (String folder in Directory.EnumerateDirectories(rootLogFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^(?:Sbm|BusMgr|Web|)(?:Control|Portal|Api)$", RegexOptions.IgnoreCase))
|
||||
responseData.Folders.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log Year Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogYearList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogYearList(SbmModel_Control model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Years { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of year folders under the selected folder.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetYearList")]
|
||||
[Route("System/Ajax/Logs/GetYears")]
|
||||
public IActionResult Ajax_GetLogYearList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogYearList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogYearList responseData = new AjaxResponse_LogYearList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Control.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Control.System.Logs.Filter.Year = "";
|
||||
SessionData_Control.System.Logs.Filter.Month = "";
|
||||
|
||||
// Identify folders in selected log folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder);
|
||||
foreach (String folder in Directory.EnumerateDirectories(logFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^\\d{4}$"))
|
||||
responseData.Years.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log Month Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogMonthList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogMonthList(SbmModel_Control model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Months { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of year folders under the selected folder.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetMonthList")]
|
||||
[Route("System/Ajax/Logs/GetMonths")]
|
||||
public IActionResult Ajax_GetLogMonthList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogMonthList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogMonthList responseData = new AjaxResponse_LogMonthList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Control.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Control.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Control.System.Logs.Filter.Month = "";
|
||||
//SessionData_Control.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year);
|
||||
foreach (String folder in Directory.EnumerateDirectories(logFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^\\d{6}$"))
|
||||
responseData.Months.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log File List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFileList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFileList(SbmModel_Control model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFileData> Files { get; } = new List<LogFileData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetFileList")]
|
||||
[Route("System/Ajax/Logs/GetFiles")]
|
||||
public IActionResult Ajax_GetLogFileList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFileList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogFileList responseData = new AjaxResponse_LogFileList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Control.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Control.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Control.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year, model.LogsFilter.Month);
|
||||
DirectoryInfo folder = new DirectoryInfo(logFolder);
|
||||
foreach (FileInfo file in folder.EnumerateFiles())
|
||||
{
|
||||
responseData.Files.Add(new LogFileData() { Name = file.Name, UpdateFmt = file.LastWriteTime.ToString("d-MMM-yy HH:mm"), Size = file.Length });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log File ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFile : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFile(SbmModel_Control model) : base(model) { }
|
||||
// Log file.
|
||||
public class LogFileData
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String Data { get; set; }
|
||||
public String Html { get; set; } = "";
|
||||
}
|
||||
public LogFileData File { get; } = new LogFileData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetFile")]
|
||||
[Route("System/Ajax/Logs/GetLogFile")]
|
||||
public IActionResult Ajax_GetLogFile(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFile";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogFile responseData = new AjaxResponse_LogFile(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Control.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Control.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Control.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
responseData.File.Path = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year, model.LogsFilter.Month, model.LogsFilter.Filename);
|
||||
responseData.File.Name = Path.GetFileName(responseData.File.Path);
|
||||
try
|
||||
{
|
||||
String[] fileLines = FileUtil.ReadAllFileLines(responseData.File.Path);
|
||||
responseData.File.Data = String.Join("\n", fileLines);
|
||||
// Construct html data.
|
||||
foreach (var fileLine in fileLines)
|
||||
{
|
||||
String line = fileLine;
|
||||
List<String> classNames = new List<string>();
|
||||
if (fileLine.IsMatch("^\t{2}"))
|
||||
{
|
||||
line = Regex.Replace(fileLine, "^\t+", "");
|
||||
classNames.Add("tab2");
|
||||
}
|
||||
if (fileLine.IsMatch("^\t"))
|
||||
{
|
||||
line = Regex.Replace(fileLine, "^\t", "");
|
||||
classNames.Add("tab");
|
||||
}
|
||||
if (line.IsMatch("\\d{8}:\\d{6}\\s+(error|err)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("err");
|
||||
else if (line.IsMatch("\\d{8}:\\d{6}\\s+(warn|wrn)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("wrn");
|
||||
else if (line.IsMatch("\\d{8}:\\d{6}\\s+(info|inf)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("inf");
|
||||
responseData.File.Html += $"<div class='{String.Join(" ", classNames)}'>" + line + "</div>";
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc, "reading log file", 0)}");
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.System;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
{
|
||||
@@ -29,6 +33,34 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
return RedirectToAction("", "");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// System - Logs.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public IActionResult Logs()
|
||||
{
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Refresh model.
|
||||
Model_System model = new Model_System(Localiser);
|
||||
RefreshModel(model);
|
||||
model.LogsFilter.Folder = StringUtil.OnBlank(SessionData_Control.System.Logs.Filter.Folder, "Control");
|
||||
model.LogsFilter.Year = StringUtil.OnBlank(SessionData_Control.System.Logs.Filter.Year, DateTime.Today.ToString("yyyy"));
|
||||
model.LogsFilter.Month = StringUtil.OnBlank(SessionData_Control.System.Logs.Filter.Month, DateTime.Today.ToString("yyyyMM"));
|
||||
|
||||
// Core Database view.
|
||||
return View("Views/System/Logs.cshtml", model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
|
||||
+2
-2
@@ -5,11 +5,11 @@ using System;
|
||||
namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_CoreDatabase : SbmModel_Control
|
||||
public class Model_RepositoryDatabase : SbmModel_Control
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_CoreDatabase(SbmLocaliser localiser) :
|
||||
public Model_RepositoryDatabase(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
@@ -24,9 +24,11 @@ namespace Sarand.BusinessMgr.Web.Control.Models.System
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database page properties.
|
||||
// ToDo: System-Database model may not be required..
|
||||
public class DatabaseFilterData
|
||||
{
|
||||
public String Instance { get; set; }
|
||||
public String Context { get; set; }
|
||||
public String Search { get; set; }
|
||||
}
|
||||
public DatabaseFilterData DatabaseFilter { get; } = new DatabaseFilterData();
|
||||
@@ -42,8 +44,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.System
|
||||
List<CodeDesc> items = new List<CodeDesc>();
|
||||
if (ValidUserSession)
|
||||
{
|
||||
items.Add("Core", Localiser["label.core"]);
|
||||
items.Add("Reference", Localiser["label.reference"]);
|
||||
items.Add("Control", Localiser["label.control"]);
|
||||
items.Add("Support", Localiser["label.support"]);
|
||||
}
|
||||
return new SelectList(items, "Code", "Desc");
|
||||
@@ -51,7 +52,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.System
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Logs page properties.
|
||||
public String LoggingRootFolder { get; } = Regex.Replace(SaLogger.LogFolder, "[\\\\/]Admin$", "");
|
||||
public String LoggingRootFolder { get; } = Regex.Replace(SaLogger.LogFolder, "[\\\\/](?:Sbm|BusMgr|Web)Control$", "");
|
||||
// Log file filter.
|
||||
public class LogsFilterData
|
||||
{
|
||||
|
||||
@@ -432,8 +432,8 @@
|
||||
<data name="caption.instance.initialise" xml:space="preserve">
|
||||
<value>Initialise Instance</value>
|
||||
</data>
|
||||
<data name="label.database.core" xml:space="preserve">
|
||||
<value>Core database</value>
|
||||
<data name="label.repository.database" xml:space="preserve">
|
||||
<value>Repository database</value>
|
||||
</data>
|
||||
<data name="caption.database.core" xml:space="preserve">
|
||||
<value>Core Database</value>
|
||||
@@ -507,4 +507,34 @@
|
||||
<data name="label.strength" xml:space="preserve">
|
||||
<value>Strength</value>
|
||||
</data>
|
||||
<data name="label.control" xml:space="preserve">
|
||||
<value>Control</value>
|
||||
</data>
|
||||
<data name="system.caption.logs" xml:space="preserve">
|
||||
<value>System Logs</value>
|
||||
</data>
|
||||
<data name="label.root.folder" xml:space="preserve">
|
||||
<value>Root folder</value>
|
||||
</data>
|
||||
<data name="label.folder" xml:space="preserve">
|
||||
<value>Folder</value>
|
||||
</data>
|
||||
<data name="label.year" xml:space="preserve">
|
||||
<value>Year</value>
|
||||
</data>
|
||||
<data name="label.month" xml:space="preserve">
|
||||
<value>Month</value>
|
||||
</data>
|
||||
<data name="label.file" xml:space="preserve">
|
||||
<value>File</value>
|
||||
</data>
|
||||
<data name="label.updated" xml:space="preserve">
|
||||
<value>Updated</value>
|
||||
</data>
|
||||
<data name="label.size" xml:space="preserve">
|
||||
<value>Size</value>
|
||||
</data>
|
||||
<data name="label.repository.schema" xml:space="preserve">
|
||||
<value>Repository schema</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -126,11 +126,11 @@
|
||||
<table class="sbc-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="">@Localiser["label.schema"]</th>
|
||||
<th class="">@Localiser["label.table"]</th>
|
||||
<th class="">@Localiser["label.column"]</th>
|
||||
<th class="">@Localiser["label.index"]</th>
|
||||
<th class="" style="min-width:50%;">@Localiser["label.comment"]</th>
|
||||
<th class="width10pc">@Localiser["label.schema"]</th>
|
||||
<th class="width20pc">@Localiser["label.table"]</th>
|
||||
<th class="width20pc">@Localiser["label.column"]</th>
|
||||
<th class="width20pc">@Localiser["label.index"]</th>
|
||||
<th class="width30pc">@Localiser["label.comment"]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
@* Instance - Repository Database Schema *@
|
||||
@model Model_System
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Instance - Repository Database Schema";
|
||||
Model.AdditionalFiles_JS.Add("js/sbc-ins-rep-sch.js");
|
||||
}
|
||||
|
||||
<div class="sbc-panel Schema fullheight">
|
||||
|
||||
<script type="text/javascript">
|
||||
sbc.msg.dbSchemaValid = '@Localiser.GetJavascriptText("msg.database.schema.valid")';
|
||||
</script>
|
||||
|
||||
<div class="sbc-panel-data sbc-flex">
|
||||
|
||||
@* Filter form - wrap header to include paging controls. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSchemaFilter", @class = "sbc-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sbc-panel-header">
|
||||
<div class="row">
|
||||
<div class="fixed">
|
||||
@* <partial name="~/Views/Common/ResultsPaging.cshtml" /> *@
|
||||
</div>
|
||||
<div class="col center"><div class="sbc-panel-caption">@Localiser["caption.database.core"]</div></div>
|
||||
<div class="fixed">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-dark navbar-right sbc-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 sbc-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Filter Panel *@
|
||||
<div class="sbc-panel-filter">
|
||||
@Html.HiddenFor(model => model.DatabaseFilter.Instance, new { @id = "", @class = "FilterInstance" })
|
||||
<div class="row">
|
||||
<div class="col-sm-4 row pb4">
|
||||
<div class="col-sm-5 sbc-label text-left text-sm-right">@Localiser["label.context"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.DropDownListFor(model => model.DatabaseFilter.Context, Model.GetInstanceContextsForSelect(), "", new { @id = "", @class = "FilterContext" })
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 row pb4">
|
||||
<div class="col-sm-5 sbc-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.TextBoxFor(model => model.DatabaseFilter.Search, new { @id = "", @class = "FilterSearch", @maxlength = "32" })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="sbc-panel-item-table sbc-flex">
|
||||
<table class="sbc-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="width10pc">@Localiser["label.schema"]</th>
|
||||
<th class="width20pc">@Localiser["label.table"]</th>
|
||||
<th class="width20pc">@Localiser["label.column"]</th>
|
||||
<th class="width20pc">@Localiser["label.index"]</th>
|
||||
<th class="width25pc">@Localiser["label.comment"]</th>
|
||||
<th class="width5pc"></th>
|
||||
</tr>
|
||||
<tr><td colspan="6"><div class="sbc-panel-messages"></div></td></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Element templates *@
|
||||
<div class="sbc-panel-item-template">
|
||||
@* Filter Burger option template - ul is ignored *@
|
||||
<ul class="sbc-dropdown-menu SchemaFilter">
|
||||
<li class="sbc-dropdown-item sbc-action"><div class="sbc-label">XXX</div></li>
|
||||
</ul>
|
||||
@* Schema row template - table is ignored. *@
|
||||
<table class="">
|
||||
<tr class="sbc-row-item SchemaItem">
|
||||
<td class=""><div class="SchemaName"></div></td>
|
||||
<td class=""><div class="TableName"></div></td>
|
||||
<td class=""><div class="ColumnName"></div></td>
|
||||
<td class=""><div class="IndexName"></div></td>
|
||||
<td class=""><div class="Comment"></div></td>
|
||||
<td>
|
||||
<div class="right">
|
||||
@* Burger menu *@
|
||||
<ul class="nav navbar-nav navbar-light navbar-right sbc-burger">
|
||||
<li class="dropdown-toggle caret-off">
|
||||
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbc-ellipsis-dot"></span><span class="sbc-ellipsis-dot"></span><span class="sbc-ellipsis-dot"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right sbc-dropdown-menu">@* Menu items will be inserted here. *@</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@* Item Burger option template - ul is ignored *@
|
||||
<ul class="sbc-dropdown-menu Schema">
|
||||
<li class="sbc-dropdown-item sbc-action"><div class="sbc-label">XXX</div></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
@* Instance - Core Database*@
|
||||
@model Model_CoreDatabase
|
||||
@* Instance - Repository Database Tables *@
|
||||
@model Model_RepositoryDatabase
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Instance - Core Database";
|
||||
Model.AdditionalFiles_JS.Add("js/sbc-ins-coredb.js");
|
||||
ViewData["Title"] = "Instance - Repository Database Tables";
|
||||
Model.AdditionalFiles_JS.Add("js/sbc-ins-rep-db.js");
|
||||
}
|
||||
|
||||
<div class="sbc-panel Tables fullheight">
|
||||
@@ -128,7 +128,8 @@
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('Instance/Owner');">@Localiser["label.owners"]</div>
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('Instance/Repository');">@Localiser["label.repositories"]</div>
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('Instance/CoreDatabase');">@Localiser["label.database.core"]</div>
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('Instance/Repository/Database/Tables');">@Localiser["label.repository.database"]</div>
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('Instance/Repository/Database/Schema');">@Localiser["label.repository.schema"]</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -148,7 +149,7 @@
|
||||
@Localiser["label.system"]
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('System/Database');">@Localiser["label.database"]</div>
|
||||
@* <div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('System/Database');">@Localiser["label.database"]</div> *@
|
||||
<div class="dropdown-item text-dark sbc-action" onclick="sbc.goToPage('System/Logs');">@Localiser["label.logs"]</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
@model Model_System
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "System - Logs";
|
||||
Model.AdditionalFiles_JS.Add("js/sbc-sys-logs.js");
|
||||
}
|
||||
|
||||
<style>
|
||||
#dlgLogFile .FileData
|
||||
{
|
||||
font-family: Courier New, Courier, monospace;
|
||||
font-size: 10px;
|
||||
color: slategray;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#dlgLogFile .FileData .tab
|
||||
{
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
#dlgLogFile .FileData .tab2
|
||||
{
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
#dlgLogFile .FileData .err
|
||||
{
|
||||
color: darkred;
|
||||
}
|
||||
|
||||
#dlgLogFile .FileData .wrn
|
||||
{
|
||||
color: darkorange;
|
||||
}
|
||||
|
||||
#dlgLogFile .FileData .inf
|
||||
{
|
||||
color: darkGreen;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sbc-panel LogFiles">
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<div class="sbc-panel-data">
|
||||
<div class="sbc-panel-header row">
|
||||
<div class="fixed"></div>
|
||||
<div class="col center"><div class="sbc-panel-caption">@Localiser["system.caption.logs"]</div></div>
|
||||
<div class="fixed row">
|
||||
<div class="sbc-action sbc-results-refresh"><img src="~/img/action/refresh24.png" alt="@(Localiser["label.refresh"])" title="@(Localiser["label.refresh"])" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sbc-panel-filter">
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmLogsFilter", @class = "sbc-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
<input type="hidden" name="LogsFilter.Filename" class="FilterLogFilename" />
|
||||
<div class="row">
|
||||
<div class="col-sm-12 row mb-1">
|
||||
<div class="col-sm-4 col-md-3 sbc-label text-left text-sm-right" style="padding-top:2px;">@Localiser["label.root.folder"]</div>
|
||||
<div class="col-sm-8 col-md-9 sbc-value mt-1 bold">@(Model.LoggingRootFolder)</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-4 row">
|
||||
<div class="col-sm-4 col-md-5 sbc-label text-left text-sm-right">@Localiser["label.folder"]</div>
|
||||
<div class="col-sm-8 col-md-7 mb-1"><div style="max-width:200px;"><select id="cbFilterLogFolder" name="LogsFilter.Folder" class="FilterLogFolder"></select></div></div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-4 row">
|
||||
<div class="col-sm-4 col-md-5 sbc-label text-left text-sm-right">@Localiser["label.year"]</div>
|
||||
<div class="col-sm-8 col-md-7 mb-1"><div style="max-width:200px;"><select id="cbFilterLogYear" name="LogsFilter.Year" class="FilterLogYear"></select></div></div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-4 row">
|
||||
<div class="col-sm-4 col-md-5 sbc-label text-left text-sm-right">@Localiser["label.month"]</div>
|
||||
<div class="col-sm-8 col-md-7"><div style="max-width:200px;"><select id="cbFilterLogMonth" name="LogsFilter.Month" class="FilterLogMonth"></select></div></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="sbc-panel-results">
|
||||
<div class="sbc-panel-messages"></div>
|
||||
@* Log file list. *@
|
||||
<div class="sbc-panel-info" style="min-height:120px;max-height:100%;overflow-y:auto;">
|
||||
<table class="sbc-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-2">@Localiser["label.file"]</th>
|
||||
<th class="center">@Localiser["label.updated"]</th>
|
||||
<th class="center">@Localiser["label.size"]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
@* Log file template. *@
|
||||
<table class="sbc-panel-item-template">
|
||||
<tr class="sbc-panel-item LogFile pointer">
|
||||
<td><div class="Filename pl-2 pt-1"></div></td>
|
||||
<td><div class="Updated center"></div></td>
|
||||
<td><div class="Size center"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="dlgLogFile" class="sbc-dialog">
|
||||
<form>
|
||||
<input type="hidden" class="LogFilename" />
|
||||
</form>
|
||||
<div class="sbc-data FileData"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
sbc.data.logFolder = '@(Localiser.EscapeJavascriptText(Model.LogsFilter.Folder))';
|
||||
sbc.data.logYear = '@(Localiser.EscapeJavascriptText(Model.LogsFilter.Year))';
|
||||
sbc.data.logMonth = '@(Localiser.EscapeJavascriptText(Model.LogsFilter.Month))';
|
||||
</script>
|
||||
@@ -6,4 +6,5 @@
|
||||
@using Sarand.BusinessMgr.Web.Control.Models.Account
|
||||
@using Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
@using Sarand.BusinessMgr.Web.Control.Models.Param
|
||||
@using Sarand.BusinessMgr.Web.Control.Models.System
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
var $msgs = $('.sbc-panel-messages', $pnlSchema).hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
$('.DatabaseInstance', $frm.dbSchema).val(instance);
|
||||
sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formId: $frm.dbSchema.prop('id'), callbackFn: ch.handleDbSchemaResponse, noWaitIcon: true };
|
||||
sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formSel: $frm.dbSchema, callbackFn: ch.handleDbSchemaResponse, noWaitIcon: true };
|
||||
sbc.doAjaxRequest(sbc.ajax.dbSchema, delay || 50);
|
||||
ch.awaitingSchemaResponse = true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
env.$pnl.table.find('tbody tr').remove();
|
||||
env.$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
env.ajax.tables = env.ajax.tables || { url: sbc.url.base + 'Instance/CoreDatabase/Ajax/GetTables', formSel: env.$frm.filter, callbackFn: function (response) { cd.displayItems(env, response); } };
|
||||
env.ajax.tables = env.ajax.tables || { url: sbc.url.base + 'Instance/Repository/Ajax/GetTables', formSel: env.$frm.filter, callbackFn: function (response) { cd.displayItems(env, response); } };
|
||||
sbc.doAjaxRequest(env.ajax.tables, delay || 50);
|
||||
cd.awaitingRefreshResponse = true;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* SBM - Control - Instance - Core Database.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ds = sbc.mdl.repDbSchema = { env: {}, data: {} };
|
||||
let $pnl = ds.$pnl = {}, $frm = ds.$frm = {}, $dlg = ds.$dlg = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ds.refreshDbSchema = function (delay)
|
||||
{
|
||||
if (sbc.awaitingLogin) return;
|
||||
if (!$frm.filter.find('.FilterContext').val()) return;
|
||||
if (!ds.awaitingSchemaResponse)
|
||||
{
|
||||
$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
ds.clearItems();
|
||||
sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formSel: $frm.filter, callbackFn: ds.handleDbSchemaResponse, noWaitIcon: true };
|
||||
sbc.doAjaxRequest(sbc.ajax.dbSchema, delay || 50);
|
||||
ds.awaitingSchemaResponse = true;
|
||||
}
|
||||
ds.handleDbSchemaResponse = function (response)
|
||||
{
|
||||
//sbc.debug('handleDbSchemaResponse', response);
|
||||
delete ds.awaitingSchemaResponse;
|
||||
$pnl.msgs.hide().empty();
|
||||
var $table = $pnl.table.find('table.sbc-item-list');
|
||||
ds.clearItems();
|
||||
if (!response.success) return;
|
||||
// Items.
|
||||
var items = response.items;
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbc-message">' + sbc.msg.dbSchemaValid + '</div>')).fadeIn(500);
|
||||
for (const item of items)
|
||||
$table.append(ds.populateDbSchemaItem(ds.getDbSchemaRowTemplate(), item));
|
||||
}
|
||||
ds.getDbSchemaTableTemplate = function ()
|
||||
{
|
||||
return $pnl.tmpl.find('.sbc-panel-item-table.Schema').clone().hide();
|
||||
}
|
||||
ds.getDbSchemaRowTemplate = function ()
|
||||
{
|
||||
return $pnl.tmpl.find('.sbc-row-item.SchemaItem').clone();
|
||||
}
|
||||
ds.populateDbSchemaItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$item.prop('id', sbc.itemIdPrefix + item.id);
|
||||
$('.SchemaName', $item).text(item.schemaName);
|
||||
$('.TableName', $item).text(item.tableName);
|
||||
$('.IndexName', $item).text(item.indexName);
|
||||
$('.ColumnName', $item).text(item.columnName);
|
||||
$('.Comment', $item).text(item.comment);
|
||||
return $item;
|
||||
}
|
||||
ds.clearItems = function ()
|
||||
{
|
||||
$pnl.table.find('table.sbc-item-list').find('tbody tr').remove();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.items = $('.sbc-panel.Schema');
|
||||
$frm.filter = $pnl.items.find('#frmSchemaFilter');
|
||||
$frm.filter.on('change', '.FilterContext', ds.refreshDbSchema);
|
||||
$frm.filter.on('input', '.FilterSearch', ds.refreshDbSchema);
|
||||
$frm.filter.find('.FilterInstance').val('BusMgr');
|
||||
$pnl.table = $pnl.items.find('.sbc-panel-item-table');
|
||||
$pnl.msgs = $pnl.items.find('.sbc-panel-messages');
|
||||
$pnl.tmpl = $pnl.items.find('.sbc-panel-item-template');
|
||||
setTimeout(function () { ds.refreshDbSchema(); }, 500);
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Admin - System Logs page scripts.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let sl = sbc.sysLogs = { data: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
|
||||
let $pnl = sl.$pnl; let $frm = sl.$frm; let $ctrl = sl.$ctrl; let $dlg = sl.$dlg;
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.refreshFolders = function (delay)
|
||||
{
|
||||
if (!sl.data.awaitingRefreshFoldersResponse)
|
||||
{
|
||||
sl.clearFiles();
|
||||
//$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sbc.ajax.refreshFolders = sbc.ajax.refreshFolders || { url: sbc.url.base + 'System/Ajax/Logs/GetFolders', formSel: sl.$frm.filter, callbackFn: sl.doRefreshFolders };
|
||||
sbc.doAjaxRequest(sbc.ajax.refreshFolders, delay || 50);
|
||||
sl.data.awaitingRefreshFoldersResponse = true;
|
||||
}
|
||||
sl.doRefreshFolders = function (response)
|
||||
{
|
||||
sbc.debug('doRefreshFolders', response);
|
||||
delete sl.data.awaitingRefreshFoldersResponse;
|
||||
sl.clearFilterFolders();
|
||||
sbc.refreshControlValues(response.controlValues);
|
||||
$pnl.msgs.hide().empty();
|
||||
if (!response.success) return;
|
||||
// Folders.
|
||||
var items = response.folders;
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbc-message">' + sbc.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (const item of items)
|
||||
$ctrl.cbFolders.append($('<option value="' + item.name + '">' + item.name + '</option>'));
|
||||
if (sbc.data.logFolder) $ctrl.cbFolders.val(sbc.data.logFolder);
|
||||
if (!$ctrl.cbFolders.val()) $ctrl.cbFolders.val(items[0].name);
|
||||
delete sbc.data.logFolder;
|
||||
if ($ctrl.cbFolders.val()) $ctrl.cbFolders.trigger('change');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.clearFilterFolders = function ()
|
||||
{
|
||||
sl.clearFilterYears();
|
||||
$('option', $ctrl.cbFolders).remove();
|
||||
}
|
||||
sl.clearFilterYears = function ()
|
||||
{
|
||||
sl.clearFilterMonths();
|
||||
$('option', $ctrl.cbYears).remove();
|
||||
}
|
||||
sl.clearFilterMonths = function ()
|
||||
{
|
||||
sl.clearFiles();
|
||||
$('option', $ctrl.cbMonths).remove();
|
||||
}
|
||||
sl.clearFiles = function ()
|
||||
{
|
||||
$pnl.msgs.hide().empty();
|
||||
$pnl.list.find('tbody tr').remove();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.refreshYears = function (delay)
|
||||
{
|
||||
if (!sl.data.awaitingRefreshYearsResponse)
|
||||
{
|
||||
sl.clearFiles();
|
||||
//$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sbc.ajax.refreshYears = sbc.ajax.refreshYears || { url: sbc.url.base + 'System/Ajax/Logs/GetYears', formSel: sl.$frm.filter, callbackFn: sl.doRefreshYears };
|
||||
sbc.doAjaxRequest(sbc.ajax.refreshYears, delay || 50);
|
||||
sl.data.awaitingRefreshYearsResponse = true;
|
||||
}
|
||||
sl.doRefreshYears = function (response)
|
||||
{
|
||||
//sbc.debug('doRefreshYears', response);
|
||||
delete sl.data.awaitingRefreshYearsResponse;
|
||||
sl.clearFilterYears();
|
||||
sbc.refreshControlValues(response.controlValues);
|
||||
$pnl.msgs.hide().empty();
|
||||
if (!response.success) return;
|
||||
// Years.
|
||||
var items = response.years;
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbc-message">' + sbc.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$ctrl.cbYears.append($('<option value="' + items[itemIdx].name + '">' + items[itemIdx].name + '</option>'));
|
||||
if (sbc.data.logYear) $ctrl.cbYears.val(sbc.data.logYear);
|
||||
delete sbc.data.logYear;
|
||||
if ($ctrl.cbYears.val()) $ctrl.cbYears.trigger('change');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.refreshMonths = function (delay)
|
||||
{
|
||||
if (!sl.data.awaitingRefreshMonthsResponse)
|
||||
{
|
||||
sl.clearFiles();
|
||||
//$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sbc.ajax.refreshMonths = sbc.ajax.refreshMonths || { url: sbc.url.base + 'System/Ajax/Logs/GetMonths', formSel: sl.$frm.filter, callbackFn: sl.doRefreshMonths };
|
||||
sbc.doAjaxRequest(sbc.ajax.refreshMonths, delay || 50);
|
||||
sl.data.awaitingRefreshMonthsResponse = true;
|
||||
}
|
||||
sl.doRefreshMonths = function (response)
|
||||
{
|
||||
//sbc.debug('doRefreshMonths', response);
|
||||
delete sl.data.awaitingRefreshMonthsResponse;
|
||||
sl.clearFilterMonths();
|
||||
sbc.refreshControlValues(response.controlValues);
|
||||
$pnl.msgs.hide().empty();
|
||||
if (!response.success) return;
|
||||
sbc.data.logYear = $ctrl.cbYears.val();
|
||||
// Months.
|
||||
var items = response.months;
|
||||
if (!items.length)
|
||||
return $pnl.msgs.append($('<div class="sbc-message">' + sbc.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$ctrl.cbMonths.append($('<option value="' + items[itemIdx].name + '">' + items[itemIdx].name + '</option>'));
|
||||
if (sbc.data.logMonth) $ctrl.cbMonths.val(sbc.data.logMonth);
|
||||
if (!$ctrl.cbMonths.val() && items.length) $ctrl.cbMonths.val(items[0].name);
|
||||
delete sbc.data.logMonth;
|
||||
if ($ctrl.cbMonths.val()) $ctrl.cbMonths.trigger('change');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.refreshFiles = function (delay)
|
||||
{
|
||||
if (!sl.data.awaitingRefreshFilesResponse)
|
||||
{
|
||||
sl.clearFiles();
|
||||
//$pnl.msgs.hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sbc.ajax.refreshFiles = sbc.ajax.refreshFiles || { url: sbc.url.base + 'System/Ajax/Logs/GetFiles', formSel: sl.$frm.filter, callbackFn: sl.doRefreshFiles };
|
||||
sbc.doAjaxRequest(sbc.ajax.refreshFiles, delay || 50);
|
||||
sl.data.awaitingRefreshFilesResponse = true;
|
||||
}
|
||||
sl.doRefreshFiles = function (response)
|
||||
{
|
||||
//sbc.debug('doRefreshFiles', response);
|
||||
delete sl.data.awaitingRefreshFilesResponse;
|
||||
sl.clearFiles();
|
||||
sbc.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
sbc.data.logMonth = $ctrl.cbMonths.val();
|
||||
// Files.
|
||||
var items = response.files;
|
||||
sl.data.files = response.files;
|
||||
if (!(items || []).length)
|
||||
return $pnl.msgs.append($('<div class="sbc-message">' + sbc.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$pnl.list.append(sl.populateItem(sl.getFileTemplate(), items[itemIdx]));
|
||||
$pnl.list.fadeIn(50);
|
||||
}
|
||||
sl.populateItem = function ($item, item)
|
||||
{
|
||||
if (!item) return $item;
|
||||
$item.off('click').on('click', function () { sl.showFile(item.name) });
|
||||
$('.Filename', $item).text(item.name);
|
||||
$('.Updated', $item).text(item.updateFmt);
|
||||
$('.Size', $item).text(sbc.formatFileSize(item.size, 2));
|
||||
return $item;
|
||||
}
|
||||
sl.getFileTemplate = function ()
|
||||
{
|
||||
return $('.sbc-panel-item-template .sbc-panel-item.LogFile', $pnl.results).clone();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.showFile = function (filename, delay)
|
||||
{
|
||||
$('.FilterLogFilename', $frm.filter).val(filename);
|
||||
sl.setFileTitle(filename);
|
||||
if (!sl.data.awaitingGetFileResponse)
|
||||
{
|
||||
sl.setFileData($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>'));
|
||||
sl.openFileDlg();
|
||||
}
|
||||
sbc.ajax.getFile = sbc.ajax.getFile || { url: sbc.url.base + 'System/Ajax/Logs/GetFile', formSel: sl.$frm.filter, callbackFn: sl.onShowFile };
|
||||
sbc.doAjaxRequest(sbc.ajax.getFile, delay || 50);
|
||||
sl.data.awaitingGetFileResponse = true;
|
||||
}
|
||||
sl.onShowFile = function (response)
|
||||
{
|
||||
//sbc.debug('doGetFiles', response);
|
||||
delete sl.data.awaitingGetFileResponse;
|
||||
$pnl.msgs.hide().empty();
|
||||
if (!response.success) return;
|
||||
|
||||
// Configure file action buttons.
|
||||
let files = sl.data.files;
|
||||
let filename = response.file.name;
|
||||
$ctrl.filePrev.prop('disabled', (files || []).length < 2 || !filename || files[0].name == filename);
|
||||
$ctrl.fileNext.prop('disabled', (files || []).length < 2 || !filename || files[files.length - 1].name == filename);
|
||||
|
||||
// Display table details.
|
||||
sl.setFileTitle(filename || response.popupTitle);
|
||||
$('.LogFilename', $dlg.file).val(filename);
|
||||
sl.setFileData(response.file.html);
|
||||
sl.openFileDlg();
|
||||
}
|
||||
sl.openFileDlg = function ()
|
||||
{
|
||||
sbc.openDialog($dlg.file, $(win).width(), $(win).height());
|
||||
}
|
||||
sl.setFileTitle = function (filename)
|
||||
{
|
||||
$dlg.file.dialog('option', 'title', "File: " + filename);
|
||||
}
|
||||
sl.setFileData = function (data)
|
||||
{
|
||||
$('.FileData', $dlg.file).html(data);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sl.onCreateLogFileDlg = function ()
|
||||
{
|
||||
let $btnPane = $('#dlgLogFile + div.ui-dialog-buttonpane');
|
||||
$pnl.logFileActions = $('<div id="LogFileActions" style="float:left;">');
|
||||
$ctrl.filePrev = $('<button type="button" class="ui-button ui-corner-all ui-widget">').prop('value', 'LogFilePrev').text('Prev').on('click', sl.prevLogFile);
|
||||
$ctrl.fileNext = $('<button type="button" class="ui-button ui-corner-all ui-widget">').prop('value', 'LogFileNext').text('Next').on('click', sl.nextLogFile);
|
||||
$btnPane.append($pnl.logFileActions.append($ctrl.filePrev).append($ctrl.fileNext));
|
||||
}
|
||||
sl.prevLogFile = function ()
|
||||
{
|
||||
let files = sl.data.files;
|
||||
if ((files || []).length < 2) return;
|
||||
let filename = $('.LogFilename', $dlg.file).val();
|
||||
let filenamePrev = files[files.length - 1].name;
|
||||
for (let fileIdx = 0; fileIdx < files.length; fileIdx++)
|
||||
{
|
||||
let filenameNext = files[fileIdx].name;
|
||||
if (filenameNext == filename)
|
||||
{
|
||||
sl.showFile(filenamePrev);
|
||||
return;
|
||||
}
|
||||
filenamePrev = filenameNext;
|
||||
}
|
||||
}
|
||||
sl.nextLogFile = function ()
|
||||
{
|
||||
let files = sl.data.files;
|
||||
if ((files || []).length < 2) return;
|
||||
let filename = $('.LogFilename', $dlg.file).val();
|
||||
let filenameNext = files[0].name;
|
||||
for (let fileIdx = files.length - 1; fileIdx >= 0; fileIdx--)
|
||||
{
|
||||
let filenamePrev = files[fileIdx].name;
|
||||
if (filenamePrev == filename)
|
||||
{
|
||||
sl.showFile(filenameNext);
|
||||
return;
|
||||
}
|
||||
filenameNext = filenamePrev;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.logFiles = $('.LogFiles');
|
||||
$pnl.filter = $pnl.logFiles.find('.sbc-panel-filter');
|
||||
$pnl.results = $pnl.logFiles.find('.sbc-panel-results');
|
||||
$pnl.msgs = $pnl.results.find('.sbc-panel-messages')
|
||||
$pnl.list = $pnl.results.find('table.sbc-item-list')
|
||||
|
||||
$pnl.filter.on('click', '.sbc-action.sbc-results-refresh', function () { sl.refreshFiles(); });
|
||||
$('.sbc-input').on('input', function () { sbc.clearControlError(this); });
|
||||
|
||||
$frm.filter = $('#frmLogsFilter');
|
||||
$ctrl.cbFolders = $frm.filter.find('#cbFilterLogFolder').on('change', function () { sl.refreshYears(250); });
|
||||
$ctrl.cbYears = $frm.filter.find('#cbFilterLogYear').on('change', function () { sl.refreshMonths(250); });
|
||||
$ctrl.cbMonths = $frm.filter.find('#cbFilterLogMonth').on('change', function () { sl.refreshFiles(250); });
|
||||
|
||||
var opt = sbc.dlgOpts();
|
||||
opt.buttons[sbc.lbl.close] = function () { $(this).dialog('close'); sl.setFileData(); };
|
||||
opt.create = sl.onCreateLogFileDlg;
|
||||
$dlg.file = $('#dlgLogFile').dialog(opt);
|
||||
|
||||
setTimeout(sl.refreshFolders, 250);
|
||||
});
|
||||
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -4534,7 +4534,7 @@ input[type="button"].btn-block {
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 1.0)' stroke-width='4' stroke-linecap='round' stroke-miterlimit='10' d='M4 6h22M4 14h22M4 22h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-text {
|
||||
|
||||
@@ -280,7 +280,8 @@ namespace Sarand.BusinessMgr.Web.Portal.App
|
||||
{
|
||||
// New Session context.
|
||||
ushort sessionContextIdx = sessionContextIdx_Next++;
|
||||
sessionContextData = new SessionContextData_Control(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebPortal), owner.Id, repository.Id);
|
||||
bool demoRepository = repositoryContext.EqualsCI(Sbm.RepositoryContext_Demo);
|
||||
sessionContextData = new SessionContextData_Control(new SbmSessionContext_Web(sessionContextIdx, demoRepository ? Sbm.Application.WebDemo : 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}.");
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Components
|
||||
// Business components.
|
||||
// NB Keep these accessors protected to avoid them being called by the model binding logic before the session data is ready.
|
||||
protected SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(SessionData_Portal); return internals; } }
|
||||
public SbmInternals GetInternals() { return Internals; }
|
||||
// Managers.
|
||||
protected SbmAccountMgr AccountMgr { get { return Internals.AccountMgr; } }
|
||||
protected SbmCommodityMgr CommodityMgr { get { return Internals.CommodityMgr; } }
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
|
||||
}
|
||||
public Sbm.AffiliateType GetFilterContactType()
|
||||
{
|
||||
Sbm.AffiliateType affiliateType = (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Filter.ContactType);
|
||||
Sbm.AffiliateType affiliateType = (Sbm.AffiliateType)SbmSystem.GetSystemCodes(Sbm.SystemCode.AffiliateType).GetTypeForCode(Filter.ContactType);
|
||||
if (affiliateType == 0 && !StringUtil.IsBlank(Filter.ContactType) && StringUtil.IsNumeric(Filter.ContactType, true))
|
||||
affiliateType = (Sbm.AffiliateType)StringUtil.ToInt(Filter.ContactType);
|
||||
return affiliateType;
|
||||
|
||||
@@ -99,13 +99,13 @@ else
|
||||
|
||||
#tblWelcome tr th
|
||||
{
|
||||
padding: 4px 4px;
|
||||
padding: 6px 8px 4px 8px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#tblWelcome tr td
|
||||
{
|
||||
padding: 4px 4px;
|
||||
padding: 4px 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -120,30 +120,36 @@ else
|
||||
<th style="min-width:200px;">@Localiser["label.context"]</th>
|
||||
<th class="center" style="min-width:80px;">@Localiser["label.count"]</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Contacts')">
|
||||
<td class="">@Localiser["label.contacts"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Contacts')">@Model.GetContactCount()</td>
|
||||
<td class="center sbm-action-text">@Model.GetContactCount()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Customers')">
|
||||
<td class="">@Localiser["label.customers"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Customers')">@Model.GetCustomerCount()</td>
|
||||
<td class="center">@Model.GetCustomerCount()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Suppliers')">
|
||||
<td class="">@Localiser["label.suppliers"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Suppliers')">@Model.GetSupplierCount()</td>
|
||||
<td class="center">@Model.GetSupplierCount()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Commodity')">
|
||||
<td class="">@Localiser["label.commodities"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Commodity')">@Model.GetCommodityCount()</td>
|
||||
<td class="center">@Model.GetCommodityCount()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@if (Model.GetInternals().SessionConsole.AllowOption(Sbm.ConfigOption.Assets))
|
||||
{
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Assets/Asset')">
|
||||
<td class="">@Localiser["label.assets"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Assets/Asset')">@Model.GetAssetCount()</td>
|
||||
<td class="center">@Model.GetAssetCount()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
}
|
||||
@if (Model.GetInternals().SessionConsole.AllowOption(Sbm.ConfigOption.Vehicles))
|
||||
{
|
||||
<tr class="sbm-action-text" onclick="sbm.goToPage('Vehicles/Vehicle')">
|
||||
<td class="">@Localiser["label.vehicles"]</td>
|
||||
<td class="center sbm-action-text" onclick="sbm.goToPage('Vehicles/Vehicle')">@Model.GetVehicleCount()</td>
|
||||
<td class="center">@Model.GetVehicleCount()</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -109,9 +109,11 @@
|
||||
</button>
|
||||
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
||||
<ul class="navbar-nav flex-grow-1">
|
||||
@*
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">@Localiser["label.home"]</a>
|
||||
</li>
|
||||
*@
|
||||
@if (Model.AwaitingLogin)
|
||||
{
|
||||
<li class="nav-item">
|
||||
|
||||
@@ -4534,7 +4534,7 @@ input[type="button"].btn-block {
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 1.0)' stroke-width='4' stroke-linecap='round' stroke-miterlimit='10' d='M4 6h22M4 14h22M4 22h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-text {
|
||||
|
||||
Reference in New Issue
Block a user