mirror of
https://github.com/ENSL/ensl.org.git
synced 2025-02-04 15:31:09 +00:00
Creating view to show confirmed matches, fixing bugs in permission logic and making proposal status updates ajax requests
This commit is contained in:
parent
548b15489c
commit
62bc78274a
7 changed files with 88 additions and 33 deletions
|
@ -1,5 +1,5 @@
|
||||||
class ContestsController < ApplicationController
|
class ContestsController < ApplicationController
|
||||||
before_filter :get_contest, only: [:show, :edit, :update, :destroy, :del_map, :scores, :recalc]
|
before_filter :get_contest, only: [:show, :edit, :update, :destroy, :del_map, :scores, :recalc, :confirmed_matches]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
# @contests = Contest.all
|
# @contests = Contest.all
|
||||||
|
@ -102,6 +102,10 @@ class ContestsController < ApplicationController
|
||||||
redirect_to contests_url
|
redirect_to contests_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def confirmed_matches
|
||||||
|
@match_props = MatchProposal.confirmed_for_contest(@contest)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_contest
|
def get_contest
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class MatchProposalsController < ApplicationController
|
class MatchProposalsController < ApplicationController
|
||||||
before_filter :get_match
|
before_filter :get_match
|
||||||
def index
|
def index
|
||||||
|
raise AccessError unless @match.user_in_match?(cuser)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
@ -25,25 +26,35 @@ class MatchProposalsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@proposal = MatchProposal.find(params[:id])
|
raise AccessError unless request.xhr? # Only respond to ajax requests
|
||||||
raise AccessError unless @proposal.can_update?(cuser, params[:match_proposal])
|
rjson = {}
|
||||||
@proposal.status = params[:match_proposal][:status]
|
proposal = MatchProposal.find(params[:id])
|
||||||
if @proposal.save
|
unless proposal
|
||||||
# TODO: rework messages
|
rjson[:error] = {
|
||||||
# TODO: make it so only one proposal can be confirmed for a match at any given time
|
code: 404,
|
||||||
action = case @proposal.status
|
message: "No proposal with id #{params[:id]}"
|
||||||
when MatchProposal::STATUS_CONFIRMED
|
}
|
||||||
"Confirmed Proposal for #{Time.use_zone(view_context.timezone_offset) { @proposal.proposed_time.strftime('%d %B %y %H:%M %Z') }}"
|
render(json: rjson, status: :not_found) && return
|
||||||
when MatchProposal::STATUS_REJECTED
|
end
|
||||||
"Rejected Proposal for #{Time.use_zone(view_context.timezone_offset) { @proposal.proposed_time.strftime('%d %B %y %H:%M %Z') }}"
|
unless proposal.can_update?(cuser, params[:match_proposal])
|
||||||
else
|
rjson[:error] = {
|
||||||
"Smthn went wrong"
|
code: 403,
|
||||||
end
|
message: "You are not allowed to update the state to #{MatchProposal.status_strings[params[:match_proposal][:status].to_i]}"
|
||||||
flash[:notice] = action
|
}
|
||||||
else
|
render(json: rjson, status: :forbidden) && return
|
||||||
flash[:notice] = "Error"
|
end
|
||||||
|
proposal.status = params[:match_proposal][:status]
|
||||||
|
if proposal.save
|
||||||
|
rjson[:status] = MatchProposal.status_strings[proposal.status]
|
||||||
|
rjson[:message] = "Successfully updated status to #{MatchProposal.status_strings[proposal.status]}"
|
||||||
|
render(json: rjson, status: :success)
|
||||||
|
else
|
||||||
|
rjson[:error] = {
|
||||||
|
code: 500,
|
||||||
|
message: 'Something went wrong! Please try again.'
|
||||||
|
}
|
||||||
|
render(json: rjson, status: 500)
|
||||||
end
|
end
|
||||||
redirect_to(match_proposals_path(@match))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -19,8 +19,10 @@ class MatchProposal < ActiveRecord::Base
|
||||||
scope :of_match, ->(match) { where('match_id = ?', match.id) }
|
scope :of_match, ->(match) { where('match_id = ?', match.id) }
|
||||||
scope :confirmed_for_match, ->(match) { where('match_id = ? AND status = ?', match.id, STATUS_CONFIRMED) }
|
scope :confirmed_for_match, ->(match) { where('match_id = ? AND status = ?', match.id, STATUS_CONFIRMED) }
|
||||||
scope :confirmed_upcoming, ->{ where('status = ? AND proposed_time > UTC_TIMESTAMP()', STATUS_CONFIRMED) }
|
scope :confirmed_upcoming, ->{ where('status = ? AND proposed_time > UTC_TIMESTAMP()', STATUS_CONFIRMED) }
|
||||||
|
scope :confirmed_for_contest,
|
||||||
|
->(contest){ includes(:match).where(matches:{contest_id: contest.id}, status: STATUS_CONFIRMED).all}
|
||||||
|
|
||||||
def status_strings
|
def self.status_strings
|
||||||
{STATUS_PENDING => 'Pending',
|
{STATUS_PENDING => 'Pending',
|
||||||
STATUS_REVOKED => 'Revoked',
|
STATUS_REVOKED => 'Revoked',
|
||||||
STATUS_REJECTED => 'Rejected',
|
STATUS_REJECTED => 'Rejected',
|
||||||
|
@ -47,7 +49,11 @@ class MatchProposal < ActiveRecord::Base
|
||||||
cuser && cuser.admin?
|
cuser && cuser.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def state_immutable?
|
||||||
|
status == STATUS_REJECTED ||
|
||||||
|
status == STATUS_DELAYED ||
|
||||||
|
status == STATUS_REVOKED
|
||||||
|
end
|
||||||
|
|
||||||
def status_change_allowed?(cuser, new_status)
|
def status_change_allowed?(cuser, new_status)
|
||||||
case new_status
|
case new_status
|
||||||
|
@ -58,17 +64,20 @@ class MatchProposal < ActiveRecord::Base
|
||||||
# only confirmed matches can be set to delayed
|
# only confirmed matches can be set to delayed
|
||||||
# only admins can set matches to delayed and only if they are not playing in that match
|
# only admins can set matches to delayed and only if they are not playing in that match
|
||||||
# matches can only be delayed if they are not to far in the future
|
# matches can only be delayed if they are not to far in the future
|
||||||
return false unless self.status == STATUS_CONFIRMED && cuser.admin? &&
|
return self.status == STATUS_CONFIRMED && cuser.admin? &&
|
||||||
!self.match.user_in_match?(cuser) && self.proposed_time <= CONFIRMATION_LIMIT.minutes.from_now
|
!self.match.user_in_match?(cuser) && self.proposed_time <= CONFIRMATION_LIMIT.minutes.from_now
|
||||||
when STATUS_REVOKED
|
when STATUS_REVOKED
|
||||||
# unconfirmed can only be revoked by team making the proposal
|
# unconfirmed can only be revoked by team making the proposal
|
||||||
# confirmed can only be revoked if soon enough before match time
|
# confirmed can only be revoked if soon enough before match time
|
||||||
return false unless self.status == STATUS_PENDING && self.team == cuser.team ||
|
return self.status == STATUS_PENDING && self.team == cuser.team ||
|
||||||
self.status == STATUS_CONFIRMED && self.proposed_time > CONFIRMATION_LIMIT.minutes.from_now
|
self.status == STATUS_CONFIRMED && self.proposed_time > CONFIRMATION_LIMIT.minutes.from_now
|
||||||
when STATUS_CONFIRMED, STATUS_REJECTED
|
when STATUS_CONFIRMED, STATUS_REJECTED
|
||||||
# only team proposed to can reject or confirm and only if soon enough before match time
|
# only team proposed to can reject or confirm and only if soon enough before match time
|
||||||
return false unless self.status == STATUS_PENDING && self.team != cuser.team &&
|
status_ok = self.status == STATUS_PENDING
|
||||||
self.proposed_time < CONFIRMATION_LIMIT.minutes.from_now
|
team_ok = self.team != cuser.team
|
||||||
|
time_ok = CONFIRMATION_LIMIT.minutes.from_now < self.proposed_time
|
||||||
|
|
||||||
|
return status_ok && team_ok && time_ok
|
||||||
else
|
else
|
||||||
# invalid status
|
# invalid status
|
||||||
return false
|
return false
|
||||||
|
|
13
app/views/contests/confirmed_matches.html.erb
Normal file
13
app/views/contests/confirmed_matches.html.erb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<h1 class="title">Confirmed Matches for <%= @contest.name %></h1>
|
||||||
|
<table class="striped">
|
||||||
|
<tr>
|
||||||
|
<th>Match</th>
|
||||||
|
<th>Scheduled for</th>
|
||||||
|
</tr>
|
||||||
|
<% @match_props && @match_props.each do |mp| %>
|
||||||
|
<tr>
|
||||||
|
<th><%= link_to mp.match.contester1, contester_path(mp.match.contester1) %> VS <%= link_to mp.match.contester2, contester_path(mp.match.contester2) %></th>
|
||||||
|
<th><%= longertime(mp.proposed_time) %></th>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
|
@ -1,7 +1,8 @@
|
||||||
<h1>Proposals</h1>
|
<h1>Proposals</h1>
|
||||||
|
<h2><%= @match.contester1 %> VS <%= @match.contester2 %></h2>
|
||||||
<%= link_to 'Back', match_path(@match), class: 'button' %>
|
<%= link_to 'Back', match_path(@match), class: 'button' %>
|
||||||
<% if @match.match_proposals.empty? %>
|
<% if @match.match_proposals.empty? %>
|
||||||
<h4>There are no proposals yet</h4>
|
<h4 style="clear: both;">There are no proposals yet</h4>
|
||||||
<% else %>
|
<% else %>
|
||||||
<table id="proposals" class="striped">
|
<table id="proposals" class="striped">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -16,13 +17,19 @@
|
||||||
<tr class="<%=cycle('even', 'odd') %>">
|
<tr class="<%=cycle('even', 'odd') %>">
|
||||||
<td><%= proposal.team.name %></td>
|
<td><%= proposal.team.name %></td>
|
||||||
<td><%= longtime proposal.proposed_time %> </td>
|
<td><%= longtime proposal.proposed_time %> </td>
|
||||||
<td><%= proposal.status_strings[proposal.status] %></td>
|
<td><%= MatchProposal.status_strings[proposal.status] %></td>
|
||||||
<% if @match.can_make_proposal?(cuser) %>
|
<% if @match.can_make_proposal?(cuser) %>
|
||||||
<td>
|
<td>
|
||||||
<%= form_for proposal, url: match_proposal_path(@match, proposal) do |f| %>
|
<% unless proposal.state_immutable? %>
|
||||||
<%= f.hidden_field :status, value: 0 %>
|
<%= form_for proposal, url: match_proposal_path(@match, proposal) do |f| %>
|
||||||
<%= link_to_function icon('check'), "proposalStateSubmit(#{MatchProposal::STATUS_CONFIRMED},#{proposal.id})" %>
|
<%= f.hidden_field :status, value: 0 %>
|
||||||
<%= link_to_function icon('times'), "proposalStateSubmit(#{MatchProposal::STATUS_REJECTED},#{proposal.id})" %>
|
<%= link_to_function icon('check'), "proposalStateSubmit(#{MatchProposal::STATUS_CONFIRMED},#{proposal.id})", title: 'Confirm' %>
|
||||||
|
<%= link_to_function icon('times'), "proposalStateSubmit(#{MatchProposal::STATUS_REJECTED},#{proposal.id})", title: 'Reject' %>
|
||||||
|
<%= link_to_function icon('eraser'), "proposalStateSubmit(#{MatchProposal::STATUS_REVOKED},#{proposal.id})", title: 'Revoke' %>
|
||||||
|
<% if proposal.status_change_allowed?(cuser, MatchProposal::STATUS_DELAYED) %>
|
||||||
|
<%= link_to_function icon('hourglass'), "proposalStateSubmit(#{MatchProposal::STATUS_DELAYED},#{proposal.id})", title: 'Delay' %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -33,7 +40,16 @@
|
||||||
function proposalStateSubmit(newState, formID) {
|
function proposalStateSubmit(newState, formID) {
|
||||||
var form = $('#edit_match_proposal_' + formID);
|
var form = $('#edit_match_proposal_' + formID);
|
||||||
form.children("input[type='hidden']").val(newState);
|
form.children("input[type='hidden']").val(newState);
|
||||||
form.submit();
|
$.post(form.attr('action'),form.serialize(), function(data) {
|
||||||
|
datajson = data.responseText;
|
||||||
|
tr = form.closest('tr');
|
||||||
|
tr.children('td').eq(1).html(datajson.status);
|
||||||
|
alert(datajson.message);
|
||||||
|
}, 'json')
|
||||||
|
.error(function (err) {
|
||||||
|
errjson = JSON.parse(err.responseText);
|
||||||
|
alert(errjson.error.message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -116,7 +116,7 @@
|
||||||
<p><%= @match.report.html_safe %></p>
|
<p><%= @match.report.html_safe %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if cuser and (cuser.admin? or @match.of_user cuser) %>
|
<% if cuser and (cuser.admin? or @match.user_in_match? cuser) %>
|
||||||
<div class="referee">
|
<div class="referee">
|
||||||
<%= link_to 'Proposals', match_proposals_path(@match), class: 'button' %>
|
<%= link_to 'Proposals', match_proposals_path(@match), class: 'button' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,6 +51,8 @@ Ensl::Application.routes.draw do
|
||||||
resources :users
|
resources :users
|
||||||
resources :locks
|
resources :locks
|
||||||
resources :contesters
|
resources :contesters
|
||||||
|
|
||||||
|
get "contests/:id/confirmedmatches" => "contests#confirmed_matches", as: :confirmed_matches
|
||||||
resources :contests
|
resources :contests
|
||||||
resources :challenges
|
resources :challenges
|
||||||
resources :servers
|
resources :servers
|
||||||
|
|
Loading…
Reference in a new issue