diff --git a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs similarity index 90% rename from src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs rename to src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs index e63713d..c065a62 100644 --- a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs +++ b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs @@ -12,7 +12,7 @@ using MissionControl.Data; namespace MissionControl.Data.Migrations { [DbContext(typeof(MissionControlContext))] - [Migration("20260727193151_Add_MissionLaunches")] + [Migration("20260727222052_Add_MissionLaunches")] partial class Add_MissionLaunches { /// @@ -75,8 +75,7 @@ namespace MissionControl.Data.Migrations b.HasKey("Id"); - b.HasIndex("MissionId") - .IsUnique(); + b.HasIndex("MissionId"); b.ToTable("MissionLaunches"); }); @@ -84,8 +83,8 @@ namespace MissionControl.Data.Migrations modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b => { b.HasOne("MissionControl.Domain.Entities.Mission", "Mission") - .WithOne("MissionLaunch") - .HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId") + .WithMany("MissionLaunches") + .HasForeignKey("MissionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -94,7 +93,7 @@ namespace MissionControl.Data.Migrations modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b => { - b.Navigation("MissionLaunch"); + b.Navigation("MissionLaunches"); }); #pragma warning restore 612, 618 } diff --git a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs similarity index 96% rename from src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs rename to src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs index da53e03..5e9d5ee 100644 --- a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs +++ b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs @@ -35,8 +35,7 @@ namespace MissionControl.Data.Migrations migrationBuilder.CreateIndex( name: "IX_MissionLaunches_MissionId", table: "MissionLaunches", - column: "MissionId", - unique: true); + column: "MissionId"); } /// diff --git a/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs b/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs index cc18c8c..363de12 100644 --- a/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs +++ b/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs @@ -72,8 +72,7 @@ namespace MissionControl.Data.Migrations b.HasKey("Id"); - b.HasIndex("MissionId") - .IsUnique(); + b.HasIndex("MissionId"); b.ToTable("MissionLaunches"); }); @@ -81,8 +80,8 @@ namespace MissionControl.Data.Migrations modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b => { b.HasOne("MissionControl.Domain.Entities.Mission", "Mission") - .WithOne("MissionLaunch") - .HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId") + .WithMany("MissionLaunches") + .HasForeignKey("MissionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -91,7 +90,7 @@ namespace MissionControl.Data.Migrations modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b => { - b.Navigation("MissionLaunch"); + b.Navigation("MissionLaunches"); }); #pragma warning restore 612, 618 } diff --git a/src/MissionControl.Data/MissionControlContext.cs b/src/MissionControl.Data/MissionControlContext.cs index 4cf14d9..c5637e0 100644 --- a/src/MissionControl.Data/MissionControlContext.cs +++ b/src/MissionControl.Data/MissionControlContext.cs @@ -12,9 +12,10 @@ public class MissionControlContext(DbContextOptions optio protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() - .HasOne(mission => mission.MissionLaunch) + .HasMany(mission => mission.MissionLaunches) .WithOne(missionLaunch => missionLaunch.Mission) - .HasForeignKey(missionLaunch => missionLaunch.MissionId); + .HasForeignKey(missionLaunch => missionLaunch.MissionId) + .IsRequired(); modelBuilder.ApplyConfigurationsFromAssembly(typeof(MissionControlContext).Assembly); } diff --git a/src/MissionControl.Domain/Entities/Mission.cs b/src/MissionControl.Domain/Entities/Mission.cs index 2114f44..99651d9 100644 --- a/src/MissionControl.Domain/Entities/Mission.cs +++ b/src/MissionControl.Domain/Entities/Mission.cs @@ -12,5 +12,5 @@ public class Mission public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow; - public MissionLaunch? MissionLaunch { get; set; } + public ICollection MissionLaunches { get; set; } = new List(); } diff --git a/src/MissionControl.Server/Endpoints/Missions/Contract.cs b/src/MissionControl.Server/Endpoints/Missions/Contract.cs index d5f8062..5c6b830 100644 --- a/src/MissionControl.Server/Endpoints/Missions/Contract.cs +++ b/src/MissionControl.Server/Endpoints/Missions/Contract.cs @@ -15,7 +15,7 @@ public record MissionResponse public required DateTimeOffset CreatedAt { get; init; } - public MissionLaunchResponse? MissionLaunch { get; set; } + public IReadOnlyList MissionLaunches { get; set; } = []; public static MissionResponse FromDomain(Mission mission) => new() @@ -25,6 +25,6 @@ public record MissionResponse Description = mission.Description, Status = mission.Status, CreatedAt = mission.CreatedAt, - MissionLaunch = mission.MissionLaunch != null ? MissionLaunchResponse.FromDomain(mission.MissionLaunch) : null, + MissionLaunches = mission.MissionLaunches.Select(MissionLaunchResponse.FromDomain).ToList(), }; } diff --git a/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs b/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs index ef20adb..b07c3dd 100644 --- a/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs +++ b/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs @@ -16,7 +16,7 @@ public class ListMissions(MissionControlContext dbContext) { var missions = await dbContext.Missions .AsNoTracking() - .Include(m => m.MissionLaunch) + .Include(m => m.MissionLaunches) .OrderByDescending(m => m.CreatedAt) .ToListAsync(ct); diff --git a/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs b/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs index 29bcd9c..fa66805 100644 --- a/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs +++ b/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs @@ -1,6 +1,5 @@ using FastEndpoints; using FluentValidation; -using Microsoft.AspNetCore.Mvc; using MissionControl.Data; using MissionControl.Domain.Entities; diff --git a/src/mission-control-client/src/api/missions.ts b/src/mission-control-client/src/api/missions.ts index 542db50..4cc1632 100644 --- a/src/mission-control-client/src/api/missions.ts +++ b/src/mission-control-client/src/api/missions.ts @@ -9,7 +9,7 @@ export type Mission = { description: string | null; status: MissionStatus; createdAt: string; - missionLaunch: MissionLaunch | null; + missionLaunches: MissionLaunch[]; }; export type CreateMissionRequest = {