mirror of https://github.com/abpframework/eventhub
committed by
GitHub
37 changed files with 4033 additions and 19 deletions
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
public interface IOrganizationAppService : IApplicationService |
||||
|
{ |
||||
|
Task<PagedResultDto<OrganizationInListDto>> GetListAsync(OrganizationListFilterDto input); |
||||
|
|
||||
|
Task<OrganizationProfileDto> GetAsync(Guid id); |
||||
|
|
||||
|
Task<OrganizationProfileDto> GetByNameAsync(string name); |
||||
|
|
||||
|
Task<OrganizationProfileDto> UpdateAsync(Guid id, UpdateOrganizationDto input); |
||||
|
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations.Memberships |
||||
|
{ |
||||
|
public interface IOrganizationMembershipAppService : IApplicationService |
||||
|
{ |
||||
|
Task<PagedResultDto<OrganizationMemberDto>> GetListAsync(OrganizationMemberListFilterDto input); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations.Memberships |
||||
|
{ |
||||
|
public class OrganizationMemberDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string OrganizationName { 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,12 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations.Memberships |
||||
|
{ |
||||
|
public class OrganizationMemberListFilterDto : PagedResultRequestDto |
||||
|
{ |
||||
|
public Guid? OrganizationId { get; set; } |
||||
|
|
||||
|
public string UserName { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
public class OrganizationInListDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public int MemberCount { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
public class OrganizationListFilterDto : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public int? MinMemberCount { get; set; } |
||||
|
|
||||
|
public int? MaxMemberCount { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
public class OrganizationProfileDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public byte[] ProfilePictureContent { get; set; } |
||||
|
|
||||
|
public string OwnerUserName { get; set; } |
||||
|
|
||||
|
public string OwnerEmail { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public string Website { get; set; } |
||||
|
|
||||
|
public string TwitterUsername { get; set; } |
||||
|
|
||||
|
public string GitHubUsername { get; set; } |
||||
|
|
||||
|
public string FacebookUsername { get; set; } |
||||
|
|
||||
|
public string InstagramUsername { get; set; } |
||||
|
|
||||
|
public string MediumUsername { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using EventHub.Organizations; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
public class UpdateOrganizationDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(OrganizationConsts.MaxDisplayNameLength, MinimumLength = OrganizationConsts.MinDisplayNameLength)] |
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[StringLength(OrganizationConsts.MaxDescriptionNameLength, MinimumLength = OrganizationConsts.MinDescriptionNameLength)] |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public byte[] ProfilePictureContent { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxWebsiteLength)] |
||||
|
public string Website { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxTwitterUsernameLength)] |
||||
|
public string TwitterUsername { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxGitHubUsernameLength)] |
||||
|
public string GitHubUsername { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxFacebookUsernameLength)] |
||||
|
public string FacebookUsername { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxInstagramUsernameLength)] |
||||
|
public string InstagramUsername { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(OrganizationConsts.MaxMediumUsernameLength)] |
||||
|
public string MediumUsername { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using EventHub.Localization; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace EventHub.Admin |
||||
|
{ |
||||
|
public class EventHubAdminAppService : ApplicationService |
||||
|
{ |
||||
|
protected EventHubAdminAppService() |
||||
|
{ |
||||
|
LocalizationResource = typeof(EventHubResource); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using AutoMapper; |
||||
|
using EventHub.Admin.Organizations; |
||||
|
using EventHub.Admin.Organizations.Memberships; |
||||
|
using EventHub.Organizations; |
||||
|
using EventHub.Organizations.Memberships; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
|
||||
|
namespace EventHub.Admin |
||||
|
{ |
||||
|
public class EventHubAdminApplicationAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public EventHubAdminApplicationAutoMapperProfile() |
||||
|
{ |
||||
|
CreateMap<Organization, OrganizationInListDto>(); |
||||
|
|
||||
|
CreateMap<Organization, OrganizationProfileDto>() |
||||
|
.Ignore(x => x.OwnerUserName) |
||||
|
.Ignore(x => x.OwnerEmail) |
||||
|
.Ignore(x => x.ProfilePictureContent); |
||||
|
|
||||
|
CreateMap<OrganizationMemberWithDetails, OrganizationMemberDto>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Admin.Permissions; |
||||
|
using EventHub.Organizations.Memberships; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
|
||||
|
namespace EventHub.Admin.Organizations.Memberships |
||||
|
{ |
||||
|
[Authorize(EventHubPermissions.Organizations.Memberships.Default)] |
||||
|
public class OrganizationMembershipAppService : ApplicationService, IOrganizationMembershipAppService |
||||
|
{ |
||||
|
private readonly IOrganizationMembershipRepository _organizationMembershipRepository; |
||||
|
private readonly IRepository<IdentityUser, Guid> _userRepository; |
||||
|
|
||||
|
public OrganizationMembershipAppService( |
||||
|
IOrganizationMembershipRepository organizationMembershipRepository, |
||||
|
IRepository<IdentityUser, Guid> userRepository) |
||||
|
{ |
||||
|
_organizationMembershipRepository = organizationMembershipRepository; |
||||
|
_userRepository = userRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<PagedResultDto<OrganizationMemberDto>> GetListAsync(OrganizationMemberListFilterDto input) |
||||
|
{ |
||||
|
IdentityUser user = null; |
||||
|
if (!input.UserName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
input.UserName = input.UserName.ToLower(); |
||||
|
user = await _userRepository.SingleOrDefaultAsync(x => x.UserName.ToLower() == input.UserName); |
||||
|
if (user is null) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.UserNotFound) |
||||
|
.WithData("UserName", input.UserName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var members = await _organizationMembershipRepository.GetMemberListAsync(input.OrganizationId, user?.Id, input.SkipCount, input.MaxResultCount); |
||||
|
var totalCount = await _organizationMembershipRepository.GetCountAsync(input.OrganizationId, user?.Id); |
||||
|
|
||||
|
return new PagedResultDto<OrganizationMemberDto>( |
||||
|
totalCount, |
||||
|
ObjectMapper.Map<List<OrganizationMemberWithDetails>, List<OrganizationMemberDto>>(members) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,165 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Admin.Permissions; |
||||
|
using EventHub.Organizations; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.BlobStoring; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace EventHub.Admin.Organizations |
||||
|
{ |
||||
|
[Authorize(EventHubPermissions.Organizations.Default)] |
||||
|
public class OrganizationAppService : EventHubAdminAppService, IOrganizationAppService |
||||
|
{ |
||||
|
private readonly IRepository<Organization, Guid> _organizationRepository; |
||||
|
private readonly IRepository<IdentityUser, Guid> _identityUserRepository; |
||||
|
private readonly IBlobContainer<OrganizationProfilePictureContainer> _organizationBlobContainer; |
||||
|
|
||||
|
public OrganizationAppService( |
||||
|
IRepository<Organization, Guid> organizationRepository, |
||||
|
IRepository<IdentityUser, Guid> identityUserRepository, |
||||
|
IBlobContainer<OrganizationProfilePictureContainer> organizationBlobContainer) |
||||
|
{ |
||||
|
_organizationRepository = organizationRepository; |
||||
|
_identityUserRepository = identityUserRepository; |
||||
|
_organizationBlobContainer = organizationBlobContainer; |
||||
|
} |
||||
|
|
||||
|
public async Task<PagedResultDto<OrganizationInListDto>> GetListAsync(OrganizationListFilterDto input) |
||||
|
{ |
||||
|
var query = await _organizationRepository.GetQueryableAsync(); |
||||
|
|
||||
|
if (!input.Name.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
input.Name = input.Name.ToLower(); |
||||
|
query = query.Where(o => o.Name.ToLower().Contains(input.Name)); |
||||
|
} |
||||
|
|
||||
|
if (!input.DisplayName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
input.DisplayName = input.DisplayName.ToLower(); |
||||
|
query = query.Where(o => o.DisplayName.ToLower().Contains(input.DisplayName)); |
||||
|
} |
||||
|
|
||||
|
if (input.MinMemberCount != null) |
||||
|
{ |
||||
|
query = query.Where(o => o.MemberCount >= input.MinMemberCount); |
||||
|
} |
||||
|
|
||||
|
if (input.MaxMemberCount != null) |
||||
|
{ |
||||
|
query = query.Where(o => o.MemberCount <= input.MaxMemberCount); |
||||
|
} |
||||
|
|
||||
|
var totalCount = await AsyncExecuter.CountAsync(query); |
||||
|
|
||||
|
query = query.OrderBy(string.IsNullOrWhiteSpace(input.Sorting) |
||||
|
? OrganizationConsts.DefaultSorting |
||||
|
: input.Sorting); |
||||
|
|
||||
|
query = query.PageBy(input); |
||||
|
|
||||
|
var organizationListDto = ObjectMapper |
||||
|
.Map<List<Organization>, List<OrganizationInListDto>>(await AsyncExecuter.ToListAsync(query)); |
||||
|
|
||||
|
return new PagedResultDto<OrganizationInListDto>(totalCount, organizationListDto); |
||||
|
} |
||||
|
|
||||
|
public async Task<OrganizationProfileDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var organization = await _organizationRepository.GetAsync(id); |
||||
|
|
||||
|
var dto = ObjectMapper.Map<Organization, OrganizationProfileDto>(organization); |
||||
|
|
||||
|
var user = await _identityUserRepository.GetAsync(organization.OwnerUserId); |
||||
|
dto.OwnerUserName = user.UserName; |
||||
|
dto.OwnerEmail = user.Email; |
||||
|
|
||||
|
dto.ProfilePictureContent = await GetCoverImageAsync(organization.Id); |
||||
|
|
||||
|
return dto; |
||||
|
} |
||||
|
|
||||
|
public async Task<OrganizationProfileDto> GetByNameAsync(string name) |
||||
|
{ |
||||
|
var organization = await _organizationRepository.FindAsync(x => x.Name.ToLower() == name.ToLower()); |
||||
|
if (organization is null) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.OrganizationNotFound) |
||||
|
.WithData("OrganizationName", name); |
||||
|
} |
||||
|
|
||||
|
var dto = ObjectMapper.Map<Organization, OrganizationProfileDto>(organization); |
||||
|
|
||||
|
var user = await _identityUserRepository.GetAsync(organization.OwnerUserId); |
||||
|
dto.OwnerUserName = user.UserName; |
||||
|
dto.OwnerEmail = user.Email; |
||||
|
|
||||
|
dto.ProfilePictureContent = await GetCoverImageAsync(organization.Id); |
||||
|
|
||||
|
return dto; |
||||
|
} |
||||
|
|
||||
|
[Authorize(EventHubPermissions.Organizations.Update)] |
||||
|
public async Task<OrganizationProfileDto> UpdateAsync(Guid id, UpdateOrganizationDto input) |
||||
|
{ |
||||
|
var organization = await _organizationRepository.GetAsync(id); |
||||
|
|
||||
|
organization.SetDisplayName(input.DisplayName); |
||||
|
organization.SetDescription(input.Description); |
||||
|
|
||||
|
organization.Website = input.Website; |
||||
|
organization.TwitterUsername = input.TwitterUsername; |
||||
|
organization.GitHubUsername = input.GitHubUsername; |
||||
|
organization.FacebookUsername = input.FacebookUsername; |
||||
|
organization.InstagramUsername = input.InstagramUsername; |
||||
|
organization.MediumUsername = input.MediumUsername; |
||||
|
|
||||
|
if (input.ProfilePictureContent?.Length > 0) |
||||
|
{ |
||||
|
await SaveCoverImageAsync(organization.Id, input.ProfilePictureContent); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
await DeleteCoverImageAsync(organization.Id); |
||||
|
} |
||||
|
|
||||
|
await _organizationRepository.UpdateAsync(organization); |
||||
|
|
||||
|
return ObjectMapper.Map<Organization, OrganizationProfileDto>(organization); |
||||
|
} |
||||
|
|
||||
|
[Authorize(EventHubPermissions.Organizations.Delete)] |
||||
|
public async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await _organizationRepository.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
private async Task<byte[]> GetCoverImageAsync(Guid id) |
||||
|
{ |
||||
|
var blobName = id.ToString(); |
||||
|
|
||||
|
return await _organizationBlobContainer.GetAllBytesOrNullAsync(blobName); |
||||
|
} |
||||
|
|
||||
|
private async Task SaveCoverImageAsync(Guid id, byte[] coverImageContent) |
||||
|
{ |
||||
|
var blobName = id.ToString(); |
||||
|
|
||||
|
await _organizationBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting: true); |
||||
|
} |
||||
|
|
||||
|
private async Task DeleteCoverImageAsync(Guid id) |
||||
|
{ |
||||
|
var blobName = id.ToString(); |
||||
|
|
||||
|
await _organizationBlobContainer.DeleteAsync(blobName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Admin.Organizations.Memberships; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace EventHub.Admin.Controllers.Organizations.Memberships |
||||
|
{ |
||||
|
[Controller] |
||||
|
[Area("eventhub-admin")] |
||||
|
[ControllerName("OrganizationMembership")] |
||||
|
[Route("/api/eventhub/organization-memberships")] |
||||
|
public class OrganizationMembershipController : AbpController, IOrganizationMembershipAppService |
||||
|
{ |
||||
|
private readonly IOrganizationMembershipAppService _organizationMembershipAppService; |
||||
|
|
||||
|
public OrganizationMembershipController(IOrganizationMembershipAppService organizationMembershipAppService) |
||||
|
{ |
||||
|
_organizationMembershipAppService = organizationMembershipAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public async Task<PagedResultDto<OrganizationMemberDto>> GetListAsync(OrganizationMemberListFilterDto input) |
||||
|
{ |
||||
|
return await _organizationMembershipAppService.GetListAsync(input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Admin.Organizations; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace EventHub.Admin.Controllers.Organizations |
||||
|
{ |
||||
|
[Controller] |
||||
|
[Area("eventhub-admin")] |
||||
|
[ControllerName("Organization")] |
||||
|
[Route("/api/eventhub/organizations")] |
||||
|
public class OrganizationController : AbpController, IOrganizationAppService |
||||
|
{ |
||||
|
private readonly IOrganizationAppService _organizationAppService; |
||||
|
|
||||
|
public OrganizationController(IOrganizationAppService organizationAppService) |
||||
|
{ |
||||
|
_organizationAppService = organizationAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public Task<PagedResultDto<OrganizationInListDto>> GetListAsync(OrganizationListFilterDto input) |
||||
|
{ |
||||
|
return _organizationAppService.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public Task<OrganizationProfileDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return _organizationAppService.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-name/{name}")] |
||||
|
public Task<OrganizationProfileDto> GetByNameAsync(string name) |
||||
|
{ |
||||
|
return _organizationAppService.GetByNameAsync(name); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
public Task<OrganizationProfileDto> UpdateAsync(Guid id, UpdateOrganizationDto input) |
||||
|
{ |
||||
|
return _organizationAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
public Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return _organizationAppService.DeleteAsync(id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,268 @@ |
|||||
|
@page "/organizations" |
||||
|
@using Volo.Abp.BlazoriseUI.Components |
||||
|
@using EventHub.Admin.Permissions |
||||
|
@using Microsoft.AspNetCore.Authorization |
||||
|
@using EventHub.Admin.Organizations |
||||
|
@using EventHub.Organizations |
||||
|
@using Volo.Abp.AspNetCore.Components.Notifications |
||||
|
@inherits EventHubComponentBase |
||||
|
@inject NavigationManager NavigationManager |
||||
|
@attribute [Authorize(EventHubPermissions.Organizations.Default)] |
||||
|
@inject IOrganizationAppService OrganizationAppService |
||||
|
@inject IUiNotificationService UiNotificationService |
||||
|
|
||||
|
<Card> |
||||
|
<CardHeader> |
||||
|
@* ************************* PAGE HEADER ************************* *@ |
||||
|
<h2>@L["Organizations"]</h2> |
||||
|
</CardHeader> |
||||
|
|
||||
|
@* ************************* SEARCH ************************* *@ |
||||
|
|
||||
|
<CardBody> |
||||
|
<Form> |
||||
|
<div id="FilterSection" class="row mt-3"> |
||||
|
<Column ColumnSize="ColumnSize.Is3"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["Name"]</FieldLabel> |
||||
|
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@Filter.Name"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
|
||||
|
<Column ColumnSize="ColumnSize.Is3"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["DisplayName"]</FieldLabel> |
||||
|
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@Filter.DisplayName"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
|
||||
|
<Column ColumnSize="ColumnSize.Is3"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["MinMemberCount"]</FieldLabel> |
||||
|
<NumericEdit TValue="int?" KeyPress="OnKeyPress" @bind-Value="@Filter.MinMemberCount"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
|
||||
|
<Column ColumnSize="ColumnSize.Is3"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["MaxMemberCount"]</FieldLabel> |
||||
|
<NumericEdit TValue="int?" KeyPress="OnKeyPress" @bind-Value="@Filter.MaxMemberCount"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
</div> |
||||
|
</Form> |
||||
|
|
||||
|
@* ************************* DATA GRID ************************* *@ |
||||
|
<DataGrid TItem="OrganizationInListDto" |
||||
|
Data="OrganizationList" |
||||
|
ReadData="OnDataGridReadAsync" |
||||
|
TotalItems="TotalCount" |
||||
|
ShowPager="true" |
||||
|
PageSize="PageSize" |
||||
|
Responsive="true"> |
||||
|
<DataGridColumns> |
||||
|
<DataGridEntityActionsColumn TItem="OrganizationInListDto"> |
||||
|
<DisplayTemplate> |
||||
|
<EntityActions TItem="OrganizationInListDto"> |
||||
|
<EntityAction TItem="OrganizationInListDto" |
||||
|
RequiredPolicy="@EventHubPermissions.Organizations.Memberships.Default" |
||||
|
Clicked="@(() => NavigationManager.NavigateTo($"/organization-memberships/{context.Id}"))" |
||||
|
Text="@L["Members"]"> |
||||
|
</EntityAction> |
||||
|
<EntityAction TItem="OrganizationInListDto" |
||||
|
RequiredPolicy="@EventHubPermissions.Organizations.Update" |
||||
|
Clicked="() => OpenEditOrganizationModal(context)" |
||||
|
Text="@L["Edit"]"> |
||||
|
</EntityAction> |
||||
|
<EntityAction TItem="OrganizationInListDto" |
||||
|
RequiredPolicy="@EventHubPermissions.Organizations.Delete" |
||||
|
Clicked="() => DeleteOrganizationAsync(context)" |
||||
|
ConfirmationMessage="@(() => L["DeleteConfirmationMessage"])" |
||||
|
Text="@L["Delete"]"> |
||||
|
</EntityAction> |
||||
|
</EntityActions> |
||||
|
</DisplayTemplate> |
||||
|
</DataGridEntityActionsColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationInListDto" |
||||
|
Field="Name" |
||||
|
Caption="@L["Name"]"> |
||||
|
</DataGridColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationInListDto" |
||||
|
Field="DisplayName" |
||||
|
Caption="@L["DisplayName"]"> |
||||
|
</DataGridColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationInListDto" |
||||
|
Field="MemberCount" |
||||
|
Caption="@L["MemberCount"]"> |
||||
|
</DataGridColumn> |
||||
|
</DataGridColumns> |
||||
|
</DataGrid> |
||||
|
</CardBody> |
||||
|
</Card> |
||||
|
|
||||
|
@* ************************* EDIT MODAL ************************* *@ |
||||
|
|
||||
|
<Modal @ref="EditOrganizationModal" Closing="@OnEditModalClosing"> |
||||
|
<ModalContent Centered="true" Size="ModalSize.Large"> |
||||
|
<Form id="EditOrganizationForm"> |
||||
|
<ModalHeader> |
||||
|
<ModalTitle>@L["UpdateOrganization"]</ModalTitle> |
||||
|
<CloseButton Clicked="() => EditOrganizationModal.Hide()"/> |
||||
|
</ModalHeader> |
||||
|
<ModalBody> |
||||
|
<Tabs SelectedTab="@SelectedTabInEditModal" SelectedTabChanged="@OnSelectedTabChangedInEditModal"> |
||||
|
<Items> |
||||
|
<Tab Name="@TabContentInEditModal.OrganizationProfile.ToString()">@L["OrganizationInfo"]</Tab> |
||||
|
<Tab Name="@TabContentInEditModal.ProfileImage.ToString()">@L["ProfileImage"]</Tab> |
||||
|
</Items> |
||||
|
<Content> |
||||
|
<TabPanel Name="@TabContentInEditModal.OrganizationProfile.ToString()"> |
||||
|
<Validations Mode="ValidationMode.Auto" Model="@EditOrganizationModal" ValidateOnLoad="false"> |
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["DisplayName"] *</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.DisplayName"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["Description"] *</FieldLabel> |
||||
|
<MemoEdit Rows="4" TValue="string" @bind-Text="@EditingOrganization.Description"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</MemoEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["Website"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.Website"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["TwitterUsername"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.TwitterUsername"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["GitHubUsername"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.GitHubUsername"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["FacebookUsername"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.FacebookUsername"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["InstagramUsername"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.InstagramUsername"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
<Validation> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["MediumUsername"]</FieldLabel> |
||||
|
<TextEdit TValue="string" @bind-Text="@EditingOrganization.MediumUsername"> |
||||
|
<Feedback> |
||||
|
<ValidationError/> |
||||
|
</Feedback> |
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
</Validation> |
||||
|
|
||||
|
</Validations> |
||||
|
</TabPanel> |
||||
|
<TabPanel Name="@TabContentInEditModal.ProfileImage.ToString()"> |
||||
|
@if (!IsLoadingProfileImage) |
||||
|
{ |
||||
|
@if (!ProfileImageUrl.IsNullOrEmpty()) |
||||
|
{ |
||||
|
<div class="text-center mt-4"> |
||||
|
<img src="@ProfileImageUrl" class="organization-profile-img" width="600" height="340" alt="profile-image"/> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<div class="d-flex justify-content-center mt-4"> |
||||
|
<div class="spinner-border" role="status"> |
||||
|
<span class="sr-only">@L["Loading"]...</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
<div class="mt-3 mb-2"> |
||||
|
<Field Horizontal="true"> |
||||
|
<FieldLabel ColumnSize="ColumnSize.Is3">@L["ChooseProfileImage"]</FieldLabel> |
||||
|
<FieldBody ColumnSize="ColumnSize.Is6"> |
||||
|
<FileEdit MaxMessageSize="@OrganizationConsts.MaxProfilePictureFileSize" Filter=".jpg, .png" Changed="@OnProfileImageFileChanged" Progressed="@OnProgressedForProfileImage" AutoReset="true"/> |
||||
|
</FieldBody> |
||||
|
<Column ColumnSize="ColumnSize.Is3"> |
||||
|
@if (!ProfileImageUrl.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
<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="() => EditOrganizationModal.Hide()"> |
||||
|
@L["Cancel"] |
||||
|
</Button> |
||||
|
<Button Type="ButtonType.Submit" PreventDefaultOnSubmit="true" Color="Color.Primary" |
||||
|
Clicked="UpdateOrganizationAsync"> |
||||
|
<i class="fa-check fa"></i> @L["Save"] |
||||
|
</Button> |
||||
|
</ModalFooter> |
||||
|
</Form> |
||||
|
</ModalContent> |
||||
|
</Modal> |
||||
@ -0,0 +1,167 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Blazorise; |
||||
|
using Blazorise.DataGrid; |
||||
|
using EventHub.Admin.Organizations; |
||||
|
using Microsoft.AspNetCore.Components.Web; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Web.Pages |
||||
|
{ |
||||
|
public partial class OrganizationManagement |
||||
|
{ |
||||
|
private IReadOnlyList<OrganizationInListDto> OrganizationList { get; set; } |
||||
|
private OrganizationListFilterDto Filter { get; set; } |
||||
|
private int CurrentPage { get; set; } |
||||
|
private string CurrentSorting { get; set; } |
||||
|
private int TotalCount { get; set; } |
||||
|
private int PageSize { get; } |
||||
|
|
||||
|
private OrganizationProfileDto Organization { get; set; } |
||||
|
private string ProfileImageUrl { get; set; } |
||||
|
|
||||
|
private Guid EditingOrganizationId { get; set; } |
||||
|
private UpdateOrganizationDto EditingOrganization { get; set; } |
||||
|
private Modal EditOrganizationModal { get; set; } |
||||
|
private IFileEntry FileEntry { get; set; } |
||||
|
private bool IsLoadingProfileImage { get; set; } |
||||
|
private string SelectedTabInEditModal { get; set; } |
||||
|
|
||||
|
public OrganizationManagement() |
||||
|
{ |
||||
|
Filter = new OrganizationListFilterDto(); |
||||
|
PageSize = LimitedResultRequestDto.DefaultMaxResultCount; |
||||
|
|
||||
|
OrganizationList = new List<OrganizationInListDto>(); |
||||
|
EditingOrganization = new UpdateOrganizationDto(); |
||||
|
IsLoadingProfileImage = false; |
||||
|
SelectedTabInEditModal = TabContentInEditModal.OrganizationProfile.ToString(); |
||||
|
} |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
await GetOrganizationsAsync(); |
||||
|
} |
||||
|
|
||||
|
private async Task OnDataGridReadAsync(DataGridReadDataEventArgs<OrganizationInListDto> 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 GetOrganizationsAsync(); |
||||
|
await InvokeAsync(StateHasChanged); |
||||
|
} |
||||
|
|
||||
|
private async Task GetOrganizationsAsync() |
||||
|
{ |
||||
|
Filter.MaxResultCount = PageSize; |
||||
|
Filter.SkipCount = CurrentPage * PageSize; |
||||
|
Filter.Sorting = CurrentSorting; |
||||
|
|
||||
|
var result = await OrganizationAppService.GetListAsync(Filter); |
||||
|
OrganizationList = result.Items; |
||||
|
TotalCount = (int) result.TotalCount; |
||||
|
} |
||||
|
|
||||
|
private async Task OpenEditOrganizationModal(OrganizationInListDto input) |
||||
|
{ |
||||
|
EditingOrganizationId = input.Id; |
||||
|
Organization = await OrganizationAppService.GetAsync(EditingOrganizationId); |
||||
|
FillProfileImageUrl(Organization.ProfilePictureContent); |
||||
|
|
||||
|
EditingOrganization = ObjectMapper.Map<OrganizationProfileDto, UpdateOrganizationDto>(Organization); |
||||
|
EditOrganizationModal.Show(); |
||||
|
} |
||||
|
|
||||
|
private async Task UpdateOrganizationAsync() |
||||
|
{ |
||||
|
await OrganizationAppService.UpdateAsync(EditingOrganizationId, EditingOrganization); |
||||
|
await GetOrganizationsAsync(); |
||||
|
EditOrganizationModal.Hide(); |
||||
|
} |
||||
|
|
||||
|
private void OnDeleteCoverImageButtonClicked() |
||||
|
{ |
||||
|
EditingOrganization.ProfilePictureContent = null; |
||||
|
FileEntry = new FileEntry(); |
||||
|
ProfileImageUrl = null; |
||||
|
IsLoadingProfileImage = false; |
||||
|
} |
||||
|
|
||||
|
private async Task DeleteOrganizationAsync(OrganizationInListDto organization) |
||||
|
{ |
||||
|
await OrganizationAppService.DeleteAsync(organization.Id); |
||||
|
await GetOrganizationsAsync(); |
||||
|
} |
||||
|
|
||||
|
private async Task OnProfileImageFileChanged(FileChangedEventArgs e) |
||||
|
{ |
||||
|
FileEntry = e.Files.FirstOrDefault(); |
||||
|
if (FileEntry is null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
IsLoadingProfileImage = true; |
||||
|
|
||||
|
using (var stream = new MemoryStream()) |
||||
|
{ |
||||
|
await FileEntry.WriteToStreamAsync(stream); |
||||
|
|
||||
|
stream.Seek(0, SeekOrigin.Begin); |
||||
|
EditingOrganization.ProfilePictureContent = stream.ToArray(); |
||||
|
FillProfileImageUrl(EditingOrganization.ProfilePictureContent); |
||||
|
await InvokeAsync(StateHasChanged); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void FillProfileImageUrl(byte[] content) |
||||
|
{ |
||||
|
if (content != null) |
||||
|
{ |
||||
|
var imageBase64Data = Convert.ToBase64String(content); |
||||
|
var imageDataUrl = $"data:image/png;base64,{imageBase64Data}"; |
||||
|
ProfileImageUrl = imageDataUrl; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void OnProgressedForProfileImage(FileProgressedEventArgs e) |
||||
|
{ |
||||
|
if (e.Percentage == 100D) |
||||
|
{ |
||||
|
IsLoadingProfileImage = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void OnSelectedTabChangedInEditModal(string name) |
||||
|
{ |
||||
|
SelectedTabInEditModal = name; |
||||
|
} |
||||
|
|
||||
|
private void OnEditModalClosing(CancelEventArgs e) |
||||
|
{ |
||||
|
IsLoadingProfileImage = false; |
||||
|
SelectedTabInEditModal = TabContentInEditModal.OrganizationProfile.ToString(); |
||||
|
} |
||||
|
|
||||
|
private async Task OnKeyPress(KeyboardEventArgs e) |
||||
|
{ |
||||
|
if (e.Code == "Enter" || e.Code == "NumpadEnter") |
||||
|
{ |
||||
|
await GetOrganizationsAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public enum TabContentInEditModal : byte |
||||
|
{ |
||||
|
OrganizationProfile = 0, |
||||
|
ProfileImage |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
@page "/organization-memberships/{OrganizationId:guid?}" |
||||
|
@using Volo.Abp.BlazoriseUI.Components |
||||
|
@using EventHub.Admin.Organizations.Memberships |
||||
|
@using EventHub.Admin.Permissions |
||||
|
@using Microsoft.AspNetCore.Authorization |
||||
|
@inherits EventHubComponentBase |
||||
|
@attribute [Authorize(EventHubPermissions.Organizations.Memberships.Default)] |
||||
|
@inject IOrganizationMembershipAppService OrganizationMembershipAppService |
||||
|
|
||||
|
<Card> |
||||
|
<CardHeader> |
||||
|
@* ************************* HEADER ************************* *@ |
||||
|
<h2> |
||||
|
@L["OrganizationMemberships"] |
||||
|
@if (OrganizationId.HasValue && !OrganizationName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
<span> (@OrganizationName)</span> |
||||
|
} |
||||
|
</h2> |
||||
|
</CardHeader> |
||||
|
|
||||
|
@* ************************* SEARCH ************************* *@ |
||||
|
<CardBody> |
||||
|
<div id="FilterSection" class="mt-3 ml-2"> |
||||
|
<Row> |
||||
|
<Column ColumnSize="ColumnSize.Is6"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["OrganizationName"]</FieldLabel> |
||||
|
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@OrganizationName"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
|
||||
|
<Column ColumnSize="ColumnSize.Is6"> |
||||
|
<Field> |
||||
|
<FieldLabel>@L["UserName"]</FieldLabel> |
||||
|
<TextEdit TValue="string" KeyPress="OnKeyPress" @bind-Text="@Filter.UserName"/> |
||||
|
</Field> |
||||
|
</Column> |
||||
|
</Row> |
||||
|
</div> |
||||
|
|
||||
|
@* ************************* DATA GRID ************************* *@ |
||||
|
<DataGrid TItem="OrganizationMemberDto" |
||||
|
Data="OrganizationMemberList" |
||||
|
ReadData="OnDataGridReadAsync" |
||||
|
TotalItems="TotalCount" |
||||
|
ShowPager="true" |
||||
|
PageSize="PageSize" |
||||
|
Responsive="true" |
||||
|
Sortable="false"> |
||||
|
<DataGridColumns> |
||||
|
<DataGridColumn TItem="OrganizationMemberDto" |
||||
|
Field="OrganizationName" |
||||
|
Caption="@L["OrganizationName"]"> |
||||
|
</DataGridColumn> |
||||
|
<DataGridColumn TItem="OrganizationMemberDto" |
||||
|
Field="UserName" |
||||
|
Caption="@L["UserName"]"> |
||||
|
</DataGridColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationMemberDto" |
||||
|
Field="Email" |
||||
|
Caption="@L["Email"]"> |
||||
|
</DataGridColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationMemberDto" |
||||
|
Field="Name" |
||||
|
Caption="@L["Name"]"> |
||||
|
</DataGridColumn> |
||||
|
|
||||
|
<DataGridColumn TItem="OrganizationMemberDto" |
||||
|
Field="Surname" |
||||
|
Caption="@L["Surname"]"> |
||||
|
</DataGridColumn> |
||||
|
</DataGridColumns> |
||||
|
</DataGrid> |
||||
|
</CardBody> |
||||
|
</Card> |
||||
@ -0,0 +1,98 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Blazorise.DataGrid; |
||||
|
using EventHub.Admin.Organizations; |
||||
|
using EventHub.Admin.Organizations.Memberships; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.AspNetCore.Components.Web; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Admin.Web.Pages |
||||
|
{ |
||||
|
public partial class OrganizationMembershipManagement |
||||
|
{ |
||||
|
[Parameter] |
||||
|
public Guid? OrganizationId { get; set; } |
||||
|
private string OrganizationName { get; set; } |
||||
|
|
||||
|
[Inject] |
||||
|
protected IOrganizationAppService OrganizationAppService { get; set; } |
||||
|
|
||||
|
|
||||
|
private IReadOnlyList<OrganizationMemberDto> OrganizationMemberList { get; set; } |
||||
|
private OrganizationMemberListFilterDto Filter { get; set; } |
||||
|
private int CurrentPage { get; set; } |
||||
|
private int TotalCount { get; set; } |
||||
|
private int PageSize { get; } |
||||
|
|
||||
|
public OrganizationMembershipManagement() |
||||
|
{ |
||||
|
Filter = new OrganizationMemberListFilterDto(); |
||||
|
PageSize = LimitedResultRequestDto.DefaultMaxResultCount; |
||||
|
|
||||
|
OrganizationMemberList = new List<OrganizationMemberDto>(); |
||||
|
} |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
await GetOrganizationMembershipsAsync(); |
||||
|
|
||||
|
if (OrganizationId.HasValue) |
||||
|
{ |
||||
|
OrganizationName = (await OrganizationAppService.GetAsync(OrganizationId.Value)).Name; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task OnDataGridReadAsync(DataGridReadDataEventArgs<OrganizationMemberDto> e) |
||||
|
{ |
||||
|
CurrentPage = e.Page - 1; |
||||
|
await GetOrganizationMembershipsAsync(); |
||||
|
await InvokeAsync(StateHasChanged); |
||||
|
} |
||||
|
|
||||
|
private async Task GetOrganizationMembershipsAsync() |
||||
|
{ |
||||
|
Filter.MaxResultCount = PageSize; |
||||
|
Filter.SkipCount = CurrentPage * PageSize; |
||||
|
|
||||
|
if (OrganizationId.HasValue) |
||||
|
{ |
||||
|
Filter.OrganizationId = OrganizationId!.Value; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Filter.OrganizationId = null; |
||||
|
} |
||||
|
|
||||
|
if (!Filter.UserName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
Filter.UserName = Filter.UserName.Trim(); |
||||
|
} |
||||
|
|
||||
|
var result = await OrganizationMembershipAppService.GetListAsync(Filter); |
||||
|
OrganizationMemberList = result.Items; |
||||
|
TotalCount = (int) result.TotalCount; |
||||
|
} |
||||
|
|
||||
|
private async Task OnKeyPress(KeyboardEventArgs e) |
||||
|
{ |
||||
|
if (e.Code == "Enter" || e.Code == "NumpadEnter") |
||||
|
{ |
||||
|
if (OrganizationName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
OrganizationId = null; |
||||
|
OrganizationName = null; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var organization = await OrganizationAppService.GetByNameAsync(OrganizationName.Trim()); |
||||
|
OrganizationId = organization.Id; |
||||
|
OrganizationName = organization.Name; |
||||
|
} |
||||
|
|
||||
|
await GetOrganizationMembershipsAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace EventHub.Organizations.Memberships |
||||
|
{ |
||||
|
public interface IOrganizationMembershipRepository : IRepository<OrganizationMembership, Guid> |
||||
|
{ |
||||
|
Task<List<OrganizationMemberWithDetails>> GetMemberListAsync( |
||||
|
Guid? organizationId, |
||||
|
Guid? userId, |
||||
|
int skipCount, |
||||
|
int maxResultCount, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<int> GetCountAsync( |
||||
|
Guid? organizationId, |
||||
|
Guid? userId, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace EventHub.Organizations.Memberships |
||||
|
{ |
||||
|
public class OrganizationMemberWithDetails : Entity<Guid> |
||||
|
{ |
||||
|
public string OrganizationName { 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,40 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Organizations; |
||||
|
using EventHub.Organizations.Memberships; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities.Events; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.EventBus; |
||||
|
|
||||
|
namespace EventHub.Domain.Organizations.Memberships |
||||
|
{ |
||||
|
public class OrganizationMembershipChangedEventHandler : ILocalEventHandler<EntityCreatedEventData<OrganizationMembership>>, |
||||
|
ILocalEventHandler<EntityDeletedEventData<OrganizationMembership>>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IRepository<Organization, Guid> _organizationRepository; |
||||
|
|
||||
|
public OrganizationMembershipChangedEventHandler(IRepository<Organization, Guid> organizationRepository) |
||||
|
{ |
||||
|
_organizationRepository = organizationRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task HandleEventAsync(EntityCreatedEventData<OrganizationMembership> eventData) |
||||
|
{ |
||||
|
var organization = await _organizationRepository.GetAsync(eventData.Entity.OrganizationId); |
||||
|
|
||||
|
organization.MemberCount++; |
||||
|
|
||||
|
await _organizationRepository.UpdateAsync(organization); |
||||
|
} |
||||
|
|
||||
|
public async Task HandleEventAsync(EntityDeletedEventData<OrganizationMembership> eventData) |
||||
|
{ |
||||
|
var organization = await _organizationRepository.GetAsync(eventData.Entity.OrganizationId); |
||||
|
|
||||
|
organization.MemberCount--; |
||||
|
|
||||
|
await _organizationRepository.UpdateAsync(organization); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Organizations; |
||||
|
using EventHub.Organizations.Memberships; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace EventHub.EntityFrameworkCore.Organizations.Memberships |
||||
|
{ |
||||
|
public class OrganizationMembershipRepository : EfCoreRepository<EventHubDbContext, OrganizationMembership, Guid>, |
||||
|
IOrganizationMembershipRepository |
||||
|
{ |
||||
|
public OrganizationMembershipRepository(IDbContextProvider<EventHubDbContext> dbContextProvider) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async Task<List<OrganizationMemberWithDetails>> GetMemberListAsync( |
||||
|
Guid? organizationId, |
||||
|
Guid? userId, |
||||
|
int skipCount, |
||||
|
int maxResultCount, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var dbContext = await GetDbContextAsync(); |
||||
|
|
||||
|
var organizationMembershipsDbSet = dbContext.Set<OrganizationMembership>(); |
||||
|
var identityUserDbSet = dbContext.Set<IdentityUser>(); |
||||
|
var organizationDbSet = dbContext.Set<Organization>(); |
||||
|
|
||||
|
var query = organizationMembershipsDbSet |
||||
|
.Join(organizationDbSet, t => t.OrganizationId, organization => organization.Id, |
||||
|
(organizationMember, organization) => new {organizationMember, organization}) |
||||
|
.Join(identityUserDbSet, organizationWithMember => organizationWithMember.organizationMember.UserId, |
||||
|
user => user.Id, (organizationWithMember, user) => new {organizationWithMember, user}) |
||||
|
.WhereIf(userId.HasValue, t => t.user.Id == userId) |
||||
|
.WhereIf(organizationId.HasValue, |
||||
|
t => t.organizationWithMember.organizationMember.OrganizationId == organizationId) |
||||
|
.OrderByDescending(o => o.organizationWithMember.organizationMember.CreationTime) |
||||
|
.Select(t => new OrganizationMemberWithDetails |
||||
|
{ |
||||
|
OrganizationName = t.organizationWithMember.organization.Name, |
||||
|
UserName = t.user.UserName, |
||||
|
Email = t.user.Email, |
||||
|
Name = t.user.Name, |
||||
|
Surname = t.user.Surname |
||||
|
}); |
||||
|
|
||||
|
return await query |
||||
|
.PageBy(skipCount, maxResultCount) |
||||
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
|
||||
|
public async Task<int> GetCountAsync( |
||||
|
Guid? organizationId, |
||||
|
Guid? userId, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var dbContext = await GetDbContextAsync(); |
||||
|
|
||||
|
var organizationMembershipsDbSet = dbContext.Set<OrganizationMembership>(); |
||||
|
var identityUserDbSet = dbContext.Set<IdentityUser>(); |
||||
|
|
||||
|
return await organizationMembershipsDbSet |
||||
|
.Join(identityUserDbSet, organizationMember => organizationMember.UserId, user => user.Id, |
||||
|
(organizationMember, user) => new {organizationMember, user}) |
||||
|
.WhereIf(userId.HasValue, t => t.user.Id == userId) |
||||
|
.WhereIf(organizationId.HasValue, t => t.organizationMember.OrganizationId == organizationId) |
||||
|
.CountAsync(GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace EventHub.Migrations |
||||
|
{ |
||||
|
public partial class Added_MemberCount_To_Organization : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AddColumn<int>( |
||||
|
name: "MemberCount", |
||||
|
table: "EhOrganizations", |
||||
|
type: "integer", |
||||
|
nullable: false, |
||||
|
defaultValue: 0); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "MemberCount", |
||||
|
table: "EhOrganizations"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue