ORSANCO Flows - Frontend Design Document
1. Overview
This document outlines the frontend design for the ORSANCO River Flows system upgrade. The primary goals are to improve data query capabilities, enhance map navigation, and provide a dedicated bulk download interface for long-term flow data analysis.
1.1 Key Objectives
- Enable multi-parameter queries (flow, velocity, stage) over extended time periods (2009-present)
- Improve station search and map navigation functionality
- Create a dedicated bulk download page separate from visualization
- Implement token-based API authentication
- Enhance user experience with Material-UI components
- Maintain consistent design patterns across the application
1.2 Technology Stack
- Framework: React
- UI Library: Material-UI (MUI)
- Map Library: Current implementation
- State Management: React Context API
- API Communication: REST with token authentication
- Hosting: Azure Static Web App
2. Application Structure
2.1 Page Architecture
The application consists of four main pages:
/
├── Overview (existing - informational)
├── Map (enhanced)
├── Daily Flows (enhanced)
└── Bulk Download (new)
2.2 Navigation Flow
3. Page Designs
3.1 Overview Page
Status: No changes required
Keep existing informational content about the system.
3.2 Map Page (Enhanced)
3.2.1 Layout
┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [🔍] [📍] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ │
│ │
│ MAP VIEWPORT │
│ (Current Implementation) │
│ │
│ │
│ │
└────────────────────────────────────────────────────────────┘
3.2.2 Top Action Bar
The action bar sits in the top-right corner with the following items:
Site-Wide Actions:
- Theme Toggle (🌓): Switch between light/dark mode
- Settings (⚙️): Application settings modal
Page-Specific Actions:
- Search for River Station (🔍): Opens station search modal
- Search for Location (📍): Opens geocoder search modal
3.2.3 Search for River Station Modal
┌──────────────────────────────────────────────────┐
│ Search for River Station [X] │
├──────────────────────────────────────────────────┤
│ │
│ River │
│ [Select River ▼] │
│ │
│ Reach │
│ [Select Reach ▼] │
│ │
│ Station │
│ [Search stations... ] 🔍 │
│ (Autocomplete with dropdown) │
│ │
│ [Cancel] [Go] │
└──────────────────────────────────────────────────┘
Behavior:
- River dropdown populates from
/api/rivers/ - Selecting river filters reach dropdown
- Station autocomplete searches within selected reach
- "Go" button zooms map to selected station
- Closes modal automatically after navigation
3.2.4 Search for Location Modal
┌──────────────────────────────────────────────────┐
│ Search for Location [X] │
├──────────────────────────────────────────────────┤
│ │
│ Enter city, address, or coordinates │
│ [Type location... ] 🔍 │
│ │
│ Suggestions: │
│ • Cincinnati, OH │
│ • Owensboro, KY │
│ • Louisville, KY │
│ │
│ [Cancel] [Go] │
└──────────────────────────────────────────────────┘
Behavior:
- Uses geocoding service to convert text to coordinates
- Zooms map to resolved location
- Shows error message if location not found
3.2.5 Map Interaction
Station Click Behavior:
- User clicks station marker on map
- Station is marked as "active" (highlighted)
- Active station ID is stored in context
- Popup shows basic station info with "View Data" button
- "View Data" navigates to Daily Flows page with station pre-selected
Camera State:
- Map remembers camera position (zoom level and center) when navigating away
- Returns to same position when user returns to Map page
- Resets to default only on app refresh or explicit reset
3.3 Daily Flows Page (Enhanced)
3.3.1 Layout
┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ Daily Flows │
├────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Station Selection │ │
│ │ ┌────────────┬────────────┬──────────────────────┐ │ │
│ │ │River │Reach │Station │ │ │
│ │ │[Select ▼] │[Select ▼] │[Search... ] 🔍 │ │ │
│ │ └────────────┴────────────┴──────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Date Range │ │
│ │ Start Date: [📅 11/01/2024] Days: [30] │ │
│ │ [Load Data] │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ FLOW CHART (Min/Avg/Max) │ │
│ │ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Download: [CSV] [JSON] │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
3.3.2 Station Selection Component
Tiered Dropdown System:
- River Dropdown: Select from all available rivers
- Reach Dropdown: Filtered by selected river
- Station Autocomplete: Search/filter stations within reach, with optional multi-select support
Data Flow:
Default Behavior:
- If user arrives from Map page with active station, pre-populate all three fields
- Station selection persists in context until changed
- Changing river resets reach and station
- Changing reach resets station only
3.3.3 Date Range Controls
- Start Date: MUI DatePicker component
- Number of Days: Numeric input (default: 30, max: 365 for this page)
- Load Data: Button to fetch and render chart
Current Limitation:
- This page maintains the current limitation of ~1 year max
- For longer periods, users should use Bulk Download page
3.4 Bulk Download Page (New)
This is the primary addition to support extended multi-parameter queries without visualization overhead.
3.4.1 Layout Overview
┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ Bulk Data Download │
├──────────────────────────────────────────────────────────┬─┤
│ ┌─────────────────────┬─────────────────────────────┐ │ │
│ │ SINGLE STATION │ MULTIPLE STATIONS (FID) │ │ │
│ │ SELECTION (Left) │ SELECTION (Right) │ │Q│
│ │ │ │ │U│
│ │ │ │ │E│
│ │ │ │ │R│
│ │ │ │ │Y│
│ │ │ │ │ │
│ │ │ │ │H│
│ │ │ │ │I│
│ │ │ │ │S│
│ │ │ │ │T│
│ │ │ │ │O│
│ │ │ │ │R│
│ │ │ │ │Y│
│ └─────────────────────┴─────────────────────────────┘ │ │
│ ┌──────────────────────────────────────────────────┐ │ │
│ │ QUERY PARAMETERS (Bottom) │ │ │
│ └──────────────────────────────────────────────────┘ │ │
└──────────────────────────────────────────────────────────┴─┘
3.4.2 Detailed Layout
┌────────────────────────────────────────────────────────────────────────────────┐
│ Bulk Data Download │
├──────────────────────────────────────────────┬─────────────────────────────────┤
│ SINGLE STATION SELECTION │ QUERY HISTORY │
│ ┌──────────────────────────────┐ │ ┌─────────────────────────────┐ │
│ │ River │ │ │ 🟢 Complete │ │
│ │ [Select River ▼] │ │ │ Station 699.5 │ │
│ │ │ │ │ 2009-2024, All params │ │
│ │ Reach │ │ │ [Download] [Delete] │ │
│ │ [Select Reach ▼] │ │ ├─────────────────────────────┤ │
│ │ │ │ │ 🔵 Processing... │ │
│ │ Station(s) │ │ │ Stations 700.0-705.5 │ │
│ │ [Search stations... ] 🔍 │ │ │ 2020-2024, Flow only │ │
│ │ (Autocomplete w/ multi) │ │ │ │ │
│ │ │ │ ├─────────────────────────────┤ │
│ │ Selected: Station 699.5 │ │ │ ⏱️ Queued │ │
│ │ Station 700.2 │ │ │ Station 606.0 │ │
│ └──────────────────────────────┘ │ │ 2009-2024, All params │ │
│ │ └─────────────────────────────┘ │
│ OR │ │
│ │ Storage Used: 234 MB / 10 GB │
│ MULTIPLE STATIONS (FID) │ [Clear All Completed] [Refresh] │
│ ┌──────────────────────────────┐ │ │
│ │ Enter comma-separated FIDs │ └─────────────────────────────────┘
│ │ │
│ │ [1, 5, 23, 45, 67, ...] │
│ │ │
│ │ │
│ │ │
│ └──────────────────────────────┘
├────────────────────────────────────────────────────────────────────────────────┤
│ QUERY PARAMETERS │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ Date Range │ │
│ │ Start: [📅 01/01/2009] End: [📅 11/11/2024] │ │
│ │ │ │
│ │ Parameters │ │
│ │ ☑ Flow ☑ Velocity ☑ Stage │ │
│ │ │ │
│ │ Aggregation │ │
│ │ ○ None (Raw 15-min data) │ │
│ │ ● Daily ( ☑ Min ☑ Max ☑ Average ) │ │
│ │ ○ Hourly ( ☐ Min ☐ Max ☐ Average ) │ │
│ │ │ │
│ │ [Submit Query] │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘
3.4.3 Component Breakdown
Left Panel: Single Station Selection
River Dropdown
- Fetches rivers from
/api/rivers/ - MUI Select component
- On change: Clear reach and station selections
Reach Dropdown
- Filtered based on selected river
- Fetches from
/api/reaches/?river={riverId} - On change: Clear station selection
Station Autocomplete (Multi-Select)
- MUI Autocomplete with
multiple={true} - Searches within selected reach
- As user types, filters matching stations by name or river mile
- Selected stations appear as chips below the input
- Each chip has an X to remove
Center Panel: Multiple Stations (FID List)
FID Text Input
- Large text area for comma-separated FIDs
- Example placeholder: "1, 5, 23, 45, 67, 89, ..."
- Validates on blur: checks if FIDs exist
- Shows error if any FID is invalid
- Use case: User has pre-identified list of stations from external analysis
Mutual Exclusivity:
- If user enters FIDs, disable left panel (single station selection)
- If user selects stations on left, disable FID input
- Clear button to reset and enable both sides
Right Panel: Query History
Query List Items
Each query shows:
- Status indicator (colored circle)
- 🟢 Green: Complete
- 🔵 Blue: Processing
- ⏱️ Gray: Queued
- 🔴 Red: Failed
- Station name(s) or count
- Date range summary
- Parameters requested
- Action buttons: [Download][Delete]
Status Display:
- Auto-refreshes every 10 seconds if any query is Queued/Processing
- Manual refresh button available
- "Clear All Completed" button removes all successful downloads
Storage Gauge:
- Shows total storage used by cached queries
- Example: "234 MB / 10 GB"
- Visual progress bar
- Queries auto-delete after 30 days OR manual delete
Bottom Panel: Query Parameters
Date Range
- Start Date: MUI DatePicker (earliest available: 2009)
- End Date: MUI DatePicker (latest: today)
- No hard limit on range (can request full 2009-2024)
Parameters Checkboxes
- Flow, Velocity, Stage
- Must select at least one
- All three selected by default
Aggregation Radio + Checkboxes
- None: Raw 15-minute increment data
- Daily: Aggregated by day with sub-options
- Min, Max, Average (multiple can be selected)
- Hourly: Aggregated by hour with sub-options
- Min, Max, Average (multiple can be selected)
Submit Query Button
- Validates inputs
- Sends POST request to
/api/bulk-download/ - Adds new query to Query History with "Queued" status
- Disables button while submitting
3.4.4 User Flows
Flow 1: Single Station Query
Flow 2: Multiple Station Query (FID List)
3.4.5 CSV Output Format
File Naming Convention:
For single station:
20090101_20241111_StationName699-5.csv
For multiple stations (in ZIP):
20090101_20241111_Stations_Multiple.zip
├── 20090101_20241111_Station699-5.csv
├── 20090101_20241111_Station700-2.csv
└── 20090101_20241111_Station705-0.csv
CSV Structure (Wide Format):
Example with Daily aggregation and all parameters:
DateTime,Flow_Min,Flow_Max,Flow_Avg,Velocity_Min,Velocity_Max,Velocity_Avg,Stage_Min,Stage_Max,Stage_Avg
2024-01-01,12500,15300,13800,2.3,3.1,2.7,450.2,451.8,450.9
2024-01-02,13200,16100,14500,2.5,3.3,2.9,451.0,452.5,451.6
Example with raw data and only Flow parameter:
DateTime,Flow
2024-01-01 00:00:00,12500
2024-01-01 00:15:00,12550
2024-01-01 00:30:00,12600
ZIP Compression:
- Individual CSVs > 50MB are auto-zipped
- Multiple station queries are always zipped
- ZIP file size displayed in Query History
4. Component Library
4.1 Reusable Components
StationSelector
Props:
river: Selected river IDreach: Selected reach IDstation: Selected station ID(s)multiSelect: Boolean (default: false)onChange: Callback function
Behavior:
- Tiered dropdowns for River → Reach → Station
- Autocomplete for station search
- Optional multi-select support
QueryHistoryCard
Props:
query: Query object {id, status, stations, dateRange, parameters, downloadUrl}onDownload: CallbackonDelete: Callback
Displays:
- Status indicator
- Query summary
- Action buttons
AggregationSelector
Props:
aggregationType: "none" | "daily" | "hourly"aggregators: ["min", "max", "avg"]onChange: Callback
Displays:
- Radio buttons for type
- Checkboxes for aggregator functions
4.2 Context Providers
AuthContext
- Manages authentication token
- Handles token refresh
- Provides auth status and user info
StationContext
- Stores selected/active station from map
- Persists across page navigation
- Provides station selection methods
QueryContext
- Manages bulk download query state
- Tracks query history
- Provides query submission methods
MapContext
- Stores map camera state (zoom, center)
- Remembers position across navigation
5. Theme & Styling
5.1 Material-UI Theme
Color Palette (Light Mode):
- Primary:
#1976d2(Blue) - Secondary:
#424242(Gray) - Background:
#fafafa - Surface:
#ffffff
Color Palette (Dark Mode):
- Primary:
#90caf9(Light Blue) - Secondary:
#bdbdbd(Light Gray) - Background:
#121212 - Surface:
#1e1e1e
5.2 Status Colors
- Queued:
#9e9e9e(Gray) - Processing:
#2196f3(Blue) - Complete:
#4caf50(Green) - Failed:
#f44336(Red)
5.3 Typography
- Headers: Roboto, Bold
- Body: Roboto, Regular
- Monospace (FID input): 'Roboto Mono', monospace
6. Responsive Design
6.1 Breakpoints
- Desktop: ≥ 1200px (default layout)
- Tablet: 768px - 1199px (adjust bulk download to stack vertically)
- Mobile: < 768px (single column, simplified interface)
6.2 Bulk Download Page Responsive Behavior
Desktop (≥ 1200px):
- Side-by-side layout: Single Selection | FID Input | Query History
Tablet (768px - 1199px):
- Stack vertically: Single Selection, FID Input, Query Parameters, Query History
Mobile (< 768px):
- Full-width stacked components
- Query History as expandable section at bottom
- Simplified station selector (single select only)
7. Accessibility
7.1 WCAG 2.1 AA Compliance
- Color contrast ratios ≥ 4.5:1
- Keyboard navigation support
- ARIA labels on all interactive elements
- Focus indicators on all focusable elements
7.2 Screen Reader Support
- Semantic HTML structure
- Alt text for icons
- Status announcements for query state changes
8. Performance Considerations
8.1 Optimization Strategies
- Lazy load Bulk Download page components
- Debounce autocomplete searches (300ms)
- Paginate query history (show last 50, load more on scroll)
- Memoize station selector component
- Virtual scrolling for long station lists
8.2 Loading States
- Skeleton screens for initial data load
- Spinner for query submission
- Progress indicators for query processing
9. Error Handling
9.1 User-Facing Error Messages
API Errors:
- Connection failed: "Unable to connect to server. Please check your connection and try again."
- Timeout: "Request timed out. The query may be too large. Try reducing the date range."
- Authentication failed: "Session expired. Please refresh the page and log in again."
Validation Errors:
- No station selected: "Please select at least one station."
- No parameters selected: "Please select at least one parameter (Flow, Velocity, or Stage)."
- Invalid date range: "End date must be after start date."
- Invalid FID: "FID '999' not found. Please check your input."
9.2 Error UI Components
- Toast Notifications: For transient errors (auto-dismiss after 5s)
- Inline Errors: For form validation (red text below input)
- Error Boundaries: Catch component errors and show fallback UI
10. Future Enhancements
10.1 Potential Features (Not in Current Scope)
- Email/SMS notifications when query completes
- Saved query templates
- Query scheduling (e.g., weekly exports)
- Data visualization preview in bulk download
- Compare multiple stations side-by-side
- Export to additional formats (Excel, Parquet)
- API endpoint documentation page
- User accounts with query history
10.2 QA Features (Future)
- Optional QA filtering during download:
- Remove negative values
- Flag anomalies (e.g., >3 std dev from moving average)
- Interpolate missing data
- QA report summary in downloaded ZIP
11. Implementation Notes
11.1 Development Phases
Phase 1: Foundation (2 weeks)
- Set up MUI theme and components
- Implement authentication flow
- Create reusable StationSelector component
Phase 2: Map Enhancements (1 week)
- Add action bar to map page
- Implement search modals
- Add camera state persistence
Phase 3: Daily Flows Enhancement (1 week)
- Add StationSelector to Daily Flows page
- Implement station persistence from map
- Update data fetching logic
Phase 4: Bulk Download Page (3 weeks)
- Create page layout and components
- Implement query submission
- Build Query History UI
- Add Azure Table/Blob Storage integration
Phase 5: Testing & Polish (1 week)
- End-to-end testing
- Performance optimization
- Accessibility audit
- Bug fixes
11.2 Testing Strategy
- Unit tests for all components (Jest + React Testing Library)
- Integration tests for user flows
- E2E tests for critical paths (Playwright)
- Accessibility testing (axe-core)
- Performance testing (Lighthouse)
12. Appendix
12.1 Wireframe References
See inline ASCII diagrams in sections 3.2-3.4
12.2 User Stories
As a biologist, I want to search for a station by river mile so that I can quickly find flow data for a field site.
As a data analyst, I want to download 20 years of flow data for multiple stations so that I can calculate long-term flow statistics.
As a field technician, I want to match flow data with sampling events so that I can correlate water quality with river conditions.
As a manager, I want to see query history so that I can track what data has been downloaded for reporting purposes.
12.3 Glossary
- FID: Feature ID, unique identifier for each station
- River Mile: Distance in miles from the mouth of a river
- Reach: A specific section of a river between two points
- Stage: Water surface elevation (though technically "elevation" in the system)
- Aggregation: Statistical summarization of data over time periods
Document Version: 1.0 Last Updated: November 12, 2025 Author: Jake Status: Draft for Review