Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@
"recharts": "^3.6.0"
},
"devDependencies": {
"@eslint/js": "^9.39.2",
"@eslint/js": "^10.0.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@vitejs/plugin-react-swc": "^4.2.2",
"eslint": "^9.39.2",
"eslint-plugin-react-hooks": "^7.0.0",
"eslint": "^10.0.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.0",
"globals": "^17.0.0",
"happy-dom": "^20.9.0",
"jsdom": "^29.1.1",
"typescript": "~6.0.0",
"typescript-eslint": "^8.52.0",
"typescript-eslint": "^8.60.0",
"vite": "^8.0.0",
"vitest": "^3"
}
Expand Down
9 changes: 1 addition & 8 deletions src/pages/repository/RepositoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ export const RepositoryPage: React.FC = () => {
const {org: orgName, repo: repoName} = useParams();
const [searchParams] = useSearchParams();

const queryTab = searchParams.get('tab') || RepoPageTabs.RESULTS;
const [currentTab, setCurrentTab] = React.useState(queryTab);
const currentTab = searchParams.get('tab') || RepoPageTabs.RESULTS;
const navigate = useNavigate();

const updateUrlTab = (tab: string) => {
Expand All @@ -47,11 +46,6 @@ export const RepositoryPage: React.FC = () => {
});
};

// Updates currentTab if query param changes
React.useEffect(() => {
setCurrentTab(queryTab);
}, [queryTab]);

const orgQuery = useQuery({
queryKey: ["getOrgByName", orgName],
enabled: !!orgName,
Expand Down Expand Up @@ -171,7 +165,6 @@ export const RepositoryPage: React.FC = () => {
activeKey={currentTab}
onChange={(key: string) => {
if (key === RepoPageTabs.CONFIGS || key === RepoPageTabs.RESULTS || key === RepoPageTabs.TRENDS) {
setCurrentTab(key);
updateUrlTab(key);
}
}}
Expand Down
36 changes: 15 additions & 21 deletions src/pages/run_result/RunResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ type StatusFilter = 'all' | 'drifted' | 'errored' | 'skipped' | 'ok';

const RunResultPage: React.FC = () => {
const [searchText, setSearchText] = React.useState('');
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>('all');
const [userSetFilter, setUserSetFilter] = React.useState<StatusFilter | null>(null);
const [drawerOpen, setDrawerOpen] = React.useState(false);
const [selectedProject, setSelectedProject] = React.useState<ProjectAnalysisRun | null>(null);
const hasInitializedFilter = React.useRef(false);

const axios = useAxios();
const {org: orgName, repo: repoName, run: runUuid} = useParams();
Expand All @@ -91,24 +90,19 @@ const RunResultPage: React.FC = () => {

const run = runQuery.data;

// Set default filter based on priority: drifted > errored > skipped > all (on initial load)
React.useEffect(() => {
if (run && !hasInitializedFilter.current) {
hasInitializedFilter.current = true;
const driftedCount = run.projects?.filter(p => p.drifted && !p.skipped_due_to_pr && p.succeeded).length ?? 0;
const erroredCount = run.projects?.filter(p => !p.succeeded).length ?? 0;
const skippedCount = run.projects?.filter(p => p.skipped_due_to_pr && p.succeeded).length ?? 0;

if (driftedCount > 0) {
setStatusFilter('drifted');
} else if (erroredCount > 0) {
setStatusFilter('errored');
} else if (skippedCount > 0) {
setStatusFilter('skipped');
}
// If no drifted, errored, or skipped projects, keep the default 'all' filter
}
// Default filter priority: drifted > errored > skipped > all. The user's explicit
// pick (userSetFilter) always wins so the auto-pick can't clobber it on refetch.
const defaultFilter = React.useMemo<StatusFilter>(() => {
if (!run) return 'all';
const driftedCount = run.projects?.filter(p => p.drifted && !p.skipped_due_to_pr && p.succeeded).length ?? 0;
if (driftedCount > 0) return 'drifted';
const erroredCount = run.projects?.filter(p => !p.succeeded).length ?? 0;
if (erroredCount > 0) return 'errored';
const skippedCount = run.projects?.filter(p => p.skipped_due_to_pr && p.succeeded).length ?? 0;
if (skippedCount > 0) return 'skipped';
return 'all';
}, [run]);
const statusFilter: StatusFilter = userSetFilter ?? defaultFilter;
const allProjects = React.useMemo(() => run?.projects ?? [], [run?.projects]);

// Filter projects based on search text and status filter
Expand Down Expand Up @@ -317,7 +311,7 @@ const RunResultPage: React.FC = () => {
/>
<Segmented
value={statusFilter}
onChange={(value) => setStatusFilter(value as StatusFilter)}
onChange={(value) => setUserSetFilter(value as StatusFilter)}
options={[
{label: `All (${counts.all})`, value: 'all'},
{label: `Drifted (${counts.drifted})`, value: 'drifted'},
Expand Down Expand Up @@ -395,7 +389,7 @@ const RunResultPage: React.FC = () => {
</Space>
}
>
<Button onClick={() => { setSearchText(''); setStatusFilter('all'); }}>
<Button onClick={() => { setSearchText(''); setUserSetFilter('all'); }}>
Clear Filters
</Button>
</Empty>
Expand Down