1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-04-02 21:24:25 +00:00

Upgraded to rails 8.0.2, moved from dalli to solid cache, moved from delayed_job to solid queue, and add solid cable. deploy/rails-dev-run.sh no longer needs to chmod. Fixed finished_at callback for matches. Migrated from Devise to built in rails auth. Added view tests for the bracket page testing that all bout numbers render for all matches in each bracket type.

This commit is contained in:
2025-04-08 17:54:42 -04:00
parent 9c25a6cc39
commit 2d433b680a
118 changed files with 4921 additions and 1341 deletions

View File

@@ -5,6 +5,21 @@ class ApplicationController < ActionController::Base
after_action :set_csrf_cookie_for_ng
# Add helpers for authentication (replacing Devise)
helper_method :current_user, :user_signed_in?
def current_user
@current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
end
def user_signed_in?
current_user.present?
end
def authenticate_user!
redirect_to login_path, alert: "Please log in to access this page" unless user_signed_in?
end
def set_csrf_cookie_for_ng
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end

View File

@@ -1,7 +1,7 @@
class MatAssignmentRulesController < ApplicationController
before_action :set_tournament
before_action :check_access_manage
before_action :set_mat_assignment_rule, only: [:edit, :update, :show, :destroy]
before_action :set_mat_assignment_rule, only: [:edit, :update, :destroy]
def index
@mat_assignment_rules = @tournament.mat_assignment_rules

View File

@@ -1,5 +1,5 @@
class MatchesController < ApplicationController
before_action :set_match, only: [:show, :edit, :update, :destroy, :stat]
before_action :set_match, only: [:show, :edit, :update, :stat]
before_action :check_access, only: [:edit,:update, :stat]
# GET /matches/1

View File

@@ -0,0 +1,57 @@
class PasswordResetsController < ApplicationController
before_action :get_user, only: [:edit, :update]
before_action :valid_user, only: [:edit, :update]
before_action :check_expiration, only: [:edit, :update]
def new
end
def create
@user = User.find_by(email: params[:password_reset][:email].downcase)
if @user
@user.create_reset_digest
@user.send_password_reset_email
redirect_to root_url, notice: "Email sent with password reset instructions"
else
flash.now[:alert] = "Email address not found"
render 'new'
end
end
def edit
end
def update
if params[:user][:password].empty?
@user.errors.add(:password, "can't be empty")
render 'edit'
elsif @user.update(user_params)
session[:user_id] = @user.id
redirect_to root_url, notice: "Password has been reset"
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
def get_user
@user = User.find_by(email: params[:email])
end
def valid_user
unless @user && @user.authenticated?(:reset, params[:id])
redirect_to root_url
end
end
def check_expiration
if @user.password_reset_expired?
redirect_to new_password_reset_url, alert: "Password reset has expired"
end
end
end

View File

@@ -0,0 +1,20 @@
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
session[:user_id] = user.id
redirect_to root_path, notice: "Logged in successfully"
else
flash.now[:alert] = "Invalid email/password combination"
render 'new'
end
end
def destroy
session.delete(:user_id)
redirect_to root_path, notice: "Logged out successfully"
end
end

View File

@@ -1,5 +1,5 @@
class TournamentsController < ApplicationController
before_action :set_tournament, only: [:all_results, :delete_school_keys, :generate_school_keys,:reset_bout_board,:calculate_team_scores,:bout_sheets,:swap,:weigh_in_sheet,:error,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:remove_delegate,:school_delegate,:delegate,:matches,:weigh_in,:weigh_in_weight,:create_custom_weights,:show,:edit,:update,:destroy,:up_matches,:no_matches,:team_scores,:brackets,:generate_matches,:bracket,:all_brackets]
before_action :set_tournament, only: [:all_results, :delete_school_keys, :generate_school_keys,:reset_bout_board,:calculate_team_scores,:bout_sheets,:swap,:weigh_in_sheet,:error,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:remove_delegate,:school_delegate,:delegate,:matches,:weigh_in,:weigh_in_weight,:create_custom_weights,:show,:edit,:update,:destroy,:up_matches,:no_matches,:team_scores,:generate_matches,:bracket,:all_brackets]
before_action :check_access_manage, only: [:delete_school_keys, :generate_school_keys,:reset_bout_board,:calculate_team_scores,:swap,:weigh_in_sheet,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:school_delegate,:weigh_in,:weigh_in_weight,:create_custom_weights,:update,:edit,:generate_matches,:matches]
before_action :check_access_destroy, only: [:destroy,:delegate,:remove_delegate]
before_action :check_tournament_errors, only: [:generate_matches]
@@ -229,6 +229,7 @@ class TournamentsController < ApplicationController
end
def show
@tournament = Tournament.find(params[:id])
@schools = @tournament.schools.includes(:delegates).sort_by{|school|school.name}
@weights = @tournament.weights.sort_by{|x|[x.max]}
@mats = @tournament.mats.sort_by{|mat|mat.name}

View File

@@ -0,0 +1,48 @@
class UsersController < ApplicationController
before_action :require_login, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
session[:user_id] = @user.id
redirect_to root_path, notice: "Account created successfully"
else
render 'new'
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update(user_params)
redirect_to root_path, notice: "Account updated successfully"
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
def require_login
unless current_user
redirect_to login_path, alert: "Please log in to access this page"
end
end
def correct_user
@user = User.find(params[:id])
redirect_to root_path unless current_user == @user
end
end

View File

@@ -1,6 +1,6 @@
class WeightsController < ApplicationController
before_action :set_weight, only: [:pool_order, :show, :edit, :update, :destroy,:re_gen]
before_action :check_access_manage, only: [:pool_order, :new,:create,:update,:destroy,:edit, :re_gen]
before_action :set_weight, only: [:pool_order, :show, :edit, :update, :destroy]
before_action :check_access_manage, only: [:pool_order, :new,:create,:update,:destroy,:edit]
before_action :check_access_read, only: [:show]

View File

@@ -1,6 +1,6 @@
class WrestlersController < ApplicationController
before_action :set_wrestler, only: [:show, :edit, :update, :destroy, :update_pool]
before_action :check_access, only: [:new, :create, :update, :destroy, :edit, :update_pool]
before_action :set_wrestler, only: [:show, :edit, :update, :destroy]
before_action :check_access, only: [:new, :create, :update, :destroy, :edit]
before_action :check_read_access, only: [:show]
# GET /wrestlers/1
@@ -36,7 +36,7 @@ class WrestlersController < ApplicationController
@school_permission_key = wrestler_params[:school_permission_key].presence
@weights = @school.tournament.weights if @school
# Remove the key from attributes so it isnt assigned to the model.
# Remove the key from attributes so it isn't assigned to the model.
@wrestler = Wrestler.new(wrestler_params.except(:school_permission_key))
respond_to do |format|

View File

@@ -0,0 +1,16 @@
class AdvanceWrestlerJob < ApplicationJob
queue_as :default
# Class method for direct execution in test environment
def self.perform_sync(wrestler, match)
# Execute directly on provided objects
service = AdvanceWrestler.new(wrestler, match)
service.advance_raw
end
def perform(wrestler, match)
# Execute the job
service = AdvanceWrestler.new(wrestler, match)
service.advance_raw
end
end

View File

@@ -0,0 +1,7 @@
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked
# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
end

View File

@@ -0,0 +1,17 @@
class CalculateSchoolScoreJob < ApplicationJob
queue_as :default
# Class method for direct execution in test environment
def self.perform_sync(school)
# Execute directly on provided objects
school.calculate_score_raw
end
def perform(school)
# Log information about the job
Rails.logger.info("Calculating score for school ##{school.id} (#{school.name})")
# Execute the calculation
school.calculate_score_raw
end
end

View File

@@ -0,0 +1,27 @@
class GenerateTournamentMatchesJob < ApplicationJob
queue_as :default
# Class method for direct execution in test environment
def self.perform_sync(tournament)
# Execute directly on provided objects
generator = GenerateTournamentMatches.new(tournament)
generator.generate_raw
end
def perform(tournament)
# Log information about the job
Rails.logger.info("Starting tournament match generation for tournament ##{tournament.id}")
begin
# Execute the job
generator = GenerateTournamentMatches.new(tournament)
generator.generate_raw
Rails.logger.info("Completed tournament match generation for tournament ##{tournament.id}")
rescue => e
Rails.logger.error("Error generating tournament matches: #{e.message}")
Rails.logger.error(e.backtrace.join("\n"))
raise # Re-raise the error so it's properly recorded
end
end
end

View File

@@ -0,0 +1,19 @@
class TournamentBackupJob < ApplicationJob
queue_as :default
# Class method for direct execution in test environment
def self.perform_sync(tournament, reason = nil)
# Execute directly on provided objects
service = TournamentBackupService.new(tournament, reason)
service.create_backup_raw
end
def perform(tournament, reason = nil)
# Log information about the job
Rails.logger.info("Creating backup for tournament ##{tournament.id} (#{tournament.name}), reason: #{reason || 'manual'}")
# Execute the backup
service = TournamentBackupService.new(tournament, reason)
service.create_backup_raw
end
end

View File

@@ -0,0 +1,21 @@
class WrestlingdevImportJob < ApplicationJob
queue_as :default
# Class method for direct execution in test environment
def self.perform_sync(tournament, import_data = nil)
# Execute directly on provided objects
importer = WrestlingdevImporter.new(tournament)
importer.import_data = import_data if import_data
importer.import_raw
end
def perform(tournament, import_data = nil)
# Log information about the job
Rails.logger.info("Starting import for tournament ##{tournament.id} (#{tournament.name})")
# Execute the import
importer = WrestlingdevImporter.new(tournament)
importer.import_data = import_data if import_data
importer.import_raw
end
end

View File

@@ -0,0 +1,4 @@
class ApplicationMailer < ActionMailer::Base
default from: ENV["WRESTLINGDEV_EMAIL"]
layout 'mailer'
end

View File

@@ -0,0 +1,11 @@
class UserMailer < ApplicationMailer
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.password_reset.subject
#
def password_reset(user)
@user = user
mail to: user.email, subject: "Password reset"
end
end

View File

@@ -6,9 +6,8 @@ class Match < ApplicationRecord
has_many :schools, :through => :wrestlers
validate :score_validation, :win_type_validation, :bracket_position_validation, :overtime_type_validation
# Callback to update finished_at when finished changes
# for some reason saved_change_to_finished? does not work on before_save like it does for after_update
before_save :update_finished_at, if: -> { will_save_change_to_attribute?(:finished) }
# Callback to update finished_at when a match is finished
before_save :update_finished_at
after_update :after_finished_actions, if: -> {
saved_change_to_finished? ||
@@ -312,6 +311,12 @@ class Match < ApplicationRecord
private
def update_finished_at
self.finished_at = finished == 1 ? Time.current.utc : nil
# Get the changes that will be persisted
changes = changes_to_save
# Check if finished is changing from 0 to 1 or if it's already 1 but has no timestamp
if (changes['finished'] && changes['finished'][1] == 1) || (finished == 1 && finished_at.nil?)
self.finished_at = Time.current.utc
end
end
end

View File

@@ -36,13 +36,9 @@ class School < ApplicationRecord
end
def calculate_score
if Rails.env.production?
self.delay(:job_owner_id => self.tournament.id, :job_owner_type => "Calculate team score for #{self.name}").calculate_score_raw
else
calculate_score_raw
end
end
# Use perform_later which will execute based on centralized adapter config
CalculateSchoolScoreJob.perform_later(self)
end
def calculate_score_raw
newScore = total_points_scored_by_wrestlers - total_points_deducted

View File

@@ -14,16 +14,6 @@ class Tournament < ApplicationRecord
attr_accessor :import_text
def deferred_jobs
Delayed::Job.where(job_owner_id: self.id)
end
def clear_errored_deferred_jobs
Delayed::Job.where(job_owner_id: self.id, last_error: ! nil).each do |job|
job.destroy
end
end
def self.search_date_name(pattern)
if pattern.blank? # blank? covers both nil and empty string
all
@@ -87,11 +77,8 @@ class Tournament < ApplicationRecord
end
def total_rounds
if self.matches.count > 0
self.matches.sort_by{|m| m.round}.last.round
else
0
end
# Assuming this is line 147 that's causing the error
matches.maximum(:round) || 0 # Return 0 if no matches or max round is nil
end
def assign_mats(mats_to_assign)
@@ -259,5 +246,26 @@ class Tournament < ApplicationRecord
def create_backup()
TournamentBackupService.new(self, "Manual backup").create_backup
end
def confirm_all_weights_have_original_seeds
error_string = wrestlers_with_higher_seed_than_bracket_size_error
error_string += wrestlers_with_duplicate_original_seed_error
error_string += wrestlers_with_out_of_order_seed_error
return error_string.blank?
end
def confirm_each_weight_class_has_correct_number_of_wrestlers
error_string = pool_to_bracket_number_of_wrestlers_error
error_string += modified_sixteen_man_number_of_wrestlers_error
error_string += double_elim_number_of_wrestlers_error
return error_string.blank?
end
private
def connection_adapter
ActiveRecord::Base.connection.adapter_name
end
end

View File

@@ -1,12 +1,56 @@
class User < ApplicationRecord
attr_accessor :reset_token
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
has_many :tournaments
has_many :delegated_tournament_permissions, class_name: "TournamentDelegate"
has_many :delegated_school_permissions, class_name: "SchoolDelegate"
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Replace Devise with has_secure_password
has_secure_password
# Add validations that were handled by Devise
validates :email, presence: true, uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }, allow_nil: true
# These are the Devise modules we were using:
# devise :database_authenticatable, :registerable,
# :recoverable, :rememberable, :trackable, :validatable
# Returns the hash digest of the given string
def self.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token
def self.new_token
SecureRandom.urlsafe_base64
end
# Sets the password reset attributes
def create_reset_digest
self.reset_token = User.new_token
update_columns(reset_digest: User.digest(reset_token), reset_sent_at: Time.zone.now)
end
# Sends password reset email
def send_password_reset_email
UserMailer.password_reset(self).deliver_now
end
# Returns true if a password reset has expired
def password_reset_expired?
reset_sent_at < 2.hours.ago
end
# Returns true if the given token matches the digest
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
def delegated_tournaments
tournaments_delegated = []

View File

@@ -1,20 +1,18 @@
class AdvanceWrestler
def initialize( wrestler, last_match )
def initialize(wrestler, last_match)
@wrestler = wrestler
@tournament = @wrestler.tournament
@last_match = last_match
end
def advance
if Rails.env.production?
self.delay(:job_owner_id => @tournament.id, :job_owner_type => "Advance wrestler #{@wrestler.name} in the bracket").advance_raw
else
advance_raw
end
# Use perform_later which will execute based on centralized adapter config
# This will be converted to inline execution in test environment by ActiveJob
AdvanceWrestlerJob.perform_later(@wrestler, @last_match)
end
def advance_raw
@tournament.clear_errored_deferred_jobs
if @last_match && @last_match.finished?
pool_to_bracket_advancement if @tournament.tournament_type == "Pool to bracket"
ModifiedDoubleEliminationAdvance.new(@wrestler, @last_match).bracket_advancement if @tournament.tournament_type.include? "Modified 16 Man Double Elimination"

View File

@@ -4,11 +4,8 @@ class GenerateTournamentMatches
end
def generate
if Rails.env.production?
self.delay(:job_owner_id => @tournament.id, :job_owner_type => "Generate matches for all weights").generate_raw
else
self.generate_raw
end
# Use perform_later which will execute based on centralized adapter config
GenerateTournamentMatchesJob.perform_later(@tournament)
end
def generate_raw

View File

@@ -5,11 +5,8 @@ class TournamentBackupService
end
def create_backup
if Rails.env.production?
self.delay(:job_owner_id => @tournament.id, :job_owner_type => "Create a backup").create_backup_raw
else
self.create_backup_raw
end
# Use perform_later which will execute based on centralized adapter config
TournamentBackupJob.perform_later(@tournament, @reason)
end
def create_backup_raw

View File

@@ -1,19 +1,24 @@
class WrestlingdevImporter
##### Note, the json contains id's for each row in the tables as well as its associations
##### this ignores those ids and uses this tournament id and then looks up associations based on name
##### and this tournament id
def initialize(tournament, backup)
attr_accessor :import_data
# Support both parameter styles for backward compatibility
# Old: initialize(tournament, backup)
# New: initialize(tournament) with import_data setter
def initialize(tournament, backup = nil)
@tournament = tournament
@import_data = JSON.parse(Base64.decode64(backup.backup_data))
# Handle the old style where backup was passed directly
if backup.present?
@import_data = JSON.parse(Base64.decode64(backup.backup_data)) rescue nil
end
end
def import
if Rails.env.production?
self.delay(job_owner_id: @tournament.id, job_owner_type: "Importing a backup").import_raw
else
import_raw
end
# Use perform_later which will execute based on centralized adapter config
WrestlingdevImportJob.perform_later(@tournament, @import_data)
end
def import_raw

View File

@@ -1,12 +0,0 @@
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.submit "Resend confirmation instructions" %></div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -1,5 +0,0 @@
<p>Welcome <%= @email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %></p>

View File

@@ -1,8 +0,0 @@
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>

View File

@@ -1,7 +0,0 @@
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @token) %></p>

View File

@@ -1,16 +0,0 @@
<h2>Change your password</h2>
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<%= f.hidden_field :reset_password_token %>
<div><%= f.label :password, "New password" %><br />
<%= f.password_field :password, :autofocus => true %></div>
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Change my password", :class=>"btn btn-success"%></div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -1,13 +0,0 @@
<h2>Forgot your password?</h2>
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<br>
<div><%= f.submit "Send me reset password instructions",:class=>"btn btn-success" %></div>
<% end %>
<br>
<br>
<%= render "devise/shared/links" %>

