diff --git a/internal/database/release.go b/internal/database/release.go
index 9379b85..071d873 100644
--- a/internal/database/release.go
+++ b/internal/database/release.go
@@ -551,7 +551,8 @@ FROM (
CROSS JOIN (
SELECT
COUNT(CASE WHEN status = 'PUSH_APPROVED' THEN 0 END) AS push_approved_count,
- COUNT(CASE WHEN status = 'PUSH_REJECTED' THEN 0 END) AS push_rejected_count
+ COUNT(CASE WHEN status = 'PUSH_REJECTED' THEN 0 END) AS push_rejected_count,
+ COUNT(CASE WHEN status = 'PUSH_ERROR' THEN 0 END) AS push_error_count
FROM release_action_status
) AS foo`
@@ -562,7 +563,7 @@ CROSS JOIN (
var rls domain.ReleaseStats
- if err := row.Scan(&rls.TotalCount, &rls.FilteredCount, &rls.FilterRejectedCount, &rls.PushApprovedCount, &rls.PushRejectedCount); err != nil {
+ if err := row.Scan(&rls.TotalCount, &rls.FilteredCount, &rls.FilterRejectedCount, &rls.PushApprovedCount, &rls.PushRejectedCount, &rls.PushErrorCount); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
diff --git a/internal/domain/release.go b/internal/domain/release.go
index 2275473..c82d312 100644
--- a/internal/domain/release.go
+++ b/internal/domain/release.go
@@ -150,6 +150,7 @@ type ReleaseStats struct {
FilterRejectedCount int64 `json:"filter_rejected_count"`
PushApprovedCount int64 `json:"push_approved_count"`
PushRejectedCount int64 `json:"push_rejected_count"`
+ PushErrorCount int64 `json:"push_error_count"`
}
type ReleasePushStatus string
diff --git a/web/src/components/data-table/Cells.tsx b/web/src/components/data-table/Cells.tsx
index e58a6f6..531b7f0 100644
--- a/web/src/components/data-table/Cells.tsx
+++ b/web/src/components/data-table/Cells.tsx
@@ -8,6 +8,8 @@ import { toast } from "react-hot-toast";
import { formatDistanceToNowStrict } from "date-fns";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { ArrowPathIcon, CheckIcon } from "@heroicons/react/24/solid";
+import { ArrowDownTrayIcon, ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
+import { ExternalLink } from "../ExternalLink";
import { ClockIcon, XMarkIcon, NoSymbolIcon } from "@heroicons/react/24/outline";
import { APIClient } from "@api/APIClient";
@@ -21,6 +23,10 @@ interface CellProps {
value: string;
}
+interface LinksCellProps {
+ value: Release;
+}
+
export const AgeCell = ({ value }: CellProps) => (
{formatDistanceToNowStrict(new Date(value), { addSuffix: false })}
@@ -243,3 +249,20 @@ export const ReleaseStatusCell = ({ value }: ReleaseStatusCellProps) => (
))}
);
+
+export const LinksCell = ({ value }: LinksCellProps) => {
+ return (
+
+ {value.download_url && (
+
+
+
+ )}
+ {value.info_url && (
+
+
+
+ )}
+
+ );
+};
diff --git a/web/src/components/data-table/index.tsx b/web/src/components/data-table/index.tsx
index 14fe1c4..7d52dd9 100644
--- a/web/src/components/data-table/index.tsx
+++ b/web/src/components/data-table/index.tsx
@@ -4,4 +4,4 @@
*/
export { Button, PageButton } from "./Buttons";
-export { AgeCell, IndexerCell, TitleCell, ReleaseStatusCell } from "./Cells";
\ No newline at end of file
+export { AgeCell, IndexerCell, TitleCell, ReleaseStatusCell, LinksCell } from "./Cells";
diff --git a/web/src/screens/dashboard/Stats.tsx b/web/src/screens/dashboard/Stats.tsx
index a458840..2ac10ec 100644
--- a/web/src/screens/dashboard/Stats.tsx
+++ b/web/src/screens/dashboard/Stats.tsx
@@ -6,33 +6,49 @@
import { useQuery } from "@tanstack/react-query";
import { APIClient } from "@api/APIClient";
import { classNames } from "@utils";
+import { useNavigate } from "react-router-dom";
+import { LinkIcon } from "@heroicons/react/24/solid";
interface StatsItemProps {
name: string;
value?: number;
placeholder?: string;
+ onClick?: () => void;
}
-const StatsItem = ({ name, placeholder, value }: StatsItemProps) => (
+const StatsItem = ({ name, placeholder, value, onClick }: StatsItemProps) => (
- {name}
+
-
- {placeholder}
-
-
-
- {value}
-
+
+
+ {placeholder}
+
+
+ {value}
+
+
);
export const Stats = () => {
+ const navigate = useNavigate();
+ const handleStatClick = (filterType: string) => {
+ if (filterType) {
+ navigate(`/releases?filter=${filterType}`);
+ } else {
+ navigate("/releases");
+ }
+ };
+
const { isLoading, data } = useQuery({
queryKey: ["dash_release_stats"],
queryFn: APIClient.release.stats,
@@ -45,11 +61,12 @@ export const Stats = () => {
Stats
-
-
+
+ handleStatClick("")} value={data?.filtered_count ?? 0} />
{/* */}
-
-
+ handleStatClick("PUSH_APPROVED")} value={data?.push_approved_count ?? 0} />
+ handleStatClick("PUSH_REJECTED")} value={data?.push_rejected_count ?? 0 } />
+ handleStatClick("PUSH_ERROR")} value={data?.push_error_count ?? 0} />
);
diff --git a/web/src/screens/releases/Filters.tsx b/web/src/screens/releases/Filters.tsx
index f92d25f..41a913d 100644
--- a/web/src/screens/releases/Filters.tsx
+++ b/web/src/screens/releases/Filters.tsx
@@ -124,8 +124,14 @@ const FilterOption = ({ label, value }: FilterOptionProps) => (
);
export const PushStatusSelectColumnFilter = ({
- column: { filterValue, setFilter, id }
+ column: { filterValue, setFilter, id },
+ initialFilterValue
}: FilterProps