Browse Source

add ability to edit track and session in event edit page

and add two todos
pull/79/head
berkansasmaz 5 years ago
parent
commit
ae91428ded
No known key found for this signature in database GPG Key ID: 884D815C3F32BE00
  1. 1
      src/EventHub.Application/Events/EventAppService.cs
  2. 1
      src/EventHub.Domain.Shared/EventHubErrorCodes.cs
  3. 1
      src/EventHub.Domain.Shared/Localization/EventHub/en.json
  4. 2
      src/EventHub.Domain/Events/Event.cs
  5. 6
      src/EventHub.Web/Controllers/WidgetsController.cs
  6. 8
      src/EventHub.Web/EventHubWebAutoMapperProfile.cs
  7. 35
      src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml
  8. 15
      src/EventHub.Web/Pages/Events/Components/CreateEventArea/_progressSection.cshtml
  9. 32
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/CreateOrEditEventAreaViewComponent.cs
  10. 35
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/Default.cshtml
  11. 10
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_addSessionSection.cshtml
  12. 10
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_addTrackSection.cshtml
  13. 0
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_modelNullErrorSection.cshtml
  14. 8
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_newEventSection.cshtml
  15. 10
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_previewSection.cshtml
  16. 20
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_progressSection.cshtml
  17. 0
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.css
  18. 22
      src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.js
  19. 140
      src/EventHub.Web/Pages/Events/Edit.cshtml
  20. 193
      src/EventHub.Web/Pages/Events/Edit.cshtml.cs
  21. 94
      src/EventHub.Web/Pages/Events/Edit.js
  22. 6
      src/EventHub.Web/Pages/Events/New.cshtml
  23. 1
      src/EventHub.Web/Pages/Pricing.cshtml

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

@ -262,6 +262,7 @@ namespace EventHub.Events
[Authorize]
public async Task UpdateAsync(Guid id, UpdateEventDto input)
{
// TODO(berkansasmaz): Should it be updated on past events?
var @event = await _eventRepository.GetAsync(id);
await CheckIfValidOwnerAsync(@event);

1
src/EventHub.Domain.Shared/EventHubErrorCodes.cs

@ -19,7 +19,6 @@
public const string TrackNameAlreadyExist = "EventHub:TrackNameAlreadyExist";
public const string TrackNotFound = "EventHub:TrackNotFound";
public const string SessionNotFound = "EventHub:SessionNotFound";
public const string DraftEventNotFound = "EventHub:DraftEventNotFound";
public const string SessionTitleAlreadyExist = "EventHub:SessionTitleAlreadyExist";
}

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

@ -158,7 +158,6 @@
"EventHub:SessionNotFound": "The session not found!",
"EventHub:SessionTimeShouldBeInTheEventTime": "Session time should be in the event time!",
"EventHub:SessionTimeConflictsWithAnExistingSession": "Session time conflicts with an existing session!",
"EventHub:DraftEventNotFound": "The draft event not found!",
"EventHub:SessionTitleAlreadyExist": "The session {Title} already exists"
}
}

2
src/EventHub.Domain/Events/Event.cs

@ -243,7 +243,7 @@ namespace EventHub.Events
private void CheckIfValidSessionTime(DateTime startTime, DateTime endTime)
{
// TODO: This control is already done in Track and even Session. Do you really need this?
// TODO(berkansasmaz): This control is already done in Track and even Session. Do you really need this?
if (startTime > endTime)
{
throw new BusinessException(EventHubErrorCodes.SessionEndTimeCantBeEarlierThanStartTime);

6
src/EventHub.Web/Controllers/WidgetsController.cs

@ -1,6 +1,6 @@
using System;
using EventHub.Web.Pages.Events.Components.AttendeesArea;
using EventHub.Web.Pages.Events.Components.CreateEventArea;
using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea;
using EventHub.Web.Pages.Events.Components.LocationArea;
using EventHub.Web.Pages.Events.Components.RegistrationArea;
using EventHub.Web.Pages.Organizations.Components.JoinArea;
@ -70,10 +70,10 @@ namespace EventHub.Web.Controllers
}
[HttpGet]
public IActionResult CreateEventArea(string eventUrlCode, CreateEventAreaViewComponent.ProgressStepType stepType)
public IActionResult CreateOrEditEventArea(string eventUrlCode, CreateOrEditEventAreaViewComponent.ProgressStepType stepType)
{
return ViewComponent(
typeof(CreateEventAreaViewComponent),
typeof(CreateOrEditEventAreaViewComponent),
new
{
eventUrlCode,

8
src/EventHub.Web/EventHubWebAutoMapperProfile.cs

@ -1,7 +1,7 @@
using AutoMapper;
using EventHub.Events;
using EventHub.Organizations;
using EventHub.Web.Pages.Events.Components.CreateEventArea;
using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea;
using EventHub.Web.Pages.Organizations;
using Volo.Abp.AutoMapper;
using EditPageModel = EventHub.Web.Pages.Events.EditPageModel;
@ -13,13 +13,11 @@ namespace EventHub.Web
public EventHubWebAutoMapperProfile()
{
CreateMap<NewPageModel.CreateOrganizationViewModel, CreateOrganizationDto>();
CreateMap<CreateEventAreaViewComponent.NewEventViewModel, CreateEventDto>()
CreateMap<CreateOrEditEventAreaViewComponent.NewEventViewModel, CreateEventDto>()
.Ignore(x => x.CoverImageStreamContent);
CreateMap<OrganizationProfileDto, EditOrganizationViewModel>();
CreateMap<EditOrganizationViewModel, UpdateOrganizationDto>();
CreateMap<EventDetailDto, CreateEventAreaViewComponent.NewEventViewModel>();
CreateMap<EventDetailDto, EditPageModel.EditEventViewModel>();
CreateMap<EditPageModel.EditEventViewModel, UpdateEventDto>();
CreateMap<EventDetailDto, CreateOrEditEventAreaViewComponent.NewEventViewModel>();
}
}
}

35
src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml

@ -1,35 +0,0 @@
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using Microsoft.AspNetCore.Http
@model EventHub.Web.Pages.Events.Components.CreateEventArea.CreateEventAreaViewComponent.NewEventViewModel
@{
if (Model is null)
{
throw new BadHttpRequestException("");
}
var eventId = ViewData["EventId"] as Guid?;
var eventUrlCode = ViewData["EventUrlCode"]?.ToString();
var result = Enum.TryParse(ViewData["StepType"]!.ToString(), out CreateEventAreaViewComponent.ProgressStepType stepType);
if (!result)
{
throw new BadHttpRequestException("");
}
}
<div id="CreateEventContainer" style="@(stepType != CreateEventAreaViewComponent.ProgressStepType.NewEvent ? "display: none" : "")">
<partial name="_newEventSection.cshtml" model="@Model"/>
</div>
<div id="CreateTrackContainer" style="@(stepType != CreateEventAreaViewComponent.ProgressStepType.NewTrack ? "display: none" : "")">
<partial name="_addTrackSection.cshtml" model="@Model.Tracks"/>
</div>
<div id="CreateSessionContainer" style="@(stepType != CreateEventAreaViewComponent.ProgressStepType.NewSession ? "display: none" : "")">
<partial name="_addSessionSection.cshtml" model="@Model.Tracks"/>
</div>
<div id="PreviewContainer" style="@(stepType != CreateEventAreaViewComponent.ProgressStepType.Preview ? "display: none" : "")">
<partial name="_previewSection.cshtml" model="@Model"/>
</div>
<input type="hidden" id="EventId" value="@eventId"/>
<input type="hidden" id="EventUrlCode" value="@eventUrlCode"/>

15
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_progressSection.cshtml

@ -1,15 +0,0 @@
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@model EventHub.Web.Pages.Events.Components.CreateEventArea.CreateEventAreaViewComponent.ProgressStepType
<div class="px-4 py-1">
<div class="progresses py-4">
<ul class="d-flex align-items-center justify-content-between">
<li id="step-1" class="create-steps @(Model == CreateEventAreaViewComponent.ProgressStepType.NewEvent ? "blue" : "")">1<span>New Event</span></li>
<li id="step-2" class="create-steps @(Model == CreateEventAreaViewComponent.ProgressStepType.NewTrack ? "blue" : "")">2<span>Add Track</span></li>
<li id="step-3" class="create-steps @(Model == CreateEventAreaViewComponent.ProgressStepType.NewSession ? "blue" : "")">3<span>Add Session</span></li>
</ul>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>

32
src/EventHub.Web/Pages/Events/Components/CreateEventArea/CreateEventAreaViewComponent.cs → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/CreateOrEditEventAreaViewComponent.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
@ -13,29 +12,27 @@ using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Authorization;
using Volo.Abp.Users;
namespace EventHub.Web.Pages.Events.Components.CreateEventArea;
namespace EventHub.Web.Pages.Events.Components.CreateOrEditEventArea;
[Widget(
AutoInitialize = true,
RefreshUrl = "/Widgets/CreateEventArea",
ScriptFiles = new[] { "/Pages/Events/Components/CreateEventArea/create-event-area.js" },
StyleFiles = new[] { "/Pages/Events/Components/CreateEventArea/create-event-area.css" }
RefreshUrl = "/Widgets/CreateOrEditEventArea",
ScriptFiles = new[] { "/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.js" },
StyleFiles = new[] { "/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.css" }
)]
public class CreateEventAreaViewComponent : AbpViewComponent
public class CreateOrEditEventAreaViewComponent : AbpViewComponent
{
private readonly IEventAppService _eventAppService;
private readonly IOrganizationAppService _organizationAppService;
private readonly ICurrentUser _currentUser;
public CreateEventAreaViewComponent(
public CreateOrEditEventAreaViewComponent(
IEventAppService eventAppService,
IOrganizationAppService organizationAppService,
ICurrentUser currentUser)
@ -46,8 +43,8 @@ public class CreateEventAreaViewComponent : AbpViewComponent
}
public async Task<IViewComponentResult> InvokeAsync(
string eventUrlCode,
ProgressStepType stepType = ProgressStepType.NewEvent)
string eventUrlCode,
ProgressStepType stepType = ProgressStepType.Event)
{
NewEventViewModel model = null;
if (!eventUrlCode.IsNullOrWhiteSpace())
@ -66,7 +63,7 @@ public class CreateEventAreaViewComponent : AbpViewComponent
await FillViewDataAsync(stepType, model);
return View("~/Pages/Events/Components/CreateEventArea/Default.cshtml", model);
return View("~/Pages/Events/Components/CreateOrEditEventArea/Default.cshtml", model);
}
private async Task<string> GetOrganizationNameAsync(Guid organizationId)
@ -131,12 +128,12 @@ public class CreateEventAreaViewComponent : AbpViewComponent
ViewData["StepType"] = stepType.ToString();
switch (stepType)
{
case ProgressStepType.NewEvent:
case ProgressStepType.Event:
ViewData["Organizations"] = await GetOrganizationsSelectItemAsync();
ViewData["Countries"] = await GetCountriesSelectItemAsync();
ViewData["Languages"] = GetLanguagesSelectItem();
break;
case ProgressStepType.NewSession:
case ProgressStepType.Session:
ViewData["Languages"] = GetLanguagesSelectItem();
break;
case ProgressStepType.Preview:
@ -145,7 +142,6 @@ public class CreateEventAreaViewComponent : AbpViewComponent
{
ViewData["CountryName"] = await GetCountryNameAsync(model.CountryId!.Value);
}
break;
}
}
@ -210,9 +206,9 @@ public class CreateEventAreaViewComponent : AbpViewComponent
public enum ProgressStepType : byte
{
NewEvent = 0,
NewTrack,
NewSession,
Event = 0,
Track,
Session,
Preview
}
}

35
src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/Default.cshtml

@ -0,0 +1,35 @@
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@using Microsoft.AspNetCore.Http
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel
@{
if (Model is null)
{
throw new BadHttpRequestException("");
}
var eventId = ViewData["EventId"] as Guid?;
var eventUrlCode = ViewData["EventUrlCode"]?.ToString();
var result = Enum.TryParse(ViewData["StepType"]!.ToString(), out CreateOrEditEventAreaViewComponent.ProgressStepType stepType);
if (!result)
{
throw new BadHttpRequestException("");
}
}
<div id="CreateEventContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Event ? "display: none" : "")">
<partial name="_newEventSection.cshtml" model="@Model"/>
</div>
<div id="CreateTrackContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Track ? "display: none" : "")">
<partial name="_addTrackSection.cshtml" model="@Model.Tracks"/>
</div>
<div id="CreateSessionContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Session ? "display: none" : "")">
<partial name="_addSessionSection.cshtml" model="@Model.Tracks"/>
</div>
<div id="PreviewContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Preview ? "display: none" : "")">
<partial name="_previewSection.cshtml" model="@Model"/>
</div>
<input type="hidden" id="EventId" value="@eventId"/>
<input type="hidden" id="EventUrlCode" value="@eventUrlCode"/>

10
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addSessionSection.cshtml → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_addSessionSection.cshtml

@ -1,12 +1,12 @@
@using EventHub.Web.Pages.Events
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using EventHub.Events
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@using Microsoft.AspNetCore.Http
@model List<EventHub.Events.TrackDto>
@{
var languages = new List<SelectListItem>();
@if (ViewData["StepType"]!.ToString() == CreateEventAreaViewComponent.ProgressStepType.NewSession.ToString())
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Session.ToString())
{
languages = ViewData["Languages"] as List<SelectListItem>;
if (languages is null || !languages.Any())
@ -24,7 +24,7 @@
}
}
<partial name="_progressSection.cshtml" model="@CreateEventAreaViewComponent.ProgressStepType.NewSession" />
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" />
@if (Model is not null)
{
@ -96,12 +96,12 @@
<div class="row">
<div class="col-6">
<button id="PreviousStepButtonInSessionSection"
data-target-step="@CreateEventAreaViewComponent.ProgressStepType.NewTrack"
data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track"
class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous
Step </button>
</div>
<div class="col-6 text-end">
<button id="PreviewButtonInSessionSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-primary step-transition">Preview <i class="fa fa-arrow-right ms-2"></i></button>
<button id="PreviewButtonInSessionSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-primary step-transition">Preview <i class="fa fa-arrow-right ms-2"></i></button>
</div>
</div>
</div>

10
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addTrackSection.cshtml → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_addTrackSection.cshtml

@ -1,8 +1,8 @@
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using EventHub.Events
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@model List<EventHub.Events.TrackDto>
<partial name="_progressSection.cshtml" model="@CreateEventAreaViewComponent.ProgressStepType.NewTrack"/>
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track"/>
@if (Model is not null)
{
@ -39,11 +39,11 @@
<div class="card-footer bg-white border-0 p-5 pt-1">
<div class="row">
<div class="col-6">
<button id="PreviousStepButtonInTrackSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.NewEvent" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
<button id="PreviousStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Event" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
</div>
<div class="col-6 text-end">
<button id="SkipThisStepButtonInTrackSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-link step-transition text-decoration-none">Skip This Step</button>
<button id="NextStepButtonInTrackSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.NewSession" class="btn btn-primary step-transition" @(Model.Any() ? "" : "disabled")>Next Step <i class="fa fa-arrow-right ms-2"></i></button>
<button id="SkipThisStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-link step-transition text-decoration-none">Skip This Step</button>
<button id="NextStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" class="btn btn-primary step-transition" @(Model.Any() ? "" : "disabled")>Next Step <i class="fa fa-arrow-right ms-2"></i></button>
</div>
</div>
</div>

0
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_modelNullErrorSection.cshtml → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_modelNullErrorSection.cshtml

8
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_newEventSection.cshtml → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_newEventSection.cshtml

@ -1,8 +1,8 @@
@using EventHub.Web
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@using Microsoft.AspNetCore.Http
@using Microsoft.Extensions.Options
@model EventHub.Web.Pages.Events.Components.CreateEventArea.CreateEventAreaViewComponent.NewEventViewModel
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel
@inject IOptions<EventHubUrlOptions> UrlOptions
@{
@ -11,7 +11,7 @@
var languages = new List<SelectListItem>();
var eventId = ViewData["EventId"] as Guid?;
@if (ViewData["StepType"]!.ToString() == CreateEventAreaViewComponent.ProgressStepType.NewEvent.ToString())
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Event.ToString())
{
organizations = ViewData["Organizations"] as List<SelectListItem>;
if (organizations is null || !organizations.Any())
@ -33,7 +33,7 @@
}
}
<partial name="_progressSection.cshtml" model="@CreateEventAreaViewComponent.ProgressStepType.NewEvent" />
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Event" />
@if (Model is not null)
{
<form id="CreateEventForm" method="post" enctype="multipart/form-data">

10
src/EventHub.Web/Pages/Events/Components/CreateEventArea/_previewSection.cshtml → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_previewSection.cshtml

@ -1,16 +1,16 @@
@using EventHub.Web
@using EventHub.Web.Pages.Events
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@using Microsoft.AspNetCore.Http
@using Microsoft.Extensions.Options
@model EventHub.Web.Pages.Events.Components.CreateEventArea.CreateEventAreaViewComponent.NewEventViewModel
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel
@inject IOptions<EventHubUrlOptions> UrlOptions
@{
var organizationName = "";
var countryName = "";
Guid? eventId = null;
@if (ViewData["StepType"]!.ToString() == CreateEventAreaViewComponent.ProgressStepType.Preview.ToString())
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Preview.ToString())
{
eventId = ViewData["EventId"] as Guid?;
@ -208,11 +208,11 @@
<div class="col-6">
@if (Model.Tracks.Any() && Model.Tracks.First().Sessions.Any())
{
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.NewSession" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
}
else
{
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateEventAreaViewComponent.ProgressStepType.NewTrack" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button>
}
</div>
<div class="col-6 text-end">

20
src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/_progressSection.cshtml

@ -0,0 +1,20 @@
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.ProgressStepType
@{
var eventId = ViewData["EventId"] as Guid?;
var prefixOfStep = eventId.HasValue ? "Edit" : "New";
}
<div class="px-4 py-1">
<div class="progresses py-4">
<ul class="d-flex align-items-center justify-content-between">
<li id="step-1" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Event ? "blue" : "")">1<span>@prefixOfStep Event</span></li>
<li id="step-2" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Track ? "blue" : "")">2<span>@prefixOfStep Track</span></li>
<li id="step-3" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Session ? "blue" : "")">3<span>@prefixOfStep Session</span></li>
</ul>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>

0
src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.css → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.css

22
src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.js → src/EventHub.Web/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.js

@ -1,13 +1,13 @@
(function () {
abp.widgets.CreateEventArea = function ($wrapper) {
abp.widgets.CreateOrEditEventArea = function ($wrapper) {
var l = abp.localization.getResource('EventHub');
toastr.options.timeOut = 500;
toastr.options.preventDuplicates = true;
var stepType = {
"NewEvent": "NewEvent",
"NewTrack": "NewTrack",
"NewSession": "NewSession",
"Event": "Event",
"Track": "Track",
"Session": "Session",
"Preview": "Preview"
}
@ -18,7 +18,7 @@
var filter = {
eventUrlCode: "",
stepType: stepType.NewEvent
stepType: stepType.Event
}
var getFilters = function () {
@ -142,7 +142,7 @@
eventApiService.addTrack(eventIdInput.val(), {name: trackName}).then(function () {
$('#AddTrackModal').modal('hide');
abp.notify.success('Added the track');
FillFilter(stepType.NewTrack);
FillFilter(stepType.Track);
widgetManager.refresh();
});
});
@ -181,7 +181,7 @@
eventApiService.updateTrack(eventIdInput.val(), trackId, {name: trackName}).then(function () {
$('#EditTrackModal').modal('hide');
abp.notify.success('Updated the track');
FillFilter(stepType.NewTrack)
FillFilter(stepType.Track)
widgetManager.refresh();
});
});
@ -192,7 +192,7 @@
e.preventDefault();
eventApiService.deleteTrack(eventIdInput.val(), this.id).then(function () {
abp.notify.success('Successfully deleted');
FillFilter(stepType.NewTrack)
FillFilter(stepType.Track)
widgetManager.refresh();
});
});
@ -230,7 +230,7 @@
eventApiService.addSession(eventIdInput.val(), trackId, input).then(function () {
$('#AddSessionModal').modal('hide');
abp.notify.success('Added the session');
FillFilter(stepType.NewSession);
FillFilter(stepType.Session);
widgetManager.refresh();
});
});
@ -276,7 +276,7 @@
eventApiService.updateSession(eventIdInput.val(), editSessionForm.find('#TrackId').val(), editSessionForm.find('#SessionId').val(), input).then(function () {
$('#EditSessionModal').modal('hide');
abp.notify.success('Updated the session');
FillFilter(stepType.NewSession);
FillFilter(stepType.Session);
widgetManager.refresh();
});
});
@ -290,7 +290,7 @@
eventApiService.deleteSession(eventIdInput.val(), trackId, clickedSessionId).then(function () {
abp.notify.success('Successfully deleted');
FillFilter(stepType.NewSession)
FillFilter(stepType.Session)
widgetManager.refresh();
});
});

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

@ -1,135 +1,19 @@
@page "/event/edit/{url}"
@inject IHtmlLocalizer<EventHubResource> L
@using EventHub.Localization
@using EventHub.Web
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@model EventHub.Web.Pages.Events.EditPageModel
@inject IOptions<EventHubUrlOptions> UrlOptions
@section scripts {
<abp-script src="/Pages/Events/Edit.js"/>
<abp-script src="/libs/awesomplete/awesomplete.min.js" />
}
<form method="post" enctype="multipart/form-data">
<div class="container pt-4">
<div class="row py-4">
<div class="col-md-9 mx-auto profile-content">
<div class="card">
<div class="card-body" style="min-height: 496px">
<h3 class="mb-4">Edit Event</h3>
<div class="form">
<div class="row">
<input type="hidden" value="@Model.Url" id="event-detail-url"/>
<abp-input asp-for="Event.Id"/>
<div class="col-md-6">
<div class="form-label-group">
<select asp-for="Event.OrganizationId" asp-items="Model.Organizations" class="form-select">
<option selected value="">Organization</option>
</select>
<span asp-validation-for="Event.OrganizationId" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" id="inputTitle" asp-for="Event.Title" class="form-control" placeholder="Title">
<label for="inputTitle">Title</label>
<span asp-validation-for="Event.Title" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input id="inputStartdate" asp-for="Event.StartTime" class="form-control" placeholder="Start Date">
<label for="inputStartdate">Start Date</label>
<span asp-validation-for="Event.StartTime" class="text-danger"></span>
</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>
<span asp-validation-for="Event.EndTime" class="text-danger"></span>
</div>
</div>
<div class="col-md-12">
<div class="form-label-group form-floating">
<textarea rows="5" type="text" id="inputDescription" asp-for="Event.Description" class="form-control" placeholder="Description"></textarea>
<span asp-validation-for="Event.Description" class="text-danger"></span>
</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="@(UrlOptions.Value.Api.EnsureEndsWith('/') + $"api/eventhub/event/cover-image/{Model.Event.Id}")" 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>
<span asp-validation-for="Event.CoverImageFile" class="text-danger"></span>
</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>
<span asp-validation-for="Event.IsOnline" class="text-danger"></span>
</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>
<span asp-validation-for="Event.OnlineLink" class="text-danger"></span>
</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>
<span asp-validation-for="Event.Capacity" class="text-danger"></span>
</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>
<span asp-validation-for="Event.CountryId" class="text-danger"></span>
</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>
<span asp-validation-for="Event.City" class="text-danger"></span>
</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>
<span asp-validation-for="Event.Language" class="text-danger"></span>
</div>
@section styles {
<abp-style src="/libs/awesomplete/awesomplete.css" />
}
<div class="col-md-12 text-end">
<button type="submit" class="btn btn-primary btn-lg">
@L["Submit"]
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<div class="container mt-5">
@await Component.InvokeAsync(typeof(CreateOrEditEventAreaViewComponent), new
{
eventUrlCode = Model.UrlCode,
stepType = CreateOrEditEventAreaViewComponent.ProgressStepType.Event
})
</div>

193
src/EventHub.Web/Pages/Events/Edit.cshtml.cs

@ -1,202 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Events;
using EventHub.Organizations;
using EventHub.Web.Helpers;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Content;
using Volo.Abp.Users;
namespace EventHub.Web.Pages.Events
{
public class EditPageModel : EventHubPageModel
{
[BindProperty(SupportsGet = true)]
public new string Url { get; set; }
public string UrlCode { get; set; }
[BindProperty]
public EditEventViewModel Event { get; set; }
public List<SelectListItem> Organizations { get; private set; }
public List<SelectListItem> Countries { get; private set; }
public List<SelectListItem> Languages { get; private set; }
private readonly IEventAppService _eventAppService;
private readonly IOrganizationAppService _organizationAppService;
public EditPageModel(
IEventAppService eventAppService,
IOrganizationAppService organizationAppService)
{
_eventAppService = eventAppService;
_organizationAppService = organizationAppService;
}
public async Task OnGetAsync()
public EditPageModel()
{
var urlCode = EventUrlCodeHelper.GetCodeFromUrl(Url);
var eventDetailDto = await _eventAppService.GetByUrlCodeAsync(urlCode);
Event = ObjectMapper.Map<EventDetailDto, EditEventViewModel>(eventDetailDto);
await FillOrganizationsAsync();
await FillCountriesAsync();
FillLanguages();
}
public async Task<IActionResult> OnPostAsync()
public void OnGet(string url)
{
try
{
ValidateModel();
var updateEventDto = ObjectMapper.Map<EditEventViewModel, UpdateEventDto>(Event);
await using var memoryStream = new MemoryStream();
if (Event.CoverImageFile != null && Event.CoverImageFile.Length > 0)
{
await Event.CoverImageFile.CopyToAsync(memoryStream);
memoryStream.Position = 0;
updateEventDto.CoverImageStreamContent = new RemoteStreamContent(memoryStream, fileName: Event.CoverImageFile.FileName, contentType: Event.CoverImageFile.ContentType);
}
await _eventAppService.UpdateAsync(Event.Id, updateEventDto);
await memoryStream.DisposeAsync();
return RedirectToPage("./Detail", new { url = Url });
}
catch (Exception exception)
{
ShowAlert(exception);
await FillOrganizationsAsync();
await FillCountriesAsync();
FillLanguages();
return Page();
}
}
private async Task FillOrganizationsAsync()
{
var result = await _organizationAppService.GetOrganizationsByUserIdAsync(CurrentUser.GetId());
Organizations = result.Items.Select(
organization => new SelectListItem
{
Value = organization.Id.ToString(),
Text = organization.DisplayName
}
).ToList();
if (Event.OrganizationId != Guid.Empty)
{
Organizations.Single(x => x.Value == Event.OrganizationId.ToString()).Selected = true;
}
}
private async Task FillCountriesAsync()
{
var result = await _eventAppService.GetCountriesLookupAsync();
Countries = result.Select(
country => new SelectListItem
{
Value = country.Id.ToString(),
Text = country.Name
}
).ToList();
if (Event.CountryId.HasValue)
{
Countries.Single(x => x.Value == Event.CountryId.ToString()).Selected = true;
}
}
private void FillLanguages()
{
var result = CultureInfo.GetCultures(CultureTypes.NeutralCultures)
.DistinctBy(x => x.EnglishName)
.OrderBy(x => x.EnglishName)
.ToList();
result.Remove(result.Single(x => x.TwoLetterISOLanguageName == "iv")); // Invariant Language
Languages = result.Select(
cultureInfo => new SelectListItem
{
Value = cultureInfo.TwoLetterISOLanguageName,
Text = cultureInfo.EnglishName
}
).ToList();
if (!string.IsNullOrWhiteSpace(Event.Language))
{
Languages.Single(x => x.Value == Event.Language).Selected = true;
}
}
public class EditEventViewModel
{
[HiddenInput]
public Guid Id { get; set; }
[SelectItems(nameof(Organizations))]
[DisplayName("Organization")]
public Guid OrganizationId { get; set; }
[Required]
[StringLength(EventConsts.MaxTitleLength, MinimumLength = EventConsts.MinTitleLength)]
public string Title { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime StartTime { get; set; } = DateTime.Now;
[Required]
[DataType(DataType.DateTime)]
public DateTime EndTime { get; set; } = DateTime.Now;
[Required]
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)]
[TextArea]
public string Description { get; set; }
[CanBeNull]
[Display(Name = "Cover Image")]
[DataType(DataType.Upload)]
[MaxFileSize(EventConsts.MaxCoverImageFileSize)]
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })]
public IFormFile CoverImageFile { get; set; }
[Required]
public bool IsOnline { get; set; }
[CanBeNull]
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)]
public string OnlineLink { get; set; }
[SelectItems(nameof(Countries))]
[DisplayName("Country")]
public Guid? CountryId { get; set; }
[CanBeNull]
[StringLength(EventConsts.MaxCityLength, MinimumLength = EventConsts.MinCityLength)]
public string City { get; set; }
[SelectItems(nameof(Languages))]
[DisplayName("Language")]
public string Language { get; set; }
[Range(1, int.MaxValue)]
public int? Capacity { get; set; }
UrlCode = EventUrlCodeHelper.GetCodeFromUrl(url);
}
}
}
}

94
src/EventHub.Web/Pages/Events/Edit.js

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

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

@ -1,7 +1,7 @@
@page "/events/new/{eventUrlCode?}"
@inject IHtmlLocalizer<EventHubResource> L
@using EventHub.Localization
@using EventHub.Web.Pages.Events.Components.CreateEventArea
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea
@using Microsoft.AspNetCore.Mvc.Localization
@model EventHub.Web.Pages.Events.NewPageModel
@ -90,10 +90,10 @@
}
else
{
@await Component.InvokeAsync(typeof(CreateEventAreaViewComponent), new
@await Component.InvokeAsync(typeof(CreateOrEditEventAreaViewComponent), new
{
eventUrlCode = Model.EventUrlCode,
stepType = CreateEventAreaViewComponent.ProgressStepType.NewEvent
stepType = CreateOrEditEventAreaViewComponent.ProgressStepType.Event
})
}
</div>

1
src/EventHub.Web/Pages/Pricing.cshtml

@ -8,6 +8,7 @@
<abp-style src="/Pages/Pricing.css" />
}
@* TODO(berkansasmaz): Use real words instead of dummy words.*@
<main class="static-page container mt-5">
<h1 class="text-center mb-3">Pricing</h1>
<p class="text-center mb-5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut nulla consequat, tempus sapien in,

Loading…
Cancel
Save