From 214d27650822db1013b02944cb0b778f48b7cf29 Mon Sep 17 00:00:00 2001 From: Emiliano Frascaro Date: Tue, 9 Jun 2026 09:14:38 +0200 Subject: [PATCH] =?UTF-8?q?Migliora=20UI=20archivio=20replay=20societ?= =?UTF-8?q?=C3=A0=20con=20play=20e=20azioni=20separate.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anteprima cliccabile con pulsante play, badge stato, select visibilità compatti e colonna azioni senza sovrapposizioni. Co-authored-by: Cursor --- backend/app/views/layouts/marketing.html.erb | 2 +- .../public/club_recordings/index.html.erb | 182 +++++++----- backend/public/marketing.css | 275 ++++++++++++++++++ 3 files changed, 382 insertions(+), 77 deletions(-) diff --git a/backend/app/views/layouts/marketing.html.erb b/backend/app/views/layouts/marketing.html.erb index 88e6de9..f4580de 100644 --- a/backend/app/views/layouts/marketing.html.erb +++ b/backend/app/views/layouts/marketing.html.erb @@ -8,7 +8,7 @@ <%= render "shared/meta_tags" %> <%= yield :head %> - + data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>> <%= render "shared/cookie_banner" %> diff --git a/backend/app/views/public/club_recordings/index.html.erb b/backend/app/views/public/club_recordings/index.html.erb index 6ab75f4..31bb3cd 100644 --- a/backend/app/views/public/club_recordings/index.html.erb +++ b/backend/app/views/public/club_recordings/index.html.erb @@ -1,7 +1,7 @@ <% content_for :title, "Replay — #{@club.name}" %> <% content_for :robots, "noindex, nofollow" %> -
+
<%= link_to "← #{@club.name}", public_club_path(@club), class: "back-link" %>

Archivio Replay

@@ -48,83 +48,113 @@ <% end %> <% if @recordings.any? %> -
- - - - - - - - - - - - - - - - - <% @recordings.each do |rec| %> +
+
+
TitoloPiattaformaDataDurataViewsScadenzaStatoVisibilità
+ - - - - - - - - - - + + + + + + + + + + - <% end %> - -
- <% if rec.thumbnail_url %> - - <% end %> - - <%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true do %> - <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> - <%= hidden_field_tag :status, @filter_status if @filter_status.present? %> - <%= text_field_tag "recording[title]", rec.title_or_default, class: "input", style: "min-width:12rem", onchange: "this.form.submit()" %> - <% end %> - <%= rec.source_platform_label %><%= l_local(rec.recorded_at_or_fallback) %><%= rec.duration_label %><%= rec.view_count %> - <% if rec.expires_at %> - <%= l_local(rec.expires_at) %> - <% if rec.days_until_expiry && rec.days_until_expiry.positive? %> -
(<%= rec.days_until_expiry %> gg) - <% end %> - <% else %> - — - <% end %> -
<%= rec.status_label %> - <%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true do %> - <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> - <%= hidden_field_tag :status, @filter_status if @filter_status.present? %> - <%= select_tag "recording[privacy_status]", - options_for_select([["Pubblico", "public"], ["Privato (link)", "unlisted"]], rec.privacy_status), - onchange: "this.form.submit()" %> - <% end %> - - <% if rec.replay_url %> - <%= link_to "Sito", rec.replay_url, target: "_blank", rel: "noopener" %> - <% end %> - <% if rec.team.entitlements.phone_download_enabled? && rec.ready? %> - · <%= link_to "MP4", public_replay_download_path(rec.stream_session_id) %> - <% end %> - <% ent = rec.team.entitlements %> - <% if ent.premium_full? && ent.youtube_enabled? && rec.ready? && rec.youtube_video_id.blank? %> - · <%= button_to "YouTube", public_club_recording_publish_youtube_path(@club, rec), method: :post, class: "btn-link", style: "display:inline;padding:0;border:0;background:none;color:inherit;cursor:pointer;text-decoration:underline" %> - <% elsif rec.youtube_watch_url %> - · <%= link_to "YT", rec.youtube_watch_url, target: "_blank", rel: "noopener" %> - <% end %> - · <%= button_to "Elimina", public_club_recording_path(@club, rec), method: :delete, - params: { team_id: @filter_team_id, status: @filter_status }.compact, - class: "btn-link", style: "display:inline;padding:0;border:0;background:none;color:#e53935;cursor:pointer", - form: { data: { turbo_confirm: "Eliminare definitivamente questo replay? Verranno rimossi i file sul server e il video YouTube collegato." } } %> - AnteprimaTitoloPiattaformaDataDurataViewsScadenzaStatoVisibilitàAzioni
+ + + <% @recordings.each do |rec| %> + <% ent = rec.team.entitlements %> + <% can_play = rec.ready? && rec.replay_url.present? %> + + + <% if can_play %> + <%= link_to rec.replay_url, class: "replay-archive__thumb", target: "_blank", rel: "noopener", title: "Guarda replay" do %> + <% if rec.thumbnail_url %> + + <% else %> + + <% end %> + + <% end %> + <% else %> +
"> + <% if rec.thumbnail_url %> + + <% else %> + + <% end %> +
+ <% end %> + + + <%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true, class: "replay-archive__title-form" do %> + <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> + <%= hidden_field_tag :status, @filter_status if @filter_status.present? %> + <%= text_field_tag "recording[title]", rec.title_or_default, class: "replay-archive__title-input", onchange: "this.form.submit()" %> + <% end %> + + <%= rec.source_platform_label %> + <%= l_local(rec.recorded_at_or_fallback) %> + <%= rec.duration_label %> + <%= rec.view_count %> + + <% if rec.expires_at %> + <%= l_local(rec.expires_at) %> + <% if rec.days_until_expiry && rec.days_until_expiry.positive? %> + (<%= rec.days_until_expiry %> gg) + <% end %> + <% else %> + — + <% end %> + + + <%= rec.status_label %> + + + <%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true, class: "replay-archive__privacy-form" do %> + <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> + <%= hidden_field_tag :status, @filter_status if @filter_status.present? %> + <%= select_tag "recording[privacy_status]", + options_for_select([["Pubblico", "public"], ["Privato", "unlisted"]], rec.privacy_status), + class: "replay-archive__privacy-select", + onchange: "this.form.submit()" %> + <% end %> + + +
+ <% if can_play %> + <%= link_to rec.replay_url, class: "replay-archive__action replay-archive__action--play", target: "_blank", rel: "noopener", title: "Guarda replay" do %> + + Play + <% end %> + <% end %> + <% if ent.phone_download_enabled? && rec.ready? %> + <%= link_to "MP4", public_replay_download_path(rec.stream_session_id), class: "replay-archive__action replay-archive__action--secondary", title: "Scarica MP4" %> + <% end %> + <% if ent.premium_full? && ent.youtube_enabled? && rec.ready? && rec.youtube_video_id.blank? %> + <%= button_to "YT", public_club_recording_publish_youtube_path(@club, rec), method: :post, class: "replay-archive__action replay-archive__action--secondary", title: "Pubblica su YouTube" %> + <% elsif rec.youtube_watch_url %> + <%= link_to "YT", rec.youtube_watch_url, class: "replay-archive__action replay-archive__action--secondary", target: "_blank", rel: "noopener", title: "Apri su YouTube" %> + <% end %> + <%= button_to public_club_recording_path(@club, rec), method: :delete, + params: { team_id: @filter_team_id, status: @filter_status }.compact, + class: "replay-archive__action replay-archive__action--danger", + title: "Elimina replay", + form: { data: { turbo_confirm: "Eliminare definitivamente questo replay? Verranno rimossi i file sul server e il video YouTube collegato." }, class: "replay-archive__action-form" } do %> + + Elimina + <% end %> +
+ + + <% end %> + + +
<% else %>

Nessuna registrazione ancora. I replay compaiono al termine delle dirette Premium.

diff --git a/backend/public/marketing.css b/backend/public/marketing.css index a0beda4..7170d67 100644 --- a/backend/public/marketing.css +++ b/backend/public/marketing.css @@ -1354,3 +1354,278 @@ label { display: block; margin-bottom: 6px; font-size: 0.9rem; color: #c8c8d4; f body.cookie-banner-visible { padding-bottom: 120px; } + +/* —— Archivio replay società —— */ +.replay-archive__card { + padding: 0; + overflow: hidden; +} + +.replay-archive__table-wrap { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.replay-archive-table { + width: 100%; + min-width: 920px; + border-collapse: collapse; +} + +.replay-archive-table th, +.replay-archive-table td { + padding: 12px 10px; + border-bottom: 1px solid #2a2a36; + vertical-align: middle; +} + +.replay-archive-table th { + font-size: 0.78rem; + font-weight: 600; + color: #9a9aaa; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.replay-archive-table__col-thumb { + width: 108px; +} + +.replay-archive-table__col-title { + min-width: 11rem; +} + +.replay-archive-table__col-privacy { + width: 8.5rem; +} + +.replay-archive-table__col-actions { + width: 1%; + white-space: nowrap; +} + +.replay-archive-table__nowrap { + white-space: nowrap; + font-size: 0.9rem; +} + +.replay-archive-table__sub { + display: block; + font-size: 0.75rem; + margin-top: 2px; +} + +.replay-archive__thumb { + position: relative; + display: block; + width: 96px; + height: 54px; + border-radius: 8px; + overflow: hidden; + background: #0f0f14; + border: 1px solid #3a3a48; + text-decoration: none; + transition: border-color 0.15s, transform 0.15s; +} + +a.replay-archive__thumb:hover { + border-color: #e53935; + transform: scale(1.03); +} + +.replay-archive__thumb--static { + cursor: default; + opacity: 0.72; +} + +.replay-archive__thumb-img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +.replay-archive__thumb-placeholder { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + font-size: 1.25rem; + color: #555; +} + +.replay-archive__play-btn { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 36px; + height: 36px; + border-radius: 50%; + background: rgba(229, 57, 53, 0.95); + color: #fff; + font-size: 0.85rem; + line-height: 36px; + text-align: center; + padding-left: 3px; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45); + pointer-events: none; +} + +.replay-archive__title-form, +.replay-archive__privacy-form, +.replay-archive__action-form { + margin: 0; + display: block; +} + +.replay-archive__title-input { + width: 100%; + min-width: 10rem; + max-width: 18rem; + margin: 0; + padding: 8px 10px; + font-size: 0.92rem; +} + +.replay-archive__privacy-select { + width: 100%; + min-width: 7.5rem; + margin: 0; + padding: 8px 10px; + font-size: 0.85rem; +} + +.replay-archive__status { + display: inline-block; + padding: 4px 10px; + border-radius: 999px; + font-size: 0.78rem; + font-weight: 600; + white-space: nowrap; +} + +.replay-archive__status--ready { + background: rgba(76, 175, 80, 0.18); + color: #81c784; +} + +.replay-archive__status--processing { + background: rgba(255, 193, 7, 0.15); + color: #ffca28; +} + +.replay-archive__status--failed, +.replay-archive__status--expired { + background: rgba(229, 57, 53, 0.15); + color: #ef9a9a; +} + +.replay-archive__actions { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + gap: 6px; +} + +.replay-archive__action { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + min-height: 34px; + padding: 0 10px; + border-radius: 8px; + border: 1px solid #3d3d4a; + background: #1c1c26; + color: #e8e8f0; + font-size: 0.8rem; + font-weight: 600; + text-decoration: none; + cursor: pointer; + white-space: nowrap; + transition: background 0.15s, border-color 0.15s; +} + +.replay-archive__action:hover { + background: #262632; + border-color: #5a5a68; + color: #fff; +} + +.replay-archive__action--play { + background: #e53935; + border-color: #e53935; + color: #fff; + min-width: 34px; + padding: 0 12px; +} + +.replay-archive__action--play:hover { + background: #c62828; + border-color: #c62828; + color: #fff; +} + +.replay-archive__action--secondary { + font-size: 0.75rem; + padding: 0 8px; +} + +.replay-archive__action--danger { + border-color: rgba(229, 57, 53, 0.45); + color: #ef9a9a; +} + +.replay-archive__action--danger:hover { + background: rgba(229, 57, 53, 0.15); + border-color: #e53935; + color: #ffcdd2; +} + +.replay-archive .replay-filter-form { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + gap: 12px 16px; + margin-bottom: 20px; +} + +.replay-archive .replay-filter-form label { + margin: 0 0 4px; +} + +.replay-archive .replay-filter-form .input { + width: auto; + min-width: 10rem; + margin: 0; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +@media (max-width: 720px) { + .replay-archive__action-label { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + } + + .replay-archive__action--play { + min-width: 40px; + padding: 0; + } +}