diff --git a/Server/Bibblan.csproj b/Server/Bibblan.csproj
index 3defcaf..3fa154e 100644
--- a/Server/Bibblan.csproj
+++ b/Server/Bibblan.csproj
@@ -14,6 +14,8 @@
9.*-*
+
+
diff --git a/Server/Business/Services/CalibreService.cs b/Server/Business/Services/CalibreService.cs
new file mode 100644
index 0000000..672af21
--- /dev/null
+++ b/Server/Business/Services/CalibreService.cs
@@ -0,0 +1,44 @@
+using Bibblan.Models;
+using Bibblan.ViewModels;
+
+namespace Bibblan.Business.Services
+{
+ public class CalibreService
+ {
+ CalibreContext _context;
+ public CalibreService(CalibreContext context)
+ {
+ _context = context;
+ }
+
+ public IQueryable GetAllBooks()
+ {
+ return from b in _context.Books
+ join ba in _context.BooksAuthorsLink on b.Id equals ba.Book
+ join a in _context.Authors on ba.Author equals a.Id
+ join comment in _context.Comments on b.Id equals comment.Book into comments
+ from comment in comments.DefaultIfEmpty()
+ join bl in _context.BooksLanguagesLink on b.Id equals bl.Book
+ join l in _context.Languages on bl.LangCode equals l.Id
+ join bs in _context.BooksSeriesLink on b.Id equals bs.Book into book_series_link
+ from bs in book_series_link.DefaultIfEmpty()
+ join s in _context.Series on bs.Series equals s.Id into series
+ from s in series.DefaultIfEmpty()
+ orderby b.Title
+ select new BookVm
+ {
+ Id = b.Id,
+ Title = b.Title,
+ AuthorId = a.Id,
+ Author = a.Sort,
+ Comments = comment.Text,
+ Language = l.LangCode,
+ Path = b.Path,
+ HasCover = b.HasCover == "1",
+ Formats = (from d in _context.Data where d.Book == b.Id orderby d.Format select new DataVm { Id = d.Id, Format = d.Format, FileName = d.Name + "." + d.Format.ToLower() }).ToList(),
+ SeriesName = s.Name,
+ SeriesNumber = b.SeriesIndex
+ };
+ }
+ }
+}
diff --git a/Server/Controllers/CalibreController.cs b/Server/Controllers/CalibreController.cs
new file mode 100644
index 0000000..6a1c147
--- /dev/null
+++ b/Server/Controllers/CalibreController.cs
@@ -0,0 +1,23 @@
+using Bibblan.Business.Services;
+using Bibblan.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Bibblan.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ public class CalibreController : ControllerBase
+ {
+ CalibreService service;
+ public CalibreController(CalibreContext db) {
+ service = new CalibreService(db);
+ }
+
+ [HttpGet("books")]
+ public IActionResult GetBooks()
+ {
+ var books = service.GetAllBooks().Take(100).ToList();
+ return Ok(books);
+ }
+ }
+}
diff --git a/Server/Models/CalibreContext.cs b/Server/Models/CalibreContext.cs
new file mode 100644
index 0000000..e9d07c2
--- /dev/null
+++ b/Server/Models/CalibreContext.cs
@@ -0,0 +1,765 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Bibblan.Models
+{
+ public partial class Authors
+ {
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public string Sort { get; set; }
+ public string Link { get; set; }
+ }
+
+ public partial class Books
+ {
+ public long Id { get; set; }
+ public string Title { get; set; }
+ public string Sort { get; set; }
+ public string Timestamp { get; set; }
+ public string Pubdate { get; set; }
+ public double SeriesIndex { get; set; }
+ public string AuthorSort { get; set; }
+ public string Isbn { get; set; }
+ public string Lccn { get; set; }
+ public string Path { get; set; }
+ public long Flags { get; set; }
+ public string Uuid { get; set; }
+ public string HasCover { get; set; }
+ public string LastModified { get; set; }
+ }
+
+ public partial class BooksAuthorsLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long Author { get; set; }
+ }
+
+ public partial class BooksLanguagesLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long LangCode { get; set; }
+ public long ItemOrder { get; set; }
+ }
+
+ public partial class BooksPluginData
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public string Name { get; set; }
+ public string Val { get; set; }
+ }
+
+ public partial class BooksPublishersLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long Publisher { get; set; }
+ }
+
+ public partial class BooksRatingsLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long Rating { get; set; }
+ }
+
+ public partial class BooksSeriesLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long Series { get; set; }
+ }
+
+ public partial class BooksTagsLink
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public long Tag { get; set; }
+ }
+
+
+ public partial class Comments
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public string Text { get; set; }
+ }
+
+ public partial class ConversionOptions
+ {
+ public long Id { get; set; }
+ public string Format { get; set; }
+ public long? Book { get; set; }
+ public byte[] Data { get; set; }
+ }
+
+ public partial class CustomColumns
+ {
+ public long Id { get; set; }
+ public string Label { get; set; }
+ public string Name { get; set; }
+ public string Datatype { get; set; }
+ public string MarkForDelete { get; set; }
+ public string Editable { get; set; }
+ public string Display { get; set; }
+ public string IsMultiple { get; set; }
+ public string Normalized { get; set; }
+ }
+
+ public partial class Data
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public string Format { get; set; }
+ public long UncompressedSize { get; set; }
+ public string Name { get; set; }
+ }
+
+ public partial class Feeds
+ {
+ public long Id { get; set; }
+ public string Title { get; set; }
+ public string Script { get; set; }
+ }
+
+ public partial class Identifiers
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ public string Type { get; set; }
+ public string Val { get; set; }
+ }
+
+ public partial class Languages
+ {
+ public long Id { get; set; }
+ public string LangCode { get; set; }
+ }
+
+ public partial class LibraryId
+ {
+ public long Id { get; set; }
+ public string Uuid { get; set; }
+ }
+
+ public partial class MetadataDirtied
+ {
+ public long Id { get; set; }
+ public long Book { get; set; }
+ }
+
+ public partial class Preferences
+ {
+ public long Id { get; set; }
+ public string Key { get; set; }
+ public string Val { get; set; }
+ }
+
+ public partial class Publishers
+ {
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public string Sort { get; set; }
+ }
+
+ public partial class Ratings
+ {
+ public long Id { get; set; }
+ public long? Rating { get; set; }
+ }
+
+ public partial class Series
+ {
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public string Sort { get; set; }
+ }
+
+ public partial class Tags
+ {
+ public long Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ public partial class CalibreContext : DbContext
+ {
+ public virtual DbSet Authors { get; set; }
+ public virtual DbSet Books { get; set; }
+ public virtual DbSet BooksAuthorsLink { get; set; }
+ public virtual DbSet BooksLanguagesLink { get; set; }
+ public virtual DbSet BooksPluginData { get; set; }
+ public virtual DbSet BooksPublishersLink { get; set; }
+ public virtual DbSet BooksRatingsLink { get; set; }
+ public virtual DbSet BooksSeriesLink { get; set; }
+ public virtual DbSet BooksTagsLink { get; set; }
+ public virtual DbSet Comments { get; set; }
+ public virtual DbSet ConversionOptions { get; set; }
+ public virtual DbSet CustomColumns { get; set; }
+ public virtual DbSet Data { get; set; }
+ public virtual DbSet Feeds { get; set; }
+ public virtual DbSet Identifiers { get; set; }
+ public virtual DbSet Languages { get; set; }
+ public virtual DbSet LibraryId { get; set; }
+ public virtual DbSet MetadataDirtied { get; set; }
+ public virtual DbSet Preferences { get; set; }
+ public virtual DbSet Publishers { get; set; }
+ public virtual DbSet Ratings { get; set; }
+ public virtual DbSet Series { get; set; }
+ public virtual DbSet Tags { get; set; }
+
+ public CalibreContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("authors");
+
+ entity.HasIndex(e => e.Name)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Link)
+ .IsRequired()
+ .HasColumnName("link")
+ .HasDefaultValueSql("\"\"");
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.Sort).HasColumnName("sort");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books");
+
+ entity.HasIndex(e => e.AuthorSort)
+ .HasDatabaseName("authors_idx");
+
+ entity.HasIndex(e => e.Sort)
+ .HasDatabaseName("books_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.AuthorSort).HasColumnName("author_sort");
+
+ entity.Property(e => e.Flags)
+ .HasColumnName("flags")
+ .HasDefaultValueSql("1");
+
+ entity.Property(e => e.HasCover)
+ .HasColumnName("has_cover")
+ .HasColumnType("BOOL")
+ .HasDefaultValueSql("0");
+
+ entity.Property(e => e.Isbn)
+ .HasColumnName("isbn")
+ .HasDefaultValueSql("\"\"");
+
+ entity.Property(e => e.LastModified)
+ .IsRequired()
+ .HasColumnName("last_modified")
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("\"2000-01-01 00:00:00+00:00\"");
+
+ entity.Property(e => e.Lccn)
+ .HasColumnName("lccn")
+ .HasDefaultValueSql("\"\"");
+
+ entity.Property(e => e.Path)
+ .IsRequired()
+ .HasColumnName("path")
+ .HasDefaultValueSql("\"\"");
+
+ entity.Property(e => e.Pubdate)
+ .HasColumnName("pubdate")
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ entity.Property(e => e.SeriesIndex)
+ .HasColumnName("series_index")
+ .HasDefaultValueSql("1.0");
+
+ entity.Property(e => e.Sort).HasColumnName("sort");
+
+ entity.Property(e => e.Timestamp)
+ .HasColumnName("timestamp")
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ entity.Property(e => e.Title)
+ .IsRequired()
+ .HasColumnName("title")
+ .HasDefaultValueSql("'Unknown'");
+
+ entity.Property(e => e.Uuid).HasColumnName("uuid");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_authors_link");
+
+ entity.HasIndex(e => e.Author)
+ .HasDatabaseName("books_authors_link_aidx");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_authors_link_bidx");
+
+ entity.HasIndex(e => new { e.Book, e.Author })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Author).HasColumnName("author");
+
+ entity.Property(e => e.Book).HasColumnName("book");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_languages_link");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_languages_link_bidx");
+
+ entity.HasIndex(e => e.LangCode)
+ .HasDatabaseName("books_languages_link_aidx");
+
+ entity.HasIndex(e => new { e.Book, e.LangCode })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.ItemOrder)
+ .HasColumnName("item_order")
+ .HasDefaultValueSql("0");
+
+ entity.Property(e => e.LangCode).HasColumnName("lang_code");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_plugin_data");
+
+ entity.HasIndex(e => new { e.Book, e.Name })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.Val)
+ .IsRequired()
+ .HasColumnName("val");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_publishers_link");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_publishers_link_bidx");
+
+ entity.HasIndex(e => e.Publisher)
+ .HasDatabaseName("books_publishers_link_aidx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Publisher).HasColumnName("publisher");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_ratings_link");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_ratings_link_bidx");
+
+ entity.HasIndex(e => e.Rating)
+ .HasDatabaseName("books_ratings_link_aidx");
+
+ entity.HasIndex(e => new { e.Book, e.Rating })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Rating).HasColumnName("rating");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_series_link");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_series_link_bidx");
+
+ entity.HasIndex(e => e.Series)
+ .HasDatabaseName("books_series_link_aidx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Series).HasColumnName("series");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("books_tags_link");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("books_tags_link_bidx");
+
+ entity.HasIndex(e => e.Tag)
+ .HasDatabaseName("books_tags_link_aidx");
+
+ entity.HasIndex(e => new { e.Book, e.Tag })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Tag).HasColumnName("tag");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("comments");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("comments_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Text)
+ .IsRequired()
+ .HasColumnName("text");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("conversion_options");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("conversion_options_idx_b");
+
+ entity.HasIndex(e => e.Format)
+ .HasDatabaseName("conversion_options_idx_a");
+
+ entity.HasIndex(e => new { e.Format, e.Book })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Data)
+ .IsRequired()
+ .HasColumnName("data");
+
+ entity.Property(e => e.Format)
+ .IsRequired()
+ .HasColumnName("format");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("custom_columns");
+
+ entity.HasIndex(e => e.Label)
+ .HasDatabaseName("custom_columns_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Datatype)
+ .IsRequired()
+ .HasColumnName("datatype");
+
+ entity.Property(e => e.Display)
+ .IsRequired()
+ .HasColumnName("display")
+ .HasDefaultValueSql("\"{}\"");
+
+ entity.Property(e => e.Editable)
+ .IsRequired()
+ .HasColumnName("editable")
+ .HasColumnType("BOOL")
+ .HasDefaultValueSql("1");
+
+ entity.Property(e => e.IsMultiple)
+ .IsRequired()
+ .HasColumnName("is_multiple")
+ .HasColumnType("BOOL")
+ .HasDefaultValueSql("0");
+
+ entity.Property(e => e.Label)
+ .IsRequired()
+ .HasColumnName("label");
+
+ entity.Property(e => e.MarkForDelete)
+ .IsRequired()
+ .HasColumnName("mark_for_delete")
+ .HasColumnType("BOOL")
+ .HasDefaultValueSql("0");
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.Normalized)
+ .IsRequired()
+ .HasColumnName("normalized")
+ .HasColumnType("BOOL");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("data");
+
+ entity.HasIndex(e => e.Book)
+ .HasDatabaseName("data_idx");
+
+ entity.HasIndex(e => e.Format)
+ .HasDatabaseName("formats_idx");
+
+ entity.HasIndex(e => new { e.Book, e.Format })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Format)
+ .IsRequired()
+ .HasColumnName("format");
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.UncompressedSize).HasColumnName("uncompressed_size");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("feeds");
+
+ entity.HasIndex(e => e.Title)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Script)
+ .IsRequired()
+ .HasColumnName("script");
+
+ entity.Property(e => e.Title)
+ .IsRequired()
+ .HasColumnName("title");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("identifiers");
+
+ entity.HasIndex(e => new { e.Book, e.Type })
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+
+ entity.Property(e => e.Type)
+ .IsRequired()
+ .HasColumnName("type")
+ .HasDefaultValueSql("\"isbn\"");
+
+ entity.Property(e => e.Val)
+ .IsRequired()
+ .HasColumnName("val");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("languages");
+
+ entity.HasIndex(e => e.LangCode)
+ .HasDatabaseName("languages_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.LangCode)
+ .IsRequired()
+ .HasColumnName("lang_code");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("library_id");
+
+ entity.HasIndex(e => e.Uuid)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Uuid)
+ .IsRequired()
+ .HasColumnName("uuid");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("metadata_dirtied");
+
+ entity.HasIndex(e => e.Book)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Book).HasColumnName("book");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("preferences");
+
+ entity.HasIndex(e => e.Key)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Key)
+ .IsRequired()
+ .HasColumnName("key");
+
+ entity.Property(e => e.Val)
+ .IsRequired()
+ .HasColumnName("val");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("publishers");
+
+ entity.HasIndex(e => e.Name)
+ .HasDatabaseName("publishers_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.Sort).HasColumnName("sort");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("ratings");
+
+ entity.HasIndex(e => e.Rating)
+ .IsUnique();
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Rating).HasColumnName("rating");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("series");
+
+ entity.HasIndex(e => e.Name)
+ .HasDatabaseName("series_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+
+ entity.Property(e => e.Sort).HasColumnName("sort");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.ToTable("tags");
+
+ entity.HasIndex(e => e.Name)
+ .HasDatabaseName("tags_idx");
+
+ entity.Property(e => e.Id)
+ .HasColumnName("id")
+ .ValueGeneratedNever();
+
+ entity.Property(e => e.Name)
+ .IsRequired()
+ .HasColumnName("name");
+ });
+ }
+ }
+}
diff --git a/Server/Program.cs b/Server/Program.cs
index 1b52868..2f43674 100644
--- a/Server/Program.cs
+++ b/Server/Program.cs
@@ -1,3 +1,6 @@
+using Bibblan.Models;
+using Microsoft.EntityFrameworkCore;
+
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
@@ -6,6 +9,10 @@ builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
+var db = "metadata.db";
+var connection = $"Data Source={db};Mode=ReadOnly;";
+builder.Services.AddDbContext(options => options.UseSqlite(connection));
+
var app = builder.Build();
app.UseDefaultFiles();
diff --git a/Server/ViewModels/AuthorVm.cs b/Server/ViewModels/AuthorVm.cs
new file mode 100644
index 0000000..082090c
--- /dev/null
+++ b/Server/ViewModels/AuthorVm.cs
@@ -0,0 +1,9 @@
+namespace Bibblan.ViewModels
+{
+ public class AuthorVm
+ {
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public int BookCount { get; set; }
+ }
+}
diff --git a/Server/ViewModels/BookVm.cs b/Server/ViewModels/BookVm.cs
new file mode 100644
index 0000000..1dff4a9
--- /dev/null
+++ b/Server/ViewModels/BookVm.cs
@@ -0,0 +1,27 @@
+using Bibblan.Models;
+
+namespace Bibblan.ViewModels
+{
+ public class BookVm
+ {
+ public long Id { get; set; }
+ public string Title { get; set; }
+ public string Author { get; set; }
+ public long AuthorId { get; set; }
+ public string Comments { get; set; }
+ public string Language { get; set; }
+ public string Path { get; set; }
+ public List Formats { get; set; }
+ public bool HasCover { get; set; }
+ public string SeriesName { get; set; }
+ public double SeriesNumber { get; set; }
+
+ public string TitleAndSeries
+ {
+ get
+ {
+ return Title + (!string.IsNullOrWhiteSpace(SeriesName) ? $" ({SeriesName + (SeriesNumber > 0 ? $" {SeriesNumber:##}" : string.Empty)})" : string.Empty);
+ }
+ }
+ }
+}
diff --git a/Server/ViewModels/DataVm.cs b/Server/ViewModels/DataVm.cs
new file mode 100644
index 0000000..591c4d1
--- /dev/null
+++ b/Server/ViewModels/DataVm.cs
@@ -0,0 +1,9 @@
+namespace Bibblan.ViewModels
+{
+ public class DataVm
+ {
+ public long Id { get; set; }
+ public string Format { get; set; }
+ public string FileName { get; set; }
+ }
+}