This major update implements a complete user annotation system: ## 🎯 New Features - User notes with position tracking for media items - Text highlighting with customizable colors - Highlight-note associations for detailed annotations - Full CRUD API for both notes and highlights - Backward compatibility with existing ebook endpoints ## 📊 Database Changes - Add media_notes table (id, media_item_id, user_id, content, position, timestamps) - Add media_highlights table (id, media_item_id, user_id, selection_text, start/end_position, color, optional note_id) - Add foreign key relationships with CASCADE deletes - Add proper indexes for performance - Add database schema views for ebook backward compatibility ## 🔧 API Implementation - Complete REST API endpoints for notes and highlights - JWT authentication with proper middleware bypass - Request validation with meaningful error responses - UUID validation and type safety - Support for hex color codes in highlights ## 🧪 Testing & Documentation - Comprehensive test suite covering authentication scenarios - Bruno API collection for manual testing - Detailed testing guide with troubleshooting - Updated documentation in README and TESTING.md ## 📁 Backward Compatibility - Existing ebook endpoints continue working - Database views maintain API contracts - No breaking changes for existing integrations The annotation system is now fully functional and ready for production use.
41 lines
6.6 KiB
Go
41 lines
6.6 KiB
Go
// Code generated by templ - DO NOT EDIT.
|
|
|
|
// templ: version: v0.3.977
|
|
package templates
|
|
|
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
|
|
import "github.com/a-h/templ"
|
|
import templruntime "github.com/a-h/templ/runtime"
|
|
|
|
func Register() templ.Component {
|
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
return templ_7745c5c3_CtxErr
|
|
}
|
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
if !templ_7745c5c3_IsBuffer {
|
|
defer func() {
|
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
if templ_7745c5c3_Err == nil {
|
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
}
|
|
}()
|
|
}
|
|
ctx = templ.InitializeContext(ctx)
|
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
if templ_7745c5c3_Var1 == nil {
|
|
templ_7745c5c3_Var1 = templ.NopComponent
|
|
}
|
|
ctx = templ.ClearChildren(ctx)
|
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Register</title><script src=\"https://cdn.tailwindcss.com\"></script><script src=\"https://unpkg.com/htmx.org@1.9.10\"></script><style>\n :root {\n --bg-primary: #1a1b26;\n --bg-secondary: #16161e;\n --text-primary: #a9b1d6;\n --text-secondary: #565f89;\n --accent: #7aa2f7;\n --border: #414868;\n }\n .theme-tokyo-night {\n --bg-primary: #1a1b26;\n --bg-secondary: #16161e;\n --text-primary: #a9b1d6;\n --text-secondary: #565f89;\n --accent: #7aa2f7;\n --border: #414868;\n }\n .theme-dracula {\n --bg-primary: #282a36;\n --bg-secondary: #21222c;\n --text-primary: #f8f8f2;\n --text-secondary: #6272a4;\n --accent: #bd93f9;\n --border: #44475a;\n }\n .theme-nord {\n --bg-primary: #2e3440;\n --bg-secondary: #3b4252;\n --text-primary: #eceff4;\n --text-secondary: #5e81ac;\n --accent: #88c0d0;\n --border: #4c566a;\n }\n .theme-solarized-dark {\n --bg-primary: #002b36;\n --bg-secondary: #073642;\n --text-primary: #93a1a1;\n --text-secondary: #586e75;\n --accent: #2aa198;\n --border: #586e75;\n }\n .theme-monokai {\n --bg-primary: #272822;\n --bg-secondary: #3e3d32;\n --text-primary: #f8f8f2;\n --text-secondary: #75715e;\n --accent: #a6e22e;\n --border: #49483e;\n }\n .theme-one-dark-pro {\n --bg-primary: #282c34;\n --bg-secondary: #21252b;\n --text-primary: #abb2bf;\n --text-secondary: #5c6370;\n --accent: #61dafb;\n --border: #3e4451;\n }\n .theme-material-dark {\n --bg-primary: #263238;\n --bg-secondary: #37474f;\n --text-primary: #eeffff;\n --text-secondary: #546e7a;\n --accent: #80cbc4;\n --border: #455a64;\n }\n .theme-catppuccin-mocha {\n --bg-primary: #1e1e2e;\n --bg-secondary: #181825;\n --text-primary: #cdd6f4;\n --text-secondary: #bac2de;\n --accent: #f38ba8;\n --border: #313244;\n }\n .theme-catppuccin-macchiato {\n --bg-primary: #24273a;\n --bg-secondary: #1e2030;\n --text-primary: #cad3f5;\n --text-secondary: #b8c0e0;\n --accent: #f0c6c6;\n --border: #363a4f;\n }\n .theme-catppuccin-frappe {\n --bg-primary: #303446;\n --bg-secondary: #292c3c;\n --text-primary: #c6d0f5;\n --text-secondary: #b5bfe2;\n --accent: #f2d5cf;\n --border: #414559;\n }\n .theme-catppuccin-latte {\n --bg-primary: #eff1f5;\n --bg-secondary: #e6e9ef;\n --text-primary: #4c4f69;\n --text-secondary: #5c5f77;\n --accent: #d20f39;\n --border: #bcc0cc;\n }\n body {\n background-color: var(--bg-primary);\n color: var(--text-primary);\n }\n .card {\n background-color: var(--bg-secondary);\n border-color: var(--border);\n }\n .btn-primary {\n background-color: var(--accent);\n color: var(--bg-primary);\n }\n .btn-primary:hover {\n opacity: 0.8;\n }\n </style></head><body class=\"theme-tokyo-night min-h-screen\"><div class=\"container mx-auto px-4 py-8 max-w-md\"><h1 class=\"text-3xl font-bold text-center mb-8\">Register for Bookmann</h1><form hx-post=\"/api/auth/register\" hx-target=\"#result\" hx-swap=\"innerHTML\" class=\"bg-white p-6 rounded-lg shadow-md\"><div class=\"mb-4\"><label class=\"block text-gray-700 mb-2\">Email</label> <input type=\"email\" name=\"email\" class=\"w-full px-3 py-2 border rounded\" required></div><div class=\"mb-4\"><label class=\"block text-gray-700 mb-2\">Username</label> <input type=\"text\" name=\"username\" class=\"w-full px-3 py-2 border rounded\" required></div><div class=\"mb-4\"><label class=\"block text-gray-700 mb-2\">Password</label> <input type=\"password\" name=\"password\" class=\"w-full px-3 py-2 border rounded\" required></div><button type=\"submit\" class=\"w-full bg-green-500 text-white py-2 rounded hover:bg-green-600\">Register</button></form><div id=\"result\" class=\"mt-4 text-center\"></div><p class=\"text-center mt-4\"><a href=\"/login\" class=\"text-blue-500 hover:underline\">Already have an account? Login</a></p></div></body></html>")
|
|
if templ_7745c5c3_Err != nil {
|
|
return templ_7745c5c3_Err
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
var _ = templruntime.GeneratedTemplate
|