This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Aberwyn.Models;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
@@ -10,13 +13,20 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly RoleManager<IdentityRole> _roleManager;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public AdminController(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
|
||||
|
||||
public AdminController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RoleManager<IdentityRole> roleManager,
|
||||
ApplicationDbContext context)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_roleManager = roleManager;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var users = _userManager.Users.ToList();
|
||||
@@ -86,8 +96,48 @@ namespace Aberwyn.Controllers
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult Todo()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetTodoTasks()
|
||||
{
|
||||
var tasks = await _context.TodoTasks.ToListAsync();
|
||||
return Json(tasks);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddTodoTask([FromBody] TodoTask task)
|
||||
{
|
||||
task.CreatedAt = DateTime.UtcNow;
|
||||
task.Priority = task.Priority == 0 ? 1 : task.Priority; // default till låg om ej satt
|
||||
_context.TodoTasks.Add(task);
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok(task);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> UpdateTodoTask([FromBody] TodoTask task)
|
||||
{
|
||||
var existing = await _context.TodoTasks.FindAsync(task.Id);
|
||||
if (existing == null) return NotFound();
|
||||
|
||||
existing.Title = task.Title;
|
||||
existing.Status = task.Status;
|
||||
existing.Priority = task.Priority;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class AdminUserViewModel
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Aberwyn.Data
|
||||
public DbSet<AppSetting> AppSettings { get; set; }
|
||||
public DbSet<BudgetItemDefinition> BudgetItemDefinitions { get; set; }
|
||||
public DbSet<BudgetCategoryDefinition> BudgetCategoryDefinitions { get; set; }
|
||||
public DbSet<TodoTask> TodoTasks { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
541
Aberwyn/Migrations/20250529183339_CreateTodoTaskTable.Designer.cs
generated
Normal file
541
Aberwyn/Migrations/20250529183339_CreateTodoTaskTable.Designer.cs
generated
Normal file
@@ -0,0 +1,541 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250529183339_CreateTodoTaskTable")]
|
||||
partial class CreateTodoTaskTable
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.AppSetting", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AppSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BudgetCategoryDefinitionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryDefinitionId");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetCategoryDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("BudgetItemDefinitionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.HasIndex("BudgetItemDefinitionId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("DefaultCategory")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetItemDefinitions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.TodoTask", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetCategoryDefinitionId");
|
||||
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
|
||||
b.Navigation("Definition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetItemDefinitionId");
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Aberwyn/Migrations/20250529183339_CreateTodoTaskTable.cs
Normal file
39
Aberwyn/Migrations/20250529183339_CreateTodoTaskTable.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class CreateTodoTaskTable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TodoTasks",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Priority = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TodoTasks", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TodoTasks");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,6 +286,31 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.TodoTask", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TodoTasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
@@ -416,7 +441,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "BudgetItemDefinition")
|
||||
b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition")
|
||||
.WithMany()
|
||||
.HasForeignKey("BudgetCategoryDefinitionId");
|
||||
|
||||
@@ -428,7 +453,7 @@ namespace Aberwyn.Migrations
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
|
||||
b.Navigation("BudgetItemDefinition");
|
||||
b.Navigation("Definition");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
|
||||
@@ -7,4 +7,14 @@
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class TodoTask
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Status { get; set; } // "ideas", "doing", "done"
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
223
Aberwyn/Views/Admin/Todo.cshtml
Normal file
223
Aberwyn/Views/Admin/Todo.cshtml
Normal file
@@ -0,0 +1,223 @@
|
||||
@{
|
||||
ViewData["Title"] = "Todo";
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="sv" ng-app="todoApp">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>@ViewData["Title"]</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
|
||||
<style>
|
||||
.todo-board {
|
||||
padding: 20px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.todo-columns {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.todo-column {
|
||||
background: #f1f5f9;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
width: 250px;
|
||||
min-height: 200px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.todo-column h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.todo-task {
|
||||
background: white;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 6px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
cursor: move;
|
||||
}
|
||||
input[type="text"] {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
padding: 6px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button {
|
||||
margin-top: 6px;
|
||||
padding: 6px 10px;
|
||||
background-color: #3b82f6;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.priority-low {
|
||||
border-left: 4px solid #10b981;
|
||||
}
|
||||
.priority-medium {
|
||||
border-left: 4px solid #f59e0b;
|
||||
}
|
||||
.priority-high {
|
||||
border-left: 4px solid #ef4444;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body ng-controller="TodoController" class="todo-board" ng-init="loadTasks()">
|
||||
|
||||
<h1>🗂️ Min idé-board</h1>
|
||||
|
||||
<div class="todo-columns">
|
||||
<div class="todo-column" ng-repeat="col in columns">
|
||||
<h2>{{ col.title }}</h2>
|
||||
|
||||
<div class="todo-task {{ priorityClass(task.priority) }}"
|
||||
ng-repeat="task in filteredTasks(col.id) track by task.id"
|
||||
draggable-task
|
||||
task="task"
|
||||
on-task-drop="moveTask(task, col.id)">
|
||||
{{ task.title }}
|
||||
<div>
|
||||
<small>Prioritet:
|
||||
<select ng-model="task.priority" ng-change="updatePriority(task)">
|
||||
<option value="1">Låg</option>
|
||||
<option value="2">Medel</option>
|
||||
<option value="3">Hög</option>
|
||||
</select>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="col.id === 'ideas'">
|
||||
<input type="text" ng-model="newTask.title" placeholder="Ny idé..." />
|
||||
<select ng-model="newTask.priority">
|
||||
<option value="1">Låg</option>
|
||||
<option value="2">Medel</option>
|
||||
<option value="3">Hög</option>
|
||||
</select>
|
||||
<button type="button" ng-click="addTask()">Lägg till</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var app = angular.module("todoApp", []);
|
||||
|
||||
app.controller("TodoController", function ($scope, $http) {
|
||||
$scope.columns = [
|
||||
{ id: "ideas", title: "💡 Idéer" },
|
||||
{ id: "doing", title: "🔧 Pågående" },
|
||||
{ id: "done", title: "✅ Klart" }
|
||||
];
|
||||
|
||||
$scope.tasks = [];
|
||||
$scope.newTask = {
|
||||
title: '',
|
||||
priority: 2
|
||||
};
|
||||
|
||||
$scope.loadTasks = function () {
|
||||
$http.get("/Admin/GetTodoTasks").then(res => {
|
||||
$scope.tasks = res.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addTask = function () {
|
||||
console.log("addTask:");
|
||||
|
||||
const title = $scope.newTask.title;
|
||||
const priority = $scope.newTask.priority;
|
||||
|
||||
if (typeof title !== 'string' || !title.trim()) {
|
||||
console.warn("Titel är tom eller ogiltig:", title);
|
||||
return;
|
||||
}
|
||||
console.log("post check");
|
||||
|
||||
const task = {
|
||||
title: title.trim(),
|
||||
status: "ideas",
|
||||
priority: priority
|
||||
};
|
||||
console.log("post title trim");
|
||||
|
||||
$http.post("/Admin/AddTodoTask", task, {
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
}).then(res => {
|
||||
$scope.tasks.push(res.data);
|
||||
$scope.newTask.title = '';
|
||||
$scope.newTask.priority = 2;
|
||||
console.log("Created task");
|
||||
}, err => {
|
||||
console.error("Fel vid POST:", err);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.moveTask = function (task, newStatus) {
|
||||
task.status = newStatus;
|
||||
$http.post("/Admin/UpdateTodoTask", task);
|
||||
};
|
||||
|
||||
$scope.updatePriority = function (task) {
|
||||
$http.post("/Admin/UpdateTodoTask", task);
|
||||
};
|
||||
|
||||
$scope.priorityClass = function (priority) {
|
||||
return {
|
||||
1: 'priority-low',
|
||||
2: 'priority-medium',
|
||||
3: 'priority-high'
|
||||
}[priority];
|
||||
};
|
||||
|
||||
$scope.filteredTasks = function (status) {
|
||||
if (!$scope.tasks || !$scope.tasks.length) return [];
|
||||
|
||||
// För säkerhets skull jämför lowercase
|
||||
return $scope.tasks.filter(t => (t.status || '').toLowerCase() === status.toLowerCase());
|
||||
};
|
||||
|
||||
$scope.loadTasks();
|
||||
});
|
||||
|
||||
app.directive("draggableTask", function () {
|
||||
return {
|
||||
restrict: "A",
|
||||
scope: {
|
||||
task: "=",
|
||||
onTaskDrop: "&"
|
||||
},
|
||||
link: function (scope, element) {
|
||||
element.attr("draggable", true);
|
||||
element.on("dragstart", function (e) {
|
||||
e.dataTransfer.setData("text/plain", JSON.stringify(scope.task));
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.directive("ngRepeat", function () {
|
||||
return {
|
||||
restrict: "A",
|
||||
link: function (scope, element) {
|
||||
element.on("dragover", function (e) {
|
||||
e.preventDefault();
|
||||
element.css("background-color", "#e0f2fe");
|
||||
});
|
||||
element.on("dragleave", function () {
|
||||
element.css("background-color", "");
|
||||
});
|
||||
element.on("drop", function (e) {
|
||||
e.preventDefault();
|
||||
const data = e.dataTransfer.getData("text/plain");
|
||||
const task = JSON.parse(data);
|
||||
scope.onTaskDrop({ task });
|
||||
element.css("background-color", "");
|
||||
scope.$apply();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user