mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-14 09:25:47 +01:00
Merge pull request #1554 from InterN0te/dev-addRatio
Add Torrents ratio in Torrents Queue Widget
This commit is contained in:
@@ -25,13 +25,19 @@
|
|||||||
"labelFilter": {
|
"labelFilter": {
|
||||||
"label": "Label list",
|
"label": "Label list",
|
||||||
"description": "When 'is whitelist' checked, this will act as a whitelist. If not checked, this is a blacklist. Will not do anything when empty"
|
"description": "When 'is whitelist' checked, this will act as a whitelist. If not checked, this is a blacklist. Will not do anything when empty"
|
||||||
|
},
|
||||||
|
"displayRatioWithFilter": {
|
||||||
|
"label": "Display filtered torrents list ratio",
|
||||||
|
"info": "If disabled, only the global ratio will be display. The global ratio will still use the labels if set"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"card": {
|
"card": {
|
||||||
"footer": {
|
"footer": {
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"lastUpdated": "Last updated {{time}} ago"
|
"lastUpdated": "Last updated {{time}} ago",
|
||||||
|
"ratioGlobal": "Global ratio",
|
||||||
|
"ratioWithFilter": "Ratio with filter"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"header": {
|
"header": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { NormalizedTorrent, TorrentState } from '@ctrl/shared-torrent';
|
import { NormalizedTorrent, TorrentState } from '@ctrl/shared-torrent';
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { ITorrent, filterTorrents } from './TorrentTile';
|
import { ITorrent, filterTorrents, getTorrentsRatio } from './TorrentTile';
|
||||||
|
|
||||||
describe('TorrentTile', () => {
|
describe('TorrentTile', () => {
|
||||||
it('filter torrents when stale', () => {
|
it('filter torrents when stale', () => {
|
||||||
@@ -229,6 +229,43 @@ describe('TorrentTile', () => {
|
|||||||
expect(filtered.includes(torrents[1])).toBe(false);
|
expect(filtered.includes(torrents[1])).toBe(false);
|
||||||
expect(filtered.at(1)).toBe(torrents[2]);
|
expect(filtered.at(1)).toBe(torrents[2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('calcul ratio', () => {
|
||||||
|
// arrange
|
||||||
|
const widget: ITorrent = {
|
||||||
|
id: 'abc',
|
||||||
|
area: {
|
||||||
|
type: 'sidebar',
|
||||||
|
properties: {
|
||||||
|
location: 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shape: {},
|
||||||
|
type: 'torrents-status',
|
||||||
|
properties: {
|
||||||
|
labelFilter: [],
|
||||||
|
labelFilterIsWhitelist: false,
|
||||||
|
displayCompletedTorrents: false,
|
||||||
|
displayActiveTorrents: false,
|
||||||
|
speedLimitOfActiveTorrents: 10,
|
||||||
|
displayStaleTorrents: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const torrents: NormalizedTorrent[] = [
|
||||||
|
constructTorrent('HH', 'I am completed', true, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// act
|
||||||
|
const filtered = filterTorrents(widget, torrents);
|
||||||
|
const ratioGlobal = getTorrentsRatio(widget, torrents, false);
|
||||||
|
const ratioWithFilter = getTorrentsRatio(widget, torrents, true);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(filtered.length).toBe(0);
|
||||||
|
expect(filtered.includes(torrents[1])).toBe(false);
|
||||||
|
expect(ratioGlobal).toBe(378535535/23024335);
|
||||||
|
expect(ratioWithFilter).toBe(-1); //infinite ratio
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const constructTorrent = (
|
const constructTorrent = (
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ const definition = defineWidget({
|
|||||||
type: 'multiple-text',
|
type: 'multiple-text',
|
||||||
defaultValue: [] as string[],
|
defaultValue: [] as string[],
|
||||||
},
|
},
|
||||||
|
displayRatioWithFilter: {
|
||||||
|
type: 'switch',
|
||||||
|
defaultValue: true,
|
||||||
|
info: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
gridstack: {
|
gridstack: {
|
||||||
minWidth: 2,
|
minWidth: 2,
|
||||||
@@ -148,6 +153,9 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
|||||||
const duration = dayjs.duration(difference, 'ms');
|
const duration = dayjs.duration(difference, 'ms');
|
||||||
const humanizedDuration = duration.humanize();
|
const humanizedDuration = duration.humanize();
|
||||||
|
|
||||||
|
const ratioGlobal = getTorrentsRatio(widget, torrents, false);
|
||||||
|
const ratioWithFilter = getTorrentsRatio(widget, torrents, true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" sx={{ height: '100%' }} ref={ref}>
|
<Flex direction="column" sx={{ height: '100%' }} ref={ref}>
|
||||||
<ScrollArea sx={{ height: '100%', width: '100%' }} mb="xs">
|
<ScrollArea sx={{ height: '100%', width: '100%' }} mb="xs">
|
||||||
@@ -193,6 +201,13 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
|||||||
|
|
||||||
<Text color="dimmed" size="xs">
|
<Text color="dimmed" size="xs">
|
||||||
{t('card.footer.lastUpdated', { time: humanizedDuration })}
|
{t('card.footer.lastUpdated', { time: humanizedDuration })}
|
||||||
|
{` - ${t('card.footer.ratioGlobal')} : ${
|
||||||
|
ratioGlobal === -1 ? '∞' : ratioGlobal.toFixed(2)
|
||||||
|
}`}
|
||||||
|
{widget.properties.displayRatioWithFilter &&
|
||||||
|
` - ${t('card.footer.ratioWithFilter')} : ${
|
||||||
|
ratioWithFilter === -1 ? '∞' : ratioWithFilter.toFixed(2)
|
||||||
|
}`}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -238,4 +253,30 @@ const filterTorrentsByLabels = (
|
|||||||
return torrents.filter((torrent) => !labels.includes(torrent.label as string));
|
return torrents.filter((torrent) => !labels.includes(torrent.label as string));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getTorrentsRatio = (
|
||||||
|
widget: ITorrent,
|
||||||
|
torrents: NormalizedTorrent[],
|
||||||
|
applyAllFilter: boolean
|
||||||
|
) => {
|
||||||
|
if (applyAllFilter) {
|
||||||
|
torrents = filterTorrents(widget, torrents);
|
||||||
|
} else if (widget.properties.labelFilter.length > 0) {
|
||||||
|
torrents = filterTorrentsByLabels(
|
||||||
|
torrents,
|
||||||
|
widget.properties.labelFilter,
|
||||||
|
widget.properties.labelFilterIsWhitelist
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalDownloadedSum = torrents.reduce(
|
||||||
|
(sum, torrent) => sum + torrent.totalDownloaded,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
return totalDownloadedSum > 0
|
||||||
|
? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) /
|
||||||
|
totalDownloadedSum
|
||||||
|
: -1;
|
||||||
|
};
|
||||||
|
|
||||||
export default definition;
|
export default definition;
|
||||||
|
|||||||
Reference in New Issue
Block a user