mirror of https://github.com/abpframework/eventhub
committed by
GitHub
47 changed files with 1928 additions and 33 deletions
@ -0,0 +1,10 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public class CountryLookupDto : EntityDto<Guid> |
|||
{ |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public class EventDetailDto : EntityDto<Guid> |
|||
{ |
|||
public string Title { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
|
|||
public DateTime EndTime { get; set; } |
|||
|
|||
public byte[] CoverImageContent { get; set; } |
|||
|
|||
public bool IsOnline { get; set; } |
|||
|
|||
public string OnlineLink { get; set; } |
|||
|
|||
public Guid? CountryId { get; set; } |
|||
|
|||
public string City { get; set; } |
|||
|
|||
public string Language { get; set; } |
|||
|
|||
public int? Capacity { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public class EventInListDto : EntityDto<Guid> |
|||
{ |
|||
public string Title { get; set; } |
|||
|
|||
public string OrganizationDisplayName { get; set; } |
|||
|
|||
public int AttendeeCount { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public class EventListFilterDto : PagedAndSortedResultRequestDto |
|||
{ |
|||
public DateTime? MinStartTime { get; set; } |
|||
public DateTime? MaxStartTime { get; set; } |
|||
public string Title { get; set; } |
|||
public string OrganizationDisplayName { get; set; } |
|||
public int? MinAttendeeCount { get; set; } |
|||
public int? MaxAttendeeCount { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public interface IEventAppService : IApplicationService |
|||
{ |
|||
Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input); |
|||
|
|||
Task<EventDetailDto> GetAsync(Guid id); |
|||
|
|||
Task UpdateAsync(Guid id, UpdateEventDto input); |
|||
|
|||
Task<List<CountryLookupDto>> GetCountriesLookupAsync(); |
|||
|
|||
Task<byte[]> GetCoverImageAsync(Guid id); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace EventHub.Admin.Events.Registrations |
|||
{ |
|||
public class EventAttendeeDto |
|||
{ |
|||
public Guid UserId { get; set; } |
|||
|
|||
public string UserName { get; set; } |
|||
|
|||
public string Email { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string Surname { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Events.Registrations |
|||
{ |
|||
public class GetEventRegistrationListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public Guid EventId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventHub.Admin.Events.Registrations |
|||
{ |
|||
public interface IEventRegistrationAppService : IApplicationService |
|||
{ |
|||
Task<PagedResultDto<EventAttendeeDto>> GetAttendeesAsync(GetEventRegistrationListInput input); |
|||
|
|||
Task UnRegisterAttendeeAsync(Guid eventId, Guid attendeeId); |
|||
|
|||
Task RegisterUsersAsync(Guid eventId, List<Guid> userIds); |
|||
|
|||
Task<List<Guid>> GetAllAttendeeIdsAsync(Guid eventId); |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using EventHub.Events; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
public class UpdateEventDto |
|||
{ |
|||
[Required] |
|||
[StringLength(EventConsts.MaxTitleLength, MinimumLength = EventConsts.MinTitleLength)] |
|||
public string Title { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)] |
|||
public string Description { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.DateTime)] |
|||
public DateTime StartTime { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.DateTime)] |
|||
public DateTime EndTime { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public byte[] CoverImageContent { get; set; } |
|||
|
|||
public bool IsOnline { get; set; } |
|||
|
|||
[CanBeNull] |
|||
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)] |
|||
public string OnlineLink { get; set; } |
|||
public Guid? CountryId { get; set; } |
|||
|
|||
[CanBeNull] |
|||
[StringLength(EventConsts.MaxCityLength, MinimumLength = EventConsts.MinCityLength)] |
|||
public string City { get; set; } |
|||
|
|||
[CanBeNull] |
|||
[StringLength(EventConsts.MaxLanguageLength, MinimumLength = EventConsts.MinLanguageLength)] |
|||
public string Language { get; set; } |
|||
|
|||
[Range(1, int.MaxValue)] |
|||
public int? Capacity { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Users |
|||
{ |
|||
public class GetUserListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string Username { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventHub.Admin.Users |
|||
{ |
|||
public interface IUserAppService : IApplicationService |
|||
{ |
|||
Task<PagedResultDto<UserDto>> GetListAsync(GetUserListInput input); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Auditing; |
|||
|
|||
namespace EventHub.Admin.Users |
|||
{ |
|||
public class UserDto : EntityDto<Guid>, IHasCreationTime |
|||
{ |
|||
public string Username { get; set; } |
|||
|
|||
public string Email { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string Surname { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Permissions; |
|||
using EventHub.Countries; |
|||
using EventHub.Events; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EventHub.Admin.Events |
|||
{ |
|||
[Authorize(EventHubPermissions.Events.Default)] |
|||
public class EventAppService : EventHubAdminAppService, IEventAppService |
|||
{ |
|||
private readonly IEventRepository _eventRepository; |
|||
private readonly IBlobContainer<EventCoverImageContainer> _eventBlobContainer; |
|||
private readonly EventManager _eventManager; |
|||
private readonly IRepository<Country, Guid> _countryRepository; |
|||
|
|||
public EventAppService( |
|||
IEventRepository eventRepository, |
|||
IBlobContainer<EventCoverImageContainer> eventBlobContainer, |
|||
EventManager eventManager, |
|||
IRepository<Country, Guid> countryRepository) |
|||
{ |
|||
_eventRepository = eventRepository; |
|||
_eventBlobContainer = eventBlobContainer; |
|||
_eventManager = eventManager; |
|||
_countryRepository = countryRepository; |
|||
} |
|||
|
|||
public async Task<EventDetailDto> GetAsync(Guid id) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
|
|||
var eventDetailDto = ObjectMapper.Map<Event, EventDetailDto>(@event); |
|||
eventDetailDto.CoverImageContent = await GetCoverImageAsync(id); |
|||
|
|||
return eventDetailDto; |
|||
} |
|||
|
|||
public async Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input) |
|||
{ |
|||
var totalCount = await _eventRepository.GetCountAsync(input.Title, input.OrganizationDisplayName, input.MinAttendeeCount, |
|||
input.MaxAttendeeCount, input.MinStartTime, input.MaxStartTime); |
|||
|
|||
var items = await _eventRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, |
|||
input.Title, input.OrganizationDisplayName, input.MinAttendeeCount, input.MaxAttendeeCount, |
|||
input.MinStartTime, input.MaxStartTime); |
|||
|
|||
var events = ObjectMapper.Map<List<EventWithDetails>, List<EventInListDto>>(items); |
|||
|
|||
return new PagedResultDto<EventInListDto>(totalCount, events); |
|||
} |
|||
|
|||
[Authorize(EventHubPermissions.Events.Update)] |
|||
public async Task UpdateAsync(Guid id, UpdateEventDto input) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
|
|||
await _eventManager.SetLocationAsync(@event, input.IsOnline, input.OnlineLink, input.CountryId, input.City); |
|||
@event.SetTitle(input.Title); |
|||
@event.SetDescription(input.Description); |
|||
@event.Language = input.Language; |
|||
@event.SetTime(input.StartTime, @event.EndTime); |
|||
await _eventManager.SetCapacityAsync(@event, input.Capacity); |
|||
|
|||
await SetCoverImageAsync(blobName: id.ToString(), input.CoverImageContent); |
|||
|
|||
await _eventRepository.UpdateAsync(@event); |
|||
} |
|||
|
|||
public async Task<byte[]> GetCoverImageAsync(Guid id) |
|||
{ |
|||
var blobName = id.ToString(); |
|||
|
|||
return await _eventBlobContainer.GetAllBytesOrNullAsync(blobName); |
|||
} |
|||
|
|||
public async Task<List<CountryLookupDto>> GetCountriesLookupAsync() |
|||
{ |
|||
var countriesQueryable = await _countryRepository.GetQueryableAsync(); |
|||
|
|||
var query = from country in countriesQueryable |
|||
orderby country.Name |
|||
select country; |
|||
|
|||
var countries = await AsyncExecuter.ToListAsync(query); |
|||
|
|||
return ObjectMapper.Map<List<Country>, List<CountryLookupDto>>(countries); |
|||
} |
|||
|
|||
private async Task SetCoverImageAsync(string blobName, byte[] coverImageContent, bool overrideExisting = true) |
|||
{ |
|||
await _eventBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Permissions; |
|||
using Volo.Abp.Application.Dtos; |
|||
using EventHub.Events.Registrations; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using EventHub.Events; |
|||
using EventHub.Users; |
|||
|
|||
namespace EventHub.Admin.Events.Registrations |
|||
{ |
|||
[Authorize(EventHubPermissions.Events.Registrations.Default)] |
|||
public class EventRegistrationAppService : EventHubAdminAppService, IEventRegistrationAppService |
|||
{ |
|||
private readonly IUserRepository _userRepository; |
|||
private readonly IEventRegistrationRepository _eventRegistrationRepository; |
|||
private readonly IEventRepository _eventRepository; |
|||
private readonly EventRegistrationManager _eventRegistrationManager; |
|||
|
|||
public EventRegistrationAppService( |
|||
IUserRepository userRepository, |
|||
IEventRegistrationRepository eventRegistrationRepository, |
|||
IEventRepository eventRepository, |
|||
EventRegistrationManager eventRegistrationManager) |
|||
{ |
|||
_userRepository = userRepository; |
|||
_eventRegistrationRepository = eventRegistrationRepository; |
|||
_eventRepository = eventRepository; |
|||
_eventRegistrationManager = eventRegistrationManager; |
|||
} |
|||
|
|||
public async Task<PagedResultDto<EventAttendeeDto>> GetAttendeesAsync(GetEventRegistrationListInput input) |
|||
{ |
|||
var totalCount = await _eventRegistrationRepository.GetCountAsync(input.EventId); |
|||
var items = await _eventRegistrationRepository.GetListAsync(input.EventId, input.Sorting, input.SkipCount, input.MaxResultCount); |
|||
var users = ObjectMapper.Map<List<EventRegistrationWithDetails>, List<EventAttendeeDto>>(items); |
|||
|
|||
return new PagedResultDto<EventAttendeeDto>(totalCount, users); |
|||
} |
|||
|
|||
[Authorize(EventHubPermissions.Events.Registrations.RemoveAttendee)] |
|||
public async Task UnRegisterAttendeeAsync(Guid eventId, Guid attendeeId) |
|||
{ |
|||
await _eventRegistrationRepository.DeleteAsync(x => x.EventId == eventId && x.UserId == attendeeId); |
|||
} |
|||
|
|||
[Authorize(EventHubPermissions.Events.Registrations.AddAttendee)] |
|||
public async Task RegisterUsersAsync(Guid eventId, List<Guid> userIds) |
|||
{ |
|||
if (userIds == null || !userIds.Any()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var @event = await _eventRepository.GetAsync(eventId); |
|||
|
|||
var userQueryable = await _userRepository.GetQueryableAsync(); |
|||
var query = userQueryable.Where(user => userIds.Contains(user.Id)); |
|||
|
|||
var users = await AsyncExecuter.ToListAsync(query); |
|||
foreach (var user in users) |
|||
{ |
|||
await _eventRegistrationManager.RegisterAsync(@event, user); |
|||
} |
|||
} |
|||
|
|||
public async Task<List<Guid>> GetAllAttendeeIdsAsync(Guid eventId) |
|||
{ |
|||
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync(); |
|||
var userQueryable = await _userRepository.GetQueryableAsync(); |
|||
|
|||
var query = from eventRegistration in eventRegistrationQueryable |
|||
join user in userQueryable on eventRegistration.UserId equals user.Id |
|||
where eventRegistration.EventId == eventId |
|||
orderby eventRegistration.CreationTime descending |
|||
select user.Id; |
|||
|
|||
return await AsyncExecuter.ToListAsync(query); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Permissions; |
|||
using EventHub.Users; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace EventHub.Admin.Users |
|||
{ |
|||
[Authorize(EventHubPermissions.Users.Default)] |
|||
public class UserAppService : EventHubAdminAppService, IUserAppService |
|||
{ |
|||
private readonly IUserRepository _userRepository; |
|||
|
|||
public UserAppService(IUserRepository userRepository) |
|||
{ |
|||
_userRepository = userRepository; |
|||
} |
|||
|
|||
public async Task<PagedResultDto<UserDto>> GetListAsync(GetUserListInput input) |
|||
{ |
|||
var totalCount = await _userRepository.GetCountAsync(input.Username); |
|||
var items = await _userRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Username); |
|||
var users = ObjectMapper.Map<List<IdentityUser>, List<UserDto>>(items); |
|||
|
|||
return new PagedResultDto<UserDto>(totalCount, users); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Events; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace EventHub.Admin.Controllers.Events |
|||
{ |
|||
[RemoteService(Name = EventHubAdminRemoteServiceConsts.RemoteServiceName)] |
|||
[Controller] |
|||
[Area("eventhub-admin")] |
|||
[ControllerName("Event")] |
|||
[Route("/api/eventhub/admin/event")] |
|||
public class EventController : AbpController, IEventAppService |
|||
{ |
|||
private readonly IEventAppService _eventAppService; |
|||
|
|||
public EventController(IEventAppService eventAppService) |
|||
{ |
|||
_eventAppService = eventAppService; |
|||
} |
|||
|
|||
[HttpGet("{id}")] |
|||
public Task<EventDetailDto> GetAsync(Guid id) |
|||
{ |
|||
return _eventAppService.GetAsync(id); |
|||
} |
|||
|
|||
[HttpGet("countries")] |
|||
public Task<List<CountryLookupDto>> GetCountriesLookupAsync() |
|||
{ |
|||
return _eventAppService.GetCountriesLookupAsync(); |
|||
} |
|||
|
|||
[HttpGet("cover-image/{id}")] |
|||
public Task<byte[]> GetCoverImageAsync(Guid id) |
|||
{ |
|||
return _eventAppService.GetCoverImageAsync(id); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input) |
|||
{ |
|||
return _eventAppService.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
public Task UpdateAsync(Guid id, UpdateEventDto input) |
|||
{ |
|||
return _eventAppService.UpdateAsync(id, input); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Events.Registrations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace EventHub.Admin.Controllers.Events.Registrations |
|||
{ |
|||
[RemoteService(Name = EventHubAdminRemoteServiceConsts.RemoteServiceName)] |
|||
[Controller] |
|||
[Area("eventhub-admin")] |
|||
[ControllerName("EventRegistration")] |
|||
[Route("/api/eventhub/admin/event-registration")] |
|||
public class EventRegistrationController : AbpController, IEventRegistrationAppService |
|||
{ |
|||
private readonly IEventRegistrationAppService _eventRegistrationAppService; |
|||
|
|||
public EventRegistrationController(IEventRegistrationAppService eventRegistrationAppService) |
|||
{ |
|||
_eventRegistrationAppService = eventRegistrationAppService; |
|||
} |
|||
|
|||
[HttpGet("{eventId}")] |
|||
public Task<List<Guid>> GetAllAttendeeIdsAsync(Guid eventId) |
|||
{ |
|||
return _eventRegistrationAppService.GetAllAttendeeIdsAsync(eventId); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public Task<PagedResultDto<EventAttendeeDto>> GetAttendeesAsync(GetEventRegistrationListInput input) |
|||
{ |
|||
return _eventRegistrationAppService.GetAttendeesAsync(input); |
|||
} |
|||
|
|||
[HttpPost] |
|||
public Task RegisterUsersAsync(Guid eventId, List<Guid> userIds) |
|||
{ |
|||
return _eventRegistrationAppService.RegisterUsersAsync(eventId, userIds); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
public Task UnRegisterAttendeeAsync(Guid eventId, Guid attendeeId) |
|||
{ |
|||
return _eventRegistrationAppService.UnRegisterAttendeeAsync(eventId, attendeeId); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using EventHub.Admin.Users; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace EventHub.Admin.Controllers.Users |
|||
{ |
|||
[RemoteService(Name = EventHubAdminRemoteServiceConsts.RemoteServiceName)] |
|||
[Controller] |
|||
[Area("eventhub-admin")] |
|||
[ControllerName("User")] |
|||
[Route("/api/eventhub/admin/user")] |
|||
public class UserController : AbpController, IUserAppService |
|||
{ |
|||
private readonly IUserAppService _userAppService; |
|||
|
|||
public UserController(IUserAppService userAppService) |
|||
{ |
|||
_userAppService = userAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public Task<PagedResultDto<UserDto>> GetListAsync(GetUserListInput input) |
|||
{ |
|||
return _userAppService.GetListAsync(input); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
@using EventHub.Admin.Users |
|||
@inherits EventHubComponentBase |
|||
@inject IUserAppService UserAppService |
|||
|
|||
<Modal @ref="@UserPickerModal" Closing="@ClosingUserPickerModal"> |
|||
<ModalContent Centered="true"> |
|||
<ModalHeader> |
|||
<ModalTitle>@L["AddUser"]</ModalTitle> |
|||
<CloseButton Clicked="CloseUserPickerModalAsync" /> |
|||
</ModalHeader> |
|||
<ModalBody> |
|||
<div id="UserFilterSection" class="row mt-3"> |
|||
<Column ColumnSize="ColumnSize.Is12"> |
|||
<Field> |
|||
<FieldLabel>@L["UserName"]</FieldLabel> |
|||
<TextEdit TValue="string" KeyPress="OnKeyPressed" @bind-Text="@Filter.Username" /> |
|||
</Field> |
|||
</Column> |
|||
</div> |
|||
|
|||
<DataGrid TItem="UserDto" |
|||
Data="UserList" |
|||
ReadData="OnDataGridReadAsync" |
|||
TotalItems="TotalCount" |
|||
ShowPager="true" |
|||
PageSize="PageSize" |
|||
Responsive="true"> |
|||
<DataGridColumns> |
|||
<DataGridColumn Sortable="false" TItem="UserDto" Field="@nameof(UserDto.Id)"> |
|||
<CaptionTemplate> |
|||
<Check TValue="bool" @bind-Checked="@AllUserSelected"></Check> |
|||
</CaptionTemplate> |
|||
<DisplayTemplate> |
|||
@if (SelectAllUsers.ContainsKey(context.Id)) |
|||
{ |
|||
<Check TValue="bool" @bind-Checked="@SelectAllUsers[context.Id]"></Check> |
|||
} |
|||
</DisplayTemplate> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="UserDto" Field="@nameof(UserDto.Username)" Caption="@L["UserName"].Value"> |
|||
<DisplayTemplate> |
|||
@(context.Username) |
|||
</DisplayTemplate> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="UserDto" Field="@nameof(UserDto.Name)" Caption="@L["Name"].Value"> |
|||
<DisplayTemplate> |
|||
@(context.Name) |
|||
</DisplayTemplate> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="UserDto" Field="@nameof(UserDto.Surname)" Caption="@L["Surname"].Value"> |
|||
<DisplayTemplate> |
|||
@(context.Surname) |
|||
</DisplayTemplate> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="UserDto" Field="@nameof(UserDto.Email)" Caption="@L["Email"].Value"> |
|||
<DisplayTemplate> |
|||
@(context.Email) |
|||
</DisplayTemplate> |
|||
</DataGridColumn> |
|||
</DataGridColumns> |
|||
</DataGrid> |
|||
</ModalBody> |
|||
<ModalFooter> |
|||
<Button Color="Color.Secondary" Clicked="CloseUserPickerModalAsync">@L["Cancel"]</Button> |
|||
<Button Color="Color.Primary" Clicked="SaveUserPickerFormAsync">@L["Save"]</Button> |
|||
</ModalFooter> |
|||
</ModalContent> |
|||
</Modal> |
|||
@ -0,0 +1,128 @@ |
|||
using Blazorise; |
|||
using EventHub.Admin.Users; |
|||
using Microsoft.AspNetCore.Components; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Blazorise.DataGrid; |
|||
using Microsoft.AspNetCore.Components.Web; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventHub.Admin.Web.Components.UserPicker |
|||
{ |
|||
public partial class UserPicker |
|||
{ |
|||
public Modal UserPickerModal { get; set; } |
|||
|
|||
[Parameter] |
|||
public EventCallback SaveFormAsync { get; set; } |
|||
|
|||
[Parameter] |
|||
public List<Guid> SelectedUserIds { get; set; } = new List<Guid>(); |
|||
|
|||
private GetUserListInput Filter { get; set; } |
|||
|
|||
private IReadOnlyList<UserDto> UserList { get; set; } |
|||
private int CurrentPage { get; set; } |
|||
private string CurrentSorting { get; set; } |
|||
private int TotalCount { get; set; } |
|||
private int PageSize { get; } |
|||
|
|||
public Dictionary<Guid, bool> SelectAllUsers = new(); |
|||
private bool AllUserSelected |
|||
{ |
|||
get => SelectAllUsers.All(x => x.Value); |
|||
set |
|||
{ |
|||
foreach (var key in SelectAllUsers.Keys) |
|||
{ |
|||
SelectAllUsers[key] = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public UserPicker() |
|||
{ |
|||
Filter = new GetUserListInput(); |
|||
PageSize = LimitedResultRequestDto.DefaultMaxResultCount; |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await GetUsersAsync(); |
|||
} |
|||
|
|||
protected override async Task OnParametersSetAsync() |
|||
{ |
|||
await GetUsersAsync(); |
|||
} |
|||
|
|||
private async Task GetUsersAsync() |
|||
{ |
|||
Filter.MaxResultCount = PageSize; |
|||
Filter.SkipCount = CurrentPage * PageSize; |
|||
Filter.Sorting = CurrentSorting; |
|||
|
|||
var result = await UserAppService.GetListAsync(Filter); |
|||
UserList = result.Items; |
|||
TotalCount = (int)result.TotalCount; |
|||
|
|||
FillSelectedUserList(); |
|||
} |
|||
|
|||
private void FillSelectedUserList() |
|||
{ |
|||
SelectAllUsers = new Dictionary<Guid, bool>(); |
|||
|
|||
foreach (var user in UserList) |
|||
{ |
|||
SelectAllUsers.Add(user.Id, SelectedUserIds.Contains(user.Id)); |
|||
} |
|||
} |
|||
|
|||
private async Task OnKeyPressed(KeyboardEventArgs e) |
|||
{ |
|||
if (e.Code is "Enter" or "NumpadEnter") |
|||
{ |
|||
await GetUsersAsync(); |
|||
} |
|||
} |
|||
|
|||
private async Task OnDataGridReadAsync(DataGridReadDataEventArgs<UserDto> e) |
|||
{ |
|||
CurrentSorting = e.Columns |
|||
.Where(c => c.Direction != SortDirection.None) |
|||
.Select(c => c.Field + (c.Direction == SortDirection.Descending ? " DESC" : "")) |
|||
.JoinAsString(","); |
|||
CurrentPage = e.Page - 1; |
|||
|
|||
await GetUsersAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
public Task OpenUserPickerModalAsync() |
|||
{ |
|||
UserPickerModal.Show(); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public Task CloseUserPickerModalAsync() |
|||
{ |
|||
UserPickerModal.Hide(); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
private async Task SaveUserPickerFormAsync() |
|||
{ |
|||
await SaveFormAsync.InvokeAsync(); |
|||
} |
|||
|
|||
private void ClosingUserPickerModal(ModalClosingEventArgs eventArgs) |
|||
{ |
|||
eventArgs.Cancel = eventArgs.CloseReason == CloseReason.FocusLostClosing; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
@page "/event/{EventId:guid}/attendees" |
|||
@using EventHub.Admin.Web.Components.UserPicker |
|||
@using EventHub.Admin.Events.Registrations |
|||
@using EventHub.Admin.Permissions |
|||
@using EventHub.Admin.Users |
|||
@inherits EventHubComponentBase |
|||
@inject IEventRegistrationAppService EventRegistrationAppService |
|||
@inject IUserAppService UserAppService |
|||
|
|||
<Card> |
|||
<CardHeader> |
|||
<h2>@L["Attendees"]</h2> |
|||
|
|||
<Paragraph Alignment="TextAlignment.Right"> |
|||
@if (CanAddAttendee) |
|||
{ |
|||
<Button Color="Color.Primary" |
|||
Clicked="OpenUserPickerModal"> |
|||
@L["AddNewUser"] |
|||
</Button> |
|||
} |
|||
</Paragraph> |
|||
</CardHeader> |
|||
|
|||
<CardBody> |
|||
<DataGrid TItem="EventAttendeeDto" |
|||
Data="AttendeeList" |
|||
ReadData="OnDataGridReadAsync" |
|||
TotalItems="TotalCount" |
|||
ShowPager="true" |
|||
PageSize="PageSize" |
|||
Responsive="true"> |
|||
<DataGridColumns> |
|||
<DataGridEntityActionsColumn TItem="EventAttendeeDto"> |
|||
<DisplayTemplate> |
|||
<EntityActions TItem="EventAttendeeDto"> |
|||
<EntityAction TItem="EventAttendeeDto" |
|||
RequiredPolicy="@EventHubPermissions.Events.Registrations.RemoveAttendee" |
|||
Clicked="() => RemoveAttendeeAsync(context)" |
|||
ConfirmationMessage="@(() => L["AttendeeRemoveConfirmationMessage"])" |
|||
Text="@L["RemoveUser"]"> |
|||
</EntityAction> |
|||
</EntityActions> |
|||
</DisplayTemplate> |
|||
</DataGridEntityActionsColumn> |
|||
|
|||
<DataGridColumn TItem="EventAttendeeDto" |
|||
Field="UserName" |
|||
Caption="@L["UserName"]"> |
|||
</DataGridColumn> |
|||
<DataGridColumn TItem="EventAttendeeDto" |
|||
Field="Name" |
|||
Caption="@L["Name"]"> |
|||
</DataGridColumn> |
|||
<DataGridColumn TItem="EventAttendeeDto" |
|||
Field="Surname" |
|||
Caption="@L["Surname"]"> |
|||
</DataGridColumn> |
|||
<DataGridColumn TItem="EventAttendeeDto" |
|||
Field="Email" |
|||
Caption="@L["Email"]"> |
|||
</DataGridColumn> |
|||
</DataGridColumns> |
|||
</DataGrid> |
|||
</CardBody> |
|||
</Card> |
|||
|
|||
|
|||
<UserPicker @ref="UserPickerModalRef" SelectedUserIds="SelectedUserIds" SaveFormAsync="AddSelectedUsersToEventAsync" /> |
|||
@ -0,0 +1,113 @@ |
|||
using Microsoft.AspNetCore.Components; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Admin.Events.Registrations; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Blazorise; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Blazorise.DataGrid; |
|||
using EventHub.Admin.Permissions; |
|||
using EventHub.Admin.Web.Components.UserPicker; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
|
|||
namespace EventHub.Admin.Web.Pages |
|||
{ |
|||
public partial class AttendeeDetail |
|||
{ |
|||
[Parameter] |
|||
public Guid EventId { get; set; } |
|||
private IReadOnlyList<EventAttendeeDto> AttendeeList { get; set; } |
|||
private int CurrentPage { get; set; } |
|||
private string CurrentSorting { get; set; } |
|||
private int TotalCount { get; set; } |
|||
private int PageSize { get; } |
|||
private bool CanAddAttendee { get; set; } |
|||
private GetEventRegistrationListInput Filter { get; set; } |
|||
|
|||
public UserPicker UserPickerModalRef { get; set; } |
|||
private List<Guid> SelectedUserIds { get; set; } |
|||
public AttendeeDetail() |
|||
{ |
|||
PageSize = LimitedResultRequestDto.DefaultMaxResultCount; |
|||
Filter = new GetEventRegistrationListInput(); |
|||
SelectedUserIds = new List<Guid>(); |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await SetPermissionsAsync(); |
|||
await GetAttendeesAsync(); |
|||
} |
|||
|
|||
private async Task GetAttendeesAsync() |
|||
{ |
|||
Filter.EventId = EventId; |
|||
Filter.MaxResultCount = PageSize; |
|||
Filter.SkipCount = CurrentPage * PageSize; |
|||
Filter.Sorting = CurrentSorting; |
|||
|
|||
var result = await EventRegistrationAppService.GetAttendeesAsync(Filter); |
|||
|
|||
AttendeeList = result.Items; |
|||
TotalCount = (int)result.TotalCount; |
|||
|
|||
SelectedUserIds = await EventRegistrationAppService.GetAllAttendeeIdsAsync(EventId); |
|||
} |
|||
|
|||
private async Task SetPermissionsAsync() |
|||
{ |
|||
CanAddAttendee = await AuthorizationService.IsGrantedAsync(EventHubPermissions.Events.Registrations.AddAttendee); |
|||
} |
|||
|
|||
private async Task OnDataGridReadAsync(DataGridReadDataEventArgs<EventAttendeeDto> e) |
|||
{ |
|||
CurrentSorting = e.Columns |
|||
.Where(c => c.Direction != SortDirection.None) |
|||
.Select(c => c.Field + (c.Direction == SortDirection.Descending ? " DESC" : "")) |
|||
.JoinAsString(","); |
|||
CurrentPage = e.Page - 1; |
|||
|
|||
await GetAttendeesAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
private async Task RemoveAttendeeAsync(EventAttendeeDto attendee) |
|||
{ |
|||
await EventRegistrationAppService.UnRegisterAttendeeAsync(EventId, attendee.UserId); |
|||
await GetAttendeesAsync(); |
|||
} |
|||
|
|||
private async Task AddSelectedUsersToEventAsync() |
|||
{ |
|||
try |
|||
{ |
|||
var selectedUserIds = UserPickerModalRef |
|||
.SelectAllUsers |
|||
.Where(x => x.Value) |
|||
.Select(x => x.Key) |
|||
.ToList(); |
|||
|
|||
var removedAttendees = SelectedUserIds.Except(selectedUserIds).ToList(); |
|||
foreach (var attendeeId in removedAttendees) |
|||
{ |
|||
await EventRegistrationAppService.UnRegisterAttendeeAsync(EventId, attendeeId); |
|||
} |
|||
|
|||
await EventRegistrationAppService.RegisterUsersAsync(EventId, selectedUserIds); |
|||
await UserPickerModalRef.CloseUserPickerModalAsync(); |
|||
|
|||
await GetAttendeesAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
private async Task OpenUserPickerModal() |
|||
{ |
|||
await UserPickerModalRef.OpenUserPickerModalAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,293 @@ |
|||
@page "/events" |
|||
@using Microsoft.AspNetCore.Authorization |
|||
@using EventHub.Admin.Permissions |
|||
@using EventHub.Admin.Events |
|||
@using EventHub.Events |
|||
@using Volo.Abp.AspNetCore.Components.Notifications |
|||
@inherits EventHubComponentBase |
|||
@attribute [Authorize(EventHubPermissions.Events.Default)] |
|||
@inject IEventAppService EventAppService |
|||
@inject NavigationManager NavigationManager |
|||
|
|||
<Card> |
|||
<CardHeader> |
|||
<h2>@L["Events"]</h2> |
|||
</CardHeader> |
|||
|
|||
<CardBody> |
|||
<Form> |
|||
<div id="FilterSection" class="row mt-3"> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["Title"]</FieldLabel> |
|||
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@Filter.Title"/> |
|||
</Field> |
|||
</Column> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["OrganizationDisplayName"]</FieldLabel> |
|||
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@Filter.OrganizationDisplayName"/> |
|||
</Field> |
|||
</Column> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["MinStartTime"]</FieldLabel> |
|||
<DateEdit TValue="DateTime?" Date="@Filter.MinStartTime" DateChanged="OnSelectedDateChangedForMinStartTime" /> |
|||
</Field> |
|||
</Column> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["MaxStartTime"]</FieldLabel> |
|||
<DateEdit TValue="DateTime?" Date="@Filter.MaxStartTime" DateChanged="OnSelectedDateChangedForMaxStartTime" /> |
|||
</Field> |
|||
</Column> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["MinAttendeeCount"]</FieldLabel> |
|||
<NumericEdit TValue="int?" KeyPress="OnKeyPress" @bind-Value="@Filter.MinAttendeeCount"/> |
|||
</Field> |
|||
</Column> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
<Field> |
|||
<FieldLabel>@L["MaxAttendeeCount"]</FieldLabel> |
|||
<NumericEdit TValue="int?" KeyPress="OnKeyPress" @bind-Value="@Filter.MaxAttendeeCount"/> |
|||
</Field> |
|||
</Column> |
|||
</div> |
|||
</Form> |
|||
|
|||
<DataGrid TItem="EventInListDto" |
|||
Data="EventList" |
|||
ReadData="OnDataGridReadAsync" |
|||
TotalItems="TotalCount" |
|||
ShowPager="true" |
|||
PageSize="PageSize" |
|||
Responsive="true"> |
|||
<DataGridColumns> |
|||
<DataGridEntityActionsColumn TItem="EventInListDto"> |
|||
<DisplayTemplate> |
|||
<EntityActions TItem="EventInListDto"> |
|||
<EntityAction TItem="EventInListDto" |
|||
RequiredPolicy="@EventHubPermissions.Events.Update" |
|||
Clicked="() => OpenEditEventModal(context)" |
|||
Text="@L["Edit"]"> |
|||
</EntityAction> |
|||
<EntityAction TItem="EventInListDto" |
|||
RequiredPolicy="@EventHubPermissions.Events.Registrations.Default" |
|||
Clicked="@(() => NavigationManager.NavigateTo($"/event/{context.Id}/attendees"))" |
|||
Text="@L["Attendees"]"> |
|||
</EntityAction> |
|||
</EntityActions> |
|||
</DisplayTemplate> |
|||
</DataGridEntityActionsColumn> |
|||
|
|||
<DataGridColumn TItem="EventInListDto" |
|||
Field="Title" |
|||
Caption="@L["Title"]"> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="EventInListDto" |
|||
Field="OrganizationDisplayName" |
|||
Caption="@L["OrganizationDisplayName"]"> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="EventInListDto" |
|||
Field="AttendeeCount" |
|||
Caption="@L["AttendeeCount"]"> |
|||
</DataGridColumn> |
|||
|
|||
<DataGridColumn TItem="EventInListDto" |
|||
Field="StartTime" |
|||
Caption="@L["StartTime"]"> |
|||
</DataGridColumn> |
|||
</DataGridColumns> |
|||
</DataGrid> |
|||
</CardBody> |
|||
</Card> |
|||
|
|||
<Modal @ref="EditEventModal" Closing="@OnEditModalClosing"> |
|||
<ModalContent Centered="true" Size="ModalSize.Large"> |
|||
<Form id="EditEventForm"> |
|||
<ModalHeader> |
|||
<ModalTitle>@L["UpdateEvent"]</ModalTitle> |
|||
<CloseButton Clicked="() => EditEventModal.Hide()" /> |
|||
</ModalHeader> |
|||
<ModalBody> |
|||
<Tabs SelectedTab="@SelectedTabInEditModal" SelectedTabChanged="@OnSelectedTabChangedInEditModal"> |
|||
<Items> |
|||
<Tab Name="@EventEditTabs.EventInfo.ToString()">@L["EventInfo"]</Tab> |
|||
<Tab Name="@EventEditTabs.Timing.ToString()">@L["Timing"]</Tab> |
|||
<Tab Name="@EventEditTabs.CoverImage.ToString()">@L["CoverImage"]</Tab> |
|||
</Items> |
|||
<Content> |
|||
<TabPanel Name="@EventEditTabs.EventInfo.ToString()" Class="mt-3"> |
|||
<Validations Mode="ValidationMode.Auto" Model="@EditEventModal" ValidateOnLoad="false"> |
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["Title"] *</FieldLabel> |
|||
<TextEdit TValue="string" @bind-Text="@EditingEvent.Title"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</TextEdit> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["Description"] *</FieldLabel> |
|||
<MemoEdit @bind-Text="@EditingEvent.Description"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</MemoEdit> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["IsOnline"]</FieldLabel> |
|||
<Select @bind-SelectedValue="@EditingEvent.IsOnline"> |
|||
<SelectItem Value="@Boolean.TrueString">@L["Online"]</SelectItem> |
|||
<SelectItem Value="@Boolean.FalseString">@L["InPerson"]</SelectItem> |
|||
</Select> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["Language"]</FieldLabel> |
|||
<Select @bind-SelectedValue="@EditingEvent.Language"> |
|||
@if (Languages != null && Languages.Any()) |
|||
{ |
|||
foreach (var language in Languages) |
|||
{ |
|||
<SelectItem Value="@language.Value">@language.Text</SelectItem> |
|||
} |
|||
} |
|||
</Select> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
@if (EditingEvent.IsOnline) |
|||
{ |
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["OnlineLink"] *</FieldLabel> |
|||
<MemoEdit @bind-Text="@EditingEvent.OnlineLink"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</MemoEdit> |
|||
</Field> |
|||
</Validation> |
|||
} |
|||
else |
|||
{ |
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["Country"] *</FieldLabel> |
|||
<Select @bind-SelectedValue="@EditingEvent.CountryId"> |
|||
@if (Countries != null && Countries.Any()) |
|||
{ |
|||
@foreach (var country in Countries) |
|||
{ |
|||
<SelectItem Value="@country.Id">@country.Name</SelectItem> |
|||
} |
|||
} |
|||
</Select> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["City"] *</FieldLabel> |
|||
<TextEdit TValue="string" @bind-Text="@EditingEvent.City"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</TextEdit> |
|||
</Field> |
|||
</Validation> |
|||
} |
|||
|
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["Capacity"]</FieldLabel> |
|||
<NumericEdit TValue="int?" @bind-Value="@EditingEvent.Capacity"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</NumericEdit> |
|||
</Field> |
|||
</Validation> |
|||
|
|||
</Validations> |
|||
</TabPanel> |
|||
<TabPanel Name="@EventEditTabs.Timing.ToString()" Class="mt-3"> |
|||
<Validations Mode="ValidationMode.Auto" Model="@EditEventModal" ValidateOnLoad="false"> |
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["StartTime"] *</FieldLabel> |
|||
<DateEdit TValue="DateTime" @bind-Date="@EditingEvent.StartTime"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</DateEdit> |
|||
</Field> |
|||
</Validation> |
|||
<Validation> |
|||
<Field> |
|||
<FieldLabel>@L["EndTime"] *</FieldLabel> |
|||
<DateEdit TValue="DateTime" @bind-Date="@EditingEvent.EndTime"> |
|||
<Feedback> |
|||
<ValidationError/> |
|||
</Feedback> |
|||
</DateEdit> |
|||
</Field> |
|||
</Validation> |
|||
</Validations> |
|||
</TabPanel> |
|||
<TabPanel Name="@EventEditTabs.CoverImage.ToString()" Class="mt-3"> |
|||
@if (!string.IsNullOrEmpty(CoverImageUrl)) |
|||
{ |
|||
<div class="text-center mt-4"> |
|||
<img src="@CoverImageUrl" class="event-cover" width="600" height="340" alt="cover-image"/> |
|||
</div> |
|||
} |
|||
|
|||
<div class="mt-3 mb-2"> |
|||
<Field Horizontal="true"> |
|||
<FieldLabel ColumnSize="ColumnSize.Is3">@L["ChooseCoverImage"]</FieldLabel> |
|||
<FieldBody ColumnSize="ColumnSize.Is6"> |
|||
<FileEdit MaxMessageSize="@EventConsts.MaxCoverImageFileSize" Filter="@string.Join(", ", EventConsts.AllowedCoverImageExtensions)" Changed="@OnCoverImageFileChanged" AutoReset="true"/> |
|||
</FieldBody> |
|||
<Column ColumnSize="ColumnSize.Is3"> |
|||
@if (!string.IsNullOrEmpty(CoverImageUrl)) |
|||
{ |
|||
<Button Color="Color.Warning" Clicked="@OnDeleteCoverImageButtonClicked">@L["DeleteCoverImage"]</Button> |
|||
} |
|||
else |
|||
{ |
|||
<Button disabled Color="Color.Secondary" Clicked="@OnDeleteCoverImageButtonClicked">@L["DeleteCoverImage"]</Button> |
|||
} |
|||
</Column> |
|||
</Field> |
|||
</div> |
|||
</TabPanel> |
|||
</Content> |
|||
</Tabs> |
|||
</ModalBody> |
|||
<ModalFooter> |
|||
<Button Color="Color.Secondary" |
|||
Clicked="() => EditEventModal.Hide()"> |
|||
@L["Cancel"] |
|||
</Button> |
|||
<Button Type="ButtonType.Submit" PreventDefaultOnSubmit="true" Color="Color.Primary" |
|||
Clicked="UpdateEventAsync"> |
|||
<i class="fa-check fa"></i> @L["Save"] |
|||
</Button> |
|||
</ModalFooter> |
|||
</Form> |
|||
</ModalContent> |
|||
</Modal> |
|||
@ -0,0 +1,202 @@ |
|||
using EventHub.Admin.Events; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Blazorise; |
|||
using Blazorise.DataGrid; |
|||
using Volo.Abp.Application.Dtos; |
|||
using System; |
|||
using System.ComponentModel; |
|||
using Microsoft.AspNetCore.Components.Web; |
|||
using System.IO; |
|||
using System.Globalization; |
|||
using NUglify.Helpers; |
|||
using Volo.Abp; |
|||
|
|||
namespace EventHub.Admin.Web.Pages |
|||
{ |
|||
public partial class EventManagement |
|||
{ |
|||
private IReadOnlyList<EventInListDto> EventList { get; set; } |
|||
private EventListFilterDto Filter { get; set; } |
|||
private int CurrentPage { get; set; } |
|||
private string CurrentSorting { get; set; } |
|||
private int TotalCount { get; set; } |
|||
private int PageSize { get; } |
|||
private Guid EditingEventId { get; set; } |
|||
private EventDetailDto Event { get; set; } |
|||
private UpdateEventDto EditingEvent { get; set; } |
|||
private Modal EditEventModal { get; set; } |
|||
private string SelectedTabInEditModal { get; set; } |
|||
private string CoverImageUrl { get; set; } |
|||
private IFileEntry FileEntry { get; set; } |
|||
private List<CountryLookupDto> Countries { get; set; } |
|||
private List<Language> Languages { get; set; } |
|||
|
|||
public EventManagement() |
|||
{ |
|||
Filter = new EventListFilterDto(); |
|||
PageSize = LimitedResultRequestDto.DefaultMaxResultCount; |
|||
SelectedTabInEditModal = EventEditTabs.EventInfo.ToString(); |
|||
EditingEvent = new UpdateEventDto(); |
|||
Countries = new List<CountryLookupDto>(); |
|||
Languages = new List<Language>(); |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await GetEventsAsync(); |
|||
await FillCountriesAsync(); |
|||
FillLanguages(); |
|||
} |
|||
|
|||
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 Language |
|||
{ |
|||
Value = cultureInfo.TwoLetterISOLanguageName, |
|||
Text = cultureInfo.EnglishName |
|||
}).ToList(); |
|||
} |
|||
|
|||
private async Task GetEventsAsync() |
|||
{ |
|||
Filter.MaxResultCount = PageSize; |
|||
Filter.SkipCount = CurrentPage * PageSize; |
|||
Filter.Sorting = CurrentSorting; |
|||
|
|||
var result = await EventAppService.GetListAsync(Filter); |
|||
EventList = result.Items; |
|||
TotalCount = (int)result.TotalCount; |
|||
} |
|||
|
|||
private async Task OnDataGridReadAsync(DataGridReadDataEventArgs<EventInListDto> e) |
|||
{ |
|||
CurrentSorting = e.Columns |
|||
.Where(c => c.Direction != SortDirection.None) |
|||
.Select(c => c.Field + (c.Direction == SortDirection.Descending ? " DESC" : "")) |
|||
.JoinAsString(","); |
|||
CurrentPage = e.Page - 1; |
|||
|
|||
await GetEventsAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
private async Task OpenEditEventModal(EventInListDto input) |
|||
{ |
|||
EditingEventId = input.Id; |
|||
Event = await EventAppService.GetAsync(EditingEventId); |
|||
|
|||
EditingEvent = ObjectMapper.Map<EventDetailDto, UpdateEventDto>(Event); |
|||
FillCoverImageUrl(EditingEvent.CoverImageContent); |
|||
|
|||
EditEventModal.Show(); |
|||
} |
|||
|
|||
private void OnEditModalClosing(CancelEventArgs e) |
|||
{ |
|||
SelectedTabInEditModal = EventEditTabs.EventInfo.ToString(); |
|||
} |
|||
|
|||
private void OnSelectedTabChangedInEditModal(string name) |
|||
{ |
|||
SelectedTabInEditModal = name; |
|||
} |
|||
|
|||
private async Task UpdateEventAsync() |
|||
{ |
|||
if (!EditingEvent.IsOnline && (!EditingEvent.CountryId.HasValue || string.IsNullOrWhiteSpace(EditingEvent.City))) |
|||
{ |
|||
throw new UserFriendlyException(L["CountryAndCityRequiredForUpdateInPersonEvent"]); |
|||
} |
|||
|
|||
await EventAppService.UpdateAsync(EditingEventId, EditingEvent); |
|||
await GetEventsAsync(); |
|||
|
|||
CoverImageUrl = string.Empty; |
|||
EditEventModal.Hide(); |
|||
} |
|||
|
|||
private async Task OnKeyPress(KeyboardEventArgs e) |
|||
{ |
|||
if (e.Code is "Enter" or "NumpadEnter") |
|||
{ |
|||
await GetEventsAsync(); |
|||
} |
|||
} |
|||
|
|||
private async Task OnSelectedDateChangedForMinStartTime(DateTime? minStartTime) |
|||
{ |
|||
Filter.MinStartTime = minStartTime; |
|||
await GetEventsAsync(); |
|||
} |
|||
|
|||
private async Task OnSelectedDateChangedForMaxStartTime(DateTime? maxStartTime) |
|||
{ |
|||
Filter.MaxStartTime = maxStartTime; |
|||
await GetEventsAsync(); |
|||
} |
|||
|
|||
private void FillCoverImageUrl(byte[] content) |
|||
{ |
|||
if (content.IsNullOrEmpty()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var imageBase64Data = Convert.ToBase64String(content); |
|||
var imageDataUrl = $"data:image/png;base64,{imageBase64Data}"; |
|||
CoverImageUrl = imageDataUrl; |
|||
} |
|||
|
|||
private async Task OnCoverImageFileChanged(FileChangedEventArgs e) |
|||
{ |
|||
FileEntry = e.Files.FirstOrDefault(); |
|||
if (FileEntry is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
using (var stream = new MemoryStream()) |
|||
{ |
|||
await FileEntry.WriteToStreamAsync(stream); |
|||
|
|||
stream.Seek(0, SeekOrigin.Begin); |
|||
EditingEvent.CoverImageContent = stream.ToArray(); |
|||
FillCoverImageUrl(EditingEvent.CoverImageContent); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
} |
|||
|
|||
private void OnDeleteCoverImageButtonClicked() |
|||
{ |
|||
EditingEvent.CoverImageContent = null; |
|||
FileEntry = new FileEntry(); |
|||
CoverImageUrl = null; |
|||
} |
|||
|
|||
private async Task FillCountriesAsync() |
|||
{ |
|||
Countries = await EventAppService.GetCountriesLookupAsync(); |
|||
} |
|||
|
|||
private enum EventEditTabs : byte |
|||
{ |
|||
EventInfo, |
|||
Timing, |
|||
CoverImage |
|||
} |
|||
|
|||
private class Language |
|||
{ |
|||
public string Value { get; set; } |
|||
public string Text { get; set; } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public class EventWithDetails |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string Title { get; set; } |
|||
|
|||
public string OrganizationDisplayName { get; set; } |
|||
|
|||
public int AttendeeCount { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public interface IEventRepository : IRepository<Event, Guid> |
|||
{ |
|||
Task<int> GetCountAsync( |
|||
string title = null, |
|||
string organizationDisplayName = null, |
|||
int? minAttendeeCount = null, |
|||
int? maxAttendeeCount = null, |
|||
DateTime? minStartTime = null, |
|||
DateTime? maxStartTime = null, |
|||
CancellationToken cancellationToken = default |
|||
); |
|||
|
|||
Task<List<EventWithDetails>> 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, |
|||
CancellationToken cancellationToken = default |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using Volo.Abp.Auditing; |
|||
|
|||
namespace EventHub.Events.Registrations |
|||
{ |
|||
public class EventRegistrationWithDetails : IHasCreationTime |
|||
{ |
|||
public Guid UserId { get; set; } |
|||
|
|||
public string UserName { get; set; } |
|||
|
|||
public string Email { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string Surname { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EventHub.Events.Registrations |
|||
{ |
|||
public interface IEventRegistrationRepository : IRepository<EventRegistration, Guid> |
|||
{ |
|||
Task<int> GetCountAsync(Guid eventId, CancellationToken cancellationToken = default); |
|||
|
|||
Task<List<EventRegistrationWithDetails>> GetListAsync( |
|||
Guid eventId, |
|||
string sorting = null, |
|||
int skipCount = 0, |
|||
int maxResultCount = int.MaxValue, |
|||
CancellationToken cancellationToken = default |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace EventHub.Users |
|||
{ |
|||
public interface IUserRepository : IRepository<IdentityUser, Guid> |
|||
{ |
|||
Task<List<IdentityUser>> GetListAsync( |
|||
string sorting = null, |
|||
int skipCount = 0, |
|||
int maxResultCount = int.MaxValue, |
|||
string username = null, |
|||
CancellationToken cancellationToken = default |
|||
); |
|||
|
|||
Task<int> GetCountAsync( |
|||
string username = null, |
|||
CancellationToken cancellationToken = default |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Events; |
|||
using EventHub.Events.Registrations; |
|||
using EventHub.Organizations; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
|
|||
namespace EventHub.EntityFrameworkCore.Events |
|||
{ |
|||
public class EventRepository : EfCoreRepository<EventHubDbContext, Event, Guid>, IEventRepository |
|||
{ |
|||
public EventRepository(IDbContextProvider<EventHubDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public async Task<int> GetCountAsync( |
|||
string title = null, |
|||
string organizationDisplayName = null, |
|||
int? minAttendeeCount = null, |
|||
int? maxAttendeeCount = null, |
|||
DateTime? minStartTime = null, |
|||
DateTime? maxStartTime = null, |
|||
CancellationToken cancellationToken = default |
|||
) |
|||
{ |
|||
var dbContext = await GetDbContextAsync(); |
|||
|
|||
var eventQueryable = await GetQueryableAsync(); |
|||
var eventRegistrationQueryable = dbContext.Set<EventRegistration>().AsQueryable(); |
|||
var organizationQueryable = dbContext.Set<Organization>().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); |
|||
|
|||
return await query.CountAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
|
|||
public async Task<List<EventWithDetails>> 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, |
|||
CancellationToken cancellationToken = default |
|||
) |
|||
{ |
|||
var dbContext = await GetDbContextAsync(); |
|||
|
|||
var eventQueryable = await GetQueryableAsync(); |
|||
var eventRegistrationQueryable = dbContext.Set<EventRegistration>().AsQueryable(); |
|||
var organizationQueryable = dbContext.Set<Organization>().AsQueryable(); |
|||
|
|||
var query = (from @event in eventQueryable |
|||
join organization in organizationQueryable on @event.OrganizationId equals organization.Id |
|||
select new EventWithDetails |
|||
{ |
|||
Id = @event.Id, |
|||
Title = @event.Title, |
|||
StartTime = @event.StartTime, |
|||
OrganizationDisplayName = organization.DisplayName, |
|||
AttendeeCount = (from eventRegistration in eventRegistrationQueryable |
|||
where eventRegistration.EventId == @event.Id |
|||
select @eventRegistration).Count() |
|||
}) |
|||
.WhereIf(!string.IsNullOrWhiteSpace(title), x => x.Title.ToLower().Contains(title.ToLower())) |
|||
.WhereIf(!string.IsNullOrWhiteSpace(organizationDisplayName), |
|||
x => x.OrganizationDisplayName.ToLower().Contains(organizationDisplayName.ToLower())) |
|||
.WhereIf(minStartTime.HasValue, x => x.StartTime >= minStartTime) |
|||
.WhereIf(maxStartTime.HasValue, x => x.StartTime <= maxStartTime) |
|||
.WhereIf(minAttendeeCount.HasValue, x => x.AttendeeCount >= minAttendeeCount) |
|||
.WhereIf(maxAttendeeCount.HasValue, x => x.AttendeeCount <= maxAttendeeCount) |
|||
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? EventConsts.DefaultSorting : sorting) |
|||
.PageBy(skipCount, maxResultCount); |
|||
|
|||
return await query.ToListAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
using EventHub.Events.Registrations; |
|||
using System; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace EventHub.EntityFrameworkCore.Events.Registrations |
|||
{ |
|||
public class EventRegistrationRepository : EfCoreRepository<EventHubDbContext, EventRegistration, Guid>, IEventRegistrationRepository |
|||
{ |
|||
public EventRegistrationRepository(IDbContextProvider<EventHubDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public async Task<int> GetCountAsync(Guid eventId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var userQueryable = (await GetDbContextAsync()).Set<IdentityUser>().AsQueryable(); |
|||
|
|||
var query = from eventRegistration in (await GetQueryableAsync()) |
|||
join user in userQueryable on eventRegistration.UserId equals user.Id |
|||
where eventRegistration.EventId == eventId |
|||
select user; |
|||
|
|||
return await query.CountAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
|
|||
public async Task<List<EventRegistrationWithDetails>> GetListAsync( |
|||
Guid eventId, |
|||
string sorting = null, |
|||
int skipCount = 0, |
|||
int maxResultCount = int.MaxValue, |
|||
CancellationToken cancellationToken = default |
|||
) |
|||
{ |
|||
var userQueryable = (await GetDbContextAsync()).Set<IdentityUser>().AsQueryable(); |
|||
|
|||
var query = (from eventRegistration in (await GetQueryableAsync()) |
|||
join user in userQueryable on eventRegistration.UserId equals user.Id |
|||
where eventRegistration.EventId == eventId |
|||
select new EventRegistrationWithDetails |
|||
{ |
|||
UserId = user.Id, |
|||
Name = user.Name, |
|||
Surname = user.Surname, |
|||
UserName = user.UserName, |
|||
Email = user.Email, |
|||
CreationTime = user.CreationTime |
|||
}) |
|||
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? nameof(EventRegistrationWithDetails.CreationTime) : sorting) |
|||
.PageBy(skipCount, maxResultCount); |
|||
|
|||
return await query.ToListAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Users; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace EventHub.EntityFrameworkCore.Users |
|||
{ |
|||
public class UserRepository : EfCoreRepository<EventHubDbContext, IdentityUser, Guid>, IUserRepository |
|||
{ |
|||
public UserRepository(IDbContextProvider<EventHubDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public async Task<int> GetCountAsync(string username = null, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await (await GetQueryableAsync()) |
|||
.WhereIf(!string.IsNullOrWhiteSpace(username), user => user.UserName.ToLower().Contains(username.ToLower())) |
|||
.CountAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
|
|||
public async Task<List<IdentityUser>> GetListAsync( |
|||
string sorting = null, |
|||
int skipCount = 0, |
|||
int maxResultCount = int.MaxValue, |
|||
string username = null, |
|||
CancellationToken cancellationToken = default |
|||
) |
|||
{ |
|||
return await (await GetQueryableAsync()) |
|||
.WhereIf(!string.IsNullOrWhiteSpace(username), user => user.UserName.ToLower().Contains(username.ToLower())) |
|||
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? nameof(IdentityUser.CreationTime) : sorting) |
|||
.PageBy(skipCount, maxResultCount) |
|||
.ToListAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue