Improve contest page and match list for maps

Improve brackets
Update gitignore and docs.
This commit is contained in:
Ari Timonen 2020-03-28 22:39:41 +02:00
parent 747ef21d5b
commit f6b30be278
18 changed files with 94 additions and 18 deletions

5
.gitignore vendored
View file

@ -60,6 +60,11 @@ pickle-email-*.html
# Sublime # Sublime
*.sublime* *.sublime*
# Vscode
.vscode/
.rakeTasks
.generators
# Gemtags # Gemtags
*.tags *.tags
*.gemtags *.gemtags

View file

@ -17,7 +17,8 @@ Just run and open http://localhost:4000/
sudo echo `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ensl_dev_db` db >> /etc/hosts sudo echo `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ensl_dev_db` db >> /etc/hosts
1. VS Code and RubyMine are great IDE's/editors. 1. VS Code and RubyMine are great IDE's/editors.
1. To run VS Code plugin Ruby Test Explorer in docker container you need to create path to custom 1. To run VS Code plugin Ruby Test Explorer in docker container you need to create path to custom path, copy the formatter and it whines about
and it still fails a bit. https://github.com/connorshea/vscode-ruby-test-adapter/issues/21
1. Do not commit too much without testing. Also keep commits small for documentation and reversability issues. 1. Do not commit too much without testing. Also keep commits small for documentation and reversability issues.
1. You need to rebuild the docker image when you change gems. 1. You need to rebuild the docker image when you change gems.
@ -41,7 +42,7 @@ FIXME, TODO, EXPLAIN, OBSOLETE
## Handy commands ## Handy commands
Build or rebuild Build or rebuild
docker-compose -f docker-compose.dev.yml build` docker-compose -f docker-compose.dev.yml build`
To get inside docker web+test containers: To get inside docker web+test containers:

View file

@ -29,9 +29,14 @@
font-weight: normal; font-weight: normal;
text-align: center; text-align: center;
margin-bottom: 25px; margin-bottom: 25px;
margin-top: 20px;
color: $light-blue; color: $light-blue;
text-transform: uppercase; text-transform: uppercase;
} }
h4:first-child {
margin-top: 0px;
}
.widget-content-wrapper { .widget-content-wrapper {
@include span-columns(12); @include span-columns(12);
@ -70,6 +75,10 @@
text-align: center; text-align: center;
} }
div.controls, div.fields, div.select-wrapper {
width: 100%;
}
.button, .button,
.controls input { .controls input {
@include linear-gradient(#585858, #585858); @include linear-gradient(#585858, #585858);
@ -81,6 +90,7 @@
border: 0; border: 0;
line-height: 30px; line-height: 30px;
height: 30px; height: 30px;
padding: 1px 0px 0px 5px;
width: 175px; width: 175px;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@ -90,10 +100,15 @@
float: none; float: none;
} }
.button { .button.big {
height: 62px;
}
.button, .select {
clear: both; clear: both;
display: block; display: block;
margin: 0 auto; margin-left: auto;
margin-right: auto;
} }
&:last-child { &:last-child {

View file

@ -14,9 +14,14 @@
h4 { h4 {
@include span-columns(12); @include span-columns(12);
margin-bottom: 20px; margin-bottom: 20px;
margin-top: 20px;
color: $light-blue; color: $light-blue;
} }
h4:first-child {
margin-top: 0px;
}
.widget-content-wrapper { .widget-content-wrapper {
@include span-columns(12); @include span-columns(12);
font-size: 12px; font-size: 12px;

View file

@ -20,11 +20,11 @@ class BracketsController < ApplicationController
def update def update
raise AccessError unless @bracket.can_update? cuser raise AccessError unless @bracket.can_update? cuser
if @bracket.update_attributes(Bracket.params(params, cuser)) and @bracket.update_cells(params.permit(:cell)[:cell]) if @bracket.update_attributes(Bracket.params(params, cuser)) and @bracket.update_cells(params.permit(:cell))
flash[:notice] = t(:brackets_update) flash[:notice] = t(:brackets_update)
end end
render :edit render :edit, layout: 'full'
end end
def destroy def destroy

View file

@ -23,7 +23,11 @@ class Bracket < ActiveRecord::Base
has_many :bracketers has_many :bracketers
def to_s def to_s
"#" + self.id.to_s if name
name
else
"Bracket #%d" % [id]
end
end end
def get_bracketer row, col def get_bracketer row, col

View file

@ -42,7 +42,7 @@ class Contest < ActiveRecord::Base
scope :active, -> { where.not(status: STATUS_CLOSED) } scope :active, -> { where.not(status: STATUS_CLOSED) }
scope :inactive, -> { where(status: STATUS_CLOSED) } scope :inactive, -> { where(status: STATUS_CLOSED) }
scope :joinable, -> { where(status: STATUS_OPEN) } scope :joinable, -> { where(table[:status].eq(STATUS_OPEN).and(table[:end].gt(Time.now.utc))) }
scope :with_contesters, -> { includes(:contesters) } scope :with_contesters, -> { includes(:contesters) }
scope :ordered, -> { order("start DESC") } scope :ordered, -> { order("start DESC") }
scope :nsls1, -> { where("name LIKE ?", "NSL S1:%") } scope :nsls1, -> { where("name LIKE ?", "NSL S1:%") }
@ -132,6 +132,12 @@ class Contest < ActiveRecord::Base
c.uniq.pluck(:score).count == c.count c.uniq.pluck(:score).count == c.count
end end
def can_join?(cuser)
byebug
cuser and !cuser&.banned?(Ban::TYPE_LEAGUE) and \
(cuser&.lead_teams.not_in_contest(self).exists?) and \
Contest.joinable.where(id: self).exists?
end
def can_create? cuser def can_create? cuser
cuser and cuser.admin? cuser and cuser.admin?

View file

@ -18,6 +18,7 @@ class Map < ActiveRecord::Base
#attr_protected :id, :updated_at, :created_at, :deleted #attr_protected :id, :updated_at, :created_at, :deleted
has_and_belongs_to_many :contests has_and_belongs_to_many :contests
has_many :matches, -> (map){ unscope(:where).where("map1_id = :id OR map2_id = :id", id: map.id) }
scope :basic, -> { where(deleted: false).order("name") } scope :basic, -> { where(deleted: false).order("name") }
scope :with_name, -> (name) { where(name: name) } scope :with_name, -> (name) { where(name: name) }

View file

@ -164,6 +164,7 @@ class Match < ActiveRecord::Base
matchers.where(contester_id: contester2_id) matchers.where(contester_id: contester2_id)
end end
# FIXME: this is a view helper and doesn't belong here
def get_friendly(param = nil) def get_friendly(param = nil)
if param.nil? if param.nil?
friendly == contester1.team ? contester1 : contester2 friendly == contester1.team ? contester1 : contester2
@ -174,6 +175,7 @@ class Match < ActiveRecord::Base
end end
end end
# FIXME: this is a view helper and doesn't belong here
def get_opponent(param = nil) def get_opponent(param = nil)
if param.nil? if param.nil?
friendly == contester1.team ? contester2 : contester1 friendly == contester1.team ? contester2 : contester1

View file

@ -49,6 +49,7 @@ class Team < ActiveRecord::Base
scope :inactive, -> { where(active: false) } scope :inactive, -> { where(active: false) }
scope :ordered, -> { order("name") } scope :ordered, -> { order("name") }
scope :recruiting, -> { where("recruiting IS NOT NULL AND recruiting != ''") } scope :recruiting, -> { where("recruiting IS NOT NULL AND recruiting != ''") }
scope :not_in_contest, -> (contest) { joins(:contests).where.not('contests.id': contest.id) }
belongs_to :founder, :class_name => "User", :optional => true belongs_to :founder, :class_name => "User", :optional => true

View file

@ -68,6 +68,8 @@ class User < ActiveRecord::Base
has_many :teamers, :dependent => :destroy has_many :teamers, :dependent => :destroy
has_many :active_teams, -> { where("teamers.rank >= ? AND teams.active = ?", Teamer::RANK_MEMBER, true) }, \ has_many :active_teams, -> { where("teamers.rank >= ? AND teams.active = ?", Teamer::RANK_MEMBER, true) }, \
:through => :teamers, :source => "team" :through => :teamers, :source => "team"
has_many :lead_teams, -> { where("teamers.rank >= ? AND teams.active = ?", Teamer::RANK_DEPUTEE, true) }, \
:through => :teamers, :source => "team"
has_many :active_contesters, -> { where("contesters.active = ?", true) }, \ has_many :active_contesters, -> { where("contesters.active = ?", true) }, \
:through => :active_teams, :source => "contesters" :through => :active_teams, :source => "contesters"
has_many :active_contests, -> { where("contests.status != ?", Contest::STATUS_CLOSED) }, \ has_many :active_contests, -> { where("contests.status != ?", Contest::STATUS_CLOSED) }, \

View file

@ -1,3 +1,7 @@
<h3>
<%= bracket.name if !bracket.name&.empty? and !defined? edit %>
</h3>
<table class="brackets"> <table class="brackets">
<% rows = bracket.slots*2-1 %> <% rows = bracket.slots*2-1 %>
<% cols = 2+(bracket.slots/4) %> <% cols = 2+(bracket.slots/4) %>
@ -23,7 +27,7 @@
<td class="<%= element_class %>"> <td class="<%= element_class %>">
<% if element_class == "team" %> <% if element_class == "team" %>
<% if params[:action] == "edit" %> <% if defined? edit %>
<%= select_tag "cell[#{row}][#{col}]", options_for_select(bracket.options, :selected => bracket.default(row, col)) %> <%= select_tag "cell[#{row}][#{col}]", options_for_select(bracket.options, :selected => bracket.default(row, col)) %>
<% elsif bracketer %> <% elsif bracketer %>
<% if bracketer.match %> <% if bracketer.match %>

View file

@ -4,12 +4,17 @@
<%= form_for(@bracket) do |f| %> <%= form_for(@bracket) do |f| %>
<%= render 'shared/errors', messages: @bracket.errors.full_messages %> <%= render 'shared/errors', messages: @bracket.errors.full_messages %>
<div class="fields">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="fields"> <div class="fields">
<%= f.label :slots %> <%= f.label :slots %>
<%= f.text_field :slots %> <%= f.text_field :slots %>
</div> </div>
<%= render partial: "bracket", locals: { bracket: @bracket } %> <%= render partial: "bracket", locals: { bracket: @bracket, edit: true } %>
<div class="controls"> <div class="controls">
<%= f.submit 'Update' %> <%= f.submit 'Update' %>

View file

@ -110,7 +110,10 @@
<%= hidden_field_tag :type, 'contest' %> <%= hidden_field_tag :type, 'contest' %>
<%= f.hidden_field :contest_id %> <%= f.hidden_field :contest_id %>
<div class="fields horizontal">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="fields horizontal"> <div class="fields horizontal">
<%= f.label :slots %> <%= f.label :slots %>
<%= f.text_field :slots %> <%= f.text_field :slots %>

View file

@ -20,11 +20,27 @@
<dd>Sunday: <%= Time.use_zone(timezone_offset) { @contest.default_time.strftime("%H:%M %Z") } %></dd> <dd>Sunday: <%= Time.use_zone(timezone_offset) { @contest.default_time.strftime("%H:%M %Z") } %></dd>
</dl> </dl>
<%= link_to 'Scheduled Matches', confirmed_matches_path(@contest), class: 'button' %> <%= link_to 'Scheduled Matches', confirmed_matches_path(@contest), class: 'button big' %>
<% if @contest.can_update?(cuser) %> <% if @contest.can_update?(cuser) %>
<%= link_to 'Edit Contest', edit_contest_path(@contest), class: 'button' %> <%= link_to 'Edit Contest', edit_contest_path(@contest), class: 'button' %>
<% end %> <% end %>
<h4>Join Contest</h4>
<% if @contest.can_join?(cuser) %>
<%= form_for @contest.contesters.build, html: { class: 'square' } do |f| %>
<%= f.hidden_field :contest_id %>
<div class="fields inline">
<%= f.collection_select :team_id, cuser.lead_teams, :id, :name %>
</div>
<div class="controls inline">
<%= f.submit "Join Contest" %>
</div>
<% end %>
<% end %>
</div> </div>
<% end %> <% end %>

View file

@ -14,6 +14,11 @@
<p><%= link_to (h @map.download), (h @map.download) %></p> <p><%= link_to (h @map.download), (h @map.download) %></p>
<% end %> <% end %>
<h4>Played in these matches (<%= @map.matches.count %>):</h4>
<ul class="disc">
<%= render partial: 'matches/list', locals: {matches: @map.matches} %>
</ul>
<h4>Played in Contests</h4> <h4>Played in Contests</h4>
<ul class="disc"> <ul class="disc">
<% @map.contests.each do |contest| %> <% @map.contests.each do |contest| %>

View file

@ -1,6 +1,6 @@
<table id="matches" class="<%= 'contest' if contest %> striped"> <table id="matches" class="<%= 'contest' if defined? contest and contest %> striped">
<tr> <tr>
<% if contest %> <% if defined? contest and contest %>
<th class="contest">Contest</th> <th class="contest">Contest</th>
<th class="opponent">Opponent</th> <th class="opponent">Opponent</th>
<% else %> <% else %>
@ -17,9 +17,9 @@
</tr> </tr>
<% matches.each do |match| %> <% matches.each do |match| %>
<% match.friendly = friendly %> <% match.friendly = defined? friendly ? friendly : nil %>
<tr> <tr>
<% if contest %> <% if defined? contest and contest %>
<td> <td>
<%= namelink match.contest %> <%= namelink match.contest %>
</td> </td>
@ -37,14 +37,14 @@
<% end %> <% end %>
<td class="score"> <td class="score">
<%= link_to match, :class => "bold #{match.score_color}" do %> <%= link_to match, :class => "bold #{match.score_color}" do %>
<% if friendly == match.contester1.team %> <% if match.friendly == match.contester1.team %>
<%=h match.score1 %> - <%=h match.score2 %> <%=h match.score1 %> - <%=h match.score2 %>
<% else %> <% else %>
<%=h match.score2 %> - <%=h match.score1 %> <%=h match.score2 %> - <%=h match.score1 %>
<% end %> <% end %>
<% end %> <% end %>
</td> </td>
<% if match.contest.contest_type == Contest::TYPE_LADDER %> <% if match.contest.contest_type == Contest::TYPE_LADDER and !(max_columns < 4 if (defined? max_columns)) %>
<td> <td>
<% if match.get_friendly(:points) > 0 %> <% if match.get_friendly(:points) > 0 %>
<%= icon 'chevron-up' %> <%= icon 'chevron-up' %>

View file

@ -13,6 +13,7 @@ Ensl::Application.configure do
# Compress JavaScripts and CSS # Compress JavaScripts and CSS
config.assets.compress = true config.assets.compress = true
config.assets.js_compressor = :uglifier
# Don't fallback to assets pipeline if a precompiled asset is missed # Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true config.assets.compile = true