Add sorting columns
This commit is contained in:
parent
adf24cbd5c
commit
90adbcfb7c
34 changed files with 833 additions and 80 deletions
|
|
@ -54,9 +54,9 @@ namespace Start.Server.Controllers {
|
|||
[Route("Create")]
|
||||
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(BookmarkContainerDto))]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> CreateBookmarkContainer([FromBody] string title) {
|
||||
public async Task<IActionResult> CreateBookmarkContainer(string title, int sortOrder) {
|
||||
BookmarkContainerDto? container = (await this.bookmarkContainerService
|
||||
.CreateBookmarkContainer(this.GetAuthorizedUserId(), title))
|
||||
.CreateBookmarkContainer(this.GetAuthorizedUserId(), title, sortOrder))
|
||||
?.MapToDto();
|
||||
|
||||
if (container == null)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ namespace Start.Server.Controllers {
|
|||
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(BookmarkGroupDto))]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> CreateBookmarkGroup(string title, string color,
|
||||
int bookmarkContainerId) {
|
||||
int sortOrder, int bookmarkContainerId) {
|
||||
BookmarkGroup? newGroup = await this.bookmarkGroupService
|
||||
.CreateBookmarkGroup(this.GetAuthorizedUserId(), title, color, bookmarkContainerId);
|
||||
.CreateBookmarkGroup(this.GetAuthorizedUserId(), title, color, sortOrder, bookmarkContainerId);
|
||||
|
||||
if (newGroup == null)
|
||||
return BadRequest();
|
||||
|
|
|
|||
|
|
@ -37,9 +37,10 @@ namespace Start.Server.Controllers {
|
|||
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(BookmarkDto))]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> CreateBookmark(string title, string url, string? notes,
|
||||
int bookmarkGroupId) {
|
||||
int sortOrder, int bookmarkGroupId) {
|
||||
BookmarkDto? bookmark = (await this.bookmarkService
|
||||
.CreateBookmark(this.GetAuthorizedUserId(), title, url, notes, bookmarkGroupId))
|
||||
.CreateBookmark(this.GetAuthorizedUserId(), title, url, notes, sortOrder,
|
||||
bookmarkGroupId))
|
||||
?.MapToDto();
|
||||
|
||||
if (bookmark == null)
|
||||
|
|
|
|||
508
Start/Server/Data/Migrations/20211220002043_AddSorting.Designer.cs
generated
Normal file
508
Start/Server/Data/Migrations/20211220002043_AddSorting.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Start.Server.Data;
|
||||
|
||||
namespace Start.Server.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20211220002043_AddSorting")]
|
||||
partial class AddSorting
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "5.0.11");
|
||||
|
||||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
|
||||
{
|
||||
b.Property<string>("UserCode")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClientId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50000)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceCode")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Expiration")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SessionId")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SubjectId")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserCode");
|
||||
|
||||
b.HasIndex("DeviceCode")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Expiration");
|
||||
|
||||
b.ToTable("DeviceCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
|
||||
{
|
||||
b.Property<string>("Key")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClientId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ConsumedTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Data")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50000)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Expiration")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SessionId")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SubjectId")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.HasIndex("Expiration");
|
||||
|
||||
b.HasIndex("SubjectId", "ClientId", "Type");
|
||||
|
||||
b.HasIndex("SubjectId", "SessionId", "Type");
|
||||
|
||||
b.ToTable("PersistedGrants");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.Bookmark", b =>
|
||||
{
|
||||
b.Property<int>("BookmarkId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BookmarkGroupId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasMaxLength(5000)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("BookmarkId");
|
||||
|
||||
b.HasIndex("BookmarkGroupId");
|
||||
|
||||
b.ToTable("Bookmarks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkContainer", b =>
|
||||
{
|
||||
b.Property<int>("BookmarkContainerId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ApplicationUserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("BookmarkContainerId");
|
||||
|
||||
b.HasIndex("ApplicationUserId");
|
||||
|
||||
b.ToTable("BookmarkContainers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkGroup", b =>
|
||||
{
|
||||
b.Property<int>("BookmarkGroupId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BookmarkContainerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasMaxLength(6)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("BookmarkGroupId");
|
||||
|
||||
b.HasIndex("BookmarkContainerId");
|
||||
|
||||
b.ToTable("BookmarkGroups");
|
||||
});
|
||||
|
||||
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("Start.Server.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Start.Server.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("Start.Server.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Start.Server.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.Bookmark", b =>
|
||||
{
|
||||
b.HasOne("Start.Server.Models.BookmarkGroup", "BookmarkGroup")
|
||||
.WithMany("Bookmarks")
|
||||
.HasForeignKey("BookmarkGroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BookmarkGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkContainer", b =>
|
||||
{
|
||||
b.HasOne("Start.Server.Models.ApplicationUser", "ApplicationUser")
|
||||
.WithMany("BookmarkContainers")
|
||||
.HasForeignKey("ApplicationUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("ApplicationUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkGroup", b =>
|
||||
{
|
||||
b.HasOne("Start.Server.Models.BookmarkContainer", "BookmarkContainer")
|
||||
.WithMany("BookmarkGroups")
|
||||
.HasForeignKey("BookmarkContainerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BookmarkContainer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Navigation("BookmarkContainers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkContainer", b =>
|
||||
{
|
||||
b.Navigation("BookmarkGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Start.Server.Models.BookmarkGroup", b =>
|
||||
{
|
||||
b.Navigation("Bookmarks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Start/Server/Data/Migrations/20211220002043_AddSorting.cs
Normal file
42
Start/Server/Data/Migrations/20211220002043_AddSorting.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Start.Server.Data.Migrations {
|
||||
public partial class AddSorting : Migration {
|
||||
protected override void Up(MigrationBuilder migrationBuilder) {
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SortOrder",
|
||||
table: "Bookmarks",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SortOrder",
|
||||
table: "BookmarkGroups",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SortOrder",
|
||||
table: "BookmarkContainers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder) {
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SortOrder",
|
||||
table: "Bookmarks");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SortOrder",
|
||||
table: "BookmarkGroups");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SortOrder",
|
||||
table: "BookmarkContainers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -328,6 +328,9 @@ namespace Start.Server.Data.Migrations
|
|||
.HasMaxLength(5000)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
|
|
@ -355,8 +358,12 @@ namespace Start.Server.Data.Migrations
|
|||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("BookmarkContainerId");
|
||||
|
|
@ -380,6 +387,9 @@ namespace Start.Server.Data.Migrations
|
|||
.HasMaxLength(6)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(300)
|
||||
|
|
|
|||
|
|
@ -46,10 +46,28 @@ namespace Start.Server.Data.Services {
|
|||
}
|
||||
|
||||
public async Task<BookmarkContainer?> CreateBookmarkContainer(string userId,
|
||||
string title) {
|
||||
string title, int sortOrder) {
|
||||
// No need to worry about ownership here
|
||||
|
||||
BookmarkContainer newContainer = new(userId, title);
|
||||
// Increase the sorting ID for these items if it's needed to make room for this item
|
||||
List<BookmarkContainer>? containers = this.db.BookmarkContainers
|
||||
.Where(bc => bc.ApplicationUserId == userId)
|
||||
.SortContainers()
|
||||
.ToList();
|
||||
|
||||
if (containers == null)
|
||||
return null;
|
||||
|
||||
// Fix up sort order just in case
|
||||
for (int i = 0; i < containers.Count; i++) {
|
||||
containers[i].SortOrder = i;
|
||||
|
||||
// Make room for the new container
|
||||
if (i >= sortOrder)
|
||||
containers[i].SortOrder++;
|
||||
}
|
||||
|
||||
BookmarkContainer newContainer = new(userId, title, sortOrder);
|
||||
await this.db.BookmarkContainers.AddAsync(newContainer);
|
||||
await this.db.SaveChangesAsync();
|
||||
return newContainer;
|
||||
|
|
@ -57,15 +75,39 @@ namespace Start.Server.Data.Services {
|
|||
|
||||
public async Task<BookmarkContainer?> UpdateBookmarkContainer(string userId,
|
||||
BookmarkContainer bookmarkContainer) {
|
||||
BookmarkContainer? exitingBookmarkContainer = await this.db.BookmarkContainers
|
||||
.SingleOrDefaultAsync(bc => bc.BookmarkContainerId
|
||||
== bookmarkContainer.BookmarkContainerId);
|
||||
BookmarkContainer? existingBookmarkContainer = await this.db.BookmarkContainers
|
||||
.SingleOrDefaultAsync(bc =>
|
||||
bc.BookmarkContainerId == bookmarkContainer.BookmarkContainerId);
|
||||
|
||||
if (exitingBookmarkContainer == null
|
||||
if (existingBookmarkContainer == null
|
||||
|| !BookmarkOwnershipTools
|
||||
.IsBookmarkContainerOwner(this.db, userId, bookmarkContainer.BookmarkContainerId))
|
||||
return null;
|
||||
|
||||
// If the sort order has changed, then the other containers need to be shuffled around
|
||||
if (existingBookmarkContainer.SortOrder < bookmarkContainer.SortOrder) {
|
||||
// The container has been moved to a higher sort order
|
||||
var affectedContainers = db.BookmarkContainers
|
||||
.Where(bc => bc.ApplicationUserId == userId)
|
||||
.Where(bc => bc.SortOrder > existingBookmarkContainer.SortOrder)
|
||||
.Where(bc => bc.SortOrder <= bookmarkContainer.SortOrder)
|
||||
.ToList();
|
||||
|
||||
affectedContainers.ForEach(bc => bc.SortOrder -= 1);
|
||||
// Let the save changes below save this
|
||||
}
|
||||
else if (existingBookmarkContainer.SortOrder > bookmarkContainer.SortOrder) {
|
||||
// The container has been moved to a lower sort order
|
||||
var affectedContainers = db.BookmarkContainers
|
||||
.Where(bc => bc.ApplicationUserId == userId)
|
||||
.Where(bc => bc.SortOrder < existingBookmarkContainer.SortOrder)
|
||||
.Where(bc => bc.SortOrder >= bookmarkContainer.SortOrder)
|
||||
.ToList();
|
||||
|
||||
affectedContainers.ForEach(bc => bc.SortOrder += 1);
|
||||
// Let the save changes below save this
|
||||
}
|
||||
|
||||
this.db.Entry(bookmarkContainer).State = EntityState.Modified;
|
||||
await this.db.SaveChangesAsync();
|
||||
|
||||
|
|
@ -86,6 +128,22 @@ namespace Start.Server.Data.Services {
|
|||
this.db.BookmarkContainers.Remove(bookmarkContainer);
|
||||
await this.db.SaveChangesAsync();
|
||||
|
||||
List<BookmarkContainer>? containers = this.db.BookmarkContainers
|
||||
.Where(bc => bc.ApplicationUserId == userId)
|
||||
.SortContainers()
|
||||
.ToList();
|
||||
|
||||
if (containers == null)
|
||||
// The container *was* deleted, so indicate as such
|
||||
return true;
|
||||
|
||||
// Fix up sort order just in case
|
||||
for (int i = 0; i < containers.Count; i++) {
|
||||
containers[i].SortOrder = i;
|
||||
}
|
||||
|
||||
await this.db.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ namespace Start.Server.Data.Services {
|
|||
}
|
||||
|
||||
public async Task<BookmarkGroup?> CreateBookmarkGroup(string userId, string title,
|
||||
string color, int bookmarkContainerId) {
|
||||
string color, int sortOrder, int bookmarkContainerId) {
|
||||
if (!BookmarkOwnershipTools
|
||||
.IsBookmarkContainerOwner(this.db, userId, bookmarkContainerId))
|
||||
return null;
|
||||
|
||||
BookmarkGroup newBookmarkGroup = new(title, color, bookmarkContainerId);
|
||||
BookmarkGroup newBookmarkGroup = new(title, color, sortOrder, bookmarkContainerId);
|
||||
await this.db.BookmarkGroups.AddAsync(newBookmarkGroup);
|
||||
await this.db.SaveChangesAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ namespace Start.Server.Data.Services {
|
|||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Bookmark?> CreateBookmark(string userId, string title, string url, string? notes,
|
||||
int bookmarkGroupId) {
|
||||
public async Task<Bookmark?> CreateBookmark(string userId, string title, string url,
|
||||
string? notes, int sortOrder, int bookmarkGroupId) {
|
||||
if (!BookmarkOwnershipTools.IsBookmarkGroupOwner(this.db, userId, bookmarkGroupId))
|
||||
return null;
|
||||
|
||||
Bookmark newBookmark = new(title, url, notes, bookmarkGroupId);
|
||||
Bookmark newBookmark = new(title, url, notes, sortOrder, bookmarkGroupId);
|
||||
|
||||
await db.Bookmarks.AddAsync(newBookmark);
|
||||
await db.SaveChangesAsync();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Start.Server.Data.Services.Interfaces {
|
|||
bool includeGroups = false, bool includeBookmarks = false);
|
||||
|
||||
public Task<BookmarkContainer?> CreateBookmarkContainer(string userId,
|
||||
string title);
|
||||
string title, int sortOrder);
|
||||
public Task<BookmarkContainer?> UpdateBookmarkContainer(string userId,
|
||||
BookmarkContainer bookmarkContainer);
|
||||
public Task<bool> DeleteBookmarkContainer(string userId, int bookmarkContainerId);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Start.Server.Models;
|
||||
using Start.Shared;
|
||||
|
||||
namespace Start.Server.Data.Services.Interfaces {
|
||||
public interface IBookmarkGroupService {
|
||||
|
|
@ -12,7 +10,7 @@ namespace Start.Server.Data.Services.Interfaces {
|
|||
bool includeBookmarks = false);
|
||||
|
||||
public Task<BookmarkGroup?> CreateBookmarkGroup(string userId, string title,
|
||||
string color, int bookmarkContainerId);
|
||||
string color, int sortOrder, int bookmarkContainerId);
|
||||
public Task<BookmarkGroup?> UpdateBookmarkGroup(string userId,
|
||||
BookmarkGroup bookmarkGroup);
|
||||
public Task<bool> DeleteBookmarkGroup(string userId, int bookmarkGroupId);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Start.Server.Data.Services.Interfaces {
|
|||
public Task<IList<Bookmark>> GetUserBookmarks(string userId);
|
||||
|
||||
public Task<Bookmark?> CreateBookmark(string userId, string title, string url,
|
||||
string? notes, int bookmarkGroupId);
|
||||
string? notes, int sortOrder, int bookmarkGroupId);
|
||||
public Task<Bookmark?> UpdateBookmark(string userId, Bookmark bookmark);
|
||||
public Task<bool> DeleteBookmark(string userId, int bookmarkId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ namespace Start.Server.Extensions {
|
|||
public static class BookmarkMaps {
|
||||
public static BookmarkDto MapToDto(this Bookmark bookmark) {
|
||||
return new BookmarkDto(bookmark.BookmarkId, bookmark.Title, bookmark.Url,
|
||||
bookmark.Notes, bookmark.BookmarkGroupId);
|
||||
bookmark.Notes, bookmark.SortOrder, bookmark.BookmarkGroupId);
|
||||
}
|
||||
|
||||
public static BookmarkGroupDto MapToDto(this BookmarkGroup bookmarkGroup) {
|
||||
return new BookmarkGroupDto(bookmarkGroup.BookmarkGroupId, bookmarkGroup.Title,
|
||||
bookmarkGroup.Color, bookmarkGroup.BookmarkContainerId,
|
||||
bookmarkGroup.Color, bookmarkGroup.SortOrder, bookmarkGroup.BookmarkContainerId,
|
||||
bookmarkGroup.Bookmarks?.Select(b => b.MapToDto()).ToList());
|
||||
}
|
||||
|
||||
public static BookmarkContainerDto MapToDto(this BookmarkContainer bookmarkContainer) {
|
||||
return new BookmarkContainerDto(bookmarkContainer.BookmarkContainerId,
|
||||
bookmarkContainer.Title,
|
||||
bookmarkContainer.Title, bookmarkContainer.SortOrder,
|
||||
bookmarkContainer.BookmarkGroups?.Select(bg => bg.MapToDto()).ToList());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
Start/Server/Extensions/SortingExtensions.cs
Normal file
28
Start/Server/Extensions/SortingExtensions.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Start.Server.Models;
|
||||
|
||||
namespace Start.Server.Extensions {
|
||||
public static class SortingExtensions {
|
||||
public static IEnumerable<BookmarkContainer> SortContainers(
|
||||
this IEnumerable<BookmarkContainer> bookmarkContainers) {
|
||||
return bookmarkContainers
|
||||
.OrderBy(bc => bc.SortOrder)
|
||||
.ThenBy(bc => bc.BookmarkContainerId);
|
||||
}
|
||||
|
||||
public static IEnumerable<BookmarkGroup> SortGroups(
|
||||
this IEnumerable<BookmarkGroup> bookmarkGroups) {
|
||||
return bookmarkGroups
|
||||
.OrderBy(bg => bg.SortOrder)
|
||||
.ThenBy(bg => bg.BookmarkGroupId);
|
||||
}
|
||||
|
||||
public static IEnumerable<Bookmark> SortBookmarks(
|
||||
this IEnumerable<Bookmark> bookmarks) {
|
||||
return bookmarks
|
||||
.OrderBy(b => b.SortOrder)
|
||||
.ThenBy(b => b.BookmarkId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Start.Server.Models {
|
||||
/// <summary>A bookmark with display text and a URL to link to</summary>
|
||||
|
|
@ -17,21 +16,24 @@ namespace Start.Server.Models {
|
|||
/// <summary>Arbitrary notes about the bookmark</summary>
|
||||
[MaxLength(5000)]
|
||||
public string? Notes { get; set; }
|
||||
/// <summary>Used for sorting lists of bookmarks</summary>
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
/// <summary>The unique ID for the group the bookmark is in</summary>
|
||||
public int BookmarkGroupId { get; set; }
|
||||
/// <summary>The group the bookmark is in</summary>
|
||||
public BookmarkGroup? BookmarkGroup { get; set; }
|
||||
|
||||
public Bookmark(string title, string url, string? notes, int bookmarkGroupId) {
|
||||
public Bookmark(string title, string url, string? notes, int sortOrder, int bookmarkGroupId) {
|
||||
this.Title = title;
|
||||
this.Url = url;
|
||||
this.Notes = notes;
|
||||
this.SortOrder = sortOrder;
|
||||
this.BookmarkGroupId = bookmarkGroupId;
|
||||
}
|
||||
|
||||
public Bookmark(int bookmarkId, string title, string url, string? notes, int bookmarkGroupId)
|
||||
: this(title, url, notes, bookmarkGroupId) {
|
||||
public Bookmark(int bookmarkId, string title, string url, string? notes, int sortOrder,
|
||||
int bookmarkGroupId) : this(title, url, notes, sortOrder, bookmarkGroupId) {
|
||||
this.BookmarkId = bookmarkId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Start.Server.Models {
|
||||
|
|
@ -8,9 +7,11 @@ namespace Start.Server.Models {
|
|||
/// <summary>A unique ID for the container</summary>
|
||||
[Key]
|
||||
public int BookmarkContainerId { get; set; }
|
||||
|
||||
/// <summary>A title to disply to the user</summary>
|
||||
[MaxLength(300)]
|
||||
public string Title { get; set; }
|
||||
/// <summary>Used for sorting lists of bookmark containers</summary>
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
/// <summary>The unique ID of the user that this container belongs to</summary>
|
||||
public string ApplicationUserId { get; set; }
|
||||
|
|
@ -20,13 +21,14 @@ namespace Start.Server.Models {
|
|||
/// <summary>The <see cref="BookmarkGroup"/>s in this container</summary>
|
||||
public List<BookmarkGroup>? BookmarkGroups { get; set; }
|
||||
|
||||
public BookmarkContainer(string applicationUserId, string title) {
|
||||
public BookmarkContainer(string applicationUserId, string title, int sortOrder) {
|
||||
this.ApplicationUserId = applicationUserId;
|
||||
this.Title = title;
|
||||
this.SortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public BookmarkContainer(int bookmarkContainerId, string applicationUserId, string title)
|
||||
: this(applicationUserId, title) {
|
||||
public BookmarkContainer(int bookmarkContainerId, string applicationUserId, string title,
|
||||
int sortOrder) : this(applicationUserId, title, sortOrder) {
|
||||
this.BookmarkContainerId = bookmarkContainerId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Start.Server.Models {
|
||||
|
|
@ -15,6 +14,8 @@ namespace Start.Server.Models {
|
|||
/// <summary>A hex color for the group</summary>
|
||||
[MaxLength(6)]
|
||||
public string Color { get; set; }
|
||||
/// <summary>Used for sorting lists of bookmark groups</summary>
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
/// <summary>The unique ID of the container this group is in</summary>
|
||||
public int BookmarkContainerId { get; set; }
|
||||
|
|
@ -24,14 +25,15 @@ namespace Start.Server.Models {
|
|||
/// <summary>The bookmarks in this group</summary>
|
||||
public List<Bookmark>? Bookmarks { get; set; }
|
||||
|
||||
public BookmarkGroup(string title, string color, int bookmarkContainerId) {
|
||||
public BookmarkGroup(string title, string color, int sortOrder, int bookmarkContainerId) {
|
||||
this.Title = title;
|
||||
this.Color = color;
|
||||
this.SortOrder = sortOrder;
|
||||
this.BookmarkContainerId = bookmarkContainerId;
|
||||
}
|
||||
|
||||
public BookmarkGroup(int bookmarkGroupId, string title, string color,
|
||||
int bookmarkContainerId) : this(title, color, bookmarkContainerId) {
|
||||
public BookmarkGroup(int bookmarkGroupId, string title, string color, int sortOrder,
|
||||
int bookmarkContainerId) : this(title, color, sortOrder, bookmarkContainerId) {
|
||||
this.BookmarkGroupId = bookmarkGroupId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue