more wip on the issues

pull/4083/head
tidusjar 4 years ago
parent b7bb0869da
commit 1289b840a0

@ -3,6 +3,7 @@ using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ombi.Core.Engine.V2 namespace Ombi.Core.Engine.V2
@ -10,7 +11,8 @@ namespace Ombi.Core.Engine.V2
public interface IIssuesEngine public interface IIssuesEngine
{ {
Task<IEnumerable<IssuesSummaryModel>> GetIssues(int position, int take, IssueStatus status); Task<IEnumerable<IssuesSummaryModel>> GetIssues(int position, int take, IssueStatus status, CancellationToken token);
Task<IEnumerable<IssuesSummaryModel>> GetIssuesByTitle(string title, CancellationToken token);
} }
public class IssuesEngine : IIssuesEngine public class IssuesEngine : IIssuesEngine
@ -28,9 +30,9 @@ namespace Ombi.Core.Engine.V2
_comments = comments; _comments = comments;
} }
public async Task<IEnumerable<IssuesSummaryModel>> GetIssues(int position, int take, IssueStatus status) public async Task<IEnumerable<IssuesSummaryModel>> GetIssues(int position, int take, IssueStatus status, CancellationToken token)
{ {
var issues = await _issues.GetAll().Where(x => x.Status == status).Skip(position).Take(take).ToListAsync(); var issues = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).Where(x => x.Status == status).Skip(position).Take(take).OrderBy(x => x.Title).ToListAsync(token);
var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g }); var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g });
var model = new List<IssuesSummaryModel>(); var model = new List<IssuesSummaryModel>();
@ -48,6 +50,27 @@ namespace Ombi.Core.Engine.V2
return model; return model;
} }
public async Task<IEnumerable<IssuesSummaryModel>> GetIssuesByTitle(string title, CancellationToken token)
{
var lowerTitle = title.ToLowerInvariant();
var issues = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).Where(x => x.Title.ToLowerInvariant() == lowerTitle).ToListAsync(token);
var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g });
var model = new List<IssuesSummaryModel>();
foreach (var group in grouped)
{
model.Add(new IssuesSummaryModel
{
Count = group.Issues.Count(),
Title = group.Title,
Issues = group.Issues
});
}
return model;
}
} }
public class IssuesSummaryModel public class IssuesSummaryModel

