From f689eab807985b003fc917653370311d9053571a Mon Sep 17 00:00:00 2001 From: jikrana Date: Mon, 17 Aug 2026 11:24:26 +0530 Subject: [PATCH 1/2] feat: add organization filter to contributors --- src/pages/ContributorsPage.jsx | 85 +++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/pages/ContributorsPage.jsx b/src/pages/ContributorsPage.jsx index e89fd97..390521c 100644 --- a/src/pages/ContributorsPage.jsx +++ b/src/pages/ContributorsPage.jsx @@ -11,11 +11,12 @@ import AnalysisBanner from '../components/AnalysisBanner' import { ContributorSkeleton } from '../components/Orgexplorerskeletons' export default function ContributorsPage() { - const { model, isComplete, loading, runFullExplore } = useApp() + const { model, isComplete, loading, runFullExplore, orgs } = useApp() const [search, setSearch] = useState('') const [shown, setShown] = useState(20) const [openInfo, setOpenInfo] = useState(null) - const busFactorRef = useRef(null) + const [selectedOrg, setSelectedOrg] = useState('all') + const busFactorRef = useRef(null) const freshnessRef = useRef(null) const signalRef = useRef(null) @@ -48,11 +49,38 @@ export default function ContributorsPage() { const navigate = useNavigate() const contributors = model?.contributors ?? [] - const busFactor = useMemo(() => computeBusFactor(contributors), [contributors]) + const organizationOptions = useMemo(() => { + return (orgs ?? []).map(org => org.login) + }, [orgs]) - const filtered = useMemo(() => - contributors.filter(c => !search || c.login.toLowerCase().includes(search.toLowerCase())), - [contributors, search]) + + + + const scopedContributors = useMemo(() => { + if (selectedOrg === 'all') { + return contributors + } + + return contributors.filter(contributor => + contributor.orgs.includes(selectedOrg) + ) + }, [contributors, selectedOrg]) + + const busFactor = useMemo( + () => computeBusFactor(scopedContributors), + [scopedContributors] + ) + const filtered = useMemo(() => { + const normalizedSearch = search.trim().toLowerCase() + + if (!normalizedSearch) { + return scopedContributors + } + + return scopedContributors.filter(contributor => + contributor.login.toLowerCase().includes(normalizedSearch) + ) + }, [scopedContributors, search]) const { sorted, sortConfig, onSort } = useSortedData(filtered, 'totalContribs', 'desc') const visible = sorted.slice(0, shown) @@ -60,10 +88,22 @@ export default function ContributorsPage() { if(loading) return if (!model) return null - const topActive = contributors.slice(0, 10).filter(c => c.freshness > 50).length - const freshPct = contributors.length ? Math.round(topActive / Math.min(10, contributors.length) * 100) : 0 - const connectors = contributors.filter(c => c.isConnector) - const crossOrg = contributors.filter(c => c.isCrossOrg) + const topActive = scopedContributors + .slice(0, 10) + .filter(c => c.freshness > 50) + .length + + const freshPct = scopedContributors.length + ? Math.round( + topActive / Math.min(10, scopedContributors.length) * 100 + ) + : 0 + + const connectors = scopedContributors.filter( + c => c.isConnector + ) + + const crossOrg = scopedContributors.filter(c => c.isCrossOrg) const riskColor = r => r === 'critical' ? 'var(--red)' : r === 'high' ? 'var(--amber)' : 'var(--green)' const riskBar = r => r === 'critical' ? '90%' : r === 'high' ? '60%' : '25%' @@ -83,7 +123,7 @@ export default function ContributorsPage() { title="Contributor Intelligence" subtitle="Analyzing contribution patterns, coverage risk, and organizational health" right={ - } @@ -245,6 +285,29 @@ export default function ContributorsPage() { placeholder="Search by username..." style={{ ...C.input, width: 220 }} /> + {organizationOptions.length > 0 && ( + + )} {filtered.length} contributors found From 177f09d50cb48ee84e8963a11ca9c0e70f4fecce Mon Sep 17 00:00:00 2001 From: jikrana Date: Mon, 17 Aug 2026 12:23:54 +0530 Subject: [PATCH 2/2] fix: show empty state for filtered contributors --- src/pages/ContributorsPage.jsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pages/ContributorsPage.jsx b/src/pages/ContributorsPage.jsx index 390521c..10298f6 100644 --- a/src/pages/ContributorsPage.jsx +++ b/src/pages/ContributorsPage.jsx @@ -312,7 +312,7 @@ export default function ContributorsPage() { {filtered.length} contributors found - {contributors?.length ? + {filtered?.length ? (<> @@ -442,10 +442,15 @@ export default function ContributorsPage() { > } - title="No contributors found" - description="We couldn't find any contributor data for this organization. " + title={search.trim() ? 'No matching contributors' : 'No contributors found'} + description={ + search.trim() + ? `No contributors match "${search}".` + : "We couldn't find any contributor data for this organization." + } buttonText="Go to Home" - onButtonClick={() => navigate('/')} /> + onButtonClick={() => navigate('/')} + /> )}