mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-22 06:13:22 -07:00
changes
This commit is contained in:
parent
178cf03a5e
commit
75e4f2517b
31 changed files with 2460 additions and 2135 deletions
|
@ -1,70 +1,71 @@
|
|||
{
|
||||
"name": "ombi",
|
||||
"version": "3.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --port 3578 --configuration hmr",
|
||||
"build": "node --max_old_space_size=6144 node_modules/@angular/cli/bin/ng build -c production",
|
||||
"lint": "ng lint",
|
||||
"docs:json": "compodoc -p ./tsconfig.json -e json -d .",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"chromatic": "chromatic --exit-zero-on-changes",
|
||||
"storybookbuild": "yarn build-storybook"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^16.2.12",
|
||||
"@angular/cdk": "^14.2.7",
|
||||
"@angular/common": "^16.2.12",
|
||||
"@angular/compiler": "^16.2.12",
|
||||
"@angular/core": "^16.2.12",
|
||||
"@angular/forms": "^16.2.12",
|
||||
"@angular/material": "^14.2.7",
|
||||
"@angular/platform-browser": "^16.2.12",
|
||||
"@angular/platform-browser-dynamic": "^16.2.12",
|
||||
"@angular/platform-server": "^16.2.12",
|
||||
"@angular/router": "^16.2.12",
|
||||
"@angularclass/hmr": "^3.0.0",
|
||||
"@auth0/angular-jwt": "^5.0.2",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@microsoft/signalr": "^6.0.23",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"@ngxs/devtools-plugin": "3.8.1",
|
||||
"@ngxs/store": "3.8.1",
|
||||
"@types/jquery": "^3.5.23",
|
||||
"@yellowspot/ng-truncate": "^2.0.0",
|
||||
"angularx-qrcode": "^15.0.0",
|
||||
"bootstrap": "^4.2.1",
|
||||
"core-js": "^2.5.4",
|
||||
"jquery": "3.7.1",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.1",
|
||||
"ng2-cookies": "^1.0.12",
|
||||
"ngx-clipboard": "^12.1.0",
|
||||
"ngx-infinite-scroll": "^9.0.0",
|
||||
"ngx-moment": "^3.0.1",
|
||||
"ngx-order-pipe": "^2.2.0",
|
||||
"popper.js": "^1.14.3",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^15.4.1",
|
||||
"rxjs": "^7.5.4",
|
||||
"ts-md5": "^1.2.7",
|
||||
"zone.js": "~0.13.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.2.12",
|
||||
"@angular/cli": "^16.2.12",
|
||||
"@angular/compiler-cli": "^16.2.12",
|
||||
"@babel/core": "^7.18.9",
|
||||
"@compodoc/compodoc": "^1.1.19",
|
||||
"@storybook/angular": "^6.5.9",
|
||||
"chromatic": "^6.7.1",
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"protractor": "~5.4.0",
|
||||
"ts-node": "~5.0.1",
|
||||
"tslint": "^5.12.0"
|
||||
}
|
||||
"name": "ombi",
|
||||
"version": "4.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --port 3578 --configuration hmr",
|
||||
"build": "node --max_old_space_size=6144 node_modules/@angular/cli/bin/ng build -c production",
|
||||
"lint": "ng lint",
|
||||
"docs:json": "compodoc -p ./tsconfig.json -e json -d .",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"chromatic": "chromatic --exit-zero-on-changes",
|
||||
"storybookbuild": "yarn build-storybook"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^16.2.12",
|
||||
"@angular/cdk": "^14.2.7",
|
||||
"@angular/common": "^16.2.12",
|
||||
"@angular/compiler": "^16.2.12",
|
||||
"@angular/core": "^16.2.12",
|
||||
"@angular/forms": "^16.2.12",
|
||||
"@angular/material": "^14.2.7",
|
||||
"@angular/platform-browser": "^16.2.12",
|
||||
"@angular/platform-browser-dynamic": "^16.2.12",
|
||||
"@angular/platform-server": "^16.2.12",
|
||||
"@angular/router": "^16.2.12",
|
||||
"@angularclass/hmr": "^3.0.0",
|
||||
"@auth0/angular-jwt": "^5.0.2",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@microsoft/signalr": "^6.0.23",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"@ngxs/devtools-plugin": "3.8.1",
|
||||
"@ngxs/store": "3.8.1",
|
||||
"@types/jquery": "^3.5.23",
|
||||
"@yellowspot/ng-truncate": "^2.0.0",
|
||||
"angularx-qrcode": "^16.0.0",
|
||||
"bootstrap": "^4.2.1",
|
||||
"core-js": "^2.5.4",
|
||||
"date-fns": "2.30.0",
|
||||
"jquery": "3.7.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"ng2-cookies": "^1.0.12",
|
||||
"ngx-clipboard": "^16.0.0",
|
||||
"ngx-date-fns": "^11.0.0",
|
||||
"ngx-infinite-scroll": "^17.0.0",
|
||||
"popper.js": "^1.14.3",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^15.4.1",
|
||||
"rxjs": "^7.5.4",
|
||||
"ts-md5": "^1.2.7",
|
||||
"zone.js": "0.14.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.2.12",
|
||||
"@angular/cli": "^16.2.12",
|
||||
"@angular/compiler-cli": "^16.2.12",
|
||||
"@babel/core": "^7.18.9",
|
||||
"@compodoc/compodoc": "^1.1.19",
|
||||
"@storybook/angular": "^6.5.9",
|
||||
"@types/node": "^20.11.17",
|
||||
"chromatic": "^6.7.1",
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"protractor": "~5.4.0",
|
||||
"ts-node": "~5.0.1",
|
||||
"tslint": "^5.12.0"
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
<p id="detailed-request-requestedby-{{request.mediaId}}">{{'MediaDetails.RequestedBy' | translate}} {{request.username}}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<p id="detailed-request-date-{{request.mediaId}}">{{'MediaDetails.OnDate' | translate}} {{request.requestDate | amFromUtc | amLocal | amUserLocale | amDateFormat: 'l LT'}}</p>
|
||||
<p id="detailed-request-date-{{request.mediaId}}">{{'MediaDetails.OnDate' | translate}} {{request.requestDate | dfnsFormat: 'Ppp'}}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<p id="detailed-request-status-{{request.mediaId}}">{{'MediaDetails.Status' | translate}} <span class="badge badge-{{getClass(request)}}">{{getStatus(request) | translate}}</span></p>
|
||||
|
|
|
@ -1,43 +1,42 @@
|
|||
import { OmbiCommonModules } from "../modules";
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { ImageService } from "../../services";
|
||||
import { fadeInOutAnimation } from "app/animations/fadeinout";
|
||||
import { OmbiCommonModules } from '../modules';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ImageService } from '../../services';
|
||||
import { fadeInOutAnimation } from 'app/animations/fadeinout';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'ombi-image-background',
|
||||
templateUrl: './image-background.component.html',
|
||||
styleUrls: ['./image-background.component.scss'],
|
||||
imports: [...OmbiCommonModules, BrowserAnimationsModule],
|
||||
providers: [ ImageService ],
|
||||
animations: [ fadeInOutAnimation ],
|
||||
})
|
||||
export class ImageBackgroundComponent implements OnInit, OnDestroy {
|
||||
standalone: true,
|
||||
selector: 'ombi-image-background',
|
||||
templateUrl: './image-background.component.html',
|
||||
styleUrls: ['./image-background.component.scss'],
|
||||
imports: [...OmbiCommonModules, BrowserAnimationsModule],
|
||||
providers: [ImageService],
|
||||
animations: [fadeInOutAnimation],
|
||||
})
|
||||
export class ImageBackgroundComponent implements OnInit, OnDestroy {
|
||||
public background: any;
|
||||
public name: string;
|
||||
private timer: any;
|
||||
|
||||
public background: any;
|
||||
public name: string;
|
||||
private timer: NodeJS.Timeout;
|
||||
constructor(private images: ImageService, private sanitizer: DomSanitizer) {}
|
||||
|
||||
constructor(private images: ImageService, private sanitizer: DomSanitizer) { }
|
||||
public ngOnDestroy(): void {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
public ngOnInit(): void {
|
||||
this.cycleBackground();
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.cycleBackground();
|
||||
this.timer = setInterval(() => {
|
||||
this.cycleBackground();
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
this.timer = setInterval(() => {
|
||||
this.cycleBackground();
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
private cycleBackground() {
|
||||
this.images.getRandomBackgroundWithInfo().subscribe((x) => {
|
||||
this.background = this.sanitizer.bypassSecurityTrustStyle("url(" + x.url + ")");
|
||||
this.name = x.name;
|
||||
});
|
||||
}
|
||||
}
|
||||
private cycleBackground() {
|
||||
this.images.getRandomBackgroundWithInfo().subscribe((x) => {
|
||||
this.background = this.sanitizer.bypassSecurityTrustStyle('url(' + x.url + ')');
|
||||
this.name = x.name;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { CommonModule } from "@angular/common";
|
||||
import { MomentModule } from "ngx-moment";
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
export const OmbiCommonModules = [ CommonModule, MomentModule ];
|
||||
export const OmbiCommonModules = [CommonModule];
|
||||
|
|
|
@ -1,28 +1,42 @@
|
|||
<mat-card class="issue-card" *ngIf="!deleted">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{issue.subject}}</mat-card-title>
|
||||
<mat-card-subtitle>{{'Issues.UserOnDate' | translate: { user: issue.userReported?.userName, date: issue.createdDate | amLocal | amUserLocale | amDateFormat: 'LL' } }}</mat-card-subtitle>
|
||||
<mat-card-subtitle>{{issue.issueCategory.value}}</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<p>
|
||||
{{issue.description}}
|
||||
</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button (click)="openChat(issue)" color="accent"><i class="far fa-comments"></i> {{'Issues.Chat' | translate }}</button>
|
||||
<div *ngIf="isAdmin && settings;then content else empty"></div>
|
||||
<ng-template #content>
|
||||
<button mat-raised-button color="accent"
|
||||
*ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress"
|
||||
(click)="inProgress(issue)">{{'Issues.MarkInProgress' | translate }}</button>
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{ issue.subject }}</mat-card-title>
|
||||
<mat-card-subtitle>{{
|
||||
'Issues.UserOnDate' | translate: { user: issue.userReported?.userName, date: issue.createdDate | dfnsFormat: 'PP' }
|
||||
}}</mat-card-subtitle>
|
||||
<mat-card-subtitle>{{ issue.issueCategory.value }}</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<p>
|
||||
{{ issue.description }}
|
||||
</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button (click)="openChat(issue)" color="accent"><i class="far fa-comments"></i> {{ 'Issues.Chat' | translate }}</button>
|
||||
<div *ngIf="isAdmin && settings; then content; else empty"></div>
|
||||
<ng-template #content>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
*ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress"
|
||||
(click)="inProgress(issue)"
|
||||
>
|
||||
{{ 'Issues.MarkInProgress' | translate }}
|
||||
</button>
|
||||
|
||||
<button mat-raised-button color="accent"
|
||||
*ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress"
|
||||
(click)="resolve(issue)">{{'Issues.MarkResolved' | translate}}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
*ngIf="(issue.status === IssueStatus.Pending && !settings.enableInProgress) || issue.status == IssueStatus.InProgress"
|
||||
(click)="resolve(issue)"
|
||||
>
|
||||
{{ 'Issues.MarkResolved' | translate }}
|
||||
</button>
|
||||
|
||||
<button mat-raised-button color="warn" (click)="delete(issue)"><i class="far fa-times-circle"></i> {{'Issues.Delete' | translate}}</button></ng-template>
|
||||
<ng-template #empty></ng-template>
|
||||
</mat-card-actions>
|
||||
<button mat-raised-button color="warn" (click)="delete(issue)">
|
||||
<i class="far fa-times-circle"></i> {{ 'Issues.Delete' | translate }}
|
||||
</button></ng-template
|
||||
>
|
||||
<ng-template #empty></ng-template>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
|
|
|
@ -1,95 +1,124 @@
|
|||
<div *ngIf="issue">
|
||||
<div class="row issue-details">
|
||||
<div class="myBg backdrop" [style.background-image]="backgroundPath"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
<h1>{{issue.title}} </h1>
|
||||
<div class="col-md-6">
|
||||
<img class="img-responsive poster" src="{{posterPath}}" alt="poster">
|
||||
<div class="row issue-details">
|
||||
<div class="myBg backdrop" [style.background-image]="backgroundPath"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.6) 100%)"></div>
|
||||
<h1>{{ issue.title }}</h1>
|
||||
<div class="col-md-6">
|
||||
<img class="img-responsive poster" src="{{ posterPath }}" alt="poster" />
|
||||
|
||||
<div class="issue-status">
|
||||
<span *ngIf="issue.status === IssueStatus.Pending" id="pendingLabel" class="label label-warning">{{IssueStatus[issue.status]}}</span>
|
||||
<span *ngIf="issue.status === IssueStatus.InProgress" id="inprogressLabel" class="label label-info">{{IssueStatus[issue.status]}}</span>
|
||||
<span *ngIf="issue.status === IssueStatus.Resolved" id="resolvedLabel" class="label label-success">{{IssueStatus[issue.status]}}</span>
|
||||
</div>
|
||||
<span class="label label-success">{{issue.issueCategory.value}}</span>
|
||||
<br>
|
||||
<span class="reported-by">
|
||||
<h3 *ngIf="issue.userReported?.alias">{{'Issues.ReportedBy' | translate}}:</h3>
|
||||
<h3 *ngIf="!issue.userReported?.alias">{{'Issues.ReportedBy' | translate}}:</h3>
|
||||
</span>
|
||||
<span class="reported-user">
|
||||
<h3 *ngIf="issue.userReported?.alias">{{issue.userReported.alias}}</h3>
|
||||
<h3 *ngIf="!issue.userReported?.alias">{{issue.userReported.userName}}</h3>
|
||||
</span>
|
||||
<br>
|
||||
<span class="subject-category"><h3 *ngIf="issue.subject">{{'Issues.Subject' | translate}}:</h3></span>
|
||||
<span class="subject"><h3 *ngIf="issue.subject">{{issue.subject}}</h3></span>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label for="description" class="control-label" [translate]="'Issues.Description'"></label>
|
||||
<div>
|
||||
<textarea class="form-control-custom form-control" disabled="disabled" [(ngModel)]="issue.description" rows="5" type="text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="issue-status">
|
||||
<span *ngIf="issue.status === IssueStatus.Pending" id="pendingLabel" class="label label-warning">{{
|
||||
IssueStatus[issue.status]
|
||||
}}</span>
|
||||
<span *ngIf="issue.status === IssueStatus.InProgress" id="inprogressLabel" class="label label-info">{{
|
||||
IssueStatus[issue.status]
|
||||
}}</span>
|
||||
<span *ngIf="issue.status === IssueStatus.Resolved" id="resolvedLabel" class="label label-success">{{
|
||||
IssueStatus[issue.status]
|
||||
}}</span>
|
||||
</div>
|
||||
<span class="label label-success">{{ issue.issueCategory.value }}</span>
|
||||
<br />
|
||||
<span class="reported-by">
|
||||
<h3 *ngIf="issue.userReported?.alias">{{ 'Issues.ReportedBy' | translate }}:</h3>
|
||||
<h3 *ngIf="!issue.userReported?.alias">{{ 'Issues.ReportedBy' | translate }}:</h3>
|
||||
</span>
|
||||
<span class="reported-user">
|
||||
<h3 *ngIf="issue.userReported?.alias">{{ issue.userReported.alias }}</h3>
|
||||
<h3 *ngIf="!issue.userReported?.alias">{{ issue.userReported.userName }}</h3>
|
||||
</span>
|
||||
<br />
|
||||
<span class="subject-category"
|
||||
><h3 *ngIf="issue.subject">{{ 'Issues.Subject' | translate }}:</h3></span
|
||||
>
|
||||
<span class="subject"
|
||||
><h3 *ngIf="issue.subject">{{ issue.subject }}</h3></span
|
||||
>
|
||||
<br />
|
||||
<div class="form-group">
|
||||
<label for="description" class="control-label" [translate]="'Issues.Description'"></label>
|
||||
<div>
|
||||
<textarea
|
||||
class="form-control-custom form-control"
|
||||
disabled="disabled"
|
||||
[(ngModel)]="issue.description"
|
||||
rows="5"
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row chat-window col-xs-7 col-md-5" id="chat_window_1" style="margin-left: 10px">
|
||||
<div class="col-xs-12 col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading top-bar">
|
||||
<div class="col-md-8 col-xs-8">
|
||||
<h3 class="panel-title"><span class="glyphicon glyphicon-comment"></span> {{ 'Issues.Comments' | translate }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="comments" class="panel-body msg_container_base">
|
||||
<div *ngIf="comments.length <= 0" class="row msg_container base_receive">
|
||||
<div class="col-md-10 col-xs-10">
|
||||
<div class="messages msg_sent">
|
||||
<p [translate]="'Issues.NoComments'"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div
|
||||
*ngFor="let comment of comments"
|
||||
class="row msg_container"
|
||||
[ngClass]="{ base_sent: comment.adminComment, base_receive: !comment.adminComment }"
|
||||
>
|
||||
<div class="col-md-10 col-xs-10">
|
||||
<div class="messages msg_sent">
|
||||
<i
|
||||
*ngIf="isAdmin"
|
||||
style="float: right"
|
||||
class="fas fa-times"
|
||||
aria-hidden="true"
|
||||
(click)="deleteComment(comment.id)"
|
||||
></i>
|
||||
<p>{{ comment.comment }}</p>
|
||||
<time>{{ comment.username }} • {{ comment.date | dfnsFormat: 'Ppp' }}</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<div class="input-group">
|
||||
<input
|
||||
id="btn-input"
|
||||
type="text"
|
||||
class="form-control input-sm chat_input"
|
||||
[(ngModel)]="newComment.comment"
|
||||
[attr.placeholder]="'Issues.WriteMessagePlaceholder' | translate"
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
class="btn btn-primary btn-sm"
|
||||
id="btn-chat"
|
||||
(click)="addComment()"
|
||||
[translate]="'Issues.SendMessageButton'"
|
||||
></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row chat-window col-xs-7 col-md-5" id="chat_window_1" style="margin-left:10px;">
|
||||
<div class="col-xs-12 col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading top-bar">
|
||||
<div class="col-md-8 col-xs-8">
|
||||
<h3 class="panel-title">
|
||||
<span class="glyphicon glyphicon-comment"></span> {{'Issues.Comments' | translate}}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="comments" class="panel-body msg_container_base">
|
||||
<div *ngIf="comments.length <= 0" class="row msg_container base_receive">
|
||||
<div class="col-md-10 col-xs-10">
|
||||
|
||||
<div class="messages msg_sent">
|
||||
<p [translate]="'Issues.NoComments'"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let comment of comments" class="row msg_container" [ngClass]="{'base_sent': comment.adminComment, 'base_receive': !comment.adminComment}">
|
||||
<div class="col-md-10 col-xs-10">
|
||||
|
||||
<div class="messages msg_sent"> <i *ngIf="isAdmin" style="float:right;" class="fas fa-times" aria-hidden="true" (click)="deleteComment(comment.id)"></i>
|
||||
<p>{{comment.comment}}</p>
|
||||
<time>{{comment.username}} • {{comment.date | amFromUtc | amLocal | amUserLocale | amDateFormat: 'l LT'}}</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<div class="input-group">
|
||||
<input id="btn-input" type="text" class="form-control input-sm chat_input" [(ngModel)]="newComment.comment" [attr.placeholder]="'Issues.WriteMessagePlaceholder' | translate" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary btn-sm" id="btn-chat" (click)="addComment()" [translate]="'Issues.SendMessageButton'"></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div *ngIf="isAdmin && settings">
|
||||
<div *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress">
|
||||
<button class="btn btn-primary btn-sm bottom-btn" (click)="inProgress()">{{'Issues.MarkInProgress' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="issue.status === IssueStatus.Pending && !settings.enableInProgress || issue.status == IssueStatus.InProgress">
|
||||
<button class="btn btn-primary btn-sm bottom-btn" (click)="resolve()" [translate]="'Issues.MarkResolved'"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div *ngIf="isAdmin && settings">
|
||||
<div *ngIf="issue.status === IssueStatus.Pending && settings.enableInProgress">
|
||||
<button class="btn btn-primary btn-sm bottom-btn" (click)="inProgress()">{{ 'Issues.MarkInProgress' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="(issue.status === IssueStatus.Pending && !settings.enableInProgress) || issue.status == IssueStatus.InProgress">
|
||||
<button class="btn btn-primary btn-sm bottom-btn" (click)="resolve()" [translate]="'Issues.MarkResolved'"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,47 +1,34 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
// import { NbChatModule, NbThemeModule } from '@nebular/theme';
|
||||
|
||||
import { OrderModule } from "ngx-order-pipe";
|
||||
import { AuthGuard } from '../auth/auth.guard';
|
||||
|
||||
import { AuthGuard } from "../auth/auth.guard";
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { SharedModule } from "../shared/shared.module";
|
||||
import { IssueDetailsComponent } from './issueDetails.component';
|
||||
import { IssuesComponent } from './issues.component';
|
||||
import { IssuesTableComponent } from './issuestable.component';
|
||||
import { IssuesDetailsComponent } from './components/details/details.component';
|
||||
|
||||
import { IssueDetailsComponent } from "./issueDetails.component";
|
||||
import { IssuesComponent } from "./issues.component";
|
||||
import { IssuesTableComponent } from "./issuestable.component";
|
||||
import { IssuesDetailsComponent } from "./components/details/details.component";
|
||||
import { PipeModule } from '../pipes/pipe.module';
|
||||
|
||||
import { PipeModule } from "../pipes/pipe.module";
|
||||
|
||||
import * as fromComponents from "./components";
|
||||
import * as fromComponents from './components';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "", component: IssuesComponent, canActivate: [AuthGuard] },
|
||||
{ path: ":providerId", component: IssuesDetailsComponent, canActivate: [AuthGuard] },
|
||||
{ path: '', component: IssuesComponent, canActivate: [AuthGuard] },
|
||||
{ path: ':providerId', component: IssuesDetailsComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
OrderModule,
|
||||
PipeModule,
|
||||
SharedModule,
|
||||
// NbChatModule,
|
||||
],
|
||||
declarations: [
|
||||
IssuesComponent,
|
||||
IssueDetailsComponent,
|
||||
IssuesTableComponent,
|
||||
...fromComponents.components
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
],
|
||||
providers: [
|
||||
...fromComponents.providers
|
||||
],
|
||||
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
PipeModule,
|
||||
SharedModule,
|
||||
// NbChatModule,
|
||||
],
|
||||
declarations: [IssuesComponent, IssueDetailsComponent, IssuesTableComponent, ...fromComponents.components],
|
||||
exports: [RouterModule],
|
||||
providers: [...fromComponents.providers],
|
||||
})
|
||||
export class IssuesModule { }
|
||||
export class IssuesModule {}
|
||||
|
|
|
@ -1,137 +1,138 @@
|
|||
<div *ngIf="movie" class="left-panel-details">
|
||||
<div class="rating medium-font">
|
||||
<span *ngIf="movie.voteAverage"
|
||||
matTooltip="{{'MediaDetails.Votes' | translate }} {{movie.voteCount | thousandShort: 1}}">
|
||||
<img class="rating-small" src="{{baseUrl}}/images/tmdb-logo.svg"> {{movie.voteAverage | number:'1.0-1'}}/10
|
||||
</span>
|
||||
<span *ngIf="ratings?.critics_rating && ratings?.critics_score">
|
||||
<img class="rating-small"
|
||||
src="{{baseUrl}}/images/{{ratings.critics_rating === 'Rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}">
|
||||
{{ratings.critics_score}}%
|
||||
</span>
|
||||
<span *ngIf="ratings?.audience_rating && ratings?.audience_score">
|
||||
<img class="rating-small"
|
||||
src="{{baseUrl}}/images/{{ratings.audience_rating === 'Upright' ? 'rotten-audience-fresh.svg' : 'rotten-audience-rotten.svg'}}">
|
||||
{{ratings.audience_score}}%
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="streams?.length > 0" class="streaming-on">
|
||||
<hr>
|
||||
<span class="label">{{'MediaDetails.StreamingOn' | translate }}</span>
|
||||
<div>
|
||||
<span *ngFor="let stream of streams">
|
||||
<img class="stream-small" [matTooltip]="stream.streamingProvider" src="https://image.tmdb.org/t/p/original{{stream.logo}}">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<span class="label">{{'MediaDetails.Status' | translate }}</span>
|
||||
<span id="status"> {{ this.movie.status | translateStatus }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{'MediaDetails.Availability' | translate }}</span>
|
||||
<span *ngIf="movie.available || movie.available4K"> {{'Common.Available' | translate}}</span>
|
||||
<span *ngIf="!movie.available && !movie.available4K"> {{'Common.NotAvailable' | translate}}</span>
|
||||
</div>
|
||||
<div *ngIf="(!movie.available && movie.requested) || (!movie.available4K && movie.has4KRequest)">
|
||||
<span class="label">{{'MediaDetails.RequestStatus' | translate }}</span>
|
||||
<div>{{getStatus(movie) | translate}}</div>
|
||||
</div>
|
||||
<div class="rating medium-font">
|
||||
<span *ngIf="movie.voteAverage" matTooltip="{{ 'MediaDetails.Votes' | translate }} {{ movie.voteCount | thousandShort: 1 }}">
|
||||
<img class="rating-small" src="{{ baseUrl }}/images/tmdb-logo.svg" /> {{ movie.voteAverage | number: '1.0-1' }}/10
|
||||
</span>
|
||||
<span *ngIf="ratings?.critics_rating && ratings?.critics_score">
|
||||
<img
|
||||
class="rating-small"
|
||||
src="{{ baseUrl }}/images/{{ ratings.critics_rating === 'Rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg' }}"
|
||||
/>
|
||||
{{ ratings.critics_score }}%
|
||||
</span>
|
||||
<span *ngIf="ratings?.audience_rating && ratings?.audience_score">
|
||||
<img
|
||||
class="rating-small"
|
||||
src="{{ baseUrl }}/images/{{ ratings.audience_rating === 'Upright' ? 'rotten-audience-fresh.svg' : 'rotten-audience-rotten.svg' }}"
|
||||
/>
|
||||
{{ ratings.audience_score }}%
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="streams?.length > 0" class="streaming-on">
|
||||
<hr />
|
||||
<span class="label">{{ 'MediaDetails.StreamingOn' | translate }}</span>
|
||||
<div>
|
||||
<span *ngFor="let stream of streams">
|
||||
<img class="stream-small" [matTooltip]="stream.streamingProvider" src="https://image.tmdb.org/t/p/original{{ stream.logo }}" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<span class="label">{{ 'MediaDetails.Status' | translate }}</span>
|
||||
<span id="status"> {{ this.movie.status | translateStatus }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{ 'MediaDetails.Availability' | translate }}</span>
|
||||
<span *ngIf="movie.available || movie.available4K"> {{ 'Common.Available' | translate }}</span>
|
||||
<span *ngIf="!movie.available && !movie.available4K"> {{ 'Common.NotAvailable' | translate }}</span>
|
||||
</div>
|
||||
<div *ngIf="(!movie.available && movie.requested) || (!movie.available4K && movie.has4KRequest)">
|
||||
<span class="label">{{ 'MediaDetails.RequestStatus' | translate }}</span>
|
||||
<div>{{ getStatus(movie) | translate }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="request">
|
||||
<span class="label">{{'MediaDetails.RequestedBy' | translate }}</span>
|
||||
<span id="requestedByInfo"> {{request.requestedUser.userAlias}}</span>
|
||||
</div>
|
||||
<div *ngIf="request">
|
||||
<span class="label">{{ 'MediaDetails.RequestedBy' | translate }}</span>
|
||||
<span id="requestedByInfo"> {{ request.requestedUser.userAlias }}</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="request">
|
||||
<span class="label">{{'MediaDetails.RequestDate' | translate }}</span>
|
||||
<span *ngIf="request.requestedDate < request.requestedDate4k"> {{request.requestedDate4k | amUserLocale | amDateFormat: 'LL'}}</span>
|
||||
<span *ngIf="request.requestedDate > request.requestedDate4k"> {{request.requestedDate | amUserLocale | amDateFormat: 'LL'}}</span>
|
||||
</div>
|
||||
<div *ngIf="request">
|
||||
<span class="label">{{ 'MediaDetails.RequestDate' | translate }}</span>
|
||||
<span *ngIf="request.requestedDate < request.requestedDate4k"> {{ request.requestedDate4k | dfnsFormat: 'PP' }}</span>
|
||||
<span *ngIf="request.requestedDate > request.requestedDate4k"> {{ request.requestedDate | dfnsFormat: 'PP' }}</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="request && request.source !== RequestSource.Ombi">
|
||||
<span class="label">{{'MediaDetails.RequestSource' | translate }}</span>
|
||||
{{RequestSource[request.source]}}
|
||||
</div>
|
||||
<div *ngIf="request && request.source !== RequestSource.Ombi">
|
||||
<span class="label">{{ 'MediaDetails.RequestSource' | translate }}</span>
|
||||
{{ RequestSource[request.source] }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="request && ( request.deniedReason || request.deniedReason4K )">
|
||||
<span class="label">{{'MediaDetails.DeniedReason' | translate }}</span>
|
||||
<div *ngIf="request.deniedReason">
|
||||
<span id="deniedReasonInfo">{{request.deniedReason}}</span>
|
||||
</div>
|
||||
<div *ngIf="request.deniedReason4K">
|
||||
<span id="deniedReasonInfo4K">{{request.deniedReason4K}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="request && (request.deniedReason || request.deniedReason4K)">
|
||||
<span class="label">{{ 'MediaDetails.DeniedReason' | translate }}</span>
|
||||
<div *ngIf="request.deniedReason">
|
||||
<span id="deniedReasonInfo">{{ request.deniedReason }}</span>
|
||||
</div>
|
||||
<div *ngIf="request.deniedReason4K">
|
||||
<span id="deniedReasonInfo4K">{{ request.deniedReason4K }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="movie.quality">
|
||||
<span class="label">{{ 'MediaDetails.Quality' | translate }}</span>
|
||||
<div>{{ movie.quality | quality }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="movie.quality">
|
||||
<span class="label">{{'MediaDetails.Quality' | translate }}</span>
|
||||
<div>{{movie.quality | quality}}</div>
|
||||
</div>
|
||||
<div *ngIf="movie.available4K">
|
||||
<span class="label">{{ 'MediaDetails.Quality' | translate }} </span>
|
||||
<span>{{ '4K' | quality }}</span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="movie.available4K">
|
||||
<span class="label">{{'MediaDetails.Quality' | translate }} </span>
|
||||
<span>{{"4K" | quality}}</span>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request && request.rootPathOverrideTitle">
|
||||
<span class="label">{{ 'MediaDetails.RootFolderOverride' | translate }}</span>
|
||||
<div>{{ request.rootPathOverrideTitle }}</div>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request && request.qualityOverrideTitle">
|
||||
<span class="label">{{ 'MediaDetails.QualityOverride' | translate }}</span>
|
||||
<div>{{ request.qualityOverrideTitle }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="advancedOptions && request && request.rootPathOverrideTitle">
|
||||
<span class="label">{{'MediaDetails.RootFolderOverride' | translate }}</span>
|
||||
<div>{{request.rootPathOverrideTitle}}</div>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request && request.qualityOverrideTitle">
|
||||
<span class="label">{{'MediaDetails.QualityOverride' | translate }}</span>
|
||||
<div>{{request.qualityOverrideTitle}}</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<span class="label">{{ 'MediaDetails.TheatricalRelease' | translate }}</span>
|
||||
{{ movie.releaseDate | dfnsFormat: 'PP' }}
|
||||
|
||||
<div *ngIf="movie.digitalReleaseDate">
|
||||
<span class="label">{{ 'MediaDetails.DigitalRelease' | translate }}</span>
|
||||
{{ movie.digitalReleaseDate | dfnsFormat: 'PP' }}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div *ngIf="movie.voteCount">
|
||||
<span class="label">{{ 'MediaDetails.Votes' | translate }}</span>
|
||||
{{ movie.voteCount | thousandShort: 1 }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{ 'MediaDetails.Runtime' | translate }}</span>
|
||||
{{ 'MediaDetails.Minutes' | translate: { runtime: movie.runtime } }}
|
||||
</div>
|
||||
<div *ngIf="movie.revenue">
|
||||
<span class="label">{{ 'MediaDetails.Revenue' | translate }}</span>
|
||||
{{ movie.revenue | currency: 'USD' }}
|
||||
</div>
|
||||
<div *ngIf="movie.budget">
|
||||
<span class="label">{{ 'MediaDetails.Budget' | translate }}</span>
|
||||
{{ movie.budget | currency: 'USD' }}
|
||||
</div>
|
||||
|
||||
<span class="label">{{'MediaDetails.TheatricalRelease' | translate }}</span>
|
||||
{{movie.releaseDate | amUserLocale | amDateFormat: 'LL': 'mediumDate'}}
|
||||
<hr />
|
||||
<div class="genre-button-container" *ngIf="movie.genres">
|
||||
<span class="label">{{ 'MediaDetails.GenresLabel' | translate }}</span>
|
||||
<div>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let genre of movie.genres">
|
||||
{{ genre.name }}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="movie.digitalReleaseDate">
|
||||
<span class="label">{{'MediaDetails.DigitalRelease' | translate }}</span>
|
||||
{{movie.digitalReleaseDate | amUserLocale | amDateFormat: 'LL': 'mediumDate'}}
|
||||
</div>
|
||||
|
||||
<div *ngIf="movie.voteCount">
|
||||
<span class="label">{{'MediaDetails.Votes' | translate }}</span>
|
||||
{{movie.voteCount | thousandShort: 1}}
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{'MediaDetails.Runtime' | translate }}</span>
|
||||
{{'MediaDetails.Minutes' | translate:{runtime: movie.runtime} }}
|
||||
</div>
|
||||
<div *ngIf="movie.revenue">
|
||||
<span class="label">{{'MediaDetails.Revenue' | translate }}</span>
|
||||
{{movie.revenue | currency: 'USD'}}
|
||||
</div>
|
||||
<div *ngIf="movie.budget">
|
||||
<span class="label">{{'MediaDetails.Budget' | translate }}</span>
|
||||
{{movie.budget | currency: 'USD'}}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="genre-button-container" *ngIf="movie.genres">
|
||||
<span class="label">{{'MediaDetails.GenresLabel' | translate }}</span>
|
||||
<div>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let genre of movie.genres">
|
||||
{{genre.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="keyword-button-container" *ngIf="movie?.keywords?.keywordsValue?.length > 0">
|
||||
<span class="label">{{'MediaDetails.Keywords' | translate }}</span>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let keyword of movie.keywords.keywordsValue">
|
||||
{{keyword.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="keyword-button-container" *ngIf="movie?.keywords?.keywordsValue?.length > 0">
|
||||
<span class="label">{{ 'MediaDetails.Keywords' | translate }}</span>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let keyword of movie.keywords.keywordsValue">
|
||||
{{ keyword.name }}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
<section id="summary-wrapper">
|
||||
<div class="full-screenshot enabled" [style.background-image]="background"></div>
|
||||
<div class="full-screenshot enabled overlay"></div>
|
||||
|
||||
<section id="summary-wrapper">
|
||||
<div class="full-screenshot enabled" [style.background-image]="background"></div>
|
||||
<div class="full-screenshot enabled overlay"></div>
|
||||
<div class="container summary">
|
||||
<div class="container title-top-banner">
|
||||
<div class="row">
|
||||
<div class="mobile-top-text">
|
||||
<h1 id="mediaTitle" class="large-text">
|
||||
{{ title }}
|
||||
<span *ngIf="releaseDateFormat" class="grey-text"> ({{ releaseDate | dfnsFormat: 'P' }})</span>
|
||||
</h1>
|
||||
|
||||
<div class="container summary">
|
||||
<div class="container title-top-banner">
|
||||
<div class="row">
|
||||
<div
|
||||
class="mobile-top-text">
|
||||
<h1 id="mediaTitle" class="large-text">{{title}}
|
||||
<span *ngIf="releaseDateFormat" class="grey-text">
|
||||
({{releaseDate | amLocal | amDateFormat: 'YYYY'}})</span>
|
||||
</h1>
|
||||
|
||||
<h2 class="tagline">{{tagline}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<h2 class="tagline">{{ tagline }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -1,82 +1,85 @@
|
|||
<div class="left-panel-details">
|
||||
<div>
|
||||
<div class="rating medium-font">
|
||||
<span *ngIf="tv.rating">
|
||||
<img class="rating-small" src="{{baseUrl}}/images/tmdb-logo.svg"> {{tv.rating * 10 | number : '1.2-2'}}%
|
||||
</span>
|
||||
<span *ngIf="ratings?.score && ratings?.class">
|
||||
<img class="rating-small" src="{{baseUrl}}/images/{{ratings.class === 'rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}"> {{ratings.score}}%
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="streams?.length > 0" id="streamingContainer" class="streaming-on-container">
|
||||
<hr>
|
||||
<div class="streaming-on-content">
|
||||
<span class="label">{{'MediaDetails.StreamingOn' | translate }}</span>
|
||||
<div>
|
||||
<span *ngFor="let stream of sortBy('order')">
|
||||
<img class="stream-small" id="stream{{stream.streamingProvider}}" [matTooltip]="stream.streamingProvider" src="https://image.tmdb.org/t/p/original{{stream.logo}}">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div *ngIf="tv.status">
|
||||
<span class="label">{{'MediaDetails.Status' | translate }}</span>
|
||||
<span id="status"> {{ tv.status | translateStatus }}</span>
|
||||
</div>
|
||||
<span class="label">{{'MediaDetails.FirstAired' | translate }}</span>
|
||||
{{tv.firstAired | amLocal | amUserLocale | amDateFormat: 'LL' }}
|
||||
</div>
|
||||
<div>
|
||||
<div class="rating medium-font">
|
||||
<span *ngIf="tv.rating">
|
||||
<img class="rating-small" src="{{ baseUrl }}/images/tmdb-logo.svg" /> {{ tv.rating * 10 | number: '1.2-2' }}%
|
||||
</span>
|
||||
<span *ngIf="ratings?.score && ratings?.class">
|
||||
<img class="rating-small" src="{{ baseUrl }}/images/{{ ratings.class === 'rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg' }}" />
|
||||
{{ ratings.score }}%
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="streams?.length > 0" id="streamingContainer" class="streaming-on-container">
|
||||
<hr />
|
||||
<div class="streaming-on-content">
|
||||
<span class="label">{{ 'MediaDetails.StreamingOn' | translate }}</span>
|
||||
<div>
|
||||
<span *ngFor="let stream of sortBy('order')">
|
||||
<img
|
||||
class="stream-small"
|
||||
id="stream{{ stream.streamingProvider }}"
|
||||
[matTooltip]="stream.streamingProvider"
|
||||
src="https://image.tmdb.org/t/p/original{{ stream.logo }}"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div *ngIf="tv.status">
|
||||
<span class="label">{{ 'MediaDetails.Status' | translate }}</span>
|
||||
<span id="status"> {{ tv.status | translateStatus }}</span>
|
||||
</div>
|
||||
<span class="label">{{ 'MediaDetails.FirstAired' | translate }}</span>
|
||||
{{ tv.firstAired | dfnsFormat: 'PP' }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="seasonCount">
|
||||
<span class="label">{{'MediaDetails.Seasons' | translate }}</span>
|
||||
{{seasonCount}}
|
||||
</div>
|
||||
<div *ngIf="totalEpisodes">
|
||||
<span class="label">{{'MediaDetails.Episodes' | translate }}</span>
|
||||
{{totalEpisodes}}
|
||||
</div>
|
||||
<div *ngIf="seasonCount">
|
||||
<span class="label">{{ 'MediaDetails.Seasons' | translate }}</span>
|
||||
{{ seasonCount }}
|
||||
</div>
|
||||
<div *ngIf="totalEpisodes">
|
||||
<span class="label">{{ 'MediaDetails.Episodes' | translate }}</span>
|
||||
{{ totalEpisodes }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="advancedOptions && request?.rootPathOverrideTitle">
|
||||
<span class="label">{{'MediaDetails.RootFolderOverride' | translate }}</span>
|
||||
<div>{{request.rootPathOverrideTitle}}</div>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request?.qualityOverrideTitle">
|
||||
<span class="label">{{'MediaDetails.QualityOverride' | translate }}</span>
|
||||
<div>{{request.qualityOverrideTitle}}</div>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request?.rootPathOverrideTitle">
|
||||
<span class="label">{{ 'MediaDetails.RootFolderOverride' | translate }}</span>
|
||||
<div>{{ request.rootPathOverrideTitle }}</div>
|
||||
</div>
|
||||
<div *ngIf="advancedOptions && request?.qualityOverrideTitle">
|
||||
<span class="label">{{ 'MediaDetails.QualityOverride' | translate }}</span>
|
||||
<div>{{ request.qualityOverrideTitle }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="label">{{'MediaDetails.Runtime' | translate }}</span>
|
||||
{{'MediaDetails.Minutes' | translate:{ runtime: tv.runtime} }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{ 'MediaDetails.Runtime' | translate }}</span>
|
||||
{{ 'MediaDetails.Minutes' | translate: { runtime: tv.runtime } }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="tv.network">
|
||||
<span class="label">{{'MediaDetails.Network' | translate }}</span>
|
||||
{{tv.network.name}}
|
||||
</div>
|
||||
<div *ngIf="tv.network">
|
||||
<span class="label">{{ 'MediaDetails.Network' | translate }}</span>
|
||||
{{ tv.network.name }}
|
||||
</div>
|
||||
|
||||
<div class="genre-button-container" *ngIf="tv.genres">
|
||||
<span class="label">{{ 'MediaDetails.GenresLabel' | translate }}</span>
|
||||
<div>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let genre of tv.genres">
|
||||
{{ genre.name }}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="genre-button-container" *ngIf="tv.genres">
|
||||
<span class="label">{{'MediaDetails.GenresLabel' | translate }}</span>
|
||||
<div>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let genre of tv.genres">
|
||||
{{genre.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="keyword-button-container" *ngIf="tv?.keywords?.keywordsValue?.length > 0">
|
||||
<span class="label">{{'MediaDetails.Keywords' | translate }}</span>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let keyword of tv.keywords.keywordsValue">
|
||||
{{keyword.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="keyword-button-container" *ngIf="tv?.keywords?.keywordsValue?.length > 0">
|
||||
<span class="label">{{ 'MediaDetails.Keywords' | translate }}</span>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let keyword of tv.keywords.keywordsValue">
|
||||
{{ keyword.name }}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,69 +1,73 @@
|
|||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let season of tv.seasonRequests">
|
||||
<ng-template mat-tab-label>
|
||||
<div attr.data-test="classStatus{{ season.seasonNumber }}" class="{{ getStatusClass(season) }} top-right">
|
||||
<span>{{ 'Requests.Season' | translate }} {{ season.seasonNumber }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let season of tv.seasonRequests">
|
||||
<mat-card *ngIf="season.overview" class="mat-elevation-z8">
|
||||
<mat-card-content>
|
||||
<p>{{ season.overview }}</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<ng-template mat-tab-label>
|
||||
<div attr.data-test="classStatus{{season.seasonNumber}}" class="{{getStatusClass(season)}} top-right">
|
||||
<span>{{ 'Requests.Season' | translate }} {{season.seasonNumber}}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<table mat-table [dataSource]="season.episodes" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
attr.data-test="masterCheckbox{{ season.seasonNumber }}"
|
||||
*ngIf="isSeasonCheckable(season)"
|
||||
(change)="$event ? masterToggle(season.episodes) : null"
|
||||
[checked]="selection.hasValue() && isAllSelected(season.episodes)"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected(season.episodes)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
attr.data-test="episodeCheckbox{{ season.seasonNumber }}{{ row.episodeNumber }}"
|
||||
*ngIf="!row.available && !row.requested && !row.approved"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<mat-card *ngIf="season.overview" class="mat-elevation-z8">
|
||||
<mat-card-content>
|
||||
<p>{{season.overview}}</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<ng-container matColumnDef="number">
|
||||
<th mat-header-cell *matHeaderCellDef>#</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.episodeNumber }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.GridTitle' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.title }}</td>
|
||||
</ng-container>
|
||||
|
||||
<table mat-table [dataSource]="season.episodes" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="airDate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.AirDate' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.airDate | dfnsFormat: 'P' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox attr.data-test="masterCheckbox{{season.seasonNumber}}" *ngIf="isSeasonCheckable(season)" (change)="$event ? masterToggle(season.episodes) : null"
|
||||
[checked]="selection.hasValue() && isAllSelected(season.episodes)"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected(season.episodes)">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox attr.data-test="episodeCheckbox{{season.seasonNumber}}{{row.episodeNumber}}" *ngIf="!row.available && !row.requested && !row.approved" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.GridStatus' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let ep">
|
||||
<div
|
||||
attr.data-test="episodeStatus{{ season.seasonNumber }}{{ ep.episodeNumber }}"
|
||||
class="{{ getEpisodeStatusClass(ep) }} top-right"
|
||||
>
|
||||
<span>{{ ep.requestStatus | translate }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="number">
|
||||
<th mat-header-cell *matHeaderCellDef> # </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.episodeNumber}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.GridTitle' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="airDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.AirDate' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.airDate | amLocal | amUserLocale | amDateFormat: 'L' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.GridStatus' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let ep">
|
||||
<div attr.data-test="episodeStatus{{season.seasonNumber}}{{ep.episodeNumber}}" class="{{getEpisodeStatusClass(ep)}} top-right">
|
||||
<span>{{ep.requestStatus | translate}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
(click)="selection.toggle(row)">
|
||||
</tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
|
||||
</mat-tab-group>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" (click)="selection.toggle(row)"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<!-- <div *ngIf="isAdmin">
|
||||
<button *ngIf="!request.approved" mat-raised-button color="accent" (click)="approve(request);"> {{ 'Common.Approve' | translate }}</button>
|
||||
|
@ -73,16 +77,15 @@
|
|||
</div>
|
||||
-->
|
||||
|
||||
|
||||
<button *ngIf="!tv.fullyAvailable && requestable" mat-fab color="accent" id="addFabBtn" class="floating-fab" [matMenuTriggerFor]="aboveMenu">
|
||||
<i class="fas fa-plus fa-lg"></i>
|
||||
<mat-menu #aboveMenu="matMenu" yPosition="above">
|
||||
<i class="fas fa-plus fa-lg"></i>
|
||||
<mat-menu #aboveMenu="matMenu" yPosition="above">
|
||||
<button id="requestAll" mat-menu-item (click)="requestAllSeasons()">{{ 'Search.TvShows.AllSeasons' | translate }}</button>
|
||||
|
||||
<button id="requestAll" mat-menu-item (click)="requestAllSeasons()">{{'Search.TvShows.AllSeasons' | translate }}</button>
|
||||
<button id="requestFirst" mat-menu-item (click)="requestFirstSeason()">{{ 'Search.TvShows.FirstSeason' | translate }}</button>
|
||||
|
||||
<button id="requestFirst" mat-menu-item (click)="requestFirstSeason()">{{ 'Search.TvShows.FirstSeason' | translate }}</button>
|
||||
<button id="requestLatest" mat-menu-item (click)="requestLatestSeason()">{{ 'Search.TvShows.LatestSeason' | translate }}</button>
|
||||
|
||||
<button id="requestLatest" mat-menu-item (click)="requestLatestSeason()">{{ 'Search.TvShows.LatestSeason' | translate }}</button>
|
||||
|
||||
<button id="requestSelected" mat-menu-item (click)="submitRequests()">{{ 'Common.Request' | translate }}</button>
|
||||
</mat-menu>
|
||||
<button id="requestSelected" mat-menu-item (click)="submitRequests()">{{ 'Common.Request' | translate }}</button>
|
||||
</mat-menu>
|
||||
</button>
|
||||
|
|
|
@ -1,66 +1,69 @@
|
|||
<mat-accordion class="mat-elevation-z8">
|
||||
<mat-expansion-panel *ngFor="let request of tvRequest">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<div> {{ request.requestStatus | translate }}</div>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
{{'MediaDetails.RequestedByOn' | translate: {
|
||||
user: request.requestedUser.userAlias,
|
||||
date: request.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL' } }}
|
||||
<span *ngIf="request.denied"> - {{request.deniedReason}}</span>
|
||||
<span *ngIf="request.source !== RequestSource.Ombi"> {{'MediaDetails.RequestSource' | translate }} {{RequestSource[request.source]}}</span>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-expansion-panel *ngFor="let request of tvRequest">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<div>{{ request.requestStatus | translate }}</div>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
{{
|
||||
'MediaDetails.RequestedByOn'
|
||||
| translate
|
||||
: {
|
||||
user: request.requestedUser.userAlias,
|
||||
date: request.requestedDate | dfnsFormat: 'PP'
|
||||
}
|
||||
}}
|
||||
<span *ngIf="request.denied"> - {{ request.deniedReason }}</span>
|
||||
<span *ngIf="request.source !== RequestSource.Ombi"
|
||||
> {{ 'MediaDetails.RequestSource' | translate }} {{ RequestSource[request.source] }}</span
|
||||
>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let season of request.seasonRequests" label="{{ 'Requests.Season' | translate }} {{ season.seasonNumber }}">
|
||||
<table mat-table [dataSource]="season.episodes" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="number">
|
||||
<th mat-header-cell *matHeaderCellDef>#</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.episodeNumber }}</td>
|
||||
</ng-container>
|
||||
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let season of request.seasonRequests" label="{{ 'Requests.Season' | translate }} {{season.seasonNumber}}">
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.GridTitle' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.title }}</td>
|
||||
</ng-container>
|
||||
|
||||
<table mat-table [dataSource]="season.episodes" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="airDate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.AirDate' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.airDate | dfnsFormat: 'P' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.GridStatus' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let ep">
|
||||
<span> {{ request.requestStatus | translate }} </span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="number">
|
||||
<th mat-header-cell *matHeaderCellDef> # </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.episodeNumber}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.GridTitle' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="airDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.AirDate' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.airDate | amLocal | amUserLocale | amDateFormat: 'L' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'Requests.GridStatus' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let ep">
|
||||
<span> {{ request.requestStatus | translate }} </span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
|
||||
</mat-tab-group>
|
||||
|
||||
<div *ngIf="isAdmin">
|
||||
<button *ngIf="!request.approved" mat-raised-button color="accent" (click)="approve(request);"> {{ 'Common.Approve' | translate }}</button>
|
||||
<button *ngIf="!request.available" mat-raised-button color="warn" (click)="changeAvailability(request, true);">{{ 'Requests.MarkAvailable' | translate }}</button>
|
||||
<button *ngIf="request.available" mat-raised-button color="warn" (click)="changeAvailability(request, false);">{{ 'Requests.MarkUnavailable' | translate }}</button>
|
||||
<button *ngIf="!request.denied" mat-raised-button color="danger" (click)="deny(request);">{{ 'Requests.Deny' | translate }}</button>
|
||||
<button mat-raised-button color="accent" (click)="reProcessRequest(request);">{{ 'MediaDetails.ReProcessRequest' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="isAdmin || manageOwnRequests">
|
||||
<button mat-raised-button color="danger" (click)="delete(request);">{{ 'Requests.RequestPanel.Delete' | translate }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
</mat-expansion-panel>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<div *ngIf="isAdmin">
|
||||
<button *ngIf="!request.approved" mat-raised-button color="accent" (click)="approve(request)">{{ 'Common.Approve' | translate }}</button>
|
||||
<button *ngIf="!request.available" mat-raised-button color="warn" (click)="changeAvailability(request, true)">
|
||||
{{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
<button *ngIf="request.available" mat-raised-button color="warn" (click)="changeAvailability(request, false)">
|
||||
{{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button *ngIf="!request.denied" mat-raised-button color="danger" (click)="deny(request)">{{ 'Requests.Deny' | translate }}</button>
|
||||
<button mat-raised-button color="accent" (click)="reProcessRequest(request)">{{ 'MediaDetails.ReProcessRequest' | translate }}</button>
|
||||
</div>
|
||||
<div *ngIf="isAdmin || manageOwnRequests">
|
||||
<button mat-raised-button color="danger" (click)="delete(request)">{{ 'Requests.RequestPanel.Delete' | translate }}</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
|
11
src/Ombi/ClientApp/src/app/pipes/OrderPipe.ts
Normal file
11
src/Ombi/ClientApp/src/app/pipes/OrderPipe.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { orderBy as _orderBy } from 'lodash-es';
|
||||
|
||||
@Pipe({
|
||||
name: 'orderBy',
|
||||
})
|
||||
export class OrderPipe<T> implements PipeTransform {
|
||||
transform(data: T[], orderBy: string, direction: 'asc' | 'desc' = 'asc'): T[] {
|
||||
return _orderBy(data, orderBy, direction);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import { Pipe, PipeTransform } from "@angular/core";
|
||||
import * as moment from "moment";
|
||||
|
||||
const momentConstructor = moment;
|
||||
|
||||
@Pipe({ name: "amUserLocale" })
|
||||
export class UserLocalePipe implements PipeTransform {
|
||||
transform(value: moment.MomentInput): moment.Moment {
|
||||
const locale = navigator.language;
|
||||
return momentConstructor(value).locale(locale);
|
||||
}
|
||||
}
|
|
@ -1,22 +1,21 @@
|
|||
import { ModuleWithProviders, NgModule } from "@angular/core";
|
||||
import { HumanizePipe } from "./HumanizePipe";
|
||||
import { TranslateStatusPipe } from "./TranslateStatus";
|
||||
import { ThousandShortPipe } from "./ThousandShortPipe";
|
||||
import { SafePipe } from "./SafePipe";
|
||||
import { QualityPipe } from "./QualityPipe";
|
||||
import { UserLocalePipe } from "./UserLocalePipe";
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { HumanizePipe } from './HumanizePipe';
|
||||
import { TranslateStatusPipe } from './TranslateStatus';
|
||||
import { ThousandShortPipe } from './ThousandShortPipe';
|
||||
import { SafePipe } from './SafePipe';
|
||||
import { QualityPipe } from './QualityPipe';
|
||||
import { OrderPipe } from './OrderPipe';
|
||||
|
||||
@NgModule({
|
||||
imports: [],
|
||||
declarations: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, UserLocalePipe, TranslateStatusPipe ],
|
||||
exports: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, UserLocalePipe, TranslateStatusPipe ],
|
||||
imports: [],
|
||||
declarations: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe],
|
||||
exports: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe],
|
||||
})
|
||||
export class PipeModule {
|
||||
|
||||
public static forRoot(): ModuleWithProviders<PipeModule> {
|
||||
return {
|
||||
ngModule: PipeModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
public static forRoot(): ModuleWithProviders<PipeModule> {
|
||||
return {
|
||||
ngModule: PipeModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,72 +1,128 @@
|
|||
<div class="mat-elevation-z8">
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
|
||||
<!-- <div class="row"> -->
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
(click)="switchFilter(RequestFilter.All)"
|
||||
[attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AllRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
(click)="switchFilter(RequestFilter.Pending)"
|
||||
[attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.PendingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
(click)="switchFilter(RequestFilter.Processing)"
|
||||
[attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.ProcessingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
(click)="switchFilter(RequestFilter.Available)"
|
||||
[attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AvailableRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
(click)="switchFilter(RequestFilter.Denied)"
|
||||
[attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.DeniedRequests' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="row"> -->
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" (click)="switchFilter(RequestFilter.All)" [attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.AllRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Pending)" [attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.PendingRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Processing)" [attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.ProcessingRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Available)" [attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.AvailableRequests' | translate}}</button>
|
||||
<button type="button" (click)="switchFilter(RequestFilter.Denied)" [attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.DeniedRequests' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="{{ 'Requests.RequestsToDisplay' | translate }}" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="requests table"
|
||||
matSort
|
||||
[matSortActive]="defaultSort"
|
||||
matSortDisableClear
|
||||
[matSortDirection]="defaultOrder"
|
||||
>
|
||||
<ng-container matColumnDef="artistName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.ArtistName' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.artistName }}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.AlbumName' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | dfnsFormat: 'P' }})</td>
|
||||
</ng-container>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="{{'Requests.RequestsToDisplay' | translate}}" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<table mat-table [dataSource]="dataSource" class="requests table" matSort [matSortActive]="defaultSort" matSortDisableClear [matSortDirection]="defaultOrder">
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.RequestedBy' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.requestedUser?.userAlias }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.requestedDate | dfnsFormat: 'PP' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestStatus' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.requestStatus | translate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="artistName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.ArtistName' | translate}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.artistName}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.AlbumName' | translate}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{
|
||||
'Requests.Details' | translate
|
||||
}}</a>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="warn"
|
||||
(click)="openOptions(element)"
|
||||
*ngIf="isAdmin || (manageOwnRequests && element.requestedUser?.userName == userName)"
|
||||
>
|
||||
{{ 'Requests.Options' | translate }}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.RequestedBy' | translate}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedUser?.userAlias}} </td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.RequestDate' | translate}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL'}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.RequestStatus' | translate}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.requestStatus | translate}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</a>
|
||||
<button mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName )"> {{ 'Requests.Options' | translate}}</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
</div>
|
||||
|
|
|
@ -1,123 +1,198 @@
|
|||
<div class="mat-elevation-z8">
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
|
||||
<!-- <div class="row"> -->
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
id="filterAll"
|
||||
(click)="switchFilter(RequestFilter.All)"
|
||||
[attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AllRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterPending"
|
||||
(click)="switchFilter(RequestFilter.Pending)"
|
||||
[attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.PendingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterProcessing"
|
||||
(click)="switchFilter(RequestFilter.Processing)"
|
||||
[attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.ProcessingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterAvailable"
|
||||
(click)="switchFilter(RequestFilter.Available)"
|
||||
[attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AvailableRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterDenied"
|
||||
(click)="switchFilter(RequestFilter.Denied)"
|
||||
[attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.DeniedRequests' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="row"> -->
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" id="filterAll" (click)="switchFilter(RequestFilter.All)" [attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.AllRequests' | translate}}</button>
|
||||
<button type="button" id="filterPending" (click)="switchFilter(RequestFilter.Pending)" [attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.PendingRequests' | translate}}</button>
|
||||
<button type="button" id="filterProcessing" (click)="switchFilter(RequestFilter.Processing)" [attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.ProcessingRequests' | translate}}</button>
|
||||
<button type="button" id="filterAvailable" (click)="switchFilter(RequestFilter.Available)" [attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.AvailableRequests' | translate}}</button>
|
||||
<button type="button" id="filterDenied" (click)="switchFilter(RequestFilter.Denied)" [attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.DeniedRequests' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select
|
||||
id="requestsToDisplayDropdown"
|
||||
placeholder="{{ 'Requests.RequestsToDisplay' | translate }}"
|
||||
[(value)]="gridCount"
|
||||
(selectionChange)="ngAfterViewInit()"
|
||||
>
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="requests table"
|
||||
matSort
|
||||
[matSortActive]="defaultSort"
|
||||
matSortDisableClear
|
||||
[matSortDirection]="defaultOrder"
|
||||
>
|
||||
<ng-container matColumnDef="select" *ngIf="isAdmin">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
id="adminMasterCheckbox"
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
id="adminMasterCheckbox{{ row.id }}"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select id="requestsToDisplayDropdown" placeholder="{{'Requests.RequestsToDisplay' | translate}}" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<table mat-table [dataSource]="dataSource" class="requests table" matSort [matSortActive]="defaultSort" matSortDisableClear [matSortDirection]="defaultOrder">
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestsTitle' | translate }}</th>
|
||||
<td mat-cell id="title{{ element.id }}" *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | dfnsFormat: 'P' }})</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="select" *ngIf="isAdmin">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox id="adminMasterCheckbox" (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox id="adminMasterCheckbox{{row.id}}" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.RequestedBy' | translate }}</th>
|
||||
<td mat-cell id="requestedBy{{ element.id }}" *matCellDef="let element">
|
||||
{{ element.requestedByAlias ? element.requestedByAlias : element.requestedUser?.userAlias }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.RequestsTitle' | translate}} </th>
|
||||
<td mat-cell id="title{{element.id}}" *matCellDef="let element"> {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
|
||||
<td mat-cell id="requestedDate{{ element.id }}" *matCellDef="let element">{{ getRequestDate(element) | dfnsFormat: 'PP' }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedUser.requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.RequestedBy' | translate}} </th>
|
||||
<td mat-cell id="requestedBy{{element.id}}" *matCellDef="let element"> {{element.requestedByAlias ? element.requestedByAlias : element.requestedUser?.userAlias}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.Status' | translate }}</th>
|
||||
<td mat-cell id="status{{ element.id }}" *matCellDef="let element">{{ element.status | translateStatus }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="has4kRequest">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.Has4KRequest' | translate }}</th>
|
||||
<td mat-cell id="has4kRequest{{ element.id }}" *matCellDef="let element">
|
||||
<i *ngIf="element.has4KRequest" class="fas fa-check"></i>
|
||||
<i *ngIf="!element.has4KRequest" class="fas fa-times"></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.RequestDate' | translate}} </th>
|
||||
<td mat-cell id="requestedDate{{element.id}}" *matCellDef="let element"> {{getRequestDate(element) | amLocal | amUserLocale | amDateFormat: 'LL'}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestStatus' | translate }}</th>
|
||||
<td mat-cell id="requestedStatus{{ element.id }}" *matCellDef="let element">{{ element.requestStatus | translate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.Status' | translate}} </th>
|
||||
<td mat-cell id="status{{element.id}}" *matCellDef="let element"> {{element.status |translateStatus }} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="watchedByRequestedUser">
|
||||
<th mat-header-cell *matHeaderCellDef disableClear matTooltip="{{ 'Requests.WatchedTooltip' | translate }}">
|
||||
{{ 'Requests.Watched' | translate }}
|
||||
</th>
|
||||
<td mat-cell id="watchedByRequestedUser{{ element.id }}" *matCellDef="let element">
|
||||
<mat-checkbox
|
||||
[checked]="element.watchedByRequestedUser"
|
||||
disabled="true"
|
||||
matTooltip="{{ 'Requests.WatchedByUsersCount' | translate: { count: element.playedByUsersCount } }}"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="has4kRequest">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.Has4KRequest' | translate}} </th>
|
||||
<td mat-cell id="has4kRequest{{element.id}}" *matCellDef="let element">
|
||||
<i *ngIf="element.has4KRequest" class="fas fa-check"></i>
|
||||
<i *ngIf="!element.has4KRequest" class="fas fa-times"></i>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a id="detailsButton{{ element.id }}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{
|
||||
'Requests.Details' | translate
|
||||
}}</a>
|
||||
<a
|
||||
id="optionsButton{{ element.id }}"
|
||||
mat-raised-button
|
||||
color="warn"
|
||||
(click)="openOptions(element)"
|
||||
*ngIf="isAdmin || (manageOwnRequests && element.requestedUser?.userName == userName)"
|
||||
>
|
||||
{{ 'Requests.Options' | translate }}</a
|
||||
>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{ 'Requests.RequestStatus' | translate}} </th>
|
||||
<td mat-cell id="requestedStatus{{element.id}}" *matCellDef="let element"> {{element.requestStatus | translate}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="watchedByRequestedUser">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
disableClear
|
||||
matTooltip="{{ 'Requests.WatchedTooltip' | translate}}">
|
||||
{{ 'Requests.Watched' | translate}}
|
||||
</th>
|
||||
<td mat-cell id="watchedByRequestedUser{{element.id}}" *matCellDef="let element">
|
||||
<mat-checkbox
|
||||
[checked]="element.watchedByRequestedUser"
|
||||
disabled="true"
|
||||
matTooltip="{{'Requests.WatchedByUsersCount' | translate: {count: element.playedByUsersCount} }}">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</a>
|
||||
<a id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName ) "> {{ 'Requests.Options' | translate}}</a>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
</div>
|
||||
|
||||
<button id="bulkFab" *ngIf="selection.hasValue() && isAdmin" mat-fab color="accent" class="floating-fab" [matMenuTriggerFor]="aboveMenu">
|
||||
<i class="fas fa-bars"></i></button>
|
||||
<mat-menu #aboveMenu="matMenu" yPosition="above">
|
||||
<button id="approveFabButton" mat-menu-item (click)="bulkApprove()">{{'Requests.RequestPanel.Approve' | translate}}</button>
|
||||
<button *ngIf="is4kEnabled" id="approve4kFabButton" mat-menu-item (click)="bulkApprove4K()">{{'Requests.RequestPanel.Approve4K' | translate}}</button>
|
||||
<button id="denyFabButton" mat-menu-item (click)="bulkDeny()">{{'Requests.RequestPanel.Deny' | translate}}</button>
|
||||
<button *ngIf="is4kEnabled" id="deny4kFabButton" mat-menu-item (click)="bulkDeny4K()">{{'Requests.RequestPanel.Deny4K' | translate}}</button>
|
||||
<button id="deleteFabButton" mat-menu-item (click)="bulkDelete()">{{'Requests.RequestPanel.Delete' | translate}}</button>
|
||||
</mat-menu>
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<mat-menu #aboveMenu="matMenu" yPosition="above">
|
||||
<button id="approveFabButton" mat-menu-item (click)="bulkApprove()">{{ 'Requests.RequestPanel.Approve' | translate }}</button>
|
||||
<button *ngIf="is4kEnabled" id="approve4kFabButton" mat-menu-item (click)="bulkApprove4K()">
|
||||
{{ 'Requests.RequestPanel.Approve4K' | translate }}
|
||||
</button>
|
||||
<button id="denyFabButton" mat-menu-item (click)="bulkDeny()">{{ 'Requests.RequestPanel.Deny' | translate }}</button>
|
||||
<button *ngIf="is4kEnabled" id="deny4kFabButton" mat-menu-item (click)="bulkDeny4K()">{{ 'Requests.RequestPanel.Deny4K' | translate }}</button>
|
||||
<button id="deleteFabButton" mat-menu-item (click)="bulkDelete()">{{ 'Requests.RequestPanel.Delete' | translate }}</button>
|
||||
</mat-menu>
|
||||
|
|
|
@ -1,89 +1,152 @@
|
|||
<div class="mat-elevation-z8">
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
|
||||
<grid-spinner [loading]="isLoadingResults"></grid-spinner>
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
id="filterAll"
|
||||
(click)="switchFilter(RequestFilter.All)"
|
||||
[attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AllRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterPending"
|
||||
(click)="switchFilter(RequestFilter.Pending)"
|
||||
[attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.PendingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterProcessing"
|
||||
(click)="switchFilter(RequestFilter.Processing)"
|
||||
[attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.ProcessingRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterAvailable"
|
||||
(click)="switchFilter(RequestFilter.Available)"
|
||||
[attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.AvailableRequests' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="filterDenied"
|
||||
(click)="switchFilter(RequestFilter.Denied)"
|
||||
[attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'"
|
||||
[ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'"
|
||||
mat-raised-button
|
||||
class="grow"
|
||||
>
|
||||
{{ 'Requests.DeniedRequests' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select
|
||||
id="requestsToDisplayDropdown"
|
||||
placeholder="{{ 'Requests.RequestsToDisplay' | translate }}"
|
||||
[(value)]="gridCount"
|
||||
(selectionChange)="ngAfterViewInit()"
|
||||
>
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-md-center top-spacing">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" id="filterAll" (click)="switchFilter(RequestFilter.All)" [attr.color]="currentFilter === RequestFilter.All ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.All ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.AllRequests' | translate}}</button>
|
||||
<button type="button" id="filterPending" (click)="switchFilter(RequestFilter.Pending)" [attr.color]="currentFilter === RequestFilter.Pending ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Pending ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.PendingRequests' | translate}}</button>
|
||||
<button type="button" id="filterProcessing" (click)="switchFilter(RequestFilter.Processing)" [attr.color]="currentFilter === RequestFilter.Processing ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Processing ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.ProcessingRequests' | translate}}</button>
|
||||
<button type="button" id="filterAvailable" (click)="switchFilter(RequestFilter.Available)" [attr.color]="currentFilter === RequestFilter.Available ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Available ? 'mat-accent' : 'mat-primary'" mat-raised-button
|
||||
class="grow">{{'Requests.AvailableRequests' | translate}}</button>
|
||||
<button type="button" id="filterDenied" (click)="switchFilter(RequestFilter.Denied)" [attr.color]="currentFilter === RequestFilter.Denied ? 'accent' : 'primary'" [ngClass]="currentFilter === RequestFilter.Denied ? 'mat-accent' : 'mat-primary'" mat-raised-button class="grow">{{'Requests.DeniedRequests' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="dataSource"
|
||||
class="requests table"
|
||||
matSort
|
||||
[matSortActive]="defaultSort"
|
||||
matSortDisableClear
|
||||
[matSortDirection]="defaultOrder"
|
||||
>
|
||||
<ng-container matColumnDef="series">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.RequestsTitle' | translate }}</th>
|
||||
<td mat-cell id="title{{ element.id }}" *matCellDef="let element">{{ element.parentRequest.title }}</td>
|
||||
</ng-container>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 offset-md-10">
|
||||
<mat-form-field>
|
||||
<mat-select id="requestsToDisplayDropdown" placeholder="{{'Requests.RequestsToDisplay' | translate}}" [(value)]="gridCount" (selectionChange)="ngAfterViewInit()">
|
||||
<mat-option value="10">10</mat-option>
|
||||
<mat-option value="15">15</mat-option>
|
||||
<mat-option value="30">30</mat-option>
|
||||
<mat-option value="100">100</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container matColumnDef="requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.RequestedBy' | translate }}</th>
|
||||
<td mat-cell id="requestedBy{{ element.id }}" *matCellDef="let element">
|
||||
{{ element.requestedByAlias ? element.requestedByAlias : element.requestedUser.userAlias }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" class="requests table" matSort [matSortActive]="defaultSort" matSortDisableClear [matSortDirection]="defaultOrder">
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
|
||||
<td id="requestedDate{{ element.id }}" mat-cell *matCellDef="let element">
|
||||
{{ element.requestedDate | dfnsFormat: 'PP' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.RequestStatus' | translate }}</th>
|
||||
<td mat-cell id="requestedStatus{{ element.id }}" *matCellDef="let element">{{ element.requestStatus | translate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="series">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.RequestsTitle' | translate}} </th>
|
||||
<td mat-cell id="title{{element.id}}" *matCellDef="let element"> {{element.parentRequest.title}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.Status' | translate }}</th>
|
||||
<td mat-cell id="status{{ element.id }}" *matCellDef="let element">
|
||||
{{ element.parentRequest.status | translateStatus }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedBy">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.RequestedBy' | translate}} </th>
|
||||
<td mat-cell id="requestedBy{{element.id}}" *matCellDef="let element"> {{element.requestedByAlias ? element.requestedByAlias : element.requestedUser.userAlias}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="watchedByRequestedUser">
|
||||
<th mat-header-cell *matHeaderCellDef disableClear matTooltip="{{ 'Requests.WatchedProgressTooltip' | translate }}">
|
||||
{{ 'Requests.Watched' | translate }}
|
||||
</th>
|
||||
<td mat-cell id="requestedUserPlayedProgress{{ element.id }}" *matCellDef="let element">
|
||||
<mat-progress-bar mode="determinate" value="{{ element.requestedUserPlayedProgress }}" class="played-progress"></mat-progress-bar>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestedDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear> {{'Requests.RequestDate' | translate}} </th>
|
||||
<td id="requestedDate{{element.id}}" mat-cell *matCellDef="let element">
|
||||
{{element.requestedDate | amLocal | amUserLocale | amDateFormat: 'LL'}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a
|
||||
id="detailsButton{{ element.id }}"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[routerLink]="'/details/tv/' + element.parentRequest.externalProviderId"
|
||||
>{{ 'Requests.Details' | translate }}</a
|
||||
>
|
||||
<button id="optionsButton{{ element.id }}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin">
|
||||
{{ 'Requests.Options' | translate }}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="requestStatus">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.RequestStatus' | translate}} </th>
|
||||
<td mat-cell id="requestedStatus{{element.id}}" *matCellDef="let element"> {{element.requestStatus | translate}} </td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef> {{'Requests.Status' | translate}} </th>
|
||||
<td mat-cell id="status{{element.id}}" *matCellDef="let element">
|
||||
{{element.parentRequest.status | translateStatus }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="watchedByRequestedUser">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
disableClear
|
||||
matTooltip="{{ 'Requests.WatchedProgressTooltip' | translate}}">
|
||||
{{ 'Requests.Watched' | translate}}
|
||||
</th>
|
||||
<td mat-cell id="requestedUserPlayedProgress{{element.id}}" *matCellDef="let element">
|
||||
<mat-progress-bar mode="determinate" value="{{element.requestedUserPlayedProgress}}" class="played-progress"></mat-progress-bar>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<a id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/tv/' + element.parentRequest.externalProviderId">{{'Requests.Details' | translate}}</a>
|
||||
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin">{{'Requests.Options' | translate}}</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="gridCount"></mat-paginator>
|
||||
</div>
|
||||
|
|
|
@ -1,288 +1,316 @@
|
|||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" id="search" class="form-control form-control-custom searchwidth" [placeholder]="'Search.Search' | translate"
|
||||
(keyup)="search($event)">
|
||||
<span class="input-group-btn">
|
||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||
<i class="fas fa-filter"></i> {{ 'Requests.Filter' | translate }}
|
||||
</button>
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fas fa-sort"></i> {{ 'Requests.Sort' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
|
||||
<li>
|
||||
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' |
|
||||
translate }}
|
||||
|
||||
</a>
|
||||
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{
|
||||
'Requests.SortRequestDateDesc' | translate }}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.TitleDesc, $event)">{{ 'Requests.SortTitleDesc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.StatusAsc, $event)">{{ 'Requests.SortStatusAsc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.StatusDesc, $event)">{{ 'Requests.SortStatusDesc' | translate}}
|
||||
|
||||
</a>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
class="form-control form-control-custom searchwidth"
|
||||
[placeholder]="'Search.Search' | translate"
|
||||
(keyup)="search($event)"
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||
<i class="fas fa-filter"></i> {{ 'Requests.Filter' | translate }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="btn btn-sm btn-primary-outline dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<i class="fas fa-sort"></i> {{ 'Requests.Sort' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
|
||||
<li>
|
||||
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' | translate }} </a>
|
||||
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{ 'Requests.SortRequestDateDesc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.TitleDesc, $event)">{{ 'Requests.SortTitleDesc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.StatusAsc, $event)">{{ 'Requests.SortStatusAsc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.StatusDesc, $event)">{{ 'Requests.SortStatusDesc' | translate }} </a>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<div>
|
||||
<div *ngFor="let request of movieRequests">
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="request.backgroundPath"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
<div class="col-sm-2 small-padding">
|
||||
<div *ngFor="let request of movieRequests">
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="request.backgroundPath"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.6) 100%)"></div>
|
||||
<div class="col-sm-2 small-padding">
|
||||
<img class="img-responsive poster" src="{{ request.posterPath }}" alt="poster" />
|
||||
</div>
|
||||
|
||||
<img class="img-responsive poster" src="{{request.posterPath}}" alt="poster">
|
||||
<div class="col-sm-5 small-padding">
|
||||
<div>
|
||||
<a href="http://www.imdb.com/title/{{ request.imdbId }}/" target="_blank">
|
||||
<h4 class="request-title">{{ request.title }} ({{ request.releaseDate | dfnsFormat: 'P' }})</h4>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div class="request-info">
|
||||
<div class="request-by">
|
||||
<span>{{ 'Requests.RequestedBy' | translate }} </span>
|
||||
<span *ngIf="request.requestedByAlias">{{ request.requestedByAlias }}</span>
|
||||
<span *ngIf="!request.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{ request.requestedUser.userName }}</span>
|
||||
<span *ngIf="isAdmin && request.requestedUser.alias">{{ request.requestedUser.alias }}</span>
|
||||
<span *ngIf="isAdmin && !request.requestedUser.alias">{{ request.requestedUser.userName }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="request-status">
|
||||
<span>{{ 'Requests.Status' | translate }} </span>
|
||||
<span class="label label-success" id="requestedStatusLabel">{{ request.status }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="requested-status">
|
||||
<span>{{ 'Requests.RequestStatus' | translate }} </span>
|
||||
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
|
||||
<span
|
||||
*ngIf="request.approved && !request.available"
|
||||
id="processingRequestLabel"
|
||||
class="label label-info"
|
||||
[translate]="'Common.ProcessingRequest'"
|
||||
></span>
|
||||
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
|
||||
<span
|
||||
*ngIf="!request.approved && !request.availble && !request.denied"
|
||||
id="pendingApprovalLabel"
|
||||
class="label label-warning"
|
||||
[translate]="'Common.PendingApproval'"
|
||||
></span>
|
||||
</div>
|
||||
<div *ngIf="request.denied" id="requestDenied">
|
||||
{{ 'Requests.Denied' | translate }}
|
||||
<i style="color: red" class="fas fa-check" pTooltip="{{ request.deniedReason }}"></i>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-5 small-padding">
|
||||
<div>
|
||||
<a href="http://www.imdb.com/title/{{request.imdbId}}/" target="_blank">
|
||||
<h4 class="request-title">{{request.title}} ({{request.releaseDate | amLocal | amDateFormat:
|
||||
'YYYY'}})</h4>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div class="request-info">
|
||||
<div class="request-by">
|
||||
<span>{{ 'Requests.RequestedBy' | translate }} </span>
|
||||
<span *ngIf="request.requestedByAlias">{{request.requestedByAlias}}</span>
|
||||
<span *ngIf="!request.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span>
|
||||
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span>
|
||||
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="request-status">
|
||||
<span>{{ 'Requests.Status' | translate }} </span>
|
||||
<span class="label label-success" id="requestedStatusLabel">{{request.status}}</span>
|
||||
</div>
|
||||
<div id="releaseDate">
|
||||
{{ 'Requests.TheatricalRelease' | translate: { date: request.releaseDate | dfnsFormat: 'PP' } }}
|
||||
</div>
|
||||
<div *ngIf="request.digitalReleaseDate" id="digitalReleaseDate">
|
||||
{{ 'Requests.DigitalRelease' | translate: { date: request.digitalReleaseDate | dfnsFormat: 'PP' } }}
|
||||
</div>
|
||||
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | dfnsFormat: 'PP' }}</div>
|
||||
<br />
|
||||
</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="request.qualityOverrideTitle" class="quality-override">
|
||||
{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{ request.qualityOverrideTitle }} </span>
|
||||
</div>
|
||||
<div *ngIf="request.rootPathOverrideTitle" class="root-override">
|
||||
{{ 'Requests.RootFolderOverride' | translate }}
|
||||
<span>{{ request.rootPathOverrideTitle }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-push-6">
|
||||
<a
|
||||
*ngIf="request.showSubscribe && !request.subscribed"
|
||||
style="color: white"
|
||||
(click)="subscribe(request)"
|
||||
pTooltip="Subscribe for notifications"
|
||||
>
|
||||
<i class="fas fa-rss"></i>
|
||||
</a>
|
||||
<a
|
||||
*ngIf="request.showSubscribe && request.subscribed"
|
||||
style="color: red"
|
||||
(click)="unSubscribe(request)"
|
||||
pTooltip="Unsubscribe notification"
|
||||
>
|
||||
<i class="fas fa-rss"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="!request.approved" id="approveBtn">
|
||||
<form>
|
||||
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit">
|
||||
<i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="requested-status">
|
||||
<span>{{ 'Requests.RequestStatus' | translate }} </span>
|
||||
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
|
||||
<span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info"
|
||||
[translate]="'Common.ProcessingRequest'"></span>
|
||||
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
|
||||
<span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel"
|
||||
class="label label-warning" [translate]="'Common.PendingApproval'"></span>
|
||||
<!--Radarr Root Folder-->
|
||||
<div *ngIf="radarrRootFolders?.length > 1" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning-outline dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let folder of radarrRootFolders">
|
||||
<a href="#" (click)="selectRootFolder(request, folder, $event)">{{ folder.path }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div *ngIf="request.denied" id="requestDenied">
|
||||
{{ 'Requests.Denied' | translate }}
|
||||
<i style="color:red;" class="fas fa-check" pTooltip="{{request.deniedReason}}"></i>
|
||||
<!--Radarr Quality Profiles -->
|
||||
<div *ngIf="radarrProfiles?.length > 1" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning-outline dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let profile of radarrProfiles">
|
||||
<a href="#" (click)="selectQualityProfile(request, profile, $event)">{{ profile.name }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div *ngIf="!request.denied" id="denyBtn">
|
||||
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="markBtnGroup">
|
||||
<button
|
||||
id="unavailableBtn"
|
||||
*ngIf="request.available"
|
||||
(click)="changeAvailability(request, false)"
|
||||
style="text-align: right"
|
||||
value="false"
|
||||
class="btn btn-sm btn-info-outline change"
|
||||
>
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="availableBtn"
|
||||
*ngIf="!request.available"
|
||||
(click)="changeAvailability(request, true)"
|
||||
style="text-align: right"
|
||||
value="true"
|
||||
class="btn btn-sm btn-success-outline change"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(request)">
|
||||
<form>
|
||||
<button
|
||||
id="removeBtn"
|
||||
(click)="removeRequest(request)"
|
||||
style="text-align: right"
|
||||
class="btn btn-sm btn-danger-outline delete"
|
||||
>
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
||||
<button
|
||||
class="btn btn-sm btn-primary-outline dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, request)">{{ cat.value }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<div id="releaseDate">{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate |
|
||||
amLocal | amUserLocale | amDateFormat: 'LL'} }}</div>
|
||||
<div *ngIf="request.digitalReleaseDate" id="digitalReleaseDate">{{ 'Requests.DigitalRelease' |
|
||||
translate: {date: request.digitalReleaseDate | amLocal | amUserLocale | amDateFormat: 'LL'} }}</div>
|
||||
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal
|
||||
| amUserLocale | amDateFormat: 'LL'}}</div>
|
||||
<br />
|
||||
</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="request.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' |
|
||||
translate }}
|
||||
<span>{{request.qualityOverrideTitle}} </span>
|
||||
</div>
|
||||
<div *ngIf="request.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' |
|
||||
translate }}
|
||||
<span>{{request.rootPathOverrideTitle}} </span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-push-6">
|
||||
|
||||
<a *ngIf="request.showSubscribe && !request.subscribed" style="color:white" (click)="subscribe(request)"
|
||||
pTooltip="Subscribe for notifications">
|
||||
<i class="fas fa-rss"></i>
|
||||
</a>
|
||||
<a *ngIf="request.showSubscribe && request.subscribed" style="color:red" (click)="unSubscribe(request)"
|
||||
pTooltip="Unsubscribe notification">
|
||||
<i class="fas fa-rss"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="!request.approved" id="approveBtn">
|
||||
<form>
|
||||
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve"
|
||||
type="submit">
|
||||
<i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!--Radarr Root Folder-->
|
||||
<div *ngIf="radarrRootFolders?.length > 1" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let folder of radarrRootFolders">
|
||||
<a href="#" (click)="selectRootFolder(request, folder, $event)">{{folder.path}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Radarr Quality Profiles -->
|
||||
<div *ngIf="radarrProfiles?.length > 1" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let profile of radarrProfiles">
|
||||
<a href="#" (click)="selectQualityProfile(request, profile, $event)">{{profile.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!request.denied" id="denyBtn">
|
||||
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form id="markBtnGroup">
|
||||
<button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)"
|
||||
style="text-align: right" value="false" class="btn btn-sm btn-info-outline change">
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)"
|
||||
style="text-align: right" value="true" class="btn btn-sm btn-success-outline change">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(request)">
|
||||
<form>
|
||||
<button id="removeBtn" (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete">
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, request)">{{cat.value}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<p-paginator [rows]="10" [totalRecords]="totalMovies" (onPageChange)="paginate($event)"></p-paginator>
|
||||
<p-paginator [rows]="10" [totalRecords]="totalMovies" (onPageChange)="paginate($event)"></p-paginator>
|
||||
</div>
|
||||
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{ requestToDeny.title }}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest()" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay = false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
</p-dialog>
|
||||
|
||||
<issue-report [movie]="true" [visible]="issuesBarVisible" (visibleChange)="issuesBarVisible = $event;" [title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected" [id]="issueRequest?.id" [providerId]="issueProviderId"></issue-report>
|
||||
|
||||
<issue-report
|
||||
[movie]="true"
|
||||
[visible]="issuesBarVisible"
|
||||
(visibleChange)="issuesBarVisible = $event"
|
||||
[title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected"
|
||||
[id]="issueRequest?.id"
|
||||
[providerId]="issueProviderId"
|
||||
></issue-report>
|
||||
|
||||
<p-sidebar [(visible)]="filterDisplay" styleClass="ui-sidebar-md side-back side-small">
|
||||
<h3>{{ 'Requests.Filter' | translate }}</h3>
|
||||
<hr>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderAvailability' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Available" name="Availability" (click)="filterAvailability(filterType.Available, $event)">
|
||||
<label for="Available">{{ 'Common.Available' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="notAvailable" name="Availability" (click)="filterAvailability(filterType.NotAvailable, $event)">
|
||||
<label for="notAvailable">{{ 'Common.NotAvailable' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderRequestStatus' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="approved" name="Status" (click)="filterStatus(filterType.Approved, $event)">
|
||||
<label for="approved">{{ 'Filter.Approved' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Processing" name="Status" (click)="filterStatus(filterType.Processing, $event)">
|
||||
<label for="Processing">{{ 'Common.ProcessingRequest' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="pendingApproval" name="Status" (click)="filterStatus(filterType.PendingApproval, $event)">
|
||||
<label for="pendingApproval">{{ 'Filter.PendingApproval' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3>{{ 'Requests.Filter' | translate }}</h3>
|
||||
<hr />
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderAvailability' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Available" name="Availability" (click)="filterAvailability(filterType.Available, $event)" />
|
||||
<label for="Available">{{ 'Common.Available' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="notAvailable" name="Availability" (click)="filterAvailability(filterType.NotAvailable, $event)" />
|
||||
<label for="notAvailable">{{ 'Common.NotAvailable' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderRequestStatus' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="approved" name="Status" (click)="filterStatus(filterType.Approved, $event)" />
|
||||
<label for="approved">{{ 'Filter.Approved' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Processing" name="Status" (click)="filterStatus(filterType.Processing, $event)" />
|
||||
<label for="Processing">{{ 'Common.ProcessingRequest' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="pendingApproval" name="Status" (click)="filterStatus(filterType.PendingApproval, $event)" />
|
||||
<label for="pendingApproval">{{ 'Filter.PendingApproval' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm btn-primary-outline" (click)="clearFilter($event)">
|
||||
<i class="fas fa-filter"></i> {{ 'Filter.ClearFilter' | translate }}</button>
|
||||
<button class="btn btn-sm btn-primary-outline" (click)="clearFilter($event)">
|
||||
<i class="fas fa-filter"></i> {{ 'Filter.ClearFilter' | translate }}
|
||||
</button>
|
||||
</p-sidebar>
|
||||
|
|
|
@ -1,116 +1,107 @@
|
|||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" id="search" class="form-control form-control-custom searchwidth" [placeholder]="'Search.Search' | translate"
|
||||
(keyup)="search($event)">
|
||||
<span class="input-group-btn">
|
||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||
<i class="fas fa-filter"></i> {{ 'Requests.Filter' | translate }}
|
||||
</button>
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fas fa-sort"></i> {{ 'Requests.Sort' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
|
||||
<li>
|
||||
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' |
|
||||
translate }}
|
||||
|
||||
</a>
|
||||
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{
|
||||
'Requests.SortRequestDateDesc' | translate }}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.TitleDesc, $event)">{{ 'Requests.SortTitleDesc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.StatusAsc, $event)">{{ 'Requests.SortStatusAsc' | translate}}
|
||||
|
||||
</a>
|
||||
<a (click)="setOrder(OrderType.StatusDesc, $event)">{{ 'Requests.SortStatusDesc' | translate}}
|
||||
|
||||
</a>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
class="form-control form-control-custom searchwidth"
|
||||
[placeholder]="'Search.Search' | translate"
|
||||
(keyup)="search($event)"
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
|
||||
<i class="fas fa-filter"></i> {{ 'Requests.Filter' | translate }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="btn btn-sm btn-primary-outline dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<i class="fas fa-sort"></i> {{ 'Requests.Sort' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
|
||||
<li>
|
||||
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' | translate }} </a>
|
||||
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{ 'Requests.SortRequestDateDesc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.TitleDesc, $event)">{{ 'Requests.SortTitleDesc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.StatusAsc, $event)">{{ 'Requests.SortStatusAsc' | translate }} </a>
|
||||
<a (click)="setOrder(OrderType.StatusDesc, $event)">{{ 'Requests.SortStatusDesc' | translate }} </a>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<div class="col-md-12">
|
||||
<div *ngFor="let request of albumRequests" class="col-md-4">
|
||||
<div class="row">
|
||||
<div class="album-bg backdrop" [style.background-image]="request.background"></div>
|
||||
<div class="album-tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
<div *ngFor="let request of albumRequests" class="col-md-4">
|
||||
<div class="row">
|
||||
<div class="album-bg backdrop" [style.background-image]="request.background"></div>
|
||||
<div class="album-tint" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.6) 100%)"></div>
|
||||
|
||||
<div class="col-sm-12 small-padding">
|
||||
<img *ngIf="request.disk" class="img-responsive poster album-cover" src="{{request.disk}}" alt="poster">
|
||||
</div>
|
||||
<div class="col-sm-12 small-padding">
|
||||
<img *ngIf="request.disk" class="img-responsive poster album-cover" src="{{ request.disk }}" alt="poster" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 small-padding">
|
||||
<div>
|
||||
<h4>
|
||||
<a href="" target="_blank">
|
||||
{{ request.title | truncate: 36 }}
|
||||
</a>
|
||||
</h4>
|
||||
<h5>
|
||||
<a href="">
|
||||
{{ request.artistName }}
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 small-padding">
|
||||
<div>
|
||||
<h4>
|
||||
<a href="" target="_blank">
|
||||
{{request.title | truncate: 36}}
|
||||
</a>
|
||||
<div class="request-info">
|
||||
<div class="request-by">
|
||||
<span>{{ 'Requests.RequestedBy' | translate }} </span>
|
||||
<span *ngIf="request.requestedByAlias">{{ request.requestedByAlias }}</span>
|
||||
<span *ngIf="!request.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{ request.requestedUser.userName }}</span>
|
||||
<span *ngIf="isAdmin && request.requestedUser.alias">{{ request.requestedUser.alias }}</span>
|
||||
<span *ngIf="isAdmin && !request.requestedUser.alias">{{ request.requestedUser.userName }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</h4>
|
||||
<h5>
|
||||
<a href="">
|
||||
{{request.artistName}}
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="requested-status">
|
||||
<span>{{ 'Requests.RequestStatus' | translate }} </span>
|
||||
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
|
||||
<span
|
||||
*ngIf="request.approved && !request.available"
|
||||
id="processingRequestLabel"
|
||||
class="label label-info"
|
||||
[translate]="'Common.ProcessingRequest'"
|
||||
></span>
|
||||
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
|
||||
<span *ngIf="request.deniedReason" title="{{ request.deniedReason }}">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span
|
||||
*ngIf="!request.approved && !request.availble && !request.denied"
|
||||
id="pendingApprovalLabel"
|
||||
class="label label-warning"
|
||||
[translate]="'Common.PendingApproval'"
|
||||
></span>
|
||||
</div>
|
||||
<div *ngIf="request.denied" id="requestDenied">
|
||||
{{ 'Requests.Denied' | translate }}
|
||||
<i style="color: red" class="fas fa-check" pTooltip="{{ request.deniedReason }}"></i>
|
||||
</div>
|
||||
|
||||
<div class="request-info">
|
||||
<div class="request-by">
|
||||
<span>{{ 'Requests.RequestedBy' | translate }} </span>
|
||||
<span *ngIf="request.requestedByAlias">{{request.requestedByAlias}}</span>
|
||||
<span *ngIf="!request.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span>
|
||||
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span>
|
||||
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="requested-status">
|
||||
<span>{{ 'Requests.RequestStatus' | translate }} </span>
|
||||
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
|
||||
<span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info"
|
||||
[translate]="'Common.ProcessingRequest'"></span>
|
||||
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
|
||||
<span *ngIf="request.deniedReason" title="{{request.deniedReason}}">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel"
|
||||
class="label label-warning" [translate]="'Common.PendingApproval'"></span>
|
||||
|
||||
</div>
|
||||
<div *ngIf="request.denied" id="requestDenied">
|
||||
{{ 'Requests.Denied' | translate }}
|
||||
<i style="color:red;" class="fas fa-check" pTooltip="{{request.deniedReason}}"></i>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | amLocal |
|
||||
amDateFormat: 'LL'} }}</div>
|
||||
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal
|
||||
| amDateFormat: 'LL'}}</div>
|
||||
<br />
|
||||
</div>
|
||||
<!-- <div *ngIf="isAdmin">
|
||||
<div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: { date: request.releaseDate | dfnsFormat: 'PP' } }}</div>
|
||||
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | dfnsFormat: 'PP' }}</div>
|
||||
<br />
|
||||
</div>
|
||||
<!-- <div *ngIf="isAdmin">
|
||||
<div *ngIf="request.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{request.qualityOverrideTitle}} </span>
|
||||
</div>
|
||||
|
@ -118,10 +109,9 @@
|
|||
<span>{{request.rootPathOverrideTitle}} </span>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
<div class="col-sm-12 small-padding">
|
||||
<!-- <div class="row">
|
||||
</div>
|
||||
<div class="col-sm-12 small-padding">
|
||||
<!-- <div class="row">
|
||||
<div class="col-md-2 col-md-push-6">
|
||||
|
||||
<a *ngIf="request.showSubscribe && !request.subscribed" style="color:white" (click)="subscribe(request)" pTooltip="Subscribe for notifications">
|
||||
|
@ -132,17 +122,16 @@
|
|||
</a>
|
||||
</div>
|
||||
</div> -->
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="!request.approved" id="approveBtn">
|
||||
<form class="col-md-6">
|
||||
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve"
|
||||
type="submit">
|
||||
<i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="!request.approved" id="approveBtn">
|
||||
<form class="col-md-6">
|
||||
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit">
|
||||
<i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!--Radarr Root Folder-->
|
||||
<!-- <div *ngIf="radarrRootFolders" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<!--Radarr Root Folder-->
|
||||
<!-- <div *ngIf="radarrRootFolders" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
|
||||
</button>
|
||||
|
@ -157,8 +146,8 @@
|
|||
</ul>
|
||||
</div> -->
|
||||
|
||||
<!--Radarr Quality Profiles -->
|
||||
<!-- <div *ngIf="radarrProfiles" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<!--Radarr Quality Profiles -->
|
||||
<!-- <div *ngIf="radarrProfiles" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
|
||||
</button>
|
||||
|
@ -173,117 +162,129 @@
|
|||
</ul>
|
||||
</div> -->
|
||||
|
||||
<div *ngIf="!request.denied" id="denyBtn" class="col-md-6">
|
||||
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!request.denied" id="denyBtn" class="col-md-6">
|
||||
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="markBtnGroup">
|
||||
<button
|
||||
id="unavailableBtn"
|
||||
*ngIf="request.available"
|
||||
(click)="changeAvailability(request, false)"
|
||||
style="text-align: right"
|
||||
value="false"
|
||||
class="btn btn-sm btn-info-outline change"
|
||||
>
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="availableBtn"
|
||||
*ngIf="!request.available"
|
||||
(click)="changeAvailability(request, true)"
|
||||
style="text-align: right"
|
||||
value="true"
|
||||
class="btn btn-sm btn-success-outline change"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(request)">
|
||||
<form id="removeBtn">
|
||||
<button (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete">
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
||||
<button
|
||||
class="btn btn-sm btn-primary-outline dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, request)">{{ cat.value }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<form id="markBtnGroup">
|
||||
<button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)"
|
||||
style="text-align: right" value="false" class="btn btn-sm btn-info-outline change">
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)"
|
||||
style="text-align: right" value="true" class="btn btn-sm btn-success-outline change">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(request)">
|
||||
<form id="removeBtn">
|
||||
<button (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete">
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, request)">{{cat.value}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<p-paginator [rows]="10" [totalRecords]="totalAlbums" (onPageChange)="paginate($event)"></p-paginator>
|
||||
<p-paginator [rows]="10" [totalRecords]="totalAlbums" (onPageChange)="paginate($event)"></p-paginator>
|
||||
</div>
|
||||
|
||||
|
||||
<issue-report [movie]="true" [visible]="issuesBarVisible" (visibleChange)="issuesBarVisible = $event;" [title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected" [id]="issueRequest?.id" [providerId]="issueProviderId"></issue-report>
|
||||
|
||||
<issue-report
|
||||
[movie]="true"
|
||||
[visible]="issuesBarVisible"
|
||||
(visibleChange)="issuesBarVisible = $event"
|
||||
[title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected"
|
||||
[id]="issueRequest?.id"
|
||||
[providerId]="issueProviderId"
|
||||
></issue-report>
|
||||
|
||||
<p-sidebar [(visible)]="filterDisplay" styleClass="ui-sidebar-md side-back side-small">
|
||||
<h3>{{ 'Requests.Filter' | translate }}</h3>
|
||||
<hr>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderAvailability' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Available" name="Availability" (click)="filterAvailability(filterType.Available, $event)">
|
||||
<label for="Available">{{ 'Common.Available' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="notAvailable" name="Availability" (click)="filterAvailability(filterType.NotAvailable, $event)">
|
||||
<label for="notAvailable">{{ 'Common.NotAvailable' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderRequestStatus' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="approved" name="Status" (click)="filterStatus(filterType.Approved, $event)">
|
||||
<label for="approved">{{ 'Filter.Approved' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Processing" name="Status" (click)="filterStatus(filterType.Processing, $event)">
|
||||
<label for="Processing">{{ 'Common.ProcessingRequest' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="pendingApproval" name="Status" (click)="filterStatus(filterType.PendingApproval, $event)">
|
||||
<label for="pendingApproval">{{ 'Filter.PendingApproval' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3>{{ 'Requests.Filter' | translate }}</h3>
|
||||
<hr />
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderAvailability' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Available" name="Availability" (click)="filterAvailability(filterType.Available, $event)" />
|
||||
<label for="Available">{{ 'Common.Available' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="notAvailable" name="Availability" (click)="filterAvailability(filterType.NotAvailable, $event)" />
|
||||
<label for="notAvailable">{{ 'Common.NotAvailable' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ 'Filter.FilterHeaderRequestStatus' | translate }}</h4>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="approved" name="Status" (click)="filterStatus(filterType.Approved, $event)" />
|
||||
<label for="approved">{{ 'Filter.Approved' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Processing" name="Status" (click)="filterStatus(filterType.Processing, $event)" />
|
||||
<label for="Processing">{{ 'Common.ProcessingRequest' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="pendingApproval" name="Status" (click)="filterStatus(filterType.PendingApproval, $event)" />
|
||||
<label for="pendingApproval">{{ 'Filter.PendingApproval' | translate }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm btn-primary-outline" (click)="clearFilter($event)">
|
||||
<i class="fas fa-filter"></i> {{ 'Filter.ClearFilter' | translate }}</button>
|
||||
<button class="btn btn-sm btn-primary-outline" (click)="clearFilter($event)">
|
||||
<i class="fas fa-filter"></i> {{ 'Filter.ClearFilter' | translate }}
|
||||
</button>
|
||||
</p-sidebar>
|
||||
|
||||
|
||||
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{ requestToDeny.title }}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest()" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay = false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
</p-dialog>
|
|
@ -1,128 +1,167 @@
|
|||
<div *ngIf="childRequests">
|
||||
<hr />
|
||||
<div *ngFor="let child of childRequests" class="clearfix">
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<div *ngFor="let child of childRequests" class="clearfix">
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-2">
|
||||
<span [translate]="'Requests.RequestedBy'"></span>
|
||||
<span *ngIf="child.requestedByAlias">{{ child.requestedByAlias }}</span>
|
||||
<span *ngIf="!child.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{ child.requestedUser.userName }}</span>
|
||||
<span *ngIf="isAdmin && child.requestedUser.alias">{{ child.requestedUser.alias }}</span>
|
||||
<span *ngIf="isAdmin && !child.requestedUser.alias">{{ child.requestedUser.userName }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-2">
|
||||
<span [translate]="'Requests.RequestedBy'"></span>
|
||||
<span *ngIf="child.requestedByAlias">{{child.requestedByAlias}}</span>
|
||||
<span *ngIf="!child.requestedByAlias">
|
||||
<span *ngIf="!isAdmin">{{child.requestedUser.userName}}</span>
|
||||
<span *ngIf="isAdmin && child.requestedUser.alias">{{child.requestedUser.alias}}</span>
|
||||
<span *ngIf="isAdmin && !child.requestedUser.alias">{{child.requestedUser.userName}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-1 col-md-push-9">
|
||||
<button
|
||||
id="subscribeBtn"
|
||||
*ngIf="child.showSubscribe && !child.subscribed"
|
||||
(click)="subscribe(child)"
|
||||
class="btn btn-sm btn-primary-outline"
|
||||
pTooltip="Subscribe for notifications"
|
||||
type="submit"
|
||||
>
|
||||
<i class="fas fa-rss"></i> Subscribe
|
||||
</button>
|
||||
<button
|
||||
id="subscribeBtn"
|
||||
*ngIf="child.showSubscribe && child.subscribed"
|
||||
(click)="unSubscribe(child)"
|
||||
class="btn btn-sm btn-danger-outline"
|
||||
pTooltip="UnSubscribe for notifications"
|
||||
type="submit"
|
||||
>
|
||||
<i class="fas fa-rss"></i> UnSubscribe
|
||||
</button>
|
||||
|
||||
<div class="col-md-1 col-md-push-9">
|
||||
<button id="subscribeBtn" *ngIf="child.showSubscribe && !child.subscribed" (click)="subscribe(child)"
|
||||
class="btn btn-sm btn-primary-outline" pTooltip="Subscribe for notifications" type="submit"><i
|
||||
class="fas fa-rss"></i> Subscribe</button>
|
||||
<button id="subscribeBtn" *ngIf="child.showSubscribe && child.subscribed" (click)="unSubscribe(child)"
|
||||
class="btn btn-sm btn-danger-outline" pTooltip="UnSubscribe for notifications" type="submit"><i
|
||||
class="fas fa-rss"></i> UnSubscribe</button>
|
||||
<div *ngIf="isAdmin">
|
||||
<button
|
||||
id="approveBtn"
|
||||
*ngIf="child.canApprove && !child.approved"
|
||||
(click)="approve(child)"
|
||||
class="btn btn-sm btn-success-outline"
|
||||
type="submit"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="unavailableBtn"
|
||||
*ngIf="child.available"
|
||||
(click)="changeAvailability(child, false)"
|
||||
style="text-align: right"
|
||||
value="false"
|
||||
class="btn btn-sm btn-info-outline change"
|
||||
>
|
||||
<i class="fas fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="availableBtn"
|
||||
*ngIf="!child.available"
|
||||
(click)="changeAvailability(child, true)"
|
||||
style="text-align: right"
|
||||
value="true"
|
||||
class="btn btn-sm btn-success-outline change"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
|
||||
</button>
|
||||
|
||||
<button id="denyBtn" *ngIf="!child.denied" type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(child)">
|
||||
<button id="removeBtn" type="button" (click)="removeRequest(child)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Remove' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<ngb-tabset>
|
||||
<div *ngFor="let season of child.seasonRequests">
|
||||
<ngb-tab [id]="season.seasonNumber" [title]="season.seasonNumber">
|
||||
<ng-template ngbTabContent>
|
||||
<h2>{{ 'Requests.Season' | translate }} {{ season.seasonNumber }}</h2>
|
||||
|
||||
<div *ngIf="isAdmin">
|
||||
<button id="approveBtn" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline"
|
||||
type="submit"><i class="fas fa-plus"></i> {{ 'Common.Approve' | translate }}</button>
|
||||
<button id="unavailableBtn" *ngIf="child.available" (click)="changeAvailability(child, false)"
|
||||
style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fas fa-minus"></i>
|
||||
{{ 'Requests.MarkUnavailable' | translate }}</button>
|
||||
<button id="availableBtn" *ngIf="!child.available" (click)="changeAvailability(child, true)" style="text-align: right"
|
||||
value="true" class="btn btn-sm btn-success-outline change"><i class="fas fa-plus"></i> {{
|
||||
'Requests.MarkAvailable' | translate }}</button>
|
||||
|
||||
<button id="denyBtn" *ngIf="!child.denied" type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny">
|
||||
<i class="fas fa-times"></i> {{ 'Requests.Deny' | translate }}</button>
|
||||
|
||||
</div>
|
||||
<div *ngIf="isAdmin || isRequestUser(child)">
|
||||
<button id="removeBtn" type="button" (click)="removeRequest(child)" class="btn btn-sm btn-danger-outline deny"><i
|
||||
class="fas fa-times"></i> {{ 'Requests.Remove' | translate }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<ngb-tabset>
|
||||
|
||||
<div *ngFor="let season of child.seasonRequests">
|
||||
<ngb-tab [id]="season.seasonNumber" [title]="season.seasonNumber">
|
||||
<ng-template ngbTabContent>
|
||||
<h2>{{ 'Requests.Season' | translate }} {{season.seasonNumber}}</h2>
|
||||
|
||||
<table class="table table-striped table-hover table-responsive table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a>
|
||||
#
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.GridTitle' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.AirDate' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.GridStatus' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let ep of season.episodes">
|
||||
<td>
|
||||
{{ep.episodeNumber}}
|
||||
</td>
|
||||
<td>
|
||||
{{ep.title}}
|
||||
</td>
|
||||
<td>
|
||||
{{ep.airDate | amLocal | amUserLocale | amDateFormat: 'L' }}
|
||||
</td>
|
||||
<td>
|
||||
<span *ngIf="child.denied" class="label label-danger" id="deniedLabel"
|
||||
[translate]="'Common.Denied'">
|
||||
<i style="color:red;" class="fas fa-check" pTooltip="{{child.deniedReason}}"></i>
|
||||
</span>
|
||||
<span *ngIf="!child.denied && ep.available" class="label label-success" id="availableLabel"
|
||||
[translate]="'Common.Available'"></span>
|
||||
<span *ngIf="!child.denied &&ep.approved && !ep.available" class="label label-info"
|
||||
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span>
|
||||
<div *ngIf="!child.denied && !ep.approved">
|
||||
<div *ngIf="!ep.available"><span class="label label-warning" id="pendingApprovalLabel"
|
||||
[translate]="'Common.PendingApproval'"></span></div>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ng-template>
|
||||
</ngb-tab>
|
||||
</div>
|
||||
</ngb-tabset>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-hover table-responsive table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a> # </a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.GridTitle' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.AirDate' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a>
|
||||
{{ 'Requests.GridStatus' | translate }}
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let ep of season.episodes">
|
||||
<td>
|
||||
{{ ep.episodeNumber }}
|
||||
</td>
|
||||
<td>
|
||||
{{ ep.title }}
|
||||
</td>
|
||||
<td>
|
||||
{{ ep.airDate | dfnsFormat: 'P' }}
|
||||
</td>
|
||||
<td>
|
||||
<span *ngIf="child.denied" class="label label-danger" id="deniedLabel" [translate]="'Common.Denied'">
|
||||
<i style="color: red" class="fas fa-check" pTooltip="{{ child.deniedReason }}"></i>
|
||||
</span>
|
||||
<span
|
||||
*ngIf="!child.denied && ep.available"
|
||||
class="label label-success"
|
||||
id="availableLabel"
|
||||
[translate]="'Common.Available'"
|
||||
></span>
|
||||
<span
|
||||
*ngIf="!child.denied && ep.approved && !ep.available"
|
||||
class="label label-info"
|
||||
id="processingRequestLabel"
|
||||
[translate]="'Common.ProcessingRequest'"
|
||||
></span>
|
||||
<div *ngIf="!child.denied && !ep.approved">
|
||||
<div *ngIf="!ep.available">
|
||||
<span
|
||||
class="label label-warning"
|
||||
id="pendingApprovalLabel"
|
||||
[translate]="'Common.PendingApproval'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ng-template>
|
||||
</ngb-tab>
|
||||
</div>
|
||||
</ngb-tabset>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{ requestToDeny.title }}''" [(visible)]="denyDisplay" [draggable]="false">
|
||||
<span>Please enter a rejection reason, the user will be notified of this:</span>
|
||||
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
|
||||
<p-footer>
|
||||
<button type="button" (click)="denyRequest()" label="Reject" class="btn btn-success">Deny</button>
|
||||
<button type="button" (click)="denyDisplay = false" label="Close" class="btn btn-danger">Close</button>
|
||||
</p-footer>
|
||||
</p-dialog>
|
|
@ -1,112 +1,146 @@
|
|||
<div class="form-group">
|
||||
<div>
|
||||
<input type="text" id="search" class="form-control form-control-custom" [placeholder]="'Common.Search' | translate" (keyup)="search($event)">
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
class="form-control form-control-custom"
|
||||
[placeholder]="'Common.Search' | translate"
|
||||
(keyup)="search($event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div>
|
||||
<div *ngFor="let node of tvRequests.collection">
|
||||
<!--This is the section that holds the parent level results set-->
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="node?.background"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
|
||||
<div *ngFor="let node of tvRequests.collection">
|
||||
<!--This is the section that holds the parent level results set-->
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="myBg backdrop" [style.background-image]="node?.background"></div>
|
||||
<div class="tint" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.6) 100%)"></div>
|
||||
|
||||
<div class="col-sm-2 small-padding">
|
||||
<div class="col-sm-2 small-padding">
|
||||
<img class="img-responsive poster" src="{{ node.posterPath || null }}" alt="poster" />
|
||||
</div>
|
||||
|
||||
<img class="img-responsive poster" src="{{node.posterPath || null}}" alt="poster">
|
||||
<div class="col-sm-5 small-padding">
|
||||
<div>
|
||||
<a href="http://www.imdb.com/title/{{ node.imdbId }}/" target="_blank">
|
||||
<h4 class="request-title">{{ node.title }} ({{ node.releaseDate | dfnsFormat: 'P' }})</h4>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<span>Status: </span>
|
||||
<span class="label label-success">{{ node.status }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div>Release Date: {{ node.releaseDate | dfnsFormat: 'PP' }}</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="node.qualityOverrideTitle" class="quality-override">
|
||||
{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{ node.qualityOverrideTitle }} </span>
|
||||
</div>
|
||||
<div *ngIf="node.rootPathOverrideTitle" class="root-override">
|
||||
{{ 'Requests.RootFolderOverride' | translate }}
|
||||
<span>{{ node.rootPathOverrideTitle }} </span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-5 small-padding">
|
||||
<div>
|
||||
<a href="http://www.imdb.com/title/{{node.imdbId}}/" target="_blank">
|
||||
<h4 class="request-title">{{node.title}} ({{node.releaseDate | amLocal| amUserLocale | amDateFormat: 'YYYY'}})</h4>
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<span>Status: </span>
|
||||
<span class="label label-success">{{node.status}}</span>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
||||
<button style="text-align: right" class="btn btn-sm btn-success-outline" (click)="openClosestTab(node, $event)">
|
||||
<i class="fas fa-plus"></i> View
|
||||
</button>
|
||||
<div *ngIf="isAdmin">
|
||||
<!--Sonarr Root Folder-->
|
||||
<div *ngIf="sonarrRootFolders?.length > 1" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning-outline dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let folder of sonarrRootFolders">
|
||||
<a href="#" (click)="selectRootFolder(node, folder, $event)">{{ folder.path }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Sonarr Quality Profiles -->
|
||||
<div *ngIf="sonarrProfiles?.length > 1" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning-outline dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let profile of sonarrProfiles">
|
||||
<a href="#" (click)="selectQualityProfile(node, profile, $event)">{{ profile.name }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issueBtn">
|
||||
<button
|
||||
class="btn btn-sm btn-primary-outline dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, node)">{{ cat.value }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
||||
<div *ngIf="node.open">
|
||||
<tvrequests-children
|
||||
[childRequests]="node.childRequests"
|
||||
[isAdmin]="isAdmin"
|
||||
[currentUser]="currentUser"
|
||||
(requestDeleted)="childRequestDeleted($event)"
|
||||
></tvrequests-children>
|
||||
</div>
|
||||
|
||||
<div>Release Date: {{node.releaseDate | amLocal | amUserLocale | amDateFormat: 'LL'}}</div>
|
||||
<div *ngIf="isAdmin">
|
||||
<div *ngIf="node.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' | translate }}
|
||||
<span>{{node.qualityOverrideTitle}} </span>
|
||||
</div>
|
||||
<div *ngIf="node.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' | translate }}
|
||||
<span>{{node.rootPathOverrideTitle}} </span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
||||
|
||||
<button style="text-align: right" class="btn btn-sm btn-success-outline" (click)="openClosestTab(node,$event)">
|
||||
<i class="fas fa-plus"></i> View</button>
|
||||
<div *ngIf="isAdmin">
|
||||
<!--Sonarr Root Folder-->
|
||||
<div *ngIf="sonarrRootFolders?.length > 1" class="btn-group btn-split" id="rootFolderBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let folder of sonarrRootFolders">
|
||||
<a href="#" (click)="selectRootFolder(node, folder, $event)">{{folder.path}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Sonarr Quality Profiles -->
|
||||
<div *ngIf="sonarrProfiles?.length > 1" class="btn-group btn-split" id="changeQualityBtn">
|
||||
<button type="button" class="btn btn-sm btn-warning-outline">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li *ngFor="let profile of sonarrProfiles">
|
||||
<a href="#" (click)="selectQualityProfile(node, profile, $event)">{{profile.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issueBtn">
|
||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fas fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li *ngFor="let cat of issueCategories">
|
||||
<a [routerLink]="" (click)="reportIssue(cat, node)">{{cat.value}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
||||
<div *ngIf="node.open">
|
||||
<tvrequests-children [childRequests]="node.childRequests" [isAdmin]="isAdmin" [currentUser]="currentUser" (requestDeleted)="childRequestDeleted($event)"></tvrequests-children>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
|
||||
<p-paginator [rows]="10" [totalRecords]="totalTv" (onPageChange)="paginate($event)"></p-paginator>
|
||||
<p-paginator [rows]="10" [totalRecords]="totalTv" (onPageChange)="paginate($event)"></p-paginator>
|
||||
</div>
|
||||
|
||||
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title" [issueCategory]="issueCategorySelected" [id]="issueRequest?.id" [providerId]="issueProviderId" (visibleChange)="issuesBarVisible = $event;"></issue-report>
|
||||
<issue-report
|
||||
[movie]="false"
|
||||
[visible]="issuesBarVisible"
|
||||
[title]="issueRequest?.title"
|
||||
[issueCategory]="issueCategorySelected"
|
||||
[id]="issueRequest?.id"
|
||||
[providerId]="issueProviderId"
|
||||
(visibleChange)="issuesBarVisible = $event"
|
||||
></issue-report>
|
||||
|
|
|
@ -1,28 +1,21 @@
|
|||
|
||||
|
||||
<h1 mat-dialog-title><i class="fas fa-code-branch"></i> Latest Version: {{data.updateVersionString}}</h1>
|
||||
<h1 mat-dialog-title><i class="fas fa-code-branch"></i> Latest Version: {{ data.updateVersionString }}</h1>
|
||||
<mat-dialog-content>
|
||||
<div [innerHTML]="data.changeLogs">
|
||||
</div>
|
||||
<div [innerHTML]="data.changeLogs"></div>
|
||||
|
||||
<div class="mat-table">
|
||||
<div class="mat-header-row">
|
||||
<div class="mat-header-cell">Binary</div>
|
||||
<div class="mat-header-cell">Download</div>
|
||||
</div>
|
||||
<div *ngFor="let d of data.downloads" class="mat-row">
|
||||
<div class="mat-cell">{{ d.name }}</div>
|
||||
<div class="mat-cell"><a href="{{ d.url }}">Download</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mat-table">
|
||||
<div class="mat-header-row">
|
||||
<div class="mat-header-cell">Binary</div>
|
||||
<div class="mat-header-cell">Download</div></div>
|
||||
<div *ngFor="let d of data.downloads" class="mat-row" >
|
||||
<div class="mat-cell">{{d.name}}</div>
|
||||
<div class="mat-cell"><a href="{{d.url}}">Download</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<small>Updated at {{data.updateDate | amUserLocale | amDateFormat: 'LL' }}</small>
|
||||
<small>Updated at {{ data.updateDate | dfnsFormat: 'PP' }}</small>
|
||||
</mat-dialog-content>
|
||||
|
||||
|
||||
<div mat-dialog-actions class="right-buttons">
|
||||
<button mat-raised-button id="cancelButton" [mat-dialog-close]="" color="warn"><i class="fas fa-times"></i> Close</button>
|
||||
<button mat-raised-button id="cancelButton" [mat-dialog-close]="" color="warn"><i class="fas fa-times"></i> Close</button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
<div class='container'>
|
||||
<div class='chatbox'>
|
||||
<div class='chatbox__user-list'>
|
||||
<h1>{{ "NavigationBar.UserManagement" | translate }}</h1>
|
||||
<div class='chatbox__user--active' *ngFor="let user of userList">
|
||||
<p>{{user}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chatbox-message-box">
|
||||
<div class="chatbox__messages" *ngFor="let m of messages">
|
||||
<div class="chatbox__messages__user-message">
|
||||
<div class="chatbox__messages__user-message--ind-message" [ngClass]="{'sender': m.chatType === ChatType.Sender, 'reciever':m.chatType === ChatType.Reciever }">
|
||||
<p class="name" *ngIf="m?.username">{{m.username}}</p>
|
||||
<br/>
|
||||
<p class="message">{{m.message}}</p>
|
||||
<p class="timestamp">{{m.date | amFromUtc | amLocal | amUserLocale | amDateFormat: 'l LT'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form">
|
||||
<input type="text" [(ngModel)]="currentMessage" [placeholder]="'Issues.EnterYourMessage' | translate">
|
||||
<button mat-raised-button class="add-message" (click)="addMessage()">{{ "Issues.SendMessageButton" | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="chatbox">
|
||||
<div class="chatbox__user-list">
|
||||
<h1>{{ 'NavigationBar.UserManagement' | translate }}</h1>
|
||||
<div class="chatbox__user--active" *ngFor="let user of userList">
|
||||
<p>{{ user }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chatbox-message-box">
|
||||
<div class="chatbox__messages" *ngFor="let m of messages">
|
||||
<div class="chatbox__messages__user-message">
|
||||
<div
|
||||
class="chatbox__messages__user-message--ind-message"
|
||||
[ngClass]="{ sender: m.chatType === ChatType.Sender, reciever: m.chatType === ChatType.Reciever }"
|
||||
>
|
||||
<p class="name" *ngIf="m?.username">{{ m.username }}</p>
|
||||
<br />
|
||||
<p class="message">{{ m.message }}</p>
|
||||
<p class="timestamp">{{ m.date | dfnsFormat: 'Ppp' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form">
|
||||
<input type="text" [(ngModel)]="currentMessage" [placeholder]="'Issues.EnterYourMessage' | translate" />
|
||||
<button mat-raised-button class="add-message" (click)="addMessage()">{{ 'Issues.SendMessageButton' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,74 +1,93 @@
|
|||
<div mat-dialog-content class="background">
|
||||
<div *ngIf="!requestable">
|
||||
{{'MediaDetails.EpisodeSelector.NoEpisodes' | translate}}
|
||||
</div>
|
||||
<div *ngIf="requestable" class="row">
|
||||
<div class="col-12 action-buttons-right">
|
||||
<button id="episodeModalAllSeasons" (click)="requestAllSeasons()" color="primary" mat-raised-button class="btn-spacing"
|
||||
matTooltip="{{'MediaDetails.EpisodeSelector.AllSeasonsTooltip' | translate}}">{{'Search.TvShows.AllSeasons' | translate }}</button>
|
||||
<div *ngIf="!requestable">
|
||||
{{ 'MediaDetails.EpisodeSelector.NoEpisodes' | translate }}
|
||||
</div>
|
||||
<div *ngIf="requestable" class="row">
|
||||
<div class="col-12 action-buttons-right">
|
||||
<button
|
||||
id="episodeModalAllSeasons"
|
||||
(click)="requestAllSeasons()"
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
class="btn-spacing"
|
||||
matTooltip="{{ 'MediaDetails.EpisodeSelector.AllSeasonsTooltip' | translate }}"
|
||||
>
|
||||
{{ 'Search.TvShows.AllSeasons' | translate }}
|
||||
</button>
|
||||
|
||||
<button id="episodeModalFirstSeason" (click)="requestFirstSeason()" color="accent" mat-raised-button class="btn-spacing"
|
||||
matTooltip="{{'MediaDetails.EpisodeSelector.FirstSeasonTooltip' | translate}}">{{ 'Search.TvShows.FirstSeason' | translate }}</button>
|
||||
<button id="episodeModalLatestSeason" (click)="requestLatestSeason()" color="warn" mat-raised-button class="btn-spacing"
|
||||
matTooltip="{{'MediaDetails.EpisodeSelector.LatestSeasonTooltip' | translate}}">{{ 'Search.TvShows.LatestSeason' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
id="episodeModalFirstSeason"
|
||||
(click)="requestFirstSeason()"
|
||||
color="accent"
|
||||
mat-raised-button
|
||||
class="btn-spacing"
|
||||
matTooltip="{{ 'MediaDetails.EpisodeSelector.FirstSeasonTooltip' | translate }}"
|
||||
>
|
||||
{{ 'Search.TvShows.FirstSeason' | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="episodeModalLatestSeason"
|
||||
(click)="requestLatestSeason()"
|
||||
color="warn"
|
||||
mat-raised-button
|
||||
class="btn-spacing"
|
||||
matTooltip="{{ 'MediaDetails.EpisodeSelector.LatestSeasonTooltip' | translate }}"
|
||||
>
|
||||
{{ 'Search.TvShows.LatestSeason' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12" *ngFor="let season of data.series.seasonRequests">
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<mat-checkbox *ngIf="!season.seasonAvailable && isSeasonCheckable(season)" (click)="$event.stopPropagation();" (change)="seasonChanged($event, season)">
|
||||
{{ 'MediaDetails.EpisodeSelector.SeasonNumber' | translate: { number: season.seasonNumber } }}</mat-checkbox>
|
||||
<span *ngIf="season.seasonAvailable || !isSeasonCheckable(season)">{{ 'MediaDetails.EpisodeSelector.SeasonNumber' | translate: { number: season.seasonNumber } }}</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<!-- Description -->
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="row">
|
||||
<div class="col-12" *ngFor="let season of data.series.seasonRequests">
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<mat-checkbox
|
||||
*ngIf="!season.seasonAvailable && isSeasonCheckable(season)"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="seasonChanged($event, season)"
|
||||
>
|
||||
{{ 'MediaDetails.EpisodeSelector.SeasonNumber' | translate: { number: season.seasonNumber } }}</mat-checkbox
|
||||
>
|
||||
<span *ngIf="season.seasonAvailable || !isSeasonCheckable(season)">{{
|
||||
'MediaDetails.EpisodeSelector.SeasonNumber' | translate: { number: season.seasonNumber }
|
||||
}}</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<!-- Description -->
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="row" *ngFor="let ep of season.episodes">
|
||||
<div class="col-1">
|
||||
<div *ngIf="!ep.available && !ep.requested && !ep.approved">
|
||||
<mat-checkbox *ngIf="!ep.selected" [ngModel]="ep.selected" (click)="addRequest(ep)"></mat-checkbox>
|
||||
<mat-checkbox *ngIf="ep.selected" [ngModel]="ep.selected" (click)="removeRequest(ep)"></mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
{{ep.episodeNumber}}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{{ep.title}}
|
||||
</div>
|
||||
<div class="col-2" *ngIf="ep.airDateDisplay != 'Unknown'">
|
||||
{{ep.airDate | amLocal | amUserLocale | amDateFormat: 'L' }}
|
||||
</div>
|
||||
<div class="col-2" *ngIf="ep.airDateDisplay == 'Unknown'">
|
||||
{{ep.airDateDisplay }}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{{ep.requestStatus | translate}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</mat-expansion-panel>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="row" *ngFor="let ep of season.episodes">
|
||||
<div class="col-1">
|
||||
<div *ngIf="!ep.available && !ep.requested && !ep.approved">
|
||||
<mat-checkbox *ngIf="!ep.selected" [ngModel]="ep.selected" (click)="addRequest(ep)"></mat-checkbox>
|
||||
<mat-checkbox *ngIf="ep.selected" [ngModel]="ep.selected" (click)="removeRequest(ep)"></mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
{{ ep.episodeNumber }}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{{ ep.title }}
|
||||
</div>
|
||||
<div class="col-2" *ngIf="ep.airDateDisplay != 'Unknown'">
|
||||
{{ ep.airDate | dfnsFormat: 'P' }}
|
||||
</div>
|
||||
<div class="col-2" *ngIf="ep.airDateDisplay == 'Unknown'">
|
||||
{{ ep.airDateDisplay }}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{{ ep.requestStatus | translate }}
|
||||
</div>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div mat-dialog-actions *ngIf="requestable">
|
||||
<div class="action-buttons-right">
|
||||
|
||||
<button (click)="submitRequests()" mat-raised-button class="btn-spacing btn-orange">{{
|
||||
'Common.Request' | translate }}</button>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="action-buttons-right">
|
||||
<button (click)="submitRequests()" mat-raised-button class="btn-spacing btn-orange">{{ 'Common.Request' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,141 +1,141 @@
|
|||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AdminRequestDialogComponent } from "./admin-request-dialog/admin-request-dialog.component";
|
||||
import { AdvancedSearchDialogComponent } from "./advanced-search-dialog/advanced-search-dialog.component";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { DetailsGroupComponent } from "../issues/components/details-group/details-group.component";
|
||||
import { EpisodeRequestComponent } from "./episode-request/episode-request.component";
|
||||
import { GenreSelectComponent } from "./components/genre-select/genre-select.component";
|
||||
import { InputSwitchModule } from "primeng/inputswitch";
|
||||
import { IssuesReportComponent } from "./issues-report.component";
|
||||
import { KeywordSearchComponent } from "./components/keyword-search/keyword-search.component";
|
||||
import { MatAutocompleteModule } from "@angular/material/autocomplete";
|
||||
import { AdminRequestDialogComponent } from './admin-request-dialog/admin-request-dialog.component';
|
||||
import { AdvancedSearchDialogComponent } from './advanced-search-dialog/advanced-search-dialog.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { DetailsGroupComponent } from '../issues/components/details-group/details-group.component';
|
||||
import { EpisodeRequestComponent } from './episode-request/episode-request.component';
|
||||
import { GenreSelectComponent } from './components/genre-select/genre-select.component';
|
||||
import { InputSwitchModule } from 'primeng/inputswitch';
|
||||
import { IssuesReportComponent } from './issues-report.component';
|
||||
import { KeywordSearchComponent } from './components/keyword-search/keyword-search.component';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatChipsModule } from "@angular/material/chips";
|
||||
import { MatDialogModule } from "@angular/material/dialog";
|
||||
import { MatExpansionModule } from "@angular/material/expansion";
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
|
||||
import { MatProgressBarModule } from "@angular/material/progress-bar";
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatSlideToggleModule } from "@angular/material/slide-toggle";
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatTabsModule } from "@angular/material/tabs";
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
import { MomentModule } from "ngx-moment";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { PipeModule } from "../pipes/pipe.module";
|
||||
import { RoleModule } from "./role-directive/role.module";
|
||||
import { SidebarModule } from "primeng/sidebar";
|
||||
import { TranslateModule } from "@ngx-translate/core";
|
||||
import { TruncateModule } from "@yellowspot/ng-truncate";
|
||||
import { WatchProvidersSelectComponent } from "./components/watch-providers-select/watch-providers-select.component";
|
||||
import { NgModule } from '@angular/core';
|
||||
import { PipeModule } from '../pipes/pipe.module';
|
||||
import { RoleModule } from './role-directive/role.module';
|
||||
import { SidebarModule } from 'primeng/sidebar';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TruncateModule } from '@yellowspot/ng-truncate';
|
||||
import { WatchProvidersSelectComponent } from './components/watch-providers-select/watch-providers-select.component';
|
||||
import { DateFnsModule } from 'ngx-date-fns';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
IssuesReportComponent,
|
||||
EpisodeRequestComponent,
|
||||
DetailsGroupComponent,
|
||||
AdminRequestDialogComponent,
|
||||
AdvancedSearchDialogComponent,
|
||||
KeywordSearchComponent,
|
||||
GenreSelectComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
],
|
||||
imports: [
|
||||
RoleModule,
|
||||
SidebarModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
InputSwitchModule,
|
||||
TruncateModule,
|
||||
MomentModule,
|
||||
MatCardModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
MatAutocompleteModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
MatRadioModule,
|
||||
MatButtonModule,
|
||||
MatNativeDateModule,
|
||||
MatChipsModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
MatToolbarModule,
|
||||
MatCheckboxModule,
|
||||
TranslateModule,
|
||||
MatExpansionModule,
|
||||
MatDialogModule,
|
||||
MatTooltipModule,
|
||||
MatSelectModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatTreeModule,
|
||||
MatStepperModule,
|
||||
MatSnackBarModule,
|
||||
PipeModule,
|
||||
],
|
||||
exports: [
|
||||
RoleModule,
|
||||
TranslateModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
SidebarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
IssuesReportComponent,
|
||||
EpisodeRequestComponent,
|
||||
AdminRequestDialogComponent,
|
||||
AdvancedSearchDialogComponent,
|
||||
GenreSelectComponent,
|
||||
KeywordSearchComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
DetailsGroupComponent,
|
||||
TruncateModule,
|
||||
InputSwitchModule,
|
||||
MatTreeModule,
|
||||
MomentModule,MatCardModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
MatChipsModule,
|
||||
MatButtonModule,
|
||||
MatNativeDateModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSnackBarModule,
|
||||
MatSidenavModule,
|
||||
MatSelectModule,
|
||||
MatListModule,
|
||||
MatToolbarModule,
|
||||
MatTooltipModule,
|
||||
MatAutocompleteModule,
|
||||
MatCheckboxModule,
|
||||
MatExpansionModule,
|
||||
MatDialogModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatStepperModule,
|
||||
MatSlideToggleModule,
|
||||
],
|
||||
declarations: [
|
||||
IssuesReportComponent,
|
||||
EpisodeRequestComponent,
|
||||
DetailsGroupComponent,
|
||||
AdminRequestDialogComponent,
|
||||
AdvancedSearchDialogComponent,
|
||||
KeywordSearchComponent,
|
||||
GenreSelectComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
],
|
||||
imports: [
|
||||
RoleModule,
|
||||
SidebarModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
InputSwitchModule,
|
||||
TruncateModule,
|
||||
MatCardModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
MatAutocompleteModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
MatRadioModule,
|
||||
MatButtonModule,
|
||||
MatNativeDateModule,
|
||||
MatChipsModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatListModule,
|
||||
MatToolbarModule,
|
||||
MatCheckboxModule,
|
||||
TranslateModule,
|
||||
MatExpansionModule,
|
||||
MatDialogModule,
|
||||
MatTooltipModule,
|
||||
MatSelectModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatTreeModule,
|
||||
MatStepperModule,
|
||||
MatSnackBarModule,
|
||||
PipeModule,
|
||||
],
|
||||
exports: [
|
||||
RoleModule,
|
||||
TranslateModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
SidebarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
IssuesReportComponent,
|
||||
EpisodeRequestComponent,
|
||||
AdminRequestDialogComponent,
|
||||
AdvancedSearchDialogComponent,
|
||||
GenreSelectComponent,
|
||||
KeywordSearchComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
DetailsGroupComponent,
|
||||
TruncateModule,
|
||||
InputSwitchModule,
|
||||
MatTreeModule,
|
||||
MatCardModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
MatChipsModule,
|
||||
MatButtonModule,
|
||||
MatNativeDateModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatSnackBarModule,
|
||||
MatSidenavModule,
|
||||
MatSelectModule,
|
||||
MatListModule,
|
||||
MatToolbarModule,
|
||||
MatTooltipModule,
|
||||
MatAutocompleteModule,
|
||||
MatCheckboxModule,
|
||||
MatExpansionModule,
|
||||
MatDialogModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatStepperModule,
|
||||
MatSlideToggleModule,
|
||||
DateFnsModule,
|
||||
],
|
||||
})
|
||||
export class SharedModule {}
|
||||
|
|
|
@ -1,191 +1,201 @@
|
|||
<div class="small-middle-container">
|
||||
<div class="buttons">
|
||||
<div class="buttons">
|
||||
<a type="button" mat-raised-button color="primary" data-test="adduserbtn" [routerLink]="['/usermanagement/user']">Add User To Ombi</a>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
style="float: right"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="showBulkEdit = !showBulkEdit"
|
||||
[disabled]="this.selection.selected.length <= 0"
|
||||
>
|
||||
Bulk Edit
|
||||
</button>
|
||||
</div>
|
||||
<div class="content">
|
||||
<table mat-table *ngIf="dataSource" [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
[aria-label]="checkboxLabel()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
[aria-label]="checkboxLabel(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<a type="button" mat-raised-button color="primary" data-test="adduserbtn" [routerLink]="['/usermanagement/user']">Add User To Ombi</a>
|
||||
<ng-container matColumnDef="username">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Username</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.userName }}</td>
|
||||
</ng-container>
|
||||
|
||||
<button type="button" style="float:right;" mat-raised-button color="primary" (click)="showBulkEdit = !showBulkEdit" [disabled]="this.selection.selected.length <= 0">Bulk Edit</button>
|
||||
<ng-container matColumnDef="alias">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.alias }}</td>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
<div class="content" >
|
||||
<table mat-table *ngIf="dataSource" [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.emailAddress }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
[aria-label]="checkboxLabel()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
[aria-label]="checkboxLabel(row)">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="remainingRequests">
|
||||
<th mat-header-cell *matHeaderCellDef>Requests Remaining</th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.hasLimit">
|
||||
{{ 'UserManagment.MovieRemaining' | translate: { remaining: u.movieRequestQuota.remaining, total: u.movieRequestLimit } }}
|
||||
</div>
|
||||
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.hasLimit">
|
||||
{{ 'UserManagment.TvRemaining' | translate: { remaining: u.episodeRequestQuota.remaining, total: u.episodeRequestLimit } }}
|
||||
</div>
|
||||
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.hasLimit">
|
||||
{{ 'UserManagment.MusicRemaining' | translate: { remaining: u.musicRequestQuota.remaining, total: u.musicRequestLimit } }}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="username">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Username </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.userName}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="nextRequestDue">
|
||||
<th mat-header-cell *matHeaderCellDef>Next Request Due</th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.remaining != u.movieRequestLimit">
|
||||
{{ 'UserManagment.MovieDue' | translate: { date: (u.movieRequestQuota.nextRequest | dfnsFormat: 'P') } }}
|
||||
</div>
|
||||
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.remaining != u.episodeRequestLimit">
|
||||
{{ 'UserManagment.TvDue' | translate: { date: (u.episodeRequestQuota.nextRequest | dfnsFormat: 'P') } }}
|
||||
</div>
|
||||
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.remaining != u.musicRequestLimit">
|
||||
{{ 'UserManagment.MusicDue' | translate: { date: (u.musicRequestQuota.nextRequest | dfnsFormat: 'P') } }}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="lastLoggedIn">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last Logged In</th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<span *ngIf="u.lastLoggedIn">
|
||||
{{ u.lastLoggedIn | dfnsFormat: 'Ppp' }}
|
||||
</span>
|
||||
<span *ngIf="!u.lastLoggedIn"> Not logged in yet! </span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="alias">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alias </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.alias}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="userType">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>User Type</th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<span *ngIf="u.userType === 1">Local User</span>
|
||||
<span *ngIf="u.userType === 2">Plex User</span>
|
||||
<span *ngIf="u.userType === 3">Emby User</span>
|
||||
<span *ngIf="u.userType === 4">Emby Connect User</span>
|
||||
<span *ngIf="u.userType === 5">Jellyfin User</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Email </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.emailAddress}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="roles">
|
||||
<th mat-header-cell *matHeaderCellDef>Roles</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div *ngFor="let claim of element.claims">
|
||||
<span *ngIf="claim.enabled">{{ claim.value }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="remainingRequests">
|
||||
<th mat-header-cell *matHeaderCellDef> Requests Remaining </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.hasLimit">
|
||||
{{'UserManagment.MovieRemaining' | translate: {remaining: u.movieRequestQuota.remaining, total: u.movieRequestLimit} }}
|
||||
</div>
|
||||
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.hasLimit">
|
||||
{{'UserManagment.TvRemaining' | translate: {remaining: u.episodeRequestQuota.remaining, total: u.episodeRequestLimit} }}
|
||||
</div>
|
||||
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.hasLimit">
|
||||
{{'UserManagment.MusicRemaining' | translate: {remaining: u.musicRequestQuota.remaining, total: u.musicRequestLimit} }}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<a id="edit{{ u.userName }}" mat-raised-button color="accent" [routerLink]="['/usermanagement/user/' + u.id]">Edit</a>
|
||||
<button *ngIf="!u.hasLoggedIn" mat-raised-button color="accent" (click)="welcomeEmail(u)" [disabled]="!applicationUrl">
|
||||
<i class="far fa-paper-plane"></i> Welcome
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="nextRequestDue">
|
||||
<th mat-header-cell *matHeaderCellDef> Next Request Due </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.remaining != u.movieRequestLimit">
|
||||
{{'UserManagment.MovieDue' | translate: {date: (u.movieRequestQuota.nextRequest | amLocal | amUserLocale | amDateFormat: 'l')} }}
|
||||
</div>
|
||||
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.remaining != u.episodeRequestLimit">
|
||||
{{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | amLocal | amUserLocale | amDateFormat: 'l')} }}
|
||||
</div>
|
||||
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.remaining != u.musicRequestLimit">
|
||||
{{'UserManagment.MusicDue' | translate: {date: (u.musicRequestQuota.nextRequest | amLocal | amUserLocale | amDateFormat: 'l')} }}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="lastLoggedIn">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Last Logged In </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<span *ngIf="u.lastLoggedIn">
|
||||
{{u.lastLoggedIn | amFromUtc | amLocal | amUserLocale | amDateFormat: 'l LT'}}
|
||||
</span>
|
||||
<span *ngIf="!u.lastLoggedIn">
|
||||
Not logged in yet!
|
||||
</span> </td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<ng-container matColumnDef="userType">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> User Type </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<span *ngIf="u.userType === 1">Local User</span>
|
||||
<span *ngIf="u.userType === 2">Plex User</span>
|
||||
<span *ngIf="u.userType === 3">Emby User</span>
|
||||
<span *ngIf="u.userType === 4">Emby Connect User</span>
|
||||
<span *ngIf="u.userType === 5">Jellyfin User</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Table -->
|
||||
|
||||
<ng-container matColumnDef="roles">
|
||||
<th mat-header-cell *matHeaderCellDef> Roles </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div *ngFor="let claim of element.claims">
|
||||
<span *ngIf="claim.enabled">{{claim.value}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<p-sidebar [(visible)]="showBulkEdit" position="right" [modal]="false" [style]="{ width: '40em' }">
|
||||
<div>
|
||||
<div *ngFor="let c of availableClaims">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<mat-slide-toggle id="create{{ c.value }}" [(ngModel)]="c.enabled" [attr.name]="'create' + c.value">
|
||||
<small>{{ c.value | humanize }}</small></mat-slide-toggle
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Movie Request Limit</mat-label>
|
||||
<input matInput id="movieRequestLimit" name="movieRequestLimit" [(ngModel)]="bulkMovieLimit" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<mat-label>Movie Request Limit Type</mat-label>
|
||||
<mat-select id="movieRequestLimitType" [(value)]="movieRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{ RequestLimitType[value] }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Episode Request Limit</mat-label>
|
||||
<input matInput id="episodeRequestLimit" name="episodeRequestLimit" [(ngModel)]="bulkEpisodeLimit" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<mat-label>Episode Request Limit Type</mat-label>
|
||||
<mat-select id="episodeRequestLimitType" [(value)]="episodeRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{ RequestLimitType[value] }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Music Request Limit</mat-label>
|
||||
<input matInput id="musicRequestLimit" name="musicRequestLimit" [(ngModel)]="bulkMusicLimit" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<mat-label>Music Request Limit Type</mat-label>
|
||||
<mat-select id="musicRequestLimitType" [(value)]="musicRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{ RequestLimitType[value] }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>
|
||||
<mat-select [(value)]="bulkStreaming">
|
||||
<mat-option *ngFor="let value of countries" [value]="value">
|
||||
{{ value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<a id="edit{{u.userName}}" mat-raised-button color="accent" [routerLink]="['/usermanagement/user/' + u.id]">Edit</a>
|
||||
<button *ngIf="!u.hasLoggedIn" mat-raised-button color="accent" (click)="welcomeEmail(u)" [disabled]="!applicationUrl"><i class="far fa-paper-plane"></i> Welcome</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<!-- Table -->
|
||||
|
||||
|
||||
|
||||
<p-sidebar [(visible)]="showBulkEdit" position="right" [modal]="false" [style]="{width:'40em'}">
|
||||
<div>
|
||||
<div *ngFor="let c of availableClaims">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<mat-slide-toggle id="create{{c.value}}" [(ngModel)]="c.enabled" [attr.name]="'create' + c.value">
|
||||
<small>{{c.value | humanize}}</small></mat-slide-toggle>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Movie Request Limit</mat-label>
|
||||
<input matInput id="movieRequestLimit" name="movieRequestLimit" [(ngModel)]="bulkMovieLimit">
|
||||
</mat-form-field></div>
|
||||
<div class="col-6">
|
||||
<mat-label>Movie Request Limit Type</mat-label>
|
||||
<mat-select id="movieRequestLimitType" [(value)]="movieRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{RequestLimitType[value]}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Episode Request Limit</mat-label>
|
||||
<input matInput id="episodeRequestLimit" name="episodeRequestLimit" [(ngModel)]="bulkEpisodeLimit">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<mat-label>Episode Request Limit Type</mat-label>
|
||||
<mat-select id="episodeRequestLimitType" [(value)]="episodeRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{RequestLimitType[value]}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label>Music Request Limit</mat-label>
|
||||
<input matInput id="musicRequestLimit" name="musicRequestLimit" [(ngModel)]="bulkMusicLimit">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<mat-label>Music Request Limit Type</mat-label>
|
||||
<mat-select id="musicRequestLimitType" [(value)]="musicRequestLimitType">
|
||||
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||
{{RequestLimitType[value]}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<mat-form-field appearance="outline" class="full">
|
||||
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>
|
||||
<mat-select [(value)]="bulkStreaming">
|
||||
<mat-option *ngFor="let value of countries" [value]="value">
|
||||
{{value}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<button type="button" mat-raised-button color="primary" (click)="bulkUpdate()">Update Users</button>
|
||||
</p-sidebar>
|
||||
</div>
|
||||
<button type="button" mat-raised-button color="primary" (click)="bulkUpdate()">Update Users</button>
|
||||
</p-sidebar>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,53 +1,40 @@
|
|||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { IdentityService, PlexService, RadarrService, SonarrService } from "../services";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { IdentityService, PlexService, RadarrService, SonarrService } from '../services';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { AuthGuard } from "../auth/auth.guard";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { ConfirmDialogModule } from "primeng/confirmdialog";
|
||||
import { MultiSelectModule } from "primeng/multiselect";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { OrderModule } from "ngx-order-pipe";
|
||||
import { PipeModule } from "../pipes/pipe.module";
|
||||
import { SharedModule } from "../shared/shared.module";
|
||||
import { SidebarModule } from "primeng/sidebar";
|
||||
import { TooltipModule } from "primeng/tooltip";
|
||||
import { UserManagementComponent } from "./usermanagement.component";
|
||||
import { UserManagementUserComponent } from "./usermanagement-user.component";
|
||||
import { AuthGuard } from '../auth/auth.guard';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
||||
import { MultiSelectModule } from 'primeng/multiselect';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { PipeModule } from '../pipes/pipe.module';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { SidebarModule } from 'primeng/sidebar';
|
||||
import { TooltipModule } from 'primeng/tooltip';
|
||||
import { UserManagementComponent } from './usermanagement.component';
|
||||
import { UserManagementUserComponent } from './usermanagement-user.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "", component: UserManagementComponent, canActivate: [AuthGuard] },
|
||||
{ path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] },
|
||||
{ path: "user/:id", component: UserManagementUserComponent, canActivate: [AuthGuard] },
|
||||
{ path: '', component: UserManagementComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'user', component: UserManagementUserComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'user/:id', component: UserManagementUserComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule.forChild(routes),
|
||||
MultiSelectModule,
|
||||
PipeModule,
|
||||
ConfirmDialogModule,
|
||||
TooltipModule,
|
||||
OrderModule,
|
||||
SidebarModule,
|
||||
SharedModule,
|
||||
],
|
||||
declarations: [
|
||||
UserManagementComponent,
|
||||
UserManagementUserComponent,
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
],
|
||||
providers: [
|
||||
IdentityService,
|
||||
PlexService,
|
||||
RadarrService,
|
||||
SonarrService,
|
||||
],
|
||||
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule.forChild(routes),
|
||||
MultiSelectModule,
|
||||
PipeModule,
|
||||
ConfirmDialogModule,
|
||||
TooltipModule,
|
||||
SidebarModule,
|
||||
SharedModule,
|
||||
],
|
||||
declarations: [UserManagementComponent, UserManagementUserComponent],
|
||||
exports: [RouterModule],
|
||||
providers: [IdentityService, PlexService, RadarrService, SonarrService],
|
||||
})
|
||||
export class UserManagementModule { }
|
||||
export class UserManagementModule {}
|
||||
|
|
|
@ -1,39 +1,23 @@
|
|||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { OrderModule } from "ngx-order-pipe";
|
||||
import { OverlayPanelModule } from "primeng/overlaypanel";
|
||||
import { TabViewModule } from "primeng/tabview";
|
||||
import { OverlayPanelModule } from 'primeng/overlaypanel';
|
||||
import { TabViewModule } from 'primeng/tabview';
|
||||
|
||||
import { VoteService } from "../services";
|
||||
import { VoteService } from '../services';
|
||||
|
||||
import { AuthGuard } from "../auth/auth.guard";
|
||||
import { AuthGuard } from '../auth/auth.guard';
|
||||
|
||||
import { SharedModule as OmbiShared } from "../shared/shared.module";
|
||||
import { SharedModule as OmbiShared } from '../shared/shared.module';
|
||||
|
||||
import { VoteComponent } from "./vote.component";
|
||||
import { VoteComponent } from './vote.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "", component: VoteComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
const routes: Routes = [{ path: '', component: VoteComponent, canActivate: [AuthGuard] }];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
OrderModule,
|
||||
OmbiShared,
|
||||
TabViewModule,
|
||||
OverlayPanelModule,
|
||||
],
|
||||
declarations: [
|
||||
VoteComponent,
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
],
|
||||
providers: [
|
||||
VoteService,
|
||||
],
|
||||
|
||||
imports: [RouterModule.forChild(routes), OmbiShared, TabViewModule, OverlayPanelModule],
|
||||
declarations: [VoteComponent],
|
||||
exports: [RouterModule],
|
||||
providers: [VoteService],
|
||||
})
|
||||
export class VoteModule { }
|
||||
export class VoteModule {}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"useDefineForClassFields": false,
|
||||
"target": "ES2022",
|
||||
|
@ -24,6 +23,9 @@
|
|||
"dom"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
|
|
|
@ -1844,6 +1844,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.21.0":
|
||||
version "7.23.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
|
||||
integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
|
||||
|
@ -2551,11 +2558,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@scarf/scarf@^1.1.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.3.0.tgz#f8c75560d0dace4452dee1e31995e6396e61f3ee"
|
||||
integrity sha512-lHKK8M5CTcpFj2hZDB3wIjb0KAbEOgDmiJGDv1WBRfQgRm/a8/XMEkG/N1iM01xgbUDsPQwi42D+dFo1XPAKew==
|
||||
|
||||
"@schematics/angular@16.2.12":
|
||||
version "16.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-16.2.12.tgz#13e00e7390903cfc00eb8d5c2e74986262aff6ec"
|
||||
|
@ -3397,6 +3399,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.62.tgz#5b80d7a800f86842c5fadc066a63d6312208805c"
|
||||
integrity sha512-/zbPnIBkef8sT+6vw6BxdvU3dCxRI0v6rBu/6IvXnRNtOPILucigqhUBPYxtQ/8JdAna0JLTAcNTCDmQ77QYkQ==
|
||||
|
||||
"@types/node@^20.11.17":
|
||||
version "20.11.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.17.tgz#cdd642d0e62ef3a861f88ddbc2b61e32578a9292"
|
||||
integrity sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
|
||||
|
@ -3434,13 +3443,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
|
||||
integrity sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==
|
||||
|
||||
"@types/qrcode@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-1.5.0.tgz#6a98fe9a9a7b2a9a3167b6dde17eff999eabe40b"
|
||||
integrity sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/qs@*", "@types/qs@^6.9.5":
|
||||
version "6.9.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8"
|
||||
|
@ -4077,13 +4079,12 @@ amdefine@>=0.0.4:
|
|||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==
|
||||
|
||||
angularx-qrcode@^15.0.0:
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-15.0.1.tgz#349b558715c99d933cb62b264ff1bd7b269b334d"
|
||||
integrity sha512-CirpL2rhhYX/QZ1OSaJ/fusABjDlwl1oYBqaLRqmyie0xTbscWqTBW0DEoht2yCNGN8Wt+JmZwTLxYG6tLuWeQ==
|
||||
angularx-qrcode@^16.0.0:
|
||||
version "16.0.2"
|
||||
resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-16.0.2.tgz#86af924191546394cb93f9fb8d0c42edd0132894"
|
||||
integrity sha512-FztOM7vjNu88sGxUU5jG2I+A9TxZBXXYBWINjpwIBbTL+COMgrtzXnScG7TyQeNknv5w3WFJWn59PcngRRYVXA==
|
||||
dependencies:
|
||||
"@types/qrcode" "1.5.0"
|
||||
qrcode "1.5.1"
|
||||
qrcode "1.5.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
ansi-align@^3.0.0:
|
||||
|
@ -5969,6 +5970,13 @@ data-urls@^2.0.0:
|
|||
whatwg-mimetype "^2.3.0"
|
||||
whatwg-url "^8.0.0"
|
||||
|
||||
date-fns@2.30.0:
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
|
||||
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
@ -9299,6 +9307,11 @@ locate-path@^7.1.0:
|
|||
dependencies:
|
||||
p-locate "^6.0.0"
|
||||
|
||||
lodash-es@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
|
@ -9893,11 +9906,6 @@ mkdirp@^2.1.6:
|
|||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19"
|
||||
integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==
|
||||
|
||||
moment@^2.29.1:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
||||
morgan@^1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
|
||||
|
@ -10020,42 +10028,34 @@ ng2-cookies@^1.0.12:
|
|||
resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc"
|
||||
integrity sha512-oWRcKAAX81VrVb6ZVzLCf7mmaFM18eebsPOSxQG+bC3AtEm3LNT9zULfOE2Xwsddf5UM2STGcAocEKWNw84vSg==
|
||||
|
||||
ngx-clipboard@^12.1.0:
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-12.3.1.tgz#565d73b946b10719242e532e748ad912cf8bc97a"
|
||||
integrity sha512-qrUmkfYXEBQZQ4wNKno8yw5eOSxtdkzCPFFPil/XVVc93MNIKUme8aLbS3TEMB4PGsxopjbuTAzV7fptiSOIww==
|
||||
dependencies:
|
||||
ngx-window-token "^2.0.0"
|
||||
tslib "^1.9.0"
|
||||
|
||||
ngx-infinite-scroll@^9.0.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-9.1.0.tgz#6716a47613ff59f236b85c3ce291b2fd57106824"
|
||||
integrity sha512-ZulbahgFsoPmP8cz7qPGDeFX9nKiSm74aav8vXNSI1ZoPiGYY5FQd8AK+yXqygY7tyCJRyt8Wp3DIg7zgP5dPA==
|
||||
dependencies:
|
||||
"@scarf/scarf" "^1.1.0"
|
||||
opencollective-postinstall "^2.0.2"
|
||||
|
||||
ngx-moment@^3.0.1:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-moment/-/ngx-moment-3.5.0.tgz#97a4575a05d038612229b9fe09c4910353020613"
|
||||
integrity sha512-QC/5XNC0BW6WkJkwZT4r2A29j/8sJAmhuQJrEnEdpW35GvkemccuxEUAwo/PwkzPB/CHaquR00E6P2HVEQ1iEg==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
ngx-order-pipe@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.2.0.tgz#14ab50dfe0a679e5216138ff9a0820a83173a4fe"
|
||||
integrity sha512-fym4A3j0XMqETskCm0tHUHQWCgB1p1MrIstFA3jCClJqNU9KjtQh/AE4C7srUkz9U3HIBIAN9D3ty2L9l/jvmA==
|
||||
ngx-clipboard@^16.0.0:
|
||||
version "16.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-16.0.0.tgz#bb97584d33e8009420b8d7f83b185f68ca06869f"
|
||||
integrity sha512-rZ/Eo1PqiKMiyF8tdjhmUkoUu68f7OzBJ7YH1YFeh2RAaNrerTaW8XfFOzppSckjFQqA1fwGSYuTTJlDhDag5w==
|
||||
dependencies:
|
||||
ngx-window-token ">=7.0.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
ngx-window-token@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ngx-window-token/-/ngx-window-token-2.0.1.tgz#8f91221af4116aa9f49bb3f7a6f1111639884fba"
|
||||
integrity sha512-rvqdqJEfnWXQFU5fyfYt06E10tR/UtFOYdF3QebfcOh5VIJhnTKiprX8e4B9OrX7WEVFm9BT8uV72xXcEgsaKA==
|
||||
ngx-date-fns@^11.0.0:
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-date-fns/-/ngx-date-fns-11.0.0.tgz#5413e78868596097d7652e1f9bb871eb07debe92"
|
||||
integrity sha512-lpWjWL4yQDvhvqynrUtvft81NkVbBDfSl97UoaHWKFwfScnmplR3XsEnguNZQte4S/RIOxV4TZ+eM6gFlAN2SQ==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
ngx-infinite-scroll@^17.0.0:
|
||||
version "17.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-17.0.0.tgz#15726104d5b4e248a6eb96b03149959b20233ae8"
|
||||
integrity sha512-pQXLuRiuhRuDKD3nmgyW1V08JVNBepmk6nb8qjHc5hgsWNts01+R/p33rYcRDzcut6/PWqGyrZ9o9i8swzMYMA==
|
||||
dependencies:
|
||||
tslib "^2.3.0"
|
||||
|
||||
ngx-window-token@>=7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ngx-window-token/-/ngx-window-token-7.0.0.tgz#2e1bc76846411a388188b802154e4841d3e27856"
|
||||
integrity sha512-5+XfRVSY7Dciu8xyCNMkOlH2UfwR9W2P1Pirz7caaZgOZDjFbL8aEO2stjfJJm2FFf1D6dlVHNzhLWGk9HGkqA==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
nice-napi@^1.0.2:
|
||||
version "1.0.2"
|
||||
|
@ -10493,7 +10493,7 @@ open@^7.0.3:
|
|||
is-docker "^2.0.0"
|
||||
is-wsl "^2.1.1"
|
||||
|
||||
opencollective-postinstall@^2.0.2, opencollective-postinstall@^2.0.3:
|
||||
opencollective-postinstall@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
|
||||
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
|
||||
|
@ -11433,10 +11433,10 @@ q@^1.4.1:
|
|||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
|
||||
|
||||
qrcode@1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.1.tgz#0103f97317409f7bc91772ef30793a54cd59f0cb"
|
||||
integrity sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg==
|
||||
qrcode@1.5.3:
|
||||
version "1.5.3"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170"
|
||||
integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==
|
||||
dependencies:
|
||||
dijkstrajs "^1.0.1"
|
||||
encode-utf8 "^1.0.3"
|
||||
|
@ -13522,16 +13522,11 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
|
||||
|
||||
typescript@^5.0.4:
|
||||
typescript@5.2.2, typescript@^5.0.4:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||
|
||||
typescript@~5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
|
||||
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.17.4"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue