mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-30 23:45:46 +02:00
New: Improve history details for release grabs
This commit is contained in:
@@ -3,6 +3,7 @@ import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import Link from 'Components/Link/Link';
|
||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './HistoryDetails.css';
|
||||
|
||||
@@ -10,7 +11,10 @@ function HistoryDetails(props) {
|
||||
const {
|
||||
indexer,
|
||||
eventType,
|
||||
data
|
||||
date,
|
||||
data,
|
||||
shortDateFormat,
|
||||
timeFormat
|
||||
} = props;
|
||||
|
||||
if (eventType === 'indexerQuery' || eventType === 'indexerRss') {
|
||||
@@ -22,7 +26,9 @@ function HistoryDetails(props) {
|
||||
offset,
|
||||
source,
|
||||
host,
|
||||
url
|
||||
url,
|
||||
elapsedTime,
|
||||
cached
|
||||
} = data;
|
||||
|
||||
return (
|
||||
@@ -104,6 +110,24 @@ function HistoryDetails(props) {
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
elapsedTime ?
|
||||
<DescriptionListItem
|
||||
title={translate('ElapsedTime')}
|
||||
data={`${elapsedTime}ms${cached === '1' ? ' (cached)' : null}`}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
date ?
|
||||
<DescriptionListItem
|
||||
title={translate('Date')}
|
||||
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
@@ -111,10 +135,19 @@ function HistoryDetails(props) {
|
||||
if (eventType === 'releaseGrabbed') {
|
||||
const {
|
||||
source,
|
||||
host,
|
||||
grabTitle,
|
||||
url
|
||||
url,
|
||||
publishedDate,
|
||||
infoUrl,
|
||||
downloadClient,
|
||||
downloadClientName,
|
||||
elapsedTime,
|
||||
grabMethod
|
||||
} = data;
|
||||
|
||||
const downloadClientNameInfo = downloadClientName ?? downloadClient;
|
||||
|
||||
return (
|
||||
<DescriptionList>
|
||||
{
|
||||
@@ -135,6 +168,15 @@ function HistoryDetails(props) {
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
data ?
|
||||
<DescriptionListItem
|
||||
title={translate('Host')}
|
||||
data={host}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
data ?
|
||||
<DescriptionListItem
|
||||
@@ -144,6 +186,33 @@ function HistoryDetails(props) {
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
infoUrl ?
|
||||
<DescriptionListItem
|
||||
title={translate('InfoUrl')}
|
||||
data={<Link to={infoUrl}>{infoUrl}</Link>}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
publishedDate ?
|
||||
<DescriptionListItem
|
||||
title={translate('PublishedDate')}
|
||||
data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
downloadClientNameInfo ?
|
||||
<DescriptionListItem
|
||||
title={translate('DownloadClient')}
|
||||
data={downloadClientNameInfo}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
data ?
|
||||
<DescriptionListItem
|
||||
@@ -152,11 +221,40 @@ function HistoryDetails(props) {
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
elapsedTime ?
|
||||
<DescriptionListItem
|
||||
title={translate('ElapsedTime')}
|
||||
data={`${elapsedTime}ms`}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
grabMethod ?
|
||||
<DescriptionListItem
|
||||
title={translate('Redirected')}
|
||||
data={grabMethod.toLowerCase() === 'redirect' ? translate('Yes') : translate('No')}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
date ?
|
||||
<DescriptionListItem
|
||||
title={translate('Date')}
|
||||
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
|
||||
if (eventType === 'indexerAuth') {
|
||||
const { elapsedTime } = data;
|
||||
|
||||
return (
|
||||
<DescriptionList
|
||||
descriptionClassName={styles.description}
|
||||
@@ -170,6 +268,24 @@ function HistoryDetails(props) {
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
elapsedTime ?
|
||||
<DescriptionListItem
|
||||
title={translate('ElapsedTime')}
|
||||
data={`${elapsedTime}ms`}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
date ?
|
||||
<DescriptionListItem
|
||||
title={translate('Date')}
|
||||
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
@@ -181,6 +297,15 @@ function HistoryDetails(props) {
|
||||
title={translate('Name')}
|
||||
data={data.query}
|
||||
/>
|
||||
|
||||
{
|
||||
date ?
|
||||
<DescriptionListItem
|
||||
title={translate('Date')}
|
||||
data={formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/> :
|
||||
null
|
||||
}
|
||||
</DescriptionList>
|
||||
);
|
||||
}
|
||||
@@ -188,6 +313,7 @@ function HistoryDetails(props) {
|
||||
HistoryDetails.propTypes = {
|
||||
indexer: PropTypes.object.isRequired,
|
||||
eventType: PropTypes.string.isRequired,
|
||||
date: PropTypes.string.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired
|
||||
|
@@ -29,6 +29,7 @@ function HistoryDetailsModal(props) {
|
||||
isOpen,
|
||||
eventType,
|
||||
indexer,
|
||||
date,
|
||||
data,
|
||||
shortDateFormat,
|
||||
timeFormat,
|
||||
@@ -49,6 +50,7 @@ function HistoryDetailsModal(props) {
|
||||
<HistoryDetails
|
||||
eventType={eventType}
|
||||
indexer={indexer}
|
||||
date={date}
|
||||
data={data}
|
||||
shortDateFormat={shortDateFormat}
|
||||
timeFormat={timeFormat}
|
||||
@@ -71,6 +73,7 @@ HistoryDetailsModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
eventType: PropTypes.string.isRequired,
|
||||
indexer: PropTypes.object.isRequired,
|
||||
date: PropTypes.string.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
|
@@ -20,21 +20,22 @@ function getIconName(eventType) {
|
||||
}
|
||||
}
|
||||
|
||||
function getIconKind(successful) {
|
||||
switch (successful) {
|
||||
case false:
|
||||
return kinds.DANGER;
|
||||
default:
|
||||
return kinds.DEFAULT;
|
||||
function getIconKind(successful, redirect) {
|
||||
if (redirect) {
|
||||
return kinds.INFO;
|
||||
} else if (!successful) {
|
||||
return kinds.DANGER;
|
||||
}
|
||||
|
||||
return kinds.DEFAULT;
|
||||
}
|
||||
|
||||
function getTooltip(eventType, data, indexer) {
|
||||
function getTooltip(eventType, data, indexer, redirect) {
|
||||
switch (eventType) {
|
||||
case 'indexerQuery':
|
||||
return `Query "${data.query}" sent to ${indexer.name}`;
|
||||
case 'releaseGrabbed':
|
||||
return `Release grabbed from ${indexer.name}`;
|
||||
return redirect ? `Release grabbed via redirect from ${indexer.name}` : `Release grabbed from ${indexer.name}`;
|
||||
case 'indexerAuth':
|
||||
return `Auth attempted for ${indexer.name}`;
|
||||
case 'indexerRss':
|
||||
@@ -45,9 +46,12 @@ function getTooltip(eventType, data, indexer) {
|
||||
}
|
||||
|
||||
function HistoryEventTypeCell({ eventType, successful, data, indexer }) {
|
||||
const { grabMethod } = data;
|
||||
const redirect = grabMethod && grabMethod.toLowerCase() === 'redirect';
|
||||
|
||||
const iconName = getIconName(eventType);
|
||||
const iconKind = getIconKind(successful);
|
||||
const tooltip = getTooltip(eventType, data, indexer);
|
||||
const iconKind = getIconKind(successful, redirect);
|
||||
const tooltip = getTooltip(eventType, data, indexer, redirect);
|
||||
|
||||
return (
|
||||
<TableRowCell
|
||||
|
@@ -370,8 +370,9 @@ class HistoryRow extends Component {
|
||||
return (
|
||||
<RelativeDateCell
|
||||
key={name}
|
||||
date={date}
|
||||
className={styles.date}
|
||||
date={date}
|
||||
includeSeconds={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -408,6 +409,7 @@ class HistoryRow extends Component {
|
||||
<HistoryDetailsModal
|
||||
isOpen={this.state.isDetailsModalOpen}
|
||||
eventType={eventType}
|
||||
date={date}
|
||||
data={data}
|
||||
indexer={indexer}
|
||||
isMarkingAsFailed={isMarkingAsFailed}
|
||||
|
@@ -74,7 +74,7 @@ function IndexerHistoryRow(props: IndexerHistoryRowProps) {
|
||||
</div>
|
||||
</TableRowCell>
|
||||
|
||||
<RelativeDateCell date={date} />
|
||||
<RelativeDateCell date={date} includeSeconds={true} />
|
||||
|
||||
<TableRowCell className={styles.source}>
|
||||
{data.source ? data.source : null}
|
||||
@@ -91,6 +91,7 @@ function IndexerHistoryRow(props: IndexerHistoryRowProps) {
|
||||
<HistoryDetailsModal
|
||||
isOpen={isDetailsModalOpen}
|
||||
eventType={eventType}
|
||||
date={date}
|
||||
data={data}
|
||||
indexer={indexer}
|
||||
shortDateFormat={shortDateFormat}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
@@ -73,6 +74,9 @@ namespace NzbDrone.Core.Download
|
||||
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
|
||||
};
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
string downloadClientId;
|
||||
try
|
||||
{
|
||||
@@ -111,6 +115,11 @@ namespace NzbDrone.Core.Download
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sw.Stop();
|
||||
grabEvent.ElapsedTime = sw.ElapsedMilliseconds;
|
||||
}
|
||||
|
||||
_logger.ProgressInfo("Report sent to {0}. {1}", downloadClient.Definition.Name, downloadTitle);
|
||||
|
||||
@@ -144,6 +153,9 @@ namespace NzbDrone.Core.Download
|
||||
GrabTrigger = source == "Prowlarr" ? GrabTrigger.Manual : GrabTrigger.Api
|
||||
};
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
byte[] downloadedBytes;
|
||||
|
||||
try
|
||||
@@ -172,6 +184,11 @@ namespace NzbDrone.Core.Download
|
||||
_eventAggregator.PublishEvent(grabEvent);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sw.Stop();
|
||||
grabEvent.ElapsedTime = sw.ElapsedMilliseconds;
|
||||
}
|
||||
|
||||
_logger.Trace("Downloaded {0} bytes from {1}", downloadedBytes.Length, link);
|
||||
_eventAggregator.PublishEvent(grabEvent);
|
||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Indexers;
|
||||
@@ -203,8 +204,24 @@ namespace NzbDrone.Core.History
|
||||
history.Data.Add("Host", message.Host ?? string.Empty);
|
||||
history.Data.Add("GrabMethod", message.Redirect ? "Redirect" : "Proxy");
|
||||
history.Data.Add("GrabTitle", message.Title);
|
||||
history.Data.Add("Categories", string.Join(",", message.Release.Categories.Select(x => x.Id) ?? Array.Empty<int>()));
|
||||
history.Data.Add("Url", message.Url ?? string.Empty);
|
||||
history.Data.Add("ElapsedTime", message.ElapsedTime.ToString());
|
||||
|
||||
if (message.Release.InfoUrl.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
history.Data.Add("InfoUrl", message.Release.InfoUrl);
|
||||
}
|
||||
|
||||
if (message.DownloadClient.IsNotNullOrWhiteSpace() || message.DownloadClientName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
history.Data.Add("DownloadClient", message.DownloadClient ?? string.Empty);
|
||||
history.Data.Add("DownloadClientName", message.DownloadClientName ?? string.Empty);
|
||||
}
|
||||
|
||||
if (message.Release.PublishDate != DateTime.MinValue)
|
||||
{
|
||||
history.Data.Add("PublishedDate", message.Release.PublishDate.ToString("s") + "Z");
|
||||
}
|
||||
|
||||
_historyRepository.Insert(history);
|
||||
}
|
||||
@@ -219,7 +236,7 @@ namespace NzbDrone.Core.History
|
||||
Successful = message.Successful
|
||||
};
|
||||
|
||||
history.Data.Add("ElapsedTime", message.Time.ToString());
|
||||
history.Data.Add("ElapsedTime", message.ElapsedTime.ToString());
|
||||
|
||||
_historyRepository.Insert(history);
|
||||
}
|
||||
|
@@ -6,13 +6,13 @@ namespace NzbDrone.Core.Indexers.Events
|
||||
{
|
||||
public int IndexerId { get; set; }
|
||||
public bool Successful { get; set; }
|
||||
public long Time { get; set; }
|
||||
public long ElapsedTime { get; set; }
|
||||
|
||||
public IndexerAuthEvent(int indexerId, bool successful, long time)
|
||||
public IndexerAuthEvent(int indexerId, bool successful, long elapsedTime)
|
||||
{
|
||||
IndexerId = indexerId;
|
||||
Successful = successful;
|
||||
Time = time;
|
||||
ElapsedTime = elapsedTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ namespace NzbDrone.Core.Indexers.Events
|
||||
public string DownloadId { get; set; }
|
||||
public IIndexer Indexer { get; set; }
|
||||
public GrabTrigger GrabTrigger { get; set; }
|
||||
public long ElapsedTime { get; set; }
|
||||
|
||||
public IndexerDownloadEvent(ReleaseInfo release, bool successful, string source, string host, string title, string url)
|
||||
{
|
||||
|
@@ -424,6 +424,7 @@
|
||||
"IndexerVipExpiringHealthCheckMessage": "Indexer VIP benefits expiring soon: {indexerNames}",
|
||||
"Indexers": "Indexers",
|
||||
"Info": "Info",
|
||||
"InfoUrl": "Info URL",
|
||||
"InitialFailure": "Initial Failure",
|
||||
"InstanceName": "Instance Name",
|
||||
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
|
||||
@@ -555,6 +556,7 @@
|
||||
"ProxyValidationBadRequest": "Failed to test proxy. Status code: {statusCode}",
|
||||
"ProxyValidationUnableToConnect": "Unable to connect to proxy: {exceptionMessage}. Check the log surrounding this error for details",
|
||||
"Public": "Public",
|
||||
"PublishedDate": "Published Date",
|
||||
"Publisher": "Publisher",
|
||||
"Query": "Query",
|
||||
"QueryOptions": "Query Options",
|
||||
@@ -568,6 +570,7 @@
|
||||
"Reddit": "Reddit",
|
||||
"Redirect": "Redirect",
|
||||
"RedirectHelpText": "Redirect incoming download request for indexer and pass the grab directly instead of proxying the request via {appName}",
|
||||
"Redirected": "Redirected",
|
||||
"Refresh": "Refresh",
|
||||
"RefreshMovie": "Refresh movie",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "Branch {0} is not a valid {appName} release branch, you will not receive updates",
|
||||
|
Reference in New Issue
Block a user