diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c67d50..4be761f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,7 @@ name: CI on: push: - branches: [dev, main] pull_request: - branches: [dev, main] jobs: test: diff --git a/src/core/fixtures/sample_data.json b/src/core/fixtures/sample_data.json index 641dd5a..6341c86 100644 --- a/src/core/fixtures/sample_data.json +++ b/src/core/fixtures/sample_data.json @@ -385,7 +385,7 @@ "media_type": "MUSIC", "status": "COMPLETED", "pub_year": 2000, - "review": "Une expérimentation audacieuse qui a divisé les fans mais reste un chef-d'œuvre.", + "review": "Une expérimentation audacieuse qui a divisé les fans mais reste un chef-d'œuvre. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", "score": 9, "review_date": "2019", "contributors": [6], diff --git a/src/core/migrations/0007_alter_media_score.py b/src/core/migrations/0007_alter_media_score.py new file mode 100644 index 0000000..858f3b2 --- /dev/null +++ b/src/core/migrations/0007_alter_media_score.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0 on 2025-12-27 15:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_alter_agent_created_at_alter_media_created_at'), + ] + + operations = [ + migrations.AlterField( + model_name='media', + name='score', + field=models.IntegerField(blank=True, choices=[(1, 'Detested'), (2, 'Hated'), (3, 'Disliked'), (4, 'Not appreciated'), (5, 'Moderately appreciated'), (6, 'Appreciated'), (7, 'Enjoyed'), (8, 'Really enjoyed'), (9, 'Loved'), (10, 'Adored')], null=True, verbose_name='Review score'), + ), + ] diff --git a/src/core/models.py b/src/core/models.py index 89fa711..67d4329 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -83,16 +83,16 @@ class Media(models.Model): null=True, blank=True, choices={ - 1: _("1⭐ - Detested"), - 2: _("2⭐ - Hated"), - 3: _("3⭐ - Disliked"), - 4: _("4⭐ - Not appreciated"), - 5: _("5⭐ - Moderately appreciated"), - 6: _("6⭐ - Appreciated"), - 7: _("7⭐ - Enjoyed"), - 8: _("8⭐ - Really enjoyed"), - 9: _("9⭐ - Loved"), - 10: _("10⭐ - Adored"), + 1: _("Detested"), + 2: _("Hated"), + 3: _("Disliked"), + 4: _("Not appreciated"), + 5: _("Moderately appreciated"), + 6: _("Appreciated"), + 7: _("Enjoyed"), + 8: _("Really enjoyed"), + 9: _("Loved"), + 10: _("Adored"), }, ) review_date = PartialDateField( diff --git a/src/core/urls.py b/src/core/urls.py index 53738cb..e3132b0 100644 --- a/src/core/urls.py +++ b/src/core/urls.py @@ -12,4 +12,6 @@ path("agents/search-htmx/", views.agent_search_htmx, name="agent_search_htmx"), path("agents/select-htmx/", views.agent_select_htmx, name="agent_select_htmx"), path("media/validate_field/", validate_media_field, name="media_validate_field"), + path("media//review-full/", views.media_review_full_htmx, name="media_review_full_htmx"), + path("media//review-clamped/", views.media_review_clamped_htmx, name="media_review_clamped_htmx"), ] diff --git a/src/core/views.py b/src/core/views.py index 29f31bd..2fb02d9 100644 --- a/src/core/views.py +++ b/src/core/views.py @@ -201,3 +201,17 @@ def agent_select_htmx(request): return render(request, "partials/contributor-chip.html", {"agent": agent}) except Agent.DoesNotExist: return render(request, "partials/contributor-chip.html", {"agent": None, "error": "Agent not found"}) + + +@login_required +def media_review_clamped_htmx(request, pk): + """HTMX view: return clamped review for a media item (for table cell collapse).""" + media = get_object_or_404(Media, pk=pk) + return render(request, "partials/media-review-clamped.html", {"media": media}) + + +@login_required +def media_review_full_htmx(request, pk): + """HTMX view: return full review for a media item (for table cell expansion).""" + media = get_object_or_404(Media, pk=pk) + return render(request, "partials/media-review-full.html", {"media": media}) diff --git a/src/static/js/base.js b/src/static/js/base.js index ac92eda..0a34154 100644 --- a/src/static/js/base.js +++ b/src/static/js/base.js @@ -74,7 +74,7 @@ function createFilterBadge(filterName, displayText, badgeClass = 'badge-secondar badge.dataset.filter = filterName; badge.innerHTML = ` ${displayText} - `; diff --git a/src/templates/base.html b/src/templates/base.html index 8159b59..8792da8 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -20,7 +20,7 @@ {% tailwind_css %} {% htmx_script %} - +
{% block navbar %} {% endif %} @@ -100,7 +100,7 @@

{% translate "My media" %}

{% if filters.review_from and filters.review_to %}→{% endif %} {{ filters.review_to }}
{% endif %} @@ -110,7 +110,7 @@

{% translate "My media" %}

