Implement Phase 3 of v1.3.0 tags feature per microformats-tags-design.md: Routes (starpunk/routes/public.py): - Add /tag/<tag> archive route with normalization and 404 handling - Pre-load tags in index route for all notes - Pre-load tags in note route for individual notes Admin (starpunk/routes/admin.py): - Parse comma-separated tag input in create route - Parse tag input in update route - Pre-load tags when displaying edit form - Empty tag field removes all tags Templates: - Add tag input field to templates/admin/edit.html - Add tag input field to templates/admin/new.html - Use Jinja2 map filter to display existing tags Implementation details: - Tag URL parameter normalized to lowercase before lookup - Tags pre-loaded using object.__setattr__ pattern (like media) - parse_tag_input() handles trim, dedupe, normalization - All existing tests pass (micropub categories, admin routes) Per architect design: - No pagination on tag archives (acceptable for v1.3.0) - No autocomplete in admin (out of scope) - Follows existing media loading patterns Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
159 lines
5.6 KiB
Markdown
159 lines
5.6 KiB
Markdown
# v1.3.0 Phase 3 Implementation Report
|
|
|
|
**Date**: 2025-12-10
|
|
**Developer**: StarPunk Developer
|
|
**Phase**: Phase 3 - Routes and Admin
|
|
**Status**: Complete
|
|
|
|
## Summary
|
|
|
|
Implemented Phase 3 of the v1.3.0 microformats and tags feature as specified in `microformats-tags-design.md`. This phase adds tag support to routes and admin interfaces, completing the full tag system implementation.
|
|
|
|
## Changes Implemented
|
|
|
|
### 1. Public Routes (`starpunk/routes/public.py`)
|
|
|
|
#### Tag Archive Route
|
|
- **Route**: `/tag/<tag>`
|
|
- **Functionality**:
|
|
- Normalizes tag parameter to lowercase before lookup
|
|
- Returns 404 if tag not found
|
|
- Loads all published notes with the specified tag
|
|
- Pre-loads media and tags for each note
|
|
- **Template**: `templates/tag.html` (not created in this phase, per design doc)
|
|
|
|
#### Index Route Updates
|
|
- Pre-loads tags for each note using `object.__setattr__(note, '_cached_tags', tags)`
|
|
- Consistent with media loading pattern
|
|
|
|
#### Note Route Updates
|
|
- Pre-loads tags for the note using `object.__setattr__(note, '_cached_tags', tags)`
|
|
- Tags available in template via `note.tags`
|
|
|
|
### 2. Admin Routes (`starpunk/routes/admin.py`)
|
|
|
|
#### Create Note Route
|
|
- Added `tags` parameter extraction from form
|
|
- Parses comma-separated tags using `parse_tag_input()`
|
|
- Passes tags to `create_note()` function
|
|
- Empty tag field creates note without tags
|
|
|
|
#### Edit Note Form Route
|
|
- Pre-loads tags when loading the edit form
|
|
- Tags available for display in form via `note.tags`
|
|
|
|
#### Update Note Route
|
|
- Added `tags` parameter extraction from form
|
|
- Parses comma-separated tags using `parse_tag_input()`
|
|
- Passes tags to `update_note()` function
|
|
- Empty tag field removes all tags from note
|
|
|
|
### 3. Admin Templates
|
|
|
|
#### `templates/admin/edit.html`
|
|
- Added tag input field between slug and published checkbox
|
|
- Pre-fills with existing tags: `{{ note.tags|map(attribute='display_name')|join(', ') }}`
|
|
- Placeholder text provides example format
|
|
- Help text explains comma separation and blank field behavior
|
|
|
|
#### `templates/admin/new.html`
|
|
- Added tag input field between media upload and published checkbox
|
|
- Placeholder text provides example format
|
|
- Help text explains comma separation
|
|
|
|
## Design Decisions
|
|
|
|
Following the architect's Q&A responses:
|
|
|
|
1. **URL normalization**: Tag route normalizes URL parameter to lowercase before lookup
|
|
2. **Tag loading**: Pre-load using `object.__setattr__()` pattern (consistent with media)
|
|
3. **Admin input**: Plain text field, comma-separated
|
|
4. **Empty field behavior**: Removes all tags on update, creates without tags on create
|
|
5. **Tag parsing**: Uses `parse_tag_input()` which handles trim, dedupe, and normalization
|
|
|
|
## Testing
|
|
|
|
All existing tests pass:
|
|
- Micropub category tests pass (tags work via API)
|
|
- Custom slug tests pass (admin routes work)
|
|
- Microformats tests pass (templates load correctly)
|
|
|
|
Only one pre-existing test failure unrelated to this implementation:
|
|
- `test_migration_race_condition.py::TestGraduatedLogging::test_debug_level_for_early_retries`
|
|
- This is a logging test issue, not related to tag functionality
|
|
|
|
## Files Modified
|
|
|
|
1. `/home/phil/Projects/starpunk/starpunk/routes/public.py`
|
|
- Added tag archive route
|
|
- Updated index route to pre-load tags
|
|
- Updated note route to pre-load tags
|
|
|
|
2. `/home/phil/Projects/starpunk/starpunk/routes/admin.py`
|
|
- Updated create route to handle tag input
|
|
- Updated edit form route to pre-load tags
|
|
- Updated update route to handle tag input
|
|
|
|
3. `/home/phil/Projects/starpunk/templates/admin/edit.html`
|
|
- Added tag input field
|
|
|
|
4. `/home/phil/Projects/starpunk/templates/admin/new.html`
|
|
- Added tag input field
|
|
|
|
## Integration with Previous Phases
|
|
|
|
This phase completes the tag system started in Phase 1 (backend) and Phase 2 (templates):
|
|
|
|
- **Phase 1**: Database schema and `starpunk/tags.py` module
|
|
- **Phase 2**: Template markup for displaying tags
|
|
- **Phase 3**: Routes and admin integration (this phase)
|
|
|
|
All three phases work together to provide:
|
|
- Tag creation via admin interface
|
|
- Tag creation via Micropub API (already working from Phase 1)
|
|
- Tag display on note pages (from Phase 2)
|
|
- Tag archive pages (new route)
|
|
- Tag loading in all relevant routes (performance optimization)
|
|
|
|
## Known Limitations
|
|
|
|
Per design document:
|
|
- No pagination on tag archive pages (acceptable for v1.3.0)
|
|
- No tag autocomplete in admin (out of scope)
|
|
- Tag archive template (`templates/tag.html`) not created yet (will be done in template phase)
|
|
|
|
## Next Steps
|
|
|
|
According to the design document, the next phase should be:
|
|
- **Phase 4**: Validation with mf2py and indiewebify.me
|
|
- Create `templates/tag.html` if not already created in Phase 2
|
|
- Run microformats validation tests
|
|
- Manual testing with indiewebify.me
|
|
|
|
## Verification
|
|
|
|
To verify this implementation:
|
|
|
|
```bash
|
|
# Run tests
|
|
uv run pytest tests/test_micropub.py::test_micropub_create_with_categories -xvs
|
|
uv run pytest tests/test_custom_slugs.py tests/test_microformats.py -xvs
|
|
|
|
# Test in browser
|
|
1. Create note via admin with tags: "Python, IndieWeb, Testing"
|
|
2. Edit note and change tags
|
|
3. Set tags to empty string to remove all tags
|
|
4. View note page to see tags displayed
|
|
5. Click tag link to view tag archive (404 until template created)
|
|
```
|
|
|
|
## Notes
|
|
|
|
The implementation strictly follows the architect's design in `microformats-tags-design.md`. All decisions documented in the Q&A section were applied:
|
|
- Tag normalization happens in route before lookup
|
|
- Pre-loading pattern matches media loading
|
|
- Admin forms use simple text input with comma separation
|
|
- Empty field removes tags (explicit user action)
|
|
|
|
No architectural decisions were made by the developer - all followed existing patterns and architect specifications.
|