using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Utils; using Saxonite.Net.Core.Web.Base.App; using Saxonite.Net.Core.Web.Online.App; using Saxonite.Net.Core.Web.Online.Models; using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Consoles; using Saxonite.Net.Standard.Base.Mgr; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Saxonite.Net.Core.Web.Online.Controllers { //======================================================================= // Online Activity Controller - Ajax actions only. //======================================================================= public partial class ActivityController : SaxController_Online { //------------------------------------------------------------------- // Construction. public ActivityController(SaxLocaliser localiser, ILogger logger) : base(localiser, logger) { } //------------------------------------------------------------------- // Data definitions. /// Activity details for home page list. private class ActivityResponseData { public short ItemType { get; set; } public String ItemTypeClass { get; set; } public String ItemId { get; set; } public String Organisation { get; set; } public String Author { get; set; } public String Caption { get; set; } public String Blurb { get; set; } public String Sport { get; set; } public String Region { get; set; } public int Reaction { get; set; } public String PublishedOnFmt { get; set; } } /// Article activity info. private class ActivityResponseData_Article { public ActivityResponseData_Article(SaxController_Online controller, SaxModel_Online model, SaxArticle article, SaxOrganisation organisation) { Organisation = organisation?.Name ?? null; Author = model.GetUserAccountDisplayName(article.UserAccountIdAuthor); Headline = article.Headline; Summary = article.Summary; Sport = model.GetSportCaption(article.SportIdPrimary); Region = model.GetRegionCaption(article.RegionIdPrimary); PublishedOnFmt = model.Localiser.FormatDate(article.PublishedAt); SaxArticle.ContentData content = SaxArticle.ExtractContent(article.BodyData); foreach (SaxArticle.ContentData.SegmentData segment in content.Segments) Content.Segments.Add(new ContentData.SegmentData(controller, segment)); } public String Organisation { get; set; } public String Author { get; set; } public String Headline { get; set; } public String Summary { get; set; } public String Sport { get; set; } public String Region { get; set; } public String PublishedOnFmt { get; set; } public class ContentData { public class SegmentData { public SegmentData(SaxController_Online controller, SaxArticle.ContentData.SegmentData segment) { if (segment.Body.IsValid()) { Body = new BodyData(); Body.Html = segment.Body.Html; } else if (segment.Image.IsValid()) { Image = new ImageData(); Image.Link = ArticleController.GetArticleImageLink(controller, segment.Image.ItemImageId); } } public class BodyData { public String Html { get; set; } } public BodyData Body { get; } public class ImageData { public String Link { get; set; } } public ImageData Image { get; } } public List Segments { get; } = new List(); } public ContentData Content { get; } = new ContentData(); } /// Event activity info. private class ActivityResponseData_Event { public ActivityResponseData_Event(SaxModel_Online model, SaxOrganisationEvent organisationEvent) { Organisation = model.GetOrganisationName(organisationEvent.OrganisationId); EventAt = DateUtil.Format(organisationEvent.EventAt, "d-MMM-yy"); if (organisationEvent.EventAt.Hour>0 || organisationEvent.EventAt.Minute > 0) EventAt += DateUtil.Format(organisationEvent.EventAt, " HH:ss"); Summary = organisationEvent.Summary; Details = organisationEvent.Details; Sport = model.GetSportCaption(organisationEvent.SportIdPrimary); Region = model.GetRegionCaption(organisationEvent.RegionIdCountry); PublishedOnFmt = model.Localiser.FormatDate(organisationEvent.PublishedAt); } public String Organisation { get; set; } public String EventAt{ get; set; } public String Summary { get; set; } public String Details { get; set; } public String Sport { get; set; } public String Region { get; set; } public String PublishedOnFmt { get; set; } } /// Opportunity activity info. private class ActivityResponseData_Opportunity { public ActivityResponseData_Opportunity(SaxModel_Online model, SaxOrganisationOpportunity opportunity) { Organisation = model.GetOrganisationName(opportunity.OrganisationId); Position = opportunity.Position; Outline = opportunity.Outline; Sport = model.GetSportCaption(opportunity.SportIdPrimary); Region = model.GetRegionCaption(opportunity.RegionIdPrimary); PublishedOnFmt = model.Localiser.FormatDate(opportunity.PublishedAt); } public String Organisation { get; set; } public String Position { get; set; } public String Outline { get; set; } public String Sport { get; set; } public String Region { get; set; } public String PublishedOnFmt { get; set; } } //------------------------------------------------------------------- // Activities //------------------------------------------------------------------- private class AjaxResponse_ActivityList : AjaxResponse_Base { public List Activities { get; } = new List(); } //------------------------------------------------------------------- [HttpPost] [Route("Activity/Ajax/GetList")] [Route("Activity/Ajax/GetActivityList")] [Route("Activity/Ajax/GetActivities")] public IActionResult Ajax_GetActivityList(Model_Activity model) { String fn = GetType().Name + ".Ajax_GetActivityList"; String messageTitle = Localiser["activity.caption.activities"]; AjaxResponse_ActivityList responseData = new AjaxResponse_ActivityList(); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); SaxSessionData_Online sessionData = SessionData_Online; // User context. SysId userAccountId = UserAccountId; SaxActivityConsole.IndexContext indexContext = new SaxActivityConsole.IndexContext(userAccountId); // Period. indexContext.EffectiveTo = DateTime.Today; // Regions. if (SysId.IsValid(sessionData.User.RegionIdProvince)) indexContext.RegionIds.Add(sessionData.User.RegionIdProvince); else if (SysId.IsValid(sessionData.User.RegionIdCountry)) indexContext.RegionIds.Add(sessionData.User.RegionIdCountry); // Sports. indexContext.SportIds.AddRange(sessionData.Profile.Sports.Select(item => item.SportId)); // Populate activities. List activityItemIds = new List(); SaxActivityConsole.IndexResults indexResults = ActivityConsole.QueryIndex(indexContext); foreach (SaxActivityConsole.IndexResults.ActivityData itemData in indexResults.Items) { activityItemIds.Add(itemData.ItemId); ActivityResponseData activityData = new ActivityResponseData(); activityData.ItemType = itemData.ItemId.Type; if (itemData.ItemId.Type == (int)Sax.DataItemType.Article) activityData.ItemTypeClass = "Article"; else if (itemData.ItemId.Type == (int)Sax.DataItemType.OrganisationEvent) activityData.ItemTypeClass = "Event"; else if (itemData.ItemId.Type == (int)Sax.DataItemType.OrganisationOpportunity) activityData.ItemTypeClass = "Opportunity"; // ToDo Mask activity index Id with cross-reference stored in session data. activityData.ItemId = model.EncryptId(itemData.ItemId.Id); activityData.Organisation = itemData.Organisation; activityData.Author = itemData.Author; activityData.Caption = itemData.Caption; activityData.Blurb = itemData.Blurb; activityData.Sport = Localiser.GetSportName(itemData.SportId, itemData.SportName); activityData.Region = Localiser.GetRegionName(itemData.RegionId, itemData.RegionName); activityData.Reaction = (int)itemData.Reaction; activityData.PublishedOnFmt = Localiser.FormatDate(itemData.EffectiveOn); responseData.Activities.Add(activityData); } if (!activityItemIds.IsEmpty()) ActivityConsole.RecordUserActivitiesListed(userAccountId, activityItemIds, DbUpdateInfo); // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Activity Info //------------------------------------------------------------------- private class AjaxResponse_ActivityInfo : AjaxResponse_Base { public ActivityResponseData_Article Article { get; set; } public ActivityResponseData_Event Event { get; set; } public ActivityResponseData_Opportunity Opportunity { get; set; } } //------------------------------------------------------------------- [HttpPost] [Route("Activity/Ajax/GetInfo")] [Route("Activity/Ajax/GetItemInfo")] [Route("Activity/Ajax/GetActivityInfo")] [Route("Activity/Ajax/GetActivity")] public IActionResult Ajax_GetActivityInfo(Model_Activity model) { String fn = GetType().Name + ".Ajax_GetActivityInfo"; String messageTitle = Localiser["activity.caption.activity"]; AjaxResponse_ActivityInfo responseData = new AjaxResponse_ActivityInfo(); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); SaxSessionData_Online sessionData = SessionData_Online; // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Identify activity. Sax.DataItemType itemType = (Sax.DataItemType)StringUtil.ToShort(model.ActivityItemType); SysId itemId = model.ExtractSysId(model.ActivityItemId); if (itemType <= 0 || !SysId.IsValid(itemId)) { SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + GetLogSuffix()); return Json(responseData); } // Retrieve activity details. if (itemType == Sax.DataItemType.Article) { // Article. SaxArticle article = ActivityMgr.GetArticleById(itemId); disposableItems.Add(article); if (article == null) { SaLogger.Warn(fn + " Article not found for Activity Id: " + itemId.ToString() + "." + GetLogSuffix()); return Json(responseData); } SaxOrganisation organisation = AccountMgr.GetOrganisationById(article.OrganisationId); disposableItems.Add(organisation); responseData.Article = new ActivityResponseData_Article(this, model, article, organisation); } else if (itemType == Sax.DataItemType.OrganisationEvent) { // Organisation Event. SaxOrganisationEvent organisationEvent = ActivityMgr.GetOrganisationEventById(itemId); disposableItems.Add(organisationEvent); if (organisationEvent == null) { SaLogger.Warn(fn + " Event not found for Activity Id: " + itemId.ToString() + "." + GetLogSuffix()); return Json(responseData); } responseData.Event = new ActivityResponseData_Event(model, organisationEvent); } else if (itemType == Sax.DataItemType.OrganisationOpportunity) { // Organisation Opportunity. SaxOrganisationOpportunity opportunity = ActivityMgr.GetOrganisationOpportunityById(itemId); disposableItems.Add(opportunity); if (opportunity == null) { SaLogger.Warn(fn + " Opportunity not found for Activity Id: " + itemId.ToString() + "." + GetLogSuffix()); return Json(responseData); } responseData.Opportunity = new ActivityResponseData_Opportunity(model, opportunity); } // Record activty viewing. if (!ActivityConsole.RecordUserActivityViewed(UserAccountId, new ItemId((short)itemType, itemId), DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to record Activity Viewing: " + ActivityConsole.ErrorStateMessage + "." + GetLogSuffix()); return Json(responseData); } } // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Activity Reaction. //------------------------------------------------------------------- private class AjaxResponse_ActivityReaction : AjaxResponse_Base { public int Reaction { get; set; } } //------------------------------------------------------------------- [HttpPost] [Route("Activity/Ajax/React")] [Route("Activity/Ajax/Reaction")] public IActionResult Ajax_SetActivityReaction(Model_Activity model) { String fn = GetType().Name + ".Ajax_SetActivityReaction"; String messageTitle = Localiser["activity.caption.activity"]; AjaxResponse_ActivityReaction responseData = new AjaxResponse_ActivityReaction(); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); SaxSessionData_Online sessionData = SessionData_Online; // Identify activity. Sax.DataItemType itemType = (Sax.DataItemType)StringUtil.ToShort(model.ActivityItemType); SysId itemId = model.ExtractSysId(model.ActivityItemId); if (itemType <= 0 || !SysId.IsValid(itemId)) { SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + GetLogSuffix()); return Json(responseData); } // Record activity reaction. if (!ActivityConsole.RecordUserActivityReaction(UserAccountId, new ItemId((short)itemType, itemId), model.GetActivityReaction(), DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to record Activity Reaction: " + ActivityConsole.ErrorStateMessage + "." + GetLogSuffix()); return Json(responseData); } // Complete response. responseData.Reaction = (int)model.GetActivityReaction(); responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- } //======================================================================= }