diff --git a/Wave/Components/ModalComponent.razor b/Wave/Components/ModalComponent.razor index 4418698..371c492 100644 --- a/Wave/Components/ModalComponent.razor +++ b/Wave/Components/ModalComponent.razor @@ -6,7 +6,7 @@ @if (ShowCloseButton) {
- +
} diff --git a/Wave/Components/Pages/Deleted.razor b/Wave/Components/Pages/Deleted.razor index 946e16c..b826b3b 100644 --- a/Wave/Components/Pages/Deleted.razor +++ b/Wave/Components/Pages/Deleted.razor @@ -12,6 +12,27 @@

@Localizer["Title"]

+ + +
+ +

@Localizer["Confirm_Title"]

+

@Localizer["Confirm_Description"]

+ +
+ + + +
+ +
+ +
+
@@ -25,6 +46,7 @@ @code { [CascadingParameter(Name = "TitlePostfix")] private string TitlePostfix { get; set; } = default!; + private static string ModalId => "ConfirmDeleteDialog"; private List
Articles { get; } = []; @@ -55,4 +77,15 @@ Articles.RemoveAt(Articles.FindIndex(a => a.Id == article.Id)); } + private async Task DeleteAll() { + await using var context = await ContextFactory.CreateDbContextAsync(); + + context.RemoveRange(await context.Set
() + .IgnoreQueryFilters().IgnoreAutoIncludes() + .Where(a => a.IsDeleted) + .ToListAsync()); + await context.SaveChangesAsync(); + Articles.Clear(); + } + } \ No newline at end of file diff --git a/Wave/Data/ApplicationDbContext.cs b/Wave/Data/ApplicationDbContext.cs index c53d831..9d5ad3d 100644 --- a/Wave/Data/ApplicationDbContext.cs +++ b/Wave/Data/ApplicationDbContext.cs @@ -74,8 +74,8 @@ public class ApplicationDbContext(DbContextOptions options category.HasMany(c => c.Articles).WithMany(a => a.Categories) .UsingEntity( - ac => ac.HasOne(a => a.Article).WithMany().OnDelete(DeleteBehavior.NoAction), - ac => ac.HasOne(a => a.Category).WithMany().OnDelete(DeleteBehavior.NoAction), + ac => ac.HasOne(a => a.Article).WithMany().OnDelete(DeleteBehavior.Cascade), + ac => ac.HasOne(a => a.Category).WithMany().OnDelete(DeleteBehavior.Restrict), articleCategory => { articleCategory.HasKey(ac => ac.Id); articleCategory.ToTable("ArticleCategories"); diff --git a/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.Designer.cs b/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.Designer.cs new file mode 100644 index 0000000..aa7b820 --- /dev/null +++ b/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.Designer.cs @@ -0,0 +1,752 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Wave.Data; + +#nullable disable + +namespace Wave.Data.Migrations.postgres +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240604123612_HardDeleteArticles")] + partial class HardDeleteArticles + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:CollationDefinition:default-case-insensitive", "und-u-kf-upper-ks-level1,und-u-kf-upper-ks-level1,icu,False") + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Wave.Data.ApiClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApiKeyKey") + .HasColumnType("character varying(128)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("ApiKeyKey"); + + b.ToTable("ApiClaim"); + }); + + modelBuilder.Entity("Wave.Data.ApiKey", b => + { + b.Property("Key") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("OwnerName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Key"); + + b.ToTable("ApiKey"); + }); + + modelBuilder.Entity("Wave.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AboutTheAuthor") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Biography") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)"); + + b.Property("BiographyHtml") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("ContactEmail") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ContactPhone") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ContactPhoneBusiness") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ContactWebsite") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Wave.Data.Article", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyHtml") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyPlain") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue(""); + + b.Property("CanBePublic") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("boolean") + .HasComputedColumnSql("\"IsDeleted\" = false AND \"Status\" = 2", true); + + b.Property("CreationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("LastModified") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("PublishDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewerId") + .HasColumnType("text"); + + b.Property("Slug") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasDefaultValue(""); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("ReviewerId"); + + b.ToTable("Articles", (string)null); + }); + + modelBuilder.Entity("Wave.Data.ArticleCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArticleId") + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.HasIndex("CategoryId"); + + b.ToTable("ArticleCategories", (string)null); + }); + + modelBuilder.Entity("Wave.Data.ArticleImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ArticleId") + .HasColumnType("uuid"); + + b.Property("ImageDescription") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId"); + + b.ToTable("Images", (string)null); + }); + + modelBuilder.Entity("Wave.Data.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Color") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(25); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .UseCollation("default-case-insensitive"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Categories", (string)null); + }); + + modelBuilder.Entity("Wave.Data.EmailNewsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArticleId") + .HasColumnType("uuid"); + + b.Property("DistributionDateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSend") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ArticleId") + .IsUnique(); + + b.ToTable("Newsletter", (string)null); + }); + + modelBuilder.Entity("Wave.Data.EmailSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .UseCollation("default-case-insensitive"); + + b.Property("Language") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(8) + .HasColumnType("character varying(8)") + .HasDefaultValue("en-US"); + + b.Property("LastMailOpened") + .HasColumnType("timestamp with time zone"); + + b.Property("LastMailReceived") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UnsubscribeReason") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Unsubscribed") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("Unsubscribed"); + + b.ToTable("NewsletterSubscribers", (string)null); + }); + + modelBuilder.Entity("Wave.Data.ProfilePicture", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("ImageId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId") + .IsUnique(); + + b.ToTable("ProfilePictures", (string)null); + }); + + modelBuilder.Entity("Wave.Data.UserLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApplicationUserId") + .HasColumnType("text"); + + b.Property("UrlString") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserLink"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Wave.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Wave.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Wave.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Wave.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Wave.Data.ApiClaim", b => + { + b.HasOne("Wave.Data.ApiKey", null) + .WithMany("ApiClaims") + .HasForeignKey("ApiKeyKey") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Wave.Data.Article", b => + { + b.HasOne("Wave.Data.ApplicationUser", "Author") + .WithMany("Articles") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Wave.Data.ApplicationUser", "Reviewer") + .WithMany() + .HasForeignKey("ReviewerId") + .OnDelete(DeleteBehavior.SetNull); + + b.OwnsMany("Wave.Data.ArticleHeading", "Headings", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Anchor") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b1.Property("ArticleId") + .HasColumnType("uuid"); + + b1.Property("Label") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.Property("Order") + .HasColumnType("integer"); + + b1.HasKey("Id"); + + b1.HasIndex("ArticleId"); + + b1.ToTable("ArticleHeading"); + + b1.WithOwner() + .HasForeignKey("ArticleId"); + }); + + b.Navigation("Author"); + + b.Navigation("Headings"); + + b.Navigation("Reviewer"); + }); + + modelBuilder.Entity("Wave.Data.ArticleCategory", b => + { + b.HasOne("Wave.Data.Article", "Article") + .WithMany() + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Wave.Data.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Article"); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Wave.Data.ArticleImage", b => + { + b.HasOne("Wave.Data.Article", null) + .WithMany("Images") + .HasForeignKey("ArticleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Wave.Data.EmailNewsletter", b => + { + b.HasOne("Wave.Data.Article", "Article") + .WithOne() + .HasForeignKey("Wave.Data.EmailNewsletter", "ArticleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Article"); + }); + + modelBuilder.Entity("Wave.Data.ProfilePicture", b => + { + b.HasOne("Wave.Data.ApplicationUser", null) + .WithOne("ProfilePicture") + .HasForeignKey("Wave.Data.ProfilePicture", "ApplicationUserId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Wave.Data.UserLink", b => + { + b.HasOne("Wave.Data.ApplicationUser", null) + .WithMany("Links") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Wave.Data.ApiKey", b => + { + b.Navigation("ApiClaims"); + }); + + modelBuilder.Entity("Wave.Data.ApplicationUser", b => + { + b.Navigation("Articles"); + + b.Navigation("Links"); + + b.Navigation("ProfilePicture"); + }); + + modelBuilder.Entity("Wave.Data.Article", b => + { + b.Navigation("Images"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.cs b/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.cs new file mode 100644 index 0000000..f7a0553 --- /dev/null +++ b/Wave/Data/Migrations/postgres/20240604123612_HardDeleteArticles.cs @@ -0,0 +1,106 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Wave.Data.Migrations.postgres; + +/// +public partial class HardDeleteArticles : Migration { + /// + protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.DropForeignKey( + name: "FK_ArticleCategories_Articles_ArticleId", + table: "ArticleCategories"); + + migrationBuilder.DropForeignKey( + name: "FK_ArticleCategories_Categories_CategoryId", + table: "ArticleCategories"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ArticleHeading", + table: "ArticleHeading"); + + migrationBuilder.AlterColumn( + name: "ArticleId", + table: "ArticleHeading", + type: "uuid", + nullable: true, + oldClrType: typeof(Guid), + oldType: "uuid"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ArticleHeading", + table: "ArticleHeading", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_ArticleHeading_ArticleId", + table: "ArticleHeading", + column: "ArticleId"); + + migrationBuilder.AddForeignKey( + name: "FK_ArticleCategories_Articles_ArticleId", + table: "ArticleCategories", + column: "ArticleId", + principalTable: "Articles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_ArticleCategories_Categories_CategoryId", + table: "ArticleCategories", + column: "CategoryId", + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropForeignKey( + name: "FK_ArticleCategories_Articles_ArticleId", + table: "ArticleCategories"); + + migrationBuilder.DropForeignKey( + name: "FK_ArticleCategories_Categories_CategoryId", + table: "ArticleCategories"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ArticleHeading", + table: "ArticleHeading"); + + migrationBuilder.DropIndex( + name: "IX_ArticleHeading_ArticleId", + table: "ArticleHeading"); + + migrationBuilder.AlterColumn( + name: "ArticleId", + table: "ArticleHeading", + type: "uuid", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + oldClrType: typeof(Guid), + oldType: "uuid", + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_ArticleHeading", + table: "ArticleHeading", + columns: new[] {"ArticleId", "Id"}); + + migrationBuilder.AddForeignKey( + name: "FK_ArticleCategories_Articles_ArticleId", + table: "ArticleCategories", + column: "ArticleId", + principalTable: "Articles", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ArticleCategories_Categories_CategoryId", + table: "ArticleCategories", + column: "CategoryId", + principalTable: "Categories", + principalColumn: "Id"); + } +} \ No newline at end of file diff --git a/Wave/Data/Migrations/postgres/ApplicationDbContextModelSnapshot.cs b/Wave/Data/Migrations/postgres/ApplicationDbContextModelSnapshot.cs index 009fed2..924311e 100644 --- a/Wave/Data/Migrations/postgres/ApplicationDbContextModelSnapshot.cs +++ b/Wave/Data/Migrations/postgres/ApplicationDbContextModelSnapshot.cs @@ -632,9 +632,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.OwnsMany("Wave.Data.ArticleHeading", "Headings", b1 => { - b1.Property("ArticleId") - .HasColumnType("uuid"); - b1.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("integer"); @@ -646,6 +643,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(256) .HasColumnType("character varying(256)"); + b1.Property("ArticleId") + .HasColumnType("uuid"); + b1.Property("Label") .IsRequired() .HasMaxLength(128) @@ -654,7 +654,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Property("Order") .HasColumnType("integer"); - b1.HasKey("ArticleId", "Id"); + b1.HasKey("Id"); + + b1.HasIndex("ArticleId"); b1.ToTable("ArticleHeading"); @@ -674,13 +676,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasOne("Wave.Data.Article", "Article") .WithMany() .HasForeignKey("ArticleId") - .OnDelete(DeleteBehavior.NoAction) + .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("Wave.Data.Category", "Category") .WithMany() .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.NoAction) + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); b.Navigation("Article"); diff --git a/Wave/Resources/Components/Pages/Deleted.de-DE.resx b/Wave/Resources/Components/Pages/Deleted.de-DE.resx index e45146a..a553e6d 100644 --- a/Wave/Resources/Components/Pages/Deleted.de-DE.resx +++ b/Wave/Resources/Components/Pages/Deleted.de-DE.resx @@ -104,4 +104,16 @@ Artikel Wiederherstellen + + Artikel Löschen + + + Sind Sie sich sicher? + + + Ja, Artikel unwiederruflich löschen + + + Diese Operation ist unwiederruflich + \ No newline at end of file diff --git a/Wave/Resources/Components/Pages/Deleted.resx b/Wave/Resources/Components/Pages/Deleted.resx index 8e6aa87..bafde79 100644 --- a/Wave/Resources/Components/Pages/Deleted.resx +++ b/Wave/Resources/Components/Pages/Deleted.resx @@ -104,4 +104,16 @@ Restore Article + + Delete Articles + + + Are you sure? + + + This action is irreversible. + + + Yes, permanently delete articles + \ No newline at end of file