mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 09:12:57 -07:00
Got everything but filtering on the requests grid
This commit is contained in:
parent
23cafa4d10
commit
c491e74335
9 changed files with 148 additions and 26 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
|
using Ombi.Core.Models.UI;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine.Interfaces
|
namespace Ombi.Core.Engine.Interfaces
|
||||||
|
@ -18,5 +19,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
|
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
|
||||||
Task<RequestEngineResult> ApproveMovieById(int requestId);
|
Task<RequestEngineResult> ApproveMovieById(int requestId);
|
||||||
Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason);
|
Task<RequestEngineResult> DenyMovieById(int modelId, string denyReason);
|
||||||
|
Task<RequestsViewModel<MovieRequests>> GetRequests(int count, int position, string sortProperty, string sortOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using Ombi.Helpers;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
@ -200,6 +201,54 @@ namespace Ombi.Core.Engine
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RequestsViewModel<MovieRequests>> GetRequests(int count, int position, string sortProperty, string sortOrder)
|
||||||
|
{
|
||||||
|
var shouldHide = await HideFromOtherUsers();
|
||||||
|
IQueryable<MovieRequests> allRequests;
|
||||||
|
if (shouldHide.Hide)
|
||||||
|
{
|
||||||
|
allRequests =
|
||||||
|
MovieRepository.GetWithUser(shouldHide
|
||||||
|
.UserId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
allRequests =
|
||||||
|
MovieRepository
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
requests.ForEach(async x =>
|
||||||
|
{
|
||||||
|
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
||||||
|
await CheckForSubscription(shouldHide, x);
|
||||||
|
});
|
||||||
|
return new RequestsViewModel<MovieRequests>
|
||||||
|
{
|
||||||
|
Collection = requests,
|
||||||
|
Total = total
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private IQueryable<MovieRequests> OrderMovies(IQueryable<MovieRequests> allRequests, OrderType type)
|
private IQueryable<MovieRequests> OrderMovies(IQueryable<MovieRequests> allRequests, OrderType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
import { RequestsListComponent } from "./requests-list.component";
|
import { RequestsListComponent } from "./requests-list.component";
|
||||||
import { MoviesGridComponent } from "./movies-grid/movies-grid.component";
|
import { MoviesGridComponent } from "./movies-grid/movies-grid.component";
|
||||||
|
|
||||||
|
import { RequestServiceV2 } from "../../services/requestV2.service";
|
||||||
|
import { RequestService } from "../../services";
|
||||||
|
|
||||||
export const components: any[] = [
|
export const components: any[] = [
|
||||||
RequestsListComponent,
|
RequestsListComponent,
|
||||||
MoviesGridComponent,
|
MoviesGridComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const providers: any[] = [
|
||||||
|
RequestService,
|
||||||
|
RequestServiceV2,
|
||||||
|
];
|
||||||
|
|
|
@ -1,14 +1,25 @@
|
||||||
<div class="example-table-container mat-elevation-z8 ">
|
<div class="mat-elevation-z8">
|
||||||
<div class="example-loading-shade" *ngIf="isLoadingResults">
|
<div class="loading-shade" *ngIf="isLoadingResults">
|
||||||
<mat-spinner *ngIf="isLoading"></mat-spinner>
|
<div *ngIf="isLoadingResults" class="row justify-content-md-center top-spacing loading-spinner">
|
||||||
|
<mat-spinner [color]="'accent'"></mat-spinner>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<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="requestedDate"
|
<table mat-table [dataSource]="dataSource" class="table" matSort matSortActive="requestedDate"
|
||||||
matSortDisableClear matSortDirection="desc">
|
matSortDisableClear matSortDirection="desc">
|
||||||
|
|
||||||
|
|
||||||
<ng-container matColumnDef="requestedBy">
|
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Requested By </th>
|
<th mat-header-cell *matHeaderCellDef > Requested By </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.requestedUser?.userAlias}} </td>
|
<td mat-cell *matCellDef="let element"> {{element.requestedUser?.userAlias}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -24,13 +35,13 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="status">
|
<ng-container matColumnDef="status">
|
||||||
<th mat-header-cell *matHeaderCellDef> Status </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Status </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
|
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
<ng-container matColumnDef="requestStatus">
|
<ng-container matColumnDef="requestStatus">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> Request Status </th>
|
<th mat-header-cell *matHeaderCellDef > Request Status </th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<div *ngIf="element.approved && !element.available">{{'Common.ProcessingRequest' | translate}}</div>
|
<div *ngIf="element.approved && !element.available">{{'Common.ProcessingRequest' | translate}}</div>
|
||||||
<div *ngIf="element.requested && !element.approved && !element.available">{{'Common.PendingApproval' |
|
<div *ngIf="element.requested && !element.approved && !element.available">{{'Common.PendingApproval' |
|
||||||
|
@ -49,9 +60,9 @@
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<mat-paginator [length]="resultsLength" [pageSize]="30"></mat-paginator>
|
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Component, AfterViewInit, ViewChild } from "@angular/core";
|
import { Component, AfterViewInit, ViewChild } from "@angular/core";
|
||||||
import { RequestService } from "../../../services";
|
|
||||||
import { IMovieRequests, OrderType, FilterType, IRequestsViewModel } from "../../../interfaces";
|
import { IMovieRequests, OrderType, FilterType, IRequestsViewModel } from "../../../interfaces";
|
||||||
import { MatPaginator, MatSort } from "@angular/material";
|
import { MatPaginator, MatSort } from "@angular/material";
|
||||||
import { merge, Observable, of as observableOf } from 'rxjs';
|
import { merge, Observable, of as observableOf } from 'rxjs';
|
||||||
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
|
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { RequestServiceV2 } from "../../../services/requestV2.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./movies-grid.component.html",
|
templateUrl: "./movies-grid.component.html",
|
||||||
selector: "movies-grid",
|
selector: "movies-grid",
|
||||||
|
@ -14,13 +15,13 @@ export class MoviesGridComponent implements AfterViewInit {
|
||||||
public dataSource: IMovieRequests[] = [];
|
public dataSource: IMovieRequests[] = [];
|
||||||
public resultsLength: number;
|
public resultsLength: number;
|
||||||
public isLoadingResults = true;
|
public isLoadingResults = true;
|
||||||
public displayedColumns: string[] = ['requestedBy', 'title', 'requestedDate', 'status', 'requestStatus', 'actions'];
|
public displayedColumns: string[] = ['requestedUser.requestedBy', 'title', 'requestedDate', 'status', 'requestStatus', 'actions'];
|
||||||
public gridCount = 30;
|
public gridCount: string = "15";
|
||||||
|
|
||||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
@ViewChild(MatSort) sort: MatSort;
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
constructor(private requestService: RequestService) {
|
constructor(private requestService: RequestServiceV2) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +41,7 @@ export class MoviesGridComponent implements AfterViewInit {
|
||||||
this.isLoadingResults = true;
|
this.isLoadingResults = true;
|
||||||
// eturn this.exampleDatabase!.getRepoIssues(
|
// eturn this.exampleDatabase!.getRepoIssues(
|
||||||
// this.sort.active, this.sort.direction, this.paginator.pageIndex);
|
// this.sort.active, this.sort.direction, this.paginator.pageIndex);
|
||||||
return this.requestService.getMovieRequests(this.gridCount, this.paginator.pageIndex * this.gridCount, OrderType.RequestedDateDesc,
|
return this.requestService.getMovieRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction);
|
||||||
{ availabilityFilter: FilterType.None, statusFilter: FilterType.None});
|
|
||||||
}),
|
}),
|
||||||
map((data: IRequestsViewModel<IMovieRequests>) => {
|
map((data: IRequestsViewModel<IMovieRequests>) => {
|
||||||
// Flip flag to show that loading has finished.
|
// Flip flag to show that loading has finished.
|
||||||
|
|
|
@ -5,14 +5,9 @@
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height:100%;
|
||||||
}
|
}
|
||||||
.example-table-container {
|
.loading-shade {
|
||||||
position: relative;
|
|
||||||
max-height: 400px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.example-loading-shade {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
import { RequestService } from "../services";
|
|
||||||
|
|
||||||
import { SharedModule } from "../shared/shared.module";
|
import { SharedModule } from "../shared/shared.module";
|
||||||
import { PipeModule } from "../pipes/pipe.module";
|
import { PipeModule } from "../pipes/pipe.module";
|
||||||
|
@ -22,15 +21,15 @@ const routes: Routes = [
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...fromComponents.components
|
...fromComponents.components
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
RequestService,
|
...fromComponents.providers
|
||||||
],
|
],
|
||||||
|
|
||||||
})
|
})
|
||||||
export class RequestsListModule { }
|
export class RequestsListModule { }
|
||||||
|
|
20
src/Ombi/ClientApp/src/app/services/requestV2.service.ts
Normal file
20
src/Ombi/ClientApp/src/app/services/requestV2.service.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
|
import { HttpClient } from "@angular/common/http";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
import { ServiceHelpers } from "./service.helpers";
|
||||||
|
import { IRequestsViewModel, IMovieRequests } from "../interfaces";
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RequestServiceV2 extends ServiceHelpers {
|
||||||
|
constructor(http: HttpClient, public platformLocation: PlatformLocation) {
|
||||||
|
super(http, "/api/v2/Requests/", platformLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMovieRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IMovieRequests>> {
|
||||||
|
return this.http.get<IRequestsViewModel<IMovieRequests>>(`${this.url}movie/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/Ombi/Controllers/V2/RequestsController.cs
Normal file
38
src/Ombi/Controllers/V2/RequestsController.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Ombi.Core;
|
||||||
|
using Ombi.Core.Engine.Interfaces;
|
||||||
|
using Ombi.Core.Models.UI;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
|
namespace Ombi.Controllers.V2
|
||||||
|
{
|
||||||
|
[ApiV2]
|
||||||
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
public class RequestsController : ControllerBase
|
||||||
|
{
|
||||||
|
public RequestsController(IMovieRequestEngine movieRequestEngine)
|
||||||
|
{
|
||||||
|
_movieRequestEngine = movieRequestEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IMovieRequestEngine _movieRequestEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets movie requests.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The count of items you want to return. e.g. 30</param>
|
||||||
|
/// <param name="position">The position. e.g. position 60 for a 2nd page (since we have already got the first 30 items)</param>
|
||||||
|
/// <param name="sort">The item to sort on e.g. "requestDate"</param>
|
||||||
|
/// <param name="sortOrder">asc or desc</param>
|
||||||
|
[HttpGet("movie/{count:int}/{position:int}/{sort}/{sortOrder}")]
|
||||||
|
public async Task<RequestsViewModel<MovieRequests>> GetRequests(int count, int position, string sort, string sortOrder)
|
||||||
|
{
|
||||||
|
return await _movieRequestEngine.GetRequests(count, position, sort, sortOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue