Skip to content

Commit 8d2c7ab

Browse files
authored
Merge pull request #13 from d3mocide/refactor/frontend-phase1-15579225299763484055
Refactor Frontend Core (MapContainer & Sidebar)
2 parents 3a422a7 + 9efb7d9 commit 8d2c7ab

20 files changed

Lines changed: 2168 additions & 2150 deletions

REFACTORING_REPORT.md

Lines changed: 56 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,28 @@ MeshRF is a full-stack RF propagation and link analysis application for LoRa mes
2424

2525
## Files by Size (All Files ≥ 200 Lines)
2626

27-
| Rank | File | Lines | Priority |
28-
|------|------|-------|----------|
29-
| 1 | `src/components/Map/MapContainer.jsx` | 1173 | CRITICAL |
30-
| 2 | `src/components/Layout/Sidebar.jsx` | 829 | CRITICAL |
31-
| 3 | `src/components/Map/LinkAnalysisPanel.jsx` | 643 | HIGH |
32-
| 4 | `src/components/Map/UI/SiteAnalysisResultsPanel.jsx` | 609 | HIGH |
33-
| 5 | `src/components/Map/OptimizationLayer.jsx` | 517 | HIGH |
34-
| 6 | `rf-engine/server.py` | 475 | HIGH |
35-
| 7 | `src/components/Map/UI/NodeManager.jsx` | 440 | MEDIUM |
36-
| 8 | `src/components/Map/OptimizationResultsPanel.jsx` | 435 | MEDIUM |
37-
| 9 | `src/components/Map/LinkLayer.jsx` | 429 | MEDIUM |
38-
| 10 | `rf-engine/tasks/viewshed.py` | 398 | MEDIUM |
39-
| 11 | `src/utils/rfMath.js` | 366 | LOW |
40-
| 12 | `src/components/Map/BatchNodesPanel.jsx` | 354 | MEDIUM |
41-
| 13 | `src/hooks/useViewshedTool.js` | 343 | MEDIUM |
42-
| 14 | `rf-engine/tile_manager.py` | 334 | MEDIUM |
43-
| 15 | `src/components/Map/BatchProcessing.jsx` | 321 | LOW |
44-
| 16 | `src/components/Map/UI/GuidanceOverlays.jsx` | 318 | LOW |
45-
| 17 | `src/context/RFContext.jsx` | 307 | MEDIUM |
46-
| 18 | `src/hooks/useRFCoverageTool.js` | 277 | LOW |
47-
| 19 | `src/components/Map/Controls/ViewshedControl.jsx` | 225 | LOW |
48-
| 20 | `rf-engine/rf_physics.py` | 221 | LOW |
27+
| Rank | File | Lines | Priority | Status |
28+
|------|------|-------|----------|--------|
29+
| 1 | `src/components/Map/MapContainer.jsx` | 1173 | CRITICAL | **REFACTORED** |
30+
| 2 | `src/components/Layout/Sidebar.jsx` | 829 | CRITICAL | **REFACTORED** |
31+
| 3 | `src/components/Map/LinkAnalysisPanel.jsx` | 643 | HIGH | Pending |
32+
| 4 | `src/components/Map/UI/SiteAnalysisResultsPanel.jsx` | 609 | HIGH | Pending |
33+
| 5 | `src/components/Map/OptimizationLayer.jsx` | 517 | HIGH | Pending |
34+
| 6 | `rf-engine/server.py` | 475 | HIGH | Pending |
35+
| 7 | `src/components/Map/UI/NodeManager.jsx` | 440 | MEDIUM | Pending |
36+
| 8 | `src/components/Map/OptimizationResultsPanel.jsx` | 435 | MEDIUM | Pending |
37+
| 9 | `src/components/Map/LinkLayer.jsx` | 429 | MEDIUM | Pending |
38+
| 10 | `rf-engine/tasks/viewshed.py` | 398 | MEDIUM | Pending |
39+
| 11 | `src/utils/rfMath.js` | 366 | LOW | Pending |
40+
| 12 | `src/components/Map/BatchNodesPanel.jsx` | 354 | MEDIUM | Pending |
41+
| 13 | `src/hooks/useViewshedTool.js` | 343 | MEDIUM | Pending |
42+
| 14 | `rf-engine/tile_manager.py` | 334 | MEDIUM | Pending |
43+
| 15 | `src/components/Map/BatchProcessing.jsx` | 321 | LOW | Pending |
44+
| 16 | `src/components/Map/UI/GuidanceOverlays.jsx` | 318 | LOW | Pending |
45+
| 17 | `src/context/RFContext.jsx` | 307 | MEDIUM | **REFACTORED** (Facade) |
46+
| 18 | `src/hooks/useRFCoverageTool.js` | 277 | LOW | Pending |
47+
| 19 | `src/components/Map/Controls/ViewshedControl.jsx` | 225 | LOW | Pending |
48+
| 20 | `rf-engine/rf_physics.py` | 221 | LOW | Pending |
4949

5050
---
5151

@@ -57,62 +57,29 @@ MeshRF is a full-stack RF propagation and link analysis application for LoRa mes
5757

5858
#### 1. `src/components/Map/MapContainer.jsx` — 1173 lines
5959

60-
**What it does**: The main map orchestrator. Manages all map layers, tool modes, user interactions, and coordinates between Leaflet, WASM workers, and React state.
61-
62-
**Why it's a problem**: At 1173 lines it violates single-responsibility badly. It contains map config, event handlers, layer rendering logic, tool state machines, and full JSX output — all in one file. Changes to any one tool risk breaking others.
63-
64-
**Logical sections**:
65-
1. Imports and SVG icon definitions (lines 1–50)
66-
2. Map initialization and state setup (lines 60–150)
67-
3. Tool event handlers and callbacks (lines 160–350)
68-
4. Layer rendering conditions (lines 360–600)
69-
5. Main JSX render (lines 610–1173)
70-
71-
**Suggested split**:
72-
73-
```
74-
src/components/Map/
75-
├── MapContainer.jsx (~200 lines) — core orchestration only
76-
├── config/
77-
│ └── MapConfig.js (~50 lines) — Leaflet tile/options config
78-
├── hooks/
79-
│ └── useMapEventHandlers.js (~150 lines) — click, drag, keypress handlers
80-
├── layers/
81-
│ ├── ViewshedLayerManager.jsx (~150 lines)
82-
│ ├── CoverageLayerManager.jsx (~150 lines)
83-
│ ├── OptimizationLayerManager.jsx (~150 lines)
84-
│ └── LinkLayerManager.jsx (~150 lines)
85-
```
86-
87-
**Target**: MapContainer.jsx shrinks to ~200 lines of pure composition.
60+
**Status**: Refactored (Phase 1b)
61+
- **Extracted Managers**:
62+
- `LinkLayerManager.jsx`: Handles Link Layer and Panel.
63+
- `ViewshedLayerManager.jsx`: Handles Viewshed Layer, Marker, Control.
64+
- `CoverageLayerManager.jsx`: Handles RF Coverage Layer, Marker, Recalc Logic.
65+
- `OptimizationLayerManager.jsx`: Handles Optimization Layer, Multi-site clicks, Simulation results.
66+
- **Extracted Hooks**:
67+
- `useLinkTool.js`: Manages link state (nodes, stats, locking).
68+
- `useMapEventHandlers.js`: Manages map click/interaction logic.
69+
- **Result**: `MapContainer.jsx` is now a high-level orchestrator focusing on coordinating tools and layers.
8870

8971
---
9072

9173
#### 2. `src/components/Layout/Sidebar.jsx` — 829 lines
9274

93-
**What it does**: Configuration panel for RF hardware, environment, LoRa band settings, batch processing, and map options.
94-
95-
**Why it's a problem**: A single component rendering 6 logically distinct panels. Each panel has its own state, event handlers, and JSX. Changes to hardware settings risk breaking environment settings and vice versa.
96-
97-
**Logical sections**:
98-
1. `CollapsibleSection` helper component (lines 6–57)
99-
2. State and hooks (lines 59–166)
100-
3. Hardware configuration (lines 300–535)
101-
4. Environment settings (lines 537–625)
102-
5. LoRa band settings (lines 627–707)
103-
6. Batch + settings footer (lines 711–829)
104-
105-
**Suggested split**:
106-
107-
```
108-
src/components/Layout/
109-
├── Sidebar.jsx (~150 lines) — layout and section composition
110-
└── sections/
111-
├── HardwareSection.jsx (~200 lines) — device, antenna, power, cable
112-
├── EnvironmentSection.jsx (~150 lines) — ground type, climate, k-factor
113-
├── LoRaBandSection.jsx (~150 lines) — frequency, BW, SF, CR
114-
└── CollapsibleSection.jsx (~60 lines) — reusable wrapper
115-
```
75+
**Status**: Refactored (Phase 1a)
76+
- **Extracted Sections**:
77+
- `HardwareSection.jsx`: Device, Antenna, Power, Cable settings.
78+
- `EnvironmentSection.jsx`: ITM params (Ground, Climate, K-Factor).
79+
- `LoRaBandSection.jsx`: Radio settings (Freq, BW, SF, CR).
80+
- `SettingsSection.jsx`: Global settings (Units, Map Style).
81+
- **Reusable Component**: `CollapsibleSection.jsx`.
82+
- **Result**: `Sidebar.jsx` is now a clean layout container composing these sections.
11683

11784
---
11885

@@ -307,18 +274,14 @@ rf-engine/
307274

308275
#### 12. `src/context/RFContext.jsx` — 307 lines
309276

