Various UI Fixes and Updates

Closes #188
Closes #185
Closes #187
This commit is contained in:
Qstick 2018-01-25 22:01:53 -05:00
commit 54e9f88648
89 changed files with 2354 additions and 995 deletions

View file

@ -1,6 +1,7 @@
using System;
using System;
using System.Linq;
using Nancy.Responses;
using NzbDrone.Common.TPL;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.Messaging.Events;
@ -16,12 +17,18 @@ namespace Lidarr.Api.V1.Queue
{
private readonly IQueueService _queueService;
private readonly IPendingReleaseService _pendingReleaseService;
private readonly Debouncer _broadcastDebounce;
public QueueStatusModule(IBroadcastSignalRMessage broadcastSignalRMessage, IQueueService queueService, IPendingReleaseService pendingReleaseService)
: base(broadcastSignalRMessage, "queue/status")
{
_queueService = queueService;
_pendingReleaseService = pendingReleaseService;
_broadcastDebounce = new Debouncer(BroadcastChange, TimeSpan.FromSeconds(5));
Get["/"] = x => GetQueueStatusResponse();
}
@ -32,25 +39,38 @@ namespace Lidarr.Api.V1.Queue
private QueueStatusResource GetQueueStatus()
{
_broadcastDebounce.Pause();
var queue = _queueService.GetQueue();
var pending = _pendingReleaseService.GetPendingQueue();
return new QueueStatusResource
var resource = new QueueStatusResource
{
Count = queue.Count + pending.Count,
Errors = queue.Any(q => q.TrackedDownloadStatus.Equals("Error", StringComparison.InvariantCultureIgnoreCase)),
Warnings = queue.Any(q => q.TrackedDownloadStatus.Equals("Warning", StringComparison.InvariantCultureIgnoreCase))
};
_broadcastDebounce.Resume();
return resource;
}
private void BroadcastChange()
{
BroadcastResourceChange(ModelAction.Updated, GetQueueStatus());
}
public void Handle(QueueUpdatedEvent message)
{
BroadcastResourceChange(ModelAction.Updated, GetQueueStatus());
_broadcastDebounce.Execute();
}
public void Handle(PendingReleasesUpdatedEvent message)
{
BroadcastResourceChange(ModelAction.Updated, GetQueueStatus());
_broadcastDebounce.Execute();
}
}
}
}

View file

@ -17,8 +17,9 @@ using HttpStatusCode = System.Net.HttpStatusCode;
namespace Lidarr.Api.V1.TrackFiles
{
public class TrackModule : LidarrRestModuleWithSignalR<TrackFileResource, TrackFile>,
IHandle<TrackFileAddedEvent>
public class TrackFileModule : LidarrRestModuleWithSignalR<TrackFileResource, TrackFile>,
IHandle<TrackFileAddedEvent>,
IHandle<TrackFileDeletedEvent>
{
private readonly IMediaFileService _mediaFileService;
private readonly IDeleteMediaFiles _mediaFileDeletionService;
@ -26,7 +27,7 @@ namespace Lidarr.Api.V1.TrackFiles
private readonly IAlbumService _albumService;
private readonly IUpgradableSpecification _upgradableSpecification;
public TrackModule(IBroadcastSignalRMessage signalRBroadcaster,
public TrackFileModule(IBroadcastSignalRMessage signalRBroadcaster,
IMediaFileService mediaFileService,
IDeleteMediaFiles mediaFileDeletionService,
IArtistService artistService,
@ -170,5 +171,11 @@ namespace Lidarr.Api.V1.TrackFiles
{
BroadcastResourceChange(ModelAction.Updated, message.TrackFile.Id);
}
public void Handle(TrackFileDeletedEvent message)
{
BroadcastResourceChange(ModelAction.Deleted, message.TrackFile.Id);
}
}
}

View file

@ -2,6 +2,7 @@ using System.Collections.Generic;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Music;
using NzbDrone.Core.Music.Events;
@ -15,7 +16,8 @@ namespace Lidarr.Api.V1.Tracks
{
public abstract class TrackModuleWithSignalR : LidarrRestModuleWithSignalR<TrackResource, Track>,
IHandle<TrackInfoRefreshedEvent>,
IHandle<TrackImportedEvent>
IHandle<TrackImportedEvent>,
IHandle<TrackFileDeletedEvent>
{
protected readonly ITrackService _trackService;
protected readonly IArtistService _artistService;
@ -131,5 +133,13 @@ namespace Lidarr.Api.V1.Tracks
}
}
public void Handle(TrackFileDeletedEvent message)
{
foreach (var track in message.TrackFile.Tracks.Value)
{
BroadcastResourceChange(ModelAction.Deleted, track.Id);
}
}
}
}

View file

@ -35,8 +35,15 @@ namespace Lidarr.Http
protected void BroadcastResourceChange(ModelAction action, int id)
{
var resource = GetResourceById(id);
BroadcastResourceChange(action, resource);
if (action == ModelAction.Deleted)
{
BroadcastResourceChange(action, new TResource { Id = id });
}
else
{
var resource = GetResourceById(id);
BroadcastResourceChange(action, resource);
}
}

View file

@ -83,6 +83,10 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(new TrackFileMoveResult());
_downloadClientItem = Builder<DownloadClientItem>.CreateNew().Build();
Mocker.GetMock<IMediaFileService>()
.Setup(s => s.GetFilesWithRelativePath(It.IsAny<int>(), It.IsAny<string>()))
.Returns(new List<TrackFile>());
}
[Test]
@ -198,5 +202,19 @@ namespace NzbDrone.Core.Test.MediaFiles
Mocker.GetMock<IUpgradeMediaFiles>()
.Verify(v => v.UpgradeTrackFile(It.IsAny<TrackFile>(), _approvedDecisions.First().LocalTrack, false), Times.Once());
}
[Test]
public void should_delete_existing_metadata_files_with_the_same_path()
{
Mocker.GetMock<IMediaFileService>()
.Setup(s => s.GetFilesWithRelativePath(It.IsAny<int>(), It.IsAny<string>()))
.Returns(Builder<TrackFile>.CreateListOfSize(1).BuildList());
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, false);
Mocker.GetMock<IMediaFileService>()
.Verify(v => v.Delete(It.IsAny<TrackFile>(), DeleteMediaFileReason.ManualOverride), Times.Once());
}
}
}

View file

@ -26,7 +26,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
var monoVersion = _platformInfo.Version;
if (monoVersion == new Version("4.4.0") || monoVersion == new Version("4.4.1"))
if (monoVersion == new Version("4.4") || monoVersion == new Version("4.4.1"))
{
_logger.Debug("Mono version {0}", monoVersion);
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Your Mono version {monoVersion} has a bug that causes issues connecting to indexers/download clients. You should upgrade to a higher version");
@ -34,7 +34,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
if (monoVersion >= new Version("4.4"))
{
_logger.Debug("Mono version is 4.6 or better: {0}", monoVersion);
_logger.Debug("Mono version is 4.4 or better: {0}", monoVersion);
return new HealthCheck(GetType());
}

View file

@ -248,6 +248,12 @@ namespace NzbDrone.Core.History
_logger.Debug("Removing track file from DB as part of cleanup routine, not creating history event.");
return;
}
else if (message.Reason == DeleteMediaFileReason.ManualOverride)
{
_logger.Debug("Removing track file from DB as part of manual override of existing file, not creating history event.");
return;
}
foreach (var track in message.TrackFile.Tracks.Value)
{

View file

@ -1,10 +1,11 @@
namespace NzbDrone.Core.MediaFiles
namespace NzbDrone.Core.MediaFiles
{
public enum DeleteMediaFileReason
{
MissingFromDisk,
Manual,
Upgrade,
NoLinkedEpisodes
NoLinkedEpisodes,
ManualOverride
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
@ -11,6 +11,7 @@ namespace NzbDrone.Core.MediaFiles
List<TrackFile> GetFilesByArtist(int artistId);
List<TrackFile> GetFilesByAlbum(int albumId);
List<TrackFile> GetFilesWithoutMediaInfo();
List<TrackFile> GetFilesWithRelativePath(int artistId, string relativePath);
}
@ -35,5 +36,13 @@ namespace NzbDrone.Core.MediaFiles
{
return Query.Where(c => c.AlbumId == albumId).ToList();
}
public List<TrackFile> GetFilesWithRelativePath(int artistId, string relativePath)
{
return Query.Where(c => c.ArtistId == artistId)
.AndWhere(c => c.RelativePath == relativePath)
.ToList();
}
}
}
}

View file

@ -24,6 +24,7 @@ namespace NzbDrone.Core.MediaFiles
List<string> FilterExistingFiles(List<string> files, Artist artist);
TrackFile Get(int id);
List<TrackFile> Get(IEnumerable<int> ids);
List<TrackFile> GetFilesWithRelativePath(int artistId, string relativePath);
}
@ -98,6 +99,11 @@ namespace NzbDrone.Core.MediaFiles
return _mediaFileRepository.Get(ids).ToList();
}
public List<TrackFile> GetFilesWithRelativePath(int artistId, string relativePath)
{
return _mediaFileRepository.GetFilesWithRelativePath(artistId, relativePath);
}
public void HandleAsync(ArtistDeletedEvent message)
{
var files = GetFilesByArtist(message.Artist.Id);

View file

@ -147,7 +147,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
}
Logger.Debug()
.Message("Unknown audio format: '{0}' in '{1}'.", string.Join(", ", audioFormat, audioCodecID, audioProfile, audioCodecLibrary))
.Message("Unknown audio format: '{0}'.", string.Join(", ", audioFormat, audioCodecID, audioProfile, audioCodecLibrary))
.WriteSentryWarn("UnknownAudioFormat", mediaInfo.ContainerFormat, audioFormat, audioCodecID)
.Write();

View file

@ -115,6 +115,15 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
else
{
trackFile.RelativePath = localTrack.Artist.Path.GetRelativePath(trackFile.Path);
// Delete existing files from the DB mapped to this path
var previousFiles = _mediaFileService.GetFilesWithRelativePath(localTrack.Artist.Id, trackFile.RelativePath);
foreach (var previousFile in previousFiles)
{
_mediaFileService.Delete(previousFile, DeleteMediaFileReason.ManualOverride);
}
}
_mediaFileService.Add(trackFile);