From d9eab040297d41b38f744bd75f2439807cdd6a9a Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sat, 8 Mar 2014 19:01:51 +0000 Subject: [PATCH] Add new feature, set file date to episode aired date. Fix, use alternative Trakt API field for episode air time. Improve the Preview Rename tip. Add, new setting "Set File Date to Airdate" on the Media Management tab of the Settings page to toggle this feature for new, imported and auto updating media files. Change, home page "Series Editor" - "Rename" button to "Update Files" and add "Set File Date To Air Date" action button to this modal to add capability of updating legacy media. Add, non UTC functions given that Windows undesirably adds time to file times set when using UTC. Fix, the Trakt API response show.air_time_utc contains erroneous data, this is replaced with show.air_time. --- .../Config/MediaManagementConfigResource.cs | 1 + src/NzbDrone.Api/Logs/LogFileModule.cs | 2 +- src/NzbDrone.Common/Disk/DiskProviderBase.cs | 36 +++- src/NzbDrone.Common/Disk/IDiskProvider.cs | 3 + .../MediaCoverServiceFixture.cs | 2 +- .../NotUnpackingSpecificationFixture.cs | 2 +- .../RecycleBinProviderTests/CleanupFixture.cs | 4 +- .../Configuration/ConfigService.cs | 6 + .../Configuration/IConfigService.cs | 1 + .../MediaCover/MediaCoverService.cs | 2 +- .../Commands/AirDateSeriesCommand.cs | 18 ++ .../MediaFiles/EpisodeFileMovingService.cs | 8 + .../NotUnpackingSpecification.cs | 2 +- .../MediaFiles/Events/SeriesAirDatedEvent.cs | 15 ++ .../MediaFiles/RecycleBinProvider.cs | 2 +- .../MediaFiles/UpdateEpisodeFileService.cs | 156 ++++++++++++++++++ .../MetadataSource/TraktProxy.cs | 2 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 3 + .../Series/Editor/SeriesEditorFooterView.js | 34 ++-- .../SeriesEditorFooterViewTemplate.html | 2 +- .../UpdateFilesSeriesView.js} | 19 ++- .../UpdateFilesSeriesViewTemplate.html} | 11 +- src/UI/Series/series.less | 6 +- .../FileManagementViewTemplate.html | 17 ++ 24 files changed, 316 insertions(+), 38 deletions(-) create mode 100644 src/NzbDrone.Core/MediaFiles/Commands/AirDateSeriesCommand.cs create mode 100644 src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs create mode 100644 src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs rename src/UI/Series/Editor/{Rename/RenameSeriesView.js => UpdateFiles/UpdateFilesSeriesView.js} (58%) rename src/UI/Series/Editor/{Rename/RenameSeriesViewTemplate.html => UpdateFiles/UpdateFilesSeriesViewTemplate.html} (56%) diff --git a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs index 9ff4efc66..279955620 100644 --- a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs +++ b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs @@ -6,6 +6,7 @@ namespace NzbDrone.Api.Config public class MediaManagementConfigResource : RestResource { public Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; } + public Boolean FileDateAiredDate { get; set; } public String RecycleBin { get; set; } public Boolean AutoDownloadPropers { get; set; } public Boolean CreateEmptySeriesFolders { get; set; } diff --git a/src/NzbDrone.Api/Logs/LogFileModule.cs b/src/NzbDrone.Api/Logs/LogFileModule.cs index b896e6020..544866a1d 100644 --- a/src/NzbDrone.Api/Logs/LogFileModule.cs +++ b/src/NzbDrone.Api/Logs/LogFileModule.cs @@ -35,7 +35,7 @@ private List GetLogFiles() { Id = i + 1, Filename = Path.GetFileName(file), - LastWriteTime = _diskProvider.GetLastFileWrite(file) + LastWriteTime = _diskProvider.GetLastFileWriteUTC(file) }); } diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index d4a21b3c4..42aadc7c9 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -77,6 +77,20 @@ public DateTime GetLastFolderWrite(string path) } public DateTime GetLastFileWrite(string path) + { + PathEnsureFileExists(path); + + return new FileInfo(path).LastWriteTime; + } + + public DateTime GetLastFileWriteUTC(string path) + { + PathEnsureFileExists(path); + + return new FileInfo(path).LastWriteTimeUtc; + } + + private void PathEnsureFileExists(string path) { Ensure.That(path, () => path).IsValidPath(); @@ -84,8 +98,6 @@ public DateTime GetLastFileWrite(string path) { throw new FileNotFoundException("File doesn't exist: " + path); } - - return new FileInfo(path).LastWriteTimeUtc; } public void EnsureFolder(string path) @@ -305,6 +317,26 @@ public void FolderSetLastWriteTimeUtc(string path, DateTime dateTime) Directory.SetLastWriteTimeUtc(path, dateTime); } + public void FileSetLastWriteTime(string path, DateTime dateTime) + { + Ensure.That(path, () => path).IsValidPath(); + + File.SetLastWriteTime(path, dateTime); + } + public void FileSetLastAccessTime(string path, DateTime dateTime) + { + Ensure.That(path, () => path).IsValidPath(); + + File.SetLastAccessTimeUtc(path, dateTime); + } + + public void FileSetLastAccessTimeUtc(string path, DateTime dateTime) + { + Ensure.That(path, () => path).IsValidPath(); + + File.SetLastAccessTimeUtc(path, dateTime); + } + public bool IsFileLocked(string file) { try diff --git a/src/NzbDrone.Common/Disk/IDiskProvider.cs b/src/NzbDrone.Common/Disk/IDiskProvider.cs index 5eac1610d..fa7abc2b0 100644 --- a/src/NzbDrone.Common/Disk/IDiskProvider.cs +++ b/src/NzbDrone.Common/Disk/IDiskProvider.cs @@ -14,6 +14,7 @@ public interface IDiskProvider DateTime GetLastFolderWrite(string path); DateTime GetLastFileWrite(string path); + DateTime GetLastFileWriteUTC(string path); void EnsureFolder(string path); bool FolderExists(string path); bool FileExists(string path); @@ -33,6 +34,8 @@ public interface IDiskProvider void WriteAllText(string filename, string contents); void FileSetLastWriteTimeUtc(string path, DateTime dateTime); void FolderSetLastWriteTimeUtc(string path, DateTime dateTime); + void FileSetLastWriteTime(string path, DateTime dateTime); + void FileSetLastAccessTime(string path, DateTime dateTime); bool IsFileLocked(string path); string GetPathRoot(string path); string GetParentFolder(string path); diff --git a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs index f06a50f77..ad3d58fa7 100644 --- a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs @@ -29,7 +29,7 @@ public void should_convert_trakts_urls_to_local() new MediaCover.MediaCover {CoverType = MediaCoverTypes.Banner} }; - Mocker.GetMock().Setup(c => c.GetLastFileWrite(It.IsAny())) + Mocker.GetMock().Setup(c => c.GetLastFileWriteUTC(It.IsAny())) .Returns(new DateTime(1234)); Mocker.GetMock().Setup(c => c.FileExists(It.IsAny())) diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecificationFixture.cs index ba39c485e..275f52601 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecificationFixture.cs @@ -42,7 +42,7 @@ private void GivenInWorkingFolder() private void GivenLastWriteTimeUtc(DateTime time) { Mocker.GetMock() - .Setup(s => s.GetLastFileWrite(It.IsAny())) + .Setup(s => s.GetLastFileWriteUTC(It.IsAny())) .Returns(time); } diff --git a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs index ba42b585a..32b673728 100644 --- a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs +++ b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs @@ -21,7 +21,7 @@ private void WithExpired() Mocker.GetMock().Setup(s => s.GetLastFolderWrite(It.IsAny())) .Returns(DateTime.UtcNow.AddDays(-10)); - Mocker.GetMock().Setup(s => s.GetLastFileWrite(It.IsAny())) + Mocker.GetMock().Setup(s => s.GetLastFileWriteUTC(It.IsAny())) .Returns(DateTime.UtcNow.AddDays(-10)); } @@ -30,7 +30,7 @@ private void WithNonExpired() Mocker.GetMock().Setup(s => s.GetLastFolderWrite(It.IsAny())) .Returns(DateTime.UtcNow.AddDays(-3)); - Mocker.GetMock().Setup(s => s.GetLastFileWrite(It.IsAny())) + Mocker.GetMock().Setup(s => s.GetLastFileWriteUTC(It.IsAny())) .Returns(DateTime.UtcNow.AddDays(-3)); } diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index a0aa00bc8..6a39a8191 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -86,6 +86,12 @@ public bool AutoUnmonitorPreviouslyDownloadedEpisodes set { SetValue("AutoUnmonitorPreviouslyDownloadedEpisodes", value); } } + public bool FileDateAiredDate + { + get { return GetValueBoolean("FileDateAiredDate"); } + set { SetValue("FileDateAiredDate", value); } + } + public int Retention { get { return GetValueInt("Retention", 0); } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index ca44cc046..22993f8be 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -20,6 +20,7 @@ public interface IConfigService //Media Management Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; } + Boolean FileDateAiredDate { get; set; } String RecycleBin { get; set; } Boolean AutoDownloadPropers { get; set; } Boolean CreateEmptySeriesFolders { get; set; } diff --git a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs index a208f28bd..540d99a76 100644 --- a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -67,7 +67,7 @@ public void ConvertToLocalUrls(int seriesId, IEnumerable covers) if (_diskProvider.FileExists(filePath)) { - var lastWrite = _diskProvider.GetLastFileWrite(filePath); + var lastWrite = _diskProvider.GetLastFileWriteUTC(filePath); mediaCover.Url += "?lastWrite=" + lastWrite.Ticks; } } diff --git a/src/NzbDrone.Core/MediaFiles/Commands/AirDateSeriesCommand.cs b/src/NzbDrone.Core/MediaFiles/Commands/AirDateSeriesCommand.cs new file mode 100644 index 000000000..ed1fd5f81 --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/Commands/AirDateSeriesCommand.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.MediaFiles.Commands +{ + public class AirDateSeriesCommand : Command + { + public List SeriesIds { get; set; } + + public override bool SendUpdatesToClient + { + get + { + return true; + } + } + } +} diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index 904fbb29e..df8e3e9f3 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -22,18 +22,21 @@ public interface IMoveEpisodeFiles public class EpisodeFileMovingService : IMoveEpisodeFiles { private readonly IEpisodeService _episodeService; + private readonly IUpdateEpisodeFileService _updateEpisodeFileService; private readonly IBuildFileNames _buildFileNames; private readonly IDiskProvider _diskProvider; private readonly IConfigService _configService; private readonly Logger _logger; public EpisodeFileMovingService(IEpisodeService episodeService, + IUpdateEpisodeFileService updateEpisodeFileService, IBuildFileNames buildFileNames, IDiskProvider diskProvider, IConfigService configService, Logger logger) { _episodeService = episodeService; + _updateEpisodeFileService = updateEpisodeFileService; _buildFileNames = buildFileNames; _diskProvider = diskProvider; _configService = configService; @@ -102,6 +105,11 @@ private EpisodeFile MoveFile(EpisodeFile episodeFile, Series series, string dest _diskProvider.MoveFile(episodeFile.Path, destinationFilename); episodeFile.Path = destinationFilename; + if (_configService.FileDateAiredDate) + { + _updateEpisodeFileService.ChangeFileDateToAirdate(episodeFile, series); + } + try { _logger.Trace("Setting last write time on series folder: {0}", series.Path); diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecification.cs index 50279a4e2..4edad3102 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotUnpackingSpecification.cs @@ -42,7 +42,7 @@ public bool IsSatisfiedBy(LocalEpisode localEpisode) return false; } - if (_diskProvider.GetLastFileWrite(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5)) + if (_diskProvider.GetLastFileWriteUTC(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5)) { _logger.Trace("{0} appears to be unpacking still", localEpisode.Path); return false; diff --git a/src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs b/src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs new file mode 100644 index 000000000..d830dabb8 --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs @@ -0,0 +1,15 @@ +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.MediaFiles.Events +{ + public class SeriesAirDatedEvent : IEvent + { + public Series Series { get; private set; } + + public SeriesAirDatedEvent(Series series) + { + Series = series; + } + } +} diff --git a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs index 4c5140c9a..8daafc574 100644 --- a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs +++ b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs @@ -139,7 +139,7 @@ public void Cleanup() foreach (var file in _diskProvider.GetFiles(_configService.RecycleBin, SearchOption.TopDirectoryOnly)) { - if (_diskProvider.GetLastFileWrite(file).AddDays(7) > DateTime.UtcNow) + if (_diskProvider.GetLastFileWriteUTC(file).AddDays(7) > DateTime.UtcNow) { logger.Trace("File hasn't expired yet, skipping: {0}", file); continue; diff --git a/src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs b/src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs new file mode 100644 index 000000000..318bce24b --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Common.Disk; +using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Instrumentation; +using NzbDrone.Core.MediaFiles.Commands; +using NzbDrone.Core.MediaFiles.Events; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.MediaFiles +{ + public interface IUpdateEpisodeFileService + { + void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series); + } + + public class UpdateEpisodeFileService : IUpdateEpisodeFileService, + IExecute, + IHandle + { + private readonly IDiskProvider _diskProvider; + private readonly IConfigService _configService; + private readonly ISeriesService _seriesService; + private readonly IEpisodeService _episodeService; + private readonly IEventAggregator _eventAggregator; + private readonly Logger _logger; + + public UpdateEpisodeFileService(IDiskProvider diskProvider, + IConfigService configService, + ISeriesService seriesService, + IEpisodeService episodeService, + IEventAggregator eventAggregator, + Logger logger) + { + _diskProvider = diskProvider; + _configService = configService; + _seriesService = seriesService; + _episodeService = episodeService; + _eventAggregator = eventAggregator; + _logger = logger; + } + + public void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series) + { + var episode = new Episode(); + episode.AirDate = episodeFile.Episodes.Value.First().AirDate; + episode.EpisodeFile = episodeFile; + episode.EpisodeFileId = 1; + + var episodes = new List(); + episodes.Add(episode); + + ChangeFileDateToAirdate(episodes, series); + } + + private void ChangeFileDateToAirdate(List episodes, Series series) + { + if (!episodes.Any()) + { + _logger.ProgressDebug("{0} has no media files available to update with air dates", series.Title); + } + + else + { + var done = new List(); + + _logger.ProgressDebug("{0} ... checking {1} media file dates match air date", series.Title, episodes.Count); + + foreach (var episode in episodes) + { + if (episode.HasFile + && episode.EpisodeFile.IsLoaded + && ChangeFileDate(episode.EpisodeFile.Value.Path, episode.AirDate, series.AirTime)) + { + done.Add(episode); + } + } + + if (done.Any()) + { + _eventAggregator.PublishEvent(new SeriesAirDatedEvent(series)); + _logger.ProgressDebug("{0} had {1} of {2} media file dates changed to the date and time the episode aired", series.Title, done.Count, episodes.Count); + } + + else + { + _logger.ProgressDebug("{0} has all its media file dates matching the date each aired", series.Title); + } + } + } + + public void Execute(AirDateSeriesCommand message) + { + var seriesToAirDate = _seriesService.GetSeries(message.SeriesIds); + + foreach (var series in seriesToAirDate) + { + var episodes = _episodeService.EpisodesWithFiles(series.Id); + + ChangeFileDateToAirdate(episodes, series); + } + } + + public void Handle(SeriesScannedEvent message) + { + if (_configService.FileDateAiredDate) + { + var episodes = _episodeService.EpisodesWithFiles(message.Series.Id); + + ChangeFileDateToAirdate(episodes, message.Series); + } + } + + private bool ChangeFileDate(String filePath, String fileDate, String fileTime) + { + DateTime dateTime, oldDateTime; + bool result = false; + + if (DateTime.TryParse(fileDate + ' ' + fileTime, out dateTime)) + { + // avoiding false +ve checks and set date skewing by not using UTC (Windows) + oldDateTime = _diskProvider.GetLastFileWrite(filePath); + + if (!DateTime.Equals(dateTime, oldDateTime)) + { + try + { + _diskProvider.FileSetLastWriteTime(filePath, dateTime); + _diskProvider.FileSetLastAccessTime(filePath, dateTime); + _logger.Info("Date of file [{0}] changed from \"{1}\" to \"{2}\"", filePath, oldDateTime, dateTime); + result = true; + } + + catch (Exception ex) + { + _logger.WarnException("Unable to set date of file [" + filePath + "]", ex); + } + } + } + + else + { + _logger.Warn("Could not create valid date to set [{0}]", filePath); + } + + return result; + } + } +} diff --git a/src/NzbDrone.Core/MetadataSource/TraktProxy.cs b/src/NzbDrone.Core/MetadataSource/TraktProxy.cs index 86d7cc94f..2743ab083 100644 --- a/src/NzbDrone.Core/MetadataSource/TraktProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/TraktProxy.cs @@ -78,7 +78,7 @@ private static Series MapSeries(Show show) series.Overview = show.overview; series.Runtime = show.runtime; series.Network = show.network; - series.AirTime = show.air_time_utc; + series.AirTime = show.air_time; series.TitleSlug = show.url.ToLower().Replace("http://trakt.tv/show/", ""); series.Status = GetSeriesStatus(show.status, show.ended); series.Ratings = GetRatings(show.ratings); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 640fef368..bf7965de1 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -308,6 +308,7 @@ + @@ -318,9 +319,11 @@ + + diff --git a/src/UI/Series/Editor/SeriesEditorFooterView.js b/src/UI/Series/Editor/SeriesEditorFooterView.js index cf02a09f1..0efc65562 100644 --- a/src/UI/Series/Editor/SeriesEditorFooterView.js +++ b/src/UI/Series/Editor/SeriesEditorFooterView.js @@ -10,7 +10,7 @@ define( 'AddSeries/RootFolders/RootFolderCollection', 'Shared/Toolbar/ToolbarLayout', 'AddSeries/RootFolders/RootFolderLayout', - 'Series/Editor/Rename/RenameSeriesView', + 'Series/Editor/UpdateFiles/UpdateFilesSeriesView', 'Config' ], function (_, Marionette, @@ -21,26 +21,26 @@ define( RootFolders, ToolbarLayout, RootFolderLayout, - RenameSeriesView, + UpdateFilesSeriesView, Config) { return Marionette.ItemView.extend({ template: 'Series/Editor/SeriesEditorFooterViewTemplate', ui: { - monitored : '.x-monitored', - qualityProfile: '.x-quality-profiles', - seasonFolder : '.x-season-folder', - rootFolder : '.x-root-folder', - selectedCount : '.x-selected-count', - saveButton : '.x-save', - renameButton : '.x-rename', - container : '.series-editor-footer' + monitored : '.x-monitored', + qualityProfile : '.x-quality-profiles', + seasonFolder : '.x-season-folder', + rootFolder : '.x-root-folder', + selectedCount : '.x-selected-count', + saveButton : '.x-save', + updateFilesButton: '.x-update-files', + container : '.series-editor-footer' }, events: { 'click .x-save' : '_updateAndSave', 'change .x-root-folder': '_rootFolderChanged', - 'click .x-rename' : '_rename' + 'click .x-update-files': '_updateFiles' }, templateHelpers: function () { @@ -119,7 +119,7 @@ define( this.ui.seasonFolder.attr('disabled', ''); this.ui.rootFolder.attr('disabled', ''); this.ui.saveButton.attr('disabled', ''); - this.ui.renameButton.attr('disabled', ''); + this.ui.updateFilesButton.attr('disabled', ''); } else { @@ -128,7 +128,7 @@ define( this.ui.seasonFolder.removeAttr('disabled', ''); this.ui.rootFolder.removeAttr('disabled', ''); this.ui.saveButton.removeAttr('disabled', ''); - this.ui.renameButton.removeAttr('disabled', ''); + this.ui.updateFilesButton.removeAttr('disabled', ''); } }, @@ -162,12 +162,12 @@ define( }); }, - _rename: function () { + _updateFiles: function () { var selected = this.editorGrid.getSelectedModels(); - var renameSeriesView = new RenameSeriesView({ series: selected }); - this.listenToOnce(renameSeriesView, 'seriesRenamed', this._afterSave); + var updateFilesSeriesView = new UpdateFilesSeriesView({ series: selected }); + this.listenToOnce(updateFilesSeriesView, 'updatingFiles', this._afterSave); - vent.trigger(vent.Commands.OpenModalCommand, renameSeriesView); + vent.trigger(vent.Commands.OpenModalCommand, updateFilesSeriesView); } }); }); diff --git a/src/UI/Series/Editor/SeriesEditorFooterViewTemplate.html b/src/UI/Series/Editor/SeriesEditorFooterViewTemplate.html index 88a1d382c..48995092d 100644 --- a/src/UI/Series/Editor/SeriesEditorFooterViewTemplate.html +++ b/src/UI/Series/Editor/SeriesEditorFooterViewTemplate.html @@ -45,7 +45,7 @@ 0 series selected - + \ No newline at end of file diff --git a/src/UI/Series/Editor/Rename/RenameSeriesView.js b/src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesView.js similarity index 58% rename from src/UI/Series/Editor/Rename/RenameSeriesView.js rename to src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesView.js index c573433bf..e0e7b55ba 100644 --- a/src/UI/Series/Editor/Rename/RenameSeriesView.js +++ b/src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesView.js @@ -9,10 +9,11 @@ define( ], function (_, vent, Backbone, Marionette, CommandController) { return Marionette.ItemView.extend({ - template: 'Series/Editor/Rename/RenameSeriesViewTemplate', + template: 'Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate', events: { - 'click .x-confirm-rename': '_rename' + 'click .x-confirm-rename': '_rename', + 'click .x-confirm-airdate': '_setFileAirDate' }, initialize: function (options) { @@ -29,7 +30,19 @@ define( seriesIds : seriesIds }); - this.trigger('seriesRenamed'); + this.trigger('updatingFiles'); + vent.trigger(vent.Commands.CloseModalCommand); + }, + + _setFileAirDate: function () { + var seriesIds = _.pluck(this.series, 'id'); + + CommandController.Execute('AirDateSeries', { + name: 'AirDateSeries', + seriesIds: seriesIds + }); + + this.trigger('updatingFiles'); vent.trigger(vent.Commands.CloseModalCommand); } }); diff --git a/src/UI/Series/Editor/Rename/RenameSeriesViewTemplate.html b/src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate.html similarity index 56% rename from src/UI/Series/Editor/Rename/RenameSeriesViewTemplate.html rename to src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate.html index e9c2e58c7..836c70310 100644 --- a/src/UI/Series/Editor/Rename/RenameSeriesViewTemplate.html +++ b/src/UI/Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate.html @@ -1,23 +1,24 @@  - +
+ +
+
+