Add hero image support for registries
- Registry entity and DB updated with hero image fields - Admin UI: upload, preview, remove hero image with validation - Public registry page displays hero image if present - View models and RegistryService handle hero image data (base64) - Localization updated for hero image UI strings - Minor: Fix ShowCreateForm property in Home.razor
This commit is contained in:
@@ -7,6 +7,8 @@ public class Registry
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public DateOnly? BirthDate { get; set; }
|
||||
public string? BabyName { get; set; }
|
||||
public byte[]? HeroImageData { get; set; }
|
||||
public string? HeroImageContentType { get; set; }
|
||||
public string? HeaderContentHtml { get; set; }
|
||||
public string? ShippingAddress { get; set; }
|
||||
public string CurrencyCode { get; set; } = "EUR";
|
||||
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using BirthList.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BirthList.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(RegistryDbContext))]
|
||||
[Migration("20260517000000_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.26")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemContribution", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<DateTimeOffset>("ContributedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<Guid>("RegistryItemId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("TransferMessage")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryItemId");
|
||||
|
||||
b.ToTable("ItemContributions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemPurchase", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("PurchasedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("RegistryItemId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryItemId");
|
||||
|
||||
b.ToTable("ItemPurchases");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.PlatformOwner", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("AssignedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("PlatformOwners");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.Registry", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("BabyName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<DateOnly?>("BirthDate")
|
||||
.HasColumnType("date");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<string>("HeaderContentHtml")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("PublicLinkCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<int>("RegistryType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ShippingAddress")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ThemeKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(250)
|
||||
.HasColumnType("nvarchar(250)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PublicLinkCode")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Registries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdmin", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("AddedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.HasKey("RegistryId", "UserId");
|
||||
|
||||
b.ToTable("RegistryAdmins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdminInvite", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<DateTimeOffset?>("RedeemedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("SentToEmail")
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("nvarchar(320)");
|
||||
|
||||
b.Property<string>("Token")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("nvarchar(120)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId");
|
||||
|
||||
b.HasIndex("Token")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RegistryAdminInvites");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<bool>("CanBeSecondHand")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<int>("DesiredQuantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IsGiven")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<decimal>("MoneyFulfilledAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("nvarchar(300)");
|
||||
|
||||
b.Property<bool>("ParticipationAllowed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<decimal?>("ParticipationTargetAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("PictureUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("nvarchar(2048)");
|
||||
|
||||
b.Property<decimal?>("PriceAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("ProductUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("nvarchar(2048)");
|
||||
|
||||
b.Property<int>("PurchasedQuantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId");
|
||||
|
||||
b.ToTable("RegistryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistrySettings", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("BankAccountBic")
|
||||
.HasMaxLength(11)
|
||||
.HasColumnType("nvarchar(11)");
|
||||
|
||||
b.Property<string>("BankAccountDisplayName")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("nvarchar(120)");
|
||||
|
||||
b.Property<string>("BankAccountIban")
|
||||
.HasMaxLength(34)
|
||||
.HasColumnType("nvarchar(34)");
|
||||
|
||||
b.HasKey("RegistryId");
|
||||
|
||||
b.ToTable("RegistrySettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryVisit", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("LastVisitedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.HasKey("RegistryId", "UserId");
|
||||
|
||||
b.ToTable("RegistryVisits");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemContribution", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.RegistryItem", "RegistryItem")
|
||||
.WithMany("Contributions")
|
||||
.HasForeignKey("RegistryItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("RegistryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemPurchase", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.RegistryItem", "RegistryItem")
|
||||
.WithMany("Purchases")
|
||||
.HasForeignKey("RegistryItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("RegistryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdmin", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdminInvite", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("AdminInvites")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistrySettings", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithOne()
|
||||
.HasForeignKey("BirthList.Domain.Entities.RegistrySettings", "RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryVisit", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Visits")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.Registry", b =>
|
||||
{
|
||||
b.Navigation("AdminInvites");
|
||||
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("Items");
|
||||
|
||||
b.Navigation("Visits");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.Navigation("Contributions");
|
||||
|
||||
b.Navigation("Purchases");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BirthList.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PlatformOwners",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
AssignedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PlatformOwners", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Registries",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Title = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
|
||||
PublicLinkCode = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
BabyName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
BirthDate = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
RegistryType = table.Column<int>(type: "int", nullable: false),
|
||||
HeaderContentHtml = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
ShippingAddress = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
CurrencyCode = table.Column<string>(type: "nvarchar(3)", maxLength: 3, nullable: false),
|
||||
ThemeKey = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
CreatedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Registries", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RegistryAdmins",
|
||||
columns: table => new
|
||||
{
|
||||
RegistryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
AddedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RegistryAdmins", x => new { x.RegistryId, x.UserId });
|
||||
table.ForeignKey(
|
||||
name: "FK_RegistryAdmins_Registries_RegistryId",
|
||||
column: x => x.RegistryId,
|
||||
principalTable: "Registries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RegistryAdminInvites",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
RegistryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Token = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false),
|
||||
SentToEmail = table.Column<string>(type: "nvarchar(320)", maxLength: 320, nullable: true),
|
||||
ExpiresAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||
RedeemedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RegistryAdminInvites", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_RegistryAdminInvites_Registries_RegistryId",
|
||||
column: x => x.RegistryId,
|
||||
principalTable: "Registries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RegistryItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
RegistryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(300)", maxLength: 300, nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
PictureUrl = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
|
||||
ProductUrl = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
|
||||
CurrencyCode = table.Column<string>(type: "nvarchar(3)", maxLength: 3, nullable: false),
|
||||
PriceAmount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true),
|
||||
DesiredQuantity = table.Column<int>(type: "int", nullable: false),
|
||||
PurchasedQuantity = table.Column<int>(type: "int", nullable: false),
|
||||
ParticipationAllowed = table.Column<bool>(type: "bit", nullable: false),
|
||||
ParticipationTargetAmount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true),
|
||||
MoneyFulfilledAmount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
|
||||
CanBeSecondHand = table.Column<bool>(type: "bit", nullable: false),
|
||||
IsGiven = table.Column<bool>(type: "bit", nullable: false),
|
||||
CreatedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RegistryItems", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_RegistryItems_Registries_RegistryId",
|
||||
column: x => x.RegistryId,
|
||||
principalTable: "Registries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RegistrySettings",
|
||||
columns: table => new
|
||||
{
|
||||
RegistryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
BankAccountIban = table.Column<string>(type: "nvarchar(34)", maxLength: 34, nullable: true),
|
||||
BankAccountBic = table.Column<string>(type: "nvarchar(11)", maxLength: 11, nullable: true),
|
||||
BankAccountDisplayName = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RegistrySettings", x => x.RegistryId);
|
||||
table.ForeignKey(
|
||||
name: "FK_RegistrySettings_Registries_RegistryId",
|
||||
column: x => x.RegistryId,
|
||||
principalTable: "Registries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "RegistryVisits",
|
||||
columns: table => new
|
||||
{
|
||||
RegistryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
LastVisitedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_RegistryVisits", x => new { x.RegistryId, x.UserId });
|
||||
table.ForeignKey(
|
||||
name: "FK_RegistryVisits_Registries_RegistryId",
|
||||
column: x => x.RegistryId,
|
||||
principalTable: "Registries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ItemContributions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
RegistryItemId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
Amount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
|
||||
CurrencyCode = table.Column<string>(type: "nvarchar(3)", maxLength: 3, nullable: false),
|
||||
TransferMessage = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
|
||||
ContributedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ItemContributions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ItemContributions_RegistryItems_RegistryItemId",
|
||||
column: x => x.RegistryItemId,
|
||||
principalTable: "RegistryItems",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ItemPurchases",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
RegistryItemId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
Quantity = table.Column<int>(type: "int", nullable: false),
|
||||
PurchasedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ItemPurchases", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ItemPurchases_RegistryItems_RegistryItemId",
|
||||
column: x => x.RegistryItemId,
|
||||
principalTable: "RegistryItems",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ItemContributions_RegistryItemId",
|
||||
table: "ItemContributions",
|
||||
column: "RegistryItemId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ItemPurchases_RegistryItemId",
|
||||
table: "ItemPurchases",
|
||||
column: "RegistryItemId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PlatformOwners_UserId",
|
||||
table: "PlatformOwners",
|
||||
column: "UserId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Registries_PublicLinkCode",
|
||||
table: "Registries",
|
||||
column: "PublicLinkCode",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_RegistryAdminInvites_RegistryId",
|
||||
table: "RegistryAdminInvites",
|
||||
column: "RegistryId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_RegistryAdminInvites_Token",
|
||||
table: "RegistryAdminInvites",
|
||||
column: "Token",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_RegistryItems_RegistryId",
|
||||
table: "RegistryItems",
|
||||
column: "RegistryId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ItemContributions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ItemPurchases");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PlatformOwners");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RegistryAdminInvites");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RegistryAdmins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RegistryItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RegistrySettings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RegistryVisits");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Registries");
|
||||
}
|
||||
}
|
||||
}
|
||||
+559
@@ -0,0 +1,559 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using BirthList.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BirthList.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(RegistryDbContext))]
|
||||
[Migration("20260519130000_AddHeroImageToRegistry")]
|
||||
partial class AddHeroImageToRegistry
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.26")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemContribution", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<DateTimeOffset>("ContributedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<Guid>("RegistryItemId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("TransferMessage")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryItemId");
|
||||
|
||||
b.ToTable("ItemContributions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemPurchase", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("PurchasedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("RegistryItemId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryItemId");
|
||||
|
||||
b.ToTable("ItemPurchases");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.PlatformOwner", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("AssignedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("PlatformOwners");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.Registry", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("BabyName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<DateOnly?>("BirthDate")
|
||||
.HasColumnType("date");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<string>("HeaderContentHtml")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("HeroImageContentType")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<byte[]>("HeroImageData")
|
||||
.HasColumnType("varbinary(max)");
|
||||
|
||||
b.Property<string>("PublicLinkCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<int>("RegistryType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ShippingAddress")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ThemeKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(250)
|
||||
.HasColumnType("nvarchar(250)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PublicLinkCode")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Registries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdmin", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("AddedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.HasKey("RegistryId", "UserId");
|
||||
|
||||
b.ToTable("RegistryAdmins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdminInvite", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<DateTimeOffset?>("RedeemedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("SentToEmail")
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("nvarchar(320)");
|
||||
|
||||
b.Property<string>("Token")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("nvarchar(120)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId");
|
||||
|
||||
b.HasIndex("Token")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RegistryAdminInvites");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("CurrencyCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("nvarchar(3)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<int>("DesiredQuantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IsGiven")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<decimal>("MoneyFulfilledAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("nvarchar(300)");
|
||||
|
||||
b.Property<bool>("ParticipationAllowed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<decimal?>("ParticipationTargetAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("PictureUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("nvarchar(2048)");
|
||||
|
||||
b.Property<bool?>("PreferSecondHand")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<decimal?>("PriceAmount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<string>("ProductUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("nvarchar(2048)");
|
||||
|
||||
b.Property<int>("PurchasedQuantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId");
|
||||
|
||||
b.HasIndex("CategoryId", "SortOrder");
|
||||
|
||||
b.ToTable("RegistryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItemCategory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId", "Name");
|
||||
|
||||
b.HasIndex("RegistryId", "SortOrder");
|
||||
|
||||
b.ToTable("RegistryItemCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistrySettings", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("BankAccountBic")
|
||||
.HasMaxLength(11)
|
||||
.HasColumnType("nvarchar(11)");
|
||||
|
||||
b.Property<string>("BankAccountDisplayName")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("nvarchar(120)");
|
||||
|
||||
b.Property<string>("BankAccountIban")
|
||||
.HasMaxLength(34)
|
||||
.HasColumnType("nvarchar(34)");
|
||||
|
||||
b.Property<string>("ContributionAmountQrCodesJson")
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("nvarchar(4000)");
|
||||
|
||||
b.Property<string>("ContributionQrCodeUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("nvarchar(2048)");
|
||||
|
||||
b.Property<bool>("ShowBankAccountName")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.HasKey("RegistryId");
|
||||
|
||||
b.ToTable("RegistrySettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryVisit", b =>
|
||||
{
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<DateTimeOffset>("LastVisitedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.HasKey("RegistryId", "UserId");
|
||||
|
||||
b.ToTable("RegistryVisits");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.UserActionLog", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("ActionType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("decimal(18,2)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("Details")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("RegistryId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid?>("RegistryItemId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(450)
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RegistryId");
|
||||
|
||||
b.ToTable("UserActionLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemContribution", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.RegistryItem", "RegistryItem")
|
||||
.WithMany("Contributions")
|
||||
.HasForeignKey("RegistryItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("RegistryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.ItemPurchase", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.RegistryItem", "RegistryItem")
|
||||
.WithMany("Purchases")
|
||||
.HasForeignKey("RegistryItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("RegistryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdmin", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryAdminInvite", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("AdminInvites")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.RegistryItemCategory", "Category")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.NoAction)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItemCategory", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("ItemCategories")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistrySettings", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithOne()
|
||||
.HasForeignKey("BirthList.Domain.Entities.RegistrySettings", "RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryVisit", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("Visits")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.UserActionLog", b =>
|
||||
{
|
||||
b.HasOne("BirthList.Domain.Entities.Registry", "Registry")
|
||||
.WithMany("ActionLogs")
|
||||
.HasForeignKey("RegistryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Registry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.Registry", b =>
|
||||
{
|
||||
b.Navigation("ActionLogs");
|
||||
|
||||
b.Navigation("AdminInvites");
|
||||
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("ItemCategories");
|
||||
|
||||
b.Navigation("Items");
|
||||
|
||||
b.Navigation("Visits");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItem", b =>
|
||||
{
|
||||
b.Navigation("Contributions");
|
||||
|
||||
b.Navigation("Purchases");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BirthList.Domain.Entities.RegistryItemCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BirthList.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddHeroImageToRegistry : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "HeroImageData",
|
||||
table: "Registries",
|
||||
type: "varbinary(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "HeroImageContentType",
|
||||
table: "Registries",
|
||||
type: "nvarchar(100)",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "HeroImageData",
|
||||
table: "Registries");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "HeroImageContentType",
|
||||
table: "Registries");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,6 +135,13 @@ namespace BirthList.Infrastructure.Migrations
|
||||
b.Property<string>("HeaderContentHtml")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("HeroImageContentType")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<byte[]>("HeroImageData")
|
||||
.HasColumnType("varbinary(max)");
|
||||
|
||||
b.Property<string>("PublicLinkCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@page "/"
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@using BirthList.Web.Features.Registries
|
||||
|
||||
@@ -121,7 +122,7 @@
|
||||
protected IReadOnlyList<RegistrySummaryViewModel> MyRegistries { get; private set; } = [];
|
||||
protected IReadOnlyList<RegistrySummaryViewModel> VisitedRegistries { get; private set; } = [];
|
||||
protected string? ErrorMessage { get; private set; }
|
||||
protected bool ShowCreateForm { get; private set; }
|
||||
protected bool ShowCreateForm { get; set; }
|
||||
|
||||
[Inject] private RegistryService RegistryService { get; set; } = null!;
|
||||
[Inject] private RegistryUserContext RegistryUserContext { get; set; } = null!;
|
||||
|
||||
@@ -338,6 +338,28 @@ else
|
||||
<small class="form-text text-muted">@L["RegistryAdmin.LineBreaksPreserved"]</small>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<label class="form-label">@L["RegistryAdmin.HeroImage"]</label>
|
||||
@if (!string.IsNullOrWhiteSpace(SettingsModel.HeroImageBase64))
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">@L["RegistryAdmin.CurrentHeroImage"]</label>
|
||||
<div>
|
||||
<img src="data:@SettingsModel.HeroImageContentType;base64,@SettingsModel.HeroImageBase64" alt="Hero" class="img-thumbnail" style="max-height: 200px;" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger mt-2" @onclick="RemoveHeroImageAsync">@L["RegistryAdmin.RemoveHeroImage"]</button>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<label class="form-label small">@L["RegistryAdmin.UploadImage"]</label>
|
||||
<InputFile class="form-control" OnChange="OnHeroImageSelectedAsync" accept="image/*" />
|
||||
@if (!string.IsNullOrWhiteSpace(HeroImageUploadMessage))
|
||||
{
|
||||
<small class="text-muted">@HeroImageUploadMessage</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<label class="form-label">@L["RegistryAdmin.TopContent"]</label>
|
||||
<div class="editor-wrapper">
|
||||
|
||||
@@ -5,6 +5,7 @@ using BirthList.Web.Services;
|
||||
using Blazored.TextEditor;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
@@ -55,6 +56,7 @@ public partial class RegistryAdmin : ComponentBase
|
||||
protected string? InviteLink { get; private set; }
|
||||
protected BlazoredTextEditor? TextEditor { get; set; }
|
||||
protected string ActiveTab { get; set; } = "items";
|
||||
protected string? HeroImageUploadMessage { get; set; }
|
||||
protected RenderFragment ToolbarContent => builder =>
|
||||
{
|
||||
builder.AddMarkupContent(0, @"<span class='ql-formats'><select class='ql-size'><option value='small'></option><option selected></option><option value='large'></option><option value='huge'></option></select><select class='ql-header'><option selected></option><option value='1'></option><option value='2'></option><option value='3'></option><option value='4'></option><option value='5'></option></select></span>");
|
||||
@@ -805,4 +807,48 @@ public partial class RegistryAdmin : ComponentBase
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task OnHeroImageSelectedAsync(InputFileChangeEventArgs e)
|
||||
{
|
||||
HeroImageUploadMessage = null;
|
||||
|
||||
try
|
||||
{
|
||||
const long maxFileSize = 10 * 1024 * 1024; // 10 MB
|
||||
var file = e.File;
|
||||
|
||||
if (file.Size > maxFileSize)
|
||||
{
|
||||
HeroImageUploadMessage = $"File size exceeds maximum of 10 MB";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
HeroImageUploadMessage = "Only image files are allowed";
|
||||
return;
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
await file.OpenReadStream(maxFileSize).CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
|
||||
SettingsModel.HeroImageBase64 = Convert.ToBase64String(memoryStream.ToArray());
|
||||
SettingsModel.HeroImageContentType = file.ContentType;
|
||||
|
||||
HeroImageUploadMessage = "Image uploaded successfully. Click 'Save Settings' to apply.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HeroImageUploadMessage = $"Error uploading image: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
protected Task RemoveHeroImageAsync()
|
||||
{
|
||||
SettingsModel.HeroImageBase64 = string.Empty;
|
||||
SettingsModel.HeroImageContentType = null;
|
||||
HeroImageUploadMessage = "Image will be removed when you save settings.";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
else
|
||||
{
|
||||
<div class="registry-shell @RegistryThemeService.GetCssClass(Registry.RegistryType, Registry.ThemeKey)">
|
||||
@if (!string.IsNullOrWhiteSpace(Registry.HeroImageBase64))
|
||||
{
|
||||
<div class="hero-image-container mb-4">
|
||||
<img src="data:@Registry.HeroImageContentType;base64,@Registry.HeroImageBase64" alt="@Registry.Title" class="hero-image img-fluid w-100" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<h1>@(string.IsNullOrWhiteSpace(Registry.BabyName) ? Registry.Title : Registry.BabyName)</h1>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(Registry.HeaderContentHtml))
|
||||
|
||||
@@ -4,6 +4,20 @@
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.hero-image-container {
|
||||
margin: 0 -1rem;
|
||||
max-height: 400px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.hero-image {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
max-height: 400px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.item-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
|
||||
@@ -53,6 +53,8 @@ public sealed class RegistrySettingsEditModel
|
||||
{
|
||||
public string? BabyName { get; set; }
|
||||
public DateOnly? BirthDate { get; set; }
|
||||
public string? HeroImageBase64 { get; set; }
|
||||
public string? HeroImageContentType { get; set; }
|
||||
public string? HeaderContentHtml { get; set; }
|
||||
public string? ShippingAddress { get; set; }
|
||||
public string CurrencyCode { get; set; } = "€";
|
||||
@@ -80,6 +82,8 @@ public sealed class RegistryPublicViewModel
|
||||
public string Title { get; init; } = string.Empty;
|
||||
public string PublicLinkCode { get; init; } = string.Empty;
|
||||
public string? BabyName { get; init; }
|
||||
public string? HeroImageBase64 { get; init; }
|
||||
public string? HeroImageContentType { get; init; }
|
||||
public string? HeaderContentHtml { get; init; }
|
||||
public string? ShippingAddress { get; init; }
|
||||
public string CurrencyCode { get; init; } = "€";
|
||||
|
||||
@@ -299,6 +299,8 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
Title = registry.Title,
|
||||
PublicLinkCode = registry.PublicLinkCode,
|
||||
BabyName = registry.BabyName,
|
||||
HeroImageBase64 = registry.HeroImageData != null ? Convert.ToBase64String(registry.HeroImageData) : null,
|
||||
HeroImageContentType = registry.HeroImageContentType,
|
||||
HeaderContentHtml = registry.HeaderContentHtml,
|
||||
ShippingAddress = registry.ShippingAddress,
|
||||
CurrencyCode = registry.CurrencyCode,
|
||||
@@ -336,6 +338,8 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
{
|
||||
BabyName = registry.BabyName,
|
||||
BirthDate = registry.BirthDate,
|
||||
HeroImageBase64 = registry.HeroImageData != null ? Convert.ToBase64String(registry.HeroImageData) : null,
|
||||
HeroImageContentType = registry.HeroImageContentType,
|
||||
HeaderContentHtml = registry.HeaderContentHtml,
|
||||
ShippingAddress = registry.ShippingAddress,
|
||||
CurrencyCode = registry.CurrencyCode,
|
||||
@@ -372,6 +376,18 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
|
||||
registry.BabyName = string.IsNullOrWhiteSpace(model.BabyName) ? null : model.BabyName.Trim();
|
||||
registry.BirthDate = model.BirthDate;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.HeroImageBase64))
|
||||
{
|
||||
registry.HeroImageData = Convert.FromBase64String(model.HeroImageBase64);
|
||||
registry.HeroImageContentType = model.HeroImageContentType;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(model.HeroImageBase64) && model.HeroImageBase64 == string.Empty)
|
||||
{
|
||||
registry.HeroImageData = null;
|
||||
registry.HeroImageContentType = null;
|
||||
}
|
||||
|
||||
registry.HeaderContentHtml = string.IsNullOrWhiteSpace(model.HeaderContentHtml) ? null : model.HeaderContentHtml;
|
||||
registry.ShippingAddress = string.IsNullOrWhiteSpace(model.ShippingAddress) ? null : model.ShippingAddress.Trim();
|
||||
registry.CurrencyCode = NormalizeCurrencySymbol(model.CurrencyCode);
|
||||
|
||||
@@ -175,6 +175,10 @@
|
||||
<data name="RegistryAdmin.Theme.Modern" xml:space="preserve"><value>Moderne</value></data>
|
||||
<data name="RegistryAdmin.ShippingAddress" xml:space="preserve"><value>Adresse de livraison</value></data>
|
||||
<data name="RegistryAdmin.LineBreaksPreserved" xml:space="preserve"><value>Les sauts de ligne seront conservés</value></data>
|
||||
<data name="RegistryAdmin.HeroImage" xml:space="preserve"><value>Image héros</value></data>
|
||||
<data name="RegistryAdmin.UploadImage" xml:space="preserve"><value>Télécharger une image</value></data>
|
||||
<data name="RegistryAdmin.RemoveHeroImage" xml:space="preserve"><value>Supprimer l'image héros</value></data>
|
||||
<data name="RegistryAdmin.CurrentHeroImage" xml:space="preserve"><value>Image héros actuelle</value></data>
|
||||
<data name="RegistryAdmin.TopContent" xml:space="preserve"><value>Contenu d'en-tête</value></data>
|
||||
<data name="RegistryAdmin.WelcomeText" xml:space="preserve"><value>Texte d'accueil</value></data>
|
||||
<data name="RegistryAdmin.BankAccountSettings" xml:space="preserve"><value>Paramètres du compte bancaire</value></data>
|
||||
|
||||
@@ -175,6 +175,10 @@
|
||||
<data name="RegistryAdmin.Theme.Modern" xml:space="preserve"><value>Modern</value></data>
|
||||
<data name="RegistryAdmin.ShippingAddress" xml:space="preserve"><value>Leveringsadres</value></data>
|
||||
<data name="RegistryAdmin.LineBreaksPreserved" xml:space="preserve"><value>Regeleinden blijven behouden</value></data>
|
||||
<data name="RegistryAdmin.HeroImage" xml:space="preserve"><value>Hero-afbeelding</value></data>
|
||||
<data name="RegistryAdmin.UploadImage" xml:space="preserve"><value>Afbeelding uploaden</value></data>
|
||||
<data name="RegistryAdmin.RemoveHeroImage" xml:space="preserve"><value>Hero-afbeelding verwijderen</value></data>
|
||||
<data name="RegistryAdmin.CurrentHeroImage" xml:space="preserve"><value>Huidige hero-afbeelding</value></data>
|
||||
<data name="RegistryAdmin.TopContent" xml:space="preserve"><value>Bovenste inhoud</value></data>
|
||||
<data name="RegistryAdmin.WelcomeText" xml:space="preserve"><value>Welkomsttekst</value></data>
|
||||
<data name="RegistryAdmin.BankAccountSettings" xml:space="preserve"><value>Bankrekeninginstellingen</value></data>
|
||||
|
||||
@@ -501,6 +501,18 @@
|
||||
<data name="RegistryAdmin.LineBreaksPreserved" xml:space="preserve">
|
||||
<value>[[Line breaks will be preserved]]</value>
|
||||
</data>
|
||||
<data name="RegistryAdmin.HeroImage" xml:space="preserve">
|
||||
<value>[[Hero image]]</value>
|
||||
</data>
|
||||
<data name="RegistryAdmin.UploadImage" xml:space="preserve">
|
||||
<value>[[Upload image]]</value>
|
||||
</data>
|
||||
<data name="RegistryAdmin.RemoveHeroImage" xml:space="preserve">
|
||||
<value>[[Remove hero image]]</value>
|
||||
</data>
|
||||
<data name="RegistryAdmin.CurrentHeroImage" xml:space="preserve">
|
||||
<value>[[Current hero image]]</value>
|
||||
</data>
|
||||
<data name="RegistryAdmin.TopContent" xml:space="preserve">
|
||||
<value>[[Top content]]</value>
|
||||
</data>
|
||||
|
||||
@@ -182,6 +182,10 @@
|
||||
<data name="RegistryAdmin.Theme.Modern" xml:space="preserve"><value>Modern</value></data>
|
||||
<data name="RegistryAdmin.ShippingAddress" xml:space="preserve"><value>Shipping address</value></data>
|
||||
<data name="RegistryAdmin.LineBreaksPreserved" xml:space="preserve"><value>Line breaks will be preserved</value></data>
|
||||
<data name="RegistryAdmin.HeroImage" xml:space="preserve"><value>Hero image</value></data>
|
||||
<data name="RegistryAdmin.UploadImage" xml:space="preserve"><value>Upload image</value></data>
|
||||
<data name="RegistryAdmin.RemoveHeroImage" xml:space="preserve"><value>Remove hero image</value></data>
|
||||
<data name="RegistryAdmin.CurrentHeroImage" xml:space="preserve"><value>Current hero image</value></data>
|
||||
<data name="RegistryAdmin.TopContent" xml:space="preserve"><value>Top content</value></data>
|
||||
<data name="RegistryAdmin.WelcomeText" xml:space="preserve"><value>Welcome text</value></data>
|
||||
<data name="RegistryAdmin.BankAccountSettings" xml:space="preserve"><value>Bank Account Settings</value></data>
|
||||
|
||||
Reference in New Issue
Block a user