Kavita/UI/Web/src/app/_services/series.service.ts
Joseph Milazzo 00f0ad5a3f
Misc Enhancements (#1525)
* Moved the data connection for the Database out of appsettings.json and hardcoded it. This will allow for more customization and cleaner update process.

* Removed unneeded code

* Updated pdf viewer to 15.0.0 (pdf 2.6), which now supports east-asian fonts

* Fixed up some regex parsing for volumes that have a float number.

* Fixed a bug where the tooltip for Publication Status wouldn't show

* Fixed some weird parsing rules where v1.1 would parse as volume 1 chapter 1

* Fixed a bug where bookmarking button was hidden for admins without bookmark role (due to migration)

* Unified the star rating component in series detail to match metadata filter.

* Fixed a bug in the bulk selection code when using shift selection, where the inverse of what was selected would be toggled.

* Fixed some old code where if on all series page, only English as a language would return. We now return all languages of all libraries.

* Updated api/metadata/languages documentation

* Refactored some bookmark api names: get-bookmarks -> chapter-bookmarks, get-all-bookmarks -> all-bookmarks, get-series-bookmarks -> series-bookmarks, etc.

* Refactored all cases of createSeriesFilter to filterUtiltityService.

Added ability to search for a series on Bookmarks page.

Fixed a bug where people filters wouldn't respect the disable flag froms ettings.

* Cleaned up a bit of the circular downloader code.

* Implemented Russian Parsing

* Fixed an issue where some users that had a missing theme entry wouldn't be able to update their user preferences.

* Refactored normalization to exclude !, thus allowing series with ! to be different from each other.

* Fixed a migration exit case

* Fixed broken unit test
2022-09-13 16:59:26 -07:00

209 lines
8.9 KiB
TypeScript

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { FilterUtilitiesService } from '../shared/_services/filter-utilities.service';
import { UtilityService } from '../shared/_services/utility.service';
import { Chapter } from '../_models/chapter';
import { ChapterMetadata } from '../_models/chapter-metadata';
import { CollectionTag } from '../_models/collection-tag';
import { PaginatedResult } from '../_models/pagination';
import { Series } from '../_models/series';
import { RelatedSeries } from '../_models/series-detail/related-series';
import { SeriesDetail } from '../_models/series-detail/series-detail';
import { SeriesFilter } from '../_models/series-filter';
import { SeriesGroup } from '../_models/series-group';
import { SeriesMetadata } from '../_models/series-metadata';
import { Volume } from '../_models/volume';
import { ImageService } from './image.service';
@Injectable({
providedIn: 'root'
})
export class SeriesService {
baseUrl = environment.apiUrl;
paginatedResults: PaginatedResult<Series[]> = new PaginatedResult<Series[]>();
paginatedSeriesForTagsResults: PaginatedResult<Series[]> = new PaginatedResult<Series[]>();
constructor(private httpClient: HttpClient, private imageService: ImageService,
private utilityService: UtilityService, private filterUtilitySerivce: FilterUtilitiesService) { }
getAllSeries(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
const data = this.filterUtilitySerivce.createSeriesFilter(filter);
return this.httpClient.post<PaginatedResult<Series[]>>(this.baseUrl + 'series/all', data, {observe: 'response', params}).pipe(
map((response: any) => {
return this.utilityService.createPaginatedResult(response, this.paginatedResults);
})
);
}
getSeriesForLibrary(libraryId: number, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
const data = this.filterUtilitySerivce.createSeriesFilter(filter);
return this.httpClient.post<PaginatedResult<Series[]>>(this.baseUrl + 'series?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(
map((response: any) => {
return this.utilityService.createPaginatedResult(response, this.paginatedResults);
})
);
}
getAllSeriesByIds(seriesIds: Array<number>) {
return this.httpClient.post<Series[]>(this.baseUrl + 'series/series-by-ids', {seriesIds: seriesIds});
}
getSeries(seriesId: number) {
return this.httpClient.get<Series>(this.baseUrl + 'series/' + seriesId);
}
getVolumes(seriesId: number) {
return this.httpClient.get<Volume[]>(this.baseUrl + 'series/volumes?seriesId=' + seriesId);
}
getVolume(volumeId: number) {
return this.httpClient.get<Volume>(this.baseUrl + 'series/volume?volumeId=' + volumeId);
}
getChapter(chapterId: number) {
return this.httpClient.get<Chapter>(this.baseUrl + 'series/chapter?chapterId=' + chapterId);
}
getChapterMetadata(chapterId: number) {
return this.httpClient.get<ChapterMetadata>(this.baseUrl + 'series/chapter-metadata?chapterId=' + chapterId);
}
getSeriesForMangaFile(mangaFileId: number) {
return this.httpClient.get<Series | null>(this.baseUrl + 'series/series-for-mangafile?mangaFileId=' + mangaFileId);
}
getSeriesForChapter(chapterId: number) {
return this.httpClient.get<Series | null>(this.baseUrl + 'series/series-for-chapter?chapterId=' + chapterId);
}
delete(seriesId: number) {
return this.httpClient.delete<boolean>(this.baseUrl + 'series/' + seriesId);
}
deleteMultipleSeries(seriesIds: Array<number>) {
return this.httpClient.post<boolean>(this.baseUrl + 'series/delete-multiple', {seriesIds});
}
updateRating(seriesId: number, userRating: number, userReview: string) {
return this.httpClient.post(this.baseUrl + 'series/update-rating', {seriesId, userRating, userReview});
}
updateSeries(model: any) {
return this.httpClient.post(this.baseUrl + 'series/update', model);
}
markRead(seriesId: number) {
return this.httpClient.post<void>(this.baseUrl + 'reader/mark-read', {seriesId});
}
markUnread(seriesId: number) {
return this.httpClient.post<void>(this.baseUrl + 'reader/mark-unread', {seriesId});
}
getRecentlyAdded(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {
const data = this.filterUtilitySerivce.createSeriesFilter(filter);
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
return this.httpClient.post<Series[]>(this.baseUrl + 'series/recently-added?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(
map(response => {
return this.utilityService.createPaginatedResult(response, new PaginatedResult<Series[]>());
})
);
}
getRecentlyUpdatedSeries() {
return this.httpClient.post<SeriesGroup[]>(this.baseUrl + 'series/recently-updated-series', {});
}
getWantToRead(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter): Observable<PaginatedResult<Series[]>> {
const data = this.filterUtilitySerivce.createSeriesFilter(filter);
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
return this.httpClient.post<Series[]>(this.baseUrl + 'want-to-read/', data, {observe: 'response', params}).pipe(
map(response => {
return this.utilityService.createPaginatedResult(response, new PaginatedResult<Series[]>());
}));
}
getOnDeck(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {
const data = this.filterUtilitySerivce.createSeriesFilter(filter);
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
return this.httpClient.post<Series[]>(this.baseUrl + 'series/on-deck?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(
map(response => {
return this.utilityService.createPaginatedResult(response, new PaginatedResult<Series[]>());
}));
}
refreshMetadata(series: Series) {
return this.httpClient.post(this.baseUrl + 'series/refresh-metadata', {libraryId: series.libraryId, seriesId: series.id});
}
scan(libraryId: number, seriesId: number, force = false) {
return this.httpClient.post(this.baseUrl + 'series/scan', {libraryId: libraryId, seriesId: seriesId, forceUpdate: force});
}
analyzeFiles(libraryId: number, seriesId: number) {
return this.httpClient.post(this.baseUrl + 'series/analyze', {libraryId: libraryId, seriesId: seriesId});
}
getMetadata(seriesId: number) {
return this.httpClient.get<SeriesMetadata>(this.baseUrl + 'series/metadata?seriesId=' + seriesId).pipe(map(items => {
items?.collectionTags.forEach(tag => tag.coverImage = this.imageService.getCollectionCoverImage(tag.id));
return items;
}));
}
updateMetadata(seriesMetadata: SeriesMetadata, collectionTags: CollectionTag[]) {
const data = {
seriesMetadata,
collectionTags,
};
return this.httpClient.post(this.baseUrl + 'series/metadata', data, {responseType: 'text' as 'json'});
}
getSeriesForTag(collectionTagId: number, pageNum?: number, itemsPerPage?: number) {
let params = new HttpParams();
params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);
return this.httpClient.get<PaginatedResult<Series[]>>(this.baseUrl + 'series/series-by-collection?collectionId=' + collectionTagId, {observe: 'response', params}).pipe(
map((response: any) => {
return this.utilityService.createPaginatedResult(response, this.paginatedSeriesForTagsResults);
})
);
}
getRelatedForSeries(seriesId: number) {
return this.httpClient.get<RelatedSeries>(this.baseUrl + 'series/all-related?seriesId=' + seriesId);
}
updateRelationships(seriesId: number, adaptations: Array<number>, characters: Array<number>,
contains: Array<number>, others: Array<number>, prequels: Array<number>,
sequels: Array<number>, sideStories: Array<number>, spinOffs: Array<number>,
alternativeSettings: Array<number>, alternativeVersions: Array<number>, doujinshis: Array<number>) {
return this.httpClient.post(this.baseUrl + 'series/update-related?seriesId=' + seriesId,
{seriesId, adaptations, characters, sequels, prequels, contains, others, sideStories, spinOffs,
alternativeSettings, alternativeVersions, doujinshis});
}
getSeriesDetail(seriesId: number) {
return this.httpClient.get<SeriesDetail>(this.baseUrl + 'series/series-detail?seriesId=' + seriesId);
}
}