diff --git a/plugins/Common/Common.csproj b/plugins/Common/Common.csproj
index 7ef3cf24c..5d1d9423a 100644
--- a/plugins/Common/Common.csproj
+++ b/plugins/Common/Common.csproj
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/plugins/Common/Views/Widgets/HtmlBlock/Index.cshtml b/plugins/Common/Views/Widgets/HtmlBlock/Index.cshtml
new file mode 100644
index 000000000..bd76827b2
--- /dev/null
+++ b/plugins/Common/Views/Widgets/HtmlBlock/Index.cshtml
@@ -0,0 +1 @@
+@Html.Raw(Model)
\ No newline at end of file
diff --git a/plugins/Common/Widgets/HtmlBlock.cs b/plugins/Common/Widgets/HtmlBlock.cs
new file mode 100644
index 000000000..594f8caab
--- /dev/null
+++ b/plugins/Common/Widgets/HtmlBlock.cs
@@ -0,0 +1,44 @@
+using Core.Services;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Common.Widgets
+{
+ [ViewComponent(Name = "HtmlBlock")]
+ public class HtmlBlock : ViewComponent
+ {
+ IDataService _db;
+
+ public HtmlBlock(IDataService db)
+ {
+ _db = db;
+ }
+
+ public IViewComponentResult Invoke(string id, string theme, string author)
+ {
+ string model = @"
";
+
+ var existing = _db.HtmlWidgets.Single(w => w.Name == id && w.Theme == theme && w.Author == author);
+
+ if (existing == null)
+ {
+ _db.HtmlWidgets.Add(new Core.Data.HtmlWidget {
+ Name = id,
+ Theme = theme,
+ Author = author,
+ Content = model
+ });
+ _db.Complete();
+ }
+ else
+ {
+ model = existing.Content;
+ }
+
+ return View("~/Views/Widgets/HtmlBlock/Index.cshtml", model);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/App/Views/Themes/Standard/_Shared/_Header.cshtml b/src/App/Views/Themes/Standard/_Shared/_Header.cshtml
index 45727edf8..9fb94f571 100644
--- a/src/App/Views/Themes/Standard/_Shared/_Header.cshtml
+++ b/src/App/Views/Themes/Standard/_Shared/_Header.cshtml
@@ -1,16 +1,14 @@
\ No newline at end of file
diff --git a/src/App/app.db b/src/App/app.db
index 98a46add3..1e6bfb723 100644
Binary files a/src/App/app.db and b/src/App/app.db differ
diff --git a/src/Core/Data/AppDbContext.cs b/src/Core/Data/AppDbContext.cs
index bd47e989d..ec782f432 100644
--- a/src/Core/Data/AppDbContext.cs
+++ b/src/Core/Data/AppDbContext.cs
@@ -15,6 +15,7 @@ public AppDbContext(DbContextOptions options) : base(options)
public DbSet BlogPosts { get; set; }
public DbSet Authors { get; set; }
public DbSet Notifications { get; set; }
+ public DbSet HtmlWidtes { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
diff --git a/src/Core/Data/Domain/HtmlWidget.cs b/src/Core/Data/Domain/HtmlWidget.cs
new file mode 100644
index 000000000..3937a4a3e
--- /dev/null
+++ b/src/Core/Data/Domain/HtmlWidget.cs
@@ -0,0 +1,11 @@
+namespace Core.Data
+{
+ public class HtmlWidget
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Theme { get; set; }
+ public string Author { get; set; }
+ public string Content { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Core/Data/Repositories/HtmlWidgetRepository.cs b/src/Core/Data/Repositories/HtmlWidgetRepository.cs
new file mode 100644
index 000000000..556e4035b
--- /dev/null
+++ b/src/Core/Data/Repositories/HtmlWidgetRepository.cs
@@ -0,0 +1,16 @@
+namespace Core.Data
+{
+ public interface IHtmlWidgetRepository : IRepository
+ {
+ }
+
+ public class HtmlWidgetRepository : Repository, IHtmlWidgetRepository
+ {
+ AppDbContext _db;
+
+ public HtmlWidgetRepository(AppDbContext db) : base(db)
+ {
+ _db = db;
+ }
+ }
+}
diff --git a/src/Core/Migrations/20180917014904_HtmlWidgets.Designer.cs b/src/Core/Migrations/20180917014904_HtmlWidgets.Designer.cs
new file mode 100644
index 000000000..2bbb7eef1
--- /dev/null
+++ b/src/Core/Migrations/20180917014904_HtmlWidgets.Designer.cs
@@ -0,0 +1,337 @@
+//
+using System;
+using Core.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Core.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ [Migration("20180917014904_HtmlWidgets")]
+ partial class HtmlWidgets
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
+
+ modelBuilder.Entity("Core.Data.AppUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessFailedCount");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken();
+
+ b.Property("Email")
+ .HasMaxLength(256);
+
+ b.Property("EmailConfirmed");
+
+ b.Property("LockoutEnabled");
+
+ b.Property("LockoutEnd");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256);
+
+ b.Property("PasswordHash");
+
+ b.Property("PhoneNumber");
+
+ b.Property("PhoneNumberConfirmed");
+
+ b.Property("SecurityStamp");
+
+ b.Property("TwoFactorEnabled");
+
+ b.Property("UserName")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasName("UserNameIndex");
+
+ b.ToTable("AspNetUsers");
+ });
+
+ modelBuilder.Entity("Core.Data.Author", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AppUserId")
+ .HasMaxLength(160);
+
+ b.Property("AppUserName")
+ .HasMaxLength(160);
+
+ b.Property("Avatar")
+ .HasMaxLength(160);
+
+ b.Property("Bio");
+
+ b.Property("Created");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(160);
+
+ b.Property("Email");
+
+ b.Property("IsAdmin");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("Core.Data.BlogPost", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AuthorId");
+
+ b.Property("Categories")
+ .HasMaxLength(2000);
+
+ b.Property("Content")
+ .IsRequired();
+
+ b.Property("Cover")
+ .HasMaxLength(255);
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(450);
+
+ b.Property("IsFeatured");
+
+ b.Property("PostViews");
+
+ b.Property("Published");
+
+ b.Property("Rating");
+
+ b.Property("Slug")
+ .IsRequired()
+ .HasMaxLength(160);
+
+ b.Property("Title")
+ .IsRequired()
+ .HasMaxLength(160);
+
+ b.HasKey("Id");
+
+ b.ToTable("BlogPosts");
+ });
+
+ modelBuilder.Entity("Core.Data.HtmlWidget", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Author");
+
+ b.Property("Content");
+
+ b.Property("Name");
+
+ b.Property("Theme");
+
+ b.HasKey("Id");
+
+ b.ToTable("HtmlWidtes");
+ });
+
+ modelBuilder.Entity("Core.Data.Notification", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AlertType");
+
+ b.Property("AuthorId");
+
+ b.Property("Content");
+
+ b.Property("DateNotified");
+
+ b.Property("Notifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Notifications");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken();
+
+ b.Property("Name")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasName("RoleNameIndex");
+
+ b.ToTable("AspNetRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClaimType");
+
+ b.Property("ClaimValue");
+
+ b.Property("RoleId")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClaimType");
+
+ b.Property("ClaimValue");
+
+ b.Property("UserId")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider");
+
+ b.Property("ProviderKey");
+
+ b.Property("ProviderDisplayName");
+
+ b.Property("UserId")
+ .IsRequired();
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId");
+
+ b.Property("RoleId");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId");
+
+ b.Property("LoginProvider");
+
+ b.Property("Name");
+
+ b.Property("Value");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.HasOne("Core.Data.AppUser")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.HasOne("Core.Data.AppUser")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("Core.Data.AppUser")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.HasOne("Core.Data.AppUser")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Core/Migrations/20180917014904_HtmlWidgets.cs b/src/Core/Migrations/20180917014904_HtmlWidgets.cs
new file mode 100644
index 000000000..f5b4ebbfa
--- /dev/null
+++ b/src/Core/Migrations/20180917014904_HtmlWidgets.cs
@@ -0,0 +1,32 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Core.Migrations
+{
+ public partial class HtmlWidgets : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "HtmlWidtes",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Name = table.Column(nullable: true),
+ Theme = table.Column(nullable: true),
+ Author = table.Column(nullable: true),
+ Content = table.Column(nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_HtmlWidtes", x => x.Id);
+ });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "HtmlWidtes");
+ }
+ }
+}
diff --git a/src/Core/Migrations/AppDbContextModelSnapshot.cs b/src/Core/Migrations/AppDbContextModelSnapshot.cs
index 656a17f92..a753512fc 100644
--- a/src/Core/Migrations/AppDbContextModelSnapshot.cs
+++ b/src/Core/Migrations/AppDbContextModelSnapshot.cs
@@ -138,6 +138,24 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("BlogPosts");
});
+ modelBuilder.Entity("Core.Data.HtmlWidget", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Author");
+
+ b.Property("Content");
+
+ b.Property("Name");
+
+ b.Property("Theme");
+
+ b.HasKey("Id");
+
+ b.ToTable("HtmlWidtes");
+ });
+
modelBuilder.Entity("Core.Data.Notification", b =>
{
b.Property("Id")
diff --git a/src/Core/Services/DataService.cs b/src/Core/Services/DataService.cs
index 7f6e48533..e47abcfdc 100644
--- a/src/Core/Services/DataService.cs
+++ b/src/Core/Services/DataService.cs
@@ -8,6 +8,7 @@ public interface IDataService : IDisposable
IPostRepository BlogPosts { get; }
IAuthorRepository Authors { get; }
INotificationRepository Notifications { get; }
+ IHtmlWidgetRepository HtmlWidgets { get; }
int Complete();
}
@@ -23,11 +24,13 @@ public DataService(AppDbContext db)
BlogPosts = new PostRepository(_db);
Authors = new AuthorRepository(_db);
Notifications = new NotificationRepository(_db);
+ HtmlWidgets = new HtmlWidgetRepository(_db);
}
public IPostRepository BlogPosts { get; private set; }
public IAuthorRepository Authors { get; private set; }
public INotificationRepository Notifications { get; private set; }
+ public IHtmlWidgetRepository HtmlWidgets { get; private set; }
public int Complete()
{