diff --git a/src/Ombi.Core/Engine/IMusicRequestEngine.cs b/src/Ombi.Core/Engine/IMusicRequestEngine.cs index 02a051343..306d5c477 100644 --- a/src/Ombi.Core/Engine/IMusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/IMusicRequestEngine.cs @@ -23,5 +23,7 @@ namespace Ombi.Core.Engine Task> SearchAlbumRequest(string search); Task UserHasRequest(string userId); Task GetRemainingRequests(OmbiUser user = null); + Task> GetRequestsByStatus(int count, int position, string sort, string sortOrder, RequestStatus available); + Task> GetRequests(int count, int position, string sort, string sortOrder); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index 39987f2ad..e473c1fb1 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -23,6 +23,7 @@ using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; +using System.ComponentModel; namespace Ombi.Core.Engine { @@ -253,6 +254,28 @@ namespace Ombi.Core.Engine return allRequests; } + + private async Task CheckForSubscription(HideResult shouldHide, List albumRequests) + { + var requestIds = albumRequests.Select(x => x.Id); + var sub = await _subscriptionRepository.GetAll().Where(s => + s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) + .ToListAsync(); + foreach (var x in albumRequests) + { + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id); + x.Subscribed = hasSub != null; + } + } + } + private async Task CheckForSubscription(HideResult shouldHide, AlbumRequest x) { if (shouldHide.UserId == x.RequestedUserId) @@ -500,6 +523,110 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"{model.Title} has been successfully added!", RequestId = model.Id }; } - + public async Task> GetRequestsByStatus(int count, int position, string sortProperty, string sortOrder, RequestStatus status) + { + var shouldHide = await HideFromOtherUsers(); + IQueryable allRequests; + if (shouldHide.Hide) + { + allRequests = + MusicRepository.GetWithUser(shouldHide + .UserId); + } + else + { + allRequests = + MusicRepository + .GetWithUser(); + } + + switch (status) + { + case RequestStatus.PendingApproval: + allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.ProcessingRequest: + allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.Available: + allRequests = allRequests.Where(x => x.Available); + break; + case RequestStatus.Denied: + allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available); + break; + default: + break; + } + + var prop = TypeDescriptor.GetProperties(typeof(AlbumRequest)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(AlbumRequest)).Find("RequestedDate", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); + return new RequestsViewModel + { + Collection = requests, + Total = total + }; + } + + public async Task> GetRequests(int count, int position, string sortProperty, string sortOrder) + { + var shouldHide = await HideFromOtherUsers(); + IQueryable allRequests; + if (shouldHide.Hide) + { + allRequests = + MusicRepository.GetWithUser(shouldHide + .UserId); + } + else + { + allRequests = + MusicRepository + .GetWithUser(); + } + + var prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find("RequestedDate", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); + return new RequestsViewModel + { + Collection = requests, + Total = total + }; + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/AlbumRequest.cs b/src/Ombi.Store/Entities/Requests/AlbumRequest.cs index 2735603c6..eecf05e6e 100644 --- a/src/Ombi.Store/Entities/Requests/AlbumRequest.cs +++ b/src/Ombi.Store/Entities/Requests/AlbumRequest.cs @@ -17,5 +17,34 @@ namespace Ombi.Store.Entities.Requests public bool Subscribed { get; set; } [NotMapped] public bool ShowSubscribe { get; set; } + + + [NotMapped] + public string RequestStatus { + get + { + if (Available) + { + return "Common.Available"; + } + + if (Denied ?? false) + { + return "Common.Denied"; + } + + if (Approved & !Available) + { + return "Common.ProcessingRequest"; + } + + if (!Approved && !Available) + { + return "Common.PendingApproval"; + } + + return string.Empty; + } + } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html index e40815036..94bb66a12 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html @@ -1,3 +1,3 @@
- +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html index fe89c22b2..34dc80a47 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html @@ -3,7 +3,7 @@ Advanced Options
- Radarr Quality Profile + {{'MediaDetails.RadarrProfile' | translate }} {{profile.name}} @@ -11,7 +11,7 @@
- Radarr Root Folders + {{'MediaDetails.RadarrFolder' | translate }} {{profile.path}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index 99fdd5685..8c9f73baf 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -1,17 +1,17 @@
- Status: + {{'MediaDetails.Status' | translate }}:
{{movie.status}}
- Availability + {{'MediaDetails.Availability' | translate }}
{{'Common.Available' | translate}}
{{'Common.NotAvailable' | translate}}
- Request Status + {{'MediaDetails.RequestStatus' | translate }}
{{'Common.ProcessingRequest' | translate}}
{{'Common.PendingApproval' | translate}}
@@ -19,21 +19,21 @@
- Quality: + {{'MediaDetails.Quality' | translate }}:
{{movie.quality | quality}}
- Root Folder Override + {{'MediaDetails.RootFolderOverride' | translate }}
{{advancedOptions.rootFolder.path}}
- Quality Override + {{'MediaDetails.QualityOverride' | translate }}
{{advancedOptions.profile.name}}

- Genres: + {{'MediaDetails.Genres' | translate }}:
@@ -44,45 +44,45 @@

- Theatrical Release: + {{'MediaDetails.TheatricalRelease' | translate }}:
{{movie.releaseDate | date: 'mediumDate'}}
- Digital Release: + {{'MediaDetails.DigitalRelease' | translate }}:
{{movie.digitalReleaseDate | date: 'mediumDate'}}
- User Score: + {{'MediaDetails.UserScore' | translate }}:
{{movie.voteAverage | number:'1.0-1'}} / 10
- Votes: + {{'MediaDetails.Votes' | translate }}:
{{movie.voteCount | thousandShort: 1}}
- Runtime: -
{{movie.runtime}} Minutes
+ {{'MediaDetails.Runtime' | translate }}: +
{{'MediaDetails.Minutes' | translate:{runtime: movie.runtime} }}
- Revenue: + {{'MediaDetails.Revenue' | translate }}:
{{movie.revenue | currency: 'USD'}}
- Budget: + {{'MediaDetails.Budget' | translate }}:
{{movie.budget | currency: 'USD'}}

- Keywords/Tags: + {{'MediaDetails.Keywords' | translate }}: {{keyword.name}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html index 5c5844817..cfee3bc06 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html @@ -1,6 +1,6 @@
- Status: + {{'MediaDetails.Status' | translate }}:
{{tv.status}}
@@ -13,15 +13,9 @@
- Status: + {{'MediaDetails.Runtime' | translate }}:
- {{tv.status}} -
-
-
- Runtime: -
- {{tv.runtime}} Minutes + {{'MediaDetails.Minutes' | translate:{ runtime: tv.runtime} }}
@@ -38,7 +32,7 @@
- Genres: + {{'MediaDetails.Genres' | translate }}:
{{genre}} | diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html new file mode 100644 index 000000000..63e771e89 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html @@ -0,0 +1,72 @@ +
+ + + + +
+
+ + + + + +
+
+ +
+
+ + + 10 + 15 + 30 + 100 + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'Requests.ArtistName' | translate}} {{element.artistName}} {{ 'Requests.AlbumName' | translate}} {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) {{'Requests.RequestedBy' | translate}} {{element.requestedUser?.userAlias}} {{ 'Requests.RequestDate' | translate}} {{element.requestedDate | amLocal | amDateFormat: 'LL'}} {{ 'Requests.RequestStatus' | translate}} {{element.requestStatus | translate}} + + +
+ + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss new file mode 100644 index 000000000..fd5a5e47c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss @@ -0,0 +1,49 @@ +@import "~styles/variables.scss"; + +.dark .mat-header-cell { + background: $accent-dark !important; + font-size: 1em; + font-weight: bold; + color: #303030; +} + +.mat-form-field { + float:right; + margin-right:20px; +} + +/*::ng-deep .dark .mat-form-field-label{ + font-size: 1.2em; +}*/ + +::ng-deep .mat-form-field-infix { + width: 8em; + margin-top:1em; +} + +::ng-deep .dark .mat-tab-label-active{ + background: $accent-dark !important; + color: #303030 !important; + font-weight:bold; +} + +::ng-deep .mat-tab-label{ + opacity: 1; +} + +::ng-deep .row { + margin-right:0; + margin-left:0; +} + +@media (min-width: 500px) { + .justify-content-md-center { + justify-content: normal !important; + } +} + +@media (min-width: 1170px){ + .justify-content-md-center { + justify-content: center !important; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts new file mode 100644 index 000000000..4a9c3d0d7 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts @@ -0,0 +1,136 @@ +import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef, OnInit } from "@angular/core"; +import { IRequestsViewModel, IAlbumRequest } from "../../../interfaces"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; +import { merge, Observable, of as observableOf } from 'rxjs'; +import { catchError, map, startWith, switchMap } from 'rxjs/operators'; + +import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { AuthService } from "../../../auth/auth.service"; +import { StorageService } from "../../../shared/storage/storage-service"; +import { RequestFilterType } from "../../models/RequestFilterType"; + +@Component({ + templateUrl: "./albums-grid.component.html", + selector: "albums-grid", + styleUrls: ["./albums-grid.component.scss"] +}) +export class AlbumsGridComponent implements OnInit, AfterViewInit { + public dataSource: IAlbumRequest[] = []; + public resultsLength: number; + public isLoadingResults = true; + public displayedColumns: string[] = ['artistName', 'title', 'requestedUser.requestedBy', 'requestStatus','requestedDate', 'actions']; + public gridCount: string = "15"; + public isAdmin: boolean; + public defaultSort: string = "requestedDate"; + public defaultOrder: string = "desc"; + public currentFilter: RequestFilterType = RequestFilterType.All; + + public RequestFilter = RequestFilterType; + + + private storageKey = "Albums_DefaultRequestListSort"; + private storageKeyOrder = "Albums_DefaultRequestListSortOrder"; + private storageKeyGridCount = "Albums_DefaultGridCount"; + private storageKeyCurrentFilter = "Albums_DefaultFilter"; + + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any }>(); + + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef, + private auth: AuthService, private storageService: StorageService) { + + } + + public ngOnInit() { + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + + const defaultCount = this.storageService.get(this.storageKeyGridCount); + const defaultSort = this.storageService.get(this.storageKey); + const defaultOrder = this.storageService.get(this.storageKeyOrder); + const defaultFilter = +this.storageService.get(this.storageKeyCurrentFilter); + if (defaultSort) { + this.defaultSort = defaultSort; + } + if (defaultOrder) { + this.defaultOrder = defaultOrder; + } + if (defaultCount) { + this.gridCount = defaultCount; + } + if (defaultFilter) { + this.currentFilter = defaultFilter; + } + } + + public async ngAfterViewInit() { + + this.storageService.save(this.storageKeyGridCount, this.gridCount); + this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString()); + + // If the user changes the sort order, reset back to the first page. + this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + this.paginator.showFirstLastButtons = true; + + merge(this.sort.sortChange, this.paginator.page, this.currentFilter) + .pipe( + startWith({}), + switchMap((value: any) => { + this.isLoadingResults = true; + if (value.active || value.direction) { + this.storageService.save(this.storageKey, value.active); + this.storageService.save(this.storageKeyOrder, value.direction); + } + return this.loadData(); + }), + map((data: IRequestsViewModel) => { + // Flip flag to show that loading has finished. + this.isLoadingResults = false; + this.resultsLength = data.total; + + return data.collection; + }), + catchError((err) => { + this.isLoadingResults = false; + return observableOf([]); + }) + ).subscribe(data => this.dataSource = data); + } + + public loadData(): Observable> { + switch(RequestFilterType[RequestFilterType[this.currentFilter]]) { + case RequestFilterType.All: + return this.requestService.getAlbumRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Pending: + return this.requestService.getAlbumPendingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Available: + return this.requestService.getAlbumAvailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Processing: + return this.requestService.getAlbumProcessingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Denied: + return this.requestService.getAlbumDeniedRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + } + + } + + public openOptions(request: IAlbumRequest) { + const filter = () => { + this.dataSource = this.dataSource.filter((req) => { + return req.id !== request.id; + }) + }; + + const onChange = () => { + this.ref.detectChanges(); + }; + + this.onOpenOptions.emit({ request: request, filter: filter, onChange: onChange }); + } + + public switchFilter(type: RequestFilterType) { + this.currentFilter = type; + this.ngAfterViewInit(); + } +} diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/index.ts b/src/Ombi/ClientApp/src/app/requests-list/components/index.ts index 0cc8837e5..eac024141 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/index.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/index.ts @@ -6,13 +6,15 @@ import { RequestService } from "../../services"; import { TvGridComponent } from "./tv-grid/tv-grid.component"; import { GridSpinnerComponent } from "./grid-spinner/grid-spinner.component"; import { RequestOptionsComponent } from "./options/request-options.component"; +import { AlbumsGridComponent } from "./albums-grid/albums-grid.component"; export const components: any[] = [ RequestsListComponent, MoviesGridComponent, TvGridComponent, GridSpinnerComponent, - RequestOptionsComponent + RequestOptionsComponent, + AlbumsGridComponent ]; export const entryComponents: any[] = [ diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index 90f651164..5d7372de6 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -72,6 +72,7 @@ export class MoviesGridComponent implements OnInit, AfterViewInit { // If the user changes the sort order, reset back to the first page. this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + this.paginator.showFirstLastButtons = true; merge(this.sort.sortChange, this.paginator.page, this.currentFilter) .pipe( diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts index 153942810..5a4ef4430 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -19,6 +19,9 @@ export class RequestOptionsComponent { if (this.data.type === RequestType.tvShow) { await this.requestService.deleteChild(this.data.id).toPromise(); } + if (this.data.type === RequestType.album) { + await this.requestService.removeAlbumRequest(this.data.id).toPromise(); + } this.bottomSheetRef.dismiss({type: UpdateType.Delete}); return; @@ -31,6 +34,9 @@ export class RequestOptionsComponent { if (this.data.type === RequestType.tvShow) { await this.requestService.approveChild({id: this.data.id}).toPromise(); } + if (this.data.type === RequestType.album) { + await this.requestService.approveAlbum({id: this.data.id}).toPromise(); + } this.bottomSheetRef.dismiss({type: UpdateType.Approve}); return; diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html index 623987a1c..9a58c9d1d 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html @@ -12,8 +12,9 @@ -

Coming soon

-

...

+ + +
diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts index 891331be1..7617808a2 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts @@ -67,6 +67,7 @@ export class TvGridComponent implements OnInit, AfterViewInit { this.storageService.save(this.storageKeyGridCount, this.gridCount); this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString()); + this.paginator.showFirstLastButtons = true; // If the user changes the sort order, reset back to the first page. this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); diff --git a/src/Ombi/ClientApp/src/app/services/notification.service.ts b/src/Ombi/ClientApp/src/app/services/notification.service.ts index d72440610..df2e6c737 100644 --- a/src/Ombi/ClientApp/src/app/services/notification.service.ts +++ b/src/Ombi/ClientApp/src/app/services/notification.service.ts @@ -7,7 +7,7 @@ export class NotificationService { private config: MatSnackBarConfig = { duration:3000, - + } public success(body: string) { diff --git a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts index 0bf234dc7..3d71ce3a6 100644 --- a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; import { ServiceHelpers } from "./service.helpers"; -import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions, IRequestEngineResult } from "../interfaces"; +import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions, IRequestEngineResult, IAlbumRequest } from "../interfaces"; @Injectable() @@ -24,7 +24,7 @@ export class RequestServiceV2 extends ServiceHelpers { public getMovieProcessingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}movie/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); } - + public getMoviePendingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}movie/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); } @@ -35,34 +35,53 @@ export class RequestServiceV2 extends ServiceHelpers { public getTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } + } public getPendingTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } + } public getProcessingTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } + } public getAvailableTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } + } public getDeniedTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } - + } + public updateMovieAdvancedOptions(options: IMovieAdvancedOptions): Observable { return this.http.post(`${this.url}movie/advancedoptions`, options, {headers: this.headers}); } - + public getMovieUnavailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}movie/unavailable/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); } public getTvUnavailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/unavailable/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } - + } + + public getAlbumRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumAvailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumProcessingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumPendingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html index c411fe537..eb143bccb 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html @@ -1,5 +1,5 @@  -
+
Plex Configuration
diff --git a/src/Ombi/Controllers/V2/RequestsController.cs b/src/Ombi/Controllers/V2/RequestsController.cs index f78cfac21..a4d0b578f 100644 --- a/src/Ombi/Controllers/V2/RequestsController.cs +++ b/src/Ombi/Controllers/V2/RequestsController.cs @@ -14,15 +14,18 @@ namespace Ombi.Controllers.V2 { public class RequestsController : V2Controller { - public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine) + + private readonly IMovieRequestEngine _movieRequestEngine; + private readonly ITvRequestEngine _tvRequestEngine; + private readonly IMusicRequestEngine _musicRequestEngine; + + public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IMusicRequestEngine musicRequestEngine) { _movieRequestEngine = movieRequestEngine; _tvRequestEngine = tvRequestEngine; + _musicRequestEngine = musicRequestEngine; } - private readonly IMovieRequestEngine _movieRequestEngine; - private readonly ITvRequestEngine _tvRequestEngine; - /// /// Gets movie requests. /// @@ -129,5 +132,35 @@ namespace Ombi.Controllers.V2 { return await _movieRequestEngine.UpdateAdvancedOptions(options); } + + [HttpGet("albums/available/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAvailableAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Available); + } + + [HttpGet("album/processing/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetProcessingAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.ProcessingRequest); + } + + [HttpGet("album/pending/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetPendingAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.PendingApproval); + } + + [HttpGet("album/denied/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetDeniedAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Denied); + } + + [HttpGet("album/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequests(count, position, sort, sortOrder); + } } } \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 34c16cc79..f6fb32259 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -113,6 +113,8 @@ "Title": "Requests", "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", "TvTab": "TV Shows", "MusicTab": "Music", "RequestedBy": "Requested By", @@ -227,6 +229,25 @@ "RequestSelectedAlbums": "Request Selected Albums", "ViewCollection":"View Collection", "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions":"Advanced Options", + "RadarrProfile":"Radarr Quality Profile", + "RadarrFolder":"Radarr Root Folder", + "Status":"Status", + "Availability":"Availability", + "RequestStatus":"Request Status", + "Quality":"Quality", + "RootFolderOverride":"Root Folder Override", + "QualityOverride":"Quality Override", + "Genres":"Genres", + "TheatricalRelease":"Theatrical Release", + "DigitalRelease":"Digital Release", + "UserScore":"User Score", + "Votes":"Votes", + "Runtime":"Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue":"Revenue", + "Budget":"Budget", + "Keywords":"Keywords/Tags", "Casts": { "CastTitle": "Cast", "Character": "Character",