diff --git a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Details.razor b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Details.razor index 5d4064e..6fdccf0 100644 --- a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Details.razor +++ b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Details.razor @@ -1,29 +1,60 @@ -@using Oqtane.Modules.Controls +@using Oqtane +@using Oqtane.Modules.Controls +@using Oqtane.Themes.Controls @using SZUAbsolventenverein.Module.EventRegistration.Services @using SZUAbsolventenverein.Module.EventRegistration.Models +@using System.Text.RegularExpressions @namespace SZUAbsolventenverein.Module.EventRegistration @inherits ModuleBase @inject IEventRegistrationService EventRegistrationService @inject NavigationManager NavigationManager @inject IStringLocalizer Localizer +@inject IStringLocalizer SharedLocalizer +@inject IUserService UserService +@inject IProfileService ProfileService +@inject ISettingService SettingService -
-
- -
- -
+

Anmeldung zum Event

+ +

Willst du am Event (@_name) teilnehmen?

+@_eventDate.ToLocalTime() - @_location +
+ @((MarkupString) _description) +
+ +@if (PageState.User != null) { + @if (Status != null) + { +

Status: + @if (Status == true) + { + @Localizer["Zugesagt"]
+

+ } else + { + @Localizer["Abgesagt"]
+

+ } +

+ } else { +
+ +
+ } +} else +{ +

Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.

+
+ +
- - @Localizer["Cancel"] -

- +} @code { - public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View; public override string Actions => "Details"; @@ -34,29 +65,88 @@ new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" } }; - private ElementReference form; - private bool validated = false; + // private ElementReference form; + // private bool validated = false; private int _id; private string _name; - private string _createdby; - private DateTime _createdon; - private string _modifiedby; - private DateTime _modifiedon; + private string _description; + private DateTime _eventDate; + private string _location; + + private Response _response; + private bool? Status; + + private List _profiles = new List(); + private Dictionary _settings; + + private async Task SendResponse(bool response) + { + if(ValidateProfiles()) { + if(_response == null) + { + _response = new Response(); + _response.EventRegistrationId = _id; + _response.OwnerId = PageState.User.UserId; + _response.ModuleId = ModuleState.ModuleId; + _response.ResponseType = response; + _response = await EventRegistrationService.AddResponseAsync(_response); + } else + { + _response.ResponseType = response; + _response = await EventRegistrationService.UpdateResponseAsync(_response); + } + if(_response != null) Status = _response.ResponseType; + } else + { + var currentPathAndQuery = new Uri(NavigationManager.Uri).PathAndQuery; + var encodedReturnUrl = Uri.EscapeDataString(currentPathAndQuery); + var link = $"/profile?tab=Profile&returnurl={encodedReturnUrl}"; + + AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], $"Vervollständige hier dein Profil mit deinem Jahrgang und deiner Fachrichtung: Link zum Profil"), MessageType.Warning); + } + } + + private async void Zusage() + { + await SendResponse(true); + } + + private async void Absage() + { + await SendResponse(false); + } protected override async Task OnInitializedAsync() { try { + if(PageState.User != null) { + _profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId); + var user = await UserService.GetUserAsync(PageState.User.UserId, PageState.Site.SiteId); + if (user != null) + { + _settings = user.Settings; + } + } + _id = Int32.Parse(PageState.QueryString["id"]); - Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId); - if (EventRegistration != null) + + Event currentEvent; + Response rsvp; + (currentEvent, rsvp) = await EventRegistrationService.GetEventDetails(_id, ModuleState.ModuleId); + if (currentEvent != null) { - _name = EventRegistration.Name; - _createdby = EventRegistration.CreatedBy; - _createdon = EventRegistration.CreatedOn; - _modifiedby = EventRegistration.ModifiedBy; - _modifiedon = EventRegistration.ModifiedOn; + _name = currentEvent.Name; + _description = currentEvent.Description; + _eventDate = currentEvent.EventDate; + _location = currentEvent.Location; + } + + if(rsvp != null) + { + _response = rsvp; + Status = rsvp.ResponseType; } } catch (Exception ex) @@ -66,40 +156,45 @@ } } - private async Task Save() + + private bool ValidateProfiles() { - try + foreach (Profile profile in _profiles) { - validated = true; - var interop = new Oqtane.UI.Interop(JSRuntime); - if (await interop.FormValid(form)) + var value = GetProfileValue(profile.Name, string.Empty); + if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(profile.DefaultValue)) { - if (PageState.Action == "Add") - { - Event EventRegistration = new Event(); - EventRegistration.ModuleId = ModuleState.ModuleId; - EventRegistration.Name = _name; - EventRegistration = await EventRegistrationService.AddEventRegistrationAsync(EventRegistration); - await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration); - } - else - { - Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId); - EventRegistration.Name = _name; - await EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration); - await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration); - } - NavigationManager.NavigateTo(NavigateUrl()); + _settings = SettingService.SetSetting(_settings, profile.Name, profile.DefaultValue); } - else + if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin)) { - AddModuleMessage(Localizer["Message.SaveValidation"], MessageType.Warning); + if (profile.IsRequired && string.IsNullOrEmpty(value)) + { + AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], profile.Title), MessageType.Warning); + return false; + } + if (!string.IsNullOrEmpty(profile.Validation)) + { + Regex regex = new Regex(profile.Validation); + bool valid = regex.Match(value).Success; + if (!valid) + { + AddModuleMessage(string.Format(SharedLocalizer["ProfileInvalid"], profile.Title), MessageType.Warning); + return false; + } + } } } - catch (Exception ex) + return true; + } + + private string GetProfileValue(string SettingName, string DefaultValue) + { + string value = SettingService.GetSetting(_settings, SettingName, DefaultValue); + if (value.Contains("]")) { - await logger.LogError(ex, "Error Saving EventRegistration {Error}", ex.Message); - AddModuleMessage(Localizer["Message.SaveError"], MessageType.Error); + value = value.Substring(value.IndexOf("]") + 1); } + return value; } } diff --git a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Edit.razor b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Edit.razor index 706958f..6edc5af 100644 --- a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Edit.razor +++ b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Edit.razor @@ -1,6 +1,7 @@ @using Oqtane.Modules.Controls @using SZUAbsolventenverein.Module.EventRegistration.Services @using SZUAbsolventenverein.Module.EventRegistration.Models +@using Microsoft.AspNetCore.Components.Forms @namespace SZUAbsolventenverein.Module.EventRegistration @inherits ModuleBase @@ -16,13 +17,30 @@
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ + +
@Localizer["Cancel"]

