mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-20 13:23:20 -07:00
More on the issues, we can now work through the issues flow
This commit is contained in:
parent
c787e58f3b
commit
cdfe91e3a4
14 changed files with 449 additions and 275 deletions
|
@ -1,44 +1,40 @@
|
|||
<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 *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">
|
||||
<div class="small-middle-container">
|
||||
<section id="info-wrapper">
|
||||
<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-->
|
||||
<div class="col-12 col-lg-3 col-xl-3 media-row">
|
||||
<!--Next to poster-->
|
||||
<div class="col-12 col-lg-3 col-xl-3 media-row">
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- <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> -->
|
||||
<!-- <span *ngIf="!movie.available">
|
||||
<!-- <span *ngIf="!movie.available">
|
||||
<span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span>
|
||||
|
||||
<ng-template #requestedBtn>
|
||||
|
@ -54,7 +50,7 @@
|
|||
'Common.Request' | translate }}</button>
|
||||
</ng-template>
|
||||
</span> -->
|
||||
<!-- <span *ngIf="isAdmin && hasRequest">
|
||||
<!-- <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>
|
||||
|
@ -73,7 +69,7 @@
|
|||
'MediaDetails.Denied' | translate }}</button>
|
||||
</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> -->
|
||||
|
@ -81,41 +77,50 @@
|
|||
|
||||
|
||||
|
||||
</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="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="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">
|
||||
<mat-accordion class="mat-elevation-z8 spacing-below">
|
||||
<mat-expansion-panel>
|
||||
|
@ -186,20 +191,20 @@
|
|||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="bottom-page-gap">
|
||||
</div>
|
||||
</section>
|
||||
<div class="bottom-page-gap">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 { MovieAdminPanelComponent } from "./movie/panels/movie-admin-panel/movie-admin-panel.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 { 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";
|
||||
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[] = [
|
||||
MovieDetailsComponent,
|
||||
|
@ -36,6 +37,7 @@ export const components: any[] = [
|
|||
ArtistDetailsComponent,
|
||||
ArtistInformationPanel,
|
||||
ArtistReleasePanel,
|
||||
IssuesPanelComponent,
|
||||
];
|
||||
|
||||
export const entryComponents: any[] = [
|
||||
|
@ -50,4 +52,5 @@ export const providers: any[] = [
|
|||
RequestService,
|
||||
RadarrService,
|
||||
RequestServiceV2,
|
||||
IssuesService,
|
||||
];
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<!--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]="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>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -109,7 +109,11 @@
|
|||
|
||||
<div class="row">
|
||||
<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-header>
|
||||
<mat-panel-title>
|
||||
|
@ -117,7 +121,7 @@
|
|||
</mat-panel-title>
|
||||
</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="sidebar affixable affix-top preview-poster">
|
||||
|
|
|
@ -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>
|
|
@ -0,0 +1,7 @@
|
|||
.action-buttons {
|
||||
padding-top: 1%;
|
||||
}
|
||||
|
||||
.button-padding {
|
||||
padding: 1%;
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,29 +1,27 @@
|
|||
<h1 mat-dialog-title>{{ 'Issues.IssueDialog.Title' | translate}}</h1>
|
||||
<div mat-dialog-content>
|
||||
|
||||
<div class="col-12">
|
||||
<mat-form-field class="col-12">
|
||||
<mat-label>{{'Issues.IssueDialog.SelectCategory' | translate}}</mat-label>
|
||||
<mat-select [(ngModel)]="issue.issueCategoryId">
|
||||
<mat-option *ngFor="let cat of issueCategories" [value]="cat.id">
|
||||
{{cat.value}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="col-12">
|
||||
<mat-form-field class="col-12">
|
||||
<mat-label>{{'Issues.IssueDialog.SelectCategory' | translate}}</mat-label>
|
||||
<mat-select [(ngModel)]="issue.issueCategoryId">
|
||||
<mat-option *ngFor="let cat of issueCategories" [value]="cat.id">
|
||||
{{cat.value}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="col-12">
|
||||
<input matInput placeholder="{{ 'Issues.IssueDialog.TitlePlaceholder' | translate}}" [(ngModel)]="issue.subject">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-12">
|
||||
<input matInput placeholder="{{ 'Issues.IssueDialog.TitlePlaceholder' | translate}}" [(ngModel)]="issue.subject">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="col-12">
|
||||
<textarea matInput placeholder="{{ 'Issues.IssueDialog.DescriptionPlaceholder' | translate}}"
|
||||
[(ngModel)]="issue.description"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-form-field class="col-12">
|
||||
<textarea matInput placeholder="{{ 'Issues.IssueDialog.DescriptionPlaceholder' | translate}}" [(ngModel)]="issue.description"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()">{{ 'Common.Cancel' | translate}}</button>
|
||||
<button mat-button (click)="createIssue()" [mat-dialog-close]="data"
|
||||
cdkFocusInitial>{{ 'Common.Submit' | translate}}</button>
|
||||
<button mat-button (click)="onNoClick()">{{ 'Common.Cancel' | translate}}</button>
|
||||
<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>
|
||||
</div>
|
|
@ -41,7 +41,6 @@ export class NewIssueComponent implements OnInit {
|
|||
this.issueCategories = await this.issueService.getCategories().toPromise();
|
||||
}
|
||||
|
||||
|
||||
public async createIssue() {
|
||||
const result = await this.issueService.createIssue(this.issue).toPromise();
|
||||
if(result) {
|
||||
|
|
|
@ -1,105 +1,110 @@
|
|||
<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 *ngIf="tv">
|
||||
|
||||
<top-banner [background]="tv.background" [available]="tv.available" [title]="tv.title" [releaseDate]="tv.firstAired"
|
||||
[tagline]="tv.certification"></top-banner>
|
||||
<top-banner [background]="tv.background" [available]="tv.available" [title]="tv.title" [releaseDate]="tv.firstAired" [tagline]="tv.certification"></top-banner>
|
||||
|
||||
<section id="info-wrapper">
|
||||
<div class="small-middle-container">
|
||||
<div class="row">
|
||||
<section id="info-wrapper">
|
||||
<div class="small-middle-container">
|
||||
<div class="row">
|
||||
|
||||
<media-poster [posterPath]="tv.images.medium"></media-poster>
|
||||
<media-poster [posterPath]="tv.images.medium"></media-poster>
|
||||
|
||||
<!--Next to poster-->
|
||||
<div class="col-12 col-lg-3 col-xl-3 media-row">
|
||||
<!--Next to poster-->
|
||||
<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()"
|
||||
[imdbId]="tv.imdbId" [available]="tv.available" [plexUrl]="tv.plexUrl" [embyUrl]="tv.embyUrl">
|
||||
</social-icons>
|
||||
<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">
|
||||
</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"
|
||||
(click)="request()"><i class="fa fa-plus"></i>
|
||||
<button *ngIf="!tv.fullyAvailable" mat-raised-button class="btn-spacing" color="primary" (click)="request()"><i class="fa fa-plus"></i>
|
||||
{{ '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>
|
||||
<button *ngIf="tv.partlyAvailable && !tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent"
|
||||
[disabled]>
|
||||
<button *ngIf="tv.partlyAvailable && !tv.fullyAvailable" mat-raised-button class="btn-spacing" color="accent" [disabled]>
|
||||
<i class="fa fa-check"></i> {{'Common.PartiallyAvailable' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-2">
|
||||
<button *ngIf="(tvRequest)" mat-raised-button class="btn-spacing" color="danger" (click)="issue()">
|
||||
<i class="fa fa-exclamation"></i> {{
|
||||
'Requests.ReportIssue' | translate }}</button>
|
||||
|
||||
<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="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>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-2">
|
||||
|
||||
<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-2">
|
||||
<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>
|
||||
|
||||
|
||||
<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 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>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="bottom-page-gap">
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</div>
|
|
@ -6,8 +6,9 @@ import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2";
|
|||
import { MatDialog } from "@angular/material";
|
||||
import { YoutubeTrailerComponent } from "../shared/youtube-trailer.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 { NewIssueComponent } from "../shared/new-issue/new-issue.component";
|
||||
|
||||
@Component({
|
||||
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' })
|
||||
}
|
||||
|
||||
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() {
|
||||
debugger;
|
||||
let trailerLink = this.tv.trailer;
|
||||
|
|
|
@ -1,30 +1,26 @@
|
|||
@import "~@angular/material/theming";
|
||||
@import "~styles/variables.scss";
|
||||
|
||||
//MINE
|
||||
@media (max-width: 570px) {
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.mobile-poster {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 70px;
|
||||
left: 12px;
|
||||
bottom: 2px;
|
||||
}
|
||||
|
||||
|
||||
#info-wrapper .sidebar-poster {
|
||||
margin-top: -126px !important;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.mobile-poster {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 70px;
|
||||
left: 12px;
|
||||
bottom: 2px;
|
||||
}
|
||||
#info-wrapper .sidebar-poster {
|
||||
margin-top: -126px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#summary-wrapper {
|
||||
height: 350px !important;
|
||||
}
|
||||
#summary-wrapper {
|
||||
height: 350px !important;
|
||||
}
|
||||
}
|
||||
|
||||
#summary-wrapper .full-screenshot,
|
||||
|
@ -32,190 +28,190 @@
|
|||
#watching-wrapper .full-screenshot,
|
||||
.hero-wrapper .full-screenshot,
|
||||
#statics-top-wrapper .full-screenshot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-position: 50% 10%;
|
||||
opacity: 0;
|
||||
transition: all 1s;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-position: 50% 10%;
|
||||
opacity: 0;
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
#summary-wrapper,
|
||||
.summary-wrapper {
|
||||
background-color: #000;
|
||||
background-size: cover;
|
||||
background-position: 50% 10%;
|
||||
transition: all .5s;
|
||||
height: 450px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
background-size: cover;
|
||||
background-position: 50% 10%;
|
||||
transition: all .5s;
|
||||
height: 450px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
#summary-wrapper .full-screenshot.enabled,
|
||||
.summary-wrapper .full-screenshot.enabled,
|
||||
#watching-wrapper .full-screenshot.enabled,
|
||||
.hero-wrapper .full-screenshot.enabled,
|
||||
#statics-top-wrapper .full-screenshot.enabled {
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#summary-wrapper .shadow-base,
|
||||
.summary-wrapper .shadow-base {
|
||||
bottom: 0;
|
||||
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: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%);
|
||||
background-repeat: repeat-x;
|
||||
bottom: 0;
|
||||
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: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.shadow-base {
|
||||
height: 75px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
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: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0);
|
||||
height: 75px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
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: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
|
||||
background-repeat: repeat-x;
|
||||
// filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0);
|
||||
}
|
||||
|
||||
.available-bottom-border {
|
||||
border-bottom: solid 8px #1DE9B6;
|
||||
border-bottom: solid 8px #1DE9B6;
|
||||
}
|
||||
|
||||
#summary-wrapper .summary .container,
|
||||
.summary-wrapper .summary .container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#summary-wrapper,
|
||||
.summary-wrapper {
|
||||
background-color: #000;
|
||||
background-size: cover;
|
||||
background-position: 50% 10%;
|
||||
transition: all .5s;
|
||||
height: 550px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
background-size: cover;
|
||||
background-position: 50% 10%;
|
||||
transition: all .5s;
|
||||
height: 550px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.grey-text {
|
||||
color: #999;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#summary-wrapper .summary .container h1,
|
||||
.summary-wrapper .summary .container h1 {
|
||||
margin: 0;
|
||||
text-shadow: 1px 1px 5px #000;
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
text-shadow: 1px 1px 5px #000;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
#info-wrapper {
|
||||
min-height: 600px;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
|
||||
#info-wrapper .sidebar.affixable.affix-top {
|
||||
position: relative !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
#info-wrapper .sidebar-poster {
|
||||
margin-top: -280px;
|
||||
width: 250px;
|
||||
margin-top: -280px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
#info-wrapper .sidebar .poster {
|
||||
border: solid 3px #fff;
|
||||
position: relative;
|
||||
-webkit-box-shadow: 0 0 20px 0 #666;
|
||||
box-shadow: 0 0 20px 0 #666;
|
||||
border: solid 3px #fff;
|
||||
position: relative;
|
||||
-webkit-box-shadow: 0 0 20px 0 #666;
|
||||
box-shadow: 0 0 20px 0 #666;
|
||||
}
|
||||
|
||||
#info-wrapper .sidebar .poster img {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info-wrapper .sidebar .poster .real {
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.card-spacer {
|
||||
padding-top: 1%;
|
||||
padding-top: 1%;
|
||||
}
|
||||
|
||||
.card-full {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.imdb-color {
|
||||
color: black;
|
||||
background-color: #f5de50;
|
||||
color: black;
|
||||
background-color: #f5de50;
|
||||
}
|
||||
|
||||
.btn-spacing {
|
||||
margin-right: 10px !important;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
.spacing-below {
|
||||
margin-bottom: 15px !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.left-seperator {
|
||||
margin-left: 40px;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
text-shadow: 1px 1px 5px #000;
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
text-shadow: 1px 1px 5px #000;
|
||||
}
|
||||
|
||||
.preview-poster {
|
||||
width: 173px;
|
||||
width: 173px;
|
||||
}
|
||||
|
||||
.media-icons {
|
||||
color: mat-color($ombi-app-primary) !important;
|
||||
padding: 1%;
|
||||
color: mat-color($ombi-app-primary) !important;
|
||||
padding: 1%;
|
||||
}
|
||||
|
||||
.media-row {
|
||||
padding-top: 2%;
|
||||
padding-top: 2%;
|
||||
}
|
||||
|
||||
.cast-profile-img {
|
||||
border-radius: 10%;
|
||||
width: 170px;
|
||||
border-radius: 10%;
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.small-middle-container {
|
||||
margin: auto;
|
||||
width: 95%;
|
||||
margin: auto;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.keywords-panel {
|
||||
margin-top: 8%;
|
||||
margin-top: 8%;
|
||||
}
|
||||
|
||||
.medium-font {
|
||||
font-size: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.issuesPanel {
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
|
@ -29,6 +29,10 @@ export class IssuesService extends ServiceHelpers {
|
|||
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[]> {
|
||||
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> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,6 +169,14 @@ namespace Ombi.Controllers.V1
|
|||
.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>
|
||||
/// Get's all the issue comments by id
|
||||
/// </summary>
|
||||
|
|
|
@ -188,7 +188,14 @@
|
|||
"TitlePlaceholder": "Short title of your issue",
|
||||
"SelectCategory": "Select Category",
|
||||
"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": {
|
||||
"ClearFilter": "Clear Filter",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue