Commit Graph

25 Commits

Author SHA1 Message Date
74c0a68aeb Refactor Tautulli integration to use efficient pre-aggregated APIs
Major performance improvement: Replace manual history aggregation with
Tautulli's built-in stats APIs. This eliminates the need to fetch and
process thousands of history records on every page load.

Changes:
- useTautulliStats composable completely rewritten:
  - Use get_home_stats for overall watch statistics (pre-aggregated)
  - Use get_plays_by_date for daily activity (already grouped by day)
  - Use get_plays_by_dayofweek for weekly patterns (pre-calculated)
  - Use get_plays_by_hourofday for hourly distribution (pre-calculated)
  - Remove fetchUserHistory() and manual aggregation functions

- ActivityPage updates:
  - Fetch all data in parallel with Promise.all for faster loading
  - Use user_id instead of username for better API performance
  - Simplified data processing since API returns pre-aggregated data

Benefits:
- 10-100x faster data loading (no need to fetch/process full history)
- Reduced network bandwidth (smaller API responses)
- Less client-side computation (no manual aggregation)
- Better scalability for large time ranges (365+ days)
- Consistent with Tautulli's internal calculations
2026-02-27 19:21:13 +01:00
64a833c9f8 Improve mobile UX: condense torrent table and standardize page layouts
- TorrentTable: Condense to 2 columns on mobile (title+meta, actions)
  - Title shown on first line, size/seeders on second line
  - Hide separate seed/size columns on mobile (desktop only)
  - Improved spacing and readability for mobile screens

- Standardize page layouts to match ActivityPage:
  - TorrentsPage: Update header style, padding, and container structure
  - GenPasswordPage: Align header and content layout with other pages
  - Consistent 3rem desktop padding, 0.75rem mobile padding
  - Unified h1 styling: 2rem desktop, 1.5rem mobile, font-weight 300

- Minor improvements:
  - Remove console.log statements from usePlexApi
  - Fix duration unit handling in useTautulliStats
  - Adjust AdminStats label font sizing
  - Reduce Graph.vue point radius for cleaner charts
2026-02-27 19:21:13 +01:00
0c4c30d1a0 Refactor: Modernize Activity page UI to match site design
Update page structure:
- Rename wrapper class to 'activity' (matches AdminPage pattern)
- Update h1 to activity__title with consistent styling
- Organize content with BEM naming convention

Redesign controls:
- Replace basic input with styled input-wrapper component
- Add input-suffix "days" label inside input container
- Custom number input styling with hover/focus states
- Better ToggleButton integration with control-label
- Responsive flex layout with proper mobile handling

Enhance chart presentation:
- Wrap each graph in chart-card component
- Add background, borders, and rounded corners
- Clear chart-card__title headers
- Fixed height charts (35vh desktop, 30vh mobile)
- Minimum height prevents squashing (300px/250px)
- Consistent spacing and padding

Improve top content section:
- Grid layout for top content items (3 cols → 1 col mobile)
- Card-based items with borders and hover effects
- Hover: border highlight + translateY animation
- Better visual hierarchy with section-title

Styling details:
- Use CSS variables (--background-ui, --text-color-50, etc.)
- Match AdminPage typography (2rem title, 300 weight)
- Consistent border-radius (12px cards, 8px inputs)
- Proper mobile-only responsive breakpoints
- Remove old commented-out code

Result: Professional, cohesive design matching rest of site 
2026-02-27 19:21:13 +01:00
e0ce0ea6da Fix: Add localStorage fallback for Plex authentication checks
Issue: ActivityPage and route guards showed "not authenticated"
even when Plex was linked via Settings page.

Root cause: Plex user data stored in localStorage but route guards
and ActivityPage only checked Vuex store (state.settings.plexUserId).

Changes:
- Update routes.ts hasPlexAccount() to check both:
  1. Vuex store (user/plexUserId)
  2. localStorage (plex_user_data) as fallback

- Update ActivityPage plexUserId computed to check both:
  1. Vuex store first
  2. localStorage plex_user_data.id as fallback

Why two sources?
- Vuex store: Set from JWT token (backend user settings)
- localStorage: Set immediately when linking Plex account
- localStorage persists across page reloads
- Provides seamless experience without backend round-trip

Now Activity page correctly shows data when Plex is linked ✓
2026-02-27 19:21:13 +01:00
d1578723c4 Feature: Integrate Tautulli stats with enhanced Activity page
Create useTautulliStats composable (247 lines):
- fetchUserHistory() - Get watch history from Tautulli API
- calculateWatchStats() - Total hours, plays by media type
- groupByDay() - Daily activity (plays & duration)
- groupByDayOfWeek() - Weekly patterns by media type
- getTopContent() - Most watched content ranking
- getHourlyDistribution() - Watch patterns by hour of day

Update ActivityPage.vue with new visualizations:
- Stats overview cards (4 metrics: plays, hours, movies, episodes)
- Activity per day line chart (plays or duration)
- Activity by media type stacked bar chart (movies/shows/music)
- NEW: Hourly distribution chart
- NEW: Top 10 most watched content list

Features:
- Direct Tautulli API integration (no backend needed)
- Real-time data from Plex watch history
- Configurable time range (days filter)
- Toggle between plays count and watch duration
- Responsive grid layout for stats cards
- Styled top content ranking with hover effects

Benefits:
- Rich visualization of actual watch patterns
- See viewing habits by time of day
- Identify most rewatched content
- Compare movie vs TV viewing
- All data from authoritative source (Tautulli)

ActivityPage now provides comprehensive watch analytics! 📊
2026-02-27 19:21:13 +01:00
ac591cbebe Refactor: Complete PlexSettings modularization with modal components
- Create PlexLibraryModal.vue (365 lines) for detailed library view
  - Stats overview (total items, episodes/tracks, duration)
  - Recently added items with posters and metadata
  - Top genres with visual bar charts
  - Fully responsive modal design

- Create PlexUnlinkModal.vue (138 lines) for account unlinking
  - Confirmation dialog with feature loss warnings
  - Clean modal UI with cancel/confirm actions

- Refactor PlexSettings.vue: 2094 lines → 498 lines (76% reduction)
  - Replace inline UI with PlexAuthButton component
  - Replace profile card with PlexProfileCard component
  - Replace stats grid with PlexLibraryStats component
  - Replace server info with PlexServerInfo component
  - Use PlexLibraryModal and PlexUnlinkModal for overlays
  - Integrate usePlexAuth, usePlexApi, usePlexLibraries composables
  - Remove 1596 lines of duplicate template and logic
  - Maintain all functionality with cleaner architecture

Total extraction: 2031 lines from monolithic file into 10 modular components
Build verified successfully ✓
2026-02-27 19:21:12 +01:00
77c89fa520 Enhance Plex integration with real API data and interactive library modal
Major improvements to Plex integration:
- Replace Vuex store dependency with localStorage-based connection detection
- Fetch and display real Plex user data (username, email, subscription, 2FA status)
- Add user badges: Plex Pass, member years, 2FA, experimental features
- Properly format Unix timestamp joined dates
- Remove success message box, add elegant checkmark icon next to username
- Add Plex connection badge to main user profile

Real-time Plex API integration:
- Fetch actual library counts from Plex server (movies, shows, music)
- Display real server name from user's Plex account
- Load recently added items with actual titles, years, and ratings
- Calculate real genre statistics from library metadata
- Compute actual duration totals from item metadata
- Count actual episodes (TV shows) and tracks (music)
- Sync library on demand with fresh data from Plex API

Interactive library modal:
- Replace toast messages with rich modal showing library details
- Display recently added items with poster images
- Show genre distribution with animated bar charts
- Add loading states with animated dots
- Disable empty library cards
- Modal appears above header with proper z-index
- Blur backdrop for better focus
- Fully responsive mobile design

Store Plex data in localStorage:
- Cache user profile data including subscription info
- Store auth token in secure cookie (30 day expiration)
- Load from cache for instant display on page load
- Refresh data on authentication and manual sync

Add Plex connection indicator to user profile:
- Orange Plex badge in settings profile header
- Shows 'Connected as [username]' below member info
- Loads username from localStorage on mount
2026-02-27 19:21:12 +01:00
9c7e0bd3b3 Refactor and optimize admin page components
- Remove unused imports and auto-refresh functionality
- Reduce padding and spacing for more compact admin layout
- Simplify stats generation and remove unused variables
- Adjust font sizes and icon sizes for better consistency
- Improve line-height on admin page title
- Minor performance optimizations
2026-02-27 19:21:12 +01:00
e1aaa3f1ea Redesign settings page with profile hero card
- Create single-page settings layout (removed sidebar navigation)
- Add large profile hero card with avatar, stats, and user info
- Display user stats: Requests and Magnets Added
- Compact spacing and improved typography hierarchy
- Section headers at 1.5rem for better hierarchy
- Reduced whitespace while maintaining readability
- Max-width: 800px for better content focus
2026-02-27 19:21:12 +01:00
fd842b218b v2 - lift all w/ icons, reactive layout, sort & filter 2026-02-27 19:21:12 +01:00
0f774e8f2e admin page & components 2026-02-27 19:21:12 +01:00
8e586811ec Feat: vite & upgraded dependencies (#100)
* On every route change, update local variables from query params

* ResultSection is keyed to query to force re-render

* Resolved lint warnings

* replace webpack w/ vite

* update all imports with alias @ and scss

* vite environment variables, also typed

* upgraded eslint, defined new rules & added ignore comments

* resolved linting issues

* moved index.html to project root

* updated dockerfile w/ build stage before runtime image definition

* sign drone config
2026-02-23 20:53:19 +01:00
dec15194e4 Fix: Search query reload (#79)
* On every route change, update local variables from query params

* ResultSection is keyed to query to force re-render

* Resolved lint warnings
2022-08-27 11:58:30 +02:00
2fed03a882 fix: updated plex_userid to camelcase 2022-08-19 10:49:16 +02:00
3594b18872 Resolved ALL eslint issues for project 2022-08-12 23:46:55 +02:00
29dfe55974 Renamed 404 and home with Page suffix 2022-08-12 23:45:47 +02:00
e7a0e08938 Increased width of activity days page input 2022-08-11 18:43:43 +02:00
41067aae84 Resolved all ts lint errors on build 2022-08-11 18:37:33 +02:00
81bead113f Fixed chartjs breaking changes 2022-08-09 01:05:29 +02:00
dc69b4086c Split activity graph into component & typed 2022-08-08 18:44:07 +02:00
b7e7fe9c55 Ugraded all pages to vue 3 & typescript 2022-08-06 16:10:37 +02:00
7478016384 Removed window eventhub, replaced w/ store 2022-07-26 23:12:39 +02:00
5eadb0b47a Removed storage.js, long ago replaced by store 2022-07-26 22:14:48 +02:00
d585af2193 🧹 moved files around 2022-07-26 20:30:29 +02:00
023b2cd86e Renamed/moved files around 2022-07-26 19:49:54 +02:00