310-
**What it does**: Central React Context holding all RF configuration state — hardware, radio, environment, and UI state — shared across all components.
311-
312-
**Suggested split**:
313-
314-
```
315-
src/context/
316-
├── RFContext.jsx (~80 lines) — root provider composing all contexts
317-
├── HardwareContext.jsx (~80 lines) — Node A/B antenna/device config
318-
├── EnvironmentContext.jsx (~60 lines) — ITM model parameters
319-
├── RadioContext.jsx (~60 lines) — LoRa band settings
320-
└── UIContext.jsx (~60 lines) — tool mode, sidebar, edit mode
321-
```
277+
**Status**: Refactored (Phase 1)
278+
- Implemented **Facade Strategy**:
279+
- `UIContext.jsx`: UI state.
280+
- `HardwareContext.jsx`: Node configs.
281+
- `EnvironmentContext.jsx`: ITM params.
282+
- `RadioContext.jsx`: LoRa settings.
283+
- `RFContext.jsx`: Wrapper that composes these contexts and exports a unified hook.
284+
- **Result**: Clean separation of concerns while maintaining backward compatibility.
322285

323286
---
324287

@@ -350,21 +313,17 @@ src/hooks/
350313

351314
---
352315

353-
## Recommended Refactoring Phases
354-
355-
### Phase 1 — Frontend Core (Highest ROI)
356-
357-
Target the two largest files to eliminate the "big ball of mud" problem:
316+
## Refactoring Progress
358317

359-
1. **MapContainer.jsx** (1173 → ~200 lines): Extract 4 layer manager components and a `useMapEventHandlers` hook. This is the highest-risk file for accidental regressions.
360-
2. **Sidebar.jsx** (829 → ~150 lines): Extract 3 section components and the `CollapsibleSection` helper.
318+
### Phase 1 — Frontend Core (COMPLETED)
361319

362-
**Expected effort**: 3–5 days
363-
**Risk**: Medium — both files have complex state wiring; test thoroughly after each split.
320+
1. **MapContainer.jsx** (1173 → ~250 lines): Refactored into Layer Managers (`LinkLayerManager`, `ViewshedLayerManager`, `CoverageLayerManager`, `OptimizationLayerManager`) and Hooks (`useLinkTool`, `useMapEventHandlers`).
321+
2. **Sidebar.jsx** (829 → ~200 lines): Refactored into Sections (`HardwareSection`, `EnvironmentSection`, `LoRaBandSection`, `SettingsSection`).
322+
3. **RFContext.jsx**: Refactored using Facade pattern (`UIContext`, `HardwareContext`, `EnvironmentContext`, `RadioContext`).
364323

365324
---
366325

367-
### Phase 2 — Backend API Structure
326+
### Phase 2 — Backend API Structure (NEXT)
368327

369328
Reorganize `server.py` into FastAPI routers — this is low-risk since Python imports are explicit and easy to verify:
370329

@@ -383,13 +342,13 @@ Reorganize `server.py` into FastAPI routers — this is low-risk since Python im
383342
7. **viewshed.py** (398 → ~120 lines): Separate Celery task definition from processing logic and image utilities.
384343

385344
**Expected effort**: 2–3 days
386-
**Risk**: Medium — analysis panels have complex prop drilling; consider whether this is a good time to introduce a data-fetching pattern (e.g., React Query).
345+
**Risk**: Medium — analysis panels have complex prop drilling.
387346

388347
---
389348

390349
### Phase 4 — State Management
391350

392-
8. **RFContext.jsx** (307 → ~80 lines each): Split into 4 focused contexts. This change affects nearly every component, so coordinate with Phase 1 changes.
351+
8. **RFContext.jsx** (307 → ~80 lines each): Split into 4 focused contexts. This change affects nearly every component, so coordinate with Phase 1 changes. (ALREADY COMPLETED IN PHASE 1 VIA FACADE)
393352

394353
**Expected effort**: 1–2 days
395354
**Risk**: High — touches every component. Do this last and test end-to-end.
@@ -402,17 +361,3 @@ Reorganize `server.py` into FastAPI routers — this is low-risk since Python im
402361

403362
**Expected effort**: 2–3 days
404363
**Risk**: Low.
405-
406-
---
407-
408-
## General Recommendations
409-
410-
1. **Extract algorithms from UI**: Several components contain inline algorithms (BFS in `SiteAnalysisResultsPanel`, diffraction in `LinkAnalysisPanel`). Move all pure logic to `src/utils/` or `rf-engine/utils/` — this makes testing significantly easier.
411-
412-
2. **Introduce a service layer**: API calls are scattered across hooks and components. Centralizing them in `src/services/rfService.js` and `src/services/elevationService.js` would decouple components from fetch logic.
413-
414-
3. **Colocate tests**: As files are split, add unit tests for extracted utility functions. Pure math functions like those in `rfMath.js` and `rf_physics.py` are ideal first targets.
415-
416-
4. **Avoid premature abstraction**: Not every file needs splitting. The LOW-priority files (≤225 lines) are generally well-scoped — leave them unless they grow.
417-
418-
5. **Incremental approach**: Refactor one file at a time. Avoid large "big bang" refactors that make code review difficult and increase regression risk.

0 commit comments

Comments
 (0)