From 2f86ece0e58bf4241554708c60cf57bef394fd22 Mon Sep 17 00:00:00 2001 From: Sara Gowen <9001998+dynamictulip@users.noreply.github.com> Date: Thu, 17 Apr 2025 23:51:32 +0100 Subject: [PATCH 1/3] Add healthchecks to API --- .../PocketDDD.Server.WebAPI.csproj | 39 ++++++++++--------- .../PocketDDD.Server.WebAPI/Program.cs | 27 +++++++------ 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/PocketDDD.Server/PocketDDD.Server.WebAPI/PocketDDD.Server.WebAPI.csproj b/PocketDDD.Server/PocketDDD.Server.WebAPI/PocketDDD.Server.WebAPI.csproj index c44ada4..0e212e9 100644 --- a/PocketDDD.Server/PocketDDD.Server.WebAPI/PocketDDD.Server.WebAPI.csproj +++ b/PocketDDD.Server/PocketDDD.Server.WebAPI/PocketDDD.Server.WebAPI.csproj @@ -1,25 +1,26 @@ - - net8.0 - enable - enable - 94f2b34d-f80b-4de4-ac9c-d0fb8e36fd07 - + + net8.0 + enable + enable + 94f2b34d-f80b-4de4-ac9c-d0fb8e36fd07 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - - - - - - + + + + + + diff --git a/PocketDDD.Server/PocketDDD.Server.WebAPI/Program.cs b/PocketDDD.Server/PocketDDD.Server.WebAPI/Program.cs index 8496f23..6bb707f 100644 --- a/PocketDDD.Server/PocketDDD.Server.WebAPI/Program.cs +++ b/PocketDDD.Server/PocketDDD.Server.WebAPI/Program.cs @@ -3,29 +3,30 @@ using PocketDDD.Server.Services; using PocketDDD.Server.WebAPI.Authentication; -string corsPolicy = "corsPolicy"; +var corsPolicy = "corsPolicy"; var builder = WebApplication.CreateBuilder(args); // Add services to the container. - builder.Services.AddControllers(); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddCors(options => { options.AddPolicy(corsPolicy, - builder => - { - builder.AllowAnyHeader() - .AllowAnyMethod() - .AllowAnyOrigin(); - }); + builder => + { + builder.AllowAnyHeader() + .AllowAnyMethod() + .AllowAnyOrigin(); + }); }); builder.Services.AddDbContext( - options => options.UseSqlServer("name=ConnectionStrings:PocketDDDContext")); + options => options.UseSqlServer("name=ConnectionStrings:PocketDDDContext") +); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -37,7 +38,10 @@ builder.Services.AddHttpClient(); builder.Services.AddAuthentication() - .AddScheme(UserIsRegisteredAuthHandler.SchemeName, null); + .AddScheme(UserIsRegisteredAuthHandler.SchemeName, null); + +builder.Services.AddHealthChecks() + .AddDbContextCheck(); var app = builder.Build(); @@ -55,5 +59,6 @@ app.UseAuthorization(); app.MapControllers(); +app.MapHealthChecks("/healthz"); -app.Run(); +app.Run(); \ No newline at end of file From b313ece99f4b46ccf7aef5d6b098a9cbfe5821e2 Mon Sep 17 00:00:00 2001 From: Sara Gowen <9001998+dynamictulip@users.noreply.github.com> Date: Thu, 17 Apr 2025 23:52:19 +0100 Subject: [PATCH 2/3] Split out fake API --- .../Services/FakePocketDDDApiService.cs | 113 +++++++++++++++++ .../Services/PocketDDDApiService.cs | 114 +----------------- 2 files changed, 114 insertions(+), 113 deletions(-) create mode 100644 PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/FakePocketDDDApiService.cs diff --git a/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/FakePocketDDDApiService.cs b/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/FakePocketDDDApiService.cs new file mode 100644 index 0000000..7bd31e8 --- /dev/null +++ b/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/FakePocketDDDApiService.cs @@ -0,0 +1,113 @@ +using PocketDDD.Shared.API.RequestDTOs; +using PocketDDD.Shared.API.ResponseDTOs; + +namespace PocketDDD.BlazorClient.Services; + +public class FakePocketDDDApiService : IPocketDDDApiService +{ + public Task Login(string name) + { + return Task.FromResult(new LoginResultDTO(name, Guid.NewGuid().ToString())); + } + + public void SetUserAuthToken(string token) + { + } + + public async Task FetchLatestEventData(EventDataUpdateRequestDTO requestDTO) + { + if (requestDTO.Version == 1) + { + await Task.Delay(1000); + return null; + } + + return + new EventDataResponseDTO + { + Version = 1, + TimeSlots = new[] + { + new TimeSlotDTO + { + Id = 1, + From = new DateTimeOffset(2023, 4, 29, 8, 00, 0, TimeSpan.Zero), + To = new DateTimeOffset(2023, 4, 29, 8, 30, 0, TimeSpan.Zero), + Info = "Registration" + }, + new TimeSlotDTO + { + Id = 2, + From = new DateTimeOffset(2023, 4, 29, 8, 30, 0, TimeSpan.Zero), + To = new DateTimeOffset(2023, 4, 29, 9, 0, 0, TimeSpan.Zero), + Info = "Intro" + }, + new TimeSlotDTO + { + Id = 3, + From = new DateTimeOffset(2023, 4, 29, 9, 00, 0, TimeSpan.Zero), + To = new DateTimeOffset(2023, 4, 29, 10, 00, 0, TimeSpan.Zero) + }, + new TimeSlotDTO + { + Id = 4, + From = new DateTimeOffset(2023, 4, 29, 10, 0, 0, TimeSpan.Zero), + To = new DateTimeOffset(2023, 4, 29, 10, 20, 0, TimeSpan.Zero), + Info = "Coffee" + }, + new TimeSlotDTO + { + Id = 5, + From = new DateTimeOffset(2023, 4, 29, 10, 20, 0, TimeSpan.Zero), + To = new DateTimeOffset(2023, 4, 29, 11, 20, 0, TimeSpan.Zero) + } + }, + Tracks = new[] + { + new TrackDTO { Id = 1, Name = "Track 1", RoomName = "Room 1" }, + new TrackDTO { Id = 2, Name = "Track 2", RoomName = "Room 2" }, + new TrackDTO { Id = 3, Name = "Track 3", RoomName = "Room 3" } + }, + Sessions = new[] + { + new SessionDTO + { + Id = 1, + FullDescription = "Some full desk", + Speaker = "Ross", + TimeSlotId = 3, + TrackId = 1, + Title = "Blazor Session Management" + }, + new SessionDTO + { + Id = 2, + FullDescription = "Second session", + Speaker = "Jim", + TimeSlotId = 3, + TrackId = 2, + Title = "How to code" + }, + new SessionDTO + { + Id = 3, + FullDescription = "Third session", + Speaker = "Bob", + TimeSlotId = 5, + TrackId = 2, + Title = "Off by 1" + } + } + }; + } + + public Task SubmitClientEventFeedback(SubmitEventFeedbackDTO feedbackDTO) + { + return Task.FromResult(new FeedbackResponseDTO { ClientId = feedbackDTO.ClientId, Score = 2 }); + } + + public Task SubmitClientSessionFeedback(SubmitSessionFeedbackDTO feedbackDTO) + { + return Task.FromResult(new FeedbackResponseDTO { ClientId = feedbackDTO.ClientId, Score = 3 }); + } +} \ No newline at end of file diff --git a/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/PocketDDDApiService.cs b/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/PocketDDDApiService.cs index 15cb759..7fada2e 100644 --- a/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/PocketDDDApiService.cs +++ b/PocketDDD.BlazorClient/PocketDDD.BlazorClient/Services/PocketDDDApiService.cs @@ -1,9 +1,7 @@ using System.Net; -using System.Net.Http.Headers; using System.Net.Http.Json; -using MudBlazor; -using PocketDDD.Shared.API.ResponseDTOs; using PocketDDD.Shared.API.RequestDTOs; +using PocketDDD.Shared.API.ResponseDTOs; namespace PocketDDD.BlazorClient.Services; @@ -60,114 +58,4 @@ public async Task SubmitClientSessionFeedback(SubmitSession var response = await _http.PostAsJsonAsync("Feedback/ClientSessionFeedback", feedbackDTO); return (await response.Content.ReadFromJsonAsync())!; } -} - -public class FakePocketDDDApiService : IPocketDDDApiService -{ - public Task Login(string name) - { - return Task.FromResult(new LoginResultDTO(name, Guid.NewGuid().ToString())); - } - - public void SetUserAuthToken(string token) - { - - } - - public async Task FetchLatestEventData(EventDataUpdateRequestDTO requestDTO) - { - if (requestDTO.Version == 1) - { - await Task.Delay(1000); - return null; - } - - return - new EventDataResponseDTO - { - Version = 1, - TimeSlots = new[] - { - new TimeSlotDTO - { - Id = 1, - From = new DateTimeOffset(2023, 4, 29, 8, 00, 0, TimeSpan.Zero), - To = new DateTimeOffset(2023, 4, 29, 8, 30, 0, TimeSpan.Zero), - Info = "Registration" - }, - new TimeSlotDTO - { - Id = 2, - From = new DateTimeOffset(2023, 4, 29, 8, 30, 0, TimeSpan.Zero), - To = new DateTimeOffset(2023, 4, 29, 9, 0, 0, TimeSpan.Zero), - Info = "Intro" - }, - new TimeSlotDTO - { - Id = 3, - From = new DateTimeOffset(2023, 4, 29, 9, 00, 0, TimeSpan.Zero), - To = new DateTimeOffset(2023, 4, 29, 10, 00, 0, TimeSpan.Zero) - }, - new TimeSlotDTO - { - Id = 4, - From = new DateTimeOffset(2023, 4, 29, 10, 0, 0, TimeSpan.Zero), - To = new DateTimeOffset(2023, 4, 29, 10, 20, 0, TimeSpan.Zero), - Info = "Coffee" - }, - new TimeSlotDTO - { - Id = 5, - From = new DateTimeOffset(2023, 4, 29, 10, 20, 0, TimeSpan.Zero), - To = new DateTimeOffset(2023, 4, 29, 11, 20, 0, TimeSpan.Zero) - }, - }, - Tracks = new[] - { - new TrackDTO { Id = 1, Name = "Track 1", RoomName = "Room 1" }, - new TrackDTO { Id = 2, Name = "Track 2", RoomName = "Room 2" }, - new TrackDTO { Id = 3, Name = "Track 3", RoomName = "Room 3" } - }, - Sessions = new[] - { - new SessionDTO - { - Id = 1, - FullDescription = "Some full desk", - Speaker = "Ross", - TimeSlotId = 3, - TrackId = 1, - Title = "Blazor Session Management" - }, - new SessionDTO - { - Id = 2, - FullDescription = "Second session", - Speaker = "Jim", - TimeSlotId = 3, - TrackId = 2, - Title = "How to code" - }, - new SessionDTO - { - Id = 3, - FullDescription = "Third session", - Speaker = "Bob", - TimeSlotId = 5, - TrackId = 2, - Title = "Off by 1" - }, - } - }; - } - - public Task SubmitClientEventFeedback(SubmitEventFeedbackDTO feedbackDTO) - { - return Task.FromResult(new FeedbackResponseDTO { ClientId = feedbackDTO.ClientId, Score = 2 }); - } - - public Task SubmitClientSessionFeedback(SubmitSessionFeedbackDTO feedbackDTO) - { - return Task.FromResult(new FeedbackResponseDTO { ClientId = feedbackDTO.ClientId, Score = 3 }); - } } \ No newline at end of file From 0408846d349d8b0c53d3879aa711f809aec629c5 Mon Sep 17 00:00:00 2001 From: Sara Gowen <9001998+dynamictulip@users.noreply.github.com> Date: Fri, 18 Apr 2025 00:14:48 +0100 Subject: [PATCH 3/3] Add seed data for 2025 and pull breaks from sessionize --- .../Migrations/2025_SeedData.sql | 29 +++++++++++++++++++ .../Sessionize/ApiDTOs.cs | 2 +- .../SessionizeService.cs | 27 +++++++++++------ 3 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 PocketDDD.Server/PocketDDD.Server.DB/Migrations/2025_SeedData.sql diff --git a/PocketDDD.Server/PocketDDD.Server.DB/Migrations/2025_SeedData.sql b/PocketDDD.Server/PocketDDD.Server.DB/Migrations/2025_SeedData.sql new file mode 100644 index 0000000..6eb2316 --- /dev/null +++ b/PocketDDD.Server/PocketDDD.Server.DB/Migrations/2025_SeedData.sql @@ -0,0 +1,29 @@ +-- Before running this script, ensure that FullDBScript.sql has been run to create the tables + +-- Remove all the data +delete [UserSessionFeedback] +delete [UserEventFeedback] +delete [Sessions] +delete TimeSlots +delete Tracks +delete EventDetail + + +GO + +-- Reset the identity columns +DBCC CHECKIDENT ('[Tracks]', RESEED, 0); +DBCC CHECKIDENT ('[TimeSlots]', RESEED, 0); +DBCC CHECKIDENT ('[Sessions]', RESEED, 0); + +-- There is hardcoding to EventDetail ID 1 so we reset to 1 not 0 +DBCC CHECKIDENT ('[EventDetail]', RESEED, 1); -- Use if this is a brand new table that has never been used before +--DBCC CHECKIDENT ('[EventDetail]', RESEED, 0); -- Use if this is an empty table that used to have rows + +GO + +-- Add 2025 Sessionize ID +Insert into EventDetail +values (1, '8oswqcwt') + +GO diff --git a/PocketDDD.Server/PocketDDD.Server.Model/Sessionize/ApiDTOs.cs b/PocketDDD.Server/PocketDDD.Server.Model/Sessionize/ApiDTOs.cs index f2b5645..a472907 100644 --- a/PocketDDD.Server/PocketDDD.Server.Model/Sessionize/ApiDTOs.cs +++ b/PocketDDD.Server/PocketDDD.Server.Model/Sessionize/ApiDTOs.cs @@ -55,7 +55,7 @@ public class SessionizeEvent public class Session { - public int id { get; set; } + public string id { get; set; } public string title { get; set; } public string description { get; set; } public DateTime startsAt { get; set; } diff --git a/PocketDDD.Server/PocketDDD.Server.Services/SessionizeService.cs b/PocketDDD.Server/PocketDDD.Server.Services/SessionizeService.cs index 6aa07fe..3f0a9ee 100644 --- a/PocketDDD.Server/PocketDDD.Server.Services/SessionizeService.cs +++ b/PocketDDD.Server/PocketDDD.Server.Services/SessionizeService.cs @@ -5,6 +5,7 @@ using System.Net.Http.Json; namespace PocketDDD.Server.Services; + public class SessionizeService { private readonly HttpClient httpClient; @@ -50,7 +51,8 @@ public async Task UpdateFromSessionize() var dbTimeSlots = await dbContext.TimeSlots.ToListAsync(); var sessionizeTimeSlots = sessionizeEvent.sessions - .Select(x => (x.startsAt, x.endsAt)) + .Select(x => (x.startsAt, x.endsAt, x.isServiceSession, + serviceSessionDetails: x.isServiceSession ? x.title : null)) .Distinct() .ToList(); @@ -64,7 +66,7 @@ public async Task UpdateFromSessionize() EventDetail = dbEvent, From = item.startsAt, To = item.endsAt, - Info = null + Info = item.isServiceSession ? item.serviceSessionDetails : null }; dbContext.TimeSlots.Add(dbTimeSlot); } @@ -80,12 +82,16 @@ public async Task UpdateFromSessionize() foreach (var item in sessionizeEvent.sessions) { - var dbSession = dbSessions.SingleOrDefault(x => x.SessionizeId == item.id); + if (item.isServiceSession) continue; + + var sessionizeId = int.Parse(item.id); + + var dbSession = dbSessions.SingleOrDefault(x => x.SessionizeId == sessionizeId); if (dbSession == null) { dbSession = new Model.DBModel.Session { - SessionizeId = item.id, + SessionizeId = sessionizeId, EventDetail = dbEvent, SpeakerToken = Guid.NewGuid(), ShortDescription = "" @@ -103,10 +109,13 @@ public async Task UpdateFromSessionize() await dbContext.SaveChangesAsync(); } - private string GetSpeakers(List speakers, List speakerIds) - => speakerIds.Aggregate("", (acc, x) => acc + ", " + speakers.Single(s => s.id == x).fullName).Trim(','); + private string GetSpeakers(List speakers, List speakerIds) + { + return speakerIds.Aggregate("", (acc, x) => acc + ", " + speakers.Single(s => s.id == x).fullName).Trim(','); + } private TimeSlot GetTimeSlot(List timeSlots, DateTime startsAt, DateTime endsAt) - => timeSlots.Single(x => x.From == startsAt && x.To == endsAt); - -} + { + return timeSlots.Single(x => x.From == startsAt && x.To == endsAt); + } +} \ No newline at end of file