mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
New: Summary Stats
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||||
|
import RelativeDateCell from './RelativeDateCell';
|
||||||
|
|
||||||
|
function createMapStateToProps() {
|
||||||
|
return createSelector(
|
||||||
|
createUISettingsSelector(),
|
||||||
|
(uiSettings) => {
|
||||||
|
return {
|
||||||
|
showRelativeDates: uiSettings.showRelativeDates,
|
||||||
|
shortDateFormat: uiSettings.shortDateFormat,
|
||||||
|
longDateFormat: uiSettings.longDateFormat,
|
||||||
|
timeFormat: uiSettings.timeFormat
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(createMapStateToProps, null)(RelativeDateCell);
|
@@ -8,6 +8,11 @@
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quarterWidthChart {
|
||||||
|
display: inline-block;
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
.chartContainer {
|
.chartContainer {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 15px 25px;
|
padding: 15px 25px;
|
||||||
@@ -16,12 +21,32 @@
|
|||||||
background-color: var(--chartBackgroundColor);
|
background-color: var(--chartBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statContainer {
|
||||||
|
margin: 5px;
|
||||||
|
padding: 15px 25px;
|
||||||
|
height: 150px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: var(--chartBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.statTitle {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: $breakpointSmall) {
|
@media only screen and (max-width: $breakpointSmall) {
|
||||||
.halfWidthChart {
|
.halfWidthChart {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 5px;
|
|
||||||
padding: 15px 25px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
}
|
||||||
|
|
||||||
|
.quarterWidthChart {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,10 @@ interface CssExports {
|
|||||||
'chartContainer': string;
|
'chartContainer': string;
|
||||||
'fullWidthChart': string;
|
'fullWidthChart': string;
|
||||||
'halfWidthChart': string;
|
'halfWidthChart': string;
|
||||||
|
'quarterWidthChart': string;
|
||||||
|
'stat': string;
|
||||||
|
'statContainer': string;
|
||||||
|
'statTitle': string;
|
||||||
}
|
}
|
||||||
export const cssExports: CssExports;
|
export const cssExports: CssExports;
|
||||||
export default cssExports;
|
export default cssExports;
|
||||||
|
@@ -24,6 +24,7 @@ import {
|
|||||||
IndexerStatsIndexer,
|
IndexerStatsIndexer,
|
||||||
IndexerStatsUserAgent,
|
IndexerStatsUserAgent,
|
||||||
} from 'typings/IndexerStats';
|
} from 'typings/IndexerStats';
|
||||||
|
import abbreviateNumber from 'Utilities/Number/abbreviateNumber';
|
||||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import IndexerStatsFilterModal from './IndexerStatsFilterModal';
|
import IndexerStatsFilterModal from './IndexerStatsFilterModal';
|
||||||
@@ -201,6 +202,16 @@ function IndexerStats() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isLoaded = !error && isPopulated;
|
const isLoaded = !error && isPopulated;
|
||||||
|
const indexerCount = item.indexers?.length ?? 0;
|
||||||
|
const userAgentCount = item.userAgents?.length ?? 0;
|
||||||
|
const queryCount =
|
||||||
|
item.indexers?.reduce((total, indexer) => {
|
||||||
|
return total + indexer.numberOfQueries;
|
||||||
|
}, 0) ?? 0;
|
||||||
|
const grabCount =
|
||||||
|
item.indexers?.reduce((total, indexer) => {
|
||||||
|
return total + indexer.numberOfGrabs;
|
||||||
|
}, 0) ?? 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent>
|
<PageContent>
|
||||||
@@ -228,6 +239,40 @@ function IndexerStats() {
|
|||||||
|
|
||||||
{isLoaded && (
|
{isLoaded && (
|
||||||
<div>
|
<div>
|
||||||
|
<div className={styles.quarterWidthChart}>
|
||||||
|
<div className={styles.statContainer}>
|
||||||
|
<div className={styles.statTitle}>
|
||||||
|
{translate('ActiveIndexers')}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stat}>{indexerCount}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.quarterWidthChart}>
|
||||||
|
<div className={styles.statContainer}>
|
||||||
|
<div className={styles.statTitle}>
|
||||||
|
{translate('TotalQueries')}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stat}>
|
||||||
|
{abbreviateNumber(queryCount)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.quarterWidthChart}>
|
||||||
|
<div className={styles.statContainer}>
|
||||||
|
<div className={styles.statTitle}>
|
||||||
|
{translate('TotalGrabs')}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stat}>{abbreviateNumber(grabCount)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.quarterWidthChart}>
|
||||||
|
<div className={styles.statContainer}>
|
||||||
|
<div className={styles.statTitle}>
|
||||||
|
{translate('ActiveApps')}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stat}>{userAgentCount}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className={styles.fullWidthChart}>
|
<div className={styles.fullWidthChart}>
|
||||||
<div className={styles.chartContainer}>
|
<div className={styles.chartContainer}>
|
||||||
<BarChart
|
<BarChart
|
||||||
|
19
frontend/src/Utilities/Number/abbreviateNumber.js
Normal file
19
frontend/src/Utilities/Number/abbreviateNumber.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export default function abbreviateNumber(num, decimalPlaces) {
|
||||||
|
if (num === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num === 0) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
decimalPlaces = (!decimalPlaces || decimalPlaces < 0) ? 0 : decimalPlaces;
|
||||||
|
|
||||||
|
const b = (num).toPrecision(2).split('e');
|
||||||
|
const k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3);
|
||||||
|
const c = k < 1 ? num.toFixed(0 + decimalPlaces) : (num / Math.pow(10, k * 3) ).toFixed(1 + decimalPlaces);
|
||||||
|
const d = c < 0 ? c : Math.abs(c);
|
||||||
|
const e = d + ['', 'K', 'M', 'B', 'T'][k];
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
@@ -2,6 +2,8 @@
|
|||||||
"About": "About",
|
"About": "About",
|
||||||
"AcceptConfirmationModal": "Accept Confirmation Modal",
|
"AcceptConfirmationModal": "Accept Confirmation Modal",
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
|
"ActiveIndexers": "Active Indexers",
|
||||||
|
"ActiveApps": "Active Apps",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
"AddApplication": "Add Application",
|
"AddApplication": "Add Application",
|
||||||
"AddApplicationImplementation": "Add Application - {implementationName}",
|
"AddApplicationImplementation": "Add Application - {implementationName}",
|
||||||
@@ -527,10 +529,12 @@
|
|||||||
"Torrent": "Torrent",
|
"Torrent": "Torrent",
|
||||||
"Torrents": "Torrents",
|
"Torrents": "Torrents",
|
||||||
"TorznabUrl": "Torznab Url",
|
"TorznabUrl": "Torznab Url",
|
||||||
|
"TotalGrabs": "Total Grabs",
|
||||||
"TotalHostGrabs": "Total Host Grabs",
|
"TotalHostGrabs": "Total Host Grabs",
|
||||||
"TotalHostQueries": "Total Host Queries",
|
"TotalHostQueries": "Total Host Queries",
|
||||||
"TotalIndexerQueries": "Total Indexer Queries",
|
"TotalIndexerQueries": "Total Indexer Queries",
|
||||||
"TotalIndexerSuccessfulGrabs": "Total Indexer Successful Grabs",
|
"TotalIndexerSuccessfulGrabs": "Total Indexer Successful Grabs",
|
||||||
|
"TotalQueries": "Total Queries",
|
||||||
"TotalUserAgentGrabs": "Total User Agent Grabs",
|
"TotalUserAgentGrabs": "Total User Agent Grabs",
|
||||||
"TotalUserAgentQueries": "Total User Agent Queries",
|
"TotalUserAgentQueries": "Total User Agent Queries",
|
||||||
"Track": "Track",
|
"Track": "Track",
|
||||||
|
Reference in New Issue
Block a user