mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-02-07 04:22:01 -05:00
removed enabled per arr config and added enabled per arr instance
This commit is contained in:
@@ -588,7 +588,6 @@ public class ConfigurationController : ControllerBase
|
||||
var config = await _dataContext.ArrConfigs
|
||||
.FirstAsync(x => x.Type == InstanceType.Sonarr);
|
||||
|
||||
config.Enabled = newConfigDto.Enabled;
|
||||
config.FailedImportMaxStrikes = newConfigDto.FailedImportMaxStrikes;
|
||||
|
||||
// Validate the configuration
|
||||
@@ -620,7 +619,6 @@ public class ConfigurationController : ControllerBase
|
||||
var config = await _dataContext.ArrConfigs
|
||||
.FirstAsync(x => x.Type == InstanceType.Radarr);
|
||||
|
||||
config.Enabled = newConfigDto.Enabled;
|
||||
config.FailedImportMaxStrikes = newConfigDto.FailedImportMaxStrikes;
|
||||
|
||||
// Validate the configuration
|
||||
@@ -652,7 +650,6 @@ public class ConfigurationController : ControllerBase
|
||||
var config = await _dataContext.ArrConfigs
|
||||
.FirstAsync(x => x.Type == InstanceType.Lidarr);
|
||||
|
||||
config.Enabled = newConfigDto.Enabled;
|
||||
config.FailedImportMaxStrikes = newConfigDto.FailedImportMaxStrikes;
|
||||
|
||||
// Validate the configuration
|
||||
@@ -719,6 +716,7 @@ public class ConfigurationController : ControllerBase
|
||||
// Create the new instance
|
||||
var instance = new ArrInstance
|
||||
{
|
||||
Enabled = newInstance.Enabled,
|
||||
Name = newInstance.Name,
|
||||
Url = new Uri(newInstance.Url),
|
||||
ApiKey = newInstance.ApiKey,
|
||||
@@ -762,6 +760,7 @@ public class ConfigurationController : ControllerBase
|
||||
}
|
||||
|
||||
// Update the instance properties
|
||||
instance.Enabled = updatedInstance.Enabled;
|
||||
instance.Name = updatedInstance.Name;
|
||||
instance.Url = new Uri(updatedInstance.Url);
|
||||
instance.ApiKey = updatedInstance.ApiKey;
|
||||
@@ -828,6 +827,7 @@ public class ConfigurationController : ControllerBase
|
||||
// Create the new instance
|
||||
var instance = new ArrInstance
|
||||
{
|
||||
Enabled = newInstance.Enabled,
|
||||
Name = newInstance.Name,
|
||||
Url = new Uri(newInstance.Url),
|
||||
ApiKey = newInstance.ApiKey,
|
||||
@@ -870,6 +870,7 @@ public class ConfigurationController : ControllerBase
|
||||
}
|
||||
|
||||
// Update the instance properties
|
||||
instance.Enabled = updatedInstance.Enabled;
|
||||
instance.Name = updatedInstance.Name;
|
||||
instance.Url = new Uri(updatedInstance.Url);
|
||||
instance.ApiKey = updatedInstance.ApiKey;
|
||||
@@ -936,6 +937,7 @@ public class ConfigurationController : ControllerBase
|
||||
// Create the new instance
|
||||
var instance = new ArrInstance
|
||||
{
|
||||
Enabled = newInstance.Enabled,
|
||||
Name = newInstance.Name,
|
||||
Url = new Uri(newInstance.Url),
|
||||
ApiKey = newInstance.ApiKey,
|
||||
@@ -979,6 +981,7 @@ public class ConfigurationController : ControllerBase
|
||||
}
|
||||
|
||||
// Update the instance properties
|
||||
instance.Enabled = updatedInstance.Enabled;
|
||||
instance.Name = updatedInstance.Name;
|
||||
instance.Url = new Uri(updatedInstance.Url);
|
||||
instance.ApiKey = updatedInstance.ApiKey;
|
||||
|
||||
@@ -71,17 +71,14 @@ public class StatusController : ControllerBase
|
||||
{
|
||||
Sonarr = new
|
||||
{
|
||||
IsEnabled = sonarrConfig.Enabled,
|
||||
InstanceCount = sonarrConfig.Instances.Count
|
||||
},
|
||||
Radarr = new
|
||||
{
|
||||
IsEnabled = radarrConfig.Enabled,
|
||||
InstanceCount = radarrConfig.Instances.Count
|
||||
},
|
||||
Lidarr = new
|
||||
{
|
||||
IsEnabled = lidarrConfig.Enabled,
|
||||
InstanceCount = lidarrConfig.Instances.Count
|
||||
}
|
||||
}
|
||||
@@ -143,124 +140,125 @@ public class StatusController : ControllerBase
|
||||
var status = new Dictionary<string, object>();
|
||||
|
||||
// Get configurations
|
||||
var sonarrConfig = await _dataContext.ArrConfigs
|
||||
var enabledSonarrInstances = await _dataContext.ArrConfigs
|
||||
.Include(x => x.Instances)
|
||||
.Where(x => x.Type == InstanceType.Sonarr)
|
||||
.SelectMany(x => x.Instances)
|
||||
.Where(x => x.Enabled)
|
||||
.AsNoTracking()
|
||||
.FirstAsync(x => x.Type == InstanceType.Sonarr);
|
||||
var radarrConfig = await _dataContext.ArrConfigs
|
||||
.ToListAsync();
|
||||
var enabledRadarrInstances = await _dataContext.ArrConfigs
|
||||
.Include(x => x.Instances)
|
||||
.Where(x => x.Type == InstanceType.Radarr)
|
||||
.SelectMany(x => x.Instances)
|
||||
.Where(x => x.Enabled)
|
||||
.AsNoTracking()
|
||||
.FirstAsync(x => x.Type == InstanceType.Radarr);
|
||||
var lidarrConfig = await _dataContext.ArrConfigs
|
||||
.ToListAsync();
|
||||
var enabledLidarrInstances = await _dataContext.ArrConfigs
|
||||
.Include(x => x.Instances)
|
||||
.Where(x => x.Type == InstanceType.Lidarr)
|
||||
.SelectMany(x => x.Instances)
|
||||
.Where(x => x.Enabled)
|
||||
.AsNoTracking()
|
||||
.FirstAsync(x => x.Type == InstanceType.Lidarr);
|
||||
.ToListAsync();;
|
||||
|
||||
|
||||
// Check Sonarr instances
|
||||
if (sonarrConfig is { Enabled: true, Instances.Count: > 0 })
|
||||
var sonarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in enabledSonarrInstances)
|
||||
{
|
||||
var sonarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in sonarrConfig.Instances)
|
||||
try
|
||||
{
|
||||
try
|
||||
var sonarrClient = _arrClientFactory.GetClient(InstanceType.Sonarr);
|
||||
await sonarrClient.TestConnectionAsync(instance);
|
||||
|
||||
sonarrStatus.Add(new
|
||||
{
|
||||
var sonarrClient = _arrClientFactory.GetClient(InstanceType.Sonarr);
|
||||
await sonarrClient.TestConnectionAsync(instance);
|
||||
|
||||
sonarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sonarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sonarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
|
||||
status["Sonarr"] = sonarrStatus;
|
||||
}
|
||||
|
||||
status["Sonarr"] = sonarrStatus;
|
||||
|
||||
// Check Radarr instances
|
||||
if (radarrConfig is { Enabled: true, Instances.Count: > 0 })
|
||||
var radarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in enabledRadarrInstances)
|
||||
{
|
||||
var radarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in radarrConfig.Instances)
|
||||
try
|
||||
{
|
||||
try
|
||||
var radarrClient = _arrClientFactory.GetClient(InstanceType.Radarr);
|
||||
await radarrClient.TestConnectionAsync(instance);
|
||||
|
||||
radarrStatus.Add(new
|
||||
{
|
||||
var radarrClient = _arrClientFactory.GetClient(InstanceType.Radarr);
|
||||
await radarrClient.TestConnectionAsync(instance);
|
||||
|
||||
radarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
radarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
radarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
|
||||
status["Radarr"] = radarrStatus;
|
||||
}
|
||||
|
||||
status["Radarr"] = radarrStatus;
|
||||
|
||||
// Check Lidarr instances
|
||||
if (lidarrConfig is { Enabled: true, Instances.Count: > 0 })
|
||||
var lidarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in enabledLidarrInstances)
|
||||
{
|
||||
var lidarrStatus = new List<object>();
|
||||
|
||||
foreach (var instance in lidarrConfig.Instances)
|
||||
try
|
||||
{
|
||||
try
|
||||
var lidarrClient = _arrClientFactory.GetClient(InstanceType.Lidarr);
|
||||
await lidarrClient.TestConnectionAsync(instance);
|
||||
|
||||
lidarrStatus.Add(new
|
||||
{
|
||||
var lidarrClient = _arrClientFactory.GetClient(InstanceType.Lidarr);
|
||||
await lidarrClient.TestConnectionAsync(instance);
|
||||
|
||||
lidarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lidarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = true,
|
||||
Message = "Successfully connected"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lidarrStatus.Add(new
|
||||
{
|
||||
instance.Name,
|
||||
instance.Url,
|
||||
IsConnected = false,
|
||||
Message = $"Connection failed: {ex.Message}"
|
||||
});
|
||||
}
|
||||
|
||||
status["Lidarr"] = lidarrStatus;
|
||||
}
|
||||
|
||||
status["Lidarr"] = lidarrStatus;
|
||||
|
||||
return Ok(status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -7,8 +7,6 @@ public class ArrConfigDto
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public required InstanceType Type { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public short FailedImportMaxStrikes { get; set; } = -1;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Cleanuparr.Application.Features.Arr.Dtos;
|
||||
/// </summary>
|
||||
public record CreateArrInstanceDto
|
||||
{
|
||||
public bool Enabled { get; init; } = true;
|
||||
|
||||
[Required]
|
||||
public required string Name { get; init; }
|
||||
|
||||
|
||||
@@ -5,7 +5,5 @@ namespace Cleanuparr.Application.Features.Arr.Dtos;
|
||||
/// </summary>
|
||||
public record UpdateLidarrConfigDto
|
||||
{
|
||||
public bool Enabled { get; init; }
|
||||
|
||||
public short FailedImportMaxStrikes { get; init; } = -1;
|
||||
}
|
||||
@@ -5,7 +5,5 @@ namespace Cleanuparr.Application.Features.Arr.Dtos;
|
||||
/// </summary>
|
||||
public record UpdateRadarrConfigDto
|
||||
{
|
||||
public bool Enabled { get; init; }
|
||||
|
||||
public short FailedImportMaxStrikes { get; init; } = -1;
|
||||
}
|
||||
@@ -7,8 +7,6 @@ namespace Cleanuparr.Application.Features.Arr.Dtos;
|
||||
/// </summary>
|
||||
public record UpdateSonarrConfigDto
|
||||
{
|
||||
public bool Enabled { get; init; }
|
||||
|
||||
public short FailedImportMaxStrikes { get; init; } = -1;
|
||||
}
|
||||
|
||||
@@ -22,6 +20,8 @@ public record ArrInstanceDto
|
||||
/// </summary>
|
||||
public Guid? Id { get; init; }
|
||||
|
||||
public bool Enabled { get; init; } = true;
|
||||
|
||||
[Required]
|
||||
public required string Name { get; init; }
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public sealed class ContentBlocker : GenericHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig arrConfig)
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
||||
{
|
||||
IReadOnlyList<string> ignoredDownloads = ContextProvider.Get<GeneralConfig>().IgnoredDownloads;
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ public sealed class DownloadCleaner : GenericHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig arrConfig)
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
||||
{
|
||||
using var _ = LogContext.PushProperty(LogProperties.Category, instanceType.ToString());
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public sealed class QueueCleaner : GenericHandler
|
||||
await ProcessArrConfigAsync(lidarrConfig, InstanceType.Lidarr);
|
||||
}
|
||||
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig arrConfig)
|
||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
||||
{
|
||||
IReadOnlyList<string> ignoredDownloads = ContextProvider.Get<GeneralConfig>().IgnoredDownloads;
|
||||
|
||||
|
||||
@@ -147,12 +147,17 @@ public abstract class GenericHandler : IHandler
|
||||
|
||||
protected abstract Task ExecuteInternalAsync();
|
||||
|
||||
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig arrConfig);
|
||||
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType);
|
||||
|
||||
protected async Task ProcessArrConfigAsync(ArrConfig config, InstanceType instanceType, bool throwOnFailure = false)
|
||||
{
|
||||
if (!config.Enabled)
|
||||
var enabledInstances = config.Instances
|
||||
.Where(x => x.Enabled)
|
||||
.ToList();
|
||||
|
||||
if (enabledInstances.Count is 0)
|
||||
{
|
||||
_logger.LogDebug($"Skip processing {instanceType}. No enabled instances found");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,7 +165,7 @@ public abstract class GenericHandler : IHandler
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProcessInstanceAsync(arrInstance, instanceType, config);
|
||||
await ProcessInstanceAsync(arrInstance, instanceType);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Cleanuparr.Persistence.Migrations.Data
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20250620212344_InitialData")]
|
||||
[Migration("20250621123139_InitialData")]
|
||||
partial class InitialData
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -28,10 +28,6 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("enabled");
|
||||
|
||||
b.Property<short>("FailedImportMaxStrikes")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("failed_import_max_strikes");
|
||||
@@ -63,6 +59,10 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("arr_config_id");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("enabled");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
@@ -36,7 +36,6 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
{
|
||||
id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
type = table.Column<string>(type: "TEXT", nullable: false),
|
||||
enabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
failed_import_max_strikes = table.Column<short>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
@@ -183,6 +182,7 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
enabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
arr_config_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
url = table.Column<string>(type: "TEXT", nullable: false),
|
||||
@@ -276,18 +276,18 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "arr_configs",
|
||||
columns: new[] { "id", "enabled", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("6096303a-399c-42b8-be8f-60a02cec5a51"), false, (short)-1, "radarr" });
|
||||
columns: new[] { "id", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("6096303a-399c-42b8-be8f-60a02cec5a51"), (short)-1, "radarr" });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "arr_configs",
|
||||
columns: new[] { "id", "enabled", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("4fd2b82b-cffd-4b41-bcc0-204058b1e459"), false, (short)-1, "lidarr" });
|
||||
columns: new[] { "id", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("4fd2b82b-cffd-4b41-bcc0-204058b1e459"), (short)-1, "lidarr" });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "arr_configs",
|
||||
columns: new[] { "id", "enabled", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("0b38a68f-3d7b-4d98-ae96-115da62d9af2"), false, (short)-1, "sonarr" });
|
||||
columns: new[] { "id", "failed_import_max_strikes", "type" },
|
||||
values: new object[] { new Guid("0b38a68f-3d7b-4d98-ae96-115da62d9af2"), (short)-1, "sonarr" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_arr_instances_arr_config_id",
|
||||
@@ -25,10 +25,6 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("enabled");
|
||||
|
||||
b.Property<short>("FailedImportMaxStrikes")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("failed_import_max_strikes");
|
||||
@@ -60,6 +56,10 @@ namespace Cleanuparr.Persistence.Migrations.Data
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("arr_config_id");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("enabled");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
|
||||
@@ -12,8 +12,6 @@ public class ArrConfig : IConfig
|
||||
|
||||
public required InstanceType Type { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public short FailedImportMaxStrikes { get; set; } = -1;
|
||||
|
||||
public List<ArrInstance> Instances { get; set; } = [];
|
||||
|
||||
@@ -10,6 +10,8 @@ public sealed class ArrInstance
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public Guid ArrConfigId { get; set; }
|
||||
|
||||
public ArrConfig? ArrConfig { get; set; }
|
||||
|
||||
@@ -269,7 +269,7 @@ export class ConfigurationService {
|
||||
/**
|
||||
* Update Sonarr configuration (global settings only)
|
||||
*/
|
||||
updateSonarrConfig(config: {enabled: boolean, failedImportMaxStrikes: number}): Observable<any> {
|
||||
updateSonarrConfig(config: {failedImportMaxStrikes: number}): Observable<any> {
|
||||
return this.http.put<any>(this.basePathService.buildApiUrl('/configuration/sonarr'), config).pipe(
|
||||
catchError((error) => {
|
||||
console.error("Error updating Sonarr config:", error);
|
||||
@@ -292,8 +292,8 @@ export class ConfigurationService {
|
||||
/**
|
||||
* Update Radarr configuration
|
||||
*/
|
||||
updateRadarrConfig(config: RadarrConfig): Observable<RadarrConfig> {
|
||||
return this.http.put<RadarrConfig>(this.basePathService.buildApiUrl('/configuration/radarr'), config).pipe(
|
||||
updateRadarrConfig(config: {failedImportMaxStrikes: number}): Observable<any> {
|
||||
return this.http.put<any>(this.basePathService.buildApiUrl('/configuration/radarr'), config).pipe(
|
||||
catchError((error) => {
|
||||
console.error("Error updating Radarr config:", error);
|
||||
return throwError(() => new Error(error.error?.error || "Failed to update Radarr configuration"));
|
||||
@@ -315,8 +315,8 @@ export class ConfigurationService {
|
||||
/**
|
||||
* Update Lidarr configuration
|
||||
*/
|
||||
updateLidarrConfig(config: LidarrConfig): Observable<LidarrConfig> {
|
||||
return this.http.put<LidarrConfig>(this.basePathService.buildApiUrl('/configuration/lidarr'), config).pipe(
|
||||
updateLidarrConfig(config: {failedImportMaxStrikes: number}): Observable<any> {
|
||||
return this.http.put<any>(this.basePathService.buildApiUrl('/configuration/lidarr'), config).pipe(
|
||||
catchError((error) => {
|
||||
console.error("Error updating Lidarr config:", error);
|
||||
return throwError(() => new Error(error.error?.error || "Failed to update Lidarr configuration"));
|
||||
|
||||
@@ -49,44 +49,32 @@ export class LidarrConfigStore extends signalStore(
|
||||
),
|
||||
|
||||
/**
|
||||
* Save the Lidarr configuration (basic settings only)
|
||||
* Save the Lidarr global configuration
|
||||
*/
|
||||
saveConfig: rxMethod<Partial<LidarrConfig>>(
|
||||
(config$: Observable<Partial<LidarrConfig>>) => config$.pipe(
|
||||
saveConfig: rxMethod<{failedImportMaxStrikes: number}>(
|
||||
(globalConfig$: Observable<{failedImportMaxStrikes: number}>) => globalConfig$.pipe(
|
||||
tap(() => patchState(store, { saving: true, error: null })),
|
||||
switchMap(configUpdate => {
|
||||
const currentConfig = store.config();
|
||||
if (!currentConfig) {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: 'No current configuration available'
|
||||
});
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
const updatedConfig: LidarrConfig = {
|
||||
...currentConfig,
|
||||
...configUpdate
|
||||
};
|
||||
|
||||
return configService.updateLidarrConfig(updatedConfig).pipe(
|
||||
tap({
|
||||
next: () => {
|
||||
switchMap(globalConfig => configService.updateLidarrConfig(globalConfig).pipe(
|
||||
tap({
|
||||
next: () => {
|
||||
const currentConfig = store.config();
|
||||
if (currentConfig) {
|
||||
// Update the local config with the new global settings
|
||||
patchState(store, {
|
||||
config: updatedConfig,
|
||||
config: { ...currentConfig, ...globalConfig },
|
||||
saving: false
|
||||
});
|
||||
},
|
||||
error: (error) => {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: error.message || 'Failed to save Lidarr configuration'
|
||||
});
|
||||
}
|
||||
}),
|
||||
catchError(() => EMPTY)
|
||||
);
|
||||
})
|
||||
},
|
||||
error: (error) => {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: error.message || 'Failed to save Lidarr configuration'
|
||||
});
|
||||
}
|
||||
}),
|
||||
catchError(() => EMPTY)
|
||||
))
|
||||
)
|
||||
),
|
||||
|
||||
|
||||
@@ -32,14 +32,6 @@
|
||||
</ng-template>
|
||||
|
||||
<form [formGroup]="globalForm" class="p-fluid">
|
||||
<div class="field-row">
|
||||
<label class="field-label">Enable Lidarr Integration</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">When enabled, Lidarr API integration will be used</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<label class="field-label">Failed Import Max Strikes</label>
|
||||
<div>
|
||||
@@ -108,7 +100,7 @@
|
||||
type="button"
|
||||
icon="pi pi-pencil"
|
||||
class="p-button-text p-button-sm"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="lidarrSaving()"
|
||||
(click)="openEditInstanceModal(instance)"
|
||||
pTooltip="Edit instance"
|
||||
></button>
|
||||
@@ -117,7 +109,7 @@
|
||||
type="button"
|
||||
icon="pi pi-trash"
|
||||
class="p-button-text p-button-sm p-button-danger"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="lidarrSaving()"
|
||||
(click)="deleteInstance(instance)"
|
||||
pTooltip="Delete instance"
|
||||
></button>
|
||||
@@ -128,6 +120,13 @@
|
||||
<div class="instance-field">
|
||||
<label>{{ instance.url }}</label>
|
||||
</div>
|
||||
<div class="instance-field">
|
||||
<label>Status:
|
||||
<span [class]="instance.enabled ? 'text-green-500' : 'text-red-500'">
|
||||
{{ instance.enabled ? 'Enabled' : 'Disabled' }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,7 +139,7 @@
|
||||
icon="pi pi-plus"
|
||||
label="Add Instance"
|
||||
class="p-button-outlined"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="lidarrSaving()"
|
||||
(click)="openAddInstanceModal()"
|
||||
></button>
|
||||
</div>
|
||||
@@ -160,6 +159,14 @@
|
||||
(onHide)="closeInstanceModal()"
|
||||
>
|
||||
<form [formGroup]="instanceForm" class="p-fluid instance-form">
|
||||
<div class="field flex flex-row">
|
||||
<label class="field-label">Enabled</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">Enable this Lidarr instance</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="instance-name">Name *</label>
|
||||
<input
|
||||
|
||||
@@ -82,11 +82,11 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
constructor() {
|
||||
// Initialize forms
|
||||
this.globalForm = this.formBuilder.group({
|
||||
enabled: [false],
|
||||
failedImportMaxStrikes: [{ value: -1, disabled: true }],
|
||||
failedImportMaxStrikes: [-1],
|
||||
});
|
||||
|
||||
this.instanceForm = this.formBuilder.group({
|
||||
enabled: [true],
|
||||
name: ['', Validators.required],
|
||||
url: ['', [Validators.required, this.uriValidator.bind(this)]],
|
||||
apiKey: ['', Validators.required],
|
||||
@@ -95,9 +95,6 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
// Load Lidarr config data
|
||||
this.lidarrStore.loadConfig();
|
||||
|
||||
// Setup form value change listeners
|
||||
this.setupFormValueChangeListeners();
|
||||
|
||||
// Setup effect to update form when config changes
|
||||
effect(() => {
|
||||
const config = this.lidarrConfig();
|
||||
@@ -127,56 +124,13 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
*/
|
||||
private updateGlobalFormFromConfig(config: LidarrConfig): void {
|
||||
this.globalForm.patchValue({
|
||||
enabled: config.enabled,
|
||||
failedImportMaxStrikes: config.failedImportMaxStrikes,
|
||||
});
|
||||
|
||||
// Update form control disabled states
|
||||
this.updateFormControlDisabledStates(config);
|
||||
|
||||
// Store original values for dirty checking
|
||||
this.storeOriginalGlobalValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up listeners for form control value changes to manage dependent control states
|
||||
*/
|
||||
private setupFormValueChangeListeners(): void {
|
||||
// Listen for changes to the 'enabled' control
|
||||
const enabledControl = this.globalForm.get('enabled');
|
||||
if (enabledControl) {
|
||||
enabledControl.valueChanges
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(enabled => {
|
||||
this.updateMainControlsState(enabled);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update form control disabled states based on the configuration
|
||||
*/
|
||||
private updateFormControlDisabledStates(config: LidarrConfig): void {
|
||||
const enabled = config.enabled;
|
||||
this.updateMainControlsState(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state of main controls based on the 'enabled' control value
|
||||
*/
|
||||
private updateMainControlsState(enabled: boolean): void {
|
||||
const failedImportMaxStrikesControl = this.globalForm.get('failedImportMaxStrikes');
|
||||
|
||||
// Disable emitting events during state changes to prevent infinite loops
|
||||
const options = { emitEvent: false };
|
||||
|
||||
if (enabled) {
|
||||
failedImportMaxStrikesControl?.enable(options);
|
||||
} else {
|
||||
failedImportMaxStrikesControl?.disable(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store original global form values for dirty checking
|
||||
*/
|
||||
@@ -280,11 +234,7 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return;
|
||||
}
|
||||
|
||||
const currentConfig = this.lidarrConfig();
|
||||
if (!currentConfig) return;
|
||||
|
||||
const updatedConfig = {
|
||||
enabled: this.globalForm.get('enabled')?.value,
|
||||
failedImportMaxStrikes: this.globalForm.get('failedImportMaxStrikes')?.value
|
||||
};
|
||||
|
||||
@@ -330,20 +280,18 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return this.lidarrConfig()?.instances || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if instance management should be disabled
|
||||
*/
|
||||
get instanceManagementDisabled(): boolean {
|
||||
return !this.globalForm.get('enabled')?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal to add new instance
|
||||
*/
|
||||
openAddInstanceModal(): void {
|
||||
this.modalMode = 'add';
|
||||
this.editingInstance = null;
|
||||
this.instanceForm.reset();
|
||||
this.instanceForm.reset({
|
||||
enabled: true,
|
||||
name: '',
|
||||
url: '',
|
||||
apiKey: ''
|
||||
});
|
||||
this.showInstanceModal = true;
|
||||
}
|
||||
|
||||
@@ -354,6 +302,7 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
this.modalMode = 'edit';
|
||||
this.editingInstance = instance;
|
||||
this.instanceForm.patchValue({
|
||||
enabled: instance.enabled,
|
||||
name: instance.name,
|
||||
url: instance.url,
|
||||
apiKey: instance.apiKey,
|
||||
@@ -382,6 +331,7 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
}
|
||||
|
||||
const instanceData: CreateArrInstanceDto = {
|
||||
enabled: this.instanceForm.get('enabled')?.value,
|
||||
name: this.instanceForm.get('name')?.value,
|
||||
url: this.instanceForm.get('url')?.value,
|
||||
apiKey: this.instanceForm.get('apiKey')?.value,
|
||||
@@ -456,12 +406,12 @@ export class LidarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get modal title based on mode
|
||||
*/
|
||||
get modalTitle(): string {
|
||||
return this.modalMode === 'add' ? 'Add Lidarr Instance' : 'Edit Lidarr Instance';
|
||||
}
|
||||
|
||||
// Add any other necessary methods here
|
||||
}
|
||||
|
||||
@@ -49,44 +49,32 @@ export class RadarrConfigStore extends signalStore(
|
||||
),
|
||||
|
||||
/**
|
||||
* Save the Radarr configuration (basic settings only)
|
||||
* Save the Radarr global configuration
|
||||
*/
|
||||
saveConfig: rxMethod<Partial<RadarrConfig>>(
|
||||
(config$: Observable<Partial<RadarrConfig>>) => config$.pipe(
|
||||
saveConfig: rxMethod<{failedImportMaxStrikes: number}>(
|
||||
(globalConfig$: Observable<{failedImportMaxStrikes: number}>) => globalConfig$.pipe(
|
||||
tap(() => patchState(store, { saving: true, error: null })),
|
||||
switchMap(configUpdate => {
|
||||
const currentConfig = store.config();
|
||||
if (!currentConfig) {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: 'No current configuration available'
|
||||
});
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
const updatedConfig: RadarrConfig = {
|
||||
...currentConfig,
|
||||
...configUpdate
|
||||
};
|
||||
|
||||
return configService.updateRadarrConfig(updatedConfig).pipe(
|
||||
tap({
|
||||
next: () => {
|
||||
switchMap(globalConfig => configService.updateRadarrConfig(globalConfig).pipe(
|
||||
tap({
|
||||
next: () => {
|
||||
const currentConfig = store.config();
|
||||
if (currentConfig) {
|
||||
// Update the local config with the new global settings
|
||||
patchState(store, {
|
||||
config: updatedConfig,
|
||||
config: { ...currentConfig, ...globalConfig },
|
||||
saving: false
|
||||
});
|
||||
},
|
||||
error: (error) => {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: error.message || 'Failed to save Radarr configuration'
|
||||
});
|
||||
}
|
||||
}),
|
||||
catchError(() => EMPTY)
|
||||
);
|
||||
})
|
||||
},
|
||||
error: (error) => {
|
||||
patchState(store, {
|
||||
saving: false,
|
||||
error: error.message || 'Failed to save Radarr configuration'
|
||||
});
|
||||
}
|
||||
}),
|
||||
catchError(() => EMPTY)
|
||||
))
|
||||
)
|
||||
),
|
||||
|
||||
|
||||
@@ -32,14 +32,6 @@
|
||||
</ng-template>
|
||||
|
||||
<form [formGroup]="globalForm" class="p-fluid">
|
||||
<div class="field-row">
|
||||
<label class="field-label">Enable Radarr Integration</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">When enabled, Radarr API integration will be used</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<label class="field-label">Failed Import Max Strikes</label>
|
||||
<div>
|
||||
@@ -108,7 +100,7 @@
|
||||
type="button"
|
||||
icon="pi pi-pencil"
|
||||
class="p-button-text p-button-sm"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="radarrSaving()"
|
||||
(click)="openEditInstanceModal(instance)"
|
||||
pTooltip="Edit instance"
|
||||
></button>
|
||||
@@ -117,7 +109,7 @@
|
||||
type="button"
|
||||
icon="pi pi-trash"
|
||||
class="p-button-text p-button-sm p-button-danger"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="radarrSaving()"
|
||||
(click)="deleteInstance(instance)"
|
||||
pTooltip="Delete instance"
|
||||
></button>
|
||||
@@ -128,6 +120,13 @@
|
||||
<div class="instance-field">
|
||||
<label>{{ instance.url }}</label>
|
||||
</div>
|
||||
<div class="instance-field">
|
||||
<label>Status:
|
||||
<span [class]="instance.enabled ? 'text-green-500' : 'text-red-500'">
|
||||
{{ instance.enabled ? 'Enabled' : 'Disabled' }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,7 +139,7 @@
|
||||
icon="pi pi-plus"
|
||||
label="Add Instance"
|
||||
class="p-button-outlined"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="radarrSaving()"
|
||||
(click)="openAddInstanceModal()"
|
||||
></button>
|
||||
</div>
|
||||
@@ -160,6 +159,14 @@
|
||||
(onHide)="closeInstanceModal()"
|
||||
>
|
||||
<form [formGroup]="instanceForm" class="p-fluid instance-form">
|
||||
<div class="field flex flex-row">
|
||||
<label class="field-label">Enabled</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">Enable this Radarr instance</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="instance-name">Name *</label>
|
||||
<input
|
||||
|
||||
@@ -82,11 +82,11 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
constructor() {
|
||||
// Initialize forms
|
||||
this.globalForm = this.formBuilder.group({
|
||||
enabled: [false],
|
||||
failedImportMaxStrikes: [{ value: -1, disabled: true }],
|
||||
failedImportMaxStrikes: [-1],
|
||||
});
|
||||
|
||||
this.instanceForm = this.formBuilder.group({
|
||||
enabled: [true],
|
||||
name: ['', Validators.required],
|
||||
url: ['', [Validators.required, this.uriValidator.bind(this)]],
|
||||
apiKey: ['', Validators.required],
|
||||
@@ -95,9 +95,6 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
// Load Radarr config data
|
||||
this.radarrStore.loadConfig();
|
||||
|
||||
// Setup form value change listeners
|
||||
this.setupFormValueChangeListeners();
|
||||
|
||||
// Setup effect to update form when config changes
|
||||
effect(() => {
|
||||
const config = this.radarrConfig();
|
||||
@@ -127,56 +124,13 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
*/
|
||||
private updateGlobalFormFromConfig(config: RadarrConfig): void {
|
||||
this.globalForm.patchValue({
|
||||
enabled: config.enabled,
|
||||
failedImportMaxStrikes: config.failedImportMaxStrikes,
|
||||
});
|
||||
|
||||
// Update form control disabled states
|
||||
this.updateFormControlDisabledStates(config);
|
||||
|
||||
// Store original values for dirty checking
|
||||
this.storeOriginalGlobalValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up listeners for form control value changes to manage dependent control states
|
||||
*/
|
||||
private setupFormValueChangeListeners(): void {
|
||||
// Listen for changes to the 'enabled' control
|
||||
const enabledControl = this.globalForm.get('enabled');
|
||||
if (enabledControl) {
|
||||
enabledControl.valueChanges
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(enabled => {
|
||||
this.updateMainControlsState(enabled);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update form control disabled states based on the configuration
|
||||
*/
|
||||
private updateFormControlDisabledStates(config: RadarrConfig): void {
|
||||
const enabled = config.enabled;
|
||||
this.updateMainControlsState(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state of main controls based on the 'enabled' control value
|
||||
*/
|
||||
private updateMainControlsState(enabled: boolean): void {
|
||||
const failedImportMaxStrikesControl = this.globalForm.get('failedImportMaxStrikes');
|
||||
|
||||
// Disable emitting events during state changes to prevent infinite loops
|
||||
const options = { emitEvent: false };
|
||||
|
||||
if (enabled) {
|
||||
failedImportMaxStrikesControl?.enable(options);
|
||||
} else {
|
||||
failedImportMaxStrikesControl?.disable(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store original global form values for dirty checking
|
||||
*/
|
||||
@@ -280,11 +234,7 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return;
|
||||
}
|
||||
|
||||
const currentConfig = this.radarrConfig();
|
||||
if (!currentConfig) return;
|
||||
|
||||
const updatedConfig = {
|
||||
enabled: this.globalForm.get('enabled')?.value,
|
||||
failedImportMaxStrikes: this.globalForm.get('failedImportMaxStrikes')?.value
|
||||
};
|
||||
|
||||
@@ -330,20 +280,18 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return this.radarrConfig()?.instances || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if instance management should be disabled
|
||||
*/
|
||||
get instanceManagementDisabled(): boolean {
|
||||
return !this.globalForm.get('enabled')?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal to add new instance
|
||||
*/
|
||||
openAddInstanceModal(): void {
|
||||
this.modalMode = 'add';
|
||||
this.editingInstance = null;
|
||||
this.instanceForm.reset();
|
||||
this.instanceForm.reset({
|
||||
enabled: true,
|
||||
name: '',
|
||||
url: '',
|
||||
apiKey: ''
|
||||
});
|
||||
this.showInstanceModal = true;
|
||||
}
|
||||
|
||||
@@ -354,6 +302,7 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
this.modalMode = 'edit';
|
||||
this.editingInstance = instance;
|
||||
this.instanceForm.patchValue({
|
||||
enabled: instance.enabled,
|
||||
name: instance.name,
|
||||
url: instance.url,
|
||||
apiKey: instance.apiKey,
|
||||
@@ -382,6 +331,7 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
}
|
||||
|
||||
const instanceData: CreateArrInstanceDto = {
|
||||
enabled: this.instanceForm.get('enabled')?.value,
|
||||
name: this.instanceForm.get('name')?.value,
|
||||
url: this.instanceForm.get('url')?.value,
|
||||
apiKey: this.instanceForm.get('apiKey')?.value,
|
||||
@@ -456,12 +406,12 @@ export class RadarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get modal title based on mode
|
||||
*/
|
||||
get modalTitle(): string {
|
||||
return this.modalMode === 'add' ? 'Add Radarr Instance' : 'Edit Radarr Instance';
|
||||
}
|
||||
|
||||
// Add any other necessary methods here
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ export class SonarrConfigStore extends signalStore(
|
||||
/**
|
||||
* Save the Sonarr global configuration
|
||||
*/
|
||||
saveConfig: rxMethod<{enabled: boolean, failedImportMaxStrikes: number}>(
|
||||
(globalConfig$: Observable<{enabled: boolean, failedImportMaxStrikes: number}>) => globalConfig$.pipe(
|
||||
saveConfig: rxMethod<{failedImportMaxStrikes: number}>(
|
||||
(globalConfig$: Observable<{failedImportMaxStrikes: number}>) => globalConfig$.pipe(
|
||||
tap(() => patchState(store, { saving: true, error: null })),
|
||||
switchMap(globalConfig => configService.updateSonarrConfig(globalConfig).pipe(
|
||||
tap({
|
||||
|
||||
@@ -32,14 +32,6 @@
|
||||
</ng-template>
|
||||
|
||||
<form [formGroup]="globalForm" class="p-fluid">
|
||||
<div class="field-row">
|
||||
<label class="field-label">Enable Sonarr Integration</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">When enabled, Sonarr API integration will be used</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<label class="field-label">Failed Import Max Strikes</label>
|
||||
<div>
|
||||
@@ -108,7 +100,7 @@
|
||||
type="button"
|
||||
icon="pi pi-pencil"
|
||||
class="p-button-text p-button-sm"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="sonarrSaving()"
|
||||
(click)="openEditInstanceModal(instance)"
|
||||
pTooltip="Edit instance"
|
||||
></button>
|
||||
@@ -117,7 +109,7 @@
|
||||
type="button"
|
||||
icon="pi pi-trash"
|
||||
class="p-button-text p-button-sm p-button-danger"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="sonarrSaving()"
|
||||
(click)="deleteInstance(instance)"
|
||||
pTooltip="Delete instance"
|
||||
></button>
|
||||
@@ -128,6 +120,13 @@
|
||||
<div class="instance-field">
|
||||
<label>{{ instance.url }}</label>
|
||||
</div>
|
||||
<div class="instance-field">
|
||||
<label>Status:
|
||||
<span [class]="instance.enabled ? 'text-green-500' : 'text-red-500'">
|
||||
{{ instance.enabled ? 'Enabled' : 'Disabled' }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,7 +139,7 @@
|
||||
icon="pi pi-plus"
|
||||
label="Add Instance"
|
||||
class="p-button-outlined"
|
||||
[disabled]="instanceManagementDisabled"
|
||||
[disabled]="sonarrSaving()"
|
||||
(click)="openAddInstanceModal()"
|
||||
></button>
|
||||
</div>
|
||||
@@ -160,6 +159,14 @@
|
||||
(onHide)="closeInstanceModal()"
|
||||
>
|
||||
<form [formGroup]="instanceForm" class="p-fluid instance-form">
|
||||
<div class="field flex flex-row">
|
||||
<label class="field-label">Enabled</label>
|
||||
<div class="field-input">
|
||||
<p-checkbox formControlName="enabled" [binary]="true"></p-checkbox>
|
||||
<small class="form-helper-text">Enable this Sonarr instance</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="instance-name">Name *</label>
|
||||
<input
|
||||
|
||||
@@ -82,11 +82,11 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
constructor() {
|
||||
// Initialize forms
|
||||
this.globalForm = this.formBuilder.group({
|
||||
enabled: [false],
|
||||
failedImportMaxStrikes: [{ value: -1, disabled: true }],
|
||||
failedImportMaxStrikes: [-1],
|
||||
});
|
||||
|
||||
this.instanceForm = this.formBuilder.group({
|
||||
enabled: [true],
|
||||
name: ['', Validators.required],
|
||||
url: ['', [Validators.required, this.uriValidator.bind(this)]],
|
||||
apiKey: ['', Validators.required],
|
||||
@@ -95,9 +95,6 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
// Load Sonarr config data
|
||||
this.sonarrStore.loadConfig();
|
||||
|
||||
// Setup form value change listeners
|
||||
this.setupFormValueChangeListeners();
|
||||
|
||||
// Setup effect to update form when config changes
|
||||
effect(() => {
|
||||
const config = this.sonarrConfig();
|
||||
@@ -127,56 +124,13 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
*/
|
||||
private updateGlobalFormFromConfig(config: SonarrConfig): void {
|
||||
this.globalForm.patchValue({
|
||||
enabled: config.enabled,
|
||||
failedImportMaxStrikes: config.failedImportMaxStrikes,
|
||||
});
|
||||
|
||||
// Update form control disabled states
|
||||
this.updateFormControlDisabledStates(config);
|
||||
|
||||
// Store original values for dirty checking
|
||||
this.storeOriginalGlobalValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up listeners for form control value changes to manage dependent control states
|
||||
*/
|
||||
private setupFormValueChangeListeners(): void {
|
||||
// Listen for changes to the 'enabled' control
|
||||
const enabledControl = this.globalForm.get('enabled');
|
||||
if (enabledControl) {
|
||||
enabledControl.valueChanges
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(enabled => {
|
||||
this.updateMainControlsState(enabled);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update form control disabled states based on the configuration
|
||||
*/
|
||||
private updateFormControlDisabledStates(config: SonarrConfig): void {
|
||||
const enabled = config.enabled;
|
||||
this.updateMainControlsState(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state of main controls based on the 'enabled' control value
|
||||
*/
|
||||
private updateMainControlsState(enabled: boolean): void {
|
||||
const failedImportMaxStrikesControl = this.globalForm.get('failedImportMaxStrikes');
|
||||
|
||||
// Disable emitting events during state changes to prevent infinite loops
|
||||
const options = { emitEvent: false };
|
||||
|
||||
if (enabled) {
|
||||
failedImportMaxStrikesControl?.enable(options);
|
||||
} else {
|
||||
failedImportMaxStrikesControl?.disable(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store original global form values for dirty checking
|
||||
*/
|
||||
@@ -280,11 +234,7 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return;
|
||||
}
|
||||
|
||||
const currentConfig = this.sonarrConfig();
|
||||
if (!currentConfig) return;
|
||||
|
||||
const updatedConfig = {
|
||||
enabled: this.globalForm.get('enabled')?.value,
|
||||
failedImportMaxStrikes: this.globalForm.get('failedImportMaxStrikes')?.value
|
||||
};
|
||||
|
||||
@@ -330,20 +280,18 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
return this.sonarrConfig()?.instances || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if instance management should be disabled
|
||||
*/
|
||||
get instanceManagementDisabled(): boolean {
|
||||
return !this.globalForm.get('enabled')?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal to add new instance
|
||||
*/
|
||||
openAddInstanceModal(): void {
|
||||
this.modalMode = 'add';
|
||||
this.editingInstance = null;
|
||||
this.instanceForm.reset();
|
||||
this.instanceForm.reset({
|
||||
enabled: true,
|
||||
name: '',
|
||||
url: '',
|
||||
apiKey: ''
|
||||
});
|
||||
this.showInstanceModal = true;
|
||||
}
|
||||
|
||||
@@ -354,6 +302,7 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
this.modalMode = 'edit';
|
||||
this.editingInstance = instance;
|
||||
this.instanceForm.patchValue({
|
||||
enabled: instance.enabled,
|
||||
name: instance.name,
|
||||
url: instance.url,
|
||||
apiKey: instance.apiKey,
|
||||
@@ -382,6 +331,7 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
}
|
||||
|
||||
const instanceData: CreateArrInstanceDto = {
|
||||
enabled: this.instanceForm.get('enabled')?.value,
|
||||
name: this.instanceForm.get('name')?.value,
|
||||
url: this.instanceForm.get('url')?.value,
|
||||
apiKey: this.instanceForm.get('apiKey')?.value,
|
||||
@@ -456,12 +406,12 @@ export class SonarrSettingsComponent implements OnDestroy, CanComponentDeactivat
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get modal title based on mode
|
||||
*/
|
||||
get modalTitle(): string {
|
||||
return this.modalMode === 'add' ? 'Add Sonarr Instance' : 'Edit Sonarr Instance';
|
||||
}
|
||||
|
||||
// Add any other necessary methods here
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
export interface ArrInstance {
|
||||
id?: string;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
url: string;
|
||||
apiKey: string;
|
||||
@@ -12,6 +13,7 @@ export interface ArrInstance {
|
||||
* DTO for creating new Arr instances without requiring an ID
|
||||
*/
|
||||
export interface CreateArrInstanceDto {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
url: string;
|
||||
apiKey: string;
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ArrInstance } from "./arr-config.model";
|
||||
* Main LidarrConfig model representing the configuration for Lidarr integration
|
||||
*/
|
||||
export interface LidarrConfig {
|
||||
enabled: boolean;
|
||||
failedImportMaxStrikes: number;
|
||||
instances: ArrInstance[];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ArrInstance } from "./arr-config.model";
|
||||
* Main RadarrConfig model representing the configuration for Radarr integration
|
||||
*/
|
||||
export interface RadarrConfig {
|
||||
enabled: boolean;
|
||||
failedImportMaxStrikes: number;
|
||||
instances: ArrInstance[];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ArrInstance } from "./arr-config.model";
|
||||
* Main SonarrConfig model representing the configuration for Sonarr integration
|
||||
*/
|
||||
export interface SonarrConfig {
|
||||
enabled: boolean;
|
||||
failedImportMaxStrikes: number;
|
||||
instances: ArrInstance[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user