mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Adding collections support.
This commit is contained in:
parent
c852d0c3b9
commit
312ab6b80b
@ -8,18 +8,24 @@ import { ShowResolverService } from './services/show-resolver.service';
|
||||
import { LibraryResolverService } from './services/library-resolver.service';
|
||||
import { PlayerComponent } from "./player/player.component";
|
||||
import { StreamResolverService } from "./services/stream-resolver.service";
|
||||
import { CollectionComponent } from "./collection/collection.component";
|
||||
import { CollectionResolverService } from "./services/collection-resolver.service";
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } },
|
||||
{ path: "browse/:library-slug", component: BrowseComponent, resolve: { shows: LibraryResolverService } },
|
||||
{ path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService } },
|
||||
{ path: "collection/:collection-slug", component: CollectionComponent, resolve: { shows: CollectionResolverService } },
|
||||
{ path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService } },
|
||||
{ path: "**", component: NotFoundComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
imports: [RouterModule.forRoot(routes,
|
||||
{
|
||||
scrollPositionRestoration: "enabled"
|
||||
})],
|
||||
exports: [RouterModule],
|
||||
providers: [LibraryResolverService, ShowResolverService, StreamResolverService]
|
||||
})
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
<ul class="navbar-nav flex-row ml-auto">
|
||||
<li class="nav-item icon">
|
||||
<mat-icon data-toggle="tooltip" data-placement="bottom" title="Search">search</mat-icon>
|
||||
<mat-icon matTooltipPosition="below" matTooltip="Search">search</mat-icon>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="icon" routerLink="/login" routerLinkActive="active" data-toggle="tooltip" data-placement="bottom" title="Login">
|
||||
<a class="icon" routerLink="/login" routerLinkActive="active" matTooltipPosition="below" matTooltip="Login">
|
||||
<mat-icon>account_circle</mat-icon>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Event, Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
|
||||
import * as $ from "jquery";
|
||||
import "bootstrap";
|
||||
//import * as $ from "jquery";
|
||||
//import "bootstrap";
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@ -46,11 +46,6 @@ export class AppComponent
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit()
|
||||
{
|
||||
$('[data-toggle="tooltip"]').tooltip({ trigger: "hover" });
|
||||
}
|
||||
}
|
||||
|
||||
interface Library
|
||||
|
@ -7,6 +7,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@ -16,6 +17,7 @@ import { EpisodesListComponent } from './episodes-list/episodes-list.component';
|
||||
import { NotFoundComponent } from './not-found/not-found.component';
|
||||
import { PlayerComponent } from './player/player.component';
|
||||
import { ShowDetailsComponent } from './show-details/show-details.component';
|
||||
import { CollectionComponent } from './collection/collection.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -25,7 +27,8 @@ import { ShowDetailsComponent } from './show-details/show-details.component';
|
||||
BrowseComponent,
|
||||
ShowDetailsComponent,
|
||||
EpisodesListComponent,
|
||||
PlayerComponent
|
||||
PlayerComponent,
|
||||
CollectionComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -38,7 +41,8 @@ import { ShowDetailsComponent } from './show-details/show-details.component';
|
||||
MatIconModule,
|
||||
MatSelectModule,
|
||||
MatMenuModule,
|
||||
MatSliderModule
|
||||
MatSliderModule,
|
||||
MatTooltipModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div class="container-fluid justify-content-center">
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="bottom" title="Filter">
|
||||
<button mat-icon-button matTooltipPosition="below" matTooltip="Filter">
|
||||
<mat-icon>filter_list</mat-icon>
|
||||
</button>
|
||||
<button mat-button data-toggle="tooltip" data-placement="bottom" title="Sort" [matMenuTriggerFor]="sortMenu">
|
||||
<button mat-button matTooltipPosition="below" matTooltip="Sort" [matMenuTriggerFor]="sortMenu">
|
||||
<mat-icon>sort</mat-icon> Sort by {{this.sortType}} <i *ngIf="this.sortUp" class="material-icons arrow">arrow_upward</i><i *ngIf="!this.sortUp" class="material-icons arrow">arrow_downward</i>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@ button
|
||||
width: 33%;
|
||||
max-width: 200px;
|
||||
list-style: none;
|
||||
padding: 1em;
|
||||
padding: .5em;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
outline: none;
|
||||
@ -36,6 +36,7 @@ button
|
||||
@include media-breakpoint-up(md)
|
||||
{
|
||||
width: 20%;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg)
|
||||
|
@ -0,0 +1 @@
|
||||
<p>collection works!</p>
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CollectionComponent } from './collection.component';
|
||||
|
||||
describe('CollectionComponent', () => {
|
||||
let component: CollectionComponent;
|
||||
let fixture: ComponentFixture<CollectionComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CollectionComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CollectionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
15
Kyoo/ClientApp/src/app/collection/collection.component.ts
Normal file
15
Kyoo/ClientApp/src/app/collection/collection.component.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-collection',
|
||||
templateUrl: './collection.component.html',
|
||||
styleUrls: ['./collection.component.scss']
|
||||
})
|
||||
export class CollectionComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@ -13,14 +13,6 @@
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover
|
||||
{
|
||||
.episodes
|
||||
{
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.episodes
|
||||
@ -32,7 +24,6 @@
|
||||
min-width: 100%;
|
||||
flex-shrink: 0;
|
||||
flex-direction: row;
|
||||
visibility: hidden;
|
||||
|
||||
&::-webkit-scrollbar
|
||||
{
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
<div id="hover">
|
||||
<div class="back">
|
||||
<a mat-icon-button data-toggle="tooltip" data-placement="bottom" title="Back" href="/show/{{this.item.showSlug}}" routerLink="/show/{{this.item.showSlug}}">
|
||||
<a mat-icon-button matTooltipPosition="below" matTooltip="Back" href="/show/{{this.item.showSlug}}" routerLink="/show/{{this.item.showSlug}}">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</a>
|
||||
<h5>{{this.item.showTitle}}</h5>
|
||||
@ -35,10 +35,10 @@
|
||||
|
||||
<div class="buttons">
|
||||
<div class="left">
|
||||
<a *ngIf="this.item.previousEpisode" mat-icon-button data-toggle="tooltip" data-placement="top" title="Previous" routerLink="/watch/{{this.item.previousEpisode}}" href="/watch/{{this.item.previousEpisode}}" queryParamsHandling="merge">
|
||||
<a *ngIf="this.item.previousEpisode" mat-icon-button matTooltipPosition="above" matTooltip="Previous" routerLink="/watch/{{this.item.previousEpisode}}" href="/watch/{{this.item.previousEpisode}}" queryParamsHandling="merge">
|
||||
<mat-icon>skip_previous</mat-icon>
|
||||
</a>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Play" id="play" (click)="tooglePlayback()">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Play" id="play" (click)="tooglePlayback()">
|
||||
<mat-icon>{{this.playIcon}}</mat-icon>
|
||||
</button>
|
||||
<a mat-icon-button id="nextBtn" *ngIf="this.item.nextEpisode" routerLink="/watch/{{this.item.nextEpisode.link}}" href="/watch/{{this.item.nextEpisode.link}}" queryParamsHandling="merge">
|
||||
@ -55,7 +55,7 @@
|
||||
</div>
|
||||
</a>
|
||||
<div id="volume">
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Volume" (click)="toogleMute()">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Volume" (click)="toogleMute()">
|
||||
<mat-icon>{{this.volumeIcon}}</mat-icon>
|
||||
</button>
|
||||
|
||||
@ -65,19 +65,19 @@
|
||||
<ng-template #elseBlock><p>{{this.minutes | number: '2.0-0'}}:{{this.seconds | number: '2.0-0'}} / {{this.maxMinutes | number: '2.0-0'}}:{{this.maxSeconds | number: '2.0-0'}}</p></ng-template>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button *ngIf="this.item.audios.length > 0" mat-icon-button data-toggle="tooltip" data-placement="top" title="Select audio track">
|
||||
<button *ngIf="this.item.audios.length > 0" mat-icon-button matTooltipPosition="above" matTooltip="Select audio track">
|
||||
<mat-icon>music_note</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles" data-toggle="tooltip" data-placement="top" title="Select subtitle track">
|
||||
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles" matTooltipPosition="above" matTooltip="Select subtitle track">
|
||||
<mat-icon>closed_caption</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Cast">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Cast">
|
||||
<mat-icon>cast</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Settings">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Settings">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Fullscreen" id="fullscreen" (click)="fullscreen()">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Fullscreen" id="fullscreen" (click)="fullscreen()">
|
||||
<mat-icon>{{fullscreenIcon}}</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -0,0 +1,32 @@
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
|
||||
import { EMPTY, Observable } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { Collection } from "../../models/collection";
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class CollectionResolverService implements Resolve<Collection>
|
||||
{
|
||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Collection | Observable<Collection> | Promise<Collection>
|
||||
{
|
||||
let collection: string = route.paramMap.get("collection-slug");
|
||||
return this.http.get<Collection>("api/collection/" + collection).pipe(catchError((error: HttpErrorResponse) =>
|
||||
{
|
||||
console.log(error.status + " - " + error.message);
|
||||
if (error.status == 404)
|
||||
{
|
||||
this.snackBar.open("Collection \"" + collection + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||
}
|
||||
return EMPTY;
|
||||
}));
|
||||
}
|
||||
}
|
@ -12,19 +12,19 @@
|
||||
<ng-template #elseBlock><h2 class="date">{{show.startYear}}</h2></ng-template>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button mat-mini-fab data-toggle="tooltip" data-placement="top" title="Play" class="mr-3">
|
||||
<button mat-mini-fab matTooltipPosition="above" matTooltip="Play" class="mr-3">
|
||||
<mat-icon>play_arrow</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="this.show.trailerUrl" mat-icon-button data-toggle="tooltip" data-placement="top" title="Trailer">
|
||||
<button *ngIf="this.show.trailerUrl" mat-icon-button matTooltipPosition="above" matTooltip="Trailer">
|
||||
<mat-icon>local_movies</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Download">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Download">
|
||||
<mat-icon>cloud_download</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Watched">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="Watched">
|
||||
<mat-icon>done</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="More">
|
||||
<button mat-icon-button matTooltipPosition="above" matTooltip="More">
|
||||
<mat-icon>more_horiz</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -17,8 +17,13 @@ a
|
||||
{
|
||||
width: 100%;
|
||||
max-height: 75vh;
|
||||
min-height: 60vh;
|
||||
object-fit: cover;
|
||||
min-height: 20vh;
|
||||
|
||||
@include media-breakpoint-up(md)
|
||||
{
|
||||
min-height: 60vh;
|
||||
}
|
||||
}
|
||||
|
||||
&:after
|
||||
@ -194,12 +199,6 @@ hr
|
||||
min-width: 100%;
|
||||
flex-shrink: 0;
|
||||
flex-direction: row;
|
||||
visibility: hidden;
|
||||
|
||||
&:hover
|
||||
{
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar
|
||||
{
|
||||
|
3
Kyoo/ClientApp/src/models/collection.js
Normal file
3
Kyoo/ClientApp/src/models/collection.js
Normal file
@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=collection.js.map
|
1
Kyoo/ClientApp/src/models/collection.js.map
Normal file
1
Kyoo/ClientApp/src/models/collection.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"collection.js","sourceRoot":"","sources":["collection.ts"],"names":[],"mappings":""}
|
9
Kyoo/ClientApp/src/models/collection.ts
Normal file
9
Kyoo/ClientApp/src/models/collection.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Show } from "./show";
|
||||
|
||||
export interface Collection
|
||||
{
|
||||
slug: string;
|
||||
name: string;
|
||||
overview: string;
|
||||
shows: Show[];
|
||||
}
|
30
Kyoo/Controllers/CollectionController.cs
Normal file
30
Kyoo/Controllers/CollectionController.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class CollectionController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager libraryManager;
|
||||
|
||||
public CollectionController(ILibraryManager libraryManager)
|
||||
{
|
||||
this.libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<Collection> GetShows(string collectionSlug)
|
||||
{
|
||||
Collection collection = libraryManager.GetCollection(collectionSlug);
|
||||
|
||||
if (collection == null)
|
||||
return NotFound();
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ namespace Kyoo.InternalAPI
|
||||
List<Genre> GetGenreForShow(long showID);
|
||||
List<Season> GetSeasons(long showID);
|
||||
int GetSeasonCount(string showSlug, long seasonNumber);
|
||||
IEnumerable<Show> GetShowsInCollection(long collectionID);
|
||||
|
||||
//Internal HTML read
|
||||
(List<Track> audios, List<Track> subtitles) GetStreams(long episodeID, string showSlug);
|
||||
@ -31,6 +32,7 @@ namespace Kyoo.InternalAPI
|
||||
People GetPeopleBySlug(string slug);
|
||||
Genre GetGenreBySlug(string slug);
|
||||
Studio GetStudioBySlug(string slug);
|
||||
Collection GetCollection(string slug);
|
||||
|
||||
//Check if value exists
|
||||
bool IsShowRegistered(string showPath);
|
||||
@ -40,6 +42,7 @@ namespace Kyoo.InternalAPI
|
||||
bool IsEpisodeRegistered(string episodePath);
|
||||
|
||||
//Register values
|
||||
long RegisterCollection(Collection collection);
|
||||
long RegisterShow(Show show);
|
||||
long RegisterSeason(Season season);
|
||||
long RegisterEpisode(Episode episode);
|
||||
|
@ -97,6 +97,20 @@ namespace Kyoo.InternalAPI
|
||||
FOREIGN KEY(showID) REFERENCES shows(id)
|
||||
);
|
||||
|
||||
CREATE TABLE collections(
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
slug TEXT UNIQUE,
|
||||
name TEXT,
|
||||
overview TEXT,
|
||||
imgPrimary TEXT
|
||||
);
|
||||
CREATE TABLE collectionsLinks(
|
||||
collectionID INTEGER,
|
||||
showID INTEGER,
|
||||
FOREIGN KEY(collectionID) REFERENCES collections(id),
|
||||
FOREIGN KEY(showID) REFERENCES shows(id)
|
||||
);
|
||||
|
||||
CREATE TABLE studios(
|
||||
id INTEGER PRIMARY KEY UNIQUE,
|
||||
slug TEXT UNIQUE,
|
||||
@ -515,6 +529,38 @@ namespace Kyoo.InternalAPI
|
||||
// return genres;
|
||||
//}
|
||||
}
|
||||
|
||||
public Collection GetCollection(string slug)
|
||||
{
|
||||
string query = "SELECT * FROM collections WHERE slug = $slug;";
|
||||
|
||||
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("$slug", slug);
|
||||
SQLiteDataReader reader = cmd.ExecuteReader();
|
||||
|
||||
if (reader.Read())
|
||||
return Collection.FromReader(reader).SetShows(this);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Show> GetShowsInCollection(long collectionID)
|
||||
{
|
||||
string query = "SELECT * FROM shows JOIN collectionsLink l ON l.showID = shows.id WHERE l.collectionID = $id;";
|
||||
|
||||
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("$id", collectionID);
|
||||
SQLiteDataReader reader = cmd.ExecuteReader();
|
||||
List<Show> shows = new List<Show>();
|
||||
while (reader.Read())
|
||||
shows.Add(Show.FromReader(reader));
|
||||
|
||||
return shows;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Check if items exists
|
||||
@ -638,6 +684,23 @@ namespace Kyoo.InternalAPI
|
||||
#endregion
|
||||
|
||||
#region Write Into The Database
|
||||
public long RegisterCollection(Collection collection)
|
||||
{
|
||||
string query = "INSERT INTO collections (slug, name, overview, imgPrimary) VALUES($slug, $name, $overview, $imgPrimary);";
|
||||
|
||||
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("$slug", collection.Slug);
|
||||
cmd.Parameters.AddWithValue("$name", collection.Name);
|
||||
cmd.Parameters.AddWithValue("$overview", collection.Overview);
|
||||
cmd.Parameters.AddWithValue("$imgPrimary", collection.ImgPrimary);
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
cmd.CommandText = "SELECT LAST_INSERT_ROWID()";
|
||||
return (long)cmd.ExecuteScalar();
|
||||
}
|
||||
}
|
||||
|
||||
public long RegisterShow(Show show)
|
||||
{
|
||||
string query = "INSERT INTO shows (slug, title, aliases, path, overview, trailerUrl, startYear, endYear, imgPrimary, imgThumb, imgLogo, imgBackdrop, externalIDs) VALUES($slug, $title, $aliases, $path, $overview, $trailerUrl, $startYear, $endYear, $imgPrimary, $imgThumb, $imgLogo, $imgBackdrop, $externalIDs);";
|
||||
|
@ -34,6 +34,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="ClientApp\src\models\collection.ts" />
|
||||
<None Remove="ClientApp\src\models\genre.ts" />
|
||||
<None Remove="ClientApp\src\models\people.ts" />
|
||||
<None Remove="ClientApp\src\models\show.ts" />
|
||||
@ -76,6 +77,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TypeScriptCompile Include="ClientApp\src\models\collection.ts" />
|
||||
<TypeScriptCompile Include="ClientApp\src\models\genre.ts" />
|
||||
<TypeScriptCompile Include="ClientApp\src\models\people.ts" />
|
||||
<TypeScriptCompile Include="ClientApp\src\models\show.ts" />
|
||||
|
42
Kyoo/Models/Collection.cs
Normal file
42
Kyoo/Models/Collection.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Collection
|
||||
{
|
||||
[JsonIgnore] public long id;
|
||||
public string Slug;
|
||||
public string Name;
|
||||
public string Overview;
|
||||
[JsonIgnore] public string ImgPrimary;
|
||||
public IEnumerable<Show> Shows;
|
||||
|
||||
public Collection() { }
|
||||
|
||||
public Collection(long id, string slug, string name, string overview, string imgPrimary)
|
||||
{
|
||||
this.id = id;
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Overview = overview;
|
||||
ImgPrimary = imgPrimary;
|
||||
}
|
||||
|
||||
public static Collection FromReader(System.Data.SQLite.SQLiteDataReader reader)
|
||||
{
|
||||
return new Collection((long)reader["id"],
|
||||
reader["slug"] as string,
|
||||
reader["name"] as string,
|
||||
reader["overview"] as string,
|
||||
reader["imgPrimary"] as string);
|
||||
}
|
||||
|
||||
public Collection SetShows(ILibraryManager libraryManager)
|
||||
{
|
||||
Shows = libraryManager.GetShowsInCollection(id);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ namespace Kyoo
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseKestrel()
|
||||
.UseUrls("http://*:5000")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"server.urls": "http://0.0.0.0",
|
||||
"server.urls": "http://0.0.0.0:5000",
|
||||
"https_port": 44300,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user