From edd6e39c3554a793b845539527f5302093949f00 Mon Sep 17 00:00:00 2001 From: Andy Howard Date: Thu, 13 May 2021 19:36:30 +0100 Subject: [PATCH] v1.0.3.2 --- .../OrganisationController-Ajax.cs | 50 +- .../OrganisationController-Members-Ajax.cs | 20 +- .../Controllers/RegionController-Ajax.cs | 8 + .../Controllers/SecurityController-Ajax.cs | 15 +- .../Admin/Controllers/SecurityController.cs | 16 +- .../Admin/Controllers/SportController-Ajax.cs | 8 + .../Admin/Controllers/UserController-Ajax.cs | 149 ++- .../Admin/Models/Model_Organisation.cs | 8 +- .../Admin/Models/Model_OrganisationMembers.cs | 9 + .../Admin/Models/Model_Region.cs | 4 +- .../Admin/Models/Model_Sport.cs | 4 +- .../Admin/Models/Model_User.cs | 7 +- .../Localisation/SaxAdminProperties.resx | 24 + .../Views/Common/OrganisationSelection.cshtml | 2 +- ...CodeSelection.cshtml => SelectCode.cshtml} | 14 +- .../Views/Common/SelectItem.cshtml | 49 + .../Views/Organisation/Index.cshtml | 8 +- .../Organisation/Panel-MemberDialog.cshtml | 19 +- .../Panel-OrganisationDialog.cshtml | 43 +- .../Views/Region/Index.cshtml | 2 +- .../Views/Region/Panel-RegionDialog.cshtml | 11 + SaxoniteCoreWebAdmin/Views/Sport/Index.cshtml | 2 +- .../Views/Sport/Panel-SportDialog.cshtml | 11 + SaxoniteCoreWebAdmin/Views/User/Index.cshtml | 2 +- .../Views/User/Panel-UserDialog.cshtml | 13 +- ...x-codeSelection.css => sax-selectCode.css} | 4 +- .../wwwroot/css/sax-selectItem.css | 61 ++ .../wwwroot/js/sax-codeSelection.js | 83 -- SaxoniteCoreWebAdmin/wwwroot/js/sax-main.js | 11 + .../wwwroot/js/sax-organisation.js | 340 ++++--- .../wwwroot/js/sax-organisationMembers.js | 37 +- .../wwwroot/js/sax-organisationSelection.js | 14 +- SaxoniteCoreWebAdmin/wwwroot/js/sax-region.js | 260 +++--- .../wwwroot/js/sax-security.js | 153 +-- .../wwwroot/js/sax-selectCode.js | 119 +++ .../wwwroot/js/sax-selectItem.js | 124 +++ SaxoniteCoreWebAdmin/wwwroot/js/sax-sport.js | 254 ++--- SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js | 18 +- ...x.cs => AccountController-Ajax-Contact.cs} | 9 +- .../AccountController-Ajax-Organisations.cs | 89 ++ .../Controllers/SecurityController-Ajax.cs | 11 +- .../Online/Controllers/SecurityController.cs | 12 +- .../Account/Profile-Organisations.cshtml | 22 +- ...onSelection.cshtml => SelectRegion.cshtml} | 10 +- ...ortSelection.cshtml => SelectSport.cshtml} | 10 +- .../Journalist/Panel-ArticleDialog.cshtml | 4 +- .../wwwroot/css/sax-account.css | 13 +- .../wwwroot/css/sax-data.css | 28 +- .../wwwroot/css/sax-form.css | 16 +- ...gionSelection.css => sax-selectRegion.css} | 14 +- ...sportSelection.css => sax-selectSport.css} | 14 +- .../wwwroot/js/sax-account.js | 281 +++--- .../wwwroot/js/sax-journalist.js | 325 +++---- SaxoniteCoreWebOnline/wwwroot/js/sax-main.js | 870 +++++++++--------- .../wwwroot/js/sax-regionSelection.js | 132 --- .../wwwroot/js/sax-security.js | 153 +-- .../wwwroot/js/sax-selectRegion.js | 132 +++ ...x-sportSelection.js => sax-selectSport.js} | 20 +- SaxoniteStandardBase/Base/App/Sax-Version.cs | 7 +- .../Base/Bus/SaxOrganisation.cs | 45 + .../Base/Bus/SaxUserOrganisation.cs | 16 + .../Base/Mgr/SaxAccountMgr-Organisation.cs | 87 +- .../Mgr/SaxAccountMgr_Dbas-Organisation.cs | 78 ++ 63 files changed, 2694 insertions(+), 1680 deletions(-) rename SaxoniteCoreWebAdmin/Views/Common/{CodeSelection.cshtml => SelectCode.cshtml} (58%) create mode 100644 SaxoniteCoreWebAdmin/Views/Common/SelectItem.cshtml rename SaxoniteCoreWebAdmin/wwwroot/css/{sax-codeSelection.css => sax-selectCode.css} (86%) create mode 100644 SaxoniteCoreWebAdmin/wwwroot/css/sax-selectItem.css delete mode 100644 SaxoniteCoreWebAdmin/wwwroot/js/sax-codeSelection.js create mode 100644 SaxoniteCoreWebAdmin/wwwroot/js/sax-selectCode.js create mode 100644 SaxoniteCoreWebAdmin/wwwroot/js/sax-selectItem.js rename SaxoniteCoreWebOnline/Online/Controllers/{AccountController-Ajax.cs => AccountController-Ajax-Contact.cs} (95%) create mode 100644 SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Organisations.cs rename SaxoniteCoreWebOnline/Views/Common/{RegionSelection.cshtml => SelectRegion.cshtml} (73%) rename SaxoniteCoreWebOnline/Views/Common/{SportSelection.cshtml => SelectSport.cshtml} (74%) rename SaxoniteCoreWebOnline/wwwroot/css/{sax-regionSelection.css => sax-selectRegion.css} (69%) rename SaxoniteCoreWebOnline/wwwroot/css/{sax-sportSelection.css => sax-selectSport.css} (70%) delete mode 100644 SaxoniteCoreWebOnline/wwwroot/js/sax-regionSelection.js create mode 100644 SaxoniteCoreWebOnline/wwwroot/js/sax-selectRegion.js rename SaxoniteCoreWebOnline/wwwroot/js/{sax-sportSelection.js => sax-selectSport.js} (86%) diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Ajax.cs index 5abd481..0eb2f5f 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Ajax.cs @@ -30,6 +30,13 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers public String CategoryCode { get; set; } public String CategoryDesc { get; set; } public long MemberCount { get; set; } + // Region. + public long RegionId { get; set; } + public String RegionName { get; set; } + // Sport. + public long SportId { get; set; } + public String SportName { get; set; } + // Common properties. public String StatusCode { get; set; } public String StatusDesc { get; set; } } @@ -45,6 +52,21 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers data.CategoryCode = OrganisationCategories.GetCodeForType(organisation.OrganisationCategory); data.CategoryDesc = OrganisationCategories.GetDescForType(organisation.OrganisationCategory); data.MemberCount = AccountMgr.GetOrganisationMemberCount(organisation.Id); + // Region. + data.RegionId = SysId.ToLong(organisation.RegionIdPrimary); + using (SaxRegion region = ReferenceMgr.GetRegionById(organisation.RegionIdPrimary)) + { + if (region != null) + data.RegionName = region.Name; + } + // Sport. + data.SportId = SysId.ToLong(organisation.SportIdPrimary); + using (SaxSport region = ReferenceMgr.GetSportById(organisation.SportIdPrimary)) + { + if (region != null) + data.SportName = region.Name; + } + // Common properties. data.StatusCode = organisation.StatusCode; data.StatusDesc = organisation.StatusDesc; } @@ -59,6 +81,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers public class AjaxResponse_OrganisationList : AjaxResponse_Data { public List Organisations { get; } = new List(); + // Reference data. + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } } //------------------------------------------------------------------- [HttpPost] @@ -73,6 +98,11 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + // Reference data - statuses. + foreach (SaStatus status in SaxOrganisation.ValidStatuses.FindAll(item => item != SaStatus.Deleted)) + responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)); + responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxOrganisation.DefaultStatus); + // Item filter. SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params(); prmOrganisation.OrganisationFilter = model.Filter.Organisation; @@ -89,6 +119,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers ColumnDfn colPhoneAlt = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.PhoneAlt); ColumnDfn colUserCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.User_Count); ColumnDfn colMemberCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Member_Count); + ColumnDfn colRegionId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.RegionId); + ColumnDfn colRegionName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Region_Name); + ColumnDfn colSportId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.SportId); + ColumnDfn colSportName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Sport_Name); ColumnDfn colStatus = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Status); List columns = new List() { @@ -98,8 +132,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers colOrganisationCategory, colPhoneMain, colPhoneAlt, - colUserCount, - colMemberCount, + colUserCount, colMemberCount, + colRegionId, colRegionName, + colSportId, colSportName, colStatus }; @@ -120,6 +155,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers CategoryCode = values.GetString(colOrganisationCategory.DataName), CategoryDesc = OrganisationCategories.GetDescForCode(values.GetString(colOrganisationCategory.DataName)), MemberCount = StringUtil.ToLong(values.GetString(colMemberCount.DataName)), + RegionId = values.GetLong(colRegionId.DataName), + RegionName = values.GetString(colRegionName.DataName), + SportId = values.GetLong(colSportId.DataName), + SportName = values.GetString(colSportName.DataName), StatusCode = values.GetString(colStatus.DataName), StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)) }; @@ -216,8 +255,15 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers organisation.OrganisationType = model.OrganisationType; if (model.OrganisationCategoryValue != null) organisation.OrganisationCategory = model.OrganisationCategory; + if (model.OrganisationRegionId != null) + organisation.RegionIdPrimary = model.OrganisationRegionId.ToSysId(); + if (model.OrganisationSportId != null) + organisation.SportIdPrimary = model.OrganisationSportId.ToSysId(); + // Common properties. if (model.OrganisationStatusCode != null) organisation.Status = model.OrganisationStatus; + if (model.OrganisationNotes != null) + organisation.Notes = model.OrganisationNotes; // Store item. if (!SysId.IsValid(organisation.Id)) diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Members-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Members-Ajax.cs index 440163c..06facfc 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Members-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController-Members-Ajax.cs @@ -49,8 +49,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers foreach (Sax.OrganisationRole organisationRole in userOrganisation.OrganisationRoles.FindAll(item => item != Sax.OrganisationRole.Member)) data.RoleCodes.Add(OrganisationRoles.GetCodeForType(organisationRole)); data.RoleCount = userOrganisation.OrganisationRoles.Count - 1; - data.StatusCode = organisation.StatusCode; - data.StatusDesc = organisation.StatusDesc; + data.StatusCode = userOrganisation.StatusCode; + data.StatusDesc = userOrganisation.StatusDesc; } private void PopulateMemberResponseData(MemberData_Full data, SaxUserOrganisation userOrganisation, SaxUserAccount userAccount, SaxOrganisation organisation) { @@ -63,7 +63,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers public class AjaxResponse_MemberList : AjaxResponse_Data { public List Members { get; } = new List(); + // Reference data. public List MemberRoles { get; } = new List(); + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } } //------------------------------------------------------------------- [HttpPost] @@ -91,6 +94,11 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers foreach (TypeCodeDesc organisationRole in OrganisationRoles.FindAll(item => item.Type != (int)Sax.OrganisationRole.Member)) responseData.MemberRoles.Add(organisationRole.Code, Localiser.GetOrganisationRoleCaption((Sax.OrganisationRole)organisationRole.Type)); + // Reference data - statuses. + foreach (SaStatus status in SaxUserOrganisation.ValidStatuses.FindAll(item => item != SaStatus.Deleted)) + responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)); + responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxUserOrganisation.DefaultStatus); + // Item filter. SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params(); prmUserOrganisation.OrganisationIdsIncluded.Add(filterOrganisationId); @@ -277,7 +285,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers prmUserOrganisation.OrganisationMembersOnly = false; prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.Any; userOrganisation = AccountMgr.GetUserOrganisation(prmUserOrganisation); - if (userOrganisation == null) + if (userOrganisation != null) + userOrganisation.Status = SaStatus.Active; + else // Organisation not found for user. userOrganisation = AccountMgr.CreateUserOrganisation(userAccountId, organisationId); } @@ -293,8 +303,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers userOrganisation.OrganisationRoles = SaxUserOrganisation.GetOrganisationRolesFromCodes(model.GetMemberRoleCodes()); if (!userOrganisation.OrganisationRoles.Contains(Sax.OrganisationRole.Member)) userOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.Member); - - userOrganisation.Status = SaStatus.Active; + if (model.MemberStatusCode != null) + userOrganisation.Status = model.MemberStatus; // Store item. if (!SysId.IsValid(userOrganisation.Id)) diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/RegionController-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/RegionController-Ajax.cs index be82429..9fe9d7c 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/RegionController-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/RegionController-Ajax.cs @@ -53,6 +53,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers public class AjaxResponse_RegionList : AjaxResponse_Data { public List Regions { get; } = new List(); + // Reference data. + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } } //------------------------------------------------------------------- [HttpPost] @@ -67,6 +70,11 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + // Reference data - statuses. + foreach (SaStatus status in SaxRegion.ValidStatuses.FindAll(item => item != SaStatus.Deleted)) + responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)); + responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxRegion.DefaultStatus); + // Item filter. SaxRegion.Params prmRegion = new SaxRegion.Params(); prmRegion.RegionFilter = model.Filter.Region; diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController-Ajax.cs index 412e3c2..4d34b6c 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController-Ajax.cs @@ -133,7 +133,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers return userAccount; } - private void recordInvalidLoginAttempt (Model_Security model, SaxUserAccount userAccount) + private void recordInvalidLoginAttempt(Model_Security model, SaxUserAccount userAccount) { String fn = GetType().Name + ".recordInvalidLoginAttempt"; @@ -321,7 +321,13 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers // Retrieve user account. SaxUserAccount userAccount = AccountMgr.GetUserAccountByEmailAddress(model.EmailAddress); - if (userAccount != null && (userAccount.IsStatusActive || DebugMode)) + if (userAccount == null) + SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account does not exist"); + else if (!userAccount.IsStatusActive) + SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not active"); + else if (!AccountMgr.UserHasRole(userAccount.Id, Sax.UserRole.SystemAdmin)) + SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not 'Admin'"); + else { // Send password request email. SaEmailData emailData = new SaEmailData(); @@ -333,11 +339,6 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers SaLogger.Info(fn + " Password request email sent to " + model.EmailAddress, true); else SaLogger.Warn(fn + " Failed to send password request email to " + model.EmailAddress); } - else - { - if (userAccount == null) SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account does not exist"); - else if (!userAccount.IsStatusActive) SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not active"); - } // Construct response. responseData.Success = true; diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController.cs index 60124fa..ccd2bb3 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/SecurityController.cs @@ -77,12 +77,20 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers String logSuffix = requestPasswordParams.GetValidParams().Concat("", " ", "."); using (SaxUserAccount userAccount = AccountMgr.GetUserAccountById(requestPasswordParams.UserAccountId)) { - if (requestPasswordParams.IsValid(userAccount)) + if (userAccount.IsStatusActive) { - model.rpe = encryptedParams; - validSessionRequired = false; + if (AccountMgr.UserHasRole(userAccount.Id, Sax.UserRole.SystemAdmin)) + { + if (requestPasswordParams.IsValid(userAccount)) + { + model.rpe = encryptedParams; + validSessionRequired = false; + } + else SaLogger.Warn(fn + " 'Request Password' parameters supplied but invalid. " + logSuffix); + } + else SaLogger.Warn(fn + " 'Request Password' parameters supplied but account is not 'Admin'. " + logSuffix); } - else SaLogger.Warn(fn + " 'Request Password' parameters supplied but invalid. " + logSuffix); + else SaLogger.Warn(fn + " 'Request Password' parameters supplied but account is not active. " + logSuffix); } } } diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/SportController-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/SportController-Ajax.cs index cb8694d..02e5434 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/SportController-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/SportController-Ajax.cs @@ -46,6 +46,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers public class AjaxResponse_SportList : AjaxResponse_Data { public List Sports { get; } = new List(); + // Reference data. + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } } //------------------------------------------------------------------- [HttpPost] @@ -60,6 +63,11 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + // Reference data - statuses. + foreach (SaStatus status in SaxSport.ValidStatuses.FindAll(item => item != SaStatus.Deleted)) + responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)); + responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxSport.DefaultStatus); + // Item filter. SaxSport.Params prmSport = new SaxSport.Params(); prmSport.SportFilter = model.Filter.Sport; diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/UserController-Ajax.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/UserController-Ajax.cs index b2dbada..86f7484 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/UserController-Ajax.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/UserController-Ajax.cs @@ -59,20 +59,36 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers } } + //------------------------------------------------------------------- + // Utilities. + private List GetUserRoles(SysId userAccountId, SaxUserRole.StatusCat statusCat = SaxUserRole.StatusCat.NotDeleted) + { + if (!SysId.IsValid(userAccountId)) return new List(); + SaxUserRole.Params prmUserRole = new SaxUserRole.Params(); + prmUserRole.UserAccountIdsIncluded.Add(userAccountId); + prmUserRole.StatusCat = statusCat; + return AccountMgr.GetUserRoleList(prmUserRole); + } + //------------------------------------------------------------------- // Get User List ajax request. //------------------------------------------------------------------- public class AjaxResponse_UserList : AjaxResponse_Data { public List Users { get; } = new List(); + // Reference data. public List UserRoles { get; } = new List(); + public List Statuses { get; } = new List(); + public String DefaultStatusCode { get; set; } } //------------------------------------------------------------------- [HttpPost] [Route("User/Ajax/GetList")] - public IActionResult Ajax_GetList(Model_User model) + [Route("User/Ajax/GetUsers")] + [Route("User/Ajax/GetUserList")] + public IActionResult Ajax_GetUserList(Model_User model) { - String fn = GetType().Name + ".Ajax_GetList"; + String fn = GetType().Name + ".Ajax_GetUserList"; String messageTitle = Localiser["user.caption.users"]; AjaxResponse_UserList responseData = new AjaxResponse_UserList(); @@ -83,6 +99,11 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers // Reference data - user roles. foreach (TypeCodeDesc userRole in UserRoles) responseData.UserRoles.Add(userRole.Code, Localiser.GetUserRoleCaption((Sax.UserRole)userRole.Type)); + responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxUserAccount.DefaultStatus); + + // Reference data - statuses. + foreach (SaStatus status in SaxUserAccount.ValidStatuses.FindAll(item => item != SaStatus.Deleted)) + responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status)); // Item filter. SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params(); @@ -140,7 +161,6 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers // Complete response. responseData.SetPaging(model); responseData.Success = true; - return Json(responseData); } @@ -154,9 +174,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers //------------------------------------------------------------------- [HttpPost] [Route("User/Ajax/GetItem")] - public IActionResult Ajax_GetItem(Model_User model) + [Route("User/Ajax/GetUser")] + public IActionResult Ajax_GetUser(Model_User model) { - String fn = GetType().Name + ".Ajax_GetItem"; + String fn = GetType().Name + ".Ajax_GetUser"; String messageTitle = Localiser["user.caption.user"]; AjaxResponse_User responseData = new AjaxResponse_User(); @@ -176,25 +197,47 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } - // User's roles. - // Construct response. PopulateUserResponseData(responseData.user, user, GetUserRoles(user.Id).GetUserRolesByStatus(SaStatus.Active)); - - // Complete response. responseData.Success = true; - return Json(responseData); } //------------------------------------------------------------------- - private List GetUserRoles(SysId userAccountId, SaxUserRole.StatusCat statusCat = SaxUserRole.StatusCat.NotDeleted) + // Get User by email ajax request. + //------------------------------------------------------------------- + [HttpPost] + [Route("User/Ajax/GetUserByEmail")] + public IActionResult Ajax_GetUserByEmail(Model_User model) { - if (!SysId.IsValid(userAccountId)) return new List(); - SaxUserRole.Params prmUserRole = new SaxUserRole.Params(); - prmUserRole.UserAccountIdsIncluded.Add(userAccountId); - prmUserRole.StatusCat = statusCat; - return AccountMgr.GetUserRoleList(prmUserRole); + String fn = GetType().Name + ".Ajax_GetUserByEmail"; + String messageTitle = Localiser["user.caption.user"]; + AjaxResponse_User responseData = new AjaxResponse_User(); + StoreSessionData = false; + + // Validate session. + if (!ValidUserSession) + return GetAjaxResult_InvalidSession(responseData); + + // Identify user. + if (StringUtil.IsEmpty(model.UserEmailAddress)) + { + SaLogger.Warn(fn + " Attempt to get user details with blank email."); + return Json(responseData); + } + + // Retrieve user. + SaxUserAccount user = AccountMgr.GetUserAccountByEmailAddress(model.UserEmailAddress); + if (user == null) + { + SaLogger.Warn(fn + " Failed to retrieve user for Email: " + model.UserEmailAddress); + return Json(responseData); + } + + // Construct response. + PopulateUserResponseData(responseData.user, user, GetUserRoles(user.Id).GetUserRolesByStatus(SaStatus.Active)); + responseData.Success = true; + return Json(responseData); } //------------------------------------------------------------------- @@ -202,9 +245,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers //------------------------------------------------------------------- [HttpPost] [Route("User/Ajax/StoreItem")] - public IActionResult Ajax_StoreItem(Model_User model) + [Route("User/Ajax/StoreUser")] + public IActionResult Ajax_StoreUser(Model_User model) { - String fn = GetType().Name + ".Ajax_StoreItem"; + String fn = GetType().Name + ".Ajax_StoreUser"; String messageTitle = Localiser["user.caption.user"]; AjaxResponse_User responseData = new AjaxResponse_User(); @@ -225,27 +269,30 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } - // User roles, including deleted. - List userRoleCodes = model.GetUserRoleCodes(); + // User roles, including deleted in case of reassignment. List userRoles = new List(); if (user != null) userRoles = GetUserRoles(user.Id, SaxUserRole.StatusCat.Any); - foreach (String userRoleCode in userRoleCodes) + if (model.UserRoleCodes != null) { - // Role to activate. - Sax.UserRole role = (Sax.UserRole)UserRoles.GetTypeForCode(userRoleCode); - SaxUserRole userRole = userRoles.GetUserRoleByRole(role); - if (userRole == null) + List userRoleCodes = model.GetUserRoleCodes(); + foreach (String userRoleCode in userRoleCodes) { - userRole = AccountMgr.CreateUserRole(user?.Id, role); - userRoles.Add(userRole); + // Role to activate. + Sax.UserRole role = (Sax.UserRole)UserRoles.GetTypeForCode(userRoleCode); + SaxUserRole userRole = userRoles.GetUserRoleByRole(role); + if (userRole == null) + { + userRole = AccountMgr.CreateUserRole(user?.Id, role); + userRoles.Add(userRole); + } + userRole.Status = SaStatus.Active; + } + // Roles to deactivate. + foreach (SaxUserRole userRole in userRoles) + { + if (!userRoleCodes.Exists(item => item.EqualsCI(UserRoles.GetCodeForType(userRole.UserRole)))) + userRole.Status = SaStatus.Inactive; } - userRole.Status = SaStatus.Active; - } - // Roles to deactivate. - foreach (SaxUserRole userRole in userRoles) - { - if (!userRoleCodes.Exists(item => item.EqualsCI(UserRoles.GetCodeForType(userRole.UserRole)))) - userRole.Status = SaStatus.Inactive; } // Create new item if required. @@ -274,9 +321,6 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers SaLogger.Warn(fn + " Failed to insert user: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage)); } - // Apply User Account Id to dependent items. - foreach (SaxUserRole userRole in (userRoles)) - userRole.UserAccountId = user.Id; } else { @@ -287,28 +331,31 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers } } - // Associated data - User Roles. - foreach (SaxUserRole userRole in (userRoles)) + if (model.UserRoleCodes != null) { - // Store User Role. - if (!SysId.IsValid(userRole.Id)) + // Associated data - User Roles. + foreach (SaxUserRole userRole in (userRoles)) { - if (!AccountMgr.InsertUserRole(userRole, DbUpdateInfo)) - SaLogger.Warn(fn + " Failed to insert user role: " + AccountMgr.ErrorStateMessage); - } - else - { - if (!AccountMgr.UpdateUserRole(userRole, DbUpdateInfo)) - SaLogger.Warn(fn + " Failed to update user role [Id:" + SysId.ToString(userRole.Id) + "]: " + AccountMgr.ErrorStateMessage); + // Store User Role. + if (!SysId.IsValid(userRole.Id)) + { + // Apply User Account Id if not yet done (for new user). + if (!SysId.IsValid(userRole.UserAccountId)) + userRole.UserAccountId = user.Id; + if (!AccountMgr.InsertUserRole(userRole, DbUpdateInfo)) + SaLogger.Warn(fn + " Failed to insert user role: " + AccountMgr.ErrorStateMessage); + } + else + { + if (!AccountMgr.UpdateUserRole(userRole, DbUpdateInfo)) + SaLogger.Warn(fn + " Failed to update user role [Id:" + SysId.ToString(userRole.Id) + "]: " + AccountMgr.ErrorStateMessage); + } } } // Construct response. PopulateUserResponseData(responseData.user, user, userRoles.GetUserRolesByStatus(SaStatus.Active)); - - // Complete response. responseData.Success = true; - return Json(responseData); } diff --git a/SaxoniteCoreWebAdmin/Admin/Models/Model_Organisation.cs b/SaxoniteCoreWebAdmin/Admin/Models/Model_Organisation.cs index 589cdaf..580d5ab 100644 --- a/SaxoniteCoreWebAdmin/Admin/Models/Model_Organisation.cs +++ b/SaxoniteCoreWebAdmin/Admin/Models/Model_Organisation.cs @@ -52,6 +52,10 @@ namespace Saxonite.Net.Core.Web.Admin.Models public Sax.OrganisationType OrganisationType { get { return (Sax.OrganisationType)OrganisationTypes.GetTypeForCode(OrganisationTypeValue); } } public String OrganisationCategoryValue { get; set; } public Sax.OrganisationCategory OrganisationCategory { get { return (Sax.OrganisationCategory)OrganisationCategories.GetTypeForCode(OrganisationCategoryValue); } } + public String OrganisationRegionId { get; set; } + public String OrganisationSportId { get; set; } + // Common properties. + public String OrganisationNotes { get; set; } public String OrganisationStatusCode { get; set; } public SaStatus OrganisationStatus { get { return SacsSystem.GetStatusForCode(OrganisationStatusCode); } } @@ -89,9 +93,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models if (OrganisationStatusCode != null) { if (StringUtil.IsEmpty(OrganisationStatusCode)) - responseData.SetControlError(nameof(OrganisationStatusCode), Localiser["msg.validation.mandatory.value"]); + responseData.SetControlError(nameof(OrganisationStatus), Localiser["msg.validation.mandatory.value"]); else if (!SaxOrganisation.ValidStatuses.Contains(OrganisationStatus)) - responseData.SetControlError(nameof(OrganisationStatusCode), Localiser["msg.validation.invalid.value"]); + responseData.SetControlError(nameof(OrganisationStatus), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaxoniteCoreWebAdmin/Admin/Models/Model_OrganisationMembers.cs b/SaxoniteCoreWebAdmin/Admin/Models/Model_OrganisationMembers.cs index e46603a..9c6b570 100644 --- a/SaxoniteCoreWebAdmin/Admin/Models/Model_OrganisationMembers.cs +++ b/SaxoniteCoreWebAdmin/Admin/Models/Model_OrganisationMembers.cs @@ -91,6 +91,15 @@ namespace Saxonite.Net.Core.Web.Admin.Models // Roles can be left empty as the 'Member' role is automatically applied. } + // User Organisation status. + if (MemberStatusCode != null) + { + if (StringUtil.IsEmpty(MemberStatusCode)) + responseData.SetControlError(nameof(MemberStatus), Localiser["msg.validation.mandatory.value"]); + else if (!SaxOrganisation.ValidStatuses.Contains(MemberStatus)) + responseData.SetControlError(nameof(MemberStatus), Localiser["msg.validation.invalid.value"]); + } + return !responseData.HasControlErrors(); } diff --git a/SaxoniteCoreWebAdmin/Admin/Models/Model_Region.cs b/SaxoniteCoreWebAdmin/Admin/Models/Model_Region.cs index 411ef2f..817b4be 100644 --- a/SaxoniteCoreWebAdmin/Admin/Models/Model_Region.cs +++ b/SaxoniteCoreWebAdmin/Admin/Models/Model_Region.cs @@ -127,9 +127,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models if (RegionStatusCode != null) { if (StringUtil.IsEmpty(RegionStatusCode)) - responseData.SetControlError(nameof(RegionStatusCode), Localiser["msg.validation.mandatory.value"]); + responseData.SetControlError(nameof(RegionStatus), Localiser["msg.validation.mandatory.value"]); else if (!SaxRegion.ValidStatuses.Contains(RegionStatus)) - responseData.SetControlError(nameof(RegionStatusCode), Localiser["msg.validation.invalid.value"]); + responseData.SetControlError(nameof(RegionStatus), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaxoniteCoreWebAdmin/Admin/Models/Model_Sport.cs b/SaxoniteCoreWebAdmin/Admin/Models/Model_Sport.cs index b539a0f..7772eea 100644 --- a/SaxoniteCoreWebAdmin/Admin/Models/Model_Sport.cs +++ b/SaxoniteCoreWebAdmin/Admin/Models/Model_Sport.cs @@ -77,9 +77,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models if (SportStatusCode != null) { if (StringUtil.IsEmpty(SportStatusCode)) - responseData.SetControlError(nameof(SportStatusCode), Localiser["msg.validation.mandatory.value"]); + responseData.SetControlError(nameof(SportStatus), Localiser["msg.validation.mandatory.value"]); else if (!SaxSport.ValidStatuses.Contains(SportStatus)) - responseData.SetControlError(nameof(SportStatusCode), Localiser["msg.validation.invalid.value"]); + responseData.SetControlError(nameof(SportStatus), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaxoniteCoreWebAdmin/Admin/Models/Model_User.cs b/SaxoniteCoreWebAdmin/Admin/Models/Model_User.cs index d465d78..b020874 100644 --- a/SaxoniteCoreWebAdmin/Admin/Models/Model_User.cs +++ b/SaxoniteCoreWebAdmin/Admin/Models/Model_User.cs @@ -54,7 +54,10 @@ namespace Saxonite.Net.Core.Web.Admin.Models { List codes = new List(); foreach (String code in UserRoleCodes) + { + if (StringUtil.IsEmpty(code)) continue; codes.AddRange(code.Split(UserRoleCodeDelim)); + } return codes; } public String UserStatusCode { get; set; } @@ -119,9 +122,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models if (UserStatusCode != null) { if (StringUtil.IsEmpty(UserStatusCode)) - responseData.SetControlError(nameof(UserStatusCode), Localiser["msg.validation.mandatory.value"]); + responseData.SetControlError(nameof(UserStatus), Localiser["msg.validation.mandatory.value"]); else if (!SaxUserAccount.ValidStatuses.Contains(UserStatus)) - responseData.SetControlError(nameof(UserStatusCode), Localiser["msg.validation.invalid.value"]); + responseData.SetControlError(nameof(UserStatus), Localiser["msg.validation.invalid.value"]); } return !responseData.HasControlErrors(); diff --git a/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx b/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx index 2c4d709..e29de10 100644 --- a/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx +++ b/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx @@ -177,6 +177,12 @@ ISO2 code + + Selected item + + + Available items + Keep me signed-in @@ -210,12 +216,18 @@ Refresh + + Region + Remove Roles + + Search + Security @@ -228,6 +240,12 @@ none selected + + Sport + + + Status + Strength @@ -336,6 +354,9 @@ Create Region + + Select Region + Update Region @@ -384,6 +405,9 @@ Create Sport + + Select Sport + Update Sport diff --git a/SaxoniteCoreWebAdmin/Views/Common/OrganisationSelection.cshtml b/SaxoniteCoreWebAdmin/Views/Common/OrganisationSelection.cshtml index 756186c..1233f12 100644 --- a/SaxoniteCoreWebAdmin/Views/Common/OrganisationSelection.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Common/OrganisationSelection.cshtml @@ -18,7 +18,7 @@ {
@Localiser["organisation.caption.organisation"]
-
+
} diff --git a/SaxoniteCoreWebAdmin/Views/Common/CodeSelection.cshtml b/SaxoniteCoreWebAdmin/Views/Common/SelectCode.cshtml similarity index 58% rename from SaxoniteCoreWebAdmin/Views/Common/CodeSelection.cshtml rename to SaxoniteCoreWebAdmin/Views/Common/SelectCode.cshtml index 6cd890f..fe3f9f2 100644 --- a/SaxoniteCoreWebAdmin/Views/Common/CodeSelection.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Common/SelectCode.cshtml @@ -1,12 +1,12 @@ @model SaxModel_Admin @inject SaxLocaliser Localiser - - + + -
+
@* Filter *@
@@ -18,7 +18,7 @@ @* Available codes *@
-
+
@@ -30,11 +30,11 @@
- +
- +
@@ -44,7 +44,7 @@ @* Selected codes *@
-
+
diff --git a/SaxoniteCoreWebAdmin/Views/Common/SelectItem.cshtml b/SaxoniteCoreWebAdmin/Views/Common/SelectItem.cshtml new file mode 100644 index 0000000..41188ad --- /dev/null +++ b/SaxoniteCoreWebAdmin/Views/Common/SelectItem.cshtml @@ -0,0 +1,49 @@ +@model SaxModel_Admin +@inject SaxLocaliser Localiser + + + +
+ +
+ + @* Selected Item *@ +
+
+
@Localiser["label.item.selected"]:
+
+
+
+
+ + @* Item Filter *@ +
+
+
@Localiser["label.search"]
+
+
+
+
+ + @* Available items *@ +
+
@Localiser["label.items.available"]:
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+ + + +
diff --git a/SaxoniteCoreWebAdmin/Views/Organisation/Index.cshtml b/SaxoniteCoreWebAdmin/Views/Organisation/Index.cshtml index a16792a..40ba1e1 100644 --- a/SaxoniteCoreWebAdmin/Views/Organisation/Index.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Organisation/Index.cshtml @@ -19,7 +19,7 @@ {
@Localiser["organisation.caption.organisation"]
-
@Html.TextBoxFor(model => model.Filter.Organisation, new { @id = "ifFilterOrganisation", @class = "FilterOrganisation", @maxlength = "32", @onkeypress = "sax.refreshResults(250)" })
+
@Html.TextBoxFor(model => model.Filter.Organisation, new { @id = "ifFilterOrganisation", @class = "FilterOrganisation", @maxlength = "32" })
}
@@ -39,12 +39,12 @@
-
+
+
@Localiser["label.members"]: 
-
-
+
diff --git a/SaxoniteCoreWebAdmin/Views/Organisation/Panel-MemberDialog.cshtml b/SaxoniteCoreWebAdmin/Views/Organisation/Panel-MemberDialog.cshtml index 1e38f5f..b92a034 100644 --- a/SaxoniteCoreWebAdmin/Views/Organisation/Panel-MemberDialog.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Organisation/Panel-MemberDialog.cshtml @@ -12,10 +12,14 @@ sax.dlg.title.selectMemberRoles = '@Localiser.GetJavascriptText("organisation.caption.select.member.roles")'; sax.data.userRoleCodeDelim = '@Model.MemberRoleCodeDelim'; -@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmMemberId", @class = "sax-form" })) +@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmMemberId" })) { @Html.HiddenFor(model => model.UserOrganisationId, new { @id = "", @class = "UserOrganisationId" }) } +@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserEmail"})) +{ + +}
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmMember", @class = "sax-form", @onSubmit = "return false;" })) @@ -58,8 +62,19 @@
+ @* Member status *@ +
+
+ +
+
+ +
+
+
+ } - +
diff --git a/SaxoniteCoreWebAdmin/Views/Organisation/Panel-OrganisationDialog.cshtml b/SaxoniteCoreWebAdmin/Views/Organisation/Panel-OrganisationDialog.cshtml index a920989..5682e58 100644 --- a/SaxoniteCoreWebAdmin/Views/Organisation/Panel-OrganisationDialog.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Organisation/Panel-OrganisationDialog.cshtml @@ -7,6 +7,8 @@ @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrganisationId", @class = "sax-form" })) { @@ -16,7 +18,7 @@ @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrganisation", @class = "sax-form", @onSubmit = "return false;" })) { - @Html.HiddenFor(model => model.OrganisationId, new { @id="", @class = "OrganisationId" }) + @Html.HiddenFor(model => model.OrganisationId, new { @id = "", @class = "OrganisationId" }) @* Organisation name *@
@@ -51,8 +53,45 @@
- @* Organisation country *@ + @* Organisation region *@ +
+
+ +
+
+ @Html.HiddenFor(model => model.OrganisationRegionId, new { @id = "ifOrganisationRegionId", @class = "OrganisationRegionId" }) +
+
+
+
+
+ + @* Organisation sport *@ +
+
+ +
+
+ @Html.HiddenFor(model => model.OrganisationSportId, new { @id = "ifOrganisationSportId", @class = "OrganisationSportId" }) +
+
+
+
+
+ + @* Organisation status *@ +
+
+ +
+
+ +
+
+
} + +
diff --git a/SaxoniteCoreWebAdmin/Views/Region/Index.cshtml b/SaxoniteCoreWebAdmin/Views/Region/Index.cshtml index 9566fdd..a178a57 100644 --- a/SaxoniteCoreWebAdmin/Views/Region/Index.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Region/Index.cshtml @@ -19,7 +19,7 @@ {
@Localiser["region.caption.region"]
-
@Html.TextBoxFor(model => model.Filter.Region, new { @id = "ifFilterRegion", @class = "FilterRegion", @maxlength = "32", @onkeypress = "sax.refreshResults(250)" })
+
@Html.TextBoxFor(model => model.Filter.Region, new { @id = "ifFilterRegion", @class = "FilterRegion", @maxlength = "32" })
}
diff --git a/SaxoniteCoreWebAdmin/Views/Region/Panel-RegionDialog.cshtml b/SaxoniteCoreWebAdmin/Views/Region/Panel-RegionDialog.cshtml index 62c8674..e1a8007 100644 --- a/SaxoniteCoreWebAdmin/Views/Region/Panel-RegionDialog.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Region/Panel-RegionDialog.cshtml @@ -51,6 +51,17 @@
+ @* Region status *@ +
+
+ +
+
+ +
+
+
+ } diff --git a/SaxoniteCoreWebAdmin/Views/Sport/Index.cshtml b/SaxoniteCoreWebAdmin/Views/Sport/Index.cshtml index 233e163..52c7559 100644 --- a/SaxoniteCoreWebAdmin/Views/Sport/Index.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Sport/Index.cshtml @@ -19,7 +19,7 @@ {
@Localiser["sport.caption.sport"]
-
@Html.TextBoxFor(model => model.Filter.Sport, new { @id = "ifFilterSport", @class = "FilterSport", @maxlength = "32", @onkeypress = "sax.refreshResults(250)" })
+
@Html.TextBoxFor(model => model.Filter.Sport, new { @id = "ifFilterSport", @class = "FilterSport", @maxlength = "32" })
} diff --git a/SaxoniteCoreWebAdmin/Views/Sport/Panel-SportDialog.cshtml b/SaxoniteCoreWebAdmin/Views/Sport/Panel-SportDialog.cshtml index 8c1e914..e69a168 100644 --- a/SaxoniteCoreWebAdmin/Views/Sport/Panel-SportDialog.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Sport/Panel-SportDialog.cshtml @@ -29,6 +29,17 @@
+ @* Sport status *@ +
+
+ +
+
+ +
+
+
+ } diff --git a/SaxoniteCoreWebAdmin/Views/User/Index.cshtml b/SaxoniteCoreWebAdmin/Views/User/Index.cshtml index 462f26a..72c08f9 100644 --- a/SaxoniteCoreWebAdmin/Views/User/Index.cshtml +++ b/SaxoniteCoreWebAdmin/Views/User/Index.cshtml @@ -19,7 +19,7 @@ {
@Localiser["user.caption.user"]
-
@Html.TextBoxFor(model => model.Filter.User, new { @id = "ifFilterUser", @class = "FilterUser", @maxlength = "32", @onkeypress = "sax.refreshResults(250)" })
+
@Html.TextBoxFor(model => model.Filter.User, new { @id = "ifFilterUser", @class = "FilterUser", @maxlength = "32" })
} diff --git a/SaxoniteCoreWebAdmin/Views/User/Panel-UserDialog.cshtml b/SaxoniteCoreWebAdmin/Views/User/Panel-UserDialog.cshtml index ba4914f..f75ef22 100644 --- a/SaxoniteCoreWebAdmin/Views/User/Panel-UserDialog.cshtml +++ b/SaxoniteCoreWebAdmin/Views/User/Panel-UserDialog.cshtml @@ -76,8 +76,19 @@
+ @* User status *@ +
+
+ +
+
+ +
+
+
+ } - + diff --git a/SaxoniteCoreWebAdmin/wwwroot/css/sax-codeSelection.css b/SaxoniteCoreWebAdmin/wwwroot/css/sax-selectCode.css similarity index 86% rename from SaxoniteCoreWebAdmin/wwwroot/css/sax-codeSelection.css rename to SaxoniteCoreWebAdmin/wwwroot/css/sax-selectCode.css index ab980d4..8c357d0 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/css/sax-codeSelection.css +++ b/SaxoniteCoreWebAdmin/wwwroot/css/sax-selectCode.css @@ -4,7 +4,7 @@ /* Panels */ -.sax-codeSelection-codes +.sax-selectCode-codes { padding:2px 0; background-color:#f0f0f0; @@ -12,7 +12,7 @@ border-radius: 6px; } -#dlgCodeSelection.sax-form button.sax-button +#dlgSelectCode.sax-form button.sax-button { margin: 4px 0; } diff --git a/SaxoniteCoreWebAdmin/wwwroot/css/sax-selectItem.css b/SaxoniteCoreWebAdmin/wwwroot/css/sax-selectItem.css new file mode 100644 index 0000000..5251ea0 --- /dev/null +++ b/SaxoniteCoreWebAdmin/wwwroot/css/sax-selectItem.css @@ -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 .sax-label +{ + margin-right: 6px; +} + +#dlgSelectItem .sax-button +{ + padding: 2px 8px; + border-radius: 6px; +} + +#dlgSelectItem .sax-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.sax-form button.sax-button +{ + margin: 4px 0; +} + +#dlgSelectItem .sax-panel-item.Item +{ + margin: 2px 4px; + padding: 2px 4px; + background-color: #fff; + border: 2px solid #d8d8ff; + border-radius: 4px; + cursor: pointer; +} + +#dlgSelectItem .sax-panel-item.Item.sel +{ + background-color: #ececff; + border-color: #8a8aff; +} + +/* The End */ diff --git a/SaxoniteCoreWebAdmin/wwwroot/js/sax-codeSelection.js b/SaxoniteCoreWebAdmin/wwwroot/js/sax-codeSelection.js deleted file mode 100644 index f83a75c..0000000 --- a/SaxoniteCoreWebAdmin/wwwroot/js/sax-codeSelection.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Admin - User page scripts. - */ - -(function (win, doc, undef) -{ - "use strict"; - let cs = sax.codeSelection = sax.codeSelection || { fn: {}, $dlg: {}, codeIdPrefix: 'Code_' }; - - //-------------------------------------------------------------- - /* - * Code selection config: - * - caption - dialog title. - * - width: preferred dialog width (default: 400). - * - height: preferred dialog height (default: 400). - * - showFilter: whether to display filter control(s). - * - filterLabel: filter code field caption. - * - maxItems: maximum number of available items to list. - * - codes - list of {code,desc,comment} objects - * - selectedCodes - list of codes. - * - fnCallback - method to call on completion to store codes taking list of selected codes as parameter. - */ - cs.fn.openCodeSelection = function (cfg) - { - sax.debug('openCodeSelection', cfg); - cs.fn.init(); - cs.cfg = cfg; - cs.selectedCodes = cfg.selectedCodes || []; - cs.fn.displayCodes(cfg.codes); - sax.openDialog(cs.$dlg.dialog('option', { title: cfg.caption || 'Select Codes' }), cs.cfg.width || 400, cs.cfg.height || 400); - } - cs.fn.displayCodes = function (codes) - { - let $codesAvail = $('.sax-codeSelection-codes.AvailableCodes').empty(); - let $codesSelec = $('.sax-codeSelection-codes.SelectedCodes').empty(); - let $codeTmpl = $('.sax-panel-item-template .sax-panel-item.Code'); - for (let codeIdx = 0; codeIdx < codes.length; codeIdx++) - { - let code = codes[codeIdx]; - let selected = cs.selectedCodes.indexOf(code.code) >= 0; - let $code = $codeTmpl.clone(); - $($code).prop('id', cs.codeIdPrefix + code.code).attr('aria-code', code.code).on('click', function () { cs.fn.onClickCode(code.code); }).on('dblclick', function () { cs.fn.onDblClickCode(code.code); }).find('.CodeDesc').text(code.desc).end(); - if (selected) $codesSelec.append($code); - else $codesAvail.append($code); - } - } - cs.fn.onClickCode = function (code) - { - $('.sax-panel-item.Code').removeClass('sel'); - $('.sax-panel-item.Code[aria-code="' + code + '"]').addClass('sel'); - } - cs.fn.onDblClickCode = function (code) - { - let codeIdx = cs.selectedCodes.indexOf(code); - //sax.debug('onDblClickCode', code, codeIdx); - if (codeIdx >= 0) cs.selectedCodes.splice(codeIdx, 1); else cs.selectedCodes.push(code) - cs.fn.displayCodes(cs.cfg.codes) - $('.sax-panel-item.Code[aria-code="' + code + '"]').addClass('sel'); - } - cs.fn.storeCodeSelection = function () - { - //sax.debug('storeCodeSelection', cs.cfg, cs.selectedCodes); - - if (cs.cfg.fnCallback) cs.cfg.fnCallback(cs.selectedCodes); - - cs.$dlg.dialog('close'); - delete cs.cfg; - delete cs.selectedCodes; - } - - //-------------------------------------------------------------- - cs.fn.init = function () - { - if (!cs.$dlg) return; - var opt = sax.dlgOpts(); - opt.buttons[sax.dlg.btn.ok] = function () { cs.fn.storeCodeSelection(); }; - opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); }; - cs.$dlg = $('#dlgCodeSelection').dialog(opt); - } - -}(window, window.document)); - -/* The End */ \ No newline at end of file diff --git a/SaxoniteCoreWebAdmin/wwwroot/js/sax-main.js b/SaxoniteCoreWebAdmin/wwwroot/js/sax-main.js index e803240..ea735c7 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/js/sax-main.js +++ b/SaxoniteCoreWebAdmin/wwwroot/js/sax-main.js @@ -31,6 +31,10 @@ { return sax.isNumeric(value) ? parseInt(value, 10) : defaultValue || 0; } + sax.escapeRegExp = function (val) + { + return (val || '').replace(/[[{}()*+?^$|\]\.\\]/g, "\\$&"); + } sax.debug = sax.debugMode ? win.console.log.bind(win.console) : function () { }; //-------------------------------------------------------------- @@ -56,6 +60,12 @@ return index % 2 == 1 ? "other" : ""; }); } + sax.populateSelectCodeDesc = function ($sel, values) + { + $sel = $($sel).empty(); + for (const value of values) + $sel.append($('