mirror of
https://github.com/ENSL/ensl.org.git
synced 2024-11-14 17:01:20 +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
|
||||
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
|
||||
# @contests = Contest.all
|
||||
|
@ -102,6 +102,10 @@ class ContestsController < ApplicationController
|
|||
redirect_to contests_url
|
||||
end
|
||||
|
||||
def confirmed_matches
|
||||
@match_props = MatchProposal.confirmed_for_contest(@contest)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_contest
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class MatchProposalsController < ApplicationController
|
||||
before_filter :get_match
|
||||
def index
|
||||
raise AccessError unless @match.user_in_match?(cuser)
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -25,25 +26,35 @@ class MatchProposalsController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
@proposal = MatchProposal.find(params[:id])
|
||||
raise AccessError unless @proposal.can_update?(cuser, params[:match_proposal])
|
||||
@proposal.status = params[:match_proposal][:status]
|
||||
if @proposal.save
|
||||
# TODO: rework messages
|
||||
# TODO: make it so only one proposal can be confirmed for a match at any given time
|
||||
action = case @proposal.status
|
||||
when MatchProposal::STATUS_CONFIRMED
|
||||
"Confirmed Proposal for #{Time.use_zone(view_context.timezone_offset) { @proposal.proposed_time.strftime('%d %B %y %H:%M %Z') }}"
|
||||
when MatchProposal::STATUS_REJECTED
|
||||
"Rejected Proposal for #{Time.use_zone(view_context.timezone_offset) { @proposal.proposed_time.strftime('%d %B %y %H:%M %Z') }}"
|
||||
else
|
||||
"Smthn went wrong"
|
||||
end
|
||||
flash[:notice] = action
|
||||
else
|
||||
flash[:notice] = "Error"
|
||||
raise AccessError unless request.xhr? # Only respond to ajax requests
|
||||
rjson = {}
|
||||
proposal = MatchProposal.find(params[:id])
|
||||
unless proposal
|
||||
rjson[:error] = {
|
||||
code: 404,
|
||||
message: "No proposal with id #{params[:id]}"
|
||||
}
|
||||
render(json: rjson, status: :not_found) && return
|
||||
end
|
||||
unless proposal.can_update?(cuser, params[:match_proposal])
|
||||
rjson[:error] = {
|
||||
code: 403,
|
||||
message: "You are not allowed to update the state to #{MatchProposal.status_strings[params[:match_proposal][:status].to_i]}"
|
||||
}
|
||||
render(json: rjson, status: :forbidden) && return
|
||||
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
|
||||
redirect_to(match_proposals_path(@match))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -19,8 +19,10 @@ class MatchProposal < ActiveRecord::Base
|
|||
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_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_REVOKED => 'Revoked',
|
||||
STATUS_REJECTED => 'Rejected',
|
||||
|
@ -47,7 +49,11 @@ class MatchProposal < ActiveRecord::Base
|
|||
cuser && cuser.admin?
|
||||
end
|
||||
|
||||
private
|
||||
def state_immutable?
|
||||
status == STATUS_REJECTED ||
|
||||
status == STATUS_DELAYED ||
|
||||
status == STATUS_REVOKED
|
||||
end
|
||||
|
||||
def status_change_allowed?(cuser, new_status)
|
||||
case new_status
|
||||
|
@ -58,17 +64,20 @@ class MatchProposal < ActiveRecord::Base
|
|||
# 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
|
||||
# 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
|
||||
when STATUS_REVOKED
|
||||
# unconfirmed can only be revoked by team making the proposal
|
||||
# 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
|
||||
when STATUS_CONFIRMED, STATUS_REJECTED
|
||||
# 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 &&
|
||||
self.proposed_time < CONFIRMATION_LIMIT.minutes.from_now
|
||||
status_ok = self.status == STATUS_PENDING
|
||||
team_ok = self.team != cuser.team
|
||||
time_ok = CONFIRMATION_LIMIT.minutes.from_now < self.proposed_time
|
||||
|
||||
return status_ok && team_ok && time_ok
|
||||
else
|
||||
# invalid status
|
||||
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>
|
||||
<h2><%= @match.contester1 %> VS <%= @match.contester2 %></h2>
|
||||
<%= link_to 'Back', match_path(@match), class: 'button' %>
|
||||
<% if @match.match_proposals.empty? %>
|
||||
<h4>There are no proposals yet</h4>
|
||||
<h4 style="clear: both;">There are no proposals yet</h4>
|
||||
<% else %>
|
||||
<table id="proposals" class="striped">
|
||||
<tr>
|
||||
|
@ -16,13 +17,19 @@
|
|||
<tr class="<%=cycle('even', 'odd') %>">
|
||||
<td><%= proposal.team.name %></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) %>
|
||||
<td>
|
||||
<%= form_for proposal, url: match_proposal_path(@match, proposal) do |f| %>
|
||||
<%= f.hidden_field :status, value: 0 %>
|
||||
<%= link_to_function icon('check'), "proposalStateSubmit(#{MatchProposal::STATUS_CONFIRMED},#{proposal.id})" %>
|
||||
<%= link_to_function icon('times'), "proposalStateSubmit(#{MatchProposal::STATUS_REJECTED},#{proposal.id})" %>
|
||||
<% unless proposal.state_immutable? %>
|
||||
<%= form_for proposal, url: match_proposal_path(@match, proposal) do |f| %>
|
||||
<%= f.hidden_field :status, value: 0 %>
|
||||
<%= 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 %>
|
||||
</td>
|
||||
<% end %>
|
||||
|
@ -33,7 +40,16 @@
|
|||
function proposalStateSubmit(newState, formID) {
|
||||
var form = $('#edit_match_proposal_' + formID);
|
||||
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>
|
||||
<% end %>
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
<p><%= @match.report.html_safe %></p>
|
||||
</div>
|
||||
<% 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">
|
||||
<%= link_to 'Proposals', match_proposals_path(@match), class: 'button' %>
|
||||
</div>
|
||||
|
|
|
@ -51,6 +51,8 @@ Ensl::Application.routes.draw do
|
|||
resources :users
|
||||
resources :locks
|
||||
resources :contesters
|
||||
|
||||
get "contests/:id/confirmedmatches" => "contests#confirmed_matches", as: :confirmed_matches
|
||||
resources :contests
|
||||
resources :challenges
|
||||
resources :servers
|
||||
|
|
Loading…
Reference in a new issue