fix: Dashboard modal and slider library-specific behavior
Fix multiple issues with dashboard customization modal and slider not working correctly per library. Frontend changes in web/src/dashboard.ts: - Fix openDashboardSettings() to use current library ID - Add library_id parameter to dashboard preferences API call - Show toast error message on API failure instead of opening modal - Prevent opening modal with stale/inaccurate data - Fix slider query parameter mismatch - Change from 'libraryId' to 'library_id' to match backend API - Fix DOM query from collectionList.querySelector to document.querySelector - Ensure slider targets correct input element - Fix saveDashboardSettings() to refresh current library - Fetch current library data before saving preferences - Use library_id from current library, not from URL - Show toast error message on save failure - Keep modal open on error for user to retry - Add localStorage persistence for selected library - Store selectedLibrary in localStorage after switching - Enables persistence across page refreshes - Improve switchLibrary() with fade transitions - Add fade-out (150ms) before data fetch - Add fade-in (300ms) after rendering new library - Provide smooth visual feedback during library switches - Apply preferences dynamically to modal - Use applyPreferencesToModal() to update slider and toggles - Ensure modal reflects current library's settings Backend changes in internal/router/dashboard.go: - Update GetDashboardPreferences to use library_id query parameter - Matches frontend API call parameter naming Template changes in templates/dashboard.templ: - Remove duplicate renderDashboardCollections() inline script - Functionality now handled by dashboard.ts These fixes ensure that: 1. Dashboard settings work correctly per library 2. Slider reflects and updates the correct library's item limit 3. Toggles show accurate visibility state for each library 4. Library switches provide smooth visual feedback 5. Errors are properly surfaced to users via toast messages
This commit is contained in:
@@ -8,6 +8,7 @@ func registerDashboardRoutes(cfg *Config) {
|
|||||||
|
|
||||||
dashboard := protected.Group("/dashboard")
|
dashboard := protected.Group("/dashboard")
|
||||||
dashboard.GET("/sections", cfg.DashboardHandler.GetSections)
|
dashboard.GET("/sections", cfg.DashboardHandler.GetSections)
|
||||||
|
dashboard.GET("/preferences", cfg.DashboardHandler.GetPreferences)
|
||||||
dashboard.PUT("/preferences", cfg.DashboardHandler.UpdatePreferences)
|
dashboard.PUT("/preferences", cfg.DashboardHandler.UpdatePreferences)
|
||||||
dashboard.POST("/restore-system-collection", cfg.DashboardHandler.RestoreSystemCollection)
|
dashboard.POST("/restore-system-collection", cfg.DashboardHandler.RestoreSystemCollection)
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-20
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
templ Dashboard(user User, sections []handlers.SectionData, libData []LibraryData, currentLibraryID string, errorMessage string) {
|
templ Dashboard(user User, sections []handlers.SectionData, allSections []handlers.SectionData, libData []LibraryData, currentLibraryID string, hiddenCollections []string, itemsPerSection int, errorMessage string) {
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -31,7 +31,6 @@ templ Dashboard(user User, sections []handlers.SectionData, libData []LibraryDat
|
|||||||
name="library_id"
|
name="library_id"
|
||||||
class="px-4 py-2 rounded-lg border focus:ring-2 focus:ring-blue-500"
|
class="px-4 py-2 rounded-lg border focus:ring-2 focus:ring-blue-500"
|
||||||
style="background-color: var(--bg-secondary); color: var(--text-primary);"
|
style="background-color: var(--bg-secondary); color: var(--text-primary);"
|
||||||
data-action="switch-library"
|
|
||||||
>
|
>
|
||||||
for _, lib := range libData {
|
for _, lib := range libData {
|
||||||
if lib.ID == currentLibraryID {
|
if lib.ID == currentLibraryID {
|
||||||
@@ -76,7 +75,7 @@ templ Dashboard(user User, sections []handlers.SectionData, libData []LibraryDat
|
|||||||
}
|
}
|
||||||
</main>
|
</main>
|
||||||
<!-- Dashboard Settings Modal -->
|
<!-- Dashboard Settings Modal -->
|
||||||
@DashboardSettingsModal(sections)
|
@DashboardSettingsModal(allSections, hiddenCollections, itemsPerSection)
|
||||||
@ErrorToast(errorMessage)
|
@ErrorToast(errorMessage)
|
||||||
<script src="/static/woodPanelingInit.js"></script>
|
<script src="/static/woodPanelingInit.js"></script>
|
||||||
</body>
|
</body>
|
||||||
@@ -158,7 +157,7 @@ templ CollectionCarousel(section handlers.SectionData) {
|
|||||||
|
|
||||||
templ BookCard(item handlers.BookInfo) {
|
templ BookCard(item handlers.BookInfo) {
|
||||||
<div
|
<div
|
||||||
class="book-card flex-shrink-0 w-32 snap-start cursor-pointer
|
class="book-card flex-shrink-0 w-36 rounded-lg overflow-hidden snap-start cursor-pointer
|
||||||
transition-transform duration-200 hover:scale-105"
|
transition-transform duration-200 hover:scale-105"
|
||||||
data-action="view-book"
|
data-action="view-book"
|
||||||
data-book-id={ item.MediaItemID }
|
data-book-id={ item.MediaItemID }
|
||||||
@@ -167,7 +166,7 @@ templ BookCard(item handlers.BookInfo) {
|
|||||||
aria-label={ "View " + item.Title }
|
aria-label={ "View " + item.Title }
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="aspect-[2/3] rounded-lg overflow-hidden shadow-lg mb-2
|
class="aspect-[2/3] overflow-hidden shadow-lg
|
||||||
bg-gradient-to-br from-gray-700 to-gray-900"
|
bg-gradient-to-br from-gray-700 to-gray-900"
|
||||||
>
|
>
|
||||||
if item.CoverImagePath != "" {
|
if item.CoverImagePath != "" {
|
||||||
@@ -186,18 +185,20 @@ templ BookCard(item handlers.BookInfo) {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<h3 class="font-semibold text-sm line-clamp-2" style="color: var(--text-primary)">
|
<div class="book-card-text px-2 py-1 bg-[color-mix(in_srgb,var(--wood-border)_60%,transparent)]">
|
||||||
{ item.Title }
|
<h3 class="font-semibold text-base line-clamp-2" style="color: var(--text-primary)">
|
||||||
</h3>
|
{ item.Title }
|
||||||
if item.Author != "" {
|
</h3>
|
||||||
<p class="text-xs line-clamp-1" style="color: var(--text-secondary)">
|
if item.Author != "" {
|
||||||
{ item.Author }
|
<p class="text-sm line-clamp-1" style="color: var(--text-secondary)">
|
||||||
</p>
|
{ item.Author }
|
||||||
}
|
</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ DashboardSettingsModal(sections []handlers.SectionData) {
|
templ DashboardSettingsModal(sections []handlers.SectionData, hiddenCollections []string, itemsPerSection int) {
|
||||||
<div
|
<div
|
||||||
id="dashboard-settings-modal"
|
id="dashboard-settings-modal"
|
||||||
class="hidden fixed inset-0 z-50 flex items-center justify-center"
|
class="hidden fixed inset-0 z-50 flex items-center justify-center"
|
||||||
@@ -256,9 +257,9 @@ templ DashboardSettingsModal(sections []handlers.SectionData) {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="sr-only peer"
|
class="sr-only peer"
|
||||||
checked
|
if !ContainsString(hiddenCollections, section.ID) {
|
||||||
data-action="toggle-collection-visibility"
|
checked
|
||||||
data-collection-id={ section.ID }
|
}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer
|
class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer
|
||||||
@@ -275,16 +276,16 @@ templ DashboardSettingsModal(sections []handlers.SectionData) {
|
|||||||
<!-- Items Per Section Slider -->
|
<!-- Items Per Section Slider -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
|
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
|
||||||
Items per Collection: <span id="items-count-display" class="font-bold">20</span>
|
Items per Collection: <span id="items-count-display" class="font-bold">{ itemsPerSection }</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="10"
|
min="10"
|
||||||
max="50"
|
max="50"
|
||||||
step="5"
|
step="5"
|
||||||
value="20"
|
value={ itemsPerSection }
|
||||||
class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"
|
class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"
|
||||||
data-action="update-items-count"
|
data-input-action="update-items-count"
|
||||||
target="items-count-display"
|
target="items-count-display"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData, currentLibraryID string, errorMessage string) templ.Component {
|
func Dashboard(user User, sections []handlers.SectionData, allSections []handlers.SectionData, libData []LibraryData, currentLibraryID string, hiddenCollections []string, itemsPerSection int, errorMessage string) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
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
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
@@ -42,7 +42,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<!-- Sticky Library Selector --><div class=\"sticky top-0 z-40 bg-opacity-95 backdrop-blur border-b\" style=\"background-color: var(--bg-primary);\"><div class=\"w-full px-4 py-3 flex items-center justify-between\"><div class=\"flex items-center gap-4\"><label class=\"text-sm font-medium\" style=\"color: var(--text-secondary)\">Library:</label> <select id=\"library-select\" name=\"library_id\" class=\"px-4 py-2 rounded-lg border focus:ring-2 focus:ring-blue-500\" style=\"background-color: var(--bg-secondary); color: var(--text-primary);\" data-action=\"switch-library\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<!-- Sticky Library Selector --><div class=\"sticky top-0 z-40 bg-opacity-95 backdrop-blur border-b\" style=\"background-color: var(--bg-primary);\"><div class=\"w-full px-4 py-3 flex items-center justify-between\"><div class=\"flex items-center gap-4\"><label class=\"text-sm font-medium\" style=\"color: var(--text-secondary)\">Library:</label> <select id=\"library-select\" name=\"library_id\" class=\"px-4 py-2 rounded-lg border focus:ring-2 focus:ring-blue-500\" style=\"background-color: var(--bg-secondary); color: var(--text-primary);\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
var templ_7745c5c3_Var2 string
|
var templ_7745c5c3_Var2 string
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(lib.ID)
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(lib.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 38, Col: 31}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 37, Col: 31}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -68,7 +68,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(lib.Name)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(lib.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 38, Col: 53}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 37, Col: 53}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -86,7 +86,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(lib.ID)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(lib.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 40, Col: 31}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 39, Col: 31}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -99,7 +99,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(lib.Name)
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(lib.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 40, Col: 44}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 39, Col: 44}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -125,7 +125,7 @@ func Dashboard(user User, sections []handlers.SectionData, libData []LibraryData
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = DashboardSettingsModal(sections).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = DashboardSettingsModal(allSections, hiddenCollections, itemsPerSection).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 89, Col: 33}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 88, Col: 33}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -182,7 +182,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(section.IsSystem)
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(section.IsSystem)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 90, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 89, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -195,7 +195,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(section.Icon)
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(section.Icon)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 95, Col: 41}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 94, Col: 41}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -208,7 +208,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var10 string
|
var templ_7745c5c3_Var10 string
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 97, Col: 85}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 96, Col: 85}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -226,7 +226,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var11 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(section.Description)
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(section.Description)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 99, Col: 83}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 98, Col: 83}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -249,7 +249,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var12 templ.SafeURL
|
var templ_7745c5c3_Var12 templ.SafeURL
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(section.ViewAllURL)
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(section.ViewAllURL)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 105, Col: 30}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 104, Col: 30}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -267,7 +267,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var13 string
|
var templ_7745c5c3_Var13 string
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 121, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 120, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -280,7 +280,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var14 string
|
var templ_7745c5c3_Var14 string
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs("carousel-track-" + section.ID)
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs("carousel-track-" + section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 128, Col: 39}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 127, Col: 39}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -309,7 +309,7 @@ func CollectionCarousel(section handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var15 string
|
var templ_7745c5c3_Var15 string
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 149, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 148, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -344,14 +344,14 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
templ_7745c5c3_Var16 = templ.NopComponent
|
templ_7745c5c3_Var16 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"book-card flex-shrink-0 w-32 snap-start cursor-pointer\n\t\t\t\t\ttransition-transform duration-200 hover:scale-105\" data-action=\"view-book\" data-book-id=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"book-card flex-shrink-0 w-36 rounded-lg overflow-hidden snap-start cursor-pointer\n\t\t\t\t\ttransition-transform duration-200 hover:scale-105\" data-action=\"view-book\" data-book-id=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var17 string
|
var templ_7745c5c3_Var17 string
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(item.MediaItemID)
|
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(item.MediaItemID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 164, Col: 33}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 163, Col: 33}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -364,13 +364,13 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
var templ_7745c5c3_Var18 string
|
var templ_7745c5c3_Var18 string
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs("View " + item.Title)
|
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs("View " + item.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 167, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 166, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\"><div class=\"aspect-[2/3] rounded-lg overflow-hidden shadow-lg mb-2\n\t\t\t\t\t\tbg-gradient-to-br from-gray-700 to-gray-900\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\"><div class=\"aspect-[2/3] overflow-hidden shadow-lg\n\t\t\t\t\t\tbg-gradient-to-br from-gray-700 to-gray-900\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -382,7 +382,7 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
var templ_7745c5c3_Var19 string
|
var templ_7745c5c3_Var19 string
|
||||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(item.CoverImagePath)
|
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(item.CoverImagePath)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 175, Col: 30}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 174, Col: 30}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -395,7 +395,7 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
var templ_7745c5c3_Var20 string
|
var templ_7745c5c3_Var20 string
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 176, Col: 21}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 175, Col: 21}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -413,7 +413,7 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
var templ_7745c5c3_Var21 string
|
var templ_7745c5c3_Var21 string
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 184, Col: 21}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 183, Col: 21}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -424,14 +424,14 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</div><h3 class=\"font-semibold text-sm line-clamp-2\" style=\"color: var(--text-primary)\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</div><div class=\"book-card-text px-2 py-1 bg-[color-mix(in_srgb,var(--wood-border)_60%,transparent)]\"><h3 class=\"font-semibold text-base line-clamp-2\" style=\"color: var(--text-primary)\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var22 string
|
var templ_7745c5c3_Var22 string
|
||||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 190, Col: 15}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 190, Col: 16}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -442,14 +442,14 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
if item.Author != "" {
|
if item.Author != "" {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<p class=\"text-xs line-clamp-1\" style=\"color: var(--text-secondary)\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<p class=\"text-sm line-clamp-1\" style=\"color: var(--text-secondary)\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var23 string
|
var templ_7745c5c3_Var23 string
|
||||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(item.Author)
|
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(item.Author)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 194, Col: 17}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 194, Col: 18}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -460,7 +460,7 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -468,7 +468,7 @@ func BookCard(item handlers.BookInfo) templ.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
func DashboardSettingsModal(sections []handlers.SectionData, hiddenCollections []string, itemsPerSection int) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
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
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
@@ -501,7 +501,7 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var25 string
|
var templ_7745c5c3_Var25 string
|
||||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 228, Col: 37}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 229, Col: 37}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -514,7 +514,7 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var26 string
|
var templ_7745c5c3_Var26 string
|
||||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%v", section.IsSystem))
|
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%v", section.IsSystem))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 229, Col: 58}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 230, Col: 58}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -527,7 +527,7 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var27 string
|
var templ_7745c5c3_Var27 string
|
||||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(section.Icon)
|
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(section.Icon)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 235, Col: 43}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 236, Col: 43}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -540,7 +540,7 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var28 string
|
var templ_7745c5c3_Var28 string
|
||||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
|
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 237, Col: 85}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 238, Col: 85}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -568,7 +568,7 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
var templ_7745c5c3_Var29 string
|
var templ_7745c5c3_Var29 string
|
||||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 247, Col: 42}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 248, Col: 42}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -579,25 +579,48 @@ func DashboardSettingsModal(sections []handlers.SectionData) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<label class=\"relative inline-flex items-center cursor-pointer\"><input type=\"checkbox\" class=\"sr-only peer\" checked data-action=\"toggle-collection-visibility\" data-collection-id=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<label class=\"relative inline-flex items-center cursor-pointer\"><input type=\"checkbox\" class=\"sr-only peer\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var30 string
|
if !ContainsString(hiddenCollections, section.ID) {
|
||||||
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(section.ID)
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, " checked")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `dashboard.templ`, Line: 261, Col: 40}
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "><div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer\n\t\t\t\t\t\t\t\t\t\t peer-checked:after:translate-x-full peer-checked:after:border-white\n\t\t\t\t\t\t\t\t\t\t after:content-[''] after:absolute after:top-[2px] after:left-[2px]\n\t\t\t\t\t\t\t\t\t\t after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all\n\t\t\t\t\t\t\t\t\t\t peer-checked:bg-blue-600\"></div></label></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\"><div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer\n\t\t\t\t\t\t\t\t\t\t peer-checked:after:translate-x-full peer-checked:after:border-white\n\t\t\t\t\t\t\t\t\t\t after:content-[''] after:absolute after:top-[2px] after:left-[2px]\n\t\t\t\t\t\t\t\t\t\t after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all\n\t\t\t\t\t\t\t\t\t\t peer-checked:bg-blue-600\"></div></label></div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "</div><!-- Items Per Section Slider --><div class=\"mb-6\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Items per Collection: <span id=\"items-count-display\" class=\"font-bold\">20</span></label> <input type=\"range\" min=\"10\" max=\"50\" step=\"5\" value=\"20\" class=\"w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer\" data-action=\"update-items-count\" target=\"items-count-display\"></div><div class=\"flex justify-end gap-3\"><button data-action=\"close-dashboard-settings\" class=\"px-4 py-2 rounded-lg border hover:bg-gray-700 transition-colors\" style=\"border-color: var(--border); color: var(--text-primary);\">Cancel</button> <button data-action=\"save-dashboard-settings\" class=\"px-4 py-2 rounded-lg text-white font-medium hover:opacity-90 transition-opacity\" style=\"background-color: var(--accent);\">Save Changes</button></div></div></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</div><!-- Items Per Section Slider --><div class=\"mb-6\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Items per Collection: <span id=\"items-count-display\" class=\"font-bold\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var30 string
|
||||||
|
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(itemsPerSection)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 279, Col: 93}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</span></label> <input type=\"range\" min=\"10\" max=\"50\" step=\"5\" value=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var31 string
|
||||||
|
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(itemsPerSection)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/dashboard.templ`, Line: 286, Col: 28}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" class=\"w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer\" data-input-action=\"update-items-count\" target=\"items-count-display\"></div><div class=\"flex justify-end gap-3\"><button data-action=\"close-dashboard-settings\" class=\"px-4 py-2 rounded-lg border hover:bg-gray-700 transition-colors\" style=\"border-color: var(--border); color: var(--text-primary);\">Cancel</button> <button data-action=\"save-dashboard-settings\" class=\"px-4 py-2 rounded-lg text-white font-medium hover:opacity-90 transition-opacity\" style=\"background-color: var(--accent);\">Save Changes</button></div></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
+181
-47
@@ -13,51 +13,103 @@ function scrollCarousel(collectionId: string, direction: number): void {
|
|||||||
track.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
track.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDashboardSettings(): void {
|
async function openDashboardSettings(): Promise<void> {
|
||||||
|
const librarySelect = document.getElementById(
|
||||||
|
"library-select",
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
const libraryId = librarySelect?.value;
|
||||||
|
if (!libraryId) {
|
||||||
|
(window as any).showToast.error("No library selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/dashboard/preferences?library_id=${libraryId}`,
|
||||||
|
{
|
||||||
|
headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const prefs = await response.json();
|
||||||
|
applyPreferencesToModal(prefs);
|
||||||
|
} else {
|
||||||
|
(window as any).showToast.error("Failed to load library preferences");
|
||||||
|
console.error("API Error:", response.status, response.statusText);
|
||||||
|
return; // Don't open modal with stale data.
|
||||||
|
}
|
||||||
|
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"dashboard-settings-modal",
|
"dashboard-settings-modal",
|
||||||
) as HTMLElement;
|
) as HTMLElement;
|
||||||
if (modal) {
|
modal?.classList.remove("hidden");
|
||||||
modal.classList.remove("hidden");
|
}
|
||||||
|
|
||||||
|
function applyPreferencesToModal(prefs: any): void {
|
||||||
|
const collectionList = document.getElementById(
|
||||||
|
"collection-list",
|
||||||
|
) as HTMLElement;
|
||||||
|
if (!collectionList) return;
|
||||||
|
|
||||||
|
const slider = document.querySelector(
|
||||||
|
'#dashboard-settings-modal input[type="range"]',
|
||||||
|
) as HTMLInputElement;
|
||||||
|
const display = document.getElementById("items-count-display") as HTMLElement;
|
||||||
|
if (slider && display) {
|
||||||
|
slider.value = String(prefs.items_per_section);
|
||||||
|
display.textContent = String(prefs.items_per_section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update checkboxes and reorder items
|
||||||
|
const items = collectionList.querySelectorAll(
|
||||||
|
"[data-collection-id]",
|
||||||
|
) as NodeListOf<HTMLElement>;
|
||||||
|
const orderedItems: HTMLElement[] = [];
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
const collectionId = item.dataset.collectionId;
|
||||||
|
const checkbox = item.querySelector(
|
||||||
|
'input[type="checkbox"]',
|
||||||
|
) as HTMLInputElement;
|
||||||
|
|
||||||
|
// Update checkbox state
|
||||||
|
const isHidden = prefs.hidden_collections.includes(collectionId);
|
||||||
|
if (checkbox) checkbox.checked = !isHidden;
|
||||||
|
|
||||||
|
// Sort according to collection_order
|
||||||
|
const orderIndex = prefs.collection_order.indexOf(collectionId);
|
||||||
|
if (orderIndex !== -1) {
|
||||||
|
orderedItems[orderIndex] = item;
|
||||||
|
} else {
|
||||||
|
orderedItems.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reorder in DOM
|
||||||
|
orderedItems.forEach((item) => collectionList.appendChild(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDashboardSettings(): void {
|
function closeDashboardSettings(): void {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"dashboard-settings-modal",
|
"dashboard-settings-modal",
|
||||||
) as HTMLElement;
|
) as HTMLElement;
|
||||||
if (modal) {
|
modal?.classList.add("hidden");
|
||||||
modal.classList.add("hidden");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleCollectionVisibility(collectionId: string): void {
|
|
||||||
const checkbox = document.querySelector(
|
|
||||||
`input[data-collection-id="${collectionId}"]`,
|
|
||||||
) as HTMLInputElement;
|
|
||||||
if (checkbox) {
|
|
||||||
checkbox.checked = !checkbox.checked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveDashboardSettings(): Promise<void> {
|
async function saveDashboardSettings(): Promise<void> {
|
||||||
const collectionList = document.getElementById(
|
const collectionList = document.getElementById(
|
||||||
"collection-list",
|
"collection-list",
|
||||||
) as HTMLElement;
|
) as HTMLElement;
|
||||||
if (!collectionList) return;
|
if (!collectionList) return;
|
||||||
|
|
||||||
const collectionItems = collectionList.querySelectorAll(
|
const collectionItems = collectionList.querySelectorAll(
|
||||||
"[data-collection-id]",
|
"[data-collection-id]",
|
||||||
) as NodeListOf<HTMLElement>;
|
) as NodeListOf<HTMLElement>;
|
||||||
const hiddenCollections: string[] = [];
|
const hiddenCollections: string[] = [];
|
||||||
const collectionOrder: string[] = [];
|
const collectionOrder: string[] = [];
|
||||||
|
|
||||||
collectionItems.forEach((item) => {
|
collectionItems.forEach((item) => {
|
||||||
const collectionId = item.dataset.collectionId;
|
const collectionId = item.dataset.collectionId;
|
||||||
const checkbox = item.querySelector(
|
const checkbox = item.querySelector(
|
||||||
'input[type="checkbox"]',
|
'input[type="checkbox"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
|
|
||||||
if (collectionId) {
|
if (collectionId) {
|
||||||
collectionOrder.push(collectionId);
|
collectionOrder.push(collectionId);
|
||||||
if (checkbox && !checkbox.checked) {
|
if (checkbox && !checkbox.checked) {
|
||||||
@@ -65,31 +117,52 @@ async function saveDashboardSettings(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const itemsPerCollection =
|
const itemsPerCollection =
|
||||||
(document.querySelector("#items-count-display") as HTMLElement)
|
(document.querySelector("#items-count-display") as HTMLElement)
|
||||||
?.textContent || "20";
|
?.textContent || "20";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const librarySelect = document.getElementById(
|
||||||
|
"library-select",
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
const libraryId = librarySelect?.value || "";
|
||||||
const response = await (window as any).api.put("/dashboard/preferences", {
|
const response = await (window as any).api.put("/dashboard/preferences", {
|
||||||
library_id:
|
library_id: libraryId,
|
||||||
new URLSearchParams(window.location.search).get("library_id") || "",
|
|
||||||
hidden_collections: hiddenCollections,
|
hidden_collections: hiddenCollections,
|
||||||
collection_order: collectionOrder,
|
collection_order: collectionOrder,
|
||||||
items_per_section: parseInt(itemsPerCollection),
|
items_per_section: parseInt(itemsPerCollection),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
(window as any).showToast.success("Dashboard settings saved");
|
(window as any).showToast.success("Dashboard settings saved");
|
||||||
closeDashboardSettings();
|
closeDashboardSettings();
|
||||||
window.location.reload();
|
// Fetch updated sections and re-render (like switchLibrary does)
|
||||||
|
if (!libraryId) {
|
||||||
|
(window as any).showToast.error(
|
||||||
|
"Unable to refresh dashboard - no library selected",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sectionResponse = await fetch(
|
||||||
|
`/api/dashboard/sections?library_id=${libraryId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (sectionResponse.ok) {
|
||||||
|
const data = await sectionResponse.json();
|
||||||
|
renderDashboardCollections(data.sections);
|
||||||
|
localStorage.setItem("selectedLibraryId", libraryId);
|
||||||
|
} else {
|
||||||
|
(window as any).showToast.error("Failed to refresh sections");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
(window as any).showToast.error("Failed to save settings");
|
(window as any).showToast.error("Failed to save settings");
|
||||||
console.error("Save dashboard settings error:", error);
|
console.error("Save dashboard settings error:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function restoreSystemCollection(
|
async function restoreSystemCollection(
|
||||||
collectionName: string,
|
collectionName: string,
|
||||||
collectionTitle: string,
|
collectionTitle: string,
|
||||||
@@ -130,9 +203,17 @@ async function switchLibrary(libraryId: string): Promise<void> {
|
|||||||
|
|
||||||
if (!container || !loading) return;
|
if (!container || !loading) return;
|
||||||
|
|
||||||
loading.classList.remove("hidden");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Step 1: Fade out current content (150ms)
|
||||||
|
container.classList.add("opacity-0", "transition-opacity", "duration-150");
|
||||||
|
|
||||||
|
// Wait for fade-out to complete
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||||
|
|
||||||
|
// Step 2: Show loading spinner
|
||||||
|
loading.classList.remove("hidden");
|
||||||
|
|
||||||
|
// Step 3: Fetch new data
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/dashboard/sections?library_id=${libraryId}`,
|
`/api/dashboard/sections?library_id=${libraryId}`,
|
||||||
{
|
{
|
||||||
@@ -149,6 +230,7 @@ async function switchLibrary(libraryId: string): Promise<void> {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
renderDashboardCollections(data.sections);
|
renderDashboardCollections(data.sections);
|
||||||
|
localStorage.setItem("selectedLibrary", libraryId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
(window as any).showToast.error("Failed to load library");
|
(window as any).showToast.error("Failed to load library");
|
||||||
console.error("Switch library error:", error);
|
console.error("Switch library error:", error);
|
||||||
@@ -166,6 +248,7 @@ function renderDashboardCollections(sections: SectionData[]): void {
|
|||||||
// Preserve wood paneling attribute
|
// Preserve wood paneling attribute
|
||||||
const currentWood = container.getAttribute("data-wood");
|
const currentWood = container.getAttribute("data-wood");
|
||||||
|
|
||||||
|
// Replace content while still invisible (opacity-0 from switchLibrary)
|
||||||
container.innerHTML = sections
|
container.innerHTML = sections
|
||||||
.map(
|
.map(
|
||||||
(section) => `
|
(section) => `
|
||||||
@@ -223,6 +306,20 @@ function renderDashboardCollections(sections: SectionData[]): void {
|
|||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
|
// Step 5: Fade in new content (300ms for smoother entrance)
|
||||||
|
container.classList.remove("duration-150");
|
||||||
|
container.classList.add("duration-300");
|
||||||
|
|
||||||
|
// Trigger reflow to ensure transition happens
|
||||||
|
void container.offsetHeight;
|
||||||
|
|
||||||
|
// Fade to visible
|
||||||
|
container.classList.remove("opacity-0");
|
||||||
|
|
||||||
|
// Clean up transition classes after animation completes
|
||||||
|
setTimeout(() => {
|
||||||
|
container.classList.remove("transition-opacity", "duration-300");
|
||||||
|
}, 300);
|
||||||
if (currentWood) {
|
if (currentWood) {
|
||||||
container.setAttribute("data-wood", currentWood);
|
container.setAttribute("data-wood", currentWood);
|
||||||
}
|
}
|
||||||
@@ -232,14 +329,14 @@ function renderBookCard(book: BookInfo): string {
|
|||||||
const coverUrl = book.cover_image_path || "/static/placeholder-book.svg";
|
const coverUrl = book.cover_image_path || "/static/placeholder-book.svg";
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="book-card flex-shrink-0 w-32 snap-start cursor-pointer
|
<div class="book-card flex-shrink-0 w-36 rounded-lg overflow-hidden snap-start cursor-pointer
|
||||||
transition-transform duration-200 hover:scale-105"
|
transition-transform duration-200 hover:scale-105"
|
||||||
data-action="view-book"
|
data-action="view-book"
|
||||||
data-book-id="${book.media_item_id}"
|
data-book-id="${book.media_item_id}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="button"
|
role="button"
|
||||||
aria-label="View ${book.title}">
|
aria-label="View ${book.title}">
|
||||||
<div class="aspect-[2/3] rounded-lg overflow-hidden shadow-lg mb-2
|
<div class="aspect-[2/3] overflow-hidden shadow-lg
|
||||||
bg-gradient-to-br from-gray-700 to-gray-900">
|
bg-gradient-to-br from-gray-700 to-gray-900">
|
||||||
<img src="${coverUrl}"
|
<img src="${coverUrl}"
|
||||||
alt="${book.title}"
|
alt="${book.title}"
|
||||||
@@ -247,10 +344,12 @@ function renderBookCard(book: BookInfo): string {
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
onerror="this.src='/static/placeholder-book.svg'">
|
onerror="this.src='/static/placeholder-book.svg'">
|
||||||
</div>
|
</div>
|
||||||
<h3 class="font-semibold text-sm line-clamp-2" style="color: var(--text-primary)">
|
<div class="book-card-text px-2 py-1 bg-[color-mix(in_srgb,var(--wood-border)_60%,transparent)]">
|
||||||
${book.title}
|
<h3 class="font-semibold text-base line-clamp-2" style="color: var(--text-primary)">
|
||||||
</h3>
|
${book.title}
|
||||||
${book.author ? `<p class="text-xs line-clamp-1" style="color: var(--text-secondary)">${book.author}</p>` : ""}
|
</h3>
|
||||||
|
${book.author ? `<p class="text-sm line-clamp-1" style="color: var(--text-secondary)">${book.author}</p>` : ""}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -259,14 +358,29 @@ function viewBook(bookId: string): void {
|
|||||||
console.log("View book:", bookId);
|
console.log("View book:", bookId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadPage(): void {
|
async function reloadPage(): Promise<void> {
|
||||||
window.location.reload();
|
//Get current library from dropdown
|
||||||
|
const librarySelect = document.getElementById(
|
||||||
|
"library-select",
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
const currentLibraryId = librarySelect?.value;
|
||||||
|
|
||||||
|
if (!currentLibraryId) {
|
||||||
|
(window as any).showToast.error("No library selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reuse switchLibrary logic - it handles the fade transition
|
||||||
|
await switchLibrary(currentLibraryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateItemsCount(input: HTMLInputElement, targetId: string): void {
|
function updateItemsCount(
|
||||||
const display = document.getElementById(targetId) as HTMLElement;
|
input: HTMLInputElement,
|
||||||
if (display) {
|
displayTarget: string,
|
||||||
display.textContent = input.value;
|
): void {
|
||||||
|
const displayElement = document.getElementById(displayTarget) as HTMLElement;
|
||||||
|
if (displayElement) {
|
||||||
|
displayElement.textContent = input.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,13 +456,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
closeDashboardSettings();
|
closeDashboardSettings();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "toggle-collection-visibility": {
|
|
||||||
const checkbox = target as HTMLInputElement;
|
|
||||||
const colId = checkbox.dataset.collectionId;
|
|
||||||
if (colId) toggleCollectionVisibility(colId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "save-dashboard-settings":
|
case "save-dashboard-settings":
|
||||||
saveDashboardSettings();
|
saveDashboardSettings();
|
||||||
break;
|
break;
|
||||||
@@ -379,7 +486,15 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
if (select.value) switchLibrary(select.value);
|
if (select.value) switchLibrary(select.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("input", (e: Event) => {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
const actionElem = target.closest("[data-input-action]") as HTMLElement;
|
||||||
|
const action = actionElem?.getAttribute("data-input-action");
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
case "update-items-count": {
|
case "update-items-count": {
|
||||||
const input = target as HTMLInputElement;
|
const input = target as HTMLInputElement;
|
||||||
const displayTarget = input.getAttribute("target");
|
const displayTarget = input.getAttribute("target");
|
||||||
@@ -388,4 +503,23 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Load saved library on page load
|
||||||
|
const librarySelect = document.getElementById(
|
||||||
|
"library-select",
|
||||||
|
) as HTMLSelectElement;
|
||||||
|
if (librarySelect) {
|
||||||
|
librarySelect.addEventListener("change", (e) => {
|
||||||
|
const target = e.target as HTMLSelectElement;
|
||||||
|
if (target.value) {
|
||||||
|
switchLibrary(target.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const savedLibrary = localStorage.getItem("selectedLibrary");
|
||||||
|
const currentLibrary = new URLSearchParams(window.location.search).get(
|
||||||
|
"library_id",
|
||||||
|
);
|
||||||
|
if (savedLibrary && savedLibrary !== currentLibrary) {
|
||||||
|
window.location.href = `/dashboard?library_id=${savedLibrary}`;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user