diff --git a/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css
new file mode 100644
index 000000000..b3102d230
--- /dev/null
+++ b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css
@@ -0,0 +1,11 @@
+.title {
+ composes: title from '~Components/DescriptionList/DescriptionListItemTitle.css';
+
+ width: 90px;
+}
+
+.description {
+ composes: title from '~Components/DescriptionList/DescriptionListItemDescription.css';
+
+ margin-left: 110px;
+}
diff --git a/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css.d.ts b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css.d.ts
new file mode 100644
index 000000000..e0d8c2f6b
--- /dev/null
+++ b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.css.d.ts
@@ -0,0 +1,8 @@
+// This file is automatically generated.
+// Please do not change this file!
+interface CssExports {
+ 'description': string;
+ 'title': string;
+}
+export const cssExports: CssExports;
+export default cssExports;
diff --git a/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.tsx b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.tsx
new file mode 100644
index 000000000..badbee351
--- /dev/null
+++ b/frontend/src/Indexer/Index/Table/DisabledIndexerInfo.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import DescriptionList from 'Components/DescriptionList/DescriptionList';
+import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
+import formatDateTime from 'Utilities/Date/formatDateTime';
+import translate from 'Utilities/String/translate';
+import styles from './DisabledIndexerInfo.css';
+
+interface DisabledIndexerInfoProps {
+ mostRecentFailure: Date;
+ disabledTill: Date;
+ initialFailure: Date;
+ longDateFormat: string;
+ timeFormat: string;
+}
+
+function DisabledIndexerInfo(props: DisabledIndexerInfoProps) {
+ const {
+ mostRecentFailure,
+ disabledTill,
+ initialFailure,
+ longDateFormat,
+ timeFormat,
+ } = props;
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+export default DisabledIndexerInfo;
diff --git a/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx b/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx
index 365e14ced..89ecdd501 100644
--- a/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx
+++ b/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx
@@ -30,9 +30,8 @@ interface IndexerIndexRowProps {
function IndexerIndexRow(props: IndexerIndexRowProps) {
const { indexerId, columns, isSelectMode } = props;
- const { indexer, appProfile } = useSelector(
- createIndexerIndexItemSelector(props.indexerId)
- );
+ const { indexer, appProfile, status, longDateFormat, timeFormat } =
+ useSelector(createIndexerIndexItemSelector(props.indexerId));
const {
id,
@@ -44,7 +43,6 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
protocol,
privacy,
priority,
- status,
fields,
added,
capabilities,
@@ -123,6 +121,8 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
enabled={enable}
redirect={redirect}
status={status}
+ longDateFormat={longDateFormat}
+ timeFormat={timeFormat}
component={VirtualTableRowCell}
/>
);
diff --git a/frontend/src/Indexer/Index/Table/IndexerStatusCell.css b/frontend/src/Indexer/Index/Table/IndexerStatusCell.css
index fbcd5eee9..6f5022ea8 100644
--- a/frontend/src/Indexer/Index/Table/IndexerStatusCell.css
+++ b/frontend/src/Indexer/Index/Table/IndexerStatusCell.css
@@ -7,3 +7,7 @@
.statusIcon {
width: 20px !important;
}
+
+.indexerStatusTooltip {
+ display: flex;
+}
diff --git a/frontend/src/Indexer/Index/Table/IndexerStatusCell.css.d.ts b/frontend/src/Indexer/Index/Table/IndexerStatusCell.css.d.ts
index f7788f04f..c9b930d6d 100644
--- a/frontend/src/Indexer/Index/Table/IndexerStatusCell.css.d.ts
+++ b/frontend/src/Indexer/Index/Table/IndexerStatusCell.css.d.ts
@@ -1,6 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
+ 'indexerStatusTooltip': string;
'status': string;
'statusIcon': string;
}
diff --git a/frontend/src/Indexer/Index/Table/IndexerStatusCell.tsx b/frontend/src/Indexer/Index/Table/IndexerStatusCell.tsx
index 85cf08d38..4e8d1bd80 100644
--- a/frontend/src/Indexer/Index/Table/IndexerStatusCell.tsx
+++ b/frontend/src/Indexer/Index/Table/IndexerStatusCell.tsx
@@ -1,9 +1,11 @@
import React from 'react';
import Icon from 'Components/Icon';
import VirtualTableRowCell from 'Components/Table/Cells/TableRowCell';
-import { icons, kinds } from 'Helpers/Props';
+import Popover from 'Components/Tooltip/Popover';
+import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import { IndexerStatus } from 'Indexer/Indexer';
-import formatDateTime from 'Utilities/Date/formatDateTime';
+import translate from 'Utilities/String/translate';
+import DisabledIndexerInfo from './DisabledIndexerInfo';
import styles from './IndexerStatusCell.css';
interface IndexerStatusCellProps {
@@ -11,6 +13,8 @@ interface IndexerStatusCellProps {
enabled: boolean;
redirect: boolean;
status: IndexerStatus;
+ longDateFormat: string;
+ timeFormat: string;
component?: React.ElementType;
}
@@ -20,6 +24,8 @@ function IndexerStatusCell(props: IndexerStatusCellProps) {
enabled,
redirect,
status,
+ longDateFormat,
+ timeFormat,
component: Component = VirtualTableRowCell,
...otherProps
} = props;
@@ -41,13 +47,29 @@ function IndexerStatusCell(props: IndexerStatusCellProps) {
/>
}
{status ? (
-
+ }
+ title={translate('IndexerDisabled')}
+ body={
+
+
+
+ }
+ position={tooltipPositions.BOTTOM}
/>
) : null}
diff --git a/frontend/src/Indexer/Index/createIndexerIndexItemSelector.ts b/frontend/src/Indexer/Index/createIndexerIndexItemSelector.ts
index 8dc3adb7c..12d042f7a 100644
--- a/frontend/src/Indexer/Index/createIndexerIndexItemSelector.ts
+++ b/frontend/src/Indexer/Index/createIndexerIndexItemSelector.ts
@@ -2,12 +2,16 @@ import { createSelector } from 'reselect';
import Indexer from 'Indexer/Indexer';
import createIndexerAppProfileSelector from 'Store/Selectors/createIndexerAppProfileSelector';
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
+import createIndexerStatusSelector from 'Store/Selectors/createIndexerStatusSelector';
+import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
function createIndexerIndexItemSelector(indexerId: number) {
return createSelector(
createIndexerSelector(indexerId),
createIndexerAppProfileSelector(indexerId),
- (indexer: Indexer, appProfile) => {
+ createIndexerStatusSelector(indexerId),
+ createUISettingsSelector(),
+ (indexer: Indexer, appProfile, status, uiSettings) => {
// If a series is deleted this selector may fire before the parent
// selectors, which will result in an undefined series, if that happens
// we want to return early here and again in the render function to avoid
@@ -20,6 +24,9 @@ function createIndexerIndexItemSelector(indexerId: number) {
return {
indexer,
appProfile,
+ status,
+ longDateFormat: uiSettings.longDateFormat,
+ timeFormat: uiSettings.timeFormat,
};
}
);
diff --git a/frontend/src/Indexer/Indexer.ts b/frontend/src/Indexer/Indexer.ts
index 3ed4682ed..5ce83264b 100644
--- a/frontend/src/Indexer/Indexer.ts
+++ b/frontend/src/Indexer/Indexer.ts
@@ -2,6 +2,8 @@ import ModelBase from 'App/ModelBase';
export interface IndexerStatus extends ModelBase {
disabledTill: Date;
+ initialFailure: Date;
+ mostRecentFailure: Date;
}
export interface IndexerCategory extends ModelBase {
diff --git a/frontend/src/Store/Selectors/createIndexerStatusSelector.js b/frontend/src/Store/Selectors/createIndexerStatusSelector.js
index e25d618fe..1912ea1a0 100644
--- a/frontend/src/Store/Selectors/createIndexerStatusSelector.js
+++ b/frontend/src/Store/Selectors/createIndexerStatusSelector.js
@@ -1,11 +1,10 @@
import _ from 'lodash';
import { createSelector } from 'reselect';
-function createIndexerStatusSelector() {
+function createIndexerStatusSelector(indexerId) {
return createSelector(
- (state, { indexerId }) => indexerId,
(state) => state.indexerStatus.items,
- (indexerId, indexerStatus) => {
+ (indexerStatus) => {
return _.find(indexerStatus, { indexerId });
}
);
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 336bd7883..2b468a2d1 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -116,6 +116,7 @@
"Details": "Details",
"DevelopmentSettings": "Development Settings",
"Disabled": "Disabled",
+ "DisabledUntil": "Disabled Until",
"Discord": "Discord",
"Docker": "Docker",
"Donations": "Donations",
@@ -190,6 +191,7 @@
"IndexerAlreadySetup": "At least one instance of indexer is already setup",
"IndexerAuth": "Indexer Auth",
"IndexerDetails": "Indexer Details",
+ "IndexerDisabled": "Indexer Disabled",
"IndexerFlags": "Indexer Flags",
"IndexerHealthCheckNoIndexers": "No indexers enabled, Prowlarr will not return search results",
"IndexerInfo": "Indexer Info",
@@ -216,6 +218,7 @@
"IndexerVipCheckExpiredClientMessage": "Indexer VIP benefits have expired: {0}",
"IndexerVipCheckExpiringClientMessage": "Indexer VIP benefits expiring soon: {0}",
"Info": "Info",
+ "InitialFailure": "Initial Failure",
"InstanceName": "Instance Name",
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
"InteractiveSearch": "Interactive Search",
@@ -224,6 +227,7 @@
"Language": "Language",
"LastDuration": "Last Duration",
"LastExecution": "Last Execution",
+ "LastFailure": "Last Failure",
"LastWriteTime": "Last Write Time",
"LaunchBrowserHelpText": " Open a web browser and navigate to the Prowlarr homepage on app start.",
"Level": "Level",
diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerStatusResource.cs b/src/Prowlarr.Api.V1/Indexers/IndexerStatusResource.cs
index e624440a1..46379f783 100644
--- a/src/Prowlarr.Api.V1/Indexers/IndexerStatusResource.cs
+++ b/src/Prowlarr.Api.V1/Indexers/IndexerStatusResource.cs
@@ -10,6 +10,8 @@ namespace Prowlarr.Api.V1.Indexers
{
public int IndexerId { get; set; }
public DateTime? DisabledTill { get; set; }
+ public DateTime? MostRecentFailure { get; set; }
+ public DateTime? InitialFailure { get; set; }
}
public static class IndexerStatusResourceMapper
@@ -24,7 +26,9 @@ namespace Prowlarr.Api.V1.Indexers
return new IndexerStatusResource
{
IndexerId = model.ProviderId,
- DisabledTill = model.DisabledTill
+ DisabledTill = model.DisabledTill,
+ MostRecentFailure = model.MostRecentFailure,
+ InitialFailure = model.InitialFailure,
};
}