---
phase: 02-data-persistence-file-management
plan: "02"
type: execute
wave: 1
depends_on: []
files_modified:
- src/app.py
- src/templates/files.html
autonomous: true
requirements:
- FILE-03
- FILE-05
must_haves:
truths:
- "User can navigate file list (scroll up/down) to find specific files"
- "User can generate tidEDA formatted files for data transmission"
artifacts:
- path: "src/app.py"
provides: "tidEDA export API endpoint"
exports: ["POST /api/files/export"]
- path: "src/templates/files.html"
provides: "Scroll navigation and export functionality"
key_links:
- from: "src/templates/files.html"
to: "/api/files/export"
via: "fetch POST"
pattern: "fetch.*api/files/export"
---
Add scroll navigation to file list and tidEDA export functionality.
@./.planning/phases/02-data-persistence-file-management/02-CONTEXT.md
@./.planning/phases/02-data-persistence-file-management/02-RESEARCH.md
@./.planning/phases/02-data-persistence-file-management/02-01-PLAN.md
@./src/app.py
task 1: Add scroll navigation to file list
src/templates/files.html
Enhance src/templates/files.html with scroll navigation:
1. If file list exceeds viewport:
- Enable native scroll (overflow-y: auto)
- Or add pagination controls (Previous/Next buttons)
2. For touch-optimized scrolling on 7" display:
- Ensure smooth scrolling with -webkit-overflow-scrolling: touch
- Minimum touch target size: 48px for all interactive elements
3. Add file count display:
- "Showing X of Y files"
- Update after scroll/filter
4. Optional enhancements:
- Sort by date (newest first)
- Filter by filename search
- These are "OpenCode's Discretion" - implement if straightforward
The key requirement is FILE-03: User can navigate file list (scroll up/down) to find specific files.
Test by loading files page with multiple files and verifying scroll works
User can scroll through file list to find specific files
task 2: Add tidEDA export API endpoint
src/app.py
Add POST /api/files/export endpoint to src/app.py:
```python
@app.route('/api/files/export', methods=['POST'])
def api_files_export():
"""Generate tidEDA formatted export from CSV file"""
data = request.get_json() or {}
filename = data.get('filename')
if not filename:
return jsonify({"error": "filename required"}), 400
# Validate filename (security: prevent path traversal)
if '..' in filename or '/' in filename or '\\' in filename:
return jsonify({"error": "invalid filename"}), 400
# Ensure .csv extension
if not filename.endswith('.csv'):
filename = filename + '.csv'
# Read the CSV file
file_path = os.path.join(LOGGER_DIR, filename)
if not os.path.exists(file_path):
return jsonify({"error": "file not found"}), 404
# Generate tidEDA format
# Structure:
# $STATION,{station_id}
# $DATETIME,{timestamp}
# $DATA
# {original_csv_content}
# $END
settings = load_settings()
station_id = settings.get("station", {}).get("id", "UNKNOWN")
with open(file_path, 'r') as f:
csv_content = f.read()
tideda_content = f"$STATION,{station_id}\n"
tideda_content += f"$DATETIME,{datetime.now().isoformat()}\n"
tideda_content += "$DATA\n"
tideda_content += csv_content
tideda_content += "$END\n"
return jsonify({
"filename": filename.replace('.csv', '.tideda'),
"content": tideda_content,
"format": "tidEDA v1.0"
})
```
Add LOGGER_DIR constant at top of file:
```python
LOGGER_DIR = os.path.join(os.path.dirname(__file__), 'data', 'logger')
os.makedirs(LOGGER_DIR, exist_ok=True)
```
curl -s -X POST -H "Content-Type: application/json" -d '{"filename":"test.csv"}' http://localhost:8080/api/files/export
API returns tidEDA formatted content with $STATION, $DATETIME, $DATA, $END structure
task 3: Add export button to files UI
src/templates/files.html
Enhance src/templates/files.html with export functionality:
1. Add "Export" button next to each file or as a bulk action:
- Button with download icon
- Calls POST /api/files/export
2. Handle export response:
- Receive tidEDA formatted content
- Trigger browser download as .tideda file
3. Add JavaScript download helper:
```javascript
function downloadFile(filename, content) {
const blob = new Blob([content], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
```
4. Add "Generate tidEDA" button at top of page for exporting selected/all files
This satisfies FILE-05: User can generate tidEDA formatted files for data transmission.
Verify export button exists in UI and triggers download
User can generate and download tidEDA formatted files
- Scroll navigation works smoothly
- tidEDA export generates correct format
- Download works in browser
User can navigate file list with scrolling and generate tidEDA formatted files for transmission