More on the issues, we can now work through the issues flow

This commit is contained in:
Jamie Rees 2020-05-15 22:39:47 +01:00
commit cdfe91e3a4
14 changed files with 449 additions and 275 deletions

View file

@ -1,44 +1,40 @@
<div *ngIf="!artist" class="justify-content-md-center top-spacing loading-spinner"> <div *ngIf="!artist" class="justify-content-md-center top-spacing loading-spinner">
<mat-spinner [color]="'accent'"></mat-spinner> <mat-spinner [color]="'accent'"></mat-spinner>
</div> </div>
<div *ngIf="artist" class="dark-theme"> <div *ngIf="artist" class="dark-theme">
<top-banner [title]="artist.name" [background]="getBackground()" [tagline]="artist.disambiguation"></top-banner> <top-banner [title]="artist.name" [background]="getBackground()" [tagline]="artist.disambiguation"></top-banner>
<section id="info-wrapper"> <section id="info-wrapper">
<div class="small-middle-container"> <div class="small-middle-container">
<div class="row"> <div class="row">
<media-poster [posterPath]="artist.poster"></media-poster> <media-poster [posterPath]="artist.poster"></media-poster>
<!--Next to poster--> <!--Next to poster-->
<div class="col-12 col-lg-3 col-xl-3 media-row"> <div class="col-12 col-lg-3 col-xl-3 media-row">
<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>
[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>
<div class="col-12 col-lg-6 col-xl-6 media-row"> <div class="col-12 col-lg-6 col-xl-6 media-row">
<button mat-raised-button *ngIf="selectedAlbums.length === 0" class="btn-spacing" color="primary" (click)="requestAllAlbums()"> <button mat-raised-button *ngIf="selectedAlbums.length === 0" class="btn-spacing" color="primary" (click)="requestAllAlbums()">
<i class="fa fa-plus"></i> {{ 'MediaDetails.RequestAllAlbums' | translate }}</button> <i class="fa fa-plus"></i> {{ 'MediaDetails.RequestAllAlbums' | translate }}</button>
<button mat-raised-button *ngIf="selectedAlbums.length > 0" class="btn-spacing" color="primary" (click)="requestAllAlbums()"> <button mat-raised-button *ngIf="selectedAlbums.length > 0" class="btn-spacing" color="primary" (click)="requestAllAlbums()">
<i class="fa fa-plus"></i> {{ 'MediaDetails.RequestSelectedAlbums' | translate }}</button> <i class="fa fa-plus"></i> {{ 'MediaDetails.RequestSelectedAlbums' | translate }}</button>
<button mat-raised-button *ngIf="selectedAlbums.length > 0" class="btn-spacing" color="accent" (click)="clearSelection()"> <button mat-raised-button *ngIf="selectedAlbums.length > 0" class="btn-spacing" color="accent" (click)="clearSelection()">
<i class="fa fa-minus"></i> {{ 'MediaDetails.ClearSelection' | translate }}</button> <i class="fa fa-minus"></i> {{ 'MediaDetails.ClearSelection' | translate }}</button>
<!-- <button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
<!-- <button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
'Common.Available' | translate }}</button> --> 'Common.Available' | translate }}</button> -->
<!-- <span *ngIf="!movie.available"> <!-- <span *ngIf="!movie.available">
<span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span> <span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span>
<ng-template #requestedBtn> <ng-template #requestedBtn>
@ -54,7 +50,7 @@
'Common.Request' | translate }}</button> 'Common.Request' | translate }}</button>
</ng-template> </ng-template>
</span> --> </span> -->
<!-- <span *ngIf="isAdmin && hasRequest"> <!-- <span *ngIf="isAdmin && hasRequest">
<button (click)="approve()" mat-raised-button class="btn-spacing" color="accent"> <button (click)="approve()" mat-raised-button class="btn-spacing" color="accent">
<i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }} <i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}
</button> </button>
@ -73,7 +69,7 @@
'MediaDetails.Denied' | translate }}</button> '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()"> color="danger" (click)="issue()">
<i class="fa fa-exclamation"></i> {{ <i class="fa fa-exclamation"></i> {{
'Requests.ReportIssue' | translate }}</button> --> 'Requests.ReportIssue' | translate }}</button> -->
@ -81,41 +77,50 @@
</div> </div>
</div>
<div class="row">
<div class="col-12 col-md-2">
<mat-card class="mat-elevation-z8">
<mat-card-content class="medium-font">
<artist-information-panel [artist]="artist"></artist-information-panel>
</mat-card-content>
</mat-card>
</div>
<div class="col-12 col-md-10">
<div class="row">
<div class="col-12">
<mat-card class=" mat-elevation-z8 spacing-below">
<mat-card-content>
{{artist.overview}}
</mat-card-content>
</mat-card>
</div> </div>
</div>
<div class="row"> <div class="row">
<div class="col-12">
<artist-release-panel (onAlbumSelect)="albumSelected($event)"
(albumLoad)="albumLoad($event)" *ngIf="artist.releaseGroups.length > 0" [releases]="artist.releaseGroups"></artist-release-panel>
</div>
</div>
<!-- <div class="row"> <div class="col-12 col-md-2">
<mat-card class="mat-elevation-z8">
<mat-card-content class="medium-font">
<artist-information-panel [artist]="artist"></artist-information-panel>
</mat-card-content>
</mat-card>
</div>
<div class="col-12 col-md-10">
<div class="row">
<div class="col-12">
<mat-card class=" mat-elevation-z8 spacing-below">
<mat-card-content>
{{artist.overview}}
</mat-card-content>
</mat-card>
</div>
</div>
<div class="row">
<div class="col-12">
<artist-release-panel (onAlbumSelect)="albumSelected($event)" (albumLoad)="albumLoad($event)" *ngIf="artist.releaseGroups.length > 0" [releases]="artist.releaseGroups"></artist-release-panel>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="issuesPanel" *ngIf="artist.requestId">
<issues-panel [requestId]="artist.requestId" [isAdmin]="isAdmin"></issues-panel>
</div>
</div>
</div>
<!-- <div class="row">
<div class="col-12"> <div class="col-12">
<mat-accordion class="mat-elevation-z8 spacing-below"> <mat-accordion class="mat-elevation-z8 spacing-below">
<mat-expansion-panel> <mat-expansion-panel>
@ -186,20 +191,20 @@
</div>
</div>
</div> </div>
</div>
</div> <div class="bottom-page-gap">
</div>
</section>
<div class="bottom-page-gap">
</div>
</section>

View file

@ -11,12 +11,13 @@ import { DenyDialogComponent } from "./shared/deny-dialog/deny-dialog.component"
import { TvRequestsPanelComponent } from "./tv/panels/tv-requests/tv-requests-panel.component"; import { TvRequestsPanelComponent } from "./tv/panels/tv-requests/tv-requests-panel.component";
import { MovieAdminPanelComponent } from "./movie/panels/movie-admin-panel/movie-admin-panel.component"; import { MovieAdminPanelComponent } from "./movie/panels/movie-admin-panel/movie-admin-panel.component";
import { MovieAdvancedOptionsComponent } from "./movie/panels/movie-advanced-options/movie-advanced-options.component"; import { MovieAdvancedOptionsComponent } from "./movie/panels/movie-advanced-options/movie-advanced-options.component";
import { SearchService, RequestService, RadarrService } from "../../services"; import { SearchService, RequestService, RadarrService, IssuesService } from "../../services";
import { RequestServiceV2 } from "../../services/requestV2.service"; import { RequestServiceV2 } from "../../services/requestV2.service";
import { NewIssueComponent } from "./shared/new-issue/new-issue.component"; import { NewIssueComponent } from "./shared/new-issue/new-issue.component";
import { ArtistDetailsComponent } from "./artist/artist-details.component"; import { ArtistDetailsComponent } from "./artist/artist-details.component";
import { ArtistInformationPanel } from "./artist/panels/artist-information-panel/artist-information-panel.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 { ArtistReleasePanel } from "./artist/panels/artist-release-panel/artist-release-panel.component";
import { IssuesPanelComponent } from "./shared/issues-panel/issues-panel.component";
export const components: any[] = [ export const components: any[] = [
MovieDetailsComponent, MovieDetailsComponent,
@ -36,6 +37,7 @@ export const components: any[] = [
ArtistDetailsComponent, ArtistDetailsComponent,
ArtistInformationPanel, ArtistInformationPanel,
ArtistReleasePanel, ArtistReleasePanel,
IssuesPanelComponent,
]; ];
export const entryComponents: any[] = [ export const entryComponents: any[] = [
@ -50,4 +52,5 @@ export const providers: any[] = [
RequestService, RequestService,
RadarrService, RadarrService,
RequestServiceV2, RequestServiceV2,
IssuesService,
]; ];

View file

@ -16,8 +16,8 @@
<!--Next to poster--> <!--Next to poster-->
<div class="col-12 col-lg-3 col-xl-3 media-row"> <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" <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"
[available]="movie.available" [plexUrl]="movie.plexUrl" [embyUrl]="movie.embyUrl"></social-icons> [instagram]="movie.externalIds.instagramId" [available]="movie.available" [plexUrl]="movie.plexUrl" [embyUrl]="movie.embyUrl"></social-icons>
</div> </div>
@ -109,7 +109,11 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<mat-accordion class="mat-elevation-z8 spacing-below"> <div class="issuesPanel" *ngIf="movie.requestId">
<issues-panel [requestId]="movie.requestId" [isAdmin]="isAdmin"></issues-panel>
</div>
<mat-accordion class=" mat-elevation-z8 spacing-below ">
<mat-expansion-panel> <mat-expansion-panel>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title> <mat-panel-title>
@ -117,7 +121,7 @@
</mat-panel-title> </mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div class="row card-spacer" *ngIf="movie.recommendations?.results?.length > 0"> <div class="row card-spacer " *ngIf="movie.recommendations?.results?.length> 0">
<div class="col-md-2" *ngFor="let r of movie.recommendations?.results"> <div class="col-md-2" *ngFor="let r of movie.recommendations?.results">
<div class="sidebar affixable affix-top preview-poster"> <div class="sidebar affixable affix-top preview-poster">

View file

@ -0,0 +1,63 @@
<mat-accordion *ngIf="issuesCount > 0">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{'Issues.Title' | translate}}
</mat-panel-title>
<mat-panel-description>
<span *ngIf="isOutstanding">{{issuesCount}} </span><span><mat-icon *ngIf="isOutstanding" matTooltip="{{'Issues.Outstanding' | translate}}">error_outline</mat-icon></span>
<span *ngIf="!isOutstanding">{{issuesCount}}</span>
</mat-panel-description>
</mat-expansion-panel-header>
<!-- content start -->
<mat-accordion class="mat-elevation-z8">
<mat-expansion-panel *ngFor="let issue of issues">
<mat-expansion-panel-header>
<mat-panel-title>
{{ 'Issues.Subject' | translate}}: {{issue.subject}}
</mat-panel-title>
<mat-panel-description>
{{ 'Issues.ReportedBy' | translate}}: {{issue.userReported.userAlias}}
</mat-panel-description>
<mat-panel-description>
{{'Issues.Category' | translate}}: {{issue.issueCategory.value}}
</mat-panel-description>
</mat-expansion-panel-header>
<div class="row">
<div class="col">
{{'Issues.Description' | translate}}: {{issue.description}}
</div>
<div class="col">
{{'Issues.Status' | translate}}: {{IssueStatus[issue.status] | humanize}}
</div>
<div class="col" *ngIf="issue.resolvedDate">
{{'Issues.ResolvedDate' | translate}}: {{issue.resolvedDate}}
</div>
<div class="col" *ngIf="issue.createdDate">
{{'Issues.CreatedDate' | translate}}: {{issue.createdDate}}
</div>
</div>
<div *ngIf="isAdmin" class="row action-buttons">
<div class="button-padding">
<button *ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress" mat-raised-button color="accent" (click)="resolve(issue)"> {{ 'Issues.MarkResolved' | translate }}</button>
</div>
<div class="button-padding">
<button *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress" mat-raised-button color="accent" (click)="inProgress(issue)"> {{ 'Issues.MarkInProgress' | translate }}</button>
</div>
<div class="button-padding">
<button mat-raised-button color="warn" (click)="delete(issue)"> {{ 'Issues.Delete' | translate }}</button>
</div>
</div>
</mat-expansion-panel>
</mat-accordion>
<!-- content end -->
</mat-expansion-panel>
</mat-accordion>

View file

@ -0,0 +1,7 @@
.action-buttons {
padding-top: 1%;
}
.button-padding {
padding: 1%;
}

View file

@ -0,0 +1,63 @@
import { Component, Input, OnInit } from "@angular/core";
import { IssuesService, NotificationService, SettingsService } from "../../../../services";
import { RequestType, IIssues, IssueStatus, IIssueSettings } from "../../../../interfaces";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "issues-panel",
templateUrl: "./issues-panel.component.html",
styleUrls: ["./issues-panel.component.scss"]
})
export class IssuesPanelComponent implements OnInit {
@Input() public requestId: number;
@Input() public isAdmin: boolean;
public issuesCount: number;
public issues: IIssues[];
public IssueStatus = IssueStatus;
public isOutstanding: boolean;
public loadingFlag: boolean;
public settings: IIssueSettings;
constructor(private issuesService: IssuesService, private notificationService: NotificationService,
private translateService: TranslateService, private settingsService: SettingsService) {
}
public async ngOnInit() {
this.issues = await this.issuesService.getIssuesByRequestId(this.requestId);
this.issuesCount = this.issues.length;
this.calculateOutstanding();
this.settings = await this.settingsService.getIssueSettings().toPromise();
}
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;
this.calculateOutstanding();
});
}
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.issues = this.issues.filter((el) => { return el.id !== issue.id; });
this.issuesCount = this.issues.length;
this.calculateOutstanding();
}
private calculateOutstanding() {
this.isOutstanding = this.issues.some((i) => {
return i.status !== IssueStatus.Resolved;
});
}
}

View file

@ -1,29 +1,27 @@
<h1 mat-dialog-title>{{ 'Issues.IssueDialog.Title' | translate}}</h1> <h1 mat-dialog-title>{{ 'Issues.IssueDialog.Title' | translate}}</h1>
<div mat-dialog-content> <div mat-dialog-content>
<div class="col-12"> <div class="col-12">
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'Issues.IssueDialog.SelectCategory' | translate}}</mat-label> <mat-label>{{'Issues.IssueDialog.SelectCategory' | translate}}</mat-label>
<mat-select [(ngModel)]="issue.issueCategoryId"> <mat-select [(ngModel)]="issue.issueCategoryId">
<mat-option *ngFor="let cat of issueCategories" [value]="cat.id"> <mat-option *ngFor="let cat of issueCategories" [value]="cat.id">
{{cat.value}} {{cat.value}}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput placeholder="{{ 'Issues.IssueDialog.TitlePlaceholder' | translate}}" [(ngModel)]="issue.subject"> <input matInput placeholder="{{ 'Issues.IssueDialog.TitlePlaceholder' | translate}}" [(ngModel)]="issue.subject">
</mat-form-field> </mat-form-field>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<textarea matInput placeholder="{{ 'Issues.IssueDialog.DescriptionPlaceholder' | translate}}" <textarea matInput placeholder="{{ 'Issues.IssueDialog.DescriptionPlaceholder' | translate}}" [(ngModel)]="issue.description"></textarea>
[(ngModel)]="issue.description"></textarea> </mat-form-field>
</mat-form-field> </div>
</div>
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>
<button mat-button (click)="onNoClick()">{{ 'Common.Cancel' | translate}}</button> <button mat-button (click)="onNoClick()">{{ 'Common.Cancel' | translate}}</button>
<button mat-button (click)="createIssue()" [mat-dialog-close]="data" <button mat-button [disabled]="issue.subject.length <= 0 || !issue.issueCategoryId || issue.description.length <= 0" (click)="createIssue()" [mat-dialog-close]="data" cdkFocusInitial>{{ 'Common.Submit' | translate}}</button>
cdkFocusInitial>{{ 'Common.Submit' | translate}}</button>
</div> </div>

View file

@ -41,7 +41,6 @@ export class NewIssueComponent implements OnInit {
this.issueCategories = await this.issueService.getCategories().toPromise(); this.issueCategories = await this.issueService.getCategories().toPromise();
} }
public async createIssue() { public async createIssue() {
const result = await this.issueService.createIssue(this.issue).toPromise(); const result = await this.issueService.createIssue(this.issue).toPromise();
if(result) { if(result) {

View file

@ -1,105 +1,110 @@
<div *ngIf="!tv" class="justify-content-md-center top-spacing loading-spinner"> <div *ngIf="!tv" class="justify-content-md-center top-spacing loading-spinner">
<mat-spinner [color]="'accent'"></mat-spinner> <mat-spinner [color]="'accent'"></mat-spinner>
</div> </div>
<div *ngIf="tv"> <div *ngIf="tv">
<top-banner [background]="tv.background" [available]="tv.available" [title]="tv.title" [releaseDate]="tv.firstAired" <top-banner [background]="tv.background" [available]="tv.available" [title]="tv.title" [releaseDate]="tv.firstAired" [tagline]="tv.certification"></top-banner>
[tagline]="tv.certification"></top-banner>
<section id="info-wrapper"> <section id="info-wrapper">
<div class="small-middle-container"> <div class="small-middle-container">
<div class="row"> <div class="row">
<media-poster [posterPath]="tv.images.medium"></media-poster> <media-poster [posterPath]="tv.images.medium"></media-poster>
<!--Next to poster--> <!--Next to poster-->
<div class="col-12 col-lg-3 col-xl-3 media-row"> <div class="col-12 col-lg-3 col-xl-3 media-row">
<social-icons [homepage]="tv.homepage" [tvdbId]="tv.id" [hasTrailer]="tv.trailer" (openTrailer)="openDialog()" <social-icons [homepage]="tv.homepage" [tvdbId]="tv.id" [hasTrailer]="tv.trailer" (openTrailer)="openDialog()" [imdbId]="tv.imdbId" [available]="tv.available" [plexUrl]="tv.plexUrl" [embyUrl]="tv.embyUrl">
[imdbId]="tv.imdbId" [available]="tv.available" [plexUrl]="tv.plexUrl" [embyUrl]="tv.embyUrl"> </social-icons>
</social-icons>
</div> </div>
<div class="col-12 col-lg-6 col-xl-6 media-row"> <div class="col-12 col-lg-6 col-xl-6 media-row">
<button *ngIf="!tv.fullyAvailable" mat-raised-button class="btn-spacing" color="primary" <button *ngIf="!tv.fullyAvailable" mat-raised-button class="btn-spacing" color="primary" (click)="request()"><i class="fa fa-plus"></i>
(click)="request()"><i class="fa fa-plus"></i>
{{ 'Common.Request' | translate }}</button> {{ 'Common.Request' | translate }}</button>
<button *ngIf="tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" [disabled]> <button *ngIf="tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" [disabled]>
<i class="fa fa-check"></i> {{'Common.Available' | translate }}</button> <i class="fa fa-check"></i> {{'Common.Available' | translate }}</button>
<button *ngIf="tv.partlyAvailable && !tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" <button *ngIf="tv.partlyAvailable && !tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" [disabled]>
[disabled]>
<i class="fa fa-check"></i> {{'Common.PartiallyAvailable' | translate }}</button> <i class="fa fa-check"></i> {{'Common.PartiallyAvailable' | translate }}</button>
</div>
</div>
<div class="row"> <button *ngIf="(tvRequest)" mat-raised-button class="btn-spacing" color="danger" (click)="issue()">
<div class="col-12 col-md-2"> <i class="fa fa-exclamation"></i> {{
'Requests.ReportIssue' | translate }}</button>
<mat-card class="mat-elevation-z8"> </div>
<mat-card-content class="medium-font">
<tv-information-panel [tv]="tv"></tv-information-panel>
</mat-card-content>
</mat-card>
</div>
<div class="col-12 col-md-10">
<div class="row">
<div class="col-12">
<mat-card class="mat-elevation-z8 spacing-below">
<mat-card-content>
{{tv.overview}}
</mat-card-content>
</mat-card>
</div>
<div class="col-12">
<cast-carousel [cast]="tv.cast"></cast-carousel>
</div> </div>
</div> <div class="row">
</div> <div class="col-12 col-md-2">
</div>
<mat-card class="mat-elevation-z8">
<mat-card-content class="medium-font">
<tv-information-panel [tv]="tv"></tv-information-panel>
</mat-card-content>
</mat-card>
</div>
<div class="row"> <div class="col-12 col-md-10">
<div class="col-12 col-md-2"> <div class="row">
<div class="col-12">
<mat-card class="mat-elevation-z8 spacing-below">
<mat-card-content>
{{tv.overview}}
</mat-card-content>
</mat-card>
</div>
<div class="col-12">
<cast-carousel [cast]="tv.cast"></cast-carousel>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-2">
<!--Just some space yo-->
</div>
<div class="col-12 col-md-10" *ngIf="tvRequest">
<div class="issuesPanel">
<issues-panel [requestId]="tv.requestId" [isAdmin]="isAdmin"></issues-panel>
</div>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Requests
</mat-panel-title>
</mat-expansion-panel-header>
<tv-requests-panel [tvRequest]="tvRequest" [isAdmin]="isAdmin"></tv-requests-panel>
</mat-expansion-panel>
</mat-accordion>
</div>
</div>
<!--Just some space yo-->
</div> </div>
<div class="col-12 col-md-10" *ngIf="tvRequest">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Requests
</mat-panel-title>
</mat-expansion-panel-header>
<tv-requests-panel [tvRequest]="tvRequest" [isAdmin]="isAdmin"></tv-requests-panel>
</mat-expansion-panel>
</mat-accordion>
<div class="bottom-page-gap">
</div> </div>
</section>
</div>
</div>
<div class="bottom-page-gap">
</div>
</section>
</div> </div>

View file

@ -6,8 +6,9 @@ import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2";
import { MatDialog } from "@angular/material"; import { MatDialog } from "@angular/material";
import { YoutubeTrailerComponent } from "../shared/youtube-trailer.component"; import { YoutubeTrailerComponent } from "../shared/youtube-trailer.component";
import { EpisodeRequestComponent } from "../../../shared/episode-request/episode-request.component"; import { EpisodeRequestComponent } from "../../../shared/episode-request/episode-request.component";
import { IChildRequests } from "../../../interfaces"; import { IChildRequests, RequestType } from "../../../interfaces";
import { AuthService } from "../../../auth/auth.service"; import { AuthService } from "../../../auth/auth.service";
import { NewIssueComponent } from "../shared/new-issue/new-issue.component";
@Component({ @Component({
templateUrl: "./tv-details.component.html", templateUrl: "./tv-details.component.html",
@ -59,6 +60,13 @@ export class TvDetailsComponent implements OnInit {
this.dialog.open(EpisodeRequestComponent, { width: "800px", data: this.tv, panelClass: 'modal-panel' }) this.dialog.open(EpisodeRequestComponent, { width: "800px", data: this.tv, panelClass: 'modal-panel' })
} }
public async issue() {
const dialogRef = this.dialog.open(NewIssueComponent, {
width: '500px',
data: {requestId: this.tvRequest ? this.tv.requestId : null, requestType: RequestType.tvShow, imdbid: this.tv.theTvDbId, title: this.tv.title}
});
}
public openDialog() { public openDialog() {
debugger; debugger;
let trailerLink = this.tv.trailer; let trailerLink = this.tv.trailer;

View file

@ -1,30 +1,26 @@
@import "~@angular/material/theming"; @import "~@angular/material/theming";
@import "~styles/variables.scss"; @import "~styles/variables.scss";
//MINE //MINE
@media (max-width: 570px) { @media (max-width: 570px) {
h1 { h1 {
font-size: 1.5rem; font-size: 1.5rem;
} }
.mobile-poster {
.mobile-poster { display: block;
display: block; position: absolute;
position: absolute; width: 70px;
width: 70px; left: 12px;
left: 12px; bottom: 2px;
bottom: 2px; }
} #info-wrapper .sidebar-poster {
margin-top: -126px !important;
}
#info-wrapper .sidebar-poster {
margin-top: -126px !important;
}
} }
@media (max-width: 767px) { @media (max-width: 767px) {
#summary-wrapper { #summary-wrapper {
height: 350px !important; height: 350px !important;
} }
} }
#summary-wrapper .full-screenshot, #summary-wrapper .full-screenshot,
@ -32,190 +28,190 @@
#watching-wrapper .full-screenshot, #watching-wrapper .full-screenshot,
.hero-wrapper .full-screenshot, .hero-wrapper .full-screenshot,
#statics-top-wrapper .full-screenshot { #statics-top-wrapper .full-screenshot {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
background-position: 50% 10%; background-position: 50% 10%;
opacity: 0; opacity: 0;
transition: all 1s; transition: all 1s;
} }
#summary-wrapper, #summary-wrapper,
.summary-wrapper { .summary-wrapper {
background-color: #000; background-color: #000;
background-size: cover; background-size: cover;
background-position: 50% 10%; background-position: 50% 10%;
transition: all .5s; transition: all .5s;
height: 450px; height: 450px;
color: #fff; color: #fff;
position: relative; position: relative;
} }
#summary-wrapper .full-screenshot.enabled, #summary-wrapper .full-screenshot.enabled,
.summary-wrapper .full-screenshot.enabled, .summary-wrapper .full-screenshot.enabled,
#watching-wrapper .full-screenshot.enabled, #watching-wrapper .full-screenshot.enabled,
.hero-wrapper .full-screenshot.enabled, .hero-wrapper .full-screenshot.enabled,
#statics-top-wrapper .full-screenshot.enabled { #statics-top-wrapper .full-screenshot.enabled {
opacity: 1; opacity: 1;
} }
#summary-wrapper .shadow-base, #summary-wrapper .shadow-base,
.summary-wrapper .shadow-base { .summary-wrapper .shadow-base {
bottom: 0; bottom: 0;
background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%);
background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%); background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.shadow-base { .shadow-base {
height: 75px; height: 75px;
width: 100%; width: 100%;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%); background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0); // filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0);
} }
.available-bottom-border { .available-bottom-border {
border-bottom: solid 8px #1DE9B6; border-bottom: solid 8px #1DE9B6;
} }
#summary-wrapper .summary .container, #summary-wrapper .summary .container,
.summary-wrapper .summary .container { .summary-wrapper .summary .container {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
} }
#summary-wrapper, #summary-wrapper,
.summary-wrapper { .summary-wrapper {
background-color: #000; background-color: #000;
background-size: cover; background-size: cover;
background-position: 50% 10%; background-position: 50% 10%;
transition: all .5s; transition: all .5s;
height: 550px; height: 550px;
color: #fff; color: #fff;
position: relative; position: relative;
} }
.grey-text { .grey-text {
color: #999; color: #999;
} }
#summary-wrapper .summary .container h1, #summary-wrapper .summary .container h1,
.summary-wrapper .summary .container h1 { .summary-wrapper .summary .container h1 {
margin: 0; margin: 0;
text-shadow: 1px 1px 5px #000; text-shadow: 1px 1px 5px #000;
line-height: 1.2; line-height: 1.2;
} }
#info-wrapper { #info-wrapper {
min-height: 600px; min-height: 600px;
} }
#info-wrapper .sidebar.affixable.affix-top { #info-wrapper .sidebar.affixable.affix-top {
position: relative !important; position: relative !important;
} }
#info-wrapper .sidebar-poster { #info-wrapper .sidebar-poster {
margin-top: -280px; margin-top: -280px;
width: 250px; width: 250px;
} }
#info-wrapper .sidebar .poster { #info-wrapper .sidebar .poster {
border: solid 3px #fff; border: solid 3px #fff;
position: relative; position: relative;
-webkit-box-shadow: 0 0 20px 0 #666; -webkit-box-shadow: 0 0 20px 0 #666;
box-shadow: 0 0 20px 0 #666; box-shadow: 0 0 20px 0 #666;
} }
#info-wrapper .sidebar .poster img { #info-wrapper .sidebar .poster img {
width: 100%; width: 100%;
} }
.full-width { .full-width {
width: 100%; width: 100%;
} }
#info-wrapper .sidebar .poster .real { #info-wrapper .sidebar .poster .real {
height: 100%; height: 100%;
top: 0; top: 0;
left: 0; left: 0;
} }
.card-spacer { .card-spacer {
padding-top: 1%; padding-top: 1%;
} }
.card-full { .card-full {
height: 100%; height: 100%;
} }
.imdb-color { .imdb-color {
color: black; color: black;
background-color: #f5de50; background-color: #f5de50;
} }
.btn-spacing { .btn-spacing {
margin-right: 10px !important; margin-right: 10px !important;
} }
.spacing-below { .spacing-below {
margin-bottom: 15px !important; margin-bottom: 15px !important;
} }
.left-seperator { .left-seperator {
margin-left: 40px; margin-left: 40px;
} }
.tagline { .tagline {
margin-top: 10px; margin-top: 10px;
margin-left: 10px; margin-left: 10px;
text-shadow: 1px 1px 5px #000; text-shadow: 1px 1px 5px #000;
} }
.preview-poster { .preview-poster {
width: 173px; width: 173px;
} }
.media-icons { .media-icons {
color: mat-color($ombi-app-primary) !important; color: mat-color($ombi-app-primary) !important;
padding: 1%; padding: 1%;
} }
.media-row { .media-row {
padding-top: 2%; padding-top: 2%;
} }
.cast-profile-img { .cast-profile-img {
border-radius: 10%; border-radius: 10%;
width: 170px; width: 170px;
} }
.small-middle-container { .small-middle-container {
margin: auto; margin: auto;
width: 95%; width: 95%;
} }
.keywords-panel { .keywords-panel {
margin-top: 8%; margin-top: 8%;
} }
.medium-font { .medium-font {
font-size: 16px; font-size: 16px;
}
.issuesPanel {
padding-top: 1%;
padding-bottom: 1%;
} }

View file

@ -29,6 +29,10 @@ export class IssuesService extends ServiceHelpers {
return this.http.get<IIssues[]>(this.url, {headers: this.headers}); return this.http.get<IIssues[]>(this.url, {headers: this.headers});
} }
public getIssuesByRequestId(requestId: number): Promise<IIssues[]> {
return this.http.get<IIssues[]>(`${this.url}request/${requestId}`, {headers: this.headers}).toPromise();
}
public getIssuesPage(take: number, skip: number, status: IssueStatus): Observable<IIssues[]> { public getIssuesPage(take: number, skip: number, status: IssueStatus): Observable<IIssues[]> {
return this.http.get<IIssues[]>(`${this.url}${take}/${skip}/${status}`, {headers: this.headers}); return this.http.get<IIssues[]>(`${this.url}${take}/${skip}/${status}`, {headers: this.headers});
} }
@ -60,4 +64,8 @@ export class IssuesService extends ServiceHelpers {
public deleteComment(id: number): Observable<boolean> { public deleteComment(id: number): Observable<boolean> {
return this.http.delete<boolean>(`${this.url}comments/${id}`, { headers: this.headers }); return this.http.delete<boolean>(`${this.url}comments/${id}`, { headers: this.headers });
} }
public deleteIssue(id: number): Promise<boolean> {
return this.http.delete<boolean>(`${this.url}${id}`, { headers: this.headers }).toPromise();
}
} }

View file

@ -169,6 +169,14 @@ namespace Ombi.Controllers.V1
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
} }
[HttpGet("request/{id}")]
public async Task<IActionResult> GetIssueByRequestId([FromRoute] int id)
{
return new OkObjectResult(await _issues.GetAll().Where(x => x.RequestId == id)
.Include(x => x.IssueCategory)
.Include(x => x.UserReported).ToListAsync());
}
/// <summary> /// <summary>
/// Get's all the issue comments by id /// Get's all the issue comments by id
/// </summary> /// </summary>

View file

@ -188,7 +188,14 @@
"TitlePlaceholder": "Short title of your issue", "TitlePlaceholder": "Short title of your issue",
"SelectCategory": "Select Category", "SelectCategory": "Select Category",
"IssueCreated": "Issue has been created" "IssueCreated": "Issue has been created"
} },
"Outstanding": "There are outstanding issues",
"ResolvedDate": "Resolved date",
"CreatedDate": "Raised on",
"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"
}, },
"Filter": { "Filter": {
"ClearFilter": "Clear Filter", "ClearFilter": "Clear Filter",