diff --git a/src/Ombi.Helpers/NotificationSubstitues.cs b/src/Ombi.Helpers/NotificationSubstitues.cs new file mode 100644 index 000000000..69b91304d --- /dev/null +++ b/src/Ombi.Helpers/NotificationSubstitues.cs @@ -0,0 +1,18 @@ +namespace Ombi.Helpers +{ + public static class NotificationSubstitues + { + public const string Title = nameof(Title); + public const string IssueDescription = nameof(IssueDescription); + public const string IssueCategory = nameof(IssueCategory); + public const string IssueStatus = nameof(IssueStatus); + public const string IssueSubject = nameof(IssueSubject); + public const string IssueUser = nameof(IssueUser); + public const string IssueUserAlias = nameof(IssueUserAlias); + public const string RequestType = nameof(RequestType); + public const string PosterPath = nameof(PosterPath); + public const string NewIssueComment = nameof(NewIssueComment); + public const string IssueId = nameof(IssueId); + public const string AdminComment = nameof(AdminComment); + } +} diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 392fc9412..e7449e04e 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -39,7 +39,12 @@ namespace Ombi.Notifications Year = req?.ReleaseDate.Year.ToString(); Overview = req?.Overview; AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; - PosterImage = $"https://image.tmdb.org/t/p/w300/{req?.PosterPath?.TrimStart('/') ?? string.Empty}"; + + var img = req?.PosterPath ?? string.Empty; + if (img.HasValue()) + { + PosterImage = $"https://image.tmdb.org/t/p/w300/{req?.PosterPath?.TrimStart('/') ?? string.Empty}"; + } CalculateRequestStatus(req); } @@ -53,8 +58,12 @@ namespace Ombi.Notifications Year = req?.ParentRequest?.ReleaseDate.Year.ToString(); Overview = req?.ParentRequest?.Overview; AdditionalInformation = opts.AdditionalInformation; - PosterImage = - $"https://image.tmdb.org/t/p/w300/{req?.ParentRequest?.PosterPath?.TrimStart('/') ?? string.Empty}"; + var img = req?.ParentRequest?.PosterPath ?? string.Empty; + if (img.HasValue()) + { + PosterImage = + $"https://image.tmdb.org/t/p/w300/{req?.ParentRequest?.PosterPath?.TrimStart('/') ?? string.Empty}"; + } // Generate episode list. StringBuilder epSb = new StringBuilder(); @@ -94,16 +103,17 @@ namespace Ombi.Notifications private void LoadIssues(NotificationOptions opts) { - IssueDescription = opts.Substitutes.TryGetValue("IssueDescription", out string val) ? val : string.Empty; - IssueCategory = opts.Substitutes.TryGetValue("IssueCategory", out val) ? val : string.Empty; - IssueStatus = opts.Substitutes.TryGetValue("IssueStatus", out val) ? val : string.Empty; - IssueSubject = opts.Substitutes.TryGetValue("IssueSubject", out val) ? val : string.Empty; - NewIssueComment = opts.Substitutes.TryGetValue("NewIssueComment", out val) ? val : string.Empty; - UserName = opts.Substitutes.TryGetValue("IssueUser", out val) ? val : string.Empty; - Alias = opts.Substitutes.TryGetValue("IssueUserAlias", out val) ? val : string.Empty; - Type = opts.Substitutes.TryGetValue("RequestType", out val) && Enum.TryParse(val, out RequestType type) + IssueDescription = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueDescription, out string val) ? val : string.Empty; + IssueCategory = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueCategory, out val) ? val : string.Empty; + IssueStatus = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueStatus, out val) ? val : string.Empty; + IssueSubject = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueSubject, out val) ? val : string.Empty; + NewIssueComment = opts.Substitutes.TryGetValue(NotificationSubstitues.NewIssueComment, out val) ? val : string.Empty; + UserName = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueUser, out val) ? val : string.Empty; + Alias = opts.Substitutes.TryGetValue(NotificationSubstitues.IssueUserAlias, out val) ? val : string.Empty; + Type = opts.Substitutes.TryGetValue(NotificationSubstitues.RequestType, out val) && Enum.TryParse(val, out RequestType type) ? HumanizeReturnType(type) : string.Empty; + PosterImage = opts.Substitutes.TryGetValue(NotificationSubstitues.PosterPath, out val) ? $"https://image.tmdb.org/t/p/w300/{val.TrimStart('/')}" : string.Empty; } private void LoadCommon(BaseRequest req, CustomizationSettings s, UserNotificationPreferences pref, NotificationOptions opts) diff --git a/src/Ombi.Store/Entities/Requests/Issues.cs b/src/Ombi.Store/Entities/Requests/Issues.cs index 082261a15..ea64365be 100644 --- a/src/Ombi.Store/Entities/Requests/Issues.cs +++ b/src/Ombi.Store/Entities/Requests/Issues.cs @@ -25,6 +25,8 @@ namespace Ombi.Store.Entities.Requests public string UserReportedId { get; set; } public OmbiUser UserReported { get; set; } public List Comments { get; set; } + [NotMapped] + public string PosterPath { get; set; } } public enum IssueStatus diff --git a/src/Ombi/.vscode/settings.json b/src/Ombi/.vscode/settings.json index fd36c353d..0fc7fae1e 100644 --- a/src/Ombi/.vscode/settings.json +++ b/src/Ombi/.vscode/settings.json @@ -17,6 +17,7 @@ "settings", "user-management", "newsletter", - "mass-email" + "mass-email", + "issues" ] } diff --git a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts index 10de2a596..aac30c1e4 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IIssues.ts @@ -14,6 +14,7 @@ export interface IIssues { comments: IIssueComments[]; requestId: number | undefined; userReported: IUser | undefined; + posterPath: string; } export enum IssueStatus { diff --git a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.ts b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.ts index 1e30f932c..70eb69aee 100644 --- a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.ts @@ -70,6 +70,7 @@ export class IssueDetailsComponent implements OnInit { requestId: x.requestId, providerId: x.providerId, userReported: x.userReported, + posterPath: undefined, // Poster Path is not stored in the db, will always be undefined }; this.setBackground(x); }); 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 6799a8f74..eadc8d635 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/index.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/index.ts @@ -1,26 +1,26 @@ -import { MovieDetailsComponent } from "./movie/movie-details.component"; -import { YoutubeTrailerComponent } from "./shared/youtube-trailer.component"; -import { TvDetailsComponent } from "./tv/tv-details.component"; -import { MovieInformationPanelComponent } from "./movie/panels/movie-information-panel.component"; -import { TvInformationPanelComponent } from "./tv/panels/tv-information-panel/tv-information-panel.component"; -import { TopBannerComponent } from "./shared/top-banner/top-banner.component"; -import { SocialIconsComponent } from "./shared/social-icons/social-icons.component"; -import { MediaPosterComponent } from "./shared/media-poster/media-poster.component"; -import { CastCarouselComponent } from "./shared/cast-carousel/cast-carousel.component"; -import { DenyDialogComponent } from "./shared/deny-dialog/deny-dialog.component"; -import { TvRequestsPanelComponent } from "./tv/panels/tv-requests/tv-requests-panel.component"; -import { MovieAdvancedOptionsComponent } from "./movie/panels/movie-advanced-options/movie-advanced-options.component"; -import { SearchService, RequestService, RadarrService, IssuesService, SonarrService } from "../../services"; -import { RequestServiceV2 } from "../../services/requestV2.service"; -import { NewIssueComponent } from "./shared/new-issue/new-issue.component"; +import { IssuesService, RadarrService, RequestService, SearchService, SonarrService } from "../../services"; + import { ArtistDetailsComponent } from "./artist/artist-details.component"; import { ArtistInformationPanel } from "./artist/panels/artist-information-panel/artist-information-panel.component"; import { ArtistReleasePanel } from "./artist/panels/artist-release-panel/artist-release-panel.component"; +import { CastCarouselComponent } from "./shared/cast-carousel/cast-carousel.component"; +import { DenyDialogComponent } from "./shared/deny-dialog/deny-dialog.component"; import { IssuesPanelComponent } from "./shared/issues-panel/issues-panel.component"; -import { TvAdvancedOptionsComponent } from "./tv/panels/tv-advanced-options/tv-advanced-options.component"; +import { MediaPosterComponent } from "./shared/media-poster/media-poster.component"; +import { MovieAdvancedOptionsComponent } from "./movie/panels/movie-advanced-options/movie-advanced-options.component"; +import { MovieDetailsComponent } from "./movie/movie-details.component"; +import { MovieInformationPanelComponent } from "./movie/panels/movie-information-panel.component"; +import { NewIssueComponent } from "./shared/new-issue/new-issue.component"; import { RequestBehalfComponent } from "./shared/request-behalf/request-behalf.component"; +import { RequestServiceV2 } from "../../services/requestV2.service"; +import { SocialIconsComponent } from "./shared/social-icons/social-icons.component"; +import { TopBannerComponent } from "./shared/top-banner/top-banner.component"; +import { TvAdvancedOptionsComponent } from "./tv/panels/tv-advanced-options/tv-advanced-options.component"; +import { TvDetailsComponent } from "./tv/tv-details.component"; +import { TvInformationPanelComponent } from "./tv/panels/tv-information-panel/tv-information-panel.component"; import { TvRequestGridComponent } from "./tv/panels/tv-request-grid/tv-request-grid.component"; -import { DetailsGroupComponent } from "../../issues/components/details-group/details-group.component"; +import { TvRequestsPanelComponent } from "./tv/panels/tv-requests/tv-requests-panel.component"; +import { YoutubeTrailerComponent } from "./shared/youtube-trailer.component"; export const components: any[] = [ MovieDetailsComponent, 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 d0e2fa1ef..c39000359 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 @@ -145,7 +145,7 @@ export class MovieDetailsComponent { } const dialogRef = this.dialog.open(NewIssueComponent, { width: '500px', - data: { requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, providerId: provider, title: this.movie.title } + data: { requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, providerId: provider, title: this.movie.title, posterPath: this.movie.posterPath } }); } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts index a2a0b6154..4237386c4 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts @@ -11,4 +11,5 @@ export interface IIssueDialogData { requestId: number; providerId: string; title: string; + posterPath: string; } \ No newline at end of file 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 94972c70d..e3ea25111 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 @@ -1,9 +1,10 @@ import { Component, Inject, OnInit } from "@angular/core"; -import { IDenyDialogData, IIssueDialogData } from "../interfaces/interfaces"; +import { IIssueDialogData } from "../interfaces/interfaces"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { MessageService, IssuesService } from "../../../../services"; import { IIssues, IIssueCategory, IssueStatus, RequestType } from "../../../../interfaces"; import { TranslateService } from "@ngx-translate/core"; +import { firstValueFrom } from "rxjs"; @Component({ selector: "new-issue", @@ -20,7 +21,6 @@ export class NewIssueComponent implements OnInit { private issueService: IssuesService, public messageService: MessageService, private translate: TranslateService) { - debugger; this.issue = { subject: "", description: "", @@ -35,16 +35,18 @@ export class NewIssueComponent implements OnInit { title: data.title, providerId: data.providerId, userReported: undefined, + posterPath: data.posterPath, }; } public async ngOnInit(): Promise { - this.issueCategories = await this.issueService.getCategories().toPromise(); + const categories$ = this.issueService.getCategories(); + this.issueCategories = await firstValueFrom(categories$); } public async createIssue() { const result = await this.issueService.createIssue(this.issue).toPromise(); - if(result) { + if (result) { this.messageService.send(this.translate.instant("Issues.IssueDialog.IssueCreated")); } } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts index 7b1c98ba8..a0fd98f48 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts @@ -84,7 +84,7 @@ export class TvDetailsComponent implements OnInit { public async issue() { const dialogRef = this.dialog.open(NewIssueComponent, { width: '500px', - data: { requestId: this.tvRequest ? this.tv.requestId : null, requestType: RequestType.tvShow, providerId: this.tv.theTvDbId, title: this.tv.title } + data: { requestId: this.tvRequest ? this.tv.requestId : null, requestType: RequestType.tvShow, providerId: this.tv.theTvDbId, title: this.tv.title, posterPath: this.tv.images.original } }); } diff --git a/src/Ombi/ClientApp/src/app/shared/issues-report.component.ts b/src/Ombi/ClientApp/src/app/shared/issues-report.component.ts index 498ff1757..cd5810bc1 100644 --- a/src/Ombi/ClientApp/src/app/shared/issues-report.component.ts +++ b/src/Ombi/ClientApp/src/app/shared/issues-report.component.ts @@ -1,5 +1,4 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; - import { IIssueCategory, IIssues, IssueStatus, RequestType } from "../interfaces"; import { IssuesService, NotificationService } from "../services"; @@ -44,6 +43,7 @@ export class IssuesReportComponent { title: "", providerId: "", userReported: undefined, + posterPath: undefined }; } @@ -55,6 +55,7 @@ export class IssuesReportComponent { issue.issueCategoryId = this.issueCategory.id; issue.title = this.title; issue.providerId = this.providerId; + issue.posterPath = this.posterPath; if (this.movie) { issue.requestType = RequestType.movie; } else { diff --git a/src/Ombi/Controllers/V1/IssuesController.cs b/src/Ombi/Controllers/V1/IssuesController.cs index 5222cf4e7..2828b5ef2 100644 --- a/src/Ombi/Controllers/V1/IssuesController.cs +++ b/src/Ombi/Controllers/V1/IssuesController.cs @@ -244,9 +244,9 @@ namespace Ombi.Controllers.V1 var isAdmin = await _userManager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser; AddIssueNotificationSubstitutes(notificationModel, issue, user.UserName, user.UserAlias); - notificationModel.Substitutes.Add("NewIssueComment", comment.Comment); - notificationModel.Substitutes.Add("IssueId", comment.IssueId.ToString()); - notificationModel.Substitutes.Add("AdminComment", isAdmin.ToString()); + notificationModel.Substitutes.Add(NotificationSubstitues.NewIssueComment, comment.Comment); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueId, comment.IssueId.ToString()); + notificationModel.Substitutes.Add(NotificationSubstitues.AdminComment, isAdmin.ToString()); if (isAdmin) { @@ -331,14 +331,15 @@ namespace Ombi.Controllers.V1 private static void AddIssueNotificationSubstitutes(NotificationOptions notificationModel, Issues issue, string issueReportedUsername, string alias) { - notificationModel.Substitutes.Add("Title", issue.Title); - notificationModel.Substitutes.Add("IssueDescription", issue.Description); - notificationModel.Substitutes.Add("IssueCategory", issue.IssueCategory?.Value); - notificationModel.Substitutes.Add("IssueStatus", issue.Status.ToString()); - notificationModel.Substitutes.Add("IssueSubject", issue.Subject); - notificationModel.Substitutes.Add("IssueUser", issueReportedUsername); - notificationModel.Substitutes.Add("IssueUserAlias", alias); - notificationModel.Substitutes.Add("RequestType", notificationModel.RequestType.ToString()); + notificationModel.Substitutes.Add(NotificationSubstitues.Title, issue.Title); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueDescription, issue.Description); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueCategory, issue.IssueCategory?.Value); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueStatus, issue.Status.ToString()); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueSubject, issue.Subject); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueUser, issueReportedUsername); + notificationModel.Substitutes.Add(NotificationSubstitues.IssueUserAlias, alias); + notificationModel.Substitutes.Add(NotificationSubstitues.RequestType, notificationModel.RequestType.ToString()); + notificationModel.Substitutes.Add(NotificationSubstitues.PosterPath, issue.PosterPath); } } } \ No newline at end of file