diff options
author | crupest <crupest@outlook.com> | 2020-12-17 20:08:33 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-12-17 20:08:33 +0800 |
commit | 0bda82609a08965f7bfefd20af3ab5112ce98dd2 (patch) | |
tree | f46bf4624a600e04a5c14917b97073a5c69fe30b /BackEnd/Timeline | |
parent | 81ab4cf5c0a2d35042cb4f15a1ff699e7ba9068b (diff) | |
download | timeline-0bda82609a08965f7bfefd20af3ab5112ce98dd2.tar.gz timeline-0bda82609a08965f7bfefd20af3ab5112ce98dd2.tar.bz2 timeline-0bda82609a08965f7bfefd20af3ab5112ce98dd2.zip |
...
Diffstat (limited to 'BackEnd/Timeline')
5 files changed, 640 insertions, 3 deletions
diff --git a/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs b/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs index 3378a175..35bf6af3 100644 --- a/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs +++ b/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs @@ -24,5 +24,8 @@ namespace Timeline.Entities [Column("add_time")]
public DateTime AddTime { get; set; }
+
+ [Column("order")]
+ public long Order { get; set; }
}
}
diff --git a/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.Designer.cs b/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.Designer.cs new file mode 100644 index 00000000..6cc591fa --- /dev/null +++ b/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.Designer.cs @@ -0,0 +1,451 @@ +// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Entities;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20201217093401_AddHighlightTimelines")]
+ partial class AddHighlightTimelines
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.0");
+
+ modelBuilder.Entity("Timeline.Entities.DataEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<byte[]>("Data")
+ .IsRequired()
+ .HasColumnType("BLOB")
+ .HasColumnName("data");
+
+ b.Property<int>("Ref")
+ .HasColumnType("INTEGER")
+ .HasColumnName("ref");
+
+ b.Property<string>("Tag")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("tag");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Tag")
+ .IsUnique();
+
+ b.ToTable("data");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.HighlightTimelineEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<DateTime>("AddTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("add_time");
+
+ b.Property<long?>("OperatorId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("operator_id");
+
+ b.Property<long>("Order")
+ .HasColumnType("INTEGER")
+ .HasColumnName("order");
+
+ b.Property<long>("TimelineId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("timeline_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OperatorId");
+
+ b.HasIndex("TimelineId");
+
+ b.ToTable("highlight_timelines");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.JwtTokenEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<byte[]>("Key")
+ .IsRequired()
+ .HasColumnType("BLOB")
+ .HasColumnName("key");
+
+ b.HasKey("Id");
+
+ b.ToTable("jwt_token");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelineEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<DateTime>("CreateTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("create_time");
+
+ b.Property<long>("CurrentPostLocalId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("current_post_local_id");
+
+ b.Property<string>("Description")
+ .HasColumnType("TEXT")
+ .HasColumnName("description");
+
+ b.Property<DateTime>("LastModified")
+ .HasColumnType("TEXT")
+ .HasColumnName("last_modified");
+
+ b.Property<string>("Name")
+ .HasColumnType("TEXT")
+ .HasColumnName("name");
+
+ b.Property<DateTime>("NameLastModified")
+ .HasColumnType("TEXT")
+ .HasColumnName("name_last_modified");
+
+ b.Property<long>("OwnerId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("owner");
+
+ b.Property<string>("Title")
+ .HasColumnType("TEXT")
+ .HasColumnName("title");
+
+ b.Property<string>("UniqueId")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("unique_id")
+ .HasDefaultValueSql("lower(hex(randomblob(16)))");
+
+ b.Property<int>("Visibility")
+ .HasColumnType("INTEGER")
+ .HasColumnName("visibility");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OwnerId");
+
+ b.ToTable("timelines");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelineMemberEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<long>("TimelineId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("timeline");
+
+ b.Property<long>("UserId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("user");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TimelineId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("timeline_members");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelinePostEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<long?>("AuthorId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("author");
+
+ b.Property<string>("Content")
+ .HasColumnType("TEXT")
+ .HasColumnName("content");
+
+ b.Property<string>("ContentType")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("content_type");
+
+ b.Property<string>("ExtraContent")
+ .HasColumnType("TEXT")
+ .HasColumnName("extra_content");
+
+ b.Property<DateTime>("LastUpdated")
+ .HasColumnType("TEXT")
+ .HasColumnName("last_updated");
+
+ b.Property<long>("LocalId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("local_id");
+
+ b.Property<DateTime>("Time")
+ .HasColumnType("TEXT")
+ .HasColumnName("time");
+
+ b.Property<long>("TimelineId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("timeline");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.HasIndex("TimelineId");
+
+ b.ToTable("timeline_posts");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserAvatarEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<string>("DataTag")
+ .HasColumnType("TEXT")
+ .HasColumnName("data_tag");
+
+ b.Property<DateTime>("LastModified")
+ .HasColumnType("TEXT")
+ .HasColumnName("last_modified");
+
+ b.Property<string>("Type")
+ .HasColumnType("TEXT")
+ .HasColumnName("type");
+
+ b.Property<long>("UserId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("user");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("user_avatars");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<DateTime>("CreateTime")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("create_time")
+ .HasDefaultValueSql("datetime('now', 'utc')");
+
+ b.Property<DateTime>("LastModified")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("last_modified")
+ .HasDefaultValueSql("datetime('now', 'utc')");
+
+ b.Property<string>("Nickname")
+ .HasColumnType("TEXT")
+ .HasColumnName("nickname");
+
+ b.Property<string>("Password")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("password");
+
+ b.Property<string>("UniqueId")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("unique_id")
+ .HasDefaultValueSql("lower(hex(randomblob(16)))");
+
+ b.Property<string>("Username")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("username");
+
+ b.Property<DateTime>("UsernameChangeTime")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("username_change_time")
+ .HasDefaultValueSql("datetime('now', 'utc')");
+
+ b.Property<long>("Version")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasDefaultValue(0L)
+ .HasColumnName("version");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Username")
+ .IsUnique();
+
+ b.ToTable("users");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserPermissionEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<string>("Permission")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("permission");
+
+ b.Property<long>("UserId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("user_permission");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.HighlightTimelineEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "Operator")
+ .WithMany()
+ .HasForeignKey("OperatorId");
+
+ b.HasOne("Timeline.Entities.TimelineEntity", "Timeline")
+ .WithMany()
+ .HasForeignKey("TimelineId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Operator");
+
+ b.Navigation("Timeline");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelineEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "Owner")
+ .WithMany("Timelines")
+ .HasForeignKey("OwnerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Owner");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelineMemberEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.TimelineEntity", "Timeline")
+ .WithMany("Members")
+ .HasForeignKey("TimelineId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Timeline.Entities.UserEntity", "User")
+ .WithMany("TimelinesJoined")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Timeline");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelinePostEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "Author")
+ .WithMany("TimelinePosts")
+ .HasForeignKey("AuthorId");
+
+ b.HasOne("Timeline.Entities.TimelineEntity", "Timeline")
+ .WithMany("Posts")
+ .HasForeignKey("TimelineId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+
+ b.Navigation("Timeline");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserAvatarEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "User")
+ .WithOne("Avatar")
+ .HasForeignKey("Timeline.Entities.UserAvatarEntity", "UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserPermissionEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "User")
+ .WithMany("Permissions")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.TimelineEntity", b =>
+ {
+ b.Navigation("Members");
+
+ b.Navigation("Posts");
+ });
+
+ modelBuilder.Entity("Timeline.Entities.UserEntity", b =>
+ {
+ b.Navigation("Avatar");
+
+ b.Navigation("Permissions");
+
+ b.Navigation("TimelinePosts");
+
+ b.Navigation("Timelines");
+
+ b.Navigation("TimelinesJoined");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.cs b/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.cs new file mode 100644 index 00000000..e838615e --- /dev/null +++ b/BackEnd/Timeline/Migrations/20201217093401_AddHighlightTimelines.cs @@ -0,0 +1,55 @@ +using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Timeline.Migrations
+{
+ public partial class AddHighlightTimelines : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "highlight_timelines",
+ columns: table => new
+ {
+ id = table.Column<long>(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ timeline_id = table.Column<long>(type: "INTEGER", nullable: false),
+ operator_id = table.Column<long>(type: "INTEGER", nullable: true),
+ add_time = table.Column<DateTime>(type: "TEXT", nullable: false),
+ order = table.Column<long>(type: "INTEGER", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_highlight_timelines", x => x.id);
+ table.ForeignKey(
+ name: "FK_highlight_timelines_timelines_timeline_id",
+ column: x => x.timeline_id,
+ principalTable: "timelines",
+ principalColumn: "id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_highlight_timelines_users_operator_id",
+ column: x => x.operator_id,
+ principalTable: "users",
+ principalColumn: "id",
+ onDelete: ReferentialAction.Restrict);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_highlight_timelines_operator_id",
+ table: "highlight_timelines",
+ column: "operator_id");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_highlight_timelines_timeline_id",
+ table: "highlight_timelines",
+ column: "timeline_id");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "highlight_timelines");
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Migrations/DatabaseContextModelSnapshot.cs b/BackEnd/Timeline/Migrations/DatabaseContextModelSnapshot.cs index 2f0f75a2..ea3378dc 100644 --- a/BackEnd/Timeline/Migrations/DatabaseContextModelSnapshot.cs +++ b/BackEnd/Timeline/Migrations/DatabaseContextModelSnapshot.cs @@ -45,6 +45,38 @@ namespace Timeline.Migrations b.ToTable("data");
});
+ modelBuilder.Entity("Timeline.Entities.HighlightTimelineEntity", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("id");
+
+ b.Property<DateTime>("AddTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("add_time");
+
+ b.Property<long?>("OperatorId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("operator_id");
+
+ b.Property<long>("Order")
+ .HasColumnType("INTEGER")
+ .HasColumnName("order");
+
+ b.Property<long>("TimelineId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("timeline_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OperatorId");
+
+ b.HasIndex("TimelineId");
+
+ b.ToTable("highlight_timelines");
+ });
+
modelBuilder.Entity("Timeline.Entities.JwtTokenEntity", b =>
{
b.Property<long>("Id")
@@ -306,6 +338,23 @@ namespace Timeline.Migrations b.ToTable("user_permission");
});
+ modelBuilder.Entity("Timeline.Entities.HighlightTimelineEntity", b =>
+ {
+ b.HasOne("Timeline.Entities.UserEntity", "Operator")
+ .WithMany()
+ .HasForeignKey("OperatorId");
+
+ b.HasOne("Timeline.Entities.TimelineEntity", "Timeline")
+ .WithMany()
+ .HasForeignKey("TimelineId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Operator");
+
+ b.Navigation("Timeline");
+ });
+
modelBuilder.Entity("Timeline.Entities.TimelineEntity", b =>
{
b.HasOne("Timeline.Entities.UserEntity", "Owner")
diff --git a/BackEnd/Timeline/Services/HighlightTimelineService.cs b/BackEnd/Timeline/Services/HighlightTimelineService.cs index 0f4e5488..ea3e4c7e 100644 --- a/BackEnd/Timeline/Services/HighlightTimelineService.cs +++ b/BackEnd/Timeline/Services/HighlightTimelineService.cs @@ -9,10 +9,25 @@ using Timeline.Services.Exceptions; namespace Timeline.Services
{
+
+ [Serializable]
+ public class InvalidHighlightTimelineException : Exception
+ {
+ public InvalidHighlightTimelineException() { }
+ public InvalidHighlightTimelineException(string message) : base(message) { }
+ public InvalidHighlightTimelineException(string message, Exception inner) : base(message, inner) { }
+ protected InvalidHighlightTimelineException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+
+ /// <summary>
+ /// Service that controls highlight timeline.
+ /// </summary>
public interface IHighlightTimelineService
{
/// <summary>
- /// Get all highlight timelines.
+ /// Get all highlight timelines in order.
/// </summary>
/// <returns>A list of all highlight timelines.</returns>
Task<List<TimelineInfo>> GetHighlightTimelines();
@@ -39,6 +54,21 @@ namespace Timeline.Services /// <exception cref="TimelineNotExistException">Thrown when timeline with given name does not exist.</exception>
/// <exception cref="UserNotExistException">Thrown when user with given operator id does not exist.</exception>
Task<bool> RemoveHighlightTimeline(string timelineName, long? operatorId);
+
+ /// <summary>
+ /// Move a highlight timeline to a new position.
+ /// </summary>
+ /// <param name="timelineName">The timeline name.</param>
+ /// <param name="newPosition">The new position. Starts at 1.</param>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="timelineName"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="timelineName"/> is not a valid timeline name.</exception>
+ /// <exception cref="TimelineNotExistException">Thrown when timeline with given name does not exist.</exception>
+ /// <exception cref="InvalidHighlightTimelineException">Thrown when given timeline is not a highlight timeline.</exception>
+ /// <remarks>
+ /// If <paramref name="newPosition"/> is smaller than 1. Then move the timeline to head.
+ /// If <paramref name="newPosition"/> is bigger than total count. Then move the timeline to tail.
+ /// </remarks>
+ Task MoveHighlightTimeline(string timelineName, long newPosition);
}
public class HighlightTimelineService : IHighlightTimelineService
@@ -72,13 +102,13 @@ namespace Timeline.Services if (alreadyIs) return;
- _database.HighlightTimelines.Add(new HighlightTimelineEntity { TimelineId = timelineId, OperatorId = operatorId, AddTime = _clock.GetCurrentTime() });
+ _database.HighlightTimelines.Add(new HighlightTimelineEntity { TimelineId = timelineId, OperatorId = operatorId, AddTime = _clock.GetCurrentTime(), Order = await _database.HighlightTimelines.CountAsync() + 1 });
await _database.SaveChangesAsync();
}
public async Task<List<TimelineInfo>> GetHighlightTimelines()
{
- var entities = await _database.HighlightTimelines.Select(t => new { t.Id }).ToListAsync();
+ var entities = await _database.HighlightTimelines.OrderBy(t => t.Order).Select(t => new { t.Id }).ToListAsync();
var result = new List<TimelineInfo>();
@@ -106,10 +136,59 @@ namespace Timeline.Services if (entity == null) return false;
+ await using var transaction = await _database.Database.BeginTransactionAsync();
+
+ var order = entity.Order;
+
_database.HighlightTimelines.Remove(entity);
await _database.SaveChangesAsync();
+ await _database.Database.ExecuteSqlRawAsync("UPDATE highlight_timelines SET `order` = `order` - 1 WHERE `order` > {0}", order);
+
+ await transaction.CommitAsync();
+
return true;
}
+
+ public async Task MoveHighlightTimeline(string timelineName, long newPosition)
+ {
+ if (timelineName == null)
+ throw new ArgumentNullException(nameof(timelineName));
+
+ var timelineId = await _timelineService.GetTimelineIdByName(timelineName);
+
+ var entity = await _database.HighlightTimelines.SingleOrDefaultAsync(t => t.TimelineId == timelineId);
+
+ if (entity == null) throw new InvalidHighlightTimelineException("You can't move a non-highlight timeline.");
+
+ var oldPosition = entity.Order;
+
+ if (newPosition < 1)
+ {
+ newPosition = 1;
+ }
+ else
+ {
+ var totalCount = await _database.HighlightTimelines.CountAsync();
+ if (newPosition > totalCount) newPosition = totalCount;
+ }
+
+ if (oldPosition == newPosition) return;
+
+ await using var transaction = await _database.Database.BeginTransactionAsync();
+
+ if (newPosition > oldPosition)
+ {
+ await _database.Database.ExecuteSqlRawAsync("UPDATE highlight_timelines SET `order` = `order` - 1 WHERE `order` BETWEEN {0} AND {1}", oldPosition + 1, newPosition);
+ await _database.Database.ExecuteSqlRawAsync("UPDATE highlight_timelines SET `order` = {0} WHERE id = {1}", newPosition, entity.Id);
+ }
+ else
+ {
+ await _database.Database.ExecuteSqlRawAsync("UPDATE highlight_timelines SET `order` = `order` + 1 WHERE `order` BETWEEN {0} AND {1}", newPosition, oldPosition - 1);
+ await _database.Database.ExecuteSqlRawAsync("UPDATE highlight_timelines SET `order` = {0} WHERE id = {1}", newPosition, entity.Id);
+ }
+
+ await transaction.CommitAsync();
+ }
}
}
|