feat(ui): hide management controls for system collections
System collections (Not Started, Continue Reading, etc.) compute their contents dynamically from reading_progress, so manual add/remove has no effect. Hide the search bar, Remove Selected button, Add Books button, per-card checkboxes, and Remove buttons when the collection is system, making the page visually read-only. - Add IsSystem bool to CollectionData, populated from the database is_system_collection flag. - Add data-is-system to #collection-data so the JS renderer can also conditionally omit controls on library switch. - Wrap toolbar controls, book picker modal, card checkboxes, and remove buttons in if !collection.IsSystem in the template.
This commit is contained in:
+57
-48
@@ -139,33 +139,35 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
<h2 class="text-lg font-bold tracking-tight" style="color: var(--text-primary)">Books in this Collection</h2>
|
||||
<span x-show="selectedBooks.length > 0" x-text="selectedBooks.length + ' selected'" class="badge" style="display: none; background-color: var(--accent); color: var(--bg-primary);"></span>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 items-center">
|
||||
<div class="flex-1 min-w-[200px] max-w-md">
|
||||
<input
|
||||
type="text"
|
||||
id="collection-search"
|
||||
placeholder="Search within collection..."
|
||||
@input="filterCollectionBooks()"
|
||||
class="input"
|
||||
/>
|
||||
if !collection.IsSystem {
|
||||
<div class="flex flex-wrap gap-2 items-center">
|
||||
<div class="flex-1 min-w-[200px] max-w-md">
|
||||
<input
|
||||
type="text"
|
||||
id="collection-search"
|
||||
placeholder="Search within collection..."
|
||||
@input="filterCollectionBooks()"
|
||||
class="input"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@click="requestBulkRemove()"
|
||||
:disabled="selectedBooks.length === 0"
|
||||
:class="selectedBooks.length === 0 ? 'opacity-50 cursor-not-allowed' : ''"
|
||||
class="btn btn-danger"
|
||||
>
|
||||
@Icon("trash", "h-4 w-4")
|
||||
<span>Remove Selected</span>
|
||||
</button>
|
||||
<button
|
||||
@click="$store.bookPicker.open()"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
@Icon("plus", "h-4 w-4")
|
||||
<span>Add Books</span>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
@click="requestBulkRemove()"
|
||||
:disabled="selectedBooks.length === 0"
|
||||
:class="selectedBooks.length === 0 ? 'opacity-50 cursor-not-allowed' : ''"
|
||||
class="btn btn-danger"
|
||||
>
|
||||
@Icon("trash", "h-4 w-4")
|
||||
<span>Remove Selected</span>
|
||||
</button>
|
||||
<button
|
||||
@click="$store.bookPicker.open()"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
@Icon("plus", "h-4 w-4")
|
||||
<span>Add Books</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div id="books-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
if len(books) == 0 {
|
||||
@@ -174,16 +176,18 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
for _, book := range books {
|
||||
<div class="card p-4 rounded-2xl collection-book-card" data-title={ book.Title } data-author={ book.Author } data-media-id={ book.MediaItemID }>
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 pt-1">
|
||||
<label class="flex items-center cursor-pointer p-2 -m-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="w-5 h-5"
|
||||
:checked="selectedBooks.includes('{ book.MediaItemID }')"
|
||||
@change="toggleSelection('{ book.MediaItemID }')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
if !collection.IsSystem {
|
||||
<div class="flex-shrink-0 pt-1">
|
||||
<label class="flex items-center cursor-pointer p-2 -m-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="w-5 h-5"
|
||||
:checked="selectedBooks.includes('{ book.MediaItemID }')"
|
||||
@change="toggleSelection('{ book.MediaItemID }')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<div class="flex-1 min-w-0">
|
||||
<a href={ "/media/" + book.MediaItemID }>
|
||||
<h3 class="font-semibold text-lg mb-1 line-clamp-2 hover:underline" style="color: var(--text-primary)">
|
||||
@@ -215,22 +219,25 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 pt-3 border-t" style="border-color: var(--border);">
|
||||
<button
|
||||
@click="requestRemoveBook('{ book.MediaItemID }')"
|
||||
class="btn btn-secondary w-full"
|
||||
>
|
||||
@Icon("trash", "h-4 w-4")
|
||||
<span>Remove from Collection</span>
|
||||
</button>
|
||||
</div>
|
||||
if !collection.IsSystem {
|
||||
<div class="mt-3 pt-3 border-t" style="border-color: var(--border);">
|
||||
<button
|
||||
@click="requestRemoveBook('{ book.MediaItemID }')"
|
||||
class="btn btn-secondary w-full"
|
||||
>
|
||||
@Icon("trash", "h-4 w-4")
|
||||
<span>Remove from Collection</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
x-data="bookPicker"
|
||||
x-show="$store.bookPicker.isOpen"
|
||||
if !collection.IsSystem {
|
||||
<div
|
||||
x-data="bookPicker"
|
||||
x-show="$store.bookPicker.isOpen"
|
||||
@keyup.escape.window="$store.bookPicker.close()"
|
||||
@click.self="$store.bookPicker.close()"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
||||
@@ -347,6 +354,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div
|
||||
x-show="showConfirm"
|
||||
@click.self="closeConfirm()"
|
||||
@@ -374,6 +382,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
id="collection-data"
|
||||
data-id={ collection.ID }
|
||||
data-library-id={ libraryID }
|
||||
data-is-system={ collection.IsSystem }
|
||||
style="display: none;"
|
||||
></div>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user