From 6fdab7f474a665f3e6db7277e83b6a83f2a6dd7b Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 24 Oct 2025 18:22:00 +0200 Subject: [PATCH 01/26] #124 - update to aspire latest version --- src/KITT.AppHost/KITT.AppHost.csproj | 12 ++++++------ src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 2 +- .../KITT.Proposals.Web.Api.csproj | 2 +- src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj | 2 +- src/KITT.Support.Seeder/KITT.Support.Seeder.csproj | 4 ++-- src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj | 2 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 5967448..02ec4fb 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,6 +1,6 @@ - + Exe @@ -11,11 +11,11 @@ - - - - - + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index bc05eb5..a12cc94 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 50c6991..2d27b8b 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 4fc2edb..79f45b9 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index 98bfb58..b4cb56f 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index 923a605..a550eee 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 57a2a37..84903c3 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,7 +7,7 @@ - + From 72f801ad66fd7d9f46d9a55325e45ca2acb9f501 Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 7 Nov 2025 17:45:02 +0100 Subject: [PATCH 02/26] #124 - update packages --- .../DistributedApplicationBuilderExtensions.cs | 2 -- src/KITT.AppHost/KITT.AppHost.csproj | 2 +- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 2 +- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 2 +- src/KITT.Core/KITT.Core.csproj | 14 +++++++------- .../KITT.Proposals.Web.Api.csproj | 2 +- .../KITT.Proposals.Web.App.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 12 ++++++------ src/KITT.Support.Seeder/KITT.Support.Seeder.csproj | 4 ++-- .../KITT.Telegram.Functions.csproj | 8 ++++---- .../KITT.Telegram.Messages.csproj | 6 +++--- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 10 +++++----- .../KITT.Web.App.Client/KITT.Web.App.Client.csproj | 8 ++++---- src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj | 12 ++++++------ src/KITT.Web.Shared/KITT.Web.Shared.csproj | 8 ++++---- src/LemonBot.Clients/LemonBot.Clients.csproj | 4 ++-- src/LemonBot.Commands/LemonBot.Commands.csproj | 4 ++-- src/LemonBot/LemonBot.csproj | 6 +++--- .../KITT.Cms.Web.Api.Test.csproj | 8 ++++---- tests/KITT.Core.Test/KITT.Core.Test.csproj | 6 +++--- .../KITT.Telegram.Functions.Test.csproj | 4 ++-- tests/KITT.Web.Testing/KITT.Web.Testing.csproj | 2 +- 22 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs index 173940e..0ebe8ac 100644 --- a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs +++ b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs @@ -12,8 +12,6 @@ public static IResourceBuilder AddKittDatabase(th if (!builder.ExecutionContext.IsPublishMode) { var kittSql = builder.AddSqlServer(ServiceNames.Sql) - .WithContainerName("sqlserver-local") - .WithLifetime(ContainerLifetime.Persistent) .WithDataVolume("kitt-data"); return kittSql.AddDatabase(ServiceNames.Database, databaseName: "KITT"); diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 02ec4fb..859b851 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index a12cc94..a530ad8 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index 37fec1e..7b655da 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 58bb36c..c18344a 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -6,13 +6,13 @@ - - - - - - - + + + + + + + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 2d27b8b..58bd7b3 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index 1135d10..09a1276 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 79f45b9..233173d 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -10,13 +10,13 @@ - + - - - - - + + + + + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index b4cb56f..5d0a5f8 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -10,11 +10,11 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj b/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj index 0b73a36..92419a9 100644 --- a/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj +++ b/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj @@ -7,10 +7,10 @@ enable - - - - + + + + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index 75cd54f..d9243ce 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index 72d738a..20c193b 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -12,11 +12,11 @@ - - - - - + + + + + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index 9d2a983..de455df 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index a550eee..84165f3 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -14,13 +14,13 @@ - - - + + + - - + + - + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 84903c3..122901a 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -8,10 +8,10 @@ - - - - + + + + diff --git a/src/LemonBot.Clients/LemonBot.Clients.csproj b/src/LemonBot.Clients/LemonBot.Clients.csproj index 7714b8c..351ccd9 100644 --- a/src/LemonBot.Clients/LemonBot.Clients.csproj +++ b/src/LemonBot.Clients/LemonBot.Clients.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/LemonBot.Commands/LemonBot.Commands.csproj b/src/LemonBot.Commands/LemonBot.Commands.csproj index c1839c2..589a721 100644 --- a/src/LemonBot.Commands/LemonBot.Commands.csproj +++ b/src/LemonBot.Commands/LemonBot.Commands.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/LemonBot/LemonBot.csproj b/src/LemonBot/LemonBot.csproj index dc6c81f..079a315 100644 --- a/src/LemonBot/LemonBot.csproj +++ b/src/LemonBot/LemonBot.csproj @@ -6,9 +6,9 @@ enable - - - + + + diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index ab70dd0..fd09da5 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -12,11 +12,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index 26246c2..59a5773 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -14,10 +14,10 @@ - - + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj b/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj index 413a24b..5638e03 100644 --- a/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj +++ b/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj @@ -10,9 +10,9 @@ - + - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index 75a6224..6774c71 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -11,7 +11,7 @@ - + From fe945b7bd5a5c802b568856d16ff6837761b0476 Mon Sep 17 00:00:00 2001 From: albx Date: Mon, 10 Nov 2025 06:49:40 +0100 Subject: [PATCH 03/26] #124 - refactor streaming info. removed unused entities --- ...DistributedApplicationBuilderExtensions.cs | 6 +- src/KITT.AppHost/KITT.AppHost.csproj | 1 + .../Services/StreamingsEndpointsServices.cs | 8 +- src/KITT.Core/Commands/IStreamingCommands.cs | 6 +- .../Commands/IStreamingStatsCommands.cs | 11 - src/KITT.Core/Commands/StreamingCommands.cs | 20 +- .../Commands/StreamingStatsCommands.cs | 30 --- .../ServiceCollectionExtensions.cs | 3 +- src/KITT.Core/KITT.Core.csproj | 1 + ...1110054558_Refactor-Streamings.Designer.cs | 233 ++++++++++++++++++ .../20251110054558_Refactor-Streamings.cs | 120 +++++++++ .../Migrations/KittDbContextModelSnapshot.cs | 91 +------ src/KITT.Core/Models/Content.cs | 16 +- src/KITT.Core/Models/Expense.cs | 26 -- src/KITT.Core/Models/Rating.cs | 4 +- src/KITT.Core/Models/Settings.cs | 4 +- src/KITT.Core/Models/Streaming.cs | 34 +-- src/KITT.Core/Models/StreamingStats.cs | 31 --- src/KITT.Core/Persistence/KittDbContext.cs | 4 - .../Persistence/Mapping/ExpenseMapper.cs | 29 --- .../Persistence/Mapping/StreamingMapper.cs | 4 +- .../Mapping/StreamingStatsMapper.cs | 16 -- src/KITT.Core/ReadModels/Database.cs | 4 - .../Extensions/StreamingStatsExtensions.cs | 7 - src/KITT.Core/ReadModels/IDatabase.cs | 4 - .../Validators/StreamingValidator.cs | 4 +- .../Commands/StreamingCommandsTest.cs | 6 +- tests/KITT.Core.Test/Models/StreamingTests.cs | 6 +- 28 files changed, 431 insertions(+), 298 deletions(-) delete mode 100644 src/KITT.Core/Commands/IStreamingStatsCommands.cs delete mode 100644 src/KITT.Core/Commands/StreamingStatsCommands.cs create mode 100644 src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.Designer.cs create mode 100644 src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.cs delete mode 100644 src/KITT.Core/Models/Expense.cs delete mode 100644 src/KITT.Core/Models/StreamingStats.cs delete mode 100644 src/KITT.Core/Persistence/Mapping/ExpenseMapper.cs delete mode 100644 src/KITT.Core/Persistence/Mapping/StreamingStatsMapper.cs delete mode 100644 src/KITT.Core/ReadModels/Extensions/StreamingStatsExtensions.cs diff --git a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs index 0ebe8ac..7ca2778 100644 --- a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs +++ b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs @@ -12,7 +12,11 @@ public static IResourceBuilder AddKittDatabase(th if (!builder.ExecutionContext.IsPublishMode) { var kittSql = builder.AddSqlServer(ServiceNames.Sql) - .WithDataVolume("kitt-data"); + .WithDataVolume("kitt-data") + .WithDbGate(containerBuilder => + { + containerBuilder.WithExplicitStart(); + }); return kittSql.AddDatabase(ServiceNames.Database, databaseName: "KITT"); } diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 859b851..237f4b4 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -17,6 +17,7 @@ + diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index 3c02c7d..6af8c9a 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -40,8 +40,8 @@ public async Task GetAllStreamingsAsync(string userId, int ScheduledOn = s.ScheduleDate, StartingTime = s.StartingTime, Title = s.Title, - HostingChannelUrl = s.HostingChannelUrl, - YouTubeVideoUrl = s.YouTubeVideoUrl + HostingChannelUrl = s.TwitchUrl ?? string.Empty, + YouTubeVideoUrl = s.YouTubeUrl }).Skip(skip).Take(size).ToArrayAsync(); var model = new StreamingsListModel { TotalItems = streamingsQuery.Count(), Items = streamings }; @@ -61,11 +61,11 @@ public async Task GetAllStreamingsAsync(string userId, int Id = streaming.Id, ScheduleDate = streaming.ScheduleDate, EndingTime = streaming.EndingTime, - HostingChannelUrl = streaming.HostingChannelUrl, + HostingChannelUrl = streaming.TwitchUrl ?? string.Empty, StartingTime = streaming.StartingTime, StreamingAbstract = streaming.Abstract, Title = streaming.Title, - YoutubeVideoUrl = streaming.YouTubeVideoUrl, + YoutubeVideoUrl = streaming.YouTubeUrl, Slug = streaming.Slug }; } diff --git a/src/KITT.Core/Commands/IStreamingCommands.cs b/src/KITT.Core/Commands/IStreamingCommands.cs index b9ab979..880bb50 100644 --- a/src/KITT.Core/Commands/IStreamingCommands.cs +++ b/src/KITT.Core/Commands/IStreamingCommands.cs @@ -2,11 +2,11 @@ public interface IStreamingCommands { - Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, Content.SeoData seo); + Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, Content.SeoData seo); - Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, string youtubeRegistrationLink, Content.SeoData seo); + Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string youtubeUrl, Content.SeoData seo); Task DeleteStreamingAsync(Guid streamingId); - Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, string youtubeRegistrationLink, Content.SeoData seo); + Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string? youtubeUrl, Content.SeoData seo); } diff --git a/src/KITT.Core/Commands/IStreamingStatsCommands.cs b/src/KITT.Core/Commands/IStreamingStatsCommands.cs deleted file mode 100644 index d25e355..0000000 --- a/src/KITT.Core/Commands/IStreamingStatsCommands.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace KITT.Core.Commands; - -public interface IStreamingStatsCommands -{ - Task RegisterStreamingStatsAsync( - Guid streamingId, - int viewers, - int subscribers, - int userJoinedNumber, - int userLeftNumber); -} diff --git a/src/KITT.Core/Commands/StreamingCommands.cs b/src/KITT.Core/Commands/StreamingCommands.cs index 54123af..2412c03 100644 --- a/src/KITT.Core/Commands/StreamingCommands.cs +++ b/src/KITT.Core/Commands/StreamingCommands.cs @@ -19,7 +19,7 @@ public StreamingCommands(KittDbContext context, StreamingValidator validator, IM _messageBus = messageBus ?? throw new ArgumentNullException(nameof(messageBus)); } - public async Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, Content.SeoData seo) + public async Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, Content.SeoData seo) { var streaming = Streaming.Schedule( streamingTitle, @@ -28,7 +28,7 @@ public async Task ScheduleStreamingAsync(string userId, string twitchChann scheduleDate, startingTime, endingTime, - hostingChannelUrl, + twitchUrl, userId); if (!string.IsNullOrWhiteSpace(streamingAbstract)) @@ -60,7 +60,7 @@ public async Task ScheduleStreamingAsync(string userId, string twitchChann return streaming.Id; } - public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, string youtubeRegistrationLink, Content.SeoData seo) + public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string youtubeUrl, Content.SeoData seo) { var messagesToSend = new List(); @@ -89,9 +89,9 @@ public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, //messagesToSend.Add(scheduledChangedMessage); } - if (streaming.HostingChannelUrl != hostingChannelUrl) + if (streaming.TwitchUrl != twitchUrl) { - streaming.ChangeHostingChannelUrl(hostingChannelUrl); + streaming.SetTwitchUrl(twitchUrl); //var hostingChannelChangedMessage = new StreamingHostingChannelChangedMessage( // streamingId, @@ -109,9 +109,9 @@ public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, streaming.SetAbstract(streamingAbstract); } - if (streaming.YouTubeVideoUrl != youtubeRegistrationLink) + if (streaming.YouTubeUrl != youtubeUrl) { - streaming.SetRegistrationYoutubeUrl(youtubeRegistrationLink); + streaming.SetYoutubeUrl(youtubeUrl); //var videoUploadedMessage = new StreamingVideoUploadedMessage( // streamingId, // streaming.Title, @@ -157,7 +157,7 @@ public async Task DeleteStreamingAsync(Guid streamingId) //await _messageBus.SendAsync(message); } - public async Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string streamingAbstract, string youtubeRegistrationLink, Content.SeoData seo) + public async Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string? youtubeUrl, Content.SeoData seo) { var streaming = Streaming.Import( streamingTitle, @@ -166,8 +166,8 @@ public async Task ImportStreamingAsync(string userId, string twitchChannel scheduleDate, startingTime, endingTime, - hostingChannelUrl, - youtubeRegistrationLink, + twitchUrl, + youtubeUrl, streamingAbstract, userId); diff --git a/src/KITT.Core/Commands/StreamingStatsCommands.cs b/src/KITT.Core/Commands/StreamingStatsCommands.cs deleted file mode 100644 index b75676f..0000000 --- a/src/KITT.Core/Commands/StreamingStatsCommands.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace KITT.Core.Commands; - -public class StreamingStatsCommands : IStreamingStatsCommands -{ - private readonly KittDbContext _context; - - public StreamingStatsCommands(KittDbContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } - - public Task RegisterStreamingStatsAsync(Guid streamingId, int viewers, int subscribers, int userJoinedNumber, int userLeftNumber) - { - var streaming = _context.Streamings.SingleOrDefault(s => s.Id == streamingId); - if (streaming is null) - { - throw new ArgumentOutOfRangeException(nameof(streamingId)); - } - - var stats = StreamingStats.RegisterStats( - streaming, - viewers, - subscribers, - userJoinedNumber, - userLeftNumber); - - _context.Add(stats); - return _context.SaveChangesAsync(); - } -} diff --git a/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs b/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs index 58baeb1..4f01c9f 100644 --- a/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs @@ -15,8 +15,7 @@ public static IServiceCollection AddKittCore(this IServiceCollection services) .AddScoped() .AddScoped() .AddScoped() - .AddScoped() - .AddScoped(); + .AddScoped(); return services; } diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index c18344a..3678450 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -3,6 +3,7 @@ net9.0 enable + enable diff --git a/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.Designer.cs b/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.Designer.cs new file mode 100644 index 0000000..9501274 --- /dev/null +++ b/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.Designer.cs @@ -0,0 +1,233 @@ +// +using System; +using KITT.Core.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace KITT.Core.Migrations +{ + [DbContext(typeof(KittDbContext))] + [Migration("20251110054558_Refactor-Streamings")] + partial class RefactorStreamings + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("KITT.Core.Models.Content", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Abstract") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PublicationDate") + .HasColumnType("datetime2"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("Title"); + + b.HasIndex("UserId"); + + b.ToTable("KITT_Contents", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("KITT.Core.Models.Proposal", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorNickname") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(max)") + .HasDefaultValue("Moderating"); + + b.Property("SubmittedAt") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("KITT_Proposals", (string)null); + }); + + modelBuilder.Entity("KITT.Core.Models.Rating", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("NumberOfDislikes") + .HasColumnType("int"); + + b.Property("NumberOfLikes") + .HasColumnType("int"); + + b.Property("PageUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Website") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.ToTable("KITT_Ratings", (string)null); + }); + + modelBuilder.Entity("KITT.Core.Models.Settings", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("TwitchChannel") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("Id"); + + b.HasIndex("TwitchChannel"); + + b.HasIndex("UserId"); + + b.ToTable("KITT_Settings", (string)null); + }); + + modelBuilder.Entity("KITT.Core.Models.Streaming", b => + { + b.HasBaseType("KITT.Core.Models.Content"); + + b.Property("EndingTime") + .HasColumnType("time"); + + b.Property("ScheduleDate") + .HasColumnType("date"); + + b.Property("StartingTime") + .HasColumnType("time"); + + b.Property("TwitchChannel") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TwitchUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("YouTubeChannel") + .HasColumnType("nvarchar(max)"); + + b.Property("YouTubeUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasIndex("TwitchChannel"); + + b.ToTable("KITT_Streamings", (string)null); + }); + + modelBuilder.Entity("KITT.Core.Models.Content", b => + { + b.OwnsOne("KITT.Core.Models.Content+SeoData", "Seo", b1 => + { + b1.Property("ContentId") + .HasColumnType("uniqueidentifier"); + + b1.Property("Description") + .HasColumnType("nvarchar(max)"); + + b1.Property("Keywords") + .HasColumnType("nvarchar(max)"); + + b1.Property("Title") + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ContentId"); + + b1.ToTable("KITT_Contents"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Seo") + .IsRequired(); + }); + + modelBuilder.Entity("KITT.Core.Models.Streaming", b => + { + b.HasOne("KITT.Core.Models.Content", null) + .WithOne() + .HasForeignKey("KITT.Core.Models.Streaming", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.cs b/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.cs new file mode 100644 index 0000000..c2fc792 --- /dev/null +++ b/src/KITT.Core/Migrations/20251110054558_Refactor-Streamings.cs @@ -0,0 +1,120 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KITT.Core.Migrations +{ + /// + public partial class RefactorStreamings : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "KITT_Expenses"); + + migrationBuilder.DropTable( + name: "KITT_StreamingStats"); + + migrationBuilder.RenameColumn( + name: "YouTubeVideoUrl", + table: "KITT_Streamings", + newName: "YouTubeUrl"); + + migrationBuilder.RenameColumn( + name: "HostingChannelUrl", + table: "KITT_Streamings", + newName: "TwitchUrl"); + + migrationBuilder.AddColumn( + name: "YouTubeChannel", + table: "KITT_Streamings", + type: "nvarchar(max)", + nullable: true); + + migrationBuilder.AlterColumn( + name: "AuthorNickname", + table: "KITT_Proposals", + type: "nvarchar(50)", + maxLength: 50, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(50)", + oldMaxLength: 50, + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "YouTubeChannel", + table: "KITT_Streamings"); + + migrationBuilder.RenameColumn( + name: "YouTubeUrl", + table: "KITT_Streamings", + newName: "YouTubeVideoUrl"); + + migrationBuilder.RenameColumn( + name: "TwitchUrl", + table: "KITT_Streamings", + newName: "HostingChannelUrl"); + + migrationBuilder.AlterColumn( + name: "AuthorNickname", + table: "KITT_Proposals", + type: "nvarchar(50)", + maxLength: 50, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(50)", + oldMaxLength: 50); + + migrationBuilder.CreateTable( + name: "KITT_Expenses", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Description = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + ExpenseDate = table.Column(type: "datetime2", nullable: false), + Method = table.Column(type: "nvarchar(max)", nullable: false), + PaymentInfo = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + Title = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + TotalAmount = table.Column(type: "decimal(10,2)", precision: 10, scale: 2, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_KITT_Expenses", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "KITT_StreamingStats", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + StreamingId = table.Column(type: "uniqueidentifier", nullable: true), + Subscribers = table.Column(type: "int", nullable: false), + UserJoinedNumber = table.Column(type: "int", nullable: false), + UserLeftNumber = table.Column(type: "int", nullable: false), + Viewers = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_KITT_StreamingStats", x => x.Id); + table.ForeignKey( + name: "FK_KITT_StreamingStats_KITT_Streamings_StreamingId", + column: x => x.StreamingId, + principalTable: "KITT_Streamings", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_KITT_StreamingStats_StreamingId", + table: "KITT_StreamingStats", + column: "StreamingId"); + } + } +} diff --git a/src/KITT.Core/Migrations/KittDbContextModelSnapshot.cs b/src/KITT.Core/Migrations/KittDbContextModelSnapshot.cs index 33aa1ee..ecf1c44 100644 --- a/src/KITT.Core/Migrations/KittDbContextModelSnapshot.cs +++ b/src/KITT.Core/Migrations/KittDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("ProductVersion", "9.0.10") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -69,46 +69,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.UseTptMappingStrategy(); }); - modelBuilder.Entity("KITT.Core.Models.Expense", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b.Property("ExpenseDate") - .HasColumnType("datetime2"); - - b.Property("Method") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentInfo") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("TotalAmount") - .HasPrecision(10, 2) - .HasColumnType("decimal(10,2)"); - - b.HasKey("Id"); - - b.ToTable("KITT_Expenses", (string)null); - }); - modelBuilder.Entity("KITT.Core.Models.Proposal", b => { b.Property("Id") .HasColumnType("uniqueidentifier"); b.Property("AuthorNickname") + .IsRequired() .HasMaxLength(50) .HasColumnType("nvarchar(50)"); @@ -186,33 +153,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("KITT_Settings", (string)null); }); - modelBuilder.Entity("KITT.Core.Models.StreamingStats", b => - { - b.Property("Id") - .HasColumnType("uniqueidentifier"); - - b.Property("StreamingId") - .HasColumnType("uniqueidentifier"); - - b.Property("Subscribers") - .HasColumnType("int"); - - b.Property("UserJoinedNumber") - .HasColumnType("int"); - - b.Property("UserLeftNumber") - .HasColumnType("int"); - - b.Property("Viewers") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("StreamingId"); - - b.ToTable("KITT_StreamingStats", (string)null); - }); - modelBuilder.Entity("KITT.Core.Models.Streaming", b => { b.HasBaseType("KITT.Core.Models.Content"); @@ -220,11 +160,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EndingTime") .HasColumnType("time"); - b.Property("HostingChannelUrl") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - b.Property("ScheduleDate") .HasColumnType("date"); @@ -236,7 +171,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(50) .HasColumnType("nvarchar(50)"); - b.Property("YouTubeVideoUrl") + b.Property("TwitchUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("YouTubeChannel") + .HasColumnType("nvarchar(max)"); + + b.Property("YouTubeUrl") .HasMaxLength(255) .HasColumnType("nvarchar(255)"); @@ -269,16 +212,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ContentId"); }); - b.Navigation("Seo"); - }); - - modelBuilder.Entity("KITT.Core.Models.StreamingStats", b => - { - b.HasOne("KITT.Core.Models.Streaming", "Streaming") - .WithMany() - .HasForeignKey("StreamingId"); - - b.Navigation("Streaming"); + b.Navigation("Seo") + .IsRequired(); }); modelBuilder.Entity("KITT.Core.Models.Streaming", b => diff --git a/src/KITT.Core/Models/Content.cs b/src/KITT.Core/Models/Content.cs index 56e40b1..5224e56 100644 --- a/src/KITT.Core/Models/Content.cs +++ b/src/KITT.Core/Models/Content.cs @@ -5,13 +5,13 @@ public abstract class Content #region Properties public Guid Id { get; protected set; } - public string UserId { get; protected set; } + public string UserId { get; protected set; } = string.Empty; - public string Title { get; protected set; } + public string Title { get; protected set; } = string.Empty; - public string Slug { get; protected set; } + public string Slug { get; protected set; } = string.Empty; - public string Abstract { get; protected set; } + public string? Abstract { get; protected set; } public virtual SeoData Seo { get; protected set; } @@ -41,7 +41,7 @@ public virtual void ChangeTitle(string title) Title = title; } - public virtual void SetAbstract(string @abstract) + public virtual void SetAbstract(string? @abstract) { Abstract = @abstract; } @@ -64,11 +64,11 @@ public virtual void PublishOn(DateTime publicationDate) #region Inner classes public record SeoData { - public string Title { get; init; } + public string? Title { get; init; } - public string Description { get; init; } + public string? Description { get; init; } - public string Keywords { get; init; } + public string? Keywords { get; init; } } public enum ContentStatus diff --git a/src/KITT.Core/Models/Expense.cs b/src/KITT.Core/Models/Expense.cs deleted file mode 100644 index 2576820..0000000 --- a/src/KITT.Core/Models/Expense.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace KITT.Core.Models; - -public class Expense -{ - public Guid Id { get; protected set; } - - public string Title { get; protected set; } - - public DateTime ExpenseDate { get; protected set; } - - public decimal TotalAmount { get; protected set; } - - public string Description { get; protected set; } - - public PaymentMethod Method { get; protected set; } - - public string PaymentInfo { get; protected set; } - - public enum PaymentMethod - { - Cash, - Bancomat, - CreditCard, - BankAccount - } -} diff --git a/src/KITT.Core/Models/Rating.cs b/src/KITT.Core/Models/Rating.cs index e322ef4..6e61a5f 100644 --- a/src/KITT.Core/Models/Rating.cs +++ b/src/KITT.Core/Models/Rating.cs @@ -4,9 +4,9 @@ public class Rating { public Guid Id { get; protected set; } - public string Website { get; protected set; } + public string Website { get; protected set; } = string.Empty; - public string PageUrl { get; protected set; } + public string PageUrl { get; protected set; } = string.Empty; public int NumberOfLikes { get; protected set; } diff --git a/src/KITT.Core/Models/Settings.cs b/src/KITT.Core/Models/Settings.cs index 89634ec..d5cfe0d 100644 --- a/src/KITT.Core/Models/Settings.cs +++ b/src/KITT.Core/Models/Settings.cs @@ -4,9 +4,9 @@ public class Settings { public Guid Id { get; protected set; } - public string UserId { get; protected set; } + public string UserId { get; protected set; } = string.Empty; - public string TwitchChannel { get; protected set; } + public string TwitchChannel { get; protected set; } = string.Empty; #region Public methods public void Update(string twitchChannel) diff --git a/src/KITT.Core/Models/Streaming.cs b/src/KITT.Core/Models/Streaming.cs index 9cfc222..7c754ed 100644 --- a/src/KITT.Core/Models/Streaming.cs +++ b/src/KITT.Core/Models/Streaming.cs @@ -2,7 +2,9 @@ public class Streaming : Content { - public string TwitchChannel { get; protected set; } + public string? TwitchChannel { get; protected set; } + + public string? YouTubeChannel { get; protected set; } public DateOnly ScheduleDate { get; protected set; } @@ -10,9 +12,9 @@ public class Streaming : Content public TimeOnly EndingTime { get; protected set; } - public string HostingChannelUrl { get; protected set; } + public string? TwitchUrl { get; protected set; } - public string YouTubeVideoUrl { get; protected set; } + public string? YouTubeUrl { get; protected set; } #region Constructor protected Streaming() : base() { } @@ -31,19 +33,19 @@ public void ChangeSchedule(DateOnly scheduleDate, TimeOnly startingTime, TimeOnl this.EndingTime = endingTime; } - public void SetRegistrationYoutubeUrl(string youtubeUrl) + public void SetYoutubeUrl(string youtubeUrl) { - this.YouTubeVideoUrl = youtubeUrl; + YouTubeUrl = youtubeUrl; } - public void ChangeHostingChannelUrl(string hostingChannelUrl) + public void SetTwitchUrl(string twitchUrl) { - this.HostingChannelUrl = hostingChannelUrl; + TwitchUrl = twitchUrl; } #endregion #region Factory - public static Streaming Schedule(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string userId) + public static Streaming Schedule(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string userId) { if (string.IsNullOrWhiteSpace(title)) { @@ -70,9 +72,9 @@ public static Streaming Schedule(string title, string slug, string twitchChannel throw new ArgumentException("Starting time should be previuos than ending time", nameof(endingTime)); } - if (string.IsNullOrWhiteSpace(hostingChannelUrl)) + if (string.IsNullOrWhiteSpace(twitchUrl)) { - throw new ArgumentException("value cannot be empty", nameof(hostingChannelUrl)); + throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); } if (string.IsNullOrWhiteSpace(userId)) @@ -90,7 +92,7 @@ public static Streaming Schedule(string title, string slug, string twitchChannel ScheduleDate = scheduleDate, StartingTime = startingTime, EndingTime = endingTime, - HostingChannelUrl = hostingChannelUrl + TwitchUrl = twitchUrl }; streaming.Publish(); @@ -98,7 +100,7 @@ public static Streaming Schedule(string title, string slug, string twitchChannel return streaming; } - public static Streaming Import(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string hostingChannelUrl, string youtubeVideoUrl, string @abstract, string userId) + public static Streaming Import(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? youtubeUrl, string? @abstract, string userId) { if (string.IsNullOrWhiteSpace(title)) { @@ -120,9 +122,9 @@ public static Streaming Import(string title, string slug, string twitchChannel, throw new ArgumentException("Starting time should be previuos than ending time", nameof(endingTime)); } - if (string.IsNullOrWhiteSpace(hostingChannelUrl)) + if (string.IsNullOrWhiteSpace(twitchUrl)) { - throw new ArgumentException("value cannot be empty", nameof(hostingChannelUrl)); + throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); } if (string.IsNullOrWhiteSpace(userId)) @@ -140,9 +142,9 @@ public static Streaming Import(string title, string slug, string twitchChannel, ScheduleDate = scheduleDate, StartingTime = startingTime, EndingTime = endingTime, - HostingChannelUrl = hostingChannelUrl, + TwitchUrl = twitchUrl, Abstract = @abstract, - YouTubeVideoUrl = youtubeVideoUrl + YouTubeUrl = youtubeUrl }; streaming.PublishOn(scheduleDate.ToDateTime(TimeOnly.MinValue)); diff --git a/src/KITT.Core/Models/StreamingStats.cs b/src/KITT.Core/Models/StreamingStats.cs deleted file mode 100644 index a0ebf04..0000000 --- a/src/KITT.Core/Models/StreamingStats.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace KITT.Core.Models; - -public class StreamingStats -{ - public Guid Id { get; protected set; } - - public virtual Streaming Streaming { get; protected set; } - - public int Viewers { get; protected set; } - - public int Subscribers { get; protected set; } - - public int UserJoinedNumber { get; protected set; } - - public int UserLeftNumber { get; protected set; } - - public static StreamingStats RegisterStats(Streaming streaming, int viewers, int subscribers, int userJoinedNumber, int userLeftNumber) - { - ArgumentNullException.ThrowIfNull(streaming); - - return new StreamingStats - { - Id = Guid.NewGuid(), - Streaming = streaming, - Viewers = viewers, - Subscribers = subscribers, - UserJoinedNumber = userJoinedNumber, - UserLeftNumber = userLeftNumber - }; - } -} diff --git a/src/KITT.Core/Persistence/KittDbContext.cs b/src/KITT.Core/Persistence/KittDbContext.cs index 59d48b6..45507d1 100644 --- a/src/KITT.Core/Persistence/KittDbContext.cs +++ b/src/KITT.Core/Persistence/KittDbContext.cs @@ -15,10 +15,6 @@ public KittDbContext(DbContextOptions options) public DbSet Proposals { get; set; } - public DbSet Expenses { get; set; } - - public DbSet StreamingStats { get; set; } - public DbSet Ratings { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/src/KITT.Core/Persistence/Mapping/ExpenseMapper.cs b/src/KITT.Core/Persistence/Mapping/ExpenseMapper.cs deleted file mode 100644 index 776c31a..0000000 --- a/src/KITT.Core/Persistence/Mapping/ExpenseMapper.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace KITT.Core.Persistence.Mapping; - -internal class ExpenseMapper : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable($"{Defaults.TablePrefix}_Expenses"); - - builder.HasKey(e => e.Id); - builder.Property(e => e.Id).ValueGeneratedNever(); - - builder.Property(e => e.Title) - .HasMaxLength(100) - .IsRequired(); - - builder.Property(e => e.ExpenseDate).IsRequired(); - - builder.Property(e => e.TotalAmount) - .HasPrecision(10, 2) - .IsRequired(); - - builder.Property(e => e.Description).HasMaxLength(255); - builder.Property(e => e.PaymentInfo).HasMaxLength(100); - - builder.Property(e => e.Method).HasConversion(); - } -} diff --git a/src/KITT.Core/Persistence/Mapping/StreamingMapper.cs b/src/KITT.Core/Persistence/Mapping/StreamingMapper.cs index 56f9490..cc4994c 100644 --- a/src/KITT.Core/Persistence/Mapping/StreamingMapper.cs +++ b/src/KITT.Core/Persistence/Mapping/StreamingMapper.cs @@ -11,7 +11,7 @@ public void Configure(EntityTypeBuilder builder) builder.Property(s => s.TwitchChannel).HasMaxLength(50).IsRequired(); builder.HasIndex(s => s.TwitchChannel); - builder.Property(s => s.HostingChannelUrl).HasMaxLength(255).IsRequired(); - builder.Property(s => s.YouTubeVideoUrl).HasMaxLength(255); + builder.Property(s => s.TwitchUrl).HasMaxLength(255).IsRequired(); + builder.Property(s => s.YouTubeUrl).HasMaxLength(255); } } diff --git a/src/KITT.Core/Persistence/Mapping/StreamingStatsMapper.cs b/src/KITT.Core/Persistence/Mapping/StreamingStatsMapper.cs deleted file mode 100644 index bd17b85..0000000 --- a/src/KITT.Core/Persistence/Mapping/StreamingStatsMapper.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace KITT.Core.Persistence.Mapping; - -internal class StreamingStatsMapper : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable($"{Defaults.TablePrefix}_StreamingStats"); - - builder.HasKey(e => e.Id); - builder.Property(e => e.Id).ValueGeneratedNever(); - - builder.HasOne(s => s.Streaming).WithMany(); - } -} diff --git a/src/KITT.Core/ReadModels/Database.cs b/src/KITT.Core/ReadModels/Database.cs index 8162126..38f18e2 100644 --- a/src/KITT.Core/ReadModels/Database.cs +++ b/src/KITT.Core/ReadModels/Database.cs @@ -14,8 +14,4 @@ public Database(KittDbContext context) public IQueryable Settings => _context.Settings.AsNoTracking(); public IQueryable Proposals => _context.Proposals.AsNoTracking(); - - public IQueryable Expenses => _context.Expenses.AsNoTracking(); - - public IQueryable StreamingStats => _context.StreamingStats.AsNoTracking(); } diff --git a/src/KITT.Core/ReadModels/Extensions/StreamingStatsExtensions.cs b/src/KITT.Core/ReadModels/Extensions/StreamingStatsExtensions.cs deleted file mode 100644 index 3c7543f..0000000 --- a/src/KITT.Core/ReadModels/Extensions/StreamingStatsExtensions.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace KITT.Core.ReadModels; - -public static class StreamingStatsExtensions -{ - public static IQueryable ByStreaming(this IQueryable stats, Guid streamingId) - => stats.Include(s => s.Streaming).Where(s => s.Streaming.Id == streamingId); -} diff --git a/src/KITT.Core/ReadModels/IDatabase.cs b/src/KITT.Core/ReadModels/IDatabase.cs index df5a85b..1d10f95 100644 --- a/src/KITT.Core/ReadModels/IDatabase.cs +++ b/src/KITT.Core/ReadModels/IDatabase.cs @@ -7,8 +7,4 @@ public interface IDatabase IQueryable Settings { get; } IQueryable Proposals { get; } - - IQueryable Expenses { get; } - - IQueryable StreamingStats { get; } } diff --git a/src/KITT.Core/Validators/StreamingValidator.cs b/src/KITT.Core/Validators/StreamingValidator.cs index cd2625b..4f33643 100644 --- a/src/KITT.Core/Validators/StreamingValidator.cs +++ b/src/KITT.Core/Validators/StreamingValidator.cs @@ -30,8 +30,8 @@ private void DefineRules() RuleFor(streaming => streaming.TwitchChannel).MaximumLength(50).NotEmpty(); RuleFor(streaming => streaming.Title).MaximumLength(255).NotEmpty(); RuleFor(streaming => streaming.Slug).MaximumLength(255).NotEmpty(); - RuleFor(streaming => streaming.HostingChannelUrl).NotEmpty().MaximumLength(255); - RuleFor(streaming => streaming.YouTubeVideoUrl).MaximumLength(255); + RuleFor(streaming => streaming.TwitchUrl).NotEmpty().MaximumLength(255); + RuleFor(streaming => streaming.YouTubeUrl).MaximumLength(255); RuleSet(ScheduleStreamingAction, () => { diff --git a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs index ca6538e..753146b 100644 --- a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs +++ b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs @@ -134,7 +134,7 @@ public async Task ScheduleStreamingAsync_Should_Add_Streaming_With_Specified_Val Assert.Equal(scheduleDate, scheduledStreaming.ScheduleDate); Assert.Equal(startingTime, scheduledStreaming.StartingTime); Assert.Equal(endingTime, scheduledStreaming.EndingTime); - Assert.Equal(hostingChannelUrl, scheduledStreaming.HostingChannelUrl); + Assert.Equal(hostingChannelUrl, scheduledStreaming.TwitchUrl); Assert.Equal(streamingAbstract, scheduledStreaming.Abstract); } @@ -238,9 +238,9 @@ await commands.UpdateStreamingAsync( Assert.Equal(scheduleDate, updatedStreaming.ScheduleDate); Assert.Equal(startingTime, updatedStreaming.StartingTime); Assert.Equal(endingTime, updatedStreaming.EndingTime); - Assert.Equal(hostingChannelUrl, updatedStreaming.HostingChannelUrl); + Assert.Equal(hostingChannelUrl, updatedStreaming.TwitchUrl); Assert.Equal(streamingAbstract, updatedStreaming.Abstract); - Assert.Equal(youtubeRegistrationLink, updatedStreaming.YouTubeVideoUrl); + Assert.Equal(youtubeRegistrationLink, updatedStreaming.YouTubeUrl); } [Fact] diff --git a/tests/KITT.Core.Test/Models/StreamingTests.cs b/tests/KITT.Core.Test/Models/StreamingTests.cs index 1df5e9f..c6a22d7 100644 --- a/tests/KITT.Core.Test/Models/StreamingTests.cs +++ b/tests/KITT.Core.Test/Models/StreamingTests.cs @@ -170,7 +170,7 @@ public void Schedule_Should_Create_A_New_Streaming_With_Specified_Values() Assert.Equal(scheduleDate, streaming.ScheduleDate); Assert.Equal(startingTime, streaming.StartingTime); Assert.Equal(endingTime, streaming.EndingTime); - Assert.Equal(hostingChannelUrl, streaming.HostingChannelUrl); + Assert.Equal(hostingChannelUrl, streaming.TwitchUrl); Assert.NotEqual(Guid.Empty, streaming.Id); Assert.Equal(userId, streaming.UserId); } @@ -248,8 +248,8 @@ public void SetRegistrationYoutubeUrl_Should_Set_Youtube_Registration_Url_With_S var streaming = CreateStreamingForTests(); string youtubeUrl = "https://www.youtube.com"; - streaming.SetRegistrationYoutubeUrl(youtubeUrl); - Assert.Equal(youtubeUrl, streaming.YouTubeVideoUrl); + streaming.SetYoutubeUrl(youtubeUrl); + Assert.Equal(youtubeUrl, streaming.YouTubeUrl); } #endregion From 34300a8922633d6708582ca1ec8839cdfc078469 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 15 Nov 2025 16:48:54 +0100 Subject: [PATCH 04/26] #124 - update to .net 10 --- LemonBot.sln | 107 +++--------------- src/KITT.AppHost/KITT.AppHost.csproj | 14 +-- .../Endpoints/SettingsEndpoints.cs | 9 +- .../Endpoints/StreamingsEndpoints.cs | 21 ++-- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 6 +- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 4 +- .../KITT.Cms.Web.Models.csproj | 2 +- src/KITT.Core/KITT.Core.csproj | 7 +- .../Endpoints/ProposalsEndpoints.cs | 21 ++-- .../KITT.Proposals.Web.Api.csproj | 6 +- .../KITT.Proposals.Web.App.csproj | 4 +- .../KITT.Proposals.Web.Models.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 16 +-- src/KITT.Services/KITT.Services.csproj | 2 +- .../KITT.Support.Seeder.csproj | 10 +- .../KITT.Telegram.Functions.csproj | 3 - .../KITT.Telegram.Messages.csproj | 2 +- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 8 +- .../KITT.Web.App.Client.csproj | 5 +- .../KITT.Web.App/KITT.Web.App.csproj | 10 +- src/KITT.Web.Models/KITT.Web.Models.csproj | 2 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 6 +- .../LemonBot.Commands.csproj | 4 - .../KITT.Cms.Web.Api.Test.csproj | 8 +- tests/KITT.Core.Test/KITT.Core.Test.csproj | 6 +- .../KITT.Telegram.Functions.Test.csproj | 4 - .../KITT.Web.Testing/KITT.Web.Testing.csproj | 4 +- 27 files changed, 94 insertions(+), 199 deletions(-) diff --git a/LemonBot.sln b/LemonBot.sln index c92bdaf..ef0e38e 100644 --- a/LemonBot.sln +++ b/LemonBot.sln @@ -1,16 +1,10 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.0.11018.127 d18.0 +VisualStudioVersion = 18.0.11018.127 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LemonBot", "src\LemonBot\LemonBot.csproj", "{C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LemonBot.Commands", "src\LemonBot.Commands\LemonBot.Commands.csproj", "{0017D050-5521-4C55-B1CD-2DDB228CEC42}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LemonBot.Clients", "src\LemonBot.Clients\LemonBot.Clients.csproj", "{D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KITT", "KITT", "{53F76412-0B22-4C62-8519-834A82747AD4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.Models", "src\KITT.Web.Models\KITT.Web.Models.csproj", "{A9018405-BC9E-41FD-955A-5A3B4AED27A4}" @@ -23,12 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Core.Test", "tests\KIT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.App.UI", "src\KITT.Web.App.UI\KITT.Web.App.UI.csproj", "{2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Telegram.Messages", "src\KITT.Telegram.Messages\KITT.Telegram.Messages.csproj", "{6E87C525-EB68-4DAD-9F63-39E426D01668}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Telegram.Functions", "src\KITT.Telegram.Functions\KITT.Telegram.Functions.csproj", "{A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Telegram.Functions.Test", "tests\KITT.Telegram.Functions.Test\KITT.Telegram.Functions.Test.csproj", "{92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Cms.Web.Api", "src\KITT.Cms.Web.Api\KITT.Cms.Web.Api.csproj", "{406A74C4-AF3B-43C0-9D54-111B7CE24EBF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Cms.Web.Models", "src\KITT.Cms.Web.Models\KITT.Cms.Web.Models.csproj", "{7E0161FF-5AB4-451E-A95A-45D15BFC8C29}" @@ -65,6 +53,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Support.Seeder", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Services", "src\KITT.Services\KITT.Services.csproj", "{C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Telegram.Messages", "src\KITT.Telegram.Messages\KITT.Telegram.Messages.csproj", "{8C003A09-3777-AEFF-806A-A2010FD1DDDE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,42 +65,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|x64.ActiveCfg = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|x64.Build.0 = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|x86.ActiveCfg = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Debug|x86.Build.0 = Debug|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|Any CPU.Build.0 = Release|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|x64.ActiveCfg = Release|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|x64.Build.0 = Release|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|x86.ActiveCfg = Release|Any CPU - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC}.Release|x86.Build.0 = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|x64.ActiveCfg = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|x64.Build.0 = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|x86.ActiveCfg = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Debug|x86.Build.0 = Debug|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|Any CPU.Build.0 = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|x64.ActiveCfg = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|x64.Build.0 = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|x86.ActiveCfg = Release|Any CPU - {0017D050-5521-4C55-B1CD-2DDB228CEC42}.Release|x86.Build.0 = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|x64.ActiveCfg = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|x64.Build.0 = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|x86.ActiveCfg = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Debug|x86.Build.0 = Debug|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|Any CPU.Build.0 = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|x64.ActiveCfg = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|x64.Build.0 = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|x86.ActiveCfg = Release|Any CPU - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1}.Release|x86.Build.0 = Release|Any CPU {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|Any CPU.Build.0 = Debug|Any CPU {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -159,42 +113,6 @@ Global {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x64.Build.0 = Release|Any CPU {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x86.ActiveCfg = Release|Any CPU {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x86.Build.0 = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|x64.ActiveCfg = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|x64.Build.0 = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|x86.ActiveCfg = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Debug|x86.Build.0 = Debug|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|Any CPU.Build.0 = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|x64.ActiveCfg = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|x64.Build.0 = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|x86.ActiveCfg = Release|Any CPU - {6E87C525-EB68-4DAD-9F63-39E426D01668}.Release|x86.Build.0 = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|x64.ActiveCfg = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|x64.Build.0 = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|x86.ActiveCfg = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Debug|x86.Build.0 = Debug|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|Any CPU.Build.0 = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|x64.ActiveCfg = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|x64.Build.0 = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|x86.ActiveCfg = Release|Any CPU - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4}.Release|x86.Build.0 = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|x64.ActiveCfg = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|x64.Build.0 = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|x86.ActiveCfg = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Debug|x86.Build.0 = Debug|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|Any CPU.Build.0 = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|x64.ActiveCfg = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|x64.Build.0 = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|x86.ActiveCfg = Release|Any CPU - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE}.Release|x86.Build.0 = Release|Any CPU {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -375,22 +293,28 @@ Global {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x64.Build.0 = Release|Any CPU {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x86.ActiveCfg = Release|Any CPU {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x86.Build.0 = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x64.ActiveCfg = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x64.Build.0 = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x86.ActiveCfg = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x86.Build.0 = Debug|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|Any CPU.Build.0 = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x64.ActiveCfg = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x64.Build.0 = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.ActiveCfg = Release|Any CPU + {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C56ABDA1-E83F-4C97-B3C2-3A248526E4FC} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {0017D050-5521-4C55-B1CD-2DDB228CEC42} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {D2F9C1BB-F01E-459E-8C7E-F225F83A47B1} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} {53F76412-0B22-4C62-8519-834A82747AD4} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} {A9018405-BC9E-41FD-955A-5A3B4AED27A4} = {53F76412-0B22-4C62-8519-834A82747AD4} {66F99049-7BCF-47D4-81FF-8E0254FE82EE} = {53F76412-0B22-4C62-8519-834A82747AD4} {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235} = {B32B1475-75B8-41DD-BB71-D6106152C656} {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE} = {53F76412-0B22-4C62-8519-834A82747AD4} - {6E87C525-EB68-4DAD-9F63-39E426D01668} = {53F76412-0B22-4C62-8519-834A82747AD4} - {A6A4722A-4AA2-4B9C-A2FB-A7C171E03DF4} = {53F76412-0B22-4C62-8519-834A82747AD4} - {92122C69-6CEC-4FEA-BAC5-AC7F8197C6FE} = {B32B1475-75B8-41DD-BB71-D6106152C656} {406A74C4-AF3B-43C0-9D54-111B7CE24EBF} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} {7E0161FF-5AB4-451E-A95A-45D15BFC8C29} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} {A701C3B3-E70B-4386-BBD4-39B9376966EE} = {53F76412-0B22-4C62-8519-834A82747AD4} @@ -409,6 +333,7 @@ Global {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {53F76412-0B22-4C62-8519-834A82747AD4} {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} + {8C003A09-3777-AEFF-806A-A2010FD1DDDE} = {53F76412-0B22-4C62-8519-834A82747AD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08491B30-AD3E-4AEA-AAB9-40A83A96F393} diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 237f4b4..252ff2f 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,21 +1,21 @@ - + Exe - net9.0 + net10.0 enable enable 9088a778-e43f-44ea-8c00-27313c124862 - - - - - + + + + + diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index dc049ef..e15093e 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -18,18 +18,15 @@ public static IEndpointRouteBuilder MapSettingsEndpoints(this IEndpointRouteBuil settingsGroup .MapGet("", GetAllSettings) - .WithName(nameof(GetAllSettings)) - .WithOpenApi(); + .WithName(nameof(GetAllSettings)); settingsGroup .MapGet("{id}", GetSettingsDetails) - .WithName(nameof(GetSettingsDetails)) - .WithOpenApi(); + .WithName(nameof(GetSettingsDetails)); settingsGroup .MapPost("", CreateNewSettings) - .WithName(nameof(CreateNewSettings)) - .WithOpenApi(); + .WithName(nameof(CreateNewSettings)); return builder; } diff --git a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs index 98a384e..9c4ef02 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs @@ -18,38 +18,31 @@ public static IEndpointRouteBuilder MapStreamingsEndpoints(this IEndpointRouteBu streamingsGroup .MapGet("", GetAllStreamings) - .WithName(nameof(GetAllStreamings)) - .WithOpenApi(); + .WithName(nameof(GetAllStreamings)); streamingsGroup .MapGet("{id:guid}", GetStreamingDetail) - .WithName(nameof(GetStreamingDetail)) - .WithOpenApi(); + .WithName(nameof(GetStreamingDetail)); streamingsGroup .MapPost("", ScheduleStreaming) - .WithName(nameof(ScheduleStreaming)) - .WithOpenApi(); + .WithName(nameof(ScheduleStreaming)); streamingsGroup .MapPost("import", ImportStreaming) - .WithName(nameof(ImportStreaming)) - .WithOpenApi(); + .WithName(nameof(ImportStreaming)); streamingsGroup .MapPut("{id:guid}", UpdateStreaming) - .WithName(nameof(UpdateStreaming)) - .WithOpenApi(); + .WithName(nameof(UpdateStreaming)); streamingsGroup .MapDelete("{id:guid}", DeleteStreaming) - .WithName(nameof(DeleteStreaming)) - .WithOpenApi(); + .WithName(nameof(DeleteStreaming)); streamingsGroup .MapGet("stats", GetStreamingStats) - .WithName(nameof(GetStreamingStats)) - .WithOpenApi(); + .WithName(nameof(GetStreamingStats)); return builder; } diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index a530ad8..21a6729 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -1,14 +1,14 @@  - net9.0 + net10.0 enable enable - - + + diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index 7b655da..f34a2da 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj b/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj index 125f4c9..b760144 100644 --- a/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj +++ b/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 3678450..5e15f4f 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable @@ -11,9 +11,8 @@ - - - + + diff --git a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs index 2371b62..a649979 100644 --- a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs +++ b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs @@ -18,38 +18,31 @@ public static IEndpointRouteBuilder MapProposalsEndpoints(this IEndpointRouteBui proposalsGroup .MapGet("", GetAllProposals) - .WithName(nameof(GetAllProposals)) - .WithOpenApi(); + .WithName(nameof(GetAllProposals)); proposalsGroup .MapGet("{id:guid}", GetProposalDetail) - .WithName(nameof(GetProposalDetail)) - .WithOpenApi(); + .WithName(nameof(GetProposalDetail)); proposalsGroup .MapPatch("{id:guid}", AcceptProposal) - .WithName(nameof(AcceptProposal)) - .WithOpenApi(); + .WithName(nameof(AcceptProposal)); proposalsGroup .MapDelete("{id:guid}", RejectProposal) - .WithName(nameof(RejectProposal)) - .WithOpenApi(); + .WithName(nameof(RejectProposal)); proposalsGroup .MapDelete("{id:guid}/refuse", RefuseProposal) - .WithName(nameof(RefuseProposal)) - .WithOpenApi(); + .WithName(nameof(RefuseProposal)); proposalsGroup .MapPost("{id:guid}/schedule", ScheduleProposal) - .WithName(nameof(ScheduleProposal)) - .WithOpenApi(); + .WithName(nameof(ScheduleProposal)); proposalsGroup .MapGet("stats", GetProposalsStats) - .WithName(nameof(GetProposalsStats)) - .WithOpenApi(); + .WithName(nameof(GetProposalsStats)); return builder; } diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 58bd7b3..1d08659 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -1,14 +1,14 @@  - net9.0 + net10.0 enable enable - - + + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index 09a1276..ed133ea 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Proposals.Web.Models/KITT.Proposals.Web.Models.csproj b/src/KITT.Proposals.Web.Models/KITT.Proposals.Web.Models.csproj index 125f4c9..b760144 100644 --- a/src/KITT.Proposals.Web.Models/KITT.Proposals.Web.Models.csproj +++ b/src/KITT.Proposals.Web.Models/KITT.Proposals.Web.Models.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 233173d..1aa2ba9 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable true @@ -10,13 +10,13 @@ - - - - - - - + + + + + + + diff --git a/src/KITT.Services/KITT.Services.csproj b/src/KITT.Services/KITT.Services.csproj index 125f4c9..b760144 100644 --- a/src/KITT.Services/KITT.Services.csproj +++ b/src/KITT.Services/KITT.Services.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index 5d0a5f8..d25b237 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -1,20 +1,20 @@ - net9.0 + net10.0 enable enable dotnet-KITT.Support.Seeder-7ba1aa34-63f1-4522-9240-26830e3d203a - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj b/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj index 92419a9..b107dcb 100644 --- a/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj +++ b/src/KITT.Telegram.Functions/KITT.Telegram.Functions.csproj @@ -12,9 +12,6 @@ - - - PreserveNewest diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index d9243ce..01b2474 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index 20c193b..cabe019 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable @@ -12,11 +12,11 @@ - - + + - + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index de455df..55e56b3 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable true @@ -9,10 +9,9 @@ - + - diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index 84165f3..e6e1dea 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable @@ -18,9 +18,9 @@ - - - - + + + + diff --git a/src/KITT.Web.Models/KITT.Web.Models.csproj b/src/KITT.Web.Models/KITT.Web.Models.csproj index 9623deb..93f5ab4 100644 --- a/src/KITT.Web.Models/KITT.Web.Models.csproj +++ b/src/KITT.Web.Models/KITT.Web.Models.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 122901a..7e738ba 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,11 +7,11 @@ - + - + - + diff --git a/src/LemonBot.Commands/LemonBot.Commands.csproj b/src/LemonBot.Commands/LemonBot.Commands.csproj index 589a721..5e507f6 100644 --- a/src/LemonBot.Commands/LemonBot.Commands.csproj +++ b/src/LemonBot.Commands/LemonBot.Commands.csproj @@ -11,8 +11,4 @@ - - - - diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index fd09da5..72172c0 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable false @@ -12,9 +12,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index 59a5773..bfc717b 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable false @@ -14,8 +14,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj b/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj index 5638e03..7dab461 100644 --- a/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj +++ b/tests/KITT.Telegram.Functions.Test/KITT.Telegram.Functions.Test.csproj @@ -22,8 +22,4 @@ - - - - diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index 6774c71..36681b4 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable @@ -11,7 +11,7 @@ - + From d87bd743c670348cf7029716ccc00f9506ddf238 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 22 Nov 2025 17:40:55 +0100 Subject: [PATCH 05/26] #124 - update packages --- src/KITT.AppHost/KITT.AppHost.csproj | 2 +- src/KITT.Core/KITT.Core.csproj | 2 +- src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj | 4 ++-- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 1 + src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj | 2 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 4 ++-- tests/KITT.Web.Testing/KITT.Web.Testing.csproj | 4 ++-- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 252ff2f..a46d101 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 5e15f4f..ef0fd7d 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index 01b2474..c803eaa 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index cabe019..1b831a4 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -12,6 +12,7 @@ + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index e6e1dea..c1b771f 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 7e738ba..c491c49 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index 36681b4..317a603 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -12,8 +12,8 @@ - - + + From 6eb8c4227786198369c4a3193756e1bed1c78037 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 22 Nov 2025 18:02:49 +0100 Subject: [PATCH 06/26] #124 - removed old settings pages --- .../Services/SettingsEndpointsServices.cs | 35 --------- .../Endpoints/SettingsEndpoints.cs | 48 +----------- .../Endpoints/StreamingsEndpoints.cs | 3 +- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 1 - src/KITT.Cms.Web.Api/Program.cs | 2 + .../Pages/Settings/Channels.razor | 11 +++ .../Pages/Settings/Channels.razor.cs | 6 ++ .../Settings/ChannelModel.cs | 14 ++++ .../Settings/CreateNewSettingsModel.cs | 9 --- .../Settings/SettingsDetailModel.cs | 8 -- .../Settings/SettingsListModel.cs | 13 ---- .../Endpoints/ProposalsEndpoints.cs | 3 +- .../KITT.Proposals.Web.Api.csproj | 1 - src/KITT.Proposals.Web.Api/Program.cs | 2 + .../ClientsServiceCollectionExtensions.cs | 16 ---- .../Clients/Http/SettingsHttpClient.cs | 31 -------- .../Clients/ISettingsClient.cs | 10 --- .../KITT.Web.App.Client/Layout/NavMenu.razor | 6 +- .../Pages/CreateNewSettings.razor | 74 ------------------- .../KITT.Web.App.Client/Pages/Settings.razor | 56 -------------- .../KITT.Web.App.Client/Program.cs | 2 - .../KITT.Web.App.Client/_Imports.razor | 1 - .../SettingsEndpointsTest.cs | 32 -------- 23 files changed, 43 insertions(+), 341 deletions(-) create mode 100644 src/KITT.Cms.Web.App/Pages/Settings/Channels.razor create mode 100644 src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs create mode 100644 src/KITT.Cms.Web.Models/Settings/ChannelModel.cs delete mode 100644 src/KITT.Cms.Web.Models/Settings/CreateNewSettingsModel.cs delete mode 100644 src/KITT.Cms.Web.Models/Settings/SettingsDetailModel.cs delete mode 100644 src/KITT.Cms.Web.Models/Settings/SettingsListModel.cs delete mode 100644 src/KITT.Web.App/KITT.Web.App.Client/Clients/ClientsServiceCollectionExtensions.cs delete mode 100644 src/KITT.Web.App/KITT.Web.App.Client/Clients/Http/SettingsHttpClient.cs delete mode 100644 src/KITT.Web.App/KITT.Web.App.Client/Clients/ISettingsClient.cs delete mode 100644 src/KITT.Web.App/KITT.Web.App.Client/Pages/CreateNewSettings.razor delete mode 100644 src/KITT.Web.App/KITT.Web.App.Client/Pages/Settings.razor diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs index f9076b4..c2f40ac 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs @@ -15,39 +15,4 @@ public SettingsEndpointsServices(IDatabase database, ISettingsCommands commands) Database = database ?? throw new ArgumentNullException(nameof(database)); Commands = commands ?? throw new ArgumentNullException(nameof(commands)); } - - public async Task GetAllSettingsAsync(string userId) - { - var settings = await Database.Settings - .ByUserId(userId) - .OrderBy(s => s.TwitchChannel) - .Select(s => new SettingsListModel.SettingsDescriptor - { - Id = s.Id, - TwitchChannel = s.TwitchChannel - }).ToArrayAsync(); - - var model = new SettingsListModel { Items = settings }; - return model; - } - - public Task CreateNewSettingsAsync(CreateNewSettingsModel model, string userId) - { - return Commands.CreateNewSettingsAsync(userId, model.TwitchChannel); - } - - public async Task GetSettingsDetailAsync(Guid settingsId) - { - var settings = await Database.Settings.SingleOrDefaultAsync(s => s.Id == settingsId); - if (settings is null) - { - return null; - } - - return new SettingsDetailModel - { - Id = settings.Id, - TwitchChannel = settings.TwitchChannel - }; - } } diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index e15093e..86d38ed 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -13,54 +13,8 @@ public static IEndpointRouteBuilder MapSettingsEndpoints(this IEndpointRouteBuil { var settingsGroup = builder .MapGroup("api/settings") - .RequireAuthorization() - .WithParameterValidation(); - - settingsGroup - .MapGet("", GetAllSettings) - .WithName(nameof(GetAllSettings)); - - settingsGroup - .MapGet("{id}", GetSettingsDetails) - .WithName(nameof(GetSettingsDetails)); - - settingsGroup - .MapPost("", CreateNewSettings) - .WithName(nameof(CreateNewSettings)); + .RequireAuthorization(); return builder; } - - private static async Task> GetAllSettings( - SettingsEndpointsServices services, - ClaimsPrincipal user) - { - var model = await services.GetAllSettingsAsync(user.GetUserId()); - return TypedResults.Ok(model); - } - - private static async Task, NotFound>> GetSettingsDetails( - SettingsEndpointsServices services, - Guid id) - { - var settings = await services.GetSettingsDetailAsync(id); - if (settings is null) - { - return TypedResults.NotFound(); - } - - return TypedResults.Ok(settings); - } - - private static async Task, BadRequest, ValidationProblem>> CreateNewSettings( - SettingsEndpointsServices services, - ClaimsPrincipal user, - [FromBody] CreateNewSettingsModel model) - { - var settingsId = await services.CreateNewSettingsAsync(model, user.GetUserId()); - return TypedResults.CreatedAtRoute( - model, - nameof(GetSettingsDetails), - new { id = settingsId }); - } } diff --git a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs index 9c4ef02..5ddede6 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs @@ -13,8 +13,7 @@ public static IEndpointRouteBuilder MapStreamingsEndpoints(this IEndpointRouteBu { var streamingsGroup = builder .MapGroup("api/streamings") - .RequireAuthorization() - .WithParameterValidation(); + .RequireAuthorization(); streamingsGroup .MapGet("", GetAllStreamings) diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 21a6729..7e5b751 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -9,7 +9,6 @@ - diff --git a/src/KITT.Cms.Web.Api/Program.cs b/src/KITT.Cms.Web.Api/Program.cs index 956723c..0c05777 100644 --- a/src/KITT.Cms.Web.Api/Program.cs +++ b/src/KITT.Cms.Web.Api/Program.cs @@ -12,6 +12,8 @@ builder.AddServiceDefaults(); builder.AddSqlServerDbContext(ServiceNames.Database); +builder.Services.AddValidation(); + builder.Services.AddAuthentication() .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor new file mode 100644 index 0000000..79a3f66 --- /dev/null +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -0,0 +1,11 @@ +@page "/settings/channels" + +KITT - Connected channels + + + Connected channels + + +@code { + +} diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs new file mode 100644 index 0000000..af261fa --- /dev/null +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -0,0 +1,6 @@ +namespace KITT.Cms.Web.App.Pages.Settings; + +public partial class Channels +{ + +} diff --git a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs new file mode 100644 index 0000000..9264107 --- /dev/null +++ b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace KITT.Cms.Web.Models.Settings; + +public class ChannelModel +{ + public Guid Id { get; set; } + + [Required] + public string Name { get; set; } = string.Empty; + + [Required] + public string Url { get; set; } = string.Empty; +} diff --git a/src/KITT.Cms.Web.Models/Settings/CreateNewSettingsModel.cs b/src/KITT.Cms.Web.Models/Settings/CreateNewSettingsModel.cs deleted file mode 100644 index fbb1903..0000000 --- a/src/KITT.Cms.Web.Models/Settings/CreateNewSettingsModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace KITT.Cms.Web.Models.Settings; - -public class CreateNewSettingsModel -{ - [Required] - public string TwitchChannel { get; set; } = string.Empty; -} diff --git a/src/KITT.Cms.Web.Models/Settings/SettingsDetailModel.cs b/src/KITT.Cms.Web.Models/Settings/SettingsDetailModel.cs deleted file mode 100644 index d747792..0000000 --- a/src/KITT.Cms.Web.Models/Settings/SettingsDetailModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace KITT.Cms.Web.Models.Settings; - -public class SettingsDetailModel -{ - public Guid Id { get; init; } - - public string TwitchChannel { get; init; } = string.Empty; -} diff --git a/src/KITT.Cms.Web.Models/Settings/SettingsListModel.cs b/src/KITT.Cms.Web.Models/Settings/SettingsListModel.cs deleted file mode 100644 index 0d10e9d..0000000 --- a/src/KITT.Cms.Web.Models/Settings/SettingsListModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace KITT.Cms.Web.Models.Settings; - -public class SettingsListModel -{ - public IEnumerable Items { get; set; } = []; - - public record SettingsDescriptor - { - public Guid Id { get; set; } - - public string TwitchChannel { get; set; } = string.Empty; - } -} diff --git a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs index a649979..382aae7 100644 --- a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs +++ b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs @@ -13,8 +13,7 @@ public static IEndpointRouteBuilder MapProposalsEndpoints(this IEndpointRouteBui { var proposalsGroup = builder .MapGroup("api/proposals") - .RequireAuthorization() - .WithParameterValidation(); + .RequireAuthorization(); proposalsGroup .MapGet("", GetAllProposals) diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 1d08659..e7c3a17 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -9,7 +9,6 @@ - diff --git a/src/KITT.Proposals.Web.Api/Program.cs b/src/KITT.Proposals.Web.Api/Program.cs index a971462..8ea2370 100644 --- a/src/KITT.Proposals.Web.Api/Program.cs +++ b/src/KITT.Proposals.Web.Api/Program.cs @@ -12,6 +12,8 @@ builder.AddServiceDefaults(); builder.AddSqlServerDbContext(ServiceNames.Database); +builder.Services.AddValidation(); + builder.Services.AddAuthentication() .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Clients/ClientsServiceCollectionExtensions.cs b/src/KITT.Web.App/KITT.Web.App.Client/Clients/ClientsServiceCollectionExtensions.cs deleted file mode 100644 index 0fd30f1..0000000 --- a/src/KITT.Web.App/KITT.Web.App.Client/Clients/ClientsServiceCollectionExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using KITT.Web.App.Client.Clients.Http; - -namespace KITT.Web.App.Client.Clients; - -public static class ClientsServiceCollectionExtensions -{ - public static IServiceCollection AddGeneralClients( - this IServiceCollection services, - string apiBaseUrl) - { - services - .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); - - return services; - } -} diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Clients/Http/SettingsHttpClient.cs b/src/KITT.Web.App/KITT.Web.App.Client/Clients/Http/SettingsHttpClient.cs deleted file mode 100644 index 893a04c..0000000 --- a/src/KITT.Web.App/KITT.Web.App.Client/Clients/Http/SettingsHttpClient.cs +++ /dev/null @@ -1,31 +0,0 @@ -using KITT.Cms.Web.Models.Settings; -using System.Net.Http.Json; - -namespace KITT.Web.App.Client.Clients.Http; - -public class SettingsHttpClient : ISettingsClient -{ - public HttpClient Client { get; } - - public string ApiResource { get; } = "/api/cms/settings"; - - public SettingsHttpClient(HttpClient client) - { - Client = client ?? throw new ArgumentNullException(nameof(client)); - } - - public async Task CreateNewSettingsAsync(CreateNewSettingsModel model) - { - var response = await Client.PostAsJsonAsync(ApiResource, model); - if (!response.IsSuccessStatusCode) - { - throw new ApplicationException("Error creating settings"); - } - } - - public async Task GetAllSettingsAsync() - { - var model = await Client.GetFromJsonAsync(ApiResource); - return model ?? new(); - } -} diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Clients/ISettingsClient.cs b/src/KITT.Web.App/KITT.Web.App.Client/Clients/ISettingsClient.cs deleted file mode 100644 index 6793cda..0000000 --- a/src/KITT.Web.App/KITT.Web.App.Client/Clients/ISettingsClient.cs +++ /dev/null @@ -1,10 +0,0 @@ -using KITT.Cms.Web.Models.Settings; - -namespace KITT.Web.App.Client.Clients; - -public interface ISettingsClient -{ - Task GetAllSettingsAsync(); - - Task CreateNewSettingsAsync(CreateNewSettingsModel model); -} diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor b/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor index 9e0636c..d18ec32 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor +++ b/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor @@ -12,7 +12,9 @@ @Localizer[nameof(Resources.Shared.NavMenu.StreamingsMenuLabel)] @Localizer[nameof(Resources.Shared.NavMenu.ProposalsMenuLabel)] - @Localizer[nameof(Resources.Shared.NavMenu.SettingsMenuLabel)] + + Connected channels + @@ -23,4 +25,6 @@ private bool expanded = true; private bool contentsExpanded = true; + + private bool settingsExpanded = true; } diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Pages/CreateNewSettings.razor b/src/KITT.Web.App/KITT.Web.App.Client/Pages/CreateNewSettings.razor deleted file mode 100644 index 823a4e2..0000000 --- a/src/KITT.Web.App/KITT.Web.App.Client/Pages/CreateNewSettings.razor +++ /dev/null @@ -1,74 +0,0 @@ -@page "/settings/new" -@using KITT.Cms.Web.Models.Settings - -@inject ISettingsClient Client -@inject NavigationManager Navigation -@inject IMessageService MessageService - -@inject IStringLocalizer CommonLocalizer -@inject IStringLocalizer Localizer - -@*@attribute [Authorize]*@ - -KITT - @Localizer[nameof(Resources.Pages.CreateNewSettings.PageTitle)] - - - @Localizer[nameof(Resources.Pages.CreateNewSettings.PageTitle)] - - - - @CommonLocalizer[nameof(UI.Resources.Common.Back)] - - - - - - - - - - https://www.twitch.tv/ - - - - - - - @CommonLocalizer[nameof(UI.Resources.Common.Cancel)] - - - @CommonLocalizer[nameof(UI.Resources.Common.Save)] - - - - - -@code { - private CreateNewSettingsModel model = new(); - - private void Cancel() => model = new(); - - private async Task CreateNewSettingsAsync() - { - try - { - await Client.CreateNewSettingsAsync(model); - model = new(); - - Navigation.NavigateTo("settings"); - } - catch (ApplicationException ex) - { - await MessageService.ShowMessageBarAsync( - ex.Message, - MessageIntent.Error, - SectionNames.MessagesTopSectionName); - } - } -} diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Pages/Settings.razor b/src/KITT.Web.App/KITT.Web.App.Client/Pages/Settings.razor deleted file mode 100644 index 6e1c61b..0000000 --- a/src/KITT.Web.App/KITT.Web.App.Client/Pages/Settings.razor +++ /dev/null @@ -1,56 +0,0 @@ -@page "/settings" -@using KITT.Cms.Web.Models.Settings -@inject ISettingsClient Client -@inject IStringLocalizer Localizer -@inject NavigationManager Navigation -@*@attribute [Authorize]*@ - -KITT - @Localizer[nameof(Resources.Pages.Settings.PageTitle)] - - - @Localizer[nameof(Resources.Pages.Settings.PageTitle)] - - - - @Localizer[nameof(Resources.Pages.Settings.CreateNewSettingsLabel)] - - - - - Loading... - -

@Localizer[nameof(Resources.Pages.Settings.NoSettingsConfiguredMessage)]

-
- - - -
- -@code { - private bool loading = false; - - private GridItemsProvider settingsProvider = default!; - - protected override void OnInitialized() - { - loading = true; - - settingsProvider = async request => - { - try - { - var settings = await Client.GetAllSettingsAsync(); - - return GridItemsProviderResult.From( - items: settings.Items.ToList(), - totalItemCount: settings.Items.Count()); - } - finally - { - loading = false; - StateHasChanged(); - } - }; - } -} diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Program.cs b/src/KITT.Web.App/KITT.Web.App.Client/Program.cs index d6c0fd1..609a5a9 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Program.cs +++ b/src/KITT.Web.App/KITT.Web.App.Client/Program.cs @@ -2,7 +2,6 @@ using KITT.Cms.Web.App.Clients; using KITT.Proposals.Web.App.Clients; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using KITT.Web.App.Client.Clients; var builder = WebAssemblyHostBuilder.CreateDefault(args); @@ -12,7 +11,6 @@ builder.Services.AddDefaultServices(); -builder.Services.AddGeneralClients(builder.HostEnvironment.BaseAddress); builder.Services.AddCmsClients(builder.HostEnvironment.BaseAddress); builder.Services.AddProposalsClients(builder.HostEnvironment.BaseAddress); diff --git a/src/KITT.Web.App/KITT.Web.App.Client/_Imports.razor b/src/KITT.Web.App/KITT.Web.App.Client/_Imports.razor index aaa9974..bd1927b 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/_Imports.razor +++ b/src/KITT.Web.App/KITT.Web.App.Client/_Imports.razor @@ -11,7 +11,6 @@ @using Microsoft.JSInterop @using KITT.Web.App.Client @using KITT.Web.App.Client.Components -@using KITT.Web.App.Client.Clients @using KITT.Cms.Web.Models.Streamings @using KITT.Web.App.UI @using KITT.Web.App.UI.Components diff --git a/tests/KITT.Cms.Web.Api.Test/SettingsEndpointsTest.cs b/tests/KITT.Cms.Web.Api.Test/SettingsEndpointsTest.cs index b9ff3aa..26a920c 100644 --- a/tests/KITT.Cms.Web.Api.Test/SettingsEndpointsTest.cs +++ b/tests/KITT.Cms.Web.Api.Test/SettingsEndpointsTest.cs @@ -31,38 +31,6 @@ public async Task GetAllSettings_Should_Return_Unauthorized_If_User_Is_Not_Authe // Assert Assert.Equal(System.Net.HttpStatusCode.Unauthorized, response.StatusCode); } - - [Fact(Skip = "Must be fixed")] - public async Task GetAllSettings_Should_Return_Empty_List_If_No_Settings_Are_Available() - { - // Arrange - using var app = _factory.WithWebHostBuilder(builder => - { - builder.ConfigureServices( - services => services.ConfigureTestJwtOptions(CmsWebApplicationFactory.TenantId, CmsWebApplicationFactory.AppId)); - }); - - var token = TestJwtTokenProvider.JwtSecurityTokenHandler.WriteToken( - new JwtSecurityToken( - $"https://sts.windows.net/{CmsWebApplicationFactory.TenantId}/", - $"api://{CmsWebApplicationFactory.AppId}", - new TestClaimsProvider().Claims, - expires: DateTime.Now.AddMinutes(30), - signingCredentials: TestJwtTokenProvider.SigningCredentials)); - - using var client = app.CreateClient(); - client.DefaultRequestHeaders.Authorization = new("Bearer", token); - - // Act - var response = await client.GetAsync(endpoint); - - // Assert - response.EnsureSuccessStatusCode(); - var model = await response.Content.ReadFromJsonAsync(); - - Assert.NotNull(model); - Assert.Empty(model.Items); - } #endregion #region GetSettingsDetails tests From d270aec326f794f495f180cd211289215e381fd3 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 6 Dec 2025 15:13:39 +0100 Subject: [PATCH 07/26] #124 - update aspire version --- src/KITT.AppHost/KITT.AppHost.csproj | 12 ++++++------ src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 2 +- .../KITT.Proposals.Web.Api.csproj | 2 +- src/KITT.Support.Seeder/KITT.Support.Seeder.csproj | 4 ++-- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index a46d101..e6c08fd 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,6 +1,6 @@ - + Exe @@ -11,11 +11,11 @@ - - - - - + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 7e5b751..bf582d0 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index e7c3a17..934600a 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index d25b237..c709be5 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index c491c49..5cb36c4 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,7 +7,7 @@ - + From 18547cc733efda234735fbab578ba6863aa5c927 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 6 Dec 2025 15:36:00 +0100 Subject: [PATCH 08/26] #124 - moving to extension blocks --- ...DistributedApplicationBuilderExtensions.cs | 34 ++++--- .../Endpoints/SettingsEndpoints.cs | 13 ++- .../Endpoints/StreamingsEndpoints.cs | 55 +++++------ .../ClientsServiceCollectionExtensions.cs | 13 +-- .../ServiceCollectionExtensions.cs | 20 ++-- .../Extensions/ContentExtensions.cs | 20 ++-- .../Extensions/ProposalExtensions.cs | 22 +++-- .../Extensions/SettingsExtensions.cs | 6 +- .../Extensions/StreamingsExtensions.cs | 27 +++--- .../Endpoints/ProposalsEndpoints.cs | 55 +++++------ .../ClientsServiceCollectionExtensions.cs | 13 +-- .../ServiceCollectionExtensions.cs | 15 +-- .../Endpoints/AuthenticationEndpoints.cs | 23 +++-- .../KITT.Web.App/Endpoints/CmsEndpoints.cs | 93 ++++++++++--------- .../Endpoints/ProposalEndpoints.cs | 64 +++++++------ .../Azure/AzureKeyVaultExtensions.cs | 59 ++++++------ src/KITT.Web.Shared/KITT.Web.Shared.csproj | 2 +- .../Security/ClaimsPrincipalExtensions.cs | 6 +- 18 files changed, 291 insertions(+), 249 deletions(-) diff --git a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs index 7ca2778..fb04a42 100644 --- a/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs +++ b/src/KITT.AppHost/DistributedApplicationBuilderExtensions.cs @@ -5,24 +5,28 @@ namespace KITT.AppHost; public static class DistributedApplicationBuilderExtensions { - public static IResourceBuilder AddKittDatabase(this IDistributedApplicationBuilder builder) + extension(IDistributedApplicationBuilder builder) { - ArgumentNullException.ThrowIfNull(builder); - - if (!builder.ExecutionContext.IsPublishMode) + public IResourceBuilder AddKittDatabase() { - var kittSql = builder.AddSqlServer(ServiceNames.Sql) - .WithDataVolume("kitt-data") - .WithDbGate(containerBuilder => - { - containerBuilder.WithExplicitStart(); - }); + ArgumentNullException.ThrowIfNull(builder); - return kittSql.AddDatabase(ServiceNames.Database, databaseName: "KITT"); - } - else - { - return builder.AddConnectionString(ServiceNames.Database); + if (!builder.ExecutionContext.IsPublishMode) + { + var kittSql = builder.AddSqlServer(ServiceNames.Sql) + .WithDataVolume("kitt-data") + .WithDbGate(containerBuilder => + { + containerBuilder.WithExplicitStart(); + }); + + return kittSql.AddDatabase(ServiceNames.Database, databaseName: "KITT"); + } + else + { + return builder.AddConnectionString(ServiceNames.Database); + } } } + } diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index 86d38ed..b8cc1eb 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -9,12 +9,15 @@ namespace KITT.Cms.Web.Api.Endpoints; public static class SettingsEndpoints { - public static IEndpointRouteBuilder MapSettingsEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - var settingsGroup = builder - .MapGroup("api/settings") - .RequireAuthorization(); + public IEndpointRouteBuilder MapSettingsEndpoints() + { + var settingsGroup = builder + .MapGroup("api/settings") + .RequireAuthorization(); - return builder; + return builder; + } } } diff --git a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs index 5ddede6..326fac3 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/StreamingsEndpoints.cs @@ -9,41 +9,44 @@ namespace KITT.Cms.Web.Api.Endpoints; public static class StreamingsEndpoints { - public static IEndpointRouteBuilder MapStreamingsEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - var streamingsGroup = builder - .MapGroup("api/streamings") - .RequireAuthorization(); + public IEndpointRouteBuilder MapStreamingsEndpoints() + { + var streamingsGroup = builder + .MapGroup("api/streamings") + .RequireAuthorization(); - streamingsGroup - .MapGet("", GetAllStreamings) - .WithName(nameof(GetAllStreamings)); + streamingsGroup + .MapGet("", GetAllStreamings) + .WithName(nameof(GetAllStreamings)); - streamingsGroup - .MapGet("{id:guid}", GetStreamingDetail) - .WithName(nameof(GetStreamingDetail)); + streamingsGroup + .MapGet("{id:guid}", GetStreamingDetail) + .WithName(nameof(GetStreamingDetail)); - streamingsGroup - .MapPost("", ScheduleStreaming) - .WithName(nameof(ScheduleStreaming)); + streamingsGroup + .MapPost("", ScheduleStreaming) + .WithName(nameof(ScheduleStreaming)); - streamingsGroup - .MapPost("import", ImportStreaming) - .WithName(nameof(ImportStreaming)); + streamingsGroup + .MapPost("import", ImportStreaming) + .WithName(nameof(ImportStreaming)); - streamingsGroup - .MapPut("{id:guid}", UpdateStreaming) - .WithName(nameof(UpdateStreaming)); + streamingsGroup + .MapPut("{id:guid}", UpdateStreaming) + .WithName(nameof(UpdateStreaming)); - streamingsGroup - .MapDelete("{id:guid}", DeleteStreaming) - .WithName(nameof(DeleteStreaming)); + streamingsGroup + .MapDelete("{id:guid}", DeleteStreaming) + .WithName(nameof(DeleteStreaming)); - streamingsGroup - .MapGet("stats", GetStreamingStats) - .WithName(nameof(GetStreamingStats)); + streamingsGroup + .MapGet("stats", GetStreamingStats) + .WithName(nameof(GetStreamingStats)); - return builder; + return builder; + } } private static async Task> GetAllStreamings( diff --git a/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs b/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs index 36a6f68..1294921 100644 --- a/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs +++ b/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs @@ -5,13 +5,14 @@ namespace KITT.Cms.Web.App.Clients; public static class ClientsServiceCollectionExtensions { - public static IServiceCollection AddCmsClients( - this IServiceCollection services, - string apiBaseUrl) + extension(IServiceCollection services) { - services - .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); + public IServiceCollection AddCmsClients(string apiBaseUrl) + { + services + .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); - return services; + return services; + } } } diff --git a/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs b/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs index 4f01c9f..e1619eb 100644 --- a/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/KITT.Core/DependencyInjection/ServiceCollectionExtensions.cs @@ -8,15 +8,19 @@ namespace KITT.Core.DependencyInjection; public static class ServiceCollectionExtensions { - public static IServiceCollection AddKittCore(this IServiceCollection services) + extension(IServiceCollection services) { - services - .AddValidatorsFromAssemblyContaining() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped(); + public IServiceCollection AddKittCore() + { + services + .AddValidatorsFromAssemblyContaining() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); - return services; + return services; + } } + } diff --git a/src/KITT.Core/ReadModels/Extensions/ContentExtensions.cs b/src/KITT.Core/ReadModels/Extensions/ContentExtensions.cs index c1d1d04..9692e26 100644 --- a/src/KITT.Core/ReadModels/Extensions/ContentExtensions.cs +++ b/src/KITT.Core/ReadModels/Extensions/ContentExtensions.cs @@ -2,18 +2,18 @@ public static class ContentExtensions { - public static IQueryable PublishedOnly(this IQueryable source) where TContent : Content - => source.Where(c => c.Status == Content.ContentStatus.Published && c.PublicationDate <= DateTime.UtcNow); + extension(IQueryable source) where TContent : Content + { + public IQueryable PublishedOnly() + => source.Where(c => c.Status == Content.ContentStatus.Published && c.PublicationDate <= DateTime.UtcNow); - public static IQueryable DraftsOnly(this IQueryable source) where TContent : Content - => source.Where(c => c.Status == Content.ContentStatus.Draft); + public IQueryable DraftsOnly() => source.Where(c => c.Status == Content.ContentStatus.Draft); - public static IQueryable UnpublishedOnly(this IQueryable source) where TContent : Content - => source.Where(c => c.Status == Content.ContentStatus.Unpublished); + public IQueryable UnpublishedOnly() => source.Where(c => c.Status == Content.ContentStatus.Unpublished); - public static IQueryable OrderedByPublicationDate(this IQueryable source) where TContent : Content - => source.OrderBy(c => c.PublicationDate); + public IQueryable OrderedByPublicationDate() => source.OrderBy(c => c.PublicationDate); - public static IQueryable WithSlug(this IQueryable source, string slug) where TContent : Content - => source.Where(c => c.Slug == slug); + public IQueryable WithSlug(string slug) => source.Where(c => c.Slug == slug); + } + } diff --git a/src/KITT.Core/ReadModels/Extensions/ProposalExtensions.cs b/src/KITT.Core/ReadModels/Extensions/ProposalExtensions.cs index 49ff4ae..4628a47 100644 --- a/src/KITT.Core/ReadModels/Extensions/ProposalExtensions.cs +++ b/src/KITT.Core/ReadModels/Extensions/ProposalExtensions.cs @@ -2,18 +2,20 @@ public static class ProposalExtensions { - public static IQueryable Moderating(this IQueryable proposals) - => proposals.Where(p => p.Status == Proposal.ProposalStatus.Moderating); + extension(IQueryable proposals) + { + public IQueryable Moderating() => proposals.Where(p => p.Status == Proposal.ProposalStatus.Moderating); - public static IQueryable WaitingForApproval(this IQueryable proposals) - => proposals.Where(p => p.Status == Proposal.ProposalStatus.WaitingForApproval); + public IQueryable WaitingForApproval() => proposals.Where(p => p.Status == Proposal.ProposalStatus.WaitingForApproval); - public static IQueryable OrderedBySubmissionDate(this IQueryable proposals, bool ascending = true) - { - return ascending switch + public IQueryable OrderedBySubmissionDate(bool ascending = true) { - false => proposals.OrderByDescending(p => p.SubmittedAt), - _ => proposals.OrderBy(p => p.SubmittedAt) - }; + return ascending switch + { + false => proposals.OrderByDescending(p => p.SubmittedAt), + _ => proposals.OrderBy(p => p.SubmittedAt) + }; + } } + } diff --git a/src/KITT.Core/ReadModels/Extensions/SettingsExtensions.cs b/src/KITT.Core/ReadModels/Extensions/SettingsExtensions.cs index 4220a15..1537a74 100644 --- a/src/KITT.Core/ReadModels/Extensions/SettingsExtensions.cs +++ b/src/KITT.Core/ReadModels/Extensions/SettingsExtensions.cs @@ -2,6 +2,8 @@ public static class SettingsExtensions { - public static IQueryable ByUserId(this IQueryable settings, string userId) - => settings.Where(s => s.UserId == userId); + extension(IQueryable settings) + { + public IQueryable ByUserId(string userId) => settings.Where(s => s.UserId == userId); + } } diff --git a/src/KITT.Core/ReadModels/Extensions/StreamingsExtensions.cs b/src/KITT.Core/ReadModels/Extensions/StreamingsExtensions.cs index 59d0e7f..71fd55d 100644 --- a/src/KITT.Core/ReadModels/Extensions/StreamingsExtensions.cs +++ b/src/KITT.Core/ReadModels/Extensions/StreamingsExtensions.cs @@ -2,22 +2,23 @@ public static class StreamingsExtensions { - public static IQueryable ByUserId(this IQueryable streamings, string userId) - => streamings.Where(s => s.UserId == userId); - - public static IQueryable OrderedBySchedule(this IQueryable streamings, bool ascending = true) + extension(IQueryable streamings) { - return ascending ? - OrderedByScheduleAscending(streamings) : - OrderedByScheduleDescending(streamings); - } + public IQueryable ByUserId(string userId) => streamings.Where(s => s.UserId == userId); - public static IQueryable DeliveredOnly(this IQueryable streamings) - => streamings.Where(s => s.ScheduleDate < DateOnly.FromDateTime(DateTime.Today)); + public IQueryable OrderedBySchedule(bool ascending = true) + { + return ascending ? + OrderedByScheduleAscending(streamings) : + OrderedByScheduleDescending(streamings); + } - public static IQueryable Scheduled(this IQueryable streamings) - { - return streamings.Where(s => s.ScheduleDate >= DateOnly.FromDateTime(DateTime.Today)); + public IQueryable DeliveredOnly() => streamings.Where(s => s.ScheduleDate < DateOnly.FromDateTime(DateTime.Today)); + + public IQueryable Scheduled() + { + return streamings.Where(s => s.ScheduleDate >= DateOnly.FromDateTime(DateTime.Today)); + } } private static IQueryable OrderedByScheduleAscending(IQueryable streamings) diff --git a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs index 382aae7..3ada263 100644 --- a/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs +++ b/src/KITT.Proposals.Web.Api/Endpoints/ProposalsEndpoints.cs @@ -9,41 +9,44 @@ namespace KITT.Proposals.Web.Api.Endpoints; public static class ProposalsEndpoints { - public static IEndpointRouteBuilder MapProposalsEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - var proposalsGroup = builder - .MapGroup("api/proposals") - .RequireAuthorization(); + public IEndpointRouteBuilder MapProposalsEndpoints() + { + var proposalsGroup = builder + .MapGroup("api/proposals") + .RequireAuthorization(); - proposalsGroup - .MapGet("", GetAllProposals) - .WithName(nameof(GetAllProposals)); + proposalsGroup + .MapGet("", GetAllProposals) + .WithName(nameof(GetAllProposals)); - proposalsGroup - .MapGet("{id:guid}", GetProposalDetail) - .WithName(nameof(GetProposalDetail)); + proposalsGroup + .MapGet("{id:guid}", GetProposalDetail) + .WithName(nameof(GetProposalDetail)); - proposalsGroup - .MapPatch("{id:guid}", AcceptProposal) - .WithName(nameof(AcceptProposal)); + proposalsGroup + .MapPatch("{id:guid}", AcceptProposal) + .WithName(nameof(AcceptProposal)); - proposalsGroup - .MapDelete("{id:guid}", RejectProposal) - .WithName(nameof(RejectProposal)); + proposalsGroup + .MapDelete("{id:guid}", RejectProposal) + .WithName(nameof(RejectProposal)); - proposalsGroup - .MapDelete("{id:guid}/refuse", RefuseProposal) - .WithName(nameof(RefuseProposal)); + proposalsGroup + .MapDelete("{id:guid}/refuse", RefuseProposal) + .WithName(nameof(RefuseProposal)); - proposalsGroup - .MapPost("{id:guid}/schedule", ScheduleProposal) - .WithName(nameof(ScheduleProposal)); + proposalsGroup + .MapPost("{id:guid}/schedule", ScheduleProposal) + .WithName(nameof(ScheduleProposal)); - proposalsGroup - .MapGet("stats", GetProposalsStats) - .WithName(nameof(GetProposalsStats)); + proposalsGroup + .MapGet("stats", GetProposalsStats) + .WithName(nameof(GetProposalsStats)); - return builder; + return builder; + } } private static async Task> GetAllProposals( diff --git a/src/KITT.Proposals.Web.App/Clients/ClientsServiceCollectionExtensions.cs b/src/KITT.Proposals.Web.App/Clients/ClientsServiceCollectionExtensions.cs index bed3238..78d1e47 100644 --- a/src/KITT.Proposals.Web.App/Clients/ClientsServiceCollectionExtensions.cs +++ b/src/KITT.Proposals.Web.App/Clients/ClientsServiceCollectionExtensions.cs @@ -5,13 +5,14 @@ namespace KITT.Proposals.Web.App.Clients; public static class ClientsServiceCollectionExtensions { - public static IServiceCollection AddProposalsClients( - this IServiceCollection services, - string apiBaseUrl) + extension(IServiceCollection services) { - services - .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); + public IServiceCollection AddProposalsClients(string apiBaseUrl) + { + services + .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); - return services; + return services; + } } } diff --git a/src/KITT.Web.App.UI/ServiceCollectionExtensions.cs b/src/KITT.Web.App.UI/ServiceCollectionExtensions.cs index 5bed970..83d2bb2 100644 --- a/src/KITT.Web.App.UI/ServiceCollectionExtensions.cs +++ b/src/KITT.Web.App.UI/ServiceCollectionExtensions.cs @@ -5,14 +5,17 @@ namespace KITT.Web.App.UI; public static class ServiceCollectionExtensions { - public static IServiceCollection AddDefaultServices(this IServiceCollection services) + extension(IServiceCollection services) { - services.AddLocalization(); - services.AddFluentUIComponents(options => + public IServiceCollection AddDefaultServices() { - options.ValidateClassNames = false; - }); + services.AddLocalization(); + services.AddFluentUIComponents(options => + { + options.ValidateClassNames = false; + }); - return services; + return services; + } } } diff --git a/src/KITT.Web.App/KITT.Web.App/Endpoints/AuthenticationEndpoints.cs b/src/KITT.Web.App/KITT.Web.App/Endpoints/AuthenticationEndpoints.cs index 4662852..e17982b 100644 --- a/src/KITT.Web.App/KITT.Web.App/Endpoints/AuthenticationEndpoints.cs +++ b/src/KITT.Web.App/KITT.Web.App/Endpoints/AuthenticationEndpoints.cs @@ -7,20 +7,23 @@ namespace KITT.Web.App.Endpoints; public static class AuthenticationEndpoints { - public static IEndpointRouteBuilder MapAuthenticationEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - var authenticationGroup = builder.MapGroup("/authentication"); + public IEndpointRouteBuilder MapAuthenticationEndpoints() + { + var authenticationGroup = builder.MapGroup("/authentication"); - authenticationGroup - .MapGet("login", Login) - .WithName(nameof(Login)) - .AllowAnonymous(); + authenticationGroup + .MapGet("login", Login) + .WithName(nameof(Login)) + .AllowAnonymous(); - authenticationGroup - .MapGet("logout", Logout) - .WithName(nameof(Logout)); + authenticationGroup + .MapGet("logout", Logout) + .WithName(nameof(Logout)); - return builder; + return builder; + } } private static async Task Logout( diff --git a/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs b/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs index 5f972c3..e66a4d7 100644 --- a/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs +++ b/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs @@ -5,59 +5,62 @@ namespace KITT.Web.App.Endpoints; internal static class CmsEndpoints { - public static IEndpointRouteBuilder MapCmsEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - builder.MapForwarder( - "/api/cms/streamings", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/streamings", - GetScopes)) - .RequireAuthorization(); + public IEndpointRouteBuilder MapCmsEndpoints() + { + builder.MapForwarder( + "/api/cms/streamings", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/streamings", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/cms/streamings/{id}", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/streamings/{id}", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/cms/streamings/{id}", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/streamings/{id}", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/cms/streamings/import", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/streamings/import", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/cms/streamings/import", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/streamings/import", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/cms/streamings/stats", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/streamings/stats", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/cms/streamings/stats", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/streamings/stats", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/cms/settings", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/settings", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/cms/settings", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/settings", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/cms/settings/{id}", - $"https+http://{ServiceNames.CmsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/settings/{id}", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/cms/settings/{id}", + $"https+http://{ServiceNames.CmsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/settings/{id}", + GetScopes)) + .RequireAuthorization(); - return builder; + return builder; + } } - + private static IEnumerable GetScopes(IConfiguration configuration) => [ $"api://{configuration["Identity:Cms:AppId"]}/Cms.Read", diff --git a/src/KITT.Web.App/KITT.Web.App/Endpoints/ProposalEndpoints.cs b/src/KITT.Web.App/KITT.Web.App/Endpoints/ProposalEndpoints.cs index 8418680..4076d19 100644 --- a/src/KITT.Web.App/KITT.Web.App/Endpoints/ProposalEndpoints.cs +++ b/src/KITT.Web.App/KITT.Web.App/Endpoints/ProposalEndpoints.cs @@ -5,42 +5,46 @@ namespace KITT.Web.App.Endpoints; internal static class ProposalEndpoints { - public static IEndpointRouteBuilder MapProposalEndpoints(this IEndpointRouteBuilder builder) + extension(IEndpointRouteBuilder builder) { - builder.MapForwarder( - "/api/proposals", - $"https+http://{ServiceNames.ProposalsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( + public IEndpointRouteBuilder MapProposalEndpoints() + { + builder.MapForwarder( "/api/proposals", - GetScopes)) - .RequireAuthorization(); + $"https+http://{ServiceNames.ProposalsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/proposals", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/proposals/{id}", - $"https+http://{ServiceNames.ProposalsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/proposals/{id}", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/proposals/{id}", + $"https+http://{ServiceNames.ProposalsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/proposals/{id}", + GetScopes)) + .RequireAuthorization(); - builder.MapForwarder( - "/api/proposals/{id}/refuse", - $"https+http://{ServiceNames.ProposalsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/proposals/{id}/refuse", - GetScopes)) - .RequireAuthorization(); - - builder.MapForwarder( - "/api/proposals/stats", - $"https+http://{ServiceNames.ProposalsApi}", - transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/proposals/stats", - GetScopes)) - .RequireAuthorization(); + builder.MapForwarder( + "/api/proposals/{id}/refuse", + $"https+http://{ServiceNames.ProposalsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/proposals/{id}/refuse", + GetScopes)) + .RequireAuthorization(); + + builder.MapForwarder( + "/api/proposals/stats", + $"https+http://{ServiceNames.ProposalsApi}", + transformBuilder => transformBuilder.ConfigureWithTargetPath( + "/api/proposals/stats", + GetScopes)) + .RequireAuthorization(); - return builder; + return builder; + } } + private static IEnumerable GetScopes(IConfiguration configuration) => [ diff --git a/src/KITT.Web.Shared/Azure/AzureKeyVaultExtensions.cs b/src/KITT.Web.Shared/Azure/AzureKeyVaultExtensions.cs index 653edbb..089b9d4 100644 --- a/src/KITT.Web.Shared/Azure/AzureKeyVaultExtensions.cs +++ b/src/KITT.Web.Shared/Azure/AzureKeyVaultExtensions.cs @@ -7,41 +7,44 @@ namespace KITT.Web.Shared.Azure; public static class AzureKeyVaultExtensions { - public static IHostApplicationBuilder AddAzureKeyVaultClientWithEmulatorFallback(this IHostApplicationBuilder builder, string connectionStringName) + extension(IHostApplicationBuilder builder) { - ArgumentNullException.ThrowIfNull(builder); - - if (builder.Environment.IsDevelopment()) - { - var vaultUri = builder.Configuration.GetConnectionString(connectionStringName); - builder.Services.AddAzureKeyVaultEmulator(vaultUri); - } - else + public IHostApplicationBuilder AddAzureKeyVaultClientWithEmulatorFallback(string connectionStringName) { - builder.AddAzureKeyVaultClient(connectionStringName); - } + ArgumentNullException.ThrowIfNull(builder); - return builder; - } + if (builder.Environment.IsDevelopment()) + { + var vaultUri = builder.Configuration.GetConnectionString(connectionStringName); + builder.Services.AddAzureKeyVaultEmulator(vaultUri); + } + else + { + builder.AddAzureKeyVaultClient(connectionStringName); + } - public static IHostApplicationBuilder AddAzureKeyVaultSecretsWithEmulatorFallback(this IHostApplicationBuilder builder, string connectionStringName) - { - ArgumentNullException.ThrowIfNull(builder); + return builder; + } - if (builder.Environment.IsDevelopment()) + public IHostApplicationBuilder AddAzureKeyVaultSecretsWithEmulatorFallback(string connectionStringName) { - var vaultUri = builder.Configuration.GetConnectionString(connectionStringName); + ArgumentNullException.ThrowIfNull(builder); - var secretClient = KeyVaultHelper.GetSecretClient(vaultUri); - builder.Configuration.AddAzureKeyVault( - secretClient, - new AzureKeyVaultConfigurationOptions()); - } - else - { - builder.Configuration.AddAzureKeyVaultSecrets(connectionStringName); + if (builder.Environment.IsDevelopment()) + { + var vaultUri = builder.Configuration.GetConnectionString(connectionStringName); + + var secretClient = KeyVaultHelper.GetSecretClient(vaultUri); + builder.Configuration.AddAzureKeyVault( + secretClient, + new AzureKeyVaultConfigurationOptions()); + } + else + { + builder.Configuration.AddAzureKeyVaultSecrets(connectionStringName); + } + + return builder; } - - return builder; } } diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 5cb36c4..e05f7a0 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/src/KITT.Web.Shared/Security/ClaimsPrincipalExtensions.cs b/src/KITT.Web.Shared/Security/ClaimsPrincipalExtensions.cs index a46fcd5..8cd7e6d 100644 --- a/src/KITT.Web.Shared/Security/ClaimsPrincipalExtensions.cs +++ b/src/KITT.Web.Shared/Security/ClaimsPrincipalExtensions.cs @@ -5,6 +5,8 @@ namespace KITT.Web.Shared.Security; public static class ClaimsPrincipalExtensions { - public static string GetUserId(this ClaimsPrincipal user) - => user.GetObjectId()!; + extension(ClaimsPrincipal user) + { + public string GetUserId() => user.GetObjectId()!; + } } From 9b94d4e73d340f45c821bc058526cad542910871 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 6 Dec 2025 18:25:22 +0100 Subject: [PATCH 09/26] #124 - setup UI for connected channels list --- .../Pages/Settings/Channels.razor | 26 +++++++++++++++++-- .../Pages/Settings/Channels.razor.cs | 10 +++++++ src/KITT.Cms.Web.App/_Imports.razor | 2 ++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index 79a3f66..e4a7a5d 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -6,6 +6,28 @@ Connected channels -@code { + + + Add new channel + + + + + @foreach (var channel in channels) + { + + +

@channel.Name

+

@channel.Url

-} + + Edit + +
+
+ } +
\ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index af261fa..e642cd7 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -1,6 +1,16 @@ +using KITT.Cms.Web.Models.Settings; + namespace KITT.Cms.Web.App.Pages.Settings; public partial class Channels { + private List channels = []; + protected override void OnInitialized() + { + channels = [ + new ChannelModel { Id = Guid.NewGuid(), Name = "Twitch - albx87", Url = "https://www.twitch.tv/albx87" }, + new ChannelModel { Id = Guid.NewGuid(), Name = "YouTube - albx87", Url = "https://www.youtube.com/@albx87" }, + ]; + } } diff --git a/src/KITT.Cms.Web.App/_Imports.razor b/src/KITT.Cms.Web.App/_Imports.razor index 4dc0f34..43e5256 100644 --- a/src/KITT.Cms.Web.App/_Imports.razor +++ b/src/KITT.Cms.Web.App/_Imports.razor @@ -15,5 +15,7 @@ @using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons @using Microsoft.AspNetCore.Components.WebAssembly.Authentication @using Microsoft.AspNetCore.Authorization +@using FluentUI.Blazor.Community.Components +@using KITT.Cms.Web.Models.Settings @attribute [Authorize] From 43c84a22c29f1ad0ec6a7863a46581f7ed8fc02f Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 19 Dec 2025 17:58:18 +0100 Subject: [PATCH 10/26] #124 - update aspire and nuget packages --- src/KITT.AppHost/KITT.AppHost.csproj | 17 +++++++---------- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 4 ++-- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 2 +- src/KITT.Core/KITT.Core.csproj | 8 ++++---- .../KITT.Proposals.Web.Api.csproj | 4 ++-- .../KITT.Proposals.Web.App.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 4 ++-- .../KITT.Support.Seeder.csproj | 8 ++++---- .../KITT.Telegram.Messages.csproj | 4 ++-- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 10 +++++----- .../KITT.Web.App.Client.csproj | 6 +++--- .../KITT.Web.App/KITT.Web.App.csproj | 14 +++++++------- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 10 +++++----- .../KITT.Cms.Web.Api.Test.csproj | 4 ++-- tests/KITT.Core.Test/KITT.Core.Test.csproj | 2 +- tests/KITT.Web.Testing/KITT.Web.Testing.csproj | 2 +- 16 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index e6c08fd..fd47798 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,6 +1,4 @@ - - - + Exe @@ -11,13 +9,12 @@ - - - - - - - + + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index bf582d0..352db91 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index f34a2da..6ae89c5 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index ef0fd7d..9698dcb 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 934600a..ee36356 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index ed133ea..9527407 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 1aa2ba9..eeb71e3 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index c709be5..a8c098f 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,13 +8,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index c803eaa..f5e6017 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index 1b831a4..c40a6a5 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -13,11 +13,11 @@ - - - - - + + + + + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index 55e56b3..e525f8d 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index c1b771f..78070b6 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -14,13 +14,13 @@ - - - + + + - - - - + + + + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index e05f7a0..1b2b6d8 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,11 +7,11 @@ - - - - - + + + + +
diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index 72172c0..07bb7ec 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -12,8 +12,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive
- - + + diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index bfc717b..d356dfe 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -14,7 +14,7 @@
- + diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index 317a603..42f5f9b 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -11,7 +11,7 @@ - + From 18f347d399b15123a176fdabda57e71bf8533063 Mon Sep 17 00:00:00 2001 From: albx Date: Wed, 24 Dec 2025 08:18:41 +0100 Subject: [PATCH 11/26] #124 - WIP channel form panel --- .../Components/ChannelFormPanel.razor | 47 +++++++++++++++++++ .../Components/ChannelFormPanel.razor.cs | 26 ++++++++++ .../Pages/Settings/Channels.razor | 3 +- .../Pages/Settings/Channels.razor.cs | 27 +++++++++-- .../Settings/ChannelModel.cs | 8 ++++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor create mode 100644 src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor new file mode 100644 index 0000000..ecb17ec --- /dev/null +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -0,0 +1,47 @@ +@implements IDialogContentComponent + + + + + + @* + + *@ + + + + + + + + + + + + Save + + + Close + + + diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs new file mode 100644 index 0000000..565f04c --- /dev/null +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -0,0 +1,26 @@ +using KITT.Cms.Web.Models.Settings; +using Microsoft.AspNetCore.Components; +using Microsoft.FluentUI.AspNetCore.Components; + +namespace KITT.Cms.Web.App.Components; + +public partial class ChannelFormPanel : IDialogContentComponent +{ + [Parameter] + public ChannelModel Content { get; set; } = new(); + + [CascadingParameter] + public DialogReference Dialog { get; set; } = default!; + + private readonly Option[] channelTypes = Enum.GetValues().Select(t => new Option{ Value = t, Text = t.ToString() }).ToArray(); + + private string urlPrefix = string.Empty; + + private Option SelectedChannelType + { + get => new() { Value = Content.Type, Text = Content.Type.ToString() }; + set => Content.Type = value.Value; + } + + private async Task CloseAsync() => await Dialog.CloseAsync(DialogResult.Cancel()); +} diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index e4a7a5d..691c576 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -9,7 +9,8 @@ + IconStart="@(new Icons.Filled.Size20.Add())" + OnClick="OpenAddNewChannelPanelAsync"> Add new channel diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index e642cd7..169659a 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -1,16 +1,37 @@ +using KITT.Cms.Web.App.Components; using KITT.Cms.Web.Models.Settings; +using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Pages.Settings; -public partial class Channels +public partial class Channels(IDialogService dialogService) { private List channels = []; + private IDialogReference? dialogReference; + protected override void OnInitialized() { channels = [ - new ChannelModel { Id = Guid.NewGuid(), Name = "Twitch - albx87", Url = "https://www.twitch.tv/albx87" }, - new ChannelModel { Id = Guid.NewGuid(), Name = "YouTube - albx87", Url = "https://www.youtube.com/@albx87" }, + new ChannelModel { Id = Guid.NewGuid(), Type = ChannelType.Twitch, Name = "Twitch - albx87", Url = "https://www.twitch.tv/albx87" }, + new ChannelModel { Id = Guid.NewGuid(), Type = ChannelType.YouTube, Name = "YouTube - albx87", Url = "https://www.youtube.com/@albx87" }, ]; } + + private async Task OpenAddNewChannelPanelAsync() + { + var model = new ChannelModel(); + + dialogReference = await dialogService.ShowPanelAsync( + model, + new DialogParameters() + { + Content = model, + Alignment = HorizontalAlignment.Right, + Title = "Add new channel", + Width = "50em" + }); + + await dialogReference.Result; + } } diff --git a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs index 9264107..45bb63b 100644 --- a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs +++ b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs @@ -6,9 +6,17 @@ public class ChannelModel { public Guid Id { get; set; } + public ChannelType Type { get; set; } + [Required] public string Name { get; set; } = string.Empty; [Required] public string Url { get; set; } = string.Empty; } + +public enum ChannelType +{ + Twitch, + YouTube +} From 5c51ba77bd7d4472acf02425bf3a4f2b0fb93af7 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 27 Dec 2025 17:06:28 +0100 Subject: [PATCH 12/26] #124 - edit UI for channels --- .../Components/ChannelFormPanel.razor | 25 +++++++++++-------- .../Components/ChannelFormPanel.razor.cs | 13 +++++----- .../Pages/Settings/Channels.razor | 17 +++++++++---- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor index ecb17ec..349b948 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -4,16 +4,18 @@ - @* - - *@ + + + + + Id="channelUrl" + Placeholder="@UrlPlaceholder"/> diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs index 565f04c..79b177f 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -12,15 +12,14 @@ public partial class ChannelFormPanel : IDialogContentComponent [CascadingParameter] public DialogReference Dialog { get; set; } = default!; - private readonly Option[] channelTypes = Enum.GetValues().Select(t => new Option{ Value = t, Text = t.ToString() }).ToArray(); + private readonly ChannelType[] channelTypes = Enum.GetValues(); - private string urlPrefix = string.Empty; - - private Option SelectedChannelType + private string UrlPlaceholder => Content.Type switch { - get => new() { Value = Content.Type, Text = Content.Type.ToString() }; - set => Content.Type = value.Value; - } + ChannelType.Twitch => "https://www.twitch.tv/channelName", + ChannelType.YouTube => "https://www.youtube.com/@channelName", + _ => string.Empty + }; private async Task CloseAsync() => await Dialog.CloseAsync(DialogResult.Cancel()); } diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index 691c576..8ab13c8 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -23,11 +23,18 @@

@channel.Name

@channel.Url

- - Edit - + + + Edit + + + Delete + + } From b4e456b9c1b0641d25bdf33e50fef25e79116e4e Mon Sep 17 00:00:00 2001 From: albx Date: Mon, 29 Dec 2025 18:32:14 +0100 Subject: [PATCH 13/26] #124 - WIP connected channels management --- LemonBot.sln | 15 ++++ src/KITT.AppHost/KITT.AppHost.csproj | 1 + src/KITT.AppHost/Program.cs | 28 ++++++ src/KITT.Cms.Settings/ChannelType.cs | 7 ++ src/KITT.Cms.Settings/ConnectedChannel.cs | 21 +++++ .../KITT.Cms.Settings.csproj | 13 +++ .../Stores/ConnectedChannelStore.cs | 52 +++++++++++ .../Stores/IConnectedChannelStore.cs | 12 +++ .../Services/ChannelsEndpointsServices.cs | 79 +++++++++++++++++ .../Services/SettingsEndpointsServices.cs | 18 ---- .../Services/StreamingsEndpointsServices.cs | 12 +-- .../Endpoints/SettingsEndpoints.cs | 87 +++++++++++++++++++ src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 2 + src/KITT.Cms.Web.Api/Program.cs | 7 +- .../ClientsServiceCollectionExtensions.cs | 4 +- .../Http/ConnectedChannelsHttpClient.cs | 36 ++++++++ .../Clients/Http/StreamingsHttpClient.cs | 23 ++--- .../Clients/IConnectedChannelsClient.cs | 14 +++ .../Components/ChannelFormPanel.razor | 9 +- .../Components/ChannelFormPanel.razor.cs | 33 +++++++ .../Pages/Settings/Channels.razor.cs | 19 ++-- .../KITT.Cms.Web.Models.csproj | 4 + .../Settings/ChannelModel.cs | 9 +- src/KITT.Services/ServiceNames.cs | 3 + .../KITT.Web.App/Endpoints/CmsEndpoints.cs | 8 +- 25 files changed, 449 insertions(+), 67 deletions(-) create mode 100644 src/KITT.Cms.Settings/ChannelType.cs create mode 100644 src/KITT.Cms.Settings/ConnectedChannel.cs create mode 100644 src/KITT.Cms.Settings/KITT.Cms.Settings.csproj create mode 100644 src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs create mode 100644 src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs create mode 100644 src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs delete mode 100644 src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs create mode 100644 src/KITT.Cms.Web.App/Clients/Http/ConnectedChannelsHttpClient.cs create mode 100644 src/KITT.Cms.Web.App/Clients/IConnectedChannelsClient.cs diff --git a/LemonBot.sln b/LemonBot.sln index ef0e38e..b11e49d 100644 --- a/LemonBot.sln +++ b/LemonBot.sln @@ -55,6 +55,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Services", "src\KITT.S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Telegram.Messages", "src\KITT.Telegram.Messages\KITT.Telegram.Messages.csproj", "{8C003A09-3777-AEFF-806A-A2010FD1DDDE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Cms.Settings", "src\KITT.Cms.Settings\KITT.Cms.Settings.csproj", "{8393DD88-4D14-4E24-80F4-CCAD1C857D54}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -305,6 +307,18 @@ Global {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x64.Build.0 = Release|Any CPU {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.ActiveCfg = Release|Any CPU {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.Build.0 = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x64.ActiveCfg = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x64.Build.0 = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x86.ActiveCfg = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x86.Build.0 = Debug|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|Any CPU.Build.0 = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x64.ActiveCfg = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x64.Build.0 = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x86.ActiveCfg = Release|Any CPU + {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -334,6 +348,7 @@ Global {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} {8C003A09-3777-AEFF-806A-A2010FD1DDDE} = {53F76412-0B22-4C62-8519-834A82747AD4} + {8393DD88-4D14-4E24-80F4-CCAD1C857D54} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08491B30-AD3E-4AEA-AAB9-40A83A96F393} diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index fd47798..7c5d51a 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -13,6 +13,7 @@ +
diff --git a/src/KITT.AppHost/Program.cs b/src/KITT.AppHost/Program.cs index 0cea868..0115372 100644 --- a/src/KITT.AppHost/Program.cs +++ b/src/KITT.AppHost/Program.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Hosting; using KITT.Services; using KITT.AppHost; +using Aspire.Hosting.Azure; var builder = DistributedApplication.CreateBuilder(args); @@ -22,10 +23,37 @@ var kittDb = builder.AddKittDatabase(); #endregion +#region Azure Storage Account +var azureStorage = builder.AddAzureStorage(ServiceNames.DataStorageAccount) + .ConfigureInfrastructure(infra => + { + var storageAccountResource = infra.GetProvisionableResources() + .OfType() + .SingleOrDefault(); + + if (storageAccountResource is not null) + { + storageAccountResource.Kind = Azure.Provisioning.Storage.StorageKind.StorageV2; + storageAccountResource.Sku = new() + { + Name = Azure.Provisioning.Storage.StorageSkuName.StandardLrs + }; + } + }) + .RunAsEmulator(azurite => + { + azurite.WithDataVolume("kittdatastorage-data"); + }); + +var settingsTables = azureStorage.AddTables(ServiceNames.SettingsTables); +#endregion + #region CMS var cmsApi = builder.AddProject(ServiceNames.CmsApi) .WithReference(kittDb) .WaitFor(kittDb) + .WithReference(settingsTables) + .WaitFor(settingsTables) .WithEnvironment("Identity__TenantId", tenantId) .WithEnvironment("Identity__Cms__AppId", cmsApiAppId) .PublishAsAzureContainerApp((_, app) => diff --git a/src/KITT.Cms.Settings/ChannelType.cs b/src/KITT.Cms.Settings/ChannelType.cs new file mode 100644 index 0000000..b8310eb --- /dev/null +++ b/src/KITT.Cms.Settings/ChannelType.cs @@ -0,0 +1,7 @@ +namespace KITT.Cms.Settings; + +public enum ChannelType +{ + Twitch, + YouTube +} diff --git a/src/KITT.Cms.Settings/ConnectedChannel.cs b/src/KITT.Cms.Settings/ConnectedChannel.cs new file mode 100644 index 0000000..6b237eb --- /dev/null +++ b/src/KITT.Cms.Settings/ConnectedChannel.cs @@ -0,0 +1,21 @@ +using Azure; +using Azure.Data.Tables; + +namespace KITT.Cms.Settings; + +public class ConnectedChannel : ITableEntity +{ + public required string PartitionKey { get; set; } = string.Empty; + + public required string RowKey { get; set; } = string.Empty; + + public DateTimeOffset? Timestamp { get; set; } + + public ETag ETag { get; set; } + + public required string Name { get; set; } = string.Empty; + + public required string Url { get; set; } = string.Empty; + + public required ChannelType Type { get; set; } +} diff --git a/src/KITT.Cms.Settings/KITT.Cms.Settings.csproj b/src/KITT.Cms.Settings/KITT.Cms.Settings.csproj new file mode 100644 index 0000000..d005c22 --- /dev/null +++ b/src/KITT.Cms.Settings/KITT.Cms.Settings.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + + diff --git a/src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs b/src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs new file mode 100644 index 0000000..55f4f87 --- /dev/null +++ b/src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs @@ -0,0 +1,52 @@ +using Azure.Data.Tables; + +namespace KITT.Cms.Settings.Stores; + +public class ConnectedChannelStore : IConnectedChannelStore +{ + private readonly TableClient _tableClient; + + internal const string ConnectedChannelsTableName = "Settings_Channels"; + + public ConnectedChannelStore(TableServiceClient tableServiceClient) + { + _tableClient = CreateTableIfNotExist(tableServiceClient) ?? throw new ArgumentNullException("tableClient"); + } + + private TableClient? CreateTableIfNotExist(TableServiceClient tableServiceClient) + { + var tableClient = tableServiceClient.GetTableClient(ConnectedChannelsTableName); + tableClient.CreateIfNotExists(); + + return tableClient; + } + + public async Task GetConnectedChannelsAsync(string userId) + { + var channelsQuery = _tableClient.QueryAsync(c => c.PartitionKey == userId); + var channels = new List(); + + await foreach (var channel in channelsQuery) + { + channels.Add(channel); + } + + return channels.OrderBy(c => c.Name).ToArray(); + } + + public Task GetConnectedChannelAsync(Guid channelId, string userId) + { + var channels = _tableClient.Query(c => c.PartitionKey == userId && c.RowKey == channelId.ToString()); + return Task.FromResult(channels.SingleOrDefault()); + } + + public async Task SaveAsync(ConnectedChannel channel) + { + await _tableClient.UpsertEntityAsync(channel, TableUpdateMode.Replace); + } + + public async Task DeleteAsync(Guid channelId, string userId) + { + await _tableClient.DeleteEntityAsync(userId, channelId.ToString()); + } +} diff --git a/src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs b/src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs new file mode 100644 index 0000000..538d0f0 --- /dev/null +++ b/src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs @@ -0,0 +1,12 @@ +namespace KITT.Cms.Settings.Stores; + +public interface IConnectedChannelStore +{ + Task GetConnectedChannelsAsync(string userId); + + Task GetConnectedChannelAsync(Guid channelId, string userId); + + Task SaveAsync(ConnectedChannel channel); + + Task DeleteAsync(Guid channelId, string userId); +} diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs new file mode 100644 index 0000000..95d45f3 --- /dev/null +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs @@ -0,0 +1,79 @@ +using KITT.Cms.Settings; +using KITT.Cms.Settings.Stores; +using KITT.Cms.Web.Models.Settings; + +namespace KITT.Cms.Web.Api.Endpoints.Services; + +public class ChannelsEndpointsServices(IConnectedChannelStore connectedChannelStore) +{ + public async Task GetChannelsAsync(string userId) + { + var channels = await connectedChannelStore.GetConnectedChannelsAsync(userId); + return channels.Select(c => new ChannelModel + { + Id = Guid.Parse(c.RowKey), + Name = c.Name, + Url = c.Url, + Type = c.Type + }).ToArray(); + } + + public async Task GetChannelAsync(Guid channelId, string userId) + { + var channel = await connectedChannelStore.GetConnectedChannelAsync(channelId, userId); + if (channel is null) + { + return null; + } + + return new ChannelModel + { + Id = Guid.Parse(channel.RowKey), + Name = channel.Name, + Url = channel.Url, + Type = channel.Type + }; + } + + public async Task CreateChannelAsync(ChannelModel model, string userId) + { + model.Id = Guid.NewGuid(); + + var channelEntity = MapToConnectedChannel(model, userId); + await connectedChannelStore.SaveAsync(channelEntity); + + return model; + } + + public async Task DeleteChannelAsync(Guid channelId, string userId) + { + await connectedChannelStore.DeleteAsync(channelId, userId); + } + + public async Task UpdateChannelAsync(Guid channelId, ChannelModel model, string userId) + { + var connectedChannel = await connectedChannelStore.GetConnectedChannelAsync(channelId, userId); + if (connectedChannel is null) + { + throw new ArgumentOutOfRangeException(nameof(channelId)); + } + + connectedChannel.Name = model.Name; + connectedChannel.Url = model.Url; + connectedChannel.Type = model.Type; + + await connectedChannelStore.SaveAsync(connectedChannel); + } + + private static ConnectedChannel MapToConnectedChannel(ChannelModel model, string userId) + { + return new() + { + RowKey = model.Id.ToString(), + PartitionKey = userId, + Name = model.Name, + Url = model.Url, + Type = model.Type + }; + } +} diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs deleted file mode 100644 index c2f40ac..0000000 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/SettingsEndpointsServices.cs +++ /dev/null @@ -1,18 +0,0 @@ -using KITT.Cms.Web.Models.Settings; -using KITT.Core.Commands; -using KITT.Core.ReadModels; -using Microsoft.EntityFrameworkCore; - -namespace KITT.Cms.Web.Api.Endpoints.Services; - -public class SettingsEndpointsServices -{ - public IDatabase Database { get; } - public ISettingsCommands Commands { get; } - - public SettingsEndpointsServices(IDatabase database, ISettingsCommands commands) - { - Database = database ?? throw new ArgumentNullException(nameof(database)); - Commands = commands ?? throw new ArgumentNullException(nameof(commands)); - } -} diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index 6af8c9a..a10f4b5 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -5,17 +5,11 @@ namespace KITT.Cms.Web.Api.Endpoints.Services; -public class StreamingsEndpointsServices +public class StreamingsEndpointsServices(IDatabase database, IStreamingCommands commands) { - public IDatabase Database { get; } + public IDatabase Database { get; } = database ?? throw new ArgumentNullException(nameof(database)); - public IStreamingCommands Commands { get; } - - public StreamingsEndpointsServices(IDatabase database, IStreamingCommands commands) - { - Database = database ?? throw new ArgumentNullException(nameof(database)); - Commands = commands ?? throw new ArgumentNullException(nameof(commands)); - } + public IStreamingCommands Commands { get; } = commands ?? throw new ArgumentNullException(nameof(commands)); public async Task GetAllStreamingsAsync(string userId, int page, int size, StreamingQueryModel.SortDirection sort, string? query) { diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index b8cc1eb..7bc56e1 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -1,5 +1,6 @@ using KITT.Cms.Web.Api.Endpoints.Services; using KITT.Cms.Web.Models.Settings; +using KITT.Cms.Web.Models.Streamings; using KITT.Web.Shared.Security; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; @@ -17,7 +18,93 @@ public IEndpointRouteBuilder MapSettingsEndpoints() .MapGroup("api/settings") .RequireAuthorization(); + settingsGroup + .MapGet("channels", GetChannels) + .WithName(nameof(GetChannels)); + + settingsGroup + .MapPost("channels", CreateChannel) + .WithName(nameof(CreateChannel)); + + settingsGroup + .MapGet("channels/{id:guid}", GetChannelDetail) + .WithName(nameof(GetChannelDetail)); + + settingsGroup + .MapPut("channels/{id:guid}", UpdateChannel) + .WithName(nameof(UpdateChannel)); + + settingsGroup + .MapDelete("channels/{id}", DeleteChannel) + .WithName(nameof(DeleteChannel)); + return builder; } } + + private static async Task> GetChannels( + ChannelsEndpointsServices services, + ClaimsPrincipal user) + { + var userId = user.GetUserId(); + var channels = await services.GetChannelsAsync(userId); + + return TypedResults.Ok(channels); + } + + private static async Task, BadRequest, ValidationProblem>> CreateChannel( + ChannelsEndpointsServices services, + ClaimsPrincipal user, + [FromBody] ChannelModel model) + { + var userId = user.GetUserId(); + var createdChannel = await services.CreateChannelAsync(model, userId); + + return TypedResults.CreatedAtRoute(createdChannel, nameof(GetChannelDetail), new { id = createdChannel.Id }); + } + + private static async Task, NotFound>> GetChannelDetail( + ChannelsEndpointsServices services, + ClaimsPrincipal user, + Guid id) + { + var userId = user.GetUserId(); + var channel = await services.GetChannelAsync(id, userId); + if (channel is null) + { + return TypedResults.NotFound(); + } + + return TypedResults.Ok(channel); + } + + private static async Task> UpdateChannel( + ChannelsEndpointsServices services, + ClaimsPrincipal user, + Guid id, + [FromBody] ChannelModel model) + { + var userId = user.GetUserId(); + + try + { + await services.UpdateChannelAsync(id, model, userId); + return TypedResults.NoContent(); + } + catch (ArgumentOutOfRangeException) + { + return TypedResults.NotFound(); + } + } + + private static async Task> DeleteChannel( + ChannelsEndpointsServices services, + ClaimsPrincipal user, + Guid id) + { + var userId = user.GetUserId(); + await services.DeleteChannelAsync(id, userId); + + return TypedResults.NoContent(); + } } diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 352db91..96ef6fe 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,11 +7,13 @@ + + diff --git a/src/KITT.Cms.Web.Api/Program.cs b/src/KITT.Cms.Web.Api/Program.cs index 0c05777..9d5d557 100644 --- a/src/KITT.Cms.Web.Api/Program.cs +++ b/src/KITT.Cms.Web.Api/Program.cs @@ -6,12 +6,15 @@ using KITT.Telegram.Messages; using Microsoft.AspNetCore.Authentication.JwtBearer; using KITT.Services; +using KITT.Cms.Settings.Stores; var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); builder.AddSqlServerDbContext(ServiceNames.Database); +builder.AddAzureTableServiceClient(ServiceNames.SettingsTables); + builder.Services.AddValidation(); builder.Services.AddAuthentication() @@ -27,9 +30,11 @@ builder.Services.AddKittCore(); +builder.Services.AddScoped(); + builder.Services .AddScoped() - .AddScoped(); + .AddScoped(); builder.Services.AddProblemDetails(); diff --git a/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs b/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs index 1294921..8421fbe 100644 --- a/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs +++ b/src/KITT.Cms.Web.App/Clients/ClientsServiceCollectionExtensions.cs @@ -9,8 +9,8 @@ public static class ClientsServiceCollectionExtensions { public IServiceCollection AddCmsClients(string apiBaseUrl) { - services - .AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); + services.AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); + services.AddHttpClient(client => client.BaseAddress = new(apiBaseUrl)); return services; } diff --git a/src/KITT.Cms.Web.App/Clients/Http/ConnectedChannelsHttpClient.cs b/src/KITT.Cms.Web.App/Clients/Http/ConnectedChannelsHttpClient.cs new file mode 100644 index 0000000..1a6b9a4 --- /dev/null +++ b/src/KITT.Cms.Web.App/Clients/Http/ConnectedChannelsHttpClient.cs @@ -0,0 +1,36 @@ +using KITT.Cms.Web.Models.Settings; +using System.Net.Http.Json; + +namespace KITT.Cms.Web.App.Clients.Http; + +public class ConnectedChannelsHttpClient(HttpClient httpClient) : IConnectedChannelsClient +{ + public string ApiResource { get; } = "/api/cms/settings/channels"; + + public async Task CreateNewConnectedChannelAsync(ChannelModel model) + { + var response = await httpClient.PostAsJsonAsync(ApiResource, model); + response.EnsureSuccessStatusCode(); + + var createdChannel = await response.Content.ReadFromJsonAsync(); + return createdChannel ?? throw new InvalidOperationException("Invalid channel"); + } + + public async Task DeleteConnectedChannelAsync(ChannelModel model) + { + var response = await httpClient.DeleteAsync($"{ApiResource}/{model.Id}"); + response.EnsureSuccessStatusCode(); + } + + public async Task GetConnectedChannelsAsync() + { + var channels = await httpClient.GetFromJsonAsync(ApiResource); + return channels ?? []; + } + + public async Task UpdateConnectedChannelAsync(ChannelModel model) + { + var response = await httpClient.PutAsJsonAsync($"{ApiResource}/{model.Id}", model); + response.EnsureSuccessStatusCode(); + } +} diff --git a/src/KITT.Cms.Web.App/Clients/Http/StreamingsHttpClient.cs b/src/KITT.Cms.Web.App/Clients/Http/StreamingsHttpClient.cs index 20600c5..987770c 100644 --- a/src/KITT.Cms.Web.App/Clients/Http/StreamingsHttpClient.cs +++ b/src/KITT.Cms.Web.App/Clients/Http/StreamingsHttpClient.cs @@ -3,20 +3,13 @@ namespace KITT.Cms.Web.App.Clients.Http; -public class StreamingsHttpClient : IStreamingsClient +public class StreamingsHttpClient(HttpClient httpClient) : IStreamingsClient { - public HttpClient Client { get; } - public string ApiResource { get; } = "/api/cms/streamings"; - public StreamingsHttpClient(HttpClient client) - { - Client = client ?? throw new ArgumentNullException(nameof(client)); - } - public async Task ScheduleStreamingAsync(ScheduleStreamingModel model) { - var response = await Client.PostAsJsonAsync(ApiResource, model); + var response = await httpClient.PostAsJsonAsync(ApiResource, model); if (!response.IsSuccessStatusCode) { throw new ApplicationException("Error scheduling streaming"); @@ -32,7 +25,7 @@ public async Task GetAllStreamingsAsync(StreamingQueryModel url = $"{url}?{queryString}"; } - var model = await Client.GetFromJsonAsync(url); + var model = await httpClient.GetFromJsonAsync(url); return model ?? new StreamingsListModel(); } @@ -40,7 +33,7 @@ public async Task GetAllStreamingsAsync(StreamingQueryModel { try { - var model = await Client.GetFromJsonAsync($"{ApiResource}/{streamingId}"); + var model = await httpClient.GetFromJsonAsync($"{ApiResource}/{streamingId}"); return model; } catch @@ -51,7 +44,7 @@ public async Task GetAllStreamingsAsync(StreamingQueryModel public async Task UpdateStreamingAsync(StreamingDetailModel model) { - var response = await Client.PutAsJsonAsync($"{ApiResource}/{model.Id}", model); + var response = await httpClient.PutAsJsonAsync($"{ApiResource}/{model.Id}", model); if (!response.IsSuccessStatusCode) { throw new ApplicationException("Error updating streaming"); @@ -60,7 +53,7 @@ public async Task UpdateStreamingAsync(StreamingDetailModel model) public async Task DeleteStreamingAsync(Guid streamingId) { - var response = await Client.DeleteAsync($"{ApiResource}/{streamingId}"); + var response = await httpClient.DeleteAsync($"{ApiResource}/{streamingId}"); if (!response.IsSuccessStatusCode) { throw new ApplicationException("Error deleting streaming"); @@ -69,7 +62,7 @@ public async Task DeleteStreamingAsync(Guid streamingId) public async Task ImportStreamingAsync(ImportStreamingModel model) { - var response = await Client.PostAsJsonAsync($"{ApiResource}/import", model); + var response = await httpClient.PostAsJsonAsync($"{ApiResource}/import", model); if (!response.IsSuccessStatusCode) { throw new ApplicationException("Error importing streaming"); @@ -78,7 +71,7 @@ public async Task ImportStreamingAsync(ImportStreamingModel model) public async Task GetStreamingStatsAsync() { - var streamingStats = await Client.GetFromJsonAsync($"{ApiResource}/stats"); + var streamingStats = await httpClient.GetFromJsonAsync($"{ApiResource}/stats"); return streamingStats ?? new(0, 0); } } diff --git a/src/KITT.Cms.Web.App/Clients/IConnectedChannelsClient.cs b/src/KITT.Cms.Web.App/Clients/IConnectedChannelsClient.cs new file mode 100644 index 0000000..4c2f030 --- /dev/null +++ b/src/KITT.Cms.Web.App/Clients/IConnectedChannelsClient.cs @@ -0,0 +1,14 @@ +using KITT.Cms.Web.Models.Settings; + +namespace KITT.Cms.Web.App.Clients; + +public interface IConnectedChannelsClient +{ + Task GetConnectedChannelsAsync(); + + Task CreateNewConnectedChannelAsync(ChannelModel model); + + Task UpdateConnectedChannelAsync(ChannelModel model); + + Task DeleteConnectedChannelAsync(ChannelModel model); +} diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor index 349b948..4246cad 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -1,6 +1,8 @@ @implements IDialogContentComponent - +@using KITT.Cms.Settings + + @@ -39,11 +41,12 @@ + Appearance="Appearance.Accent" + OnClick="SaveAsync"> Save + OnClick="CloseAsync"> Close diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs index 79b177f..7ee9af0 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -1,5 +1,7 @@ +using KITT.Cms.Settings; using KITT.Cms.Web.Models.Settings; using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Components; @@ -9,9 +11,16 @@ public partial class ChannelFormPanel : IDialogContentComponent [Parameter] public ChannelModel Content { get; set; } = new(); + [Parameter] + public EventCallback OnSaveChannel { get; set; } + [CascadingParameter] public DialogReference Dialog { get; set; } = default!; + private EditContext context = default!; + + private bool saving = false; + private readonly ChannelType[] channelTypes = Enum.GetValues(); private string UrlPlaceholder => Content.Type switch @@ -21,5 +30,29 @@ public partial class ChannelFormPanel : IDialogContentComponent _ => string.Empty }; + protected override void OnInitialized() + { + context = new(Content); + } + + private async Task SaveAsync() + { + saving = true; + + try + { + if (!context.Validate()) + { + return; + } + + await OnSaveChannel.InvokeAsync(Content); + } + finally + { + saving = false; + } + } + private async Task CloseAsync() => await Dialog.CloseAsync(DialogResult.Cancel()); } diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 169659a..137d6f2 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -1,21 +1,24 @@ +using KITT.Cms.Web.App.Clients; using KITT.Cms.Web.App.Components; using KITT.Cms.Web.Models.Settings; using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Pages.Settings; -public partial class Channels(IDialogService dialogService) +public partial class Channels(IDialogService dialogService, IConnectedChannelsClient client) { - private List channels = []; + private ChannelModel[] channels = []; private IDialogReference? dialogReference; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - channels = [ - new ChannelModel { Id = Guid.NewGuid(), Type = ChannelType.Twitch, Name = "Twitch - albx87", Url = "https://www.twitch.tv/albx87" }, - new ChannelModel { Id = Guid.NewGuid(), Type = ChannelType.YouTube, Name = "YouTube - albx87", Url = "https://www.youtube.com/@albx87" }, - ]; + channels = await client.GetConnectedChannelsAsync(); + } + + private async Task CreateNewChannelAsync(ChannelModel channel) + { + await client.CreateNewConnectedChannelAsync(channel); } private async Task OpenAddNewChannelPanelAsync() @@ -29,7 +32,7 @@ private async Task OpenAddNewChannelPanelAsync() Content = model, Alignment = HorizontalAlignment.Right, Title = "Add new channel", - Width = "50em" + Width = "50em", }); await dialogReference.Result; diff --git a/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj b/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj index b760144..22054ac 100644 --- a/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj +++ b/src/KITT.Cms.Web.Models/KITT.Cms.Web.Models.csproj @@ -6,4 +6,8 @@ enable + + + +
diff --git a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs index 45bb63b..84d880d 100644 --- a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs +++ b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using KITT.Cms.Settings; +using System.ComponentModel.DataAnnotations; namespace KITT.Cms.Web.Models.Settings; @@ -14,9 +15,3 @@ public class ChannelModel [Required] public string Url { get; set; } = string.Empty; } - -public enum ChannelType -{ - Twitch, - YouTube -} diff --git a/src/KITT.Services/ServiceNames.cs b/src/KITT.Services/ServiceNames.cs index d83058b..6a606e1 100644 --- a/src/KITT.Services/ServiceNames.cs +++ b/src/KITT.Services/ServiceNames.cs @@ -12,4 +12,7 @@ public static class ServiceNames public const string WebApp = "kitt-webapp"; public const string Seeder = "kitt-support-seeder"; + + public const string DataStorageAccount = "kittdatastorage"; + public const string SettingsTables = "kitt-settings-tables"; } diff --git a/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs b/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs index e66a4d7..c266dbc 100644 --- a/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs +++ b/src/KITT.Web.App/KITT.Web.App/Endpoints/CmsEndpoints.cs @@ -42,18 +42,18 @@ public IEndpointRouteBuilder MapCmsEndpoints() .RequireAuthorization(); builder.MapForwarder( - "/api/cms/settings", + "/api/cms/settings/channels", $"https+http://{ServiceNames.CmsApi}", transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/settings", + "/api/settings/channels", GetScopes)) .RequireAuthorization(); builder.MapForwarder( - "/api/cms/settings/{id}", + "/api/cms/settings/channels/{id}", $"https+http://{ServiceNames.CmsApi}", transformBuilder => transformBuilder.ConfigureWithTargetPath( - "/api/settings/{id}", + "/api/settings/channels/{id}", GetScopes)) .RequireAuthorization(); From a5d97c30ffb3662440a2d756883537ff81b65367 Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 2 Jan 2026 13:54:33 +0100 Subject: [PATCH 14/26] #124 - connected channels can now be added --- ...tore.cs => ConnectedChannelsRepository.cs} | 9 +++--- ...ore.cs => IConnectedChannelsRepository.cs} | 6 ++-- .../{ => Models}/ChannelType.cs | 2 +- .../{ => Models}/ConnectedChannel.cs | 2 +- .../Services/ChannelsEndpointsServices.cs | 16 +++++----- src/KITT.Cms.Web.Api/Program.cs | 4 +-- .../Components/ChannelFormPanel.razor | 18 +++++++----- .../Components/ChannelFormPanel.razor.cs | 29 +++++++++++++------ .../Pages/Settings/Channels.razor.cs | 23 +++++++++++---- .../Settings/ChannelModel.cs | 2 +- 10 files changed, 69 insertions(+), 42 deletions(-) rename src/KITT.Cms.Settings/{Stores/ConnectedChannelStore.cs => ConnectedChannelsRepository.cs} (87%) rename src/KITT.Cms.Settings/{Stores/IConnectedChannelStore.cs => IConnectedChannelsRepository.cs} (70%) rename src/KITT.Cms.Settings/{ => Models}/ChannelType.cs (57%) rename src/KITT.Cms.Settings/{ => Models}/ConnectedChannel.cs (93%) diff --git a/src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs similarity index 87% rename from src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs rename to src/KITT.Cms.Settings/ConnectedChannelsRepository.cs index 55f4f87..d72d5cc 100644 --- a/src/KITT.Cms.Settings/Stores/ConnectedChannelStore.cs +++ b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs @@ -1,14 +1,15 @@ using Azure.Data.Tables; +using KITT.Cms.Settings.Models; -namespace KITT.Cms.Settings.Stores; +namespace KITT.Cms.Settings; -public class ConnectedChannelStore : IConnectedChannelStore +public class ConnectedChannelsRepository : IConnectedChannelsRepository { private readonly TableClient _tableClient; - internal const string ConnectedChannelsTableName = "Settings_Channels"; + internal const string ConnectedChannelsTableName = "SettingsChannels"; - public ConnectedChannelStore(TableServiceClient tableServiceClient) + public ConnectedChannelsRepository(TableServiceClient tableServiceClient) { _tableClient = CreateTableIfNotExist(tableServiceClient) ?? throw new ArgumentNullException("tableClient"); } diff --git a/src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs b/src/KITT.Cms.Settings/IConnectedChannelsRepository.cs similarity index 70% rename from src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs rename to src/KITT.Cms.Settings/IConnectedChannelsRepository.cs index 538d0f0..7de2c22 100644 --- a/src/KITT.Cms.Settings/Stores/IConnectedChannelStore.cs +++ b/src/KITT.Cms.Settings/IConnectedChannelsRepository.cs @@ -1,6 +1,8 @@ -namespace KITT.Cms.Settings.Stores; +using KITT.Cms.Settings.Models; -public interface IConnectedChannelStore +namespace KITT.Cms.Settings; + +public interface IConnectedChannelsRepository { Task GetConnectedChannelsAsync(string userId); diff --git a/src/KITT.Cms.Settings/ChannelType.cs b/src/KITT.Cms.Settings/Models/ChannelType.cs similarity index 57% rename from src/KITT.Cms.Settings/ChannelType.cs rename to src/KITT.Cms.Settings/Models/ChannelType.cs index b8310eb..5a68353 100644 --- a/src/KITT.Cms.Settings/ChannelType.cs +++ b/src/KITT.Cms.Settings/Models/ChannelType.cs @@ -1,4 +1,4 @@ -namespace KITT.Cms.Settings; +namespace KITT.Cms.Settings.Models; public enum ChannelType { diff --git a/src/KITT.Cms.Settings/ConnectedChannel.cs b/src/KITT.Cms.Settings/Models/ConnectedChannel.cs similarity index 93% rename from src/KITT.Cms.Settings/ConnectedChannel.cs rename to src/KITT.Cms.Settings/Models/ConnectedChannel.cs index 6b237eb..a9a9b7c 100644 --- a/src/KITT.Cms.Settings/ConnectedChannel.cs +++ b/src/KITT.Cms.Settings/Models/ConnectedChannel.cs @@ -1,7 +1,7 @@ using Azure; using Azure.Data.Tables; -namespace KITT.Cms.Settings; +namespace KITT.Cms.Settings.Models; public class ConnectedChannel : ITableEntity { diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs index 95d45f3..e94bbd7 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/ChannelsEndpointsServices.cs @@ -1,14 +1,14 @@ using KITT.Cms.Settings; -using KITT.Cms.Settings.Stores; +using KITT.Cms.Settings.Models; using KITT.Cms.Web.Models.Settings; namespace KITT.Cms.Web.Api.Endpoints.Services; -public class ChannelsEndpointsServices(IConnectedChannelStore connectedChannelStore) +public class ChannelsEndpointsServices(IConnectedChannelsRepository connectedChannelsRepository) { public async Task GetChannelsAsync(string userId) { - var channels = await connectedChannelStore.GetConnectedChannelsAsync(userId); + var channels = await connectedChannelsRepository.GetConnectedChannelsAsync(userId); return channels.Select(c => new ChannelModel { Id = Guid.Parse(c.RowKey), @@ -20,7 +20,7 @@ public async Task GetChannelsAsync(string userId) public async Task GetChannelAsync(Guid channelId, string userId) { - var channel = await connectedChannelStore.GetConnectedChannelAsync(channelId, userId); + var channel = await connectedChannelsRepository.GetConnectedChannelAsync(channelId, userId); if (channel is null) { return null; @@ -40,19 +40,19 @@ public async Task CreateChannelAsync(ChannelModel model, string us model.Id = Guid.NewGuid(); var channelEntity = MapToConnectedChannel(model, userId); - await connectedChannelStore.SaveAsync(channelEntity); + await connectedChannelsRepository.SaveAsync(channelEntity); return model; } public async Task DeleteChannelAsync(Guid channelId, string userId) { - await connectedChannelStore.DeleteAsync(channelId, userId); + await connectedChannelsRepository.DeleteAsync(channelId, userId); } public async Task UpdateChannelAsync(Guid channelId, ChannelModel model, string userId) { - var connectedChannel = await connectedChannelStore.GetConnectedChannelAsync(channelId, userId); + var connectedChannel = await connectedChannelsRepository.GetConnectedChannelAsync(channelId, userId); if (connectedChannel is null) { throw new ArgumentOutOfRangeException(nameof(channelId)); @@ -62,7 +62,7 @@ public async Task UpdateChannelAsync(Guid channelId, ChannelModel model, string connectedChannel.Url = model.Url; connectedChannel.Type = model.Type; - await connectedChannelStore.SaveAsync(connectedChannel); + await connectedChannelsRepository.SaveAsync(connectedChannel); } private static ConnectedChannel MapToConnectedChannel(ChannelModel model, string userId) diff --git a/src/KITT.Cms.Web.Api/Program.cs b/src/KITT.Cms.Web.Api/Program.cs index 9d5d557..6fcd02f 100644 --- a/src/KITT.Cms.Web.Api/Program.cs +++ b/src/KITT.Cms.Web.Api/Program.cs @@ -6,7 +6,7 @@ using KITT.Telegram.Messages; using Microsoft.AspNetCore.Authentication.JwtBearer; using KITT.Services; -using KITT.Cms.Settings.Stores; +using KITT.Cms.Settings; var builder = WebApplication.CreateBuilder(args); @@ -30,7 +30,7 @@ builder.Services.AddKittCore(); -builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Services .AddScoped() diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor index 4246cad..586b4b0 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -1,6 +1,6 @@ -@implements IDialogContentComponent +@implements IDialogContentComponent -@using KITT.Cms.Settings +@using KITT.Cms.Settings.Models @@ -15,37 +15,39 @@ Style="width:100%;" OptionValue="@(t => t.ToString())" OptionText="@(t => t.ToString())" - @bind-SelectedOption="Content.Type"/> - + @bind-SelectedOption="Content.Model.Type"/> + - + - + Save Close diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs index 7ee9af0..3a664ba 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -1,4 +1,4 @@ -using KITT.Cms.Settings; +using KITT.Cms.Settings.Models; using KITT.Cms.Web.Models.Settings; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; @@ -6,13 +6,10 @@ namespace KITT.Cms.Web.App.Components; -public partial class ChannelFormPanel : IDialogContentComponent +public partial class ChannelFormPanel(IToastService toastService) : IDialogContentComponent { [Parameter] - public ChannelModel Content { get; set; } = new(); - - [Parameter] - public EventCallback OnSaveChannel { get; set; } + public ViewModel Content { get; set; } = new(); [CascadingParameter] public DialogReference Dialog { get; set; } = default!; @@ -23,7 +20,7 @@ public partial class ChannelFormPanel : IDialogContentComponent private readonly ChannelType[] channelTypes = Enum.GetValues(); - private string UrlPlaceholder => Content.Type switch + private string UrlPlaceholder => Content.Model.Type switch { ChannelType.Twitch => "https://www.twitch.tv/channelName", ChannelType.YouTube => "https://www.youtube.com/@channelName", @@ -32,7 +29,7 @@ public partial class ChannelFormPanel : IDialogContentComponent protected override void OnInitialized() { - context = new(Content); + context = new(Content.Model); } private async Task SaveAsync() @@ -46,7 +43,14 @@ private async Task SaveAsync() return; } - await OnSaveChannel.InvokeAsync(Content); + await Content.OnChannelSave.InvokeAsync(Content.Model); + + toastService.ShowSuccess("Channel saved correctly"); + await Dialog.CloseAsync(DialogResult.Ok(true)); + } + catch + { + toastService.ShowError("Error saving the channel"); } finally { @@ -55,4 +59,11 @@ private async Task SaveAsync() } private async Task CloseAsync() => await Dialog.CloseAsync(DialogResult.Cancel()); + + public class ViewModel + { + public ChannelModel Model { get; set; } = new(); + + public EventCallback OnChannelSave { get; set; } + } } diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 137d6f2..8cc2cce 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -1,6 +1,7 @@ using KITT.Cms.Web.App.Clients; using KITT.Cms.Web.App.Components; using KITT.Cms.Web.Models.Settings; +using Microsoft.AspNetCore.Components; using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Pages.Settings; @@ -13,7 +14,7 @@ public partial class Channels(IDialogService dialogService, IConnectedChannelsCl protected override async Task OnInitializedAsync() { - channels = await client.GetConnectedChannelsAsync(); + await LoadConnectedChannelsAsync(); } private async Task CreateNewChannelAsync(ChannelModel channel) @@ -21,20 +22,30 @@ private async Task CreateNewChannelAsync(ChannelModel channel) await client.CreateNewConnectedChannelAsync(channel); } + private async Task LoadConnectedChannelsAsync() => channels = await client.GetConnectedChannelsAsync(); + private async Task OpenAddNewChannelPanelAsync() { - var model = new ChannelModel(); + var panelModel = new ChannelFormPanel.ViewModel + { + Model = new(), + OnChannelSave = EventCallback.Factory.Create(this, CreateNewChannelAsync) + }; dialogReference = await dialogService.ShowPanelAsync( - model, - new DialogParameters() + panelModel, + new DialogParameters() { - Content = model, + Content = panelModel, Alignment = HorizontalAlignment.Right, Title = "Add new channel", Width = "50em", }); - await dialogReference.Result; + var result = await dialogReference.Result; + if (!result.Cancelled) + { + await LoadConnectedChannelsAsync(); + } } } diff --git a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs index 84d880d..7f080d1 100644 --- a/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs +++ b/src/KITT.Cms.Web.Models/Settings/ChannelModel.cs @@ -1,4 +1,4 @@ -using KITT.Cms.Settings; +using KITT.Cms.Settings.Models; using System.ComponentModel.DataAnnotations; namespace KITT.Cms.Web.Models.Settings; From f8e81b2a718126fefcfcc9bb301f567383568ea6 Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 2 Jan 2026 14:03:21 +0100 Subject: [PATCH 15/26] #124 - edit connected channel --- .../ConnectedChannelsRepository.cs | 2 +- .../Endpoints/SettingsEndpoints.cs | 1 - .../Pages/Settings/Channels.razor | 10 ++++--- .../Pages/Settings/Channels.razor.cs | 30 +++++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs index d72d5cc..80895b2 100644 --- a/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs +++ b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs @@ -14,7 +14,7 @@ public ConnectedChannelsRepository(TableServiceClient tableServiceClient) _tableClient = CreateTableIfNotExist(tableServiceClient) ?? throw new ArgumentNullException("tableClient"); } - private TableClient? CreateTableIfNotExist(TableServiceClient tableServiceClient) + private static TableClient? CreateTableIfNotExist(TableServiceClient tableServiceClient) { var tableClient = tableServiceClient.GetTableClient(ConnectedChannelsTableName); tableClient.CreateIfNotExists(); diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index 7bc56e1..201b077 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -1,6 +1,5 @@ using KITT.Cms.Web.Api.Endpoints.Services; using KITT.Cms.Web.Models.Settings; -using KITT.Cms.Web.Models.Streamings; using KITT.Web.Shared.Security; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index 8ab13c8..29268db 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -25,13 +25,15 @@ + Appearance="Appearance.Accent" + IconStart="@(new Icons.Filled.Size20.Edit())" + OnClick="@(() => OpenEditChannelPanelAsync(channel))"> Edit + Appearance="Appearance.Outline" + IconStart="@(new Icons.Filled.Size20.Delete())" + OnClick="@(() => DeleteChannelAsync(channel))"> Delete diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 8cc2cce..84bf9df 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -48,4 +48,34 @@ private async Task OpenAddNewChannelPanelAsync() await LoadConnectedChannelsAsync(); } } + + private async Task OpenEditChannelPanelAsync(ChannelModel channel) + { + var panelModel = new ChannelFormPanel.ViewModel + { + Model = channel, + OnChannelSave = EventCallback.Factory.Create(this, CreateNewChannelAsync) + }; + + dialogReference = await dialogService.ShowPanelAsync( + panelModel, + new DialogParameters() + { + Content = panelModel, + Alignment = HorizontalAlignment.Right, + Title = $"Edit channel {channel.Name}", + Width = "50em", + }); + + var result = await dialogReference.Result; + if (!result.Cancelled) + { + await LoadConnectedChannelsAsync(); + } + } + + private async Task DeleteChannelAsync(ChannelModel channel) + { + //TODO + } } From e5b95fa4526c3395c96132dfa32ca9e9eee31745 Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 16 Jan 2026 21:58:53 +0100 Subject: [PATCH 16/26] #124 - fix reverse proxy, fix dialog close --- .../Endpoints/SettingsEndpoints.cs | 2 +- .../Components/ChannelFormPanel.razor.cs | 6 +- .../Pages/Settings/Channels.razor | 58 ++++++++++-------- .../Pages/Settings/Channels.razor.cs | 61 +++++++++++++++++-- .../TransformBuilderContextExtensions.cs | 4 +- 5 files changed, 96 insertions(+), 35 deletions(-) diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index 201b077..02850f6 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -34,7 +34,7 @@ public IEndpointRouteBuilder MapSettingsEndpoints() .WithName(nameof(UpdateChannel)); settingsGroup - .MapDelete("channels/{id}", DeleteChannel) + .MapDelete("channels/{id:guid}", DeleteChannel) .WithName(nameof(DeleteChannel)); return builder; diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs index 3a664ba..e715aec 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -12,7 +12,7 @@ public partial class ChannelFormPanel(IToastService toastService) : IDialogConte public ViewModel Content { get; set; } = new(); [CascadingParameter] - public DialogReference Dialog { get; set; } = default!; + FluentDialog Dialog { get; set; } = default!; private EditContext context = default!; @@ -46,10 +46,12 @@ private async Task SaveAsync() await Content.OnChannelSave.InvokeAsync(Content.Model); toastService.ShowSuccess("Channel saved correctly"); + await Dialog.CloseAsync(DialogResult.Ok(true)); } - catch + catch (Exception ex) { + Console.WriteLine(ex); toastService.ShowError("Error saving the channel"); } finally diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index 29268db..3f8d1b3 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -13,31 +13,39 @@ OnClick="OpenAddNewChannelPanelAsync"> Add new channel + + Refresh + - - @foreach (var channel in channels) - { - - -

@channel.Name

-

@channel.Url

+ + + @foreach (var channel in channels) + { + + +

@channel.Name

+

@channel.Url

- - - Edit - - - Delete - - -
-
- } -
\ No newline at end of file + + + Edit + + + Delete + + +
+
+ } +
+ \ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 84bf9df..53b0f1d 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -6,10 +6,15 @@ namespace KITT.Cms.Web.App.Pages.Settings; -public partial class Channels(IDialogService dialogService, IConnectedChannelsClient client) +public partial class Channels( + IDialogService dialogService, + IToastService toastService, + IConnectedChannelsClient client) { private ChannelModel[] channels = []; + private bool loading = false; + private IDialogReference? dialogReference; protected override async Task OnInitializedAsync() @@ -22,7 +27,19 @@ private async Task CreateNewChannelAsync(ChannelModel channel) await client.CreateNewConnectedChannelAsync(channel); } - private async Task LoadConnectedChannelsAsync() => channels = await client.GetConnectedChannelsAsync(); + private async Task LoadConnectedChannelsAsync() + { + loading = true; + + try + { + channels = await client.GetConnectedChannelsAsync(); + } + finally + { + loading = false; + } + } private async Task OpenAddNewChannelPanelAsync() { @@ -51,10 +68,18 @@ private async Task OpenAddNewChannelPanelAsync() private async Task OpenEditChannelPanelAsync(ChannelModel channel) { + var channelCopy = new ChannelModel + { + Id = channel.Id, + Name = channel.Name, + Type = channel.Type, + Url = channel.Url, + }; + var panelModel = new ChannelFormPanel.ViewModel { - Model = channel, - OnChannelSave = EventCallback.Factory.Create(this, CreateNewChannelAsync) + Model = channelCopy, + OnChannelSave = EventCallback.Factory.Create(this, UpdateChannelAsync) }; dialogReference = await dialogService.ShowPanelAsync( @@ -74,8 +99,34 @@ private async Task OpenEditChannelPanelAsync(ChannelModel channel) } } + private async Task UpdateChannelAsync(ChannelModel channel) + { + await client.UpdateConnectedChannelAsync(channel); + } + private async Task DeleteChannelAsync(ChannelModel channel) { - //TODO + var channelName = channel.Name; + + var confirm = await dialogService.ShowConfirmationAsync( + "You are going to delete this channel. Are you sure?", + title: $"Delete channel {channelName}"); + + var result = await confirm.Result; + + if (!result.Cancelled) + { + try + { + await client.DeleteConnectedChannelAsync(channel); + toastService.ShowSuccess($"{channelName} deleted successfully!"); + + await LoadConnectedChannelsAsync(); + } + catch + { + toastService.ShowError($"There was an error deleting channel {channelName}"); + } + } } } diff --git a/src/KITT.Web.App/KITT.Web.App/Endpoints/ReverseProxy/TransformBuilderContextExtensions.cs b/src/KITT.Web.App/KITT.Web.App/Endpoints/ReverseProxy/TransformBuilderContextExtensions.cs index 69097e7..0dae98c 100644 --- a/src/KITT.Web.App/KITT.Web.App/Endpoints/ReverseProxy/TransformBuilderContextExtensions.cs +++ b/src/KITT.Web.App/KITT.Web.App/Endpoints/ReverseProxy/TransformBuilderContextExtensions.cs @@ -11,10 +11,10 @@ public static void ConfigureWithTargetPath( string targetPath, Func> scopesResolver) { + transformBuilder.AddPathRouteValues(targetPath); + transformBuilder.AddRequestTransform(async transformContext => { - transformContext.Path = new(targetPath); - var tokenAcquisition = transformContext.HttpContext.RequestServices.GetRequiredService(); var configuration = transformContext.HttpContext.RequestServices.GetRequiredService(); var user = transformContext.HttpContext.User; From 26b07d5a82b5ee52075c506de4af9be3bfaf6e67 Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 16 Jan 2026 22:38:00 +0100 Subject: [PATCH 17/26] #124 - add channels page translations --- .../Components/ChannelFormPanel.razor | 4 +- .../Components/ChannelFormPanel.razor.cs | 12 +- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 18 ++ .../Pages/Settings/Channels.razor | 12 +- .../Pages/Settings/Channels.razor.cs | 27 +-- .../Components/ChannelFormPanel.Designer.cs | 99 ++++++++++ .../Components/ChannelFormPanel.it.resx | 132 ++++++++++++++ .../Components/ChannelFormPanel.resx | 132 ++++++++++++++ .../Pages/Settings/Channels.Designer.cs | 171 ++++++++++++++++++ .../Resources/Pages/Settings/Channels.it.resx | 156 ++++++++++++++++ .../Resources/Pages/Settings/Channels.resx | 156 ++++++++++++++++ .../KITT.Web.App.Client/Layout/NavMenu.razor | 12 +- .../Resources/Shared/NavMenu.Designer.cs | 11 +- .../Resources/Shared/NavMenu.it.resx | 5 +- .../Resources/Shared/NavMenu.resx | 3 + 15 files changed, 916 insertions(+), 34 deletions(-) create mode 100644 src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.Designer.cs create mode 100644 src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx create mode 100644 src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx create mode 100644 src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.Designer.cs create mode 100644 src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.it.resx create mode 100644 src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.resx diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor index 586b4b0..56c263b 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -44,12 +44,12 @@ Appearance="Appearance.Accent" Loading="saving" OnClick="SaveAsync"> - Save + @localizer[nameof(Resources.Components.ChannelFormPanel.SaveButtonText)] - Close + @localizer[nameof(Resources.Components.ChannelFormPanel.CloseButtonText)]
diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs index e715aec..ff315b9 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor.cs @@ -2,11 +2,14 @@ using KITT.Cms.Web.Models.Settings; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; +using Microsoft.Extensions.Localization; using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Components; -public partial class ChannelFormPanel(IToastService toastService) : IDialogContentComponent +public partial class ChannelFormPanel( + IToastService toastService, + IStringLocalizer localizer) : IDialogContentComponent { [Parameter] public ViewModel Content { get; set; } = new(); @@ -45,14 +48,13 @@ private async Task SaveAsync() await Content.OnChannelSave.InvokeAsync(Content.Model); - toastService.ShowSuccess("Channel saved correctly"); + toastService.ShowSuccess(localizer[nameof(Resources.Components.ChannelFormPanel.ChannelSavedSuccessMessage)]); await Dialog.CloseAsync(DialogResult.Ok(true)); } - catch (Exception ex) + catch { - Console.WriteLine(ex); - toastService.ShowError("Error saving the channel"); + toastService.ShowError(localizer[nameof(Resources.Components.ChannelFormPanel.ChannelSavedErrorMessage)]); } finally { diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index 6ae89c5..3d68ccc 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -21,6 +21,11 @@
+ + True + True + ChannelFormPanel.resx + True True @@ -31,6 +36,11 @@ True StreamingStats.resx + + True + True + Channels.resx + True True @@ -54,6 +64,10 @@ + + PublicResXFileCodeGenerator + ChannelFormPanel.Designer.cs + PublicResXFileCodeGenerator @@ -68,6 +82,10 @@ ResXFileCodeGenerator StreamingStats.Designer.cs + + PublicResXFileCodeGenerator + Channels.Designer.cs + ResXFileCodeGenerator Import.Designer.cs diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor index 3f8d1b3..54b8d83 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor @@ -1,9 +1,9 @@ @page "/settings/channels" -KITT - Connected channels +KITT - @localizer[nameof(Resources.Pages.Settings.Channels.PageTitle)] - Connected channels + @localizer[nameof(Resources.Pages.Settings.Channels.PageTitle)] @@ -11,13 +11,13 @@ Appearance="Appearance.Accent" IconStart="@(new Icons.Filled.Size20.Add())" OnClick="OpenAddNewChannelPanelAsync"> - Add new channel + @localizer[nameof(Resources.Pages.Settings.Channels.AddNewChannelButtonText)] - Refresh + @localizer[nameof(Resources.Pages.Settings.Channels.RefreshChannelsButtonText)] @@ -35,13 +35,13 @@ Appearance="Appearance.Accent" IconStart="@(new Icons.Filled.Size20.Edit())" OnClick="@(() => OpenEditChannelPanelAsync(channel))"> - Edit + @localizer[nameof(Resources.Pages.Settings.Channels.EditChannelButtonText)] - Delete + @localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelButtonText)] diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 53b0f1d..4664188 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -2,6 +2,7 @@ using KITT.Cms.Web.App.Components; using KITT.Cms.Web.Models.Settings; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; using Microsoft.FluentUI.AspNetCore.Components; namespace KITT.Cms.Web.App.Pages.Settings; @@ -9,14 +10,13 @@ namespace KITT.Cms.Web.App.Pages.Settings; public partial class Channels( IDialogService dialogService, IToastService toastService, - IConnectedChannelsClient client) + IConnectedChannelsClient client, + IStringLocalizer localizer) { private ChannelModel[] channels = []; private bool loading = false; - private IDialogReference? dialogReference; - protected override async Task OnInitializedAsync() { await LoadConnectedChannelsAsync(); @@ -49,17 +49,17 @@ private async Task OpenAddNewChannelPanelAsync() OnChannelSave = EventCallback.Factory.Create(this, CreateNewChannelAsync) }; - dialogReference = await dialogService.ShowPanelAsync( + var dialog = await dialogService.ShowPanelAsync( panelModel, new DialogParameters() { Content = panelModel, Alignment = HorizontalAlignment.Right, - Title = "Add new channel", + Title = localizer[nameof(Resources.Pages.Settings.Channels.AddNewChannelPanelTitle)], Width = "50em", }); - var result = await dialogReference.Result; + var result = await dialog.Result; if (!result.Cancelled) { await LoadConnectedChannelsAsync(); @@ -82,17 +82,17 @@ private async Task OpenEditChannelPanelAsync(ChannelModel channel) OnChannelSave = EventCallback.Factory.Create(this, UpdateChannelAsync) }; - dialogReference = await dialogService.ShowPanelAsync( + var dialog = await dialogService.ShowPanelAsync( panelModel, new DialogParameters() { Content = panelModel, Alignment = HorizontalAlignment.Right, - Title = $"Edit channel {channel.Name}", + Title = localizer[nameof(Resources.Pages.Settings.Channels.EditChannelPanelTitle), channel.Name], Width = "50em", }); - var result = await dialogReference.Result; + var result = await dialog.Result; if (!result.Cancelled) { await LoadConnectedChannelsAsync(); @@ -109,8 +109,9 @@ private async Task DeleteChannelAsync(ChannelModel channel) var channelName = channel.Name; var confirm = await dialogService.ShowConfirmationAsync( - "You are going to delete this channel. Are you sure?", - title: $"Delete channel {channelName}"); + localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmMessage)], + title: localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmTitle)], + primaryText: localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmPrimaryButtonText)]); var result = await confirm.Result; @@ -119,13 +120,13 @@ private async Task DeleteChannelAsync(ChannelModel channel) try { await client.DeleteConnectedChannelAsync(channel); - toastService.ShowSuccess($"{channelName} deleted successfully!"); + toastService.ShowSuccess(localizer[nameof(Resources.Pages.Settings.Channels.DeletedChannelSuccessMessage), channelName]); await LoadConnectedChannelsAsync(); } catch { - toastService.ShowError($"There was an error deleting channel {channelName}"); + toastService.ShowError(localizer[nameof(Resources.Pages.Settings.Channels.DeletedChannelErrorMessage), channelName]); } } } diff --git a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.Designer.cs b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.Designer.cs new file mode 100644 index 0000000..020de91 --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace KITT.Cms.Web.App.Resources.Components { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ChannelFormPanel { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ChannelFormPanel() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KITT.Cms.Web.App.Resources.Components.ChannelFormPanel", typeof(ChannelFormPanel).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Error saving the channel. + /// + public static string ChannelSavedErrorMessage { + get { + return ResourceManager.GetString("ChannelSavedErrorMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Channel saved correctly. + /// + public static string ChannelSavedSuccessMessage { + get { + return ResourceManager.GetString("ChannelSavedSuccessMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close. + /// + public static string CloseButtonText { + get { + return ResourceManager.GetString("CloseButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save. + /// + public static string SaveButtonText { + get { + return ResourceManager.GetString("SaveButtonText", resourceCulture); + } + } + } +} diff --git a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx new file mode 100644 index 0000000..6dd3a94 --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Errore durante il salvataggio del canale + + + Canale salvato correttamente + + + Chiudi + + + Salva + + \ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx new file mode 100644 index 0000000..29d87f4 --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Error saving the channel + + + Channel saved correctly + + + Close + + + Save + + \ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.Designer.cs b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.Designer.cs new file mode 100644 index 0000000..53295a0 --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.Designer.cs @@ -0,0 +1,171 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace KITT.Cms.Web.App.Resources.Pages.Settings { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Channels { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Channels() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KITT.Cms.Web.App.Resources.Pages.Settings.Channels", typeof(Channels).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Add new channel. + /// + public static string AddNewChannelButtonText { + get { + return ResourceManager.GetString("AddNewChannelButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add new channel. + /// + public static string AddNewChannelPanelTitle { + get { + return ResourceManager.GetString("AddNewChannelPanelTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete. + /// + public static string DeleteChannelButtonText { + get { + return ResourceManager.GetString("DeleteChannelButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are going to delete this channel. Are you sure?. + /// + public static string DeleteChannelConfirmMessage { + get { + return ResourceManager.GetString("DeleteChannelConfirmMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + public static string DeleteChannelConfirmPrimaryButtonText { + get { + return ResourceManager.GetString("DeleteChannelConfirmPrimaryButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete channel {0}. + /// + public static string DeleteChannelConfirmTitle { + get { + return ResourceManager.GetString("DeleteChannelConfirmTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error deleting channel {0}. + /// + public static string DeletedChannelErrorMessage { + get { + return ResourceManager.GetString("DeletedChannelErrorMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} deleted successfully!. + /// + public static string DeletedChannelSuccessMessage { + get { + return ResourceManager.GetString("DeletedChannelSuccessMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit. + /// + public static string EditChannelButtonText { + get { + return ResourceManager.GetString("EditChannelButtonText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit channel {0}. + /// + public static string EditChannelPanelTitle { + get { + return ResourceManager.GetString("EditChannelPanelTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connected channels. + /// + public static string PageTitle { + get { + return ResourceManager.GetString("PageTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Refresh. + /// + public static string RefreshChannelsButtonText { + get { + return ResourceManager.GetString("RefreshChannelsButtonText", resourceCulture); + } + } + } +} diff --git a/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.it.resx b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.it.resx new file mode 100644 index 0000000..4f470dd --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.it.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Nuovo canale + + + Nuovo canale + + + Cancella + + + Stai per cancellare questo canale. Sei sicuro? + + + Sì + + + Cancellazione canale {0} + + + Si è verificato un errore durante la cancellazione del canale {0} + + + {0} cancellato con successo! + + + Modifica + + + Modifica canale {0} + + + Canali collegati + + + Ricarica + + \ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.resx b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.resx new file mode 100644 index 0000000..22d9c4c --- /dev/null +++ b/src/KITT.Cms.Web.App/Resources/Pages/Settings/Channels.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Add new channel + + + Add new channel + + + Delete + + + You are going to delete this channel. Are you sure? + + + Yes + + + Delete channel {0} + + + There was an error deleting channel {0} + + + {0} deleted successfully! + + + Edit + + + Edit channel {0} + + + Connected channels + + + Refresh + + \ No newline at end of file diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor b/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor index d18ec32..2d5058f 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor +++ b/src/KITT.Web.App/KITT.Web.App.Client/Layout/NavMenu.razor @@ -1,4 +1,4 @@ -@inject IStringLocalizer Localizer +@inject IStringLocalizer localizer @@ -8,12 +8,12 @@ diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.Designer.cs b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.Designer.cs index 998bc40..07d305e 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.Designer.cs +++ b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.Designer.cs @@ -19,7 +19,7 @@ namespace KITT.Web.App.Client.Resources.Shared { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class NavMenu { @@ -87,6 +87,15 @@ public static string ProposalsMenuLabel { } } + /// + /// Looks up a localized string similar to Connected channels. + /// + public static string SettingsChannelsMenuLabel { + get { + return ResourceManager.GetString("SettingsChannelsMenuLabel", resourceCulture); + } + } + /// /// Looks up a localized string similar to Settings. /// diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.it.resx b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.it.resx index ba26043..08f8cf0 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.it.resx +++ b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.it.resx @@ -126,10 +126,13 @@ Proposte + + Canali collegati + Impostazioni Dirette - + \ No newline at end of file diff --git a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.resx b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.resx index 570bd06..7851d28 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.resx +++ b/src/KITT.Web.App/KITT.Web.App.Client/Resources/Shared/NavMenu.resx @@ -126,6 +126,9 @@ Proposals + + Connected channels + Settings From 7705a6df8b8b91c149f43ed8eec7271a7e4c870c Mon Sep 17 00:00:00 2001 From: albx Date: Fri, 16 Jan 2026 23:41:34 +0100 Subject: [PATCH 18/26] #124 - WIP new streaming form --- src/KITT.AppHost/KITT.AppHost.csproj | 4 +- .../Services/StreamingsEndpointsServices.cs | 2 +- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 2 +- .../Components/StreamingForm.razor | 104 ++++++++++++++++++ .../Components/StreamingForm.razor.cs | 78 +++++++++++++ src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 2 +- .../Pages/Streamings/Schedule.razor | 4 +- .../Pages/Streamings/Schedule.razor.cs | 8 +- .../Streamings/ScheduleStreamingModel.cs | 4 +- src/KITT.Core/KITT.Core.csproj | 6 +- .../KITT.Proposals.Web.Api.csproj | 2 +- .../KITT.Proposals.Web.App.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 4 +- .../KITT.Support.Seeder.csproj | 4 +- .../KITT.Telegram.Messages.csproj | 6 +- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 6 +- .../KITT.Web.App.Client.csproj | 2 +- .../KITT.Web.App/KITT.Web.App.csproj | 10 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 8 +- .../KITT.Cms.Web.Api.Test.csproj | 4 +- tests/KITT.Core.Test/KITT.Core.Test.csproj | 2 +- .../KITT.Web.Testing/KITT.Web.Testing.csproj | 2 +- 22 files changed, 225 insertions(+), 41 deletions(-) create mode 100644 src/KITT.Cms.Web.App/Components/StreamingForm.razor create mode 100644 src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 7c5d51a..28fae8f 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index a10f4b5..5d96fef 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -122,7 +122,7 @@ public Task ScheduleStreamingAsync(ScheduleStreamingModel model, string us model.ScheduleDate, model.StartingTime, model.EndingTime, - model.HostingChannelUrl, + model.TwitchUrl, model.StreamingAbstract, seo); } diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 96ef6fe..98a0561 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor b/src/KITT.Cms.Web.App/Components/StreamingForm.razor new file mode 100644 index 0000000..7bdf60f --- /dev/null +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs new file mode 100644 index 0000000..b22fc9b --- /dev/null +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs @@ -0,0 +1,78 @@ +using KITT.Cms.Web.App.Clients; +using KITT.Cms.Web.Models; +using KITT.Cms.Web.Models.Settings; +using Microsoft.AspNetCore.Components; +using System.ComponentModel.DataAnnotations; + +namespace KITT.Cms.Web.App.Components; + +public partial class StreamingForm( + IConnectedChannelsClient channelsClient) +{ + [Parameter] + public ViewModel Model { get; set; } = new(); + + [Parameter] + public EventCallback OnSave { get; set; } + + [Parameter] + public EventCallback OnCancel { get; set; } + + private ChannelModel[] availableTwitchChannels = []; + + private ChannelModel[] availableYouTubeChannels = []; + + protected override async Task OnInitializedAsync() + { + var channels = await channelsClient.GetConnectedChannelsAsync(); + + availableTwitchChannels = channels.Where(c => c.Type is Settings.Models.ChannelType.Twitch).ToArray(); + availableYouTubeChannels = channels.Where(c => c.Type is Settings.Models.ChannelType.YouTube).ToArray(); + } + + public class ViewModel : ContentViewModel, IValidatableObject + { + public string? TwitchChannel { get; set; } + + public string? YouTubeChannel { get; set; } + + [Required] + public string Title { get; set; } = string.Empty; + + [Required] + public string Slug { get; set; } = string.Empty; + + [Required] + public DateTime? ScheduleDate { get; set; } = DateTime.Now; + + [Required] + public DateTime? StartingTime { get; set; } = DateTime.Now; + + [Required] + public DateTime? EndingTime { get; set; } = DateTime.Now.AddHours(1); + + public string? TwitchUrl { get; set; } = string.Empty; + + public string? StreamingAbstract { get; set; } + + public string? YouTubeUrl { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(YouTubeChannel)) + { + yield return new("At least a channel must be selected", [nameof(TwitchChannel), nameof(YouTubeChannel)]); + } + + if (!string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(TwitchUrl)) + { + yield return new("Twitch URL is required since a Twitch channel has been set", [nameof(TwitchUrl)]); + } + + if (!string.IsNullOrWhiteSpace(YouTubeChannel) && string.IsNullOrWhiteSpace(YouTubeUrl)) + { + yield return new("YouTube URL is required since a YouTube channel has been set", [nameof(YouTubeUrl)]); + } + } + } +} diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index 3d68ccc..44e5eeb 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor index e415870..cb3e0f1 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor @@ -15,5 +15,5 @@ - + diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs index 54a9c24..7e4c6f9 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs @@ -24,9 +24,9 @@ public partial class Schedule [Inject] public IMessageService MessageService { get; set; } = default!; - private ScheduleForm.ViewModel model = new(); + private StreamingForm.ViewModel model = new(); - private async Task ScheduleStreamingAsync(ScheduleForm.ViewModel model) + private async Task ScheduleStreamingAsync(StreamingForm.ViewModel model) { try { @@ -47,7 +47,7 @@ await MessageService.ShowMessageBarAsync( } } - private static ScheduleStreamingModel ConvertToApiModel(ScheduleForm.ViewModel model) + private static ScheduleStreamingModel ConvertToApiModel(StreamingForm.ViewModel model) { ArgumentNullException.ThrowIfNull(model.ScheduleDate); ArgumentNullException.ThrowIfNull(model.StartingTime); @@ -58,7 +58,7 @@ private static ScheduleStreamingModel ConvertToApiModel(ScheduleForm.ViewModel m Title = model.Title, ScheduleDate = DateOnly.FromDateTime(model.ScheduleDate.Value), EndingTime = TimeOnly.FromTimeSpan(model.EndingTime.Value.TimeOfDay), - HostingChannelUrl = $"https://www.twitch.tv/{model.HostingChannelUrl}", + TwitchUrl = $"https://www.twitch.tv/{model.TwitchUrl}", Slug = model.Slug, StartingTime = TimeOnly.FromTimeSpan(model.StartingTime.Value.TimeOfDay), StreamingAbstract = model.StreamingAbstract, diff --git a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs index a393921..715cf5c 100644 --- a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs @@ -20,7 +20,9 @@ public record ScheduleStreamingModel public TimeOnly EndingTime { get; set; } [Required] - public string HostingChannelUrl { get; set; } = string.Empty; + public string TwitchUrl { get; set; } = string.Empty; + + public string YouTubeUrl { get; set; } = string.Empty; public string? StreamingAbstract { get; set; } diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 9698dcb..29ee91b 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -8,11 +8,11 @@ - + - - + + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index ee36356..055a7d8 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index 9527407..127f59a 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index eeb71e3..7f41dde 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index a8c098f..61f026d 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -10,11 +10,11 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index f5e6017..9374f55 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index c40a6a5..9d8ef78 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -13,11 +13,11 @@ - - + + - + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index e525f8d..b7c60bd 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index 78070b6..be8791f 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -16,11 +16,11 @@ - + - - - - + + + + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 1b2b6d8..c044504 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -8,10 +8,10 @@ - - - - + + + + diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index 07bb7ec..3a67c94 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -12,8 +12,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index d356dfe..a4a0653 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -14,7 +14,7 @@ - + diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index 42f5f9b..cc323d4 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -11,7 +11,7 @@ - + From 073ce23f54ebf97347c6f60e08be644f7c5a2ac6 Mon Sep 17 00:00:00 2001 From: albx Date: Tue, 27 Jan 2026 06:50:16 +0100 Subject: [PATCH 19/26] #124 - refactor schedule streaming endpoint --- .../Services/StreamingsEndpointsServices.cs | 13 +-- .../Components/StreamingForm.razor | 2 +- .../Components/StreamingForm.razor.cs | 16 ++-- .../Pages/Streamings/Schedule.razor.cs | 20 ++++- .../Streamings/ScheduleStreamingModel.cs | 25 +++++- src/KITT.Core/Commands/IStreamingCommands.cs | 14 ++- src/KITT.Core/Commands/ProposalCommands.cs | 37 ++++---- src/KITT.Core/Commands/StreamingCommands.cs | 73 ++++----------- src/KITT.Core/Models/Streaming.cs | 17 ++-- .../Validators/StreamingValidator.cs | 5 +- .../Commands/StreamingCommandsTest.cs | 88 ++++++------------- tests/KITT.Core.Test/Models/StreamingTests.cs | 78 ++++++++-------- 12 files changed, 176 insertions(+), 212 deletions(-) diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index 5d96fef..b054715 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -98,15 +98,6 @@ public Task ImportStreamingAsync(ImportStreamingModel model, string userId public Task ScheduleStreamingAsync(ScheduleStreamingModel model, string userId) { - var settings = Database.Settings - .ByUserId(userId) - .FirstOrDefault(); - - if (settings is null) - { - throw new InvalidOperationException("No settings configured"); - } - var seo = new Core.Models.Content.SeoData { Title = model.Seo.Title, @@ -116,13 +107,15 @@ public Task ScheduleStreamingAsync(ScheduleStreamingModel model, string us return Commands.ScheduleStreamingAsync( userId, - settings.TwitchChannel, + model.TwitchChannel, + model.YouTubeChannel, model.Title, model.Slug, model.ScheduleDate, model.StartingTime, model.EndingTime, model.TwitchUrl, + model.YouTubeUrl, model.StreamingAbstract, seo); } diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor b/src/KITT.Cms.Web.App/Components/StreamingForm.razor index 7bdf60f..6550d13 100644 --- a/src/KITT.Cms.Web.App/Components/StreamingForm.razor +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor @@ -22,7 +22,7 @@ Items="availableYouTubeChannels" Appearance="Appearance.Filled" Style="width:100%" - OptionValue="@(c => c.Name)" + OptionValue="@(c => c.Url)" OptionText="@(c => $"{c.Name} ({c.Url})")" @bind-Value="streaming.YouTubeChannel" /> diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs index b22fc9b..c502387 100644 --- a/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs @@ -18,23 +18,23 @@ public partial class StreamingForm( [Parameter] public EventCallback OnCancel { get; set; } - private ChannelModel[] availableTwitchChannels = []; + private ChannelModel?[] availableTwitchChannels = []; - private ChannelModel[] availableYouTubeChannels = []; + private ChannelModel?[] availableYouTubeChannels = []; protected override async Task OnInitializedAsync() { var channels = await channelsClient.GetConnectedChannelsAsync(); - availableTwitchChannels = channels.Where(c => c.Type is Settings.Models.ChannelType.Twitch).ToArray(); - availableYouTubeChannels = channels.Where(c => c.Type is Settings.Models.ChannelType.YouTube).ToArray(); + availableTwitchChannels = [null, ..channels.Where(c => c.Type is Settings.Models.ChannelType.Twitch).ToArray()]; + availableYouTubeChannels = [null, ..channels.Where(c => c.Type is Settings.Models.ChannelType.YouTube).ToArray()]; } public class ViewModel : ContentViewModel, IValidatableObject { - public string? TwitchChannel { get; set; } + public string TwitchChannel { get; set; } = string.Empty; - public string? YouTubeChannel { get; set; } + public string YouTubeChannel { get; set; } = string.Empty; [Required] public string Title { get; set; } = string.Empty; @@ -51,11 +51,11 @@ public class ViewModel : ContentViewModel, IValidatableObject [Required] public DateTime? EndingTime { get; set; } = DateTime.Now.AddHours(1); - public string? TwitchUrl { get; set; } = string.Empty; + public string TwitchUrl { get; set; } = string.Empty; public string? StreamingAbstract { get; set; } - public string? YouTubeUrl { get; set; } + public string YouTubeUrl { get; set; } = string.Empty; public IEnumerable Validate(ValidationContext validationContext) { diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs index 7e4c6f9..64cf9a4 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs @@ -49,16 +49,30 @@ await MessageService.ShowMessageBarAsync( private static ScheduleStreamingModel ConvertToApiModel(StreamingForm.ViewModel model) { - ArgumentNullException.ThrowIfNull(model.ScheduleDate); - ArgumentNullException.ThrowIfNull(model.StartingTime); - ArgumentNullException.ThrowIfNull(model.EndingTime); + if (!model.ScheduleDate.HasValue) + { + throw new ArgumentNullException(nameof(model.ScheduleDate)); + } + + if (!model.StartingTime.HasValue) + { + throw new ArgumentNullException(nameof(model.StartingTime)); + } + + if (!model.EndingTime.HasValue) + { + throw new ArgumentNullException(nameof(model.EndingTime)); + } return new ScheduleStreamingModel { Title = model.Title, + TwitchChannel = model.TwitchChannel, + YouTubeChannel = model.YouTubeChannel, ScheduleDate = DateOnly.FromDateTime(model.ScheduleDate.Value), EndingTime = TimeOnly.FromTimeSpan(model.EndingTime.Value.TimeOfDay), TwitchUrl = $"https://www.twitch.tv/{model.TwitchUrl}", + YouTubeUrl = model.YouTubeUrl, Slug = model.Slug, StartingTime = TimeOnly.FromTimeSpan(model.StartingTime.Value.TimeOfDay), StreamingAbstract = model.StreamingAbstract, diff --git a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs index 715cf5c..198310b 100644 --- a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs @@ -2,8 +2,12 @@ namespace KITT.Cms.Web.Models.Streamings; -public record ScheduleStreamingModel +public record ScheduleStreamingModel : IValidatableObject { + public string TwitchChannel { get; set; } = string.Empty; + + public string YouTubeChannel { get; set; } = string.Empty; + [Required] public string Title { get; set; } = string.Empty; @@ -19,7 +23,6 @@ public record ScheduleStreamingModel [Required] public TimeOnly EndingTime { get; set; } - [Required] public string TwitchUrl { get; set; } = string.Empty; public string YouTubeUrl { get; set; } = string.Empty; @@ -27,4 +30,22 @@ public record ScheduleStreamingModel public string? StreamingAbstract { get; set; } public SeoData Seo { get; set; } = new(); + + public IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(YouTubeChannel)) + { + yield return new("At least a channel must be selected", [nameof(TwitchChannel), nameof(YouTubeChannel)]); + } + + if (!string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(TwitchUrl)) + { + yield return new("Twitch URL is required since a Twitch channel has been set", [nameof(TwitchUrl)]); + } + + if (!string.IsNullOrWhiteSpace(YouTubeChannel) && string.IsNullOrWhiteSpace(YouTubeUrl)) + { + yield return new("YouTube URL is required since a YouTube channel has been set", [nameof(YouTubeUrl)]); + } + } } diff --git a/src/KITT.Core/Commands/IStreamingCommands.cs b/src/KITT.Core/Commands/IStreamingCommands.cs index 880bb50..5b041c1 100644 --- a/src/KITT.Core/Commands/IStreamingCommands.cs +++ b/src/KITT.Core/Commands/IStreamingCommands.cs @@ -2,7 +2,19 @@ public interface IStreamingCommands { - Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, Content.SeoData seo); + Task ScheduleStreamingAsync( + string userId, + string twitchChannel, + string youTubeChannel, + string streamingTitle, + string streamingSlug, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string youTubeUrl, + string? streamingAbstract, + Content.SeoData seo); Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string youtubeUrl, Content.SeoData seo); diff --git a/src/KITT.Core/Commands/ProposalCommands.cs b/src/KITT.Core/Commands/ProposalCommands.cs index 11369d6..1e63679 100644 --- a/src/KITT.Core/Commands/ProposalCommands.cs +++ b/src/KITT.Core/Commands/ProposalCommands.cs @@ -100,23 +100,24 @@ public Task ScheduleProposalAsync(Guid proposalId, string userId, string twitchC private void ScheduleStreaming(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string streamingAbstract, string hostingChannelUrl) { - var streaming = Streaming.Schedule( - streamingTitle, - streamingSlug, - twitchChannel, - scheduleDate, - startingTime, - endingTime, - hostingChannelUrl, - userId); - - if (!string.IsNullOrWhiteSpace(streamingAbstract)) - { - streaming.SetAbstract(streamingAbstract); - } - - _validator.ValidateForScheduleStreaming(streaming); - - _context.Streamings.Add(streaming); + throw new NotImplementedException(); + //var streaming = Streaming.Schedule( + // streamingTitle, + // streamingSlug, + // twitchChannel, + // scheduleDate, + // startingTime, + // endingTime, + // hostingChannelUrl, + // userId); + + //if (!string.IsNullOrWhiteSpace(streamingAbstract)) + //{ + // streaming.SetAbstract(streamingAbstract); + //} + + //_validator.ValidateForScheduleStreaming(streaming); + + //_context.Streamings.Add(streaming); } } diff --git a/src/KITT.Core/Commands/StreamingCommands.cs b/src/KITT.Core/Commands/StreamingCommands.cs index 2412c03..ad8a20c 100644 --- a/src/KITT.Core/Commands/StreamingCommands.cs +++ b/src/KITT.Core/Commands/StreamingCommands.cs @@ -1,6 +1,5 @@ using KITT.Core.Validators; using KITT.Telegram.Messages; -using KITT.Telegram.Messages.Streaming; namespace KITT.Core.Commands; @@ -10,25 +9,36 @@ public class StreamingCommands : IStreamingCommands private readonly StreamingValidator _validator; - private readonly IMessageBus _messageBus; - - public StreamingCommands(KittDbContext context, StreamingValidator validator, IMessageBus messageBus) + public StreamingCommands(KittDbContext context, StreamingValidator validator) { _context = context ?? throw new ArgumentNullException(nameof(context)); _validator = validator ?? throw new ArgumentNullException(nameof(validator)); - _messageBus = messageBus ?? throw new ArgumentNullException(nameof(messageBus)); } - public async Task ScheduleStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, Content.SeoData seo) + public async Task ScheduleStreamingAsync( + string userId, + string twitchChannel, + string youTubeChannel, + string streamingTitle, + string streamingSlug, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string youTubeUrl, + string? streamingAbstract, + Content.SeoData seo) { var streaming = Streaming.Schedule( streamingTitle, streamingSlug, twitchChannel, + youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, + youTubeUrl, userId); if (!string.IsNullOrWhiteSpace(streamingAbstract)) @@ -46,17 +56,6 @@ public async Task ScheduleStreamingAsync(string userId, string twitchChann _context.Streamings.Add(streaming); await _context.SaveChangesAsync(); - //var message = new StreamingScheduledMessage( - // streaming.Id, - // streamingTitle, - // streamingSlug, - // scheduleDate, - // startingTime, - // endingTime, - // hostingChannelUrl); - - //await _messageBus.SendAsync(message); - return streaming.Id; } @@ -78,30 +77,11 @@ public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, if (ScheduleHasChanged(streaming, scheduleDate, startingTime, endingTime)) { streaming.ChangeSchedule(scheduleDate, startingTime, endingTime); - //var scheduledChangedMessage = new StreamingScheduleChangedMessage( - // streamingId, - // streaming.Title, - // streaming.Slug, - // scheduleDate, - // startingTime, - // endingTime); - - //messagesToSend.Add(scheduledChangedMessage); } if (streaming.TwitchUrl != twitchUrl) { streaming.SetTwitchUrl(twitchUrl); - - //var hostingChannelChangedMessage = new StreamingHostingChannelChangedMessage( - // streamingId, - // streaming.Title, - // streaming.Slug, - // hostingChannelUrl, - // scheduleDate, - // startingTime); - - //messagesToSend.Add(hostingChannelChangedMessage); } if (streaming.Abstract != streamingAbstract) @@ -112,13 +92,6 @@ public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, if (streaming.YouTubeUrl != youtubeUrl) { streaming.SetYoutubeUrl(youtubeUrl); - //var videoUploadedMessage = new StreamingVideoUploadedMessage( - // streamingId, - // streaming.Title, - // streaming.Slug, - // youtubeRegistrationLink); - - //messagesToSend.Add(videoUploadedMessage); } if (seo is not null) @@ -129,11 +102,6 @@ public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, _validator.ValidateForUpdateStreaming(streaming); await _context.SaveChangesAsync(); - - //foreach (var message in messagesToSend) - //{ - // await _messageBus.SendAsync(message); - //} } public async Task DeleteStreamingAsync(Guid streamingId) @@ -146,15 +114,6 @@ public async Task DeleteStreamingAsync(Guid streamingId) _context.Streamings.Remove(streaming); await _context.SaveChangesAsync(); - - //var message = new StreamingCanceledMessage( - // streamingId, - // streaming.Title, - // streaming.ScheduleDate, - // streaming.StartingTime, - // streaming.EndingTime); - - //await _messageBus.SendAsync(message); } public async Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string? youtubeUrl, Content.SeoData seo) diff --git a/src/KITT.Core/Models/Streaming.cs b/src/KITT.Core/Models/Streaming.cs index 7c754ed..facbb6c 100644 --- a/src/KITT.Core/Models/Streaming.cs +++ b/src/KITT.Core/Models/Streaming.cs @@ -45,7 +45,7 @@ public void SetTwitchUrl(string twitchUrl) #endregion #region Factory - public static Streaming Schedule(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string userId) + public static Streaming Schedule(string title, string slug, string twitchChannel, string youTubeChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string youTubeUrl, string userId) { if (string.IsNullOrWhiteSpace(title)) { @@ -57,11 +57,6 @@ public static Streaming Schedule(string title, string slug, string twitchChannel throw new ArgumentException("value cannot be empty", nameof(slug)); } - if (string.IsNullOrWhiteSpace(twitchChannel)) - { - throw new ArgumentException("value cannot be empty", nameof(twitchChannel)); - } - if (scheduleDate < DateOnly.FromDateTime(DateTime.Today)) { throw new ArgumentException("Schedule date cannot be set in the past", nameof(scheduleDate)); @@ -72,7 +67,11 @@ public static Streaming Schedule(string title, string slug, string twitchChannel throw new ArgumentException("Starting time should be previuos than ending time", nameof(endingTime)); } - if (string.IsNullOrWhiteSpace(twitchUrl)) + if (!string.IsNullOrWhiteSpace(twitchChannel) && string.IsNullOrWhiteSpace(twitchUrl)) + { + throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); + } + if (!string.IsNullOrWhiteSpace(youTubeChannel) && string.IsNullOrWhiteSpace(youTubeUrl)) { throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); } @@ -89,10 +88,12 @@ public static Streaming Schedule(string title, string slug, string twitchChannel Title = title, Slug = slug, TwitchChannel = twitchChannel, + YouTubeChannel = youTubeChannel, ScheduleDate = scheduleDate, StartingTime = startingTime, EndingTime = endingTime, - TwitchUrl = twitchUrl + TwitchUrl = twitchUrl, + YouTubeUrl = youTubeUrl, }; streaming.Publish(); diff --git a/src/KITT.Core/Validators/StreamingValidator.cs b/src/KITT.Core/Validators/StreamingValidator.cs index 4f33643..7f4a8f8 100644 --- a/src/KITT.Core/Validators/StreamingValidator.cs +++ b/src/KITT.Core/Validators/StreamingValidator.cs @@ -27,11 +27,10 @@ public void ValidateForUpdateStreaming(Streaming streaming) => this.Validate(str private void DefineRules() { - RuleFor(streaming => streaming.TwitchChannel).MaximumLength(50).NotEmpty(); RuleFor(streaming => streaming.Title).MaximumLength(255).NotEmpty(); RuleFor(streaming => streaming.Slug).MaximumLength(255).NotEmpty(); - RuleFor(streaming => streaming.TwitchUrl).NotEmpty().MaximumLength(255); - RuleFor(streaming => streaming.YouTubeUrl).MaximumLength(255); + RuleFor(streaming => streaming.TwitchUrl).NotEmpty().When(streaming => !string.IsNullOrWhiteSpace(streaming.TwitchChannel)).MaximumLength(255); + RuleFor(streaming => streaming.YouTubeUrl).NotEmpty().When(streaming => !string.IsNullOrWhiteSpace(streaming.YouTubeChannel)).MaximumLength(255); RuleSet(ScheduleStreamingAction, () => { diff --git a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs index 753146b..07d0d9f 100644 --- a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs +++ b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs @@ -26,9 +26,8 @@ public void Ctor_Should_Throw_ArgumentNullException_If_Context_Is_Null() { KittDbContext context = null; var validator = new StreamingValidator(_fixture.Context); - var messageBus = new Mock().Object; - - var ex = Assert.Throws(() => new StreamingCommands(context, validator, messageBus)); + + var ex = Assert.Throws(() => new StreamingCommands(context, validator)); Assert.Equal(nameof(context), ex.ParamName); } @@ -37,9 +36,8 @@ public void Ctor_Should_Throw_ArgumentNullException_If_Validator_Is_Null() { KittDbContext context = _fixture.Context; StreamingValidator validator = null; - var messageBus = new Mock().Object; - - var ex = Assert.Throws(() => new StreamingCommands(context, validator, messageBus)); + + var ex = Assert.Throws(() => new StreamingCommands(context, validator)); Assert.Equal(nameof(validator), ex.ParamName); } #endregion @@ -55,10 +53,12 @@ public async Task ScheduleStreamingAsync_Should_Throw_ValidationException_If_Str "test1", "test-slug", "albx87", + "@albx87", DateOnly.FromDateTime(DateTime.Today.AddDays(1)), TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)), TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)), "https://www.twitch.tv/albx87", + "https://www.youtube.com/@albx87", userId); context.Add(streaming); @@ -66,16 +66,17 @@ public async Task ScheduleStreamingAsync_Should_Throw_ValidationException_If_Str }); var validator = new StreamingValidator(_fixture.Context); - var messageBus = new Mock().Object; - var commands = new StreamingCommands(_fixture.Context, validator, messageBus); + var commands = new StreamingCommands(_fixture.Context, validator); string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; string streamingTitle = "test"; string streamingSlug = "test-slug"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today.AddDays(2)); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(19)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(20)); - string hostingChannelUrl = "https://www.twitch.tv/albx87"; + string twitchUrl = "https://www.twitch.tv/albx87"; + string youTubeUrl = "https://www.youtube.com/@albx87"; string streamingAbstract = "streaming abstract"; var seo = new Content.SeoData(); @@ -83,12 +84,14 @@ public async Task ScheduleStreamingAsync_Should_Throw_ValidationException_If_Str () => commands.ScheduleStreamingAsync( userId, twitchChannel, + youTubeChannel, streamingTitle, streamingSlug, scheduleDate, startingTime, endingTime, - hostingChannelUrl, + twitchUrl, + youTubeUrl, streamingAbstract, seo)); @@ -99,29 +102,32 @@ public async Task ScheduleStreamingAsync_Should_Throw_ValidationException_If_Str public async Task ScheduleStreamingAsync_Should_Add_Streaming_With_Specified_Values() { var validator = new StreamingValidator(_fixture.Context); - var messageBus = new Mock().Object; - var commands = new StreamingCommands(_fixture.Context, validator, messageBus); + var commands = new StreamingCommands(_fixture.Context, validator); string userId = Guid.NewGuid().ToString(); string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; string streamingTitle = "test"; string streamingSlug = "test-schedule-streaming-slug"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "https://www.twitch.tv/albx87"; + string twitchUrl = "https://www.twitch.tv/albx87"; + string youTubeUrl = "https://www.twitch.tv/@albx87"; string streamingAbstract = "streaming abstract"; var seo = new Content.SeoData(); var scheduledStreamingId = await commands.ScheduleStreamingAsync( userId, twitchChannel, + youTubeChannel, streamingTitle, streamingSlug, scheduleDate, startingTime, endingTime, - hostingChannelUrl, + twitchUrl, + youTubeUrl, streamingAbstract, seo); @@ -134,53 +140,9 @@ public async Task ScheduleStreamingAsync_Should_Add_Streaming_With_Specified_Val Assert.Equal(scheduleDate, scheduledStreaming.ScheduleDate); Assert.Equal(startingTime, scheduledStreaming.StartingTime); Assert.Equal(endingTime, scheduledStreaming.EndingTime); - Assert.Equal(hostingChannelUrl, scheduledStreaming.TwitchUrl); + Assert.Equal(twitchUrl, scheduledStreaming.TwitchUrl); Assert.Equal(streamingAbstract, scheduledStreaming.Abstract); } - - [Fact(Skip = "At this moment the message bus has been disabled")] - public async Task ScheduleStreamingAsync_Should_Send_ScheduledStreamingMessage_Correctly() - { - var messageBusMock = new Mock(); - - var validator = new StreamingValidator(_fixture.Context); - var messageBus = messageBusMock.Object; - var commands = new StreamingCommands(_fixture.Context, validator, messageBus); - - string userId = Guid.NewGuid().ToString(); - string twitchChannel = "albx87"; - string streamingTitle = "test"; - string streamingSlug = "test-message-slug"; - DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); - TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); - TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "https://www.twitch.tv/albx87"; - string streamingAbstract = "streaming abstract"; - var seo = new Content.SeoData(); - - var scheduledStreamingId = await commands.ScheduleStreamingAsync( - userId, - twitchChannel, - streamingTitle, - streamingSlug, - scheduleDate, - startingTime, - endingTime, - hostingChannelUrl, - streamingAbstract, - seo); - - var expectedMessage = new StreamingScheduledMessage( - scheduledStreamingId, - streamingTitle, - streamingSlug, - scheduleDate, - startingTime, - endingTime, - hostingChannelUrl); - - messageBusMock.Verify(m => m.SendAsync(expectedMessage), Times.Once); - } #endregion #region UpdateStreamingAsync tests @@ -190,8 +152,7 @@ public async Task UpdateStreamingAsync_Should_Update_Streaming_Information_Corre var streamingId = Guid.Empty; var validator = new StreamingValidator(_fixture.Context); - var messageBus = new Mock().Object; - var commands = new StreamingCommands(_fixture.Context, validator, messageBus); + var commands = new StreamingCommands(_fixture.Context, validator); _fixture.PrepareData(context => { @@ -200,10 +161,12 @@ public async Task UpdateStreamingAsync_Should_Update_Streaming_Information_Corre "title", "slug", "albx87", + "@albx87", DateOnly.FromDateTime(DateTime.Today), TimeOnly.FromTimeSpan(TimeSpan.FromHours(19)), TimeOnly.FromTimeSpan(TimeSpan.FromHours(20)), "https://www.twitch.tv/albx87", + "https://www.youtube.com/@albx87", userId); context.Add(newStreaming); @@ -252,8 +215,7 @@ public async Task UpdateStreamingAsync_Should_Not_Update_Schedule_If_It_Is_Not_C var endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(20)); var validator = new StreamingValidator(_fixture.Context); - var messageBus = new Mock().Object; - var commands = new StreamingCommands(_fixture.Context, validator, messageBus); + var commands = new StreamingCommands(_fixture.Context, validator); _fixture.PrepareData(context => { diff --git a/tests/KITT.Core.Test/Models/StreamingTests.cs b/tests/KITT.Core.Test/Models/StreamingTests.cs index c6a22d7..b5485c9 100644 --- a/tests/KITT.Core.Test/Models/StreamingTests.cs +++ b/tests/KITT.Core.Test/Models/StreamingTests.cs @@ -14,14 +14,16 @@ public void Schedule_Should_Throw_ArgumentException_If_Title_Is_Empty(string tit { string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); Assert.Equal(nameof(title), ex.ParamName); } @@ -34,52 +36,36 @@ public void Schedule_Should_Throw_ArgumentException_If_Slug_Is_Empty(string slug { string title = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); Assert.Equal(nameof(slug), ex.ParamName); } - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - public void Schedule_Should_Throw_ArgumentException_If_Twitch_Channel_Is_Empty(string twitchChannel) - { - string title = "test"; - string slug = "test"; - DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); - TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); - TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; - string userId = Guid.NewGuid().ToString(); - - var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); - - Assert.Equal(nameof(twitchChannel), ex.ParamName); - } - [Fact] public void Schedule_Should_Throw_ArgumentException_If_Schedule_Date_Is_Past_Date() { string title = "test"; string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today.AddDays(-1)); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); Assert.Equal(nameof(scheduleDate), ex.ParamName); } @@ -90,14 +76,16 @@ public void Schedule_Should_Throw_ArgumentException_If_Ending_Time_Is_Previous_T string title = "test"; string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(15)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); Assert.Equal(nameof(endingTime), ex.ParamName); } @@ -106,20 +94,22 @@ public void Schedule_Should_Throw_ArgumentException_If_Ending_Time_Is_Previous_T [InlineData(null)] [InlineData("")] [InlineData(" ")] - public void Schedule_Should_Throw_ArgumentException_If_Hosting_Channel_Url_Is_Empty(string hostingChannelUrl) + public void Schedule_Should_Throw_ArgumentException_If_Twitch_Url_Is_Empty(string twitchUrl) { string title = "test"; string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); - Assert.Equal(nameof(hostingChannelUrl), ex.ParamName); + Assert.Equal(nameof(twitchUrl), ex.ParamName); } [Theory] @@ -131,13 +121,15 @@ public void Schedule_Should_Throw_ArgumentException_If_UserId_Is_Empty(string us string title = "test"; string slug = "test"; string twitchChannel = "albx87"; - string hostingChannelUrl = "albx87"; + string youTubeChannel = "@albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); var ex = Assert.Throws( - () => Streaming.Schedule(title, slug, twitchChannel, scheduleDate, startingTime, endingTime, hostingChannelUrl, userId)); + () => Streaming.Schedule(title, slug, twitchChannel, youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, youTubeUrl, userId)); Assert.Equal(nameof(userId), ex.ParamName); } @@ -148,29 +140,35 @@ public void Schedule_Should_Create_A_New_Streaming_With_Specified_Values() string title = "test"; string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; string userId = Guid.NewGuid().ToString(); var streaming = Streaming.Schedule( title, slug, twitchChannel, + youTubeChannel, scheduleDate, startingTime, endingTime, - hostingChannelUrl, + twitchUrl, + youTubeUrl, userId); Assert.Equal(title, streaming.Title); Assert.Equal(slug, streaming.Slug); Assert.Equal(twitchChannel, streaming.TwitchChannel); + Assert.Equal(youTubeChannel, streaming.YouTubeChannel); Assert.Equal(scheduleDate, streaming.ScheduleDate); Assert.Equal(startingTime, streaming.StartingTime); Assert.Equal(endingTime, streaming.EndingTime); - Assert.Equal(hostingChannelUrl, streaming.TwitchUrl); + Assert.Equal(twitchUrl, streaming.TwitchUrl); + Assert.Equal(youTubeUrl, streaming.YouTubeUrl); Assert.NotEqual(Guid.Empty, streaming.Id); Assert.Equal(userId, streaming.UserId); } @@ -260,19 +258,23 @@ private Streaming CreateStreamingForTests() string title = "test"; string slug = "test"; string twitchChannel = "albx87"; + string youTubeChannel = "@albx87"; DateOnly scheduleDate = DateOnly.FromDateTime(DateTime.Today); TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); - string hostingChannelUrl = "albx87"; + string twitchUrl = "albx87"; + string youTubeUrl = "@albx87"; var streaming = Streaming.Schedule( title, slug, twitchChannel, + youTubeChannel, scheduleDate, startingTime, endingTime, - hostingChannelUrl, + twitchUrl, + youTubeUrl, userId); return streaming; From 069deadbb456555aaff815d6c7764c48896ac691 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 31 Jan 2026 18:49:36 +0100 Subject: [PATCH 20/26] #124 - fix import streaming --- .../Services/StreamingsEndpointsServices.cs | 22 ++-- .../Components/StreamingForm.razor | 6 +- .../Components/StreamingForm.razor.cs | 10 -- .../Pages/Streamings/Import.razor | 85 +------------- .../Pages/Streamings/Import.razor.cs | 110 ++++++------------ .../Pages/Streamings/Schedule.razor | 3 +- .../Pages/Streamings/Schedule.razor.cs | 33 ++---- .../Pages/Streamings/StreamingDetail.razor.cs | 22 ++-- .../Streamings/ImportStreamingModel.cs | 34 ++++-- .../Streamings/ScheduleStreamingModel.cs | 10 -- src/KITT.Core/Commands/IStreamingCommands.cs | 25 +++- src/KITT.Core/Commands/StreamingCommands.cs | 17 ++- src/KITT.Core/Models/Streaming.cs | 25 ++-- .../Validators/StreamingValidator.cs | 2 - .../Commands/StreamingCommandsTest.cs | 1 + 15 files changed, 147 insertions(+), 258 deletions(-) diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index b054715..7158889 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -66,15 +66,6 @@ public async Task GetAllStreamingsAsync(string userId, int public Task ImportStreamingAsync(ImportStreamingModel model, string userId) { - var settings = Database.Settings - .ByUserId(userId) - .FirstOrDefault(); - - if (settings is null) - { - throw new InvalidOperationException("No settings configured"); - } - var seo = new Core.Models.Content.SeoData { Title = model.Seo.Title, @@ -84,15 +75,16 @@ public Task ImportStreamingAsync(ImportStreamingModel model, string userId return Commands.ImportStreamingAsync( userId, - settings.TwitchChannel, + model.TwitchChannel, + model.YouTubeChannel, model.Title, model.Slug, - DateOnly.FromDateTime(model.ScheduleDate), - TimeOnly.FromTimeSpan(model.StartingTime), - TimeOnly.FromTimeSpan(model.EndingTime), - model.HostingChannelUrl, + model.ScheduleDate, + model.StartingTime, + model.EndingTime, + model.TwitchUrl, model.StreamingAbstract, - model.YoutubeVideoUrl, + model.YouTubeUrl, seo); } diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor b/src/KITT.Cms.Web.App/Components/StreamingForm.razor index 6550d13..126ab79 100644 --- a/src/KITT.Cms.Web.App/Components/StreamingForm.razor +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor @@ -11,7 +11,7 @@ Items="availableTwitchChannels" Appearance="Appearance.Filled" Style="width:100%" - OptionValue="@(c => c.Name)" + OptionValue="@(c => c.Url)" OptionText="@(c => $"{c.Name} ({c.Url})")" @bind-Value="streaming.TwitchChannel"/> @@ -52,14 +52,14 @@ + Style="width:100%;"/> + Style="width:100%;"/> diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs index c502387..63e2a33 100644 --- a/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor.cs @@ -63,16 +63,6 @@ public IEnumerable Validate(ValidationContext validationContex { yield return new("At least a channel must be selected", [nameof(TwitchChannel), nameof(YouTubeChannel)]); } - - if (!string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(TwitchUrl)) - { - yield return new("Twitch URL is required since a Twitch channel has been set", [nameof(TwitchUrl)]); - } - - if (!string.IsNullOrWhiteSpace(YouTubeChannel) && string.IsNullOrWhiteSpace(YouTubeUrl)) - { - yield return new("YouTube URL is required since a YouTube channel has been set", [nameof(YouTubeUrl)]); - } } } } diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor b/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor index c7cf0f7..9642353 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor @@ -15,85 +15,6 @@ - - - - - - - - - - - - - - - - - https://www.twitch.tv/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor.cs index 70faf10..705f480 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Import.razor.cs @@ -1,44 +1,33 @@ using KITT.Cms.Web.App.Clients; -using KITT.Cms.Web.Models; +using KITT.Cms.Web.App.Components; using KITT.Cms.Web.Models.Streamings; using KITT.Web.App.UI; using Microsoft.AspNetCore.Components; using Microsoft.FluentUI.AspNetCore.Components; -using System.ComponentModel.DataAnnotations; namespace KITT.Cms.Web.App.Pages.Streamings; -public partial class Import +public partial class Import( + IStreamingsClient client, + NavigationManager navigation, + IToastService toastService, + IMessageService messageService) { - [Inject] - public IStreamingsClient Client { get; set; } = default!; + private StreamingForm.ViewModel model = new(); - [Inject] - public NavigationManager Navigation { get; set; } = default!; - - [Inject] - public IToastService ToastService { get; set; } = default!; - - [Inject] - public IMessageService MessageService { get; set; } = default!; - - private ViewModel model = new(); - - private string errorMessage = string.Empty; - - private async Task ImportStreamingAsync(ViewModel model) + private async Task ImportStreamingAsync(StreamingForm.ViewModel model) { try { - await Client.ImportStreamingAsync(model.ToApiModel()); - ToastService.ShowSuccess( + await client.ImportStreamingAsync(ConvertToApiModel(model)); + toastService.ShowSuccess( Localizer[nameof(Resources.Pages.Streamings.Import.StreamingImportedSuccessfully), model.Title]); - Navigation.NavigateTo("/streamings"); + navigation.NavigateTo("/streamings"); } catch (ApplicationException ex) { - await MessageService.ShowMessageBarAsync( + await messageService.ShowMessageBarAsync( ex.Message, MessageIntent.Error, SectionNames.MessagesTopSectionName); @@ -47,59 +36,36 @@ await MessageService.ShowMessageBarAsync( void Cancel() => model = new(); - class ViewModel : ContentViewModel + private static ImportStreamingModel ConvertToApiModel(StreamingForm.ViewModel model) { - [Required] - public string Title { get; set; } = string.Empty; - - [Required] - public string Slug { get; set; } = string.Empty; - - [Required] - public DateTime? ScheduleDate { get; set; } = DateTime.Now; - - [Required] - public DateTime? StartingTime { get; set; } = DateTime.Now; - - [Required] - public DateTime? EndingTime { get; set; } = DateTime.Now.AddHours(1); - - [Required] - public string HostingChannelUrl { get; set; } = string.Empty; - - public string? StreamingAbstract { get; set; } - - public string? YoutubeVideoUrl { get; set; } - - public ImportStreamingModel ToApiModel() + if (!model.ScheduleDate.HasValue) { - if (this.ScheduleDate is null) - { - throw new ArgumentNullException(nameof(ScheduleDate)); - } - - if (this.StartingTime is null) - { - throw new ArgumentNullException(nameof(this.StartingTime)); - } + throw new ArgumentNullException(nameof(model.ScheduleDate)); + } - if (this.EndingTime is null) - { - throw new ArgumentNullException(nameof(this.EndingTime)); - } + if (!model.StartingTime.HasValue) + { + throw new ArgumentNullException(nameof(model.StartingTime)); + } - return new() - { - Title = this.Title, - ScheduleDate = this.ScheduleDate.Value, - EndingTime = this.EndingTime.Value.TimeOfDay, - HostingChannelUrl = $"https://www.twitch.tv/{this.HostingChannelUrl}", - Slug = this.Slug, - StartingTime = this.StartingTime.Value.TimeOfDay, - StreamingAbstract = this.StreamingAbstract, - YoutubeVideoUrl = this.YoutubeVideoUrl, - Seo = this.Seo - }; + if (!model.EndingTime.HasValue) + { + throw new ArgumentNullException(nameof(model.EndingTime)); } + + return new ImportStreamingModel + { + Title = model.Title, + TwitchChannel = model.TwitchChannel, + YouTubeChannel = model.YouTubeChannel, + ScheduleDate = DateOnly.FromDateTime(model.ScheduleDate.Value), + EndingTime = TimeOnly.FromTimeSpan(model.EndingTime.Value.TimeOfDay), + TwitchUrl = model.TwitchUrl, + YouTubeUrl = model.YouTubeUrl, + Slug = model.Slug, + StartingTime = TimeOnly.FromTimeSpan(model.StartingTime.Value.TimeOfDay), + StreamingAbstract = model.StreamingAbstract, + Seo = model.Seo + }; } } diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor index cb3e0f1..d250928 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor @@ -16,4 +16,5 @@ + OnSave="ScheduleStreamingAsync" + OnCancel="Cancel"/> diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs index 64cf9a4..ada0829 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/Schedule.razor.cs @@ -7,23 +7,12 @@ namespace KITT.Cms.Web.App.Pages.Streamings; -public partial class Schedule +public partial class Schedule( + IStreamingsClient client, + NavigationManager navigation, + IToastService toastService, + IMessageService messageService) { - [Inject] - public IStreamingsClient Client { get; set; } = default!; - - [Inject] - public NavigationManager Navigation { get; set; } = default!; - - [Inject] - public IToastService ToastService { get; set; } = default!; - - [Inject] - public IDialogService DialogService { get; set; } = default!; - - [Inject] - public IMessageService MessageService { get; set; } = default!; - private StreamingForm.ViewModel model = new(); private async Task ScheduleStreamingAsync(StreamingForm.ViewModel model) @@ -31,22 +20,24 @@ private async Task ScheduleStreamingAsync(StreamingForm.ViewModel model) try { var scheduleStreamingModel = ConvertToApiModel(model); - await Client.ScheduleStreamingAsync(scheduleStreamingModel); + await client.ScheduleStreamingAsync(scheduleStreamingModel); - ToastService.ShowSuccess( + toastService.ShowSuccess( Localizer[nameof(Resources.Pages.Streamings.Schedule.StreamingScheduledSuccessfully), model.Title]); - Navigation.NavigateTo("/streamings"); + navigation.NavigateTo("/streamings"); } catch (ApplicationException ex) { - await MessageService.ShowMessageBarAsync( + await messageService.ShowMessageBarAsync( ex.Message, MessageIntent.Error, SectionNames.MessagesTopSectionName); } } + private void Cancel() => model = new(); + private static ScheduleStreamingModel ConvertToApiModel(StreamingForm.ViewModel model) { if (!model.ScheduleDate.HasValue) @@ -71,7 +62,7 @@ private static ScheduleStreamingModel ConvertToApiModel(StreamingForm.ViewModel YouTubeChannel = model.YouTubeChannel, ScheduleDate = DateOnly.FromDateTime(model.ScheduleDate.Value), EndingTime = TimeOnly.FromTimeSpan(model.EndingTime.Value.TimeOfDay), - TwitchUrl = $"https://www.twitch.tv/{model.TwitchUrl}", + TwitchUrl = model.TwitchUrl, YouTubeUrl = model.YouTubeUrl, Slug = model.Slug, StartingTime = TimeOnly.FromTimeSpan(model.StartingTime.Value.TimeOfDay), diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs index d370861..f499f03 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs @@ -9,21 +9,15 @@ namespace KITT.Cms.Web.App.Pages.Streamings; -public partial class StreamingDetail +public partial class StreamingDetail( + IStreamingsClient client, + IToastService toastService, + IMessageService messageService) { [Parameter] [EditorRequired] public Guid Id { get; set; } - [Inject] - public IStreamingsClient Client { get; set; } = default!; - - [Inject] - public IToastService ToastService { get; set; } = default!; - - [Inject] - public IMessageService MessageService { get; set; } = default!; - private bool isReadOnly = true; private ViewModel model = new(); @@ -47,16 +41,16 @@ private async Task EditStreamingAsync(ViewModel model) try { var detail = model.ToApiModel(Id); - await Client.UpdateStreamingAsync(detail); + await client.UpdateStreamingAsync(detail); isReadOnly = true; - ToastService.ShowSuccess(Localizer[nameof(Resources.Pages.Streamings.StreamingDetail.StreamingSavedSuccessfully)]); + toastService.ShowSuccess(Localizer[nameof(Resources.Pages.Streamings.StreamingDetail.StreamingSavedSuccessfully)]); streamingDetail = detail; } catch (ApplicationException ex) { - await MessageService.ShowMessageBarAsync( + await messageService.ShowMessageBarAsync( ex.Message, MessageIntent.Error, SectionNames.MessagesTopSectionName); @@ -65,7 +59,7 @@ await MessageService.ShowMessageBarAsync( protected override async Task OnInitializedAsync() { - streamingDetail = await Client.GetStreamingDetailAsync(Id) ?? new(); + streamingDetail = await client.GetStreamingDetailAsync(Id) ?? new(); model = ViewModel.FromStreamingDetailModel(streamingDetail); pageTitle = model.Title; diff --git a/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs b/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs index cd54620..8fe4671 100644 --- a/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs @@ -4,6 +4,10 @@ namespace KITT.Cms.Web.Models.Streamings; public record ImportStreamingModel { + public string TwitchChannel { get; set; } = string.Empty; + + public string YouTubeChannel { get; set; } = string.Empty; + [Required] public string Title { get; set; } = string.Empty; @@ -11,20 +15,36 @@ public record ImportStreamingModel public string Slug { get; set; } = string.Empty; [Required] - public DateTime ScheduleDate { get; set; } = DateTime.Now; + public DateOnly ScheduleDate { get; set; } = DateOnly.FromDateTime(DateTime.Today); [Required] - public TimeSpan StartingTime { get; set; } + public TimeOnly StartingTime { get; set; } [Required] - public TimeSpan EndingTime { get; set; } + public TimeOnly EndingTime { get; set; } - [Required] - public string HostingChannelUrl { get; set; } = string.Empty; + public string TwitchUrl { get; set; } = string.Empty; - public string? StreamingAbstract { get; set; } + public string YouTubeUrl { get; set; } = string.Empty; - public string? YoutubeVideoUrl { get; set; } + public string? StreamingAbstract { get; set; } public SeoData Seo { get; set; } = new(); + + public IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(YouTubeChannel)) + { + yield return new("At least a channel must be selected", [nameof(TwitchChannel), nameof(YouTubeChannel)]); + } + + if (!string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(TwitchUrl)) + { + yield return new("A Twitch URL is required since a Twitch channel has been selected", [nameof(TwitchUrl)]); + } + if (!string.IsNullOrWhiteSpace(YouTubeChannel) && string.IsNullOrWhiteSpace(YouTubeUrl)) + { + yield return new("A YouTube URL is required since a YouTube channel has been selected", [nameof(YouTubeUrl)]); + } + } } diff --git a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs index 198310b..ceffbbc 100644 --- a/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/ScheduleStreamingModel.cs @@ -37,15 +37,5 @@ public IEnumerable Validate(ValidationContext validationContex { yield return new("At least a channel must be selected", [nameof(TwitchChannel), nameof(YouTubeChannel)]); } - - if (!string.IsNullOrWhiteSpace(TwitchChannel) && string.IsNullOrWhiteSpace(TwitchUrl)) - { - yield return new("Twitch URL is required since a Twitch channel has been set", [nameof(TwitchUrl)]); - } - - if (!string.IsNullOrWhiteSpace(YouTubeChannel) && string.IsNullOrWhiteSpace(YouTubeUrl)) - { - yield return new("YouTube URL is required since a YouTube channel has been set", [nameof(YouTubeUrl)]); - } } } diff --git a/src/KITT.Core/Commands/IStreamingCommands.cs b/src/KITT.Core/Commands/IStreamingCommands.cs index 5b041c1..9742190 100644 --- a/src/KITT.Core/Commands/IStreamingCommands.cs +++ b/src/KITT.Core/Commands/IStreamingCommands.cs @@ -16,9 +16,30 @@ Task ScheduleStreamingAsync( string? streamingAbstract, Content.SeoData seo); - Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string youtubeUrl, Content.SeoData seo); + Task UpdateStreamingAsync( + Guid streamingId, + string streamingTitle, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string? streamingAbstract, + string youtubeUrl, + Content.SeoData seo); Task DeleteStreamingAsync(Guid streamingId); - Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string? youtubeUrl, Content.SeoData seo); + Task ImportStreamingAsync( + string userId, + string twitchChannel, + string youTubeChannel, + string streamingTitle, + string streamingSlug, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string? streamingAbstract, + string? youTubeUrl, + Content.SeoData seo); } diff --git a/src/KITT.Core/Commands/StreamingCommands.cs b/src/KITT.Core/Commands/StreamingCommands.cs index ad8a20c..cefef14 100644 --- a/src/KITT.Core/Commands/StreamingCommands.cs +++ b/src/KITT.Core/Commands/StreamingCommands.cs @@ -116,17 +116,30 @@ public async Task DeleteStreamingAsync(Guid streamingId) await _context.SaveChangesAsync(); } - public async Task ImportStreamingAsync(string userId, string twitchChannel, string streamingTitle, string streamingSlug, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string? youtubeUrl, Content.SeoData seo) + public async Task ImportStreamingAsync( + string userId, + string twitchChannel, + string youTubeChannel, + string streamingTitle, + string streamingSlug, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string? streamingAbstract, + string? youTubeUrl, + Content.SeoData seo) { var streaming = Streaming.Import( streamingTitle, streamingSlug, twitchChannel, + youTubeChannel, scheduleDate, startingTime, endingTime, twitchUrl, - youtubeUrl, + youTubeUrl, streamingAbstract, userId); diff --git a/src/KITT.Core/Models/Streaming.cs b/src/KITT.Core/Models/Streaming.cs index facbb6c..7a99478 100644 --- a/src/KITT.Core/Models/Streaming.cs +++ b/src/KITT.Core/Models/Streaming.cs @@ -67,15 +67,6 @@ public static Streaming Schedule(string title, string slug, string twitchChannel throw new ArgumentException("Starting time should be previuos than ending time", nameof(endingTime)); } - if (!string.IsNullOrWhiteSpace(twitchChannel) && string.IsNullOrWhiteSpace(twitchUrl)) - { - throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); - } - if (!string.IsNullOrWhiteSpace(youTubeChannel) && string.IsNullOrWhiteSpace(youTubeUrl)) - { - throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); - } - if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentException("value cannot be empty", nameof(userId)); @@ -101,7 +92,7 @@ public static Streaming Schedule(string title, string slug, string twitchChannel return streaming; } - public static Streaming Import(string title, string slug, string twitchChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? youtubeUrl, string? @abstract, string userId) + public static Streaming Import(string title, string slug, string twitchChannel, string youTubeChannel, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? youTubeUrl, string? @abstract, string userId) { if (string.IsNullOrWhiteSpace(title)) { @@ -113,17 +104,16 @@ public static Streaming Import(string title, string slug, string twitchChannel, throw new ArgumentException("value cannot be empty", nameof(slug)); } - if (string.IsNullOrWhiteSpace(twitchChannel)) - { - throw new ArgumentException("value cannot be empty", nameof(twitchChannel)); - } - if (startingTime >= endingTime) { throw new ArgumentException("Starting time should be previuos than ending time", nameof(endingTime)); } - if (string.IsNullOrWhiteSpace(twitchUrl)) + if (!string.IsNullOrWhiteSpace(twitchChannel) && string.IsNullOrWhiteSpace(twitchUrl)) + { + throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); + } + if (!string.IsNullOrWhiteSpace(youTubeChannel) && string.IsNullOrWhiteSpace(youTubeUrl)) { throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); } @@ -140,12 +130,13 @@ public static Streaming Import(string title, string slug, string twitchChannel, Title = title, Slug = slug, TwitchChannel = twitchChannel, + YouTubeChannel = youTubeChannel, ScheduleDate = scheduleDate, StartingTime = startingTime, EndingTime = endingTime, TwitchUrl = twitchUrl, Abstract = @abstract, - YouTubeUrl = youtubeUrl + YouTubeUrl = youTubeUrl }; streaming.PublishOn(scheduleDate.ToDateTime(TimeOnly.MinValue)); diff --git a/src/KITT.Core/Validators/StreamingValidator.cs b/src/KITT.Core/Validators/StreamingValidator.cs index 7f4a8f8..1edb77a 100644 --- a/src/KITT.Core/Validators/StreamingValidator.cs +++ b/src/KITT.Core/Validators/StreamingValidator.cs @@ -29,8 +29,6 @@ private void DefineRules() { RuleFor(streaming => streaming.Title).MaximumLength(255).NotEmpty(); RuleFor(streaming => streaming.Slug).MaximumLength(255).NotEmpty(); - RuleFor(streaming => streaming.TwitchUrl).NotEmpty().When(streaming => !string.IsNullOrWhiteSpace(streaming.TwitchChannel)).MaximumLength(255); - RuleFor(streaming => streaming.YouTubeUrl).NotEmpty().When(streaming => !string.IsNullOrWhiteSpace(streaming.YouTubeChannel)).MaximumLength(255); RuleSet(ScheduleStreamingAction, () => { diff --git a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs index 07d0d9f..28c9174 100644 --- a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs +++ b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs @@ -224,6 +224,7 @@ public async Task UpdateStreamingAsync_Should_Not_Update_Schedule_If_It_Is_Not_C "title", "slug", "albx87", + "@albx87", scheduleDate, startingTime, endingTime, From 2018253bf2dafa3418e59d9ef770d6df5651038c Mon Sep 17 00:00:00 2001 From: albx Date: Mon, 16 Feb 2026 07:35:54 +0100 Subject: [PATCH 21/26] #124 - streaming detail and update packages --- src/KITT.AppHost/KITT.AppHost.csproj | 14 ++--- .../Services/StreamingsEndpointsServices.cs | 20 ++++++-- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 6 +-- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 2 +- .../Pages/Streamings/StreamingDetail.razor | 37 +++++++++++--- .../Pages/Streamings/StreamingDetail.razor.cs | 40 +++++++++++---- .../Streamings/StreamingDetailModel.cs | 9 ++-- src/KITT.Core/Commands/IStreamingCommands.cs | 6 ++- src/KITT.Core/Commands/StreamingCommands.cs | 51 ++++++++----------- src/KITT.Core/KITT.Core.csproj | 4 +- src/KITT.Core/Models/Streaming.cs | 26 +++++++++- .../KITT.Proposals.Web.Api.csproj | 4 +- .../KITT.Proposals.Web.App.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 14 ++--- .../KITT.Support.Seeder.csproj | 8 +-- .../KITT.Telegram.Messages.csproj | 4 +- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 12 ++--- .../KITT.Web.App.Client.csproj | 6 +-- .../KITT.Web.App/KITT.Web.App.csproj | 12 ++--- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 8 +-- .../KITT.Cms.Web.Api.Test.csproj | 6 +-- .../Commands/StreamingCommandsTest.cs | 4 ++ tests/KITT.Core.Test/KITT.Core.Test.csproj | 4 +- tests/KITT.Core.Test/Models/StreamingTests.cs | 2 +- .../KITT.Web.Testing/KITT.Web.Testing.csproj | 6 +-- 25 files changed, 193 insertions(+), 114 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 28fae8f..31f7bf1 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,12 +9,12 @@ - - - - - - + + + + + + diff --git a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs index 7158889..0138e5e 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/Services/StreamingsEndpointsServices.cs @@ -53,14 +53,22 @@ public async Task GetAllStreamingsAsync(string userId, int return new() { Id = streaming.Id, + TwitchChannel = streaming.TwitchChannel, + YouTubeChannel = streaming.YouTubeChannel, ScheduleDate = streaming.ScheduleDate, EndingTime = streaming.EndingTime, - HostingChannelUrl = streaming.TwitchUrl ?? string.Empty, + TwitchUrl = streaming.TwitchUrl ?? string.Empty, StartingTime = streaming.StartingTime, StreamingAbstract = streaming.Abstract, Title = streaming.Title, - YoutubeVideoUrl = streaming.YouTubeUrl, - Slug = streaming.Slug + YouTubeUrl = streaming.YouTubeUrl ?? string.Empty, + Slug = streaming.Slug, + Seo = new Models.SeoData + { + Title = streaming.Seo?.Title ?? string.Empty, + Description = streaming.Seo?.Description ?? string.Empty, + Keywords = streaming.Seo?.Keywords ?? string.Empty, + } }; } @@ -123,13 +131,15 @@ public Task UpdateStreamingAsync(Guid streamingId, StreamingDetailModel model) return Commands.UpdateStreamingAsync( streamingId, + model.TwitchChannel, + model.YouTubeChannel, model.Title, model.ScheduleDate, model.StartingTime, model.EndingTime, - model.HostingChannelUrl, + model.TwitchUrl, model.StreamingAbstract, - model.YoutubeVideoUrl, + model.YouTubeUrl, seo); } diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 98a0561..eb00102 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index 44e5eeb..f7b1118 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor index ac99e61..de63153 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor +++ b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor @@ -32,6 +32,32 @@ OnSave="EditStreamingAsync" OnCancel="DisableEditing"> + + + + + + + + + + - @twitchBaseUrl - - + Disabled="@isReadOnly"/> + + diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs index f499f03..3e0af84 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor.cs @@ -1,5 +1,6 @@ using KITT.Cms.Web.App.Clients; using KITT.Cms.Web.Models; +using KITT.Cms.Web.Models.Settings; using KITT.Cms.Web.Models.Streamings; using KITT.Web.App.UI; using Microsoft.AspNetCore.Components; @@ -12,7 +13,8 @@ namespace KITT.Cms.Web.App.Pages.Streamings; public partial class StreamingDetail( IStreamingsClient client, IToastService toastService, - IMessageService messageService) + IMessageService messageService, + IConnectedChannelsClient channelsClient) { [Parameter] [EditorRequired] @@ -24,7 +26,9 @@ public partial class StreamingDetail( private string pageTitle = "StreamingDetail"; - private const string twitchBaseUrl = "https://www.twitch.tv/"; + private ChannelModel?[] availableTwitchChannels = []; + + private ChannelModel?[] availableYouTubeChannels = []; private void EnableEditing() => isReadOnly = false; @@ -59,14 +63,28 @@ await messageService.ShowMessageBarAsync( protected override async Task OnInitializedAsync() { + await LoadConnectedChannelsAsync(); + streamingDetail = await client.GetStreamingDetailAsync(Id) ?? new(); model = ViewModel.FromStreamingDetailModel(streamingDetail); pageTitle = model.Title; } + private async Task LoadConnectedChannelsAsync() + { + var channels = await channelsClient.GetConnectedChannelsAsync(); + + availableTwitchChannels = [null, .. channels.Where(c => c.Type is Cms.Settings.Models.ChannelType.Twitch).ToArray()]; + availableYouTubeChannels = [null, .. channels.Where(c => c.Type is Cms.Settings.Models.ChannelType.YouTube).ToArray()]; + } + class ViewModel : ContentViewModel { + public string? TwitchChannel { get; set; } + + public string? YouTubeChannel { get; set; } + [Required] public string Title { get; set; } = string.Empty; @@ -81,12 +99,11 @@ class ViewModel : ContentViewModel [Required] public DateTime? EndingTime { get; set; } = DateTime.Now.AddHours(1); - [Required] - public string HostingChannelUrl { get; set; } = string.Empty; + public string TwitchUrl { get; set; } = string.Empty; public string? StreamingAbstract { get; set; } - public string? YoutubeVideoUrl { get; set; } + public string YouTubeUrl { get; set; } = string.Empty; public StreamingDetailModel ToApiModel(Guid streamingId) { @@ -113,14 +130,16 @@ public StreamingDetailModel ToApiModel(Guid streamingId) return new() { Id = streamingId, + TwitchChannel = this.TwitchChannel, + YouTubeChannel = this.YouTubeChannel, Title = this.Title, Slug = this.Slug, ScheduleDate = DateOnly.FromDateTime(this.ScheduleDate.Value), EndingTime = TimeOnly.FromTimeSpan(this.EndingTime.Value.TimeOfDay), - HostingChannelUrl = $"{twitchBaseUrl}{this.HostingChannelUrl}", + TwitchUrl = this.TwitchUrl, StartingTime = TimeOnly.FromTimeSpan(this.StartingTime.Value.TimeOfDay), StreamingAbstract = this.StreamingAbstract, - YoutubeVideoUrl = this.YoutubeVideoUrl, + YouTubeUrl = this.YouTubeUrl, Seo = this.Seo }; } @@ -130,13 +149,16 @@ public static ViewModel FromStreamingDetailModel(StreamingDetailModel model) return new() { Title = model.Title, + TwitchChannel = model.TwitchChannel, + YouTubeChannel = model.YouTubeChannel, Slug = model.Slug, ScheduleDate = model.ScheduleDate.ToDateTime(TimeOnly.MinValue), EndingTime = model.EndingTime.ToDateTime(), StartingTime = model.StartingTime.ToDateTime(), StreamingAbstract = model.StreamingAbstract, - YoutubeVideoUrl = model.YoutubeVideoUrl, - HostingChannelUrl = model.HostingChannelUrl.Replace(twitchBaseUrl, string.Empty).Trim() + YouTubeUrl = model.YouTubeUrl, + TwitchUrl = model.TwitchUrl, + Seo = model.Seo }; } } diff --git a/src/KITT.Cms.Web.Models/Streamings/StreamingDetailModel.cs b/src/KITT.Cms.Web.Models/Streamings/StreamingDetailModel.cs index 2d4b2ea..48dcde3 100644 --- a/src/KITT.Cms.Web.Models/Streamings/StreamingDetailModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/StreamingDetailModel.cs @@ -6,6 +6,10 @@ public record StreamingDetailModel { public Guid Id { get; set; } + public string? TwitchChannel { get; set; } + + public string? YouTubeChannel { get; set; } + [Required] public string Title { get; set; } = string.Empty; @@ -20,12 +24,11 @@ public record StreamingDetailModel [Required] public TimeOnly EndingTime { get; set; } - [Required] - public string HostingChannelUrl { get; set; } = string.Empty; + public string TwitchUrl { get; set; } = string.Empty; public string? StreamingAbstract { get; set; } - public string? YoutubeVideoUrl { get; set; } + public string YouTubeUrl { get; set; } = string.Empty; public SeoData Seo { get; set; } = new(); } diff --git a/src/KITT.Core/Commands/IStreamingCommands.cs b/src/KITT.Core/Commands/IStreamingCommands.cs index 9742190..b98ace9 100644 --- a/src/KITT.Core/Commands/IStreamingCommands.cs +++ b/src/KITT.Core/Commands/IStreamingCommands.cs @@ -17,8 +17,10 @@ Task ScheduleStreamingAsync( Content.SeoData seo); Task UpdateStreamingAsync( - Guid streamingId, - string streamingTitle, + Guid streamingId, + string? twitchChannel, + string? youTubeChannel, + string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, diff --git a/src/KITT.Core/Commands/StreamingCommands.cs b/src/KITT.Core/Commands/StreamingCommands.cs index cefef14..8de0d2f 100644 --- a/src/KITT.Core/Commands/StreamingCommands.cs +++ b/src/KITT.Core/Commands/StreamingCommands.cs @@ -59,40 +59,34 @@ public async Task ScheduleStreamingAsync( return streaming.Id; } - public async Task UpdateStreamingAsync(Guid streamingId, string streamingTitle, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime, string twitchUrl, string? streamingAbstract, string youtubeUrl, Content.SeoData seo) + public async Task UpdateStreamingAsync( + Guid streamingId, + string? twitchChannel, + string? youTubeChannel, + string streamingTitle, + DateOnly scheduleDate, + TimeOnly startingTime, + TimeOnly endingTime, + string twitchUrl, + string? streamingAbstract, + string youtubeUrl, + Content.SeoData seo) { - var messagesToSend = new List(); - var streaming = _context.Streamings.SingleOrDefault(s => s.Id == streamingId); if (streaming is null) { throw new ArgumentOutOfRangeException(nameof(streamingId)); } - if (streaming.Title != streamingTitle) - { - streaming.ChangeTitle(streamingTitle); - } - - if (ScheduleHasChanged(streaming, scheduleDate, startingTime, endingTime)) - { - streaming.ChangeSchedule(scheduleDate, startingTime, endingTime); - } - - if (streaming.TwitchUrl != twitchUrl) - { - streaming.SetTwitchUrl(twitchUrl); - } - - if (streaming.Abstract != streamingAbstract) - { - streaming.SetAbstract(streamingAbstract); - } + streaming.ChangeInformation( + twitchChannel, + youTubeChannel, + streamingTitle, + streamingAbstract, + twitchUrl, + youtubeUrl); - if (streaming.YouTubeUrl != youtubeUrl) - { - streaming.SetYoutubeUrl(youtubeUrl); - } + streaming.ChangeSchedule(scheduleDate, startingTime, endingTime); if (seo is not null) { @@ -153,9 +147,4 @@ public async Task ImportStreamingAsync( return streaming.Id; } - - #region Private methods - private bool ScheduleHasChanged(Streaming streaming, DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime) - => streaming.ScheduleDate != scheduleDate || streaming.StartingTime != startingTime || streaming.EndingTime != endingTime; - #endregion } diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 29ee91b..a62ae37 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/src/KITT.Core/Models/Streaming.cs b/src/KITT.Core/Models/Streaming.cs index 7a99478..17a479a 100644 --- a/src/KITT.Core/Models/Streaming.cs +++ b/src/KITT.Core/Models/Streaming.cs @@ -21,6 +21,22 @@ protected Streaming() : base() { } #endregion #region Behaviors + public void ChangeInformation( + string? twitchChannel, + string? youTubeChannel, + string title, + string? @abstract, + string? twitchUrl, + string? youTubeUrl) + { + TwitchChannel = twitchChannel; + YouTubeChannel = youTubeChannel; + Title = title; + Abstract = @abstract; + TwitchUrl = twitchUrl; + YouTubeUrl = youTubeUrl; + } + public void ChangeSchedule(DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime) { if (startingTime >= endingTime) @@ -28,12 +44,20 @@ public void ChangeSchedule(DateOnly scheduleDate, TimeOnly startingTime, TimeOnl throw new ArgumentException("Ending time cannot be previous than starting time", nameof(endingTime)); } + if (!ScheduleHasChanged(scheduleDate, startingTime, endingTime)) + { + return; + } + this.ScheduleDate = scheduleDate; this.StartingTime = startingTime; this.EndingTime = endingTime; } - public void SetYoutubeUrl(string youtubeUrl) + public bool ScheduleHasChanged(DateOnly scheduleDate, TimeOnly startingTime, TimeOnly endingTime) + => ScheduleDate != scheduleDate || StartingTime != startingTime || EndingTime != endingTime; + + public void SetYouTubeUrl(string youtubeUrl) { YouTubeUrl = youtubeUrl; } diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 055a7d8..11eacb1 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index 127f59a..7fe21cf 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 7f41dde..79d19ad 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -10,13 +10,13 @@ - - - - - - - + + + + + + + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index 61f026d..8b88acd 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,13 +8,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index 9374f55..15ae901 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index 9d8ef78..632f309 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -12,12 +12,12 @@ - - - - - - + + + + + + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index b7c60bd..e0140b1 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index be8791f..7fc26fe 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -14,13 +14,13 @@ - - + + - - - - + + + + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index c044504..a89c6ba 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,11 +7,11 @@ - - - + + + - + diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index 3a67c94..20addd8 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -8,12 +8,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs index 28c9174..1b05e94 100644 --- a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs +++ b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs @@ -186,6 +186,8 @@ public async Task UpdateStreamingAsync_Should_Update_Streaming_Information_Corre await commands.UpdateStreamingAsync( streamingId, + "https://twitch.tv/albx87", + "https://youtube.com/@albx87", streamingTitle, scheduleDate, startingTime, @@ -247,6 +249,8 @@ public async Task UpdateStreamingAsync_Should_Not_Update_Schedule_If_It_Is_Not_C await commands.UpdateStreamingAsync( streamingId, + "https://twitch.tv/albx87", + "https://youtube.com/@albx87", streamingTitle, scheduleDate, startingTime, diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index a4a0653..3be1104 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@ all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/KITT.Core.Test/Models/StreamingTests.cs b/tests/KITT.Core.Test/Models/StreamingTests.cs index b5485c9..c753d74 100644 --- a/tests/KITT.Core.Test/Models/StreamingTests.cs +++ b/tests/KITT.Core.Test/Models/StreamingTests.cs @@ -246,7 +246,7 @@ public void SetRegistrationYoutubeUrl_Should_Set_Youtube_Registration_Url_With_S var streaming = CreateStreamingForTests(); string youtubeUrl = "https://www.youtube.com"; - streaming.SetYoutubeUrl(youtubeUrl); + streaming.SetYouTubeUrl(youtubeUrl); Assert.Equal(youtubeUrl, streaming.YouTubeUrl); } #endregion diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index cc323d4..b149f76 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -11,9 +11,9 @@ - - - + + + From d60c5d59e1dc54820477461d92c19924b5367f82 Mon Sep 17 00:00:00 2001 From: albx Date: Mon, 16 Feb 2026 07:41:22 +0100 Subject: [PATCH 22/26] #124 - fix prevent navigation message --- src/KITT.Cms.Web.App/Components/ContentForm.razor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/KITT.Cms.Web.App/Components/ContentForm.razor.cs b/src/KITT.Cms.Web.App/Components/ContentForm.razor.cs index 32c1329..b0c4293 100644 --- a/src/KITT.Cms.Web.App/Components/ContentForm.razor.cs +++ b/src/KITT.Cms.Web.App/Components/ContentForm.razor.cs @@ -53,6 +53,7 @@ private async Task SubmitAsync() finally { saving = false; + editContext?.MarkAsUnmodified(); } } From 90348b8709aa7726daa02ca48d1051fef987ba66 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 28 Feb 2026 11:10:16 +0100 Subject: [PATCH 23/26] #124 - update aspire version to 13.1.2 --- src/KITT.AppHost/KITT.AppHost.csproj | 12 ++++++------ src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 4 ++-- .../KITT.Proposals.Web.Api.csproj | 2 +- src/KITT.Support.Seeder/KITT.Support.Seeder.csproj | 4 ++-- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index 31f7bf1..f69d44a 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,11 +9,11 @@ - - - - - + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index eb00102..4cd554c 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 11eacb1..1cdc3e9 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index 8b88acd..7d74b01 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index a89c6ba..0098234 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,7 +7,7 @@ - + From 94222b23d393acf7001703399603b1d1fd04a225 Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 28 Mar 2026 18:04:32 +0100 Subject: [PATCH 24/26] #124 - update aspire and all packages --- LemonBot.sln | 356 ------------------ LemonBot.slnx | 40 ++ src/KITT.AppHost/KITT.AppHost.csproj | 14 +- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 6 +- src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj | 2 +- src/KITT.Core/KITT.Core.csproj | 6 +- .../KITT.Proposals.Web.Api.csproj | 4 +- .../KITT.Proposals.Web.App.csproj | 2 +- .../KITT.ServiceDefaults.csproj | 10 +- .../KITT.Support.Seeder.csproj | 8 +- .../KITT.Telegram.Messages.csproj | 4 +- src/KITT.Web.App.UI/KITT.Web.App.UI.csproj | 6 +- .../KITT.Web.App.Client.csproj | 2 +- .../KITT.Web.App/KITT.Web.App.csproj | 10 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 10 +- .../KITT.Cms.Web.Api.Test.csproj | 8 +- tests/KITT.Core.Test/KITT.Core.Test.csproj | 6 +- .../KITT.Web.Testing/KITT.Web.Testing.csproj | 6 +- 18 files changed, 92 insertions(+), 408 deletions(-) delete mode 100644 LemonBot.sln create mode 100644 LemonBot.slnx diff --git a/LemonBot.sln b/LemonBot.sln deleted file mode 100644 index b11e49d..0000000 --- a/LemonBot.sln +++ /dev/null @@ -1,356 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.0.11018.127 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KITT", "KITT", "{53F76412-0B22-4C62-8519-834A82747AD4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.Models", "src\KITT.Web.Models\KITT.Web.Models.csproj", "{A9018405-BC9E-41FD-955A-5A3B4AED27A4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Core", "src\KITT.Core\KITT.Core.csproj", "{66F99049-7BCF-47D4-81FF-8E0254FE82EE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{B32B1475-75B8-41DD-BB71-D6106152C656}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Core.Test", "tests\KITT.Core.Test\KITT.Core.Test.csproj", "{AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.App.UI", "src\KITT.Web.App.UI\KITT.Web.App.UI.csproj", "{2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Cms.Web.Api", "src\KITT.Cms.Web.Api\KITT.Cms.Web.Api.csproj", "{406A74C4-AF3B-43C0-9D54-111B7CE24EBF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Cms.Web.Models", "src\KITT.Cms.Web.Models\KITT.Cms.Web.Models.csproj", "{7E0161FF-5AB4-451E-A95A-45D15BFC8C29}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.Shared", "src\KITT.Web.Shared\KITT.Web.Shared.csproj", "{A701C3B3-E70B-4386-BBD4-39B9376966EE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.AppHost", "src\KITT.AppHost\KITT.AppHost.csproj", "{7C417964-199A-40D7-99AD-77A356F6B8D0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.ServiceDefaults", "src\KITT.ServiceDefaults\KITT.ServiceDefaults.csproj", "{F1D748E1-2241-446F-88D0-CEFCCCEB7A93}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.App", "src\KITT.Web.App\KITT.Web.App\KITT.Web.App.csproj", "{4CBD2E55-3636-445A-93BB-84D549D64501}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Web.App.Client", "src\KITT.Web.App\KITT.Web.App.Client\KITT.Web.App.Client.csproj", "{C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cms", "Cms", "{90F26E81-71A2-4438-ACD9-64D3AC5636AF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KITT.Cms.Web.App", "src\KITT.Cms.Web.App\KITT.Cms.Web.App.csproj", "{E51D737B-4337-47BD-84AF-97086FDDA158}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Proposals", "Proposals", "{5C9DDC07-E0A9-48AA-8D75-0188C65B2D5E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Proposals.Web.Api", "src\KITT.Proposals.Web.Api\KITT.Proposals.Web.Api.csproj", "{CA7C2776-D362-4AD6-BA88-2C0B38D71C42}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Proposals.Web.Models", "src\KITT.Proposals.Web.Models\KITT.Proposals.Web.Models.csproj", "{B7D3A829-1BFD-455B-8E7B-074DC16EE85D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Proposals.Web.App", "src\KITT.Proposals.Web.App\KITT.Proposals.Web.App.csproj", "{B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Cms.Web.Api.Test", "tests\KITT.Cms.Web.Api.Test\KITT.Cms.Web.Api.Test.csproj", "{A29853FF-53A7-499F-B309-7154A51D9908}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Web.Testing", "tests\KITT.Web.Testing\KITT.Web.Testing.csproj", "{AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Support", "Support", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Support.Seeder", "src\KITT.Support.Seeder\KITT.Support.Seeder.csproj", "{92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Services", "src\KITT.Services\KITT.Services.csproj", "{C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Telegram.Messages", "src\KITT.Telegram.Messages\KITT.Telegram.Messages.csproj", "{8C003A09-3777-AEFF-806A-A2010FD1DDDE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KITT.Cms.Settings", "src\KITT.Cms.Settings\KITT.Cms.Settings.csproj", "{8393DD88-4D14-4E24-80F4-CCAD1C857D54}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|x64.ActiveCfg = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|x64.Build.0 = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|x86.ActiveCfg = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Debug|x86.Build.0 = Debug|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|Any CPU.Build.0 = Release|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|x64.ActiveCfg = Release|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|x64.Build.0 = Release|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|x86.ActiveCfg = Release|Any CPU - {A9018405-BC9E-41FD-955A-5A3B4AED27A4}.Release|x86.Build.0 = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|x64.ActiveCfg = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|x64.Build.0 = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|x86.ActiveCfg = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Debug|x86.Build.0 = Debug|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|Any CPU.Build.0 = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|x64.ActiveCfg = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|x64.Build.0 = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|x86.ActiveCfg = Release|Any CPU - {66F99049-7BCF-47D4-81FF-8E0254FE82EE}.Release|x86.Build.0 = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|x64.ActiveCfg = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|x64.Build.0 = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Debug|x86.Build.0 = Debug|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|Any CPU.Build.0 = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|x64.ActiveCfg = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|x64.Build.0 = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|x86.ActiveCfg = Release|Any CPU - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235}.Release|x86.Build.0 = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|x64.ActiveCfg = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|x64.Build.0 = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|x86.ActiveCfg = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Debug|x86.Build.0 = Debug|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|Any CPU.Build.0 = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x64.ActiveCfg = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x64.Build.0 = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x86.ActiveCfg = Release|Any CPU - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE}.Release|x86.Build.0 = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|x64.ActiveCfg = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|x64.Build.0 = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|x86.ActiveCfg = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Debug|x86.Build.0 = Debug|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|Any CPU.Build.0 = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|x64.ActiveCfg = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|x64.Build.0 = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|x86.ActiveCfg = Release|Any CPU - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF}.Release|x86.Build.0 = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|x64.ActiveCfg = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|x64.Build.0 = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|x86.ActiveCfg = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Debug|x86.Build.0 = Debug|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|Any CPU.Build.0 = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|x64.ActiveCfg = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|x64.Build.0 = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|x86.ActiveCfg = Release|Any CPU - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29}.Release|x86.Build.0 = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|x64.ActiveCfg = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|x64.Build.0 = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|x86.ActiveCfg = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Debug|x86.Build.0 = Debug|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|Any CPU.Build.0 = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|x64.ActiveCfg = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|x64.Build.0 = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|x86.ActiveCfg = Release|Any CPU - {A701C3B3-E70B-4386-BBD4-39B9376966EE}.Release|x86.Build.0 = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|x64.ActiveCfg = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|x64.Build.0 = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|x86.ActiveCfg = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Debug|x86.Build.0 = Debug|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|Any CPU.Build.0 = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|x64.ActiveCfg = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|x64.Build.0 = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|x86.ActiveCfg = Release|Any CPU - {7C417964-199A-40D7-99AD-77A356F6B8D0}.Release|x86.Build.0 = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|x64.ActiveCfg = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|x64.Build.0 = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|x86.ActiveCfg = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Debug|x86.Build.0 = Debug|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|Any CPU.Build.0 = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|x64.ActiveCfg = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|x64.Build.0 = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|x86.ActiveCfg = Release|Any CPU - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93}.Release|x86.Build.0 = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|x64.ActiveCfg = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|x64.Build.0 = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|x86.ActiveCfg = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Debug|x86.Build.0 = Debug|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|Any CPU.Build.0 = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|x64.ActiveCfg = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|x64.Build.0 = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|x86.ActiveCfg = Release|Any CPU - {4CBD2E55-3636-445A-93BB-84D549D64501}.Release|x86.Build.0 = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|x64.ActiveCfg = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|x64.Build.0 = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|x86.ActiveCfg = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Debug|x86.Build.0 = Debug|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|Any CPU.Build.0 = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|x64.ActiveCfg = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|x64.Build.0 = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|x86.ActiveCfg = Release|Any CPU - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4}.Release|x86.Build.0 = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|x64.ActiveCfg = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|x64.Build.0 = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|x86.ActiveCfg = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Debug|x86.Build.0 = Debug|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|Any CPU.Build.0 = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|x64.ActiveCfg = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|x64.Build.0 = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|x86.ActiveCfg = Release|Any CPU - {E51D737B-4337-47BD-84AF-97086FDDA158}.Release|x86.Build.0 = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|x64.ActiveCfg = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|x64.Build.0 = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Debug|x86.Build.0 = Debug|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|Any CPU.Build.0 = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|x64.ActiveCfg = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|x64.Build.0 = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|x86.ActiveCfg = Release|Any CPU - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42}.Release|x86.Build.0 = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|x64.ActiveCfg = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|x64.Build.0 = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|x86.ActiveCfg = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Debug|x86.Build.0 = Debug|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|Any CPU.Build.0 = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|x64.ActiveCfg = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|x64.Build.0 = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|x86.ActiveCfg = Release|Any CPU - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D}.Release|x86.Build.0 = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|x64.ActiveCfg = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|x64.Build.0 = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|x86.ActiveCfg = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Debug|x86.Build.0 = Debug|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|Any CPU.Build.0 = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|x64.ActiveCfg = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|x64.Build.0 = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|x86.ActiveCfg = Release|Any CPU - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD}.Release|x86.Build.0 = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|x64.ActiveCfg = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|x64.Build.0 = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|x86.ActiveCfg = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Debug|x86.Build.0 = Debug|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|Any CPU.Build.0 = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|x64.ActiveCfg = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|x64.Build.0 = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|x86.ActiveCfg = Release|Any CPU - {A29853FF-53A7-499F-B309-7154A51D9908}.Release|x86.Build.0 = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|x64.ActiveCfg = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|x64.Build.0 = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|x86.ActiveCfg = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Debug|x86.Build.0 = Debug|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|Any CPU.Build.0 = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|x64.ActiveCfg = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|x64.Build.0 = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|x86.ActiveCfg = Release|Any CPU - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9}.Release|x86.Build.0 = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|x64.ActiveCfg = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|x64.Build.0 = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|x86.ActiveCfg = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Debug|x86.Build.0 = Debug|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|Any CPU.Build.0 = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|x64.ActiveCfg = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|x64.Build.0 = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|x86.ActiveCfg = Release|Any CPU - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98}.Release|x86.Build.0 = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|x64.ActiveCfg = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|x64.Build.0 = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|x86.ActiveCfg = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Debug|x86.Build.0 = Debug|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|Any CPU.Build.0 = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x64.ActiveCfg = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x64.Build.0 = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x86.ActiveCfg = Release|Any CPU - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1}.Release|x86.Build.0 = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x64.ActiveCfg = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x64.Build.0 = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x86.ActiveCfg = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Debug|x86.Build.0 = Debug|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|Any CPU.Build.0 = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x64.ActiveCfg = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x64.Build.0 = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.ActiveCfg = Release|Any CPU - {8C003A09-3777-AEFF-806A-A2010FD1DDDE}.Release|x86.Build.0 = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x64.ActiveCfg = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x64.Build.0 = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x86.ActiveCfg = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Debug|x86.Build.0 = Debug|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|Any CPU.Build.0 = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x64.ActiveCfg = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x64.Build.0 = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x86.ActiveCfg = Release|Any CPU - {8393DD88-4D14-4E24-80F4-CCAD1C857D54}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {53F76412-0B22-4C62-8519-834A82747AD4} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {A9018405-BC9E-41FD-955A-5A3B4AED27A4} = {53F76412-0B22-4C62-8519-834A82747AD4} - {66F99049-7BCF-47D4-81FF-8E0254FE82EE} = {53F76412-0B22-4C62-8519-834A82747AD4} - {AB7A75D3-84BA-4AFD-BC49-D0C7545FB235} = {B32B1475-75B8-41DD-BB71-D6106152C656} - {2B84BEBB-A29E-4BDE-893F-BBCCE979A0BE} = {53F76412-0B22-4C62-8519-834A82747AD4} - {406A74C4-AF3B-43C0-9D54-111B7CE24EBF} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} - {7E0161FF-5AB4-451E-A95A-45D15BFC8C29} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} - {A701C3B3-E70B-4386-BBD4-39B9376966EE} = {53F76412-0B22-4C62-8519-834A82747AD4} - {7C417964-199A-40D7-99AD-77A356F6B8D0} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {F1D748E1-2241-446F-88D0-CEFCCCEB7A93} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {4CBD2E55-3636-445A-93BB-84D549D64501} = {53F76412-0B22-4C62-8519-834A82747AD4} - {C4ED93D6-3B6F-4EF3-84D4-3B76FE7875F4} = {53F76412-0B22-4C62-8519-834A82747AD4} - {90F26E81-71A2-4438-ACD9-64D3AC5636AF} = {53F76412-0B22-4C62-8519-834A82747AD4} - {E51D737B-4337-47BD-84AF-97086FDDA158} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} - {5C9DDC07-E0A9-48AA-8D75-0188C65B2D5E} = {53F76412-0B22-4C62-8519-834A82747AD4} - {CA7C2776-D362-4AD6-BA88-2C0B38D71C42} = {5C9DDC07-E0A9-48AA-8D75-0188C65B2D5E} - {B7D3A829-1BFD-455B-8E7B-074DC16EE85D} = {5C9DDC07-E0A9-48AA-8D75-0188C65B2D5E} - {B5656CFD-8ED7-4CC8-9AE4-CD0BE14B98AD} = {5C9DDC07-E0A9-48AA-8D75-0188C65B2D5E} - {A29853FF-53A7-499F-B309-7154A51D9908} = {B32B1475-75B8-41DD-BB71-D6106152C656} - {AA34DAE8-59AE-4500-8D60-6CA2B899DCD9} = {B32B1475-75B8-41DD-BB71-D6106152C656} - {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {53F76412-0B22-4C62-8519-834A82747AD4} - {92B53BDC-3A3B-D5E5-70AE-56E877F1BB98} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {C4747EBF-4249-4D6A-9DD0-73C35E0C9AA1} = {F47298C6-FC9C-4B30-88D6-3DDAAD1B7B65} - {8C003A09-3777-AEFF-806A-A2010FD1DDDE} = {53F76412-0B22-4C62-8519-834A82747AD4} - {8393DD88-4D14-4E24-80F4-CCAD1C857D54} = {90F26E81-71A2-4438-ACD9-64D3AC5636AF} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {08491B30-AD3E-4AEA-AAB9-40A83A96F393} - EndGlobalSection -EndGlobal diff --git a/LemonBot.slnx b/LemonBot.slnx new file mode 100644 index 0000000..2d99318 --- /dev/null +++ b/LemonBot.slnx @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index f69d44a..e246fb2 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,12 +9,12 @@ - - - - - - + + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index 4cd554c..b9f7877 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj index f7b1118..83089a9 100644 --- a/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj +++ b/src/KITT.Cms.Web.App/KITT.Cms.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index a62ae37..30cc2de 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -7,12 +7,12 @@ - + - - + + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 1cdc3e9..0b40c4d 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj index 7fe21cf..fb0839b 100644 --- a/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj +++ b/src/KITT.Proposals.Web.App/KITT.Proposals.Web.App.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj index 79d19ad..884b8b9 100644 --- a/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj +++ b/src/KITT.ServiceDefaults/KITT.ServiceDefaults.csproj @@ -10,11 +10,11 @@ - - - - - + + + + + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index 7d74b01..eb38f26 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,13 +8,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj index 15ae901..6e414b4 100644 --- a/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj +++ b/src/KITT.Telegram.Messages/KITT.Telegram.Messages.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj index 632f309..a1d7593 100644 --- a/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj +++ b/src/KITT.Web.App.UI/KITT.Web.App.UI.csproj @@ -13,11 +13,11 @@ - - + + - + diff --git a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj index e0140b1..147064e 100644 --- a/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj +++ b/src/KITT.Web.App/KITT.Web.App.Client/KITT.Web.App.Client.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index 7fc26fe..a9f26c5 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -16,11 +16,11 @@ - + - - - - + + + + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index 0098234..c44acda 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,11 +7,11 @@ - - - - - + + + + + diff --git a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj index 20addd8..9e365b6 100644 --- a/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj +++ b/tests/KITT.Cms.Web.Api.Test/KITT.Cms.Web.Api.Test.csproj @@ -8,13 +8,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all diff --git a/tests/KITT.Core.Test/KITT.Core.Test.csproj b/tests/KITT.Core.Test/KITT.Core.Test.csproj index 3be1104..ec44d5d 100644 --- a/tests/KITT.Core.Test/KITT.Core.Test.csproj +++ b/tests/KITT.Core.Test/KITT.Core.Test.csproj @@ -14,15 +14,15 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj index b149f76..5b66ddc 100644 --- a/tests/KITT.Web.Testing/KITT.Web.Testing.csproj +++ b/tests/KITT.Web.Testing/KITT.Web.Testing.csproj @@ -11,9 +11,9 @@ - - - + + + From 84649a12b29555ca518837163110bf385a87241c Mon Sep 17 00:00:00 2001 From: albx Date: Sat, 4 Apr 2026 18:02:22 +0200 Subject: [PATCH 25/26] #124 - add translations for channels form. update packages and aspire version --- aspire.config.json | 5 ++++ src/KITT.AppHost/KITT.AppHost.csproj | 12 ++++----- src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj | 4 +-- .../Components/ChannelFormPanel.razor | 6 ++--- .../Components/ChannelFormPanel.Designer.cs | 27 +++++++++++++++++++ .../Components/ChannelFormPanel.it.resx | 9 +++++++ .../Components/ChannelFormPanel.resx | 9 +++++++ src/KITT.Core/KITT.Core.csproj | 2 +- .../KITT.Proposals.Web.Api.csproj | 2 +- .../KITT.Support.Seeder.csproj | 4 +-- .../KITT.Web.App/KITT.Web.App.csproj | 2 +- src/KITT.Web.Shared/KITT.Web.Shared.csproj | 4 +-- 12 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 aspire.config.json diff --git a/aspire.config.json b/aspire.config.json new file mode 100644 index 0000000..ff9018f --- /dev/null +++ b/aspire.config.json @@ -0,0 +1,5 @@ +{ + "appHost": { + "path": "src/KITT.AppHost/KITT.AppHost.csproj" + } +} \ No newline at end of file diff --git a/src/KITT.AppHost/KITT.AppHost.csproj b/src/KITT.AppHost/KITT.AppHost.csproj index e246fb2..6faa106 100644 --- a/src/KITT.AppHost/KITT.AppHost.csproj +++ b/src/KITT.AppHost/KITT.AppHost.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,11 +9,11 @@ - - - - - + + + + + diff --git a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj index b9f7877..dfd424a 100644 --- a/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj +++ b/src/KITT.Cms.Web.Api/KITT.Cms.Web.Api.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor index 56c263b..e693635 100644 --- a/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor +++ b/src/KITT.Cms.Web.App/Components/ChannelFormPanel.razor @@ -8,7 +8,7 @@ - - + /// Looks up a localized string similar to Name. + /// + public static string ChannelNameLabel { + get { + return ResourceManager.GetString("ChannelNameLabel", resourceCulture); + } + } + /// /// Looks up a localized string similar to Error saving the channel. /// @@ -78,6 +87,24 @@ public static string ChannelSavedSuccessMessage { } } + /// + /// Looks up a localized string similar to Channel type. + /// + public static string ChannelTypeLabel { + get { + return ResourceManager.GetString("ChannelTypeLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Url. + /// + public static string ChannelUrlLabel { + get { + return ResourceManager.GetString("ChannelUrlLabel", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close. /// diff --git a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx index 6dd3a94..a95de29 100644 --- a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx +++ b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.it.resx @@ -117,12 +117,21 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Nome + Errore durante il salvataggio del canale Canale salvato correttamente + + Tipologia + + + Url + Chiudi diff --git a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx index 29d87f4..43a34ab 100644 --- a/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx +++ b/src/KITT.Cms.Web.App/Resources/Components/ChannelFormPanel.resx @@ -117,12 +117,21 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Name + Error saving the channel Channel saved correctly + + Channel type + + + Url + Close diff --git a/src/KITT.Core/KITT.Core.csproj b/src/KITT.Core/KITT.Core.csproj index 30cc2de..08ff8a9 100644 --- a/src/KITT.Core/KITT.Core.csproj +++ b/src/KITT.Core/KITT.Core.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj index 0b40c4d..0877781 100644 --- a/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj +++ b/src/KITT.Proposals.Web.Api/KITT.Proposals.Web.Api.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj index eb38f26..1983e04 100644 --- a/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj +++ b/src/KITT.Support.Seeder/KITT.Support.Seeder.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj index a9f26c5..42d4668 100644 --- a/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj +++ b/src/KITT.Web.App/KITT.Web.App/KITT.Web.App.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/KITT.Web.Shared/KITT.Web.Shared.csproj b/src/KITT.Web.Shared/KITT.Web.Shared.csproj index c44acda..6d4479c 100644 --- a/src/KITT.Web.Shared/KITT.Web.Shared.csproj +++ b/src/KITT.Web.Shared/KITT.Web.Shared.csproj @@ -7,10 +7,10 @@ - + - + From 0b5f47dfa8d99d88837bd3ae84b5b7af13c53164 Mon Sep 17 00:00:00 2001 From: albx Date: Tue, 7 Apr 2026 07:39:07 +0200 Subject: [PATCH 26/26] #124 - fix comments post review --- src/KITT.Cms.Settings/ConnectedChannelsRepository.cs | 1 + src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs | 2 +- src/KITT.Cms.Web.Api/Program.cs | 4 ---- src/KITT.Cms.Web.App/Components/StreamingForm.razor | 8 ++++---- src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs | 2 +- .../Pages/Streamings/StreamingDetail.razor | 4 ++-- .../Streamings/ImportStreamingModel.cs | 2 +- src/KITT.Core/Models/Streaming.cs | 2 +- tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs | 2 +- 9 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs index 80895b2..d6adf7a 100644 --- a/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs +++ b/src/KITT.Cms.Settings/ConnectedChannelsRepository.cs @@ -11,6 +11,7 @@ public class ConnectedChannelsRepository : IConnectedChannelsRepository public ConnectedChannelsRepository(TableServiceClient tableServiceClient) { + ArgumentNullException.ThrowIfNull(tableServiceClient); _tableClient = CreateTableIfNotExist(tableServiceClient) ?? throw new ArgumentNullException("tableClient"); } diff --git a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs index 02850f6..2414a69 100644 --- a/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs +++ b/src/KITT.Cms.Web.Api/Endpoints/SettingsEndpoints.cs @@ -96,7 +96,7 @@ private static async Task> DeleteChannel( + private static async Task DeleteChannel( ChannelsEndpointsServices services, ClaimsPrincipal user, Guid id) diff --git a/src/KITT.Cms.Web.Api/Program.cs b/src/KITT.Cms.Web.Api/Program.cs index 6fcd02f..5ec12fe 100644 --- a/src/KITT.Cms.Web.Api/Program.cs +++ b/src/KITT.Cms.Web.Api/Program.cs @@ -72,7 +72,3 @@ .MapSettingsEndpoints(); app.Run(); - -#region Testing workaround -public partial class Program { } // This is a workaround for testing purposes, to allow the test project to reference the Program class. -#endregion \ No newline at end of file diff --git a/src/KITT.Cms.Web.App/Components/StreamingForm.razor b/src/KITT.Cms.Web.App/Components/StreamingForm.razor index 126ab79..7148c23 100644 --- a/src/KITT.Cms.Web.App/Components/StreamingForm.razor +++ b/src/KITT.Cms.Web.App/Components/StreamingForm.razor @@ -11,8 +11,8 @@ Items="availableTwitchChannels" Appearance="Appearance.Filled" Style="width:100%" - OptionValue="@(c => c.Url)" - OptionText="@(c => $"{c.Name} ({c.Url})")" + OptionValue="@(c => c?.Url)" + OptionText="@(c => c is null ? string.Empty : $"{c.Name} ({c.Url})")" @bind-Value="streaming.TwitchChannel"/> @@ -22,8 +22,8 @@ Items="availableYouTubeChannels" Appearance="Appearance.Filled" Style="width:100%" - OptionValue="@(c => c.Url)" - OptionText="@(c => $"{c.Name} ({c.Url})")" + OptionValue="@(c => c?.Url)" + OptionText="@(c => c is null ? string.Empty : $"{c.Name} ({c.Url})")" @bind-Value="streaming.YouTubeChannel" /> diff --git a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs index 4664188..0bd4e53 100644 --- a/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs +++ b/src/KITT.Cms.Web.App/Pages/Settings/Channels.razor.cs @@ -110,7 +110,7 @@ private async Task DeleteChannelAsync(ChannelModel channel) var confirm = await dialogService.ShowConfirmationAsync( localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmMessage)], - title: localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmTitle)], + title: localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmTitle), channelName], primaryText: localizer[nameof(Resources.Pages.Settings.Channels.DeleteChannelConfirmPrimaryButtonText)]); var result = await confirm.Result; diff --git a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor index de63153..b0b5191 100644 --- a/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor +++ b/src/KITT.Cms.Web.App/Pages/Streamings/StreamingDetail.razor @@ -39,8 +39,8 @@ Items="availableTwitchChannels" Appearance="Appearance.Filled" Style="width:100%" - OptionValue="@(c => c.Url)" - OptionText="@(c => $"{c.Name} ({c.Url})")" + OptionValue="@(c => c?.Url)" + OptionText="@(c => c is null ? string.Empty : $"{c.Name} ({c.Url})")" @bind-Value="streaming.TwitchChannel" Disabled="@isReadOnly"/> diff --git a/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs b/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs index 8fe4671..0f83aa3 100644 --- a/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs +++ b/src/KITT.Cms.Web.Models/Streamings/ImportStreamingModel.cs @@ -2,7 +2,7 @@ namespace KITT.Cms.Web.Models.Streamings; -public record ImportStreamingModel +public record ImportStreamingModel : IValidatableObject { public string TwitchChannel { get; set; } = string.Empty; diff --git a/src/KITT.Core/Models/Streaming.cs b/src/KITT.Core/Models/Streaming.cs index 17a479a..16dda70 100644 --- a/src/KITT.Core/Models/Streaming.cs +++ b/src/KITT.Core/Models/Streaming.cs @@ -139,7 +139,7 @@ public static Streaming Import(string title, string slug, string twitchChannel, } if (!string.IsNullOrWhiteSpace(youTubeChannel) && string.IsNullOrWhiteSpace(youTubeUrl)) { - throw new ArgumentException("value cannot be empty", nameof(twitchUrl)); + throw new ArgumentException("value cannot be empty", nameof(youTubeChannel)); } if (string.IsNullOrWhiteSpace(userId)) diff --git a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs index 1b05e94..40cb50f 100644 --- a/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs +++ b/tests/KITT.Core.Test/Commands/StreamingCommandsTest.cs @@ -113,7 +113,7 @@ public async Task ScheduleStreamingAsync_Should_Add_Streaming_With_Specified_Val TimeOnly startingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(16)); TimeOnly endingTime = TimeOnly.FromTimeSpan(TimeSpan.FromHours(18)); string twitchUrl = "https://www.twitch.tv/albx87"; - string youTubeUrl = "https://www.twitch.tv/@albx87"; + string youTubeUrl = "https://www.youtube.com/@albx87"; string streamingAbstract = "streaming abstract"; var seo = new Content.SeoData();