Description:
[web] added site and time out basic functionality git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@169 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r85:f0e9de51d9aa - - 23 files changed: 442 inserted, 9 deleted

@@ -0,0 +1,87
1 + class SitesController < ApplicationController
2 + # GET /sites
3 + # GET /sites.xml
4 + def index
5 + @sites = Site.find(:all)
6 +
7 + respond_to do |format|
8 + format.html # index.html.erb
9 + format.xml { render :xml => @sites }
10 + end
11 + end
12 +
13 + # GET /sites/1
14 + # GET /sites/1.xml
15 + def show
16 + @site = Site.find(params[:id])
17 +
18 + respond_to do |format|
19 + format.html # show.html.erb
20 + format.xml { render :xml => @site }
21 + end
22 + end
23 +
24 + # GET /sites/new
25 + # GET /sites/new.xml
26 + def new
27 + @site = Site.new
28 +
29 + respond_to do |format|
30 + format.html # new.html.erb
31 + format.xml { render :xml => @site }
32 + end
33 + end
34 +
35 + # GET /sites/1/edit
36 + def edit
37 + @site = Site.find(params[:id])
38 + end
39 +
40 + # POST /sites
41 + # POST /sites.xml
42 + def create
43 + @site = Site.new(params[:site])
44 + @site.clear_start_time_if_not_started
45 +
46 + respond_to do |format|
47 + if @site.save
48 + flash[:notice] = 'Site was successfully created.'
49 + format.html { redirect_to(@site) }
50 + format.xml { render :xml => @site, :status => :created, :location => @site }
51 + else
52 + format.html { render :action => "new" }
53 + format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
54 + end
55 + end
56 + end
57 +
58 + # PUT /sites/1
59 + # PUT /sites/1.xml
60 + def update
61 + @site = Site.find(params[:id])
62 + @site.clear_start_time_if_not_started
63 +
64 + respond_to do |format|
65 + if @site.update_attributes(params[:site])
66 + flash[:notice] = 'Site was successfully updated.'
67 + format.html { redirect_to(@site) }
68 + format.xml { head :ok }
69 + else
70 + format.html { render :action => "edit" }
71 + format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
72 + end
73 + end
74 + end
75 +
76 + # DELETE /sites/1
77 + # DELETE /sites/1.xml
78 + def destroy
79 + @site = Site.find(params[:id])
80 + @site.destroy
81 +
82 + respond_to do |format|
83 + format.html { redirect_to(sites_url) }
84 + format.xml { head :ok }
85 + end
86 + end
87 + end
@@ -0,0 +1,2
1 + module SitesHelper
2 + end
@@ -0,0 +1,24
1 + class Site < ActiveRecord::Base
2 +
3 + def clear_start_time_if_not_started
4 + if !self.started
5 + self.start_time = nil
6 + end
7 + end
8 +
9 + def finished?
10 + if !self.started
11 + return false
12 + end
13 +
14 + contest_time = Configuration['contest.time_limit']
15 + if tmatch = /(\d+):(\d+)/.match(contest_time)
16 + h = tmatch[1].to_i
17 + m = tmatch[2].to_i
18 + return Time.now > (self.start_time + h.hour + m.minute)
19 + else
20 + false
21 + end
22 + end
23 +
24 + end
@@ -0,0 +1,17
1 + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 +
4 + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 + <head>
6 + <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7 + <title>Sites: <%= controller.action_name %></title>
8 + <%= stylesheet_link_tag 'scaffold' %>
9 + </head>
10 + <body>
11 +
12 + <p style="color: green"><%= flash[:notice] %></p>
13 +
14 + <%= yield %>
15 +
16 + </body>
17 + </html>
@@ -0,0 +1,27
1 + <h1>Editing site</h1>
2 +
3 + <%= error_messages_for :site %>
4 +
5 + <% form_for(@site) do |f| %>
6 + <p>
7 + <b>Name</b><br />
8 + <%= f.text_field :name %>
9 + </p>
10 +
11 + <p>
12 + <b>Started</b><br />
13 + <%= f.check_box :started %>
14 + </p>
15 +
16 + <p>
17 + <b>Start time</b><br />
18 + <%= f.datetime_select :start_time %>
19 + </p>
20 +
21 + <p>
22 + <%= f.submit "Update" %>
23 + </p>
24 + <% end %>
25 +
26 + <%= link_to 'Show', @site %> |
27 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,24
1 + <h1>Listing sites</h1>
2 +
3 + <table>
4 + <tr>
5 + <th>Name</th>
6 + <th>Started</th>
7 + <th>Start time</th>
8 + </tr>
9 +
10 + <% for site in @sites %>
11 + <tr>
12 + <td><%=h site.name %></td>
13 + <td><%=h site.started %></td>
14 + <td><%=h site.start_time %></td>
15 + <td><%= link_to 'Show', site %></td>
16 + <td><%= link_to 'Edit', edit_site_path(site) %></td>
17 + <td><%= link_to 'Destroy', site, :confirm => 'Are you sure?', :method => :delete %></td>
18 + </tr>
19 + <% end %>
20 + </table>
21 +
22 + <br />
23 +
24 + <%= link_to 'New site', new_site_path %>
@@ -0,0 +1,26
1 + <h1>New site</h1>
2 +
3 + <%= error_messages_for :site %>
4 +
5 + <% form_for(@site) do |f| %>
6 + <p>
7 + <b>Name</b><br />
8 + <%= f.text_field :name %>
9 + </p>
10 +
11 + <p>
12 + <b>Started</b><br />
13 + <%= f.check_box :started %>
14 + </p>
15 +
16 + <p>
17 + <b>Start time</b><br />
18 + <%= f.datetime_select :start_time %>
19 + </p>
20 +
21 + <p>
22 + <%= f.submit "Create" %>
23 + </p>
24 + <% end %>
25 +
26 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,18
1 + <p>
2 + <b>Name:</b>
3 + <%=h @site.name %>
4 + </p>
5 +
6 + <p>
7 + <b>Started:</b>
8 + <%=h @site.started %>
9 + </p>
10 +
11 + <p>
12 + <b>Start time:</b>
13 + <%=h @site.start_time %>
14 + </p>
15 +
16 +
17 + <%= link_to 'Edit', edit_site_path(@site) %> |
18 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,15
1 + class CreateSites < ActiveRecord::Migration
2 + def self.up
3 + create_table :sites do |t|
4 + t.string :name
5 + t.boolean :started
6 + t.datetime :start_time
7 +
8 + t.timestamps
9 + end
10 + end
11 +
12 + def self.down
13 + drop_table :sites
14 + end
15 + end
@@ -0,0 +1,22
1 + class AddSiteToUserAndAddDefaultSite < ActiveRecord::Migration
2 + def self.up
3 + default_site = Site.new({:name => 'default',
4 + :started => false})
5 + default_site.save!
6 +
7 + add_column :users, :site_id, :integer
8 + User.reset_column_information
9 +
10 + User.find(:all).each do |user|
11 + user.site_id = default_site.id
12 + user.save
13 + end
14 + end
15 +
16 + def self.down
17 + remove_column :users, :site_id
18 +
19 + default_site = Site.find_by_name('default')
20 + default_site.destroy
21 + end
22 + end
@@ -0,0 +1,43
1 +
2 + require File.dirname(__FILE__) + '/../spec_helper'
3 +
4 + describe Site do
5 +
6 + before(:each) do
7 + start_time = Time.local(2008,5,10,9,00)
8 + @site = Site.new({:name => 'Test site',
9 + :started => true,
10 + :start_time => start_time })
11 + end
12 +
13 + it "should report that the contest is not finished when the contest time limit is not set" do
14 + Configuration.should_receive(:[]).with('contest.time_limit').
15 + and_return('unlimit')
16 + Time.should_not_receive(:now)
17 + @site.finished?.should == false
18 + end
19 +
20 + it "should report that the contest is finished when the contest is over" do
21 + Configuration.should_receive(:[]).with('contest.time_limit').
22 + and_return('5:00')
23 + Time.should_receive(:now).and_return(Time.local(2008,5,10,14,01))
24 + @site.finished?.should == true
25 + end
26 +
27 + it "should report if the contest is finished correctly, when the contest is over, and the contest time contains some minutes" do
28 + Configuration.should_receive(:[]).twice.with('contest.time_limit').
29 + and_return('5:15')
30 + Time.should_receive(:now).
31 + and_return(Time.local(2008,5,10,14,14),Time.local(2008,5,10,14,16))
32 + @site.finished?.should == false
33 + @site.finished?.should == true
34 + end
35 +
36 + it "should report that the contest is not finished, when the time is exactly at the finish time" do
37 + Configuration.should_receive(:[]).with('contest.time_limit').
38 + and_return('5:00')
39 + Time.should_receive(:now).and_return(Time.local(2008,5,10,14,00))
40 + @site.finished?.should == false
41 + end
42 +
43 + end
@@ -0,0 +1,11
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + one:
4 + name: MyString
5 + started: false
6 + start_time: 2008-04-09 14:08:28
7 +
8 + two:
9 + name: MyString
10 + started: false
11 + start_time: 2008-04-09 14:08:28
@@ -0,0 +1,45
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class SitesControllerTest < ActionController::TestCase
4 + def test_should_get_index
5 + get :index
6 + assert_response :success
7 + assert_not_nil assigns(:sites)
8 + end
9 +
10 + def test_should_get_new
11 + get :new
12 + assert_response :success
13 + end
14 +
15 + def test_should_create_site
16 + assert_difference('Site.count') do
17 + post :create, :site => { }
18 + end
19 +
20 + assert_redirected_to site_path(assigns(:site))
21 + end
22 +
23 + def test_should_show_site
24 + get :show, :id => sites(:one).id
25 + assert_response :success
26 + end
27 +
28 + def test_should_get_edit
29 + get :edit, :id => sites(:one).id
30 + assert_response :success
31 + end
32 +
33 + def test_should_update_site
34 + put :update, :id => sites(:one).id, :site => { }
35 + assert_redirected_to site_path(assigns(:site))
36 + end
37 +
38 + def test_should_destroy_site
39 + assert_difference('Site.count', -1) do
40 + delete :destroy, :id => sites(:one).id
41 + end
42 +
43 + assert_redirected_to sites_path
44 + end
45 + end
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class SiteTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -32,26 +32,38
32 32 redirect_to :controller => 'main', :action => 'login'
33 33 return false
34 34 end
35 35 end
36 36
37 37 return true
38 38 end
39 39
40 40 def authorization
41 41 return false unless authenticate
42 42 user = User.find(session[:user_id])
43 43 unless user.roles.detect { |role|
44 44 role.rights.detect{ |right|
45 45 right.controller == self.class.controller_name and
46 46 (right.action == 'all' or right.action == action_name)
47 47 }
48 48 }
49 49 flash[:notice] = 'You are not authorized to view the page you requested'
50 50 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
51 51 redirect_to :controller => 'main', :action => 'login'
52 52 return false
53 53 end
54 54 end
55 55
56 + def verify_time_limit
57 + return true if session[:user_id]==nil
58 + user = User.find(session[:user_id], :include => :site)
59 + return true if user==nil or user.site == nil
60 + if user.site.finished?
61 + flash[:notice] = 'Error: the contest on your site is over.'
62 + redirect_to :back
63 + return false
64 + end
65 + return true
66 + end
67 +
56 68 end
57 69
@@ -1,54 +1,68
1 1 class MainController < ApplicationController
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4
5 + #
6 + # COMMENT OUT: filter in each action instead
7 + #
8 + # before_filter :verify_time_limit, :only => [:submit]
9 +
5 10 verify :method => :post, :only => [:submit],
6 11 :redirect_to => { :action => :index }
7 12
8 13
9 14 def index
10 15 redirect_to :action => 'login'
11 16 end
12 17
13 18 def login
14 19 saved_notice = flash[:notice]
15 20 reset_session
16 21 flash[:notice] = saved_notice
17 22
18 23 render :action => 'login', :layout => 'empty'
19 24 end
20 25
21 26 def list
22 27 prepare_list_information
23 28 end
24 29
25 30 def submit
31 + user = User.find(session[:user_id])
32 +
26 33 @submission = Submission.new(params[:submission])
27 - @submission.user_id = session[:user_id]
34 + @submission.user = user
28 35 @submission.language_id = 0
29 36 @submission.source = params['file'].read if params['file']!=''
30 37 @submission.submitted_at = Time.new
38 +
39 + if user.site!=nil and user.site.finished?
40 + @submission.errors.add_to_base "The contest is over."
41 + prepare_list_information
42 + render :action => 'list' and return
43 + end
44 +
31 45 if @submission.valid?
32 46 if @submission.save == false
33 47 flash[:notice] = 'Error saving your submission'
34 48 elsif Task.create(:submission_id => @submission.id,
35 49 :status => Task::STATUS_INQUEUE) == false
36 50 flash[:notice] = 'Error adding your submission to task queue'
37 51 end
38 52 else
39 53 prepare_list_information
40 54 render :action => 'list' and return
41 55 end
42 56 redirect_to :action => 'list'
43 57 end
44 58
45 59 def source
46 60 submission = Submission.find(params[:id])
47 61 if submission.user_id == session[:user_id]
48 62 fname = submission.problem.name + '.' + submission.language.ext
49 63 send_data(submission.source,
50 64 {:filename => fname,
51 65 :type => 'text/plain'})
52 66 else
53 67 flash[:notice] = 'Error viewing source'
54 68 redirect_to :action => 'list'
@@ -1,39 +1,50
1 1 class TestController < ApplicationController
2 2
3 3 before_filter :authenticate
4 4
5 + #
6 + # COMMENT OUT: filter in each action instead
7 + #
8 + # before_filter :verify_time_limit, :only => [:submit]
9 +
5 10 verify :method => :post, :only => [:submit],
6 11 :redirect_to => { :action => :index }
7 12
8 13 def index
9 14 @user = User.find(session[:user_id])
10 15 prepare_index_information
11 16 @test_requests = @user.test_requests
12 17 end
13 18
14 19 def submit
15 20 @user = User.find(session[:user_id])
21 +
22 + if @user.site!=nil and @user.site.finished?
23 + flash[:notice] = 'Error saving your test submission: Contest is over.'
24 + redirect_to :action => 'index' and return
25 + end
26 +
16 27 test_request = TestRequest.new_from_form_params(@user,params[:test_request])
17 28 if test_request.save
18 29 redirect_to :action => 'index'
19 30 else
20 31 flash[:notice] = 'Error saving your test submission'
21 32 redirect_to :action => 'index'
22 33 end
23 34 end
24 35
25 36 def read
26 37 user = User.find(session[:user_id])
27 38 begin
28 39 test_request = TestRequest.find(params[:id])
29 40 rescue
30 41 test_request = nil
31 42 end
32 43 if test_request==nil or test_request.user_id != user.id
33 44 flash[:notice] = 'Invalid output'
34 45 redirect_to :action => 'index'
35 46 return
36 47 end
37 48 if test_request.output_file_name!=nil
38 49 data = File.open(test_request.output_file_name).read(2048)
39 50 if data==nil
@@ -24,40 +24,48
24 24 append_to menu_items, '[Log out]', 'main', 'login'
25 25
26 26 menu_items
27 27 end
28 28
29 29 def append_to(option,label, controller, action)
30 30 option << ' ' if option!=''
31 31 option << link_to_unless_current(label,
32 32 :controller => controller,
33 33 :action => action)
34 34 end
35 35
36 36 def format_short_time(time)
37 37 now = Time.now
38 38 st = ''
39 39 if (time.yday != now.yday) or
40 40 (time.year != now.year)
41 41 st = time.strftime("%x ")
42 42 end
43 43 st + time.strftime("%X")
44 44 end
45 45
46 46
47 47 def user_title_bar(user)
48 + if user.site!=nil and user.site.finished?
49 + contest_over_string = <<CONTEST_OVER
50 + <tr><td colspan="2" align="center">
51 + <span class="contest-over-msg">THE CONTEST IS OVER</span>
52 + </td></tr>
53 + CONTEST_OVER
54 + end
48 55 <<TITLEBAR
49 56 <div class="title">
50 57 <table>
58 + #{contest_over_string}
51 59 <tr>
52 60 <td class="left-col">
53 61 #{user.full_name}<br/>
54 62 Current time is #{format_short_time(Time.new)}<br/>
55 63 </td>
56 64 <td class="right-col">APIO'08</td>
57 65 </tr>
58 66 </table>
59 67 </div>
60 68 TITLEBAR
61 69 end
62 70
63 71 end
@@ -1,32 +1,34
1 1 require 'digest/sha1'
2 2
3 3 class User < ActiveRecord::Base
4 4
5 5 has_and_belongs_to_many :roles
6 6
7 7 has_many :test_requests, :order => "submitted_at DESC"
8 8
9 + belongs_to :site
10 +
9 11 validates_presence_of :login
10 12 validates_presence_of :full_name
11 13 validates_length_of :full_name, :minimum => 1
12 14
13 15 validates_presence_of :password, :if => :password_required?
14 16 validates_length_of :password, :within => 4..20, :if => :password_required?
15 17 validates_confirmation_of :password, :if => :password_required?
16 18
17 19 attr_accessor :password
18 20
19 21 before_save :encrypt_new_password
20 22
21 23 def self.authenticate(login, password)
22 24 user = find_by_login(login)
23 25 return user if user && user.authenticated?(password)
24 26 end
25 27
26 28 def authenticated?(password)
27 29 hashed_password == User.encrypt(password,self.salt)
28 30 end
29 31
30 32 def admin?
31 33 self.roles.detect {|r| r.name == 'admin' }
32 34 end
@@ -1,23 +1,25
1 1 ActionController::Routing::Routes.draw do |map|
2 + map.resources :sites
3 +
2 4 # The priority is based upon order of creation: first created -> highest priority.
3 5
4 6 # Sample of regular route:
5 7 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
6 8 # Keep in mind you can assign values other than :controller and :action
7 9
8 10 # Sample of named route:
9 11 # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
10 12 # This route can be invoked with purchase_url(:id => product.id)
11 13
12 14 # You can have the root of your site routed by hooking up ''
13 15 # -- just remember to delete public/index.html.
14 16 map.connect '', :controller => 'main', :action => 'login'
15 17
16 18 # Allow downloading Web Service WSDL as a file with an extension
17 19 # instead of a file named 'wsdl'
18 20 map.connect ':controller/service.wsdl', :action => 'wsdl'
19 21
20 22 # Install the default route as the lowest priority.
21 23 map.connect ':controller/:action/:id.:format'
22 24 map.connect ':controller/:action/:id'
23 25 end
@@ -1,36 +1,36
1 1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 2 # please use the migrations feature of ActiveRecord to incrementally modify your database, and
3 3 # then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11
12 - ActiveRecord::Schema.define(:version => 23) do
12 + ActiveRecord::Schema.define(:version => 25) do
13 13
14 14 create_table "configurations", :force => true do |t|
15 15 t.string "key"
16 16 t.string "value_type"
17 17 t.string "value"
18 18 t.datetime "created_at"
19 19 t.datetime "updated_at"
20 20 end
21 21
22 22 create_table "grader_processes", :force => true do |t|
23 23 t.string "host", :limit => 20
24 24 t.integer "pid"
25 25 t.string "mode"
26 26 t.boolean "active"
27 27 t.datetime "created_at"
28 28 t.datetime "updated_at"
29 29 t.integer "task_id"
30 30 end
31 31
32 32 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
33 33
34 34 create_table "languages", :force => true do |t|
35 35 t.string "name", :limit => 10
36 36 t.string "pretty_name"
@@ -58,83 +58,92
58 58 end
59 59
60 60 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
61 61
62 62 create_table "roles", :force => true do |t|
63 63 t.string "name"
64 64 end
65 65
66 66 create_table "roles_users", :id => false, :force => true do |t|
67 67 t.integer "role_id"
68 68 t.integer "user_id"
69 69 end
70 70
71 71 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
72 72
73 73 create_table "sessions", :force => true do |t|
74 74 t.string "session_id"
75 75 t.text "data"
76 76 t.datetime "updated_at"
77 77 end
78 78
79 79 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
80 80 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
81 81
82 + create_table "sites", :force => true do |t|
83 + t.string "name"
84 + t.boolean "started"
85 + t.datetime "start_time"
86 + t.datetime "created_at"
87 + t.datetime "updated_at"
88 + end
89 +
82 90 create_table "submissions", :force => true do |t|
83 91 t.integer "user_id"
84 92 t.integer "problem_id"
85 93 t.integer "language_id"
86 94 t.text "source"
87 95 t.binary "binary"
88 96 t.datetime "submitted_at"
89 97 t.datetime "compiled_at"
90 98 t.text "compiler_message"
91 99 t.datetime "graded_at"
92 100 t.integer "points"
93 101 t.text "grader_comment"
94 102 t.integer "number"
95 103 end
96 104
97 105 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
98 106 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
99 107
100 108 create_table "tasks", :force => true do |t|
101 109 t.integer "submission_id"
102 110 t.datetime "created_at"
103 111 t.integer "status"
104 112 t.datetime "updated_at"
105 113 end
106 114
107 115 create_table "test_requests", :force => true do |t|
108 116 t.integer "user_id"
109 117 t.integer "problem_id"
110 118 t.integer "submission_id"
111 119 t.string "input_file_name"
112 120 t.string "output_file_name"
113 121 t.string "running_stat"
114 122 t.integer "status"
115 123 t.datetime "updated_at"
116 124 t.datetime "submitted_at"
117 125 t.datetime "compiled_at"
118 126 t.text "compiler_message"
119 127 t.datetime "graded_at"
120 128 t.string "grader_comment"
121 129 t.datetime "created_at"
122 130 t.float "running_time"
123 131 t.string "exit_status"
124 132 t.integer "memory_usage"
125 133 end
126 134
127 135 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
128 136
129 137 create_table "users", :force => true do |t|
130 - t.string "login", :limit => 10
131 - t.string "full_name"
132 - t.string "hashed_password"
133 - t.string "salt", :limit => 5
134 - t.string "alias"
135 - t.string "email"
138 + t.string "login", :limit => 10
139 + t.string "full_name"
140 + t.string "hashed_password"
141 + t.string "salt", :limit => 5
142 + t.string "alias"
143 + t.string "email"
144 + t.integer "site_id"
136 145 end
137 146
138 147 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
139 148
140 149 end
@@ -1,47 +1,53
1 1 /* Normal text */
2 2 p {
3 3 font-size: 12px;
4 4 }
5 5
6 6 /* This is the main menu bad*/
7 7 div.userbar {
8 8 border-top: thin solid grey;
9 9 border-bottom: thin solid grey;
10 10 text-align: right;
11 11 font-size: 12px;
12 12 }
13 13
14 14 /* This is the top bar, displaying user's full name */
15 15 div.title {
16 16 font-size: 12px;
17 17 background: #ddffdd;
18 18 border: 1px solid black;
19 19 padding: 2px;
20 20 margin-top: 3px;
21 21 margin-bottom: 5px;
22 22 }
23 23
24 + div.title span.contest-over-msg {
25 + font-size: 15px;
26 + color: red;
27 + font-weight: bold;
28 + }
29 +
24 30 div.title table {
25 31 width: 100%;
26 32 }
27 33
28 34 div.title td.left-col {
29 35 text-align: left;
30 36 vertical-align: top;
31 37 }
32 38
33 39 div.title td.right-col {
34 40 text-align: right;
35 41 vertical-align: top;
36 42 }
37 43
38 44 /* Standard table with header and rows with alternating background */
39 45 table.info {
40 46 border: 1px solid black;
41 47 border-collapse: collapse;
42 48 font-size: 12px;
43 49 }
44 50
45 51 table.info th {
46 52 border: 1px solid black;
47 53 }
@@ -41,34 +41,34
41 41 color: #fff;
42 42 }
43 43
44 44 #errorExplanation p {
45 45 color: #333;
46 46 margin-bottom: 0;
47 47 padding: 5px;
48 48 }
49 49
50 50 #errorExplanation ul li {
51 51 font-size: 12px;
52 52 list-style: square;
53 53 }
54 54
55 55 div.uploadStatus {
56 56 margin: 5px;
57 57 }
58 58
59 59 div.progressBar {
60 60 margin: 5px;
61 61 }
62 62
63 63 div.progressBar div.border {
64 64 background-color: #fff;
65 - border: 1px solid grey;
65 + border: 1px solid gray;
66 66 width: 100%;
67 67 }
68 68
69 69 div.progressBar div.background {
70 70 background-color: #333;
71 71 height: 18px;
72 72 width: 0%;
73 73 }
74 74
You need to be logged in to leave comments. Login now