From 7417981a349b8c12b54d700beb16bc32fc445b63 Mon Sep 17 00:00:00 2001 From: Andy Howard Date: Thu, 14 Oct 2021 21:08:07 +0100 Subject: [PATCH] v1.1.7 --- .../Base/Consoles/SaxDataCacheConsole_Web.cs | 33 +++ SaxoniteCoreWeb/Base/Models/SaxModel_Base.cs | 186 +++++++++-------- .../HomeController-Ajax-AwaitingActivation.cs | 116 +++++++++++ .../Admin/Controllers/HomeController.cs | 2 +- .../Controllers/OrganisationController.cs | 6 +- .../Localisation/SaxAdminProperties.resx | 9 + SaxoniteCoreWebAdmin/Views/Home/Index.cshtml | 27 +++ SaxoniteCoreWebAdmin/wwwroot/css/sax-form.css | 2 +- SaxoniteCoreWebAdmin/wwwroot/css/sax-main.css | 2 +- SaxoniteCoreWebAdmin/wwwroot/js/sax-home.js | 73 +++++-- SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js | 2 +- .../Localisation/SaxOnlineProperties.resx | 9 + .../AccountController-Ajax-Contact.cs | 14 +- .../AccountController-Ajax-Sports.cs | 20 +- ...ountController-Ajax-UserSportExperience.cs | 4 +- .../Controllers/ArticleController-Ajax.cs | 4 +- ...ganisationController-Ajax-Opportunities.cs | 8 +- .../SearchController-Ajax-Organisations.cs | 195 ++++++++++++++++++ .../Online/Controllers/SearchController.cs | 63 ++++++ .../Online/Models/Model_Account.cs | 16 +- .../Models/Model_Search_Organisations.cs | 57 +++++ .../Online/Models/SaxModel_Online.cs | 20 +- .../Account/Profile-SportExperiences.cshtml | 1 + .../Views/Account/Profile-Sports.cshtml | 77 +++++-- .../Views/Common/RegionSelect.cshtml | 3 +- .../Views/Common/ResultsPaging.cshtml | 2 +- .../Views/Common/SportSelect.cshtml | 3 +- .../Views/Search/Organisations.cshtml | 163 +++++++++++++++ .../Search/Panel-OrganisationDialog.cshtml | 22 ++ .../Views/Shared/_Layout.cshtml | 11 +- .../wwwroot/css/sax-data.css | 7 +- .../wwwroot/css/sax-form.css | 12 +- .../wwwroot/css/sax-main.css | 2 +- SaxoniteCoreWebOnline/wwwroot/js/sax-art.js | 6 +- SaxoniteCoreWebOnline/wwwroot/js/sax-main.js | 4 +- .../wwwroot/js/sax-org-mbr.js | 10 +- .../wwwroot/js/sax-org-opp.js | 24 +-- .../wwwroot/js/sax-org-req.js | 4 +- .../wwwroot/js/sax-reg-sel.js | 20 +- .../wwwroot/js/sax-resultsPaging.js | 86 +++++--- .../wwwroot/js/sax-spt-sel.js | 17 +- .../wwwroot/js/sax-src-org.js | 175 ++++++++++++++++ .../wwwroot/js/sax-usr-pro.js | 87 ++++---- .../wwwroot/js/sax-usr-spt.js | 67 +++--- SaxoniteStandardBase/Base/App/Sax-Version.cs | 14 +- SaxoniteStandardBase/Base/App/SaxInternals.cs | 1 + .../Base/Bus/SaxOrganisation.cs | 10 + SaxoniteStandardBase/Base/Bus/SaxUserSport.cs | 16 +- .../Base/Consoles/SaxDataCacheConsole.cs | 24 ++- .../Base/Mgr/SaxAccountMgr-UserSport.cs | 6 + .../Dbas/Mgr/SaxAccountMgr_Dbas-UserSport.cs | 2 + 51 files changed, 1418 insertions(+), 326 deletions(-) create mode 100644 SaxoniteCoreWebAdmin/Admin/Controllers/HomeController-Ajax-AwaitingActivation.cs create mode 100644 SaxoniteCoreWebOnline/Online/Controllers/SearchController-Ajax-Organisations.cs create mode 100644 SaxoniteCoreWebOnline/Online/Controllers/SearchController.cs create mode 100644 SaxoniteCoreWebOnline/Online/Models/Model_Search_Organisations.cs create mode 100644 SaxoniteCoreWebOnline/Views/Search/Organisations.cshtml create mode 100644 SaxoniteCoreWebOnline/Views/Search/Panel-OrganisationDialog.cshtml create mode 100644 SaxoniteCoreWebOnline/wwwroot/js/sax-src-org.js diff --git a/SaxoniteCoreWeb/Base/Consoles/SaxDataCacheConsole_Web.cs b/SaxoniteCoreWeb/Base/Consoles/SaxDataCacheConsole_Web.cs index 3a5fddf..acd2516 100644 --- a/SaxoniteCoreWeb/Base/Consoles/SaxDataCacheConsole_Web.cs +++ b/SaxoniteCoreWeb/Base/Consoles/SaxDataCacheConsole_Web.cs @@ -19,6 +19,7 @@ namespace Saxonite.Net.Core.Web.Base.Consoles private class DataMembers { public SaxInternals internals; + public Dictionary> encryptedIdCache = new Dictionary>(); } private DataMembers data = new DataMembers(); @@ -59,6 +60,38 @@ namespace Saxonite.Net.Core.Web.Base.Consoles internals.PopulateSportCache(activeSportDataList); } + /// + /// Encrypted Ids are stored in cache to ensure that they are consistent throughout a user's session + /// by persisting them through the life of the cache (application restart). + /// Required as the encrypted values are compared in javascript. + /// Candidate encrypted value supplied by calling routine as cache doesn't know how to encrypt - used if Id not previously encrypted. + /// + public override String GetEncryptedId(Sax.DataItemType itemType, SysId id, String candidateValue) + { + // Invalid Id always has a blank encrypted value. + if (!SysId.IsValid(id)) return ""; + + // Only Regions and Sports are supported. + if (!(new List() { Sax.DataItemType.Sport, Sax.DataItemType.Region }).Contains(itemType)) + return candidateValue; + + Dictionary itemIds = data.encryptedIdCache.GetValue(itemType, null); + if (itemIds == null) + { + // Add cache entry for this item type. + itemIds = new Dictionary(); + data.encryptedIdCache.Add(itemType, itemIds); + } + String encryptedId = itemIds.GetValue(id, null); + if (encryptedId == null && !StringUtil.IsEmpty(candidateValue)) + { + // Use the candidate value and store it. + encryptedId = candidateValue; + itemIds.Add(id, encryptedId); + } + return encryptedId; + } + //------------------------------------------------------------------- // Regions. public bool RegionsSupported { get; protected set; } = false; diff --git a/SaxoniteCoreWeb/Base/Models/SaxModel_Base.cs b/SaxoniteCoreWeb/Base/Models/SaxModel_Base.cs index a2b2981..ee260f5 100644 --- a/SaxoniteCoreWeb/Base/Models/SaxModel_Base.cs +++ b/SaxoniteCoreWeb/Base/Models/SaxModel_Base.cs @@ -71,6 +71,7 @@ namespace Saxonite.Net.Core.Web.Base.Models protected SaxItemDataMgr ItemDataMgr { get { return Internals.ItemDataMgr; } } // System codes. public List DataItemTypeCodes { get { return Internals.DataItemTypeCodes; } } + public List YesNoCodes { get { return Internals.YesNoCodes; } } public List SportSpecialityLabelCodes { get { return Internals.SportSpecialityLabelCodes; } } public List SportParticipationCodes { get { return Internals.SportParticipationCodes; } } public List SportOfficiatingCodes { get { return Internals.SportOfficiatingCodes; } } @@ -127,6 +128,88 @@ namespace Saxonite.Net.Core.Web.Base.Models return new SelectList(items, "Code", "Desc"); } + //------------------------------------------------------------------- + // Version parameter for includes. + public String HrefVersion + { + get + { + DateTime versionDate = SaxSystem.AssemblyBuildAt; + if (!DateUtil.IsValid(versionDate) || SaxSystem.DebugMode) + versionDate = DateTime.Now; + return DateUtil.Format(versionDate, "yyyyMMdd" /*+ (SacsSystem.Debug ? "HHmm" : "")*/); + } + } + // Additional includes. + public List AdditionalFiles_CSS { get; set; } = new List(); + public List AdditionalFiles_JS { get; set; } = new List(); + + //------------------------------------------------------------------- + // Redirection locations. + public class RedirectLocationData + { + // Properties populated in Controller_Base.OnActionExecuted. + public String Base { get; internal set; } + public String Home { get; internal set; } + public String Home_SessionExpired { get; internal set; } + } + public RedirectLocationData RedirectLocation { get; } = new RedirectLocationData(); + + //------------------------------------------------------------------- + // Link URLs. + public class LinksData + { + public String Facebook { get; } = "https://www.facebook.com/sportierre/"; + public String LinkedIn { get; } = "https://www.linkedin.com/company/sportierre/about/"; + } + public LinksData Links { get; } = new LinksData(); + + //------------------------------------------------------------------- + // Copyright notice. + public HtmlString CopyrightNotice + { + get + { + int initialYear = 2020; + int currentYear = DateTime.Today.Year; + return Localiser.GetHtmlText("copyright.symbol.year.html", (initialYear != currentYear ? initialYear + "-" : "") + currentYear.ToString()); + } + } + + //------------------------------------------------------------------- + // Paging properties. + public class DataPaging + { + private DbQuery.Paging paging { get; } = new DbQuery.Paging(); + public void PopulatePagingTo(DbQuery.Paging resultsPaging) + { + resultsPaging.PageLength = paging.PageLength; + resultsPaging.PageNo = paging.PageNo; + } + public bool IsPaged { get { return paging.Paged; } } + public uint PageNo { get { return paging.PageNo; } set { paging.PageNo = value; } } + public ushort PageLength { get { return paging.PageLength; } set { paging.PageLength = value; } } + public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } } + public ushort ItemCount { get; set; } + private ulong itemTotal = 0; + public ulong ItemTotal + { + get { return itemTotal; } + set + { + itemTotal = value; + // Check whether the total number of items is less than the current page and reduce page no if needed. + if (IsPaged && (PageNo - 1) * PageLength > itemTotal) + PageNo = (uint)((itemTotal - 1) / PageLength + 1); + } + } + } + public DataPaging Paging { get; } = new DataPaging(); + public void PopulatePagingTo(DbQuery.Paging resultsPaging) + { + Paging.PopulatePagingTo(resultsPaging); + } + //------------------------------------------------------------------- /// /// Form control value max length. @@ -157,18 +240,6 @@ namespace Saxonite.Net.Core.Web.Base.Models return maxLength; } - //------------------------------------------------------------------- - // Copyright notice. - public HtmlString CopyrightNotice - { - get - { - int initialYear = 2020; - int currentYear = DateTime.Today.Year; - return Localiser.GetHtmlText("copyright.symbol.year.html", (initialYear != currentYear ? initialYear + "-" : "") + currentYear.ToString()); - } - } - //------------------------------------------------------------------- // Form data - Dates. // Format may depend on locale, but as long as these methods are used consistently, @@ -205,20 +276,22 @@ namespace Saxonite.Net.Core.Web.Base.Models } //------------------------------------------------------------------- - // Link URLs. - public class LinksData - { - public String Facebook { get; } = "https://www.facebook.com/saxonite/"; - public String LinkedIn { get; } = "https://www.linkedin.com/company/saxonite/about/"; - } - public LinksData Links { get; } = new LinksData(); + // Form data. + //------------------------------------------------------------------- + // Common form values. + public String FormAction { get; set; } //------------------------------------------------------------------- - // Form data. /// List of Yes/No options for dropdown. public IEnumerable YesNoOptionsForSelect { - get { return new SelectList(SaxSystem.GetCodesOfType(Sax.CodeType.YesNo), "Code", "Desc"); } + get + { + List values = new List(); + foreach (TypeCodeDesc yesNo in SaxSystem.GetCodesOfType(Sax.CodeType.YesNo)) + values.Add(new SelectListItem(yesNo.Code, GetYesNoCaption((Sax.YesNo)yesNo.Type))); + return values; + } } /// List of Sport Participation options for dropdown. @@ -270,75 +343,18 @@ namespace Saxonite.Net.Core.Web.Base.Models } //------------------------------------------------------------------- - // Version parameter for includes. - public String HrefVersion - { - get - { - DateTime versionDate = SaxSystem.AssemblyBuildAt; - if (!DateUtil.IsValid(versionDate) || SaxSystem.DebugMode) - versionDate = DateTime.Now; - return DateUtil.Format(versionDate, "yyyyMMdd" /*+ (SacsSystem.Debug ? "HHmm" : "")*/); - } - } - // Additional includes. - public List AdditionalFiles_CSS { get; set; } = new List(); - public List AdditionalFiles_JS { get; set; } = new List(); - + // Localisation. //------------------------------------------------------------------- - // Redirection locations. - public class RedirectLocationData + public String GetItemDataTypeCaption(Sax.DataItemType itemType) { - // Properties populated in Controller_Base.OnActionExecuted. - public String Base { get; internal set; } - public String Home { get; internal set; } - public String Home_SessionExpired { get; internal set; } + // Default - return code description. + return DataItemTypeCodes.GetDescForType(itemType); } - public RedirectLocationData RedirectLocation { get; } = new RedirectLocationData(); - - //------------------------------------------------------------------- - // Paging properties. - public class DataPaging + public String GetYesNoCaption(Sax.YesNo yesNo) { - private DbQuery.Paging paging { get; } = new DbQuery.Paging(); - public void PopulatePagingTo(DbQuery.Paging resultsPaging) - { - resultsPaging.PageLength = paging.PageLength; - resultsPaging.PageNo = paging.PageNo; - } - public bool IsPaged { get { return paging.Paged; } } - public uint PageNo { get { return paging.PageNo; } set { paging.PageNo = value; } } - public ushort PageLength { get { return paging.PageLength; } set { paging.PageLength = value; } } - public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } } - public ushort ItemCount { get; set; } - private ulong itemTotal = 0; - public ulong ItemTotal - { - get { return itemTotal; } - set - { - itemTotal = value; - // Check whether the total number of items is less than the current page and reduce page no if needed. - if (IsPaged && (PageNo - 1) * PageLength > itemTotal) - PageNo = (uint)((itemTotal - 1) / PageLength + 1); - } - } + // Default - return code description. + return YesNoCodes.GetDescForType(yesNo); } - public DataPaging Paging { get; } = new DataPaging(); - public void PopulatePagingTo(DbQuery.Paging resultsPaging) - { - Paging.PopulatePagingTo(resultsPaging); - } - - //------------------------------------------------------------------- - // Form properties. - /// - /// User session index to identify the site resources, eg. database. - /// Equivalent to the Site index on the login form. - /// Populates value on logout form to identify default site for next login. - /// - public ushort SessionIdx { get { return SessionContext.Index; } } - public String FormAction { get; set; } //------------------------------------------------------------------- // Messages. diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController-Ajax-AwaitingActivation.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController-Ajax-AwaitingActivation.cs new file mode 100644 index 0000000..1e0ee03 --- /dev/null +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController-Ajax-AwaitingActivation.cs @@ -0,0 +1,116 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Utils; +using Sarand.Net.Standard.Dbas.Data; +using Saxonite.Net.Core.Web.Admin.Models; +using Saxonite.Net.Standard.Base.App; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Saxonite.Net.Core.Web.Admin.Controllers +{ + //======================================================================= + // Home - Ajax - Awaiting Activation controller + //======================================================================= + partial class HomeController + { + //------------------------------------------------------------------- + // Items Awaiting Activation data. + private class ActivationItemData + { + public String ItemType { get; set; } + public String ItemTypeDesc { get; set; } + public String ItemTypeDescPlural { get; set; } + public long ItemCount { get; set; } + public String ViewLink { get; set; } + } + + //------------------------------------------------------------------- + // Get Items Awaiting Activation ajax request. + //------------------------------------------------------------------- + private class AjaxResponse_ItemsAwaitingActivation : AjaxResponse_Data + { + // Construction. + public AjaxResponse_ItemsAwaitingActivation(SaxModel_Admin model) : base(model) { } + // Table list. + public List Items { get; } = new List(); + } + //------------------------------------------------------------------- + [HttpPost] + [Route("Home/Ajax/GetItemsAwaitingActivation")] + public IActionResult Ajax_GetItemsAwaitingActivation(Model_Sport model) + { + String fn = GetType().Name + ".Ajax_GetItemsAwaitingActivation"; + String messageTitle = Localiser["home.caption.application"]; + AjaxResponse_ItemsAwaitingActivation responseData = new AjaxResponse_ItemsAwaitingActivation(model); + + // Validate session. + if (!ValidUserSession) + return GetAjaxResult_InvalidSession(responseData); + + // Core Database connection. + ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext); + + // Query to count items awaiting activation. + Dictionary tableRowCounts = new Dictionary(StringComparer.OrdinalIgnoreCase); + List query = new List() + { + // User accounts. + "SELECT", + "ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.UserAccount)) + "',", + "ItemCount = Count(*)", + "FROM UserAccount ua", + "WHERE ua.Status = 'AWA'", + // Organisations. + "UNION SELECT", + "ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.Organisation)) + "',", + "ItemCount = Count(*)", + "FROM Organisation org", + "WHERE org.Status = 'AWA'", + }; + using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n"))) + { + while (dbResultSet != null && dbResultSet.NextRecord()) + { + Sax.DataItemType itemType = EnumUtil.ParseEnum(dbResultSet.GetRecordValues().GetValue("ItemType").ToString(), Sax.DataItemType.Unknown); + String itemTypeDesc = nameof(itemType); + String itemTypeDescPlural = itemTypeDesc; + String viewLink = ""; + switch (itemType) + { + case Sax.DataItemType.UserAccount: + itemTypeDesc = "User Account"; + itemTypeDescPlural = "User Accounts"; + viewLink = Url.Action("", "User", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/'); + break; + case Sax.DataItemType.Organisation: + itemTypeDesc = "Organisation"; + itemTypeDescPlural = "Organisations"; + viewLink = Url.Action("", "Organisation", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/'); + break; + } + ActivationItemData activationItem = new ActivationItemData() + { + ItemType = nameof(itemType), + ItemTypeDesc = itemTypeDesc, + ItemTypeDescPlural = itemTypeDescPlural, + ItemCount = dbResultSet.GetRecordValues().GetValue("ItemCount").AsLong(), + ViewLink = viewLink, + }; + responseData.Items.Add(activationItem); + } + } + + // Complete response. + responseData.Success = true; + return Json(responseData); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController.cs index b14b098..eaba101 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/HomeController.cs @@ -17,7 +17,7 @@ using System.Threading.Tasks; namespace Saxonite.Net.Core.Web.Admin.Controllers { //======================================================================= - public class HomeController : SaxController_Admin + public partial class HomeController : SaxController_Admin { //------------------------------------------------------------------- // Construction. diff --git a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController.cs b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController.cs index 7748f6d..ffd4efe 100644 --- a/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController.cs +++ b/SaxoniteCoreWebAdmin/Admin/Controllers/OrganisationController.cs @@ -26,7 +26,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers //------------------------------------------------------------------- [HttpGet] - public IActionResult Index() + public IActionResult Index(String sta) { // Validate session. if (!ValidUserSession) @@ -37,6 +37,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers model.Paging.PageNo = 1; model.Paging.PageLength = 6; + // Default status. + if (sta.StartsWithCI("Awa")) + model.Filter.OrganisationStatusCategoryCode = nameof(SaxOrganisation.StatusCat.AwaitingOnly); + return View(model); } diff --git a/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx b/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx index c7645c3..4ba3c66 100644 --- a/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx +++ b/SaxoniteCoreWebAdmin/Localisation/SaxAdminProperties.resx @@ -138,9 +138,15 @@ Admin + + Awaiting Activation + Home + + No items are awaiting activation + Accounts @@ -237,6 +243,9 @@ Available items + + Items awaiting activation + Keep me signed-in diff --git a/SaxoniteCoreWebAdmin/Views/Home/Index.cshtml b/SaxoniteCoreWebAdmin/Views/Home/Index.cshtml index 9e7e652..88ff289 100644 --- a/SaxoniteCoreWebAdmin/Views/Home/Index.cshtml +++ b/SaxoniteCoreWebAdmin/Views/Home/Index.cshtml @@ -4,9 +4,35 @@ } +@* Items Awaiting Activation *@ +
+ +
+
@Localiser["home.caption.awaiting.activation"]
+
+
+
+
+ @* Items awaiting activation templates *@ +
+
+
+
+
+
+
@(Localiser["label.items.awaiting.activation"]):
+
+
+
+
+ +
+ +@* Database Schema *@
@@ -16,6 +42,7 @@
+ @* Db Schema templates *@
@(Localiser["label.table"]):
diff --git a/SaxoniteCoreWebAdmin/wwwroot/css/sax-form.css b/SaxoniteCoreWebAdmin/wwwroot/css/sax-form.css index c058511..263f196 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/css/sax-form.css +++ b/SaxoniteCoreWebAdmin/wwwroot/css/sax-form.css @@ -10,7 +10,7 @@ margin: 24px auto; padding: 0; background-color: #fff; - border: solid 2px #979797; + border: solid 1px #979797; border-color: var(--color-primary); border-radius: 4px; -webkit-border-radius: 4px; diff --git a/SaxoniteCoreWebAdmin/wwwroot/css/sax-main.css b/SaxoniteCoreWebAdmin/wwwroot/css/sax-main.css index 08c8bcd..ab5728e 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/css/sax-main.css +++ b/SaxoniteCoreWebAdmin/wwwroot/css/sax-main.css @@ -336,7 +336,7 @@ a:focus .ui-dialog.ui-widget.ui-widget-content { - border-width: 2px; + border-width: 1px; border-color: #d4af37; -moz-box-shadow: 4px 4px 6px #ccc; -webkit-box-shadow: 4px 4px 6px #ccc; diff --git a/SaxoniteCoreWebAdmin/wwwroot/js/sax-home.js b/SaxoniteCoreWebAdmin/wwwroot/js/sax-home.js index 447ede6..3e456c7 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/js/sax-home.js +++ b/SaxoniteCoreWebAdmin/wwwroot/js/sax-home.js @@ -5,17 +5,59 @@ (function (win, doc, undef) { "use strict"; + let $pnl = sax.$pnl, $dlg = sax.$dlg, $frm = sax.$frm; sax.itemIdPrefix = 'Itm_'; //-------------------------------------------------------------- - sax.refreshDbSchema= function (delay) + sax.refreshAwaitActivate = function (delay) { if (sax.awaitingLogin) return; - var $results = $('.sax-panel-results.DbSchema'); if (!sax.awaitingRefreshResponse) { - var $items = $('.sax-panel-item-list', $results).fadeOut(200).empty(); - var $msgs = $('.sax-panel-messages', $results).hide().empty().append($('
' + sax.msg.dataQuerying + '
')).fadeIn(200); + var $items = $('.sax-panel-item-list', $pnl.awaitAct).fadeOut(200).empty(); + var $msgs = $('.sax-panel-messages', $pnl.awaitAct).hide().empty().append($('
' + sax.msg.dataQuerying + '
')).fadeIn(200); + } + sax.ajax.awaitAct = sax.ajax.awaitAct || { url: sax.url.base + 'Home/Ajax/GetItemsAwaitingActivation', formId: 'frmNavigate', callbackFn: sax.handleAwaitActivateResponse, noWaitIcon: true }; + sax.doAjaxRequest(sax.ajax.awaitAct, delay || 50); + sax.awaitingRefreshResponse = true; + } + sax.handleAwaitActivateResponse = function (response) + { + //sax.debug('handleAwaitActivateResponse', response); + delete sax.awaitingRefreshResponse; + var $msgs = $('.sax-panel-messages', $pnl.awaitAct).hide().empty(); + var $items = $('.sax-panel-item-list', $pnl.awaitAct).hide().empty(); + var $tmpl = $('.sax-panel-item-template .sax-panel-item.AwaitActivateItem', $pnl.awaitAct); + if (!response.success) return; + // Items. + var items = response.items; + if (!items.length) + return $msgs.append($('
' + sax.msg.noItemsAwaitAct + '
')).fadeIn(500); + for (let itemIdx = 0; itemIdx < items.length; itemIdx++) + $items.append(sax.populateAwaitActivateItem($tmpl.clone(), items[itemIdx])); + $items.slideDown(750); + } + sax.populateAwaitActivateItem = function ($item, item) + { + if (!item) return; + if (item.viewLink)$('.sax-action.sax-view', $item).on('click', function () { sax.goToPage(item.viewLink); }); + $('.AwaitActivateItemType', $item).text(item.itemTypeDescPlural); + $('.AwaitActivateItemCount', $item).text(item.itemCount); + return $item; + } + sax.getAwaitActivateItemTemplate = function () + { + return $('.sax-panel-item-template .sax-panel-item.AwaitActivateItem', $pnl.results).clone(); + } + + //-------------------------------------------------------------- + sax.refreshDbSchema = function (delay) + { + if (sax.awaitingLogin) return; + if (!sax.awaitingRefreshResponse) + { + var $items = $('.sax-panel-item-list', $pnl.dbSchema).fadeOut(200).empty(); + var $msgs = $('.sax-panel-messages', $pnl.dbSchema).hide().empty().append($('
' + sax.msg.dataQuerying + '
')).fadeIn(200); } sax.ajax.dbSchema = sax.ajax.dbSchema || { url: sax.url.base + 'System/Ajax/ValidateDatabaseSchema', formId: 'frmNavigate', callbackFn: sax.handleDbSchemaResponse, noWaitIcon: true }; sax.doAjaxRequest(sax.ajax.dbSchema, delay || 50); @@ -25,25 +67,19 @@ { //sax.debug('handleDbSchemaResponse', response); delete sax.awaitingRefreshResponse; - var $results = $('.sax-panel-results.DbSchema'); - var $msgs = $('.sax-panel-messages', $results).hide().empty(); - var $items = $('.sax-panel-item-list', $results).hide().empty(); - var $tmpl = $('.sax-panel-item-template .sax-panel-item.DbSchemaItem', $results); + var $msgs = $('.sax-panel-messages', $pnl.dbSchema).hide().empty(); + var $items = $('.sax-panel-item-list', $pnl.dbSchema).hide().empty(); + var $tmpl = $('.sax-panel-item-template .sax-panel-item.DbSchemaItem', $pnl.dbSchema); if (!response.success) return; // Items. var items = response.items; if (!items.length) return $msgs.append($('
' + sax.msg.dbSchemaValid + '
')).fadeIn(500); for (let itemIdx = 0; itemIdx < items.length; itemIdx++) - { - let item = items[itemIdx]; - let $item = $tmpl.clone(); - sax.populateItem($item, item); - $items.append($item); - } - $items.fadeIn(50); + $items.append(sax.populateDbSchemaItem($tmpl.clone(), items[itemIdx])); + $items.slideDown(750); } - sax.populateItem = function ($item, item) + sax.populateDbSchemaItem = function ($item, item) { if (!item) return; $item.prop('id', sax.itemIdPrefix + item.id); @@ -53,11 +89,16 @@ $('.ColumnName', $item).text(item.columnName); $('.SchemaColumn', $item).toggle(!!item.columnName); $('.Comment', $item).text(item.comment); + return $item; } //-------------------------------------------------------------- $(function () { + $pnl.awaitAct = $('.sax-panel-results.AwaitActivate'); + $pnl.dbSchema = $('.sax-panel-results.DbSchema'); + + setTimeout(sax.refreshAwaitActivate, 250); setTimeout(sax.refreshDbSchema, 250); }); diff --git a/SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js b/SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js index 1e6539e..ade268e 100644 --- a/SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js +++ b/SaxoniteCoreWebAdmin/wwwroot/js/sax-user.js @@ -62,7 +62,7 @@ $('.UserFirstName', $item).text(item.firstName); $('.UserLastName', $item).text(item.lastName); $('.UserRoleCount', $item).text(item.userRoleCount); - $('.StatusDesc', $item).text(item.statusDesc); + $('.StatusDesc', $item).text(item.statusDesc).addClass('sax-status-' + item.statusCode.toLowerCase()); $('.sax-caption .sax-action').toggleClass('sax-action', !item.deleted); let $mnu = $('ul.sax-dropdown-menu', $item); if (!item.deleted) diff --git a/SaxoniteCoreWebOnline/Localisation/SaxOnlineProperties.resx b/SaxoniteCoreWebOnline/Localisation/SaxOnlineProperties.resx index b31dcad..f4ed53b 100644 --- a/SaxoniteCoreWebOnline/Localisation/SaxOnlineProperties.resx +++ b/SaxoniteCoreWebOnline/Localisation/SaxOnlineProperties.resx @@ -231,6 +231,9 @@ Alternatively + + Any + Article @@ -309,6 +312,9 @@ First name + + Follow + Forgotten password? @@ -501,6 +507,9 @@ Very Good + + View + Year diff --git a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Contact.cs b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Contact.cs index 31322c7..e4b5602 100644 --- a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Contact.cs +++ b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Contact.cs @@ -42,13 +42,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers public byte DobMonth { get; set; } public short DobYear { get; set; } // Regions. - public int RegionIdCountry { get; set; } + public String RegionIdCountry { get; set; } public String RegionCaptionCountry { get; set; } - public int RegionIdProvince { get; set; } + public String RegionIdProvince { get; set; } public String RegionCaptionProvince { get; set; } public String LocationCaption { get; set; } } - private void PopulateContactResponseData(ContactResponseData data, SaxUserAccount userAccount) + private void PopulateContactResponseData(SaxModel_Online model, ContactResponseData data, SaxUserAccount userAccount) { data.EmailAddress = userAccount.EmailAddress; data.DisplayName = userAccount.GetDisplayName(); @@ -62,8 +62,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers data.DobMonth = (byte)userAccount.DateOfBirthMonth; data.DobYear = (short)userAccount.DateOfBirthYear; // Regions. - data.RegionIdCountry = SysId.ToInt(userAccount.RegionIdCountry); - data.RegionIdProvince = SysId.ToInt(userAccount.RegionIdProvince); + data.RegionIdCountry = model.GetEncryptedRegionId(userAccount.RegionIdCountry); + data.RegionIdProvince = model.GetEncryptedRegionId(userAccount.RegionIdProvince); data.RegionCaptionCountry = Localiser.GetRegionName(Internals.GetRegion(userAccount.RegionIdCountry)); data.RegionCaptionProvince = Localiser.GetRegionName(Internals.GetRegion(userAccount.RegionIdProvince)); List locations = new List() { data.RegionCaptionProvince, data.RegionCaptionCountry }; @@ -134,7 +134,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers // Populate data to response. responseData.Contact = new ContactResponseData(); - PopulateContactResponseData(responseData.Contact, userAccount); + PopulateContactResponseData(model, responseData.Contact, userAccount); responseData.Success = true; return Json(responseData); } @@ -363,7 +363,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers // Construct response. responseData.Contact = new ContactResponseData(); - PopulateContactResponseData(responseData.Contact, userAccount); + PopulateContactResponseData(model, responseData.Contact, userAccount); responseData.Success = true; return Json(responseData); } diff --git a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Sports.cs b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Sports.cs index dcc97c7..d5f8433 100644 --- a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Sports.cs +++ b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-Sports.cs @@ -35,15 +35,17 @@ namespace Saxonite.Net.Core.Web.Online.Controllers } private class ProfileSportResponseData_Item : ProfileSportResponseData_List { + public String SportAbout { get; set; } public String SportParticipationCode { get; set; } public String SportOfficiatingCode { get; set; } } private void PopulateProfileSportResponseData(Model_Account model, SaxUserSport userSport, SaxSport sport, ProfileSportResponseData_Item data) { data.Id = SysId.ToString(userSport.Id); - data.SportId = SysId.ToString(userSport.SportId); + data.SportId = model.GetEncryptedSportId(userSport.SportId); data.SportName = sport.Name; data.SportSpecialityLabel = model.GetSportSpecialityLabel(userSport.SportId); + data.SportAbout = userSport.About; data.SportParticipationCode = SportParticipationCodes.GetCodeForType(userSport.Participation); data.SportParticipation = Localiser.GetSportParticipationTypeCaption(userSport.Participation); data.SportOfficiatingCode = SportOfficiatingCodes.GetCodeForType(userSport.Officiating); @@ -112,7 +114,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers ProfileSportResponseData_List userSportData = new ProfileSportResponseData_List() { Id = values.GetLong(colId.DataName).ToString(), - SportId = sportId.ToString(), + SportId = model.GetEncryptedSportId(sportId), SportName = values.GetString(colSportName.DataName), SportSpecialityLabel = model.GetSportSpecialityLabel(sportId), SportParticipation = Localiser.GetSportParticipationTypeCaption((Sax.SportParticipation)values.GetLong(colParticipation.DataName)), @@ -254,14 +256,24 @@ namespace Saxonite.Net.Core.Web.Online.Controllers userSport = AccountMgr.GetUserSport(prmUserSport); if (userSport != null) { - SaLogger.Info(fn + " Resurrecting User Sport with status: " + userSport.StatusDesc + ". Id: " + SysId.ToString(userSport.Id)); - userSport.Status = SaxUserSport.DefaultStatus; + if (userSport.Status == SaStatus.Deleted) + { + SaLogger.Info(fn + " Resurrecting User Sport with status: " + userSport.StatusDesc + ". Id: " + SysId.ToString(userSport.Id)); + userSport.Status = SaxUserSport.DefaultStatus; + } + else + { + responseData.SetControlError(nameof(model.ProfileSportId), Localiser["msg.validation.duplicate.value"]); + return Json(responseData); + } } else userSport = AccountMgr.CreateUserSport(SessionData.User.UserAccountId, sportId); } // Populate item properties. + if (model.ProfileSportAbout != null) + userSport.About = model.ProfileSportAbout; if (model.ProfileSportParticipationCode != null) userSport.Participation = model.ProfileSportParticipation; if (model.ProfileSportOfficiatingCode != null) diff --git a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-UserSportExperience.cs b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-UserSportExperience.cs index 5e28cf5..579f2dd 100644 --- a/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-UserSportExperience.cs +++ b/SaxoniteCoreWebOnline/Online/Controllers/AccountController-Ajax-UserSportExperience.cs @@ -70,8 +70,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers data.League = userSportExperience.League; data.Speciality = userSportExperience.Speciality; // Regions. - data.RegionIdNation = model.EncryptId(userSportExperience.RegionIdNation); - data.RegionIdProvince = model.EncryptId(userSportExperience.RegionIdProvince); + data.RegionIdNation = model.GetEncryptedRegionId(userSportExperience.RegionIdNation); + data.RegionIdProvince = model.GetEncryptedRegionId(userSportExperience.RegionIdProvince); data.RegionCaptionNation = Localiser.GetRegionName(Internals.GetRegion(userSportExperience.RegionIdNation)); data.RegionCaptionProvince = Localiser.GetRegionName(Internals.GetRegion(userSportExperience.RegionIdProvince)); List locations = new List() { data.RegionCaptionProvince, data.RegionCaptionNation }; diff --git a/SaxoniteCoreWebOnline/Online/Controllers/ArticleController-Ajax.cs b/SaxoniteCoreWebOnline/Online/Controllers/ArticleController-Ajax.cs index 2fb8446..be76719 100644 --- a/SaxoniteCoreWebOnline/Online/Controllers/ArticleController-Ajax.cs +++ b/SaxoniteCoreWebOnline/Online/Controllers/ArticleController-Ajax.cs @@ -88,8 +88,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers private void PopulateArticleResponseData(Model_Article model, SaxArticle article, ArticleData_Full data) { PopulateArticleResponseData(model, article, data as ArticleData_List); - data.RegionIdPrimary = SysId.ToString(article.RegionIdPrimary); - data.SportIdPrimary = SysId.ToString(article.SportIdPrimary); + data.RegionIdPrimary = model.GetEncryptedRegionId(article.RegionIdPrimary); + data.SportIdPrimary = model.GetEncryptedSportId(article.SportIdPrimary); data.Published = DateUtil.IsValid(article.PublishedAt); data.PublishedOn_YYYYMMDD = DateUtil.Format(article.PublishedAt, "yyyyMMdd"); data.PublishedOn_Calendar = model.FormatDateForForm(article.PublishedAt); diff --git a/SaxoniteCoreWebOnline/Online/Controllers/OrganisationController-Ajax-Opportunities.cs b/SaxoniteCoreWebOnline/Online/Controllers/OrganisationController-Ajax-Opportunities.cs index 5104e0c..251a619 100644 --- a/SaxoniteCoreWebOnline/Online/Controllers/OrganisationController-Ajax-Opportunities.cs +++ b/SaxoniteCoreWebOnline/Online/Controllers/OrganisationController-Ajax-Opportunities.cs @@ -57,8 +57,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers private void PopulateOpportunityResponseData(Model_Organisation_Opportunities model, SaxOrganisationOpportunity opportunity, OpportunityData_Detail data) { PopulateOpportunityResponseData(model, opportunity, data as OpportunityData_List); - data.RegionIdPrimary = SysId.ToString(opportunity.RegionIdPrimary); - data.SportIdPrimary = SysId.ToString(opportunity.SportIdPrimary); + data.RegionIdPrimary = model.GetEncryptedRegionId(opportunity.RegionIdPrimary); + data.SportIdPrimary = model.GetEncryptedSportId(opportunity.SportIdPrimary); data.PublishedOn_YYYYMMDD = DateUtil.Format(opportunity.PublishedAt, "yyyyMMdd"); data.ExpiresOn_YYYYMMDD = DateUtil.Format(opportunity.ExpiresAt, "yyyyMMdd"); } @@ -148,9 +148,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers // Organisation. responseData.Organisation.Id = SysId.ToString(organisation.Id); responseData.Organisation.Name = organisation.Name; - responseData.Organisation.SportId = SysId.ToString(organisation.SportIdPrimary); + responseData.Organisation.SportId = model.GetEncryptedSportId(organisation.SportIdPrimary); responseData.Organisation.SportName = model.GetSportCaption(organisation.SportIdPrimary); - responseData.Organisation.RegionId = SysId.ToString(organisation.RegionIdPrimary); + responseData.Organisation.RegionId = model.GetEncryptedRegionId(organisation.RegionIdPrimary); responseData.Organisation.RegionName = model.GetRegionCaption(organisation.RegionIdPrimary); // User details. diff --git a/SaxoniteCoreWebOnline/Online/Controllers/SearchController-Ajax-Organisations.cs b/SaxoniteCoreWebOnline/Online/Controllers/SearchController-Ajax-Organisations.cs new file mode 100644 index 0000000..0059e69 --- /dev/null +++ b/SaxoniteCoreWebOnline/Online/Controllers/SearchController-Ajax-Organisations.cs @@ -0,0 +1,195 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Saxonite.Net.Core.Web.Online.Models; +using Saxonite.Net.Core.Web.Base.App; +using Saxonite.Net.Core.Web.Base.Controllers; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Saxonite.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Utils; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; + +namespace Saxonite.Net.Core.Web.Online.Controllers +{ + //======================================================================= + // Online Search Controller - Organisations - Ajax actions. + //======================================================================= + partial class SearchController + { + //------------------------------------------------------------------- + // Account - Get Organisations. + //------------------------------------------------------------------- + private class OrganisationListData + { + public String Id { get; set; } + public String Name { get; set; } + public String SportId { get; set; } + public String SportName { get; set; } + public String RegionId { get; set; } + public String RegionName { get; set; } + } + private class AjaxResponse_Search_Organisations : AjaxResponse_Data + { + // Construction. + public AjaxResponse_Search_Organisations(SaxModel_Online model) : base(model) { } + // Organisation list. + public List Organisations { get; } = new List(); + } + // Ajax request. + [HttpPost] + [Route("Search/Ajax/Organisations")] + [Route("Search/Ajax/GetOrganisations")] + public IActionResult GetProfileOrganisations(Model_Search_Organisations model) + { + String fn = GetType().Name + ".GetProfileOrganisations"; + AjaxResponse_Search_Organisations responseData = new AjaxResponse_Search_Organisations(model); + String messageTitle = Localiser["organisation.caption.organisations"]; + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + // Query organisations that user is a member of. + SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params(); + prmOrganisation.OrganisationFilter = model.Filter.Organisation; + prmOrganisation.OrganisationType = model.FilterOrganisationType; + prmOrganisation.OrganisationCategory = model.FilterOrganisationCategory; + if (SysId.IsValid(model.FilterSportId)) + prmOrganisation.SportIdsIncluded.Add(model.FilterSportId); + if (SysId.IsValid(model.FilterRegionId)) + prmOrganisation.RegionIdsIncluded.Add(model.FilterRegionId); + prmOrganisation.StatusCat = SaxOrganisation.StatusCat.ActiveOnly; + model.Paging.ItemTotal = (ulong)AccountMgr.GetOrganisationCount(prmOrganisation); + model.PopulatePagingTo(prmOrganisation.ResultsPaging); + + List organisations = AccountMgr.GetOrganisationList(prmOrganisation); + List organisationIds = organisations.GetIds(); + + // Item columns. + ColumnDfn colId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id); + ColumnDfn colName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name); + ColumnDfn colSportId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.SportId); + ColumnDfn colSportName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Sport_Name); + ColumnDfn colRegionId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.RegionId); + ColumnDfn colRegionName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Region_Name); + List columns = new List() + { + colId, colName, + colSportId, colSportName, + colRegionId, colRegionName, + }; + + // Sort columns. + colName.SortAscending = true; + prmOrganisation.SortColumns.Add(colName); + + // Query items. + using (DbResultSet resultSet = AccountMgr.ExecuteOrganisationQuery(columns, prmOrganisation)) + { + while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) + { + NamedValue.Map values = resultSet.GetRecordValues(); + OrganisationListData organisationData = new OrganisationListData() + { + Id = model.EncryptId(new SysId(values.GetLong(colId.DataName))), + Name = values.GetString(colName.DataName), + SportId = model.GetEncryptedSportId(new SysId(values.GetLong(colSportId.DataName))), + SportName = values.GetString(colSportName.DataName), + RegionId = model.GetEncryptedRegionId(new SysId(values.GetLong(colRegionId.DataName))), + RegionName = values.GetString(colRegionName.DataName), + }; + responseData.Organisations.Add(organisationData); + } + } + if (model.Paging.IsPaged) + model.Paging.ItemCount = (ushort)responseData.Organisations.Count; + + // Complete response. + responseData.SetPaging(model); + responseData.Success = true; + return Json(responseData); + } + //------------------------------------------------------------------- + // Account - Get Organisations. + //------------------------------------------------------------------- + private class OrganisationData + { + public String Id { get; set; } + public String Name { get; set; } + public String SportId { get; set; } + public String SportName { get; set; } + public String RegionId { get; set; } + public String RegionName { get; set; } + } + private class AjaxResponse_Search_Organisation : AjaxResponse_Data + { + // Construction. + public AjaxResponse_Search_Organisation(SaxModel_Online model) : base(model) { } + // Organisation list. + public OrganisationData Organisation { get; set; } + } + // Ajax request. + [HttpPost] + [Route("Search/Ajax/Organisation")] + [Route("Search/Ajax/GetOrganisation")] + public IActionResult GetProfileOrganisation(Model_Search_Organisations model) + { + String fn = GetType().Name + ".GetProfileOrganisation"; + AjaxResponse_Search_Organisation responseData = new AjaxResponse_Search_Organisation(model); + String messageTitle = Localiser["label.organisations"]; + + // Validate session and referrer. + if (!ValidReferer) return Forbid(); + if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); + RefreshModel(model); + + + // Record disposable items as they are created so all can be disposed when needed. + using (DisposableCollection disposableItems = new DisposableCollection()) + { + + // Retrieve organisation. + SysId organisationId = model.ExtractSysId(model.OrganisationId); + if (!SysId.IsValid(organisationId)) + { + SaLogger.Warn(fn + " Organisation Id not supplied."); + return Json(responseData); + } + SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId); + if (organisation == null) + { + SaLogger.Warn(fn + " Failed to retrieve organisation. Id: " + model.OrganisationId); + return Json(responseData); + } + disposableItems.Add(organisation); + + // Populate response. + OrganisationData organisationData = new OrganisationData() + { + Id = model.EncryptId(organisation.Id), + Name = organisation.Name, + SportId = model.GetEncryptedSportId(organisation.SportIdPrimary), + SportName = model.GetSportCaption(organisation.SportIdPrimary), + RegionId = model.GetEncryptedRegionId(organisation.RegionIdPrimary), + RegionName = model.GetRegionCaption(organisation.RegionIdPrimary), + }; + responseData.Organisation = organisationData; + + } + + // Complete response. + responseData.Success = true; + return Json(responseData); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaxoniteCoreWebOnline/Online/Controllers/SearchController.cs b/SaxoniteCoreWebOnline/Online/Controllers/SearchController.cs new file mode 100644 index 0000000..282ef94 --- /dev/null +++ b/SaxoniteCoreWebOnline/Online/Controllers/SearchController.cs @@ -0,0 +1,63 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Utils; +using Saxonite.Net.Core.Web.Base.App; +using Saxonite.Net.Core.Web.Online.Models; +using Saxonite.Net.Standard.Base.Bus; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Saxonite.Net.Core.Web.Online.Controllers +{ + //======================================================================= + // Online Search Controller. + //======================================================================= + public partial class SearchController : SaxController_Online + { + //------------------------------------------------------------------- + // Construction. + public SearchController(SaxLocaliser localiser, ILogger logger) : + base(localiser, logger) + { + } + + //------------------------------------------------------------------- + [HttpGet] + public IActionResult Index() + { + // Validate session. + if (!ValidUserSession) + return RedirectToAction("", ""); + + // No 'Index' view as yet - default to home page. + return RedirectToAction("", ""); + } + + //------------------------------------------------------------------- + /// + /// Search - Organisations. + /// + [HttpGet] + public IActionResult Organisations() + { + // Validate session. + if (!ValidUserSession) + return RedirectToAction("", ""); + + // Model. + Model_Search_Organisations model = new Model_Search_Organisations(Localiser); + model.Paging.PageNo = 1; + model.Paging.PageLength = 12; + + return View(model); + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaxoniteCoreWebOnline/Online/Models/Model_Account.cs b/SaxoniteCoreWebOnline/Online/Models/Model_Account.cs index 1df728e..f32070e 100644 --- a/SaxoniteCoreWebOnline/Online/Models/Model_Account.cs +++ b/SaxoniteCoreWebOnline/Online/Models/Model_Account.cs @@ -44,8 +44,8 @@ namespace Saxonite.Net.Core.Web.Online.Models return (Sax.Gender)StringUtil.ToShort(AccountGender); } public String AccountDobDay { get; set; } - public String AccountDobMonth{ get; set; } - public String AccountDobYear{ get; set; } + public String AccountDobMonth { get; set; } + public String AccountDobYear { get; set; } // Regions. public String AccountRegionIdCountry { get; set; } public String AccountRegionCaptionCountry { get; } @@ -71,6 +71,7 @@ namespace Saxonite.Net.Core.Web.Online.Models get { return (Sax.SportOfficiating)SportOfficiatingCodes.GetTypeForCode(ProfileSportOfficiatingCode); } set { ProfileSportOfficiatingCode = SportOfficiatingCodes.GetCodeForType(value); } } + public String ProfileSportAbout { get; set; } //------------------------------------------------------------------- // Validate users's contact details. @@ -175,6 +176,17 @@ namespace Saxonite.Net.Core.Web.Online.Models responseData.SetControlError(nameof(ProfileSportId), Localiser["msg.validation.mandatory.value"]); } + // About. + if (ProfileSportAbout != null) + { + responseData.SetControlValue(nameof(ProfileSportAbout), ProfileSportAbout); + if (!StringUtil.IsEmpty(ProfileSportAbout)) + { + if (StringUtil.GetLength(ProfileSportAbout) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserSport_About)) + responseData.SetControlError(nameof(ProfileSportAbout), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserSport_About)]); + } + } + return !responseData.HasControlErrors(); } diff --git a/SaxoniteCoreWebOnline/Online/Models/Model_Search_Organisations.cs b/SaxoniteCoreWebOnline/Online/Models/Model_Search_Organisations.cs new file mode 100644 index 0000000..1f07f80 --- /dev/null +++ b/SaxoniteCoreWebOnline/Online/Models/Model_Search_Organisations.cs @@ -0,0 +1,57 @@ +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Helpers; +using Sarand.Net.Standard.Base.Utils; +using Saxonite.Net.Core.Web.Base.App; +using Saxonite.Net.Core.Web.Base.Controllers; +using Saxonite.Net.Core.Web.Base.Models; +using Saxonite.Net.Standard.Base.App; +using Saxonite.Net.Standard.Base.Bus; +using Saxonite.Net.Standard.Base.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Saxonite.Net.Core.Web.Online.Models +{ + //======================================================================= + public class Model_Search_Organisations : SaxModel_Online + { + //------------------------------------------------------------------- + // Construction. + public Model_Search_Organisations(SaxLocaliser localiser) : + base(localiser) + { + //AdditionalFiles_CSS.Add("css/sax-src-org.css"); + AdditionalFiles_JS.Add("js/sax-src-org.js"); + } + + //------------------------------------------------------------------- + // Page configuration. + + //------------------------------------------------------------------- + // Form properties. + public class FilterData + { + public String Organisation { get; set; } + public String Type { get; set; } + public String Category { get; set; } + public String RegionId { get; set; } + public String SportId { get; set; } + } + public FilterData Filter { get; } = new FilterData(); + public Sax.OrganisationType FilterOrganisationType { get { return (Sax.OrganisationType)OrganisationTypeCodes.GetTypeForCode(Filter.Type); } } + public Sax.OrganisationCategory FilterOrganisationCategory { get { return (Sax.OrganisationCategory)OrganisationCategoryCodes.GetTypeForCode(Filter.Category); } } + public SysId FilterSportId { get { return ExtractSysId(Filter.SportId); } } + public SysId FilterRegionId { get { return ExtractSysId(Filter.RegionId); } } + public String OrganisationId { get; set; } + + //------------------------------------------------------------------- + // Validation. + //------------------------------------------------------------------- + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SaxoniteCoreWebOnline/Online/Models/SaxModel_Online.cs b/SaxoniteCoreWebOnline/Online/Models/SaxModel_Online.cs index 8d4a4da..dc52025 100644 --- a/SaxoniteCoreWebOnline/Online/Models/SaxModel_Online.cs +++ b/SaxoniteCoreWebOnline/Online/Models/SaxModel_Online.cs @@ -127,6 +127,7 @@ namespace Saxonite.Net.Core.Web.Online.Models public static String ParamName_IdObfuscation_Id { get; } = "iob"; public String EncryptId(SysId id) { + if (!SysId.IsValid(id)) return ""; NameValueCollection idObfuscationParams = new NameValueCollection(); idObfuscationParams.Add(ParamName_IdObfuscation_Id, SysId.ToString(id)); return SaxController_Base.EncryptParameters(idObfuscationParams, Base64IV_IdObfuscation, Base64Key_IdObfuscation); @@ -143,9 +144,10 @@ namespace Saxonite.Net.Core.Web.Online.Models // Reference Data. //------------------------------------------------------------------- // Regions. - /// Region Data class - to be JSON serialised in Ajax responses. + /// Region Data - to be JSON serialised in Ajax responses. public class RegionData { + /// Encrypted Id public String Id { get; set; } public int RegionType { get; set; } public String RegionTypeCode { get; set; } @@ -162,7 +164,7 @@ namespace Saxonite.Net.Core.Web.Online.Models { RegionData regionData = new RegionData() { - Id = SysId.ToString(region.Id), + Id = GetEncryptedRegionId(region.Id), RegionType = (int)region.RegionType, RegionTypeCode = region.RegionType.ToString(), RegionTypeDesc = Localiser.GetRegionTypeCaption(region.RegionType), @@ -175,6 +177,10 @@ namespace Saxonite.Net.Core.Web.Online.Models } return regions; } + public String GetEncryptedRegionId(SysId regionId) + { + return DataCacheConsole.GetEncryptedRegionId(regionId, EncryptId(regionId)); + } public String GetRegionCaption(SysId regionId) { SaxRegion.Data region = DataCacheConsole.GetAllRegions().Find(item => item.Id.Equals(regionId)); @@ -187,9 +193,11 @@ namespace Saxonite.Net.Core.Web.Online.Models //------------------------------------------------------------------- // Sports. + /// Sport Data - to be JSON serialised in Ajax responses. public class SportData { - public Int32 Id { get; set; } + /// Encrypted Id + public String Id { get; set; } public String Name { get; set; } public String StatusCode { get; set; } public String StatusDesc { get; set; } @@ -201,7 +209,7 @@ namespace Saxonite.Net.Core.Web.Online.Models { SportData sportData = new SportData() { - Id = SysId.ToInt(sport.Id), + Id = GetEncryptedSportId(sport.Id), Name = GetSportCaption(sport), StatusCode = sport.StatusCode, StatusDesc = Localiser.GetStatusCaption(sport.Status) @@ -210,6 +218,10 @@ namespace Saxonite.Net.Core.Web.Online.Models } return sports; } + public String GetEncryptedSportId(SysId sportId) + { + return DataCacheConsole.GetEncryptedSportId(sportId, EncryptId(sportId)); + } // Sport caption. public String GetSportCaption(SysId sportId) { diff --git a/SaxoniteCoreWebOnline/Views/Account/Profile-SportExperiences.cshtml b/SaxoniteCoreWebOnline/Views/Account/Profile-SportExperiences.cshtml index 1bf90a8..2c4556f 100644 --- a/SaxoniteCoreWebOnline/Views/Account/Profile-SportExperiences.cshtml +++ b/SaxoniteCoreWebOnline/Views/Account/Profile-SportExperiences.cshtml @@ -18,6 +18,7 @@ diff --git a/SaxoniteCoreWebOnline/Views/Account/Profile-Sports.cshtml b/SaxoniteCoreWebOnline/Views/Account/Profile-Sports.cshtml index 0156ab7..47e037f 100644 --- a/SaxoniteCoreWebOnline/Views/Account/Profile-Sports.cshtml +++ b/SaxoniteCoreWebOnline/Views/Account/Profile-Sports.cshtml @@ -39,7 +39,7 @@ @* Sport template *@
-
+
@* Burger menu *@