diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index 152a1d923..2163784cf 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -17,5 +17,6 @@ namespace Ombi.Core.Engine.Interfaces Task ApproveMovie(MovieRequests request); Task ApproveMovieById(int requestId); Task DenyMovieById(int modelId); + IEnumerable Filter(FilterViewModel vm); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 34885aa46..2b678b74c 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -335,22 +335,41 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!" }; } - public async Task> GetApprovedRequests() + public IEnumerable Filter(FilterViewModel vm) { - var allRequests = MovieRepository.GetWithUser(); - return await allRequests.Where(x => x.Approved && !x.Available).ToListAsync(); - } + var requests = MovieRepository.GetWithUser(); + switch (vm.AvailabilityFilter) + { + case FilterType.None: + break; + case FilterType.Available: + requests = requests.Where(x => x.Available); + break; + case FilterType.NotAvailable: + requests = requests.Where(x => !x.Available); + break; + default: + throw new ArgumentOutOfRangeException(); + } - public async Task> GetNewRequests() - { - var allRequests = MovieRepository.GetWithUser(); - return await allRequests.Where(x => !x.Approved && !x.Available).ToListAsync(); - } + switch (vm.StatusFilter) + { + case FilterType.None: + break; + case FilterType.Approved: + requests = requests.Where(x => x.Approved); + break; + case FilterType.Processing: + requests = requests.Where(x => x.Approved && !x.Available); + break; + case FilterType.PendingApproval: + requests = requests.Where(x => !x.Approved && !x.Available && !(x.Denied ?? false)); + break; + default: + throw new ArgumentOutOfRangeException(); + } - public async Task> GetAvailableRequests() - { - var allRequests = MovieRepository.GetWithUser(); - return await allRequests.Where(x => !x.Approved && x.Available).ToListAsync(); + return requests; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/FilterViewModel.cs b/src/Ombi.Core/Models/Requests/FilterViewModel.cs new file mode 100644 index 000000000..27ccc39d6 --- /dev/null +++ b/src/Ombi.Core/Models/Requests/FilterViewModel.cs @@ -0,0 +1,18 @@ +namespace Ombi.Core.Models.Requests +{ + public class FilterViewModel + { + public FilterType AvailabilityFilter { get; set; } + public FilterType StatusFilter { get; set; } + } + + public enum FilterType + { + None = 0, + Available = 1, + NotAvailable = 2, + Approved = 3, + Processing = 4, + PendingApproval = 5 + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 29aa87f0a..0eb26551d 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -12,8 +12,8 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s) { - ApplicationUrl = s.ApplicationUrl; - ApplicationName = string.IsNullOrEmpty(s.ApplicationName) ? "Ombi" : s.ApplicationName; + ApplicationUrl = s?.ApplicationUrl; + ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName; RequestedUser = string.IsNullOrEmpty(req.RequestedUser.Alias) ? req.RequestedUser.UserName : req.RequestedUser.Alias; @@ -29,8 +29,8 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s) { - ApplicationUrl = s.ApplicationUrl; - ApplicationName = string.IsNullOrEmpty(s.ApplicationName) ? "Ombi" : s.ApplicationName; + ApplicationUrl = s?.ApplicationUrl; + ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName; RequestedUser = string.IsNullOrEmpty(req.RequestedUser.Alias) ? req.RequestedUser.UserName : req.RequestedUser.Alias; @@ -47,8 +47,8 @@ namespace Ombi.Notifications public void Setup(OmbiUser user, CustomizationSettings s) { - ApplicationUrl = s.ApplicationUrl; - ApplicationName = string.IsNullOrEmpty(s.ApplicationName) ? "Ombi" : s.ApplicationName; + ApplicationUrl = s?.ApplicationUrl; + ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName; RequestedUser = user.UserName; } diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index a9af167bf..9f822540c 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -115,3 +115,17 @@ export interface IEpisodesRequests { export interface IMovieRequestModel { theMovieDbId: number; } + +export interface IFilter { + availabilityFilter: FilterType; + statusFilter: FilterType; +} + +export enum FilterType { + None = 0, + Available = 1, + NotAvailable = 2, + Approved = 3, + Processing = 4, + PendingApproval = 5, +} diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 5092690e0..bd57c591e 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -1,29 +1,34 @@ +
-
- -
+
+ + + + +
+ +

