mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-13 08:42:57 -07:00
Merge remote-tracking branch 'upstream/develop' into original-language
This commit is contained in:
commit
18742776da
24 changed files with 145 additions and 197 deletions
13
.github/workflows/pr.yml
vendored
13
.github/workflows/pr.yml
vendored
|
@ -28,6 +28,8 @@ jobs:
|
|||
|
||||
unit-test:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
|
@ -45,7 +47,16 @@ jobs:
|
|||
- name: Run Unit Tests
|
||||
run: |
|
||||
cd src
|
||||
dotnet test --logger trx --results-directory "TestResults"
|
||||
dotnet test --logger "trx;LogFileName=test-results.trx" || true
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v1
|
||||
if: always()
|
||||
with:
|
||||
name: DotNET Tests
|
||||
path: "**/test-results.trx"
|
||||
reporter: dotnet-trx
|
||||
fail-on-error: true
|
||||
|
||||
analysis:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
44
CHANGELOG.md
44
CHANGELOG.md
|
@ -1,3 +1,20 @@
|
|||
## [4.16.17](https://github.com/Ombi-app/Ombi/compare/v4.16.16...v4.16.17) (2022-04-25)
|
||||
|
||||
|
||||
|
||||
## [4.16.16](https://github.com/Ombi-app/Ombi/compare/v4.16.15...v4.16.16) (2022-04-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **4616:** :bug: fixed mandatory fields ([d8f2260](https://github.com/Ombi-app/Ombi/commit/d8f2260c7ae3ed48386743b7adbd06e284487034))
|
||||
|
||||
|
||||
|
||||
## [4.16.15](https://github.com/Ombi-app/Ombi/compare/v4.16.14...v4.16.15) (2022-04-24)
|
||||
|
||||
|
||||
|
||||
## [4.16.14](https://github.com/Ombi-app/Ombi/compare/v4.16.13...v4.16.14) (2022-04-19)
|
||||
|
||||
|
||||
|
@ -321,30 +338,3 @@
|
|||
|
||||
|
||||
|
||||
# [4.12.0](https://github.com/Ombi-app/Ombi/compare/v4.11.8...v4.12.0) (2022-02-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **radarr:** 4K Requests and Radarr 4K support ([ba88848](https://github.com/Ombi-app/Ombi/commit/ba88848866b0a9dedb1e79b55c4d81a0fd453843))
|
||||
|
||||
|
||||
|
||||
## [4.11.8](https://github.com/Ombi-app/Ombi/compare/v4.11.7...v4.11.8) (2022-02-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **settings:** :bug: Fixed an issue where we were not displaying the excluded keyworks correctly in the TheMovieDbSettings page ([d3b3316](https://github.com/Ombi-app/Ombi/commit/d3b3316cbac18356b2f6b0912a3deb2c183e6534))
|
||||
|
||||
|
||||
|
||||
## [4.11.7](https://github.com/Ombi-app/Ombi/compare/v4.11.6...v4.11.7) (2022-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notifications:** :bug: This is a fix for some of the duplicate notification issues [#3825](https://github.com/Ombi-app/Ombi/issues/3825) ([22bb422](https://github.com/Ombi-app/Ombi/commit/22bb4226ead2d62e8c2c2c05be47d7da621402e2))
|
||||
|
||||
|
||||
|
||||
|
|
23
README.md
23
README.md
|
@ -665,14 +665,21 @@ Here are some of the features Ombi has:
|
|||
<sub><b>Shoghi</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Teifun2">
|
||||
<img src="https://avatars.githubusercontent.com/u/7461832?v=4" width="50;" alt="Teifun2"/>
|
||||
<br />
|
||||
<sub><b>Teifun2</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/thomasvt1">
|
||||
<img src="https://avatars.githubusercontent.com/u/2271011?v=4" width="50;" alt="thomasvt1"/>
|
||||
<br />
|
||||
<sub><b>Thomas Van Tilburg</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Tim-Trott">
|
||||
<img src="https://avatars.githubusercontent.com/u/8249434?v=4" width="50;" alt="Tim-Trott"/>
|
||||
|
@ -707,15 +714,15 @@ Here are some of the features Ombi has:
|
|||
<br />
|
||||
<sub><b>Xirg</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bazhip">
|
||||
<img src="https://avatars.githubusercontent.com/u/10350445?v=4" width="50;" alt="bazhip"/>
|
||||
<br />
|
||||
<sub><b>Tim OBrien</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/x-limitless-x">
|
||||
<img src="https://avatars.githubusercontent.com/u/17127926?v=4" width="50;" alt="x-limitless-x"/>
|
||||
|
@ -750,15 +757,15 @@ Here are some of the features Ombi has:
|
|||
<br />
|
||||
<sub><b>M4tta</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/maartenheebink">
|
||||
<img src="https://avatars.githubusercontent.com/u/28894544?v=4" width="50;" alt="maartenheebink"/>
|
||||
<br />
|
||||
<sub><b>Maartenheebink</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/masterhuck">
|
||||
<img src="https://avatars.githubusercontent.com/u/4671442?v=4" width="50;" alt="masterhuck"/>
|
||||
|
|
|
@ -532,8 +532,11 @@ namespace Ombi.Core.Engine
|
|||
x.ShowSubscribe = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!x.Available && !x.Available4K && (!x.Denied ?? true) && (!x.Denied4K ?? true))
|
||||
{
|
||||
x.ShowSubscribe = true;
|
||||
}
|
||||
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
|
||||
x.Subscribed = hasSub != null;
|
||||
}
|
||||
|
|
|
@ -269,8 +269,11 @@ namespace Ombi.Core.Engine
|
|||
x.ShowSubscribe = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!x.Available && (!x.Denied ?? false))
|
||||
{
|
||||
x.ShowSubscribe = true;
|
||||
}
|
||||
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
|
||||
x.Subscribed = hasSub != null;
|
||||
}
|
||||
|
|
|
@ -885,8 +885,11 @@ namespace Ombi.Core.Engine
|
|||
x.ShowSubscribe = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!x.Available && (!x.Denied ?? true))
|
||||
{
|
||||
x.ShowSubscribe = true;
|
||||
}
|
||||
var result = relevantSubs.FirstOrDefault(s => s.RequestId == x.Id);
|
||||
x.Subscribed = result != null;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Ombi.Core.Senders
|
|||
}
|
||||
|
||||
|
||||
return new SenderResult { Success = false, Sent = false, Message = "Something went wrong!" };
|
||||
return new SenderResult { Success = false, Sent = false };
|
||||
}
|
||||
|
||||
private async Task<SenderResult> SendToLidarr(AlbumRequest model, LidarrSettings settings)
|
||||
|
|
|
@ -133,8 +133,7 @@ namespace Ombi.Core.Senders
|
|||
|
||||
return new SenderResult
|
||||
{
|
||||
Success = false,
|
||||
Message = "Something went wrong!"
|
||||
Success = false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -343,8 +342,6 @@ namespace Ombi.Core.Senders
|
|||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
var seriesChanges = false;
|
||||
|
||||
foreach (var season in model.SeasonRequests)
|
||||
{
|
||||
foreach (var ep in season.Episodes)
|
||||
|
@ -359,53 +356,22 @@ namespace Ombi.Core.Senders
|
|||
}
|
||||
|
||||
existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
|
||||
var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList();
|
||||
var sonarrEpCount = sonarrEpisodeList.Count;
|
||||
var ourRequestCount = season.Episodes.Count;
|
||||
|
||||
var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList();
|
||||
var unairedEpisodes = sonarrEpisodeList.Where(x => x.airDateUtc > DateTime.UtcNow).Select(x => x.episodeNumber).ToList();
|
||||
|
||||
//// Check if we have requested all the latest episodes, if we have then monitor
|
||||
//// NOTE, not sure if needed since ombi ui displays future episodes anyway...
|
||||
//ourEpisodes.AddRange(unairedEpisodes);
|
||||
//var distinctEpisodes = ourEpisodes.Distinct().ToList();
|
||||
//var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes);
|
||||
|
||||
|
||||
if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/)
|
||||
{
|
||||
// We have the same amount of requests as all of the episodes in the season.
|
||||
existingSeason.monitored = true;
|
||||
seriesChanges = true;
|
||||
|
||||
// We do not need to update the episodes as marking the season as monitored will mark the episodes as monitored.
|
||||
var seasonToUpdate = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
|
||||
seasonToUpdate.monitored = true; // Update by ref
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure this season is set to monitored
|
||||
if (!existingSeason.monitored)
|
||||
{
|
||||
// We need to monitor it, problem being is all episodes will now be monitored
|
||||
// So we need to monitor the series but unmonitor every episode
|
||||
// Except the episodes that are already monitored before we update the series (we do not want to unmonitored episodes that are monitored beforehand)
|
||||
existingSeason.monitored = true;
|
||||
var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber);
|
||||
sea.monitored = true;
|
||||
//var previouslyMonitoredEpisodes = sonarrEpList.Where(x =>
|
||||
// x.seasonNumber == existingSeason.seasonNumber && x.monitored).Select(x => x.episodeNumber).ToList(); // We probably don't actually care about this
|
||||
|
||||
result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
|
||||
var epToUnmonitored = new List<Episode>();
|
||||
var newEpList = sonarrEpList.ConvertAll(ep => new Episode(ep)); // Clone it so we don't modify the original member
|
||||
foreach (var ep in newEpList.Where(x => x.seasonNumber == existingSeason.seasonNumber).ToList())
|
||||
{
|
||||
//if (previouslyMonitoredEpisodes.Contains(ep.episodeNumber))
|
||||
//{
|
||||
// // This was previously monitored.
|
||||
// continue;
|
||||
//}
|
||||
ep.monitored = false;
|
||||
epToUnmonitored.Add(ep);
|
||||
}
|
||||
|
@ -421,11 +387,6 @@ namespace Ombi.Core.Senders
|
|||
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (seriesChanges)
|
||||
{
|
||||
await SonarrApi.SeasonPass(s.ApiKey, s.FullUri, result);
|
||||
}
|
||||
|
||||
if (!s.AddOnly)
|
||||
{
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace Ombi.Store.Context
|
|||
notificationToAdd = new NotificationTemplates
|
||||
{
|
||||
NotificationType = notificationType,
|
||||
Message = "Your TV request is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
|
||||
Message = "Your TV request for {Title} is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
|
||||
Subject = "{ApplicationName}: Partially Available Request!",
|
||||
Agent = agent,
|
||||
Enabled = true,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-raised-button color="accent" [routerLink]="[element.providerId]">{{ 'Issues.Details' | translate}}</button>
|
||||
<a mat-raised-button color="accent" [routerLink]="[element.providerId]">{{ 'Issues.Details' | translate}}</a>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ export class TvRequestGridComponent {
|
|||
// Make sure something has been selected
|
||||
const selected = this.selection.hasValue();
|
||||
if (!selected && !this.tv.requestAll && !this.tv.firstSeason && !this.tv.latestSeason) {
|
||||
this.notificationService.send("You need to select some episodes!", "OK");
|
||||
this.notificationService.send(this.translate.instant("Requests.NeedToSelectEpisodes"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -80,70 +80,6 @@ export class TvRequestGridComponent {
|
|||
}
|
||||
}
|
||||
|
||||
public async approve(request: IChildRequests) {
|
||||
const result = await this.requestService.approveChild({
|
||||
id: request.id
|
||||
}).toPromise();
|
||||
|
||||
if (result.result) {
|
||||
request.approved = true;
|
||||
request.denied = false;
|
||||
request.seasonRequests.forEach((season) => {
|
||||
season.episodes.forEach((ep) => {
|
||||
ep.approved = true;
|
||||
});
|
||||
});
|
||||
this.notificationService.send("Request has been approved", "Ok");
|
||||
} else {
|
||||
this.notificationService.send(result.errorMessage, "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
public changeAvailability(request: IChildRequests, available: boolean) {
|
||||
request.available = available;
|
||||
request.seasonRequests.forEach((season) => {
|
||||
season.episodes.forEach((ep) => {
|
||||
ep.available = available;
|
||||
});
|
||||
});
|
||||
if (available) {
|
||||
this.requestService.markTvAvailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.notificationService.send(
|
||||
`This request is now available`);
|
||||
} else {
|
||||
this.notificationService.send("Request Available", x.message ? x.message : x.errorMessage);
|
||||
request.approved = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.notificationService.send(
|
||||
`This request is now unavailable`);
|
||||
} else {
|
||||
this.notificationService.send("Request Available", x.message ? x.message : x.errorMessage);
|
||||
request.approved = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
public async deny(request: IChildRequests) {
|
||||
const dialogRef = this.dialog.open(DenyDialogComponent, {
|
||||
width: '250px',
|
||||
data: {requestId: request.id, requestType: RequestType.tvShow}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
request.denied = true;
|
||||
request.seasonRequests.forEach((season) => {
|
||||
season.episodes.forEach((ep) => {
|
||||
ep.approved = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async requestAllSeasons() {
|
||||
this.tv.requestAll = true;
|
||||
await this.submitRequests();
|
||||
|
|
|
@ -6,6 +6,7 @@ import { MatDialog } from "@angular/material/dialog";
|
|||
import { MessageService } from "../../../../../services";
|
||||
import { RequestService } from "../../../../../services/request.service";
|
||||
import { RequestServiceV2 } from "../../../../../services/requestV2.service";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./tv-requests-panel.component.html",
|
||||
|
@ -24,7 +25,8 @@ export class TvRequestsPanelComponent {
|
|||
constructor(private requestService: RequestService,
|
||||
private requestService2: RequestServiceV2,
|
||||
private messageService: MessageService,
|
||||
public dialog: MatDialog) {
|
||||
public dialog: MatDialog,
|
||||
private translateService: TranslateService) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -41,7 +43,7 @@ export class TvRequestsPanelComponent {
|
|||
ep.approved = true;
|
||||
});
|
||||
});
|
||||
this.messageService.send("Request has been approved", "Ok");
|
||||
this.messageService.send(this.translateService.instant("Requests.SuccessfullyApproved"));
|
||||
} else {
|
||||
this.messageService.sendRequestEngineResultError(result);
|
||||
}
|
||||
|
@ -52,7 +54,7 @@ export class TvRequestsPanelComponent {
|
|||
|
||||
if (result) {
|
||||
this.tvRequest.splice(this.tvRequest.indexOf(request),1);
|
||||
this.messageService.send("Request has been Deleted", "Ok");
|
||||
this.messageService.send(this.translateService.instant("Requests.SuccessfullyDeleted"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,9 +69,9 @@ export class TvRequestsPanelComponent {
|
|||
this.requestService.markTvAvailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.messageService.send(
|
||||
`This request is now available`);
|
||||
this.translateService.instant("Requests.NowAvailable"));
|
||||
} else {
|
||||
this.messageService.send("Request Available", x.message ? x.message : x.errorMessage);
|
||||
this.messageService.sendRequestEngineResultError(x);
|
||||
request.approved = false;
|
||||
}
|
||||
});
|
||||
|
@ -77,9 +79,9 @@ export class TvRequestsPanelComponent {
|
|||
this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.messageService.send(
|
||||
`This request is now unavailable`);
|
||||
this.translateService.instant("Requests.NowUnavailable"));
|
||||
} else {
|
||||
this.messageService.send("Request Available", x.message ? x.message : x.errorMessage);
|
||||
this.messageService.sendRequestEngineResultError(x);
|
||||
request.approved = false;
|
||||
}
|
||||
});
|
||||
|
@ -102,11 +104,11 @@ export class TvRequestsPanelComponent {
|
|||
}
|
||||
|
||||
public reProcessRequest(request: IChildRequests) {
|
||||
this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(result => {
|
||||
if (result.result) {
|
||||
this.messageService.send(result.message ? result.message : "Successfully Re-processed the request", "Ok");
|
||||
this.requestService2.reprocessRequest(request.id, RequestType.tvShow, false).subscribe(x => {
|
||||
if (x.result) {
|
||||
this.messageService.send(this.translateService.instant("Requests.SuccessfullyReprocessed"));
|
||||
} else {
|
||||
this.messageService.sendRequestEngineResultError(result);
|
||||
this.messageService.sendRequestEngineResultError(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-raised-button color="accent" [routerLink]="'/details/artist/' + element.foreignArtistId">{{ 'Requests.Details' | translate}}</button>
|
||||
<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>
|
||||
|
|
|
@ -83,8 +83,8 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/movie/' + element.theMovieDbId">{{ 'Requests.Details' | translate}}</button>
|
||||
<button id="optionsButton{{element.id}}" mat-raised-button color="warn" (click)="openOptions(element)" *ngIf="isAdmin || ( manageOwnRequests && element.requestedUser?.userName == userName ) "> {{ 'Requests.Options' | translate}}</button>
|
||||
<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>
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button id="detailsButton{{element.id}}" mat-raised-button color="accent" [routerLink]="'/details/tv/' + element.parentRequest.externalProviderId">{{'Requests.Details' | translate}}</button>
|
||||
<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>
|
||||
|
|
|
@ -22,11 +22,15 @@ export class MessageService {
|
|||
}
|
||||
public sendRequestEngineResultError(result: IRequestEngineResult, action: string = "Ok") {
|
||||
const textKey = 'Requests.ErrorCodes.' + result.errorCode;
|
||||
const text = this.translate.instant(textKey);
|
||||
if (text !== textKey) {
|
||||
this.send(text, action);
|
||||
var text = this.translate.instant(textKey);
|
||||
if (text === textKey) { // Error code on backend may not exist in frontend
|
||||
if (result.errorMessage || result.message) {
|
||||
text = result.errorMessage ? result.errorMessage : result.message;
|
||||
} else {
|
||||
this.send(result.errorMessage ? result.errorMessage : result.message, action);
|
||||
text = this.translate.instant('ErrorPages.SomethingWentWrong');
|
||||
}
|
||||
}
|
||||
|
||||
this.send(text, action);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { TesterService, NotificationService, RadarrService } from "../../../serv
|
|||
selector: "ombi-settings-radarr-form",
|
||||
templateUrl: "./radarr-form.component.html",
|
||||
styleUrls: ["./radarr-form.component.scss"],
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class RadarrFormComponent implements OnInit {
|
||||
|
||||
|
@ -23,11 +23,11 @@ export class RadarrFormComponent implements OnInit {
|
|||
constructor(private radarrService: RadarrService,
|
||||
private notificationService: NotificationService,
|
||||
private testerService: TesterService,
|
||||
private controlContainer: ControlContainer) { }
|
||||
private controlContainer: ControlContainer) {
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.form = <FormGroup>this.controlContainer.control;
|
||||
// this.toggleValidators();
|
||||
|
||||
this.qualities = [];
|
||||
this.qualities.push({ name: "Please Select", id: -1 });
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
<mat-tab-group dynamicHeight>
|
||||
<mat-tab label="Radarr">
|
||||
<ombi-settings-radarr-form
|
||||
#normalForm
|
||||
formGroupName="radarr">
|
||||
</ombi-settings-radarr-form>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="is4kEnabled" label="Radarr 4K">
|
||||
<ombi-settings-radarr-form
|
||||
#4kForm
|
||||
formGroupName="radarr4K">
|
||||
</ombi-settings-radarr-form>
|
||||
</mat-tab>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { Component, OnInit, QueryList, ViewChild, ViewChildren } from "@angular/core";
|
||||
import { FormBuilder, FormGroup } from "@angular/forms";
|
||||
|
||||
import { IMinimumAvailability, IRadarrCombined, IRadarrProfile, IRadarrRootFolder } from "../../interfaces";
|
||||
import { NotificationService, SettingsService } from "../../services";
|
||||
import { FeaturesFacade } from "../../state/features/features.facade";
|
||||
import { RadarrFormComponent } from "./components/radarr-form.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./radarr.component.html",
|
||||
|
@ -19,11 +20,15 @@ export class RadarrComponent implements OnInit {
|
|||
public form: FormGroup;
|
||||
public is4kEnabled: boolean = false;
|
||||
|
||||
@ViewChildren('4kForm') public form4k: QueryList<RadarrFormComponent>;
|
||||
@ViewChildren('normalForm') public normalForm: QueryList<RadarrFormComponent>;
|
||||
|
||||
constructor(private settingsService: SettingsService,
|
||||
private notificationService: NotificationService,
|
||||
private featureFacade: FeaturesFacade,
|
||||
private fb: FormBuilder) { }
|
||||
|
||||
|
||||
public ngOnInit() {
|
||||
this.is4kEnabled = this.featureFacade.is4kEnabled();
|
||||
this.settingsService.getRadarr()
|
||||
|
@ -56,7 +61,16 @@ export class RadarrComponent implements OnInit {
|
|||
scanForAvailability: [x.radarr4K.scanForAvailability]
|
||||
}),
|
||||
});
|
||||
this.normalForm.changes.forEach((comp => {
|
||||
comp.first.toggleValidators();
|
||||
}))
|
||||
if (this.is4kEnabled) {
|
||||
this.form4k.changes.forEach((comp => {
|
||||
comp.first.toggleValidators();
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="buttons">
|
||||
|
||||
|
||||
<button type="button" mat-raised-button color="primary" data-test="adduserbtn" [routerLink]="['/usermanagement/user']">Add User To Ombi</button>
|
||||
<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>
|
||||
|
||||
|
@ -105,7 +105,7 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let u">
|
||||
<button id="edit{{u.userName}}" mat-raised-button color="accent" [routerLink]="['/usermanagement/user/' + u.id]">Edit</button>
|
||||
<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>
|
||||
|
|
|
@ -142,6 +142,10 @@
|
|||
background-color: $ombi-active;
|
||||
}
|
||||
|
||||
a.mat-raised-button {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: 1px solid $accent-dark;
|
||||
}
|
||||
|
|
|
@ -282,11 +282,18 @@ namespace Ombi.Controllers.V1.External
|
|||
{
|
||||
try
|
||||
{
|
||||
var currentUser = await GetCurrentUserAsync();
|
||||
|
||||
if (!currentUser.Email.HasValue())
|
||||
{
|
||||
throw new Exception($"User '{currentUser.UserName}' has no email address set on their user profile.");
|
||||
}
|
||||
|
||||
var message = new NotificationMessage
|
||||
{
|
||||
Message = "This is just a test! Success!",
|
||||
Subject = $"Ombi: Test",
|
||||
To = (await GetCurrentUserAsync()).Email,
|
||||
To = currentUser.Email,
|
||||
};
|
||||
|
||||
message.Other.Add("PlainTextBody", "This is just a test! Success!");
|
||||
|
|
|
@ -60,7 +60,8 @@
|
|||
"CheckPageForUpdates": "Check this page for continuous site updates."
|
||||
},
|
||||
"ErrorPages": {
|
||||
"NotFound": "Page not found"
|
||||
"NotFound": "Page not found",
|
||||
"SomethingWentWrong": "Something went wrong!"
|
||||
},
|
||||
"NavigationBar": {
|
||||
"Discover": "Discover",
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"version": "4.16.14"
|
||||
"version": "4.16.17"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue