Got the main artist page in

pull/3895/head
tidusjar 5 years ago
parent 6c443469af
commit e231d701cc

@ -8,6 +8,8 @@ using Hqub.MusicBrainz.API.Entities;
using Microsoft.EntityFrameworkCore.Internal;
using Moq;
using NUnit.Framework;
using Ombi.Api.Lidarr;
using Ombi.Api.Lidarr.Models;
using Ombi.Api.MusicBrainz;
using Ombi.Core.Engine.V2;
using Ombi.Core.Models.Requests;
@ -20,6 +22,7 @@ using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Test.Common;
using Artist = Hqub.MusicBrainz.API.Entities.Artist;
namespace Ombi.Core.Tests.Engine.V2
{
@ -30,6 +33,8 @@ namespace Ombi.Core.Tests.Engine.V2
private MusicSearchEngineV2 _engine;
private Mock<IMusicBrainzApi> _musicApi;
private Mock<ILidarrApi> _lidarrApi;
private Mock<ISettingsService<LidarrSettings>> _lidarrSettings;
private Fixture F;
[SetUp]
@ -48,10 +53,11 @@ namespace Ombi.Core.Tests.Engine.V2
var ombiSettings = new Mock<ISettingsService<OmbiSettings>>();
var requestSub = new Mock<IRepository<RequestSubscription>>();
_musicApi = new Mock<IMusicBrainzApi>();
var lidarrSettings = new Mock<ISettingsService<LidarrSettings>>();
_lidarrSettings = new Mock<ISettingsService<LidarrSettings>>();
_lidarrApi = new Mock<ILidarrApi>();
_engine = new MusicSearchEngineV2(principle.Object, requestService.Object, ruleEval.Object,
um.Object, cache.Object, ombiSettings.Object, requestSub.Object, _musicApi.Object,
lidarrSettings.Object);
_lidarrSettings.Object, _lidarrApi.Object);
}
@ -124,7 +130,7 @@ namespace Ombi.Core.Tests.Engine.V2
Resource = url
}
},
});
_musicApi.Setup(x => x.GetArtistInformation("pretend-artist-id")).ReturnsAsync(musicReturnVal.Create());
@ -155,6 +161,52 @@ namespace Ombi.Core.Tests.Engine.V2
yield return new TestCaseData("play.google.com", RelationLinks.Download, new Func<ArtistInformation, string>(artist => artist.Links.Google)).Returns("play.google.com").SetName("ArtistInformation_Links_Google");
yield return new TestCaseData("itunes.apple.com", RelationLinks.Download, new Func<ArtistInformation, string>(artist => artist.Links.Apple)).Returns("itunes.apple.com").SetName("ArtistInformation_Links_Apple");
}
}
[Test]
public async Task GetArtistInformation_WithPosters()
{
_lidarrSettings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new LidarrSettings
{
Enabled = true,
ApiKey = "dasdsa",
Ip = "192.168.1.7"
});
_lidarrApi.Setup(x => x.GetArtistByForeignId(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(new ArtistResult
{
images = new Image[]
{
new Image
{
coverType = "poster",
url = "posterUrl"
},
new Image
{
coverType = "logo",
url = "logoUrl"
},
new Image
{
coverType = "banner",
url = "bannerUrl"
},
new Image
{
coverType = "fanArt",
url = "fanartUrl"
},
}
});
_musicApi.Setup(x => x.GetArtistInformation("pretend-artist-id")).ReturnsAsync(F.Create<Artist>());
var result = await _engine.GetArtistInformation("pretend-artist-id");
Assert.That(result.Banner, Is.EqualTo("bannerUrl"));
Assert.That(result.Poster, Is.EqualTo("posterUrl"));
Assert.That(result.Logo, Is.EqualTo("logoUrl"));
Assert.That(result.FanArt, Is.EqualTo("fanartUrl"));
}
}
}
}
}

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Hqub.MusicBrainz.API.Entities;
using Ombi.Api.Lidarr;
using Ombi.Api.Lidarr.Models;
using Ombi.Api.MusicBrainz;
using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces;
@ -16,6 +18,7 @@ using Ombi.Settings.Settings.Models;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Artist = Hqub.MusicBrainz.API.Entities.Artist;
using ReleaseGroup = Ombi.Core.Models.Search.V2.Music.ReleaseGroup;
namespace Ombi.Core.Engine.V2
@ -24,19 +27,28 @@ namespace Ombi.Core.Engine.V2
{
private readonly IMusicBrainzApi _musicBrainzApi;
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
private readonly ILidarrApi _lidarrApi;
public MusicSearchEngineV2(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules,
OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings,
IRepository<RequestSubscription> sub, IMusicBrainzApi musicBrainzApi, ISettingsService<LidarrSettings> lidarrSettings)
IRepository<RequestSubscription> sub, IMusicBrainzApi musicBrainzApi, ISettingsService<LidarrSettings> lidarrSettings,
ILidarrApi lidarrApi)
: base(identity, requestService, rules, um, cache, ombiSettings, sub)
{
_musicBrainzApi = musicBrainzApi;
_lidarrSettings = lidarrSettings;
_lidarrApi = lidarrApi;
}
public async Task<ArtistInformation> GetArtistInformation(string artistId)
{
var artist = await _musicBrainzApi.GetArtistInformation(artistId);
var lidarrSettings = await GetLidarrSettings();
Task<ArtistResult> lidarrArtistTask = null;
if (lidarrSettings.Enabled)
{
lidarrArtistTask = _lidarrApi.GetArtistByForeignId(artistId, lidarrSettings.ApiKey, lidarrSettings.FullUri);
}
var info = new ArtistInformation
{
@ -65,9 +77,20 @@ namespace Ombi.Core.Engine.V2
info.Links = GetLinksForArtist(artist);
info.Members = GetBandMembers(artist);
if (lidarrArtistTask != null)
{
var artistResult = await lidarrArtistTask;
info.Banner = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("banner", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http","https");
info.Logo = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("logo", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https");
info.Poster = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("poster", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https");
info.FanArt = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("fanart", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https");
info.Overview = artistResult.overview;
}
return info;
}
private List<BandMember> GetBandMembers(Artist artist)
{
var members = new List<BandMember>();
@ -166,5 +189,11 @@ namespace Ombi.Core.Engine.V2
return links;
}
private LidarrSettings __lidarrSettings;
private async Task<LidarrSettings> GetLidarrSettings()
{
return __lidarrSettings ?? (__lidarrSettings = await _lidarrSettings.GetSettingsAsync());
}
}
}

@ -13,6 +13,11 @@ namespace Ombi.Core.Models.Search.V2.Music
public string Country { get; set; }
public string Region { get; set; }
public string Disambiguation { get; set; }
public string Banner { get; set; }
public string Logo { get; set; }
public string Poster { get; set; }
public string FanArt { get; set; }
public string Overview { get; set; }
public List<ReleaseGroup> ReleaseGroups { get; set; }
public ArtistLinks Links { get; set; }
public List<BandMember> Members { get; set; }

@ -7,9 +7,16 @@ export interface IArtistSearchResult {
country: string;
region: string;
disambiguation: string;
banner: string;
logo: string;
poster: string;
fanArt: string;
releaseGroups: IReleaseGroups[];
links: IArtistLinks;
members: IBandMembers[];
overview: string;
background: any;
}
export interface IReleaseGroups {

@ -4,31 +4,33 @@
<div *ngIf="artist" class="dark-theme">
<top-banner [title]="artist.name"></top-banner>
<top-banner [title]="artist.name" [background]="getBackground()" [tagline]="artist.disambiguation"></top-banner>
<section id="info-wrapper">
<div class="small-middle-container">
<div class="row">
<media-poster [posterPath]="'https://image.tmdb.org/t/p/w300/' + movie.posterPath"></media-poster>
<media-poster [posterPath]="artist.poster"></media-poster>
<!--Next to poster-->
<div class="col-12 col-lg-3 col-xl-3 media-row">
<social-icons [homepage]="movie.homepage" [theMoviedbId]="movie.id"
[hasTrailer]="movie.videos.results.length > 0" (openTrailer)="openDialog()" [imdbId]="movie.imdbId"
[twitter]="movie.externalIds.twitterId" [facebook]="movie.externalIds.facebookId"
[instagram]="movie.externalIds.instagramId" [available]="movie.available" [plexUrl]="movie.plexUrl"
[embyUrl]="movie.embyUrl"></social-icons>
<social-icons
[homepage]="artist.links.homePage"
[doNotAppend]="true"
[imdbId]="artist.links.imdb"
[twitter]="artist.links.twitter"
[facebook]="artist.links.facebook"
[instagram]="artist.links.instagram"></social-icons>
</div>
<div class="col-12 col-lg-6 col-xl-6 media-row">
<button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
'Common.Available' | translate }}</button>
<span *ngIf="!movie.available">
<!-- <button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
'Common.Available' | translate }}</button> -->
<!-- <span *ngIf="!movie.available">
<span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span>
<ng-template #requestedBtn>
@ -43,8 +45,8 @@
<i *ngIf="movie.processed && !movie.requestProcessing" class="fa fa-check"></i> {{
'Common.Request' | translate }}</button>
</ng-template>
</span>
<span *ngIf="isAdmin && hasRequest">
</span> -->
<!-- <span *ngIf="isAdmin && hasRequest">
<button (click)="approve()" mat-raised-button class="btn-spacing" color="accent">
<i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}
</button>
@ -61,12 +63,12 @@
mat-raised-button class="btn-spacing" color="warn">
<i class="fa fa-times"></i> {{
'MediaDetails.Denied' | translate }}</button>
</span>
</span> -->
<button *ngIf="(hasRequest && movieRequest) || movie.available" mat-raised-button class="btn-spacing"
<!-- <button *ngIf="(hasRequest && movieRequest) || movie.available" mat-raised-button class="btn-spacing"
color="danger" (click)="issue()">
<i class="fa fa-exclamation"></i> {{
'Requests.ReportIssue' | translate }}</button>
'Requests.ReportIssue' | translate }}</button> -->
@ -77,20 +79,10 @@
<div class="row">
<div class="col-12 col-md-2">
<button *ngIf="movie.belongsToCollection"
[routerLink]="'/discover/collection/' + movie.belongsToCollection.id" mat-raised-button
class="spacing-below full-width mat-elevation-z8">{{movie.belongsToCollection.name}}</button>
<mat-card class="mat-elevation-z8 spacing-below" *ngIf="isAdmin && movieRequest">
<mat-card-content class="medium-font">
<movie-admin-panel [movie]="movieRequest" (advancedOptionsChange)="setAdvancedOptions($event)">
</movie-admin-panel>
</mat-card-content>
</mat-card>
<mat-card class="mat-elevation-z8">
<mat-card-content class="medium-font">
<movie-information-panel [movie]="movie" [advancedOptions]="advancedOptions"></movie-information-panel>
<artist-information-panel [artist]="artist"></artist-information-panel>
</mat-card-content>
</mat-card>
@ -102,19 +94,19 @@
<div class="col-12">
<mat-card class=" mat-elevation-z8 spacing-below">
<mat-card-content>
{{movie.overview}}
{{artist.overview}}
</mat-card-content>
</mat-card>
</div>
</div>
<div class="row">
<!-- <div class="row">
<div class="col-12">
<cast-carousel [cast]="movie.credits.cast"></cast-carousel>
</div>
</div>
</div> -->
<div class="row">
<!-- <div class="row">
<div class="col-12">
<mat-accordion class="mat-elevation-z8 spacing-below">
<mat-expansion-panel>
@ -181,7 +173,7 @@
</mat-expansion-panel>
</mat-accordion>
</div>
</div>
</div> -->

@ -16,7 +16,7 @@ import { IArtistSearchResult } from "../../../interfaces/IMusicSearchResultV2";
export class ArtistDetailsComponent {
private artistId: string;
public artist: IArtistSearchResult;
public artist: IArtistSearchResult = null;
public isAdmin: boolean;
@ -35,6 +35,26 @@ export class ArtistDetailsComponent {
this.searchService.getArtistInformation(this.artistId).subscribe(x => this.artist = x);
}
public getBackground(): string {
if(this.artist.fanArt) {
this.artist.background = this.sanitizer.bypassSecurityTrustStyle
("url(" + this.artist.fanArt + ")");
return this.artist.background
}
if(this.artist.logo) {
this.artist.background = this.sanitizer.bypassSecurityTrustStyle
("url(" + this.artist.logo + ")");
return this.artist.background
}
if(this.artist.poster) {
this.artist.background = this.sanitizer.bypassSecurityTrustStyle
("url(" + this.artist.poster + ")");
return this.artist.background
}
return this.artist.background
}
public async request() {
// const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null }).toPromise();
// if (result.result) {

@ -0,0 +1,18 @@
<div *ngIf="artist">
<div>
<strong>Type:</strong>
<div>{{artist.type}}</div>
</div>
<div>
<strong>Country</strong>
<div>{{artist.country}}</div>
</div>
<div>
<strong>Start Date</strong>
<div>{{artist.startYear}}</div>
</div>
<div *ngIf="artist.endYear">
<strong>End Date</strong>
<div>{{artist.endYear}}</div>
</div>
</div>

@ -0,0 +1,12 @@
import { Component, Input, ViewEncapsulation } from "@angular/core";
import { ISearchArtistResult } from "../../../../../interfaces";
@Component({
templateUrl: "./artist-information-panel.component.html",
styleUrls: ["../../../../media-details.component.scss"],
selector: "artist-information-panel",
encapsulation: ViewEncapsulation.None
})
export class ArtistInformationPanel {
@Input() public artist: ISearchArtistResult;
}

@ -15,6 +15,7 @@ import { SearchService, RequestService, RadarrService } from "../../services";
import { RequestServiceV2 } from "../../services/requestV2.service";
import { NewIssueComponent } from "./shared/new-issue/new-issue.component";
import { ArtistDetailsComponent } from "./artist/artist-details.component";
import { ArtistInformationPanel } from "./artist/panels/artist-information-panel/artist-information-panel.component";
export const components: any[] = [
MovieDetailsComponent,
@ -32,6 +33,7 @@ export const components: any[] = [
MovieAdvancedOptionsComponent,
NewIssueComponent,
ArtistDetailsComponent,
ArtistInformationPanel
];
export const entryComponents: any[] = [

@ -13,19 +13,19 @@
<a *ngIf="hasTrailer" class="media-icons" (click)="openDialog()"><i
matTooltip="Trailer" class="fa fa-youtube-play fa-2x grow-social"></i></a>
<a *ngIf="imdbId" class="media-icons" href="https://imdb.com/title/{{imdbId}}"
<a *ngIf="imdbId" class="media-icons" [href]="doNotAppend ? imdbid : 'https://imdb.com/title/' + imdbId"
target="_blank">
<i matTooltip="Imdb" class="fa fa-imdb fa-2x grow-social"></i>
</a>
<a *ngIf="twitter" class="media-icons"
href="https://twitter.com/{{twitter}}" target="_blank">
[href]="doNotAppend ? twitter : 'https://twitter.com/' + twitter" target="_blank">
<i matTooltip="Twitter" class="fa fa-twitter fa-2x grow-social"></i>
</a>
<a *ngIf="facebook" class="media-icons"
href="https://facebook.com/{{facebook}}" target="_blank">
[href]="doNotAppend ? facebook : 'https://facebook.com/' + facebook" target="_blank">
<i matTooltip="Facebook" class="fa fa-facebook fa-2x grow-social"></i>
</a> <a *ngIf="instagram" class="media-icons"
href="https://instagram.com/{{instagram}}" target="_blank">
[href]="doNotAppend ? instagram : 'https://instagram.com/' + instagram" target="_blank">
<i matTooltip="Instagram" class="fa fa-instagram fa-2x grow-social"></i>
</a>

@ -18,6 +18,7 @@ export class SocialIconsComponent {
@Input() available: boolean;
@Input() plexUrl: string;
@Input() embyUrl: string;
@Input() doNotAppend: boolean;
@Output() openTrailer: EventEmitter<any> = new EventEmitter();

@ -1,4 +1,5 @@
import { Component, Inject, Input } from "@angular/core";
import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
@Component({
selector: "top-banner",
@ -11,5 +12,11 @@ export class TopBannerComponent {
@Input() tagline: string;
@Input() available: boolean;
@Input() background: any;
constructor(private sanitizer:DomSanitizer){}
public getBackgroundImage(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle(this.background);
}
}

Loading…
Cancel
Save