Browse Source

Merge branch 'ui-design' into berkan/revision-for-workers

pull/42/head
Berkan Sasmaz 5 years ago
parent
commit
24e5aca247
  1. 32
      etc/notes/ui-design.md
  2. 12
      src/EventHub.Application.Contracts/Events/EventDetailDto.cs
  3. 4
      src/EventHub.Application.Contracts/Events/EventInListDto.cs
  4. 10
      src/EventHub.Application.Contracts/Events/EventListFilterDto.cs
  5. 4
      src/EventHub.Application.Contracts/Events/IEventAppService.cs
  6. 2
      src/EventHub.Application.Contracts/Events/Registrations/EventAttendeeDto.cs
  7. 4
      src/EventHub.Application.Contracts/Events/Registrations/IEventRegistrationAppService.cs
  8. 11
      src/EventHub.Application.Contracts/Events/UpdateEventDto.cs
  9. 22
      src/EventHub.Application.Contracts/Organizations/CreateOrganizationDto.cs
  10. 6
      src/EventHub.Application.Contracts/Organizations/IOrganizationAppService.cs
  11. 2
      src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs
  12. 2
      src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs
  13. 10
      src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberListFilterDto.cs
  14. 10
      src/EventHub.Application.Contracts/Organizations/OrganizationListFilterDto.cs
  15. 4
      src/EventHub.Application.Contracts/Organizations/OrganizationProfileDto.cs
  16. 26
      src/EventHub.Application.Contracts/Organizations/UpdateOrganizationDto.cs
  17. 11
      src/EventHub.Application.Contracts/Users/IUserAppService.cs
  18. 19
      src/EventHub.Application.Contracts/Users/UserDto.cs
  19. 4
      src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs
  20. 92
      src/EventHub.Application/Events/EventAppService.cs
  21. 6
      src/EventHub.Application/Events/Registrations/EventRegistrationAppService.cs
  22. 7
      src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs
  23. 82
      src/EventHub.Application/Organizations/OrganizationAppService.cs
  24. 24
      src/EventHub.Application/Users/UserAppService.cs
  25. 25
      src/EventHub.DbMigrator/Data/EventHubSampleDataSeedContributor.cs
  26. 2
      src/EventHub.Domain.Shared/Events/EventConsts.cs
  27. 17
      src/EventHub.Domain.Shared/Localization/EventHub/en.json
  28. 15
      src/EventHub.Domain.Shared/Organizations/OrganizationContst.cs
  29. 17
      src/EventHub.Domain.Shared/Web/EventHubExternalUrls.cs
  30. 43
      src/EventHub.Domain/Events/Event.cs
  31. 34
      src/EventHub.Domain/Events/EventManager.cs
  32. 16
      src/EventHub.Domain/Events/Registrations/EventRegistrationManager.cs
  33. 2639
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210428213802_Added_CountryName_To_Event.Designer.cs
  34. 23
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210428213802_Added_CountryName_To_Event.cs
  35. 5271
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs
  36. 33
      src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs
  37. 1
      src/EventHub.IdentityServer/EventHub.IdentityServer.csproj
  38. 21
      src/EventHub.IdentityServer/EventHubIdentityServerModule.cs
  39. 2
      src/EventHub.IdentityServer/Pages/Index.cshtml
  40. 7
      src/EventHub.IdentityServer/abp.resourcemapping.js
  41. 5
      src/EventHub.IdentityServer/package.json
  42. 3
      src/EventHub.IdentityServer/wwwroot/assets/dropdown-arrow.svg
  43. BIN
      src/EventHub.IdentityServer/wwwroot/assets/seperator.png
  44. 3
      src/EventHub.IdentityServer/wwwroot/assets/seperator2.svg
  45. 1342
      src/EventHub.IdentityServer/wwwroot/libs/abp/utils/abp-utils.umd.js
  46. 0
      src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.css
  47. 0
      src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map
  48. 0
      src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css
  49. 0
      src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map
  50. 40
      src/EventHub.IdentityServer/wwwroot/libs/jquery-validation/jquery.validate.js
  51. 8
      src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js
  52. 2534
      src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css
  53. 4914
      src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js
  54. 72
      src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json
  55. 162
      src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md
  56. 23
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/LICENSE
  57. 122
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/README.md
  58. BIN
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/ajax-loader.gif
  59. 186
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.carousel.css
  60. 6
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.carousel.min.css
  61. 50
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.default.css
  62. 6
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.default.min.css
  63. 50
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.green.css
  64. 6
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.green.min.css
  65. BIN
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.video.play.png
  66. 3448
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/owl.carousel.js
  67. 7
      src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/owl.carousel.min.js
  68. 0
      src/EventHub.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.uz.js
  69. 12
      src/EventHub.IdentityServer/yarn.lock
  70. 1
      src/EventHub.Web.Theme/Bundling/EventHubThemeGlobalScriptContributor.cs
  71. 4
      src/EventHub.Web.Theme/Bundling/EventHubThemeGlobalStyleContributor.cs
  72. 7
      src/EventHub.Web.Theme/EventHub.Web.Theme.csproj
  73. 206
      src/EventHub.Web.Theme/Helpers/TagHelpers/GravatarTagHelper.cs
  74. 66
      src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml
  75. 13
      src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/FooterViewComponent.cs
  76. 138
      src/EventHub.Web.Theme/Themes/EventHub/Components/MainNavbar/Default.cshtml
  77. 72
      src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml
  78. 3
      src/EventHub.Web.Theme/Themes/EventHub/_ViewImports.cshtml
  79. 70
      src/EventHub.Web.Theme/wwwroot/themes/eventhub/floating-labels.css
  80. 90
      src/EventHub.Web.Theme/wwwroot/themes/eventhub/layout.css
  81. 16
      src/EventHub.Web.Theme/wwwroot/themes/eventhub/layout.js
  82. 130
      src/EventHub.Web.Theme/wwwroot/themes/eventhub/owl-edit.css
  83. 832
      src/EventHub.Web.Theme/wwwroot/themes/eventhub/style.css
  84. 46
      src/EventHub.Web/Controllers/EventController.cs
  85. 26
      src/EventHub.Web/Controllers/OrganizationController.cs
  86. 14
      src/EventHub.Web/Controllers/OrganizationMembershipController.cs
  87. 16
      src/EventHub.Web/Controllers/WidgetsController.cs
  88. 1
      src/EventHub.Web/EventHubWebAutoMapperProfile.cs
  89. 13
      src/EventHub.Web/EventHubWebModule.cs
  90. 31
      src/EventHub.Web/Helpers/CoverImageHelper.cs
  91. 29
      src/EventHub.Web/Pages/Events/Components/AttendeesArea/Default.cshtml
  92. 11
      src/EventHub.Web/Pages/Events/Components/AttendeesArea/attendees-area.css
  93. 36
      src/EventHub.Web/Pages/Events/Components/EventsArea/Default.cshtml
  94. 97
      src/EventHub.Web/Pages/Events/Components/EventsArea/EventsAreaViewComponent.cs
  95. 42
      src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml
  96. 36
      src/EventHub.Web/Pages/Events/Components/EventsArea/events-area.js
  97. 57
      src/EventHub.Web/Pages/Events/Components/LocationArea/Default.cshtml
  98. 34
      src/EventHub.Web/Pages/Events/Components/RegistrationArea/Default.cshtml
  99. 2
      src/EventHub.Web/Pages/Events/Components/RegistrationArea/RegistrationAreaViewComponent.cs
  100. 2
      src/EventHub.Web/Pages/Events/Components/RegistrationArea/registration-area.js

32
etc/notes/ui-design.md

@ -0,0 +1,32 @@
# UI Design Notes
## Implementing the Design
### Overall / Layout
* Home & Events are separated, so we should create a separation in the solution
### Home Page
* Search area:
* Language selection
* Location (country / city) search / with online option
* When (date range selection)
### Events Page
* Search area:
* Language selection
* Location (country / city) search / with online option
* When (date range selection)
## Features
### Should Implement for the Design
* ...
### Plan for Future
* Event & Organization Categories
* Event & Organization Tags (use the tagging system of CMS Kit)

12
src/EventHub.Application.Contracts/Events/EventDetailDto.cs

@ -5,10 +5,16 @@ namespace EventHub.Events
{
public class EventDetailDto : EntityDto<Guid>
{
public Guid OrganizationId { get; set; }
public string OrganizationName { get; set; }
public string OrganizationDisplayName { get; set; }
public string OwnerUserName { get; set; }
public string OwnerEmail { get; set; }
public string Title { get; set; }
public string Description { get; set; }
@ -20,6 +26,12 @@ namespace EventHub.Events
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 bool IsLive { get; set; }

4
src/EventHub.Application.Contracts/Events/EventInListDto.cs

@ -20,6 +20,10 @@ namespace EventHub.Events
public byte[] CoverImageContent { get; set; }
public bool IsOnline { get; set; }
public string Country { get; set; }
public string City { get; set; }
public int? Capacity { get; set; }

10
src/EventHub.Application.Contracts/Events/EventListFilterDto.cs

@ -10,10 +10,18 @@ namespace EventHub.Events
public DateTime? MaxDate { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? RegisteredUserId { get; set; }
public bool? IsOnline { get; set; }
public string Language { get; set; }
public Guid? CountryId { get; set; }
public EventListFilterDto()
{
MaxResultCount = 20;
MaxResultCount = 21;
}
}
}

4
src/EventHub.Application.Contracts/Events/IEventAppService.cs

@ -22,8 +22,6 @@ namespace EventHub.Events
Task UpdateAsync(Guid id, UpdateEventDto input);
Task UpdateEventTimingAsync(Guid id, UpdateEventTimingDto input);
Task SaveCoverImageAsync(Guid id, byte[] coverImageContent);
Task<byte[]> GetCoverImageAsync(Guid id);
}
}

2
src/EventHub.Application.Contracts/Events/Registrations/EventAttendeeDto.cs

@ -8,6 +8,8 @@ namespace EventHub.Events.Registrations
public string UserName { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public string Surname { get; set; }

4
src/EventHub.Application.Contracts/Events/Registrations/IEventRegistrationAppService.cs

@ -14,7 +14,7 @@ namespace EventHub.Events.Registrations
Task<bool> IsRegisteredAsync(Guid eventId);
Task<PagedResultDto<EventAttendeeDto>> GetAttendeesAsync(Guid eventId);
Task<int> GetAttendeeCountAsync(Guid eventId);
Task<bool> IsPastEventAsync(Guid eventId);
}
}

11
src/EventHub.Application.Contracts/Events/UpdateEventDto.cs

@ -13,6 +13,17 @@ namespace EventHub.Events
[Required]
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)]
public string Description { get; set; }
[CanBeNull]
public byte[] CoverImageContent { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime StartTime { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime EndTime { get; set; }
public bool IsOnline { get; set; }

22
src/EventHub.Application.Contracts/Organizations/CreateOrganizationDto.cs

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using JetBrains.Annotations;
namespace EventHub.Organizations
{
@ -15,5 +16,26 @@ namespace EventHub.Organizations
[Required]
[StringLength(OrganizationConsts.MaxDescriptionNameLength, MinimumLength = OrganizationConsts.MinDescriptionNameLength)]
public string Description { get; set; }
[CanBeNull]
public byte[] ProfilePictureContent { get; set; }
[StringLength(OrganizationConsts.MaxWebsiteLength)]
public string Website { get; set; }
[StringLength(OrganizationConsts.MaxTwitterUsernameLength)]
public string TwitterUsername { get; set; }
[StringLength(OrganizationConsts.MaxGitHubUsernameLength)]
public string GitHubUsername { get; set; }
[StringLength(OrganizationConsts.MaxFacebookUsernameLength)]
public string FacebookUsername { get; set; }
[StringLength(OrganizationConsts.MaxInstagramUsernameLength)]
public string InstagramUsername { get; set; }
[StringLength(OrganizationConsts.MaxMediumUsernameLength)]
public string MediumUsername { get; set; }
}
}

6
src/EventHub.Application.Contracts/Organizations/IOrganizationAppService.cs

@ -9,16 +9,14 @@ namespace EventHub.Organizations
{
Task CreateAsync(CreateOrganizationDto input);
Task<PagedResultDto<OrganizationInListDto>> GetListAsync(PagedResultRequestDto input);
Task<PagedResultDto<OrganizationInListDto>> GetListAsync(OrganizationListFilterDto input);
Task<OrganizationProfileDto> GetProfileAsync(string name);
Task<ListResultDto<OrganizationInListDto>> GetMyOrganizationsAsync();
Task<ListResultDto<OrganizationInListDto>> GetOrganizationsByUserIdAsync(Guid userId);
Task<bool> IsOrganizationOwnerAsync(Guid organizationId);
Task UpdateAsync(Guid id, UpdateOrganizationDto input);
Task SaveProfilePictureAsync(Guid id, byte[] bytes);
}
}

2
src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs

@ -13,6 +13,6 @@ namespace EventHub.Organizations.Memberships
Task<bool> IsJoinedAsync(Guid organizationId);
Task<PagedResultDto<OrganizationMemberDto>> GetMembersAsync(Guid organizationId);
Task<PagedResultDto<OrganizationMemberDto>> GetMembersAsync(OrganizationMemberListFilterDto input);
}
}

2
src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs

@ -8,6 +8,8 @@ namespace EventHub.Organizations.Memberships
public string UserName { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public string Surname { get; set; }

10
src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberListFilterDto.cs

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Application.Dtos;
namespace EventHub.Organizations.Memberships
{
public class OrganizationMemberListFilterDto : PagedResultRequestDto
{
public Guid OrganizationId { get; set; }
}
}

10
src/EventHub.Application.Contracts/Organizations/OrganizationListFilterDto.cs

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Application.Dtos;
namespace EventHub.Organizations
{
public class OrganizationListFilterDto : PagedResultRequestDto
{
public Guid? RegisteredUserId { get; set; }
}
}

4
src/EventHub.Application.Contracts/Organizations/OrganizationProfileDto.cs

@ -9,6 +9,10 @@ namespace EventHub.Organizations
public string DisplayName { get; set; }
public string OwnerUserName { get; set; }
public string OwnerEmail { get; set; }
public string Description { get; set; }
public string Website { get; set; }

26
src/EventHub.Application.Contracts/Organizations/UpdateOrganizationDto.cs

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using JetBrains.Annotations;
namespace EventHub.Organizations
{
@ -12,16 +13,31 @@ namespace EventHub.Organizations
[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; }
}
}

11
src/EventHub.Application.Contracts/Users/IUserAppService.cs

@ -0,0 +1,11 @@
using System.Threading.Tasks;
using EventHub.Members;
using Volo.Abp.Application.Services;
namespace EventHub.Users
{
public interface IUserAppService : IApplicationService
{
Task<UserDto> FindByUserNameAsync(string username);
}
}

19
src/EventHub.Application.Contracts/Users/UserDto.cs

@ -0,0 +1,19 @@
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Auditing;
namespace EventHub.Members
{
public class UserDto : EntityDto<Guid>, IHasCreationTime
{
public string UserName { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public DateTime CreationTime { get; set; }
}
}

4
src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs

@ -2,6 +2,7 @@
using EventHub.Countries;
using EventHub.Events;
using EventHub.Events.Registrations;
using EventHub.Members;
using EventHub.Organizations;
using EventHub.Organizations.Memberships;
using EventHub.Users;
@ -24,6 +25,7 @@ namespace EventHub
.Ignore(x => x.OrganizationDisplayName)
.Ignore(x => x.IsLiveNow);
CreateMap<Event, EventDetailDto>()
.Ignore(x => x.OrganizationId)
.Ignore(x => x.OrganizationName)
.Ignore(x => x.OrganizationDisplayName);
@ -33,6 +35,8 @@ namespace EventHub
.Ignore(x => x.Country);
CreateMap<Country, CountryLookupDto>();
CreateMap<AppUser, UserDto>();
}
}
}

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

@ -7,7 +7,6 @@ using EventHub.Events.Registrations;
using EventHub.Organizations;
using EventHub.Users;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Authorization;
using Volo.Abp.BlobStoring;
@ -20,6 +19,7 @@ namespace EventHub.Events
{
private readonly EventManager _eventManager;
private readonly EventRegistrationManager _eventRegistrationManager;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IRepository<Event, Guid> _eventRepository;
private readonly IRepository<Organization, Guid> _organizationRepository;
private readonly IRepository<AppUser, Guid> _userRepository;
@ -29,14 +29,16 @@ namespace EventHub.Events
public EventAppService(
EventManager eventManager,
EventRegistrationManager eventRegistrationManager,
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IRepository<Event, Guid> eventRepository,
IRepository<Organization, Guid> organizationRepository,
IRepository<AppUser, Guid> userRepository,
IRepository<Country, Guid> countriesRepository,
IRepository<Organization, Guid> organizationRepository,
IRepository<AppUser, Guid> userRepository,
IRepository<Country, Guid> countriesRepository,
IBlobContainer<EventCoverImageContainer> eventBlobContainer)
{
_eventManager = eventManager;
_eventRegistrationManager = eventRegistrationManager;
_eventRegistrationRepository = eventRegistrationRepository;
_eventRepository = eventRepository;
_organizationRepository = organizationRepository;
_userRepository = userRepository;
@ -65,7 +67,7 @@ namespace EventHub.Events
input.Description
);
@event.SetLocation(input.IsOnline, input.OnlineLink, input.CountryId, input.City);
await _eventManager.SetLocationAsync(@event, input.IsOnline, input.OnlineLink, input.CountryId, input.City);
@event.Language = input.Language;
await _eventManager.SetCapacityAsync(@event, input.Capacity);
@ -74,7 +76,7 @@ namespace EventHub.Events
{
await SaveCoverImageAsync(@event.Id, input.CoverImageContent);
}
await _eventRepository.InsertAsync(@event);
return ObjectMapper.Map<Event, EventDto>(@event);
@ -83,12 +85,23 @@ namespace EventHub.Events
public async Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input)
{
var eventQueryable = await _eventRepository.GetQueryableAsync();
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
var organizationQueryable = await _organizationRepository.GetQueryableAsync();
var query = from @event in eventQueryable
join organization in organizationQueryable on @event.OrganizationId equals organization.Id
select new {@event, organization};
if (input.RegisteredUserId.HasValue)
{
var registeredEvent = eventRegistrationQueryable
.Where(x => x.UserId == input.RegisteredUserId)
.Select(s => s.EventId);
var eventIds = await AsyncExecuter.ToListAsync(registeredEvent);
query = query.Where(x => eventIds.Contains(x.@event.Id));
}
if (input.MinDate.HasValue)
{
query = query.Where(i => i.@event.EndTime >= input.MinDate.Value);
@ -104,6 +117,21 @@ namespace EventHub.Events
query = query.Where(i => i.@event.OrganizationId == input.OrganizationId.Value);
}
if (input.IsOnline.HasValue)
{
query = query.Where(i => i.@event.IsOnline == input.IsOnline);
}
if (!input.Language.IsNullOrWhiteSpace())
{
query = query.Where(i => i.@event.Language == input.Language);
}
if (input.CountryId.HasValue && input.CountryId != Guid.Empty)
{
query = query.Where(i => i.@event.CountryId == input.CountryId);
}
var totalCount = await AsyncExecuter.CountAsync(query);
query = query.PageBy(input);
@ -127,6 +155,7 @@ namespace EventHub.Events
dto.OrganizationName = i.organization.Name;
dto.OrganizationDisplayName = i.organization.DisplayName;
dto.IsLiveNow = now.IsBetween(i.@event.StartTime, i.@event.EndTime);
dto.Country = i.@event.CountryName;
return dto;
}
).ToList();
@ -146,10 +175,15 @@ namespace EventHub.Events
var dto = ObjectMapper.Map<Event, EventDetailDto>(@event);
dto.OrganizationId = organization.Id;
dto.OrganizationName = organization.Name;
dto.OrganizationDisplayName = organization.DisplayName;
dto.CoverImageContent = await GetCoverImageAsync(dto.Id);
var user = await _userRepository.GetAsync(organization.OwnerUserId);
dto.OwnerUserName = user.UserName;
dto.OwnerEmail = user.Email;
return dto;
}
@ -160,15 +194,15 @@ namespace EventHub.Events
var user = await _userRepository.GetAsync(CurrentUser.GetId());
var dto = ObjectMapper.Map<Event, EventLocationDto>(@event);
dto.IsRegistered = await _eventRegistrationManager.IsRegisteredAsync(@event, user);
if (!dto.IsRegistered)
{
dto.OnlineLink = null;
dto.City = null;
}
if (dto.IsRegistered && @event.CountryId.HasValue)
{
dto.Country = (await _countriesRepository.GetAsync(@event.CountryId.Value)).Name;
@ -176,8 +210,7 @@ namespace EventHub.Events
return dto;
}
[Authorize]
public async Task<List<CountryLookupDto>> GetCountriesLookupAsync()
{
var countriesQueryable = await _countriesRepository.GetQueryableAsync();
@ -213,46 +246,33 @@ namespace EventHub.Events
);
}
@event.SetLocation(input.IsOnline, input.OnlineLink, input.CountryId, input.City);
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, input.EndTime);
await _eventManager.SetCapacityAsync(@event, input.Capacity);
await _eventRepository.UpdateAsync(@event);
}
[Authorize]
public async Task UpdateEventTimingAsync(Guid id, UpdateEventTimingDto input)
{
var @event = await _eventRepository.GetAsync(id);
if (@event.TimingChangeCount >= EventConsts.MaxTimingChangeCountForUser)
if (input.CoverImageContent != null && input.CoverImageContent.Length > 0)
{
throw new BusinessException(EventHubErrorCodes.CantChangeEventTiming)
.WithData("MaxTimingChangeLimit", EventConsts.MaxTimingChangeCountForUser);
await SaveCoverImageAsync(@event.Id, input.CoverImageContent);
}
@event.SetTime(input.StartTime, input.EndTime);
@event.TimingChangeCount++;
await _eventRepository.UpdateAsync(@event);
}
[Authorize]
public async Task SaveCoverImageAsync(Guid id, byte[] coverImageContent)
public async Task<byte[]> GetCoverImageAsync(Guid id)
{
var blobName = id.ToString();
await _eventBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting: true);
return await _eventBlobContainer.GetAllBytesOrNullAsync(blobName);
}
private async Task<byte[]> GetCoverImageAsync(Guid id)
private async Task SaveCoverImageAsync(Guid id, byte[] coverImageContent)
{
var blobName = id.ToString();
return await _eventBlobContainer.GetAllBytesOrNullAsync(blobName);
await _eventBlobContainer.SaveAsync(blobName, coverImageContent, overrideExisting: true);
}
}
}

6
src/EventHub.Application/Events/Registrations/EventRegistrationAppService.cs

@ -81,9 +81,11 @@ namespace EventHub.Events.Registrations
);
}
public async Task<int> GetAttendeeCountAsync(Guid eventId)
public async Task<bool> IsPastEventAsync(Guid eventId)
{
return await _eventRegistrationRepository.CountAsync(x => x.EventId == eventId);
var @event = await _eventRepository.GetAsync(eventId);
return _eventRegistrationManager.IsPastEvent(@event);
}
}
}

7
src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs

@ -55,19 +55,20 @@ namespace EventHub.Organizations.Memberships
);
}
public async Task<PagedResultDto<OrganizationMemberDto>> GetMembersAsync(Guid organizationId)
public async Task<PagedResultDto<OrganizationMemberDto>> GetMembersAsync(OrganizationMemberListFilterDto input)
{
var organizationMembershipsQueryable = await _organizationMembershipsRepository.GetQueryableAsync();
var userQueryable = await _userRepository.GetQueryableAsync();
var query = from organizationMembership in organizationMembershipsQueryable
join user in userQueryable on organizationMembership.UserId equals user.Id
where organizationMembership.OrganizationId == organizationId
where organizationMembership.OrganizationId == input.OrganizationId
orderby organizationMembership.CreationTime descending
select user;
var totalCount = await AsyncExecuter.CountAsync(query);
var users = await AsyncExecuter.ToListAsync(query.Take(10));
var users = await AsyncExecuter.ToListAsync(query.PageBy(input));
return new PagedResultDto<OrganizationMemberDto>(
totalCount,

82
src/EventHub.Application/Organizations/OrganizationAppService.cs

@ -2,9 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Organizations.Memberships;
using EventHub.Users;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Authorization;
using Volo.Abp.BlobStoring;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
@ -14,17 +16,23 @@ namespace EventHub.Organizations
public class OrganizationAppService : EventHubAppService, IOrganizationAppService
{
private readonly IRepository<Organization, Guid> _organizationRepository;
private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository;
private readonly OrganizationManager _organizationManager;
private readonly IBlobContainer<OrganizationProfilePictureContainer> _organizationBlobContainer;
private readonly IRepository<AppUser, Guid> _userRepository;
public OrganizationAppService(
IRepository<Organization, Guid> organizationRepository,
IRepository<OrganizationMembership, Guid> organizationMembershipsRepository,
OrganizationManager organizationManager,
IBlobContainer<OrganizationProfilePictureContainer> organizationBlobContainer)
IBlobContainer<OrganizationProfilePictureContainer> organizationBlobContainer,
IRepository<AppUser, Guid> userRepository)
{
_organizationRepository = organizationRepository;
_organizationMembershipsRepository = organizationMembershipsRepository;
_organizationManager = organizationManager;
_organizationBlobContainer = organizationBlobContainer;
_userRepository = userRepository;
}
[Authorize]
@ -37,19 +45,44 @@ namespace EventHub.Organizations
input.Description
);
await _organizationRepository.InsertAsync(organization);
organization.Website = input.Website;
organization.TwitterUsername = input.TwitterUsername;
organization.GitHubUsername = input.GitHubUsername;
organization.FacebookUsername = input.FacebookUsername;
organization.InstagramUsername = input.InstagramUsername;
organization.MediumUsername = input.MediumUsername;
await _organizationRepository.InsertAsync(organization, true);
if (input.ProfilePictureContent != null && input.ProfilePictureContent.Length > 0)
{
await SaveProfilePictureAsync(organization.Id, input.ProfilePictureContent);
}
}
public async Task<PagedResultDto<OrganizationInListDto>> GetListAsync(PagedResultRequestDto input)
public async Task<PagedResultDto<OrganizationInListDto>> GetListAsync(OrganizationListFilterDto input)
{
var organizationCount = await _organizationRepository.GetCountAsync();
var organizations = await _organizationRepository.GetPagedListAsync(
input.SkipCount,
input.MaxResultCount,
nameof(Organization.DisplayName)
);
var organizationQueryable = await _organizationRepository.GetQueryableAsync();
var organizationMemberQueryable = await _organizationMembershipsRepository.GetQueryableAsync();
var organizationDto = ObjectMapper.Map<List<Organization>, List<OrganizationInListDto>>(organizations);
var query = organizationQueryable;
if (input.RegisteredUserId.HasValue)
{
var registeredOrganization = organizationMemberQueryable
.Where(x => x.UserId == input.RegisteredUserId)
.Select(x => x.OrganizationId);
var organizationIds = await AsyncExecuter.ToListAsync(registeredOrganization);
query = query.Where(x => organizationIds.Contains(x.Id));
}
var totalCount = await AsyncExecuter.CountAsync(query);
query = query.PageBy(input);
var organizationDto = ObjectMapper
.Map<List<Organization>, List<OrganizationInListDto>>(await AsyncExecuter.ToListAsync(query));
foreach (var organization in organizationDto)
{
@ -57,7 +90,7 @@ namespace EventHub.Organizations
}
return new PagedResultDto<OrganizationInListDto>(
organizationCount,
totalCount,
organizationDto
);
}
@ -66,17 +99,18 @@ namespace EventHub.Organizations
{
var organization = await _organizationRepository.GetAsync(o => o.Name == name);
var organizationProfileDto = ObjectMapper.Map<Organization, OrganizationProfileDto>(organization);
var owner = await _userRepository.GetAsync(u => u.Id == organization.OwnerUserId);
organizationProfileDto.OwnerUserName = owner.UserName;
organizationProfileDto.OwnerEmail = owner.Email;
organizationProfileDto.ProfilePictureContent = await GetProfilePictureAsync(organizationProfileDto.Id);
return organizationProfileDto;
}
[Authorize]
public async Task<ListResultDto<OrganizationInListDto>> GetMyOrganizationsAsync()
public async Task<ListResultDto<OrganizationInListDto>> GetOrganizationsByUserIdAsync(Guid userId)
{
var currentUserId = CurrentUser.GetId();
var query = (await _organizationRepository.GetQueryableAsync()).Where(o => o.OwnerUserId == currentUserId);
var query = (await _organizationRepository.GetQueryableAsync()).Where(o => o.OwnerUserId == userId);
var organizations = await AsyncExecuter.ToListAsync(query);
var organizationDto = ObjectMapper.Map<List<Organization>, List<OrganizationInListDto>>(organizations);
@ -101,8 +135,7 @@ namespace EventHub.Organizations
if (organization.OwnerUserId != CurrentUser.GetId())
{
//TODO: throw AbpAuthorizationException instead
throw new BusinessException(EventHubErrorCodes.NotAuthorizedToUpdateOrganizationProfile)
throw new AbpAuthorizationException(EventHubErrorCodes.NotAuthorizedToUpdateOrganizationProfile)
.WithData("OrganizationName", organization.DisplayName);
}
@ -115,18 +148,21 @@ namespace EventHub.Organizations
organization.FacebookUsername = input.FacebookUsername;
organization.MediumUsername = input.MediumUsername;
if (input.ProfilePictureContent != null && input.ProfilePictureContent.Length > 0)
{
await SaveProfilePictureAsync(organization.Id, input.ProfilePictureContent);
}
await _organizationRepository.UpdateAsync(organization);
}
[Authorize]
public async Task SaveProfilePictureAsync(Guid id, byte[] bytes)
private async Task SaveProfilePictureAsync(Guid id, byte[] bytes)
{
var organization = await _organizationRepository.GetAsync(x => x.Id == id);
if (organization.OwnerUserId != CurrentUser.GetId())
{
//TODO: throw AbpAuthorizationException instead
throw new BusinessException(EventHubErrorCodes.NotAuthorizedToUpdateOrganizationProfile)
throw new AbpAuthorizationException(EventHubErrorCodes.NotAuthorizedToUpdateOrganizationProfile)
.WithData("Name", organization.DisplayName);
}

24
src/EventHub.Application/Users/UserAppService.cs

@ -0,0 +1,24 @@
using System;
using System.Threading.Tasks;
using EventHub.Members;
using Volo.Abp.Domain.Repositories;
namespace EventHub.Users
{
public class UserAppService : EventHubAppService, IUserAppService
{
private readonly IRepository<AppUser, Guid> _userRepository;
public UserAppService(IRepository<AppUser, Guid> userRepository)
{
_userRepository = userRepository;
}
public async Task<UserDto> FindByUserNameAsync(string username)
{
var user = await _userRepository.FindAsync(x => x.UserName == username);
return ObjectMapper.Map<AppUser, UserDto>(user);
}
}
}

25
src/EventHub.DbMigrator/Data/EventHubSampleDataSeedContributor.cs

@ -162,6 +162,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-1),
"Modern application design has changed quite a bit in recent years. \"Mobile-first\" and \"cloud-ready\" are the types of applications you are expected to develop. Also, to keep pace with these demands, Microsoft has revamped their complete web stack with ASP.NET Core to meet these architectural demands."
);
await _eventManager.SetLocationAsync(pastEvent1, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent1);
var pastEvent2 = await _eventManager.CreateAsync(organizationDotnetWorld,
@ -169,6 +170,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-20),
DateTime.Now.AddDays(-2),
"gRPC is a high-performance, cross-platform framework for building distributed systems and APIs. It’s an ideal choice for communication between microservices, internal network applications, or mobile devices and services.");
await _eventManager.SetLocationAsync(pastEvent2, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent2);
var pastEvent3 = await _eventManager.CreateAsync(organizationDotnetWorld,
@ -176,6 +178,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-30),
DateTime.Now.AddDays(-7),
"The explosive growth of web frameworks and the demands of users have changed the approach to building enterprise applications. Many challenges exist and just getting started can be a daunting prospect. Let's change that now.");
await _eventManager.SetLocationAsync(pastEvent3, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent3);
var pastEvent4 = await _eventManager.CreateAsync(organizationDeveloperDays,
@ -183,6 +186,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-30),
DateTime.Now.AddDays(-7),
"Functional programming and domain-driven design might not seem to be a good match, but in fact functional programming can be an excellent approach to designing decoupled, reusable systems with a rich domain model. ");
await _eventManager.SetLocationAsync(pastEvent4, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent4);
var pastEvent5 = await _eventManager.CreateAsync(organizationCSharpLovers,
@ -190,6 +194,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-32),
DateTime.Now.AddDays(-10),
"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. That sounds nice, but what is GraphQL and how can we use it in .NET?");
await _eventManager.SetLocationAsync(pastEvent5, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent5);
var pastEvent6 = await _eventManager.CreateAsync(organizationDotnetWorld,
@ -197,6 +202,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-35),
DateTime.Now.AddDays(-15),
"In this session we will walk through a real world example of a year-long modernization journey. We will take a closer look at how you can get started, what obstacles you may face and how to overcome them.");
await _eventManager.SetLocationAsync(pastEvent6, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent6);
var pastEvent7 = await _eventManager.CreateAsync(organizationDeveloperDays,
@ -204,6 +210,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-25),
DateTime.Now.AddDays(-14),
"GraphQL is making a huge splash in modern serverless applications. GraphQL allows you to present custom apis that allow the consumer of the API to decide what information they want and how it should be shaped. It also allows for real time pushes of data using web sockets and subscriptions. In this talk, you will learn how to implement this powerful API in the cloud using serverless functions in Azure.");
await _eventManager.SetLocationAsync(pastEvent7, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent7);
var pastEvent8 = await _eventManager.CreateAsync(organizationDotnetWorld,
@ -211,6 +218,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-25),
DateTime.Now.AddDays(-10),
"With the releases of .NET Core 2.x, 3.x and now .NET 5, more developers have now got to grips with the basics of using the default Microsoft Dependency Injection container that comes with .NET Core. However, the story does not end there...");
await _eventManager.SetLocationAsync(pastEvent8, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent8);
var pastEvent9 = await _eventManager.CreateAsync(organizationAngularCoders,
@ -218,6 +226,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-15),
DateTime.Now.AddDays(-2),
"How many times have you tried to start writing unit tests and didn’t know where to start? Or the tutorials weren’t clear enough? In our webinar we’ll start with just a bit of theory and then we’ll move on to examples. We’ll show you how to test basic (and a bit more complex) components, services, how to deal with dependencies, asynchronous code, forms, child components etc");
await _eventManager.SetLocationAsync(pastEvent9, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent9);
var pastEvent10 = await _eventManager.CreateAsync(organizationAngularCoders,
@ -225,6 +234,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(-45),
DateTime.Now.AddDays(-43),
"Introduction to Angular unit tests includes introduction to Jasmin and Angular testing module. You will learn to create unit tests for your Angular project by understanding Jasmin and Angular testing module which provides infrastructure for testing Angular core functionality.");
await _eventManager.SetLocationAsync(pastEvent10, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(pastEvent10);
//15 upcoming events
@ -233,6 +243,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(7),
"In the microservice environment, it is important to know the health state of the different services and handle bad states. This is why Microsoft created the ASP.NET Core Health Checks.");
await _eventManager.SetLocationAsync(upcomingEvent1, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent1);
await _eventRegistrationManager.RegisterAsync(upcomingEvent1, userSandra);
await _eventRegistrationManager.RegisterAsync(upcomingEvent1, userAlessandro);
@ -242,6 +253,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(7),
"Grab some snacks and a drink, and tech along to our online GraphQL meetup! GraphQL is all the rage nowadays, especially in the frontend community. Although Microsoft has been silent about GraphQL, the open-source community is slowly picking up the task of integrating GraphQL tech in .NET Core. This presentation will be an introduction to GraphQL for anyone who has never tried it.");
await _eventManager.SetLocationAsync(upcomingEvent2, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent2);
await _eventRegistrationManager.RegisterAsync(upcomingEvent2, userTony);
@ -250,6 +262,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(15),
"First, we will present .NET 5, it's importance in the .NET evolution, and the reasons to switch your new development to .NET 5. We will pay close attention to the challenging topic of migration to .NET 5 and provide a few guidelines. Afterward, we will dig into C# 9.0 and see how it makes us more productive and enables us to write more expressive code.");
await _eventManager.SetLocationAsync(upcomingEvent3, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent3);
await _eventRegistrationManager.RegisterAsync(upcomingEvent3, userTony);
await _eventRegistrationManager.RegisterAsync(upcomingEvent3, userAlessandro);
@ -260,6 +273,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(10),
"Join us for a discussion and live coding session where Jeff Fritz will take us on a tour of a more complex Blazor Static Web App. We'll learn how to take advantage of other Azure Services without breaking the bank while delivering cool features like search, caching, and using event-driven architecture.");
await _eventManager.SetLocationAsync(upcomingEvent4, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent4);
await _eventRegistrationManager.RegisterAsync(upcomingEvent4, userMark);
@ -268,6 +282,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(30),
"This talk starts by introducing the DDD and providing a layering model based on the DDD and the Clean Architecture. It then introduces the core building of an application built on the DDD principles. In the second part of the talk, it shows some strict coding rules for the core building blocks with real code examples and suggestions. These rules are essential to build a large scale application implements DDD patterns & practices.");
await _eventManager.SetLocationAsync(upcomingEvent5, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent5);
await _eventRegistrationManager.RegisterAsync(upcomingEvent5, userMark);
await _eventRegistrationManager.RegisterAsync(upcomingEvent5, userAlessandro);
@ -277,6 +292,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(30),
"ABP Framework is a complete infrastructure to create modern web applications by following the software development best practices and conventions. In this talk we'll examine ABP Framework top to down.");
await _eventManager.SetLocationAsync(upcomingEvent6, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent6);
await _eventRegistrationManager.RegisterAsync(upcomingEvent6, userAlessandro);
@ -285,6 +301,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now,
DateTime.Now.AddDays(30),
"This is a Zoom Meeting and the link will be provided the day of the event via email and 1 hour before the meeting start. We'll start with quick intro and then we'll deep dive into .NET dependency injection system.");
await _eventManager.SetLocationAsync(upcomingEvent7, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent7);
await _eventRegistrationManager.RegisterAsync(upcomingEvent7, userSandra);
@ -293,6 +310,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(5),
DateTime.Now.AddDays(15),
"Recently Bob Martin has categorized a set of architectures, including hexagonal architecture, onion architecture and screaming architecture as 'the clean architecture' - a layered architecture of concentric circles with a strong emphasis on separation of concerns. This architecture has become popular because of its amenability to modification as an evolutionary architecture and its support for practices such as TDD.In this presentation we will discuss the clean architecture and its benefits");
await _eventManager.SetLocationAsync(upcomingEvent8, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent8);
await _eventRegistrationManager.RegisterAsync(upcomingEvent8, userSandra);
await _eventRegistrationManager.RegisterAsync(upcomingEvent8, userAlessandro);
@ -302,6 +320,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(5),
DateTime.Now.AddDays(10),
"There are no bad practices. Just trade-offs.Let's dive into the real world! because sometimes, a 'Bad practice' is not optional...The trick is to learn and make sure you understand what's going -on, and how to it right!We will use jQuery in Angular, work with promises instead of RxJS, Pass callbacks as Inputs - and much more!");
await _eventManager.SetLocationAsync(upcomingEvent9, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent9);
await _eventRegistrationManager.RegisterAsync(upcomingEvent9, userAlessandro);
await _eventRegistrationManager.RegisterAsync(upcomingEvent9, userMark);
@ -311,6 +330,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(4),
DateTime.Now.AddDays(5),
"This meetup will explore an approach to iteratively and rigorously testing mainframe migrations to cloud, all while building “living documentation” of the old and new systems. It will discuss how visual data flows build accurate logical pictures of legacy systems, while one flow can generate automated tests for both legacy and new components. ");
await _eventManager.SetLocationAsync(upcomingEvent10, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent10);
await _eventRegistrationManager.RegisterAsync(upcomingEvent10, userAlessandro);
@ -319,6 +339,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(7),
DateTime.Now.AddDays(14),
"In this talk, we'll go through Typescript top to down and understand what it solved for software applications");
await _eventManager.SetLocationAsync(upcomingEvent11, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent11);
await _eventRegistrationManager.RegisterAsync(upcomingEvent11, userMark);
@ -327,6 +348,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(1),
DateTime.Now.AddDays(2),
"Cypress is a next-generation front end testing tool built for the modern web. They address the key pain points developers and QA engineers face when testing modern applications.In this session, we will learn how to add cypress to angular projects, setup, write, and run cypress tests.");
await _eventManager.SetLocationAsync(upcomingEvent12, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent12);
await _eventRegistrationManager.RegisterAsync(upcomingEvent12, userMark);
await _eventRegistrationManager.RegisterAsync(upcomingEvent12, userAlessandro);
@ -337,6 +359,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(10),
DateTime.Now.AddDays(12),
"Some of the topics covered in the conference: Angular core topicsThe future of Angular and Angular migration path, Bundling & Packaging, Rendering on server and mobile, Performance, Tools & The ecosystem");
await _eventManager.SetLocationAsync(upcomingEvent13, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent13);
await _eventRegistrationManager.RegisterAsync(upcomingEvent13, userAlessandro);
@ -345,6 +368,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(5),
DateTime.Now.AddDays(12),
"We’ll start by going over the differences between the two careers. Then, we’ll walk you through how to get the skills to be successful in each, and discuss the different jobs that will be available to you once you’ve acquired those skills.");
await _eventManager.SetLocationAsync(upcomingEvent14, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent14);
await _eventRegistrationManager.RegisterAsync(upcomingEvent14, userTony);
@ -353,6 +377,7 @@ namespace EventHub.DbMigrator.Data
DateTime.Now.AddDays(36),
DateTime.Now.AddDays(50),
"Mark your calendars! Join us for DevFest Silicon Valley, virtually from anywhere around the world! DevFest brings together thousands of developers from all different backgrounds and skill levels who have a shared passion for Google technologies to teach, learn, and connect. Let's keep the momentum going for DevFest 2021!");
await _eventManager.SetLocationAsync(upcomingEvent15, true, "https://www.youtube.com/" ,null, null);
await _eventRepository.InsertAsync(upcomingEvent15);
await _eventRegistrationManager.RegisterAsync(upcomingEvent15, userTony);
await _eventRegistrationManager.RegisterAsync(upcomingEvent15, userAlessandro);

2
src/EventHub.Domain.Shared/Events/EventConsts.cs

@ -23,6 +23,6 @@
public const int MaxTimingChangeCountForUser = 2;
public const int MaxCoverImageFileSize = 1024 * 1024;
public const int MaxCoverImageFileSize = 5 * 1024 * 1024;
}
}

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

@ -26,11 +26,10 @@
"Organization": "Organization",
"Submit": "Submit",
"SeeEvent": "See event",
"RegisterNow": "Register Now",
"JoinThisEvent": "Join This Event",
"LoginToRegister": "Login to register",
"CancelRegistration": "Cancel registration",
"EventRegisterSuccessMessageTitle": "Thanks for registering!",
"EventRegisterSuccessMessage": "We will send a reminder email before the event.",
"YouAttendedThisEvent": "You Attended This Event",
"EventRegisterSuccessMessage": "Your event registration has been done successfully.",
"EventRegistrationCancelledMessage": "Your event registration has been cancelled.",
"OrganizedBy": "Organized by",
"NoEventOrganizedByThisOrganizationYet": "No event organized by this organization yet!",
@ -41,8 +40,8 @@
"OrganizationJoinSuccessMessageTitle": "Thank you for your membership!",
"OrganizationJoinSuccessMessage": "See you at the events.",
"OrganizationMembershipLeaveMessage": "You left your organization membership.",
"LeaveOrganization": "Leave this organization",
"JoinOrganization": "Join the organization",
"LeaveOrganization": "leave this organization",
"JoinOrganization": "join the organization",
"Edit": "Edit",
"EditOrganization": "Edit Organization",
"PersonalWebsite": "Personal Website",
@ -57,7 +56,7 @@
"OrganizationProfilePictureInfo": "Upload 16:9 aspect ratio pictures for the best view. Maximum file size: 1MB.",
"Close": "Close",
"EventHub:CapacityOfEventFull": "\"{EventTitle}\" event capacity is full!",
"GoToEventAddress": "Go to Event Address",
"GoToOnlineAddress": "Go to Online Address",
"AttendeesCanSeeEventLocation": "Only attendees can see the event's {0}.",
"LoginToSeeLocation": "Login to see location",
"LocationHasNotSpecifiedYet": "Event {0} has not been specified yet.",
@ -72,7 +71,6 @@
"EventCoverImageExtensionNotAllowed": "This image extension is not allowed. Allowed extensions: png, jpg, jpeg",
"ChooseEventCoverImageInfo": "Maximum image size: 1MB.",
"ProfilePicturePreview": "Profile Picture Preview",
"EditEvent": "Edit Event",
"EventInformation": "Event Information",
"EventCapacityLabel": "Capacity (Optional)",
"EventCapacityInfo": "Capacity can not be lower than the currently registered user count : {0}",
@ -83,6 +81,7 @@
"EventCoverImage": "Event Cover Image",
"EventTimingPreview": "Event Timing Preview",
"CoverImagePreview": "Cover Image Preview",
"EventTimingChangeSuccessMessage": "The time of the event has been changed successfully!"
"EventTimingChangeSuccessMessage": "The time of the event has been changed successfully!",
"PastEvent": "Past Event"
}
}

15
src/EventHub.Domain.Shared/Organizations/OrganizationContst.cs

@ -11,6 +11,19 @@
public const int MinDescriptionNameLength = 50;
public const int MaxDescriptionNameLength = 1000;
public const int MaxProfilePictureFileSize = 1024 * 1024; //1MB
public const int MaxProfilePictureFileSize = 5 * 1024 * 1024;
public const int MaxWebsiteLength = 512;
public const int MaxTwitterUsernameLength = 24;
public const int MaxGitHubUsernameLength = 24;
public const int MaxFacebookUsernameLength = 24;
public const int MaxInstagramUsernameLength = 24;
public const int MaxMediumUsernameLength = 24;
}
}

17
src/EventHub.Domain.Shared/Web/EventHubExternalUrls.cs

@ -0,0 +1,17 @@
namespace EventHub.Web
{
public static class EventHubExternalUrls
{
#if DEBUG
public const string EhAccount = "https://localhost:44313";
public const string EhApi = "https://localhost:44362";
public const string EhAdmin = "https://localhost:44307";
public const string EhWww = "https://localhost:44308";
#else
public const string EhAccount = "https://localhost:44313";
public const string EhApi = "https://localhost:44362";
public const string EhAdmin = "https://localhost:44307";
public const string EhWww = "https://localhost:44308";
#endif
}
}

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

@ -20,13 +20,15 @@ namespace EventHub.Events
public string Description { get; private set; }
public bool IsOnline { get; private set; }
public bool IsOnline { get; internal set; }
public string OnlineLink { get; private set; }
public string OnlineLink { get; internal set; }
public Guid? CountryId { get; private set; }
public Guid? CountryId { get; internal set; }
public string City { get; private set; }
public string CountryName { get; internal set; }
public string City { get; internal set; }
public string Language { get; set; }
@ -75,34 +77,22 @@ namespace EventHub.Events
public Event SetTime(DateTime startTime, DateTime endTime)
{
AddLocalEvent(new EventTimeChangingEventData(this, StartTime, EndTime));
return SetTimeInternal(startTime, endTime);
}
public Event SetLocation(
bool isOnline,
string onlineLink,
Guid? countryId,
string city)
{
IsOnline = isOnline;
if (IsOnline)
if (startTime == StartTime && endTime == EndTime)
{
OnlineLink = onlineLink;
CountryId = null;
City = null;
return this;
}
else
if (TimingChangeCount >= EventConsts.MaxTimingChangeCountForUser)
{
OnlineLink = null;
CountryId = countryId;
City = city;
throw new BusinessException(EventHubErrorCodes.CantChangeEventTiming)
.WithData("MaxTimingChangeLimit", EventConsts.MaxTimingChangeCountForUser);
}
AddLocalEvent(new EventTimeChangingEventData(this, StartTime, EndTime));
return this;
return SetTimeInternal(startTime, endTime);
}
private Event SetTimeInternal(DateTime startTime, DateTime endTime)
{
if (startTime > endTime)
@ -112,6 +102,7 @@ namespace EventHub.Events
StartTime = startTime;
EndTime = endTime;
TimingChangeCount++;
return this;
}
}

34
src/EventHub.Domain/Events/EventManager.cs

@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Countries;
using EventHub.Events.Registrations;
using EventHub.Organizations;
using Volo.Abp;
@ -13,13 +14,16 @@ namespace EventHub.Events
{
private readonly EventUrlCodeGenerator _eventUrlCodeGenerator;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IRepository<Country, Guid> _countriesRepository;
public EventManager(
EventUrlCodeGenerator eventUrlCodeGenerator,
IRepository<EventRegistration, Guid> eventRegistrationRepository)
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IRepository<Country, Guid> countriesRepository)
{
_eventUrlCodeGenerator = eventUrlCodeGenerator;
_eventRegistrationRepository = eventRegistrationRepository;
_countriesRepository = countriesRepository;
}
public async Task<Event> CreateAsync(
@ -55,5 +59,33 @@ namespace EventHub.Events
@event.Capacity = capacity;
}
public async Task SetLocationAsync(
Event @event,
bool isOnline,
string onlineLink,
Guid? countryId,
string city)
{
@event.IsOnline = isOnline;
if (@event.IsOnline)
{
@event.OnlineLink = onlineLink;
@event.CountryId = null;
@event.CountryName = null;
@event.City = null;
}
else
{
Check.NotNull(countryId, nameof(countryId));
Check.NotNull(city, nameof(city));
@event.OnlineLink = null;
@event.CountryId = countryId;
@event.CountryName = (await _countriesRepository.GetAsync(@event.CountryId!.Value)).Name;
@event.City = city;
}
}
}
}

16
src/EventHub.Domain/Events/Registrations/EventRegistrationManager.cs

@ -20,7 +20,10 @@ namespace EventHub.Events.Registrations
Event @event,
AppUser user)
{
CheckEventEndTime(@event);
if (IsPastEvent(@event))
{
throw new BusinessException(EventHubErrorCodes.CantRegisterOrUnregisterForAPastEvent);
}
if (await IsRegisteredAsync(@event, user))
{
@ -48,7 +51,10 @@ namespace EventHub.Events.Registrations
Event @event,
AppUser user)
{
CheckEventEndTime(@event);
if (IsPastEvent(@event))
{
throw new BusinessException(EventHubErrorCodes.CantRegisterOrUnregisterForAPastEvent);
}
await _eventRegistrationRepository.DeleteAsync(
x => x.EventId == @event.Id && x.UserId == user.Id
@ -63,12 +69,14 @@ namespace EventHub.Events.Registrations
.AnyAsync(x => x.EventId == @event.Id && x.UserId == user.Id);
}
private void CheckEventEndTime(Event @event)
public bool IsPastEvent(Event @event)
{
if (Clock.Now > @event.EndTime)
{
throw new BusinessException(EventHubErrorCodes.CantRegisterOrUnregisterForAPastEvent);
return true;
}
return false;
}
}
}

2639
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210428213802_Added_CountryName_To_Event.Designer.cs

File diff suppressed because it is too large

23
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210428213802_Added_CountryName_To_Event.cs

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace EventHub.Migrations
{
public partial class Added_CountryName_To_Event : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "CountryName",
table: "EhEvents",
type: "text",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CountryName",
table: "EhEvents");
}
}
}

5271
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs

File diff suppressed because it is too large

33
src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using EventHub.Admin;
@ -12,6 +13,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using EventHub.EntityFrameworkCore;
using Microsoft.AspNetCore.Localization;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
@ -138,19 +140,7 @@ namespace EventHub
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
options.Languages.Add(new LanguageInfo("en", "en", "English", "gb"));
});
}
@ -196,7 +186,22 @@ namespace EventHub
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
var supportedCultures = new[]
{
new CultureInfo("en")
};
app.UseAbpRequestLocalization(options =>
{
options.DefaultRequestCulture = new RequestCulture("en");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders = new List<IRequestCultureProvider>
{
new QueryStringRequestCultureProvider(),
new CookieRequestCultureProvider()
};
});
if (!env.IsDevelopment())
{

1
src/EventHub.IdentityServer/EventHub.IdentityServer.csproj

@ -46,6 +46,7 @@
<PackageReference Include="Volo.Abp.Account.Web.IdentityServer" Version="4.2.1" />
<PackageReference Include="Volo.Abp.Account.Application" Version="4.2.1" />
<ProjectReference Include="..\EventHub.EntityFrameworkCore.DbMigrations\EventHub.EntityFrameworkCore.DbMigrations.csproj" />
<ProjectReference Include="..\EventHub.Web.Theme\EventHub.Web.Theme.csproj" />
</ItemGroup>
</Project>

21
src/EventHub.IdentityServer/EventHubIdentityServerModule.cs

@ -9,13 +9,13 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using EventHub.EntityFrameworkCore;
using EventHub.Localization;
using EventHub.Web.Theme;
using EventHub.Web.Theme.Bundling;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Auditing;
@ -35,7 +35,7 @@ namespace EventHub
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAccountWebIdentityServerModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(EventHubWebThemeModule),
typeof(EventHubEntityFrameworkCoreDbMigrationsModule),
typeof(AbpAspNetCoreSerilogModule)
)]
@ -56,25 +56,13 @@ namespace EventHub
typeof(AbpUiResource)
);
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
});
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BasicThemeBundles.Styles.Global,
EventHubThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
@ -94,6 +82,7 @@ namespace EventHub
{
options.FileSets.ReplaceEmbeddedByPhysical<EventHubDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}EventHub.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<EventHubDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}EventHub.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<EventHubWebThemeModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}EventHub.Web.Theme"));
});
}

