From 927ec08847f3fa9884c5accb310c2a43da945303 Mon Sep 17 00:00:00 2001 From: NorbertAguilera Date: Wed, 3 Jun 2026 21:22:33 +0200 Subject: [PATCH 01/14] fix(search-menu-left-site) deleted the search menu from left menu, because it was useless --- Templates/base.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Templates/base.html b/Templates/base.html index 9f42415..51d9fa7 100644 --- a/Templates/base.html +++ b/Templates/base.html @@ -125,7 +125,7 @@ {% endif %} - + From 9d60a09452df1f53801135ee37ce568fe3fe78cc Mon Sep 17 00:00:00 2001 From: Bogdan2005-19 Date: Fri, 5 Jun 2026 11:21:14 +0200 Subject: [PATCH 02/14] fix(footer): added mailto to the footer email --- Templates/base.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Templates/base.html b/Templates/base.html index 9f42415..a4d078d 100644 --- a/Templates/base.html +++ b/Templates/base.html @@ -174,7 +174,11 @@
{% trans "Legal" %}
{% trans "Contact" %}
-

info@StreamSync.com

+

+ + info@StreamSync.com + +

+34 600 000 000

From 4179d85b5ffa9278c32c06677a5d9be278d735f5 Mon Sep 17 00:00:00 2001 From: Gerard Safont Date: Sat, 6 Jun 2026 11:36:44 +0200 Subject: [PATCH 03/14] fix(info-card): moved the info card to user_client file --- .../users/settings/user_settings.html | 58 ------------ users/templates/users/types/staff_admin.html | 2 +- users/templates/users/types/user_admin.html | 2 +- users/templates/users/types/user_client.html | 94 ++++++++++++++----- 4 files changed, 71 insertions(+), 85 deletions(-) delete mode 100644 users/templates/users/settings/user_settings.html diff --git a/users/templates/users/settings/user_settings.html b/users/templates/users/settings/user_settings.html deleted file mode 100644 index fabc638..0000000 --- a/users/templates/users/settings/user_settings.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends 'users/base_profile.html' %} -{% load static %} -{% load i18n %} - -{% block content_user_setings %} - {% if user.type == 'Consumer' %} -
- - -
- -
-
{% trans "Bio" %}
-

- {% if user.bio %} - {{ user.bio }} - {% else %} - {% trans "Write a few words about you" %} - {% endif %} -

-
- -
-
{% trans "Member since" %}
-

{{ user.date_joined|date:"d/m/Y" }}

-
- -
-
{% trans "Last access" %}
-

{{ user.last_login|date:"d/m/Y" }}

-
- -
-
{% trans "Location" %}
-

- {% if user.location %} - {{ user.location }} - {% else %} - {% trans "Add your location" %} - {% endif %} -

-
- -
- - {% endif %} - - - {% if user.type == 'Consumer' %} -
- {% else %} -
- {% endif %} - {% block user_content %}{% endblock %} -
- -
-{% endblock %} \ No newline at end of file diff --git a/users/templates/users/types/staff_admin.html b/users/templates/users/types/staff_admin.html index 713f841..e6f2aa1 100644 --- a/users/templates/users/types/staff_admin.html +++ b/users/templates/users/types/staff_admin.html @@ -1,4 +1,4 @@ -{% extends 'users/settings/user_settings.html' %} +{% extends 'users/base_profile.html' %} {% load i18n %} {% block content_staff_admin %} diff --git a/users/templates/users/types/user_admin.html b/users/templates/users/types/user_admin.html index 5883179..5774e99 100644 --- a/users/templates/users/types/user_admin.html +++ b/users/templates/users/types/user_admin.html @@ -1,4 +1,4 @@ -{% extends 'users/settings/user_settings.html' %} +{% extends 'users/base_profile.html' %} {% load i18n %} {% block content_admin %} diff --git a/users/templates/users/types/user_client.html b/users/templates/users/types/user_client.html index dfce223..e4e2aa9 100644 --- a/users/templates/users/types/user_client.html +++ b/users/templates/users/types/user_client.html @@ -1,31 +1,75 @@ -{% extends 'users/settings/user_settings.html' %} +{% extends 'users/base_profile.html' %} {% load i18n %} {% block content_user %} - - - - -
- {% block parts_content %}{% endblock %} +
+ +
+ +
+
{% trans "Bio" %}
+

+ {% if user.bio %} + {{ user.bio }} + {% else %} + {% trans "Write a few words about you" %} + {% endif %} +

