Send To Device Support (#1557)
* Tweaked the logging output * Started implementing some basic idea for devices * Updated Email Service with new API routes * Implemented basic DB structure and some APIs to prep for the UI and flows. * Added an abstract class to make Unit testing easier. * Removed dependency we don't need * Updated the UI to be able to show devices and add new devices. Email field will update the platform if the user hasn't interacted with it already. * Added ability to delete a device as well * Basic ability to send files to devices works * Refactored Action code to pass ActionItem back and allow for dynamic children based on an Observable (api). Hooked in ability to send a chapter to a device. There is no logic in the FE to validate type. * Fixed a broken unit test * Implemented the ability to edit a device * Code cleanup * Fixed a bad success message * Fixed broken unit test from updating mock layer
This commit is contained in:
parent
ab0f13ef74
commit
9d7476a367
79 changed files with 3026 additions and 157 deletions
|
@ -44,6 +44,7 @@ public sealed class DataContext : IdentityDbContext<AppUser, AppRole, int,
|
|||
public DbSet<SiteTheme> SiteTheme { get; set; }
|
||||
public DbSet<SeriesRelation> SeriesRelation { get; set; }
|
||||
public DbSet<FolderPath> FolderPath { get; set; }
|
||||
public DbSet<Device> Device { get; set; }
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
|
|
|
@ -162,7 +162,15 @@ public static class DbFactory
|
|||
FilePath = filePath,
|
||||
Format = format,
|
||||
Pages = pages,
|
||||
LastModified = File.GetLastWriteTime(filePath) // NOTE: Changed this from DateTime.Now
|
||||
LastModified = File.GetLastWriteTime(filePath)
|
||||
};
|
||||
}
|
||||
|
||||
public static Device Device(string name)
|
||||
{
|
||||
return new Device()
|
||||
{
|
||||
Name = name,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
1658
API/Data/Migrations/20220921023455_DeviceSupport.Designer.cs
generated
Normal file
1658
API/Data/Migrations/20220921023455_DeviceSupport.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
73
API/Data/Migrations/20220921023455_DeviceSupport.cs
Normal file
73
API/Data/Migrations/20220921023455_DeviceSupport.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
public partial class DeviceSupport : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_SeriesRelation_Series_TargetSeriesId",
|
||||
table: "SeriesRelation");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Device",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
IpAddress = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
EmailAddress = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Platform = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
AppUserId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
LastUsed = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
Created = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
LastModified = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Device", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Device_AspNetUsers_AppUserId",
|
||||
column: x => x.AppUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Device_AppUserId",
|
||||
table: "Device",
|
||||
column: "AppUserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_SeriesRelation_Series_TargetSeriesId",
|
||||
table: "SeriesRelation",
|
||||
column: "TargetSeriesId",
|
||||
principalTable: "Series",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_SeriesRelation_Series_TargetSeriesId",
|
||||
table: "SeriesRelation");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Device");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_SeriesRelation_Series_TargetSeriesId",
|
||||
table: "SeriesRelation",
|
||||
column: "TargetSeriesId",
|
||||
principalTable: "Series",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace API.Data.Migrations
|
|||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.7");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.9");
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
|
@ -442,6 +442,43 @@ namespace API.Data.Migrations
|
|||
b.ToTable("CollectionTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Device", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EmailAddress")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("IpAddress")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastUsed")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Platform")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("Device");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -1262,6 +1299,17 @@ namespace API.Data.Migrations
|
|||
b.Navigation("Volume");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Device", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Devices")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Library", "Library")
|
||||
|
@ -1306,7 +1354,7 @@ namespace API.Data.Migrations
|
|||
b.HasOne("API.Entities.Series", "TargetSeries")
|
||||
.WithMany("RelationOf")
|
||||
.HasForeignKey("TargetSeriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.OnDelete(DeleteBehavior.ClientCascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Series");
|
||||
|
@ -1551,6 +1599,8 @@ namespace API.Data.Migrations
|
|||
{
|
||||
b.Navigation("Bookmarks");
|
||||
|
||||
b.Navigation("Devices");
|
||||
|
||||
b.Navigation("Progresses");
|
||||
|
||||
b.Navigation("Ratings");
|
||||
|
|
50
API/Data/Repositories/DeviceRepository.cs
Normal file
50
API/Data/Repositories/DeviceRepository.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs.Device;
|
||||
using API.Entities;
|
||||
using AutoMapper;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Data.Repositories;
|
||||
|
||||
public interface IDeviceRepository
|
||||
{
|
||||
void Update(Device device);
|
||||
Task<IEnumerable<DeviceDto>> GetDevicesForUserAsync(int userId);
|
||||
Task<Device> GetDeviceById(int deviceId);
|
||||
}
|
||||
|
||||
public class DeviceRepository : IDeviceRepository
|
||||
{
|
||||
private readonly DataContext _context;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public DeviceRepository(DataContext context, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public void Update(Device device)
|
||||
{
|
||||
_context.Entry(device).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<DeviceDto>> GetDevicesForUserAsync(int userId)
|
||||
{
|
||||
return await _context.Device
|
||||
.Where(d => d.AppUserId == userId)
|
||||
.OrderBy(d => d.LastUsed)
|
||||
.ProjectTo<DeviceDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Device> GetDeviceById(int deviceId)
|
||||
{
|
||||
return await _context.Device
|
||||
.Where(d => d.Id == deviceId)
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ public enum AppUserIncludes
|
|||
UserPreferences = 32,
|
||||
WantToRead = 64,
|
||||
ReadingListsWithItems = 128,
|
||||
Devices = 256,
|
||||
|
||||
}
|
||||
|
||||
|
@ -194,6 +195,11 @@ public class UserRepository : IUserRepository
|
|||
query = query.Include(u => u.WantToRead);
|
||||
}
|
||||
|
||||
if (includeFlags.HasFlag(AppUserIncludes.Devices))
|
||||
{
|
||||
query = query.Include(u => u.Devices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return query;
|
||||
|
|
|
@ -24,6 +24,7 @@ public interface IUnitOfWork
|
|||
ITagRepository TagRepository { get; }
|
||||
ISiteThemeRepository SiteThemeRepository { get; }
|
||||
IMangaFileRepository MangaFileRepository { get; }
|
||||
IDeviceRepository DeviceRepository { get; }
|
||||
bool Commit();
|
||||
Task<bool> CommitAsync();
|
||||
bool HasChanges();
|
||||
|
@ -60,6 +61,7 @@ public class UnitOfWork : IUnitOfWork
|
|||
public ITagRepository TagRepository => new TagRepository(_context, _mapper);
|
||||
public ISiteThemeRepository SiteThemeRepository => new SiteThemeRepository(_context, _mapper);
|
||||
public IMangaFileRepository MangaFileRepository => new MangaFileRepository(_context, _mapper);
|
||||
public IDeviceRepository DeviceRepository => new DeviceRepository(_context, _mapper);
|
||||
|
||||
/// <summary>
|
||||
/// Commits changes to the DB. Completes the open transaction.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue