mirror of
https://github.com/idanoo/autobrr
synced 2025-07-25 01:39:13 +00:00
enhancement(settings): make lists sortable (#800)
* initial commit * sorting for clients and networks * sort feeds * cursor pointer on hover
This commit is contained in:
parent
30cf9c55f0
commit
59f41be3ef
4 changed files with 305 additions and 33 deletions
|
@ -8,12 +8,74 @@ import { APIClient } from "../../api/APIClient";
|
|||
import { DownloadClientTypeNameMap } from "../../domain/constants";
|
||||
import toast from "react-hot-toast";
|
||||
import Toast from "../../components/notifications/Toast";
|
||||
import { useState, useMemo } from "react";
|
||||
|
||||
interface DLSettingsItemProps {
|
||||
client: DownloadClient;
|
||||
idx: number;
|
||||
}
|
||||
|
||||
interface ListItemProps {
|
||||
clients: DownloadClient;
|
||||
}
|
||||
|
||||
interface SortConfig {
|
||||
key: keyof ListItemProps["clients"] | "enabled";
|
||||
direction: "ascending" | "descending";
|
||||
}
|
||||
|
||||
function useSort(items: ListItemProps["clients"][], config?: SortConfig) {
|
||||
const [sortConfig, setSortConfig] = useState(config);
|
||||
|
||||
|
||||
|
||||
const sortedItems = useMemo(() => {
|
||||
if (!sortConfig) {
|
||||
return items;
|
||||
}
|
||||
|
||||
const sortableItems = [...items];
|
||||
|
||||
sortableItems.sort((a, b) => {
|
||||
const aValue = sortConfig.key === "enabled" ? (a[sortConfig.key] ?? false) as number | boolean | string : a[sortConfig.key] as number | boolean | string;
|
||||
const bValue = sortConfig.key === "enabled" ? (b[sortConfig.key] ?? false) as number | boolean | string : b[sortConfig.key] as number | boolean | string;
|
||||
|
||||
if (aValue < bValue) {
|
||||
return sortConfig.direction === "ascending" ? -1 : 1;
|
||||
}
|
||||
if (aValue > bValue) {
|
||||
return sortConfig.direction === "ascending" ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return sortableItems;
|
||||
}, [items, sortConfig]);
|
||||
|
||||
const requestSort = (key: keyof ListItemProps["clients"]) => {
|
||||
let direction: "ascending" | "descending" = "ascending";
|
||||
if (
|
||||
sortConfig &&
|
||||
sortConfig.key === key &&
|
||||
sortConfig.direction === "ascending"
|
||||
) {
|
||||
direction = "descending";
|
||||
}
|
||||
setSortConfig({ key, direction });
|
||||
};
|
||||
|
||||
|
||||
const getSortIndicator = (key: keyof ListItemProps["clients"]) => {
|
||||
if (!sortConfig || sortConfig.key !== key) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return sortConfig.direction === "ascending" ? "↑" : "↓";
|
||||
};
|
||||
|
||||
return { items: sortedItems, requestSort, sortConfig, getSortIndicator };
|
||||
}
|
||||
|
||||
function DownloadClientSettingsListItem({ client }: DLSettingsItemProps) {
|
||||
const [updateClientIsOpen, toggleUpdateClient] = useToggle(false);
|
||||
|
||||
|
@ -84,10 +146,13 @@ function DownloadClientSettings() {
|
|||
{ refetchOnWindowFocus: false }
|
||||
);
|
||||
|
||||
const sortedClients = useSort(data || []);
|
||||
|
||||
if (error) {
|
||||
return <p>Failed to fetch download clients</p>;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="lg:col-span-9">
|
||||
|
||||
|
@ -113,24 +178,33 @@ function DownloadClientSettings() {
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col mt-6 px-4">
|
||||
{data && data.length > 0 ?
|
||||
{sortedClients.items.length > 0 ?
|
||||
<section className="light:bg-white dark:bg-gray-800 light:shadow sm:rounded-sm">
|
||||
<ol className="min-w-full relative">
|
||||
<li className="grid grid-cols-12 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="col-span-2 sm:col-span-1 px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||
Enabled
|
||||
<div className="flex col-span-2 sm:col-span-1 px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer"
|
||||
onClick={() => sortedClients.requestSort("enabled")}>
|
||||
Enabled <span className="sort-indicator">{sortedClients.getSortIndicator("enabled")}</span>
|
||||
</div>
|
||||
<div className="col-span-6 sm:col-span-4 lg:col-span-4 pl-12 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||
Name
|
||||
<div
|
||||
className="col-span-6 sm:col-span-4 lg:col-span-4 pl-12 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer"
|
||||
onClick={() => sortedClients.requestSort("name")}
|
||||
>
|
||||
Name <span className="sort-indicator">{sortedClients.getSortIndicator("name")}</span>
|
||||
</div>
|
||||
<div className="hidden sm:flex col-span-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||
Host
|
||||
<div
|
||||
className="hidden sm:flex col-span-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer"
|
||||
onClick={() => sortedClients.requestSort("host")}
|
||||
>
|
||||
Host <span className="sort-indicator">{sortedClients.getSortIndicator("host")}</span>
|
||||
</div>
|
||||
<div className="hidden sm:flex col-span-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||
Type
|
||||
<div className="hidden sm:flex col-span-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer"
|
||||
onClick={() => sortedClients.requestSort("type")}
|
||||
>
|
||||
Type <span className="sort-indicator">{sortedClients.getSortIndicator("type")}</span>
|
||||
</div>
|
||||
</li>
|
||||
{data && data.map((client, idx) => (
|
||||
{sortedClients.items.map((client, idx) => (
|
||||
<DownloadClientSettingsListItem client={client} idx={idx} key={idx} />
|
||||
))}
|
||||
</ol>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue