3 Commits

Author SHA1 Message Date
48eb2283ab CI: Setup dotnet SDK before running automatic build
Some checks failed
/ build (push) Failing after 1m32s
2025-05-17 14:38:51 +02:00
d967449889 CI: Add CI branch as trigger for testing
Some checks failed
/ build (push) Failing after 48s
2025-05-14 21:50:56 +02:00
02a845c711 Add CI scripts to build the module automatically 2025-05-14 21:07:34 +02:00
24 changed files with 297 additions and 677 deletions

37
.gitea/workflows/ci.yml Normal file
View File

@ -0,0 +1,37 @@
on:
push:
branches:
- main
- ci
pull_request:
branches:
- main
- ci
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout Module
uses: https://github.com/actions/checkout@v4
with:
path: Module.EventRegistration
- name: Checkout Oqtane
uses: https://github.com/actions/checkout@v4
with:
repository: Diplomarbeit-Absolventenverein/oqtane.framework
path: oqtane.framework
ref: v6.1.1
- name: Setup Dotnet SDK
uses: https://github.com/actions/setup-dotnet@v4
with:
dotnet-version: '9.x'
- name: LS
run: ls -lisa
- name: Build Oqtane
run: dotnet build ./oqtane.framework/Oqtane.sln --configuration Debug
- name: Build Module
run: dotnet build ./Module.EventRegistration/SZUAbsolventenverein.Module.EventRegistration.sln --configuration Release
- name: Test
run: dotnet test ./Module.EventRegistration/SZUAbsolventenverein.Module.EventRegistration.sln --configuration Release --no-build

View File