2
src/EventHub.IdentityServer/Pages/Index.cshtml

@ -31,4 +31,4 @@
<i class="fa fa-user d-block" style="font-size: 10em; color: #aaa"></i><br/><br />
<a abp-button="Primary" asp-page="/Account/Login">Login</a>
</div>
}
}

7
src/EventHub.IdentityServer/abp.resourcemapping.js

@ -1,11 +1,12 @@
module.exports = {
aliases: {
"@node_modules": "./node_modules",
"@libs": "./wwwroot/libs"
},
clean: [
"@libs"
],
mappings: {
"@node_modules/owl.carousel/dist/**": "@libs/owl.carousel/",
}
};

5
src/EventHub.IdentityServer/package.json

@ -3,6 +3,7 @@
"name": "my-app-identityserver",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "~4.2.1"
"@abp/aspnetcore.mvc.ui.theme.basic": "~4.2.1",
"owl.carousel": "^2.3.4"
}
}
}

3
src/EventHub.IdentityServer/wwwroot/assets/dropdown-arrow.svg

@ -0,0 +1,3 @@
<svg width="6" height="4" viewBox="0 0 6 4" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.48367 0.0890989L3.00029 2.57308L0.516903 0.0887999C0.398503 -0.0296 0.206976 -0.0296 0.0885757 0.0887999C-0.0295252 0.2072 -0.0295252 0.399027 0.0885757 0.517427L2.78599 3.21573C2.90409 3.33413 3.09591 3.33413 3.21401 3.21573L5.91142 0.517451C6.02953 0.399052 6.02953 0.206926 5.91142 0.0885259C5.79362 -0.0293009 5.60177 -0.029301 5.48367 0.0890989Z" fill="#00044A"/>
</svg>

After

Width:  |  Height:  |  Size: 480 B

BIN
src/EventHub.IdentityServer/wwwroot/assets/seperator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

3
src/EventHub.IdentityServer/wwwroot/assets/seperator2.svg

@ -0,0 +1,3 @@
<svg width="4" height="4" viewBox="0 0 4 4" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="2" cy="2" r="2" fill="white" fill-opacity="0.5"/>
</svg>

After

Width:  |  Height:  |  Size: 161 B

1342
src/EventHub.IdentityServer/wwwroot/libs/abp/utils/abp-utils.umd.js

File diff suppressed because it is too large

0
src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.css

0
src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map

0
src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css

0
src/EventHub.IdentityServer/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map

40
src/EventHub.IdentityServer/wwwroot/libs/jquery-validation/jquery.validate.js

@ -1,21 +1,21 @@
/*!
* jQuery Validation Plugin v1.19.0
*
* https://jqueryvalidation.org/
*
* Copyright (c) 2018 Jörn Zaefferer
* Released under the MIT license
*/
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ["jquery"], factory );
} else if (typeof module === "object" && module.exports) {
module.exports = factory( require( "jquery" ) );
} else {
factory( jQuery );
}
}(function( $ ) {
/*!
* jQuery Validation Plugin v1.19.0
*
* https://jqueryvalidation.org/
*
* Copyright (c) 2018 Jörn Zaefferer
* Released under the MIT license
*/
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ["jquery"], factory );
} else if (typeof module === "object" && module.exports) {
module.exports = factory( require( "jquery" ) );
} else {
factory( jQuery );
}
}(function( $ ) {
$.extend( $.fn, {
// https://jqueryvalidation.org/validate/
@ -1610,7 +1610,7 @@ $.extend( $.validator, {
}
} );
// Ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
@ -1646,5 +1646,5 @@ if ( $.ajaxPrefilter ) {
return ajax.apply( this, arguments );
};
}
return $;
return $;
}));

8
src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js

File diff suppressed because one or more lines are too long

2534
src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css

File diff suppressed because it is too large

4914
src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js

File diff suppressed because it is too large

72
src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json

@ -1,37 +1,37 @@
{
"name": "malihu-custom-scrollbar-plugin",
"version": "3.1.5",
"author": "malihu (http://manos.malihu.gr)",
"description": "Highly customizable custom scrollbar jQuery plugin, featuring vertical/horizontal scrollbars, scrolling momentum, mouse-wheel, keyboard and touch support user defined callbacks etc.",
"license": "MIT",
"homepage": "http://manos.malihu.gr/jquery-custom-content-scroller",
"main": "./jquery.mCustomScrollbar.js",
"repository": {
"type": "git",
"url": "https://github.com/malihu/malihu-custom-scrollbar-plugin.git"
},
"bugs": {
"url": "https://github.com/malihu/malihu-custom-scrollbar-plugin/issues"
},
"keywords": [
"jquery-plugin",
"custom-scrollbar",
"scrollbar"
],
"files": [
"jquery.mCustomScrollbar.js",
"jquery.mCustomScrollbar.concat.min.js",
"jquery.mCustomScrollbar.css",
"mCSB_buttons.png",
"readme.md"
],
"jam": {
"dependencies": {
"jquery": ">=1.6",
"jquery-mousewheel": ">=3.0.6"
}
},
"dependencies": {
"jquery-mousewheel": ">=3.0.6"
}
{
"name": "malihu-custom-scrollbar-plugin",
"version": "3.1.5",
"author": "malihu (http://manos.malihu.gr)",
"description": "Highly customizable custom scrollbar jQuery plugin, featuring vertical/horizontal scrollbars, scrolling momentum, mouse-wheel, keyboard and touch support user defined callbacks etc.",
"license": "MIT",
"homepage": "http://manos.malihu.gr/jquery-custom-content-scroller",
"main": "./jquery.mCustomScrollbar.js",
"repository": {
"type": "git",
"url": "https://github.com/malihu/malihu-custom-scrollbar-plugin.git"
},
"bugs": {
"url": "https://github.com/malihu/malihu-custom-scrollbar-plugin/issues"
},
"keywords": [
"jquery-plugin",
"custom-scrollbar",
"scrollbar"
],
"files": [
"jquery.mCustomScrollbar.js",
"jquery.mCustomScrollbar.concat.min.js",
"jquery.mCustomScrollbar.css",
"mCSB_buttons.png",
"readme.md"
],
"jam": {
"dependencies": {
"jquery": ">=1.6",
"jquery-mousewheel": ">=3.0.6"
}
},
"dependencies": {
"jquery-mousewheel": ">=3.0.6"
}
}

162
src/EventHub.IdentityServer/wwwroot/libs/malihu-custom-scrollbar-plugin/readme.md

@ -1,82 +1,82 @@
malihu custom scrollbar plugin
================================
Highly customizable custom scrollbar jQuery plugin ([Demo](http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/complete_examples.html)). Features include:
* Vertical and/or horizontal scrollbar(s)
* Adjustable scrolling momentum
* Mouse-wheel, keyboard and touch support
* Ready-to-use themes and customization via CSS
* RTL direction support
* Option parameters for full control of scrollbar functionality
* Methods for triggering actions like scroll-to, update, destroy etc.
* User-defined callbacks
* Selectable/searchable content
**[Plugin homepage and documentation](http://manos.malihu.gr/jquery-custom-content-scroller/)** ([Changelog](http://manos.malihu.gr/jquery-custom-content-scroller/2/))
#### Installation
npm: `npm install malihu-custom-scrollbar-plugin`
Bower: `bower install malihu-custom-scrollbar-plugin`
[Manual](http://manos.malihu.gr/jquery-custom-content-scroller/#get-started-section)
#### Usage
Manual: `$(selector).mCustomScrollbar();`
[Browserify](http://browserify.org/):
var $ = require('jquery');
require('malihu-custom-scrollbar-plugin')($);
[webpack](https://webpack.github.io/):
npm install imports-loader
npm install jquery-mousewheel
npm install malihu-custom-scrollbar-plugin
module.exports = {
module: {
loaders: [
{ test: /jquery-mousewheel/, loader: "imports?define=>false&this=>window" },
{ test: /malihu-custom-scrollbar-plugin/, loader: "imports?define=>false&this=>window" }
]
}
};
var $ = require('jquery');
require("jquery-mousewheel")($);
require('malihu-custom-scrollbar-plugin')($);
Requirements
-------------------------
jQuery version **1.6.0** or higher
Browser compatibility
-------------------------
* Internet Explorer 8+
* Firefox
* Chrome
* Opera
* Safari
* iOS
* Android
* Windows Phone
License
-------------------------
MIT License (MIT)
http://opensource.org/licenses/MIT
Donate
-------------------------
malihu custom scrollbar plugin
================================
Highly customizable custom scrollbar jQuery plugin ([Demo](http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/complete_examples.html)). Features include:
* Vertical and/or horizontal scrollbar(s)
* Adjustable scrolling momentum
* Mouse-wheel, keyboard and touch support
* Ready-to-use themes and customization via CSS
* RTL direction support
* Option parameters for full control of scrollbar functionality
* Methods for triggering actions like scroll-to, update, destroy etc.
* User-defined callbacks
* Selectable/searchable content
**[Plugin homepage and documentation](http://manos.malihu.gr/jquery-custom-content-scroller/)** ([Changelog](http://manos.malihu.gr/jquery-custom-content-scroller/2/))
#### Installation
npm: `npm install malihu-custom-scrollbar-plugin`
Bower: `bower install malihu-custom-scrollbar-plugin`
[Manual](http://manos.malihu.gr/jquery-custom-content-scroller/#get-started-section)
#### Usage
Manual: `$(selector).mCustomScrollbar();`
[Browserify](http://browserify.org/):
var $ = require('jquery');
require('malihu-custom-scrollbar-plugin')($);
[webpack](https://webpack.github.io/):
npm install imports-loader
npm install jquery-mousewheel
npm install malihu-custom-scrollbar-plugin
module.exports = {
module: {
loaders: [
{ test: /jquery-mousewheel/, loader: "imports?define=>false&this=>window" },
{ test: /malihu-custom-scrollbar-plugin/, loader: "imports?define=>false&this=>window" }
]
}
};
var $ = require('jquery');
require("jquery-mousewheel")($);
require('malihu-custom-scrollbar-plugin')($);
Requirements
-------------------------
jQuery version **1.6.0** or higher
Browser compatibility
-------------------------
* Internet Explorer 8+
* Firefox
* Chrome
* Opera
* Safari
* iOS
* Android
* Windows Phone
License
-------------------------
MIT License (MIT)
http://opensource.org/licenses/MIT
Donate
-------------------------
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UYJ5G65M6ZA28

23
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/LICENSE

@ -0,0 +1,23 @@
Copyright (c) 2014 Owl
Modified work Copyright 2016-2018 David Deutsch
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

122
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/README.md

@ -0,0 +1,122 @@
# Owl Carousel 2
Touch enabled [jQuery](https://jquery.com/) plugin that lets you create a beautiful, responsive carousel slider. **To get started, check out https://owlcarousel2.github.io/OwlCarousel2/.**
**Notice:** The old Owl Carousel site (owlgraphic [dot] com) is no longer in use. Please delete all references to this in bookmarks and your own products' documentation as it's being used for malicious purposes.
## Quick start
### Install
This package can be installed with:
- [npm](https://www.npmjs.com/package/owl.carousel): `npm install --save owl.carousel` or `yarn add owl.carousel jquery`
- [bower](http://bower.io/search/?q=owl.carousel): `bower install --save owl.carousel`
Or download the [latest release](https://github.com/OwlCarousel2/OwlCarousel2/releases).
### Load
#### Webpack
Add jQuery via the "webpack.ProvidePlugin" to your webpack configuration:
const webpack = require('webpack');
//...
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
],
//...
Load the required stylesheet and JS:
```js
import 'owl.carousel/dist/assets/owl.carousel.css';
import 'owl.carousel';
```
#### Static HTML
Put the required stylesheet at the [top](https://developer.yahoo.com/performance/rules.html#css_top) of your markup:
```html
<link rel="stylesheet" href="/node_modules/owl.carousel/dist/assets/owl.carousel.min.css" />
```
```html
<link rel="stylesheet" href="/bower_components/owl.carousel/dist/assets/owl.carousel.min.css" />
```
**NOTE:** If you want to use the default navigation styles, you will also need to include `owl.theme.default.css`.
Put the script at the [bottom](https://developer.yahoo.com/performance/rules.html#js_bottom) of your markup right after jQuery:
```html
<script src="/node_modules/jquery/dist/jquery.js"></script>
<script src="/node_modules/owl.carousel/dist/owl.carousel.min.js"></script>
```
```html
<script src="/bower_components/jquery/dist/jquery.js"></script>
<script src="/bower_components/owl.carousel/dist/owl.carousel.min.js"></script>
```
### Usage
Wrap your items (`div`, `a`, `img`, `span`, `li` etc.) with a container element (`div`, `ul` etc.). Only the class `owl-carousel` is mandatory to apply proper styles:
```html
<div class="owl-carousel owl-theme">
<div> Your Content </div>
<div> Your Content </div>
<div> Your Content </div>
<div> Your Content </div>
<div> Your Content </div>
<div> Your Content </div>
<div> Your Content </div>
</div>
```
**NOTE:** The `owl-theme` class is optional, but without it, you will need to style navigation features on your own.
Call the [plugin](https://learn.jquery.com/plugins/) function and your carousel is ready.
```javascript
$(document).ready(function(){
$('.owl-carousel').owlCarousel();
});
```
## Documentation
The documentation, included in this repo in the root directory, is built with [Assemble](http://assemble.io/) and publicly available at https://owlcarousel2.github.io/OwlCarousel2/. The documentation may also be run locally.
## Building
This package comes with [Grunt](http://gruntjs.com/) and [Bower](http://bower.io/). The following tasks are available:
* `default` compiles the CSS and JS into `/dist` and builds the doc.
* `dist` compiles the CSS and JS into `/dist` only.
* `watch` watches source files and builds them automatically whenever you save.
* `test` runs [JSHint](http://www.jshint.com/) and [QUnit](http://qunitjs.com/) tests headlessly in [PhantomJS](http://phantomjs.org/).
To define which plugins are build into the distribution just edit `/_config.json` to fit your needs.
## Contributing
Please read [CONTRIBUTING.md](CONTRIBUTING.md).
## Roadmap
Please make sure to check out our [Roadmap Discussion](https://github.com/OwlCarousel2/OwlCarousel2/issues/1756).
## License
The code and the documentation are released under the [MIT License](LICENSE).

BIN
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/ajax-loader.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

186
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.carousel.css

@ -0,0 +1,186 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
/*
* Owl Carousel - Core
*/
.owl-carousel {
display: none;
width: 100%;
-webkit-tap-highlight-color: transparent;
/* position relative and z-index fix webkit rendering fonts issue */
position: relative;
z-index: 1; }
.owl-carousel .owl-stage {
position: relative;
-ms-touch-action: pan-Y;
touch-action: manipulation;
-moz-backface-visibility: hidden;
/* fix firefox animation glitch */ }
.owl-carousel .owl-stage:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0; }
.owl-carousel .owl-stage-outer {
position: relative;
overflow: hidden;
/* fix for flashing background */
-webkit-transform: translate3d(0px, 0px, 0px); }
.owl-carousel .owl-wrapper,
.owl-carousel .owl-item {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0); }
.owl-carousel .owl-item {
position: relative;
min-height: 1px;
float: left;
-webkit-backface-visibility: hidden;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none; }
.owl-carousel .owl-item img {
display: block;
width: 100%; }
.owl-carousel .owl-nav.disabled,
.owl-carousel .owl-dots.disabled {
display: none; }
.owl-carousel .owl-nav .owl-prev,
.owl-carousel .owl-nav .owl-next,
.owl-carousel .owl-dot {
cursor: pointer;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
.owl-carousel .owl-nav button.owl-prev,
.owl-carousel .owl-nav button.owl-next,
.owl-carousel button.owl-dot {
background: none;
color: inherit;
border: none;
padding: 0 !important;
font: inherit; }
.owl-carousel.owl-loaded {
display: block; }
.owl-carousel.owl-loading {
opacity: 0;
display: block; }
.owl-carousel.owl-hidden {
opacity: 0; }
.owl-carousel.owl-refresh .owl-item {
visibility: hidden; }
.owl-carousel.owl-drag .owl-item {
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
.owl-carousel.owl-grab {
cursor: move;
cursor: grab; }
.owl-carousel.owl-rtl {
direction: rtl; }
.owl-carousel.owl-rtl .owl-item {
float: right; }
/* No Js */
.no-js .owl-carousel {
display: block; }
/*
* Owl Carousel - Animate Plugin
*/
.owl-carousel .animated {
animation-duration: 1000ms;
animation-fill-mode: both; }
.owl-carousel .owl-animated-in {
z-index: 0; }
.owl-carousel .owl-animated-out {
z-index: 1; }
.owl-carousel .fadeOut {
animation-name: fadeOut; }
@keyframes fadeOut {
0% {
opacity: 1; }
100% {
opacity: 0; } }
/*
* Owl Carousel - Auto Height Plugin
*/
.owl-height {
transition: height 500ms ease-in-out; }
/*
* Owl Carousel - Lazy Load Plugin
*/
.owl-carousel .owl-item {
/**
This is introduced due to a bug in IE11 where lazy loading combined with autoheight plugin causes a wrong
calculation of the height of the owl-item that breaks page layouts
*/ }
.owl-carousel .owl-item .owl-lazy {
opacity: 0;
transition: opacity 400ms ease; }
.owl-carousel .owl-item .owl-lazy[src^=""], .owl-carousel .owl-item .owl-lazy:not([src]) {
max-height: 0; }
.owl-carousel .owl-item img.owl-lazy {
transform-style: preserve-3d; }
/*
* Owl Carousel - Video Plugin
*/
.owl-carousel .owl-video-wrapper {
position: relative;
height: 100%;
background: #000; }
.owl-carousel .owl-video-play-icon {
position: absolute;
height: 80px;
width: 80px;
left: 50%;
top: 50%;
margin-left: -40px;
margin-top: -40px;
background: url("owl.video.play.png") no-repeat;
cursor: pointer;
z-index: 1;
-webkit-backface-visibility: hidden;
transition: transform 100ms ease; }
.owl-carousel .owl-video-play-icon:hover {
-ms-transform: scale(1.3, 1.3);
transform: scale(1.3, 1.3); }
.owl-carousel .owl-video-playing .owl-video-tn,
.owl-carousel .owl-video-playing .owl-video-play-icon {
display: none; }
.owl-carousel .owl-video-tn {
opacity: 0;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
transition: opacity 400ms ease; }
.owl-carousel .owl-video-frame {
position: relative;
z-index: 1;
height: 100%;
width: 100%; }

6
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.carousel.min.css

@ -0,0 +1,6 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
.owl-carousel,.owl-carousel .owl-item{-webkit-tap-highlight-color:transparent;position:relative}.owl-carousel{display:none;width:100%;z-index:1}.owl-carousel .owl-stage{position:relative;-ms-touch-action:pan-Y;touch-action:manipulation;-moz-backface-visibility:hidden}.owl-carousel .owl-stage:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0}.owl-carousel .owl-stage-outer{position:relative;overflow:hidden;-webkit-transform:translate3d(0,0,0)}.owl-carousel .owl-item,.owl-carousel .owl-wrapper{-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}.owl-carousel .owl-item{min-height:1px;float:left;-webkit-backface-visibility:hidden;-webkit-touch-callout:none}.owl-carousel .owl-item img{display:block;width:100%}.owl-carousel .owl-dots.disabled,.owl-carousel .owl-nav.disabled{display:none}.no-js .owl-carousel,.owl-carousel.owl-loaded{display:block}.owl-carousel .owl-dot,.owl-carousel .owl-nav .owl-next,.owl-carousel .owl-nav .owl-prev{cursor:pointer;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel .owl-nav button.owl-next,.owl-carousel .owl-nav button.owl-prev,.owl-carousel button.owl-dot{background:0 0;color:inherit;border:none;padding:0!important;font:inherit}.owl-carousel.owl-loading{opacity:0;display:block}.owl-carousel.owl-hidden{opacity:0}.owl-carousel.owl-refresh .owl-item{visibility:hidden}.owl-carousel.owl-drag .owl-item{-ms-touch-action:pan-y;touch-action:pan-y;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel.owl-grab{cursor:move;cursor:grab}.owl-carousel.owl-rtl{direction:rtl}.owl-carousel.owl-rtl .owl-item{float:right}.owl-carousel .animated{animation-duration:1s;animation-fill-mode:both}.owl-carousel .owl-animated-in{z-index:0}.owl-carousel .owl-animated-out{z-index:1}.owl-carousel .fadeOut{animation-name:fadeOut}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.owl-height{transition:height .5s ease-in-out}.owl-carousel .owl-item .owl-lazy{opacity:0;transition:opacity .4s ease}.owl-carousel .owl-item .owl-lazy:not([src]),.owl-carousel .owl-item .owl-lazy[src^=""]{max-height:0}.owl-carousel .owl-item img.owl-lazy{transform-style:preserve-3d}.owl-carousel .owl-video-wrapper{position:relative;height:100%;background:#000}.owl-carousel .owl-video-play-icon{position:absolute;height:80px;width:80px;left:50%;top:50%;margin-left:-40px;margin-top:-40px;background:url(owl.video.play.png) no-repeat;cursor:pointer;z-index:1;-webkit-backface-visibility:hidden;transition:transform .1s ease}.owl-carousel .owl-video-play-icon:hover{-ms-transform:scale(1.3,1.3);transform:scale(1.3,1.3)}.owl-carousel .owl-video-playing .owl-video-play-icon,.owl-carousel .owl-video-playing .owl-video-tn{display:none}.owl-carousel .owl-video-tn{opacity:0;height:100%;background-position:center center;background-repeat:no-repeat;background-size:contain;transition:opacity .4s ease}.owl-carousel .owl-video-frame{position:relative;z-index:1;height:100%;width:100%}

50
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.default.css

@ -0,0 +1,50 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
/*
* Default theme - Owl Carousel CSS File
*/
.owl-theme .owl-nav {
margin-top: 10px;
text-align: center;
-webkit-tap-highlight-color: transparent; }
.owl-theme .owl-nav [class*='owl-'] {
color: #FFF;
font-size: 14px;
margin: 5px;
padding: 4px 7px;
background: #D6D6D6;
display: inline-block;
cursor: pointer;
border-radius: 3px; }
.owl-theme .owl-nav [class*='owl-']:hover {
background: #869791;
color: #FFF;
text-decoration: none; }
.owl-theme .owl-nav .disabled {
opacity: 0.5;
cursor: default; }
.owl-theme .owl-nav.disabled + .owl-dots {
margin-top: 10px; }
.owl-theme .owl-dots {
text-align: center;
-webkit-tap-highlight-color: transparent; }
.owl-theme .owl-dots .owl-dot {
display: inline-block;
zoom: 1;
*display: inline; }
.owl-theme .owl-dots .owl-dot span {
width: 10px;
height: 10px;
margin: 5px 7px;
background: #D6D6D6;
display: block;
-webkit-backface-visibility: visible;
transition: opacity 200ms ease;
border-radius: 30px; }
.owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span {
background: #869791; }

6
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.default.min.css

@ -0,0 +1,6 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
.owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791}

50
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.green.css

@ -0,0 +1,50 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
/*
* Green theme - Owl Carousel CSS File
*/
.owl-theme .owl-nav {
margin-top: 10px;
text-align: center;
-webkit-tap-highlight-color: transparent; }
.owl-theme .owl-nav [class*='owl-'] {
color: #FFF;
font-size: 14px;
margin: 5px;
padding: 4px 7px;
background: #D6D6D6;
display: inline-block;
cursor: pointer;
border-radius: 3px; }
.owl-theme .owl-nav [class*='owl-']:hover {
background: #4DC7A0;
color: #FFF;
text-decoration: none; }
.owl-theme .owl-nav .disabled {
opacity: 0.5;
cursor: default; }
.owl-theme .owl-nav.disabled + .owl-dots {
margin-top: 10px; }
.owl-theme .owl-dots {
text-align: center;
-webkit-tap-highlight-color: transparent; }
.owl-theme .owl-dots .owl-dot {
display: inline-block;
zoom: 1;
*display: inline; }
.owl-theme .owl-dots .owl-dot span {
width: 10px;
height: 10px;
margin: 5px 7px;
background: #D6D6D6;
display: block;
-webkit-backface-visibility: visible;
transition: opacity 200ms ease;
border-radius: 30px; }
.owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span {
background: #4DC7A0; }

6
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.theme.green.min.css

@ -0,0 +1,6 @@
/**
* Owl Carousel v2.3.4
* Copyright 2013-2018 David Deutsch
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
*/
.owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#4DC7A0;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#4DC7A0}

BIN
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/assets/owl.video.play.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

3448
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/owl.carousel.js

File diff suppressed because it is too large

7
src/EventHub.IdentityServer/wwwroot/libs/owl.carousel/owl.carousel.min.js

File diff suppressed because one or more lines are too long

0
src/EventHub.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.uz.js

12
src/EventHub.IdentityServer/yarn.lock

@ -1495,6 +1495,11 @@ jquery@>=1.12.0, "jquery@>=1.5.0 <4.0", jquery@>=1.7, "jquery@>=1.7.1 <4.0.0", j
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
jquery@>=1.8.3:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
jquery@~3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
@ -1967,6 +1972,13 @@ osenv@^0.1.4:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
owl.carousel@^2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/owl.carousel/-/owl.carousel-2.3.4.tgz#6c53dc8d24304b790e4f27a1dc4a655e973ccdc9"
integrity sha512-JaDss9+feAvEW8KZppPSpllfposEzQiW+Ytt/Xm5t/3CTJ7YVmkh6RkWixoA2yXk2boIwedYxOvrrppIGzru9A==
dependencies:
jquery ">=1.8.3"
parse-filepath@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"

1
src/EventHub.Web.Theme/Bundling/EventHubThemeGlobalScriptContributor.cs

@ -6,7 +6,6 @@ namespace EventHub.Web.Theme.Bundling
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add("/themes/eventhub/layout.js");
}
}
}

4
src/EventHub.Web.Theme/Bundling/EventHubThemeGlobalStyleContributor.cs

@ -6,7 +6,9 @@ namespace EventHub.Web.Theme.Bundling
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add("/themes/eventhub/layout.css");
context.Files.Add("/themes/eventhub/style.css");
context.Files.Add("/themes/eventhub/owl-edit.css");
context.Files.Add("/themes/eventhub/floating-labels.css");
}
}
}

7
src/EventHub.Web.Theme/EventHub.Web.Theme.csproj

@ -20,8 +20,15 @@
<ItemGroup>
<Content Remove="wwwroot\**\*.*" />
<Content Include="wwwroot\themes\eventhub\floating-labels.css" />
<Content Include="wwwroot\themes\eventhub\owl-edit.css" />
<Content Include="wwwroot\themes\eventhub\style.css" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EventHub.Domain.Shared\EventHub.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="4.2.1" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="4.2.1" />

206
src/EventHub.Web.Theme/Helpers/TagHelpers/GravatarTagHelper.cs

@ -0,0 +1,206 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace EventHub.Web.Theme.Helpers.TagHelpers
{
/// <inheritdoc />
/// <summary>
/// Returns a Globally Recognised Avatar https://en.gravatar.com
/// </summary>
[HtmlTargetElement("img", Attributes = "gravatar-email")]
public class GravatarTagHelper : TagHelper
{
private readonly IHttpContextAccessor _contextAccessor;
public GravatarTagHelper(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
/// <summary>
/// Email Address for the Gravatar
/// </summary>
[HtmlAttributeName("gravatar-email")]
public string Email { get; set; }
/// <summary>
/// Gravatar content rating (note that Gravatars are self-rated)
/// </summary>
[HtmlAttributeName("gravatar-rating")]
public GravatarRating Rating { get; set; } = GravatarRating.GeneralAudiences;
/// <summary>
/// Size in pixels (default: 80)
/// </summary>
[HtmlAttributeName("gravatar-size")]
public int Size { get; set; } = 80;
/// <summary>
/// URL to a custom default image (e.g: 'Url.Content("~/images/no-grvatar.png")' )
/// </summary>
[HtmlAttributeName("default-image-url")]
public string DefaultImageUrl { get; set; } = "";
/// <summary>
/// Prefer the default image over the users own Gravatar
/// </summary>
[HtmlAttributeName("force-default-image")]
public bool ForceDefaultImage { get; set; }
/// <summary>
/// Default image if user hasn't created a Gravatar
/// </summary>
[HtmlAttributeName("default-image")]
public GravatarDefaultImage DefaultImage { get; set; } = GravatarDefaultImage.Default;
/// <summary>
/// Always do secure (https) requests
/// </summary>
[HtmlAttributeName("force-secure-request")]
public bool ForceSecureRequest { get; set; } = true;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var emailAddress = Email == null ? string.Empty : Email.Trim().ToLower();
var url = string.Format("{0}://{1}.gravatar.com/avatar/{2}?s={3}{4}{5}{6}",
GetUrlScheme(),
GetUrlPrefix(),
GetMd5Hash(emailAddress),
Size,
GetDefaultImageParameter(),
GetForceDefaultImageParameter(),
GetRatingParameter()
);
output.Attributes.SetAttribute("src", url);
}
private string GetUrlScheme()
{
return ForceSecureRequest || _contextAccessor.HttpContext.Request.IsHttps
? "https"
: "http";
}
private string GetUrlPrefix()
{
return ForceSecureRequest || _contextAccessor.HttpContext.Request.IsHttps ? "secure" : "www";
}
private string GetDefaultImageParameter()
{
return "&d=" + (!string.IsNullOrEmpty(DefaultImageUrl)
? System.Net.WebUtility.UrlEncode(DefaultImageUrl)
: GetEnumDescription(DefaultImage));
}
private string GetForceDefaultImageParameter()
{
return ForceDefaultImage ? "&f=y" : "";
}
private string GetRatingParameter()
{
return "&r=" + GetEnumDescription(Rating);
}
/// <summary>
/// Generates an MD5 hash of the given string
/// </summary>
/// <remarks>Source: http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx </remarks>
private static string GetMd5Hash(string input)
{
// Convert the input string to a byte array and compute the hash.
var data = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
var sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
foreach (var t in data)
{
sBuilder.Append(t.ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
/// <summary>
/// Returns the value of a Description for a given Enum value
/// </summary>
/// <remarks>Source: http://blogs.msdn.com/b/abhinaba/archive/2005/10/21/483337.aspx </remarks>
/// <param name="en"></param>
/// <returns></returns>
private static string GetEnumDescription(Enum en)
{
var type = en.GetType();
var memInfo = type.GetMember(en.ToString());
if (memInfo == null || memInfo.Length <= 0)
{
return en.ToString();
}
var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Any())
{
return ((DescriptionAttribute) attrs.First()).Description;
}
return en.ToString();
}
public enum GravatarDefaultImage
{
/// <summary>Default Gravatar logo</summary>
[Description("")] Default,
/// <summary>404 - do not load any image if none is associated with the email hash, instead return an HTTP 404 (File Not Found) response</summary>
[Description("404")] Http404,
/// <summary>Mystery-Man - a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)</summary>
[Description("mm")] MysteryMan,
/// <summary>Identicon - a geometric pattern based on an email hash</summary>
[Description("identicon")] Identicon,
/// <summary>MonsterId - a generated 'monster' with different colors, faces, etc</summary>
[Description("monsterid")] MonsterId,
/// <summary>Wavatar - generated faces with differing features and backgrounds</summary>
[Description("wavatar")] Wavatar,
/// <summary>Retro - awesome generated, 8-bit arcade-style pixelated faces</summary>
[Description("retro")] Retro
}
/// <summary>
/// Gravatar allows users to self-rate their images so that they can indicate if an image is appropriate for a certain audience. By default, only 'G' rated images are displayed unless you indicate that you would like to see higher ratings
/// </summary>
public enum GravatarRating
{
/// <summary>Suitable for display on all websites with any audience type</summary>
[Description("g")] GeneralAudiences,
/// <summary>May contain rude gestures, provocatively dressed individuals, the lesser swear words, or mild violence</summary>
[Description("pg")] ParentalGuidance,
/// <summary>May contain such things as harsh profanity, intense violence, nudity, or hard drug use</summary>
[Description("r")] Restricted,
/// <summary>May contain hardcore sexual imagery or extremely disturbing violence</summary>
[Description("x")] OnlyMature
}
}
}

66
src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/Default.cshtml

@ -0,0 +1,66 @@
@using EventHub.Web
@using Microsoft.AspNetCore.Http.Extensions
@using Volo.Abp.Users
@inject ICurrentUser CurrentUser
<footer class="mt-5">
<div class="container">
<div class="row">
<div class="col-md">
<a href="@Url.Page("/index")" class="footer-logo">
EventHub
</a>
</div>
<div class="col-md">
@if (!CurrentUser.IsAuthenticated)
{
<h5>Account</h5>
<div class="footer-links">
<a href="@EventHubExternalUrls.EhAccount/account/register?returnUrl=@EventHubExternalUrls.EhWww@(System.Net.WebUtility.UrlEncode(Context.Request.GetEncodedPathAndQuery()))" class="d-block">Sign Up</a>
<a href="/account/login?returnUrl=@(System.Net.WebUtility.UrlEncode(Context.Request.GetEncodedPathAndQuery()))" class="d-block">Log In</a>
</div>
}
</div>
<div class="col-md">
<h5>Follow Us</h5>
<div class="footer-links">
<a href="https://www.facebook.com/openeventhub">
<i class="fab fa-facebook"></i>
</a>
<a href="https://twitter.com/openeventhub">
<i class="fab fa-twitter"></i>
</a>
<a href="https://www.instagram.com/openeventhub/">
<i class="fab fa-instagram"></i>
</a>
<a href="https://github.com/openeventhub">
<i class="fab fa-github"></i>
</a>
</div>
</div>
</div>
</div>
</footer>
<footer class="footer-bottom">
<div class="container">
<div class="row">
<div class="col-md-auto">
<span class="copyright">© 2021 EventHub</span>
</div>
<div class="col-md text-center text-md-right">
<a href="@EventHubExternalUrls.EhWww/terms-service">
Terms of Service
</a>
<span>
<img src="/assets/seperator2.svg" class="mx-3">
</span>
<a href="@EventHubExternalUrls.EhWww/privacy-policy">
Privacy Policy
</a>
</div>
</div>
</div>
</footer>

13
src/EventHub.Web.Theme/Themes/EventHub/Components/Footer/FooterViewComponent.cs

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace EventHub.Web.Theme.Themes.EventHub.Components.Footer
{
public class FooterViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/Themes/EventHub/Components/Footer/Default.cshtml");
}
}
}

138
src/EventHub.Web.Theme/Themes/EventHub/Components/MainNavbar/Default.cshtml

@ -1,21 +1,131 @@
@using EventHub.Web.Theme.Themes.EventHub.Components.Brand
@using EventHub.Web.Theme.Themes.EventHub.Components.Menu
@using EventHub.Web.Theme.Themes.EventHub.Components.Toolbar
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;">
@using EventHub.Web
@using Microsoft.Extensions.Localization
@using Volo.Abp.Users
@using EventHub.Localization
@using Microsoft.AspNetCore.Http.Extensions
@using Volo.Abp.Localization
@inject ICurrentUser CurrentUser
@inject ILanguageProvider LanguageProvider
@inject IStringLocalizer<EventHubResource> L
@{
var returnUrl = System.Net.WebUtility.UrlEncode(Context.Request.GetEncodedPathAndQuery());
if (returnUrl.IsNullOrWhiteSpace())
{
returnUrl = "/";
}
}
<nav class="navbar navbar-expand-lg navbar-light bg-light static-top">
<div class="container">
@(await Component.InvokeAsync<MainNavbarBrandViewComponent>())
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse"
aria-expanded="false" aria-label="Toggle navigation">
<a class="navbar-brand font-weight-bold" href="@Url.Page("/index")">EventHub</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="main-navbar-collapse">
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav mx-auto">
@(await Component.InvokeAsync<MainNavbarMenuViewComponent>())
</ul>
<ul class="navbar-nav">
@(await Component.InvokeAsync<MainNavbarToolbarViewComponent>())
<li class="nav-item @(GetPageActiveClassOrEmpty(ViewContext, "/index"))">
<a class="nav-link" href="@EventHubExternalUrls.EhWww@Url.Page("/index")">
Home
</a>
</li>
<li class="nav-item @(GetPageActiveClassOrEmpty(ViewContext, "/events/index"))">
<a class="nav-link" href="@EventHubExternalUrls.EhWww/events">Events</a>
</li>
<li class="nav-item @(GetPageActiveClassOrEmpty(ViewContext, "/organizations/index"))">
<a class="nav-link" href="@EventHubExternalUrls.EhWww/organizations">Organizations</a>
</li>
</ul>
@if (EventHubExternalUrls.EhWww.Contains(Context.Request.Host.ToString()))
{
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link event-link" href="@EventHubExternalUrls.EhWww@Url.Page("/events/new")">+ Create an Event</a>
</li>
</ul>
}
<ul class="navbar-nav">
@if (CurrentUser.IsAuthenticated)
{
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="user-avatar">
<img gravatar-email="@CurrentUser.Email" default-image="Wavatar" gravatar-size="40" width="40" height="40" class="nav-avatar avatar rounded-circle"/>
</span>
<span class="ml-2">
@if (!string.IsNullOrWhiteSpace(CurrentUser.Name) && !string.IsNullOrWhiteSpace(CurrentUser.SurName))
{
@(CurrentUser.Name + " " + CurrentUser.SurName)
}
else
{
{
@CurrentUser.UserName
}
}
</span>
</a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" href="@(EventHubExternalUrls.EhAccount.EnsureEndsWith('/') + "account/manage")" title="@L["Account"]">
<i class="fas fa-cog"></i> @L["Account"]
</a>
<a class="dropdown-item" href="@EventHubExternalUrls.EhWww/users/@CurrentUser.UserName" title="@L["Profile"]">
<i class="fas fa-user"></i> @L["Profile"]
</a>
<a class="dropdown-item" href="/account/logout?returnUrl=@returnUrl" title="@L["Logout"]">
<i class="fas fa-sign-out-alt"></i> @L["Logout"]
</a>
</div>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link" href="/account/login?returnUrl=@returnUrl">Log In</a>
</li>
<li class="nav-item">
<a class="btn btn-primary ml-lg-2" href="@EventHubExternalUrls.EhAccount/account/register?returnUrl=@returnUrl">Sign Up</a>
</li>
}
</ul>
</div>
</div>
</nav>
</nav>
@functions{
public string GetPageActiveClassOrEmpty(ViewContext viewContext, string pageUrl)
{
if (!EventHubExternalUrls.EhWww.Contains(Context.Request.Host.ToString()))
{
return "";
}
var activeRoute = viewContext?.RouteData.Values["page"]?.ToString()?.ToLowerInvariant();
pageUrl = pageUrl.ToLowerInvariant();
if (activeRoute is null)
{
return "";
}
switch (pageUrl)
{
case "/index" when activeRoute == "/index":
return activeRoute == pageUrl ? "active" : activeRoute;
case "/index":
return "";
}
pageUrl = pageUrl.Replace("/index", "");
var highLevelActiveRoute = GetHighLevelRoute(activeRoute); // "/organizations/ng-coders" => "organizations"
return highLevelActiveRoute.Contains(pageUrl) ? "active" : highLevelActiveRoute;
}
private string GetHighLevelRoute(string route)
{
route.EnsureStartsWith('/');
return route.Split("/")[1].EnsureStartsWith('/').EnsureEndsWith('/');
}
}

72
src/EventHub.Web.Theme/Themes/EventHub/Layouts/Application.cshtml

@ -6,15 +6,16 @@
@using Volo.Abp.Localization
@using Volo.Abp.Ui.Branding
@using EventHub.Web.Theme.Bundling
@using EventHub.Web.Theme.Themes.EventHub.Components.Footer
@using EventHub.Web.Theme.Themes.EventHub.Components.MainNavbar
@using EventHub.Web.Theme.Themes.EventHub.Components.PageAlerts
@using EventHub.Web
@using Microsoft.AspNetCore.Http.Extensions
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@{
Layout = null;
var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; //TODO: Better and type-safe options
var pageTitle = ViewBag.Title == null ? BrandingProvider.AppName : ViewBag.Title; //TODO: Discard to get from Title
var pageTitle = ViewBag.Title == null ? "EventHub" : ViewBag.Title;
if (PageLayout.Content.Title != null)
{
@ -40,8 +41,25 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>@pageTitle</title>
<abp-style-bundle name="@EventHubThemeBundles.Styles.Global" />
@* TODO(berkansasmaz): Get SEO content from the marketing team *@
<meta name="description" content="@(!string.IsNullOrEmpty(ViewBag.Description) ? ViewBag.Description : "EventHub Description")"/>
<meta property="og:title" content="@(!string.IsNullOrWhiteSpace(ViewBag.OgTitle) ? ViewBag.OgTitle : "EventHub Title")"/>
<meta property="og:url" content="@Context.Request.GetDisplayUrl()"/>
<meta property="og:type" content="@(!string.IsNullOrWhiteSpace(ViewBag.OgType) ? ViewBag.OgType : "website")"/>
<meta property="og:description" content="@(!string.IsNullOrWhiteSpace(ViewBag.OgDescription) ? ViewBag.OgDescription : "EventHub Description")"/>
<meta property="og:image" content="@(!string.IsNullOrWhiteSpace(ViewBag.OgImage) ? ViewBag.OgImage : EventHubExternalUrls.EhWww + "/assets/slide.jpg")"/>
<meta property="twitter:card" content="summary_large_image"/>
<meta property="twitter:site" content="@Html.Raw("@openeventhub")"/>
<meta property="twitter:title" content="@(!string.IsNullOrWhiteSpace(ViewBag.TwitterTitle) ? ViewBag.TwitterTitle : "EventHub")"/>
<meta property="twitter:description" content="@(!string.IsNullOrWhiteSpace(ViewBag.TwitterDescription) ? ViewBag.TwitterDescription : "EventHub Description")"/>
<meta property="twitter:image" content="@(!string.IsNullOrWhiteSpace(ViewBag.TwitterImage) ? ViewBag.TwitterImage : EventHubExternalUrls.EhWww + "/assets/slide.jpg")"/>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<abp-style src="/libs/owl.carousel/assets/owl.carousel.min.css"></abp-style>
<abp-style src="/libs/owl.carousel/assets/owl.theme.default.css"></abp-style>
<abp-style-bundle name="@EventHubThemeBundles.Styles.Global"/>
@await Component.InvokeAsync(typeof(WidgetStylesViewComponent))
@ -49,32 +67,20 @@
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Application)
</head>
<body class="abp-application-layout bg-light @rtl">
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application)
@(await Component.InvokeAsync<MainNavbarViewComponent>())
<div class="@containerClass">
@(await Component.InvokeAsync<PageAlertsViewComponent>())
<div id="AbpContentToolbar">
<div class="text-right mb-2">
@RenderSection("content_toolbar", false)
</div>
</div>
@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.First, StandardLayouts.Application)
@RenderBody()
@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.Last, StandardLayouts.Application)
</div>
<abp-script-bundle name="@EventHubThemeBundles.Scripts.Global" />
<script src="~/Abp/ApplicationConfigurationScript"></script>
<script src="~/Abp/ServiceProxyScript"></script>
@await Component.InvokeAsync(typeof(WidgetScriptsViewComponent))
@await RenderSectionAsync("scripts", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application)
<body class="abp-application-layout @rtl">
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application)
@(await Component.InvokeAsync<MainNavbarViewComponent>())
@(await Component.InvokeAsync<PageAlertsViewComponent>())
@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.First, StandardLayouts.Application)
@RenderBody()
@await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.Last, StandardLayouts.Application)
@(await Component.InvokeAsync<FooterViewComponent>())
<abp-script-bundle name="@EventHubThemeBundles.Scripts.Global"/>
<abp-script src="/libs/owl.carousel/owl.carousel.min.js" />
<script src="~/Abp/ApplicationConfigurationScript"></script>
<script src="~/Abp/ServiceProxyScript"></script>
@await Component.InvokeAsync(typeof(WidgetScriptsViewComponent))
@await RenderSectionAsync("scripts", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application)
</body>
</html>
</html>

3
src/EventHub.Web.Theme/Themes/EventHub/_ViewImports.cshtml

@ -1,4 +1,5 @@
@using System.Globalization
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
@addTagHelper *, EventHub.Web.Theme

70
src/EventHub.Web.Theme/wwwroot/themes/eventhub/floating-labels.css

@ -0,0 +1,70 @@
.form-label-group input::-webkit-input-placeholder {
color: transparent;
}
.form-label-group input:-moz-placeholder {
color: transparent;
}
.form-label-group input::-moz-placeholder {
color: transparent;
}
.form-label-group input:-ms-input-placeholder {
color: transparent;
}
.form-signin {
width: 100%;
max-width: 420px;
padding: 15px;
margin: auto;
}
.form-label-group {
position: relative;
}
.form-label-group > input {
padding: 14px 20px;
}
.form-label-group > label {
padding: 14px 20px;
}
.form-label-group > label {
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
margin-bottom: 0; /* Override default `<label>` margin */
line-height: 1.5;
cursor: text; /* Match the input under the label */
border: 1px solid transparent;
border-radius: 0.25em;
transition: all 0.1s ease-in-out;
}
.form-label-group input:not(:placeholder-shown) {
padding: 17px 20px 0;
}
.form-label-group input:not(:placeholder-shown) ~ label {
padding: 7px 20px;
font-size: 0.72em;
opacity: .75;
}
.search-event
.form-label-group > label {
color: white;
}
label {
font-size: 14px;
}
select option {
background:#EFEFF4;
color: #00044A;
}

90
src/EventHub.Web.Theme/wwwroot/themes/eventhub/layout.css

@ -1,90 +0,0 @@
#main-navbar-tools a.dropdown-toggle {
text-decoration: none;
color: #fff;
}
.navbar .dropdown-submenu {
position: relative;
}
.navbar .dropdown-menu {
margin: 0;
padding: 0;
}
.navbar .dropdown-menu a {
font-size: .9em;
padding: 10px 15px;
display: block;
min-width: 210px;
text-align: left;
border-radius: 0.25rem;
min-height: 44px;
}
.navbar .dropdown-submenu a::after {
transform: rotate(-90deg);
position: absolute;
right: 16px;
top: 18px;
}
.navbar .dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
}
.card-header .btn {
padding: 2px 6px;
}
.card-header h5 {
margin: 0;
}
.container > .card {
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
}
@media screen and (min-width: 768px) {
.navbar .dropdown:hover > .dropdown-menu {
display: block;
}
.navbar .dropdown-submenu:hover > .dropdown-menu {
display: block;
}
}
.input-validation-error {
border-color: #dc3545;
}
.field-validation-error {
font-size: 0.8em;
}
.dataTables_scrollBody {
min-height: 248px;
}
div.dataTables_wrapper div.dataTables_info {
padding-top: 11px;
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_length label {
padding-top: 10px;
margin-bottom: 0;
}
.rtl .dropdown-menu-right {
right: auto;
left: 0;
}
.rtl .dropdown-menu-right a {
text-align: right;
}
.rtl .navbar .dropdown-menu a {
text-align: right;
}
.rtl .navbar .dropdown-submenu .dropdown-menu {
top: 0;
left: auto;
right: 100%;
}

16
src/EventHub.Web.Theme/wwwroot/themes/eventhub/layout.js

@ -1,16 +0,0 @@
$(function () {
$('.dropdown-menu a.dropdown-toggle').on('click', function (e) {
if (!$(this).next().hasClass('show')) {
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
}
var $subMenu = $(this).next(".dropdown-menu");
$subMenu.toggleClass('show');
$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) {
$('.dropdown-submenu .show').removeClass("show");
});
return false;
});
});

130
src/EventHub.Web.Theme/wwwroot/themes/eventhub/owl-edit.css

@ -0,0 +1,130 @@
.main-slider
.owl-theme .owl-nav {
margin-top: 0 !important;
position: absolute;
top: 45%;
left: 0;
width: 100%;
}
.main-slider .owl-carousel .owl-nav button.owl-prev,
.main-slider .owl-carousel .owl-nav button.owl-next {
width: 40px;
height: 40px;
background: rgb(255 255 255 / 22%);
transition: background-color .3s ease;
position: absolute;
display: inline-block;
left: 8%;
border-radius: 40px;
overflow: hidden;
}
.main-slider .owl-carousel .owl-nav button.owl-next {
right: 8%;
left: auto;
}
.main-slider .owl-carousel .owl-nav button.owl-prev:hover,
.main-slider .owl-carousel .owl-nav button.owl-next:hover {
background: rgb(255 255 255 / 35%);
}
.main-slider .owl-carousel .owl-nav button span {
font-size: 40px;
color: transparent;
line-height: 37px;
}
.owl-theme .owl-dots .owl-dot span:focus,
.owl-carousel .owl-nav button:focus {
outline: none;
}
.main-slider .owl-carousel .owl-nav button.owl-next::before {
content: "";
position: absolute;
width: 40px;
height: 40px;
top:0;
left: 0;
background-image: url(../../../../assets/slider-right.svg);
background-position: center;
background-repeat: no-repeat;
}
.main-slider .owl-carousel .owl-nav button.owl-prev::before {
content: "";
position: absolute;
width: 40px;
height: 40px;
top:0;
left: 0;
background-image: url(../../../../assets/slider-left.svg);
background-position: center;
background-repeat: no-repeat;
}
.card-slider .owl-carousel .owl-nav button.owl-prev,
.card-slider .owl-carousel .owl-nav button.owl-next {
width: 9px;
height: 15px;
background: rgb(255 255 255 / 22%);
transition: background-color .3s ease;
display: inline-block;
overflow: hidden;
position: relative;
color: transparent;
}
.card-slider .owl-carousel .owl-nav button.owl-next::before {
content: "";
position: absolute;
width: 9px;
height: 15px;
top:0;
left: 0;
background-image: url(../../../../assets/owl-2-right.svg);
background-position: center;
background-repeat: no-repeat;
}
.card-slider .owl-carousel .owl-nav button.owl-prev::before {
content: "";
position: absolute;
width: 9px;
height: 15px;
top:0;
left: 0;
background-image: url(../../../../assets/owl-2-left.svg);
background-position: center;
background-repeat: no-repeat;
}
.card-slider .owl-theme .owl-dots .owl-dot span {
background: rgba(108, 127, 147, 0.2);
margin: 5px;
}
.card-slider .owl-theme .owl-dots .owl-dot.active span,
.card-slider .owl-theme .owl-dots .owl-dot:hover span {
background: #00044A;
}
.card-slider .owl-theme .owl-dots {
text-align: center;
position: absolute;
top: -50px;
right: 20px;
width: 100px;
}
.card-slider .owl-theme .owl-nav {
margin-top: 0px;
position: absolute;
text-align: center;
top: -52px;
right: 0;
width: 140px;
}
.card-slider .owl-prev {
float: left;
}
.card-slider .owl-next {
float: right;
}

832
src/EventHub.Web.Theme/wwwroot/themes/eventhub/style.css

@ -0,0 +1,832 @@
body {
font-family: 'Poppins', sans-serif;
line-height: 1.5;
background-color: #F8F9FA;
color: #6B7E92;
font-size: 14px;
font-weight: 400;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
margin-bottom: .5rem;
font-weight: 700;
line-height: 1.2;
color: #00044A;
}
.h1, h1 {
font-size: 36px;
}
.h2, h2 {
font-size: 30px;
color: #00044A;
margin-top: .5rem;
}
.h3, h3 {
font-size: 24px;
margin-bottom: 1rem;
}
.h4, h4 {
font-size: 18px;
font-weight: 600;
}
p.lead {
font-size: 14px;
font-weight: 500;
color: #00044A;
}
p {
color: #6B7E92;
font-size: 14px;
font-weight: 400;
}
/*NAVBAR*/
.navbar {
box-shadow: 0 5px 10px rgba(0, 4, 74, 0.05) !important;
}
.navbar .nav-link {
font-size: 14px;
color: #00044A !important;
}
.navbar .nav-item .btn {
margin: -3px 0;
}
.navbar-brand {
color: #00044A !important;
}
.navbar .nav-link.event-link {
color: #65D6A0 !important;
font-weight: 600;
}
.navbar-light.navbar {
background-color: #fff !important;
}
.navbar-expand-lg {
min-height: 74px;
padding: 17px;
}
.user-avatar {
width: 40px;
height: 10px;
display: inline-block;
position: relative;
}
.nav-avatar {
position: absolute;
top: -14px;
left: 0;
}
@media (min-width: 992px) {
.navbar-expand-lg .navbar-nav .nav-link {
padding-right: 4px;
padding-left: 4px;
margin-right: 12px;
margin-left: 12px;
transition: color 0.3s ease;
}
.active .nav-link {
background-image: url(../../../../assets/underline.svg);
background-repeat: no-repeat;
background-size: inherit;
background-position: center 28px;
color: #df2751 !important;
}
.nav-link:hover {
color: #df2751 !important;
}
}
.btn {
border-radius: 10px !important;
font-weight: 600;
font-size: 14px;
padding: 10px 20px;
}
.btn-primary {
background-color: #E8345D !important;
border-color: #E8345D !important;
}
.btn-primary:hover {
background-color: #df2751 !important;
border-color: #df2751 !important;
}
.btn-secondary {
background-color: rgba(221, 203, 247,.4) !important;
border: 0;
color: #2E1777;
}
.btn-secondary:hover {
background-color: rgba(221, 203, 247,.6) !important;
border: 0;
color: #2E1777;
}
.btn-success {
background-color: #65D6A0 !important;
border-color: #65D6A0 !important;
}
.btn-success:hover {
background-color: #4dbb86 !important;
border-color: #4dbb86 !important;
}
.btn-link {
font-weight: 600;
color: #00044A;
font-size: 12px;
}
.btn-link img{
width: 6px !important;
display: inline-block !important;
}
.btn-link:hover {
text-decoration: none;
color: #df2751;
}
.btn-link.btn-lg {
color: #E8345D;
font-weight: 700;
font-size: 16px;
}
.current-language-name {display: none;}
@media (min-width: 1200px){
.container, .container-lg, .container-md, .container-sm, .container-xl {
max-width: 996px;
}
.navbar .container {
max-width: 1200px;
}
}
@media (max-width: 768px){
.current-language-name {display: inline-block;}
.main-slider .owl-nav {display: none;}
}
.card {
border: 1px solid rgba(107, 126, 146, 0.09);
border-radius: 10px;
margin-bottom: 34px;
overflow: hidden;
}
.card-img-top {
width: 100%;
}
.card-img-left {
position: inherit;
}
.event-small-image {
width: 60px;
border-radius: 10px;
}
.event-info h5 {
font-size: 18px;
font-weight: 700;
color: #00044A;
margin-bottom: 5px !important;
}
.event-info small {
font-size: 10px;
font-weight: 500;
color: #6F32E2;
margin-bottom: 15px;
display: block;
}
.event-info {
height: 154px;
margin-bottom: 15px;
overflow: hidden;
}
.online-event .event-info {
height: 135px;
margin-bottom: 19px;
overflow: hidden;
}
.event-info p {
font-size: 13px;
font-weight: 400;
color: #6B7E92;
}
.event-date small{
color: #E8345D;
font-size: 10px;
font-weight: 500;
display: block;
}
.event-date span{
color: #00044A;
font-size: 22px;
font-weight: 700;
display: block;
line-height: 1.2;
}
.bg-primary {
background: #00044A !important;
}
.form-control, .form-select {
display: block;
width: 100%;
height: calc(1.5em + .75rem + 2px);
height: 52px;
padding: .375rem 1rem;
font-size: 14px !important;
font-weight: 500;
line-height: 1.5;
color: #00044A;
background-color: #EFEFF4;
border: 1px solid #EFEFF4;
border-radius: 10px;
}
.search-event .form-control, .search-event .form-select {
color: #ffffff;
background-color: rgba(255,255,255,.2);
border: 1px solid rgba(255,255,255,.4);
}
.search-event .btn-group-lg > .search-event .btn, .search-event .btn-lg {
height: 52px;
padding: 14px 20px;
}
.border-left {
border-color: #00044A !important;
}
.slider-container {
height: 530px;
background-size: cover;
padding: 0 20px;
}
.slider-container h1 {
font-size: 60px;
color: white;
font-weight: 700;
}
.slider-container p.lead {
font-size: 20px;
color: white;
}
.search-event {
position: relative;
top:-59px;
z-index: 99;
}
.search-event .card-body,
.profile-content .card-body{
padding: 32px;
}
.profile-content .form-control ,
.profile-content .form-select {
border: 1px solid rgba(107, 126, 146, 0.20);
background-color: white;
margin-bottom: 30px;
color: #6B7E92;
}
.profile-content label,
.profile-content label {
color: #6B7E92;
}
.form-row>.col, .form-row>[class*=col-] {
padding-right: 10px;
padding-left: 10px;
}
.form-select{
background-color: #EFEFF4;
border: 1px solid #EFEFF4;
background-image: url("../../../../assets/select-arrow.svg");
background-position: right 20px center;
background-repeat: no-repeat;
background-size: 10px;
padding: 10px 30px 10px 20px;
outline: none;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
}
.form-select::-ms-expand {
display: none;
}
@media (min-width: 768px){
.filter-select select {
min-width: 140px;
}
}
@media (max-width: 768px){
.filter-select select {
width: 100%;
}
}
.dropdown-toggle::after {
display: inline-block;
margin-left: .255em;
vertical-align: .255em;
content: "";
border: 0;
width: 6px;
height: 4px;
background: url(../../../../assets/dropdown-arrow.svg) center center no-repeat;
background-size: contain;
top: 2px;
position: relative;
}
.dropdown-menu {
border-radius: 10px;
min-width: 130px;
border-color: rgba(142, 160, 178, 0.2);
box-shadow: 0 0 8px rgba(0, 4, 74, 0.1);
}
.dropdown-menu::before {
position: absolute;
top: -7px;
left: 10px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid rgba(142, 160, 178, 0.3);
border-left: 7px solid transparent;
border-bottom-color: rgba(142, 160, 178, 0.3);
content: '';
}
.dropdown-menu::after {
position: absolute;
top: -6px;
left: 11px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
border-left: 6px solid transparent;
content: '';
}
.dropdown-menu.dropdown-menu-right::before {
left: auto;
right: 10px;
}
.dropdown-menu.dropdown-menu-right::after {
left: auto;
right: 11px;
}
.dropdown-item {
font-size: 13px;
padding: .5rem 1.5rem;
color: #00044A;
}
.dropdown-divider {
margin: 5px 24px;
border-top: 1px solid rgba(142, 160, 178, 0.2);
}
.dropdown-icon {
width: 15px;
height: 15px;
margin-right: 4px;
}
footer {
background: #00044A;
padding: 3.5em 0 2em;
}
.footer-logo {
color: white;
font-size: 20px;
font-weight: 600;
margin-bottom: 32px;
margin-top: 16px;
display: block;
}
.footer-logo:hover {
text-decoration: none;
color: white;
}
footer h5{
color: white;
font-size: 16px;
font-weight: 500;
margin-top: 24px;
margin-bottom: 16px;
}
footer .footer-links a{
color: white;
opacity: .65;
transition: opacity .25s;
font-size: 14px;
margin: 16px 16px 16px 0;
}
footer .footer-links a:hover{
text-decoration: none;
color: white;
opacity: 1;
}
.footer-bottom {
margin-top: 0;
padding: 2em 0;
border-top: 1px solid rgba(255,255,255,.2);
}
.footer-bottom span,.footer-bottom a {
color: rgba(255,255,255,.5);
font-size: 12px;
}
.footer-bottom a:hover {
text-decoration: none;
transition: color .25s;
color: white;
}
.flag-icon {
border-radius: 4px;
}
.inner-banner {
text-align: center;
height: 250px;
background: url(../../../../assets/inner-banner.png) center center no-repeat;
background-size: cover;
margin-bottom: 30px;
}
.inner-banner.inner-banner-2 {
background-image: url(../../../../assets/inner-banner-2.png);
}
.inner-banner h1 {
color: white;
font-size: 30px;
font-weight: 600;
}
.inner-banner nav.breadcrumb-container {
display: inline-block;
}
nav.breadcrumb-container .breadcrumb {
background: none;
margin: 0;
font-size: 12px;
opacity: .7;
}
nav.breadcrumb-container .breadcrumb a,nav.breadcrumb-container .breadcrumb li{
color: white;
}
.breadcrumb-item+.breadcrumb-item::before {
padding-right: 1.25rem;
padding-left: .75rem;
color: white;
content: ">";
}
.list-style {
background: #efeff4;
border-radius: 10px;
padding: 8px;
width: 100%;
display: flex;
}
.list-style a{
background: #efeff4;
color: #00044A;
opacity: .6;
padding: 8px 15px;
display: block;
border-radius: 8px;
height: 36px;
font-size: 14px;
transition: opacity .2s, background-color .2s;
}
.list-style a img{ position: relative;
top: -1px;
margin-right: 4px;
}
.list-style a.selected {
background: #fff;
box-shadow: 0 0 10px rgba(0, 4, 74, 0.15);
opacity:1;
z-index: 4;
}
.list-style a:hover{
opacity:1;
text-decoration: none;
}
@media (max-width: 768px){
.list-style {
margin-top: 15px;
}
.list-style a{
width: 50%;
text-align: center;
}
footer {
text-align: center;
}
footer .footer-links a{
margin: 16px;
}
}
.detail-image img{
width: 100%;
border-radius: 10px;
}
.detail-page h1 {
font-size: 30px;
color:#00044A;
}
.detail-pin {
color:#6F32E2;
font-size: 14px;
}
.detail-page p {
color: #6B7E92;
font-size: 16px;
}
p .text-primary {
color: #00044A !important;
font-weight: 500;
}
.org-avatar {
margin: 5px 10px 5px 0;
width: 40px;
height: 40px;
}
.list-span {
line-height: 168px; }
.list-span span {
font-size: 1em;
color: #fff;
opacity: 0.5;
line-height: 1;
font-weight: 100;
text-shadow: 0 0 35px rgba(0, 0, 0, 0.5); }
@media screen and (max-width: 767px) {
.list-span {
width: 100%;
height: 150px;
line-height: 150px;
margin-bottom: 1em; }
.list-span span {
font-size: 1em;
line-height: 150px; } }
.carousel-list-span {
line-height: 215px; }
.carousel-list-span span {
font-size: 1em;
color: #fff;
opacity: 0.5;
line-height: 1;
font-weight: 100;
text-shadow: 0 0 35px rgba(0, 0, 0, 0.5); }
@media screen and (max-width: 767px) {
.carousel-list-span {
width: 100%;
height: 150px;
line-height: 150px;
margin-bottom: 1em; }
.carousel-list-spann span {
font-size: 1em;
line-height: 150px; } }
.detail-span {
line-height: 112px; }
.detail-span span {
font-size: 1em;
color: #fff;
opacity: 0.5;
line-height: 1;
font-weight: 100;
text-shadow: 0 0 35px rgba(0, 0, 0, 0.5); }
@media screen and (max-width: 767px) {
.detail-span {
width: 100%;
height: 150px;
line-height: 150px;
margin-bottom: 1em; }
.detail-span span {
font-size: 1em;
line-height: 150px; } }
.detail-head {
font-weight: normal;
font-size: 18px;
}
.map-container {
border-radius: 10px;
overflow: hidden;
}
.tag-container a {
display: inline-block;
background: #EFEFF4;
color: #00044a;
padding: 6px 18px;
margin: 10px 10px 10px 0;
font-size: 14px;
border-radius: 10px;
}
.tag-container a:hover {
text-decoration: none;
background: #dddde7;
}
.share-container a {
margin: 10px 10px 10px 0;
display: inline-block;
}
/* detail pages */
@media screen and (max-width: 768px) {
.profile-nav {
display: block;
text-align: center;
}
.nav-tabs.profile-nav .nav-item .nav-link {
font-size: 14px !important;
}
}
.nav-tabs.profile-nav .nav-item .nav-link {
border: 0;
color: #00044A;
font-size: 16px;
border-bottom: 2px solid transparent;
}
.nav-tabs.profile-nav .nav-item.show .nav-link,
.nav-tabs.profile-nav .nav-link.active {
color: #00044A;
background: none;
border:0;
border-bottom: 2px solid #00044A;
font-weight: 600;
}
.nav-tabs.profile-nav .nav-item .nav-link:hover {
border: 0;
color: #00044A !important;
border-bottom: 2px solid #00044a28;
}
.nav-tabs.profile-nav .nav-item.show .nav-link.active:hover {
border-bottom: 2px solid #00044A;
}
.nav-tabs.profile-nav {
border:0;
border-bottom: 2px solid transparent;
}
div.checkbox.switcher label, div.radio.switcher label {
padding: 0;
}
div.checkbox.switcher label *, div.radio.switcher label * {
vertical-align: middle;
}
div.checkbox.switcher label input, div.radio.switcher label input {
display: none;
}
div.checkbox.switcher label input + span, div.radio.switcher label input + span {
position: relative;
display: inline-block;
margin-right: 10px;
width: 56px;
height: 30px;
background: rgb(107 126 146 / 20%);
border: 3px solid #e1e5e9;
border-radius: 50px;
transition: all 0.3s ease-in-out;
}
div.checkbox.switcher label input + span small, div.radio.switcher label input + span small {
position: absolute;
display: block;
width: 50%;
height: 100%;
background: #fff;
border-radius: 50%;
transition: all 0.3s ease-in-out;
left: 0;
}
div.checkbox.switcher label input:checked + span, div.radio.switcher label input:checked + span {
background: #E8345D ;
border-color: #E8345D ;
}
div.checkbox.switcher label input:checked + span small, div.radio.switcher label input:checked + span small {
left: 50%;
}
.past-events {
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
filter: grayscale(100%);
opacity: .6;
}
/* image upload */
#upload {
opacity: 0;
}
.image-area {
border: 2px dashed rgb(218 224 229);
padding: 1em;
position: relative;
border-radius: 10px;
min-height: 160px;
text-align: center;
margin-bottom: 30px;
}
.image-area::before {
content: 'Uploaded image result';
color: rgb(218 224 229);
font-weight: bold;
text-transform: uppercase;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 0.8rem;
z-index: 1;
}
.image-area img {
z-index: 2;
position: relative;
}
.badge {
padding-left: .8em;
padding-right: .8em;
border-radius: 30px;
}
.badge.badge-primary {
color: #fff;
background-color: #df2751;
}
.member-container {
margin-bottom: 30px;
}
.member-container span{
font-size: 13px;
}
.member-container .member-name {
font-size: 16px;
font-weight: 600;
display: block;
color: #00044A;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.modal-backdrop {
background-color: #354052;
}
.modal-content {
border: 0;
border-radius: 10px;
}
.modal-title {
font-size: 20px;
line-height: 1.75;
}
/*This area was made to be able to navigate between pages. It should be removed from the project*/
.page-links {
position: fixed;
width: 180px;
background: #00044a;
left: -150px;
top: 50%;
margin-top: -100px;
padding: 1em;
border-radius: 0 10px 10px 0;
z-index: 1000;
opacity: .5;
transition: opacity .3s, left .2s;
}
.page-links:hover {
opacity: .95;
left: 0px;
}
.page-links a{
display: block;
font-size: 12px;
color: #cbcdf1;
padding: 2px 0;
}
.page-links small{
font-size: 10px;
color: #999cdf;
}
/*This area was made to be able to navigate between pages. It should be removed from the project*/

46
src/EventHub.Web/Controllers/EventController.cs

@ -1,11 +1,9 @@
using System.IO;
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Events;
using EventHub.Web.Pages.Events;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using EditPageModel = EventHub.Web.Pages.Events.EditPageModel;
namespace EventHub.Web.Controllers
{
@ -19,31 +17,31 @@ namespace EventHub.Web.Controllers
_eventAppService = eventAppService;
}
[Authorize]
[HttpPost]
[Route("update-timing")]
public async Task UpdateEventTiming(EditPageModel.EditEventTimingViewModel input)
[HttpGet]
[Route("get-list")]
public async Task<IActionResult> GetList(EventListFilterDto input)
{
await _eventAppService.UpdateEventTimingAsync(input.Id, new UpdateEventTimingDto { StartTime = input.StartTime, EndTime = input.EndTime });
ViewData.Model = (await _eventAppService.GetListAsync(input)).Items.ToList();
return new PartialViewResult
{
ViewName = "~/Pages/Events/Components/EventsArea/_eventListSection.cshtml",
ViewData = ViewData
};
}
[HttpPost]
[Authorize]
[Route("save-cover-image")]
public async Task SaveCoverImage([FromForm] EventCoverImageInput input)
[HttpGet]
[Route("cover-picture-source/{eventId}")]
public async Task<IActionResult> GetArticleCoverImageAsync(Guid eventId)
{
var coverImageContent = new byte[] {};
if (input.CoverImageFile.Length > 0)
var coverImageContent = await _eventAppService.GetCoverImageAsync(eventId);
if (coverImageContent == null)
{
using (var memoryStream = new MemoryStream())
{
await input.CoverImageFile.CopyToAsync(memoryStream);
coverImageContent = memoryStream.ToArray();
}
await _eventAppService.SaveCoverImageAsync(input.EventId, coverImageContent);
return NotFound();
}
}
return File(coverImageContent, "image/jpeg");
}
}
}

26
src/EventHub.Web/Controllers/OrganizationController.cs

@ -1,8 +1,6 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Organizations;
using EventHub.Web.Pages.Organizations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
@ -18,23 +16,17 @@ namespace EventHub.Web.Controllers
_organizationAppService = organizationAppService;
}
[HttpPost]
[Authorize]
[Route("save-profile-picture")]
public async Task SaveProfilePicture([FromForm] OrganizationProfilePictureInput input)
[HttpGet]
[Route("get-list")]
public async Task<IActionResult> GetList(OrganizationListFilterDto input)
{
var profilePictureContent = new byte[] {};
ViewData.Model = (await _organizationAppService.GetListAsync(input)).Items.ToList();
if (input.ProfilePictureFile.Length > 0)
return new PartialViewResult
{
using (var memoryStream = new MemoryStream())
{
await input.ProfilePictureFile.CopyToAsync(memoryStream);
profilePictureContent = memoryStream.ToArray();
}
await _organizationAppService.SaveProfilePictureAsync(input.OrganizationId, profilePictureContent);
}
ViewName = "~/Pages/Organizations/Components/OrganizationsArea/_organizationListSection.cshtml",
ViewData = ViewData
};
}
}
}

14
src/EventHub.Web/Controllers/OrganizationMembershipController.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Organizations.Memberships;
using EventHub.Web.Pages.Organizations.Components.JoinArea;
@ -16,6 +17,19 @@ namespace EventHub.Web.Controllers
_organizationMembershipAppService = organizationMembershipAppService;
}
[HttpGet]
[Route("get-list")]
public async Task<IActionResult> GetList(OrganizationMemberListFilterDto input)
{
ViewData.Model = (await _organizationMembershipAppService.GetMembersAsync(input)).Items.ToList();
return new PartialViewResult
{
ViewName = "~/Pages/Organizations/Components/MembersArea/_memberListSection.cshtml",
ViewData = ViewData
};
}
[HttpPost]
public async Task<NoContentResult> Join(Guid organizationId)
{

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

@ -19,11 +19,23 @@ namespace EventHub.Web.Controllers
}
[HttpGet]
public IActionResult OrganizationMembersArea(Guid organizationId)
public IActionResult OrganizationMembersArea(
Guid organizationId,
int? skipCount,
int maxResultCount,
bool isPagination,
bool isMoreDetail)
{
return ViewComponent(
typeof(MembersAreaViewComponent),
new {organizationId}
new
{
organizationId,
skipCount,
maxResultCount,
isPagination,
isMoreDetail
}
);
}