@ -0,0 +1,27 @@
<h1 mat-dialog-title>Issues for {{data.title}}</h1>
<div mat-dialog-content>
<div class="row">
<div class="col-6 top-spacing" *ngFor="let issue of data.issues">
<mat-card color="accent">
<mat-card-header>
<mat-card-title>{{issue.subject}}</mat-card-title>
<mat-card-subtitle>{{issue.userReported?.userName}} on {{issue.createdDate | date:short}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>
{{issue.description}}
</p>
</mat-card-content>
<mat-card-actions *ngIf="isAdmin && settings">
<button mat-raised-button color="accent" *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress" >{{'Issues.MarkInProgress' | translate }}</button>
<button mat-raised-button color="accent" *ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress">{{'Issues.MarkResolved' | translate}}</button>
</mat-card-actions>
</mat-card>
</div>
</div>
</div>
<div mat-dialog-actions>
<button mat-raised-button color="warn" (click)="close()">Close</button>
<button *ngIf="hasRequest" mat-raised-button color="accent" (click)="navToRequest()">View Media</button>
</div>

@ -0,0 +1,9 @@
@import "~styles/variables.scss";
::ng-deep .mat-card {
background: $ombi-background-primary-accent;
}
.top-spacing {
margin-top:2%;
}

@ -0,0 +1,48 @@
import { Component, Inject, OnInit } from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { AuthService } from "../../../auth/auth.service";
import { IIssues, IIssueSettings, IssueStatus } from "../../../interfaces";
import { SettingsService } from "../../../services";
export interface IssuesDetailsGroupData {
issues: IIssues[];
title: string;
}
@Component({
selector: "issues-details-group",
templateUrl: "details-group.component.html",
styleUrls: ["details-group.component.scss"],
})
export class DetailsGroupComponent implements OnInit {
public isAdmin: boolean;
public IssueStatus = IssueStatus;
public settings: IIssueSettings;
public get hasRequest(): boolean {
return this.data.issues.some(x => x.requestId);
}
constructor(public dialogRef: MatDialogRef<DetailsGroupComponent>,
@Inject(MAT_DIALOG_DATA) public data: IssuesDetailsGroupData,
private authService: AuthService, private settingsService: SettingsService) { }
public ngOnInit() {
this.isAdmin = this.authService.hasRole("Admin") || this.authService.hasRole("PowerUser");
this.settingsService.getIssueSettings().subscribe(x => this.settings = x);
}
public close() {
this.dialogRef.close();
}
public navToRequest() {
var issue = this.data.issues.filter(x => {
return x.requestId;
})[0];
// close dialog and tell calling component to navigate
}
}

@ -3,15 +3,13 @@ import { IssuesListComponent } from "./issues-list/issues-list.component";
import { Routes } from "@angular/router"; import { Routes } from "@angular/router";
import { IssuesV2Service } from "../../services/issuesv2.service"; import { IssuesV2Service } from "../../services/issuesv2.service";
import { IdentityService, SearchService } from "../../services"; import { IdentityService, SearchService } from "../../services";
import { DetailsGroupComponent } from "./details-group/details-group.component";
export const components: any[] = [ export const components: any[] = [
IssuesListComponent, IssuesListComponent,
]; DetailsGroupComponent,
export const entryComponents: any[] = [
]; ];
export const providers: any[] = [ export const providers: any[] = [

@ -84,7 +84,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div *ngIf="isAdmin && settings"> <div *ngIf="isAdmin && settings">
<div *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress"> <div *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress">
<button class="btn btn-primary btn-sm bottom-btn" (click)="inProgress()" [translate]="'Issues.MarkInProgress'"></button> <button class="btn btn-primary btn-sm bottom-btn" (click)="inProgress()">{{'Issues.MarkInProgress' | translate }}</button>
</div> </div>
<div *ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress"> <div *ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress">
<button class="btn btn-primary btn-sm bottom-btn" (click)="resolve()" [translate]="'Issues.MarkResolved'"></button> <button class="btn btn-primary btn-sm bottom-btn" (click)="resolve()" [translate]="'Issues.MarkResolved'"></button>

@ -1,25 +1,19 @@
<div class="small-middle-container"> <div class="small-middle-container">
<mat-tab-group> <div class="row" *ngIf="count">
<mat-tab label="{{'Issues.PendingTitle' | translate}}">
<ng-template matTabContent> <div *ngIf="pendingIssues.length > 0" class="col-4">
<div *ngIf="pendingIssues"> <h2>{{'Issues.PendingTitle' | translate}}</h2>
<issues-table [issues]="pendingIssues" (changePage)="changePagePending($event)" [totalRecords]="count.pending"></issues-table> <issues-table [issues]="pendingIssues" (changePage)="changePagePending($event)" [totalRecords]="count.pending"></issues-table>
</div> </div>
</ng-template>
</mat-tab> <div *ngIf="inProgressIssues.length > 0" class="col-4">
<mat-tab *ngIf="inProgressIssues.length > 0" label="{{'Issues.InProgressTitle' | translate}}"> <h2>{{'Issues.InProgressTitle' | translate}}</h2>
<ng-template matTabContent> <issues-table [issues]="inProgressIssues" (changePage)="changePageInProg($event)" [totalRecords]="count.inProgress"></issues-table>
<div *ngIf="inProgressIssues"> </div>
<issues-table [issues]="inProgressIssues" (changePage)="changePageInProg($event)" [totalRecords]="count.inProgress"></issues-table>
</div> <div *ngIf="resolvedIssues.length > 0" class="col-4">
</ng-template> <h2>{{'Issues.ResolvedTitle' | translate}}</h2>
</mat-tab> <issues-table [issues]="resolvedIssues" (changePage)="changePageResolved($event)" [totalRecords]="count.resolved"></issues-table>
<mat-tab label="{{'Issues.ResolvedTitle' | translate}}"> </div>
<ng-template matTabContent> </div>
<div *ngIf="resolvedIssues">
<issues-table [issues]="resolvedIssues" (changePage)="changePageResolved($event)" [totalRecords]="count.resolved"></issues-table>
</div>
</ng-template>
</mat-tab>
</mat-tab-group>
</div> </div>

@ -3,8 +3,6 @@ import { RouterModule, Routes } from "@angular/router";
import { OrderModule } from "ngx-order-pipe"; import { OrderModule } from "ngx-order-pipe";
import { IdentityService, SearchService } from "../services";
import { AuthGuard } from "../auth/auth.guard"; import { AuthGuard } from "../auth/auth.guard";
import { SharedModule as OmbiShared } from "../shared/shared.module"; import { SharedModule as OmbiShared } from "../shared/shared.module";
@ -27,7 +25,7 @@ const routes: Routes = [
RouterModule.forChild(routes), RouterModule.forChild(routes),
OrderModule, OrderModule,
PipeModule, PipeModule,
OmbiShared, OmbiShared
], ],
declarations: [ declarations: [
IssuesComponent, IssuesComponent,

@ -1,6 +1,8 @@
import { Component, EventEmitter, Input, Output } from "@angular/core"; import { Component, EventEmitter, Input, Output } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces";
import { DetailsGroupComponent, IssuesDetailsGroupData } from "./components/details-group/details-group.component";
@Component({ @Component({
selector: "issues-table", selector: "issues-table",
@ -8,6 +10,8 @@ import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"
}) })
export class IssuesTableComponent { export class IssuesTableComponent {
constructor(public dialog: MatDialog) { }
@Input() public issues: IIssuesSummary[]; @Input() public issues: IIssuesSummary[];
@Input() public totalRecords: number; @Input() public totalRecords: number;
@ -50,7 +54,10 @@ export class IssuesTableComponent {
} }
public openDetails(summary: IIssuesSummary) { public openDetails(summary: IIssuesSummary) {
const dialogRef = this.dialog.open(DetailsGroupComponent, {
width: "50vw",
data: <IssuesDetailsGroupData>{ issues: summary.issues, title: summary.title },
});
} }
} }

@ -142,7 +142,7 @@ namespace Ombi.Controllers.V1
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
RequestId = i.RequestId ?? 0, RequestId = i.RequestId ?? 0,
DateTime = DateTime.Now, DateTime = DateTime.UtcNow,
NotificationType = NotificationType.Issue, NotificationType = NotificationType.Issue,
RequestType = i.RequestType, RequestType = i.RequestType,
Recipient = string.Empty, Recipient = string.Empty,

@ -18,7 +18,7 @@ namespace Ombi.Controllers.V2
[HttpGet("{position}/{take}/{status}")] [HttpGet("{position}/{take}/{status}")]
public Task<IEnumerable<IssuesSummaryModel>> GetIssuesSummary(int position, int take, IssueStatus status) public Task<IEnumerable<IssuesSummaryModel>> GetIssuesSummary(int position, int take, IssueStatus status)
{ {
return _engine.GetIssues(position, take, status); return _engine.GetIssues(position, take, status, HttpContext.RequestAborted);
} }
} }
} }

Loading…
Cancel
Save