@ -0,0 +1,35 @@
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
release:
types:
- published
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
- name: Verify commit exists in origin/main
run: |
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
git branch --remote --contains | grep origin/main
- name: Set VERSION variable from tag
run: echo "VERSION=${GITEA_REF/refs\/tags\/v/}" >> $GITEA_ENV
- name: Setup Dotnet SDK
uses: https://github.com/actions/setup-dotnet@v4
- name: Build
run: dotnet build --configuration Release /p:Version=${VERSION}
- name: Test
run: dotnet test --configuration Release /p:Version=${VERSION} --no-build
- name: Pack
run: dotnet pack --configuration Release /p:Version=${VERSION} --no-build --output .
- uses: https://github.com/actions/upload-artifact@v4
with:
name: nuget
if-no-files-found: error
retention-days: 7
path: ./*.nupkg

View File

@ -11,20 +11,5 @@ namespace SZUAbsolventenverein.Module.EventRegistration
{ {
_jsRuntime = jsRuntime; _jsRuntime = jsRuntime;
} }
public async Task CreateChart(string divid, string type, string[] labels, object[] datasets, object options)
{
try
{
await _jsRuntime.InvokeVoidAsync(
"SZUAbsolventenverein.EventRegistration.createChart",
divid, type, (object) labels, (object) datasets, options);
}
catch
{
// handle exception
}
}
} }
} }

View File

@ -1,41 +1,30 @@
@using Oqtane @using Oqtane.Modules.Controls
@using Oqtane.Modules.Controls
@using Oqtane.Themes.Controls
@using SZUAbsolventenverein.Module.EventRegistration.Services @using SZUAbsolventenverein.Module.EventRegistration.Services
@using SZUAbsolventenverein.Module.EventRegistration.Models @using SZUAbsolventenverein.Module.EventRegistration.Models
@using System.Text.RegularExpressions
@namespace SZUAbsolventenverein.Module.EventRegistration @namespace SZUAbsolventenverein.Module.EventRegistration
@inherits ModuleBase @inherits ModuleBase
@inject IEventRegistrationService EventRegistrationService @inject IEventRegistrationService EventRegistrationService
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@inject IStringLocalizer<Edit> Localizer @inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject IUserService UserService
@inject IProfileService ProfileService
@inject ISettingService SettingService
<h3>Anmeldung zum Event</h3> <h3>Anmeldung zum Event</h3>
<p>Willst du am Event (@_name) teilnehmen?</p> <p>Willst du am Event (@_name) teilnehmen?</p>
<span class="mb-6">@_eventDate.ToLocalTime() - @_location</span>
<div>
@((MarkupString) _description)
</div>
@if (PageState.User != null) { @if (PageState.User != null) {
@if (Status != null) @if (Status != null)
{ {
<p class="mt-2"><strong>Status: </strong> <p class="mt-3"><strong>Status:</strong>
@if (Status == true) @if (Status == true)
{ {
<span class ="fontsizeInf">@Localizer["Zugesagt"]</span><br /> @Localizer["Zusage"]
<p><button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button></p> <button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button>
} else } else
{ {
<span class="fontsizeInf"> @Localizer["Abgesagt"]</span><br /> @Localizer["Absage"]
<p><button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button></p> <button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button>
} }
</p> </p>
} else { } else {
@ -46,11 +35,7 @@
} }
} else } else
{ {
<p class="mt-3">Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.</p> <p class="mt-3">Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.</p> <Login />
<div class="gap-2">
<Login />
<UserProfile ShowRegister="true" />
</div>
} }
@code { @code {
@ -65,24 +50,21 @@
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" } new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
}; };
// private ElementReference form; private ElementReference form;
// private bool validated = false; private bool validated = false;
private int _id; private int _id;
private string _name; private string _name;
private string _description; private string _createdby;
private DateTime _eventDate; private DateTime _createdon;
private string _location; private string _modifiedby;
private DateTime _modifiedon;
private Response _response; private Response _response;
private bool? Status; private bool? Status;
private List<Profile> _profiles = new List<Profile>();
private Dictionary<string, string> _settings;
private async Task SendResponse(bool response) private async Task SendResponse(bool response)
{ {
if(ValidateProfiles()) {
if(_response == null) if(_response == null)
{ {
_response = new Response(); _response = new Response();
@ -97,14 +79,6 @@
_response = await EventRegistrationService.UpdateResponseAsync(_response); _response = await EventRegistrationService.UpdateResponseAsync(_response);
} }
if(_response != null) Status = _response.ResponseType; 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: <a href=\"{link}\">Link zum Profil</a>"), MessageType.Warning);
}
} }
private async void Zusage() private async void Zusage()
@ -121,15 +95,6 @@
{ {
try 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"]); _id = Int32.Parse(PageState.QueryString["id"]);
Event currentEvent; Event currentEvent;
@ -138,9 +103,10 @@
if (currentEvent != null) if (currentEvent != null)
{ {
_name = currentEvent.Name; _name = currentEvent.Name;
_description = currentEvent.Description; _createdby = currentEvent.CreatedBy;
_eventDate = currentEvent.EventDate; _createdon = currentEvent.CreatedOn;
_location = currentEvent.Location; _modifiedby = currentEvent.ModifiedBy;
_modifiedon = currentEvent.ModifiedOn;
} }
if(rsvp != null) if(rsvp != null)
@ -156,45 +122,40 @@
} }
} }
private async Task Save()
private bool ValidateProfiles()
{ {
foreach (Profile profile in _profiles) try
{ {
var value = GetProfileValue(profile.Name, string.Empty); validated = true;
if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(profile.DefaultValue)) var interop = new Oqtane.UI.Interop(JSRuntime);
if (await interop.FormValid(form))
{ {
_settings = SettingService.SetSetting(_settings, profile.Name, profile.DefaultValue); if (PageState.Action == "Add")
}
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{ {
if (profile.IsRequired && string.IsNullOrEmpty(value)) Event EventRegistration = new Event();
EventRegistration.ModuleId = ModuleState.ModuleId;
EventRegistration.Name = _name;
EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration);
}
else
{ {
AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], profile.Title), MessageType.Warning); Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId);
return false; EventRegistration.Name = _name;
await EventRegistrationService.UpdateEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration);
} }
if (!string.IsNullOrEmpty(profile.Validation)) NavigationManager.NavigateTo(NavigateUrl());
}
else
{ {
Regex regex = new Regex(profile.Validation); AddModuleMessage(Localizer["Message.SaveValidation"], MessageType.Warning);
bool valid = regex.Match(value).Success; }
if (!valid) }
catch (Exception ex)
{ {
AddModuleMessage(string.Format(SharedLocalizer["ProfileInvalid"], profile.Title), MessageType.Warning); await logger.LogError(ex, "Error Saving EventRegistration {Error}", ex.Message);
return false; AddModuleMessage(Localizer["Message.SaveError"], MessageType.Error);
} }
} }
} }
}
return true;
}
private string GetProfileValue(string SettingName, string DefaultValue)
{
string value = SettingService.GetSetting(_settings, SettingName, DefaultValue);
if (value.Contains("]"))
{
value = value.Substring(value.IndexOf("]") + 1);
}
return value;
}
}

View File

@ -1,7 +1,6 @@
@using Oqtane.Modules.Controls @using Oqtane.Modules.Controls
@using SZUAbsolventenverein.Module.EventRegistration.Services @using SZUAbsolventenverein.Module.EventRegistration.Services
@using SZUAbsolventenverein.Module.EventRegistration.Models @using SZUAbsolventenverein.Module.EventRegistration.Models
@using Microsoft.AspNetCore.Components.Forms
@namespace SZUAbsolventenverein.Module.EventRegistration @namespace SZUAbsolventenverein.Module.EventRegistration
@inherits ModuleBase @inherits ModuleBase
@ -17,23 +16,6 @@
<input id="name" class="form-control" @bind="@_name" required /> <input id="name" class="form-control" @bind="@_name" required />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="location" HelpText="Enter a Location" ResourceKey="Location">Location: </Label>
<div class="col-sm-9">
<input id="location" class="form-control" @bind="@_location" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="eventdate" HelpText="Enter a Date" ResourceKey="EventDate">EventDate: </Label>
<div class="col-sm-9">
<!--<input id="eventdate" class="form-control" @bind="@_eventDate" required />-->
<InputDate id="eventdate" class="form-control" @bind-Value="@_eventDate" Type="InputDateType.DateTimeLocal" />
</div>
</div>
<div class="mb-1 align-items-center">
<Label Class="" For="description" HelpText="Enter a description" ResourceKey="Description">Description: </Label>
<RichTextEditor @ref="@RichTextEditorHtml" Content="@_description" Placeholder="Enter a description"/>
</div>
</div> </div>
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button> <button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink> <NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
@ -42,7 +24,6 @@
{ {
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo> <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
} }
<div id="chart"></div>
</form> </form>
@code { @code {
@ -54,30 +35,19 @@
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
new Resource { ResourceType = ResourceType.Script, Bundle = "ChartJS", Url = "https://cdn.jsdelivr.net/npm/chart.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "ChartJS", Url = ModulePath() + "Module.js"}
}; };
private RichTextEditor RichTextEditorHtml;
private ElementReference form; private ElementReference form;
private bool validated = false; private bool validated = false;
private int _id; private int _id;
private string _name; private string _name;
private string _description;
private DateTime _eventDate = DateTime.Now;
private string _location;
private string _createdby; private string _createdby;
private DateTime _createdon; private DateTime _createdon;
private string _modifiedby; private string _modifiedby;
private DateTime _modifiedon; private DateTime _modifiedon;
bool _refresh = false;
private List<Response> _responses;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
try try
@ -89,19 +59,11 @@
if (EventRegistration != null) if (EventRegistration != null)
{ {
_name = EventRegistration.Name; _name = EventRegistration.Name;
_description = EventRegistration.Description;
_eventDate = EventRegistration.EventDate.ToLocalTime();
_location = EventRegistration.Location;
_createdby = EventRegistration.CreatedBy; _createdby = EventRegistration.CreatedBy;
_createdon = EventRegistration.CreatedOn; _createdon = EventRegistration.CreatedOn;
_modifiedby = EventRegistration.ModifiedBy; _modifiedby = EventRegistration.ModifiedBy;
_modifiedon = EventRegistration.ModifiedOn; _modifiedon = EventRegistration.ModifiedOn;
} }
_responses = await EventRegistrationService.GetEventResponses(_id, ModuleState.ModuleId);
Console.WriteLine("Responses count: " + (_responses != null ? _responses.Count.ToString() : "null"));
_refresh = true;
} }
} }
catch (Exception ex) catch (Exception ex)
@ -111,47 +73,12 @@
} }
} }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
try
{
await base.OnAfterRenderAsync(firstRender);
Console.WriteLine("Responses count: " + (_responses != null ? _responses.Count.ToString() : "null"));
if (_refresh && _responses != null)
{
List<string> labels = new List<string>();
List<object> datasets = new List<object>();
string[] colors = new string[] { "#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#00FFFF", "#0080FF", "#0000FF", "#8000FF", "#FF00FF", "#CCCCCC" };
labels.AddRange("Zusage", "Absage");
datasets.Add(new { label = "DS1", data = new int[] { _responses.Count(r => r.ResponseType == true), _responses.Count(r => r.ResponseType == false) }, fill = false, backgroundColor = colors });
object options = new { maintainAspectRatio = false, legend = new { display = true, position = "bottom", labels = new { fontColor = "white", fontSize = 16 } } };
var interop = new Interop(JSRuntime);
await interop.CreateChart("chart", "pie", labels.ToArray(), datasets.ToArray(), options);
_refresh = false;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Rendering Chart {Error}", ex.Message);
AddModuleMessage("Error Rendering Chart", MessageType.Error);
}
}
private async Task Save() private async Task Save()
{ {
try try
{ {
validated = true; validated = true;
var interop = new Oqtane.UI.Interop(JSRuntime); 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 (await interop.FormValid(form))
{ {
if (PageState.Action == "Add") if (PageState.Action == "Add")
@ -159,9 +86,6 @@
Event EventRegistration = new Event(); Event EventRegistration = new Event();
EventRegistration.ModuleId = ModuleState.ModuleId; EventRegistration.ModuleId = ModuleState.ModuleId;
EventRegistration.Name = _name; EventRegistration.Name = _name;
EventRegistration.Description = content;
EventRegistration.EventDate = _eventDate.ToUniversalTime();
EventRegistration.Location = _location;
EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration); EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration); await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration);
} }
@ -169,9 +93,6 @@
{ {
Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId); Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId);
EventRegistration.Name = _name; EventRegistration.Name = _name;
EventRegistration.Description = content;
EventRegistration.EventDate = _eventDate.ToUniversalTime();
EventRegistration.Location = _location;
await EventRegistrationService.UpdateEventAsync(EventRegistration); await EventRegistrationService.UpdateEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration); await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration);
} }

View File

@ -16,38 +16,24 @@ else
<ActionLink Action="Add" Security="SecurityAccessLevel.Edit" Text="Add Event" ResourceKey="Add" /> <ActionLink Action="Add" Security="SecurityAccessLevel.Edit" Text="Add Event" ResourceKey="Add" />
<br /> <br />
<br /> <br />
<p>@Status</p>
@if (@_EventRegistrations.Count != 0) @if (@_EventRegistrations.Count != 0)
{ {
<Pager Items="@_EventRegistrations">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Name"]</th>
<th style="width: 1px;">&nbsp;</th>
</Header>
<Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.EventId.ToString())" ResourceKey="Edit" /></td>
<td><ActionDialog Header="Delete EventRegistration" Message="Are You Sure You Wish To Delete This EventRegistration?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" Id="@context.EventId.ToString()" /></td>
<td>@context.Name</td>
<div class="event-list"> <td><ActionLink Action="Details" Parameters="@($"id=" + context.EventId.ToString())" ResourceKey="Details"/></td>
<div class="event-list"> </Row>
@foreach (var context in _EventRegistrations) </Pager>
{
<div class="event-card">
<h3>@context.Name</h3>
<p><strong>@Localizer["Date"]:</strong> @context.EventDate.ToLocalTime()</p>
<p><strong>@Localizer["Location"]:</strong> @context.Location</p>
<div class="event-actions">
<ActionLink Action="Edit"
Parameters="@($"id={context.EventId}")"
ResourceKey="Edit" />
<ActionDialog Action="Delete"
Security="SecurityAccessLevel.Edit"
Class="btn btn-danger"
OnClick="@(async () => await Delete(context))"
ResourceKey="Delete"
Id="@context.EventId.ToString()" />
<ActionLink Action="Details"
Parameters="@($"id={context.EventId}")"
ResourceKey="Details" />
</div>
</div>
}
</div>
</div>
} }
else else
{ {
@ -56,6 +42,8 @@ else
} }
@code { @code {
private string Status;
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
@ -92,4 +80,15 @@ else
AddModuleMessage(Localizer["Message.DeleteError"], MessageType.Error); 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";
}
} }

View File

@ -9,9 +9,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration
{ {
Name = "EventRegistration", Name = "EventRegistration",
Description = "A module to manage registration for events", Description = "A module to manage registration for events",
Version = "1.0.17", Version = "1.0.0",
ServerManagerType = "SZUAbsolventenverein.Module.EventRegistration.Manager.EventRegistrationManager, SZUAbsolventenverein.Module.EventRegistration.Server.Oqtane", ServerManagerType = "SZUAbsolventenverein.Module.EventRegistration.Manager.EventRegistrationManager, SZUAbsolventenverein.Module.EventRegistration.Server.Oqtane",
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", ReleaseVersions = "1.0.0",
Dependencies = "SZUAbsolventenverein.Module.EventRegistration.Shared.Oqtane", Dependencies = "SZUAbsolventenverein.Module.EventRegistration.Shared.Oqtane",
PackageName = "SZUAbsolventenverein.Module.EventRegistration" PackageName = "SZUAbsolventenverein.Module.EventRegistration"
}; };

View File

@ -127,10 +127,10 @@
<value>Delete</value> <value>Delete</value>
</data> </data>
<data name="Delete.Header" xml:space="preserve"> <data name="Delete.Header" xml:space="preserve">
<value>Delete</value> <value>Delete Event</value>
</data> </data>
<data name="Delete.Message" xml:space="preserve"> <data name="Delete.Message" xml:space="preserve">
<value>Are You Sure You Wish To Delete This Event? If you delete an event, all existing registrations will be deleted as well.</value> <value>Are You Sure You Wish To Delete This Event?</value>
</data> </data>
<data name="Message.DisplayNone" xml:space="preserve"> <data name="Message.DisplayNone" xml:space="preserve">
<value>No Events To Display</value> <value>No Events To Display</value>
@ -142,15 +142,6 @@
<value>Error Deleting Event</value> <value>Error Deleting Event</value>
</data> </data>
<data name="Details.Text" xml:space="preserve"> <data name="Details.Text" xml:space="preserve">
<value>Details</value> <value>Reject</value>
</data>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Date" xml:space="preserve">
<value>Date</value>
</data>
<data name="Location" xml:space="preserve">
<value>Location</value>
</data> </data>
</root> </root>

View File

@ -13,11 +13,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.9" /> <PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.9" /> <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.3" />
<PackageReference Include="System.Net.Http.Json" Version="9.0.9" /> <PackageReference Include="System.Net.Http.Json" Version="9.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -15,6 +15,27 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
private string Apiurl => CreateApiUrl("EventRegistration"); private string Apiurl => CreateApiUrl("EventRegistration");
/*public async Task<List<Models.Event>> GetEventRegistrationsAsync(int ModuleId)
{
List<Models.Event> EventRegistrations = await GetJsonAsync<List<Models.Event>>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Models.Event>().ToList());
return EventRegistrations.OrderBy(item => item.Name).ToList();
}
public async Task<Models.Event> GetEventRegistrationAsync(int EventRegistrationId, int ModuleId)
{
return await GetJsonAsync<Models.Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistrationId}/{ModuleId}", EntityNames.Module, ModuleId));
}
public async Task<Models.Event> AddEventRegistrationAsync(Models.Event EventRegistration)
{
return await PostJsonAsync<Models.Event>(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, EventRegistration.ModuleId), EventRegistration);
}
public async Task<Models.Event> UpdateEventRegistrationAsync(Models.Event EventRegistration)
{
return await PutJsonAsync<Models.Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistration.EventRegistrationId}", EntityNames.Module, EventRegistration.ModuleId), EventRegistration);
}*/
public async Task<List<Event>> GetEventsAsync(int ModuleId) public async Task<List<Event>> GetEventsAsync(int ModuleId)
{ {
List<Event> EventRegistrations = await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Event>().ToList()); List<Event> EventRegistrations = await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Event>().ToList());
@ -30,9 +51,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent); return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent);
} }
public async Task<Event> UpdateEventAsync(Event UpdatedEvent) public async Task<Event> UpdateEventAsync(Event NewEvent)
{ {
return await PutJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{UpdatedEvent.EventId}", EntityNames.Module, UpdatedEvent.ModuleId), UpdatedEvent); return await PutJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{NewEvent.EventId}", EntityNames.Module, NewEvent.ModuleId), NewEvent);
} }
public async Task DeleteEventAsync(int EventId, int ModuleId) public async Task DeleteEventAsync(int EventId, int ModuleId)
@ -55,12 +76,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId)); return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
} }
public async Task<List<Response>> GetEventResponses(int EventId, int ModuleId) public Task<List<Response>> GetEventResponses(int EventId, int ModuleId)
{
return await GetJsonAsync<List<Response>>(CreateAuthorizationPolicyUrl($"{Apiurl}/all-responses/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
}
public Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Oqtane.Services; using Oqtane.Services;
using System.Linq;
using SZUAbsolventenverein.Module.EventRegistration.Services; using SZUAbsolventenverein.Module.EventRegistration.Services;
namespace SZUAbsolventenverein.Module.EventRegistration.Startup namespace SZUAbsolventenverein.Module.EventRegistration.Startup
@ -8,11 +7,8 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Startup
public class ClientStartup : IClientStartup public class ClientStartup : IClientStartup
{ {
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{
if (!services.Any(s => s.ServiceType == typeof(IEventRegistrationService)))
{ {
services.AddScoped<IEventRegistrationService, EventRegistrationService>(); services.AddScoped<IEventRegistrationService, EventRegistrationService>();
} }
} }
} }
}

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>$projectname$</id> <id>$projectname$</id>
<version>1.0.17</version> <version>1.0.0</version>
<authors>SZUAbsolventenverein</authors> <authors>SZUAbsolventenverein</authors>
<owners>SZUAbsolventenverein</owners> <owners>SZUAbsolventenverein</owners>
<title>EventRegistration</title> <title>EventRegistration</title>
@ -16,7 +16,7 @@
<releaseNotes></releaseNotes> <releaseNotes></releaseNotes>
<summary></summary> <summary></summary>
<dependencies> <dependencies>
<dependency id="Oqtane.Framework" version="6.2.0" /> <dependency id="Oqtane.Framework" version="6.1.1" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View File

