From 2c50a229662916bb87221d26890ae675513b4366 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 5 Mar 2026 00:13:05 +0100
Subject: [PATCH 1/9] add ability to add multiple categories/pages to events
---
.config/StartSch.run.xml | 2 +-
StartSch/Components/Pages/EventEditPage.razor | 109 +++++++++++++++++-
StartSch/Data/CollaborationRequest.cs | 18 +++
StartSch/Data/Db.cs | 5 +-
.../Sqlite/SqliteDbModelSnapshot.cs | 66 +++++++++++
StartSch/Services/UserInfoService.cs | 13 ++-
6 files changed, 205 insertions(+), 8 deletions(-)
create mode 100644 StartSch/Data/CollaborationRequest.cs
diff --git a/.config/StartSch.run.xml b/.config/StartSch.run.xml
index b2b73e62..7d8ad232 100644
--- a/.config/StartSch.run.xml
+++ b/.config/StartSch.run.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/StartSch/Components/Pages/EventEditPage.razor b/StartSch/Components/Pages/EventEditPage.razor
index 5b7df930..c0460437 100644
--- a/StartSch/Components/Pages/EventEditPage.razor
+++ b/StartSch/Components/Pages/EventEditPage.razor
@@ -12,6 +12,7 @@
@inject NavigationManager Navigation
@inject IServiceProvider ServiceProvider
@inject AuthorizationService AuthorizationService
+@inject InterestService InterestService
@if (!IsResourceAvailable(
_event,
@@ -61,6 +62,65 @@
+
+
+
+
+ Kiválasztott kollaboráló körök
+
+
+ @if (_model.CollaborationCategories.Count > 0)
+ {
+
+ @foreach (var category in _model.CollaborationCategories)
+ {
+
+ @(category.Name ?? category.Page.Name ?? category.Page.PekName)
+
+
+ }
+
+ }
+
+
+ Kollaboráló kör
+
+
+ @foreach (var e in _administeredCategories.Where(c => !_model.CollaborationCategories.Contains(c)).Distinct())
+ {
+
+ }
+
+
+
+
+
+ Second Column Button
+
+
+ Kollaborálónak meghívható kör
+
+
+ @foreach (var e in _possibleParents)
+ {
+
+ }
+
+
+
+
+
+
-
+
@{
_event.Start = _model.Start?.ToLocalDateTime().InZoneLeniently(Utils.HungarianTimeZone).ToInstant();
@@ -126,7 +187,9 @@
private readonly List _possibleParents = [];
private readonly EventEditModel _model = new();
private bool _isBusy;
-
+ private int? _selectedCollaborationCategoryId;
+ private List? _administeredPages;
+ private readonly List _administeredCategories = [];
[Parameter] public int EventId { get; set; }
[SupplyParameterFromQuery(Name = "categories")]
@@ -139,6 +202,16 @@
{
await using var db = await DbFactory.CreateDbContextAsync();
+ var index = await InterestService.LoadIndex;
+ _administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
+ if (_administeredPages != null)
+ {
+ _administeredPages.ForEach(p =>
+ {
+ _administeredCategories.AddRange(p.Categories);
+ });
+ }
+
if (EventId == 0) // new event
{
Event? parent = ParentId.HasValue
@@ -181,6 +254,8 @@
.FirstOrDefaultAsync(e => e.Id == EventId);
if (_event == null)
return;
+
+ _model.CollaborationCategories = _event.Categories.ToList();
}
_model.Start = (_event.Start ?? SystemClock.Instance.GetCurrentInstant())
@@ -192,6 +267,7 @@
?? _model.Start;
_model.Title = _event.Title;
_model.DescriptionMarkdown = _event.DescriptionMarkdown;
+
if (_event.Parent != null)
{
_possibleParents.Add(_event.Parent);
@@ -210,7 +286,7 @@
Event savedEvent = await eventService.Save(
EventId,
_event!.ParentId,
- _event.Categories.Select(e => e.Id).ToHashSet(),
+ _event.Categories.Select(e => e.Id).Union(_model.CollaborationCategories.Select(e => e.Id)).ToHashSet(),
_model.Title,
_model.DescriptionMarkdown,
_model.Start?.ToLocalDateTime().InZoneLeniently(Utils.HungarianTimeZone).ToInstant(),
@@ -220,6 +296,30 @@
Navigation.NavigateTo($"/events/{savedEvent.Id}");
}
+ private int? SelectedCollaborationCategoryId
+ {
+ get => _selectedCollaborationCategoryId;
+ set
+ {
+ _selectedCollaborationCategoryId = value;
+ if (value.HasValue)
+ {
+ var category = _administeredCategories.FirstOrDefault(c => c.Id == value.Value);
+ if (category != null)
+ {
+ if (!_model.CollaborationCategories.Contains(category))
+ _model.CollaborationCategories.Add(category);
+ }
+ _selectedCollaborationCategoryId = null;
+ }
+ }
+ }
+
+ private void RemoveCollaborationCategory(Category category)
+ {
+ _model.CollaborationCategories.Remove(category);
+ }
+
private class EventEditModel
{
public DateTime? Start
@@ -235,6 +335,7 @@
public DateTime? End { get; set; }
public int? ParentId { get; set; }
+ public List CollaborationCategories { get; set; } = [];
[Length(1, 100)] public string Title { get; set; } = "";
[MaxLength(20000)] public string? DescriptionMarkdown { get; set; }
diff --git a/StartSch/Data/CollaborationRequest.cs b/StartSch/Data/CollaborationRequest.cs
new file mode 100644
index 00000000..246b082d
--- /dev/null
+++ b/StartSch/Data/CollaborationRequest.cs
@@ -0,0 +1,18 @@
+namespace StartSch.Data;
+
+public abstract class CollaborationRequest
+{
+ public int Id { get; set; }
+}
+
+public class EventCollaborationRequest : CollaborationRequest
+{
+ public int EventId { get; set; }
+ public Event Event { get; set; } = null!;
+}
+
+public class PostCollaborationRequest : CollaborationRequest
+{
+ public int PostId { get; set; }
+ public Post Post { get; set; } = null!;
+}
diff --git a/StartSch/Data/Db.cs b/StartSch/Data/Db.cs
index 93384a23..e8244e2a 100644
--- a/StartSch/Data/Db.cs
+++ b/StartSch/Data/Db.cs
@@ -15,10 +15,13 @@ public class Db(DbContextOptions options) : DbContext(options), IDataProtectionK
public DbSet Posts => Set();
public DbSet PushSubscriptions => Set();
public DbSet Users => Set();
-
+
public DbSet Interests => Set();
public DbSet CategoryInterests => Set();
public DbSet EventInterests => Set();
+ public DbSet CollaborationRequests => Set();
+ public DbSet EventCollaborationRequests => Set();
+ public DbSet PostCollaborationRequests => Set();
public DbSet ShowEventsInCategory => Set();
public DbSet ShowPostsForEvent => Set();
public DbSet ShowPostsInCategory => Set();
diff --git a/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs b/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
index 6bd000e0..a064c96e 100644
--- a/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
+++ b/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
@@ -106,6 +106,26 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("CategoryIncludes");
});
+ modelBuilder.Entity("StartSch.Data.CollaborationRequest", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Discriminator")
+ .IsRequired()
+ .HasMaxLength(34)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("CollaborationRequests");
+
+ b.HasDiscriminator().HasValue("CollaborationRequest");
+
+ b.UseTphMappingStrategy();
+ });
+
modelBuilder.Entity("StartSch.Data.EmailMessage", b =>
{
b.Property("Id")
@@ -528,6 +548,30 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasDiscriminator().HasValue("SendPushNotification");
});
+ modelBuilder.Entity("StartSch.Data.EventCollaborationRequest", b =>
+ {
+ b.HasBaseType("StartSch.Data.CollaborationRequest");
+
+ b.Property("EventId")
+ .HasColumnType("INTEGER");
+
+ b.HasIndex("EventId");
+
+ b.HasDiscriminator().HasValue("EventCollaborationRequest");
+ });
+
+ modelBuilder.Entity("StartSch.Data.PostCollaborationRequest", b =>
+ {
+ b.HasBaseType("StartSch.Data.CollaborationRequest");
+
+ b.Property("PostId")
+ .HasColumnType("INTEGER");
+
+ b.HasIndex("PostId");
+
+ b.HasDiscriminator().HasValue("PostCollaborationRequest");
+ });
+
modelBuilder.Entity("StartSch.Data.PincerOpening", b =>
{
b.HasBaseType("StartSch.Data.Event");
@@ -805,6 +849,28 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("User");
});
+ modelBuilder.Entity("StartSch.Data.EventCollaborationRequest", b =>
+ {
+ b.HasOne("StartSch.Data.Event", "Event")
+ .WithMany()
+ .HasForeignKey("EventId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Event");
+ });
+
+ modelBuilder.Entity("StartSch.Data.PostCollaborationRequest", b =>
+ {
+ b.HasOne("StartSch.Data.Post", "Post")
+ .WithMany()
+ .HasForeignKey("PostId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Post");
+ });
+
modelBuilder.Entity("StartSch.Data.CategoryInterest", b =>
{
b.HasOne("StartSch.Data.Category", "Category")
diff --git a/StartSch/Services/UserInfoService.cs b/StartSch/Services/UserInfoService.cs
index 51201496..a86ef319 100644
--- a/StartSch/Services/UserInfoService.cs
+++ b/StartSch/Services/UserInfoService.cs
@@ -19,12 +19,21 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
// Ensure we don't create the same Page twice
await using var tx = await db.BeginTransaction(IsolationLevel.Serializable);
-
+
User user = await db.Users
.FirstOrDefaultAsync(u => u.AuthSchId == authSchId)
?? db.Users.Add(new() { AuthSchId = authSchId }).Entity;
AuthSchUserInfo userInfo = context.User.Deserialize(Utils.JsonSerializerOptions)!;
+ userInfo = new AuthSchUserInfo(
+ userInfo.Email,
+ userInfo.EmailVerified,
+ new List
+ {
+ new(106, "KIR fejlesztők és üzemeltetők", new List { "Adminisztrátor" }),
+ new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" })
+ }
+ );
user.AuthSchEmail = userInfo.EmailVerified ? userInfo.Email : null;
@@ -92,7 +101,7 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
int updates = await db.SaveChangesAsync();
await tx.CommitAsync();
-
+
if (updates > 0)
cache.Remove(InterestService.CacheKey);
From 876e1f9d90b32c974916df67f41dfad616b282af Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 5 Mar 2026 15:51:45 +0100
Subject: [PATCH 2/9] Add ability to make collaboration requests events/posts
---
StartSch/Components/Pages/EventEditPage.razor | 85 +++++++--
StartSch/Components/Pages/PostEditPage.razor | 162 +++++++++++++++++-
StartSch/Data/CollaborationRequest.cs | 2 +
.../Sqlite/SqliteDbModelSnapshot.cs | 16 ++
StartSch/Services/EventService.cs | 44 +++++
StartSch/Services/PostService.cs | 45 ++++-
StartSch/Services/UserInfoService.cs | 3 +-
7 files changed, 332 insertions(+), 25 deletions(-)
diff --git a/StartSch/Components/Pages/EventEditPage.razor b/StartSch/Components/Pages/EventEditPage.razor
index c0460437..15562dca 100644
--- a/StartSch/Components/Pages/EventEditPage.razor
+++ b/StartSch/Components/Pages/EventEditPage.razor
@@ -98,22 +98,36 @@
-
- Second Column Button
-
+
+ Kiválasztott kollaborálónak meghívható körök
+
+
+ @if (_model.PossibleCollaborationPages.Count > 0)
+ {
+
+ @foreach (var page in _model.PossibleCollaborationPages)
+ {
+
+ @(page.Name ?? page.Name ?? page.PekName)
+
+
+ }
+
+ }
Kollaborálónak meghívható kör
-
+
- @foreach (var e in _possibleParents)
+ @foreach (var e in _possibleCollaborationPages)
{
-
+ @if (e.Name != null || e.PekName != null)
+ {
+
+ }
}
@@ -190,6 +204,7 @@
private int? _selectedCollaborationCategoryId;
private List
? _administeredPages;
private readonly List _administeredCategories = [];
+ private List _possibleCollaborationPages = [];
[Parameter] public int EventId { get; set; }
[SupplyParameterFromQuery(Name = "categories")]
@@ -206,10 +221,7 @@
_administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
if (_administeredPages != null)
{
- _administeredPages.ForEach(p =>
- {
- _administeredCategories.AddRange(p.Categories);
- });
+ _administeredPages.ForEach(p => { _administeredCategories.AddRange(p.Categories); });
}
if (EventId == 0) // new event
@@ -243,6 +255,11 @@
.ToListAsync();
newEvent.Categories.AddRange(categories);
+ var administeredPageIds = _administeredPages?.Select(p => p.Id).ToList() ?? [];
+ _possibleCollaborationPages = await db.Pages
+ .Where(p => !administeredPageIds.Contains(p.Id))
+ .ToListAsync();
+
_event = newEvent;
}
else // editing
@@ -254,10 +271,15 @@
.FirstOrDefaultAsync(e => e.Id == EventId);
if (_event == null)
return;
-
+
_model.CollaborationCategories = _event.Categories.ToList();
+ _model.PossibleCollaborationPages = await db.EventCollaborationRequests
+ .Where(r => r.EventId == _event.Id)
+ .Select(r => r.Page)
+ .ToListAsync();
}
+
_model.Start = (_event.Start ?? SystemClock.Instance.GetCurrentInstant())
.InZone(Utils.HungarianTimeZone)
.ToDateTimeUnspecified();
@@ -287,6 +309,7 @@
EventId,
_event!.ParentId,
_event.Categories.Select(e => e.Id).Union(_model.CollaborationCategories.Select(e => e.Id)).ToHashSet(),
+ _model.PossibleCollaborationPages.Select(p => p.Id).ToHashSet(),
_model.Title,
_model.DescriptionMarkdown,
_model.Start?.ToLocalDateTime().InZoneLeniently(Utils.HungarianTimeZone).ToInstant(),
@@ -310,6 +333,7 @@
if (!_model.CollaborationCategories.Contains(category))
_model.CollaborationCategories.Add(category);
}
+
_selectedCollaborationCategoryId = null;
}
}
@@ -320,6 +344,32 @@
_model.CollaborationCategories.Remove(category);
}
+ private int? SelectedPossibleCollaborationPageId
+ {
+ get => _selectedCollaborationCategoryId;
+ set
+ {
+ _selectedCollaborationCategoryId = value;
+ if (value.HasValue)
+ {
+ var page = _possibleCollaborationPages.FirstOrDefault(p => p.Id == value.Value);
+ if (page != null)
+ {
+ if (!_model.PossibleCollaborationPages.Contains(page))
+ _model.PossibleCollaborationPages.Add(page);
+ }
+
+ _selectedCollaborationCategoryId = null;
+ }
+ }
+ }
+
+ private void RemovePossibleCollaborationPage(Page page)
+ {
+ _model.PossibleCollaborationPages.Remove(page);
+ }
+
+
private class EventEditModel
{
public DateTime? Start
@@ -336,6 +386,7 @@
public DateTime? End { get; set; }
public int? ParentId { get; set; }
public List CollaborationCategories { get; set; } = [];
+ public List PossibleCollaborationPages { get; set; } = [];
[Length(1, 100)] public string Title { get; set; } = "";
[MaxLength(20000)] public string? DescriptionMarkdown { get; set; }
diff --git a/StartSch/Components/Pages/PostEditPage.razor b/StartSch/Components/Pages/PostEditPage.razor
index d6f34697..f54d620d 100644
--- a/StartSch/Components/Pages/PostEditPage.razor
+++ b/StartSch/Components/Pages/PostEditPage.razor
@@ -11,6 +11,7 @@
@inject NavigationManager Nav
@inject IServiceProvider ServiceProvider
@inject AuthorizationService AuthorizationService
+@inject InterestService InterestService
@if (!IsResourceAvailable(_post, AuthorizationService.CanEdit, out var unavailableStatus))
{
@@ -56,6 +57,79 @@
+
+
+
+
+ Kiválasztott kollaboráló körök
+
+
+ @if (_model.CollaborationCategories.Count > 0)
+ {
+
+ @foreach (var category in _model.CollaborationCategories)
+ {
+
+ @(category.Name ?? category.Page.Name ?? category.Page.PekName)
+
+
+ }
+
+ }
+
+
+ Kollaboráló kör
+
+
+ @foreach (var e in _administeredCategories.Where(c => !_model.CollaborationCategories.Contains(c)).Distinct())
+ {
+
+ }
+
+
+
+
+
+ Kiválasztott kollaborálónak meghívható körök
+
+
+ @if (_model.PossibleCollaborationPages.Count > 0)
+ {
+
+ @foreach (var page in _model.PossibleCollaborationPages)
+ {
+
+ @(page.Name ?? page.Name ?? page.PekName)
+
+
+ }
+
+ }
+
+ Kollaborálónak meghívható kör
+
+
+ @foreach (var e in _possibleCollaborationPages)
+ {
+ @if (e.Name != null || e.PekName != null)
+ {
+
+ }
+ }
+
+
+
+
+
+
-
+
@{
_post.Title = _model.Title;
@@ -153,6 +227,10 @@
private PostAction _action = PostAction.Publish;
private readonly NewPostModel _model = new();
private bool _isBusy;
+ private int? _selectedCollaborationCategoryId;
+ private List? _administeredPages;
+ private readonly List _administeredCategories = [];
+ private List _possibleCollaborationPages = [];
[Parameter] public int PostId { get; set; }
@@ -166,6 +244,13 @@
{
await using var db = await DbFactory.CreateDbContextAsync();
+ var index = await InterestService.LoadIndex;
+ _administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
+ if (_administeredPages != null)
+ {
+ _administeredPages.ForEach(p => { _administeredCategories.AddRange(p.Categories); });
+ }
+
if (PostId == 0) // new post
{
Post post = new() { Created = new() };
@@ -193,6 +278,11 @@
post.Event = @event;
}
+ var administeredPageIds = _administeredPages?.Select(p => p.Id).ToList() ?? [];
+ _possibleCollaborationPages = await db.Pages
+ .Where(p => !administeredPageIds.Contains(p.Id))
+ .ToListAsync();
+
_model.EventId = EventId;
_post = post;
}
@@ -205,10 +295,16 @@
.FirstOrDefaultAsync(p => p.Id == PostId);
if (_post == null)
return;
+
_model.Title = _post.Title;
_model.ContentMarkdown = _post.ContentMarkdown;
_model.ExcerptMarkdown = _post.ExcerptMarkdown;
_model.EventId = _post.Event?.Id;
+ _model.CollaborationCategories = _post.Categories.ToList();
+ _model.PossibleCollaborationPages = await db.PostCollaborationRequests
+ .Where(r => r.PostId == _post.Id)
+ .Select(r => r.Page)
+ .ToListAsync();
}
if (_post.Event != null)
@@ -247,25 +343,79 @@
await using var scope = ServiceProvider.CreateAsyncScope();
var postService = scope.ServiceProvider.GetRequiredService();
-
+
Post post = await postService.Save(
PostId,
_model.EventId,
_post!.Categories.Select(c => c.Id).ToHashSet(),
+ _model.PossibleCollaborationPages.Select(p => p.Id).ToHashSet(),
_model.Title,
_model.ContentMarkdown,
_model.ExcerptMarkdown,
- _action);
+ _action
+ );
Nav.NavigateTo($"/posts/{post.Id}");
}
+ private int? SelectedCollaborationCategoryId
+ {
+ get => _selectedCollaborationCategoryId;
+ set
+ {
+ _selectedCollaborationCategoryId = value;
+ if (value.HasValue)
+ {
+ var category = _administeredCategories.FirstOrDefault(c => c.Id == value.Value);
+ if (category != null)
+ {
+ if (!_model.CollaborationCategories.Contains(category))
+ _model.CollaborationCategories.Add(category);
+ }
+
+ _selectedCollaborationCategoryId = null;
+ }
+ }
+ }
+
+ private void RemoveCollaborationCategory(Category category)
+ {
+ _model.CollaborationCategories.Remove(category);
+ }
+
+ private int? SelectedPossibleCollaborationPageId
+ {
+ get => _selectedCollaborationCategoryId;
+ set
+ {
+ _selectedCollaborationCategoryId = value;
+ if (value.HasValue)
+ {
+ var page = _possibleCollaborationPages.FirstOrDefault(p => p.Id == value.Value);
+ if (page != null)
+ {
+ if (!_model.PossibleCollaborationPages.Contains(page))
+ _model.PossibleCollaborationPages.Add(page);
+ }
+
+ _selectedCollaborationCategoryId = null;
+ }
+ }
+ }
+
+ private void RemovePossibleCollaborationPage(Page page)
+ {
+ _model.PossibleCollaborationPages.Remove(page);
+ }
+
private class NewPostModel
{
public int? EventId { get; set; }
[Length(1, 100)] public string Title { get; set; } = "";
[MaxLength(20000)] public string? ContentMarkdown { get; set; }
[MaxLength(1000)] public string? ExcerptMarkdown { get; set; }
+ public List CollaborationCategories { get; set; } = [];
+ public List PossibleCollaborationPages { get; set; } = [];
}
}
diff --git a/StartSch/Data/CollaborationRequest.cs b/StartSch/Data/CollaborationRequest.cs
index 246b082d..744e2bb4 100644
--- a/StartSch/Data/CollaborationRequest.cs
+++ b/StartSch/Data/CollaborationRequest.cs
@@ -3,6 +3,8 @@ namespace StartSch.Data;
public abstract class CollaborationRequest
{
public int Id { get; set; }
+ public int PageId { get; set; }
+ public Page Page { get; set; } = null!;
}
public class EventCollaborationRequest : CollaborationRequest
diff --git a/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs b/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
index a064c96e..fca76402 100644
--- a/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
+++ b/StartSch/Data/Migrations/Sqlite/SqliteDbModelSnapshot.cs
@@ -117,8 +117,13 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasMaxLength(34)
.HasColumnType("TEXT");
+ b.Property("PageId")
+ .HasColumnType("INTEGER");
+
b.HasKey("Id");
+ b.HasIndex("PageId");
+
b.ToTable("CollaborationRequests");
b.HasDiscriminator().HasValue("CollaborationRequest");
@@ -711,6 +716,17 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("Includer");
});
+ modelBuilder.Entity("StartSch.Data.CollaborationRequest", b =>
+ {
+ b.HasOne("StartSch.Data.Page", "Page")
+ .WithMany()
+ .HasForeignKey("PageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Page");
+ });
+
modelBuilder.Entity("StartSch.Data.Event", b =>
{
b.HasOne("StartSch.Data.Event", "Parent")
diff --git a/StartSch/Services/EventService.cs b/StartSch/Services/EventService.cs
index d03ee898..362af740 100644
--- a/StartSch/Services/EventService.cs
+++ b/StartSch/Services/EventService.cs
@@ -12,6 +12,7 @@ public async Task Save(
int eventId,
int? parentId,
HashSet categoryIds,
+ HashSet possibleCollaborationRequestPageIds,
string title,
string? descriptionMd,
Instant? start,
@@ -44,6 +45,28 @@ await db.Categories
authorizationService.CheckCreate(@event);
db.Events.Add(@event);
+
+ // Save collaboration
+ if (possibleCollaborationRequestPageIds.Count > 0)
+ {
+ // Looking up the pages might not be needed, ALBI shall decide
+ var pages = await db.Pages
+ .Where(p => possibleCollaborationRequestPageIds.Contains(p.Id))
+ .ToListAsync();
+
+ var collaborationRequests = possibleCollaborationRequestPageIds
+ .Select(pageId => new EventCollaborationRequest
+ {
+ PageId = pageId,
+ Page = pages.First(p => p.Id == pageId),
+ Event = @event,
+ EventId = @event.Id
+ })
+ .ToList();
+
+ db.EventCollaborationRequests.AddRange(collaborationRequests);
+ }
+
}
else // Update existing event
{
@@ -74,6 +97,27 @@ await db.Categories
@event.End = end;
@event.Title = title;
@event.DescriptionMarkdown = descriptionMd;
+
+ // Update collaboration requests
+ var existingCollaborationRequests = await db.EventCollaborationRequests
+ .Where(ecr => ecr.EventId == eventId)
+ .ToListAsync();
+
+ db.EventCollaborationRequests.RemoveRange(existingCollaborationRequests);
+
+ if (possibleCollaborationRequestPageIds.Count > 0)
+ {
+ var collaborationRequests = possibleCollaborationRequestPageIds
+ .Select(pageId => new EventCollaborationRequest
+ {
+ PageId = pageId,
+ Event = @event,
+ EventId = @event.Id
+ })
+ .ToList();
+
+ db.EventCollaborationRequests.AddRange(collaborationRequests);
+ }
}
await db.SaveChangesAsync();
diff --git a/StartSch/Services/PostService.cs b/StartSch/Services/PostService.cs
index bf06d901..91518e7a 100644
--- a/StartSch/Services/PostService.cs
+++ b/StartSch/Services/PostService.cs
@@ -14,6 +14,7 @@ public async Task Save(
int postId,
int? eventId,
HashSet categoryIds,
+ HashSet possibleCollaborationRequestPageIds,
string title,
string? contentMd,
string? excerptMd,
@@ -45,6 +46,26 @@ await db.Categories
authorizationService.CheckCreate(post);
db.Posts.Add(post);
+
+ // Save collaboration
+ if (possibleCollaborationRequestPageIds.Count > 0)
+ {
+ var pages = await db.Pages
+ .Where(p => possibleCollaborationRequestPageIds.Contains(p.Id))
+ .ToListAsync();
+
+ var collaborationRequests = possibleCollaborationRequestPageIds
+ .Select(pageId => new PostCollaborationRequest
+ {
+ PageId = pageId,
+ Page = pages.First(p => p.Id == pageId),
+ Post = post,
+ PostId = post.Id
+ })
+ .ToList();
+
+ db.PostCollaborationRequests.AddRange(collaborationRequests);
+ }
}
else
{
@@ -74,6 +95,27 @@ await db.Categories
post.Title = title;
post.ExcerptMarkdown = excerptMd;
post.ContentMarkdown = contentMd;
+
+ // Update collaboration requests
+ var existingCollaborationRequests = await db.PostCollaborationRequests
+ .Where(pcr => pcr.PostId == postId)
+ .ToListAsync();
+
+ db.PostCollaborationRequests.RemoveRange(existingCollaborationRequests);
+
+ if (possibleCollaborationRequestPageIds.Count > 0)
+ {
+ var collaborationRequests = possibleCollaborationRequestPageIds
+ .Select(pageId => new PostCollaborationRequest
+ {
+ PageId = pageId,
+ Post = post,
+ PostId = post.Id
+ })
+ .ToList();
+
+ db.PostCollaborationRequests.AddRange(collaborationRequests);
+ }
}
if (action == PostAction.Publish)
@@ -81,7 +123,8 @@ await db.Categories
if (post.Published.HasValue)
throw new InvalidOperationException("Post is already published.");
post.Published = SystemClock.Instance.GetCurrentInstant();
- db.CreatePostPublishedNotifications.Add(new() { Created = SystemClock.Instance.GetCurrentInstant(), Post = post });
+ db.CreatePostPublishedNotifications.Add(new()
+ { Created = SystemClock.Instance.GetCurrentInstant(), Post = post });
}
await db.SaveChangesAsync();
diff --git a/StartSch/Services/UserInfoService.cs b/StartSch/Services/UserInfoService.cs
index a86ef319..8952826c 100644
--- a/StartSch/Services/UserInfoService.cs
+++ b/StartSch/Services/UserInfoService.cs
@@ -25,13 +25,14 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
?? db.Users.Add(new() { AuthSchId = authSchId }).Entity;
AuthSchUserInfo userInfo = context.User.Deserialize(Utils.JsonSerializerOptions)!;
+ // TODO DELETE THIS
userInfo = new AuthSchUserInfo(
userInfo.Email,
userInfo.EmailVerified,
new List
{
new(106, "KIR fejlesztők és üzemeltetők", new List { "Adminisztrátor" }),
- new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" })
+ // new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" })
}
);
From 8b6efa41acc7e0d12c847f5f332ae240436b893f Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 5 Mar 2026 15:51:53 +0100
Subject: [PATCH 3/9] Enable DetailedErrors for development
---
StartSch/appsettings.Development.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/StartSch/appsettings.Development.json b/StartSch/appsettings.Development.json
index c7ae5353..eda68355 100644
--- a/StartSch/appsettings.Development.json
+++ b/StartSch/appsettings.Development.json
@@ -1,7 +1,9 @@
{
+ "DetailedErrors": true,
"Logging": {
"LogLevel": {
- "Default": "Information"
+ "Default": "Information",
+ "Microsoft.AspNetCore.SignalR": "Debug"
}
},
"ConnectionStrings": {
From c6d055f6cff937a6465bd77c13a0387919db52e0 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 5 Mar 2026 17:07:20 +0100
Subject: [PATCH 4/9] Add collaboration management page
---
.../Components/Pages/CollaborationPage.razor | 178 ++++++++++++++++++
StartSch/Components/Pages/PagePage.razor | 13 +-
StartSch/Services/UserInfoService.cs | 3 +-
3 files changed, 191 insertions(+), 3 deletions(-)
create mode 100644 StartSch/Components/Pages/CollaborationPage.razor
diff --git a/StartSch/Components/Pages/CollaborationPage.razor b/StartSch/Components/Pages/CollaborationPage.razor
new file mode 100644
index 00000000..1ddc192a
--- /dev/null
+++ b/StartSch/Components/Pages/CollaborationPage.razor
@@ -0,0 +1,178 @@
+@attribute [Authorize]
+@page "/collaborations/{PageId:int}"
+
+@using StartSch.Services
+
+@rendermode InteractiveServerWithoutPrerendering
+@layout MainLayout
+@inherits ResourcePage
+
+@inject IDbContextFactory DbFactory
+@inject InterestService InterestService
+@inject AuthorizationService AuthorizationService
+
+@if (!IsResourceAvailable(_page, AuthorizationService.CanCreatePost, out var status))
+{
+
+ return;
+}
+
+
+
+
+
Oldal együttműködési kérelmei
+
+
+ @if (_items.Count == 0)
+ {
+ Nincsenek együttműködési kérelmek.
+ }
+ else
+ {
+
+ @foreach (var request in _items)
+ {
+ -
+ @if (request is EventCollaborationRequest eventRequest)
+ {
+
+ Esemény együttműködés
+
+
+
+ Szervező: @(eventRequest.Event.Categories.FirstOrDefault()?.Page.Name ?? eventRequest.Event.Categories.FirstOrDefault()?.Page.PekName ?? "Ismeretlen")
+
+ }
+ else if (request is PostCollaborationRequest postRequest)
+ {
+
+ Poszt együttműködés
+
+
+
+ Szerző: @(postRequest.Post.Categories.FirstOrDefault()?.Page.Name ?? postRequest.Post.Categories.FirstOrDefault()?.Page.PekName ?? "Ismeretlen")
+
+ }
+
+
+
+
+
+
+ }
+
+ }
+
+
+
+@code {
+ private Page? _page;
+ private readonly List _items = [];
+ [Parameter] public int PageId { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ await InterestService.LoadIndex;
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ _page = await db.Pages.FirstOrDefaultAsync(g => g.Id == PageId);
+ if (_page == null)
+ return;
+
+ _items.AddRange(await db.EventCollaborationRequests
+ .Include(r => r.Event)
+ .ThenInclude(e => e.Categories)
+ .ThenInclude(c => c.Page)
+ .Where(r => r.PageId == PageId)
+ .ToListAsync());
+
+ _items.AddRange(await db.PostCollaborationRequests
+ .Include(r => r.Post)
+ .ThenInclude(p => p.Categories)
+ .ThenInclude(c => c.Page)
+ .Where(r => r.PageId == PageId)
+ .ToListAsync());
+ }
+
+ private async Task Accept(CollaborationRequest request)
+ {
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ var page = await db.Pages
+ .Include(p => p.Categories)
+ .FirstOrDefaultAsync(p => p.Id == PageId);
+
+ if (page == null || page.Categories.Count == 0) return;
+ var category = page.Categories[0];
+
+ if (request is EventCollaborationRequest evInfo)
+ {
+ var ev = await db.Events
+ .Include(e => e.Categories)
+ .FirstOrDefaultAsync(e => e.Id == evInfo.EventId);
+
+ if (ev != null)
+ {
+ if (!ev.Categories.Any(c => c.Id == category.Id))
+ ev.Categories.Add(category);
+
+ var toRemove = await db.EventCollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == evInfo.Id);
+ if (toRemove != null)
+ db.EventCollaborationRequests.Remove(toRemove);
+ }
+ }
+ else if (request is PostCollaborationRequest postInfo)
+ {
+ var post = await db.Posts
+ .Include(p => p.Categories)
+ .FirstOrDefaultAsync(p => p.Id == postInfo.PostId);
+
+ if (post != null)
+ {
+ if (!post.Categories.Any(c => c.Id == category.Id))
+ post.Categories.Add(category);
+
+ var toRemove = await db.PostCollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == postInfo.Id);
+ if (toRemove != null)
+ db.PostCollaborationRequests.Remove(toRemove);
+ }
+ }
+
+ await db.SaveChangesAsync();
+ _items.Remove(request);
+ }
+
+ private async Task Deny(CollaborationRequest request)
+ {
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ if (request is EventCollaborationRequest evInfo)
+ {
+ var toRemove = await db.EventCollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == evInfo.Id);
+ if (toRemove != null)
+ db.EventCollaborationRequests.Remove(toRemove);
+ }
+ else if (request is PostCollaborationRequest postInfo)
+ {
+ var toRemove = await db.PostCollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == postInfo.Id);
+ if (toRemove != null)
+ db.PostCollaborationRequests.Remove(toRemove);
+ }
+
+ await db.SaveChangesAsync();
+ _items.Remove(request);
+ }
+}
diff --git a/StartSch/Components/Pages/PagePage.razor b/StartSch/Components/Pages/PagePage.razor
index c1f3146e..287a32f2 100644
--- a/StartSch/Components/Pages/PagePage.razor
+++ b/StartSch/Components/Pages/PagePage.razor
@@ -28,7 +28,7 @@
account_circle
- PéK
+ PéK
/
@(_page.PekName ?? _page.PekId.ToString())
@@ -62,8 +62,10 @@
@{
var canCreateEvent = AuthorizationService.CanCreateEvent(_page);
var canCreatePost = AuthorizationService.CanCreatePost(_page);
+ // TODO what role should be required to accept collaboration requests ASK ALBI
+ var canAcceptCollaborationRequests = canCreatePost && canCreateEvent;
}
- @if (canCreateEvent || canCreatePost)
+ @if (canCreateEvent || canCreatePost || canAcceptCollaborationRequests)
{
@{
@@ -85,6 +87,13 @@
Új poszt
}
+ @if (canAcceptCollaborationRequests)
+ {
+
+ chat_info
+ Kollaborációs kérelmek
+
+ }
}
diff --git a/StartSch/Services/UserInfoService.cs b/StartSch/Services/UserInfoService.cs
index 8952826c..0e6603dc 100644
--- a/StartSch/Services/UserInfoService.cs
+++ b/StartSch/Services/UserInfoService.cs
@@ -32,7 +32,8 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
new List
{
new(106, "KIR fejlesztők és üzemeltetők", new List { "Adminisztrátor" }),
- // new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" })
+ new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" }),
+ new(37, "Body-Kör", new List { "Adminisztrátor" })
}
);
From 4cd61ffaeb4adfff4d9f01cbec4fcf992a83a993 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 5 Mar 2026 17:08:07 +0100
Subject: [PATCH 5/9] Clean up UserInfoService.cs
---
StartSch/Services/UserInfoService.cs | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/StartSch/Services/UserInfoService.cs b/StartSch/Services/UserInfoService.cs
index 0e6603dc..e012320f 100644
--- a/StartSch/Services/UserInfoService.cs
+++ b/StartSch/Services/UserInfoService.cs
@@ -19,23 +19,11 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
// Ensure we don't create the same Page twice
await using var tx = await db.BeginTransaction(IsolationLevel.Serializable);
-
User user = await db.Users
.FirstOrDefaultAsync(u => u.AuthSchId == authSchId)
?? db.Users.Add(new() { AuthSchId = authSchId }).Entity;
AuthSchUserInfo userInfo = context.User.Deserialize(Utils.JsonSerializerOptions)!;
- // TODO DELETE THIS
- userInfo = new AuthSchUserInfo(
- userInfo.Email,
- userInfo.EmailVerified,
- new List
- {
- new(106, "KIR fejlesztők és üzemeltetők", new List { "Adminisztrátor" }),
- new(68, "Kari Hallgatói Képviselet", new List { "Adminisztrátor" }),
- new(37, "Body-Kör", new List { "Adminisztrátor" })
- }
- );
user.AuthSchEmail = userInfo.EmailVerified ? userInfo.Email : null;
@@ -103,7 +91,6 @@ public async Task OnUserInformationReceived(UserInformationReceivedContext conte
int updates = await db.SaveChangesAsync();
await tx.CommitAsync();
-
if (updates > 0)
cache.Remove(InterestService.CacheKey);
From 2a1f8d860cf0292fb08bc263e421f068591a78c0 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 19 Mar 2026 18:35:14 +0100
Subject: [PATCH 6/9] Merge categoryIds and possibleCollaborationRequestPageIds
and compute possibleCollaborationRequestPageIds dynamically in EventService
and PostServic
---
StartSch/Components/Pages/EventEditPage.razor | 1 -
StartSch/Components/Pages/PostEditPage.razor | 3 +--
StartSch/Services/EventService.cs | 13 ++++++-------
StartSch/Services/PostService.cs | 12 ++++++------
4 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/StartSch/Components/Pages/EventEditPage.razor b/StartSch/Components/Pages/EventEditPage.razor
index 15562dca..42f4781f 100644
--- a/StartSch/Components/Pages/EventEditPage.razor
+++ b/StartSch/Components/Pages/EventEditPage.razor
@@ -309,7 +309,6 @@
EventId,
_event!.ParentId,
_event.Categories.Select(e => e.Id).Union(_model.CollaborationCategories.Select(e => e.Id)).ToHashSet(),
- _model.PossibleCollaborationPages.Select(p => p.Id).ToHashSet(),
_model.Title,
_model.DescriptionMarkdown,
_model.Start?.ToLocalDateTime().InZoneLeniently(Utils.HungarianTimeZone).ToInstant(),
diff --git a/StartSch/Components/Pages/PostEditPage.razor b/StartSch/Components/Pages/PostEditPage.razor
index f54d620d..8c22000f 100644
--- a/StartSch/Components/Pages/PostEditPage.razor
+++ b/StartSch/Components/Pages/PostEditPage.razor
@@ -347,8 +347,7 @@
Post post = await postService.Save(
PostId,
_model.EventId,
- _post!.Categories.Select(c => c.Id).ToHashSet(),
- _model.PossibleCollaborationPages.Select(p => p.Id).ToHashSet(),
+ _post!.Categories.Select(c => c.Id).Union(_model.CollaborationCategories.Select(c => c.Id)).ToHashSet(),
_model.Title,
_model.ContentMarkdown,
_model.ExcerptMarkdown,
diff --git a/StartSch/Services/EventService.cs b/StartSch/Services/EventService.cs
index 362af740..9cfda4cf 100644
--- a/StartSch/Services/EventService.cs
+++ b/StartSch/Services/EventService.cs
@@ -12,13 +12,18 @@ public async Task Save(
int eventId,
int? parentId,
HashSet categoryIds,
- HashSet possibleCollaborationRequestPageIds,
string title,
string? descriptionMd,
Instant? start,
Instant? end)
{
Event @event;
+ var possibleCollaborationRequestPageIds = await db.Categories
+ .Where(c => categoryIds.Contains(c.Id))
+ .Select(c => c.PageId)
+ .Distinct()
+ .Where(pageId => !authorizationService.AdministeredPageIds.Contains(pageId))
+ .ToListAsync();
if (eventId == 0) // Create a new event
{
@@ -49,16 +54,10 @@ await db.Categories
// Save collaboration
if (possibleCollaborationRequestPageIds.Count > 0)
{
- // Looking up the pages might not be needed, ALBI shall decide
- var pages = await db.Pages
- .Where(p => possibleCollaborationRequestPageIds.Contains(p.Id))
- .ToListAsync();
-
var collaborationRequests = possibleCollaborationRequestPageIds
.Select(pageId => new EventCollaborationRequest
{
PageId = pageId,
- Page = pages.First(p => p.Id == pageId),
Event = @event,
EventId = @event.Id
})
diff --git a/StartSch/Services/PostService.cs b/StartSch/Services/PostService.cs
index 91518e7a..99ca9b60 100644
--- a/StartSch/Services/PostService.cs
+++ b/StartSch/Services/PostService.cs
@@ -14,13 +14,18 @@ public async Task Save(
int postId,
int? eventId,
HashSet categoryIds,
- HashSet possibleCollaborationRequestPageIds,
string title,
string? contentMd,
string? excerptMd,
PostAction action)
{
Post post;
+ var possibleCollaborationRequestPageIds = await db.Categories
+ .Where(c => categoryIds.Contains(c.Id))
+ .Select(c => c.PageId)
+ .Distinct()
+ .Where(pageId => !authorizationService.AdministeredPageIds.Contains(pageId))
+ .ToListAsync();
if (postId == 0)
{
@@ -50,15 +55,10 @@ await db.Categories
// Save collaboration
if (possibleCollaborationRequestPageIds.Count > 0)
{
- var pages = await db.Pages
- .Where(p => possibleCollaborationRequestPageIds.Contains(p.Id))
- .ToListAsync();
-
var collaborationRequests = possibleCollaborationRequestPageIds
.Select(pageId => new PostCollaborationRequest
{
PageId = pageId,
- Page = pages.First(p => p.Id == pageId),
Post = post,
PostId = post.Id
})
From be3ad7562f1b59456b695c68dfd01fc592525919 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Sat, 21 Mar 2026 10:18:44 +0100
Subject: [PATCH 7/9] resolve all issues mentioned in #183
---
.../Components/Pages/AdminDashboardPage.razor | 47 +++-
.../Components/Pages/CollaborationPage.razor | 62 ++--
.../Pages/CollaborationRequestPage.razor | 179 ++++++++++++
StartSch/Components/Pages/EventEditPage.razor | 262 ++++++++---------
StartSch/Components/Pages/PagePage.razor | 11 +-
StartSch/Components/Pages/PostEditPage.razor | 264 ++++++++----------
StartSch/Services/AuthorizationService.cs | 5 +
StartSch/Services/EventService.cs | 67 +++--
StartSch/Services/FontCache.cs | 1 +
StartSch/Services/PostService.cs | 68 +++--
StartSch/js/app.ts | 7 +
11 files changed, 603 insertions(+), 370 deletions(-)
create mode 100644 StartSch/Components/Pages/CollaborationRequestPage.razor
diff --git a/StartSch/Components/Pages/AdminDashboardPage.razor b/StartSch/Components/Pages/AdminDashboardPage.razor
index bb70d07a..60a004d6 100644
--- a/StartSch/Components/Pages/AdminDashboardPage.razor
+++ b/StartSch/Components/Pages/AdminDashboardPage.razor
@@ -7,6 +7,7 @@
@inject AuthorizationService AuthorizationService
@inject InterestService InterestService
+@inject IDbContextFactory DbFactory
Adminisztráció
@@ -30,8 +31,29 @@
}
+
+
+ Kollaborációs kérelmek
+ @if (_collaborationRequests.Count == 0)
+ {
+ Nincs függő kérelmed.
+ }
+ else
+ {
+
+ }
+
}
-
+
Azokat a köröket adminisztrálhatod, amelyiknél
PéK-en
@@ -49,11 +71,34 @@
@code {
private List? _administeredPages;
+ private readonly List _collaborationRequests = [];
protected override async Task OnInitializedAsync()
{
var index = await InterestService.LoadIndex;
_administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
+
+ if (_administeredPages is not { Count: > 0 })
+ return;
+
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ _collaborationRequests.AddRange(await db.CollaborationRequests
+ .Where(r => AuthorizationService.AdministeredPageIds.Contains(r.PageId))
+ .Include(r => r.Page)
+ .Include(r => ((EventCollaborationRequest)r).Event)
+ .Include(r => ((PostCollaborationRequest)r).Post)
+ .OrderByDescending(r => r.Id)
+ .ToListAsync());
}
+ private static string DescribeRequest(CollaborationRequest request) => request switch
+ {
+ EventCollaborationRequest eventRequest =>
+ $"Esemény: {eventRequest.Event.Title} -> {eventRequest.Page.GetName()}",
+ PostCollaborationRequest postRequest =>
+ $"Poszt: {postRequest.Post.Title} -> {postRequest.Page.GetName()}",
+ _ => $"Kérelem #{request.Id}"
+ };
+
}
diff --git a/StartSch/Components/Pages/CollaborationPage.razor b/StartSch/Components/Pages/CollaborationPage.razor
index 1ddc192a..d23084af 100644
--- a/StartSch/Components/Pages/CollaborationPage.razor
+++ b/StartSch/Components/Pages/CollaborationPage.razor
@@ -8,10 +8,9 @@
@inherits ResourcePage
@inject IDbContextFactory DbFactory
-@inject InterestService InterestService
@inject AuthorizationService AuthorizationService
-@if (!IsResourceAvailable(_page, AuthorizationService.CanCreatePost, out var status))
+@if (!IsResourceAvailable(_page, AuthorizationService.CanAcceptCollaborationRequests, out var status))
{
return;
@@ -60,12 +59,12 @@
}
-
-
+
}
@@ -81,25 +80,20 @@
protected override async Task OnInitializedAsync()
{
- await InterestService.LoadIndex;
await using var db = await DbFactory.CreateDbContextAsync();
_page = await db.Pages.FirstOrDefaultAsync(g => g.Id == PageId);
if (_page == null)
return;
- _items.AddRange(await db.EventCollaborationRequests
- .Include(r => r.Event)
+ _items.AddRange(await db.CollaborationRequests
+ .Where(r => r.PageId == PageId)
+ .Include(r => ((EventCollaborationRequest)r).Event)
.ThenInclude(e => e.Categories)
.ThenInclude(c => c.Page)
- .Where(r => r.PageId == PageId)
- .ToListAsync());
-
- _items.AddRange(await db.PostCollaborationRequests
- .Include(r => r.Post)
+ .Include(r => ((PostCollaborationRequest)r).Post)
.ThenInclude(p => p.Categories)
.ThenInclude(c => c.Page)
- .Where(r => r.PageId == PageId)
.ToListAsync());
}
@@ -111,7 +105,8 @@
.Include(p => p.Categories)
.FirstOrDefaultAsync(p => p.Id == PageId);
- if (page == null || page.Categories.Count == 0) return;
+ if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page) || page.Categories.Count == 0)
+ return;
var category = page.Categories[0];
if (request is EventCollaborationRequest evInfo)
@@ -125,10 +120,10 @@
if (!ev.Categories.Any(c => c.Id == category.Id))
ev.Categories.Add(category);
- var toRemove = await db.EventCollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == evInfo.Id);
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
if (toRemove != null)
- db.EventCollaborationRequests.Remove(toRemove);
+ db.CollaborationRequests.Remove(toRemove);
}
}
else if (request is PostCollaborationRequest postInfo)
@@ -142,10 +137,10 @@
if (!post.Categories.Any(c => c.Id == category.Id))
post.Categories.Add(category);
- var toRemove = await db.PostCollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == postInfo.Id);
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
if (toRemove != null)
- db.PostCollaborationRequests.Remove(toRemove);
+ db.CollaborationRequests.Remove(toRemove);
}
}
@@ -157,21 +152,16 @@
{
await using var db = await DbFactory.CreateDbContextAsync();
- if (request is EventCollaborationRequest evInfo)
- {
- var toRemove = await db.EventCollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == evInfo.Id);
- if (toRemove != null)
- db.EventCollaborationRequests.Remove(toRemove);
- }
- else if (request is PostCollaborationRequest postInfo)
- {
- var toRemove = await db.PostCollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == postInfo.Id);
- if (toRemove != null)
- db.PostCollaborationRequests.Remove(toRemove);
- }
+ var page = await db.Pages.FirstOrDefaultAsync(p => p.Id == PageId);
+ if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page))
+ return;
+
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
+ if (toRemove == null)
+ return;
+ db.CollaborationRequests.Remove(toRemove);
await db.SaveChangesAsync();
_items.Remove(request);
}
diff --git a/StartSch/Components/Pages/CollaborationRequestPage.razor b/StartSch/Components/Pages/CollaborationRequestPage.razor
new file mode 100644
index 00000000..540505a1
--- /dev/null
+++ b/StartSch/Components/Pages/CollaborationRequestPage.razor
@@ -0,0 +1,179 @@
+@attribute [Authorize]
+@page "/collaboration-requests/{CollaborationRequestId:int}"
+
+@using StartSch.Services
+
+@rendermode InteractiveServerWithoutPrerendering
+@layout MainLayout
+
+@inject IDbContextFactory DbFactory
+@inject AuthorizationService AuthorizationService
+@inject NavigationManager Navigation
+
+
+ @if (_request == null)
+ {
+
+ Kérelem nem található
+ A keresett kollaborációs kérelem nem létezik, vagy már feldolgozták.
+
+ }
+ else if (_targetPage == null || !AuthorizationService.CanAcceptCollaborationRequests(_targetPage))
+ {
+
+ Nincs jogosultság
+ Ehhez a kollaborációs kérelemhez nincs jogosultságod.
+
+ }
+ else
+ {
+
+ Kollaborációs kérelem #@_request.Id
+
+
+ Cél oldal:
+ @_targetPage.GetName()
+
+
+ @if (_request is EventCollaborationRequest eventRequest)
+ {
+
+ Típus: Esemény
+
+ Tartalom: @eventRequest.Event.Title
+
+ }
+ else if (_request is PostCollaborationRequest postRequest)
+ {
+
+ Típus: Poszt
+
+ Tartalom: @postRequest.Post.Title
+
+ }
+
+
+ Accept(_request!)" class="small filled round" disabled="@_isBusy">
+ Elfogadás
+
+ Deny(_request!)" class="small text round error standard" disabled="@_isBusy">
+ Elutasítás
+
+
+ Vissza
+
+
+
+ }
+
+
+@code {
+ private CollaborationRequest? _request;
+ private Page? _targetPage;
+ private bool _isBusy;
+
+ [Parameter] public int CollaborationRequestId { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ _request = await db.CollaborationRequests
+ .Where(r => r.Id == CollaborationRequestId)
+ .Include(r => r.Page)
+ .Include(r => ((EventCollaborationRequest)r).Event)
+ .Include(r => ((PostCollaborationRequest)r).Post)
+ .FirstOrDefaultAsync();
+
+ _targetPage = _request?.Page;
+ }
+
+ private async Task Accept(CollaborationRequest request)
+ {
+ if (_isBusy)
+ return;
+
+ _isBusy = true;
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ var page = await db.Pages
+ .Include(p => p.Categories)
+ .FirstOrDefaultAsync(p => p.Id == request.PageId);
+
+ if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page) || page.Categories.Count == 0)
+ {
+ _isBusy = false;
+ return;
+ }
+
+ var category = page.Categories[0];
+
+ if (request is EventCollaborationRequest evInfo)
+ {
+ var ev = await db.Events
+ .Include(e => e.Categories)
+ .FirstOrDefaultAsync(e => e.Id == evInfo.EventId);
+
+ if (ev != null)
+ {
+ if (!ev.Categories.Any(c => c.Id == category.Id))
+ ev.Categories.Add(category);
+
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == request.PageId);
+ if (toRemove != null)
+ db.CollaborationRequests.Remove(toRemove);
+ }
+ }
+ else if (request is PostCollaborationRequest postInfo)
+ {
+ var post = await db.Posts
+ .Include(p => p.Categories)
+ .FirstOrDefaultAsync(p => p.Id == postInfo.PostId);
+
+ if (post != null)
+ {
+ if (!post.Categories.Any(c => c.Id == category.Id))
+ post.Categories.Add(category);
+
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == request.PageId);
+ if (toRemove != null)
+ db.CollaborationRequests.Remove(toRemove);
+ }
+ }
+
+ await db.SaveChangesAsync();
+ _isBusy = false;
+ Navigation.NavigateTo("/dashboard");
+ }
+
+ private async Task Deny(CollaborationRequest request)
+ {
+ if (_isBusy)
+ return;
+
+ _isBusy = true;
+ await using var db = await DbFactory.CreateDbContextAsync();
+
+ var page = await db.Pages.FirstOrDefaultAsync(p => p.Id == request.PageId);
+ if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page))
+ {
+ _isBusy = false;
+ return;
+ }
+
+ var toRemove = await db.CollaborationRequests
+ .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == request.PageId);
+ if (toRemove == null)
+ {
+ _isBusy = false;
+ return;
+ }
+
+ db.CollaborationRequests.Remove(toRemove);
+ await db.SaveChangesAsync();
+ _isBusy = false;
+ Navigation.NavigateTo("/dashboard");
+ }
+}
diff --git a/StartSch/Components/Pages/EventEditPage.razor b/StartSch/Components/Pages/EventEditPage.razor
index 42f4781f..6fb7a8c7 100644
--- a/StartSch/Components/Pages/EventEditPage.razor
+++ b/StartSch/Components/Pages/EventEditPage.razor
@@ -62,77 +62,45 @@
-
-
-
-
- Kiválasztott kollaboráló körök
-
+
+
+ Kollaboráló körök
+
- @if (_model.CollaborationCategories.Count > 0)
- {
-
- @foreach (var category in _model.CollaborationCategories)
- {
-
- @(category.Name ?? category.Page.Name ?? category.Page.PekName)
-
-
- }
-
- }
-
- Kollaboráló kör
-
-
- @foreach (var e in _administeredCategories.Where(c => !_model.CollaborationCategories.Contains(c)).Distinct())
- {
-
- }
-
-
-
-
-
- Kiválasztott kollaborálónak meghívható körök
-
-
- @if (_model.PossibleCollaborationPages.Count > 0)
- {
-
- @foreach (var page in _model.PossibleCollaborationPages)
- {
-
- @(page.Name ?? page.Name ?? page.PekName)
-
-
- }
-
- }
-
-
Kollaborálónak meghívható kör
-
-
- @foreach (var e in _possibleCollaborationPages)
- {
- @if (e.Name != null || e.PekName != null)
+ @if (GetSelectedCollaborationPages().Count > 0)
+ {
+
+
+ @foreach (var collabPage in GetSelectedCollaborationPages())
+ {
+ RemoveCollaborationPage(collabPage)">
+ @if (RequiresCollaborationRequest(collabPage))
{
-
+ pending
}
- }
-
-
+ @collabPage.GetName()
+
+ }
+
+ }
+
+
+
+ add
+ Kör hozzáadása
+
+
+ @if (GetPagesRequiringRequest().Count > 0)
+ {
+
+ pending
+ Kollaborációs kérelmet igényel:
+ @string.Join(", ", GetPagesRequiringRequest().Select(p => p.GetName()))
+
+ }
@@ -195,16 +163,59 @@
-@code {
+@if (_isPagePickerOpen)
+{
+
+
+ Kör hozzáadása
+
+
+
+
+
+ Bezárás
+
+
+}
+@code {
private Event? _event;
+ private Page? _parentPage;
private readonly List
_possibleParents = [];
private readonly EventEditModel _model = new();
private bool _isBusy;
- private int? _selectedCollaborationCategoryId;
- private List? _administeredPages;
- private readonly List _administeredCategories = [];
- private List _possibleCollaborationPages = [];
+ private bool _isPagePickerOpen;
+ private List _allPages = [];
+
[Parameter] public int EventId { get; set; }
[SupplyParameterFromQuery(Name = "categories")]
@@ -217,14 +228,12 @@
{
await using var db = await DbFactory.CreateDbContextAsync();
- var index = await InterestService.LoadIndex;
- _administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
- if (_administeredPages != null)
- {
- _administeredPages.ForEach(p => { _administeredCategories.AddRange(p.Categories); });
- }
+ _allPages = await db.Pages
+ .Include(p => p.Categories)
+ .OrderBy(p => p.Name ?? p.PekName ?? p.PincerName)
+ .ToListAsync();
- if (EventId == 0) // new event
+ if (EventId == 0)
{
Event? parent = ParentId.HasValue
? await db.Events
@@ -236,7 +245,7 @@
if (ParentId.HasValue && parent == null)
return;
- Event newEvent = new()
+ var newEvent = new Event
{
Start = SystemClock.Instance.GetCurrentInstant(),
Title = "",
@@ -248,21 +257,15 @@
return;
List categoryIds = CategoryIds.Split(',').Select(int.Parse).ToList();
-
List categories = await db.Categories
.Include(c => c.Page)
- .Where(g => categoryIds.Contains(g.Id))
+ .Where(c => categoryIds.Contains(c.Id))
.ToListAsync();
newEvent.Categories.AddRange(categories);
- var administeredPageIds = _administeredPages?.Select(p => p.Id).ToList() ?? [];
- _possibleCollaborationPages = await db.Pages
- .Where(p => !administeredPageIds.Contains(p.Id))
- .ToListAsync();
-
_event = newEvent;
}
- else // editing
+ else
{
_event = await db.Events
.Include(e => e.Parent)
@@ -273,12 +276,24 @@
return;
_model.CollaborationCategories = _event.Categories.ToList();
- _model.PossibleCollaborationPages = await db.EventCollaborationRequests
+
+ var requestedPageIds = await db.EventCollaborationRequests
.Where(r => r.EventId == _event.Id)
- .Select(r => r.Page)
+ .Select(r => r.PageId)
+ .Distinct()
.ToListAsync();
- }
+ var requestedCategories = await db.Categories
+ .Include(c => c.Page)
+ .Where(c => requestedPageIds.Contains(c.PageId) && c.Name == null)
+ .ToListAsync();
+
+ foreach (var category in requestedCategories)
+ {
+ if (_model.CollaborationCategories.All(c => c.Id != category.Id))
+ _model.CollaborationCategories.Add(category);
+ }
+ }
_model.Start = (_event.Start ?? SystemClock.Instance.GetCurrentInstant())
.InZone(Utils.HungarianTimeZone)
@@ -307,8 +322,8 @@
Event savedEvent = await eventService.Save(
EventId,
- _event!.ParentId,
- _event.Categories.Select(e => e.Id).Union(_model.CollaborationCategories.Select(e => e.Id)).ToHashSet(),
+ _model.ParentId,
+ _model.CollaborationCategories.Select(c => c.Id).ToHashSet(),
_model.Title,
_model.DescriptionMarkdown,
_model.Start?.ToLocalDateTime().InZoneLeniently(Utils.HungarianTimeZone).ToInstant(),
@@ -318,56 +333,42 @@
Navigation.NavigateTo($"/events/{savedEvent.Id}");
}
- private int? SelectedCollaborationCategoryId
- {
- get => _selectedCollaborationCategoryId;
- set
- {
- _selectedCollaborationCategoryId = value;
- if (value.HasValue)
- {
- var category = _administeredCategories.FirstOrDefault(c => c.Id == value.Value);
- if (category != null)
- {
- if (!_model.CollaborationCategories.Contains(category))
- _model.CollaborationCategories.Add(category);
- }
+ private void OpenPagePicker() => _isPagePickerOpen = true;
+ private void ClosePagePicker() => _isPagePickerOpen = false;
- _selectedCollaborationCategoryId = null;
- }
- }
- }
+ private bool RequiresCollaborationRequest(Page page)
+ => !AuthorizationService.AdministeredPageIds.Contains(page.Id);
- private void RemoveCollaborationCategory(Category category)
+ private List GetSelectedCollaborationPages()
{
- _model.CollaborationCategories.Remove(category);
+ var selectedPageIds = _model.CollaborationCategories.Select(c => c.PageId).ToHashSet();
+ return _allPages.Where(p => selectedPageIds.Contains(p.Id)).ToList();
}
- private int? SelectedPossibleCollaborationPageId
- {
- get => _selectedCollaborationCategoryId;
- set
- {
- _selectedCollaborationCategoryId = value;
- if (value.HasValue)
- {
- var page = _possibleCollaborationPages.FirstOrDefault(p => p.Id == value.Value);
- if (page != null)
- {
- if (!_model.PossibleCollaborationPages.Contains(page))
- _model.PossibleCollaborationPages.Add(page);
- }
+ private List GetPagesRequiringRequest()
+ => GetSelectedCollaborationPages().Where(RequiresCollaborationRequest).ToList();
- _selectedCollaborationCategoryId = null;
- }
- }
+ private List GetAddablePages()
+ {
+ var selectedPageIds = _model.CollaborationCategories.Select(c => c.PageId).ToHashSet();
+ return _allPages.Where(p => !selectedPageIds.Contains(p.Id)).ToList();
}
- private void RemovePossibleCollaborationPage(Page page)
+ private void AddCollaborationPage(int pageId)
{
- _model.PossibleCollaborationPages.Remove(page);
+ var page = _allPages.FirstOrDefault(p => p.Id == pageId);
+ var category = page?.Categories.FirstOrDefault(c => c.Name == null) ?? page?.Categories.FirstOrDefault();
+ if (category == null)
+ return;
+
+ if (_model.CollaborationCategories.All(c => c.Id != category.Id))
+ _model.CollaborationCategories.Add(category);
+
+ _isPagePickerOpen = false;
}
+ private void RemoveCollaborationPage(Page page)
+ => _model.CollaborationCategories.RemoveAll(c => c.PageId == page.Id);
private class EventEditModel
{
@@ -385,7 +386,6 @@
public DateTime? End { get; set; }
public int? ParentId { get; set; }
public List CollaborationCategories { get; set; } = [];
- public List PossibleCollaborationPages { get; set; } = [];
[Length(1, 100)] public string Title { get; set; } = "";
[MaxLength(20000)] public string? DescriptionMarkdown { get; set; }
diff --git a/StartSch/Components/Pages/PagePage.razor b/StartSch/Components/Pages/PagePage.razor
index 287a32f2..02e9da50 100644
--- a/StartSch/Components/Pages/PagePage.razor
+++ b/StartSch/Components/Pages/PagePage.razor
@@ -62,10 +62,8 @@
@{
var canCreateEvent = AuthorizationService.CanCreateEvent(_page);
var canCreatePost = AuthorizationService.CanCreatePost(_page);
- // TODO what role should be required to accept collaboration requests ASK ALBI
- var canAcceptCollaborationRequests = canCreatePost && canCreateEvent;
}
- @if (canCreateEvent || canCreatePost || canAcceptCollaborationRequests)
+ @if (canCreateEvent || canCreatePost)
{
@{
@@ -87,13 +85,6 @@
Új poszt
}
- @if (canAcceptCollaborationRequests)
- {
-
- chat_info
- Kollaborációs kérelmek
-
- }
}
diff --git a/StartSch/Components/Pages/PostEditPage.razor b/StartSch/Components/Pages/PostEditPage.razor
index 8c22000f..bf552087 100644
--- a/StartSch/Components/Pages/PostEditPage.razor
+++ b/StartSch/Components/Pages/PostEditPage.razor
@@ -64,68 +64,39 @@
Kiválasztott kollaboráló körök
- @if (_model.CollaborationCategories.Count > 0)
+ @if (GetSelectedCollaborationPages().Count > 0)
{
-
- @foreach (var category in _model.CollaborationCategories)
- {
-
- @(category.Name ?? category.Page.Name ?? category.Page.PekName)
-
-
- }
+
+
+ @foreach (var collabPage in GetSelectedCollaborationPages())
+ {
+ RemoveCollaborationPage(collabPage)">
+ @if (RequiresCollaborationRequest(collabPage))
+ {
+ pending
+ }
+ @collabPage.GetName()
+
+ }
+
}
-
- Kollaboráló kör
-
-
- @foreach (var e in _administeredCategories.Where(c => !_model.CollaborationCategories.Contains(c)).Distinct())
- {
-
- }
-
-
-
-
-
- Kiválasztott kollaborálónak meghívható körök
+
+
+ add
+ Kör hozzáadása
+
- @if (_model.PossibleCollaborationPages.Count > 0)
+ @if (GetPagesRequiringRequest().Count > 0)
{
-
- @foreach (var page in _model.PossibleCollaborationPages)
- {
-
- @(page.Name ?? page.Name ?? page.PekName)
-
-
- }
-
+
+ pending
+ Kollaborációs kérelmet igényel:
+ @string.Join(", ", GetPagesRequiringRequest().Select(p => p.GetName()))
+
}
-
- Kollaborálónak meghívható kör
-
-
- @foreach (var e in _possibleCollaborationPages)
- {
- @if (e.Name != null || e.PekName != null)
- {
-
- }
- }
-
-
@@ -201,8 +172,51 @@
-@code {
+@if (_isPagePickerOpen)
+{
+
+
+ Kör hozzáadása
+
+
+
+
+ Bezárás
+
+
+}
+
+@code {
// /posts/0/edit?categories=1,2&event=1
// - new post, set initial relationships from queries
// - groups are set from query // TODO: revisit PostEditPage
@@ -210,27 +224,14 @@
// /posts/1/edit
// - edit post
// - groups must not change
- //
- // A post is owned by at least one group and can optionally belong to an event.
- //
- // A user must not be able to write a post in the name of a group they are not an admin of, unless the post
- // belongs to an event with every group (signifying an agreement between the groups).
- //
- // Event can always be modified, but if it is set:
- // - post.Groups must be a subset of event.Groups
- // - user must be a part of at least one of post.Groups
- //
- // If the event is not set, the post must belong to a single group, which the user must be an admin of
private readonly List
_relevantEvents = [];
private Post? _post;
private PostAction _action = PostAction.Publish;
private readonly NewPostModel _model = new();
private bool _isBusy;
- private int? _selectedCollaborationCategoryId;
- private List? _administeredPages;
- private readonly List _administeredCategories = [];
- private List _possibleCollaborationPages = [];
+ private bool _isPagePickerOpen;
+ private List _allPages = [];
[Parameter] public int PostId { get; set; }
@@ -244,14 +245,14 @@
{
await using var db = await DbFactory.CreateDbContextAsync();
- var index = await InterestService.LoadIndex;
- _administeredPages = index.GetPages(AuthorizationService.AdministeredPageIds);
- if (_administeredPages != null)
- {
- _administeredPages.ForEach(p => { _administeredCategories.AddRange(p.Categories); });
- }
+ await InterestService.LoadIndex;
+
+ _allPages = await db.Pages
+ .Include(p => p.Categories)
+ .OrderBy(p => p.Name ?? p.PekName ?? p.PincerName)
+ .ToListAsync();
- if (PostId == 0) // new post
+ if (PostId == 0)
{
Post post = new() { Created = new() };
@@ -259,12 +260,12 @@
return;
List categoryIds = CategoryIds.Split(',').Select(int.Parse).ToList();
-
List categories = await db.Categories
.Include(c => c.Page)
.Where(c => categoryIds.Contains(c.Id))
.ToListAsync();
post.Categories.AddRange(categories);
+ _model.CollaborationCategories = categories.ToList();
if (EventId != null)
{
@@ -278,15 +279,10 @@
post.Event = @event;
}
- var administeredPageIds = _administeredPages?.Select(p => p.Id).ToList() ?? [];
- _possibleCollaborationPages = await db.Pages
- .Where(p => !administeredPageIds.Contains(p.Id))
- .ToListAsync();
-
_model.EventId = EventId;
_post = post;
}
- else // editing post
+ else
{
_post = await db.Posts
.Include(p => p.Categories)
@@ -301,30 +297,32 @@
_model.ExcerptMarkdown = _post.ExcerptMarkdown;
_model.EventId = _post.Event?.Id;
_model.CollaborationCategories = _post.Categories.ToList();
- _model.PossibleCollaborationPages = await db.PostCollaborationRequests
+
+ var requestedPageIds = await db.PostCollaborationRequests
.Where(r => r.PostId == _post.Id)
- .Select(r => r.Page)
+ .Select(r => r.PageId)
+ .Distinct()
+ .ToListAsync();
+
+ var requestedCategories = await db.Categories
+ .Include(c => c.Page)
+ .Where(c => requestedPageIds.Contains(c.PageId) && c.Name == null)
.ToListAsync();
+
+ foreach (var category in requestedCategories)
+ {
+ if (_model.CollaborationCategories.All(c => c.Id != category.Id))
+ _model.CollaborationCategories.Add(category);
+ }
}
if (_post.Event != null)
_relevantEvents.Add(_post.Event);
- // We need to find all events that the post can belong to (_relevantEvents), without updating categories
- //
- // SQL too hard, only allow updating event for posts owned by a single page
List owners = _post.GetOwners();
if (owners.Count != 1)
return;
- // Not supported by EF:
- // _relevantEvents.AddRange((await _db.Events
- // .Include(e => e.Groups)
- // .Where(e => gs.All(g => e.Groups.Contains(g)))
- // .OrderByDescending(e => e.StartUtc)
- // .Take(30)
- // .ToListAsync())
- // .Where(e => e != _post.Event));
- // If you smart, open a PR
+
Page owner = owners[0];
_relevantEvents.AddRange((await db.Events
.Include(e => e.Categories)
@@ -343,11 +341,11 @@
await using var scope = ServiceProvider.CreateAsyncScope();
var postService = scope.ServiceProvider.GetRequiredService();
-
+
Post post = await postService.Save(
PostId,
_model.EventId,
- _post!.Categories.Select(c => c.Id).Union(_model.CollaborationCategories.Select(c => c.Id)).ToHashSet(),
+ _model.CollaborationCategories.Select(c => c.Id).ToHashSet(),
_model.Title,
_model.ContentMarkdown,
_model.ExcerptMarkdown,
@@ -357,56 +355,43 @@
Nav.NavigateTo($"/posts/{post.Id}");
}
- private int? SelectedCollaborationCategoryId
- {
- get => _selectedCollaborationCategoryId;
- set
- {
- _selectedCollaborationCategoryId = value;
- if (value.HasValue)
- {
- var category = _administeredCategories.FirstOrDefault(c => c.Id == value.Value);
- if (category != null)
- {
- if (!_model.CollaborationCategories.Contains(category))
- _model.CollaborationCategories.Add(category);
- }
+ private void OpenPagePicker() => _isPagePickerOpen = true;
+ private void ClosePagePicker() => _isPagePickerOpen = false;
- _selectedCollaborationCategoryId = null;
- }
- }
- }
+ private bool RequiresCollaborationRequest(Page page)
+ => !AuthorizationService.AdministeredPageIds.Contains(page.Id);
- private void RemoveCollaborationCategory(Category category)
+ private List GetSelectedCollaborationPages()
{
- _model.CollaborationCategories.Remove(category);
+ var selectedPageIds = _model.CollaborationCategories.Select(c => c.PageId).ToHashSet();
+ return _allPages.Where(p => selectedPageIds.Contains(p.Id)).ToList();
}
- private int? SelectedPossibleCollaborationPageId
- {
- get => _selectedCollaborationCategoryId;
- set
- {
- _selectedCollaborationCategoryId = value;
- if (value.HasValue)
- {
- var page = _possibleCollaborationPages.FirstOrDefault(p => p.Id == value.Value);
- if (page != null)
- {
- if (!_model.PossibleCollaborationPages.Contains(page))
- _model.PossibleCollaborationPages.Add(page);
- }
+ private List GetPagesRequiringRequest()
+ => GetSelectedCollaborationPages().Where(RequiresCollaborationRequest).ToList();
- _selectedCollaborationCategoryId = null;
- }
- }
+ private List GetAddablePages()
+ {
+ var selectedPageIds = _model.CollaborationCategories.Select(c => c.PageId).ToHashSet();
+ return _allPages.Where(p => !selectedPageIds.Contains(p.Id)).ToList();
}
- private void RemovePossibleCollaborationPage(Page page)
+ private void AddCollaborationPage(int pageId)
{
- _model.PossibleCollaborationPages.Remove(page);
+ var page = _allPages.FirstOrDefault(p => p.Id == pageId);
+ var category = page?.Categories.FirstOrDefault(c => c.Name == null) ?? page?.Categories.FirstOrDefault();
+ if (category == null)
+ return;
+
+ if (_model.CollaborationCategories.All(c => c.Id != category.Id))
+ _model.CollaborationCategories.Add(category);
+
+ _isPagePickerOpen = false;
}
+ private void RemoveCollaborationPage(Page page)
+ => _model.CollaborationCategories.RemoveAll(c => c.PageId == page.Id);
+
private class NewPostModel
{
public int? EventId { get; set; }
@@ -414,7 +399,6 @@
[MaxLength(20000)] public string? ContentMarkdown { get; set; }
[MaxLength(1000)] public string? ExcerptMarkdown { get; set; }
public List CollaborationCategories { get; set; } = [];
- public List PossibleCollaborationPages { get; set; } = [];
}
}
diff --git a/StartSch/Services/AuthorizationService.cs b/StartSch/Services/AuthorizationService.cs
index d2758872..256e1aac 100644
--- a/StartSch/Services/AuthorizationService.cs
+++ b/StartSch/Services/AuthorizationService.cs
@@ -96,6 +96,11 @@ public bool CanCreatePost(Page page)
{
return AdministeredPageIds.Contains(page.Id);
}
+
+ public bool CanAcceptCollaborationRequests(Page page)
+ {
+ return AdministeredPageIds.Contains(page.Id);
+ }
public bool CanRead(Page page)
{
diff --git a/StartSch/Services/EventService.cs b/StartSch/Services/EventService.cs
index 9cfda4cf..92cc3ae5 100644
--- a/StartSch/Services/EventService.cs
+++ b/StartSch/Services/EventService.cs
@@ -18,40 +18,46 @@ public async Task Save(
Instant? end)
{
Event @event;
- var possibleCollaborationRequestPageIds = await db.Categories
+ var administeredPageIds = authorizationService.AdministeredPageIds;
+ var selectedCategories = await db.Categories
.Where(c => categoryIds.Contains(c.Id))
- .Select(c => c.PageId)
- .Distinct()
- .Where(pageId => !authorizationService.AdministeredPageIds.Contains(pageId))
.ToListAsync();
if (eventId == 0) // Create a new event
{
+ var newParent = parentId.HasValue
+ ? await db.Events
+ .Include(e => e.Categories)
+ .Where(e => e.Id == parentId)
+ .FirstAsync()
+ : null;
+
@event = new()
{
Title = title,
DescriptionMarkdown = descriptionMd,
Start = start,
End = end,
- Parent = parentId.HasValue
- ? await db.Events
- .Include(e => e.Categories)
- .Where(e => e.Id == parentId)
- .FirstAsync()
- : null,
+ Parent = newParent,
};
- @event.Categories.AddRange(
- await db.Categories
- .Where(c => categoryIds.Contains(c.Id))
- .ToListAsync()
- );
+ var assignableCategories = selectedCategories
+ .Where(c => administeredPageIds.Contains(c.PageId)
+ || (newParent != null && newParent.Categories.Any(pc => pc.Id == c.Id)))
+ .ToList();
+ @event.Categories.AddRange(assignableCategories);
authorizationService.CheckCreate(@event);
db.Events.Add(@event);
-
- // Save collaboration
+
+ var possibleCollaborationRequestPageIds = selectedCategories
+ .Select(c => c.PageId)
+ .Except(assignableCategories.Select(c => c.PageId))
+ .Where(pageId => !administeredPageIds.Contains(pageId))
+ .Distinct()
+ .ToList();
+
if (possibleCollaborationRequestPageIds.Count > 0)
{
var collaborationRequests = possibleCollaborationRequestPageIds
@@ -65,7 +71,6 @@ await db.Categories
db.EventCollaborationRequests.AddRange(collaborationRequests);
}
-
}
else // Update existing event
{
@@ -75,6 +80,8 @@ await db.Categories
.Include(e => e.Categories)
.FirstAsync(e => e.Id == eventId);
+ var existingCategoryIds = @event.Categories.Select(c => c.Id).ToHashSet();
+
var newParent = parentId == null
? null
: @event.Parent is { } parent && parent.Id == parentId
@@ -82,28 +89,36 @@ await db.Categories
: await db.Events
.Include(e => e.Categories)
.FirstAsync(e => e.Id == parentId);
- var newCategories = await db.Categories
- .Where(c => categoryIds.Contains(c.Id))
- .ToListAsync();
- authorizationService.CheckUpdate(@event, newParent, newCategories);
+ var assignableCategories = selectedCategories
+ .Where(c => administeredPageIds.Contains(c.PageId)
+ || existingCategoryIds.Contains(c.Id)
+ || (newParent != null && newParent.Categories.Any(pc => pc.Id == c.Id)))
+ .ToList();
+
+ authorizationService.CheckUpdate(@event, newParent, assignableCategories);
@event.Parent = newParent;
@event.Categories.Clear();
- @event.Categories.AddRange(newCategories);
+ @event.Categories.AddRange(assignableCategories);
@event.Start = start;
@event.End = end;
@event.Title = title;
@event.DescriptionMarkdown = descriptionMd;
-
- // Update collaboration requests
+
var existingCollaborationRequests = await db.EventCollaborationRequests
.Where(ecr => ecr.EventId == eventId)
.ToListAsync();
-
db.EventCollaborationRequests.RemoveRange(existingCollaborationRequests);
+ var possibleCollaborationRequestPageIds = selectedCategories
+ .Select(c => c.PageId)
+ .Except(assignableCategories.Select(c => c.PageId))
+ .Where(pageId => !administeredPageIds.Contains(pageId))
+ .Distinct()
+ .ToList();
+
if (possibleCollaborationRequestPageIds.Count > 0)
{
var collaborationRequests = possibleCollaborationRequestPageIds
diff --git a/StartSch/Services/FontCache.cs b/StartSch/Services/FontCache.cs
index 39d86dee..651585cd 100644
--- a/StartSch/Services/FontCache.cs
+++ b/StartSch/Services/FontCache.cs
@@ -75,6 +75,7 @@ public class FontCache
"open_in_browser",
"open_in_full",
"open_in_new",
+ "pending",
"publish",
"restaurant",
"save",
diff --git a/StartSch/Services/PostService.cs b/StartSch/Services/PostService.cs
index 99ca9b60..d18356df 100644
--- a/StartSch/Services/PostService.cs
+++ b/StartSch/Services/PostService.cs
@@ -20,39 +20,45 @@ public async Task Save(
PostAction action)
{
Post post;
- var possibleCollaborationRequestPageIds = await db.Categories
+ var administeredPageIds = authorizationService.AdministeredPageIds;
+ var selectedCategories = await db.Categories
.Where(c => categoryIds.Contains(c.Id))
- .Select(c => c.PageId)
- .Distinct()
- .Where(pageId => !authorizationService.AdministeredPageIds.Contains(pageId))
.ToListAsync();
- if (postId == 0)
+ if (postId == 0) // Create a new post
{
+ var newEvent = eventId.HasValue
+ ? await db.Events
+ .Include(e => e.Categories)
+ .FirstAsync(e => e.Id == eventId)
+ : null;
+
post = new()
{
Title = title,
ExcerptMarkdown = excerptMd,
ContentMarkdown = contentMd,
Created = SystemClock.Instance.GetCurrentInstant(),
- Event = eventId.HasValue
- ? await db.Events
- .Include(e => e.Categories)
- .FirstAsync(e => e.Id == eventId)
- : null
+ Event = newEvent,
};
- post.Categories.AddRange(
- await db.Categories
- .Where(c => categoryIds.Contains(c.Id))
- .ToListAsync()
- );
+ var newCategories = selectedCategories
+ .Where(c => administeredPageIds.Contains(c.PageId)
+ || (newEvent != null && newEvent.Categories.Any(ec => ec.Id == c.Id)))
+ .ToList();
+ post.Categories.AddRange(newCategories);
authorizationService.CheckCreate(post);
db.Posts.Add(post);
-
- // Save collaboration
+
+ var possibleCollaborationRequestPageIds = selectedCategories
+ .Select(c => c.PageId)
+ .Except(newCategories.Select(c => c.PageId))
+ .Where(pageId => !administeredPageIds.Contains(pageId))
+ .Distinct()
+ .ToList();
+
if (possibleCollaborationRequestPageIds.Count > 0)
{
var collaborationRequests = possibleCollaborationRequestPageIds
@@ -60,14 +66,14 @@ await db.Categories
{
PageId = pageId,
Post = post,
- PostId = post.Id
+ PostId = post.Id,
})
.ToList();
db.PostCollaborationRequests.AddRange(collaborationRequests);
}
}
- else
+ else // Update existing post
{
post = await db.Posts
.Include(p => p.Categories)
@@ -75,6 +81,8 @@ await db.Categories
.ThenInclude(e => e!.Categories)
.FirstAsync(p => p.Id == postId);
+ var existingCategoryIds = post.Categories.Select(c => c.Id).ToHashSet();
+
var newEvent = eventId == null
? null
: post.Event is { } existingEvent && existingEvent.Id == eventId
@@ -82,9 +90,12 @@ await db.Categories
: await db.Events
.Include(e => e.Categories)
.FirstAsync(e => e.Id == eventId);
- var newCategories = await db.Categories
- .Where(c => categoryIds.Contains(c.Id))
- .ToListAsync();
+
+ var newCategories = selectedCategories
+ .Where(c => administeredPageIds.Contains(c.PageId)
+ || existingCategoryIds.Contains(c.Id)
+ || (newEvent != null && newEvent.Categories.Any(ec => ec.Id == c.Id)))
+ .ToList();
authorizationService.CheckUpdate(post, newEvent, newCategories);
@@ -95,14 +106,19 @@ await db.Categories
post.Title = title;
post.ExcerptMarkdown = excerptMd;
post.ContentMarkdown = contentMd;
-
- // Update collaboration requests
+
var existingCollaborationRequests = await db.PostCollaborationRequests
.Where(pcr => pcr.PostId == postId)
.ToListAsync();
-
db.PostCollaborationRequests.RemoveRange(existingCollaborationRequests);
+ var possibleCollaborationRequestPageIds = selectedCategories
+ .Select(c => c.PageId)
+ .Except(newCategories.Select(c => c.PageId))
+ .Where(pageId => !administeredPageIds.Contains(pageId))
+ .Distinct()
+ .ToList();
+
if (possibleCollaborationRequestPageIds.Count > 0)
{
var collaborationRequests = possibleCollaborationRequestPageIds
@@ -110,7 +126,7 @@ await db.Categories
{
PageId = pageId,
Post = post,
- PostId = post.Id
+ PostId = post.Id,
})
.ToList();
diff --git a/StartSch/js/app.ts b/StartSch/js/app.ts
index e1b44a68..2e368bca 100644
--- a/StartSch/js/app.ts
+++ b/StartSch/js/app.ts
@@ -3,6 +3,13 @@ import "@material/web/button/filled-button.js";
import "@material/web/button/filled-tonal-button.js";
import "@material/web/button/outlined-button.js";
import "@material/web/button/text-button.js";
+import "@material/web/chips/assist-chip.js";
+import "@material/web/chips/chip-set.js";
+import "@material/web/chips/input-chip.js";
+import "@material/web/list/list.js";
+import "@material/web/list/list-item.js";
+import "@material/web/divider/divider.js";
+import "@material/web/dialog/dialog.js";
import "@material/web/icon/icon.js";
import "@material/web/iconbutton/icon-button.js";
import "@material/web/ripple/ripple.js";
From 2718db9f597163740857d740b437d7dce6883035 Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Sat, 21 Mar 2026 10:19:13 +0100
Subject: [PATCH 8/9] delete unused CollaborationPage.razor
---
.../Components/Pages/CollaborationPage.razor | 168 ------------------
1 file changed, 168 deletions(-)
delete mode 100644 StartSch/Components/Pages/CollaborationPage.razor
diff --git a/StartSch/Components/Pages/CollaborationPage.razor b/StartSch/Components/Pages/CollaborationPage.razor
deleted file mode 100644
index d23084af..00000000
--- a/StartSch/Components/Pages/CollaborationPage.razor
+++ /dev/null
@@ -1,168 +0,0 @@
-@attribute [Authorize]
-@page "/collaborations/{PageId:int}"
-
-@using StartSch.Services
-
-@rendermode InteractiveServerWithoutPrerendering
-@layout MainLayout
-@inherits ResourcePage
-
-@inject IDbContextFactory DbFactory
-@inject AuthorizationService AuthorizationService
-
-@if (!IsResourceAvailable(_page, AuthorizationService.CanAcceptCollaborationRequests, out var status))
-{
-
- return;
-}
-
-
-
-
-
Oldal együttműködési kérelmei
-
-
- @if (_items.Count == 0)
- {
- Nincsenek együttműködési kérelmek.
- }
- else
- {
-
- @foreach (var request in _items)
- {
- -
- @if (request is EventCollaborationRequest eventRequest)
- {
-
- Esemény együttműködés
-
-
-
- Szervező: @(eventRequest.Event.Categories.FirstOrDefault()?.Page.Name ?? eventRequest.Event.Categories.FirstOrDefault()?.Page.PekName ?? "Ismeretlen")
-
- }
- else if (request is PostCollaborationRequest postRequest)
- {
-
- Poszt együttműködés
-
-
-
- Szerző: @(postRequest.Post.Categories.FirstOrDefault()?.Page.Name ?? postRequest.Post.Categories.FirstOrDefault()?.Page.PekName ?? "Ismeretlen")
-
- }
-
-
- Accept(request)" class="small filled round">
- Elfogadás
-
- Deny(request)"
- class="small text round error standard">Elutasítás
-
-
-
- }
-
- }
-
-
-
-@code {
- private Page? _page;
- private readonly List _items = [];
- [Parameter] public int PageId { get; set; }
-
- protected override async Task OnInitializedAsync()
- {
- await using var db = await DbFactory.CreateDbContextAsync();
-
- _page = await db.Pages.FirstOrDefaultAsync(g => g.Id == PageId);
- if (_page == null)
- return;
-
- _items.AddRange(await db.CollaborationRequests
- .Where(r => r.PageId == PageId)
- .Include(r => ((EventCollaborationRequest)r).Event)
- .ThenInclude(e => e.Categories)
- .ThenInclude(c => c.Page)
- .Include(r => ((PostCollaborationRequest)r).Post)
- .ThenInclude(p => p.Categories)
- .ThenInclude(c => c.Page)
- .ToListAsync());
- }
-
- private async Task Accept(CollaborationRequest request)
- {
- await using var db = await DbFactory.CreateDbContextAsync();
-
- var page = await db.Pages
- .Include(p => p.Categories)
- .FirstOrDefaultAsync(p => p.Id == PageId);
-
- if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page) || page.Categories.Count == 0)
- return;
- var category = page.Categories[0];
-
- if (request is EventCollaborationRequest evInfo)
- {
- var ev = await db.Events
- .Include(e => e.Categories)
- .FirstOrDefaultAsync(e => e.Id == evInfo.EventId);
-
- if (ev != null)
- {
- if (!ev.Categories.Any(c => c.Id == category.Id))
- ev.Categories.Add(category);
-
- var toRemove = await db.CollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
- if (toRemove != null)
- db.CollaborationRequests.Remove(toRemove);
- }
- }
- else if (request is PostCollaborationRequest postInfo)
- {
- var post = await db.Posts
- .Include(p => p.Categories)
- .FirstOrDefaultAsync(p => p.Id == postInfo.PostId);
-
- if (post != null)
- {
- if (!post.Categories.Any(c => c.Id == category.Id))
- post.Categories.Add(category);
-
- var toRemove = await db.CollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
- if (toRemove != null)
- db.CollaborationRequests.Remove(toRemove);
- }
- }
-
- await db.SaveChangesAsync();
- _items.Remove(request);
- }
-
- private async Task Deny(CollaborationRequest request)
- {
- await using var db = await DbFactory.CreateDbContextAsync();
-
- var page = await db.Pages.FirstOrDefaultAsync(p => p.Id == PageId);
- if (page == null || !AuthorizationService.CanAcceptCollaborationRequests(page))
- return;
-
- var toRemove = await db.CollaborationRequests
- .FirstOrDefaultAsync(r => r.Id == request.Id && r.PageId == PageId);
- if (toRemove == null)
- return;
-
- db.CollaborationRequests.Remove(toRemove);
- await db.SaveChangesAsync();
- _items.Remove(request);
- }
-}
From 08a1846646a3675e09e36badbc05d64285eb005a Mon Sep 17 00:00:00 2001
From: TGyAkos
Date: Thu, 26 Mar 2026 20:50:40 +0100
Subject: [PATCH 9/9] fix add icon and EventEditPage.razor
---
StartSch/Components/Pages/EventEditPage.razor | 1 +
StartSch/Services/FontCache.cs | 1 +
2 files changed, 2 insertions(+)
diff --git a/StartSch/Components/Pages/EventEditPage.razor b/StartSch/Components/Pages/EventEditPage.razor
index 6fb7a8c7..13b99d67 100644
--- a/StartSch/Components/Pages/EventEditPage.razor
+++ b/StartSch/Components/Pages/EventEditPage.razor
@@ -262,6 +262,7 @@
.Where(c => categoryIds.Contains(c.Id))
.ToListAsync();
newEvent.Categories.AddRange(categories);
+ _model.CollaborationCategories = categories.ToList();
_event = newEvent;
}
diff --git a/StartSch/Services/FontCache.cs b/StartSch/Services/FontCache.cs
index 651585cd..534f4343 100644
--- a/StartSch/Services/FontCache.cs
+++ b/StartSch/Services/FontCache.cs
@@ -42,6 +42,7 @@ public class FontCache
IconNames =
[
"account_circle",
+ "add",
"admin_panel_settings",
"amend",
"arrow_forward",