1
src/EventHub.Web/EventHubWebAutoMapperProfile.cs

@ -18,7 +18,6 @@ namespace EventHub.Web
CreateMap<EditOrganizationViewModel, UpdateOrganizationDto>();
CreateMap<EventDetailDto, EditPageModel.EditEventViewModel>();
CreateMap<EditPageModel.EditEventViewModel, UpdateEventDto>();
CreateMap<EventDetailDto, EditPageModel.EditEventTimingViewModel>();
}
}
}

13
src/EventHub.Web/EventHubWebModule.cs

@ -11,6 +11,7 @@ using EventHub.Localization;
using EventHub.Web.Menus;
using EventHub.Web.Theme;
using EventHub.Web.Theme.Bundling;
using Microsoft.AspNetCore.Mvc.RazorPages;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
@ -78,6 +79,7 @@ namespace EventHub.Web
ConfigureVirtualFileSystem(hostingEnvironment);
ConfigureNavigationServices(configuration);
ConfigureSwaggerServices(context.Services);
ConfigureRazorPageOptions();
}
private void ConfigureBundles()
@ -109,6 +111,17 @@ namespace EventHub.Web
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
});
}
private void ConfigureRazorPageOptions()
{
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizePage("/Events/New");
options.Conventions.AuthorizePage("/Events/Edit");
options.Conventions.AuthorizePage("/Organizations/New");
options.Conventions.AuthorizePage("/Organizations/Edit");
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{

31
src/EventHub.Web/Helpers/CoverImageHelper.cs

@ -0,0 +1,31 @@
using System;
using System.Linq;
using System.Text;
using Volo.Abp;
namespace EventHub.Web.Helpers
{
public class CoverImageHelper
{
private static readonly string[] ImageColors =
{
"linear-gradient(135deg, #41003d 0%, #a10097 100%)",
"linear-gradient(135deg, #163e4b 0%, #297791 100%)",
"linear-gradient(135deg, #660040 0%, #aa006b 100%)",
"linear-gradient(135deg, #240d88 0%, #571fff 100%)",
};
public static string GetRandomColor(string articleTitle)
{
long total = articleTitle.Truncate(32).ToCharArray().Sum(c => c);
return ImageColors[total % ImageColors.Length];
}
public static string GetContentOfImage(string content)
{
content = Check.NotNullOrWhiteSpace(content, nameof(content));
return content.ToUpper();
}
}
}

29
src/EventHub.Web/Pages/Events/Components/AttendeesArea/Default.cshtml

@ -1,14 +1,17 @@
@model EventHub.Web.Pages.Events.Components.AttendeesArea.AttendeesAreaViewComponent.AttendeesAreaViewComponentModel
<abp-card class="mb-3" data-event-id="@Model.EventId">
<abp-card-body>
<abp-card-title>Attendees (@Model.TotalCount)</abp-card-title>
<abp-card-text>
<ul id="EventAttendeeList">
@foreach (var attendee in Model.Attendees)
{
<li class="border p-2 mb-2"><i class="fas fa-user"></i> @Model.GetAttendeeName(attendee)</li>
}
</ul>
</abp-card-text>
</abp-card-body>
</abp-card>
<h5 class="detail-head mt-5 font-weight-bold" data-event-id="@Model.EventId">Attendees (@Model.TotalCount)</h5>
@if (Model.TotalCount > 0)
{
<div>
@foreach (var attendee in Model.Attendees)
{
<a href="/users/@attendee.UserName">
<img gravatar-email="@attendee.Email" default-image="Wavatar" gravatar-size="40" class="org-avatar rounded-circle" data-toggle="tooltip" title="@attendee.UserName" />
</a>
}
</div>
}
else
{
<p>There is no attendee</p>
}

11
src/EventHub.Web/Pages/Events/Components/AttendeesArea/attendees-area.css

@ -1,10 +1 @@
#EventAttendeeList
{
list-style: none;
padding: 0;
}
#EventAttendeeList li
{
}


36
src/EventHub.Web/Pages/Events/Components/EventsArea/Default.cshtml

@ -0,0 +1,36 @@
@model EventHub.Web.Pages.Events.Components.EventsArea.EventsAreaViewComponent.ListAreaViewComponentModel
@if (Model.Events != null && Model.Events.Count > 0)
{
<div id="EventList" class="row" data-hash-code="@Model.GetHashCode()" data-total-count="@Model.TotalCount" data-skip-count="@Model.SkipCount" data-max-result-count="@Model.MaxResultCount">
<partial name="~/Pages/Events/Components/EventsArea/_eventListSection.cshtml" model="@Model.Events"/>
</div>
@if (Model.IsPagination && Model.TotalCount > Model.MaxResultCount && Model.TotalCount > Model.Events.Count)
{
<div id="load-more-section-@Model.GetHashCode()" class="row">
<div class="col text-center">
<button
id="LoadMoreButton-@Model.GetHashCode()"
class="btn btn-secondary btn-lg"
data-url="@Url.Action("GetList","Event",
new {
minDate = Model.MinDate,
maxDate = Model.MaxDate,
organizationId = Model.OrganizationId,
registeredUserId = Model.RegisteredUserId,
isOnline = Model.IsOnline,
language = Model.Language,
countryId = Model.CountryId,
maxResultCount = Model.MaxResultCount
})">
Load More
</button>
</div>
</div>
}
}
else
{
<p>There is no Event</p>
}

97
src/EventHub.Web/Pages/Events/Components/EventsArea/EventsAreaViewComponent.cs

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EventHub.Events;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
namespace EventHub.Web.Pages.Events.Components.EventsArea
{
[Widget(
AutoInitialize = true,
ScriptFiles = new[] {"/Pages/Events/Components/EventsArea/events-area.js"})]
public class EventsAreaViewComponent : AbpViewComponent
{
private readonly IEventAppService _eventAppService;
public EventsAreaViewComponent(IEventAppService eventAppService)
{
_eventAppService = eventAppService;
}
public async Task<IViewComponentResult> InvokeAsync(
Guid? organizationId,
Guid? registeredUserId,
DateTime? minDate,
DateTime? maxDate,
bool? isOnline,
string language,
Guid? countryId,
int? skipCount,
int maxResultCount = 15,
bool isPagination = true)
{
var result = await _eventAppService.GetListAsync(
new EventListFilterDto
{
OrganizationId = organizationId,
RegisteredUserId = registeredUserId,
MinDate = minDate,
MaxDate = maxDate,
IsOnline = isOnline,
Language = language,
CountryId = countryId,
SkipCount = skipCount.GetValueOrDefault(),
MaxResultCount = maxResultCount
}
);
return View(
"~/Pages/Events/Components/EventsArea/Default.cshtml",
new ListAreaViewComponentModel
{
Events = result.Items,
TotalCount = result.TotalCount,
OrganizationId = organizationId,
RegisteredUserId = registeredUserId,
MinDate = minDate,
MaxDate = maxDate,
IsOnline = isOnline,
Language = language,
CountryId = countryId,
SkipCount = skipCount.GetValueOrDefault(),
MaxResultCount = maxResultCount,
IsPagination = isPagination
}
);
}
public class ListAreaViewComponentModel
{
public IReadOnlyList<EventInListDto> Events { get; set; }
public long TotalCount { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? RegisteredUserId { get; set; }
public DateTime? MinDate { get; set; }
public DateTime? MaxDate { get; set; }
public bool? IsOnline { get; set; }
public string Language { get; set; }
public Guid? CountryId { get; set; }
public int SkipCount { get; set; }
public int MaxResultCount { get; set; }
public bool IsPagination { get; set; }
}
}
}

42
src/EventHub.Web/Pages/Events/Components/EventsArea/_eventListSection.cshtml

@ -0,0 +1,42 @@
@using System.Globalization
@using EventHub.Web.Helpers
@using EventHub.Web.Pages.Events
@model List<EventHub.Events.EventInListDto>
@foreach (var eventDto in Model)
{
<div class="col-lg-4 col-md-6 event">
<div class="card">
@if (eventDto.CoverImageContent is null)
{
<div class="rounded list-span text-center" style="background: @(CoverImageHelper.GetRandomColor(eventDto.Title))">
<span>@CoverImageHelper.GetContentOfImage(eventDto.Title).TruncateWithPostfix(30)</span>
</div>
}
else
{
<img abp-card-image="Top" style="max-height: 400px; min-height: 160px;" src="@($"data:image/png;base64,{Convert.ToBase64String(eventDto.CoverImageContent)}")" alt="@eventDto.Title"/>
}
<div class="card-body">
<div class="event-container">
<div class="form-row">
<div class="col-3">
<div class="event-date text-center">
<small>@eventDto.StartTime.ToString("MMM")</small>
<span>@eventDto.StartTime.Day</span>
</div>
</div>
<div class="col-9">
<div class="event-info">
<h5>@eventDto.Title</h5>
<small>@eventDto.StartTime.ToString("hh tt", CultureInfo.InvariantCulture) - @eventDto.EndTime.ToString("hh tt", CultureInfo.InvariantCulture) | @EventDateHelper.GetLocationInfo(eventDto)</small>
<p>@eventDto.Description</p>
</div>
<a href="@Url.Page("/Events/Detail", new {url = eventDto.Url})" class="btn btn-link p-0">Learn More <img src="/assets/more-btn.svg"></a>
</div>
</div>
</div>
</div>
</div>
</div>
}

36
src/EventHub.Web/Pages/Events/Components/EventsArea/events-area.js

@ -0,0 +1,36 @@
(function () {
abp.widgets.EventsArea = function ($wrapper) {
var totalCount = Number($wrapper.find('[data-total-count]').attr('data-total-count'))
var skipCount = Number($wrapper.find('[data-skip-count]').attr('data-skip-count'))
var maxResultCount = Number($wrapper.find('[data-max-result-count]').attr('data-max-result-count'))
var hashCode = Number($wrapper.find('[data-hash-code]').attr('data-hash-code'))
skipCount += maxResultCount;
function init() {
var loadMoreButton = $wrapper.find('#LoadMoreButton-' + hashCode);
loadMoreButton.click(function (e) {
e.preventDefault();
loadMoreButton.buttonBusy(true);
abp.ajax({
type: 'GET',
dataType: 'html',
contentType: 'text/html; charset=utf-8',
url: (loadMoreButton.attr('data-url') + '&skipCount=' + skipCount)
}).then(function (response) {
var eventList = $wrapper.find('#EventList')
eventList.append(response);
skipCount += maxResultCount;
}).always(function () {
if (skipCount >= totalCount) {
$('#load-more-section-' + hashCode).hide();
}
loadMoreButton.buttonBusy(false);
});
});
}
return {
init: init
};
};
})();

57
src/EventHub.Web/Pages/Events/Components/LocationArea/Default.cshtml

@ -1,45 +1,42 @@
@using EventHub.Localization
@using EventHub.Web.Pages.Events
@using Microsoft.AspNetCore.Mvc.Localization
@inject IHtmlLocalizer<EventHubResource> L
@model EventHub.Web.Pages.Events.Components.LocationArea.LocationAreaViewComponent.LocationAreaViewComponentModel
<abp-card class="mb-3" data-event-id="@Model.EventId">
<abp-card-body>
<abp-card-title>@L["Location"] <i class="fas fa-map-marker-alt"></i></abp-card-title>
@if (Model.IsRegistered)
<div data-event-id="@Model.EventId">
@if (Model.IsRegistered)
{
if (Model.IsOnline)
{
if (Model.IsOnline)
if (Model.OnlineLink != null)
{
if (Model.OnlineLink != null)
{
<a href="@Model.OnlineLink">@L["GoToEventAddress"]</a>
}
else
{
<p>@L["LocationHasNotSpecifiedYet", "URL"]</p>
}
}else
<a class="detail-pin" href="@Model.OnlineLink"><img src="/assets/pin.svg"> @L["GoToOnlineAddress"]</a>
}
else
{
if (Model.Country != null && Model.City != null)
{
<p>@Model.Country/@Model.City</p>
}
else
{
<p>@L["LocationHasNotSpecifiedYet", "location"]</p>
}
<span>@L["LocationHasNotSpecifiedYet", "URL"]</span>
}
}
else
}else
{
if (Model.IsOnline)
if (Model.Country != null && Model.City != null)
{
<p>@L["AttendeesCanSeeEventLocation", "URL"]</p>
<span class="detail-pin"><img src="/assets/pin.svg"> @EventDateHelper.GetLocationInfo(Model.IsOnline, Model.City, Model.Country, ", ")</span>
}
else
{
<p>@L["AttendeesCanSeeEventLocation", "location"]</p>
<span class="detail-pin">@L["LocationHasNotSpecifiedYet", "location"]</span>
}
}
</abp-card-body>
</abp-card>
}
else
{
if (Model.IsOnline)
{
<span class="detail-pin">@L["AttendeesCanSeeEventLocation", "URL"]</span>
}
else
{
<span class="detail-pin">@L["AttendeesCanSeeEventLocation", "location"]</span>
}
}
</div>

34
src/EventHub.Web/Pages/Events/Components/RegistrationArea/Default.cshtml

@ -2,33 +2,37 @@
@using Microsoft.AspNetCore.Mvc.Localization
@inject IHtmlLocalizer<EventHubResource> L
@model EventHub.Web.Pages.Events.Components.RegistrationArea.RegistrationAreaViewComponent.RegistrationAreaViewComponentModel
<abp-card class="mb-3" data-event-id="@Model.EventId">
<abp-card-body>
<div data-event-id="@Model.EventId">
@if (Model.IsLoggedIn)
{
if (Model.IsRegistered)
{
<abp-button id="EventCancelRegistrationButton"
button-type="Secondary"
size="Block"
icon="fas fa-times"
text="@L["CancelRegistration"].Value"
data-url="@Url.Action("Unregister","EventRegistration", new { eventId = Model.EventId })" />
<abp-button class="mt-4" id="EventCancelRegistrationButton"
button-type="Success"
size="Large"
text="@L["YouAttendedThisEvent"].Value"
data-url="@Url.Action("Unregister", "EventRegistration", new {eventId = Model.EventId})"/>
}else if (Model.IsPastEvent)
{
<abp-button class="mt-4" id="PastEventButton"
button-type="Dark"
size="Large"
text="@L["PastEvent"].Value"
disabled="true"
abp-tooltip-top="@L["EventHub:CantRegisterOrUnregisterForAPastEvent"].Value" />
}
else
{
<abp-button id="EventRegisterButton"
<abp-button class="mt-4" id="EventRegisterButton"
button-type="Primary"
size="Block"
icon="fas fa-plus"
text="@L["RegisterNow"].Value"
size="Large"
text="@L["JoinThisEvent"].Value"
data-url="@Url.Action("Register","EventRegistration", new { eventId = Model.EventId })"/>
}
}
else
{
<a abp-button="Primary"
<a abp-button="Primary" class="btn btn-primary btn-lg mt-4"
href="@Url.Action("Login", "Account", new { returnUrl = Context.Request.Path.Value })"> @L["LoginToRegister"]</a>
}
</abp-card-body>
</abp-card>
</div>

2
src/EventHub.Web/Pages/Events/Components/RegistrationArea/RegistrationAreaViewComponent.cs

@ -37,6 +37,7 @@ namespace EventHub.Web.Pages.Events.Components.RegistrationArea
if (model.IsLoggedIn)
{
model.IsRegistered = await _eventRegistrationAppService.IsRegisteredAsync(eventId);
model.IsPastEvent = await _eventRegistrationAppService.IsPastEventAsync(eventId);
}
return View("~/Pages/Events/Components/RegistrationArea/Default.cshtml", model);
@ -47,6 +48,7 @@ namespace EventHub.Web.Pages.Events.Components.RegistrationArea
public Guid EventId { get; set; }
public bool IsLoggedIn { get; set; }
public bool IsRegistered { get; set; }
public bool IsPastEvent { get; set; }
}
}
}

2
src/EventHub.Web/Pages/Events/Components/RegistrationArea/registration-area.js

@ -21,7 +21,7 @@
}).then(function (){
widgetManager.refresh();
abp.event.trigger('EventHub.Event.RegistrationStatusChanged');
abp.message.success(l('EventRegisterSuccessMessage'), l('EventRegisterSuccessMessageTitle'));
abp.message.success(l('EventRegisterSuccessMessage'));
}).always(function (){
$registerButton.buttonBusy(false);
});

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save