From b7bb0869da1163af78f94891dc1a16c6c5b0b0bf Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 12 Feb 2021 21:39:57 +0000 Subject: [PATCH 1/6] Made a start on the issues rework --- src/Ombi.Core/Engine/V2/IssuesEngine.cs | 59 +++++++++++++++++++ src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi/ClientApp/angular.json | 5 +- .../ClientApp/src/app/interfaces/IIssues.ts | 6 ++ .../src/app/issues/components/index.ts | 5 ++ .../src/app/issues/issues.component.ts | 17 +++--- .../ClientApp/src/app/issues/issues.module.ts | 3 +- .../src/app/issues/issuestable.component.html | 25 ++------ .../src/app/issues/issuestable.component.ts | 10 +++- .../src/app/services/issuesv2.service.ts | 19 ++++++ src/Ombi/Controllers/V2/IssuesController.cs | 24 ++++++++ 11 files changed, 139 insertions(+), 35 deletions(-) create mode 100644 src/Ombi.Core/Engine/V2/IssuesEngine.cs create mode 100644 src/Ombi/ClientApp/src/app/services/issuesv2.service.ts create mode 100644 src/Ombi/Controllers/V2/IssuesController.cs diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs new file mode 100644 index 000000000..a596e7ac9 --- /dev/null +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Core.Engine.V2 +{ + + public interface IIssuesEngine + { + Task> GetIssues(int position, int take, IssueStatus status); + } + + public class IssuesEngine : IIssuesEngine + { + private readonly IRepository _categories; + private readonly IRepository _issues; + private readonly IRepository _comments; + + public IssuesEngine(IRepository categories, + IRepository issues, + IRepository comments) + { + _categories = categories; + _issues = issues; + _comments = comments; + } + + public async Task> GetIssues(int position, int take, IssueStatus status) + { + var issues = await _issues.GetAll().Where(x => x.Status == status).Skip(position).Take(take).ToListAsync(); + var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g }); + + var model = new List(); + + 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 string Title { get; set; } + public int Count { get; set; } + public IEnumerable Issues { get; set; } + } +} diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index d5e577d84..ef9c9230c 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -114,6 +114,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterHttp(this IServiceCollection services) diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json index 2e3ff44e5..41030a25a 100644 --- a/src/Ombi/ClientApp/angular.json +++ b/src/Ombi/ClientApp/angular.json @@ -124,5 +124,8 @@ } } }, - "defaultProject": "ombi" + "defaultProject": "ombi", + "cli": { + "analytics": false + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts index dce9882ec..b01749057 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts @@ -62,3 +62,9 @@ export interface IUpdateStatus { issueId: number; status: IssueStatus; } + +export interface IIssuesSummary { + title: string; + count: number; + issues: IIssues[]; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts index 93bb4907d..932f1eeb4 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/index.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -1,6 +1,8 @@ import { AuthGuard } from "../../auth/auth.guard"; import { IssuesListComponent } from "./issues-list/issues-list.component"; import { Routes } from "@angular/router"; +import { IssuesV2Service } from "../../services/issuesv2.service"; +import { IdentityService, SearchService } from "../../services"; @@ -13,6 +15,9 @@ export const entryComponents: any[] = [ ]; export const providers: any[] = [ + IssuesV2Service, + IdentityService, + SearchService, ]; export const routes: Routes = [ diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.ts b/src/Ombi/ClientApp/src/app/issues/issues.component.ts index b8482f1ff..5dc02845e 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.ts @@ -2,9 +2,10 @@ import { Component, OnInit } from "@angular/core"; import { IssuesService } from "../services"; -import { IIssueCount, IIssues, IPagenator, IssueStatus } from "../interfaces"; +import { IIssueCount, IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; import { PageEvent } from '@angular/material/paginator'; +import { IssuesV2Service } from "../services/issuesv2.service"; @Component({ templateUrl: "issues.component.html", @@ -12,9 +13,9 @@ import { PageEvent } from '@angular/material/paginator'; }) export class IssuesComponent implements OnInit { - public pendingIssues: IIssues[]; - public inProgressIssues: IIssues[]; - public resolvedIssues: IIssues[]; + public pendingIssues: IIssuesSummary[]; + public inProgressIssues: IIssuesSummary[]; + public resolvedIssues: IIssuesSummary[]; public count: IIssueCount; @@ -23,7 +24,7 @@ export class IssuesComponent implements OnInit { private inProgressSkip = 0; private resolvedSkip = 0; - constructor(private issueService: IssuesService) { } + constructor(private issuev2Service: IssuesV2Service, private issueService: IssuesService) { } public ngOnInit() { this.getPending(); @@ -48,19 +49,19 @@ export class IssuesComponent implements OnInit { } private getPending() { - this.issueService.getIssuesPage(this.takeAmount, this.pendingSkip, IssueStatus.Pending).subscribe(x => { + this.issuev2Service.getIssues(this.pendingSkip, this.takeAmount, IssueStatus.Pending).subscribe(x => { this.pendingIssues = x; }); } private getInProg() { - this.issueService.getIssuesPage(this.takeAmount, this.inProgressSkip, IssueStatus.InProgress).subscribe(x => { + this.issuev2Service.getIssues(this.inProgressSkip, this.takeAmount, IssueStatus.InProgress).subscribe(x => { this.inProgressIssues = x; }); } private getResolved() { - this.issueService.getIssuesPage(this.takeAmount, this.resolvedSkip, IssueStatus.Resolved).subscribe(x => { + this.issuev2Service.getIssues(this.resolvedSkip, this.takeAmount, IssueStatus.Resolved).subscribe(x => { this.resolvedIssues = x; }); } diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index 2607d336a..ab55f69cf 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -39,8 +39,7 @@ const routes: Routes = [ RouterModule, ], providers: [ - IdentityService, - SearchService, + ...fromComponents.providers ], }) diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html index e266a718a..8244536ad 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html @@ -6,32 +6,15 @@ {{element.title}} - - {{ 'Issues.Category' | translate}} - {{element.issueCategory.value}} - - - - {{ 'Issues.Subject' | translate}} - {{element.subject}} - - - - {{ 'Issues.Status' | translate}} - {{IssueStatus[element.status] | humanize}} - - - - {{ 'Issues.ReportedBy' | translate}} - {{element.userReported.userAlias}} + + {{ 'Issues.Count' | translate}} + {{element.count}} - - - + diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts index ff584a35e..1ad929741 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IIssues, IPagenator, IssueStatus } from "../interfaces"; +import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; @Component({ selector: "issues-table", @@ -8,12 +8,12 @@ import { IIssues, IPagenator, IssueStatus } from "../interfaces"; }) export class IssuesTableComponent { - @Input() public issues: IIssues[]; + @Input() public issues: IIssuesSummary[]; @Input() public totalRecords: number; @Output() public changePage = new EventEmitter(); - public displayedColumns = ["title", "category", "subject", "status", "reportedBy", "actions"] + public displayedColumns = ["title", "count", "actions"] public IssueStatus = IssueStatus; public resultsLength: number; public gridCount: string = "15"; @@ -49,4 +49,8 @@ export class IssuesTableComponent { this.changePage.emit(event); } + public openDetails(summary: IIssuesSummary) { + + } + } diff --git a/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts b/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts new file mode 100644 index 000000000..69b5c01c4 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts @@ -0,0 +1,19 @@ +import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; +import { Injectable, Inject } from "@angular/core"; + +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +import { IIssueCategory, IIssueComments, IIssueCount, IIssues, IIssuesChat, IIssuesSummary, INewIssueComments, IssueStatus, IUpdateStatus } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable() +export class IssuesV2Service extends ServiceHelpers { + constructor(http: HttpClient, @Inject(APP_BASE_HREF) href:string) { + super(http, "/api/v2/Issues/", href); + } + + public getIssues(position: number, take: number, status: IssueStatus): Observable { + return this.http.get(`${this.url}${position}/${take}/${status}`, {headers: this.headers}); + } +} diff --git a/src/Ombi/Controllers/V2/IssuesController.cs b/src/Ombi/Controllers/V2/IssuesController.cs new file mode 100644 index 000000000..c2b65cc99 --- /dev/null +++ b/src/Ombi/Controllers/V2/IssuesController.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Mvc; +using Ombi.Core.Engine.V2; +using Ombi.Store.Entities.Requests; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Ombi.Controllers.V2 +{ + public class IssuesController : V2Controller + { + private readonly IIssuesEngine _engine; + + public IssuesController(IIssuesEngine engine) + { + _engine = engine; + } + + [HttpGet("{position}/{take}/{status}")] + public Task> GetIssuesSummary(int position, int take, IssueStatus status) + { + return _engine.GetIssues(position, take, status); + } + } +} From 1289b840a051141f43e7beb8e3e751325c5c311d Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 13 Feb 2021 22:35:07 +0000 Subject: [PATCH 2/6] more wip on the issues --- src/Ombi.Core/Engine/V2/IssuesEngine.cs | 29 +++++++++-- .../details-group.component.html | 27 +++++++++++ .../details-group.component.scss | 9 ++++ .../details-group/details-group.component.ts | 48 +++++++++++++++++++ .../src/app/issues/components/index.ts | 6 +-- .../app/issues/issueDetails.component.html | 2 +- .../src/app/issues/issues.component.html | 40 +++++++--------- .../ClientApp/src/app/issues/issues.module.ts | 4 +- .../src/app/issues/issuestable.component.ts | 9 +++- src/Ombi/Controllers/V1/IssuesController.cs | 2 +- src/Ombi/Controllers/V2/IssuesController.cs | 2 +- 11 files changed, 141 insertions(+), 37 deletions(-) create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs index a596e7ac9..f154d0eca 100644 --- a/src/Ombi.Core/Engine/V2/IssuesEngine.cs +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -3,6 +3,7 @@ using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Core.Engine.V2 @@ -10,7 +11,8 @@ namespace Ombi.Core.Engine.V2 public interface IIssuesEngine { - Task> GetIssues(int position, int take, IssueStatus status); + Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token); + Task> GetIssuesByTitle(string title, CancellationToken token); } public class IssuesEngine : IIssuesEngine @@ -28,9 +30,9 @@ namespace Ombi.Core.Engine.V2 _comments = comments; } - public async Task> GetIssues(int position, int take, IssueStatus status) + public async Task> 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 model = new List(); @@ -48,6 +50,27 @@ namespace Ombi.Core.Engine.V2 return model; } + public async Task> 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(); + + foreach (var group in grouped) + { + model.Add(new IssuesSummaryModel + { + Count = group.Issues.Count(), + Title = group.Title, + Issues = group.Issues + }); + } + + return model; + } + } public class IssuesSummaryModel diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html new file mode 100644 index 000000000..7c3c04fdd --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html @@ -0,0 +1,27 @@ +

Issues for {{data.title}}

+
+ +
+
+ + + {{issue.subject}} + {{issue.userReported?.userName}} on {{issue.createdDate | date:short}} + + +

+ {{issue.description}} +

+
+ + + + +
+
+
+
+
+ + +
diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss new file mode 100644 index 000000000..d6dcd67de --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss @@ -0,0 +1,9 @@ +@import "~styles/variables.scss"; + +::ng-deep .mat-card { + background: $ombi-background-primary-accent; +} + +.top-spacing { + margin-top:2%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts new file mode 100644 index 000000000..aea5eb123 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts @@ -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, + @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 + } + +} diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts index 932f1eeb4..7bf8e197a 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/index.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -3,15 +3,13 @@ import { IssuesListComponent } from "./issues-list/issues-list.component"; import { Routes } from "@angular/router"; import { IssuesV2Service } from "../../services/issuesv2.service"; import { IdentityService, SearchService } from "../../services"; +import { DetailsGroupComponent } from "./details-group/details-group.component"; export const components: any[] = [ IssuesListComponent, -]; - - -export const entryComponents: any[] = [ + DetailsGroupComponent, ]; export const providers: any[] = [ diff --git a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html index c2de76c2b..b5fc59304 100644 --- a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html @@ -84,7 +84,7 @@
- +
diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.html b/src/Ombi/ClientApp/src/app/issues/issues.component.html index ff8440569..4d9daeffc 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.html @@ -1,25 +1,19 @@
- - - -
- -
-
-
- - -
- -
-
-
- - -
- -
-
-
-
+
+ +
+

{{'Issues.PendingTitle' | translate}}

+ +
+ +
+

{{'Issues.InProgressTitle' | translate}}

+ +
+ +
+

{{'Issues.ResolvedTitle' | translate}}

+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index ab55f69cf..70b8a4bb1 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -3,8 +3,6 @@ import { RouterModule, Routes } from "@angular/router"; import { OrderModule } from "ngx-order-pipe"; -import { IdentityService, SearchService } from "../services"; - import { AuthGuard } from "../auth/auth.guard"; import { SharedModule as OmbiShared } from "../shared/shared.module"; @@ -27,7 +25,7 @@ const routes: Routes = [ RouterModule.forChild(routes), OrderModule, PipeModule, - OmbiShared, + OmbiShared ], declarations: [ IssuesComponent, diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts index 1ad929741..7ed826fc5 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts @@ -1,6 +1,8 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; +import { MatDialog } from "@angular/material/dialog"; import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; +import { DetailsGroupComponent, IssuesDetailsGroupData } from "./components/details-group/details-group.component"; @Component({ selector: "issues-table", @@ -8,6 +10,8 @@ import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces" }) export class IssuesTableComponent { + constructor(public dialog: MatDialog) { } + @Input() public issues: IIssuesSummary[]; @Input() public totalRecords: number; @@ -50,7 +54,10 @@ export class IssuesTableComponent { } public openDetails(summary: IIssuesSummary) { - + const dialogRef = this.dialog.open(DetailsGroupComponent, { + width: "50vw", + data: { issues: summary.issues, title: summary.title }, + }); } } diff --git a/src/Ombi/Controllers/V1/IssuesController.cs b/src/Ombi/Controllers/V1/IssuesController.cs index 4dfd3781a..23b2320d1 100644 --- a/src/Ombi/Controllers/V1/IssuesController.cs +++ b/src/Ombi/Controllers/V1/IssuesController.cs @@ -142,7 +142,7 @@ namespace Ombi.Controllers.V1 var notificationModel = new NotificationOptions { RequestId = i.RequestId ?? 0, - DateTime = DateTime.Now, + DateTime = DateTime.UtcNow, NotificationType = NotificationType.Issue, RequestType = i.RequestType, Recipient = string.Empty, diff --git a/src/Ombi/Controllers/V2/IssuesController.cs b/src/Ombi/Controllers/V2/IssuesController.cs index c2b65cc99..214482b54 100644 --- a/src/Ombi/Controllers/V2/IssuesController.cs +++ b/src/Ombi/Controllers/V2/IssuesController.cs @@ -18,7 +18,7 @@ namespace Ombi.Controllers.V2 [HttpGet("{position}/{take}/{status}")] public Task> GetIssuesSummary(int position, int take, IssueStatus status) { - return _engine.GetIssues(position, take, status); + return _engine.GetIssues(position, take, status, HttpContext.RequestAborted); } } } From 6683f8070ca6f59e9c4e2c2b3b3c9d5b9c35d58f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 15 Feb 2021 22:42:23 +0000 Subject: [PATCH 3/6] more wip on the issues --- src/Ombi.Core/Engine/V2/IssuesEngine.cs | 33 ++++--- src/Ombi/ClientApp/src/app/app.module.ts | 1 + .../ClientApp/src/app/interfaces/IIssues.ts | 1 + .../components/details/details.component.html | 38 ++++++++ .../components/details/details.component.scss | 9 ++ .../components/details/details.component.ts | 88 +++++++++++++++++++ .../src/app/issues/components/index.ts | 8 +- .../issues-list/issues-list.component.html | 21 ----- .../issues-list/issues-list.component.ts | 68 -------------- .../issues-list/issues-list.constants.ts | 3 - .../src/app/issues/issues.component.html | 39 ++++---- .../ClientApp/src/app/issues/issues.module.ts | 7 +- .../src/app/issues/issuestable.component.html | 2 +- .../src/app/issues/issuestable.component.ts | 11 +-- .../movie/movie-details.component.ts | 6 +- .../issues-panel/issues-panel.component.ts | 8 +- .../shared/new-issue/new-issue.component.ts | 6 +- .../src/app/services/issuesv2.service.ts | 4 + src/Ombi/Controllers/V2/IssuesController.cs | 7 ++ 19 files changed, 209 insertions(+), 151 deletions(-) create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details/details.component.html create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details/details.component.scss create mode 100644 src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts delete mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html delete mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts delete mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs index f154d0eca..f938e8ec6 100644 --- a/src/Ombi.Core/Engine/V2/IssuesEngine.cs +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -12,7 +12,7 @@ namespace Ombi.Core.Engine.V2 public interface IIssuesEngine { Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token); - Task> GetIssuesByTitle(string title, CancellationToken token); + Task GetIssuesByProviderId(string providerId, CancellationToken token); } public class IssuesEngine : IIssuesEngine @@ -32,7 +32,7 @@ namespace Ombi.Core.Engine.V2 public async Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token) { - 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 issues = await _issues.GetAll().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 model = new List(); @@ -43,32 +43,30 @@ namespace Ombi.Core.Engine.V2 { Count = group.Issues.Count(), Title = group.Title, - Issues = group.Issues + ProviderId = group.Issues.FirstOrDefault()?.ProviderId }); } return model; } - public async Task> GetIssuesByTitle(string title, CancellationToken token) + public async Task GetIssuesByProviderId(string providerId, 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(); + var issues = await _issues.GetAll().Include(x => x.Comments).ThenInclude(x => x.User).Include(x => x.UserReported).Include(x => x.IssueCategory).Where(x => x.ProviderId == providerId).ToListAsync(token); + var grouped = issues.GroupBy(x => x.Title, (key, g) => new { Title = key, Issues = g }).FirstOrDefault(); - foreach (var group in grouped) + if (grouped == null) { - model.Add(new IssuesSummaryModel - { - Count = group.Issues.Count(), - Title = group.Title, - Issues = group.Issues - }); + return null; } - return model; + return new IssuesSummaryModel + { + Count = grouped.Issues.Count(), + Title = grouped.Title, + ProviderId = grouped.Issues.FirstOrDefault()?.ProviderId, + Issues = grouped.Issues + }; } } @@ -77,6 +75,7 @@ namespace Ombi.Core.Engine.V2 { public string Title { get; set; } public int Count { get; set; } + public string ProviderId { get; set; } public IEnumerable Issues { get; set; } } } diff --git a/src/Ombi/ClientApp/src/app/app.module.ts b/src/Ombi/ClientApp/src/app/app.module.ts index cfaf783cf..4de2c9f9f 100644 --- a/src/Ombi/ClientApp/src/app/app.module.ts +++ b/src/Ombi/ClientApp/src/app/app.module.ts @@ -145,6 +145,7 @@ export function JwtTokenGetter() { MatCheckboxModule, MatProgressSpinnerModule, MDBBootstrapModule.forRoot(), + // NbThemeModule.forRoot({ name: 'dark'}), JwtModule.forRoot({ config: { tokenGetter: JwtTokenGetter, diff --git a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts index b01749057..10de2a596 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts @@ -66,5 +66,6 @@ export interface IUpdateStatus { export interface IIssuesSummary { title: string; count: number; + providerId: string; issues: IIssues[]; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html new file mode 100644 index 000000000..b8e8dc1f6 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html @@ -0,0 +1,38 @@ +
+ +

Issues for {{details.title}}

+
+ Has Request {{hasRequest}} +
+
+
+
+
{{issue.subject}}
+ {{issue.userReported?.userName}} on {{issue.createdDate | date:short}} +
+
+

+ {{issue.description}} +

+
+
+ + + + + + +
+ +
+
+
+
+
+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.scss b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.scss new file mode 100644 index 000000000..d6dcd67de --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.scss @@ -0,0 +1,9 @@ +@import "~styles/variables.scss"; + +::ng-deep .mat-card { + background: $ombi-background-primary-accent; +} + +.top-spacing { + margin-top:2%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts new file mode 100644 index 000000000..ed00bc041 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts @@ -0,0 +1,88 @@ +import { Component, Inject, OnInit, ViewEncapsulation } from "@angular/core"; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ActivatedRoute, ActivatedRouteSnapshot, Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { AuthService } from "../../../auth/auth.service"; +import { IIssues, IIssueSettings, IIssuesSummary, IssueStatus, RequestType } from "../../../interfaces"; +import { IssuesService, NotificationService, SettingsService } from "../../../services"; +import { IssuesV2Service } from "../../../services/issuesv2.service"; + + +export interface IssuesDetailsGroupData { + issues: IIssues[]; + title: string; +} + +@Component({ + selector: "issues-details", + templateUrl: "details.component.html", + styleUrls: ["details.component.scss"], + encapsulation: ViewEncapsulation.None +}) +export class IssuesDetailsComponent implements OnInit { + + public details: IIssuesSummary; + public isAdmin: boolean; + public IssueStatus = IssueStatus; + public settings: IIssueSettings; + public get hasRequest(): boolean { + return this.details.issues.some(x => x.requestId); + } + + private providerId: string; + + constructor(private authService: AuthService, private settingsService: SettingsService, + private issueServiceV2: IssuesV2Service, private route: ActivatedRoute, private router: Router, + private issuesService: IssuesService, private translateService: TranslateService, private notificationService: NotificationService) { + this.route.params.subscribe(async (params: any) => { + if (typeof params.providerId === 'string' || params.providerId instanceof String) { + this.providerId = params.providerId; + } + }); + } + + public ngOnInit() { + this.isAdmin = this.authService.hasRole("Admin") || this.authService.hasRole("PowerUser"); + this.settingsService.getIssueSettings().subscribe(x => this.settings = x); + this.issueServiceV2.getIssuesByProviderId(this.providerId).subscribe(x => this.details = x); + } + + public resolve(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.Resolved}).subscribe(x => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsResolved")); + issue.status = IssueStatus.Resolved; + }); + } + + public inProgress(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.InProgress}).subscribe(x => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsInProgress")); + issue.status = IssueStatus.InProgress; + }); + } + + public async delete(issue: IIssues) { + await this.issuesService.deleteIssue(issue.id); + this.notificationService.success(this.translateService.instant("Issues.DeletedIssue")); + this.details.issues = this.details.issues.filter((el) => { return el.id !== issue.id; }); + } + + + public navToMedia() { + const firstIssue = this.details.issues[0]; + switch(firstIssue.requestType) { + case RequestType.movie: + this.router.navigate(['/details/movie/', firstIssue.providerId]); + return; + + case RequestType.album: + this.router.navigate(['/details/artist/', firstIssue.providerId]); + return; + + case RequestType.tvShow: + this.router.navigate(['/details/tv/', firstIssue.providerId]); + return; + } + } + +} diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts index 7bf8e197a..86ceefe89 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/index.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -1,23 +1,19 @@ import { AuthGuard } from "../../auth/auth.guard"; -import { IssuesListComponent } from "./issues-list/issues-list.component"; import { Routes } from "@angular/router"; import { IssuesV2Service } from "../../services/issuesv2.service"; import { IdentityService, SearchService } from "../../services"; import { DetailsGroupComponent } from "./details-group/details-group.component"; +import { IssuesDetailsComponent } from "./details/details.component"; export const components: any[] = [ - IssuesListComponent, DetailsGroupComponent, + IssuesDetailsComponent, ]; export const providers: any[] = [ IssuesV2Service, IdentityService, SearchService, -]; - -export const routes: Routes = [ - { path: "", component: IssuesListComponent, canActivate: [AuthGuard] }, ]; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html deleted file mode 100644 index 61f154193..000000000 --- a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts deleted file mode 100644 index 82883a4f2..000000000 --- a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Component, OnInit } from "@angular/core"; - -import { IssuesService } from "../../../services"; - -import { IIssueCount, IIssues, IPagenator, IssueStatus } from "../../../interfaces"; -import { COLUMNS } from "./issues-list.constants"; - -@Component({ - selector: "issues-list", - templateUrl: "issues-list.component.html", -}) -export class IssuesListComponent implements OnInit { - - public columnsToDisplay = COLUMNS - - public pendingIssues: IIssues[]; - public inProgressIssues: IIssues[]; - public resolvedIssues: IIssues[]; - - public count: IIssueCount; - - private takeAmount = 10; - private pendingSkip = 0; - private inProgressSkip = 0; - private resolvedSkip = 0; - - constructor(private issueService: IssuesService) { } - - public ngOnInit() { - this.getPending(); - this.getInProg(); - this.getResolved(); - this.issueService.getIssuesCount().subscribe(x => this.count = x); - } - - public changePagePending(event: IPagenator) { - this.pendingSkip = event.first; - this.getPending(); - } - - public changePageInProg(event: IPagenator) { - this.inProgressSkip = event.first; - this.getInProg(); - } - - public changePageResolved(event: IPagenator) { - this.resolvedSkip = event.first; - this.getResolved(); - } - - private getPending() { - this.issueService.getIssuesPage(this.takeAmount, this.pendingSkip, IssueStatus.Pending).subscribe(x => { - this.pendingIssues = x; - }); - } - - private getInProg() { - this.issueService.getIssuesPage(this.takeAmount, this.inProgressSkip, IssueStatus.InProgress).subscribe(x => { - this.inProgressIssues = x; - }); - } - - private getResolved() { - this.issueService.getIssuesPage(this.takeAmount, this.resolvedSkip, IssueStatus.Resolved).subscribe(x => { - this.resolvedIssues = x; - }); - } -} diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts deleted file mode 100644 index f4a00e24b..000000000 --- a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const COLUMNS = [ - "title" -] \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.html b/src/Ombi/ClientApp/src/app/issues/issues.component.html index 4d9daeffc..72734ed85 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.html @@ -1,19 +1,28 @@
-
+
-
-

{{'Issues.PendingTitle' | translate}}

- -
- -
-

{{'Issues.InProgressTitle' | translate}}

- -
- -
-

{{'Issues.ResolvedTitle' | translate}}

- -
+ + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index 70b8a4bb1..08896a086 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -1,5 +1,6 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; +// import { NbChatModule, NbThemeModule } from '@nebular/theme'; import { OrderModule } from "ngx-order-pipe"; @@ -10,6 +11,7 @@ import { SharedModule as OmbiShared } from "../shared/shared.module"; import { IssueDetailsComponent } from "./issueDetails.component"; import { IssuesComponent } from "./issues.component"; import { IssuesTableComponent } from "./issuestable.component"; +import { IssuesDetailsComponent } from "./components/details/details.component"; import { PipeModule } from "../pipes/pipe.module"; @@ -17,7 +19,7 @@ import * as fromComponents from "./components"; const routes: Routes = [ { path: "", component: IssuesComponent, canActivate: [AuthGuard] }, - { path: ":id", component: IssueDetailsComponent, canActivate: [AuthGuard] }, + { path: ":providerId", component: IssuesDetailsComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -25,7 +27,8 @@ const routes: Routes = [ RouterModule.forChild(routes), OrderModule, PipeModule, - OmbiShared + OmbiShared, + // NbChatModule, ], declarations: [ IssuesComponent, diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html index 8244536ad..8e22d3e51 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html @@ -14,7 +14,7 @@ - + diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts index 7ed826fc5..0fd81a534 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts @@ -1,8 +1,7 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; -import { IIssues, IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; -import { DetailsGroupComponent, IssuesDetailsGroupData } from "./components/details-group/details-group.component"; +import { IIssuesSummary, IPagenator, IssueStatus } from "../interfaces"; @Component({ selector: "issues-table", @@ -52,12 +51,4 @@ export class IssuesTableComponent { public paginate(event: IPagenator) { this.changePage.emit(event); } - - public openDetails(summary: IIssuesSummary) { - const dialogRef = this.dialog.open(DetailsGroupComponent, { - width: "50vw", - data: { issues: summary.issues, title: summary.title }, - }); - } - } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index 988859245..912f8a32c 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -113,9 +113,13 @@ export class MovieDetailsComponent { } public async issue() { + let provider = this.movie.id.toString(); + if (this.movie.imdbId) { + provider = this.movie.imdbId; + } const dialogRef = this.dialog.open(NewIssueComponent, { width: '500px', - data: { requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, providerId: this.movie.imdbId ? this.movie.imdbId : this.movie.id, title: this.movie.title } + data: { requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, providerId: provider, title: this.movie.title } }); } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts index dda7bcb89..206be2141 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts @@ -6,10 +6,11 @@ import { TranslateService } from "@ngx-translate/core"; @Component({ selector: "issues-panel", templateUrl: "./issues-panel.component.html", - styleUrls: ["./issues-panel.component.scss"] + styleUrls: ["./issues-panel.component.scss"], + }) export class IssuesPanelComponent implements OnInit { - + @Input() public providerId: string; @Input() public isAdmin: boolean; @@ -22,7 +23,6 @@ export class IssuesPanelComponent implements OnInit { constructor(private issuesService: IssuesService, private notificationService: NotificationService, private translateService: TranslateService, private settingsService: SettingsService) { - } public async ngOnInit() { @@ -54,7 +54,7 @@ export class IssuesPanelComponent implements OnInit { this.issuesCount = this.issues.length; this.calculateOutstanding(); } - + private calculateOutstanding() { this.isOutstanding = this.issues.some((i) => { return i.status !== IssueStatus.Resolved; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts index c42c14fe2..94972c70d 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts @@ -10,7 +10,7 @@ import { TranslateService } from "@ngx-translate/core"; templateUrl: "./new-issue.component.html", }) export class NewIssueComponent implements OnInit { - + public issue: IIssues; public issueCategories: IIssueCategory[]; @@ -40,9 +40,9 @@ export class NewIssueComponent implements OnInit { public async ngOnInit(): Promise { this.issueCategories = await this.issueService.getCategories().toPromise(); - } + } - public async createIssue() { + public async createIssue() { const result = await this.issueService.createIssue(this.issue).toPromise(); if(result) { this.messageService.send(this.translate.instant("Issues.IssueDialog.IssueCreated")); diff --git a/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts b/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts index 69b5c01c4..d792702a0 100644 --- a/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/issuesv2.service.ts @@ -16,4 +16,8 @@ export class IssuesV2Service extends ServiceHelpers { public getIssues(position: number, take: number, status: IssueStatus): Observable { return this.http.get(`${this.url}${position}/${take}/${status}`, {headers: this.headers}); } + + public getIssuesByProviderId(providerId: string): Observable { + return this.http.get(`${this.url}details/${providerId}`, {headers: this.headers}); + } } diff --git a/src/Ombi/Controllers/V2/IssuesController.cs b/src/Ombi/Controllers/V2/IssuesController.cs index 214482b54..84eafa3ad 100644 --- a/src/Ombi/Controllers/V2/IssuesController.cs +++ b/src/Ombi/Controllers/V2/IssuesController.cs @@ -20,5 +20,12 @@ namespace Ombi.Controllers.V2 { return _engine.GetIssues(position, take, status, HttpContext.RequestAborted); } + + + [HttpGet("details/{providerId}")] + public Task GetIssueDetails(string providerId) + { + return _engine.GetIssuesByProviderId(providerId, HttpContext.RequestAborted); + } } } From f777e5d171886a85f2968fa4d5a2c54a8a609df2 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 26 Feb 2021 23:10:52 +0000 Subject: [PATCH 4/6] Added the basic comment functionality --- .../ClientApp/src/app/auth/auth.service.ts | 4 + .../details-group.component.html | 1 - .../components/details/details.component.html | 5 +- .../components/details/details.component.ts | 9 +- .../src/app/issues/components/index.ts | 6 +- .../issue-chat/issue-chat.component.html | 6 + .../issue-chat/issue-chat.component.scss | 9 + .../issue-chat/issue-chat.component.ts | 87 +++++ .../ClientApp/src/app/issues/issues.module.ts | 4 +- .../shared/chat-box/chat-box.component.html | 23 ++ .../shared/chat-box/chat-box.component.scss | 329 ++++++++++++++++++ .../app/shared/chat-box/chat-box.component.ts | 46 +++ 12 files changed, 520 insertions(+), 9 deletions(-) create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.html create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.scss create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts create mode 100644 src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html create mode 100644 src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss create mode 100644 src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.ts diff --git a/src/Ombi/ClientApp/src/app/auth/auth.service.ts b/src/Ombi/ClientApp/src/app/auth/auth.service.ts index 3eace43a4..afc0a2491 100644 --- a/src/Ombi/ClientApp/src/app/auth/auth.service.ts +++ b/src/Ombi/ClientApp/src/app/auth/auth.service.ts @@ -74,6 +74,10 @@ export class AuthService extends ServiceHelpers { return false; } + public isAdmin() { + return this.hasRole("Admin") || this.hasRole("PowerUser"); + } + public logout() { this.store.remove("id_token"); } diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html index 7c3c04fdd..9738e24c7 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html @@ -1,6 +1,5 @@

Issues for {{data.title}}

-
diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html index b8e8dc1f6..08cb2dc44 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html @@ -3,6 +3,7 @@

Issues for {{details.title}}

Has Request {{hasRequest}} +
@@ -16,7 +17,7 @@

- +
-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts index ed00bc041..accc99e60 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts @@ -1,11 +1,12 @@ import { Component, Inject, OnInit, ViewEncapsulation } from "@angular/core"; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { ActivatedRoute, ActivatedRouteSnapshot, Router } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; import { AuthService } from "../../../auth/auth.service"; import { IIssues, IIssueSettings, IIssuesSummary, IssueStatus, RequestType } from "../../../interfaces"; import { IssuesService, NotificationService, SettingsService } from "../../../services"; import { IssuesV2Service } from "../../../services/issuesv2.service"; +import { IssueChatComponent } from "../issue-chat/issue-chat.component"; export interface IssuesDetailsGroupData { @@ -33,7 +34,8 @@ export class IssuesDetailsComponent implements OnInit { constructor(private authService: AuthService, private settingsService: SettingsService, private issueServiceV2: IssuesV2Service, private route: ActivatedRoute, private router: Router, - private issuesService: IssuesService, private translateService: TranslateService, private notificationService: NotificationService) { + private issuesService: IssuesService, private translateService: TranslateService, private notificationService: NotificationService, + private dialog: MatDialog) { this.route.params.subscribe(async (params: any) => { if (typeof params.providerId === 'string' || params.providerId instanceof String) { this.providerId = params.providerId; @@ -67,6 +69,9 @@ export class IssuesDetailsComponent implements OnInit { this.details.issues = this.details.issues.filter((el) => { return el.id !== issue.id; }); } + public openChat(issue: IIssues) { + this.dialog.open(IssueChatComponent, { width: "80vh", data: { issueId: issue.id }, panelClass: 'modal-panel' }) + } public navToMedia() { const firstIssue = this.details.issues[0]; diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts index 86ceefe89..99a07492b 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/index.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -1,15 +1,17 @@ -import { AuthGuard } from "../../auth/auth.guard"; -import { Routes } from "@angular/router"; import { IssuesV2Service } from "../../services/issuesv2.service"; import { IdentityService, SearchService } from "../../services"; import { DetailsGroupComponent } from "./details-group/details-group.component"; import { IssuesDetailsComponent } from "./details/details.component"; +import { IssueChatComponent } from "./issue-chat/issue-chat.component"; +import { ChatBoxComponent } from "../../shared/chat-box/chat-box.component"; export const components: any[] = [ DetailsGroupComponent, IssuesDetailsComponent, + IssueChatComponent, + ChatBoxComponent, ]; export const providers: any[] = [ diff --git a/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.html b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.html new file mode 100644 index 000000000..fe6c13ce7 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.html @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.scss b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.scss new file mode 100644 index 000000000..d6dcd67de --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.scss @@ -0,0 +1,9 @@ +@import "~styles/variables.scss"; + +::ng-deep .mat-card { + background: $ombi-background-primary-accent; +} + +.top-spacing { + margin-top:2%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts new file mode 100644 index 000000000..a1ecf27f3 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts @@ -0,0 +1,87 @@ +import { Component, Inject, OnInit } from "@angular/core"; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { AuthService } from "../../../auth/auth.service"; +import { ILocalUser } from "../../../auth/IUserLogin"; +import { IIssuesChat, IIssueSettings, IssueStatus } from "../../../interfaces"; +import { IssuesService, SettingsService } from "../../../services"; +import { ChatMessages, ChatType } from "../../../shared/chat-box/chat-box.component"; + + +export interface ChatData { + issueId: number; + title: string; + } + +@Component({ + selector: "issue-chat", + templateUrl: "issue-chat.component.html", + styleUrls: ["issue-chat.component.scss"], +}) +export class IssueChatComponent implements OnInit { + + public isAdmin: boolean; + public comments: IIssuesChat[]; + public IssueStatus = IssueStatus; + public settings: IIssueSettings; + public messages: ChatMessages[] = []; + + public loaded: boolean; + + private user: ILocalUser; + + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: ChatData, + private authService: AuthService, private settingsService: SettingsService, + private issueService: IssuesService) { } + + public ngOnInit() { + this.isAdmin = this.authService.isAdmin(); + this.user = this.authService.claims(); + this.settingsService.getIssueSettings().subscribe(x => this.settings = x); + this.issueService.getComments(this.data.issueId).subscribe(x => { + this.comments = x; + this.mapMessages(); + this.loaded = true; + }); + } + + + public deleteComment(commentId: number) { + + } + + public addComment(comment: string) { + this.issueService.addComment({ + comment: comment, + issueId: this.data.issueId + }).subscribe(comment => { + this.messages.push({ + chatType: ChatType.Sender, + date: comment.date, + id: -1, + message: comment.comment, + username: comment.user.userName + }); + }); + + } + + public close() { + this.dialogRef.close(); + } + + private mapMessages() { + this.comments.forEach((m: IIssuesChat) => { + this.messages.push({ + chatType: m.username === this.user.name ? ChatType.Sender : ChatType.Reciever, + date: m.date, + id: m.id, + message: m.comment, + username: m.username + }); + }); + } + + +} diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index 08896a086..4bf232f25 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe"; import { AuthGuard } from "../auth/auth.guard"; -import { SharedModule as OmbiShared } from "../shared/shared.module"; +import { SharedModule } from "../shared/shared.module"; import { IssueDetailsComponent } from "./issueDetails.component"; import { IssuesComponent } from "./issues.component"; @@ -27,7 +27,7 @@ const routes: Routes = [ RouterModule.forChild(routes), OrderModule, PipeModule, - OmbiShared, + SharedModule, // NbChatModule, ], declarations: [ diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html new file mode 100644 index 000000000..85463dea1 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html @@ -0,0 +1,23 @@ +
+
+
+

Users

+
+

{{user}}

+
+
+
+
+
+

{{m.username}}

+
+

{{m.message}}

+

{{m.date | amLocal | amDateFormat: 'l LT'}}

+
+
+
+
+ + +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss new file mode 100644 index 000000000..d64de471b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss @@ -0,0 +1,329 @@ +// Variables +$primary: rgba(23, 190, 187, 1); +$secondary: rgba(240, 166, 202, 1); + +$active: rgba(23, 190, 187, 0.8); +$busy: rgba(252, 100, 113, 0.8); +$away: rgba(255, 253, 130, 0.8); + +// Triangle Mixin +@mixin triangle($color, $size, $direction) { + width: 0; + height: 0; + @if $direction == "up" { + border-right: ($size + px) solid transparent; + border-left: ($size + px) solid transparent; + border-bottom: ($size + px) solid $color; + } + @if $direction == "down" { + border-right: ($size + px) solid transparent; + border-left: ($size + px) solid transparent; + border-top: ($size + px) solid $color; + } + @if $direction == "right" { + border-top: ($size + px) solid transparent; + border-bottom: ($size + px) solid transparent; + border-left: ($size + px) solid $color; + } + @if $direction == "left" { + border-top: ($size + px) solid transparent; + border-bottom: ($size + px) solid transparent; + border-right: ($size + px) solid $color; + } +} + +* { + margin: 0; padding: 0; + box-sizing: border-box; + font-family: 'Nunito', sans-serif; +} + +html,body { + background: linear-gradient(120deg, $primary, $secondary); + overflow: hidden; +} + +.container { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + height: 70vh; + h1 { + margin: 0.5em auto; + color: #FFF; + text-align: center; + } +} + +.chatbox { + background: rgba(255, 255, 255, 0.05); + width: 600px; + height: 75%; + border-radius: 0.2em; + position: relative; + box-shadow: 1px 1px 12px rgba(0, 0, 0, 0.1); + + .sender { + float: right; + &:after { + content: ''; + position: absolute; + margin: -1.5em -18.98em; + @include triangle(rgba(255, 255, 255, 0.2), 10, left); + } + } + .reciever { + float: left; + &:after { + content: ''; + position: absolute; + margin: -1.5em 2.65em; + @include triangle(rgba(255, 255, 255, 0.2), 10, right); + } + } + &__messages__user-message { + width: 450px; + } + &__messages__user-message--ind-message { + background: rgba(255, 255, 255, 0.2); + padding: 1em 0; + height: auto; + width: 65%; + border-radius: 5px; + margin: 2em 1em; + overflow: auto; + & > p.name { + color: #FFF; + font-size: 1em; + } + & > p.message { + color: #FFF; + font-size: 0.7em; + margin: 0 2.8em; + }& > p.timestamp { + color: #FFF; + font-size: 0.7em; + margin: 0 2.8em; + } + } + &__user-list { + background: rgba(255, 255, 255, 0.1); + width: 25%; + height: 100%; + float: right; + border-top-right-radius: 0.2em; + border-bottom-right-radius: 0.2em; + h1 { + background: rgba(255, 255, 255, 0.05); + color: rgba(255, 255, 255, 0.9); + font-size: 0.9em; + padding: 1em; + margin: 0; + font-weight: 300; + text-align: center; + } + } + &__user { + width: 0.5em; + height: 0.5em; + border-radius: 100%; + margin: 1em 0.7em; + &--active { + @extend .chatbox__user; + background: $active; + } + &--busy { + @extend .chatbox__user; + background: $busy; + } + &--away { + @extend .chatbox__user; + background: $away; + } + } + p { + float: left; + text-align: left; + margin: -0.25em 2em; + font-size: 0.7em; + font-weight: 300; + color: #FFF; + width: 200px; + } + .form { + background: #222; + input { + background: rgba(255, 255, 255, 0.03); + position: absolute; + bottom: 0; + left: 0; + border: none; + width: 75%; + padding: 1.2em; + outline: none; + color: rgba(255, 255, 255, 0.9); + font-weight: 300; + } + .add-message { + background: rgba(255, 255, 255, 0.03); + position: absolute; + bottom: 1.5%; + right: 26%; + border: none; + outline: none; + color: rgba(255, 255, 255, 0.9); + font-weight: 300; + } + } +} + +// Placeholder Styling +::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.9); +} + +:-moz-placeholder { + color: rgba(255, 255, 255, 0.9); +} + +::-moz-placeholder { + color: rgba(255, 255, 255, 0.9); +} + +:-ms-input-placeholder { + color: rgba(255, 255, 255, 0.9); +} + +// ::-webkit-scrollbar { +// width: 4px; +// } +// ::-webkit-scrollbar-thumb { +// background-color: #4c4c6a; +// border-radius: 2px; +// } +// .chatbox { +// width: 300px; +// height: 400px; +// max-height: 400px; +// display: flex; +// flex-direction: column; +// overflow: hidden; +// box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28); +// } +// .chat-window { +// flex: auto; +// max-height: calc(100% - 60px); +// background: #2f323b; +// overflow: auto; +// } +// .chat-input { +// flex: 0 0 auto; +// height: 60px; +// background: #40434e; +// border-top: 1px solid #2671ff; +// box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28); +// } +// .chat-input input { +// height: 59px; +// line-height: 60px; +// outline: 0 none; +// border: none; +// width: calc(100% - 60px); +// color: white; +// text-indent: 10px; +// font-size: 12pt; +// padding: 0; +// background: #40434e; +// } +// .chat-input button { +// float: right; +// outline: 0 none; +// border: none; +// background: rgba(255,255,255,.25); +// height: 40px; +// width: 40px; +// border-radius: 50%; +// padding: 2px 0 0 0; +// margin: 10px; +// transition: all 0.15s ease-in-out; +// } +// .chat-input input[good] + button { +// box-shadow: 0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24); +// background: #2671ff; +// } +// .chat-input input[good] + button:hover { +// box-shadow: 0 8px 17px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); +// } +// .chat-input input[good] + button path { +// fill: white; +// } +// .msg-container { +// position: relative; +// display: inline-block; +// width: 100%; +// margin: 0 0 10px 0; +// padding: 0; +// } +// .msg-box { +// display: flex; +// background: #5b5e6c; +// padding: 10px 10px 0 10px; +// border-radius: 0 6px 6px 0; +// max-width: 80%; +// width: auto; +// float: left; +// box-shadow: 0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24); +// } +// .user-img { +// display: inline-block; +// border-radius: 50%; +// height: 40px; +// width: 40px; +// background: #2671ff; +// margin: 0 10px 10px 0; +// } +// .flr { +// flex: 1 0 auto; +// display: flex; +// flex-direction: column; +// width: calc(100% - 50px); +// } +// .messages { +// flex: 1 0 auto; +// } +// .msg { +// display: inline-block; +// font-size: 11pt; +// line-height: 13pt; +// color: rgba(255,255,255,.7); +// margin: 0 0 4px 0; +// } +// .msg:first-of-type { +// margin-top: 8px; +// } +// .timestamp { +// color: rgba(0,0,0,.38); +// font-size: 8pt; +// margin-bottom: 10px; +// } +// .username { +// margin-right: 3px; +// } +// .posttime { +// margin-left: 3px; +// } +// .msg-self .msg-box { +// border-radius: 6px 0 0 6px; +// background: #2671ff; +// float: right; +// } +// .msg-self .user-img { +// margin: 0 0 10px 10px; +// } +// .msg-self .msg { +// text-align: right; +// } +// .msg-self .timestamp { +// text-align: right; +// } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.ts b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.ts new file mode 100644 index 000000000..697977563 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.ts @@ -0,0 +1,46 @@ +import { AfterContentChecked, AfterViewInit, Component, EventEmitter, Inject, Input, OnInit, Output } from "@angular/core"; + + +export interface ChatMessages { + id: number; + message: string; + date: Date; + username: string; + chatType: ChatType; + } + + export enum ChatType { + Sender, + Reciever + } + +@Component({ + selector: "ombi-chat-box", + templateUrl: "chat-box.component.html", + styleUrls: ["chat-box.component.scss"], +}) +export class ChatBoxComponent implements OnInit { + @Input() messages: ChatMessages[]; + @Output() onAddMessage: EventEmitter = new EventEmitter(); + @Output() onDeleteMessage: EventEmitter = new EventEmitter(); + + public currentMessage: string; + public userList: string[]; + public ChatType = ChatType; + + public ngOnInit(): void { + const allUsernames = this.messages.map(x => x.username); + this.userList = allUsernames.filter((v, i, a) => a.indexOf(v) === i); + } + + public deleteMessage(id: number) { + this.onDeleteMessage.emit(id); + } + + public addMessage() { + if (this.currentMessage) { + this.onAddMessage.emit(this.currentMessage); + this.currentMessage = ''; + } + } +} From 67c7d73ca1cd839bc4c86d845d6cb1904e74ad3d Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 3 Mar 2021 21:28:37 +0000 Subject: [PATCH 5/6] think i've finished the new issues work --- src/Ombi.Core/Engine/V2/IssuesEngine.cs | 2 +- .../details-group.component.html | 53 ++++++++------- .../details-group.component.scss | 4 +- .../details-group/details-group.component.ts | 67 ++++++++++--------- .../components/details/details.component.html | 39 +++-------- .../components/details/details.component.ts | 2 +- .../src/app/issues/components/index.ts | 2 - .../issue-chat/issue-chat.component.ts | 2 +- .../src/app/media-details/components/index.ts | 1 + .../issues-panel/issues-panel.component.html | 7 +- .../shared/chat-box/chat-box.component.html | 2 +- .../shared/chat-box/chat-box.component.scss | 5 +- .../ClientApp/src/app/shared/shared.module.ts | 4 ++ src/Ombi/wwwroot/translations/en.json | 4 +- 14 files changed, 97 insertions(+), 97 deletions(-) diff --git a/src/Ombi.Core/Engine/V2/IssuesEngine.cs b/src/Ombi.Core/Engine/V2/IssuesEngine.cs index f938e8ec6..830dd4295 100644 --- a/src/Ombi.Core/Engine/V2/IssuesEngine.cs +++ b/src/Ombi.Core/Engine/V2/IssuesEngine.cs @@ -32,7 +32,7 @@ namespace Ombi.Core.Engine.V2 public async Task> GetIssues(int position, int take, IssueStatus status, CancellationToken token) { - var issues = await _issues.GetAll().Where(x => x.Status == status).Skip(position).Take(take).OrderBy(x => x.Title).ToListAsync(token); + var issues = await _issues.GetAll().Where(x => x.Status == status && x.ProviderId != null).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 model = new List(); diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html index 9738e24c7..c4906baac 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.html @@ -1,26 +1,27 @@ -

Issues for {{data.title}}

-
-
-
- - - {{issue.subject}} - {{issue.userReported?.userName}} on {{issue.createdDate | date:short}} - - -

- {{issue.description}} -

-
- - - - -
-
-
-
-
- - -
+ + + {{issue.subject}} + {{issue.userReported?.userName}} on {{issue.createdDate | date:short}} + + +

+ {{issue.description}} +

+
+ + +
here is ignored
+ + + + + + + +
+
+ diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss index d6dcd67de..c244fdd09 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.scss @@ -1,7 +1,7 @@ @import "~styles/variables.scss"; -::ng-deep .mat-card { - background: $ombi-background-primary-accent; +::ng-deep .issue-card { + border: 3px solid $ombi-background-primary-accent; } .top-spacing { diff --git a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts index aea5eb123..4f7ddc612 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/details-group/details-group.component.ts @@ -1,48 +1,55 @@ -import { Component, Inject, OnInit } from "@angular/core"; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { AuthService } from "../../../auth/auth.service"; +import { Component, Input } from "@angular/core"; +import { MatDialog } from '@angular/material/dialog'; +import { TranslateService } from "@ngx-translate/core"; import { IIssues, IIssueSettings, IssueStatus } from "../../../interfaces"; -import { SettingsService } from "../../../services"; - - -export interface IssuesDetailsGroupData { - issues: IIssues[]; - title: string; - } +import { IssuesService, NotificationService } from "../../../services"; +import { IssueChatComponent } from "../issue-chat/issue-chat.component"; @Component({ selector: "issues-details-group", templateUrl: "details-group.component.html", styleUrls: ["details-group.component.scss"], }) -export class DetailsGroupComponent implements OnInit { +export class DetailsGroupComponent { - public isAdmin: boolean; + @Input() public issue: IIssues; + @Input() public isAdmin: boolean; + @Input() public settings: IIssueSettings; + + public deleted: boolean; public IssueStatus = IssueStatus; - public settings: IIssueSettings; public get hasRequest(): boolean { - return this.data.issues.some(x => x.requestId); + if (this.issue.requestId) { + return true; + } + return false; } - constructor(public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: IssuesDetailsGroupData, - private authService: AuthService, private settingsService: SettingsService) { } + constructor( + private translateService: TranslateService, private issuesService: IssuesService, + private notificationService: NotificationService, private dialog: MatDialog) { } - public ngOnInit() { - this.isAdmin = this.authService.hasRole("Admin") || this.authService.hasRole("PowerUser"); - this.settingsService.getIssueSettings().subscribe(x => this.settings = x); + public async delete(issue: IIssues) { + await this.issuesService.deleteIssue(issue.id); + this.notificationService.success(this.translateService.instant("Issues.DeletedIssue")); + this.deleted = true; } - public close() { - this.dialogRef.close(); - } - - public navToRequest() { - var issue = this.data.issues.filter(x => { - return x.requestId; - })[0]; + public openChat(issue: IIssues) { + this.dialog.open(IssueChatComponent, { width: "100vh", data: { issueId: issue.id }, panelClass: 'modal-panel' }) + } - // close dialog and tell calling component to navigate - } + public resolve(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.Resolved}).subscribe(() => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsResolved")); + issue.status = IssueStatus.Resolved; + }); + } + public inProgress(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.InProgress}).subscribe(() => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsInProgress")); + issue.status = IssueStatus.InProgress; + }); + } } diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html index 08cb2dc44..bc0e8a794 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.html @@ -1,39 +1,20 @@ -
+

Issues for {{details.title}}

- Has Request {{hasRequest}} - + {{'Issues.Requested' | translate}} + + + +
+ +
-
-
-
{{issue.subject}}
- {{issue.userReported?.userName}} on {{issue.createdDate | date:short}} -
-
-

- {{issue.description}} -

-
-
- - - - - - -
- -
+
-
-
\ No newline at end of file +
diff --git a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts index accc99e60..4003acd40 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/details/details.component.ts @@ -70,7 +70,7 @@ export class IssuesDetailsComponent implements OnInit { } public openChat(issue: IIssues) { - this.dialog.open(IssueChatComponent, { width: "80vh", data: { issueId: issue.id }, panelClass: 'modal-panel' }) + this.dialog.open(IssueChatComponent, { width: "100vh", data: { issueId: issue.id }, panelClass: 'modal-panel' }) } public navToMedia() { diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts index 99a07492b..52e4ed03c 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/index.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -1,6 +1,5 @@ import { IssuesV2Service } from "../../services/issuesv2.service"; import { IdentityService, SearchService } from "../../services"; -import { DetailsGroupComponent } from "./details-group/details-group.component"; import { IssuesDetailsComponent } from "./details/details.component"; import { IssueChatComponent } from "./issue-chat/issue-chat.component"; import { ChatBoxComponent } from "../../shared/chat-box/chat-box.component"; @@ -8,7 +7,6 @@ import { ChatBoxComponent } from "../../shared/chat-box/chat-box.component"; export const components: any[] = [ - DetailsGroupComponent, IssuesDetailsComponent, IssueChatComponent, ChatBoxComponent, diff --git a/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts index a1ecf27f3..023fdbf12 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/issue-chat/issue-chat.component.ts @@ -20,7 +20,7 @@ export interface ChatData { export class IssueChatComponent implements OnInit { public isAdmin: boolean; - public comments: IIssuesChat[]; + public comments: IIssuesChat[] = []; public IssueStatus = IssueStatus; public settings: IIssueSettings; public messages: ChatMessages[] = []; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/index.ts b/src/Ombi/ClientApp/src/app/media-details/components/index.ts index 240fba28a..e8cb89d4a 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/index.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/index.ts @@ -20,6 +20,7 @@ import { IssuesPanelComponent } from "./shared/issues-panel/issues-panel.compone import { TvAdvancedOptionsComponent } from "./tv/panels/tv-advanced-options/tv-advanced-options.component"; import { RequestBehalfComponent } from "./shared/request-behalf/request-behalf.component"; import { TvRequestGridComponent } from "./tv/panels/tv-request-grid/tv-request-grid.component"; +import { DetailsGroupComponent } from "../../issues/components/details-group/details-group.component"; export const components: any[] = [ MovieDetailsComponent, diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html index c4c05dff9..d71ca8fcd 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html @@ -13,6 +13,11 @@ + +
+ +
+
diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html index 85463dea1..aa19bf1db 100644 --- a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.html @@ -1,4 +1,4 @@ -
+

Users

diff --git a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss index d64de471b..70f83b85f 100644 --- a/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss +++ b/src/Ombi/ClientApp/src/app/shared/chat-box/chat-box.component.scss @@ -49,6 +49,7 @@ html,body { align-items: center; flex-direction: column; height: 70vh; + width: 100%; h1 { margin: 0.5em auto; color: #FFF; @@ -58,8 +59,8 @@ html,body { .chatbox { background: rgba(255, 255, 255, 0.05); - width: 600px; - height: 75%; + width: 85%; + height: 100%; border-radius: 0.2em; position: relative; box-shadow: 1px 1px 12px rgba(0, 0, 0, 0.1); diff --git a/src/Ombi/ClientApp/src/app/shared/shared.module.ts b/src/Ombi/ClientApp/src/app/shared/shared.module.ts index ed93fa375..afe27bb7e 100644 --- a/src/Ombi/ClientApp/src/app/shared/shared.module.ts +++ b/src/Ombi/ClientApp/src/app/shared/shared.module.ts @@ -36,11 +36,13 @@ import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; import { MatSlideToggleModule } from "@angular/material/slide-toggle"; import { MatTabsModule } from "@angular/material/tabs"; import { EpisodeRequestComponent } from "./episode-request/episode-request.component"; +import { DetailsGroupComponent } from "../issues/components/details-group/details-group.component"; @NgModule({ declarations: [ IssuesReportComponent, EpisodeRequestComponent, + DetailsGroupComponent, ], imports: [ SidebarModule, @@ -76,6 +78,7 @@ import { EpisodeRequestComponent } from "./episode-request/episode-request.compo ], entryComponents: [ EpisodeRequestComponent, + DetailsGroupComponent, ], exports: [ TranslateModule, @@ -86,6 +89,7 @@ import { EpisodeRequestComponent } from "./episode-request/episode-request.compo MatProgressSpinnerModule, IssuesReportComponent, EpisodeRequestComponent, + DetailsGroupComponent, TruncateModule, InputSwitchModule, MatTreeModule, diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 0efb3fe88..4b82d8224 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -216,7 +216,9 @@ "MarkedAsResolved": "This issue has now been marked as resolved!", "MarkedAsInProgress": "This issue has now been marked as in progress!", "Delete": "Delete issue", - "DeletedIssue": "Issue has been deleted" + "DeletedIssue": "Issue has been deleted", + "Chat":"Chat", + "Requested":"Requested" }, "Filter": { "ClearFilter": "Clear Filter", From 9337311718c7a1930e022e44071852e3076fb785 Mon Sep 17 00:00:00 2001 From: Xirg Date: Sat, 6 Mar 2021 11:33:02 +0100 Subject: [PATCH 6/6] added icon for apple homescreen icon the icon is already here, just the tag missing --- src/Ombi/ClientApp/src/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/ClientApp/src/index.html b/src/Ombi/ClientApp/src/index.html index 9b4005ca1..4d077697d 100644 --- a/src/Ombi/ClientApp/src/index.html +++ b/src/Ombi/ClientApp/src/index.html @@ -14,6 +14,7 @@ +