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; using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Core.Web.Online.Helpers; using Org.BouncyCastle.Security; using static Saxonite.Net.Standard.Base.App.Sax; namespace Saxonite.Net.Core.Web.Online.Controllers { //======================================================================= // Online Search Controller - Organisations - Ajax actions. //======================================================================= partial class SearchController { //------------------------------------------------------------------- // Account - Get Organisations. //------------------------------------------------------------------- private class OrganisationListData : AjaxResponse_Data.ItemData_Base { public String Name { get; set; } public String CategoryDesc { get; set; } public String SportName { get; set; } public String RegionName { get; set; } public String LogoUrl { 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 Ajax_GetOrganisations(Model_Search_Organisations model) { String fn = GetType().Name + ".Ajax_GetOrganisations"; 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); // Ensure data is paged to avoid leaking large volumes. model.Paging.PageNo = Math.Max(1, model.Paging.PageNo); model.Paging.PageLength = Math.Max(Math.Min(Sax.Config.Online.Search.Organisations.PageLengthMax, model.Paging.PageLength), (ushort)1); // 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; prmOrganisation.OrganisationCategoriesExcluded.Add(Sax.OrganisationCategory.Partner); prmOrganisation.OrganisationCategoriesExcluded.Add(Sax.OrganisationCategory.Other); 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 colCategory = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationCategory_Desc); 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); ColumnDfn colLogoCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.LogoImage_Count); List columns = new List() { colId, colName, colCategory, colSportId, colSportName, colRegionId, colRegionName, colLogoCount }; // 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(); SysId organisationId = new SysId(values.GetLong(colId.DataName)); Sax.OrganisationCategory category = (Sax.OrganisationCategory)OrganisationCategoryCodes.GetTypeForCode(values.GetString(colCategory.DataName)); OrganisationListData organisationData = new OrganisationListData() { Id = model.EncryptId(organisationId), Name = values.GetString(colName.DataName), CategoryDesc = Localiser.GetOrganisationCategoryCaption(category), SportName = values.GetString(colSportName.DataName), RegionName = values.GetString(colRegionName.DataName), }; // Logo. if (values.GetLong(colLogoCount.DataName) > 0) organisationData.LogoUrl = GetOrganisationLogoLink(organisationId, false); // Add item to the list. 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 Organisation. //------------------------------------------------------------------- /// /// Associations are grouped by type and direction (parent->child). ///
The organisation specified in each case is the 'other' organisation (not the current 'target' organisation).
///
private class AssociationTypeData { public String Caption { get; set; } public List Organisations { get; } = new List(); } /// /// Association Organisation - the one that is not the current 'target' organisation. ///
Region and Sport are only populate if different from the 'target' organisation.
///
private class AssociationOrganisationData { public String Name { get; set; } public String Display { get { String display = Name; if (!StringUtil.IsBlank(Sport) || !StringUtil.IsBlank(Region)) display += " (" + String.Join(", ", new List { Sport, Region }.Where(item => !StringUtil.IsBlank(item))) + ")"; return display; } } public String Region { get; set; } public String Sport { get; set; } } private class OrganisationItemData : OrganisationListData { public String TypeDesc { get; set; } public String About { get; set; } public String Facilities { get; set; } public List Contacts { get; set; } public String Address { get; set; } public String PostalCode { get; set; } public List Associations { get; } = new List(); } private class AjaxResponse_Search_Organisation : AjaxResponse_Data { // Construction. public AjaxResponse_Search_Organisation(SaxModel_Online model) : base(model) { } // Organisation list. public OrganisationItemData Organisation { get; set; } } // Ajax request. [HttpPost] [Route("Search/Ajax/Organisation")] [Route("Search/Ajax/GetOrganisation")] public IActionResult Ajax_GetOrganisation(Model_Search_Organisations model) { String fn = GetType().Name + ".Ajax_GetOrganisation"; AjaxResponse_Search_Organisation responseData = new AjaxResponse_Search_Organisation(model); String messageTitle = Localiser["label.organisation"]; // 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); // ToDo May-2022 TESTING. //SaLogger.Info(fn + " Organisation: " + organisation.Name + "\nAbout: " + organisation.About + "\nFacilities: " + organisation.Facilities, true); // Populate response. OrganisationItemData organisationData = new OrganisationItemData() { Id = model.EncryptId(organisation.Id), Name = organisation.Name, CategoryDesc = Localiser.GetOrganisationCategoryCaption(organisation.OrganisationCategory), TypeDesc = Localiser.GetOrganisationTypeCaption(organisation.OrganisationType), SportName = model.GetSportCaption(organisation.SportIdPrimary), RegionName = model.GetRegionCaption(organisation.RegionIdPrimary), About = organisation.About, Facilities = organisation.Facilities, }; responseData.Organisation = organisationData; // Contacts. SaxContactData contactData = new SaxContactData(organisation.ContactData); if (contactData.Methods.Count > 0) { responseData.Organisation.Contacts = new List(); foreach (Sax.ContactMethod method in contactData.Methods) { AjaxResponse_Data.ItemLabelValue contact = new AjaxResponse_Data.ItemLabelValue() { Label = Localiser.GetContactMethodCaption(method), Value = SaxContactMethodHelper_Online.GetContactMethodHtml(method, contactData.GetContactMethodValue(method), Localiser) }; responseData.Organisation.Contacts.Add(contact); } } // Organisation address. SaxItemAddress address = ItemDataMgr.GetFirstItemAddressByItemAndType(organisation.GetItemId()); if (address != null) { String addressLines = (new List() { address.Line1, address.Line2, address.Line3 }).Concat(", ", "", "", true, true); String addressTownProvince = (new List() { address.Town, address.Province }).Concat(", ", "", "", true, true); organisationData.Address = (new List() { addressLines, addressTownProvince }).Concat("\n", "", "", true, true); organisationData.PostalCode = address.PostalCode; } // Associations. Dictionary> associationTypeGroups = new Dictionary>(); ColumnDfn colId = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.Id); ColumnDfn colAssociationType = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.AssociationType); ColumnDfn colItemTypeFrom = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.ItemTypeFrom); ColumnDfn colItemIdFrom = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.ItemIdFrom); ColumnDfn colOrganisationFrom_Name = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationFrom_Name); ColumnDfn colOrganisationFrom_SportIdPrimary = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationFrom_SportIdPrimary); ColumnDfn colOrganisationFrom_RegionIdPrimary = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationFrom_RegionIdPrimary); ColumnDfn colItemTypeTo = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.ItemTypeTo); ColumnDfn colItemIdTo = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.ItemIdTo); ColumnDfn colOrganisationTo_Name = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationTo_Name); ColumnDfn colOrganisationTo_SportIdPrimary = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationTo_SportIdPrimary); ColumnDfn colOrganisationTo_RegionIdPrimary = ItemDataMgr.GetItemAssociationColumnDfn(SaxItemAssociation.Column.OrganisationTo_RegionIdPrimary); List associationCols = new List() { colId, colAssociationType, colItemTypeFrom, colItemIdFrom, colOrganisationFrom_Name, colOrganisationFrom_SportIdPrimary, colOrganisationFrom_RegionIdPrimary, colItemTypeTo, colItemIdTo, colOrganisationTo_Name, colOrganisationTo_SportIdPrimary, colOrganisationTo_RegionIdPrimary }; SaxItemAssociation.Params prmAssociations = new SaxItemAssociation.Params(); prmAssociations.ItemIdsIncluded.Add(organisation.GetItemId()); prmAssociations.StatusCat = SaxItemAssociation.StatusCat.ActiveOnly; using (DbResultSet resultSet = ItemDataMgr.ExecuteItemAssociationQuery(associationCols, prmAssociations)) { while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) { NamedValue.Map values = resultSet.GetRecordValues(); SysId associationId = new SysId(values.GetLong(colId.DataName)); Sax.AssociationType associationType = (Sax.AssociationType)values.GetLong(colAssociationType.DataName); ItemId itemIdFrom = new ItemId((short)values.GetLong(colItemTypeFrom.DataName), new SysId(values.GetLong(colItemIdFrom.DataName))); ItemId itemIdTo = new ItemId((short)values.GetLong(colItemTypeTo.DataName), new SysId(values.GetLong(colItemIdTo.DataName))); bool associationTypeDirectionReversed = associationType == Sax.AssociationType.Affiliate && itemIdTo.Id.Equals(organisation.Id); // Determine association type group. SaxItemAssociation.TypeOptionData assocTypeOption = new SaxItemAssociation.TypeOptionData(associationType, associationTypeDirectionReversed, GetAssociationTypeOptionCaption(associationType, associationTypeDirectionReversed)); List organisations = associationTypeGroups.GetValue(assocTypeOption, null); if (organisations == null) associationTypeGroups.Add(assocTypeOption, organisations = new List()); // Populate organisation properties. SysId orgSportIdFrom = new SysId(values.GetLong(colOrganisationFrom_SportIdPrimary.DataName)); SysId orgRegionIdFrom = new SysId(values.GetLong(colOrganisationFrom_RegionIdPrimary.DataName)); SysId orgSportIdTo = new SysId(values.GetLong(colOrganisationTo_SportIdPrimary.DataName)); SysId orgRegionIdTo = new SysId(values.GetLong(colOrganisationTo_RegionIdPrimary.DataName)); if (itemIdTo.Id.Equals(organisation.Id)) { // 'From' item is the 'Other' organisation. AssociationOrganisationData assocOrgData = new AssociationOrganisationData(); assocOrgData.Name = values.GetString(colOrganisationFrom_Name.DataName); if (!orgSportIdFrom.Equals(orgSportIdTo)) assocOrgData.Sport = model.GetSportCaption(orgSportIdFrom); if (!orgRegionIdFrom.Equals(orgRegionIdTo)) assocOrgData.Region = model.GetRegionCaption(orgRegionIdFrom); organisations.Add(assocOrgData); } else { // 'To' item is the 'Other' organisation. AssociationOrganisationData assocOrgData = new AssociationOrganisationData(); assocOrgData.Name = values.GetString(colOrganisationTo_Name.DataName); if (!orgSportIdFrom.Equals(orgSportIdTo)) assocOrgData.Sport = model.GetSportCaption(orgSportIdTo); if (!orgRegionIdFrom.Equals(orgRegionIdTo)) assocOrgData.Region = model.GetRegionCaption(orgRegionIdTo); organisations.Add(assocOrgData); } } } // Populate associations to response. foreach (SaxItemAssociation.TypeOptionData associationTypeGroup in associationTypeGroups.Keys.OrderBy(item => (int)item.TypeOption)) { AssociationTypeData associationTypeData = new AssociationTypeData(); associationTypeData.Caption = associationTypeGroup.Caption; associationTypeData.Organisations.AddRange(associationTypeGroups.GetValue(associationTypeGroup, new List()).OrderBy(item => item.Name).ToList()); responseData.Organisation.Associations.Add(associationTypeData); } } // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- /// /// Caption to display above list of corresponding associated organisation for the 'target' organisation. /// private String GetAssociationTypeOptionCaption(Sax.AssociationType associationType, bool reversed) { switch (SaxItemAssociation.GetAssociationTypeOption(associationType, reversed)) { case AssociationTypeOption.AffiliateParent: return "Affiliated to"; case AssociationTypeOption.AffiliateChild: return "Affiliates"; case AssociationTypeOption.Partner: return "Partners"; } return "Unknown relationship"; } //------------------------------------------------------------------- } //======================================================================= }