diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/IOrganizationAppService.cs b/src/EventHub.Admin.Application.Contracts/Organizations/IOrganizationAppService.cs index e2ac1ce..0a1a715 100644 --- a/src/EventHub.Admin.Application.Contracts/Organizations/IOrganizationAppService.cs +++ b/src/EventHub.Admin.Application.Contracts/Organizations/IOrganizationAppService.cs @@ -1,6 +1,5 @@ using System; using System.Threading.Tasks; -using EventHub.Admin.Application.Contracts.Organizations; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs new file mode 100644 index 0000000..b471473 --- /dev/null +++ b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs @@ -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> GetListAsync(OrganizationMemberListFilterDto input); + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs new file mode 100644 index 0000000..f356ca1 --- /dev/null +++ b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs @@ -0,0 +1,16 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EventHub.Admin.Organizations.Memberships +{ + public class OrganizationMemberDto : EntityDto + { + public string UserName { get; set; } + + public string Email { get; set; } + + public string Name { get; set; } + + public string Surname { get; set; } + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberListFilterDto.cs b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberListFilterDto.cs new file mode 100644 index 0000000..8c6cce2 --- /dev/null +++ b/src/EventHub.Admin.Application.Contracts/Organizations/Memberships/OrganizationMemberListFilterDto.cs @@ -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; } + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/OrganizationListFilterDto.cs b/src/EventHub.Admin.Application.Contracts/Organizations/OrganizationListFilterDto.cs index d9acaf1..43c2a65 100644 --- a/src/EventHub.Admin.Application.Contracts/Organizations/OrganizationListFilterDto.cs +++ b/src/EventHub.Admin.Application.Contracts/Organizations/OrganizationListFilterDto.cs @@ -1,13 +1,12 @@ -using System; using Volo.Abp.Application.Dtos; -namespace EventHub.Admin.Application.Contracts.Organizations +namespace EventHub.Admin.Organizations { public class OrganizationListFilterDto : PagedAndSortedResultRequestDto { - public string? Name { get; set; } + public string Name { get; set; } - public string? DisplayName { get; set; } + public string DisplayName { get; set; } public int? MinMemberCount { get; set; } diff --git a/src/EventHub.Admin.Application.Contracts/Organizations/UpdateOrganizationDto.cs b/src/EventHub.Admin.Application.Contracts/Organizations/UpdateOrganizationDto.cs index fcc0ce9..c90c59b 100644 --- a/src/EventHub.Admin.Application.Contracts/Organizations/UpdateOrganizationDto.cs +++ b/src/EventHub.Admin.Application.Contracts/Organizations/UpdateOrganizationDto.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel.DataAnnotations; using EventHub.Organizations; using JetBrains.Annotations; diff --git a/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissionDefinitionProvider.cs b/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissionDefinitionProvider.cs index 469f16e..b9790b9 100644 --- a/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissionDefinitionProvider.cs +++ b/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissionDefinitionProvider.cs @@ -10,10 +10,11 @@ namespace EventHub.Admin.Permissions { var eventHubGroup = context.AddGroup(EventHubPermissions.GroupName); - var tenantsPermission = eventHubGroup.AddPermission(EventHubPermissions.Organizations.Default, L("Permission:OrganizationManagement")); - tenantsPermission.AddChild(EventHubPermissions.Organizations.Create, L("Permission:Create")); - tenantsPermission.AddChild(EventHubPermissions.Organizations.Update, L("Permission:Edit")); - tenantsPermission.AddChild(EventHubPermissions.Organizations.Delete, L("Permission:Delete")); + var organizationsPermission = eventHubGroup.AddPermission(EventHubPermissions.Organizations.Default, L("Permission:OrganizationManagement")); + organizationsPermission.AddChild(EventHubPermissions.Organizations.Create, L("Permission:Create")); + organizationsPermission.AddChild(EventHubPermissions.Organizations.Update, L("Permission:Edit")); + organizationsPermission.AddChild(EventHubPermissions.Organizations.Delete, L("Permission:Delete")); + organizationsPermission.AddChild(EventHubPermissions.Organizations.Memberships.Default, L("Permission:MembershipManagement")); } private static LocalizableString L(string name) diff --git a/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissions.cs b/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissions.cs index ecae825..a1003bc 100644 --- a/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissions.cs +++ b/src/EventHub.Admin.Application.Contracts/Permissions/EventHubPermissions.cs @@ -10,6 +10,11 @@ public const string Create = Default + ".Create"; public const string Update = Default + ".Update"; public const string Delete = Default + ".Delete"; + + public static class Memberships + { + public const string Default = Organizations.Default + ".Memberships"; + } } } } \ No newline at end of file diff --git a/src/EventHub.Admin.Application/EventHubAdminAppService.cs b/src/EventHub.Admin.Application/EventHubAdminAppService.cs index 3ef4f1b..5fd1056 100644 --- a/src/EventHub.Admin.Application/EventHubAdminAppService.cs +++ b/src/EventHub.Admin.Application/EventHubAdminAppService.cs @@ -1,11 +1,11 @@ using EventHub.Localization; using Volo.Abp.Application.Services; -namespace EventHub.Admin.Application +namespace EventHub.Admin { public class EventHubAdminAppService : ApplicationService { - public EventHubAdminAppService() + protected EventHubAdminAppService() { LocalizationResource = typeof(EventHubResource); } diff --git a/src/EventHub.Admin.Application/EventHubApplicationAutoMapperProfile.cs b/src/EventHub.Admin.Application/EventHubApplicationAutoMapperProfile.cs index 6b20518..6d40c34 100644 --- a/src/EventHub.Admin.Application/EventHubApplicationAutoMapperProfile.cs +++ b/src/EventHub.Admin.Application/EventHubApplicationAutoMapperProfile.cs @@ -1,7 +1,9 @@ using AutoMapper; using EventHub.Admin.Organizations; +using EventHub.Admin.Organizations.Memberships; using EventHub.Organizations; using Volo.Abp.AutoMapper; +using Volo.Abp.Identity; namespace EventHub.Admin { @@ -15,6 +17,8 @@ namespace EventHub.Admin .Ignore(x => x.OwnerUserName) .Ignore(x => x.OwnerEmail) .Ignore(x => x.ProfilePictureContent); + + CreateMap(); } } } diff --git a/src/EventHub.Admin.Application/Organizations/Memberships/OrganizationMembershipAppService.cs b/src/EventHub.Admin.Application/Organizations/Memberships/OrganizationMembershipAppService.cs new file mode 100644 index 0000000..6dbbb00 --- /dev/null +++ b/src/EventHub.Admin.Application/Organizations/Memberships/OrganizationMembershipAppService.cs @@ -0,0 +1,52 @@ +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.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Entities; +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 _userRepository; + + public OrganizationMembershipAppService( + IOrganizationMembershipRepository organizationMembershipRepository, + IRepository userRepository) + { + _organizationMembershipRepository = organizationMembershipRepository; + _userRepository = userRepository; + } + + public async Task> GetListAsync(OrganizationMemberListFilterDto input) + { + IdentityUser user = null; + if (!input.UserName.IsNullOrWhiteSpace()) + { + input.UserName = input.UserName.ToLower(); + user = await _userRepository.SingleOrDefaultAsync(x => x.UserName.ToLower().Contains(input.UserName)); + if (user is null) + { + throw new EntityNotFoundException(typeof(IdentityUser), 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( + totalCount, + ObjectMapper.Map, List>(members) + ); + } + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Application/Organizations/OrganizationAppService.cs b/src/EventHub.Admin.Application/Organizations/OrganizationAppService.cs index fc164c1..79c3c5c 100644 --- a/src/EventHub.Admin.Application/Organizations/OrganizationAppService.cs +++ b/src/EventHub.Admin.Application/Organizations/OrganizationAppService.cs @@ -3,18 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; using System.Threading.Tasks; -using EventHub.Admin.Application; -using EventHub.Admin.Application.Contracts.Organizations; using EventHub.Admin.Permissions; using EventHub.Organizations; -using EventHub.Organizations.Memberships; -using EventHub.Users; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.BlobStoring; using Volo.Abp.Domain.Repositories; using Volo.Abp.Identity; -using Volo.Abp.Identity.Settings; namespace EventHub.Admin.Organizations { @@ -41,17 +36,14 @@ namespace EventHub.Admin.Organizations if (!input.Name.IsNullOrWhiteSpace()) { - query = query.Where(o => o.Name.Contains(input.Name)); + input.Name = input.Name.ToLower(); + query = query.Where(o => o.Name.ToLower().Contains(input.Name)); } if (!input.DisplayName.IsNullOrWhiteSpace()) { - query = query.Where(o => o.DisplayName.Contains(input.DisplayName)); - } - - if (!input.DisplayName.IsNullOrWhiteSpace()) - { - query = query.Where(o => o.DisplayName.Contains(input.DisplayName)); + input.DisplayName = input.DisplayName.ToLower(); + query = query.Where(o => o.DisplayName.ToLower().Contains(input.DisplayName)); } if (input.MinMemberCount != null) @@ -86,11 +78,12 @@ namespace EventHub.Admin.Organizations dto.OwnerUserName = user.UserName; dto.OwnerEmail = user.Email; - dto.ProfilePictureContent = await GetCoverImageAsync(id); + dto.ProfilePictureContent = await GetCoverImageAsync(organization.Id); return dto; } + [Authorize(EventHubPermissions.Organizations.Update)] public async Task UpdateAsync(Guid id, UpdateOrganizationDto input) { var organization = await _organizationRepository.GetAsync(id); diff --git a/src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/Memberships/OrganizationMembershipController.cs b/src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/Memberships/OrganizationMembershipController.cs new file mode 100644 index 0000000..0dbc4cb --- /dev/null +++ b/src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/Memberships/OrganizationMembershipController.cs @@ -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> GetListAsync(OrganizationMemberListFilterDto input) + { + return await _organizationMembershipAppService.GetListAsync(input); + } + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.HttpApi.Host/Controllers/OrganizationController.cs b/src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/OrganizationController.cs similarity index 93% rename from src/EventHub.Admin.HttpApi.Host/Controllers/OrganizationController.cs rename to src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/OrganizationController.cs index 93984b7..9774488 100644 --- a/src/EventHub.Admin.HttpApi.Host/Controllers/OrganizationController.cs +++ b/src/EventHub.Admin.HttpApi.Host/Controllers/Organizations/OrganizationController.cs @@ -1,12 +1,11 @@ using System; using System.Threading.Tasks; -using EventHub.Admin.Application.Contracts.Organizations; using EventHub.Admin.Organizations; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Application.Dtos; using Volo.Abp.AspNetCore.Mvc; -namespace EventHub.Admin.Controllers +namespace EventHub.Admin.Controllers.Organizations { [Controller] [Area("eventhub-admin")] diff --git a/src/EventHub.Admin.Web/Menus/EventHubMenuContributor.cs b/src/EventHub.Admin.Web/Menus/EventHubMenuContributor.cs index 90fd929..9e5e401 100644 --- a/src/EventHub.Admin.Web/Menus/EventHubMenuContributor.cs +++ b/src/EventHub.Admin.Web/Menus/EventHubMenuContributor.cs @@ -1,9 +1,12 @@ using System; using System.Threading.Tasks; +using EventHub.Admin.Permissions; using EventHub.Localization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; using Volo.Abp.Account.Localization; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.UI.Navigation; using Volo.Abp.Users; @@ -30,7 +33,7 @@ namespace EventHub.Admin.Web.Menus } } - private Task ConfigureMainMenuAsync(MenuConfigurationContext context) + private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) { var l = context.GetLocalizer(); @@ -43,8 +46,8 @@ namespace EventHub.Admin.Web.Menus icon: "fas fa-home" ) ); - - return Task.CompletedTask; + + await AddOrganizationMenu(context, l); } private Task ConfigureUserMenuAsync(MenuConfigurationContext context) @@ -67,5 +70,16 @@ namespace EventHub.Admin.Web.Menus return Task.CompletedTask; } + + private Task AddOrganizationMenu(MenuConfigurationContext context, IStringLocalizer l) + { + var organizationMenu = new ApplicationMenuItem(EventHubMenus.OrganizationManagement.GroupName, l["Menu:OrganizationManagement"], icon: "fa fa-sitemap"); + context.Menu.Items.Insert(2, organizationMenu); + + organizationMenu.AddItem(new ApplicationMenuItem(EventHubMenus.OrganizationManagement.Organizations, l["Organizations"], url: "/organizations").RequirePermissions(EventHubPermissions.Organizations.Default)); + organizationMenu.AddItem(new ApplicationMenuItem(EventHubMenus.OrganizationManagement.OrganizationMemberships, l["OrganizationMemberships"], url: "/organization-memberships").RequirePermissions(EventHubPermissions.Organizations.Memberships.Default)); + + return Task.CompletedTask; + } } } diff --git a/src/EventHub.Admin.Web/Menus/EventHubMenus.cs b/src/EventHub.Admin.Web/Menus/EventHubMenus.cs index e24ac1c..66562a1 100644 --- a/src/EventHub.Admin.Web/Menus/EventHubMenus.cs +++ b/src/EventHub.Admin.Web/Menus/EventHubMenus.cs @@ -5,7 +5,11 @@ private const string Prefix = "EventHub"; public const string Home = Prefix + ".Home"; - //Add your menu items here... - + public static class OrganizationManagement + { + public const string GroupName = Prefix + ".OrganizationManagement"; + public const string Organizations = GroupName + ".Organizations"; + public const string OrganizationMemberships = GroupName + ".OrganizationMemberships"; + } } } \ No newline at end of file diff --git a/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor b/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor new file mode 100644 index 0000000..5a8a0c3 --- /dev/null +++ b/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor @@ -0,0 +1,255 @@ +@page "/organizations" +@using Volo.Abp.BlazoriseUI.Components +@using EventHub.Admin.Permissions +@using Microsoft.AspNetCore.Authorization +@using EventHub.Admin.Organizations +@using EventHub.Organizations +@inherits EventHubComponentBase +@inject NavigationManager NavigationManager +@attribute [Authorize(EventHubPermissions.Organizations.Default)] +@inject IOrganizationAppService OrganizationAppService + + + + @* ************************* PAGE HEADER ************************* *@ +

