mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 01:02:57 -07:00
Added filtering on status to the requests page
This commit is contained in:
parent
1ea6a6dc48
commit
4a8c1cd25a
10 changed files with 139 additions and 67 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -248,3 +248,4 @@ _Pvt_Extensions
|
|||
*.vscode
|
||||
/src/Ombi/database.json
|
||||
/src/Ombi/healthchecksdb
|
||||
/src/Ombi/ClientApp/package-lock.json
|
||||
|
|
|
@ -267,10 +267,10 @@ namespace Ombi.Core.Engine
|
|||
allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value));
|
||||
break;
|
||||
case RequestStatus.Available:
|
||||
allRequests = allRequests.Where(x => x.Available && (!x.Denied.HasValue || !x.Denied.Value));
|
||||
allRequests = allRequests.Where(x => x.Available);
|
||||
break;
|
||||
case RequestStatus.Denied:
|
||||
allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value);
|
||||
allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -332,12 +332,11 @@ namespace Ombi.Core.Engine
|
|||
//var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true);
|
||||
}
|
||||
|
||||
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
|
||||
? allRequests.OrderBy(x => prop.GetValue(x))
|
||||
: allRequests.OrderByDescending(x => prop.GetValue(x));
|
||||
var total = await allRequests.CountAsync();
|
||||
var requests = await allRequests.Skip(position).Take(count)
|
||||
.ToListAsync();
|
||||
var requests = (sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
|
||||
? allRequests.ToList().OrderBy(x => prop.GetValue(x))
|
||||
: 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<MovieRequests>
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace Ombi.Store.Context
|
|||
}
|
||||
|
||||
needToSave = true;
|
||||
NotificationTemplates notificationToAdd;
|
||||
NotificationTemplates notificationToAdd = null;
|
||||
switch (notificationType)
|
||||
{
|
||||
case NotificationType.NewRequest:
|
||||
|
@ -207,7 +207,10 @@ namespace Ombi.Store.Context
|
|||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
NotificationTemplates.Add(notificationToAdd);
|
||||
if (notificationToAdd != null)
|
||||
{
|
||||
NotificationTemplates.Add(notificationToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,57 +1,73 @@
|
|||
<div class="mat-elevation-z8">
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Requests to Display" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" class="table" matSort [matSortActive]="defaultSort"
|
||||
matSortDisableClear [matSortDirection]="defaultOrder">
|
||||
<!-- <div class="row"> -->
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" (click)="switchFilter(RequestFilter.All)" [attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'" mat-raised-button class="btn grow">{{'Requests.AllRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Pending)" [attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'" mat-raised-button class="btn grow">{{'Requests.PendingRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Processing)" [attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="btn grow">{{'Requests.ProcessingRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Available)" [attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="btn grow">{{'Requests.AvailableRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Denied)" [attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'" mat-raised-button class="btn grow">{{'Requests.DeniedRequests' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Requests to Display" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<table mat-table [dataSource]="dataSource" class="table" matSort [matSortActive]="defaultSort" matSortDisableClear [matSortDirection]="defaultOrder">
|
||||
|
||||
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef > Requested By </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedUser?.userAlias}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef> Requested By </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedUser?.userAlias}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Title </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} ({{element.releaseDate | amLocal | amDateFormat:
|
||||
'YYYY'}}) </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Title </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Request Date </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedDate | amLocal | amDateFormat: 'LL'}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Request Date </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedDate | amLocal | amDateFormat: 'LL'}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Status </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Status </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Request Status </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestStatus | translate}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Request Status </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestStatus | translate}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" >
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element" >
|
||||
<button mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">Details</button>
|
||||
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin">Options</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">Details</button>
|
||||
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin">Options</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
</div>
|
|
@ -7,6 +7,7 @@ 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: "./movies-grid.component.html",
|
||||
|
@ -19,14 +20,19 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
|||
public isLoadingResults = true;
|
||||
public displayedColumns: string[] = ['requestedUser.requestedBy', 'title', 'requestedDate', 'status', 'requestStatus', 'actions'];
|
||||
public gridCount: string = "15";
|
||||
public showUnavailableRequests: boolean;
|
||||
public isAdmin: boolean;
|
||||
public defaultSort: string = "requestedDate";
|
||||
public defaultOrder: string = "desc";
|
||||
|
||||
public RequestFilter = RequestFilterType;
|
||||
|
||||
private currentFilter: RequestFilterType = RequestFilterType.All;
|
||||
|
||||
private storageKey = "Movie_DefaultRequestListSort";
|
||||
private storageKeyOrder = "Movie_DefaultRequestListSortOrder";
|
||||
private storageKeyGridCount = "Movie_DefaultGridCount";
|
||||
private storageKeyCurrentFilter = "Movie_DefaultFilter";
|
||||
private $data: Observable<any>;
|
||||
|
||||
@Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any }>();
|
||||
|
||||
|
@ -39,18 +45,24 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
|
||||
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) {
|
||||
if (defaultCount) {
|
||||
this.gridCount = defaultCount;
|
||||
}
|
||||
if (defaultFilter) {
|
||||
this.currentFilter = defaultFilter;
|
||||
}
|
||||
}
|
||||
|
||||
public async ngAfterViewInit() {
|
||||
|
@ -60,13 +72,12 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
|||
// this.resultsLength = results.total;
|
||||
|
||||
this.storageService.save(this.storageKeyGridCount, this.gridCount);
|
||||
|
||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||
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);
|
||||
|
||||
merge(this.sort.sortChange, this.paginator.page)
|
||||
merge(this.sort.sortChange, this.paginator.page, this.currentFilter)
|
||||
.pipe(
|
||||
startWith({}),
|
||||
switchMap((value: any) => {
|
||||
|
@ -92,11 +103,19 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
|
||||
public loadData(): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||
if (this.showUnavailableRequests) {
|
||||
return this.requestService.getMovieUnavailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
} else {
|
||||
return this.requestService.getMovieRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
switch(RequestFilterType[RequestFilterType[this.currentFilter]]) {
|
||||
case RequestFilterType.All:
|
||||
return this.requestService.getMovieRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
case RequestFilterType.Pending:
|
||||
return this.requestService.getMoviePendingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
case RequestFilterType.Available:
|
||||
return this.requestService.getMovieAvailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
case RequestFilterType.Processing:
|
||||
return this.requestService.getMovieProcessingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
case RequestFilterType.Denied:
|
||||
return this.requestService.getMovieDeniedRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public openOptions(request: IMovieRequests) {
|
||||
|
@ -112,4 +131,9 @@ export class MoviesGridComponent implements OnInit, AfterViewInit {
|
|||
|
||||
this.onOpenOptions.emit({ request: request, filter: filter, onChange: onChange });
|
||||
}
|
||||
|
||||
public switchFilter(type: RequestFilterType) {
|
||||
this.currentFilter = type;
|
||||
this.ngAfterViewInit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export enum RequestFilterType {
|
||||
All,
|
||||
Pending,
|
||||
Processing,
|
||||
Available,
|
||||
Denied
|
||||
}
|
|
@ -17,6 +17,22 @@ export class RequestServiceV2 extends ServiceHelpers {
|
|||
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getMovieAvailableRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getMovieProcessingRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getMoviePendingRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getMovieDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getTvRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IChildRequests>> {
|
||||
return this.http.get<IRequestsViewModel<IChildRequests>>(`${this.url}tv/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<mat-checkbox formControlName="ignoreCertificateErrors" matTooltip="Enable if you are having connectivity problems over SSL">
|
||||
Ignore any certificate errors
|
||||
Ignore any certificate errors (Please restart after changing)
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace Ombi.Controllers.V2
|
|||
}
|
||||
|
||||
[HttpGet("movie/availble/{count:int}/{position:int}/{sort}/{sortOrder}")]
|
||||
[HttpGet("movie/available/{count:int}/{position:int}/{sort}/{sortOrder}")]
|
||||
public async Task<RequestsViewModel<MovieRequests>> GetAvailableRequests(int count, int position, string sort, string sortOrder)
|
||||
{
|
||||
return await _movieRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Available);
|
||||
|
|
|
@ -153,7 +153,12 @@
|
|||
"NextHours": "Another request will be added in {{time}} hours",
|
||||
"NextMinutes": "Another request will be added in {{time}} minutes",
|
||||
"NextMinute": "Another request will be added in {{time}} minute"
|
||||
}
|
||||
},
|
||||
"AllRequests": "All Requests",
|
||||
"PendingRequests": "Pending Requests",
|
||||
"ProcessingRequests": "Processing Requests",
|
||||
"AvailableRequests": "Available Requests",
|
||||
"DeniedRequests": "Denied Requests"
|
||||
},
|
||||
"Issues": {
|
||||
"Title": "Issues",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue