diff --git a/src/EventHub.Application.Contracts/Events/IEventAppService.cs b/src/EventHub.Application.Contracts/Events/IEventAppService.cs index c287748..0b4ec1b 100644 --- a/src/EventHub.Application.Contracts/Events/IEventAppService.cs +++ b/src/EventHub.Application.Contracts/Events/IEventAppService.cs @@ -26,6 +26,8 @@ namespace EventHub.Events Task UpdateAsync(Guid id, UpdateEventDto input); Task AddTrackAsync(Guid id, AddTractDto input); + + Task UpdateTrackAsync(Guid id, Guid trackId, UpdateTrackDto input); Task DeleteTrackAsync(Guid id, Guid trackId); diff --git a/src/EventHub.Application.Contracts/Events/SessionDto.cs b/src/EventHub.Application.Contracts/Events/SessionDto.cs new file mode 100644 index 0000000..42bf3ae --- /dev/null +++ b/src/EventHub.Application.Contracts/Events/SessionDto.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace EventHub.Events; + +public class SessionDto : EntityDto +{ + public Guid TrackId { get; set; } + + public string Title { get; set; } + + public DateTime StartTime { get; set; } + + public DateTime EndTime { get; set; } + + public string Description { get; set; } + + public string Language { get; set; } + + public List Speakers { get; set; } + + public SessionDto() + { + Speakers = new List(); + } +} diff --git a/src/EventHub.Application.Contracts/Events/SpeakerDto.cs b/src/EventHub.Application.Contracts/Events/SpeakerDto.cs new file mode 100644 index 0000000..2f00a3b --- /dev/null +++ b/src/EventHub.Application.Contracts/Events/SpeakerDto.cs @@ -0,0 +1,13 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EventHub.Events; + +public class SpeakerDto : EntityDto +{ + public Guid SessionId { get; set; } + + public Guid UserId { get; set; } + + public string UserName { get; set; } +} diff --git a/src/EventHub.Application.Contracts/Events/TrackDto.cs b/src/EventHub.Application.Contracts/Events/TrackDto.cs index 9e9e18b..2a555b9 100644 --- a/src/EventHub.Application.Contracts/Events/TrackDto.cs +++ b/src/EventHub.Application.Contracts/Events/TrackDto.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Volo.Abp.Application.Dtos; namespace EventHub.Events; @@ -6,4 +7,11 @@ namespace EventHub.Events; public class TrackDto : EntityDto { public string Name { get; set; } + + public List Sessions { get; set; } + + public TrackDto() + { + Sessions = new List(); + } } diff --git a/src/EventHub.Application.Contracts/Events/UpdateTrackDto.cs b/src/EventHub.Application.Contracts/Events/UpdateTrackDto.cs new file mode 100644 index 0000000..6434578 --- /dev/null +++ b/src/EventHub.Application.Contracts/Events/UpdateTrackDto.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace EventHub.Events; + +public class UpdateTrackDto +{ + [Required] + [StringLength(TrackConsts.MaxNameLength)] + public string Name { get; set; } +} diff --git a/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs b/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs index f73087a..4740b6b 100644 --- a/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs +++ b/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs @@ -32,7 +32,14 @@ namespace EventHub .Ignore(x => x.OrganizationName) .Ignore(x => x.OrganizationDisplayName); - CreateMap(); + CreateMap() + .ForMember(x => x.Sessions, memberOptions => memberOptions.MapFrom(m => m.Sessions)); + + CreateMap() + .ForMember(x => x.Speakers, memberOptions => memberOptions.MapFrom(m => m.Speakers)); + + CreateMap() + .Ignore(x => x.UserName); CreateMap(); diff --git a/src/EventHub.Application/Events/EventAppService.cs b/src/EventHub.Application/Events/EventAppService.cs index 75936d5..a2dc966 100644 --- a/src/EventHub.Application/Events/EventAppService.cs +++ b/src/EventHub.Application/Events/EventAppService.cs @@ -187,6 +187,11 @@ namespace EventHub.Events dto.OwnerUserName = user.UserName; dto.OwnerEmail = user.Email; + foreach (var speaker in from track in dto.Tracks from session in track.Sessions from speaker in session.Speakers select speaker) + { + speaker.UserName = (await _userRepository.GetAsync(speaker.UserId)).UserName; + } + return dto; } @@ -270,6 +275,19 @@ namespace EventHub.Events await _eventRepository.UpdateAsync(@event); } + public async Task UpdateTrackAsync(Guid id, Guid trackId, UpdateTrackDto input) + { + var @event = await _eventRepository.GetAsync(id, true); + await CheckOwnerControlAsync(@event); + + @event.UpdateTrack( + trackId, + input.Name + ); + + await _eventRepository.UpdateAsync(@event); + } + public async Task DeleteTrackAsync(Guid id, Guid trackId) { var @event = await _eventRepository.GetAsync(id, true); diff --git a/src/EventHub.Domain/Events/Event.cs b/src/EventHub.Domain/Events/Event.cs index 75e4f65..d5b9a86 100644 --- a/src/EventHub.Domain/Events/Event.cs +++ b/src/EventHub.Domain/Events/Event.cs @@ -140,6 +140,25 @@ namespace EventHub.Events return this; } + public Event UpdateTrack(Guid trackId, string name) + { + if (Tracks.Any(x => x.Name == name)) + { + throw new BusinessException(EventHubErrorCodes.TrackNameAlreadyExist) + .WithData("Name", name); + } + + var track = Tracks.SingleOrDefault(x => x.Id == trackId); + if (track is null) + { + throw new BusinessException(EventHubErrorCodes.TrackNotFound); + } + + track.SetName(name); + + return this; + } + public Event RemoveTrack(Guid trackId) { var track = Tracks.SingleOrDefault(x => x.Id == trackId); diff --git a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Events/EventRepository.cs b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Events/EventRepository.cs index e6219b8..46977ea 100644 --- a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Events/EventRepository.cs +++ b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Events/EventRepository.cs @@ -20,12 +20,12 @@ namespace EventHub.EntityFrameworkCore.Events } public async Task GetCountAsync( - string title = null, - string organizationDisplayName = null, - int? minAttendeeCount = null, - int? maxAttendeeCount = null, - DateTime? minStartTime = null, - DateTime? maxStartTime = null, + string title = null, + string organizationDisplayName = null, + int? minAttendeeCount = null, + int? maxAttendeeCount = null, + DateTime? minStartTime = null, + DateTime? maxStartTime = null, CancellationToken cancellationToken = default ) { @@ -36,35 +36,36 @@ namespace EventHub.EntityFrameworkCore.Events var organizationQueryable = dbContext.Set().AsQueryable(); var query = (from @event in eventQueryable - join organization in organizationQueryable on @event.OrganizationId equals organization.Id - select new - { - Event = @event, - Organization = organization, - AttendeeCount = (from eventRegistration in eventRegistrationQueryable - where eventRegistration.EventId == @event.Id - select @eventRegistration).Count() - }) - .WhereIf(!string.IsNullOrWhiteSpace(title), x => x.Event.Title.ToLower().Contains(title.ToLower())) - .WhereIf(!string.IsNullOrWhiteSpace(organizationDisplayName), x => x.Organization.DisplayName.ToLower().Contains(organizationDisplayName.ToLower())) - .WhereIf(minStartTime.HasValue, x => x.Event.StartTime >= minStartTime) - .WhereIf(maxStartTime.HasValue, x => x.Event.StartTime <= maxStartTime) - .WhereIf(minAttendeeCount.HasValue, x => x.AttendeeCount >= minAttendeeCount) - .WhereIf(maxAttendeeCount.HasValue, x => x.AttendeeCount <= maxAttendeeCount); + join organization in organizationQueryable on @event.OrganizationId equals organization.Id + select new + { + Event = @event, + Organization = organization, + AttendeeCount = (from eventRegistration in eventRegistrationQueryable + where eventRegistration.EventId == @event.Id + select @eventRegistration).Count() + }) + .WhereIf(!string.IsNullOrWhiteSpace(title), x => x.Event.Title.ToLower().Contains(title.ToLower())) + .WhereIf(!string.IsNullOrWhiteSpace(organizationDisplayName), + x => x.Organization.DisplayName.ToLower().Contains(organizationDisplayName.ToLower())) + .WhereIf(minStartTime.HasValue, x => x.Event.StartTime >= minStartTime) + .WhereIf(maxStartTime.HasValue, x => x.Event.StartTime <= maxStartTime) + .WhereIf(minAttendeeCount.HasValue, x => x.AttendeeCount >= minAttendeeCount) + .WhereIf(maxAttendeeCount.HasValue, x => x.AttendeeCount <= maxAttendeeCount); return await query.CountAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync( string sorting = null, - int skipCount = 0, - int maxResultCount = int.MaxValue, - string title = null, - string organizationDisplayName = null, - int? minAttendeeCount = null, - int? maxAttendeeCount = null, - DateTime? minStartTime = null, - DateTime? maxStartTime = null, + int skipCount = 0, + int maxResultCount = int.MaxValue, + string title = null, + string organizationDisplayName = null, + int? minAttendeeCount = null, + int? maxAttendeeCount = null, + DateTime? minStartTime = null, + DateTime? maxStartTime = null, CancellationToken cancellationToken = default ) { @@ -98,10 +99,13 @@ namespace EventHub.EntityFrameworkCore.Events return await query.ToListAsync(GetCancellationToken(cancellationToken)); } - + public override async Task> WithDetailsAsync() { - return (await GetQueryableAsync()).Include(x => x.Tracks).ThenInclude(x => x.Sessions); + return (await GetQueryableAsync()) + .Include(e => e.Tracks) + .ThenInclude(t => t.Sessions) + .ThenInclude(s => s.Speakers); } } } diff --git a/src/EventHub.HttpApi/Controllers/Events/EventController.cs b/src/EventHub.HttpApi/Controllers/Events/EventController.cs index fab0029..f9909e5 100644 --- a/src/EventHub.HttpApi/Controllers/Events/EventController.cs +++ b/src/EventHub.HttpApi/Controllers/Events/EventController.cs @@ -88,7 +88,14 @@ namespace EventHub.Controllers.Events await _eventAppService.AddTrackAsync(id, input); } - [HttpPost] + [HttpPut] + [Route("{id}/tracks/{trackId}")] + public async Task UpdateTrackAsync(Guid id, Guid trackId, UpdateTrackDto input) + { + await _eventAppService.UpdateTrackAsync(id, trackId, input); + } + + [HttpDelete] [Route("{id}/tracks/{trackId}")] public async Task DeleteTrackAsync(Guid id, Guid trackId) { diff --git a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml index e1b5a46..7b21f38 100644 --- a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml +++ b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/Default.cshtml @@ -24,6 +24,9 @@
+
+ +
diff --git a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addSessionSection.cshtml b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addSessionSection.cshtml new file mode 100644 index 0000000..36e8c1d --- /dev/null +++ b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addSessionSection.cshtml @@ -0,0 +1,65 @@ +@using EventHub.Web.Pages.Events +@using EventHub.Web.Pages.Events.Components.CreateEventArea +@model List + + + +@if (Model is not null) +{ +
+
+
+
+

Add Session

+ + + + @foreach (var track in Model) + { + + } + + + + + @foreach (var track in Model) + { + + } + + + +
@track.Name
+ @foreach (var session in track.Sessions) + { +
+ @session.Title + @EventDateHelper.GetTimeRangeText(TimeOnly.FromDateTime(session.StartTime), TimeOnly.FromDateTime(session.EndTime)) | @session.Language + @foreach (var speaker in session.Speakers) + { + @speaker.UserName + } + + Edit + +
+ } + +
+
+ +
+
+
+} diff --git a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addTrackSection.cshtml b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addTrackSection.cshtml index 6806b01..788cf1e 100644 --- a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addTrackSection.cshtml +++ b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/_addTrackSection.cshtml @@ -38,11 +38,11 @@ diff --git a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.js b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.js index 6c35acf..b0664c5 100644 --- a/src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.js +++ b/src/EventHub.Web/Pages/Events/Components/CreateEventArea/create-event-area.js @@ -106,13 +106,11 @@ abp.notify.error('Track name must be different from the previous name.'); return; } - eventApiService.deleteTrack(eventIdInput.val(), trackId).then(function () { - eventApiService.addTrack(eventIdInput.val(), {name: trackName}).then(function () { - $('#EditTrackModal').modal('hide'); - abp.notify.success('Updated the track'); - FillFilter(stepType.NewTrack) - widgetManager.refresh(); - }); + eventApiService.updateTrack(eventIdInput.val(), trackId, { name: trackName}).then(function () { + $('#EditTrackModal').modal('hide'); + abp.notify.success('Updated the track'); + FillFilter(stepType.NewTrack) + widgetManager.refresh(); }); }); } diff --git a/src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml b/src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml index 587f8c1..cfa7c3d 100644 --- a/src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml +++ b/src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml @@ -23,7 +23,7 @@
@eventDto.Title
- @eventDto.StartTime.ToString("hh tt", CultureInfo.InvariantCulture) - @eventDto.EndTime.ToString("hh tt", CultureInfo.InvariantCulture) | @EventDateHelper.GetLocationInfo(eventDto) + @EventDateHelper.GetTimeRangeText(TimeOnly.FromDateTime(eventDto.StartTime), TimeOnly.FromDateTime(eventDto.EndTime)) | @EventDateHelper.GetLocationInfo(eventDto)

@eventDto.Description

Learn More @@ -33,4 +33,4 @@
-} \ No newline at end of file +} diff --git a/src/EventHub.Web/Pages/Events/EventDateHelper.cs b/src/EventHub.Web/Pages/Events/EventDateHelper.cs index 0aab7c7..2b8605a 100644 --- a/src/EventHub.Web/Pages/Events/EventDateHelper.cs +++ b/src/EventHub.Web/Pages/Events/EventDateHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; using EventHub.Events; @@ -24,6 +25,16 @@ namespace EventHub.Web.Pages.Events return sb.ToString(); } + public static string GetTimeRangeText(TimeOnly startTime, TimeOnly endTime) + { + var sb = new StringBuilder(); + sb.Append(startTime.ToString("hh tt", CultureInfo.InvariantCulture)); + sb.Append(" - "); + sb.Append(endTime.ToString("hh tt", CultureInfo.InvariantCulture)); + + return sb.ToString(); + } + public static string GetLocationInfo(EventInListDto eventItem) { if (eventItem.IsOnline)