@L["Organizations"]

+
+ +@* ************************* SEARCH ************************* *@ + + +
+
+ + + @L["Name"] + + + + + + + @L["DisplayName"] + + + + + + + @L["MinMemberCount"] + + + + + + + @L["MaxMemberCount"] + + + +
+
+ + @* ************************* DATA GRID ************************* *@ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +@* ************************* EDIT MODAL ************************* *@ + + + +
+ + @L["UpdateOrganization"] + + + + + + Organization Info + Profile Image + + + + + + + @L["DisplayName"] * + + + + + + + + + + + @L["Description"] + + + + + + + + + + + @L["Website"] + + + + + + + + + + + @L["TwitterUsername"] + + + + + + + + + + + @L["GitHubUsername"] + + + + + + + + + + + @L["FacebookUsername"] + + + + + + + + + + + + @L["InstagramUsername"] + + + + + + + + + + + @L["MediumUsername"] + + + + + + + + + + + + @if (!ProfileImageUrl.IsNullOrEmpty()) + { + @if (!IsLoadingProfileImage) + { +
+ profile-image +
+ } + else + { +
+
+ Loading... +
+
+ } + } + +
+ + @L["ChooseProfileImage"] + + + + +
+
+
+
+
+ + + + +
+
+
\ No newline at end of file diff --git a/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor.cs b/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor.cs new file mode 100644 index 0000000..f4135b2 --- /dev/null +++ b/src/EventHub.Admin.Web/Pages/OrganizationManagement.razor.cs @@ -0,0 +1,162 @@ +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 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(); + EditingOrganization = new UpdateOrganizationDto(); + IsLoadingProfileImage = false; + SelectedTabInEditModal = TabContentInEditModal.OrganizationProfile.ToString(); + } + + protected override async Task OnInitializedAsync() + { + await GetOrganizationsAsync(); + } + + private async Task OnDataGridReadAsync(DataGridReadDataEventArgs 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(Organization); + EditOrganizationModal.Show(); + } + + private async Task UpdateOrganizationAsync() + { + await OrganizationAppService.UpdateAsync(EditingOrganizationId, EditingOrganization); + await GetOrganizationsAsync(); + EditOrganizationModal.Hide(); + } + + private async Task DeleteOrganizationAsync(OrganizationInListDto organization) + { + await OrganizationAppService.DeleteAsync(organization.Id); + await GetOrganizationsAsync(); + } + + private async Task OnProfileImageFileChanged(FileChangedEventArgs e) + { + IsLoadingProfileImage = true; + + if (e.Files != null && e.Files.Any()) + { + FileEntry = e.Files[0]; + + if (FileEntry != null) + { + 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 + } +} \ No newline at end of file diff --git a/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor b/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor new file mode 100644 index 0000000..3474b5e --- /dev/null +++ b/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor @@ -0,0 +1,63 @@ +@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 + + + + @* ************************* HEADER ************************* *@ +

+ @L["OrganizationMemberships"] + @if (OrganizationId.HasValue && !OrganizationName.IsNullOrWhiteSpace()) + { + (@OrganizationName) + } +

+
+ + @* ************************* SEARCH ************************* *@ + +
+ + @L["UserName"] + + +
+ + @* ************************* DATA GRID ************************* *@ + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor.cs b/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor.cs new file mode 100644 index 0000000..f8e6a86 --- /dev/null +++ b/src/EventHub.Admin.Web/Pages/OrganizationMembershipManagement.razor.cs @@ -0,0 +1,76 @@ +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; } + public string OrganizationName { get; set; } + [Inject] + protected IOrganizationAppService OrganizationAppService { get; set; } + + + private IReadOnlyList 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(); + } + + protected override async Task OnInitializedAsync() + { + await GetOrganizationMembershipsAsync(); + + if (OrganizationId.HasValue) + { + OrganizationName = (await OrganizationAppService.GetAsync(OrganizationId.Value)).Name; + } + } + + private async Task OnDataGridReadAsync(DataGridReadDataEventArgs 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; + } + + 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") + { + await GetOrganizationMembershipsAsync(); + } + } + } +} \ No newline at end of file diff --git a/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs b/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs index 744d74d..d6a43ea 100644 --- a/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs +++ b/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using EventHub.Users; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Repositories; diff --git a/src/EventHub.Domain/Organizations/Memberships/IOrganizationMembershipRepository.cs b/src/EventHub.Domain/Organizations/Memberships/IOrganizationMembershipRepository.cs new file mode 100644 index 0000000..c8b25b7 --- /dev/null +++ b/src/EventHub.Domain/Organizations/Memberships/IOrganizationMembershipRepository.cs @@ -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 + { + Task> GetMemberListAsync( + Guid? organizationId, + Guid? userId, + int skipCount, + int maxResultCount, + CancellationToken cancellationToken = default); + + Task GetCountAsync( + Guid? organizationId, + Guid? userId, + CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Organizations/Memberships/OrganizationMembershipRepository.cs b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Organizations/Memberships/OrganizationMembershipRepository.cs new file mode 100644 index 0000000..91fa861 --- /dev/null +++ b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/Organizations/Memberships/OrganizationMembershipRepository.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +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, IOrganizationMembershipRepository + { + public OrganizationMembershipRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + + } + + public async Task> GetMemberListAsync( + Guid? organizationId, + Guid? userId, + int skipCount, + int maxResultCount, + CancellationToken cancellationToken = default) + { + var dbContext = await GetDbContextAsync(); + + var organizationMembershipsDbSet = dbContext.Set(); + var identityUserDbSet = dbContext.Set(); + + var query = 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) + .OrderByDescending(x => x.organizationMember.CreationTime) + .Select(x => x.user); + + return await query + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public async Task GetCountAsync( + Guid? organizationId, + Guid? userId, + CancellationToken cancellationToken = default) + { + var dbContext = await GetDbContextAsync(); + + var organizationMembershipsDbSet = dbContext.Set(); + var identityUserDbSet = dbContext.Set(); + + 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)); + } + } +} \ No newline at end of file