diff options
| author | Luke <luke.pulverenti@gmail.com> | 2016-02-06 22:24:18 -0500 |
|---|---|---|
| committer | Luke <luke.pulverenti@gmail.com> | 2016-02-06 22:24:18 -0500 |
| commit | b398b4eaabad357027dbcf2a210edcada8a984fd (patch) | |
| tree | 9dad1e9409b6c1eb0f4110d4795ee276546aba6d | |
| parent | bc6c0bd0b7ec6f57651c21726f66f9cf7a69cba3 (diff) | |
| parent | c02635c2569b0dfe2144c337cc0f8591e55c528c (diff) | |
Merge pull request #1432 from softworkz/SeriesDetectionV2
Supersedes #1192: Auto-Organize - Added feature to remember/persist series matching in manual organization dialog
13 files changed, 228 insertions, 27 deletions
diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs index 29a982629..a08cc099e 100644 --- a/MediaBrowser.Api/Library/FileOrganizationService.cs +++ b/MediaBrowser.Api/Library/FileOrganizationService.cs @@ -74,6 +74,34 @@ namespace MediaBrowser.Api.Library public bool RememberCorrection { get; set; } } + [Route("/Library/FileOrganizationSmartMatch", "GET", Summary = "Gets smart match entries")] + public class GetSmartMatchInfos : IReturn<QueryResult<SmartMatchInfo>> + { + /// <summary> + /// Skips over a given number of items within the results. Use for paging. + /// </summary> + /// <value>The start index.</value> + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + /// <summary> + /// The maximum number of items to return + /// </summary> + /// <value>The limit.</value> + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } + } + + [Route("/Library/FileOrganizationSmartMatch/{Id}/Delete", "POST", Summary = "Deletes a smart match entry")] + public class DeleteSmartMatchEntry + { + [ApiMember(Name = "Id", Description = "Item ID", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "MatchString", Description = "SmartMatch String", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string MatchString { get; set; } + } + [Authenticated(Roles = "Admin")] public class FileOrganizationService : BaseApiService { @@ -130,5 +158,21 @@ namespace MediaBrowser.Api.Library Task.WaitAll(task); } + + public object Get(GetSmartMatchInfos request) + { + var result = _iFileOrganizationService.GetSmartMatchInfos(new FileOrganizationResultQuery + { + Limit = request.Limit, + StartIndex = request.StartIndex + }); + + return ToOptimizedSerializedResultUsingCache(result); + } + + public void Post(DeleteSmartMatchEntry request) + { + _iFileOrganizationService.DeleteSmartMatchEntry(request.Id, request.MatchString); + } } } diff --git a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs b/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs index ff22b0cdc..8d7f4e117 100644 --- a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs +++ b/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs @@ -67,5 +67,19 @@ namespace MediaBrowser.Controller.FileOrganization /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken); + + /// <summary> + /// Returns a list of smart match entries + /// </summary> + /// <param name="query">The query.</param> + /// <returns>IEnumerable{SmartMatchInfo}.</returns> + QueryResult<SmartMatchInfo> GetSmartMatchInfos(FileOrganizationResultQuery query); + + /// <summary> + /// Deletes a smart match entry. + /// </summary> + /// <param name="Id">Item Id.</param> + /// <param name="matchString">The match string to delete.</param> + void DeleteSmartMatchEntry(string Id, string matchString); } } diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index b8c64b643..cea13f86e 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -668,6 +668,9 @@ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs"> <Link>FileOrganization\FileSortingStatus.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\FileOrganization\SmartMatchInfo.cs"> + <Link>FileOrganization\SmartMatchInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\FileOrganization\TvFileOrganizationOptions.cs"> <Link>FileOrganization\TvFileOrganizationOptions.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index e74468eff..6c484ffc9 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -633,6 +633,9 @@ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs"> <Link>FileOrganization\FileSortingStatus.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\FileOrganization\SmartMatchInfo.cs"> + <Link>FileOrganization\SmartMatchInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\FileOrganization\TvFileOrganizationOptions.cs"> <Link>FileOrganization\TvFileOrganizationOptions.cs</Link> </Compile> diff --git a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs index ae701ea68..071897b51 100644 --- a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs +++ b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs @@ -1,4 +1,5 @@ +using System.Collections.Generic; namespace MediaBrowser.Model.FileOrganization { public class AutoOrganizeOptions @@ -9,9 +10,16 @@ namespace MediaBrowser.Model.FileOrganization /// <value>The tv options.</value> public TvFileOrganizationOptions TvOptions { get; set; } + /// <summary> + /// Gets or sets a list of smart match entries. + /// </summary> + /// <value>The smart match entries.</value> + public List<SmartMatchInfo> SmartMatchInfos { get; set; } + public AutoOrganizeOptions() { TvOptions = new TvFileOrganizationOptions(); + SmartMatchInfos = new List<SmartMatchInfo>(); } } } diff --git a/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs b/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs new file mode 100644 index 000000000..808c0b006 --- /dev/null +++ b/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs @@ -0,0 +1,19 @@ + +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Model.FileOrganization +{ + public class SmartMatchInfo + { + public Guid Id { get; set; } + public string Name { get; set; } + public FileOrganizerType OrganizerType { get; set; } + public List<string> MatchStrings { get; set; } + + public SmartMatchInfo() + { + MatchStrings = new List<string>(); + } + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index db278baa1..a5191192c 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -137,6 +137,7 @@ <Compile Include="Dto\MetadataEditorInfo.cs" /> <Compile Include="Dto\NameIdPair.cs" /> <Compile Include="Dto\NameValuePair.cs" /> + <Compile Include="FileOrganization\SmartMatchInfo.cs" /> <Compile Include="MediaInfo\LiveStreamRequest.cs" /> <Compile Include="MediaInfo\LiveStreamResponse.cs" /> <Compile Include="MediaInfo\PlaybackInfoRequest.cs" /> diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 73cc5ab01..a952b60d5 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -46,12 +46,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public Task<FileOrganizationResult> OrganizeEpisodeFile(string path, CancellationToken cancellationToken) { - var options = _config.GetAutoOrganizeOptions().TvOptions; + var options = _config.GetAutoOrganizeOptions(); return OrganizeEpisodeFile(path, options, false, cancellationToken); } - public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken) + public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken) { _logger.Info("Sorting file {0}", path); @@ -110,6 +110,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization premiereDate, options, overwriteExisting, + false, result, cancellationToken).ConfigureAwait(false); } @@ -145,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return result; } - public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) + public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, AutoOrganizeOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); @@ -159,6 +160,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization null, options, true, + request.RememberCorrection, result, cancellationToken).ConfigureAwait(false); @@ -173,12 +175,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization int? episodeNumber, int? endingEpiosdeNumber, DateTime? premiereDate, - TvFileOrganizationOptions options, + AutoOrganizeOptions options, bool overwriteExisting, + bool rememberCorrection, FileOrganizationResult result, CancellationToken cancellationToken) { - var series = GetMatchingSeries(seriesName, result); + var series = GetMatchingSeries(seriesName, result, options); if (series == null) { @@ -197,6 +200,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization premiereDate, options, overwriteExisting, + rememberCorrection, result, cancellationToken); } @@ -207,15 +211,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization int? episodeNumber, int? endingEpiosdeNumber, DateTime? premiereDate, - TvFileOrganizationOptions options, + AutoOrganizeOptions options, bool overwriteExisting, + bool rememberCorrection, FileOrganizationResult result, CancellationToken cancellationToken) { _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); + var originalExtractedSeriesString = result.ExtractedName; + // Proceed to sort the file - var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false); + var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options.TvOptions, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { @@ -234,7 +241,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (!overwriteExisting) { - if (options.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath)) + if (options.TvOptions.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath)) { _logger.Info("File {0} already copied to new path {1}, stopping organization", sourcePath, newPath); result.Status = FileSortingStatus.SkippedExisting; @@ -251,7 +258,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } - PerformFileSorting(options, result); + PerformFileSorting(options.TvOptions, result); if (overwriteExisting) { @@ -285,6 +292,31 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } } + + if (rememberCorrection) + { + SaveSmartMatchString(originalExtractedSeriesString, series, options); + } + } + + private void SaveSmartMatchString(string matchString, Series series, AutoOrganizeOptions options) + { + SmartMatchInfo info = options.SmartMatchInfos.Find(i => i.Id == series.Id); + + if (info == null) + { + info = new SmartMatchInfo(); + info.Id = series.Id; + info.OrganizerType = FileOrganizerType.Episode; + info.Name = series.Name; + options.SmartMatchInfos.Add(info); + } + + if (!info.MatchStrings.Contains(matchString, StringComparer.OrdinalIgnoreCase)) + { + info.MatchStrings.Add(matchString); + _config.SaveAutoOrganizeOptions(options); + } } private void DeleteLibraryFile(string path, bool renameRelatedFiles, string targetPath) @@ -435,7 +467,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } - private Series GetMatchingSeries(string seriesName, FileOrganizationResult result) + private Series GetMatchingSeries(string seriesName, FileOrganizationResult result, AutoOrganizeOptions options) { var parsedName = _libraryManager.ParseName(seriesName); @@ -445,13 +477,28 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.ExtractedName = nameWithoutYear; result.ExtractedYear = yearInName; - return _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + var series = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) .Cast<Series>() .Select(i => NameUtils.GetMatchScore(nameWithoutYear, yearInName, i)) .Where(i => i.Item2 > 0) .OrderByDescending(i => i.Item2) .Select(i => i.Item1) .FirstOrDefault(); + + if (series == null) + { + SmartMatchInfo info = options.SmartMatchInfos.Where(e => e.MatchStrings.Contains(seriesName, StringComparer.OrdinalIgnoreCase)).FirstOrDefault(); + + if (info != null) + { + series = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + .Cast<Series>() + .Where(i => i.Id == info.Id) + .FirstOrDefault(); + } + } + + return series ?? new Series(); } /// <summary> diff --git a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs index e43ab3665..c560152db 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs @@ -10,6 +10,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { return manager.GetConfiguration<AutoOrganizeOptions>("autoorganize"); } + public static void SaveAutoOrganizeOptions(this IConfigurationManager manager, AutoOrganizeOptions options) + { + manager.SaveConfiguration("autoorganize", options); + } } public class AutoOrganizeOptionsFactory : IConfigurationFactory diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index 839a85adb..3dd6a9be0 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -11,6 +11,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; using System; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; @@ -96,9 +97,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return _repo.Delete(resultId); } - private TvFileOrganizationOptions GetTvOptions() + private AutoOrganizeOptions GetAutoOrganizeptions() { - return _config.GetAutoOrganizeOptions().TvOptions; + return _config.GetAutoOrganizeOptions(); } public async Task PerformOrganization(string resultId) @@ -113,7 +114,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeEpisodeFile(result.OriginalPath, GetTvOptions(), true, CancellationToken.None) + await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeptions(), true, CancellationToken.None) .ConfigureAwait(false); } @@ -127,7 +128,55 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeWithCorrection(request, GetTvOptions(), CancellationToken.None).ConfigureAwait(false); + await organizer.OrganizeWithCorrection(request, GetAutoOrganizeptions(), CancellationToken.None).ConfigureAwait(false); + } + + public QueryResult<SmartMatchInfo> GetSmartMatchInfos(FileOrganizationResultQuery query) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + + var options = GetAutoOrganizeptions(); + + var items = options.SmartMatchInfos.Skip(query.StartIndex ?? 0).Take(query.Limit ?? Int32.MaxValue); + + return new QueryResult<SmartMatchInfo>() + { + Items = items.ToArray(), + TotalRecordCount = items.Count() + }; + } + + public void DeleteSmartMatchEntry(string IdString, string matchString) + { + Guid Id; + + if (!Guid.TryParse(IdString, out Id)) + { + throw new ArgumentNullException("Id"); + } + + if (string.IsNullOrEmpty(matchString)) + { + throw new ArgumentNullException("matchString"); + } + + var options = GetAutoOrganizeptions(); + + SmartMatchInfo info = options.SmartMatchInfos.Find(i => i.Id == Id); + + if (info != null && info.MatchStrings.Contains(matchString)) + { + info.MatchStrings.Remove(matchString); + if (info.MatchStrings.Count == 0) + { + options.SmartMatchInfos.Remove(info); + } + + _config.SaveAutoOrganizeOptions(options); + } } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs index f1fe5539f..ace3b5af7 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs @@ -50,17 +50,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization get { return "Library"; } } - private TvFileOrganizationOptions GetTvOptions() + private AutoOrganizeOptions GetAutoOrganizeOptions() { - return _config.GetAutoOrganizeOptions().TvOptions; + return _config.GetAutoOrganizeOptions(); } public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - if (GetTvOptions().IsEnabled) + if (GetAutoOrganizeOptions().TvOptions.IsEnabled) { await new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) - .Organize(GetTvOptions(), cancellationToken, progress).ConfigureAwait(false); + .Organize(GetAutoOrganizeOptions(), cancellationToken, progress).ConfigureAwait(false); } } @@ -74,12 +74,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public bool IsHidden { - get { return !GetTvOptions().IsEnabled; } + get { return !GetAutoOrganizeOptions().TvOptions.IsEnabled; } } public bool IsEnabled { - get { return GetTvOptions().IsEnabled; } + get { return GetAutoOrganizeOptions().TvOptions.IsEnabled; } } public bool IsActivityLogged diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 3e5296639..845fcdff2 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -52,13 +52,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return false; } - public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress) + public async Task Organize(AutoOrganizeOptions options, CancellationToken cancellationToken, IProgress<double> progress) { - var watchLocations = options.WatchLocations.ToList(); + var watchLocations = options.TvOptions.WatchLocations.ToList(); var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize) .OrderBy(_fileSystem.GetCreationTimeUtc) - .Where(i => EnableOrganization(i, options)) + .Where(i => EnableOrganization(i, options.TvOptions)) .ToList(); var processedFolders = new HashSet<string>(); @@ -76,7 +76,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization try { - var result = await organizer.OrganizeEpisodeFile(file.FullName, options, options.OverwriteExistingEpisodes, cancellationToken).ConfigureAwait(false); + var result = await organizer.OrganizeEpisodeFile(file.FullName, options, options.TvOptions.OverwriteExistingEpisodes, cancellationToken).ConfigureAwait(false); if (result.Status == FileSortingStatus.Success && !processedFolders.Contains(file.DirectoryName, StringComparer.OrdinalIgnoreCase)) { processedFolders.Add(file.DirectoryName); @@ -100,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization foreach (var path in processedFolders) { - var deleteExtensions = options.LeftOverFileExtensionsToDelete + var deleteExtensions = options.TvOptions.LeftOverFileExtensionsToDelete .Select(i => i.Trim().TrimStart('.')) .Where(i => !string.IsNullOrEmpty(i)) .Select(i => "." + i) @@ -111,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization DeleteLeftOverFiles(path, deleteExtensions); } - if (options.DeleteEmptyFolders) + if (options.TvOptions.DeleteEmptyFolders) { if (!IsWatchFolder(path, watchLocations)) { diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index efb2d4b69..1c4bbea16 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -101,6 +101,12 @@ <Content Include="dashboard-ui\components\chromecasthelpers.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\autoorganizesmart.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\bower_components\fastclick\lib\fastclick.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\components\recordingcreator\recordingcreator.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -281,6 +287,9 @@ <Content Include="dashboard-ui\scripts\mysyncsettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\autoorganizesmart.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\searchmenu.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
|
