Browse Source

Edit event creation page

pull/41/head
Berkan Sasmaz 6 years ago
parent
commit
44eccaffb4
  1. 2
      src/EventHub.Application.Contracts/Events/EventDetailDto.cs
  2. 1
      src/EventHub.Application/Events/EventAppService.cs
  3. 2
      src/EventHub.Domain.Shared/Localization/EventHub/en.json
  4. 2
      src/EventHub.Web/Pages/Events/Components/EventsArea/Default.cshtml
  5. 2
      src/EventHub.Web/Pages/Events/Components/EventsArea/EventsAreaViewComponent.cs
  6. 2
      src/EventHub.Web/Pages/Events/Components/LocationArea/Default.cshtml
  7. 8
      src/EventHub.Web/Pages/Events/Detail.cshtml
  8. 140
      src/EventHub.Web/Pages/Events/New.cshtml
  9. 70
      src/EventHub.Web/Pages/Events/New.cshtml.cs
  10. 55
      src/EventHub.Web/Pages/Events/New.js
  11. 28
      src/EventHub.Web/Pages/Organizations/Components/OrganizationsArea/_organizationListSection.cshtml
  12. 19
      src/EventHub.Web/Pages/Organizations/New.js

2
src/EventHub.Application.Contracts/Events/EventDetailDto.cs

@ -9,6 +9,8 @@ namespace EventHub.Events
public string OrganizationDisplayName { get; set; } public string OrganizationDisplayName { get; set; }
public string OwnerEmail { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string Description { get; set; } public string Description { get; set; }

1
src/EventHub.Application/Events/EventAppService.cs

@ -164,6 +164,7 @@ namespace EventHub.Events
dto.OrganizationName = organization.Name; dto.OrganizationName = organization.Name;
dto.OrganizationDisplayName = organization.DisplayName; dto.OrganizationDisplayName = organization.DisplayName;
dto.OwnerEmail = (await _userRepository.GetAsync(organization.OwnerUserId)).Email;
dto.CoverImageContent = await GetCoverImageAsync(dto.Id); dto.CoverImageContent = await GetCoverImageAsync(dto.Id);
return dto; return dto;

2
src/EventHub.Domain.Shared/Localization/EventHub/en.json

@ -56,7 +56,7 @@
"OrganizationProfilePictureInfo": "Upload 16:9 aspect ratio pictures for the best view. Maximum file size: 1MB.", "OrganizationProfilePictureInfo": "Upload 16:9 aspect ratio pictures for the best view. Maximum file size: 1MB.",
"Close": "Close", "Close": "Close",
"EventHub:CapacityOfEventFull": "\"{EventTitle}\" event capacity is full!", "EventHub:CapacityOfEventFull": "\"{EventTitle}\" event capacity is full!",
"GoToEventAddress": "Go to Event Address", "GoToOnlineAddress": "Go to Online Address",
"AttendeesCanSeeEventLocation": "Only attendees can see the event's {0}.", "AttendeesCanSeeEventLocation": "Only attendees can see the event's {0}.",
"LoginToSeeLocation": "Login to see location", "LoginToSeeLocation": "Login to see location",
"LocationHasNotSpecifiedYet": "Event {0} has not been specified yet.", "LocationHasNotSpecifiedYet": "Event {0} has not been specified yet.",

2
src/EventHub.Web/Pages/Events/Components/EventsArea/Default.cshtml

@ -6,7 +6,7 @@
<partial name="~/Pages/Events/Components/EventsArea/_eventListSection.cshtml" model="@Model.Events"/> <partial name="~/Pages/Events/Components/EventsArea/_eventListSection.cshtml" model="@Model.Events"/>
</div> </div>
@if (Model.IsPagination && Model.TotalCount >= 10 && Model.TotalCount > Model.Events.Count) @if (Model.IsPagination && Model.TotalCount > Model.MaxResultCount && Model.TotalCount > Model.Events.Count)
{ {
<div class="row load-more-section"> <div class="row load-more-section">
<div class="col text-center"> <div class="col text-center">

2
src/EventHub.Web/Pages/Events/Components/EventsArea/EventsAreaViewComponent.cs

@ -14,8 +14,6 @@ namespace EventHub.Web.Pages.Events.Components.EventsArea
public class EventsAreaViewComponent : AbpViewComponent public class EventsAreaViewComponent : AbpViewComponent
{ {
private readonly IEventAppService _eventAppService; private readonly IEventAppService _eventAppService;
public List<EventInListDto> Events { get; set; }
public EventsAreaViewComponent(IEventAppService eventAppService) public EventsAreaViewComponent(IEventAppService eventAppService)
{ {

2
src/EventHub.Web/Pages/Events/Components/LocationArea/Default.cshtml

@ -10,7 +10,7 @@
{ {
if (Model.OnlineLink != null) if (Model.OnlineLink != null)
{ {
<a class="detail-pin" href="@Model.OnlineLink"><img src="/assets/pin.svg"> @L["GoToEventAddress"]</a> <a class="detail-pin" href="@Model.OnlineLink"><img src="/assets/pin.svg"> @L["GoToOnlineAddress"]</a>
} }
else else
{ {

8
src/EventHub.Web/Pages/Events/Detail.cshtml

@ -33,7 +33,7 @@
{ {
<h1 class="mt-4 mt-md-0"> <h1 class="mt-4 mt-md-0">
@Model.Event.Title @Model.Event.Title
<a href="/event/edit/@Model.Event.Url" class="btn btn-primary text-white"> <a href="/event/edit/@Model.Event.Url" class="btn btn-primary btn-xs text-white">
<i class="far fa-edit"></i> <i class="far fa-edit"></i>
</a> </a>
</h1> </h1>
@ -44,11 +44,9 @@
} }
@await Component.InvokeAsync(typeof(LocationAreaViewComponent), new {eventId = Model.Event.Id}) @await Component.InvokeAsync(typeof(LocationAreaViewComponent), new {eventId = Model.Event.Id})
<h5 class="detail-head mt-4">Organizers</h5> <h5 class="detail-head mt-4">Owner</h5>
<div> <div>
<img src="/assets/avatar2.png" class="org-avatar"> <img gravatar-email="@Model.Event.OwnerEmail" default-image="Wavatar" gravatar-size="60" class="org-avatar avatar rounded-circle"/>
<img src="/assets/avatar3.png" class="org-avatar">
<img src="/assets/avatar4.png" class="org-avatar">
</div> </div>
@await Component.InvokeAsync(typeof(RegistrationAreaViewComponent), new {eventId = Model.Event.Id}) @await Component.InvokeAsync(typeof(RegistrationAreaViewComponent), new {eventId = Model.Event.Id})
</div> </div>

140
src/EventHub.Web/Pages/Events/New.cshtml

@ -2,14 +2,12 @@
@inject IHtmlLocalizer<EventHubResource> L @inject IHtmlLocalizer<EventHubResource> L
@using EventHub.Localization @using EventHub.Localization
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EventHub.Web.Pages.Events.NewPageModel @model EventHub.Web.Pages.Events.NewPageModel
@section scripts { @section scripts {
<abp-script src="/Pages/Events/New.js"/> <abp-script src="/Pages/Events/New.js"/>
} }
<h1>@L["NewEvent"]</h1>
@if (!Model.Organizations.Any()) @if (!Model.Organizations.Any())
{ {
<abp-alert alert-type="Danger"> <abp-alert alert-type="Danger">
@ -19,31 +17,111 @@
} }
else else
{ {
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">
<abp-select asp-for="Event.OrganizationId" /> <div class="container pt-4">
<abp-input asp-for="Event.Title" /> <div class="row py-4">
<abp-input asp-for="Event.StartTime" /> <div class="col-md-9 mx-auto profile-content">
<abp-input asp-for="Event.EndTime" />
<abp-input asp-for="Event.Description" /> <div class="card">
<abp-input asp-for="Event.CoverImageFile" /> <div class="card-body" style="min-height: 496px">
<abp-input asp-for="Event.IsOnline" /> <h3 class="mb-4">Create New Event</h3>
<div id="event-link-group" style="display: none"> <div class="form">
<abp-input asp-for="Event.OnlineLink" /> <div class="row">
</div> <div class="col-md-6">
<div id="event-location-group"> <div class="form-label-group">
<abp-select asp-for="Event.CountryId" /> <select asp-for="Event.OrganizationId" asp-items="Model.Organizations" class="form-select">
<abp-input asp-for="Event.City" /> <option selected value="">Organization</option>
</div> </select>
<abp-select asp-for="Event.Language" /> </div>
<abp-input asp-for="Event.Capacity" /> </div>
<abp-button size="Large" button-type="Primary" type="submit" text="@L["Submit"].Value" /> <div class="col-md-6">
</form> <div class="form-label-group">
<input type="text" id="inputTitle" asp-for="Event.Title" class="form-control" placeholder="Title">
<abp-modal centered="true" scrollable="true" size="Small" id="cover-image-preview-modal"> <label for="inputTitle">Title</label>
<abp-modal-header title="Cover Image Preview"></abp-modal-header> </div>
<abp-modal-body> </div>
<img class="img-fluid" id="img-upload" alt="event-cover-image-preview"/> <div class="col-md-6">
</abp-modal-body> <div class="form-label-group">
<abp-modal-footer buttons="@(AbpModalButtons.Close)"></abp-modal-footer> <input id="inputStartdate" asp-for="Event.StartTime" class="form-control" placeholder="Start Date">
</abp-modal> <label for="inputStartdate">Start Date</label>
} </div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input id="inputEnddate" asp-for="Event.EndTime" class="form-control" placeholder="End Date">
<label for="inputEnddate">End Date</label>
</div>
</div>
<div class="col-md-12">
<div class="form-label-group">
<input type="text" id="inputDescription" asp-for="Event.Description" class="form-control" placeholder="Description">
<label for="inputDescription">Description</label>
</div>
</div>
<div class="col-md-12">
<h4 class="mb-4">Cover Image</h4>
<div class="row">
<div class="col-5">
<div class="image-area"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div>
</div>
<div class="col-7">
<div>
<p class="mb-3">For horizontal format 600x300 sized upload images.</p>
<input type="file" id="Event_CoverImageFile" asp-for="Event.CoverImageFile" class="form-control border-0" hidden>
<label id="upload-label" for="Event_CoverImageFile" class="btn btn-primary btn-lg text-white">Choose file</label>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<select class="form-select" asp-for="Event.IsOnline">
<option selected="selected" value="">Event Type</option>
<option value="@Boolean.TrueString">Online</option>
<option value="@Boolean.FalseString">In Person</option>
</select>
</div>
<div class="col-md-6 event-link-group" style="display: none">
<div class="form-label-group">
<input type="text" id="inputOnlineLink" asp-for="Event.OnlineLink" class="form-control" placeholder="Online Link">
<label for="inputOnlineLink">Online Link</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="number" id="inputCapacity" asp-for="Event.Capacity" class="form-control" placeholder="Capacity">
<label for="inputCapacity">Capacity</label>
</div>
</div>
<div class="col-md-6 event-location-group">
<select asp-for="Event.CountryId" asp-items="Model.Countries" class="form-select">
<option selected="" value="">Country</option>
</select>
</div>
<div class="col-md-6 event-location-group">
<div class="form-label-group">
<input type="text" id="inputCity" asp-for="Event.City" class="form-control" placeholder="City">
<label for="inputCity">City</label>
</div>
</div>
<div class="col-md-6">
<select asp-for="Event.Language" asp-items="Model.Languages" aria-label="en" class="form-select">
<option selected value="">Language</option>
</select>
</div>
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary btn-lg">
Publish New Event
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
}

70
src/EventHub.Web/Pages/Events/New.cshtml.cs

@ -50,7 +50,38 @@ namespace EventHub.Web.Pages.Events
await FillCountriesAsync(); await FillCountriesAsync();
FillLanguages(); FillLanguages();
} }
public async Task<IActionResult> OnPostAsync()
{
try
{
ValidateModel();
var input = ObjectMapper.Map<NewEventViewModel, CreateEventDto>(Event);
if (Event.CoverImageFile != null && Event.CoverImageFile.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await Event.CoverImageFile.CopyToAsync(memoryStream);
input.CoverImageContent = memoryStream.ToArray();
}
}
var eventDto = await _eventAppService.CreateAsync(input);
return RedirectToPage("/Events/Detail", new {url = eventDto.UrlCode});
}
catch (Exception exception)
{
ShowAlert(exception);
await FillOrganizationsAsync();
await FillCountriesAsync();
FillLanguages();
return Page();
}
}
private async Task FillOrganizationsAsync() private async Task FillOrganizationsAsync()
{ {
var result = await _organizationAppService.GetMyOrganizationsAsync(); var result = await _organizationAppService.GetMyOrganizationsAsync();
@ -92,36 +123,6 @@ namespace EventHub.Web.Pages.Events
} }
).ToList(); ).ToList();
} }
public async Task<IActionResult> OnPostAsync()
{
try
{
ValidateModel();
var input = ObjectMapper.Map<NewEventViewModel, CreateEventDto>(Event);
if (Event.CoverImageFile != null && Event.CoverImageFile.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await Event.CoverImageFile.CopyToAsync(memoryStream);
input.CoverImageContent = memoryStream.ToArray();
}
}
var eventDto = await _eventAppService.CreateAsync(input);
return RedirectToPage("/Events/Detail", new {url = eventDto.UrlCode});
}
catch (Exception exception)
{
ShowAlert(exception);
await FillOrganizationsAsync();
await FillCountriesAsync();
FillLanguages();
return Page();
}
}
public class NewEventViewModel public class NewEventViewModel
{ {
@ -134,10 +135,12 @@ namespace EventHub.Web.Pages.Events
public string Title { get; set; } public string Title { get; set; }
[Required] [Required]
public DateTime StartTime { get; set; } [DataType(DataType.DateTime)]
public DateTime StartTime { get; set; } = DateTime.Now;
[Required] [Required]
public DateTime EndTime { get; set; } [DataType(DataType.DateTime)]
public DateTime EndTime { get; set; } = DateTime.Now;
[Required] [Required]
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)] [StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)]
@ -151,7 +154,8 @@ namespace EventHub.Web.Pages.Events
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })] [AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })]
public IFormFile CoverImageFile { get; set; } public IFormFile CoverImageFile { get; set; }
public bool IsOnline { get; set; } [Required]
public bool? IsOnline { get; set; }
[CanBeNull] [CanBeNull]
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)] [StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)]

