/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
import { FunctionComponent } from 'react';
import { Box, Typography, Pagination, CircularProgress } from '@mui/material';
import { ScanCard } from '../scan-card';
import { SearchToolbar, CountsToolbar } from '../toolbars';
import { AutoRefresh } from '../common';
import { useQuarantinedTab } from '../../../hooks/scan-admin';
import { useScanContext } from '../../../context/scan-admin';
import { useTheme } from '@mui/material/styles';
/**
* Quarantined tab component that displays extensions flagged by security scans.
* Uses the useQuarantinedTab hook to consume context.
*/
export const QuarantinedTabContent: FunctionComponent = () => {
const theme = useTheme();
const { state } = useScanContext();
const {
scans,
isLoading,
lastRefreshed,
autoRefresh,
onAutoRefreshChange,
totalCount,
search,
globalFilters,
quarantineFilters,
pagination,
selection,
toggleCheck,
selectAll,
deselectAll,
isAllSelected,
bulkActions,
hasThreatScanners,
} = useQuarantinedTab();
// Calculate allowed/blocked/needs review counts from scanCounts
const allowedCount = state.scanCounts?.ALLOWED ?? 0;
const blockedCount = state.scanCounts?.BLOCKED ?? 0;
const needsReviewCount = state.scanCounts?.NEEDS_REVIEW ?? 0;
const handleSelectAllChange = (checked: boolean) => {
if (checked) {
selectAll();
} else {
deselectAll();
}
};
return (
<>
({
label: scanner,
value: scanner,
checked: quarantineFilters.threatScannerFilters.has(scanner),
}))}
onFilterOptionToggle={quarantineFilters.toggleThreatScanner}
dateRange={globalFilters.dateRange}
onDateRangeChange={globalFilters.setDateRange}
enforcement={globalFilters.enforcement}
onEnforcementChange={globalFilters.setEnforcement}
/>
{isLoading ? (
) : (!hasThreatScanners || scans.length === 0) ? (
No quarantined extensions
Extensions flagged by security scans will appear here
) : (
scans.map((scan) => {
// Only show checkbox for scans that need review:
// - No admin decision yet AND
// - Has at least one enforced threat (unenforced threats don't require review)
const hasEnforcedThreat = scan.threats.some(t => t.enforcedFlag);
const needsReview = !scan.adminDecision?.decision && hasEnforcedThreat;
return (
);
})
)}
{pagination.totalPages > 1 && (
pagination.goToPage(page - 1)}
disabled={isLoading}
color='secondary'
size='large'
showFirstButton
showLastButton
/>
)}
>
);
};