feat(web): update frontend TypeScript modules and API types
This commit updates the web frontend TypeScript modules: Core modules: - admin.ts: Admin panel functionality and user management - analytics.ts: Analytics dashboard and data visualization - api-explorer.ts: Interactive API documentation explorer - api.ts: Core API client with request/response handling - collections.ts: Book collection management UI - conflicts.ts: Sync conflict resolution interface - custom-section-builder.ts: Dynamic section builder for UI - docs.ts: Documentation viewer and navigation - dom.ts: DOM manipulation utilities and helpers - header.ts: Application header with navigation - library.ts: Library view and book grid management - linking.ts: Device-book linking interface - password_validation.ts: Client-side password strength validation - queue.ts: Device sync queue management UI - search.ts: Full-text search with Lunr integration - storage.ts: Local storage and cache management - theme.ts: Theme management and CSS variable updates - themeDropdown.ts: Theme selector dropdown component - toast.ts: Toast notification system - woodPaneling.ts: Visual theme effects - woodPanelingInit.ts: Visual effects initialization Type definitions: - api.d.ts: Updated TypeScript definitions for API responses These updates enhance the frontend with improved functionality for book management, device synchronization, and user experience.
This commit is contained in:
Vendored
+200
-185
@@ -11,75 +11,75 @@
|
||||
// Note: internal/handlers/search.go has an unused MediaItemSummary - ignore it
|
||||
// Used in: search.ts
|
||||
interface MediaItemSummary {
|
||||
id: string;
|
||||
library_id: string;
|
||||
title: string;
|
||||
author?: string;
|
||||
isbn?: string;
|
||||
description?: string;
|
||||
file_path: string;
|
||||
file_size?: number;
|
||||
mime_type?: string;
|
||||
cover_image_path?: string;
|
||||
series?: string;
|
||||
series_number?: number;
|
||||
tags?: string[];
|
||||
asin?: string;
|
||||
date_published?: string;
|
||||
publisher?: string;
|
||||
contributors?: string[];
|
||||
language?: string;
|
||||
edition?: string;
|
||||
page_count?: number;
|
||||
genre?: string;
|
||||
copyright_year?: number;
|
||||
goodreads_id?: string;
|
||||
openlibrary_id?: string;
|
||||
google_books_id?: string;
|
||||
added_by_admin_id?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
format_group: string;
|
||||
format_mimetype?: string;
|
||||
is_reflowable?: boolean;
|
||||
has_fixed_layout?: boolean;
|
||||
total_characters?: number;
|
||||
chapter_count?: number;
|
||||
entitlement_id?: string;
|
||||
revision_number?: number;
|
||||
kobo_content_id?: string;
|
||||
kobo_metadata?: string;
|
||||
tags_search?: string[];
|
||||
contributors_search?: string[];
|
||||
file_sha256?: string;
|
||||
opf_identifier?: string;
|
||||
opf_uuid?: string;
|
||||
hash_confidence?: string;
|
||||
library_name: string;
|
||||
library_type_name: string;
|
||||
id: string;
|
||||
library_id: string;
|
||||
title: string;
|
||||
author?: string;
|
||||
isbn?: string;
|
||||
description?: string;
|
||||
file_path: string;
|
||||
file_size?: number;
|
||||
mime_type?: string;
|
||||
cover_image_path?: string;
|
||||
series?: string;
|
||||
series_number?: number;
|
||||
tags?: string[];
|
||||
asin?: string;
|
||||
date_published?: string;
|
||||
publisher?: string;
|
||||
contributors?: string[];
|
||||
language?: string;
|
||||
edition?: string;
|
||||
page_count?: number;
|
||||
genre?: string;
|
||||
copyright_year?: number;
|
||||
goodreads_id?: string;
|
||||
openlibrary_id?: string;
|
||||
google_books_id?: string;
|
||||
added_by_admin_id?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
format_group: string;
|
||||
format_mimetype?: string;
|
||||
is_reflowable?: boolean;
|
||||
has_fixed_layout?: boolean;
|
||||
total_characters?: number;
|
||||
chapter_count?: number;
|
||||
entitlement_id?: string;
|
||||
revision_number?: number;
|
||||
kobo_content_id?: string;
|
||||
kobo_metadata?: string;
|
||||
tags_search?: string[];
|
||||
contributors_search?: string[];
|
||||
file_sha256?: string;
|
||||
opf_identifier?: string;
|
||||
opf_uuid?: string;
|
||||
hash_confidence?: string;
|
||||
library_name: string;
|
||||
library_type_name: string;
|
||||
}
|
||||
|
||||
// Matches handlers.CollectionData / CollectionResponse JSON response
|
||||
// Source: internal/handlers/collections.go:123-131 CollectionResponse
|
||||
// Used in: collections.ts
|
||||
interface CollectionData {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
color: string;
|
||||
icon: string;
|
||||
auto_assign_rules?: unknown;
|
||||
created_at: string;
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
color: string;
|
||||
icon: string;
|
||||
auto_assign_rules?: unknown;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
// Matches handlers.BookInfo JSON response (internal/handlers/collections.go:66-71)
|
||||
// JSON tags: media_item_id, title, author, cover_image_path
|
||||
// Used in: collections.templ (server-rendered), collections.ts
|
||||
interface BookInfo {
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
cover_image_path: string;
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
cover_image_path: string;
|
||||
}
|
||||
|
||||
// Dashboard type definitions
|
||||
@@ -87,237 +87,252 @@ interface BookInfo {
|
||||
// Source: handlers.SectionData in collections.go (lines 73-81)
|
||||
// Used in: dashboard API responses, TypeScript dashboard components
|
||||
interface SectionData {
|
||||
id: string;
|
||||
is_system: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
items: BookInfo[];
|
||||
view_all_url: string;
|
||||
priority: number;
|
||||
id: string;
|
||||
is_system: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
items: BookInfo[];
|
||||
view_all_url: string;
|
||||
priority: number;
|
||||
}
|
||||
|
||||
// Matches database.UserDashboardPreferences and dashboard preferences API
|
||||
// Source: internal/database/models.go:381-390
|
||||
// Used in: dashboard preferences API
|
||||
interface DashboardPreferences {
|
||||
library_id: string;
|
||||
hidden_collections: string[];
|
||||
collection_order: string[];
|
||||
items_per_section: number;
|
||||
library_id: string;
|
||||
hidden_collections: string[];
|
||||
collection_order: string[];
|
||||
items_per_section: number;
|
||||
}
|
||||
|
||||
// Matches handlers.UnlinkedBookData JSON response
|
||||
// Used in: unlinked_books.ts, unlinked_books.templ
|
||||
interface UnlinkedBookData {
|
||||
progress_id: string;
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: 'koreader' | 'kobo' | 'web';
|
||||
title_from_device: string;
|
||||
file_path: string;
|
||||
sha256: string;
|
||||
last_sync_time: string;
|
||||
confidence_score: number;
|
||||
potential_matches: PotentialMatchData[];
|
||||
progress_id: string;
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: "koreader" | "kobo" | "web";
|
||||
title_from_device: string;
|
||||
file_path: string;
|
||||
sha256: string;
|
||||
last_sync_time: string;
|
||||
confidence_score: number;
|
||||
potential_matches: PotentialMatchData[];
|
||||
}
|
||||
|
||||
interface PotentialMatchData {
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
confidence: number;
|
||||
cover_image_path?: string;
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
confidence: number;
|
||||
cover_image_path?: string;
|
||||
}
|
||||
|
||||
// Matches collection rule objects
|
||||
// Used in: collection_rules.ts
|
||||
interface CollectionRule {
|
||||
id: string;
|
||||
field: 'genre' | 'series' | 'author' | 'language' | 'publisher' | 'copyright_year' | 'tags';
|
||||
operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with' | 'greater_than' | 'less_than';
|
||||
value: string;
|
||||
enabled: boolean;
|
||||
priority: number;
|
||||
id: string;
|
||||
field:
|
||||
| "genre"
|
||||
| "series"
|
||||
| "author"
|
||||
| "language"
|
||||
| "publisher"
|
||||
| "copyright_year"
|
||||
| "tags";
|
||||
operator:
|
||||
| "equals"
|
||||
| "not_equals"
|
||||
| "contains"
|
||||
| "not_contains"
|
||||
| "starts_with"
|
||||
| "ends_with"
|
||||
| "greater_than"
|
||||
| "less_than";
|
||||
value: string;
|
||||
enabled: boolean;
|
||||
priority: number;
|
||||
}
|
||||
|
||||
// Matches API test rule responses
|
||||
// Used in: collection_rules.ts (test results)
|
||||
interface TestRuleMatch {
|
||||
title: string;
|
||||
author: string;
|
||||
cover_image_path?: string;
|
||||
title: string;
|
||||
author: string;
|
||||
cover_image_path?: string;
|
||||
}
|
||||
|
||||
// Matches handlers.SearchResponse (internal/handlers/search.go)
|
||||
interface SearchResponse {
|
||||
results: SearchBookResponse[];
|
||||
total: number;
|
||||
results: SearchBookResponse[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
interface SearchBookResponse {
|
||||
id: string;
|
||||
title: string;
|
||||
authors: SearchAuthor[];
|
||||
id: string;
|
||||
title: string;
|
||||
authors: SearchAuthor[];
|
||||
}
|
||||
|
||||
interface SearchAuthor {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
}
|
||||
|
||||
// Matches AuthResponse (internal/handlers/auth.go:59-65)
|
||||
interface AuthResponse {
|
||||
access_token: string;
|
||||
refresh_token?: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
user: UserProfile;
|
||||
access_token: string;
|
||||
refresh_token?: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
user: UserProfile;
|
||||
}
|
||||
|
||||
interface UserProfile {
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
first_name?: string;
|
||||
last_name?: string;
|
||||
role: string;
|
||||
theme?: string;
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
first_name?: string;
|
||||
last_name?: string;
|
||||
role: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
// Matches handlers.ReadingStatsResponse (internal/handlers/analytics.go:26-35)
|
||||
// Used in: analytics.ts
|
||||
interface ReadingStatsResponse {
|
||||
total_books_read: number;
|
||||
total_pages_read: number;
|
||||
total_reading_time_minutes: number;
|
||||
average_session_time_minutes: number;
|
||||
longest_session_minutes: number;
|
||||
most_active_day_of_week: string;
|
||||
completion_rate: number;
|
||||
daily_reading_minutes: DailyReading[];
|
||||
total_books_read: number;
|
||||
total_pages_read: number;
|
||||
total_reading_time_minutes: number;
|
||||
average_session_time_minutes: number;
|
||||
longest_session_minutes: number;
|
||||
most_active_day_of_week: string;
|
||||
completion_rate: number;
|
||||
daily_reading_minutes: DailyReading[];
|
||||
}
|
||||
|
||||
interface DailyReading {
|
||||
date: string;
|
||||
minutes: number;
|
||||
pages: number;
|
||||
date: string;
|
||||
minutes: number;
|
||||
pages: number;
|
||||
}
|
||||
|
||||
// Matches handlers.DeviceUsageResponse (internal/handlers/analytics.go:43-45)
|
||||
// Note: Response is wrapped: { devices: DeviceUsage[] }
|
||||
// Used in: analytics.ts
|
||||
interface DeviceUsageResponse {
|
||||
devices: DeviceUsage[];
|
||||
devices: DeviceUsage[];
|
||||
}
|
||||
|
||||
interface DeviceUsage {
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: string;
|
||||
sync_count: number;
|
||||
last_sync: string;
|
||||
total_time_seconds: number;
|
||||
total_time_minutes: number;
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: string;
|
||||
sync_count: number;
|
||||
last_sync: string;
|
||||
total_time_seconds: number;
|
||||
total_time_minutes: number;
|
||||
}
|
||||
|
||||
// Matches handlers.PopularBooksResponse (internal/handlers/analytics.go:57-59)
|
||||
// Note: Response is wrapped: { books: PopularBook[] }
|
||||
// Used in: analytics.ts
|
||||
interface PopularBooksResponse {
|
||||
books: PopularBook[];
|
||||
books: PopularBook[];
|
||||
}
|
||||
|
||||
interface PopularBook {
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
read_count: number;
|
||||
avg_completion: number;
|
||||
last_read: string;
|
||||
media_item_id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
read_count: number;
|
||||
avg_completion: number;
|
||||
last_read: string;
|
||||
}
|
||||
|
||||
// Matches handlers.QueueItemResponse (internal/handlers/queue.go:35-51)
|
||||
// Used in: queue.ts
|
||||
interface QueueItemResponse {
|
||||
id: string;
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: string;
|
||||
media_item_id?: string;
|
||||
media_title?: string;
|
||||
user_email: string;
|
||||
sync_type: string;
|
||||
priority: number;
|
||||
attempts: number;
|
||||
max_attempts: number;
|
||||
status: string;
|
||||
error_message?: string;
|
||||
created_at: string;
|
||||
processed_at?: string;
|
||||
id: string;
|
||||
device_id: string;
|
||||
device_name: string;
|
||||
device_type: string;
|
||||
media_item_id?: string;
|
||||
media_title?: string;
|
||||
user_email: string;
|
||||
sync_type: string;
|
||||
priority: number;
|
||||
attempts: number;
|
||||
max_attempts: number;
|
||||
status: string;
|
||||
error_message?: string;
|
||||
created_at: string;
|
||||
processed_at?: string;
|
||||
}
|
||||
|
||||
// Matches handlers.QueueStatsResponse (internal/handlers/queue.go:27-33)
|
||||
// Used in: queue.ts
|
||||
interface QueueStatsResponse {
|
||||
pending_count: number;
|
||||
processing_count: number;
|
||||
failed_count: number;
|
||||
completed_count: number;
|
||||
total_count: number;
|
||||
pending_count: number;
|
||||
processing_count: number;
|
||||
failed_count: number;
|
||||
completed_count: number;
|
||||
total_count: number;
|
||||
}
|
||||
|
||||
// Matches handlers.ConflictDetailResponse (internal/handlers/conflicts.go:42-53)
|
||||
// Used in: conflicts.ts
|
||||
interface ConflictDetailResponse {
|
||||
id: string;
|
||||
media_item_id: string;
|
||||
media_item_title: string;
|
||||
conflict_type: string;
|
||||
conflict_data: Record<string, ConflictSourceData>;
|
||||
resolution_status: string;
|
||||
resolution_data?: Record<string, unknown>;
|
||||
resolved_by?: string;
|
||||
resolved_at?: string;
|
||||
created_at: string;
|
||||
id: string;
|
||||
media_item_id: string;
|
||||
media_item_title: string;
|
||||
conflict_type: string;
|
||||
conflict_data: Record<string, ConflictSourceData>;
|
||||
resolution_status: string;
|
||||
resolution_data?: Record<string, unknown>;
|
||||
resolved_by?: string;
|
||||
resolved_at?: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
// Matches handlers.ConflictSourceData (internal/handlers/conflicts.go:36-40)
|
||||
interface ConflictSourceData {
|
||||
source: string;
|
||||
timestamp: string;
|
||||
data: Record<string, unknown>;
|
||||
source: string;
|
||||
timestamp: string;
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// Matches handlers.ConflictListResponse (internal/handlers/conflicts.go:55-59)
|
||||
// Used in: conflicts.ts
|
||||
interface ConflictListResponse {
|
||||
conflicts: ConflictDetailResponse[];
|
||||
total: number;
|
||||
unresolved: number;
|
||||
conflicts: ConflictDetailResponse[];
|
||||
total: number;
|
||||
unresolved: number;
|
||||
}
|
||||
|
||||
// Matches handlers.ConflictResolveResponse (internal/handlers/conflicts.go:61-65)
|
||||
// Used in: conflicts.ts
|
||||
interface ConflictResolveResponse {
|
||||
conflict_resolved: boolean;
|
||||
applied_to: Record<string, boolean>;
|
||||
devices_synced: string[];
|
||||
conflict_resolved: boolean;
|
||||
applied_to: Record<string, boolean>;
|
||||
devices_synced: string[];
|
||||
}
|
||||
|
||||
// Matches handlers.BulkResolveResponse (internal/handlers/conflicts.go:424-429)
|
||||
// Used in: conflicts.ts
|
||||
interface BulkResolveResponse {
|
||||
results: ConflictResult[];
|
||||
total: number;
|
||||
success: number;
|
||||
failed: number;
|
||||
results: ConflictResult[];
|
||||
total: number;
|
||||
success: number;
|
||||
failed: number;
|
||||
}
|
||||
|
||||
// Matches handlers.ConflictResult (internal/handlers/conflicts.go:431-436)
|
||||
interface ConflictResult {
|
||||
conflict_id: string;
|
||||
status: string;
|
||||
error?: string;
|
||||
winner?: string;
|
||||
conflict_id: string;
|
||||
status: string;
|
||||
error?: string;
|
||||
winner?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user