55
src/EventHub.Web/Pages/Events/New.js

@ -1,48 +1,63 @@
$(function () { $(function () {
var l = abp.localization.getResource('EventHub'); var l = abp.localization.getResource('EventHub');
$("#Event_CountryId").prepend("<option value='' selected='selected'></option>"); var isOnline = $("#Event_IsOnline option:selected").val()
$("#Event_Language").prepend("<option value='' selected='selected'></option>"); if (isOnline === "True") {
$(".event-link-group").show();
$('#Event_IsOnline').click(function() { $(".event-location-group").hide();
if ($(this).is(':checked')) { }else{
$("#event-link-group").show(); $(".event-link-group").hide();
$("#event-location-group").hide(); $(".event-location-group").show();
}
$('#Event_IsOnline').on('change', '', function() {
var isOnline = $("#Event_IsOnline option:selected").val()
if (isOnline === "True") {
$(".event-link-group").show();
$(".event-location-group").hide();
}else{ }else{
$("#event-link-group").hide(); $(".event-link-group").hide();
$("#event-location-group").show(); $(".event-location-group").show();
} }
}); });
var infoArea = document.getElementById( 'upload-label' );
var fileInput = document.getElementById('Event_CoverImageFile'); var fileInput = document.getElementById('Event_CoverImageFile');
var file; var file;
fileInput.addEventListener('change', function () { fileInput.addEventListener('change', function () {
var showModal = true; var showFile = true;
file = fileInput.files[0]; file = fileInput.files[0];
if (file === undefined){
$('#Event_CoverImageFile').val('');
$('#imageResult').attr('src', '#');
infoArea.textContent = 'Choose file'
return;
}
var permittedExtensions = ["jpg", "jpeg", "png"] var permittedExtensions = ["jpg", "jpeg", "png"]
var fileExtension = $(this).val().split('.').pop(); var fileExtension = $(this).val().split('.').pop();
if (permittedExtensions.indexOf(fileExtension) === -1) { if (permittedExtensions.indexOf(fileExtension) === -1) {
showModal = false; showFile = false;
abp.message.error(l('EventCoverImageExtensionNotAllowed')) abp.message.error(l('EventCoverImageExtensionNotAllowed'))
.then(() => { .then(() => {
$('#Event_CoverImageFile').val(''); $('#Event_CoverImageFile').val('');
file = null; file = null;
}); });
} }
else if(file.size > 1024*1024) { else if(file.size > 1024*1024) {
showModal = false; showFile = false;
abp.message.error(l('EventCoverImageSizeExceedMessage')) abp.message.error(l('EventCoverImageSizeExceedMessage'))
.then(() => { .then(() => {
$('#Event_CoverImageFile').val(''); $('#Event_CoverImageFile').val('');
file = null; file = null;
}); });
} }
var img = new Image(); var img = new Image();
img.onload = function() { img.onload = function () {
var imageError = true; var imageError = true;
var sizes = { var sizes = {
width: this.width, width: this.width,
@ -50,22 +65,22 @@ $(function () {
}; };
URL.revokeObjectURL(this.src); URL.revokeObjectURL(this.src);
if(showModal && imageError) { if(showFile && imageError) {
readURL(file); readURL(file);
$('#cover-image-preview-modal').modal('show');
} }
} }
var objectURL = URL.createObjectURL(file); var objectURL = URL.createObjectURL(file);
img.src = objectURL; img.src = objectURL;
}); });
function readURL(input) { function readURL(input) {
if (input) { if (input) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function (e) { reader.onload = function (e) {
$('#img-upload').attr('src', e.target.result); $('#imageResult').attr('src', e.target.result);
infoArea.textContent = 'File name: ' + input.name;
} }
reader.readAsDataURL(input); reader.readAsDataURL(input);

28
src/EventHub.Web/Pages/Organizations/Components/OrganizationsArea/_organizationListSection.cshtml

@ -0,0 +1,28 @@
@model List<EventHub.Organizations.OrganizationInListDto>
@foreach (var organization in Model)
{
<div class="col-lg-4 col-md-6 organization">
<div class="card">
@if (organization.ProfilePictureContent == null)
{
<img src="assets/card-img.png" class="card-img-top" alt="@organization.Name">
}
else
{
<img src="@($"data:image/png;base64,{Convert.ToBase64String(organization.ProfilePictureContent)}")" class="card-img-top" alt="@organization.Name">
}
<div class="card-body">
<div class="event-container">
<div class="event-info">
<h5>@organization.DisplayName</h5>
<p>
@organization.Description
</p>
</div>
<a href="@Url.Page("/Organizations/Profile", new {name = organization.Name})" class="btn btn-link p-0">Details <img src="assets/more-btn.svg"></a>
</div>
</div>
</div>
</div>
}

19
src/EventHub.Web/Pages/Organizations/New.js

@ -1,23 +1,33 @@
$(function () { $(function () {
var l = abp.localization.getResource('EventHub'); var l = abp.localization.getResource('EventHub');
var infoArea = document.getElementById( 'upload-label' );
var fileInput = document.getElementById('Organization_ProfilePictureFile'); var fileInput = document.getElementById('Organization_ProfilePictureFile');
var file; var file;
fileInput.addEventListener('change', function () { fileInput.addEventListener('change', function () {
var showFile = true;
file = fileInput.files[0]; file = fileInput.files[0];
if (file === undefined){
$('#Organization_ProfilePictureFile').val('');
$('#imageResult').attr('src', '#');
infoArea.textContent = 'Choose file'
return;
}
var permittedExtensions = ["jpg", "jpeg", "png"] var permittedExtensions = ["jpg", "jpeg", "png"]
var fileExtension = $(this).val().split('.').pop(); var fileExtension = $(this).val().split('.').pop();
if (permittedExtensions.indexOf(fileExtension) === -1) { if (permittedExtensions.indexOf(fileExtension) === -1) {
abp.message.error(l('OrganizationCoverImageExtensionNotAllowed')) showFile = false;
abp.message.error(l('OrganizationProfilePictureExtensionNotAllowed'))
.then(() => { .then(() => {
$('#Organization_ProfilePictureFile').val(''); $('#Organization_ProfilePictureFile').val('');
file = null; file = null;
}); });
} else if (file.size > 1024 * 1024) { } else if (file.size > 1024 * 1024) {
abp.message.error(l('OrganizationCoverImageSizeExceedMessage')) showFile = false;
abp.message.error(l('OrganizationProfilePictureSizeExceedMessage'))
.then(() => { .then(() => {
$('#Organization_ProfilePictureFile').val(''); $('#Organization_ProfilePictureFile').val('');
file = null; file = null;
@ -33,7 +43,7 @@ $(function () {
}; };
URL.revokeObjectURL(this.src); URL.revokeObjectURL(this.src);
if (imageError) { if (showFile && imageError) {
readURL(file); readURL(file);
} }
} }
@ -48,6 +58,7 @@ $(function () {
reader.onload = function (e) { reader.onload = function (e) {
$('#imageResult').attr('src', e.target.result); $('#imageResult').attr('src', e.target.result);
infoArea.textContent = 'File name: ' + input.name;
} }
reader.readAsDataURL(input); reader.readAsDataURL(input);

Loading…
Cancel
Save