-
+ +
-
-
+
+
poster
-
+ @@ -69,57 +82,71 @@
- +
- +
- +
- +
- - + +
- + @@ -136,4 +163,47 @@ + [issueCategory]="issueCategorySelected" [id]="issueRequest?.id" [providerId]=""> + + + +

{{ 'Filter.Filter' | translate }}

+
+ +

{{ 'Filter.FilterHeaderAvailability' | translate }}

+
+
+ + +
+
+
+
+ + +
+
+ +

{{ 'Filter.FilterHeaderRequestStatus' | translate }}

+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 6835325f1..af0fd1abc 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -8,7 +8,7 @@ import { Subject } from "rxjs/Subject"; import { AuthService } from "../auth/auth.service"; import { NotificationService, RadarrService, RequestService } from "../services"; -import { IIssueCategory, IMovieRequests, IRadarrProfile, IRadarrRootFolder } from "../interfaces"; +import { FilterType, IFilter, IIssueCategory, IMovieRequests, IRadarrProfile, IRadarrRootFolder } from "../interfaces"; @Component({ selector: "movie-requests", @@ -32,6 +32,10 @@ export class MovieRequestsComponent implements OnInit { public issueProviderId: string; public issueCategorySelected: IIssueCategory; + public filterDisplay: boolean; + public filter: IFilter; + public filterType = FilterType; + private currentlyLoaded: number; private amountToLoad: number; @@ -62,6 +66,9 @@ export class MovieRequestsComponent implements OnInit { this.currentlyLoaded = 100; this.loadInit(); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + this.filter = { + availabilityFilter: FilterType.None, + statusFilter: FilterType.None}; } public loadMore() { @@ -139,6 +146,32 @@ export class MovieRequestsComponent implements OnInit { event.preventDefault(); } + public clearFilter() { + this.filterDisplay = false; + this.filter.availabilityFilter = FilterType.None; + this.filter.statusFilter = FilterType.None; + + this.resetSearch(); + } + + public filterAvailability(filter: FilterType) { + this.filter.availabilityFilter = filter; + this.requestService.filterMovies(this.filter) + .subscribe(x => { + this.setOverrides(x); + this.movieRequests = x; + }); + } + + public filterStatus(filter: FilterType) { + this.filter.statusFilter = filter; + this.requestService.filterMovies(this.filter) + .subscribe(x => { + this.setOverrides(x); + this.movieRequests = x; + }); + } + private loadRequests(amountToLoad: number, currentlyLoaded: number) { this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1) .subscribe(x => { diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 7dab9baa2..d0999f8ca 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -6,7 +6,7 @@ import { Observable } from "rxjs/Rx"; import { TreeNode } from "primeng/primeng"; import { IRequestEngineResult } from "../interfaces"; -import { IChildRequests, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, ITvRequests, ITvUpdateModel } from "../interfaces"; +import { IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, ITvRequests, ITvUpdateModel } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -106,4 +106,7 @@ export class RequestService extends ServiceHelpers { public deleteChild(child: IChildRequests): Observable { return this.http.delete(`${this.url}tv/child/${child.id}`, {headers: this.headers}); } -} + public filterMovies(filter: IFilter): Observable { + return this.http.post(`${this.url}movie/filter`, JSON.stringify(filter), {headers: this.headers}); + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html index 8f828ef32..80331272c 100644 --- a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html @@ -1,6 +1,6 @@  - +
User Importer Settings diff --git a/src/Ombi/ClientApp/app/shared/issues-report.component.html b/src/Ombi/ClientApp/app/shared/issues-report.component.html index bc043d068..9560f76f6 100644 --- a/src/Ombi/ClientApp/app/shared/issues-report.component.html +++ b/src/Ombi/ClientApp/app/shared/issues-report.component.html @@ -1,6 +1,7 @@
+

Reporting an Issue for "{{title}}"

Issue type: {{issueCategory.value}}

diff --git a/src/Ombi/ClientApp/styles/Themes/plex.scss b/src/Ombi/ClientApp/styles/Themes/plex.scss index 6dfb13db5..d32f81000 100644 --- a/src/Ombi/ClientApp/styles/Themes/plex.scss +++ b/src/Ombi/ClientApp/styles/Themes/plex.scss @@ -332,6 +332,10 @@ button.list-group-item:focus { box-shadow: 0px 0px 3.5em #000000; } +.side-small { + width:20em $i; +} + .ui-widget-overlay .ui-sidebar-mask { background: black; } diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index fa6ae8d6e..b53392c19 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -421,6 +421,43 @@ $border-radius: 10px; margin-bottom: 10px; } +.radio label { + display: inline-block; + cursor: pointer; + position: relative; + padding-left: 25px; + margin-right: 15px; + font-size: 13px; + margin-bottom: 10px; +} + +.radio label:before { + content: ""; + display: inline-block; + width: 18px; + height: 18px; + margin-right: 10px; + position: absolute; + left: 0; + bottom: 1px; + border: 2px solid #eee; + border-radius: 3px; +} + +.radio input[type=radio] { + display: none; +} + +.radio input[type=radio]:checked + label:before { + content: "\2713"; + font-size: 13px; + color: #fafafa; + text-align: center; + line-height: 13px; +} + + + .small-checkbox label:before { content: ""; display: inline-block; @@ -901,4 +938,8 @@ a > h4:hover { content: attr(data-label) } } +} + +.searchWidth { + width: 94%; } \ No newline at end of file diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index b2ca921c9..bc73fb5df 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -328,40 +328,15 @@ namespace Ombi.Controllers return movies || tv; } - - ///// - ///// Gets the specific grid model for the requests (for modelling the UI). - ///// - ///// - //[HttpGet("tv/grid")] - //[ApiExplorerSettings(IgnoreApi = true)] - //public async Task> GetTvRequestsGrid() - //{ - // return await GetGrid(TvRequestEngine); - //} - - ///// - ///// Gets the specific grid model for the requests (for modelling the UI). - ///// - ///// - //[HttpGet("movie/grid")] - //[ApiExplorerSettings(IgnoreApi = true)] - //public async Task> GetMovieRequestsGrid() - //{ - // return await GetGrid(MovieRequestEngine); - //} - - //private async Task> GetGrid(IRequestEngine engine) where T : BaseRequestModel - //{ - // var allRequests = await engine.GetRequests(); - // var r = allRequests.ToList(); - // var model = new RequestGridModel - // { - // Available = r.Where(x => x.Available && !x.Approved), - // Approved = r.Where(x => x.Approved && !x.Available), - // New = r.Where(x => !x.Available && !x.Approved) - // }; - // return model; - //} + /// + /// Returns a filtered list + /// + /// + /// + [HttpPost("movie/filter")] + public IEnumerable Filter([FromBody] FilterViewModel vm) + { + return MovieRequestEngine.Filter(vm); + } } } \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index edffeeffd..0d3f3805e 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -12,6 +12,7 @@ "Common": { "ContinueButton": "Continue", "Available": "Available", + "NotAvailable": "Not Available", "ProcessingRequest": "Processing Request", "PendingApproval": "Pending Approval", "RequestDenied":"Request Denied", @@ -110,7 +111,9 @@ "Season":"Season:", "GridTitle":"Title", "AirDate":"AirDate", - "GridStatus":"Status" + "GridStatus":"Status", + "ReportIssue":"Report Issue", + "Filter":"Filter" }, "Issues":{ "Title":"Issues", @@ -130,5 +133,11 @@ "Comments":"Comments", "WriteMessagePlaceholder":"Write your message here...", "ReportedBy":"Reported By" + }, + "Filter":{ + "ClearFilter":"Clear Filter", + "FilterHeaderAvailability":"Availability", + "FilterHeaderRequestStatus":"Status", + "Approved":"Approved" } }