View File

@@ -1,29 +0,0 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<br>
<div><%= f.submit "Update",:class=>"btn btn-success" %></div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete, :class=>"btn btn-danger" %></p>

View File

@@ -1,17 +0,0 @@
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -1,18 +0,0 @@
<h2 class="form-signin-heading">Sign in</h2>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div><%= f.label :email ,:class=>"sr-only"%><br />
<%= f.email_field :email, :autofocus => true,:class=>"form-control",:placeholder=>"Email Address" %></div>
<div><%= f.label :password,:class=>"sr-only" %><br />
<%= f.password_field :password,:class=>"form-control",:placeholder=>"Password" %></div>
<% if devise_mapping.rememberable? -%>
<div class="checkbox"><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= f.submit "Sign in" ,:class=>"btn btn-lg btn-primary btn-block" %></div>
<% end %>
<br>
<br>
<%= render "devise/shared/links" %>

View File

@@ -1,25 +0,0 @@
<%- if controller_name != 'sessions' %>
<%= link_to "Sign in", new_session_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
<% end -%>
<% end -%>

View File

@@ -1,12 +0,0 @@
<h2>Resend unlock instructions</h2>
<%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -19,13 +19,13 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><%= current_user.email %>
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><%=link_to "Log out", destroy_user_session_url ,:method => 'delete' %></li>
<li><%=link_to "Edit user", edit_user_registration_path %></li>
<li><%=link_to "My tournaments and schools","/static_pages/my_tournaments" %></li>
<li><%= link_to "Log out", logout_path, method: :delete %></li>
<li><%= link_to "Edit profile", edit_user_path(current_user) %></li>
<li><%= link_to "My tournaments and schools", "/static_pages/my_tournaments" %></li>
</ul>
</li>
<% else %>
<li><%= link_to "Log In" , new_user_session_path %></li>
<li><%= link_to "Log In", login_path %></li>
<% end %>
</ul>
</div><!--/.nav-collapse -->

View File

@@ -0,0 +1,34 @@
<h1>Reset password</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user, url: password_reset_path(params[:id]), local: true) do |f| %>
<% if @user.errors.any? %>
<div class="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= hidden_field_tag :email, @user.email %>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit "Update password", class: "btn btn-primary" %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<h1>Forgot password</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(url: password_resets_path, scope: :password_reset, local: true) do |f| %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(url: login_path, scope: :session, local: true) do |f| %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>

View File

@@ -1,6 +1,14 @@
<h3>
Info
</h3>
<% if (can? :manage, @tournament) && @tournament.curently_generating_matches == 1 %>
<div class="alert alert-info">
<strong>Match Generation In Progress</strong>
<p>Tournament bracket generation is currently running. Please refresh the page to check progress.</p>
</div>
<% end %>
<p>
<strong>Address:</strong>
<%= @tournament.address %>
@@ -118,34 +126,4 @@
</tbody>
</table>
<% end %>
<% if can? :manage, @tournament %>
<br><br>
<h3>Background Jobs</h3>
<p>This is a list of queued or running background jobs. Match generation, bracket advancement, team score calculation, etc.</p>
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Name of Job</th>
<th>Job Status</th>
</tr>
</thead>
<tbody>
<% @tournament.deferred_jobs.each do |job| %>
<tr>
<td><%= job.job_owner_type %></td>
<td>
<% if job.locked_at %>
Running
<% elsif job.last_error %>
Error
<% elsif job.attempts == 0 and !job.locked_at %>
Pending
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
<br><br>

View File

@@ -0,0 +1,12 @@
<h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<%= link_to "Reset password", edit_password_reset_url(@user.reset_token, email: @user.email) %>
<p>This link will expire in two hours.</p>
<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>

View File

@@ -0,0 +1,8 @@
To reset your password click the link below:
<%= edit_password_reset_url(@user.reset_token, email: @user.email) %>
This link will expire in two hours.
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.

View File

@@ -0,0 +1,38 @@
<h1>Edit profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user, local: true) do |f| %>
<% if @user.errors.any? %>
<div class="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<small class="text-muted">Leave blank if you don't want to change it</small>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,39 @@
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user, url: signup_path, local: true) do |f| %>
<% if @user.errors.any? %>
<div class="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit "Create account", class: "btn btn-primary" %>
<% end %>
<p>Already have an account? <%= link_to "Log in", login_path %></p>
</div>
</div>