@ -3,10 +3,10 @@
TargetFramework=$1 TargetFramework=$1
ProjectName=$2 ProjectName=$2
cp -f "../Client/bin/Debug/$TargetFramework/$ProjectName.Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Client/bin/Debug/$TargetFramework/$ProjectName$.Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -f "../Client/bin/Debug/$TargetFramework/$ProjectName.Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Client/bin/Debug/$TargetFramework/$ProjectName$.Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -f "../Server/bin/Debug/$TargetFramework/$ProjectName.Server.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Server/bin/Debug/$TargetFramework/$ProjectName$.Server.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -f "../Server/bin/Debug/$TargetFramework/$ProjectName.Server.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Server/bin/Debug/$TargetFramework/$ProjectName$.Server.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -f "../Shared/bin/Debug/$TargetFramework/$ProjectName.Shared.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Shared/bin/Debug/$TargetFramework/$ProjectName$.Shared.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -f "../Shared/bin/Debug/$TargetFramework/$ProjectName.Shared.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/" cp -f "../Shared/bin/Debug/$TargetFramework/$ProjectName$.Shared.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/$TargetFramework/"
cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/" cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/"

View File

@ -1,5 +1,6 @@
TargetFramework=$1 TargetFramework=$1
ProjectName=$2 ProjectName=$2
"..\..\oqtane.framework\oqtane.package\nuget.exe" pack %ProjectName%.nuspec -Properties targetframework=%TargetFramework%;projectname=%ProjectName% ../../oqtane.framework/Oqtane.Package/nuget.exe pack %ProjectName%.nuspec -Properties targetframework=%TargetFramework%;projectname=%ProjectName%
cp -f "*.nupkg" "..\..\oqtane.framework\Oqtane.Server\Packages\" cp -f "*.nupkg" "..\..\oqtane.framework\Oqtane.Server\Packages\"

View File

@ -131,24 +131,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
} }
} }
// GET api/<controller>/5
[HttpGet("all-respones/{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<List<Models.Response>> GetResponses(int id, int moduleid)
{
List<Models.Response> eventResponses = await _EventRegistrationService.GetEventResponses(id, moduleid);
if (eventResponses != null && IsAuthorizedEntityId(EntityNames.Module, moduleid))
{
return eventResponses;
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {EventRegistrationId} {ModuleId}", id, moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// TODO: Add Event Response Endpoints. // TODO: Add Event Response Endpoints.
} }
} }

View File

@ -40,19 +40,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
{ {
// TODO: Export event Responses as well. // TODO: Export event Responses as well.
string content = ""; string content = "";
List<object> exportData = new List<object>(); List<Models.Event> EventRegistrations = _EventRepository.GetEvents(module.ModuleId).ToList();
foreach (var events in _EventRepository.GetEvents(module.ModuleId)) if (EventRegistrations != null)
{ {
var responses = _ResponseRepository.GetResponses(events.EventId, module.ModuleId); content = JsonSerializer.Serialize(EventRegistrations);
exportData.Add(new
{
Event = events,
Responses = responses.ToList()
});
};
if (exportData != null)
{
content = JsonSerializer.Serialize(exportData);
} }
return content; return content;
} }

View File

@ -26,10 +26,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
var responseEB = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase); var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase);
responseEB.Drop(); entityBuilder.Drop();
var eventEB = new EventEntityBuilder(migrationBuilder, ActiveDatabase); var entityBuilder2 = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase);
eventEB.Drop(); entityBuilder2.Drop();
} }
} }
} }

View File

@ -1,35 +0,0 @@
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
}
}
}

View File

@ -19,10 +19,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.9" /> <PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -6,7 +6,6 @@ using Oqtane.Enums;
using Oqtane.Extensions; using Oqtane.Extensions;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Models; using Oqtane.Models;
using Oqtane.Repository;
using Oqtane.Security; using Oqtane.Security;
using Oqtane.Shared; using Oqtane.Shared;
using SZUAbsolventenverein.Module.EventRegistration.Models; using SZUAbsolventenverein.Module.EventRegistration.Models;
@ -18,19 +17,15 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
{ {
private readonly IEventRepository _EventRepository; private readonly IEventRepository _EventRepository;
private readonly IResponseRepository _ResponseRepository; private readonly IResponseRepository _ResponseRepository;
private readonly INotificationRepository _NotificationRepository;
private readonly IUserRepository _UserRepository;
private readonly IUserPermissions _userPermissions; private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger; private readonly ILogManager _logger;
private readonly IHttpContextAccessor _accessor; private readonly IHttpContextAccessor _accessor;
private readonly Alias _alias; private readonly Alias _alias;
public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, INotificationRepository NotificationRepository, IUserRepository UserRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor) public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
{ {
_EventRepository = EventRepository; _EventRepository = EventRepository;
_ResponseRepository = ResponseRepository; _ResponseRepository = ResponseRepository;
_NotificationRepository = NotificationRepository;
_UserRepository = UserRepository;
_userPermissions = userPermissions; _userPermissions = userPermissions;
_logger = logger; _logger = logger;
_accessor = accessor; _accessor = accessor;
@ -57,12 +52,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View)) if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View))
{ {
Response = _ResponseRepository.AddResponse(Response); 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); _logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response);
} }
else else
@ -79,12 +68,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View)) if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View))
{ {
Response = _ResponseRepository.UpdateResponse(Response); 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); _logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response);
} }
else else
@ -122,34 +105,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
} }
} }
public Task<List<Event>> 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<Event> UpdateEventAsync(Event UpdatedEvent)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, UpdatedEvent.ModuleId, PermissionNames.Edit))
{
UpdatedEvent = _EventRepository.UpdateEvent(UpdatedEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Event Updated {NewEvent}", UpdatedEvent);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Update Attempt {NewEvent}", UpdatedEvent);
UpdatedEvent = null;
}
return Task.FromResult(UpdatedEvent);
}
public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId) public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId)
{ {
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
@ -176,19 +131,87 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Response Get Attempt {ModuleId}", ModuleId); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Response Get Attempt {ModuleId}", ModuleId);
return null; return null;
} }
}
public Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId)
{
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public Task<List<Event>> GetEventsAsync(int ModuleId)
private void SendEventResponseNotification(string subject, string body)
{ {
User user = _UserRepository.GetUser(_accessor.HttpContext.User.UserId()); if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
Notification notification = new Notification(_alias.SiteId, user, subject, body); {
_NotificationRepository.AddNotification(notification); 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<Event> 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<Models.Event> GetEventRegistrationAsync(int EventRegistrationId, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_EventRegistrationRepository.GetEventRegistration(EventRegistrationId));
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {EventRegistrationId} {ModuleId}", EventRegistrationId, ModuleId);
return null;
}
}
public Task<Models.Event> AddEventRegistrationAsync(Models.Event EventRegistration)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, EventRegistration.ModuleId, PermissionNames.Edit))
{
EventRegistration = _EventRegistrationRepository.AddEventRegistration(EventRegistration);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {EventRegistration}", EventRegistration);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {EventRegistration}", EventRegistration);
EventRegistration = null;
}
return Task.FromResult(EventRegistration);
}
public Task<Models.Event> UpdateEventRegistrationAsync(Models.Event EventRegistration)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, EventRegistration.ModuleId, PermissionNames.Edit))
{
EventRegistration = _EventRegistrationRepository.UpdateEventRegistration(EventRegistration);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "EventRegistration Updated {EventRegistration}", EventRegistration);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Update Attempt {EventRegistration}", EventRegistration);
EventRegistration = null;
}
return Task.FromResult(EventRegistration);
}
}*/
}
} }

View File

@ -1,201 +1 @@
/* Module Custom Styles */ /* Module Custom Styles */
.mb-6 {
margin-bottom: 6rem;
}
.mt-3 {
margin-top: 3rem;
}
.mt-2 strong {
font-size: 1.4rem; /* Textgr<67><72>e <20> Standard ist ca. 1rem */
font-weight: 700;
}
.fontsizeInf {
font-size: 1.4rem; /* Textgr<67><72>e <20> 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 <20>belt<6C>ter
box-shadow: 0 6px 14px rgba(0,0,0,0.5);
}
*/
/* nachher <20> 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<65>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<65>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 <20>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));
}
}

View File

@ -2,25 +2,4 @@
var SZUAbsolventenverein = SZUAbsolventenverein || {}; var SZUAbsolventenverein = SZUAbsolventenverein || {};
SZUAbsolventenverein.EventRegistration = { SZUAbsolventenverein.EventRegistration = {
createChart: async function (divid, type, labels, datasets, options) {
var container = document.getElementById(divid);
if (container.hasChildNodes()) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
}
var canvas = document.createElement('canvas');
canvas.id = divid + '-canvas';
container.appendChild(canvas);
var ctx = canvas.getContext('2d');
var chart = new Chart(ctx, {
type: type,
data: {
labels: labels,
datasets: datasets
},
options: options
});
}
}; };

View File

@ -5,84 +5,26 @@ using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Services namespace SZUAbsolventenverein.Module.EventRegistration.Services
{ {
/// <summary>
/// Methods for managing events and their responses
/// </summary>
public interface IEventRegistrationService public interface IEventRegistrationService
{ {
/// <summary> /* Reine Events */
/// Alle Events eines Moduls abrufen
/// </summary>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Liste aller Veranstaltungen</returns>
Task<List<Event>> GetEventsAsync(int ModuleId); Task<List<Event>> GetEventsAsync(int ModuleId);
/// <summary>
/// Ein bestimmtes Event abrufen
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Das Event selbst</returns>
Task<Event> GetEventAsync(int EventId, int ModuleId); Task<Event> GetEventAsync(int EventId, int ModuleId);
/// <summary>
/// Ein neues Event anlegen
/// </summary>
/// <param name="NewEvent">das anzulegende Event</param>
/// <returns>das angelegte Event</returns>
Task<Event> AddEventAsync(Event NewEvent); Task<Event> AddEventAsync(Event NewEvent);
/// <summary> Task<Event> UpdateEventAsync(Event NewEvent);
/// Ändern eines bestehenden Events
/// </summary>
/// <param name="UpdatedEvent">Das Eventobjekt mit aktualisierte Event</param>
/// <returns>das gespeicherte Event</returns>
Task<Event> UpdateEventAsync(Event UpdatedEvent);
/// <summary>
/// Löschen eines Events
/// </summary>
/// <param name="EventId">das zu löschende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns></returns>
Task DeleteEventAsync(int EventId, int ModuleId); Task DeleteEventAsync(int EventId, int ModuleId);
/// <summary>
/// Eine neue Antwort zu einem Event hinzufügen /* Events & Responses */
/// </summary>
/// <param name="Response">die Antwort</param>
/// <returns>die gespeicherte Antwort</returns>
Task<Response> AddResponseAsync(Response Response); Task<Response> AddResponseAsync(Response Response);
/// <summary>
/// Eine bestehende Antwort zu einem Event aktualisieren
/// </summary>
/// <param name="Response">die neue Antwort</param>
/// <returns>die gespeicherte neue Antwort</returns>
Task<Response> UpdateResponseAsync(Response Response); Task<Response> UpdateResponseAsync(Response Response);
/// <summary>
/// Details zu einem Event abrufen (Event + Antwort vom auktuellen Benutzer)
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Tuple aus Event und Antwort</returns>
Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId); Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId);
/// <summary>
/// Alle Antworten zu einem Event abrufen
/// </summary>
/// <param name="EventId">das Event, dessen Antworten geladen werden sollen</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Liste aller Antworten auf das Event</returns>
Task<List<Response>> GetEventResponses(int EventId, int ModuleId); Task<List<Response>> GetEventResponses(int EventId, int ModuleId);
/// <summary>
/// 10 Antworten eines Events abrufen, welche gewichtet zurückgeliefert werden
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="MouleId">das aufrufende Modul</param>
/// <returns>Liste mit 10 </returns>
Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId);
} }
} }

View File

@ -13,10 +13,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Models
public int ModuleId { get; set; } public int ModuleId { get; set; }
public string Name { 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 string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; } public DateTime CreatedOn { get; set; }
public string ModifiedBy { get; set; } public string ModifiedBy { get; set; }