feat(assets): filter inventory by sync source
Dropdown on the Assets page (All / Wazuh / Nessus / Intune+Defender / Manual). Backend already accepts ?source=; this just wires the UI.
This commit is contained in:
@@ -17,6 +17,7 @@ export default function AssetsPage() {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [showInactive, setShowInactive] = useState(false);
|
||||
const [sourceFilter, setSourceFilter] = useState('');
|
||||
// Table sort state
|
||||
const [sortBy, setSortBy] = useState<string>('hostname');
|
||||
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');
|
||||
@@ -56,6 +57,7 @@ export default function AssetsPage() {
|
||||
const params: any = {};
|
||||
if (searchText) params.search = searchText;
|
||||
if (showInactive) params.include_inactive = true;
|
||||
if (sourceFilter) params.source = sourceFilter;
|
||||
params.sort_by = sortBy;
|
||||
params.sort_order = sortOrder;
|
||||
params.limit = pageSize;
|
||||
@@ -114,14 +116,14 @@ export default function AssetsPage() {
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [searchText, showInactive, sortBy, sortOrder, pageSize]);
|
||||
}, [searchText, showInactive, sortBy, sortOrder, pageSize, sourceFilter]);
|
||||
|
||||
// Fetch on page / filter / search change (debounced for typing).
|
||||
useEffect(() => {
|
||||
const t = setTimeout(fetchAssets, searchText ? 300 : 0);
|
||||
return () => clearTimeout(t);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [page, pageSize, sortBy, sortOrder, showInactive, searchText]);
|
||||
}, [page, pageSize, sortBy, sortOrder, showInactive, searchText, sourceFilter]);
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
||||
|
||||
@@ -332,6 +334,18 @@ export default function AssetsPage() {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<select
|
||||
value={sourceFilter}
|
||||
onChange={(e) => setSourceFilter(e.target.value)}
|
||||
title="Filter by the source that first registered the asset"
|
||||
className="rounded-sm border-0 py-1.5 pl-3 pr-8 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-vulncheck-blue sm:text-sm font-mono"
|
||||
>
|
||||
<option value="">All sources</option>
|
||||
<option value="WAZUH">Wazuh</option>
|
||||
<option value="NESSUS">Nessus</option>
|
||||
<option value="INTUNE">Intune / Defender</option>
|
||||
<option value="MANUAL">Manual</option>
|
||||
</select>
|
||||
<label className="flex items-center gap-1.5 text-xs font-mono text-gray-600 cursor-pointer whitespace-nowrap" title="INACTIVE assets are always shown (amber badge). Tick to also show operator-retired DECOMMISSIONED assets.">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
||||
Reference in New Issue
Block a user