id="contributor-badge"> {{ contributor.name }} {% endif %} diff --git a/src/templates/partials/media-items.html b/src/templates/partials/media-items.html index 9a551e5..b7f6708 100644 --- a/src/templates/partials/media-items.html +++ b/src/templates/partials/media-items.html @@ -3,13 +3,13 @@ {% if view_mode == 'grid' %} {# Grid items #} {% for media in media_list %} -
-
+
+
{% if media.cover %} {{ media.title }} {% else %}
@@ -17,23 +17,25 @@
{% endif %}
-
+

{{ media.title }}

-
- {{ media.get_media_type_display }} - {% if media.score %}{{ media.score }}/10{% endif %} -
- {% if media.contributors.all %} -

- {% for contributor in media.contributors.all %} - {{ contributor.name }} - {% if not forloop.last %},{% endif %} - {% endfor %} -

- {% endif %} + {% for contributor in media.contributors.all %} + {{ contributor.name }} + {% if not forloop.last %};{% endif %} + {% endfor %} + {{ media.get_media_type_display }} + {% include "partials/score-readonly.html" %} +
{% include "partials/media-review-clamped.html" %}
@@ -56,7 +58,7 @@

{{ media.title }} - + {% for contributor in media.contributors.all %} hx-target="#media-list" hx-include="#view-mode-input, #sort, #type, #status, #score, #review-from, #review-to" hx-push-url="true">{{ contributor.name }} - {% if not forloop.last %},{% endif %} + {% if not forloop.last %};{% endif %} {% endfor %} {{ media.get_media_type_display }} @@ -74,17 +76,11 @@

{{ media.get_status_display }}
{{ media.pub_year | default:"" }} - {% include "partials/score-readonly.html" %} - {{ media.created_at | date:"Y-m-d" }} + + {% include "partials/score-readonly.html" %} +
{% include "partials/media-review-clamped.html" %}
+ + {{ media.review_date | default:"" }} {% endfor %} {% endif %} -{# Load more button - replaces itself when clicked #} -{% if media_list.has_next %} -
- -
-{% endif %} diff --git a/src/templates/partials/media-list.html b/src/templates/partials/media-list.html index 9d2a4f4..b866fa7 100644 --- a/src/templates/partials/media-list.html +++ b/src/templates/partials/media-list.html @@ -3,12 +3,12 @@ {% if media_list %} {% if view_mode == 'grid' %} {# Grid view - Cards layout #} -
{% include "partials/media-items.html" %}
{% else %} {# List view - Table layout #}
- +
@@ -17,8 +17,8 @@ - - + + diff --git a/src/templates/partials/media-review-clamped.html b/src/templates/partials/media-review-clamped.html new file mode 100644 index 0000000..c6e2940 --- /dev/null +++ b/src/templates/partials/media-review-clamped.html @@ -0,0 +1,9 @@ +{# Display the review truncated to 3 lines with a 'See more' button (HTMX) #} +{% load i18n %} +{{ media.review | truncatechars:120 }} +{% if media.review and media.review|length > 120 %} + +{% endif %} diff --git a/src/templates/partials/media-review-full.html b/src/templates/partials/media-review-full.html new file mode 100644 index 0000000..1627ced --- /dev/null +++ b/src/templates/partials/media-review-full.html @@ -0,0 +1,7 @@ +{# Displays the full review for a media item (HTMX) #} +{% load i18n %} +
{{ media.review }}
+ diff --git a/src/templates/partials/score-readonly.html b/src/templates/partials/score-readonly.html index a614578..e8a7d8c 100644 --- a/src/templates/partials/score-readonly.html +++ b/src/templates/partials/score-readonly.html @@ -1,40 +1,34 @@ {% load i18n %} -
- {% if media.score %} - {{ media.get_score_display }} - {% else %} - {% translate "Not rated" %} - {% endif %} -
-
-
+
-
-
-
-
-
-
-
-
-
+{% if media.score %}
{{ media.get_score_display }}
{% endif %} diff --git a/uv.lock b/uv.lock index cc3c5e9..4f89c8f 100644 --- a/uv.lock +++ b/uv.lock @@ -1023,15 +1023,15 @@ wheels = [ [[package]] name = "poethepoet" -version = "0.38.0" +version = "0.39.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pastel" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4d/14/d1f795f314c4bf3ad6d64216e370bdfda73093ed76e979485778b655a7ac/poethepoet-0.38.0.tar.gz", hash = "sha256:aeeb2f0a2cf0d3afa833976eff3ac7b8f5e472ae64171824900d79d3c68163c7", size = 77339, upload-time = "2025-11-23T13:51:28.246Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/f5/7561bc002bcd40c96633173fb2eb5daf2589dd4dfc4a2cb1b1a2cc6bb60f/poethepoet-0.39.0.tar.gz", hash = "sha256:85f279ffaf2a58ba31db2048ab897740d4db839233c3f28740cf0517b3367710", size = 79816, upload-time = "2025-12-25T15:10:57.799Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/89/2bf7d43ef4b0d60f446933ae9d3649f95c2c45c47b6736d121b602c28361/poethepoet-0.38.0-py3-none-any.whl", hash = "sha256:214bd9fcb348ff3dfd1466579d67e0c02242451a7044aced1a79641adef9cad0", size = 101938, upload-time = "2025-11-23T13:51:26.518Z" }, + { url = "https://files.pythonhosted.org/packages/b2/18/9f356cdf243ca90a985f2e8e9eab938b1ddac461acfa6348db434ba70525/poethepoet-0.39.0-py3-none-any.whl", hash = "sha256:2865b04230df0fb43b6fb4f739c975b19be03d6db18f0ab760b3fb5c56b50b5c", size = 104763, upload-time = "2025-12-25T15:10:56.099Z" }, ] [[package]]
{% translate "Cover" %}{% translate "Type" %} {% translate "Status" %} {% translate "Year" %}{% translate "Score" %}{% translate "Created at" %}{% translate "Review" %}{% translate "Reviewed on" %}