Commit Graph

25 Commits

Author SHA1 Message Date
Brian Fertig 3586e1da9a feat: add song selection toolbar and popular songs section
- Enable bulk song selection with custom checkboxes and select-all header row
- Add "Most Popular" section (scored by likes + 2×favorites) alongside Trending
- Improve horizontal scrolling for liked strips with grab/grabbing cursor and drag-to-scroll logic
- Introduce neon divider (`hr.hr-neon`) for visual separation between sections
- Update CSS grid layout for selectable song lists to accommodate checkboxes
2026-04-14 20:12:45 -06:00
Brian Fertig dc64286b15 feat(admin): add bulk visibility update for songs
- Add `/songs/bulk-visibility` POST endpoint to update visibility of multiple selected songs in bulk
  - Enforces VIP permission checks before allowing 'vip' visibility setting
  - Updates only songs user has permission to manage

- Extend song list UI with a new "Change Visibility" dropdown button and menu
  - Menu items are conditionally rendered based on user role/VIP status
  - Integrated with existing bulk action toolbar (toggles, prevents overlap)

- Implement frontend logic to:
  - Toggle visibility dropdown independently from other bulk menus
  - Submit selected song IDs and chosen visibility via fetch POST request
  - Update UI in-place after successful update (badges, selection reset)
  - Show toast notification with count of updated songs

- Includes badge rendering helper for consistent visibility display
2026-04-14 19:25:10 -06:00
Brian Fertig 771165f042 Add VIP visibility tier for songs and playlists
- Introduce `vip` visibility level with CSS badge styling
- Update admin routes to restrict VIP setting to admins and VIP users
- Extend visibility logic in public routes (`canView`, `denyAccess`)
- Add VIP-specific SQL queries in playlists, social, and songs services
- Update EJS templates to show VIP badges and radio options for authorized users
2026-04-14 19:12:02 -06:00
Brian Fertig 5828b9c9f1 feat: Add faceted search & trending strip to songs page + mobile nav toggle
- Add genre and uploader filters to /songs with persistent query params in pagination
- Implement site-wide "Trending" strip showing recently liked songs
- Introduce responsive hamburger nav for mobile with animated icon & ARIA support
- Refactor song row layout: move duration into separate `.song-duration` element
- Update CSS for mobile grid (2 columns), optimized song rows, and facet selects
2026-04-13 23:12:33 -06:00
Brian Fertig c71538b45d feat: add song playlist appearances section and edit buttons for creators
- Introduce a new "Appears in" section on song pages showing playlists containing the song (public/logged_in visibility)
- Add secondary button styling for Edit links on song and playlist detail pages, visible only to creators
- Implement `getPlaylistsForSong()` service function with guest/user-aware queries
- Update view templates to render edit buttons and playlist appearance cards
2026-04-13 21:08:22 -06:00
Brian Fertig 428cfb1008 feat: add PWA support and refine creativity parameter handling
- Register service worker (`sw.js`) with cache-first static assets and network-first HTML pages
- Update `site.webmanifest` with app name, colors, icons at `/static/`, and standalone display mode
- Add `<meta name="theme-color">` in layout for browser UI theming
- Simplify creativity slider: change range from 0–10 to 3.0–7.0 (step 0.5), aligning frontend and backend logic
- Adjust `generate.js` route and `generation.js` service to accept direct temperature values (3.0–7.0) instead of scaled inputs
2026-04-13 19:42:30 -06:00
Brian Fertig 4602087400 feat: implement VIP access control and configurable generation cooldown
- Add `generation_cooldown_seconds` column to `site_settings` (default 180s)
- Add `is_vip` column to `users` table (default 0/false)
- Introduce new `requireVip` middleware for enforcing VIP-only routes
- Restrict song generation access to VIP users or admins
- Add admin UI endpoints to grant/remove VIP status per user
- Allow admins to configure generation cooldown period via admin panel
- Update generation service to use dynamic cooldown (replacing hardcoded 3 minutes)
- Enhance generate page UI with Re-Gen button, improved placeholder text, and rate-limit state updates
- Update header navigation to show "My Music" and "Generate" only for VIP/admin users
2026-04-12 19:26:31 -06:00
Brian Fertig 4046bc20e0 `feat: normalize cover image handling with centralized processing`
- Centralize cover image processing into a new `imageService.processCoverImage()` helper that resizes and crops images to 1000×1000 JPEG.
- Replace ad-hoc embedded-art handling in admin routes (`writeEmbeddedCover`) and publish route (`uploadCover`) with unified `saveCover` function supporting both uploaded files and embedded picture buffers.
- Ensure all cover uploads (songs, playlists, generated songs) go through the new async processing pipeline with proper temp-file cleanup and error handling.
- Update routes to use `async` handlers where cover processing is involved.
2026-04-12 18:06:35 -06:00
Brian Fertig 8b4a28e062 feat: add AI song generation via ComfyUI with rate limiting and admin configuration
- Add database schema for site_settings and generated_songs tables with migration 011_generation.sql
- Implement backend services for settings management and generation workflow (submit/poll ComfyUI)
- Create routes for admin panel (/admin) to configure generation parameters, upload workflow JSON, manage users
- Create generate routes (/generate) with rate limiting (3min cooldown, 10/hour limit), form submission, polling, streaming
- Add frontend UI: generate page with form and rate-limit panel, publish flow for completed generations
- Integrate generation link into header navigation for verified users when enabled
2026-04-12 17:45:12 -06:00
Brian Fertig dfeedb1acd feat: implement genre selection with new-genre fallback in song forms
- Add client-side genre dropdown populated from existing genres + option to add new genre via text input
- Introduce resolveGenre() helper to prioritize new-genre input over selection, handling the "__new__" sentinel value
- Update admin routes and form rendering to pass available genres and preserve user selections on validation errors
- Add listGenres() service method and CSS styling for genre field layout

This replaces the simple text input with a more user-friendly dropdown experience while still supporting custom genres.
2026-04-12 15:13:41 -06:00
Brian Fertig 983b00f375 feat(admin): add bulk song selection with playlist assignment
- Introduces bulk checkboxes on the songs list page to select multiple songs
- Adds a toolbar with dropdown to add selected songs to existing playlists or create a new playlist
- Implements `/songs/bulk-add` POST endpoint for efficient batch addition of tracks to playlists
- Auto-upgrades playlist visibility when adding more-restrictive songs
- Supports preselecting songs via query parameter when creating a new playlist (`?songs=1,2,3`)
- Includes custom-styled checkboxes, toast notifications, and keyboard-friendly UI interactions
2026-04-12 13:58:22 -06:00
Brian Fertig 021d0694df feat: implement user notifications system
- Add UI components for notification navigation (btn + badge) and notification list with unread indicators
- Introduce notifications service with CRUD methods for managing user notifications
- Trigger notifications when users like/favorite songs or playlists via social actions
- Add /account/notifications route to view and mark all notifications as read
- Display unread count in header and account page navigation
2026-04-12 11:43:24 -06:00
Brian Fertig 347cf97da7 feat: add Open Graph and Twitter Card meta tags for public pages
- Introduce appBaseUrl config option for absolute URLs in social cards
- Generate og metadata for song and playlist pages with title, description, image, and URL
- Include partial layout support for rendering OG/Twitter meta tags conditionally
2026-04-12 10:43:19 -06:00
Brian Fertig 20bd6422a6 refactor: rename admin routes and views to mymusic namespace
- Move /admin/* routes to /mymusic/* for clearer user-focused section naming
- Rename admin/ view templates to mymusic/ with updated paths and URLs
- Add cover art preview in song edit form with current cover thumbnail styling
- Update navigation active states to use new /mymusic* paths
- Change now-playing creator link from window.open() to direct navigation
2026-04-12 10:29:00 -06:00
Brian Fertig 25d68e1dcb feat: add user profiles with slugs and enhance now-playing UI
- Add database migration to create unique `slug` column for users table
- Implement profile routes (`/profiles`, `/profiles/:slug`) with views for:
  • listing verified user profiles with avatars, song/playlist counts
  • individual profile pages showing user's songs, playlists, liked items
- Add helper functions in `users.js`, `songs.js`, `playlists.js`, and `social.js`
  to support public visibility filtering and profile data enrichment
- Enhance now-playing overlay UI with:
  • vinyl sleeve animation (sleeve + record peeking behind cover)
  • clickable creator info to open profile page if slug exists
  • track row click to jump directly to a song in the queue
- Update CSS for profiles grid, detail creator links, and overlay styling
- Add "Profiles" link to header navigation

This enables a full user profile system with vanity URLs and improves the
music player experience with visual polish and direct navigation.
2026-04-11 13:46:12 -06:00
Brian Fertig be5857fe3b feat: add user avatars with cropping and image lightbox
- Add `avatar_path` column to users table via migration 008
- Integrate `cropperjs` and `sharp` for avatar upload, cropping (600×600), and PNG conversion
- Serve avatars at `/media/avatars` with static caching; expose `/static/vendor/cropperjs`
- Add avatar management UI in account settings with modal cropping workflow
- Display creator avatars on song/playlist detail pages (fallback to initial)
- Implement generic image lightbox (`lightbox.js`) for cover art with zoom animations and keyboard support
- Refactor song/playlist detail views to use responsive layout and lightbox-enabled covers
2026-04-11 10:08:05 -06:00
Brian Fertig f044d98afc feat: implement social actions (like/favorite) for songs and playlists
- Add database tables for song/playlist likes and favorites
- Create `social` service with toggle functions and enrichment helpers
- Implement `/api/:type/:id/(like|favorite)` routes with CSRF protection
- Add like/favorite buttons to player, song lists, playlists, and cards
- Support guest → login redirect via `data-require-login`
- Inject CSRF token into layout for JS API requests
2026-04-11 09:12:21 -06:00
Brian Fertig a24f2fe75d feat: add configurable site name via SITE_NAME env var
- Introduce `SITE_NAME` environment variable with fallback to 'Bri-Tunes'
- Propagate `siteName` to templates via `res.locals`
- Replace hardcoded 'Bri-Tunes' references in layout, header, home title, and boot sequence
- Update `.env.example` with new variable
2026-04-11 08:34:11 -06:00
Brian Fertig 5394e0cef4 feat: replace ID-based URLs with slugs for songs and playlists
- Add `slug` column to `songs` and `playlists` tables via migrations 005 & 006
- Implement slug generation logic (lowercase, hyphenated, unique) in both services
- Backfill existing rows with auto-generated slugs on startup
- Update public routes to use `/songs/:slug` and `/playlists/:slug`
- Replace all view templates to link using slugs instead of numeric IDs
2026-04-11 08:14:27 -06:00
Brian Fertig 041f0f2ea1 ```
feat(users): implement user disabling functionality with admin controls

- Add `disabled` column to users table via migration
- Update login flow to reject disabled accounts with 403 error
- Introduce new `/admin/users` route for admin-only user management (disable/enable, verify email, delete with content)
- Extend users service to support listing all users, toggling disabled status, admin verification, and cascading deletion of user's songs/playlists
- Add admin UI for managing users with visual indication of disabled accounts (opacity reduction)
- Update navigation to include "Users" link for admins
```
2026-04-10 20:32:57 -06:00
Brian Fertig 9438330f22 feat: add playlist creation credit display, shuffle playback, drag-and-drop reordering, and email verification flow improvements
- Display playlist creator name on public and admin playlist views
- Add shuffle playback button for playlists in player UI
- Implement drag-and-drop reordering for playlist tracks with visual feedback
- Improve email verification UX: redirect pending users to verify page with resend option
- Simplify admin routes by removing redundant role checks (user-based filtering already handled)
- Adjust featured playlist count and add "show all" links on home page
2026-04-10 20:14:54 -06:00
Brian Fertig 04be828e67 feat: add email verification flow with SMTP support
- Introduce email_verified column and email_verifications table for token-based verification
- Add nodemailer dependency and create mailer service (SMTP + dev fallback to console)
- On registration, generate 24h verification token and send email (or log URL in dev)
- Add /verify-email GET route to validate tokens and mark user as verified
- Add /resend-verification POST route for logged-in users to re-send link
- Update flash system with new warning style for unverified users
- Update .env.example with APP_BASE_URL and SMTP_* configuration variables

Note: existing users are grandfathered in (email_verified=1) via migration.
2026-04-09 22:48:38 -06:00
Brian Fertig b4af77066a feat: implement three-tier visibility system for songs and playlists
- Add public/logged_in/private visibility levels to songs and playlists via database migration (002_visibility.sql)
- Replace old `is_public` boolean with new `visibility` enum in admin forms, API schemas, and services
- Implement access control logic:
  - Guests see only public items that don't contain restricted tracks
  - Logged-in users see public + logged_in items (excluding private ones)
  - Admins see all; regular users manage their own content
- Auto-upgrade playlist visibility when adding more restrictive songs
- Add UI badges for visibility levels and update admin views to reflect new hierarchy

PWA enhancements:
- Update web manifest with proper name, colors, and icon paths
- Add service worker (sw.js) with cache-first for static assets and network-first for HTML
- Register SW at root (/sw.js) with Service-Worker-Allowed header for full origin scope
- Add theme-color meta tag and navigate.js for client-side routing

Other:
- Update admin nav label from "Admin" to "My Music" to reflect role-based access
2026-04-09 22:40:18 -06:00
Brian Fertig ed13c2821c feat(admin): support auto-populating song metadata from embedded audio tags on upload
- Introduce `songUploadSchema` for flexible uploads where title/artist are optional
- Add `extractAudioMetadata()` to parse ID3/Vorbis tags and embedded cover art from uploaded files
- Merge form values with extracted metadata, falling back to filename-derived title if needed
- Automatically write embedded cover art to `media/covers/` when no manual cover is uploaded
- Update song form UI to indicate optional fields and tag-based fallback behavior
- Switch JSON rendering in partials from `<%-` (unescaped) to `<%=`, improving safety
2026-04-09 19:30:31 -06:00
Brian Fertig a515df90de first commit 2026-04-09 18:41:01 -06:00