diff --git a/src/EventHub.Application.Contracts/Events/IEventAppService.cs b/src/EventHub.Application.Contracts/Events/IEventAppService.cs index 07db0ad..dd253d3 100644 --- a/src/EventHub.Application.Contracts/Events/IEventAppService.cs +++ b/src/EventHub.Application.Contracts/Events/IEventAppService.cs @@ -21,5 +21,7 @@ namespace EventHub.Events Task IsEventOwnerAsync(Guid id); Task UpdateAsync(Guid id, UpdateEventDto input); + + Task GetCoverImageAsync(Guid id); } } diff --git a/src/EventHub.Application/Events/EventAppService.cs b/src/EventHub.Application/Events/EventAppService.cs index fb384c0..38587d1 100644 --- a/src/EventHub.Application/Events/EventAppService.cs +++ b/src/EventHub.Application/Events/EventAppService.cs @@ -261,19 +261,19 @@ namespace EventHub.Events await _eventRepository.UpdateAsync(@event); } - - private async Task SaveCoverImageAsync(Guid id, byte[] coverImageContent) + + public async Task GetCoverImageAsync(Guid id) { var blobName = id.ToString(); - await _eventBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting: true); + return await _eventBlobContainer.GetAllBytesOrNullAsync(blobName); } - private async Task GetCoverImageAsync(Guid id) + private async Task SaveCoverImageAsync(Guid id, byte[] coverImageContent) { var blobName = id.ToString(); - return await _eventBlobContainer.GetAllBytesOrNullAsync(blobName); + await _eventBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting: true); } } } \ No newline at end of file diff --git a/src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml b/src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml index 9293a6f..01bbc0b 100644 --- a/src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml +++ b/src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml @@ -9,6 +9,8 @@ @using EventHub.Web.Theme.Themes.EventHub.Components.Footer @using EventHub.Web.Theme.Themes.EventHub.Components.MainNavbar @using EventHub.Web.Theme.Themes.EventHub.Components.PageAlerts +@using EventHub.Web +@using Microsoft.AspNetCore.Http.Extensions @inject IBrandingProvider BrandingProvider @inject IPageLayout PageLayout @{ @@ -39,6 +41,18 @@ @pageTitle + @* TODO(berkansasmaz): Get SEO content from the marketing team *@ + + + + + + + + + + + @@ -46,7 +60,7 @@ - + @await Component.InvokeAsync(typeof(WidgetStylesViewComponent)) @@ -56,19 +70,19 @@ @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Application) - @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application) - @(await Component.InvokeAsync()) - @(await Component.InvokeAsync()) - @await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.First, StandardLayouts.Application) - @RenderBody() - @await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.Last, StandardLayouts.Application) - @(await Component.InvokeAsync()) - - - - - @await Component.InvokeAsync(typeof(WidgetScriptsViewComponent)) - @await RenderSectionAsync("scripts", false) - @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application) +@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application) +@(await Component.InvokeAsync()) +@(await Component.InvokeAsync()) +@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.First, StandardLayouts.Application) +@RenderBody() +@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.Last, StandardLayouts.Application) +@(await Component.InvokeAsync()) + + + + +@await Component.InvokeAsync(typeof(WidgetScriptsViewComponent)) +@await RenderSectionAsync("scripts", false) +@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application) \ No newline at end of file diff --git a/src/EventHub.Web/Controllers/EventController.cs b/src/EventHub.Web/Controllers/EventController.cs index fcc385b..f5497f3 100644 --- a/src/EventHub.Web/Controllers/EventController.cs +++ b/src/EventHub.Web/Controllers/EventController.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Threading.Tasks; using EventHub.Events; @@ -28,5 +29,19 @@ namespace EventHub.Web.Controllers ViewData = ViewData }; } + + [HttpGet] + [Route("cover-picture-source/{eventId}")] + public async Task GetArticleCoverImageAsync(Guid eventId) + { + var coverImageContent = await _eventAppService.GetCoverImageAsync(eventId); + + if (coverImageContent == null) + { + return NotFound(); + } + + return File(coverImageContent, "image/jpeg"); + } } } \ No newline at end of file diff --git a/src/EventHub.Web/Pages/Events/Detail.cshtml b/src/EventHub.Web/Pages/Events/Detail.cshtml index 191d9bc..5967d60 100644 --- a/src/EventHub.Web/Pages/Events/Detail.cshtml +++ b/src/EventHub.Web/Pages/Events/Detail.cshtml @@ -1,6 +1,7 @@ @page "/events/{url}" @inject IHtmlLocalizer L @using EventHub.Localization +@using EventHub.Web @using EventHub.Web.Helpers @using EventHub.Web.Pages.Events @using EventHub.Web.Pages.Events.Components.AttendeesArea @@ -13,6 +14,37 @@ @inject ICurrentUser CurrentUser @inject IClock Clock @model EventHub.Web.Pages.Events.DetailPageModel + +@section scripts { + +} + +@{ + string description = Model.Event.Description.Length >= 160 ? Model.Event.Description.TruncateWithPostfix(155) : Model.Event.Description; + string title = Model.Event.Title; + string coverImageUrl; + + if (Model.Event.CoverImageContent is null) + { + // TODO(berkansasmaz): Get a default image from the design team to be used in social media posts + coverImageUrl = EventHubExternalUrls.EhWww + "/assets/slide.jpg"; + } + else + { + coverImageUrl = $"{EventHubExternalUrls.EhWww}/api/event/cover-picture-source/{Model.Event.Id}"; + } + + ViewBag.Title = title; + ViewBag.Description = description; + ViewBag.OgTitle = title; + ViewBag.OgType = "event"; + ViewBag.OgDescription = description; + ViewBag.TwitterTitle = title; + ViewBag.TwitterDescription = description; + ViewBag.TwitterImage = coverImageUrl; + ViewBag.OgImage = coverImageUrl; +} +
@@ -38,7 +70,7 @@
-

@Model.Event.Title

+

@Model.Event.Title

@await Component.InvokeAsync(typeof(LocationAreaViewComponent), new {eventId = Model.Event.Id})
Owner
@@ -54,12 +86,18 @@ } @await Component.InvokeAsync(typeof(RegistrationAreaViewComponent), new {eventId = Model.Event.Id}) +
Share Event
+
Event Description
-

+

@Model.Event.Description

diff --git a/src/EventHub.Web/Pages/Events/Detail.js b/src/EventHub.Web/Pages/Events/Detail.js new file mode 100644 index 0000000..5bcb862 --- /dev/null +++ b/src/EventHub.Web/Pages/Events/Detail.js @@ -0,0 +1,30 @@ +$(function () { + var initSocialShareLinks = function () { + var pageHeader = $('#EventTitle').text(); + + $('#TwitterShareLink').attr( + 'href', + 'https://twitter.com/intent/tweet?text=' + + encodeURI( + pageHeader + ' | EventHub | ' + window.location.href + ) + ); + + $('#LinkedinShareLink').attr( + 'href', + 'https://www.linkedin.com/shareArticle?' + + 'url=' + + encodeURI(window.location.href) + + '&' + + 'mini=true' + ); + $('#FacebookShareLink').attr( + 'href', + 'https://www.facebook.com/sharer/sharer.php?' + + 'u=' + + encodeURI(window.location.href) + ); + }; + + initSocialShareLinks(); +}); \ No newline at end of file