Improve error messaging for missing information when searching

Fixed: Show missing absolute episode number/air date error message in interactive search
This commit is contained in:
Mark McDowall 2019-04-27 14:28:15 -07:00
parent 6036bc17c5
commit 26228e546e
5 changed files with 54 additions and 19 deletions

View File

@ -1,5 +1,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React, { Fragment } from 'react';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import { align, icons, sortDirections } from 'Helpers/Props'; import { align, icons, sortDirections } from 'Helpers/Props';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
@ -109,6 +110,8 @@ function InteractiveSearch(props) {
onGrabPress onGrabPress
} = props; } = props;
const errorMessage = getErrorMessage(error);
return ( return (
<div> <div>
<div className={styles.filterMenuContainer}> <div className={styles.filterMenuContainer}>
@ -125,33 +128,42 @@ function InteractiveSearch(props) {
</div> </div>
{ {
isFetching && isFetching ? <LoadingIndicator /> : null
<LoadingIndicator />
} }
{ {
!isFetching && !!error && !isFetching && error ?
<div> <div>
Unable to load results for this episode search. Try again later {
</div> errorMessage ?
<Fragment>
Search failed because its {errorMessage.charAt(0).toLowerCase() + errorMessage.slice(1)}.
Try refreshing the series info and verify the necessary information is present before searching again
</Fragment> :
'Unable to load results for this episode search. Try again later'
}
</div> :
null
} }
{ {
!isFetching && isPopulated && !totalReleasesCount && !isFetching && isPopulated && !totalReleasesCount ?
<div> <div>
No results found No results found
</div> </div> :
null
} }
{ {
!!totalReleasesCount && isPopulated && !items.length && !!totalReleasesCount && isPopulated && !items.length ?
<div> <div>
All results are hidden by the applied filter All results are hidden by the applied filter
</div> </div> :
null
} }
{ {
isPopulated && !!items.length && isPopulated && !!items.length ?
<Table <Table
columns={columns} columns={columns}
sortKey={sortKey} sortKey={sortKey}
@ -174,14 +186,16 @@ function InteractiveSearch(props) {
}) })
} }
</TableBody> </TableBody>
</Table> </Table> :
null
} }
{ {
totalReleasesCount !== items.length && !!items.length && totalReleasesCount !== items.length && !!items.length ?
<div className={styles.filteredMessage}> <div className={styles.filteredMessage}>
Some results are hidden by the applied filter Some results are hidden by the applied filter
</div> </div> :
null
} }
</div> </div>
); );

View File

@ -0,0 +1,11 @@
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Exceptions
{
public class SearchFailedException : NzbDroneException
{
public SearchFailedException(string message) : base(message)
{
}
}
}

View File

@ -13,6 +13,7 @@ using NzbDrone.Core.Tv;
using System.Linq; using System.Linq;
using NzbDrone.Common.TPL; using NzbDrone.Common.TPL;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Exceptions;
namespace NzbDrone.Core.IndexerSearch namespace NzbDrone.Core.IndexerSearch
{ {
@ -62,7 +63,8 @@ namespace NzbDrone.Core.IndexerSearch
{ {
if (string.IsNullOrWhiteSpace(episode.AirDate)) if (string.IsNullOrWhiteSpace(episode.AirDate))
{ {
throw new InvalidOperationException("Daily episode is missing AirDate. Try to refresh series info."); _logger.Error("Daily episode is missing an air date. Try refreshing the series info.");
throw new SearchFailedException("Air date is missing");
} }
return SearchDaily(series, episode, userInvokedSearch, interactiveSearch); return SearchDaily(series, episode, userInvokedSearch, interactiveSearch);
@ -205,7 +207,8 @@ namespace NzbDrone.Core.IndexerSearch
} }
else else
{ {
throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", $"Can not search for {series.Title} - S{episode.SeasonNumber:00}E{episode.EpisodeNumber:00} it does not have an absolute episode number"); _logger.Error($"Can not search for {series.Title} - S{episode.SeasonNumber:00}E{episode.EpisodeNumber:00} it does not have an absolute episode number");
throw new SearchFailedException("Absolute episode number is missing");
} }
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);

View File

@ -146,6 +146,7 @@
<Compile Include="Datastore\Migration\127_rename_release_profiles.cs" /> <Compile Include="Datastore\Migration\127_rename_release_profiles.cs" />
<Compile Include="Datastore\Migration\126_add_custom_filters.cs" /> <Compile Include="Datastore\Migration\126_add_custom_filters.cs" />
<Compile Include="DecisionEngine\Specifications\UpgradeAllowedSpecification.cs" /> <Compile Include="DecisionEngine\Specifications\UpgradeAllowedSpecification.cs" />
<Compile Include="Exceptions\SearchFailedException.cs" />
<Compile Include="Extras\Metadata\MetadataSectionType.cs" /> <Compile Include="Extras\Metadata\MetadataSectionType.cs" />
<Compile Include="Download\Aggregation\RemoteEpisodeAggregationService.cs" /> <Compile Include="Download\Aggregation\RemoteEpisodeAggregationService.cs" />
<Compile Include="Download\Aggregation\Aggregators\AggregatePreferredWordScore.cs" /> <Compile Include="Download\Aggregation\Aggregators\AggregatePreferredWordScore.cs" />

View File

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using FluentValidation; using FluentValidation;
using Nancy; using Nancy;
using Nancy.ModelBinding;
using NLog; using NLog;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
@ -110,7 +108,7 @@ namespace Sonarr.Api.V3.Indexers
} }
catch (ReleaseDownloadException ex) catch (ReleaseDownloadException ex)
{ {
_logger.ErrorException(ex.Message, ex); _logger.Error(ex, ex.Message);
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed"); throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
} }
@ -141,6 +139,10 @@ namespace Sonarr.Api.V3.Indexers
return MapDecisions(prioritizedDecisions); return MapDecisions(prioritizedDecisions);
} }
catch (SearchFailedException ex)
{
throw new NzbDroneClientException(HttpStatusCode.BadRequest, ex.Message);
}
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex, "Episode search failed: " + ex.Message); _logger.Error(ex, "Episode search failed: " + ex.Message);
@ -158,6 +160,10 @@ namespace Sonarr.Api.V3.Indexers
return MapDecisions(prioritizedDecisions); return MapDecisions(prioritizedDecisions);
} }
catch (SearchFailedException ex)
{
throw new NzbDroneClientException(HttpStatusCode.BadRequest, ex.Message);
}
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex, "Season search failed: " + ex.Message); _logger.Error(ex, "Season search failed: " + ex.Message);