@if (PageState.Action == "Edit") { - + } @@ -38,11 +56,17 @@ new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" } }; + + private RichTextEditor RichTextEditorHtml; private ElementReference form; private bool validated = false; private int _id; private string _name; + private string _description; + private DateTime _eventDate = DateTime.Now; + private string _location; + private string _createdby; private DateTime _createdon; private string _modifiedby; @@ -55,10 +79,14 @@ if (PageState.Action == "Edit") { _id = Int32.Parse(PageState.QueryString["id"]); - Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId); + Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId); if (EventRegistration != null) { _name = EventRegistration.Name; + _description = EventRegistration.Description; + _eventDate = EventRegistration.EventDate.ToLocalTime(); + _location = EventRegistration.Location; + _createdby = EventRegistration.CreatedBy; _createdon = EventRegistration.CreatedOn; _modifiedby = EventRegistration.ModifiedBy; @@ -79,6 +107,10 @@ { validated = true; var interop = new Oqtane.UI.Interop(JSRuntime); + + string content = await RichTextEditorHtml.GetHtml(); + content = Utilities.FormatContent(content, PageState.Alias, "save"); + if (await interop.FormValid(form)) { if (PageState.Action == "Add") @@ -86,14 +118,20 @@ Event EventRegistration = new Event(); EventRegistration.ModuleId = ModuleState.ModuleId; EventRegistration.Name = _name; - EventRegistration = await EventRegistrationService.AddEventRegistrationAsync(EventRegistration); + EventRegistration.Description = content; + EventRegistration.EventDate = _eventDate.ToUniversalTime(); + EventRegistration.Location = _location; + EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration); await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration); } else { - Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId); + Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId); EventRegistration.Name = _name; - await EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration); + EventRegistration.Description = content; + EventRegistration.EventDate = _eventDate.ToUniversalTime(); + EventRegistration.Location = _location; + await EventRegistrationService.UpdateEventAsync(EventRegistration); await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration); } NavigationManager.NavigateTo(NavigateUrl()); diff --git a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Index.razor b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Index.razor index 467adf1..f6c03c0 100644 --- a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Index.razor +++ b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/Index.razor @@ -16,26 +16,38 @@ else

-

@Status

@if (@_EventRegistrations.Count != 0) { - -
-   -   - @Localizer["Name"] -   -
- - - - @context.Name - @* @if(UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize)) { *@ - - @* } *@ - -
+
+
+ @foreach (var context in _EventRegistrations) + { +
+

@context.Name

+

@Localizer["Date"]: @context.EventDate.ToLocalTime()

+

@Localizer["Location"]: @context.Location

+ +
+ + + + + +
+
+ } +
+
} else { @@ -44,8 +56,6 @@ else } @code { - private string Status; - public override List Resources => new List() { new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }, @@ -58,7 +68,7 @@ else { try { - _EventRegistrations = await EventRegistrationService.GetEventRegistrationsAsync(ModuleState.ModuleId); + _EventRegistrations = await EventRegistrationService.GetEventsAsync(ModuleState.ModuleId); } catch (Exception ex) { @@ -71,9 +81,9 @@ else { try { - await EventRegistrationService.DeleteEventRegistrationAsync(EventRegistration.EventRegistrationId, ModuleState.ModuleId); + await EventRegistrationService.DeleteEventAsync(EventRegistration.EventId, ModuleState.ModuleId); await logger.LogInformation("EventRegistration Deleted {EventRegistration}", EventRegistration); - _EventRegistrations = await EventRegistrationService.GetEventRegistrationsAsync(ModuleState.ModuleId); + _EventRegistrations = await EventRegistrationService.GetEventsAsync(ModuleState.ModuleId); StateHasChanged(); } catch (Exception ex) @@ -82,15 +92,4 @@ else AddModuleMessage(Localizer["Message.DeleteError"], MessageType.Error); } } - - private async Task Accept(Event eventRegistration) - { - Status = ("EventRegistration Accepted " + eventRegistration.Name); - await logger.LogInformation("EventRegistration Accepted {EventRegistration}", eventRegistration); - } - - private void Reject() - { - Status = "EventRegistration Rejected 1"; - } } \ No newline at end of file diff --git a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/ModuleInfo.cs b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/ModuleInfo.cs index 775c53e..3beb41f 100644 --- a/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/ModuleInfo.cs +++ b/Client/Modules/SZUAbsolventenverein.Module.EventRegistration/ModuleInfo.cs @@ -9,9 +9,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration { Name = "EventRegistration", Description = "A module to manage registration for events", - Version = "1.0.0", + Version = "1.0.17", ServerManagerType = "SZUAbsolventenverein.Module.EventRegistration.Manager.EventRegistrationManager, SZUAbsolventenverein.Module.EventRegistration.Server.Oqtane", - ReleaseVersions = "1.0.0", + ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,1.0.5,1.0.6,1.0.7,1.0.8,1.0.9,1.0.10,1.0.11,1.0.12,1.0.13,1.0.14,1.0.15,1.0.16,1.0.17", Dependencies = "SZUAbsolventenverein.Module.EventRegistration.Shared.Oqtane", PackageName = "SZUAbsolventenverein.Module.EventRegistration" }; diff --git a/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Details.resx b/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Details.resx new file mode 100644 index 0000000..a998b24 --- /dev/null +++ b/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Details.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Du hast abgesagt. Schade, vielleicht nächstes Mal! + + + Absagen + + + Du hast zugesagt. Wir freuen uns auf dich! + + + Zusagen + + \ No newline at end of file diff --git a/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Index.resx b/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Index.resx index efb43f4..dcb896d 100644 --- a/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Index.resx +++ b/Client/Resources/SZUAbsolventenverein.Module.EventRegistration/Index.resx @@ -127,10 +127,10 @@ Delete - Delete Event + Delete - Are You Sure You Wish To Delete This Event? + Are You Sure You Wish To Delete This Event? If you delete an event, all existing registrations will be deleted as well. No Events To Display @@ -142,6 +142,15 @@ Error Deleting Event - Reject + Details + + + Name + + + Date + + + Location \ No newline at end of file diff --git a/Client/SZUAbsolventenverein.Module.EventRegistration.Client.csproj b/Client/SZUAbsolventenverein.Module.EventRegistration.Client.csproj index e9bcc47..04e9f12 100644 --- a/Client/SZUAbsolventenverein.Module.EventRegistration.Client.csproj +++ b/Client/SZUAbsolventenverein.Module.EventRegistration.Client.csproj @@ -13,11 +13,11 @@ - - - - - + + + + + diff --git a/Client/Services/EventRegistrationService.cs b/Client/Services/EventRegistrationService.cs index 899fd0d..6e45618 100644 --- a/Client/Services/EventRegistrationService.cs +++ b/Client/Services/EventRegistrationService.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Oqtane.Services; using Oqtane.Shared; +using SZUAbsolventenverein.Module.EventRegistration.Models; namespace SZUAbsolventenverein.Module.EventRegistration.Services { @@ -13,7 +15,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services private string Apiurl => CreateApiUrl("EventRegistration"); - public async Task> GetEventRegistrationsAsync(int ModuleId) + /*public async Task> GetEventRegistrationsAsync(int ModuleId) { List EventRegistrations = await GetJsonAsync>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty().ToList()); return EventRegistrations.OrderBy(item => item.Name).ToList(); @@ -32,11 +34,51 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services public async Task UpdateEventRegistrationAsync(Models.Event EventRegistration) { return await PutJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistration.EventRegistrationId}", EntityNames.Module, EventRegistration.ModuleId), EventRegistration); + }*/ + + public async Task> GetEventsAsync(int ModuleId) + { + List EventRegistrations = await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty().ToList()); + return EventRegistrations.OrderBy(item => item.Name).ToList(); + } + public async Task GetEventAsync(int EventId, int ModuleId) + { + return await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventId}/{ModuleId}", EntityNames.Module, ModuleId)); } - public async Task DeleteEventRegistrationAsync(int EventRegistrationId, int ModuleId) + public async Task AddEventAsync(Event NewEvent) { - await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistrationId}/{ModuleId}", EntityNames.Module, ModuleId)); + return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent); + } + + public async Task UpdateEventAsync(Event NewEvent) + { + return await PutJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{NewEvent.EventId}", EntityNames.Module, NewEvent.ModuleId), NewEvent); + } + + public async Task DeleteEventAsync(int EventId, int ModuleId) + { + await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventId}/{ModuleId}", EntityNames.Module, ModuleId)); + } + + public async Task AddResponseAsync(Response response) + { + return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/response/{response.EventRegistrationId}/{response.ModuleId}", EntityNames.Module, response.ModuleId), response); + } + + public async Task UpdateResponseAsync(Response response) + { + return await PutJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/response/{response.EventRegistrationId}/{response.ModuleId}", EntityNames.Module, response.ModuleId), response); + } + + public async Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId) + { + return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId)); + } + + public Task> GetEventResponses(int EventId, int ModuleId) + { + throw new System.NotImplementedException(); } } } diff --git a/Client/Startup/ClientStartup.cs b/Client/Startup/ClientStartup.cs index 5fb721b..0ad161d 100644 --- a/Client/Startup/ClientStartup.cs +++ b/Client/Startup/ClientStartup.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Oqtane.Services; +using System.Linq; using SZUAbsolventenverein.Module.EventRegistration.Services; namespace SZUAbsolventenverein.Module.EventRegistration.Startup @@ -8,7 +9,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Startup { public void ConfigureServices(IServiceCollection services) { - services.AddScoped(); + if (!services.Any(s => s.ServiceType == typeof(IEventRegistrationService))) + { + services.AddScoped(); + } } } } diff --git a/Package/SZUAbsolventenverein.Module.EventRegistration.nuspec b/Package/SZUAbsolventenverein.Module.EventRegistration.nuspec index 03495c4..1bf415d 100644 --- a/Package/SZUAbsolventenverein.Module.EventRegistration.nuspec +++ b/Package/SZUAbsolventenverein.Module.EventRegistration.nuspec @@ -2,7 +2,7 @@ $projectname$ - 1.0.0 + 1.0.17 SZUAbsolventenverein SZUAbsolventenverein EventRegistration @@ -16,7 +16,7 @@ - + diff --git a/Server/Controllers/EventRegistrationController.cs b/Server/Controllers/EventRegistrationController.cs index 7fe00e6..c8fb682 100644 --- a/Server/Controllers/EventRegistrationController.cs +++ b/Server/Controllers/EventRegistrationController.cs @@ -30,7 +30,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers int ModuleId; if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId)) { - return await _EventRegistrationService.GetEventRegistrationsAsync(ModuleId); + return await _EventRegistrationService.GetEventsAsync(ModuleId); } else { @@ -45,7 +45,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers [Authorize(Policy = PolicyNames.ViewModule)] public async Task Get(int id, int moduleid) { - Models.Event EventRegistration = await _EventRegistrationService.GetEventRegistrationAsync(id, moduleid); + Models.Event EventRegistration = await _EventRegistrationService.GetEventAsync(id, moduleid); if (EventRegistration != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) { return EventRegistration; @@ -65,7 +65,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers { if (ModelState.IsValid && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) { - EventRegistration = await _EventRegistrationService.AddEventRegistrationAsync(EventRegistration); + EventRegistration = await _EventRegistrationService.AddEventAsync(EventRegistration); } else { @@ -81,9 +81,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers [Authorize(Policy = PolicyNames.EditModule)] public async Task Put(int id, [FromBody] Models.Event EventRegistration) { - if (ModelState.IsValid && EventRegistration.EventRegistrationId == id && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) + if (ModelState.IsValid && EventRegistration.EventId == id && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) { - EventRegistration = await _EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration); + EventRegistration = await _EventRegistrationService.UpdateEventAsync(EventRegistration); } else { @@ -99,10 +99,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers [Authorize(Policy = PolicyNames.EditModule)] public async Task Delete(int id, int moduleid) { - Models.Event EventRegistration = await _EventRegistrationService.GetEventRegistrationAsync(id, moduleid); + Models.Event EventRegistration = await _EventRegistrationService.GetEventAsync(id, moduleid); if (EventRegistration != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) { - await _EventRegistrationService.DeleteEventRegistrationAsync(id, EventRegistration.ModuleId); + await _EventRegistrationService.DeleteEventAsync(id, EventRegistration.ModuleId); } else { @@ -110,5 +110,27 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; } } + + // GET api//5 + [HttpGet("details/{id}/{moduleid}")] + [Authorize(Policy = PolicyNames.ViewModule)] + public async Task<(Models.Event, Models.Response)> GetDetails(int id, int moduleid) + { + Models.Event EventRegistration; + Models.Response EventResponse; + (EventRegistration, EventResponse) = await _EventRegistrationService.GetEventDetails(id, moduleid); + if (EventRegistration != null && EventResponse != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId)) + { + return (EventRegistration, EventResponse); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {EventRegistrationId} {ModuleId}", id, moduleid); + HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; + return (null, null); + } + } + + // TODO: Add Event Response Endpoints. } } diff --git a/Server/Manager/EventRegistrationManager.cs b/Server/Manager/EventRegistrationManager.cs index b23c74f..cc5ac18 100644 --- a/Server/Manager/EventRegistrationManager.cs +++ b/Server/Manager/EventRegistrationManager.cs @@ -15,12 +15,14 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager { public class EventRegistrationManager : MigratableModuleBase, IInstallable, IPortable, ISearchable { - private readonly IEventRegistrationRepository _EventRegistrationRepository; + private readonly IEventRepository _EventRepository; + private readonly IResponseRepository _ResponseRepository; private readonly IDBContextDependencies _DBContextDependencies; - public EventRegistrationManager(IEventRegistrationRepository EventRegistrationRepository, IDBContextDependencies DBContextDependencies) + public EventRegistrationManager(IEventRepository EventRegistrationRepository, IResponseRepository ResponseRepository, IDBContextDependencies DBContextDependencies) { - _EventRegistrationRepository = EventRegistrationRepository; + _EventRepository = EventRegistrationRepository; + _ResponseRepository = ResponseRepository; _DBContextDependencies = DBContextDependencies; } @@ -36,17 +38,28 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager public string ExportModule(Oqtane.Models.Module module) { + // TODO: Export event Responses as well. string content = ""; - List EventRegistrations = _EventRegistrationRepository.GetEventRegistrations(module.ModuleId).ToList(); - if (EventRegistrations != null) + List exportData = new List(); + foreach (var events in _EventRepository.GetEvents(module.ModuleId)) { - content = JsonSerializer.Serialize(EventRegistrations); + var responses = _ResponseRepository.GetResponses(events.EventId, module.ModuleId); + exportData.Add(new + { + Event = events, + Responses = responses.ToList() + }); + }; + if (exportData != null) + { + content = JsonSerializer.Serialize(exportData); } return content; } public void ImportModule(Oqtane.Models.Module module, string content, string version) { + // TODO: Import event Responses as well. List EventRegistrations = null; if (!string.IsNullOrEmpty(content)) { @@ -56,7 +69,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager { foreach(var EventRegistration in EventRegistrations) { - _EventRegistrationRepository.AddEventRegistration(new Models.Event { ModuleId = module.ModuleId, Name = EventRegistration.Name }); + _EventRepository.AddEvent(new Models.Event { ModuleId = module.ModuleId, Name = EventRegistration.Name }); } } } @@ -65,14 +78,14 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager { var searchContentList = new List(); - foreach (var EventRegistration in _EventRegistrationRepository.GetEventRegistrations(pageModule.ModuleId)) + foreach (var EventRegistration in _EventRepository.GetEvents(pageModule.ModuleId)) { if (EventRegistration.ModifiedOn >= lastIndexedOn) { searchContentList.Add(new SearchContent { EntityName = "SZUAbsolventenvereinEventRegistration", - EntityId = EventRegistration.EventRegistrationId.ToString(), + EntityId = EventRegistration.EventId.ToString(), Title = EventRegistration.Name, Body = EventRegistration.Name, ContentModifiedBy = EventRegistration.ModifiedBy, diff --git a/Server/Migrations/01000000_InitializeModule.cs b/Server/Migrations/01000000_InitializeModule.cs index 83ff7b7..6d7050d 100644 --- a/Server/Migrations/01000000_InitializeModule.cs +++ b/Server/Migrations/01000000_InitializeModule.cs @@ -17,7 +17,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations protected override void Up(MigrationBuilder migrationBuilder) { - var entityBuilder = new EventRegistrationEntityBuilder(migrationBuilder, ActiveDatabase); + var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase); entityBuilder.Create(); var entityBuilder2 = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase); @@ -26,10 +26,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations protected override void Down(MigrationBuilder migrationBuilder) { - var entityBuilder = new EventRegistrationEntityBuilder(migrationBuilder, ActiveDatabase); - entityBuilder.Drop(); - var entityBuilder2 = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase); - entityBuilder2.Drop(); + var responseEB = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase); + responseEB.Drop(); + var eventEB = new EventEntityBuilder(migrationBuilder, ActiveDatabase); + eventEB.Drop(); } } } diff --git a/Server/Migrations/01000005_AddDescriptionDateTimeLocation.cs b/Server/Migrations/01000005_AddDescriptionDateTimeLocation.cs new file mode 100644 index 0000000..9f0c73a --- /dev/null +++ b/Server/Migrations/01000005_AddDescriptionDateTimeLocation.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Databases.Interfaces; +using Oqtane.Migrations; +using System; +using SZUAbsolventenverein.Module.EventRegistration.Migrations.EntityBuilders; +using SZUAbsolventenverein.Module.EventRegistration.Repository; + +namespace SZUAbsolventenverein.Module.EventRegistration.Migrations +{ + [DbContext(typeof(EventRegistrationContext))] + [Migration("SZUAbsolventenverein.Module.EventRegistration.01.00.00.05")] + public class AddDescriptionDateTimeLocation : MultiDatabaseMigration + { + public AddDescriptionDateTimeLocation(IDatabase database) : base(database) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase); + entityBuilder.AddMaxStringColumn("Description", false, true, ""); // Contents for RichTextEditor + entityBuilder.AddDateTimeColumn("EventDate", false, new DateTime()); // DateTime for the event + entityBuilder.AddStringColumn("Location", 100, false, true, ""); // Location of the event + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase); + entityBuilder.DropColumn("Description"); // RichTextEditor + entityBuilder.DropColumn("EventDate"); // DateTime + entityBuilder.DropColumn("Location"); // Location 0 + } + } +} diff --git a/Server/Migrations/EntityBuilders/EventRegistrationEntityBuilder.cs b/Server/Migrations/EntityBuilders/EventEntityBuilder.cs similarity index 52% rename from Server/Migrations/EntityBuilders/EventRegistrationEntityBuilder.cs rename to Server/Migrations/EntityBuilders/EventEntityBuilder.cs index c6f4f2f..54e4deb 100644 --- a/Server/Migrations/EntityBuilders/EventRegistrationEntityBuilder.cs +++ b/Server/Migrations/EntityBuilders/EventEntityBuilder.cs @@ -7,29 +7,29 @@ using Oqtane.Migrations.EntityBuilders; namespace SZUAbsolventenverein.Module.EventRegistration.Migrations.EntityBuilders { - public class EventRegistrationEntityBuilder : AuditableBaseEntityBuilder + public class EventEntityBuilder : AuditableBaseEntityBuilder { private const string _entityTableName = "SZUAbsolventenvereinEvent"; - private readonly PrimaryKey _primaryKey = new("PK_SZUAbsolventenvereinEvent", x => x.EventRegistrationId); - private readonly ForeignKey _moduleForeignKey = new("FK_SZUAbsolventenvereinEvent_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); + private readonly PrimaryKey _primaryKey = new("PK_SZUAbsolventenvereinEvent", x => x.EventId); + private readonly ForeignKey _moduleForeignKey = new("FK_SZUAbsolventenvereinEvent_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); - public EventRegistrationEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) + public EventEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; ForeignKeys.Add(_moduleForeignKey); } - protected override EventRegistrationEntityBuilder BuildTable(ColumnsBuilder table) + protected override EventEntityBuilder BuildTable(ColumnsBuilder table) { - EventRegistrationId = AddAutoIncrementColumn(table,"EventRegistrationId"); + EventId = AddAutoIncrementColumn(table,"EventId"); ModuleId = AddIntegerColumn(table,"ModuleId"); Name = AddMaxStringColumn(table,"Name"); AddAuditableColumns(table); return this; } - public OperationBuilder EventRegistrationId { get; set; } + public OperationBuilder EventId { get; set; } public OperationBuilder ModuleId { get; set; } public OperationBuilder Name { get; set; } } diff --git a/Server/Migrations/EntityBuilders/EventResponseEntityBuilder.cs b/Server/Migrations/EntityBuilders/EventResponseEntityBuilder.cs index 9d26e53..91f52a5 100644 --- a/Server/Migrations/EntityBuilders/EventResponseEntityBuilder.cs +++ b/Server/Migrations/EntityBuilders/EventResponseEntityBuilder.cs @@ -13,7 +13,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations.EntityBuilder private const string _entityTableName = "SZUAbsolventenvereinEventResponse"; private readonly PrimaryKey _primaryKey = new("PK_SZUAbsolventenvereinEventResponse", x => x.EventResponseId); private readonly ForeignKey _moduleForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); - private readonly ForeignKey _eventForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Event", x => x.EventRegistrationId, "SZUAbsolventenvereinEvent", "EventRegistrationId", ReferentialAction.Cascade); + private readonly ForeignKey _eventForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Event", x => x.EventRegistrationId, "SZUAbsolventenvereinEvent", "EventId", ReferentialAction.Cascade); private readonly ForeignKey _ownerForeignKey = new("FK_SZUAbsolventenvereinEventResponse_User_Owner", x => x.OwnerId, "User", "UserId", ReferentialAction.Cascade); public EventResponseEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) diff --git a/Server/Repository/EventRegistrationRepository.cs b/Server/Repository/EventRepository.cs similarity index 64% rename from Server/Repository/EventRegistrationRepository.cs rename to Server/Repository/EventRepository.cs index ac23c55..e6a5510 100644 --- a/Server/Repository/EventRegistrationRepository.cs +++ b/Server/Repository/EventRepository.cs @@ -5,27 +5,27 @@ using Oqtane.Modules; namespace SZUAbsolventenverein.Module.EventRegistration.Repository { - public class EventRegistrationRepository : IEventRegistrationRepository, ITransientService + public class EventRepository : IEventRepository, ITransientService { private readonly IDbContextFactory _factory; - public EventRegistrationRepository(IDbContextFactory factory) + public EventRepository(IDbContextFactory factory) { _factory = factory; } - public IEnumerable GetEventRegistrations(int ModuleId) + public IEnumerable GetEvents(int ModuleId) { using var db = _factory.CreateDbContext(); return db.Event.Where(item => item.ModuleId == ModuleId).ToList(); } - public Models.Event GetEventRegistration(int EventRegistrationId) + public Models.Event GetEvent(int EventRegistrationId) { - return GetEventRegistration(EventRegistrationId, true); + return GetEvent(EventRegistrationId, true); } - public Models.Event GetEventRegistration(int EventRegistrationId, bool tracking) + public Models.Event GetEvent(int EventRegistrationId, bool tracking) { using var db = _factory.CreateDbContext(); if (tracking) @@ -34,11 +34,11 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Repository } else { - return db.Event.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventRegistrationId); + return db.Event.AsNoTracking().FirstOrDefault(item => item.EventId == EventRegistrationId); } } - public Models.Event AddEventRegistration(Models.Event EventRegistration) + public Models.Event AddEvent(Models.Event EventRegistration) { using var db = _factory.CreateDbContext(); db.Event.Add(EventRegistration); @@ -46,7 +46,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Repository return EventRegistration; } - public Models.Event UpdateEventRegistration(Models.Event EventRegistration) + public Models.Event UpdateEvent(Models.Event EventRegistration) { using var db = _factory.CreateDbContext(); db.Entry(EventRegistration).State = EntityState.Modified; @@ -54,7 +54,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Repository return EventRegistration; } - public void DeleteEventRegistration(int EventRegistrationId) + public void DeleteEvent(int EventRegistrationId) { using var db = _factory.CreateDbContext(); Models.Event EventRegistration = db.Event.Find(EventRegistrationId); diff --git a/Server/Repository/IEventRegistrationRepository.cs b/Server/Repository/IEventRegistrationRepository.cs deleted file mode 100644 index c674d93..0000000 --- a/Server/Repository/IEventRegistrationRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace SZUAbsolventenverein.Module.EventRegistration.Repository -{ - public interface IEventRegistrationRepository - { - IEnumerable GetEventRegistrations(int ModuleId); - Models.Event GetEventRegistration(int EventRegistrationId); - Models.Event GetEventRegistration(int EventRegistrationId, bool tracking); - Models.Event AddEventRegistration(Models.Event EventRegistration); - Models.Event UpdateEventRegistration(Models.Event EventRegistration); - void DeleteEventRegistration(int EventRegistrationId); - } -} diff --git a/Server/Repository/IEventRepository.cs b/Server/Repository/IEventRepository.cs new file mode 100644 index 0000000..8b383b7 --- /dev/null +++ b/Server/Repository/IEventRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace SZUAbsolventenverein.Module.EventRegistration.Repository +{ + public interface IEventRepository + { + IEnumerable GetEvents(int ModuleId); + Models.Event GetEvent(int EventRegistrationId); + Models.Event GetEvent(int EventRegistrationId, bool tracking); + Models.Event AddEvent(Models.Event EventRegistration); + Models.Event UpdateEvent(Models.Event EventRegistration); + void DeleteEvent(int EventRegistrationId); + } +} diff --git a/Server/Repository/IResponseRepository.cs b/Server/Repository/IResponseRepository.cs new file mode 100644 index 0000000..0a51e72 --- /dev/null +++ b/Server/Repository/IResponseRepository.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using SZUAbsolventenverein.Module.EventRegistration.Models; + +namespace SZUAbsolventenverein.Module.EventRegistration.Repository +{ + public interface IResponseRepository + { + IEnumerable GetResponses(int ModuleId); + IEnumerable GetResponses(int EventId, int ModuleId); + Response GetResponse(int EventRegistrationId); + Response GetResponse(int EventRegistrationId, bool tracking); + Response GetResponse(int EventId, int OwnerId); + Response GetResponse(int EventId, int OwnerId, bool tracking); + Response AddResponse(Response EventResponse); + Response UpdateResponse(Response EventResponse); + void DeleteResponse(int EventResponseId); + } +} diff --git a/Server/Repository/ResponseRepository.cs b/Server/Repository/ResponseRepository.cs new file mode 100644 index 0000000..5facecf --- /dev/null +++ b/Server/Repository/ResponseRepository.cs @@ -0,0 +1,89 @@ +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Collections.Generic; +using Oqtane.Modules; +using SZUAbsolventenverein.Module.EventRegistration.Models; + +namespace SZUAbsolventenverein.Module.EventRegistration.Repository +{ + public class ResponseRepository : IResponseRepository, ITransientService + { + private readonly IDbContextFactory _factory; + + public ResponseRepository(IDbContextFactory factory) + { + _factory = factory; + } + public IEnumerable GetResponses(int ModuleId) + { + using var db = _factory.CreateDbContext(); + return db.Response.Where(item => item.ModuleId == ModuleId).ToList(); + } + + public IEnumerable GetResponses(int EventId, int ModuleId) + { + using var db = _factory.CreateDbContext(); + return db.Response.Where(item => item.ModuleId == ModuleId && item.EventRegistrationId == EventId).ToList(); + } + + public Response GetResponse(int EventRegistrationId) + { + return GetResponse(EventRegistrationId, true); + } + + public Response GetResponse(int EventRegistrationId, bool tracking) + { + using var db = _factory.CreateDbContext(); + if (tracking) + { + return db.Response.Find(EventRegistrationId); + } + else + { + return db.Response.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventRegistrationId); + } + } + + public Response GetResponse(int EventId, int OwnerId) + { + return GetResponse(EventId, OwnerId, true); + } + + public Response GetResponse(int EventId, int OwnerId, bool tracking) + { + using var db = _factory.CreateDbContext(); + if (tracking) + { + return db.Response.FirstOrDefault(item => item.EventRegistrationId == EventId && item.OwnerId == OwnerId); + } + else + { + return db.Response.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventId && item.OwnerId == OwnerId); + } + } + + public Response AddResponse(Response EventResponse) + { + using var db = _factory.CreateDbContext(); + db.Response.Add(EventResponse); + db.SaveChanges(); + return EventResponse; + } + + public Response UpdateResponse(Response EventResponse) + { + using var db = _factory.CreateDbContext(); + db.Entry(EventResponse).State = EntityState.Modified; + db.SaveChanges(); + return EventResponse; + } + + public void DeleteResponse(int EventRegistrationId) + { + using var db = _factory.CreateDbContext(); + Response EventResponse = db.Response.Find(EventRegistrationId); + db.Response.Remove(EventResponse); + db.SaveChanges(); + } + } +} diff --git a/Server/SZUAbsolventenverein.Module.EventRegistration.Server.csproj b/Server/SZUAbsolventenverein.Module.EventRegistration.Server.csproj index 7813ab4..6bf517f 100644 --- a/Server/SZUAbsolventenverein.Module.EventRegistration.Server.csproj +++ b/Server/SZUAbsolventenverein.Module.EventRegistration.Server.csproj @@ -19,10 +19,10 @@ - - - - + + + + diff --git a/Server/Services/EventRegistrationService.cs b/Server/Services/EventRegistrationService.cs index 3d2f62a..2a6f537 100644 --- a/Server/Services/EventRegistrationService.cs +++ b/Server/Services/EventRegistrationService.cs @@ -3,44 +3,186 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Oqtane.Enums; +using Oqtane.Extensions; using Oqtane.Infrastructure; using Oqtane.Models; +using Oqtane.Repository; using Oqtane.Security; using Oqtane.Shared; +using SZUAbsolventenverein.Module.EventRegistration.Models; using SZUAbsolventenverein.Module.EventRegistration.Repository; namespace SZUAbsolventenverein.Module.EventRegistration.Services { public class ServerEventRegistrationService : IEventRegistrationService { - private readonly IEventRegistrationRepository _EventRegistrationRepository; + private readonly IEventRepository _EventRepository; + private readonly IResponseRepository _ResponseRepository; + private readonly INotificationRepository _NotificationRepository; + private readonly IUserRepository _UserRepository; private readonly IUserPermissions _userPermissions; private readonly ILogManager _logger; private readonly IHttpContextAccessor _accessor; private readonly Alias _alias; - public ServerEventRegistrationService(IEventRegistrationRepository EventRegistrationRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor) + public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, INotificationRepository NotificationRepository, IUserRepository UserRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor) { - _EventRegistrationRepository = EventRegistrationRepository; + _EventRepository = EventRepository; + _ResponseRepository = ResponseRepository; + _NotificationRepository = NotificationRepository; + _UserRepository = UserRepository; _userPermissions = userPermissions; _logger = logger; _accessor = accessor; _alias = tenantManager.GetAlias(); } - public Task> GetEventRegistrationsAsync(int ModuleId) + public Task AddEventAsync(Event NewEvent) { - if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, NewEvent.ModuleId, PermissionNames.Edit)) { - return Task.FromResult(_EventRegistrationRepository.GetEventRegistrations(ModuleId).ToList()); + NewEvent = _EventRepository.AddEvent(NewEvent); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", NewEvent); } else { - _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {ModuleId}", ModuleId); + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {NewEvent}", NewEvent); + NewEvent = null; + } + return Task.FromResult(NewEvent); + } + + public Task AddResponseAsync(Response Response) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View)) + { + Response = _ResponseRepository.AddResponse(Response); + + Event currentEvent = _EventRepository.GetEvent(Response.EventRegistrationId); + string subject = Response.ResponseType ? $"Du bist erfolgreich für '{currentEvent.Name}' Registriert worden." : $"Du hast erfolgreich für '{currentEvent.Name}' abgesagt."; + string body = "Hier kann man die Infos des Events hineinpacken (HTML ist erlaubt)"; + SendEventResponseNotification(subject, body); + + _logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {NewEvent}", Response); + Response = null; + } + return Task.FromResult(Response); + } + + public Task UpdateResponseAsync(Response Response) + { + + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View)) + { + Response = _ResponseRepository.UpdateResponse(Response); + + Event currentEvent = _EventRepository.GetEvent(Response.EventRegistrationId); + string subject = Response.ResponseType ? $"Du bist erfolgreich für '{currentEvent.Name}' registriert." : $"Du hast erfolgreich für '{currentEvent.Name}' abgesagt."; + string body = currentEvent.Description; + SendEventResponseNotification(subject, body); + + _logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {NewEvent}", Response); + Response = null; + } + return Task.FromResult(Response); + } + + public Task DeleteEventAsync(int EventId, int ModuleId) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit)) + { + _EventRepository.DeleteEvent(EventId); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Event Deleted {EventId}", EventId); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Delete Attempt {EventId} {ModuleId}", EventId, ModuleId); + } + return Task.CompletedTask; + } + + public Task GetEventAsync(int EventId, int ModuleId) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) + { + return Task.FromResult(_EventRepository.GetEvent(EventId, true)); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Get Attempt {ModuleId}", ModuleId); return null; } } + public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) + { + Event currentEvent = _EventRepository.GetEvent(EventId); + Response rsvp = _ResponseRepository.GetResponse(EventId, _accessor.HttpContext.User.UserId()); + return Task.FromResult((currentEvent, rsvp)); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Get Attempt {ModuleId}", ModuleId); + return null; + } + } + + public Task> GetEventResponses(int EventId, int ModuleId) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit)) + { + return Task.FromResult(_ResponseRepository.GetResponses(EventId, ModuleId).ToList()); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Response Get Attempt {ModuleId}", ModuleId); + return null; + } + throw new System.NotImplementedException(); + } + + public Task> GetEventsAsync(int ModuleId) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) + { + return Task.FromResult(_EventRepository.GetEvents(ModuleId).ToList()); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Events Get Attempt {ModuleId}", ModuleId); + return null; + } + } + + public Task UpdateEventAsync(Event NewEvent) + { + if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, NewEvent.ModuleId, PermissionNames.Edit)) + { + NewEvent = _EventRepository.UpdateEvent(NewEvent); + _logger.Log(LogLevel.Information, this, LogFunction.Update, "Event Updated {NewEvent}", NewEvent); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Update Attempt {NewEvent}", NewEvent); + NewEvent = null; + } + return Task.FromResult(NewEvent); + } + + // TODO: Implement the methods for EventResponses + + /* + public Task GetEventRegistrationAsync(int EventRegistrationId, int ModuleId) { if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) @@ -84,18 +226,13 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services return Task.FromResult(EventRegistration); } - public Task DeleteEventRegistrationAsync(int EventRegistrationId, int ModuleId) + }*/ + + private void SendEventResponseNotification(string subject, string body) { - if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit)) - { - _EventRegistrationRepository.DeleteEventRegistration(EventRegistrationId); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "EventRegistration Deleted {EventRegistrationId}", EventRegistrationId); - } - else - { - _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Delete Attempt {EventRegistrationId} {ModuleId}", EventRegistrationId, ModuleId); - } - return Task.CompletedTask; + User user = _UserRepository.GetUser(_accessor.HttpContext.User.UserId()); + Notification notification = new Notification(_alias.SiteId, user, subject, body); + _NotificationRepository.AddNotification(notification); } } } diff --git a/Server/wwwroot/Modules/SZUAbsolventenverein.Module.EventRegistration/Module.css b/Server/wwwroot/Modules/SZUAbsolventenverein.Module.EventRegistration/Module.css index 0856a26..3e58f0f 100644 --- a/Server/wwwroot/Modules/SZUAbsolventenverein.Module.EventRegistration/Module.css +++ b/Server/wwwroot/Modules/SZUAbsolventenverein.Module.EventRegistration/Module.css @@ -1 +1,201 @@ -/* Module Custom Styles */ \ No newline at end of file +/* Module Custom Styles */ +.mb-6 { + margin-bottom: 6rem; +} + +.mt-3 { + margin-top: 3rem; +} +.mt-2 strong { + font-size: 1.4rem; /* Textgröße – Standard ist ca. 1rem */ + font-weight: 700; +} +.fontsizeInf { + font-size: 1.4rem; /* Textgröße – Standard ist ca. 1rem */ +} +.event-list { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; + justify-content: center; +} + +.event-card { + /*background-color: var(--bs-gray-dark); */ + border: 2px solid rgb(128 128 128); /* Umrandung */ + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); + padding: 1.5rem; + width: 280px; + /* color: #ddd; */ + transition: all 0.3s ease; +} + + + .event-card h3 { + margin-top: 0; + margin-bottom: 0.5rem; + } + + .event-card p { + margin: 0.2rem 0; + } + +.event-actions { + margin-top: 1rem; + display: flex; + justify-content: space-between; +} +/* vorher: +.event-card:hover { + border-color: #66ccff; + transform: translateY(-4px); <-- das ist der Übeltäter + box-shadow: 0 6px 14px rgba(0,0,0,0.5); +} +*/ + +/* nachher – kein transform mehr */ +.event-card:hover { + border-color: #66ccff; + /* statt transform die Karte minimal "anheben" */ + margin-top: -4px; /* optischer Lift */ + box-shadow: 0 6px 14px rgba(0,0,0,0.5); +} + +/* sicherheitshalber: Overlay darf nicht abgeschnitten werden */ +.event-card { + overflow: visible; +} +/* ---------- A) Hover nur auf Geräten mit Maus ---------- */ +@media (hover: hover) and (pointer: fine) { + .event-card:hover { + border-color: #66ccff; + + box-shadow: 0 6px 14px rgba(0,0,0,.5); + } +} + +/* Auf Touch-Geräten kein transform (verhindert Modal-Probleme) */ +@media (hover: none), (pointer: coarse) { + .event-card:hover { + transform: none; + box-shadow: 0 6px 14px rgba(0,0,0,.5); + } +} + +/* Sicherheitshalber: nichts abschneiden */ +.event-card { + overflow: visible; +} + + +/* ---------- B) Overlay/Modal (Desktop-Basis) ---------- */ +/* Falls schon vorhanden, kannst du diese Werte als Override nutzen */ +.overlay { + position: fixed; + inset: 0; + background: rgba(0,0,0,.45); + display: flex; + align-items: center; + justify-content: center; + padding: 2rem; + z-index: 2000; + overscroll-behavior: contain; +} + +.modal { + background: #fff; + border-radius: 10px; + box-shadow: 0 20px 60px rgba(0,0,0,.35); + width: min(92vw, 720px); + max-height: 85vh; + display: flex; + flex-direction: column; + overflow: hidden; /* für sticky header/footer */ +} + +.modal-header, +.modal-footer { + padding: 1rem 1.25rem; + background: #fff; +} + +.modal-header { + border-bottom: 1px solid rgba(0,0,0,.1); +} + +.modal-footer { + border-top: 1px solid rgba(0,0,0,.1); + display: flex; + gap: .75rem; + justify-content: flex-end; +} + +.modal-body { + padding: 1rem 1.25rem; + overflow: auto; + -webkit-overflow-scrolling: touch; +} + + /* Medien responsiv im Detail-Dialog */ + .modal-body img, + .modal-body video, + .modal-body canvas, + .modal-body iframe { + max-width: 100% !important; + height: auto !important; + display: block; + } + + +/* ---------- C) Mobile-Vollbild & Sticky-Header/Footer ---------- */ +@supports (height: 100dvh) { + .modal { + max-height: 100dvh; + } +} + +@media (max-width: 768px) { + .overlay { + padding: 0; + } + + .modal { + width: 100vw; + height: 100vh; /* nutzt auf modernen Browsern 100dvh (s.o.) */ + max-height: 100vh; + border-radius: 0; + } + + .modal-header { + position: sticky; + top: 0; + z-index: 1; + } + + .modal-footer { + position: sticky; + bottom: 0; + z-index: 1; + } + + .modal-body { + padding: 1rem; + } + + /* Lesbare Überschriften auf Mobile */ + .modal-body h1 { + font-size: clamp(1.25rem, 5.5vw, 2rem); + } + + .modal-body h2 { + font-size: clamp(1.125rem, 5vw, 1.5rem); + } +} + +/* iOS Safe-Area (Notch) */ +@supports (padding: max(0px)) { + .modal { + padding-bottom: max(0px, env(safe-area-inset-bottom)); + } +} \ No newline at end of file diff --git a/Shared/Interfaces/IEventRegistrationService.cs b/Shared/Interfaces/IEventRegistrationService.cs index 28fa34e..864b30f 100644 --- a/Shared/Interfaces/IEventRegistrationService.cs +++ b/Shared/Interfaces/IEventRegistrationService.cs @@ -1,18 +1,30 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; +using SZUAbsolventenverein.Module.EventRegistration.Models; namespace SZUAbsolventenverein.Module.EventRegistration.Services { public interface IEventRegistrationService { - Task> GetEventRegistrationsAsync(int ModuleId); + /* Reine Events */ + Task> GetEventsAsync(int ModuleId); + Task GetEventAsync(int EventId, int ModuleId); - Task GetEventRegistrationAsync(int EventRegistrationId, int ModuleId); + Task AddEventAsync(Event NewEvent); - Task AddEventRegistrationAsync(Models.Event EventRegistration); + Task UpdateEventAsync(Event NewEvent); - Task UpdateEventRegistrationAsync(Models.Event EventRegistration); + Task DeleteEventAsync(int EventId, int ModuleId); - Task DeleteEventRegistrationAsync(int EventRegistrationId, int ModuleId); + + /* Events & Responses */ + Task AddResponseAsync(Response Response); + + Task UpdateResponseAsync(Response Response); + + Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId); + + Task> GetEventResponses(int EventId, int ModuleId); } } diff --git a/Shared/Models/Event.cs b/Shared/Models/Event.cs index 200cf42..316fdfa 100644 --- a/Shared/Models/Event.cs +++ b/Shared/Models/Event.cs @@ -9,10 +9,14 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Models public class Event : IAuditable { [Key] - public int EventRegistrationId { get; set; } + public int EventId { get; set; } public int ModuleId { get; set; } public string Name { get; set; } + public string Description { get; set; } + public DateTime EventDate { get; set; } + public string Location { get; set; } + public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } public string ModifiedBy { get; set; } diff --git a/Shared/Models/Response.cs b/Shared/Models/Response.cs index d75814f..01c84d7 100644 --- a/Shared/Models/Response.cs +++ b/Shared/Models/Response.cs @@ -14,7 +14,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Models public int OwnerId { get; set; } public int EventRegistrationId { get; set; } public int ModuleId { get; set; } - public string Name { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; }