Completa modulo Replay: S3, retention, sync YouTube e gestione società.

Streaming chunked da Garage, purge con delete YouTube, privacy sincronizzata,
archivio club migliorato, retention 30/90 separata da stato abbonamento.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-08 09:33:59 +02:00
parent ae36d17adb
commit 74eee24293
17 changed files with 385 additions and 34 deletions

View File

@@ -5,7 +5,11 @@
<%= link_to "← #{@club.name}", public_club_path(@club), class: "back-link" %>
<h1>Archivio Replay</h1>
<p class="muted">Gestisci registrazioni, visibilità, download e pubblicazione YouTube.</p>
<p class="muted">
Gestisci registrazioni, visibilità e download.
<strong>Privato</strong> = link non indicizzato, non compare in <code>/replay</code> pubblico.
Eliminando un replay vengono rimossi anche i file sul server e il video YouTube collegato.
</p>
<div class="kpi-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin:20px 0">
<div class="card" style="padding:16px">
@@ -26,6 +30,23 @@
</div>
</div>
<%= form_with url: public_club_recordings_path(@club), method: :get, local: true, class: "replay-filter-form" do %>
<label for="team_id" class="muted">Squadra</label>
<select name="team_id" id="team_id" class="input" onchange="this.form.submit()">
<option value="">Tutte</option>
<% @teams.each do |team| %>
<option value="<%= team.id %>"<%= " selected" if @filter_team_id.to_s == team.id.to_s %>><%= team.name %></option>
<% end %>
</select>
<label for="status" class="muted">Stato</label>
<select name="status" id="status" class="input" onchange="this.form.submit()">
<option value="">Tutti</option>
<option value="ready"<%= " selected" if @filter_status == "ready" %>>Disponibili</option>
<option value="processing"<%= " selected" if @filter_status == "processing" %>>In elaborazione</option>
<option value="expired"<%= " selected" if @filter_status == "expired" %>>Scaduti / errore</option>
</select>
<% end %>
<% if @recordings.any? %>
<div class="card">
<table class="data">
@@ -33,6 +54,7 @@
<tr>
<th></th>
<th>Titolo</th>
<th>Piattaforma</th>
<th>Data</th>
<th>Durata</th>
<th>Views</th>
@@ -50,22 +72,40 @@
<img src="<%= rec.thumbnail_url %>" alt="" width="64" height="36" style="object-fit:cover;border-radius:4px">
<% end %>
</td>
<td><%= rec.title_or_default %></td>
<td>
<%= 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 %>
</td>
<td><%= rec.source_platform_label %></td>
<td><%= l_local(rec.recorded_at_or_fallback) %></td>
<td><%= rec.duration_label %></td>
<td><%= rec.view_count %></td>
<td><%= rec.expires_at ? l_local(rec.expires_at) : "—" %></td>
<td>
<% if rec.expires_at %>
<%= l_local(rec.expires_at) %>
<% if rec.days_until_expiry && rec.days_until_expiry.positive? %>
<br><span class="muted" style="font-size:0.75rem">(<%= rec.days_until_expiry %> gg)</span>
<% end %>
<% else %>
<% end %>
</td>
<td><%= rec.status_label %></td>
<td>
<%= 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", "unlisted"]], rec.privacy_status),
options_for_select([["Pubblico", "public"], ["Privato (link)", "unlisted"]], rec.privacy_status),
onchange: "this.form.submit()" %>
<% end %>
</td>
<td style="white-space:nowrap;font-size:0.8rem">
<% if rec.replay_url %>
<%= link_to "Guarda", rec.replay_url, target: "_blank", rel: "noopener" %>
<%= 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) %>
@@ -77,8 +117,9 @@
· <%= 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?" } } %>
form: { data: { turbo_confirm: "Eliminare definitivamente questo replay? Verranno rimossi i file sul server e il video YouTube collegato." } } %>
</td>
</tr>
<% end %>