@ -0,0 +1,28 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers | |||
{ | |||
using Microsoft.AspNetCore.Hosting; | |||
using Microsoft.AspNetCore.Mvc; | |||
using System.IO; | |||
public class PicController : Controller | |||
{ | |||
private readonly IHostingEnvironment _env; | |||
public PicController(IHostingEnvironment env) | |||
{ | |||
_env = env; | |||
} | |||
[HttpGet] | |||
[Route("api/v1/campaigns/{campaignId:int}/pic")] | |||
public IActionResult GetImage(int campaignId) | |||
{ | |||
var webRoot = _env.WebRootPath; | |||
var path = Path.Combine(webRoot, campaignId + ".png"); | |||
var buffer = System.IO.File.ReadAllBytes(path); | |||
return File(buffer, "image/png"); | |||
} | |||
} | |||
} |
@ -0,0 +1,80 @@ | |||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers | |||
{ | |||
using Microsoft.AspNetCore.Authorization; | |||
using Microsoft.AspNetCore.Mvc; | |||
using Microsoft.eShopOnContainers.WebMVC.Models; | |||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||
using System.Collections.Generic; | |||
using System.Threading.Tasks; | |||
[Authorize] | |||
public class CampaignsController : Controller | |||
{ | |||
private ICampaignService _campaignService; | |||
public CampaignsController(ICampaignService campaignService) => | |||
_campaignService = campaignService; | |||
public async Task<IActionResult> Index() | |||
{ | |||
var campaignDtoList = await _campaignService.GetCampaigns(); | |||
if(campaignDtoList is null) | |||
{ | |||
return View(); | |||
} | |||
var campaignList = MapCampaignModelListToDtoList(campaignDtoList); | |||
return View(campaignList); | |||
} | |||
public async Task<IActionResult> Details(int id) | |||
{ | |||
var campaignDto = await _campaignService.GetCampaignById(id); | |||
if (campaignDto is null) | |||
{ | |||
return NotFound(); | |||
} | |||
var campaign = new Campaign | |||
{ | |||
Id = campaignDto.Id, | |||
Name = campaignDto.Name, | |||
Description = campaignDto.Description, | |||
From = campaignDto.From, | |||
To = campaignDto.To, | |||
PictureUri = campaignDto.PictureUri | |||
}; | |||
return View(campaign); | |||
} | |||
private List<Campaign> MapCampaignModelListToDtoList(IEnumerable<CampaignDTO> campaignDtoList) | |||
{ | |||
var campaignList = new List<Campaign>(); | |||
foreach(var campaignDto in campaignDtoList) | |||
{ | |||
campaignList.Add(MapCampaignDtoToModel(campaignDto)); | |||
} | |||
return campaignList; | |||
} | |||
private Campaign MapCampaignDtoToModel(CampaignDTO campaign) | |||
{ | |||
return new Campaign | |||
{ | |||
Id = campaign.Id, | |||
Name = campaign.Name, | |||
Description = campaign.Description, | |||
From = campaign.From, | |||
To = campaign.To, | |||
PictureUri = campaign.PictureUri | |||
}; | |||
} | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
namespace Microsoft.eShopOnContainers.WebMVC.Models | |||
{ | |||
using System; | |||
public class CampaignDTO | |||
{ | |||
public int Id { get; set; } | |||
public string Name { get; set; } | |||
public string Description { get; set; } | |||
public DateTime From { get; set; } | |||
public DateTime To { get; set; } | |||
public string PictureUri { get; set; } | |||
} | |||
} |
@ -0,0 +1,71 @@ | |||
namespace Microsoft.eShopOnContainers.WebMVC.Services | |||
{ | |||
using global::WebMVC.Infrastructure; | |||
using Microsoft.AspNetCore.Authentication; | |||
using Microsoft.AspNetCore.Http; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; | |||
using Microsoft.eShopOnContainers.WebMVC.Models; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Threading.Tasks; | |||
public class CampaignService : ICampaignService | |||
{ | |||
private readonly IOptionsSnapshot<AppSettings> _settings; | |||
private readonly IHttpClient _apiClient; | |||
private readonly ILogger<CampaignService> _logger; | |||
private readonly string _remoteServiceBaseUrl; | |||
private readonly IHttpContextAccessor _httpContextAccesor; | |||
public CampaignService(IOptionsSnapshot<AppSettings> settings, IHttpClient httpClient, | |||
ILogger<CampaignService> logger, IHttpContextAccessor httpContextAccesor) | |||
{ | |||
_settings = settings; | |||
_apiClient = httpClient; | |||
_logger = logger; | |||
_remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/api/v1/campaigns/"; | |||
_httpContextAccesor = httpContextAccesor ?? throw new ArgumentNullException(nameof(httpContextAccesor)); | |||
} | |||
public async Task<IEnumerable<CampaignDTO>> GetCampaigns() | |||
{ | |||
var userId = GetUserIdentity(); | |||
var allCampaignItemsUri = API.Marketing.GetAllCampaigns(_remoteServiceBaseUrl, Guid.Parse(userId)); | |||
var authorizationToken = await GetUserTokenAsync(); | |||
var dataString = await _apiClient.GetStringAsync(allCampaignItemsUri, authorizationToken); | |||
var response = JsonConvert.DeserializeObject<IEnumerable<CampaignDTO>>(dataString); | |||
return response; | |||
} | |||
public async Task<CampaignDTO> GetCampaignById(int id) | |||
{ | |||
var userId = GetUserIdentity(); | |||
var campaignByIdItemUri = API.Marketing.GetAllCampaignById(_remoteServiceBaseUrl, id); | |||
var authorizationToken = await GetUserTokenAsync(); | |||
var dataString = await _apiClient.GetStringAsync(campaignByIdItemUri, authorizationToken); | |||
var response = JsonConvert.DeserializeObject<CampaignDTO>(dataString); | |||
return response; | |||
} | |||
private string GetUserIdentity() | |||
{ | |||
return _httpContextAccesor.HttpContext.User.FindFirst("sub").Value; | |||
} | |||
private async Task<string> GetUserTokenAsync() | |||
{ | |||
var context = _httpContextAccesor.HttpContext; | |||
return await context.Authentication.GetTokenAsync("access_token"); | |||
} | |||
} | |||
} |
@ -0,0 +1,13 @@ | |||
namespace Microsoft.eShopOnContainers.WebMVC.Services | |||
{ | |||
using Microsoft.eShopOnContainers.WebMVC.Models; | |||
using System.Collections.Generic; | |||
using System.Threading.Tasks; | |||
public interface ICampaignService | |||
{ | |||
Task<IEnumerable<CampaignDTO>> GetCampaigns(); | |||
Task<CampaignDTO> GetCampaignById(int id); | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
namespace Microsoft.eShopOnContainers.WebMVC.ViewModels | |||
{ | |||
using System; | |||
public class Campaign | |||
{ | |||
public int Id { get; set; } | |||
public string Name { get; set; } | |||
public string Description { get; set; } | |||
public DateTime From { get; set; } | |||
public DateTime To { get; set; } | |||
public string PictureUri { get; set; } | |||
} | |||
} |
@ -0,0 +1,28 @@ | |||
@{ | |||
ViewData["Title"] = "Campaign details"; | |||
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.Campaign | |||
} | |||
<section class="esh-campaigns-hero"> | |||
<div class="container"> | |||
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> | |||
</div> | |||
</section> | |||
@Html.Partial("_Header", new List<Header>() { | |||
new Header() { Controller = "Catalog", Text = "Back to catalog" }, | |||
new Header() { Controller = "Campaigns", Text = "Back to Campaigns" } }) | |||
<div class="container"> | |||
<div class="card esh-campaigns-items"> | |||
<img class="card-img-top" src="@Model.PictureUri" alt="Card image cap"> | |||
<div class="card-block"> | |||
<h4 class="card-title">@Model.Name</h4> | |||
<p class="card-text">@Model.Description</p> | |||
<p class="card-text"> | |||
<small class="text-muted"> | |||
From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") | |||
</small> | |||
</p> | |||
</div> | |||
</div> | |||
</div> |
@ -0,0 +1,36 @@ | |||
@{ | |||
ViewData["Title"] = "Campaigns"; | |||
@model IEnumerable<Campaign> | |||
} | |||
<section class="esh-campaigns-hero"> | |||
<div class="container"> | |||
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> | |||
</div> | |||
</section> | |||
@Html.Partial("_Header", new List<Header>() { | |||
new Header() { Controller = "Catalog", Text = "Back to catalog" } }) | |||
<div class="container"> | |||
<div class="card-group esh-campaigns-items row"> | |||
@foreach (var campaign in Model ?? Enumerable.Empty<Campaign>()) | |||
{ | |||
<div class="esh-campaigns-item col-md-4"> | |||
<form asp-controller="Campaigns" asp-action="Details" asp-route-id="@campaign.Id"> | |||
<div class="card-block"> | |||
<h4 class="card-title esh-campaigns-name">@campaign.Name</h4> | |||
<img class="card-img-top esh-campaigns-thumbnail" src="@campaign.PictureUri" alt="@campaign.Name"> | |||
<input class="esh-campaigns-button" type="submit" value="More details"> | |||
</div> | |||
<div class="card-footer"> | |||
<small class="text-muted"> | |||
From @campaign.From.ToString("MMMM dd, yyyy") until @campaign.To.ToString("MMMM dd, yyyy") | |||
</small> | |||
</div> | |||
</form> | |||
</div> | |||
} | |||
</div> | |||
</div> |
@ -0,0 +1,98 @@ | |||
.esh-campaigns-hero { | |||
background-image: url("../../images/main_banner.png"); | |||
background-size: cover; | |||
height: 260px; | |||
width: 100%; | |||
} | |||
.esh-campaigns-title { | |||
position: relative; | |||
top: 74.28571px; | |||
} | |||
.esh-campaigns-label::before { | |||
color: rgba(255, 255, 255, 0.5); | |||
content: attr(data-title); | |||
font-size: 0.65rem; | |||
margin-top: 0.65rem; | |||
margin-left: 0.5rem; | |||
position: absolute; | |||
text-transform: uppercase; | |||
z-index: 1; | |||
} | |||
.esh-campaigns-label::after { | |||
background-image: url("../../images/arrow-down.png"); | |||
height: 7px; | |||
content: ''; | |||
position: absolute; | |||
right: 1.5rem; | |||
top: 2.5rem; | |||
width: 10px; | |||
z-index: 1; | |||
} | |||
.esh-campaigns-items { | |||
margin-top: 1rem; | |||
} | |||
.esh-campaigns-item { | |||
text-align: center; | |||
margin-bottom: 1.5rem; | |||
width: 33%; | |||
display: inline-block; | |||
float: none !important; | |||
} | |||
@media screen and (max-width: 1024px) { | |||
.esh-campaigns-item { | |||
width: 50%; | |||
} | |||
} | |||
@media screen and (max-width: 768px) { | |||
.esh-campaigns-item { | |||
width: 100%; | |||
} | |||
} | |||
.esh-campaigns-thumbnail { | |||
max-width: 370px; | |||
width: 100%; | |||
} | |||
.esh-campaigns-button { | |||
background-color: #83D01B; | |||
border: none; | |||
color: #FFFFFF; | |||
cursor: pointer; | |||
font-size: 1rem; | |||
height: 3rem; | |||
margin-top: 1rem; | |||
transition: all 0.35s; | |||
width: 80%; | |||
} | |||
.esh-campaigns-button.is-disabled { | |||
opacity: .5; | |||
pointer-events: none; | |||
} | |||
.esh-campaigns-button:hover { | |||
background-color: #4a760f; | |||
transition: all 0.35s; | |||
} | |||
.esh-campaigns-name { | |||
font-size: 1rem; | |||
font-weight: 300; | |||
margin-top: .5rem; | |||
text-align: center; | |||
text-transform: uppercase; | |||
} | |||
.esh-campaigns-description { | |||
text-align: center; | |||
font-weight: 300; | |||
font-size: 14px; | |||
} | |||