mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-03-25 01:14:43 +00:00
Frontend authentication working.
This commit is contained in:
@@ -3,8 +3,21 @@ class ApplicationController < ActionController::Base
|
||||
# For APIs, you may want to use :null_session instead.
|
||||
protect_from_forgery with: :exception
|
||||
|
||||
after_filter :set_csrf_cookie_for_ng
|
||||
|
||||
def set_csrf_cookie_for_ng
|
||||
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
|
||||
end
|
||||
|
||||
rescue_from CanCan::AccessDenied do |exception|
|
||||
# flash[:error] = "Access denied!"
|
||||
redirect_to '/static_pages/not_allowed'
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# In Rails 4.2 and above
|
||||
def verified_request?
|
||||
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
json.cache! ["api_tournament", @tournament] do
|
||||
json.content(@tournament)
|
||||
json.(@tournament, :id, :name, :address, :director, :director_email, :tournament_type, :created_at, :updated_at)
|
||||
json.(@tournament, :id, :name, :address, :director, :director_email, :tournament_type, :created_at, :updated_at, :user_id)
|
||||
|
||||
json.schools @tournament.schools do |school|
|
||||
json.name school.name
|
||||
@@ -28,8 +28,6 @@ json.cache! ["api_tournament", @tournament] do
|
||||
json.mats @tournament.mats do |mat|
|
||||
json.name mat.name
|
||||
json.unfinishedMatches mat.unfinishedMatches do |match|
|
||||
json.w1 = match.w1
|
||||
json.w2 = match.w2
|
||||
json.bout_number match.bout_number
|
||||
json.w1_name match.w1_name
|
||||
json.w2_name match.w2_name
|
||||
@@ -42,8 +40,6 @@ json.cache! ["api_tournament", @tournament] do
|
||||
json.w2_name match.w2_name
|
||||
json.weightClass match.weight.max
|
||||
json.round match.round
|
||||
json.w1 = match.w1
|
||||
json.w2 = match.w2
|
||||
end
|
||||
|
||||
json.matches @tournament.matches do |match|
|
||||
@@ -52,7 +48,7 @@ json.cache! ["api_tournament", @tournament] do
|
||||
json.w2_name match.w2_name
|
||||
json.weightClass match.weight.max
|
||||
json.round match.round
|
||||
json.w1 = match.w1
|
||||
json.w2 = match.w2
|
||||
json.w1 match.w1
|
||||
json.w2 match.w2
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<script src="https://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.map"></script>
|
||||
|
||||
|
||||
<!--Mobile and tablet detection-->
|
||||
<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>
|
||||
|
||||
@@ -30,6 +30,10 @@ module Wrestling
|
||||
config.active_job.queue_adapter = :delayed_job
|
||||
|
||||
config.rails_lineman.lineman_project_location = "frontend"
|
||||
|
||||
config.to_prepare do
|
||||
DeviseController.respond_to :html, :json
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var app = angular.module("wrestlingdev", ["ngRoute"]).run(function($rootScope) {
|
||||
var app = angular.module("wrestlingdev", ["ngRoute","Devise"]).run(function($rootScope) {
|
||||
// adds some basic utilities to the $rootScope for debugging purposes
|
||||
$rootScope.log = function(thing) {
|
||||
console.log(thing);
|
||||
|
||||
51
frontend/app/js/controllers/login-controller.js
Normal file
51
frontend/app/js/controllers/login-controller.js
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
app.controller("loginController", function($scope, $routeParams, Auth, $rootScope) {
|
||||
$scope.credentials = {
|
||||
email: '',
|
||||
password: ''
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-HTTP-Method-Override': 'POST'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.login = function(){
|
||||
Auth.login($scope.credentials, config).then(function(user) {
|
||||
console.log(user); // => {id: 1, ect: '...'}
|
||||
$rootScope.user = user;
|
||||
$rootScope.alertClass = "alert alert-success";
|
||||
$rootScope.alertMessage = "Logged in successfully";
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
$rootScope.alertClass = "alert alert-danger";
|
||||
$rootScope.alertMessage = "Username and/or password is incorrect";
|
||||
});
|
||||
};
|
||||
|
||||
$scope.logout = function(){
|
||||
Auth.logout(config).then(function(oldUser) {
|
||||
// alert(oldUser.name + "you're signed out now.");
|
||||
$rootScope.user = null;
|
||||
$rootScope.alertClass = "alert alert-success";
|
||||
$rootScope.alertMessage = "Logged out successfully";
|
||||
}, function(error) {
|
||||
// An error occurred logging out.
|
||||
$rootScope.alertClass = "alert alert-danger";
|
||||
$rootScope.alertMessage = "There was an error logging out";
|
||||
});
|
||||
};
|
||||
|
||||
Auth.currentUser().then(function(user) {
|
||||
// User was logged in, or Devise returned
|
||||
// previously authenticated session.
|
||||
$rootScope.user = user;
|
||||
}, function(error) {
|
||||
// unauthenticated error
|
||||
$rootScope.user = null;
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
'use strict';
|
||||
app.controller("tournamentController", function($scope, tournamentsService, $routeParams, Wrestler) {
|
||||
app.controller("tournamentController", function($scope, tournamentsService, $routeParams, Wrestler, Auth, $rootScope) {
|
||||
$scope.message = "Test message in scope.";
|
||||
|
||||
|
||||
// $scope.tournamentData = "test";
|
||||
tournamentsService.tournamentDetails($routeParams.id).then(function(data) {
|
||||
//this will execute when the
|
||||
@@ -9,7 +10,43 @@ app.controller("tournamentController", function($scope, tournamentsService, $rou
|
||||
$scope.tournament = data;
|
||||
});
|
||||
|
||||
// refresh tournament data every 10 seconds
|
||||
// setInterval(function(){
|
||||
// tournamentsService.tournamentDetails($routeParams.id).then(function(data) {
|
||||
// //this will execute when the
|
||||
// //AJAX call completes.
|
||||
// $scope.tournament = data;
|
||||
// });
|
||||
// }, 10000);
|
||||
|
||||
$scope.wrestler = Wrestler;
|
||||
|
||||
$scope.showSchools = false;
|
||||
|
||||
$scope.toggleSchools = function(){
|
||||
$scope.showSchools = !$scope.showSchools;
|
||||
};
|
||||
|
||||
$scope.showWeightSeeds = false;
|
||||
|
||||
$scope.toggleWeightSeeds = function(){
|
||||
$scope.showWeightSeeds = !$scope.showWeightSeeds;
|
||||
};
|
||||
|
||||
$scope.showBoutBoard = false;
|
||||
|
||||
$scope.toggleBoutBoard = function(){
|
||||
$scope.showBoutBoard = !$scope.showBoutBoard;
|
||||
};
|
||||
|
||||
|
||||
$scope.isTournamentOwner = function(tournamentId,userId){
|
||||
if(userId == tournamentId){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
@@ -4,16 +4,15 @@ app.factory('Wrestler', function Wrestler(){
|
||||
var vm = this;
|
||||
|
||||
|
||||
vm.matches = function(matches,wrestler){
|
||||
var givenWrestler = wrestler;
|
||||
vm.matches = function(wrestler,matches){
|
||||
|
||||
console.log(givenWrestler.id);
|
||||
console.log(matches);
|
||||
return _.filter(matches, function(match){
|
||||
return match.w1 == givenWrestler.id || match.w2 == givenWrestler.id;
|
||||
return match.w1 == wrestler.id || match.w2 == wrestler.id;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
return vm;
|
||||
});
|
||||
@@ -40,5 +40,5 @@ app.config(['$routeProvider', '$locationProvider', function($routeProvider,$loca
|
||||
$routeProvider.otherwise({redirectTo: '/'});
|
||||
|
||||
//this give me normal routes instead of /#/
|
||||
$locationProvider.html5Mode(true);
|
||||
// $locationProvider.html5Mode(true);
|
||||
}]);
|
||||
@@ -1,49 +0,0 @@
|
||||
app.factory('AuthenticationService',
|
||||
['Base64', '$http', '$cookieStore', '$rootScope', '$timeout',
|
||||
function (Base64, $http, $cookieStore, $rootScope, $timeout) {
|
||||
var service = {};
|
||||
|
||||
service.Login = function (username, password, callback) {
|
||||
|
||||
/* Dummy authentication for testing, uses $timeout to simulate api call
|
||||
----------------------------------------------*/
|
||||
// $timeout(function(){
|
||||
// var response = { success: username === 'test' && password === 'test' };
|
||||
// if(!response.success) {
|
||||
// response.message = 'Username or password is incorrect';
|
||||
// }
|
||||
// callback(response);
|
||||
// }, 1000);
|
||||
|
||||
|
||||
/* Use this for real authentication
|
||||
----------------------------------------------*/
|
||||
$http.post('/api/authenticate', { username: username, password: password })
|
||||
.success(function (response) {
|
||||
callback(response);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
service.SetCredentials = function (username, password) {
|
||||
var authdata = Base64.encode(username + ':' + password);
|
||||
|
||||
$rootScope.globals = {
|
||||
currentUser: {
|
||||
username: username,
|
||||
authdata: authdata
|
||||
}
|
||||
};
|
||||
|
||||
$http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; // jshint ignore:line
|
||||
$cookieStore.put('globals', $rootScope.globals);
|
||||
};
|
||||
|
||||
service.ClearCredentials = function () {
|
||||
$rootScope.globals = {};
|
||||
$cookieStore.remove('globals');
|
||||
$http.defaults.headers.common.Authorization = 'Basic ';
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
||||
@@ -37,8 +37,8 @@ function tournamentsService($http){
|
||||
}
|
||||
|
||||
function errorCallback(err){
|
||||
console.log("error log below");
|
||||
console.log(err);
|
||||
// console.log("error log below");
|
||||
// console.log(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="wrestlingdev">
|
||||
<head>
|
||||
<base href="/">
|
||||
<base href="/#/">
|
||||
<title>WrestlingDev</title>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
@@ -21,13 +21,30 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">WrestlingDev</a>
|
||||
<a class="navbar-brand" href="/#/">WrestlingDev</a>
|
||||
</div>
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav navbar-right navbar-custom-link">
|
||||
<li><a href="/tournaments">Browse Tournaments</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/tutorials">Tutorials</a></li>
|
||||
<li><a href="/#/tournaments">Browse Tournaments</a></li>
|
||||
<li><a href="/#/about">About</a></li>
|
||||
<li><a href="/#/tutorials">Tutorials</a></li>
|
||||
<li class="dropdown" id="menuLogin" ng-controller="loginController">
|
||||
<a ng-if="user == null" class="dropdown-toggle" data-toggle="dropdown" id="navLogin">Login</a>
|
||||
<div ng-if="user == null" class="dropdown-menu" style="padding:17px;">
|
||||
<form class="form" id="formLogin">
|
||||
<input name="username" id="username" type="text" placeholder="Email" ng-model="credentials.email">
|
||||
<input name="password" id="password" type="password" placeholder="Password" ng-model="credentials.password"><br>
|
||||
<button type="button" id="btnLogin" class="btn" ng-click="login()">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<a ng-if="user != null" class="dropdown-toggle" data-toggle="dropdown" id="navLogout">{{user.email}}</a>
|
||||
<div ng-if="user != null" class="dropdown-menu" style="padding:17px;">
|
||||
<ul style="list-style-type: none;">
|
||||
<li ng-click="logout()">Logout</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
@@ -35,6 +52,10 @@
|
||||
|
||||
<div id="page-content">
|
||||
<div class="row no-margin">
|
||||
<div ng-if="alertMessage != null" ng-class="alertClass">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
{{alertMessage}}
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<!--left sidebar-->
|
||||
</div>
|
||||
@@ -66,7 +87,7 @@
|
||||
<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
|
||||
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
<br>
|
||||
<p>If you would like to run a tournament, please click log in and then click sign up.</p>
|
||||
<br>
|
||||
<a href='/tournaments' class="btn btn-large btn-primary">Browse Tournaments</a>
|
||||
<a href='/#/tournaments' class="btn btn-large btn-primary">Browse Tournaments</a>
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="tournament in allTournaments">
|
||||
<td><a ng-href="/tournaments/{{tournament.id}}">{{ tournament.name }}</a></td>
|
||||
<td><a ng-href="/#/tournaments/{{tournament.id}}">{{ tournament.name }}</a></td>
|
||||
<td>{{ tournament.date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
<a href="/tournaments" class="btn btn-default">Back to browse tournaments</a>
|
||||
<a href="/#/tournaments" class="btn btn-default">Back to browse tournaments</a>
|
||||
<h1>
|
||||
{{ tournament.name }}
|
||||
</h1>
|
||||
<h1>{{ wrestler.matches(tournament.matches,tournament.weights[0].wrestlers[0]) }}</h1>
|
||||
<p>
|
||||
<strong>Address:</strong>
|
||||
{{ tournament.address }}
|
||||
@@ -22,16 +21,19 @@
|
||||
</p>
|
||||
<br>
|
||||
<div class="panel panel-default">
|
||||
<a class="panel-heading" data-toggle="collapse" href="#Schools" aria-expanded="false" style="display: block;">
|
||||
<h3 class="panel-title">School Lineups and Team Scores<span class="pull-left clickable"><i class="glyphicon glyphicon-chevron-down"></i></span></h3>
|
||||
<a class="panel-heading" ng-click="toggleSchools()" style="display: block;">
|
||||
<h3 class="panel-title">School Lineups and Team Scores<span class="pull-left clickable"><i ng-if="showSchools == false" class="glyphicon glyphicon-chevron-down"></i>
|
||||
<i ng-if="showSchools == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
|
||||
</a>
|
||||
<div id="Schools" class="panel-collapse collapse">
|
||||
<div id="Schools" ng-if="showSchools == true">
|
||||
<div class="panel-body">
|
||||
<button ng-if="isTournamentOwner(user.id,tournament.user_id)" class="btn btn-success btn-sm">Create New School</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Score</th>
|
||||
<th ng-if="isTournamentOwner(user.id,tournament.user_id)">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -40,6 +42,7 @@
|
||||
<tr ng-repeat="school in tournament.schools | orderBy : 'score'">
|
||||
<td>{{ school.name }}</td>
|
||||
<td>{{ school.score }}</td>
|
||||
<td ng-if="isTournamentOwner(user.id,tournament.user_id)"><button class="btn btn-sm">Edit</button><button class="btn btn-danger btn-sm">Destroy</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -48,10 +51,11 @@
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<a class="panel-heading" data-toggle="collapse" href="#Weights" aria-expanded="false" style="display: block;">
|
||||
<h3 class="panel-title">Weights and Seeds<span class="pull-left clickable"><i class="glyphicon glyphicon-chevron-down"></i></span></h3>
|
||||
<a class="panel-heading" ng-click="toggleWeightSeeds()" style="display: block;">
|
||||
<h3 class="panel-title">Weights and Seeds<span class="pull-left clickable"><i ng-if="showWeightSeeds == false" class="glyphicon glyphicon-chevron-down"></i>
|
||||
<i ng-if="showWeightSeeds == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
|
||||
</a>
|
||||
<div id="Weights" class="panel-collapse collapse">
|
||||
<div id="Weights" ng-if="showWeightSeeds == true">
|
||||
<div class="panel-body">
|
||||
<p>Click weight class for seeds</p>
|
||||
<br>
|
||||
@@ -75,10 +79,11 @@
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<a class="panel-heading" data-toggle="collapse" href="#Mats" aria-expanded="false" style="display: block;" >
|
||||
<h3 class="panel-title">Mats and Bout Board<span class="pull-left clickable"><i class="glyphicon glyphicon-chevron-down"></i></span></h3>
|
||||
<a class="panel-heading" ng-click="toggleBoutBoard()" style="display: block;" >
|
||||
<h3 class="panel-title">Mats and Bout Board<span class="pull-left clickable"><i ng-if="showBoutBoard == false" class="glyphicon glyphicon-chevron-down"></i>
|
||||
<i ng-if="showBoutBoard == true" class="glyphicon glyphicon-chevron-up"></i></span></h3>
|
||||
</a>
|
||||
<div id="Mats" class="panel-collapse collapse">
|
||||
<div id="Mats" ng-if="showBoutBoard == true">
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
|
||||
@@ -26,8 +26,7 @@ module.exports = function(lineman) {
|
||||
apiProxy: {
|
||||
enabled: true,
|
||||
host: 'localhost',
|
||||
port: 8080,
|
||||
prefix: 'api'
|
||||
port: 8080
|
||||
},
|
||||
web: {
|
||||
port: 8081
|
||||
|
||||
10
frontend/vendor/js/devise-min.js
vendored
Normal file
10
frontend/vendor/js/devise-min.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// AngularDevise
|
||||
// -------------------
|
||||
// v1.2.1
|
||||
//
|
||||
// Copyright (c)2016 Justin Ridgewell
|
||||
// Distributed under MIT license
|
||||
//
|
||||
// https://github.com/cloudspace/angular_devise
|
||||
|
||||
!function(a){"use strict";var b=a.module("Devise",[]);b.provider("AuthIntercept",function(){var a=!1;this.interceptAuth=function(b){return a=!!b||void 0===b,this},this.$get=["$rootScope","$q",function(b,c){return{responseError:function(d){var e=d.config.interceptAuth;if(e=!!e||a&&void 0===e,e&&401===d.status){var f=c.defer();return b.$broadcast("devise:unauthorized",d,f),f.reject(d),f.promise}return c.reject(d)}}}]}).config(["$httpProvider",function(a){a.interceptors.push("AuthIntercept")}]),b.provider("Auth",function(){function b(b,c,d){var h={method:f[b].toLowerCase(),url:e[b]};return c&&(g?(h.data={},h.data[g]=c):h.data=c),a.extend(h,d),h}function c(b,c){a.forEach(b,function(a,d){this[d+c]=function(a){return void 0===a?b[d]:(b[d]=a,this)}},this)}function d(a){return function(){return a}}var e={login:"/users/sign_in.json",logout:"/users/sign_out.json",register:"/users.json",sendResetPasswordInstructions:"/users/password.json",resetPassword:"/users/password.json"},f={login:"POST",logout:"DELETE",register:"POST",sendResetPasswordInstructions:"POST",resetPassword:"PUT"},g="user",h=function(a){return a.data};c.call(this,f,"Method"),c.call(this,e,"Path"),this.resourceName=function(a){return void 0===a?g:(g=a,this)},this.parse=function(a){return"function"!=typeof a?h:(h=a,this)},this.$get=["$q","$http","$rootScope",function(a,c,e){function f(a){return j._currentUser=a,a}function g(){f(null),j._promise=null}function i(a){return function(b){return e.$broadcast("devise:"+a,b),b}}var j={_currentUser:null,parse:h,_promise:null,reset:function(){g(),j.currentUser()},login:function(a,d){var e=arguments.length>0,g=j.isAuthenticated();return a=a||{},c(b("login",a,d)).then(j.parse).then(f).then(function(a){return e&&!g?i("new-session")(a):a}).then(i("login"))},logout:function(a){var e=d(j._currentUser);return c(b("logout",void 0,a)).then(g).then(e).then(i("logout"))},register:function(a,d){return a=a||{},c(b("register",a,d)).then(j.parse).then(f).then(i("new-registration"))},sendResetPasswordInstructions:function(a){return a=a||{},c(b("sendResetPasswordInstructions",a)).then(j.parse).then(i("send-reset-password-instructions-successfully"))},resetPassword:function(a){return a=a||{},c(b("resetPassword",a)).then(j.parse).then(f).then(i("reset-password-successfully"))},currentUser:function(){return j.isAuthenticated()?a.when(j._currentUser):(null===j._promise&&(j._promise=j.login()),j._promise)},isAuthenticated:function(){return!!j._currentUser}};return j}]})}(angular);
|
||||
@@ -37,11 +37,11 @@ class SingleTestTest < ActionDispatch::IntegrationTest
|
||||
# Yml for wrestlers
|
||||
# @tournament.wrestlers.each do |w|
|
||||
# puts "tournament_1_#{w.name}:"
|
||||
# puts " id: #{count}"
|
||||
# puts " name: #{w.name}"
|
||||
# puts " school_id: #{w.school_id}"
|
||||
# puts " weight_id: #{w.weight_id}"
|
||||
# puts " original_seed: #{w.original_seed}"
|
||||
# puts " seed: #{w.seed}"
|
||||
# puts " season_loss: #{w.season_loss}"
|
||||
# puts " season_win: #{w.season_win}"
|
||||
# puts " criteria: #{w.criteria}"
|
||||
|
||||
Reference in New Issue
Block a user