- {(issue) => (
-
- handleIgnore(issue)}
- density={config.viewDensity}
- commentCount={issue.comments}
- >
-
-
-
- )}
+
+
+ {(repoGroup) => {
+ const isRepoCollapsed = () => collapsedRepos[repoGroup.repoFullName];
+ return (
+
+
+
+
+
+ {(issue) => (
+
+ handleIgnore(issue)}
+ density={config.viewDensity}
+ commentCount={issue.comments}
+ >
+
+
+
+ )}
+
+
+
+
+ );
+ }}
diff --git a/src/app/components/dashboard/ItemRow.tsx b/src/app/components/dashboard/ItemRow.tsx
index 395b9a7e..fd19b830 100644
--- a/src/app/components/dashboard/ItemRow.tsx
+++ b/src/app/components/dashboard/ItemRow.tsx
@@ -14,6 +14,7 @@ export interface ItemRowProps {
onIgnore: () => void;
density: "compact" | "comfortable";
commentCount?: number;
+ hideRepo?: boolean;
}
export default function ItemRow(props: ItemRowProps) {
@@ -43,14 +44,16 @@ export default function ItemRow(props: ItemRowProps) {
${isCompact() ? "px-4 py-2" : "px-4 py-3"}`}
>
{/* Repo badge */}
-
- {props.repo}
-
+
+
+ {props.repo}
+
+
{/* Main content */}
diff --git a/src/app/components/dashboard/PullRequestsTab.tsx b/src/app/components/dashboard/PullRequestsTab.tsx
index 22d97700..d91eee0c 100644
--- a/src/app/components/dashboard/PullRequestsTab.tsx
+++ b/src/app/components/dashboard/PullRequestsTab.tsx
@@ -1,4 +1,5 @@
-import { createMemo, createSignal, For, Show } from "solid-js";
+import { createEffect, createMemo, createSignal, For, Show } from "solid-js";
+import { createStore } from "solid-js/store";
import { config } from "../../stores/config";
import { viewState, setSortPreference, ignoreItem, unignoreItem, setTabFilter, resetTabFilter, resetAllTabFilters, type PullRequestFilterField } from "../../stores/view";
import type { PullRequest, ApiError } from "../../services/api";
@@ -15,6 +16,8 @@ import ReviewBadge from "../shared/ReviewBadge";
import SizeBadge from "../shared/SizeBadge";
import RoleBadge from "../shared/RoleBadge";
import SkeletonRows from "../shared/SkeletonRows";
+import ChevronIcon from "../shared/ChevronIcon";
+import { groupByRepo, computePageLayout, slicePageGroups } from "../../lib/grouping";
export interface PullRequestsTabProps {
pullRequests: PullRequest[];
@@ -103,6 +106,11 @@ const prFilterGroups: FilterChipGroupDef[] = [
export default function PullRequestsTab(props: PullRequestsTabProps) {
const [page, setPage] = createSignal(0);
+ const [collapsedRepos, setCollapsedRepos] = createStore>({});
+
+ function toggleRepo(repoFullName: string) {
+ setCollapsedRepos(repoFullName, (v) => !v);
+ }
const sortPref = createMemo(() => {
const pref = viewState.sortPreferences["pullRequests"];
@@ -190,19 +198,19 @@ export default function PullRequestsTab(props: PullRequestsTabProps) {
return { items, meta };
});
- const filteredSorted = () => filteredSortedWithMeta().items;
- const prMeta = () => filteredSortedWithMeta().meta;
-
- const pageSize = createMemo(() => config.itemsPerPage);
+ const filteredSorted = createMemo(() => filteredSortedWithMeta().items);
+ const prMeta = createMemo(() => filteredSortedWithMeta().meta);
- const pageCount = createMemo(() =>
- Math.max(1, Math.ceil(filteredSorted().length / pageSize()))
+ const repoGroups = createMemo(() => groupByRepo(filteredSorted()));
+ const pageLayout = createMemo(() => computePageLayout(repoGroups(), config.itemsPerPage));
+ const pageCount = createMemo(() => pageLayout().pageCount);
+ const pageGroups = createMemo(() =>
+ slicePageGroups(repoGroups(), pageLayout().boundaries, pageCount(), page())
);
- const pagedItems = createMemo(() => {
- const p = Math.min(page(), pageCount() - 1);
- const start = p * pageSize();
- return filteredSorted().slice(start, start + pageSize());
+ createEffect(() => {
+ const max = pageCount() - 1;
+ if (page() > max) setPage(max);
});
function handleSort(field: SortField) {
@@ -270,9 +278,18 @@ export default function PullRequestsTab(props: PullRequestsTabProps) {
{ setTabFilter("pullRequests", field as PullRequestFilterField, value); setPage(0); }}
- onReset={(field) => { resetTabFilter("pullRequests", field as PullRequestFilterField); setPage(0); }}
- onResetAll={() => { resetAllTabFilters("pullRequests"); setPage(0); }}
+ onChange={(field, value) => {
+ setTabFilter("pullRequests", field as PullRequestFilterField, value);
+ setPage(0);
+ }}
+ onReset={(field) => {
+ resetTabFilter("pullRequests", field as PullRequestFilterField);
+ setPage(0);
+ }}
+ onResetAll={() => {
+ resetAllTabFilters("pullRequests");
+ setPage(0);
+ }}
/>
@@ -284,7 +301,7 @@ export default function PullRequestsTab(props: PullRequestsTabProps) {
{/* PR rows */}
0}>
0}
+ when={pageGroups().length > 0}
fallback={