Skip to content

Commit 1b46625

Browse files
committed
React Admin v5 migration and performance optimizations
- Fixed SecurityEvents FilterButton error (v4 → v5 filter migration) - Added VirtualDatagrid and virtual scrolling for large datasets - Implemented enhanced caching and component memoization - Added performance testing utilities and bundle analysis
1 parent 63be2f5 commit 1b46625

File tree

15 files changed

+1191
-240
lines changed

15 files changed

+1191
-240
lines changed

CHANGELOG.md

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
- Created comprehensive caching improvements guide (docs/CACHING_IMPROVEMENTS.md)
2929
- Updated troubleshooting guide with startup script issues
3030
- Added Cache Inspector usage instructions
31-
## [0.5.0] - 2025-XX-XX *(In Planning)*
32-
33-
### Planned
34-
- **🔄 Advanced Search & Filtering**: Enhanced security event search capabilities
35-
- Multi-criteria search with date ranges, risk levels, event types
36-
- Advanced filter drawer with persistent URL state
37-
- Full-text search across security event messages
38-
- MITRE technique-based filtering
39-
- Performance-optimized database queries with proper indexing
31+
## [0.5.0-alpha] - 2025-09-12 *(✅ PHASE 1 COMPLETE - Advanced Search Frontend)*
32+
33+
### Added
34+
- **✅ Advanced Search & Filtering Frontend**: Complete UI implementation for enhanced security event search
35+
- **AdvancedSearchDrawer Component**: Comprehensive search interface with accordion-style filter sections
36+
- Multi-criteria filtering: date ranges, risk levels, event types, MITRE ATT&CK techniques
37+
- Full-text search with exact match and fuzzy search options
38+
- Numeric range sliders for confidence, correlation, burst, and anomaly scores
39+
- MITRE technique filtering with 25+ common security techniques organized by tactic
40+
- Real-time filter counting and active filter indicators
41+
- **Supporting Components**: Complete component library for advanced filtering
42+
- FullTextSearchInput with search mode toggles and help tooltips
43+
- DateRangePicker with quick presets (24h, 7d, 30d, 90d) and manual input
44+
- MultiSelectFilter with color coding and bulk operations
45+
- RangeSliderFilter with dual-thumb sliders and manual input fields
46+
- MitreTechniqueFilter with searchable technique database and tactic grouping
47+
- **State Management**: Complete React hook and API service implementation
48+
- useAdvancedSearch hook with URL synchronization for bookmarkable searches
49+
- advancedSearchService API client with error handling and export functionality
50+
- Debounced search with loading states and comprehensive error management
51+
- Export functionality for CSV, JSON, XLSX formats
52+
- **SecurityEvents Integration**: Seamless integration into existing SecurityEvents page
53+
- Custom toolbar with Advanced Search, Share, and Export buttons
54+
- Real-time search result summaries with performance metrics
55+
- URL persistence for shareable search states
56+
- Professional loading and error states with user-friendly feedback
57+
- **TypeScript Support**: Complete type definitions for all API interactions
58+
- Full type coverage for search requests, responses, and UI state
59+
- Type-safe filter conversion between UI and API formats
60+
61+
### Performance
62+
- **Database Optimization**: Enhanced SQLite performance with FTS5 full-text search
63+
- Composite indexes on security events for complex query optimization
64+
- SQLite FTS5 virtual table for high-performance text search
65+
- Database migration system with rollback support
66+
- Optimized query patterns for sub-2-second response times
67+
68+
### Code Quality
69+
- **ESLint Cleanup**: Significant codebase maintenance and optimization
70+
- Reduced ESLint warnings from 100+ to ~70 (major improvement)
71+
- Fixed critical useEffect dependency issues to prevent infinite loops
72+
- Removed unused imports and variables across component library
73+
- Enhanced TypeScript compatibility and type safety
74+
75+
### Planned (Phase 2)
76+
- **Analytics & Reporting**: Dashboard widgets and trend analysis
77+
- **Saved Searches**: Bookmark and manage frequently used search configurations
78+
- **Advanced Correlation**: Machine learning-based event correlation
4079

4180
## [0.4.0] - 2025-09-11 *(✅ COMPLETE - Phase 3 UI/UX Completion)*
4281

castellan-admin/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"scripts": {
4040
"start": "cross-env PORT=8080 react-scripts start",
4141
"build": "react-scripts build",
42+
"build:analyze": "npm run build && npx webpack-bundle-analyzer build/static/js/*.js",
4243
"test": "react-scripts test",
4344
"eject": "react-scripts eject"
4445
},
@@ -63,7 +64,8 @@
6364
"devDependencies": {
6465
"cross-env": "^10.0.0",
6566
"nth-check": "^2.1.1",
66-
"postcss": "^8.5.6"
67+
"postcss": "^8.5.6",
68+
"webpack-bundle-analyzer": "^4.10.2"
6769
},
6870
"overrides": {
6971
"nth-check": "^2.1.1",

castellan-admin/src/App.tsx

Lines changed: 72 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,86 @@
1-
import React, { useEffect } from 'react';
1+
import React, { useEffect, Suspense } from 'react';
22
import { Admin, Resource } from 'react-admin';
3+
import { Box, CircularProgress, Typography } from '@mui/material';
4+
import {
5+
Security as SecurityIcon,
6+
Assessment as ComplianceIcon,
7+
Computer as SystemIcon,
8+
BugReport as ThreatScannerIcon,
9+
Notifications as NotificationsIcon,
10+
Gavel as MitreIcon,
11+
Settings as ConfigurationIcon,
12+
Shield as YaraRulesIcon,
13+
FindInPage as YaraMatchesIcon,
14+
Timeline as TimelineIcon,
15+
} from '@mui/icons-material';
316
// Using production providers with real backend API
417
import { enhancedCastellanDataProvider } from './dataProvider/castellanDataProvider';
518
import { enhancedAuthProvider } from './auth/authProvider';
619
import { Layout } from './components/Layout';
7-
import { Dashboard } from './components/Dashboard';
820
import { initializeCachePreloader } from './utils/cachePreloader';
921
import './utils/cacheInspector'; // Load cache debugging tools
22+
import './utils/performanceTesting'; // Load performance testing suite
1023

11-
// Import resources
12-
import {
13-
SecurityEventList,
14-
SecurityEventShow,
15-
SecurityEventEdit,
16-
SecurityEventCreate,
17-
} from './resources/SecurityEvents'; // Reverted to original for stability
18-
import {
19-
SystemStatusList,
20-
SystemStatusShow,
21-
} from './resources/SystemStatus';
24+
// Lazy load Dashboard for better performance
25+
const Dashboard = React.lazy(() => import('./components/Dashboard').then(module => ({ default: module.Dashboard })));
2226

23-
// Import functional compliance reports components
24-
import {
25-
ComplianceReportList,
26-
ComplianceReportShow,
27-
ComplianceReportCreate,
28-
} from './resources/ComplianceReports';
27+
// Lazy-loaded resource imports for better performance and code splitting
28+
const SecurityEventList = React.lazy(() => import('./resources/SecurityEvents').then(module => ({ default: module.SecurityEventList })));
29+
const SecurityEventShow = React.lazy(() => import('./resources/SecurityEvents').then(module => ({ default: module.SecurityEventShow })));
30+
const SecurityEventEdit = React.lazy(() => import('./resources/SecurityEvents').then(module => ({ default: module.SecurityEventEdit })));
31+
const SecurityEventCreate = React.lazy(() => import('./resources/SecurityEvents').then(module => ({ default: module.SecurityEventCreate })));
2932

30-
// Import threat scanner resource
31-
import {
32-
ThreatScannerList,
33-
ThreatScannerShow,
34-
} from './resources/ThreatScanner';
33+
const SystemStatusList = React.lazy(() => import('./resources/SystemStatus').then(module => ({ default: module.SystemStatusList })));
34+
const SystemStatusShow = React.lazy(() => import('./resources/SystemStatus').then(module => ({ default: module.SystemStatusShow })));
3535

36-
// Import MITRE techniques resource
37-
import {
38-
MitreTechniquesList,
39-
MitreTechniquesShow,
40-
} from './resources/MitreTechniques';
36+
const ComplianceReportList = React.lazy(() => import('./resources/ComplianceReports').then(module => ({ default: module.ComplianceReportList })));
37+
const ComplianceReportShow = React.lazy(() => import('./resources/ComplianceReports').then(module => ({ default: module.ComplianceReportShow })));
38+
const ComplianceReportCreate = React.lazy(() => import('./resources/ComplianceReports').then(module => ({ default: module.ComplianceReportCreate })));
4139

42-
// Import YARA resources
43-
import {
44-
YaraRulesList,
45-
YaraRulesShow,
46-
YaraRulesCreate,
47-
YaraRulesEdit,
48-
} from './resources/YaraRules';
40+
const ThreatScannerList = React.lazy(() => import('./resources/ThreatScanner').then(module => ({ default: module.ThreatScannerList })));
41+
const ThreatScannerShow = React.lazy(() => import('./resources/ThreatScanner').then(module => ({ default: module.ThreatScannerShow })));
4942

50-
import {
51-
YaraMatchesList,
52-
YaraMatchesShow,
53-
} from './resources/YaraMatches';
43+
const MitreTechniquesList = React.lazy(() => import('./resources/MitreTechniques').then(module => ({ default: module.MitreTechniquesList })));
44+
const MitreTechniquesShow = React.lazy(() => import('./resources/MitreTechniques').then(module => ({ default: module.MitreTechniquesShow })));
5445

55-
// Import timeline resource
56-
import {
57-
TimelineList,
58-
} from './resources/Timeline';
46+
const YaraRulesList = React.lazy(() => import('./resources/YaraRules').then(module => ({ default: module.YaraRulesList })));
47+
const YaraRulesShow = React.lazy(() => import('./resources/YaraRules').then(module => ({ default: module.YaraRulesShow })));
48+
const YaraRulesCreate = React.lazy(() => import('./resources/YaraRules').then(module => ({ default: module.YaraRulesCreate })));
49+
const YaraRulesEdit = React.lazy(() => import('./resources/YaraRules').then(module => ({ default: module.YaraRulesEdit })));
5950

60-
// Import notification settings resource
61-
import {
62-
NotificationSettingsList,
63-
NotificationSettingsShow,
64-
NotificationSettingsCreate,
65-
NotificationSettingsEdit,
66-
} from './resources/NotificationSettings';
51+
const YaraMatchesList = React.lazy(() => import('./resources/YaraMatches').then(module => ({ default: module.YaraMatchesList })));
52+
const YaraMatchesShow = React.lazy(() => import('./resources/YaraMatches').then(module => ({ default: module.YaraMatchesShow })));
6753

68-
// Import configuration resource
69-
import {
70-
ConfigurationList,
71-
ConfigurationShow,
72-
} from './resources/Configuration';
54+
const TimelineList = React.lazy(() => import('./resources/Timeline').then(module => ({ default: module.TimelineList })));
55+
56+
const NotificationSettingsList = React.lazy(() => import('./resources/NotificationSettings').then(module => ({ default: module.NotificationSettingsList })));
57+
const NotificationSettingsShow = React.lazy(() => import('./resources/NotificationSettings').then(module => ({ default: module.NotificationSettingsShow })));
58+
const NotificationSettingsCreate = React.lazy(() => import('./resources/NotificationSettings').then(module => ({ default: module.NotificationSettingsCreate })));
59+
const NotificationSettingsEdit = React.lazy(() => import('./resources/NotificationSettings').then(module => ({ default: module.NotificationSettingsEdit })));
60+
61+
const ConfigurationList = React.lazy(() => import('./resources/Configuration').then(module => ({ default: module.ConfigurationList })));
62+
const ConfigurationShow = React.lazy(() => import('./resources/Configuration').then(module => ({ default: module.ConfigurationShow })));
7363

7464
// CastellanProFree - No edition detection needed
7565

76-
// Import Material-UI icons for resources
77-
import {
78-
Security as SecurityIcon,
79-
Assessment as ComplianceIcon,
80-
Computer as SystemIcon,
81-
BugReport as ThreatScannerIcon,
82-
Notifications as NotificationsIcon,
83-
Gavel as MitreIcon,
84-
Settings as ConfigurationIcon,
85-
Shield as YaraRulesIcon,
86-
FindInPage as YaraMatchesIcon,
87-
Timeline as TimelineIcon,
88-
} from '@mui/icons-material';
66+
// Loading fallback component for lazy-loaded resources
67+
const LoadingFallback = () => (
68+
<Box
69+
sx={{
70+
display: 'flex',
71+
flexDirection: 'column',
72+
alignItems: 'center',
73+
justifyContent: 'center',
74+
height: '200px',
75+
gap: 2
76+
}}
77+
>
78+
<CircularProgress size={40} />
79+
<Typography variant="body2" color="textSecondary">
80+
Loading component...
81+
</Typography>
82+
</Box>
83+
);
8984

9085
const App = () => {
9186
// Initialize cache preloader for immediate data availability
@@ -94,12 +89,13 @@ const App = () => {
9489
}, []);
9590

9691
return (
97-
<Admin
98-
dataProvider={enhancedCastellanDataProvider}
99-
authProvider={enhancedAuthProvider}
100-
layout={Layout}
101-
dashboard={Dashboard}
102-
>
92+
<Suspense fallback={<LoadingFallback />}>
93+
<Admin
94+
dataProvider={enhancedCastellanDataProvider}
95+
authProvider={enhancedAuthProvider}
96+
layout={Layout}
97+
dashboard={Dashboard}
98+
>
10399
{/* Security Events Resource - Available in CastellanProFree */}
104100
<Resource
105101
name="security-events"
@@ -196,6 +192,7 @@ const App = () => {
196192
recordRepresentation={() => 'System Configuration'}
197193
/>
198194
</Admin>
195+
</Suspense>
199196
);
200197
};
201198

castellan-admin/src/components/Dashboard.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ interface ThreatScan {
103103
[key: string]: any;
104104
}
105105

106-
export const Dashboard = () => {
106+
const Dashboard = React.memo(() => {
107107
const [timeRange, setTimeRange] = useState('24h');
108108
const [refreshing, setRefreshing] = useState(false);
109109
const [lastRefresh, setLastRefresh] = useState(new Date());
@@ -1157,4 +1157,6 @@ export const Dashboard = () => {
11571157
</Box>
11581158
</Box>
11591159
);
1160-
};
1160+
});
1161+
1162+
export { Dashboard };

0 commit comments

Comments
 (0)