+
+ +
+
{% trans "Member since" %}
+

{{ user.date_joined|date:"d/m/Y" }}

+
+ +
+
{% trans "Last access" %}
+

{{ user.last_login|date:"d/m/Y" }}

+
+ +
+
{% trans "Location" %}
+

+ {% if user.location %} + {{ user.location }} + {% else %} + {% trans "Add your location" %} + {% endif %} +

+
+
-{% endblock %} \ No newline at end of file +
+ + + +
+ {% block parts_content %}{% endblock %} +
+ +
+ +
+ +{% endblock %} From 33ba5977ad5cf8f6cb76a14a698d870159ec1471 Mon Sep 17 00:00:00 2001 From: Gerard Safont Date: Sat, 6 Jun 2026 11:41:06 +0200 Subject: [PATCH 04/14] style(profile-tab):redifined the visual tab --- users/static/users/css/user_settings.css | 30 +++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/users/static/users/css/user_settings.css b/users/static/users/css/user_settings.css index 73a61db..a2d7009 100644 --- a/users/static/users/css/user_settings.css +++ b/users/static/users/css/user_settings.css @@ -1,9 +1,16 @@ -¡/* ---- Tabs ---- */ +/* ---- Tabs wrapper ---- */ +.nav-tabs-wrapper { + border: 1px solid var(--border-glass); + border-bottom: none; + border-radius: 8px 8px 0 0; +} + +/* ---- Tabs ---- */ .nav-tabs { - border-bottom: 1px solid var(--border-glass) !important; + border: none !important; background: var(--bg-glass); border-radius: 8px 8px 0 0; - padding: 0 0.5rem; + padding: 0; margin-bottom: 0 !important; } @@ -12,23 +19,30 @@ border: none !important; border-bottom: 2px solid transparent !important; border-radius: 0 !important; + margin-bottom: 0 !important; padding: 14px 18px; font-size: 13px; font-weight: 500; - transition: color 0.2s, border-color 0.2s; + transition: color 0.2s, background 0.2s; background: transparent !important; font-family: 'DM Sans', sans-serif; letter-spacing: 0.02em; } .nav-tabs .nav-link:hover { - color: var(--neon-cyan) !important; + color: var(--text-primary) !important; } .nav-tabs .nav-link.active { - color: var(--neon-cyan) !important; - border-bottom: 2px solid var(--neon-cyan) !important; - text-shadow: 0 0 10px rgba(102, 252, 241, 0.4); + color: #0B0C10 !important; + background: #E0E6ED !important; + border-bottom: 2px solid transparent !important; + border-radius: 6px 6px 0 0 !important; + text-shadow: none; +} + +.nav-item:first-child .nav-link.active { + border-radius: 8px 6px 0 0 !important; } /* ---- Tab content area ---- */ From 541ff740e1a5b8ba3d28bba3672a463cb7eebc55 Mon Sep 17 00:00:00 2001 From: Gerard Safont Date: Sat, 6 Jun 2026 12:02:46 +0200 Subject: [PATCH 05/14] fix(dashboard): renamed the grafics to more understanding --- users/templates/users/parts/dashboard_age_ratings.html | 6 +++--- users/templates/users/parts/dashboard_directors.html | 6 +++--- users/templates/users/parts/dashboard_genres.html | 4 ++-- users/templates/users/parts/dashboard_overview.html | 4 ++-- users/views.py | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/users/templates/users/parts/dashboard_age_ratings.html b/users/templates/users/parts/dashboard_age_ratings.html index 85c41eb..c65a0d1 100644 --- a/users/templates/users/parts/dashboard_age_ratings.html +++ b/users/templates/users/parts/dashboard_age_ratings.html @@ -7,7 +7,7 @@
-
Age Rating Distribution
+
Views by Age Rating
@@ -27,7 +27,7 @@
Age Rating Table
Rating - Views + Visualizations @@ -54,7 +54,7 @@
Age Rating Table
data: { labels: {{ age_stats.labels|safe }}, datasets: [{ - label: 'Views', + label: 'Visualizations', data: {{ age_stats.values|safe }}, backgroundColor: '#3498db', borderRadius: 5 diff --git a/users/templates/users/parts/dashboard_directors.html b/users/templates/users/parts/dashboard_directors.html index ab4abc3..9c62a15 100644 --- a/users/templates/users/parts/dashboard_directors.html +++ b/users/templates/users/parts/dashboard_directors.html @@ -7,7 +7,7 @@
-
Top Directors
+
Top Directors by Views
@@ -27,7 +27,7 @@
Top Directors Table
Director - Views + Visualizations @@ -54,7 +54,7 @@
Top Directors Table
data: { labels: {{ director_stats.labels|safe }}, datasets: [{ - label: 'Views', + label: 'Visualizations', data: {{ director_stats.values|safe }}, backgroundColor: '#2c3e50', borderRadius: 5 diff --git a/users/templates/users/parts/dashboard_genres.html b/users/templates/users/parts/dashboard_genres.html index ab8fc21..d494d15 100644 --- a/users/templates/users/parts/dashboard_genres.html +++ b/users/templates/users/parts/dashboard_genres.html @@ -7,7 +7,7 @@
-
Genre Distribution
+
Views by Genre
@@ -27,7 +27,7 @@
Top Genres Data
Genre - Views + Visualizations diff --git a/users/templates/users/parts/dashboard_overview.html b/users/templates/users/parts/dashboard_overview.html index f66f0f2..5148afd 100644 --- a/users/templates/users/parts/dashboard_overview.html +++ b/users/templates/users/parts/dashboard_overview.html @@ -5,7 +5,7 @@ {% include 'users/parts/filter_form.html' %}
-
Global Content Analytics Summary
+
Views per Content
Export CSV @@ -22,7 +22,7 @@
Global Content Analytics Summary
Year Director Platform - Views + Visualizations Favorites diff --git a/users/views.py b/users/views.py index 4747a35..c624537 100644 --- a/users/views.py +++ b/users/views.py @@ -234,7 +234,7 @@ def export_analytics_csv(request): response['Content-Disposition'] = 'attachment; filename="analytics_report.csv"' writer = csv.writer(response) - writer.writerow(['Title', 'Genre', 'Age Rating', 'Year', 'Director', 'Platform', 'Total Views', 'Total Favorites'])#TODO translate this + writer.writerow(['Title', 'Genre', 'Age Rating', 'Year', 'Director', 'Platform', 'Total Visualizations', 'Total Favorites'])#TODO translate this for item in clean_data: writer.writerow([ From 3059c07e1d76a571b58c6e172f1ca2c2c2d72d7c Mon Sep 17 00:00:00 2001 From: Norbert <113366897+NorbertAguilera@users.noreply.github.com> Date: Sun, 7 Jun 2026 19:30:47 +0200 Subject: [PATCH 06/14] Update quality-pipeline.yml to solve errors --- .github/workflows/quality-pipeline.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/quality-pipeline.yml b/.github/workflows/quality-pipeline.yml index 5aaadf7..a9826c9 100644 --- a/.github/workflows/quality-pipeline.yml +++ b/.github/workflows/quality-pipeline.yml @@ -645,7 +645,7 @@ jobs: FAIL=0 if find . \( -name "*.js" -o -name "*.ts" -o -name "*.vue" -o -name "*.py" -o -name "*.java" \) \ - -not -path "*/node_modules/*" -not -path "*/dist/*" 2>/dev/null | grep -q .; then + -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/tests/*" -not -path "*/.venv/*" 2>/dev/null | grep -q .; then DETECTED=1 else DETECTED=0 @@ -654,7 +654,7 @@ jobs: # Unconditional frontend router guard bypass if grep -rEn "next\(true\)|beforeEach.*return true|navigate\(.*\{.*replace.*\}\)" \ --include="*.js" --include="*.ts" --include="*.vue" . 2>/dev/null \ - | grep -v node_modules | grep -v "//"; then + | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::Possible unconditional navigation guard bypass detected" fi @@ -662,14 +662,14 @@ jobs: if grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -v node_modules \ + | grep -vE "node_modules|tests/|\.venv|dist/" \ | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" \ | grep -q .; then grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -v node_modules | grep -v "//" \ + | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" echo "::error::Hardcoded password value detected in source code" FAIL=1 @@ -678,14 +678,14 @@ jobs: # eval() / exec() usage if grep -rEn "\beval\(|\bexec\(" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::eval()/exec() usage detected — review for potential code injection risk" fi # Disabled SSL/TLS certificate verification if grep -rEn "rejectUnauthorized\s*:\s*false|verify\s*=\s*False|ssl_verify\s*=\s*false" \ --include="*.js" --include="*.ts" --include="*.py" --include="*.java" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::error::SSL/TLS certificate verification disabled — man-in-the-middle attack risk" FAIL=1 fi @@ -693,7 +693,7 @@ jobs: # Sensitive tokens in URL query strings if grep -rEn "[?&](token|api_key|apikey|access_token|secret)=" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::Sensitive token/key passed in URL query string — use Authorization header instead." fi From 5a13e00266bbc7cec93673b7b791567b3707791d Mon Sep 17 00:00:00 2001 From: Norbert <113366897+NorbertAguilera@users.noreply.github.com> Date: Sun, 7 Jun 2026 19:33:07 +0200 Subject: [PATCH 07/14] Update quality-pipeline.yml returned to the oldest version --- .github/workflows/quality-pipeline.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/quality-pipeline.yml b/.github/workflows/quality-pipeline.yml index a9826c9..5aaadf7 100644 --- a/.github/workflows/quality-pipeline.yml +++ b/.github/workflows/quality-pipeline.yml @@ -645,7 +645,7 @@ jobs: FAIL=0 if find . \( -name "*.js" -o -name "*.ts" -o -name "*.vue" -o -name "*.py" -o -name "*.java" \) \ - -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/tests/*" -not -path "*/.venv/*" 2>/dev/null | grep -q .; then + -not -path "*/node_modules/*" -not -path "*/dist/*" 2>/dev/null | grep -q .; then DETECTED=1 else DETECTED=0 @@ -654,7 +654,7 @@ jobs: # Unconditional frontend router guard bypass if grep -rEn "next\(true\)|beforeEach.*return true|navigate\(.*\{.*replace.*\}\)" \ --include="*.js" --include="*.ts" --include="*.vue" . 2>/dev/null \ - | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then + | grep -v node_modules | grep -v "//"; then echo "::warning::Possible unconditional navigation guard bypass detected" fi @@ -662,14 +662,14 @@ jobs: if grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -vE "node_modules|tests/|\.venv|dist/" \ + | grep -v node_modules \ | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" \ | grep -q .; then grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//" \ + | grep -v node_modules | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" echo "::error::Hardcoded password value detected in source code" FAIL=1 @@ -678,14 +678,14 @@ jobs: # eval() / exec() usage if grep -rEn "\beval\(|\bexec\(" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then + . 2>/dev/null | grep -v node_modules | grep -v "//"; then echo "::warning::eval()/exec() usage detected — review for potential code injection risk" fi # Disabled SSL/TLS certificate verification if grep -rEn "rejectUnauthorized\s*:\s*false|verify\s*=\s*False|ssl_verify\s*=\s*false" \ --include="*.js" --include="*.ts" --include="*.py" --include="*.java" \ - . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then + . 2>/dev/null | grep -v node_modules | grep -v "//"; then echo "::error::SSL/TLS certificate verification disabled — man-in-the-middle attack risk" FAIL=1 fi @@ -693,7 +693,7 @@ jobs: # Sensitive tokens in URL query strings if grep -rEn "[?&](token|api_key|apikey|access_token|secret)=" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then + . 2>/dev/null | grep -v node_modules | grep -v "//"; then echo "::warning::Sensitive token/key passed in URL query string — use Authorization header instead." fi From 325b170f74f02b99bb9bd73fa863476dbe8758f1 Mon Sep 17 00:00:00 2001 From: NorbertAguilera Date: Sun, 7 Jun 2026 19:35:37 +0200 Subject: [PATCH 08/14] fix(ci): exclude tests/venv from static scan and fix hardcoded password --- .github/workflows/quality-pipeline.yml | 14 +++++++------- web_app/apps.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/quality-pipeline.yml b/.github/workflows/quality-pipeline.yml index 5aaadf7..a9826c9 100644 --- a/.github/workflows/quality-pipeline.yml +++ b/.github/workflows/quality-pipeline.yml @@ -645,7 +645,7 @@ jobs: FAIL=0 if find . \( -name "*.js" -o -name "*.ts" -o -name "*.vue" -o -name "*.py" -o -name "*.java" \) \ - -not -path "*/node_modules/*" -not -path "*/dist/*" 2>/dev/null | grep -q .; then + -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/tests/*" -not -path "*/.venv/*" 2>/dev/null | grep -q .; then DETECTED=1 else DETECTED=0 @@ -654,7 +654,7 @@ jobs: # Unconditional frontend router guard bypass if grep -rEn "next\(true\)|beforeEach.*return true|navigate\(.*\{.*replace.*\}\)" \ --include="*.js" --include="*.ts" --include="*.vue" . 2>/dev/null \ - | grep -v node_modules | grep -v "//"; then + | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::Possible unconditional navigation guard bypass detected" fi @@ -662,14 +662,14 @@ jobs: if grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -v node_modules \ + | grep -vE "node_modules|tests/|\.venv|dist/" \ | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" \ | grep -q .; then grep -rEn "password\s*[=:]\s*['\"][^'\"]{4,}['\"]" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" --include="*.java" \ . 2>/dev/null \ - | grep -v node_modules | grep -v "//" \ + | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//" \ | grep -vE "[[:space:]]:[a-zA-Z][a-zA-Z0-9_-]*=" echo "::error::Hardcoded password value detected in source code" FAIL=1 @@ -678,14 +678,14 @@ jobs: # eval() / exec() usage if grep -rEn "\beval\(|\bexec\(" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::eval()/exec() usage detected — review for potential code injection risk" fi # Disabled SSL/TLS certificate verification if grep -rEn "rejectUnauthorized\s*:\s*false|verify\s*=\s*False|ssl_verify\s*=\s*false" \ --include="*.js" --include="*.ts" --include="*.py" --include="*.java" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::error::SSL/TLS certificate verification disabled — man-in-the-middle attack risk" FAIL=1 fi @@ -693,7 +693,7 @@ jobs: # Sensitive tokens in URL query strings if grep -rEn "[?&](token|api_key|apikey|access_token|secret)=" \ --include="*.js" --include="*.ts" --include="*.vue" --include="*.py" \ - . 2>/dev/null | grep -v node_modules | grep -v "//"; then + . 2>/dev/null | grep -vE "node_modules|tests/|\.venv|dist/" | grep -v "//"; then echo "::warning::Sensitive token/key passed in URL query string — use Authorization header instead." fi diff --git a/web_app/apps.py b/web_app/apps.py index c071959..9abc724 100644 --- a/web_app/apps.py +++ b/web_app/apps.py @@ -41,7 +41,7 @@ def create_default_user(sender, **kwargs): username = 'admin' email = 'admin@admin.com' - password = 'adminpassword' + password = os.environ.get('DJANGO_SUPERUSER_PASSWORD', 'adminpassword') if not User.objects.filter(username=username).exists(): User.objects.create_superuser( From bc04d3f3313e540cdf5a71f1c53b219587910b51 Mon Sep 17 00:00:00 2001 From: NorbertAguilera Date: Sun, 7 Jun 2026 19:44:07 +0200 Subject: [PATCH 09/14] fix: added old configurations --- web_app/apps.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web_app/apps.py b/web_app/apps.py index 9abc724..a9bd4d5 100644 --- a/web_app/apps.py +++ b/web_app/apps.py @@ -41,8 +41,7 @@ def create_default_user(sender, **kwargs): username = 'admin' email = 'admin@admin.com' - password = os.environ.get('DJANGO_SUPERUSER_PASSWORD', 'adminpassword') - + password = 'adminpassword' if not User.objects.filter(username=username).exists(): User.objects.create_superuser( username=username, From ec23072f9a011bedad9a8275c92392511ccc8937 Mon Sep 17 00:00:00 2001 From: Karu174 Date: Mon, 8 Jun 2026 17:18:35 +0200 Subject: [PATCH 10/14] feat(history): update backend logic with date grouping, pagination, and filters --- users/views.py | 72 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/users/views.py b/users/views.py index c624537..ff42e15 100644 --- a/users/views.py +++ b/users/views.py @@ -9,6 +9,7 @@ from django.utils.crypto import get_random_string from django.contrib.sessions.models import Session from django.utils import timezone +from datetime import timedelta import json import gettext @@ -85,12 +86,71 @@ def user_profile(request): @login_required(login_url='login') @user_passes_test(is_consumer) def history(request): - # OPTIMIZACIÓN: Buscamos en el modelo real de visualizaciones y hacemos Eager Loading - visualizaciones = Visualitzacio.objects.filter(user=request.user).select_related( - 'contingut__movie', 'contingut__series' - ).prefetch_related('contingut__apis').order_by('-data_visualitzacio') - - return render(request, 'users/parts/history.html', {'visualizaciones': visualizaciones}) + user = request.user + visualizaciones = Visualitzacio.objects.filter(user=user).select_related( + 'contingut__movie', 'contingut__series', 'api' + ).order_by('-data_visualitzacio') + + platform_id = request.GET.get('platform') + if platform_id: + visualizaciones = visualizaciones.filter(api_id=platform_id) + + date_filter = request.GET.get('date') + now = timezone.now() + if date_filter == 'today': + visualizaciones = visualizaciones.filter(data_visualitzacio__date=now.date()) + elif date_filter == 'week': + visualizaciones = visualizaciones.filter(data_visualitzacio__gte=now - timedelta(days=7)) + elif date_filter == 'month': + visualizaciones = visualizaciones.filter(data_visualitzacio__gte=now - timedelta(days=30)) + + paginator = Paginator(visualizaciones, 20) + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) + + grouped_history = { + 'Avui': [], + 'Aquesta setmana': [], + 'Aquest mes': [], + 'Més antic': [] + } + + today = now.date() + week_ago = (now - timedelta(days=7)).date() + month_ago = (now - timedelta(days=30)).date() + + for vis in page_obj: + vis_date = vis.data_visualitzacio.date() + + if hasattr(vis.contingut, 'movie'): + vis.content_type = 'Movie' + elif hasattr(vis.contingut, 'series'): + vis.content_type = 'Series' + else: + vis.content_type = 'Desconegut' + + if vis_date == today: + grouped_history['Avui'].append(vis) + elif vis_date >= week_ago: + grouped_history['Aquesta setmana'].append(vis) + elif vis_date >= month_ago: + grouped_history['Aquest mes'].append(vis) + else: + grouped_history['Més antic'].append(vis) + + grouped_history = {k: v for k, v in grouped_history.items() if v} + + platforms = API.objects.all() + + context = { + 'page_obj': page_obj, + 'grouped_history': grouped_history, + 'platforms': platforms, + 'selected_platform': platform_id, + 'selected_date': date_filter, + } + + return render(request, 'users/parts/history.html', context) @login_required(login_url='login') @user_passes_test(is_consumer) From e5d54bc7d7fc3ee359872c1e36a46f921beea220 Mon Sep 17 00:00:00 2001 From: Karu174 Date: Mon, 8 Jun 2026 17:26:29 +0200 Subject: [PATCH 11/14] feat(history): redesign UI with horizontal cards, filters, and grouped timelines --- users/static/users/css/history.css | 127 +++++++++++++++-------- users/templates/users/parts/history.html | 87 ++++++++++++++-- 2 files changed, 164 insertions(+), 50 deletions(-) diff --git a/users/static/users/css/history.css b/users/static/users/css/history.css index 34dc29c..a556053 100644 --- a/users/static/users/css/history.css +++ b/users/static/users/css/history.css @@ -1,72 +1,115 @@ -/* ---- Movie cards ---- */ -.movie-card { - background: rgba(31, 40, 51, 0.6); +/* ---- Filtros y Selects ---- */ +.filter-select { + background: rgba(0, 0, 0, 0.4); + color: var(--text-primary); border: 1px solid var(--border-glass); - border-radius: 8px; - overflow: hidden; - transition: transform 0.25s, border-color 0.25s, box-shadow 0.25s; - height: 100%; + border-radius: 6px; + padding: 6px 12px; + font-size: 0.85rem; + outline: none; + transition: all 0.3s ease; } -.movie-card:hover { - transform: translateY(-5px); - border-color: rgba(102, 252, 241, 0.25); - box-shadow: 0 8px 24px rgba(102, 252, 241, 0.08); +.filter-select:focus { + border-color: var(--neon-cyan); + box-shadow: 0 0 8px rgba(102, 252, 241, 0.2); } -.movie-card-body { - padding: 1rem 1.1rem; +.filter-select option { + background: var(--bg-deep); + color: var(--text-primary); } -.movie-title { +/* ---- Agrupación por Fechas ---- */ +.history-group-title { color: var(--text-primary); - font-size: 14px; - font-weight: 600; - margin-bottom: 4px; font-family: 'Syne', sans-serif; - letter-spacing: -0.01em; + font-size: 1.1rem; + font-weight: 600; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--border-glass); } -.movie-year { - color: var(--text-muted); - font-size: 11px; - margin-bottom: 4px; +/* ---- Tarjeta Horizontal (Lista de Historial) ---- */ +.history-item-card { + transition: transform 0.2s, border-color 0.2s; + border: 1px solid transparent; + background: rgba(31, 40, 51, 0.4); } -.movie-genre { - color: var(--neon-cyan); - font-size: 11px; - margin-bottom: 8px; - opacity: 0.8; +.history-item-card:hover { + transform: translateX(5px); + border-color: rgba(102, 252, 241, 0.2); + background: rgba(31, 40, 51, 0.6); +} + +/* Miniatura del Póster */ +.history-poster-container { + width: 60px; + height: 90px; + flex-shrink: 0; + border-radius: 4px; + overflow: hidden; + background: rgba(0,0,0,0.5); } -.movie-rating { - color: #f5c518; - font-size: 12px; - margin-bottom: 8px; +.history-poster { + width: 100%; + height: 100%; + object-fit: cover; } -.movie-synopsis { +.history-poster-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; color: var(--text-muted); - font-size: 12px; - line-height: 1.5; + font-size: 1.5rem; + font-weight: bold; +} + +/* Información y Badges */ +.history-title { + color: var(--text-primary); + font-size: 1rem; + font-weight: 600; margin: 0; } -/* ---- Empty state ---- */ +.type-badge { + font-size: 0.7rem; + padding: 2px 8px; + border-radius: 12px; +} + +.platform-badge { + font-size: 0.75rem; + color: var(--text-muted); + background: rgba(255,255,255,0.05); + padding: 3px 8px; + border-radius: 4px; + border: 1px solid rgba(255,255,255,0.1); +} + +.history-time { + font-size: 0.8rem; + opacity: 0.8; +} + +/* ---- Estado Vacío (Empty state) ---- */ .history-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; - min-height: 200px; - color: var(--text-muted); - font-size: 14px; - gap: 8px; + text-align: center; } .history-empty-icon { - font-size: 32px; - opacity: 0.3; - margin-bottom: 8px; + font-size: 48px; + margin-bottom: 1rem; + opacity: 0.5; } \ No newline at end of file diff --git a/users/templates/users/parts/history.html b/users/templates/users/parts/history.html index 0ec0b64..7559471 100644 --- a/users/templates/users/parts/history.html +++ b/users/templates/users/parts/history.html @@ -1,20 +1,91 @@ {% extends 'users/types/user_client.html' %} {% load i18n %} {% load static %} + {% block extra_css %} {{ block.super }} {% endblock %} {% block parts_content %} -
- {% for movie in movies %} - {% include 'part/cardlite.html' with movie=movie %} - {% empty %} -
-
-

{% trans "No movies in history yet." %}

+
+ - {% endfor %} + + {% if grouped_history %} + {% for group_name, items in grouped_history.items %} +
+

{{ group_name }}

+
+ {% for vis in items %} +
+
+ {% if vis.contingut.poster_path %} + {{ vis.contingut.titol }} + {% else %} +
{{ vis.contingut.titol|first|upper }}
+ {% endif %} +
+ +
+
{{ vis.contingut.titol }}
+
+ {{ vis.content_type }} + + {{ vis.api.name|default:vis.api.port }} + + + {{ vis.data_visualitzacio|date:"d M Y, H:i" }} + +
+
+
+ {% endfor %} +
+
+ {% endfor %} + + {% if page_obj.paginator.num_pages > 1 %} +
+ {% include 'paginator.html' with items=page_obj %} +
+ {% endif %} + {% else %} +
+
📺
+

{% trans "No s'han trobat visualitzacions amb aquests criteris." %}

+ {% if selected_platform or selected_date %} + {% trans "Tornar a veure-ho tot" %} + {% endif %} +
+ {% endif %}
{% endblock %} \ No newline at end of file From eefdc98bbe7e813a4a1e320cb4de2604a35460e2 Mon Sep 17 00:00:00 2001 From: Karu174 Date: Mon, 8 Jun 2026 17:37:39 +0200 Subject: [PATCH 12/14] fix(history): avoid duplicate entries on platform click and clean up UI --- Templates/Details/details_base.html | 41 ++++++++++++++++++++--------- web_app/views.py | 23 ++++++++-------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Templates/Details/details_base.html b/Templates/Details/details_base.html index 3412911..7415639 100644 --- a/Templates/Details/details_base.html +++ b/Templates/Details/details_base.html @@ -48,7 +48,6 @@

{{ content.title }}

data-contingut-id="{{ content.contingut.id }}" data-api-id="{{ api.id }}"> {{ api.name|default:api.port }} - {% empty %} {% trans "No hay información de API disponible." %} @@ -137,15 +136,36 @@

{% trans "Deja tu opinión" %}

✅ {% trans "Añadido a tu historial" %}
{% endblock %} \ No newline at end of file diff --git a/Templates/paginator.html b/Templates/paginator.html new file mode 100644 index 0000000..3cb8853 --- /dev/null +++ b/Templates/paginator.html @@ -0,0 +1,44 @@ +{% load i18n %} + + + + \ No newline at end of file diff --git a/users/middleware.py b/users/middleware.py index 7109573..3ee5712 100644 --- a/users/middleware.py +++ b/users/middleware.py @@ -22,6 +22,7 @@ def __call__(self, request): 'update_user_role', 'gestion_cartelleres', 'editar_cartellera', + 'system_logs', ] if current_url_name not in exempt_url_names and not request.path.startswith('/static/'): diff --git a/users/templates/users/parts/system_logs.html b/users/templates/users/parts/system_logs.html new file mode 100644 index 0000000..e7e2100 --- /dev/null +++ b/users/templates/users/parts/system_logs.html @@ -0,0 +1,78 @@ +{% extends 'users/types/staff_admin.html' %} +{% load i18n %} + +{% block staff_admin_content %} +
+
+
+

{% trans "Logs de Sincronización" %}

+

{% trans "Registro histórico del Scheduler con las APIs externas." %}

+
+
+ +
+
+ + + + + + + + + + + {% for log in logs %} + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Fecha de Inicio" %}{% trans "Fecha Fin" %}{% trans "Estado" %}{% trans "Resumen" %}
+ {{ log.start_time|date:"d M Y, H:i:s" }} + + {% if log.end_time %} + {{ log.end_time|date:"d M Y, H:i:s" }} + {% else %} + {% trans "En curso..." %} + {% endif %} + + {% if log.status == 'SUCCESS' %} + + Éxito + + {% elif log.status == 'ERROR' %} + + Error + + {% else %} + + {{ log.status }} + + {% endif %} + + {% if log.summary %} + {{ log.summary|truncatechars:80 }} + {% else %} + - + {% endif %} +
+ {% trans "Todavía no hay ningún registro de sincronización." %} +
+
+
+ + {% if logs.has_other_pages %} +
+ {% include 'paginator.html' with items=logs %} +
+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/users/templates/users/types/staff_admin.html b/users/templates/users/types/staff_admin.html index e6f2aa1..6136a70 100644 --- a/users/templates/users/types/staff_admin.html +++ b/users/templates/users/types/staff_admin.html @@ -12,10 +12,14 @@ {% trans 'Carteleras' %} + -
+
{% block staff_admin_content %}{% endblock %}
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/users/urls.py b/users/urls.py index 6c7af8c..d435512 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,5 +1,6 @@ from django.urls import path from . import views +from web_app.views import system_logs urlpatterns = [ # Staff Admin URLs @@ -10,7 +11,7 @@ path('api/update-role/', views.update_user_role, name='update_user_role'), path('staff-admin/cartelleres/', views.gestion_cartelleres, name='gestion_cartelleres'), path('staff-admin/cartelleres/editar//', views.editar_cartellera, name='editar_cartellera'), - + path('staff-admin/logs/', system_logs, name='system_logs'), # User URLs path('profile/', views.user_profile, name='user_profile'), path('history/', views.history, name='history'), diff --git a/users/views.py b/users/views.py index ff42e15..849f821 100644 --- a/users/views.py +++ b/users/views.py @@ -480,3 +480,4 @@ def editar_cartellera(request, contingut_id): return render(request, 'users/parts/editar_cartellera.html', { 'contingut': contingut, }) + diff --git a/web_app/views.py b/web_app/views.py index 91a4bac..b4a32b8 100644 --- a/web_app/views.py +++ b/web_app/views.py @@ -4,7 +4,7 @@ from django.shortcuts import render, redirect, get_object_or_404 from web_app.forms import CustomUserAdminCreationForm, CustomUserCreationForm from web_app.models import AgeRating, API, CustomUser, Director, Genre, Movie, UserProfile, Series, Contingut, \ - AgeRating, Valoracio, Visualitzacio + AgeRating, Valoracio, Visualitzacio, SyncLog from web_app import utils import json from itertools import chain @@ -266,3 +266,16 @@ def register_platform_click(request): return JsonResponse({'status': 'error', 'message': 'Método no permitido'}, status=405) + +@user_passes_test(lambda u: u.is_superuser) +def system_logs(request): + if not request.user.is_authenticated: + return redirect('login') + + logs = SyncLog.objects.all().order_by('-start_time') + paginator = Paginator(logs, 20) + page_obj = paginator.get_page(request.GET.get('page', 1)) + + return render(request, 'users/parts/system_logs.html', { + 'logs': page_obj + }) \ No newline at end of file