196 lines
5.7 KiB
Markdown
196 lines
5.7 KiB
Markdown
---
|
|
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"
|
|
---
|
|
|
|
<objective>
|
|
Add scroll navigation to file list and tidEDA export functionality.
|
|
</objective>
|
|
|
|
<context>
|
|
@./.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
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>task 1: Add scroll navigation to file list</name>
|
|
<files>src/templates/files.html</files>
|
|
<action>
|
|
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.
|
|
</action>
|
|
<verify>
|
|
<automated>Test by loading files page with multiple files and verifying scroll works</automated>
|
|
</verify>
|
|
<done>User can scroll through file list to find specific files</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>task 2: Add tidEDA export API endpoint</name>
|
|
<files>src/app.py</files>
|
|
<action>
|
|
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)
|
|
```
|
|
</action>
|
|
<verify>
|
|
<automated>curl -s -X POST -H "Content-Type: application/json" -d '{"filename":"test.csv"}' http://localhost:8080/api/files/export</automated>
|
|
</verify>
|
|
<done>API returns tidEDA formatted content with $STATION, $DATETIME, $DATA, $END structure</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>task 3: Add export button to files UI</name>
|
|
<files>src/templates/files.html</files>
|
|
<action>
|
|
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.
|
|
</action>
|
|
<verify>
|
|
<automated>Verify export button exists in UI and triggers download</automated>
|
|
</verify>
|
|
<done>User can generate and download tidEDA formatted files</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- Scroll navigation works smoothly
|
|
- tidEDA export generates correct format
|
|
- Download works in browser
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
User can navigate file list with scrolling and generate tidEDA formatted files for transmission
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/02-data-persistence-file-management/02-02-SUMMARY.md`
|
|
</output>
|