mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-04-16 13:03:37 +00:00
New stats page, scoreboard, and live scores pages.
This commit is contained in:
70
app/views/matches/_match_results_fields.html.erb
Normal file
70
app/views/matches/_match_results_fields.html.erb
Normal file
@@ -0,0 +1,70 @@
|
||||
<% submit_label = local_assigns.fetch(:submit_label, "Update Match") %>
|
||||
<% redirect_path = local_assigns[:redirect_path] %>
|
||||
|
||||
<h4>Match Results</h4>
|
||||
<br>
|
||||
<div data-controller="match-score" data-match-score-finished-value="<%= @match.finished == 1 %>">
|
||||
<div class="field">
|
||||
<%= f.label "Win type" %><br>
|
||||
<%= f.select :win_type, Match::WIN_TYPES, { include_blank: false }, {
|
||||
data: {
|
||||
match_score_target: "winType",
|
||||
action: "change->match-score#winTypeChanged"
|
||||
}
|
||||
} %>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Overtime Type" %> Leave blank if not overtime. For High School the 1st overtime is SV-1, second overtime is TB-1, third overtime is UTB.<br>
|
||||
<%= f.select(:overtime_type, Match::OVERTIME_TYPES, {}, {
|
||||
data: {
|
||||
match_score_target: "overtimeSelect"
|
||||
}
|
||||
}) %>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Winner" %> Please choose the winner<br>
|
||||
<%= f.collection_select :winner_id, @wrestlers, :id, :name_with_school,
|
||||
{ include_blank: true },
|
||||
{
|
||||
data: {
|
||||
match_score_target: "winnerSelect",
|
||||
action: "change->match-score#winnerChanged"
|
||||
}
|
||||
}
|
||||
%>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Final Score" %>
|
||||
<br>
|
||||
<% if @match.finished == 1 %>
|
||||
<%= f.text_field :score, id: "final-score-field", data: { match_score_target: "finalScoreField" }, class: "form-control", style: "max-width: 220px;" %>
|
||||
<% else %>
|
||||
<span id="score-help-text">
|
||||
The input will adjust based on the selected win type.
|
||||
</span>
|
||||
<br>
|
||||
<div id="dynamic-score-input" data-match-score-target="dynamicScoreInput"></div>
|
||||
<p id="pin-time-tip" class="text-muted mt-2" style="display: none;" data-match-score-target="pinTimeTip">
|
||||
<strong>Tip:</strong> Pin time is an accumulation over the match, not how much time was left in the current period.
|
||||
<br>For example, if all 3 periods are 2 minutes and a pin happened with 1:27 left in the second period,
|
||||
the pin time would be <strong>2:33</strong> (2 minutes for the first period + 33 seconds elapsed in the second period).
|
||||
</p>
|
||||
<%= f.hidden_field :score, id: "final-score-field", data: { match_score_target: "finalScoreField" } %>
|
||||
<% end %>
|
||||
<div id="validation-alerts" class="text-danger mt-2" data-match-score-target="validationAlerts"></div>
|
||||
<%= hidden_field_tag :redirect_to, redirect_path if redirect_path.present? %>
|
||||
<%= f.hidden_field :finished, value: 1 %>
|
||||
<%= f.hidden_field :round, value: @match.round %>
|
||||
|
||||
<br>
|
||||
<%= f.submit submit_label, id: "update-match-btn",
|
||||
data: {
|
||||
match_score_target: "submitButton",
|
||||
action: "click->match-score#confirmWinner"
|
||||
},
|
||||
class: "btn btn-success" %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,65 +130,6 @@
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<h4>Match Results</h4>
|
||||
<br>
|
||||
<div data-controller="match-score">
|
||||
<div class="field">
|
||||
<%= f.label "Win type" %><br>
|
||||
<%= f.select :win_type, Match::WIN_TYPES, { include_blank: false }, {
|
||||
data: {
|
||||
match_score_target: "winType",
|
||||
action: "change->match-score#winTypeChanged"
|
||||
}
|
||||
} %>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Overtime Type" %> Leave blank if not overtime. For High School the 1st overtime is SV-1, second overtime is TB-1, third overtime is UTB.<br>
|
||||
<%= f.select(:overtime_type, Match::OVERTIME_TYPES) %>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Winner" %> Please choose the winner<br>
|
||||
<%= f.collection_select :winner_id, @wrestlers, :id, :name_with_school,
|
||||
{ include_blank: true },
|
||||
{
|
||||
data: {
|
||||
match_score_target: "winnerSelect",
|
||||
action: "change->match-score#winnerChanged"
|
||||
}
|
||||
}
|
||||
%>
|
||||
</div>
|
||||
<br>
|
||||
<div class="field">
|
||||
<%= f.label "Final Score" %>
|
||||
<br>
|
||||
<span id="score-help-text">
|
||||
The input will adjust based on the selected win type.
|
||||
</span>
|
||||
<br>
|
||||
<div id="dynamic-score-input" data-match-score-target="dynamicScoreInput"></div>
|
||||
<p id="pin-time-tip" class="text-muted mt-2" style="display: none;" data-match-score-target="pinTimeTip">
|
||||
<strong>Tip:</strong> Pin time is an accumulation over the match, not how much time was left in the current period.
|
||||
<br>For example, if all 3 periods are 2 minutes and a pin happened with 1:27 left in the second period,
|
||||
the pin time would be <strong>2:33</strong> (2 minutes for the first period + 33 seconds elapsed in the second period).
|
||||
</p>
|
||||
<div id="validation-alerts" class="text-danger mt-2" data-match-score-target="validationAlerts"></div>
|
||||
<%= f.hidden_field :score, id: "final-score-field", data: { match_score_target: "finalScoreField" } %>
|
||||
|
||||
<br>
|
||||
<%= f.submit "Update Match", id: "update-match-btn",
|
||||
data: {
|
||||
match_score_target: "submitButton",
|
||||
action: "click->match-score#confirmWinner"
|
||||
},
|
||||
class: "btn btn-success" %>
|
||||
</div>
|
||||
</div><!-- End of match-score controller -->
|
||||
<%= render "matches/match_results_fields", f: f, redirect_path: @match_results_redirect_path %>
|
||||
</div><!-- End of match-data controller div -->
|
||||
|
||||
<br>
|
||||
<%= f.hidden_field :finished, :value => 1 %>
|
||||
<%= f.hidden_field :round, :value => @match.round %>
|
||||
<% end %><!-- End of form_for -->
|
||||
|
||||
113
app/views/matches/_scoreboard.html.erb
Normal file
113
app/views/matches/_scoreboard.html.erb
Normal file
@@ -0,0 +1,113 @@
|
||||
<%
|
||||
source_mode = local_assigns.fetch(:source_mode, "localstorage")
|
||||
display_mode = local_assigns.fetch(:display_mode, "fullscreen")
|
||||
show_mat_banner = local_assigns.fetch(:show_mat_banner, false)
|
||||
show_stats = local_assigns.fetch(:show_stats, false)
|
||||
mat = local_assigns[:mat]
|
||||
match = local_assigns[:match]
|
||||
tournament = local_assigns[:tournament] || match&.tournament
|
||||
|
||||
fullscreen = display_mode == "fullscreen"
|
||||
root_style = if fullscreen
|
||||
"min-height: 100vh; background: #000; color: #fff; display: flex; align-items: stretch; justify-content: stretch; padding: 0; margin: 0; position: relative;"
|
||||
elsif show_stats
|
||||
"background: #000; color: #fff; padding: 0; margin: 0; position: relative; width: 100%; border: 1px solid #222;"
|
||||
else
|
||||
"background: #000; color: #fff; display: flex; align-items: stretch; justify-content: stretch; padding: 0; margin: 0; position: relative; width: 100%; min-height: 260px; border: 1px solid #222;"
|
||||
end
|
||||
inner_style = if fullscreen
|
||||
"display: grid; grid-template-rows: auto 1fr; width: 100vw; min-height: 100vh;"
|
||||
elsif show_stats
|
||||
"display: grid; grid-template-rows: auto auto auto; width: 100%;"
|
||||
else
|
||||
"display: grid; grid-template-rows: auto 1fr; width: 100%; min-height: 260px;"
|
||||
end
|
||||
board_style = fullscreen ? "display: grid; grid-template-columns: 1fr 1.3fr 1fr; width: 100%; min-height: 0;" : "display: grid; grid-template-columns: 1fr 1.2fr 1fr; width: 100%; min-height: 0; min-height: 260px;"
|
||||
panel_padding = fullscreen ? "2vw" : "1rem"
|
||||
name_size = fullscreen ? "clamp(2rem, 4vw, 4rem)" : "clamp(1rem, 2vw, 1.8rem)"
|
||||
school_size = fullscreen ? "clamp(1rem, 2vw, 2rem)" : "clamp(0.85rem, 1.3vw, 1.1rem)"
|
||||
score_size = fullscreen ? "clamp(8rem, 18vw, 16rem)" : "clamp(3rem, 8vw, 6rem)"
|
||||
period_size = fullscreen ? "clamp(1.5rem, 3vw, 2.5rem)" : "clamp(1rem, 2vw, 1.5rem)"
|
||||
clock_size = fullscreen ? "clamp(6rem, 16vw, 14rem)" : "clamp(3rem, 10vw, 5.5rem)"
|
||||
banner_offset = fullscreen ? "6vw" : "2rem"
|
||||
banner_border = fullscreen ? "0.45vw" : "4px"
|
||||
center_border = fullscreen ? "1vw" : "6px"
|
||||
%>
|
||||
|
||||
<div
|
||||
data-controller="match-scoreboard"
|
||||
data-match-scoreboard-source-mode-value="<%= source_mode %>"
|
||||
data-match-scoreboard-display-mode-value="<%= display_mode %>"
|
||||
data-match-scoreboard-match-id-value="<%= match&.id || 0 %>"
|
||||
data-match-scoreboard-mat-id-value="<%= mat&.id || 0 %>"
|
||||
data-match-scoreboard-tournament-id-value="<%= tournament&.id || 0 %>"
|
||||
data-match-scoreboard-initial-bout-number-value="<%= match&.bout_number || 0 %>"
|
||||
style="<%= root_style %>">
|
||||
<div style="<%= inner_style %>">
|
||||
<% if show_mat_banner %>
|
||||
<div style="background: #111; color: #fff; text-align: center; padding: 1vh 2vw; border-bottom: 0.5vw solid #fff;">
|
||||
<div style="font-size: clamp(1.5rem, 3vw, 3rem); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;">
|
||||
Mat <%= mat&.name %>
|
||||
</div>
|
||||
<div data-match-scoreboard-target="boutLabel" style="font-size: clamp(1rem, 2vw, 1.75rem); letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.95; margin-top: 0.3rem;">
|
||||
Bout <%= match&.bout_number || "" %>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<div style="background: #111; color: #fff; text-align: center; padding: 0.35rem 1rem; border-bottom: 4px solid #fff;">
|
||||
<div data-match-scoreboard-target="boutLabel" style="font-size: clamp(0.85rem, 1.3vw, 1.1rem); letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.95;">
|
||||
Bout <%= match&.bout_number || "" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div style="<%= board_style %>">
|
||||
<section data-match-scoreboard-target="redSection" style="background: #c91f1f; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: <%= panel_padding %>; text-align: center;">
|
||||
<div data-match-scoreboard-target="redName" style="font-size: <%= name_size %>; font-weight: 700; line-height: 1;">NO MATCH</div>
|
||||
<div data-match-scoreboard-target="redSchool" style="font-size: <%= school_size %>; margin-top: 0.75rem; opacity: 0.95;"></div>
|
||||
<div data-match-scoreboard-target="redTimerIndicator" style="font-size: <%= school_size %>; margin-top: 0.75rem;"></div>
|
||||
<div data-match-scoreboard-target="redScore" style="font-size: <%= score_size %>; font-weight: 800; line-height: 0.9; margin-top: 3vh;">0</div>
|
||||
</section>
|
||||
|
||||
<section data-match-scoreboard-target="centerSection" style="background: #050505; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: <%= panel_padding %>; text-align: center; border-left: <%= center_border %> solid #fff; border-right: <%= center_border %> solid #fff;">
|
||||
<div data-match-scoreboard-target="periodLabel" style="font-size: <%= period_size %>; font-weight: 700; margin-top: 2vh; text-transform: uppercase;">No Match</div>
|
||||
<div data-match-scoreboard-target="clock" style="font-size: <%= clock_size %>; font-weight: 800; line-height: 0.9; margin-top: 3vh;">-</div>
|
||||
<div data-match-scoreboard-target="emptyState" style="display: none; margin-top: 4vh; font-size: clamp(1.5rem, 3vw, 4rem); font-weight: 700; color: #fff;">No Match</div>
|
||||
</section>
|
||||
|
||||
<section data-match-scoreboard-target="greenSection" style="background: #1cab2d; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: <%= panel_padding %>; text-align: center;">
|
||||
<div data-match-scoreboard-target="greenName" style="font-size: <%= name_size %>; font-weight: 700; line-height: 1;">NO MATCH</div>
|
||||
<div data-match-scoreboard-target="greenSchool" style="font-size: <%= school_size %>; margin-top: 0.75rem; opacity: 0.95;"></div>
|
||||
<div data-match-scoreboard-target="greenTimerIndicator" style="font-size: <%= school_size %>; margin-top: 0.75rem;"></div>
|
||||
<div data-match-scoreboard-target="greenScore" style="font-size: <%= score_size %>; font-weight: 800; line-height: 0.9; margin-top: 3vh;">0</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<% if show_stats %>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; background: #fff; color: #111; padding: 12px;">
|
||||
<section style="border: 1px solid #d9d9d9; padding: 12px; min-width: 0;">
|
||||
<div style="font-weight: 700; margin-bottom: 8px;">Red Stats</div>
|
||||
<pre data-match-scoreboard-target="redStats" style="margin: 0; background: #f7f7f7; border: 1px solid #ececec; padding: 10px; min-height: 120px; white-space: pre-wrap; overflow-wrap: anywhere;"></pre>
|
||||
</section>
|
||||
|
||||
<section style="border: 1px solid #d9d9d9; padding: 12px; min-width: 0;">
|
||||
<div style="font-weight: 700; margin-bottom: 8px;">Green Stats</div>
|
||||
<pre data-match-scoreboard-target="greenStats" style="margin: 0; background: #f7f7f7; border: 1px solid #ececec; padding: 10px; min-height: 120px; white-space: pre-wrap; overflow-wrap: anywhere;"></pre>
|
||||
</section>
|
||||
</div>
|
||||
<div style="background: #fff; color: #111; padding: 0 12px 12px;">
|
||||
<section style="border: 1px solid #d9d9d9; padding: 12px;">
|
||||
<div style="font-weight: 700; margin-bottom: 8px;">Last Match Result</div>
|
||||
<div data-match-scoreboard-target="lastMatchResult">-</div>
|
||||
</section>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-match-scoreboard-target="timerBanner"
|
||||
style="display: none; position: absolute; left: <%= banner_offset %>; right: <%= banner_offset %>; top: 50%; transform: translateY(-50%); background: rgba(15, 15, 15, 0.96); border: <%= banner_border %> solid #fff; padding: 1.5vh 2vw; text-align: center; z-index: 20;">
|
||||
<div data-match-scoreboard-target="timerBannerLabel" style="font-size: <%= fullscreen ? "clamp(1.3rem, 2.6vw, 2.6rem)" : "clamp(0.9rem, 1.6vw, 1.25rem)" %>; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;"></div>
|
||||
<div data-match-scoreboard-target="timerBannerClock" style="font-size: <%= fullscreen ? "clamp(2.5rem, 6vw, 6rem)" : "clamp(1.6rem, 4vw, 3rem)" %>; font-weight: 800; line-height: 1; margin-top: 0.5vh;"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -10,6 +10,18 @@
|
||||
class="alert alert-secondary"
|
||||
style="padding: 5px; margin-bottom: 10px; border-radius: 4px;"></div>
|
||||
|
||||
<% unless @match.finished %>
|
||||
<div data-match-spectate-target="scoreboardContainer" style="margin-bottom: 20px;">
|
||||
<%= render "tournaments/live_score_card",
|
||||
source_mode: "websocket",
|
||||
show_mat_header: false,
|
||||
show_details: false,
|
||||
mat: @match.mat,
|
||||
match: @match,
|
||||
tournament: @tournament %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="match-details">
|
||||
<div class="wrestler-info wrestler1">
|
||||
<h4><%= @wrestler1_name %> (<%= @wrestler1_school_name %>)</h4>
|
||||
@@ -83,4 +95,4 @@
|
||||
color: white;
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
</style>
|
||||
|
||||
108
app/views/matches/state.html.erb
Normal file
108
app/views/matches/state.html.erb
Normal file
@@ -0,0 +1,108 @@
|
||||
<h1><%= @wrestler1_name %> VS. <%= @wrestler2_name %></h1>
|
||||
|
||||
<div
|
||||
data-controller="match-state"
|
||||
data-match-state-match-id-value="<%= @match.id %>"
|
||||
data-match-state-tournament-id-value="<%= @match.tournament.id %>"
|
||||
data-match-state-bout-number-value="<%= @match.bout_number %>"
|
||||
data-match-state-weight-label-value="<%= @match.weight&.max %>"
|
||||
data-match-state-bracket-position-value="<%= @match.bracket_position %>"
|
||||
data-match-state-ruleset-value="<%= @match_state_ruleset %>"
|
||||
data-match-state-w1-id-value="<%= @match.w1 || 0 %>"
|
||||
data-match-state-w2-id-value="<%= @match.w2 || 0 %>"
|
||||
data-match-state-w1-name-value="<%= @wrestler1_name %>"
|
||||
data-match-state-w2-name-value="<%= @wrestler2_name %>"
|
||||
data-match-state-w1-school-value="<%= @wrestler1_school_name %>"
|
||||
data-match-state-w2-school-value="<%= @wrestler2_school_name %>">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="panel panel-success" data-match-state-target="greenPanel">
|
||||
<div class="panel-heading">
|
||||
<strong data-match-state-target="greenLabel">Green</strong> <span data-match-state-target="greenName"><%= @wrestler1_name %></span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted" data-match-state-target="greenSchool"><%= @wrestler1_school_name %></p>
|
||||
<h2 data-match-state-target="greenScore">0</h2>
|
||||
<div data-match-state-target="greenControls"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Bout <%= @match.bout_number %></strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p><strong>Bracket Position:</strong> <%= @match.bracket_position %></p>
|
||||
<p><strong>Period:</strong> <span data-match-state-target="periodLabel"></span></p>
|
||||
<p><strong>Clock:</strong> <span data-match-state-target="clock">2:00</span></p>
|
||||
<p><strong>Status:</strong> <span data-match-state-target="clockStatus">Stopped</span></p>
|
||||
<p><strong>Match Position:</strong> <span data-match-state-target="matchPosition"></span></p>
|
||||
<p><strong>Format:</strong> <span data-match-state-target="formatName"></span></p>
|
||||
<div class="btn-group" style="margin-top: 10px;">
|
||||
<button type="button" class="btn btn-success btn-sm" data-action="click->match-state#startClock">Start</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" data-action="click->match-state#stopClock">Stop</button>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Adjust Match Clock</strong>
|
||||
<div class="btn-group" style="margin-top: 8px;">
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#subtractMinute">-1m</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#subtractSecond">-1s</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#addSecond">+1s</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#addMinute">+1m</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 12px;">
|
||||
<button type="button" class="btn btn-primary btn-sm" data-action="click->match-state#swapColors">Swap Red/Green</button>
|
||||
</div>
|
||||
<div style="margin-top: 12px;">
|
||||
<strong>Match Period Navigation</strong>
|
||||
<div class="text-muted">Use these to move between periods and choice periods.</div>
|
||||
<div class="btn-group" style="margin-top: 8px;">
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#previousPhase">Previous Period</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-action="click->match-state#nextPhase">Next Period</button>
|
||||
</div>
|
||||
<div style="margin-top: 8px;">
|
||||
<strong>Match Time Accumulation:</strong>
|
||||
<span data-match-state-target="accumulationClock">0:00</span>
|
||||
</div>
|
||||
<div style="margin-top: 12px;">
|
||||
<button type="button" class="btn btn-warning btn-sm" data-action="click->match-state#resetMatch">Reset Match</button>
|
||||
</div>
|
||||
</div>
|
||||
<div data-match-state-target="choiceActions" style="margin-top: 12px;"></div>
|
||||
<hr>
|
||||
<h4>Event Log</h4>
|
||||
<div data-match-state-target="eventLog"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="panel panel-danger" data-match-state-target="redPanel">
|
||||
<div class="panel-heading">
|
||||
<strong data-match-state-target="redLabel">Red</strong> <span data-match-state-target="redName"><%= @wrestler2_name %></span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted" data-match-state-target="redSchool"><%= @wrestler2_school_name %></p>
|
||||
<h2 data-match-state-target="redScore">0</h2>
|
||||
<div data-match-state-target="redControls"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default" data-match-state-target="matchResultsPanel">
|
||||
<div class="panel-heading">
|
||||
<strong>Submit Match Results</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<%= form_for(@match) do |f| %>
|
||||
<%= f.hidden_field :w1_stat, data: { match_state_target: "w1StatField" } %>
|
||||
<%= f.hidden_field :w2_stat, data: { match_state_target: "w2StatField" } %>
|
||||
<%= render "matches/match_results_fields", f: f, redirect_path: @match_results_redirect_path, submit_label: "Update Match" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user