Commit Graph

192 Commits

Author SHA1 Message Date
Claudio Ortolina 23d6e736e7 Uniform ux/ui of adding a new record to a set 2026-02-15 14:24:02 +00:00
Claudio Ortolina fe748782c7 Reorder record sets via drag and drop 2026-02-10 11:16:41 +00:00
Claudio Ortolina f82e764c94 Add tests for Last.fm controller 2026-02-09 11:12:38 +00:00
Claudio Ortolina fc307a0aba Add tests for health controller 2026-02-09 11:12:02 +00:00
Claudio Ortolina 356efb1c65 Add tests for archive controller 2026-02-09 11:11:41 +00:00
Claudio Ortolina 68956978e1 Add show route for record sets 2026-02-07 16:09:26 +00:00
Claudio Ortolina 29dc57abdb Simplify record sets page structure (no title, better margins) 2026-02-07 13:47:42 +00:00
Claudio Ortolina 84159a1c0d Improve test coverage
Files Created (8 files, 54 new tests)

  Fixtures

  1. test/support/fixtures/music_library/record_sets.ex — record_set/1
and record_set_with_records/2 helpers
  2. test/support/fixtures/music_library/online_store_templates.ex —
online_store_template/1 helper

  Context Tests

  3. test/music_library/record_sets_test.exs — 20 tests covering search,
count, CRUD, add/remove/move records
  4. test/music_library/online_store_templates_test.exs — 8 tests
covering list, CRUD, URL generation, validation
  5. test/music_library/search_test.exs — 5 tests covering universal
search and search counts
  6. test/music_library/notes_test.exs — 4 tests covering get, create,
update

  LiveView Tests

  7. test/music_library_web/live/record_set_live/index_test.exs — 11
tests covering listing, empty state, search, ordering,
create/edit/delete sets, remove records, reorder records
  8.
test/music_library_web/live/online_store_template_live/index_test.exs —
6 tests covering listing, create/edit/delete, toggle enabled

  Results

  - 297 tests, 0 failures (up from 243 — 54 new tests added)
  - All existing tests continue to pass

There's a remaining gettext warning that needs to be investigated
2026-02-07 10:39:22 +00:00
Claudio Ortolina 9666b24b4a Standardize button labels 2025-12-14 09:25:41 +03:00
Claudio Ortolina 0df348ae19 Add pagination for scrobble rules 2025-12-14 09:21:13 +03:00
Claudio Ortolina 84e7c06d27 Can edit scrobbled tracks album/artist mbids 2025-12-09 14:38:01 +00:00
Claudio Ortolina 5692be4e63 Update dependencies
credo 1.7.13 => 1.7.14 - requires updates to pass updated checks
2025-12-01 16:09:51 +00:00
Claudio Ortolina 71f7a38fee Don't use streams for records on this day 2025-11-26 18:50:35 +00:00
Claudio Ortolina 997ac40cc5 Fix broken test 2025-11-09 19:22:53 +00:00
copilot-swe-agent[bot] 36d1ba1b48 Fix hook and add keyboard navigation tests
Co-authored-by: cloud8421 <537608+cloud8421@users.noreply.github.com>
2025-11-09 19:22:53 +00:00
Claudio Ortolina ed99f6bda8 Implement dense grid as variation of normal grid 2025-11-03 09:49:51 +00:00
Claudio Ortolina 12272608bc Default collection and wishlist to a grid layout 2025-11-03 09:49:50 +00:00
Claudio Ortolina f4808c25c2 Update dependencies
phoenix_test 0.8.2 => 0.8.3

Includes a test fix due to PhoenixTest having changed the logic used to
match text content in a nested selector.
2025-10-27 15:21:26 +00:00
Claudio Ortolina e1a1ddd682 Speed up test
There are only 20 tracks per page, so 21 tracks are enough
2025-10-26 14:23:14 +00:00
Claudio Ortolina 89db253e59 Refactor test to use PhoenixTest APIs 2025-10-25 13:35:21 +01:00
Claudio Ortolina 4dc80cf739 Make test actually work 2025-10-25 13:18:05 +01:00
Claudio Ortolina 49b5075222 More speed up test 2025-10-25 13:07:35 +01:00
Claudio Ortolina 0b56e01162 Speed up test
Entire spec is AI generated and needs to be revised.
2025-10-25 12:59:14 +01:00
Claudio Ortolina 59eb603b3f Return more record information in the API 2025-10-25 11:52:50 +01:00
Claudio Ortolina f02564fa30 Add /api/collection/on_this_day endpoint 2025-10-24 20:06:23 +01:00
Claudio Ortolina 35aec967fe Simplify tests using PhoenixTest 2025-10-22 10:52:22 +01:00
Claudio Ortolina 40143df96d Add tests for universal search 2025-10-22 09:23:54 +01:00
Claudio Ortolina 90b3fa1fdc Refactor Records.Cover to Assets.Image 2025-09-20 07:42:38 +03:00
Claudio Ortolina e158345674 Change /covers to /assets 2025-09-18 21:26:16 +03:00
Claudio Ortolina aa72692eaf Cache transformations 2025-09-17 16:54:47 +03:00
Claudio Ortolina b0f4e18ef7 Fix API collection record cover URLs 2025-09-17 11:24:14 +03:00
Claudio Ortolina 0996b78c7b Use Transforms to serve covers at the right size 2025-09-17 10:26:38 +03:00
Claudio Ortolina d932498c11 Rename tests for consistency 2025-09-17 09:12:07 +03:00
Claudio Ortolina e7c2b92a3b Remove track count from scrobbled tracks list 2025-09-17 09:11:03 +03:00
Claudio Ortolina f42f050de0 Simplify scrobbled tracks layout
Remove no results view
2025-09-16 21:01:44 +03:00
Claudio Ortolina a0647ab91a Remove buggy tests 2025-09-16 13:15:23 +03:00
Claudio Ortolina dae334b1b7 Scrobbled tracks CRUD
- Failing tests
- Warnings
2025-09-16 12:45:36 +03:00
Claudio Ortolina ecb830b2fd Render [[Example]] links as links to the collection search 2025-09-13 15:35:02 +03:00
Claudio Ortolina 5aaa7708ee Add tests for On This Day functionality 2025-09-10 17:52:11 +03:00
Claudio Ortolina 0cb46e4ec7 Capture warning location 2025-09-04 08:31:44 +03:00
Claudio Ortolina dc77d337c0 Migrate from embedded covers to assets 2025-09-01 16:20:41 +03:00
Claudio Ortolina bd12454884 Serve covers from assets 2025-09-01 14:44:17 +03:00
Claudio Ortolina 49c3a5cba2 Serve images from assets table 2025-09-01 13:46:32 +03:00
Claudio Ortolina aee08cc2bb Use Enum for scrobble rule type 2025-07-04 14:23:19 +01:00
Claudio Ortolina 024ba38b63 Use Ecto.UUID instead of hand-rolled type 2025-07-03 21:07:42 +01:00
Claudio Ortolina d91685b646 First rough implementation of scrobble rules (Claude)
This plan outlines the implementation of functionality to manage
arbitrary rules for fixing data in the `scrobbled_tracks` table. The
system will support two types of transformations:

1. **Album Rule**: Update the album MusicBrainz ID of all tracks
belonging to a specific album (identified by album title)
2. **Artist Rule**: Update the artist MusicBrainz ID of all tracks
belonging to a specific artist (identified by artist name)

- `scrobbled_tracks` table exists with the following structure:
  - `scrobbled_at_uts` (integer, primary key)
  - `musicbrainz_id` (string) - track MusicBrainz ID
  - `title` (string) - track title
  - `cover_url` (string)
  - `scrobbled_at_label` (string)
  - `artist` (map) - embedded artist data with `musicbrainz_id` and
`name`
  - `album` (map) - embedded album data with `musicbrainz_id` and
`title`
  - `last_fm_data` (map) - raw Last.fm API response

- `LastFm.Track` - Schema for scrobbled tracks
- `LastFm.Artist` - Embedded artist schema
- `LastFm.Album` - Embedded album schema

- Main navigation has Stats, Collection, Wishlist sections
- "More" dropdown contains development tools and utilities
- Uses Phoenix LiveView for interactive components

**File**:
`priv/repo/migrations/YYYYMMDDHHMMSS_create_scrobble_rules.exs`

Create `scrobble_rules` table with:

- `id` (primary key)
- `type` (string) - "album" or "artist"
- `match_value` (string) - album title or artist name to match
- `target_musicbrainz_id` (string) - MusicBrainz ID to set
- `enabled` (boolean) - whether rule is active
- `description` (text) - optional description for the rule
- `inserted_at` (timestamp)
- `updated_at` (timestamp)

Indexes:

- `type, match_value` (compound index for efficient matching)
- `enabled` (for filtering active rules)

**File**: `lib/music_library/scrobble_rules/scrobble_rule.ex`

Create Ecto schema with:

- Field definitions matching migration
- Validations:
  - `type` must be "album" or "artist"
  - `match_value` required and non-empty
  - `target_musicbrainz_id` required and non-empty
  - `enabled` defaults to true
- Changeset functions for create/update operations

**File**: `lib/music_library/scrobble_rules.ex`

Implement context functions:

- `list_scrobble_rules(opts \\ [])` - list all rules with optional
filtering
- `get_scrobble_rule!(id)` - get specific rule by ID
- `create_scrobble_rule(attrs)` - create new rule
- `update_scrobble_rule(rule, attrs)` - update existing rule
- `delete_scrobble_rule(rule)` - delete rule
- `change_scrobble_rule(rule, attrs \\ %{})` - create changeset
- `list_enabled_rules()` - get only enabled rules for worker
- `apply_album_rule(rule)` - apply album transformation
- `apply_artist_rule(rule)` - apply artist transformation
- `apply_all_rules()` - apply all enabled rules

**File**: `lib/music_library_web/components/layouts/app.html.heex`

Add new navigation link in the "More" dropdown:

- Icon: `hero-adjustments-horizontal`
- Label: "Scrobble Rules"
- Route: `/scrobble-rules`
- Position: After "Oban" link, before separator

**File**: `lib/music_library_web/router.ex`

Add new LiveView routes in the authenticated scope:

- `/scrobble-rules` - index page
- `/scrobble-rules/new` - create new rule
- `/scrobble-rules/:id/edit` - edit existing rule

**File**: `lib/music_library_web/live/scrobble_rules_live/index.ex`

Implement LiveView with:

- List view showing all rules with status indicators
- Create/Edit forms with validation
- Delete confirmation
- Filter controls (by type, enabled/disabled)
- Manual rule application triggers
- Real-time updates via PubSub

**Template**:
`lib/music_library_web/live/scrobble_rules_live/index.html.heex`

- Table layout with rule details
- Action buttons (Edit, Delete, Apply)
- Form components for create/edit
- Status indicators for enabled/disabled rules

**File**:
`lib/music_library_web/live/scrobble_rules_live/form_component.ex`

Create reusable form component:

- Type selection (album/artist)
- Match value input with validation
- Target MusicBrainz ID input
- Description textarea
- Enable/disable toggle
- Save/Cancel actions

Where possible, use the components available at
<https://docs.fluxonui.com/1.1.4/overview.html>.

**File**: `lib/music_library/scrobble_rules/worker.ex`

Implement Oban worker:

- Scheduled to run periodically (e.g., every 30 minutes)
- Fetches all enabled rules
- Applies each rule in sequence
- Logs application results
- Handles errors gracefully
- Tracks last application time

**File**: `test/music_library/scrobble_rules_test.exs`

- Test all context functions
- Test rule application logic
- Test edge cases and error handling

**File**: `test/music_library/scrobble_rules/scrobble_rule_test.exs`

- Test schema validations
- Test changeset functions
- Test constraint validations

**File**: `test/music_library_web/live/scrobble_rules_live_test.exs`

- Test LiveView interactions
- Test form submissions
- Test real-time updates
- Test navigation and routing

**File**: `test/music_library/scrobble_rules/worker_test.exs`

- Test job execution
- Test rule application
- Test error handling
- Test scheduling

- Ensure atomic operations when applying rules
- Validate MusicBrainz IDs before applying
- Log all transformations for audit trail

- Index optimization for rule matching
- Batch processing for large datasets
- Rate limiting for external API calls

- Clear feedback on rule application
- Preview mode to show what would change
- Bulk operations for managing multiple rules
- Export/import functionality for rule sets

- Input validation and sanitization
- Rate limiting on rule creation
- Audit logging for all changes

```sql
-- scrobble_rules table
CREATE TABLE scrobble_rules (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  type TEXT NOT NULL CHECK (type IN ('album', 'artist')),
  match_value TEXT NOT NULL,
  target_musicbrainz_id TEXT NOT NULL,
  enabled BOOLEAN NOT NULL DEFAULT TRUE,
  description TEXT,
  inserted_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP NOT NULL
);

CREATE INDEX idx_scrobble_rules_type_match ON scrobble_rules(type,
match_value);
CREATE INDEX idx_scrobble_rules_enabled ON scrobble_rules(enabled);
```

```
lib/music_library/
├── scrobble_rules/
│   ├── scrobble_rule.ex          # Schema
│   └── worker.ex                 # Oban worker
└── scrobble_rules.ex             # Context

lib/music_library_web/
└── live/
    └── scrobble_rules_live/
        ├── index.ex              # LiveView
        ├── index.html.heex       # Template
        └── form_component.ex     # Form component

priv/repo/migrations/
└── YYYYMMDDHHMMSS_create_scrobble_rules.exs

test/
├── music_library/
│   ├── scrobble_rules_test.exs
│   └── scrobble_rules/
│       ├── scrobble_rule_test.exs
│       └── worker_test.exs
└── music_library_web/
    └── live/
        └── scrobble_rules_live_test.exs
```

1. Database migration and schema
2. Context module with basic CRUD operations
3. LiveView interface for rule management
4. Navigation and routing updates
5. Periodic worker implementation
6. Comprehensive testing
7. Documentation and deployment

This plan ensures a robust, maintainable solution that integrates
seamlessly with the existing Music Library application architecture.
2025-07-03 16:47:08 +01:00
Claudio Ortolina 08bc50d5dd Use tabs for scrobble activity toggle 2025-06-25 12:05:23 +03:00
Claudio Ortolina adc44e056e Reduce data size to speedup test
Suggested and executed by Claude
2025-06-14 21:15:26 +03:00
Claudio Ortolina 07d9db6011 Speed up tests by caching cover data
Suggested and executed by Claude
2025-06-14 21:15:06 +03:00
Claudio Ortolina 1d78f6c4dc Make test faster by deterministically reducing size 2025-06-14 20:04:09 +03:00