Refactor: Eliminate duplicate types - Use handler types directly

- Deleted templates.CollectionDetailData - using templates.CollectionData everywhere
- Deleted templates.BookData - using handlers.BookInfo everywhere
- Deleted templates.DeviceData - using handlers.DeviceInfo everywhere
- Deleted templates.ProgressItemData - using handlers.ProgressWithMedia everywhere
- Deleted templates.convertDevices() helper - Use handlers types directly in templates
- Enhanced handlers.ProgressWithMedia with device metadata fields
- Added handlers.getDeviceIcon() helper
- Updated all templates to import handlers package
- Cleaned up unused imports

This aligns codebase with templ's design philosophy (use Go types directly, no parallel type system)
This commit is contained in:
2026-02-12 19:48:07 -05:00
parent b5745e1554
commit 2a64ca423f
15 changed files with 639 additions and 168 deletions
+49 -25
View File
@@ -42,6 +42,7 @@
- `internal/router/device.go` - Add regenerate token route
- `internal/handlers/devices.go` - Add regenerate token handler
- `templates/devices.templ` - Add copy/regenerate UI
- `web/src/device-management.ts` - Add device management TypeScript
- `bruno/sync-kobo/api.bru` - Add URL path token requests
- `bruno/devices/regenerate-*.bru` - New token regeneration test files
- `bruno/opds/*-*.bru` - New OPDS authentication test files
@@ -86,14 +87,6 @@ SET
updated_at = NOW()
WHERE id = $1
RETURNING *;
-- name: RevokeDevice :exec
UPDATE devices
SET
auth_token = NULL,
sync_enabled = false,
updated_at = NOW()
WHERE id = $1;
```
**Verification**: Run `go build ./...` after adding this query to ensure sqlc generates the new function correctly.
@@ -504,24 +497,45 @@ func (h *DeviceHandler) RegenerateDeviceToken(c echo.Context) error {
3. Add "Regenerate Token" button for each device
4. Add JavaScript functions for copy and regenerate
#### 1.6.1 Update DeviceData Struct
**Location**: Find `DeviceData` struct (near top of file)
**Current struct** (lines vary, find structure):
**ADD FIELD** to struct:
```go
type DeviceData struct {
ID string
DeviceName string
DeviceType string
LastSync string
LastSeen string
SyncEnabled bool
AutoSync bool
SyncFrequency int
ID string
DeviceName string
DeviceType string
LastSync string
LastSeen string
SyncEnabled bool
AutoSync bool
SyncFrequency int
CreatedAt string
DeviceMetadata json.RawMessage
AuthToken string // NEW: Device API key for authentication
}
```
#### 1.6.3 Update Collection Detail Template
**File**: `templates/collection.templ`
**Location**: Line 213 (function signature)
**Current**:
```templ
templ CollectionDetail(user User, collection CollectionDetailData, books []BookData) {
```
**CHANGE** (use handlers.BookInfo):
```templ
templ CollectionDetail(user User, collection CollectionData, books []handlers.BookInfo) {
```
**ADD FIELD** to struct:
```go
AuthToken string // NEW: Device API key for authentication
}
```
@@ -872,7 +886,7 @@ put {
docs {
## Regenerate Device Token
Regenerates the auth token for a device, invalidating the old token immediately.
Regenerates auth token for a device, invalidating old token immediately.
**Method:** PUT
@@ -899,7 +913,7 @@ docs {
**Important Notes:**
- Old token stops working immediately
- Device must be updated with new token to resume syncing
- No data loss - device ID remains the same
- No data loss - device ID remains same
**Example Response:**
```json
@@ -911,14 +925,24 @@ docs {
"device_name": "My Kobo Clara",
"device_type": "kobo",
"sync_enabled": true,
"auto_sync": true
"auto_sync": true,
"sync_frequency_minutes": 5,
"created_at": "2026-02-12T10:00:00Z",
"device_metadata": "{...}"
},
"sync_urls": {
"sync_url": "http://localhost:8765/api/sync/kobo/dev_new_token",
"markup": "http://localhost:8765/api/sync/kobo/dev_new_token/markup"
"markup": "http://localhost:8765/api/sync/kobo/dev_new_token/markup",
"bookmark": "http://localhost:8765/api/sync/kobo/dev_new_token/bookmark",
"init": "http://localhost:8765/api/sync/kobo/dev_new_token/v1/initialization"
}
}
```
**Important Notes:**
- Old token stops working immediately
- Device must be updated with new token to resume syncing
- No data loss - device ID remains same
}
```
+474
View File
@@ -0,0 +1,474 @@
# Type Duplication Refactoring Plan
**Document Purpose**: Consolidate duplicate type definitions across templates/ and handlers/ packages to align with templ's design philosophy and reduce maintenance burden.
**Status**: Planning Phase
**Last Updated**: 2026-02-12
**Separation from**: IMPLEMENTATION_EXACT.md (this is independent refactoring)
**Core Principle**: **API wins** - When there's ambiguity between template types and API/handler types, the API/handler types take precedence.
---
## Executive Summary
**Problem**: Codebase maintains parallel type systems:
- `templates/types.go` - Template-specific types
- `handlers/*.go` - API response types
**Core Principle**: **API wins - when in doubt, API/handler types take precedence**
### Why "API wins"?
1. **API is public contract**: Handler types define your public API surface - these are more stable
2. **Templates are presentation**: HTML templates can format any Go type - they're flexible
3. **Single source of truth**: One authoritative type definition vs two parallel definitions
4. **Json serialization**: Handler types already have `json:"..."` tags for API responses
5. **Future API clients**: If you add mobile apps or CLI tools, they need handler types anyway
### Trade-offs
**Pro**: Simpler codebase, one type to maintain, automatic API/HTML consistency
**Con**: Templates may have unused fields visible in scope (acceptable - templ handles this well)
**Impact**:
- ~40 lines of duplicate type definitions
- Unnecessary conversion functions
- Maintenance burden (update 2 places for 1 change)
- Violates templ's design philosophy
**Solution**: Use handler types directly in templates, eliminate template-specific duplicates.
---
## Current State Analysis
### Duplicates Found
| Template Type | Handler Type | Overlap | Action |
|---------------|---------------|----------|--------|
| `DeviceData` | `DeviceInfo` | 90% | **DELETE** DeviceData |
| `BookData` | `collections.BookInfo` | 100% | **DELETE** BookData |
| `CollectionDetailData` | `CollectionData` | 100% | **DELETE** CollectionDetailData |
| `ProgressItemData` | `ProgressWithMedia` | 70% | **MERGE** (different fields) |
| `QueueItemData` | `QueueItemResponse` | 60% | **KEEP** (template uses subset) |
### Already Using Handler Types (Good Patterns)
`Conflicts` template uses `handlers.ConflictDetailResponse`
`Queue` template uses `handlers.QueueItemResponse`
**This is the pattern we want everywhere.**
---
## Refactoring Plan
### Phase 1: Eliminate Complete Duplicates
#### 1.1 Delete CollectionDetailData
**Files to Modify**:
- `templates/types.go` (lines 26-32) - DELETE struct
- `templates/collection_rules.templ` (line 3) - Change signature
- `templates/collections.templ` (line 213) - Change signature
**Changes**:
**Delete** from `templates/types.go`:
```go
type CollectionDetailData struct {
ID string
Name string
Description string
Color string
Icon string
}
```
**Update** `templates/collection_rules.templ:3`:
```templ
// BEFORE:
templ CollectionRules(user User, collection CollectionDetailData) {
// AFTER:
templ CollectionRules(user User, collection templates.CollectionData) {
```
**Update** `templates/collections.templ:213`:
```templ
// BEFORE:
templ CollectionDetail(user User, collection CollectionDetailData, books []BookData) {
// AFTER:
templ CollectionDetail(user User, collection templates.CollectionData, books []collections.BookInfo) {
```
**Test**: `go test ./templates/...` after template regeneration
---
#### 1.2 Delete BookData
**Files to Modify**:
- `templates/types.go` (lines 34-39) - DELETE struct
- `templates/collections.templ` (line 213) - Change books param
**Changes**:
**Delete** from `templates/types.go`:
```go
type BookData struct {
MediaItemID string
Title string
Author string
CoverImagePath string
}
```
**Update** `templates/collections.templ:213`:
```templ
// BEFORE:
templ CollectionDetail(user User, collection templates.CollectionData, books []BookData) {
// AFTER:
templ CollectionDetail(user User, collection templates.CollectionData, books []collections.BookInfo) {
```
**Test**: View collection detail page, verify books display correctly
---
#### 1.3 Delete DeviceData and ConvertDevices
**Files to Modify**:
- `templates/types.go` (lines 48-57) - DELETE struct
- `templates/devices.templ` (line 3) - Change signature
- `internal/router/helpers.go` (lines 46-67) - DELETE function
- `internal/router/frontend.go` (lines 161-169) - Remove conversion
**Changes**:
**Delete** from `templates/types.go`:
```go
type DeviceData struct {
ID string
DeviceName string
DeviceType string
SyncEnabled bool
AutoSync bool
SyncFrequency int32
LastSync string
LastSeen string
}
```
**Delete** from `internal/router/helpers.go`:
```go
func convertDevices(deviceInfos []handlers.DeviceInfo) []templates.DeviceData {
// ... entire function (lines 46-67)
}
```
**Update** `templates/devices.templ:3`:
```templ
// BEFORE:
templ Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegistrationData) {
// AFTER:
templ Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []PendingRegistrationData) {
```
**Update** `templates/devices.templ` template logic:
Find these patterns and update:
```templ
// BEFORE:
if device.LastSync != "" {
<span>{ device.LastSync }</span>
}
// AFTER:
if device.LastSync != nil {
<span>{ device.LastSync.Format("2006-01-02 15:04") }</span>
}
```
**Update** `internal/router/frontend.go:161-169`:
```go
// BEFORE:
deviceData, err := cfg.DeviceHandler.GetDevicesData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading devices")
}
pendingData, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading pending")
}
deviesList := convertDevices(deviceData)
pendingList := convertPending(pendingData)
// AFTER:
deviceData, err := cfg.DeviceHandler.GetDevicesData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading devices")
}
pendingData, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading pending")
}
// No conversion - use handler data directly
```
**Test**: Devices page renders correctly with proper date formatting
---
### Phase 2: Eliminate Remaining Template Types
#### 2.1 ProgressItemData → Use ProgressWithMedia
**Current Issue**:
- `handlers.ProgressWithMedia` exists as API response type
- `templates.ProgressItemData` duplicates it with minor variations
**Decision**: **API wins** - Use `handlers.ProgressWithMedia` everywhere
**Files to Modify**:
- `internal/handlers/progress.go` - Update `ProgressWithMedia` struct
- `templates/types.go` - DELETE `ProgressItemData`
- `templates/progress.templ` - Use `handlers.ProgressWithMedia`
**Changes**:
**Add fields to** `internal/handlers/progress.go:ProgressWithMedia`:
```go
// ADD fields to existing struct:
type ProgressWithMedia struct {
MediaItemID uuid.UUID `json:"media_item_id"`
Title string `json:"title"`
Author string `json:"author"`
CoverImagePath string `json:"cover_image_path"`
Percentage float64 `json:"percentage"`
CurrentPage int32 `json:"current_page"`
TotalPages int32 `json:"total_pages"`
LastReadAt time.Time `json:"last_read_at"`
Epubcfi string `json:"epubcfi"`
LastSyncDevice string `json:"last_sync_device"`
DeviceName string `json:"device_name,omitempty"` // ADD
DeviceType string `json:"device_type,omitempty"` // ADD
DeviceIcon string `json:"device_icon,omitempty"` // ADD
}
```
**Update** `internal/handlers/progress.go:GetAllProgress()` to populate new device fields.
**Delete** from `templates/types.go` (lines 99-112):
```go
type ProgressItemData struct {
// ... delete entire struct
}
```
**Update** `templates/progress.templ:3`:
```templ
// BEFORE:
templ Progress(user User, progressData []ProgressItemData) {
// AFTER:
templ Progress(user User, progressData []handlers.ProgressWithMedia) {
```
**Test**: Progress page displays device names and icons
**Delete** from `templates/types.go` (lines 99-112):
```go
type ProgressItemData struct {
// ... delete entire struct
}
```
**Update** `templates/progress.templ:3`:
```templ
// BEFORE:
templ Progress(user User, progressData []ProgressItemData) {
// AFTER:
templ Progress(user User, progressData []handlers.ProgressWithMedia) {
```
**Test**: Progress page displays device names and icons
---
### Phase 3: Update Get*Data Functions
**Issue**: Several handler functions return handler types but aren't used directly by templates due to conversion layer.
**Files to Modify**:
- `internal/router/frontend.go` - Remove conversions
**Changes**:
**Devices** (already done in Phase 1.3):
- `GetDevicesData()` returns `[]handlers.DeviceInfo`
- Template uses directly
**Progress**:
```go
// frontend.go - update progress route
protected.GET("/progress-page", func(c echo.Context) error {
// ...
progressData, err := cfg.Handler.GetAllProgressData(c)
// Returns []handlers.ProgressWithMedia directly - no conversion
// ...
})
```
**Collections**:
```go
// collections.go - update to return handler types
func (h *CollectionHandler) GetCollectionBooksData(c echo.Context) ([]collections.BookInfo, error) {
// Already returns BookInfo - just update template
}
```
---
## Summary Table
| Phase | Files Changed | Lines Removed | Lines Added | Net Change |
|-------|--------------|---------------|--------------|-------------|
| 1.1 CollectionDetailData | 3 | 7 | 2 | -5 |
| 1.2 BookData | 3 | 6 | 0 | -6 |
| 1.3 DeviceData | 4 | 24 | 5 | -19 |
| 2.1 ProgressItemData | 4 | 14 | 3 | -11 |
| **Total** | **14** | **51** | **10** | **-41** |
**Note**: QueueItemData already uses handler type (good pattern). Conflicts already uses handler type (good pattern).
---
## Testing Checklist
After each phase:
### Phase 1.1 (CollectionDetailData)
- [ ] View collection rules page
- [ ] Edit collection rules
- [ ] View collection detail page
- [ ] Add books to collection
### Phase 1.2 (BookData)
- [ ] View collection detail page
- [ ] Browse books in collection
- [ ] Book covers display correctly
### Phase 1.3 (DeviceData)
- [ ] Devices page loads
- [ ] Device cards display
- [ ] Last sync/last seen dates formatted
- [ ] Device type icons show correctly
### Phase 2.1 (ProgressItemData)
- [ ] Progress page loads
- [ ] Progress entries show device names/icons
- [ ] Percentage display works
- [ ] Cover images display
---
## Rollback Plan
If refactoring breaks functionality:
1. **Git stash** changes before starting
2. **Commit after each successful phase**
3. **Revert individual commits** if needed
4. **Keep conversion functions** commented out temporarily
```bash
# Before starting
git stash push -m "pre-refactor-state"
# After Phase 1.1
git commit -m "refactor: delete CollectionDetailData, use CollectionData"
# If Phase 1.2 breaks
git revert HEAD
# Continue with 1.3
```
---
## Benefits
### Code Quality
- ✅ Aligns with templ's design philosophy
- ✅ Single source of truth for types
- ✅ Reduced code duplication
-**API-first**: Handler types are authoritative
### Maintenance
- ✅ Update types in 1 place, not 2
- ✅ Less conversion logic to maintain
- ✅ Clearer data flow
-**Template changes automatically get API updates**
### Consistency
- ✅ All templates use handlers types (like Queue/Conflicts already do)
- ✅ API and HTML use same type definitions
- ✅ 41 fewer lines of code
-**"API wins"** principle eliminates ambiguity
---
## Future Considerations
### For IMPLEMENTATION_EXACT.md
After this refactoring, adding `AuthToken` to devices is simpler:
- Add `AuthToken string` to `handlers.DeviceInfo` struct
- Add to `GetDevicesData()` function return values
- Template automatically gets it (no conversion layer)
This **solves the critical issue** found in IMPLEMENTATION_EXACT.md analysis automatically.
### For New Features
- Define handler types with json tags first
- Templates use same types directly
- Only create template-specific types for:
- Computed/derived fields not in API
- Combining data from multiple sources
- Simplifying complex nested structures
---
## Execution Order
1. **Run tests** to ensure baseline: `go test ./...`
2. **Create feature branch**: `git checkout -b refactor/types-consolidation`
3. **Execute Phase 1.1** (CollectionDetailData) - DELETE template type, use API type
4. **Commit and test**
5. **Execute Phase 1.2** (BookData) - DELETE template type, use API type
6. **Commit and test**
7. **Execute Phase 1.3** (DeviceData) - DELETE template type, use API type
8. **Commit and test**
9. **Execute Phase 2.1** (ProgressItemData) - DELETE template type, enhance API type
10. **Final commit and test**
11. **Update IMPLEMENTATION_EXACT.md** to reference handler types only
**Total Estimated Time**: 2-3 hours with testing
**Key Mindset**: Every change removes a template type, never the reverse. API types are authoritative.
---
## Questions for User
1. **Progress template updates**: Since we're using `handlers.ProgressWithMedia` (API type) in templates, any template formatting changes (like date formatting) should be done in the template itself. Is this acceptable?
2. **Testing**: Do you have automated template tests, or is this manual testing only?
3. **Implementation plan**: Should I update IMPLEMENTATION_EXACT.md after this refactoring to reference `handlers.DeviceInfo` instead of `DeviceData`?
4. **Json tags on handler types**: Templates don't need `json:"..."` tags - should we document that these are for API responses only?
+7 -7
View File
@@ -63,6 +63,13 @@ type UpdateDeviceMappingRequest struct {
SyncDirection string `json:"sync_direction" validate:"required,oneof=bidirectional book_to_device device_to_book none"`
}
type BookInfo struct {
MediaItemID string `json:"media_item_id"`
Title string `json:"title"`
Author string `json:"author"`
CoverImagePath string `json:"cover_image_path"`
}
func (h *CollectionHandler) CreateCollection(c echo.Context) error {
user := c.Get("user").(database.Users)
userUUID := uuid.UUID(user.ID.Bytes)
@@ -171,13 +178,6 @@ func (h *CollectionHandler) GetCollection(c echo.Context) error {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
type BookInfo struct {
MediaItemID string `json:"media_item_id"`
Title string `json:"title"`
Author string `json:"author"`
CoverImagePath string `json:"cover_image_path"`
}
bookList := make([]BookInfo, 0, len(books))
for _, book := range books {
bookList = append(bookList, BookInfo{
+50 -22
View File
@@ -14,6 +14,20 @@ import (
"github.com/labstack/echo/v4"
)
// getDeviceIcon returns an emoji icon for device type
func getDeviceIcon(deviceType string) string {
switch deviceType {
case "kobo":
return "📚"
case "koreader":
return "📖"
case "kindle":
return "📱"
default:
return "📚"
}
}
// GetUniversalProgress retrieves progress with all location references
func (h *Handler) GetUniversalProgress(c echo.Context) error {
user := MustGetAuthenticatedUser(c)
@@ -229,16 +243,22 @@ func (h *Handler) GetProgressHistory(c echo.Context) error {
}
type ProgressWithMedia struct {
MediaItemID uuid.UUID
Title string
Author string
CoverImagePath string
Percentage float64
CurrentPage int32
TotalPages int32
LastReadAt time.Time
Epubcfi string
LastSyncDevice string
MediaItemID uuid.UUID `json:"media_item_id"`
Title string `json:"title"`
Author string `json:"author"`
CoverImagePath string `json:"cover_image_path"`
Percentage float64 `json:"percentage"`
CurrentPage int32 `json:"current_page"`
TotalPages int32 `json:"total_pages"`
LastReadAt time.Time `json:"last_read_at"`
Epubcfi string `json:"epubcfi"`
LastSyncDevice string `json:"last_sync_device"`
DeviceName string `json:"device_name,omitempty"`
DeviceType string `json:"device_type,omitempty"`
DeviceIcon string `json:"device_icon,omitempty"`
ProgressPercentage float64 `json:"-"`
EpubCFI string `json:"-"`
LastUpdated string `json:"-"`
}
// GetAllProgress retrieves all progress for a user with sync source info
@@ -283,17 +303,26 @@ func (h *Handler) GetAllProgress(c echo.Context) error {
deviceName = progress.LastSyncDevice.String
}
lastUpdated := ""
if progress.LastReadAt.Valid {
lastUpdated = progress.LastReadAt.Time.Format("2006-01-02 15:04")
}
progressList = append(progressList, ProgressWithMedia{
MediaItemID: progress.MediaItemID.Bytes,
Title: mediaItem.Title,
Author: author,
CoverImagePath: coverPath,
Percentage: progress.Percentage.Float64,
CurrentPage: progress.CurrentPage.Int32,
TotalPages: progress.TotalPages.Int32,
LastReadAt: progress.LastReadAt.Time,
Epubcfi: epubcfi,
LastSyncDevice: deviceName,
MediaItemID: progress.MediaItemID.Bytes,
Title: mediaItem.Title,
Author: author,
CoverImagePath: coverPath,
Percentage: progress.Percentage.Float64,
CurrentPage: progress.CurrentPage.Int32,
TotalPages: progress.TotalPages.Int32,
LastReadAt: progress.LastReadAt.Time,
Epubcfi: epubcfi,
LastSyncDevice: deviceName,
ProgressPercentage: progress.Percentage.Float64,
EpubCFI: epubcfi,
LastUpdated: lastUpdated,
DeviceIcon: getDeviceIcon(deviceName),
})
}
@@ -349,7 +378,7 @@ func (h *Handler) GetAllProgressData(c echo.Context) ([]ProgressWithMedia, error
MediaItemID: progress.MediaItemID.Bytes,
Title: mediaItem.Title,
Author: author,
CoverImagePath: coverPath,
CoverImagePath: coverPath,
Percentage: progress.Percentage.Float64,
CurrentPage: progress.CurrentPage.Int32,
TotalPages: progress.TotalPages.Int32,
@@ -361,4 +390,3 @@ func (h *Handler) GetAllProgressData(c echo.Context) ([]ProgressWithMedia, error
return progressList, nil
}
+4 -5
View File
@@ -158,18 +158,17 @@ func registerFrontendRoutes(cfg *Config) {
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading user")
}
deviceData, err := cfg.DeviceHandler.GetDevicesData(c)
devices, err := cfg.DeviceHandler.GetDevicesData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading devices")
}
pendingData, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
pendingMaps, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
if err != nil {
return c.HTML(http.StatusInternalServerError, "Error loading pending")
}
devicesList := convertDevices(deviceData)
pendingList := convertPending(pendingData)
pendingList := convertPending(pendingMaps)
var buf bytes.Buffer
err = templates.Devices(user, devicesList, pendingList).Render(c.Request().Context(), &buf)
err = templates.Devices(user, devices, pendingList).Render(c.Request().Context(), &buf)
if err != nil {
return err
}
-25
View File
@@ -2,9 +2,7 @@ package router
import (
"context"
"time"
"bookhoard/internal/handlers"
"bookhoard/templates"
"github.com/google/uuid"
@@ -43,29 +41,6 @@ func getTemplateUserWithTheme(c echo.Context, cfg *Config) (templates.User, erro
}, nil
}
func convertDevices(deviceInfos []handlers.DeviceInfo) []templates.DeviceData {
result := make([]templates.DeviceData, len(deviceInfos))
for i, d := range deviceInfos {
lastSync := ""
if d.LastSync != nil {
lastSync = d.LastSync.Format(time.RFC3339)
}
lastSeen := ""
if d.LastSeen != nil {
lastSeen = d.LastSeen.Format(time.RFC3339)
}
result[i] = templates.DeviceData{
ID: d.ID.String(),
DeviceName: d.DeviceName,
DeviceType: d.DeviceType,
SyncEnabled: d.SyncEnabled,
LastSync: lastSync,
LastSeen: lastSeen,
}
}
return result
}
func convertPending(pending []map[string]interface{}) []templates.PendingRegistrationData {
result := make([]templates.PendingRegistrationData, len(pending))
for i, p := range pending {
+1 -1
View File
@@ -1,6 +1,6 @@
package templates
templ CollectionRules(user User, collection CollectionDetailData) {
templ CollectionRules(user User, collection CollectionData) {
<!DOCTYPE html>
<html lang="en">
<head>
+1 -1
View File
@@ -8,7 +8,7 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
func CollectionRules(user User, collection CollectionDetailData) templ.Component {
func CollectionRules(user User, collection CollectionData) 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 {
+3 -1
View File
@@ -1,5 +1,7 @@
package templates
import "bookhoard/internal/handlers"
templ Collection(user User, collections []CollectionData) {
<!DOCTYPE html>
<html lang="en">
@@ -210,7 +212,7 @@ templ Collection(user User, collections []CollectionData) {
</html>
}
templ CollectionDetail(user User, collection CollectionDetailData, books []BookData) {
templ CollectionDetail(user User, collection CollectionData, books []handlers.BookInfo) {
<!DOCTYPE html>
<html lang="en">
<head>
+12 -10
View File
@@ -8,6 +8,8 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "bookhoard/internal/handlers"
func Collection(user User, collections []CollectionData) 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
@@ -55,7 +57,7 @@ func Collection(user User, collections []CollectionData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(col.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 46, Col: 60}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 48, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -68,7 +70,7 @@ func Collection(user User, collections []CollectionData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 58, Col: 109}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 60, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -81,7 +83,7 @@ func Collection(user User, collections []CollectionData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 59, Col: 103}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 61, Col: 103}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -100,7 +102,7 @@ func Collection(user User, collections []CollectionData) templ.Component {
})
}
func CollectionDetail(user User, collection CollectionDetailData, books []BookData) templ.Component {
func CollectionDetail(user User, collection CollectionData, books []handlers.BookInfo) 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 {
@@ -128,7 +130,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 219, Col: 32}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 221, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -149,7 +151,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 234, Col: 95}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 236, Col: 95}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -162,7 +164,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 236, Col: 107}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 238, Col: 107}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -175,7 +177,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 237, Col: 88}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 239, Col: 88}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -199,7 +201,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 284, Col: 131}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 286, Col: 131}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -217,7 +219,7 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 286, Col: 108}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 288, Col: 108}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
+7 -5
View File
@@ -1,6 +1,8 @@
package templates
templ Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegistrationData) {
import "bookhoard/internal/handlers"
templ Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []PendingRegistrationData) {
<!DOCTYPE html>
<html lang="en">
<head>
@@ -79,16 +81,16 @@ templ Devices(user User, devices []DeviceData, pendingRegistrations []PendingReg
</div>
<div class="flex justify-between">
<span style="color: var(--text-secondary)">Last Sync</span>
if device.LastSync != "" {
<span style="color: var(--text-primary)">{ device.LastSync }</span>
if device.LastSync != nil {
<span style="color: var(--text-primary)">{ device.LastSync.Format("2006-01-02 15:04") }</span>
} else {
<span style="color: var(--text-primary)">Never</span>
}
</div>
<div class="flex justify-between">
<span style="color: var(--text-secondary)">Last Seen</span>
if device.LastSeen != "" {
<span style="color: var(--text-primary)">{ device.LastSeen }</span>
if device.LastSeen != nil {
<span style="color: var(--text-primary)">{ device.LastSeen.Format("2006-01-02 15:04") }</span>
} else {
<span style="color: var(--text-primary)">Never</span>
}
+14 -12
View File
@@ -8,7 +8,9 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegistrationData) templ.Component {
import "bookhoard/internal/handlers"
func Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []PendingRegistrationData) 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 {
@@ -89,7 +91,7 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(device.DeviceName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 69, Col: 102}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 71, Col: 102}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -102,7 +104,7 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(device.DeviceType)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 70, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 72, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -127,15 +129,15 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if device.LastSync != "" {
if device.LastSync != nil {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<span style=\"color: var(--text-primary)\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(device.LastSync)
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(device.LastSync.Format("2006-01-02 15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 83, Col: 70}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 85, Col: 97}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -155,15 +157,15 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if device.LastSeen != "" {
if device.LastSeen != nil {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<span style=\"color: var(--text-primary)\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(device.LastSeen)
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(device.LastSeen.Format("2006-01-02 15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 91, Col: 70}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 93, Col: 97}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -206,7 +208,7 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(reg.DeviceName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 110, Col: 87}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 112, Col: 87}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -219,7 +221,7 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(reg.DeviceType)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 112, Col: 27}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 114, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -232,7 +234,7 @@ func Devices(user User, devices []DeviceData, pendingRegistrations []PendingRegi
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(reg.ExpiresAt)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 112, Col: 58}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/devices.templ`, Line: 114, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
+3 -1
View File
@@ -1,6 +1,8 @@
package templates
templ Progress(user User, progressData []ProgressItemData) {
import "bookhoard/internal/handlers"
templ Progress(user User, progressData []handlers.ProgressWithMedia) {
<!DOCTYPE html>
<html lang="en">
<head>
+14 -12
View File
@@ -8,7 +8,9 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
func Progress(user User, progressData []ProgressItemData) templ.Component {
import "bookhoard/internal/handlers"
func Progress(user User, progressData []handlers.ProgressWithMedia) 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 {
@@ -55,7 +57,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 44, Col: 121}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 46, Col: 121}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -73,7 +75,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(item.Author)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 46, Col: 116}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 48, Col: 116}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -91,7 +93,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(item.ProgressPercentage)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 50, Col: 127}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 52, Col: 127}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -104,7 +106,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item.CurrentPage)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 64, Col: 62}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 66, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -117,7 +119,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(item.TotalPages)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 64, Col: 84}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 66, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -130,7 +132,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.LastUpdated)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 69, Col: 96}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 71, Col: 96}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -143,7 +145,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceIcon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 74, Col: 83}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 76, Col: 83}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -156,7 +158,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 75, Col: 102}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 77, Col: 102}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -174,7 +176,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 84, Col: 90}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 86, Col: 90}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -187,7 +189,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceType)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 85, Col: 68}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 87, Col: 68}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -206,7 +208,7 @@ func Progress(user User, progressData []ProgressItemData) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(item.EpubCFI)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 93, Col: 65}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 95, Col: 65}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
-41
View File
@@ -23,21 +23,6 @@ type CollectionData struct {
Icon string
}
type CollectionDetailData struct {
ID string
Name string
Description string
Color string
Icon string
}
type BookData struct {
MediaItemID string
Title string
Author string
CoverImagePath string
}
type LibraryData struct {
ID string
Name string
@@ -45,17 +30,6 @@ type LibraryData struct {
TypeName string
}
type DeviceData struct {
ID string
DeviceName string
DeviceType string
SyncEnabled bool
AutoSync bool
SyncFrequency int32
LastSync string
LastSeen string
}
type PendingRegistrationData struct {
RegistrationID string
DeviceName string
@@ -96,21 +70,6 @@ type DeviceShelfMappingData struct {
CreatedAt string
}
type ProgressItemData struct {
MediaItemID string
Title string
Author string
CoverImagePath string
CurrentPage int32
TotalPages int32
ProgressPercentage float64
LastUpdated string
DeviceName string
DeviceType string
DeviceIcon string
EpubCFI string
}
type UnlinkedBookData struct {
ProgressID string
DeviceID string