@ -1,100 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers | |||||
{ | |||||
using AspNetCore.Authorization; | |||||
using AspNetCore.Mvc; | |||||
using global::WebMVC.Services.ModelDTOs; | |||||
using global::WebMVC.Services; | |||||
using global::WebMVC.ViewModels; | |||||
using Microsoft.Extensions.Options; | |||||
using Services; | |||||
using System; | |||||
using System.Threading.Tasks; | |||||
using ViewModels; | |||||
using ViewModels.Pagination; | |||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect; | |||||
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] | |||||
public class CampaignsController : Controller | |||||
{ | |||||
private readonly ICampaignService _campaignService; | |||||
private readonly ILocationService _locationService; | |||||
private readonly AppSettings _settings; | |||||
public CampaignsController(ICampaignService campaignService, ILocationService locationService, IOptionsSnapshot<AppSettings> settings) | |||||
{ | |||||
_campaignService = campaignService; | |||||
_settings = settings.Value; | |||||
_locationService = locationService; | |||||
} | |||||
public async Task<IActionResult> Index(int page = 0, int pageSize = 10) | |||||
{ | |||||
var campaignList = await _campaignService.GetCampaigns(pageSize, page); | |||||
if(campaignList is null) | |||||
{ | |||||
return View(); | |||||
} | |||||
var totalPages = (int) Math.Ceiling((decimal) campaignList.Count / pageSize); | |||||
var vm = new CampaignViewModel | |||||
{ | |||||
CampaignItems = campaignList.Data, | |||||
PaginationInfo = new PaginationInfo | |||||
{ | |||||
ActualPage = page, | |||||
ItemsPerPage = campaignList.Data.Count, | |||||
TotalItems = campaignList.Count, | |||||
TotalPages = totalPages, | |||||
Next = page == totalPages - 1 ? "is-disabled" : "", | |||||
Previous = page == 0 ? "is-disabled" : "" | |||||
} | |||||
}; | |||||
ViewBag.IsCampaignDetailFunctionActive = _settings.ActivateCampaignDetailFunction; | |||||
return View(vm); | |||||
} | |||||
public async Task<IActionResult> Details(int id) | |||||
{ | |||||
var campaignDto = await _campaignService.GetCampaignById(id); | |||||
if (campaignDto is null) | |||||
{ | |||||
return NotFound(); | |||||
} | |||||
var campaign = new CampaignItem | |||||
{ | |||||
Id = campaignDto.Id, | |||||
Name = campaignDto.Name, | |||||
Description = campaignDto.Description, | |||||
From = campaignDto.From, | |||||
To = campaignDto.To, | |||||
PictureUri = campaignDto.PictureUri | |||||
}; | |||||
return View(campaign); | |||||
} | |||||
[HttpPost] | |||||
public async Task<IActionResult> CreateNewUserLocation(CampaignViewModel model) | |||||
{ | |||||
if (ModelState.IsValid) | |||||
{ | |||||
var location = new LocationDTO() | |||||
{ | |||||
Longitude = model.Lon, | |||||
Latitude = model.Lat | |||||
}; | |||||
await _locationService.CreateOrUpdateUserLocation(location); | |||||
return RedirectToAction(nameof(Index)); | |||||
} | |||||
return View(nameof(Index), model); | |||||
} | |||||
} | |||||
} |
@ -1,49 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.WebMVC.Services | |||||
{ | |||||
using global::WebMVC.Infrastructure; | |||||
using Microsoft.Extensions.Logging; | |||||
using Microsoft.Extensions.Options; | |||||
using Newtonsoft.Json; | |||||
using System.Net.Http; | |||||
using System.Threading.Tasks; | |||||
using ViewModels; | |||||
public class CampaignService : ICampaignService | |||||
{ | |||||
private readonly IOptions<AppSettings> _settings; | |||||
private readonly HttpClient _httpClient; | |||||
private readonly ILogger<CampaignService> _logger; | |||||
private readonly string _remoteServiceBaseUrl; | |||||
public CampaignService(IOptions<AppSettings> settings, HttpClient httpClient, ILogger<CampaignService> logger) | |||||
{ | |||||
_settings = settings; | |||||
_httpClient = httpClient; | |||||
_logger = logger; | |||||
_remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/m/api/v1/campaigns/"; | |||||
} | |||||
public async Task<Campaign> GetCampaigns(int pageSize, int pageIndex) | |||||
{ | |||||
var uri = API.Marketing.GetAllCampaigns(_remoteServiceBaseUrl, pageSize, pageIndex); | |||||
var responseString = await _httpClient.GetStringAsync(uri); | |||||
var response = JsonConvert.DeserializeObject<Campaign>(responseString); | |||||
return response; | |||||
} | |||||
public async Task<CampaignItem> GetCampaignById(int id) | |||||
{ | |||||
var uri = API.Marketing.GetAllCampaignById(_remoteServiceBaseUrl, id); | |||||
var responseString = await _httpClient.GetStringAsync(uri); | |||||
var response = JsonConvert.DeserializeObject<CampaignItem>(responseString); | |||||
return response; | |||||
} | |||||
} | |||||
} |
@ -1,13 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.WebMVC.Services | |||||
{ | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using ViewModels; | |||||
public interface ICampaignService | |||||
{ | |||||
Task<Campaign> GetCampaigns(int pageSize, int pageIndex); | |||||
Task<CampaignItem> GetCampaignById(int id); | |||||
} | |||||
} |
@ -1,10 +0,0 @@ | |||||
using System.Threading.Tasks; | |||||
using WebMVC.Services.ModelDTOs; | |||||
namespace WebMVC.Services | |||||
{ | |||||
public interface ILocationService | |||||
{ | |||||
Task CreateOrUpdateUserLocation(LocationDTO location); | |||||
} | |||||
} |
@ -1,38 +0,0 @@ | |||||
using Microsoft.eShopOnContainers.WebMVC; | |||||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||||
using Microsoft.Extensions.Logging; | |||||
using Microsoft.Extensions.Options; | |||||
using Newtonsoft.Json; | |||||
using System.Net.Http; | |||||
using System.Threading.Tasks; | |||||
using WebMVC.Infrastructure; | |||||
using WebMVC.Services.ModelDTOs; | |||||
namespace WebMVC.Services | |||||
{ | |||||
public class LocationService : ILocationService | |||||
{ | |||||
private readonly IOptions<AppSettings> _settings; | |||||
private readonly HttpClient _httpClient; | |||||
private readonly ILogger<CampaignService> _logger; | |||||
private readonly string _remoteServiceBaseUrl; | |||||
public LocationService(HttpClient httpClient, IOptions<AppSettings> settings, ILogger<CampaignService> logger) | |||||
{ | |||||
_httpClient = httpClient; | |||||
_settings = settings; | |||||
_logger = logger; | |||||
_remoteServiceBaseUrl = $"{_settings.Value.MarketingUrl}/l/api/v1/locations/"; | |||||
} | |||||
public async Task CreateOrUpdateUserLocation(LocationDTO location) | |||||
{ | |||||
var uri = API.Locations.CreateOrUpdateUserLocation(_remoteServiceBaseUrl); | |||||
var locationContent = new StringContent(JsonConvert.SerializeObject(location), System.Text.Encoding.UTF8, "application/json"); | |||||
var response = await _httpClient.PostAsync(uri, locationContent); | |||||
response.EnsureSuccessStatusCode(); | |||||
} | |||||
} | |||||
} |
@ -1,20 +0,0 @@ | |||||
namespace WebMVC.ViewModels | |||||
{ | |||||
using System.Collections.Generic; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; | |||||
using WebMVC.ViewModels.Annotations; | |||||
using Newtonsoft.Json; | |||||
using System.ComponentModel.DataAnnotations; | |||||
public class CampaignViewModel | |||||
{ | |||||
public IEnumerable<CampaignItem> CampaignItems { get; set; } | |||||
public PaginationInfo PaginationInfo { get; set; } | |||||
[LongitudeCoordinate, Required] | |||||
public double Lon { get; set; } = -122.315752; | |||||
[LatitudeCoordinate, Required] | |||||
public double Lat { get; set; } = 47.604610; | |||||
} | |||||
} |
@ -1,31 +0,0 @@ | |||||
@model CampaignItem | |||||
@{ | |||||
ViewData["Title"] = "Campaign details"; | |||||
var headerList= new List<Header>() { | |||||
new Header() { Controller = "Catalog", Text = "Back to catalog" }, | |||||
new Header() { Controller = "Campaigns", Text = "Back to Campaigns" } }; | |||||
} | |||||
<section class="esh-campaigns-hero"> | |||||
<div class="container"> | |||||
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> | |||||
</div> | |||||
</section> | |||||
<partial name="_Header" model="headerList" /> | |||||
<div class="container"> | |||||
<div class="card esh-campaigns-items"> | |||||
<img class="card-img-top" src="@Model.PictureUri" alt="Card image cap"> | |||||
<div class="card-body"> | |||||
<h4 class="card-title">@Model.Name</h4> | |||||
<p class="card-text">@Model.Description</p> | |||||
</div> | |||||
<div class="card-footer"> | |||||
<small class="text-muted"> | |||||
From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> |
@ -1,79 +0,0 @@ | |||||
@model WebMVC.ViewModels.CampaignViewModel | |||||
@{ | |||||
ViewData["Title"] = "Campaigns"; | |||||
var headerList= new List<Header>() { | |||||
new Header() { Controller = "Catalog", Text = "Back to catalog" } }; | |||||
} | |||||
<section class="esh-campaigns-hero"> | |||||
<div class="container"> | |||||
<img class="esh-campaigns-title" src="~/images/main_banner_text.png" /> | |||||
</div> | |||||
</section> | |||||
<partial name="_Header" model="headerList" /> | |||||
<div class="container"> | |||||
<br /> | |||||
<div class="row"> | |||||
@if (!ViewData.ModelState.IsValid) | |||||
{ | |||||
<div class="alert alert-warning"> | |||||
@Html.ValidationSummary(false) | |||||
</div> | |||||
} | |||||
<div class="col-md-12"> | |||||
<div class="esh-campaigns-items" style="font-weight: 300;"> | |||||
UPDATE USER LOCATION | |||||
</div> | |||||
<br /> | |||||
<form class="form-inline" asp-action="CreateNewUserLocation" method="post"> | |||||
<label class="sr-only" for="longitudeInput">Name</label> | |||||
<div class="input-group mb-3"> | |||||
<div class="input-group-prepend"> | |||||
<span class="input-group-text" id="inputGroup-sizing-default">Lat</span> | |||||
</div> | |||||
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="latitudeInput" asp-for="Lat" placeholder="Latitude"> | |||||
</div> | |||||
<div class="input-group mb-3"> | |||||
<div class="input-group-prepend"> | |||||
<span class="input-group-text" id="inputGroup-sizing-default">Lon</span> | |||||
</div> | |||||
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="longitudeInput" asp-for="Lon" placeholder="Longitude"> | |||||
</div> | |||||
<div class="input-group mb-2 mr-sm-2 mb-sm-0 col-md-2"> | |||||
<input type="submit" value="Update" class="btn esh-campaigns-form-button" /> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
<br /> | |||||
@if (Model != null && Model.CampaignItems !=null && Model.CampaignItems.Any()) | |||||
{ | |||||
<div class="card-group esh-campaigns-items row"> | |||||
@foreach (var catalogItem in Model.CampaignItems) | |||||
{ | |||||
<div class="esh-campaigns-item col-md-4"> | |||||
<partial name="_campaign" model="catalogItem" /> | |||||
</div> | |||||
} | |||||
</div> | |||||
<partial name="_pagination" for="PaginationInfo" /> | |||||
} | |||||
else | |||||
{ | |||||
<div class="esh-campaigns-items row"> | |||||
THERE ARE NO CAMPAIGNS | |||||
</div> | |||||
} | |||||
</div> | |||||
@ -1,23 +0,0 @@ | |||||
@model CampaignItem | |||||
<form asp-controller="Campaigns" asp-action="Details" asp-route-id="@Model.Id"> | |||||
<div class="card"> | |||||
<img class="card-img-top esh-campaigns-thumbnail" src="@Model.PictureUri" alt="@Model.Name"> | |||||
<div class="card-body"> | |||||
<h4 class="card-title esh-campaigns-name">@Model.Name</h4> | |||||
@if (ViewBag.IsCampaignDetailFunctionActive == true) | |||||
{ | |||||
<input type="button" value="More Details" class="btn esh-campaigns-button" onClick="window.open('@Model.DetailsUri')"> | |||||
} | |||||
else | |||||
{ | |||||
<input class="esh-campaigns-button" type="submit" value="More details"> | |||||
} | |||||
</div> | |||||
<div class="card-footer esh-campaigns-card-footer-text"> | |||||
<small class="text-muted"> | |||||
From @Model.From.ToString("MMMM dd, yyyy") until @Model.To.ToString("MMMM dd, yyyy") | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</form> |
@ -1,32 +0,0 @@ | |||||
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination.PaginationInfo | |||||
<div class="esh-pager"> | |||||
<div class="container"> | |||||
<article class="esh-pager-wrapper row"> | |||||
<nav> | |||||
<a class="esh-pager-item esh-pager-item--navigable @Model.Previous" | |||||
id="Previous" | |||||
asp-controller="Campaigns" | |||||
asp-action="Index" | |||||
asp-route-page="@(Model.ActualPage -1)" | |||||
aria-label="Previous"> | |||||
Previous | |||||
</a> | |||||
<span class="esh-pager-item"> | |||||
Showing @Model.ItemsPerPage of @Model.TotalItems products - Page @(Model.ActualPage + 1) - @Model.TotalPages | |||||
</span> | |||||
<a class="esh-pager-item esh-pager-item--navigable @Model.Next" | |||||
id="Next" | |||||
asp-controller="Campaigns" | |||||
asp-action="Index" | |||||
asp-route-page="@(Model.ActualPage + 1)" | |||||
aria-label="Next"> | |||||
Next | |||||
</a> | |||||
</nav> | |||||
</article> | |||||
</div> | |||||
</div> | |||||
@ -1,116 +0,0 @@ | |||||
.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-card-footer-text { | |||||
white-space: nowrap; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
} | |||||
.esh-campaigns-form-button { | |||||
background-color: #83D01B; | |||||
border: none; | |||||
color: #FFFFFF; | |||||
cursor: pointer; | |||||
font-size: 1rem; | |||||
transition: all 0.35s; | |||||
width: 80%; | |||||
margin-top: -15px; | |||||
} | |||||
.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; | |||||
} | |||||