Description:
merge
Commit status:
[Not Reviewed]
References:
merge algo
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r840:b948bb241476 - - 9 files changed: 66 inserted, 2 deleted

@@ -0,0 +1,25
1 + = simple_form_for(@announcement) do |f|
2 + - if @announcement.errors.any?
3 + .form-row
4 + .col-sm-12
5 + #error_explanation.alert.alert-dismissable.alert-danger
6 + %button.close{type: "button", data: { dismiss: "alert"}, aria: {hidden: "true"}} ×
7 + %h3= "เกิดปัญหาในการบันทึกข้อมูลเนื่องจาก"
8 + %ul
9 + - @announcement.errors.full_messages.each do |message|
10 + %li= message
11 + .form-row
12 + .col-md-6.col-12
13 + -# = f.input :lock_version, as: :hidden
14 + = f.input :title
15 + = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
16 + = f.input :body
17 + = f.input :author
18 + = f.input :published
19 + = f.input :frontpage, label: 'Display in the front page only?'
20 + = f.input :on_nav_bar, label: 'Show on menu bar?', wrapper: :custom_boolean
21 + = f.input :contest_only, label: 'Display in contest only?'
22 + = f.submit "Create", class: 'btn btn-primary'
23 + -if content_for?(:form_buttons)
24 + = yield(:form_buttons)
25 + / = link_to 'Back', announcements_path, class: 'btn btn-default'
@@ -0,0 +1,5
1 + class AddOnNavBarToAnnouncement < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :announcements, :on_nav_bar, :boolean, default: false
4 + end
5 + end
@@ -1,116 +1,116
1 class AnnouncementsController < ApplicationController
1 class AnnouncementsController < ApplicationController
2
2
3 before_action :admin_authorization
3 before_action :admin_authorization
4
4
5 in_place_edit_for :announcement, :published
5 in_place_edit_for :announcement, :published
6
6
7 # GET /announcements
7 # GET /announcements
8 # GET /announcements.xml
8 # GET /announcements.xml
9 def index
9 def index
10 @announcements = Announcement.order(created_at: :desc)
10 @announcements = Announcement.order(created_at: :desc)
11
11
12 respond_to do |format|
12 respond_to do |format|
13 format.html # index.html.erb
13 format.html # index.html.erb
14 format.xml { render :xml => @announcements }
14 format.xml { render :xml => @announcements }
15 end
15 end
16 end
16 end
17
17
18 # GET /announcements/1
18 # GET /announcements/1
19 # GET /announcements/1.xml
19 # GET /announcements/1.xml
20 def show
20 def show
21 @announcement = Announcement.find(params[:id])
21 @announcement = Announcement.find(params[:id])
22
22
23 respond_to do |format|
23 respond_to do |format|
24 format.html # show.html.erb
24 format.html # show.html.erb
25 format.xml { render :xml => @announcement }
25 format.xml { render :xml => @announcement }
26 end
26 end
27 end
27 end
28
28
29 # GET /announcements/new
29 # GET /announcements/new
30 # GET /announcements/new.xml
30 # GET /announcements/new.xml
31 def new
31 def new
32 @announcement = Announcement.new
32 @announcement = Announcement.new
33
33
34 respond_to do |format|
34 respond_to do |format|
35 format.html # new.html.erb
35 format.html # new.html.erb
36 format.xml { render :xml => @announcement }
36 format.xml { render :xml => @announcement }
37 end
37 end
38 end
38 end
39
39
40 # GET /announcements/1/edit
40 # GET /announcements/1/edit
41 def edit
41 def edit
42 @announcement = Announcement.find(params[:id])
42 @announcement = Announcement.find(params[:id])
43 end
43 end
44
44
45 # POST /announcements
45 # POST /announcements
46 # POST /announcements.xml
46 # POST /announcements.xml
47 def create
47 def create
48 @announcement = Announcement.new(announcement_params)
48 @announcement = Announcement.new(announcement_params)
49
49
50 respond_to do |format|
50 respond_to do |format|
51 if @announcement.save
51 if @announcement.save
52 flash[:notice] = 'Announcement was successfully created.'
52 flash[:notice] = 'Announcement was successfully created.'
53 format.html { redirect_to(@announcement) }
53 format.html { redirect_to(@announcement) }
54 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
54 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
55 else
55 else
56 format.html { render :action => "new" }
56 format.html { render :action => "new" }
57 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
57 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
58 end
58 end
59 end
59 end
60 end
60 end
61
61
62 # PUT /announcements/1
62 # PUT /announcements/1
63 # PUT /announcements/1.xml
63 # PUT /announcements/1.xml
64 def update
64 def update
65 @announcement = Announcement.find(params[:id])
65 @announcement = Announcement.find(params[:id])
66
66
67 respond_to do |format|
67 respond_to do |format|
68 if @announcement.update_attributes(announcement_params)
68 if @announcement.update_attributes(announcement_params)
69 flash[:notice] = 'Announcement was successfully updated.'
69 flash[:notice] = 'Announcement was successfully updated.'
70 format.html { redirect_to(@announcement) }
70 format.html { redirect_to(@announcement) }
71 format.js {}
71 format.js {}
72 format.xml { head :ok }
72 format.xml { head :ok }
73 else
73 else
74 format.html { render :action => "edit" }
74 format.html { render :action => "edit" }
75 format.js {}
75 format.js {}
76 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
76 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
77 end
77 end
78 end
78 end
79 end
79 end
80
80
81 def toggle
81 def toggle
82 @announcement = Announcement.find(params[:id])
82 @announcement = Announcement.find(params[:id])
83 @announcement.update_attributes( published: !@announcement.published? )
83 @announcement.update_attributes( published: !@announcement.published? )
84 respond_to do |format|
84 respond_to do |format|
85 format.js { render partial: 'toggle_button',
85 format.js { render partial: 'toggle_button',
86 locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
86 locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
87 end
87 end
88 end
88 end
89
89
90 def toggle_front
90 def toggle_front
91 @announcement = Announcement.find(params[:id])
91 @announcement = Announcement.find(params[:id])
92 @announcement.update_attributes( frontpage: !@announcement.frontpage? )
92 @announcement.update_attributes( frontpage: !@announcement.frontpage? )
93 respond_to do |format|
93 respond_to do |format|
94 format.js { render partial: 'toggle_button',
94 format.js { render partial: 'toggle_button',
95 locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
95 locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
96 end
96 end
97 end
97 end
98
98
99 # DELETE /announcements/1
99 # DELETE /announcements/1
100 # DELETE /announcements/1.xml
100 # DELETE /announcements/1.xml
101 def destroy
101 def destroy
102 @announcement = Announcement.find(params[:id])
102 @announcement = Announcement.find(params[:id])
103 @announcement.destroy
103 @announcement.destroy
104
104
105 respond_to do |format|
105 respond_to do |format|
106 format.html { redirect_to(announcements_url) }
106 format.html { redirect_to(announcements_url) }
107 format.xml { head :ok }
107 format.xml { head :ok }
108 end
108 end
109 end
109 end
110
110
111 private
111 private
112
112
113 def announcement_params
113 def announcement_params
114 - params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title)
114 + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title, :on_nav_bar)
115 end
115 end
116 end
116 end
@@ -1,216 +1,221
1 require 'ipaddr'
1 require 'ipaddr'
2
2
3 class ApplicationController < ActionController::Base
3 class ApplicationController < ActionController::Base
4 protect_from_forgery
4 protect_from_forgery
5
5
6 before_action :current_user
6 before_action :current_user
7 + before_action :nav_announcement
7
8
8 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
9 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
9 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
10 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
10 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
11 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
11 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
12 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
12
13
13 #report and redirect for unauthorized activities
14 #report and redirect for unauthorized activities
14 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
15 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
15 flash[:notice] = notice
16 flash[:notice] = notice
16 redirect_to login_main_path
17 redirect_to login_main_path
17 end
18 end
18
19
19 # Returns the current logged-in user (if any).
20 # Returns the current logged-in user (if any).
20 def current_user
21 def current_user
21 return nil unless session[:user_id]
22 return nil unless session[:user_id]
22 @current_user ||= User.find(session[:user_id])
23 @current_user ||= User.find(session[:user_id])
23 end
24 end
24
25
26 + def nav_announcement
27 + @nav_announcement = Announcement.where(on_nav_bar: true)
28 + end
29 +
25 def admin_authorization
30 def admin_authorization
26 return false unless check_valid_login
31 return false unless check_valid_login
27 user = User.includes(:roles).find(session[:user_id])
32 user = User.includes(:roles).find(session[:user_id])
28 unless user.admin?
33 unless user.admin?
29 unauthorized_redirect
34 unauthorized_redirect
30 return false
35 return false
31 end
36 end
32 return true
37 return true
33 end
38 end
34
39
35 def authorization_by_roles(allowed_roles)
40 def authorization_by_roles(allowed_roles)
36 return false unless check_valid_login
41 return false unless check_valid_login
37 unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) }
42 unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) }
38 unauthorized_redirect
43 unauthorized_redirect
39 return false
44 return false
40 end
45 end
41 end
46 end
42
47
43 def testcase_authorization
48 def testcase_authorization
44 #admin always has privileged
49 #admin always has privileged
45 if @current_user.admin?
50 if @current_user.admin?
46 return true
51 return true
47 end
52 end
48
53
49 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
54 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
50 end
55 end
51
56
52
57
53 protected
58 protected
54
59
55 #redirect to root (and also force logout)
60 #redirect to root (and also force logout)
56 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
61 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
57 def check_valid_login
62 def check_valid_login
58 #check if logged in
63 #check if logged in
59 unless session[:user_id]
64 unless session[:user_id]
60 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
65 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
61 unauthorized_redirect('You need to login but you cannot log in at this time')
66 unauthorized_redirect('You need to login but you cannot log in at this time')
62 else
67 else
63 unauthorized_redirect('You need to login')
68 unauthorized_redirect('You need to login')
64 end
69 end
65 return false
70 return false
66 end
71 end
67
72
68 # check if run in single user mode
73 # check if run in single user mode
69 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
74 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
70 if @current_user==nil || (!@current_user.admin?)
75 if @current_user==nil || (!@current_user.admin?)
71 unauthorized_redirect('You cannot log in at this time')
76 unauthorized_redirect('You cannot log in at this time')
72 return false
77 return false
73 end
78 end
74 end
79 end
75
80
76 # check if the user is enabled
81 # check if the user is enabled
77 unless @current_user.enabled? || @current_user.admin?
82 unless @current_user.enabled? || @current_user.admin?
78 unauthorized_redirect 'Your account is disabled'
83 unauthorized_redirect 'Your account is disabled'
79 return false
84 return false
80 end
85 end
81
86
82 # check if user ip is allowed
87 # check if user ip is allowed
83 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
88 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
84 unless is_request_ip_allowed?
89 unless is_request_ip_allowed?
85 unauthorized_redirect 'Your IP is not allowed to login at this time.'
90 unauthorized_redirect 'Your IP is not allowed to login at this time.'
86 return false
91 return false
87 end
92 end
88 end
93 end
89
94
90 if GraderConfiguration.multicontests?
95 if GraderConfiguration.multicontests?
91 return true if @current_user.admin?
96 return true if @current_user.admin?
92 begin
97 begin
93 if @current_user.contest_stat(true).forced_logout
98 if @current_user.contest_stat(true).forced_logout
94 flash[:notice] = 'You have been automatically logged out.'
99 flash[:notice] = 'You have been automatically logged out.'
95 redirect_to :controller => 'main', :action => 'index'
100 redirect_to :controller => 'main', :action => 'index'
96 end
101 end
97 rescue
102 rescue
98 end
103 end
99 end
104 end
100 return true
105 return true
101 end
106 end
102
107
103 #redirect to root (and also force logout)
108 #redirect to root (and also force logout)
104 #if the user use different ip from the previous connection
109 #if the user use different ip from the previous connection
105 # only applicable when MULTIPLE_IP_LOGIN options is false only
110 # only applicable when MULTIPLE_IP_LOGIN options is false only
106 def authenticate_by_ip_address
111 def authenticate_by_ip_address
107 #this assume that we have already authenticate normally
112 #this assume that we have already authenticate normally
108 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
113 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
109 user = User.find(session[:user_id])
114 user = User.find(session[:user_id])
110 if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip)
115 if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip)
111 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
116 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
112 redirect_to :controller => 'main', :action => 'login'
117 redirect_to :controller => 'main', :action => 'login'
113 return false
118 return false
114 end
119 end
115 unless user.last_ip
120 unless user.last_ip
116 user.last_ip = request.remote_ip
121 user.last_ip = request.remote_ip
117 user.save
122 user.save
118 end
123 end
119 end
124 end
120 return true
125 return true
121 end
126 end
122
127
123 def authorization
128 def authorization
124 return false unless check_valid_login
129 return false unless check_valid_login
125 user = User.find(session[:user_id])
130 user = User.find(session[:user_id])
126 unless user.roles.detect { |role|
131 unless user.roles.detect { |role|
127 role.rights.detect{ |right|
132 role.rights.detect{ |right|
128 right.controller == self.class.controller_name and
133 right.controller == self.class.controller_name and
129 (right.action == 'all' || right.action == action_name)
134 (right.action == 'all' || right.action == action_name)
130 }
135 }
131 }
136 }
132 flash[:notice] = 'You are not authorized to view the page you requested'
137 flash[:notice] = 'You are not authorized to view the page you requested'
133 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
138 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
134 redirect_to :controller => 'main', :action => 'login'
139 redirect_to :controller => 'main', :action => 'login'
135 return false
140 return false
136 end
141 end
137 end
142 end
138
143
139 def verify_time_limit
144 def verify_time_limit
140 return true if session[:user_id]==nil
145 return true if session[:user_id]==nil
141 user = User.find(session[:user_id], :include => :site)
146 user = User.find(session[:user_id], :include => :site)
142 return true if user==nil || user.site == nil
147 return true if user==nil || user.site == nil
143 if user.contest_finished?
148 if user.contest_finished?
144 flash[:notice] = 'Error: the contest you are participating is over.'
149 flash[:notice] = 'Error: the contest you are participating is over.'
145 redirect_to :back
150 redirect_to :back
146 return false
151 return false
147 end
152 end
148 return true
153 return true
149 end
154 end
150
155
151 def is_request_ip_allowed?
156 def is_request_ip_allowed?
152 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
157 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
153 user_ip = IPAddr.new(request.remote_ip)
158 user_ip = IPAddr.new(request.remote_ip)
154 allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
159 allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
155
160
156 allowed.delete(' ').split(',').each do |ips|
161 allowed.delete(' ').split(',').each do |ips|
157 allow_ips = IPAddr.new(ips)
162 allow_ips = IPAddr.new(ips)
158 if allow_ips.include?(user_ip)
163 if allow_ips.include?(user_ip)
159 return true
164 return true
160 end
165 end
161 end
166 end
162 return false
167 return false
163 end
168 end
164 return true
169 return true
165 end
170 end
166
171
167 #function for datatable ajax query
172 #function for datatable ajax query
168 #return record,total_count,filter_count
173 #return record,total_count,filter_count
169 def process_query_record(record,
174 def process_query_record(record,
170 total_count: nil,
175 total_count: nil,
171 select: '',
176 select: '',
172 global_search: [],
177 global_search: [],
173 no_search: false,
178 no_search: false,
174 force_order: '',
179 force_order: '',
175 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
180 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
176 hard_limit: nil)
181 hard_limit: nil)
177 arel_table = record.model.arel_table
182 arel_table = record.model.arel_table
178
183
179 if !no_search && params['search']
184 if !no_search && params['search']
180 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
185 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
181 if !global_value.blank?
186 if !global_value.blank?
182 global_value.split.each do |value|
187 global_value.split.each do |value|
183 global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ')
188 global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ')
184 record = record.where(global_where)
189 record = record.where(global_where)
185 end
190 end
186 end
191 end
187
192
188 params['columns'].each do |i, col|
193 params['columns'].each do |i, col|
189 if !col['search']['value'].blank?
194 if !col['search']['value'].blank?
190 record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%"))
195 record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%"))
191 end
196 end
192 end
197 end
193 end
198 end
194
199
195 if !date_filter.blank?
200 if !date_filter.blank?
196 param_since = params[date_param_since]
201 param_since = params[date_param_since]
197 param_until = params[date_param_until]
202 param_until = params[date_param_until]
198 date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1)
203 date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1)
199 date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now()
204 date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now()
200 date_range = date_since..(date_until.end_of_day)
205 date_range = date_since..(date_until.end_of_day)
201 record = record.where(date_filter.to_sym => date_range)
206 record = record.where(date_filter.to_sym => date_range)
202 end
207 end
203
208
204 if force_order.blank?
209 if force_order.blank?
205 if params['order']
210 if params['order']
206 params['order'].each do |i, o|
211 params['order'].each do |i, o|
207 colName = params['columns'][o['column']]['name']
212 colName = params['columns'][o['column']]['name']
208 colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID'
213 colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID'
209 record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank?
214 record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank?
210 end
215 end
211 end
216 end
212 else
217 else
213 record = record.order(force_order)
218 record = record.order(force_order)
214 end
219 end
215
220
216 filterCount = record.count(record.model.primary_key)
221 filterCount = record.count(record.model.primary_key)
@@ -1,34 +1,45
1 + %h1 Edit Announcement
2 +
3 + -content_for(:form_buttons) do
4 + = link_to t(:back), announcements_path, class: 'card-link btn btn-secondary'
5 +
6 + = render 'form'
7 + -# old style
1 .container-fluid
8 .container-fluid
2 %h1 Editing announcement
9 %h1 Editing announcement
3 = error_messages_for :announcement
10 = error_messages_for :announcement
4 .row
11 .row
5 .col-md-6
12 .col-md-6
6 = form_for(@announcement) do |f|
13 = form_for(@announcement) do |f|
7 .form-group
14 .form-group
8 %label Title
15 %label Title
9 = f.text_field :title, class: 'form-control'
16 = f.text_field :title, class: 'form-control'
10 .form-group
17 .form-group
11 %label Notes
18 %label Notes
12 (shown internally, used to organize announcements)
19 (shown internally, used to organize announcements)
13 = f.text_field :notes, class: 'form-control'
20 = f.text_field :notes, class: 'form-control'
14 .form-group
21 .form-group
15 %label Body
22 %label Body
16 = f.text_area :body, class: 'form-control', style: 'height: 200px;'
23 = f.text_area :body, class: 'form-control', style: 'height: 200px;'
17 .form-group
24 .form-group
18 %label Author
25 %label Author
19 = f.text_field :author, class: 'form-control'
26 = f.text_field :author, class: 'form-control'
20 .checkbox
27 .checkbox
21 %label
28 %label
22 = f.check_box :published
29 = f.check_box :published
23 Published
30 Published
24 .checkbox
31 .checkbox
25 %label
32 %label
26 = f.check_box :frontpage
33 = f.check_box :frontpage
27 Show on front page?
34 Show on front page?
28 .checkbox
35 .checkbox
29 %label
36 %label
37 + = f.check_box :on_nav_bar
38 + Show on top menu bar?
39 + .checkbox
40 + %label
30 = f.check_box :contest_only
41 = f.check_box :contest_only
31 Show only in contest?
42 Show only in contest?
32 = f.submit "Update", class: 'btn btn-primary'
43 = f.submit "Update", class: 'btn btn-primary'
33 = link_to 'Show', @announcement, class: 'btn btn-default'
44 = link_to 'Show', @announcement, class: 'btn btn-default'
34 = link_to 'Back', announcements_path, class: 'btn btn-default'
45 = link_to 'Back', announcements_path, class: 'btn btn-default'
@@ -1,14 +1,22
1 %h1 New announcement
1 %h1 New announcement
2 +
3 + -content_for(:form_buttons) do
4 + = link_to t(:back), announcements_path, class: 'card-link btn btn-secondary'
5 +
6 + = render 'form'
7 +
8 + -# old style
2 = error_messages_for :announcement
9 = error_messages_for :announcement
3 = simple_form_for(@announcement) do |f|
10 = simple_form_for(@announcement) do |f|
4 .row
11 .row
5 .col-md-6
12 .col-md-6
6 = f.input :title
13 = f.input :title
7 = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
14 = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
8 = f.input :body
15 = f.input :body
9 = f.input :author
16 = f.input :author
10 = f.input :published
17 = f.input :published
11 = f.input :frontpage, label: 'Display in the front page only?'
18 = f.input :frontpage, label: 'Display in the front page only?'
12 = f.input :contest_only, label: 'Display in contest only?'
19 = f.input :contest_only, label: 'Display in contest only?'
13 = f.button :submit, "Create", class: 'btn btn-primary'
20 = f.button :submit, "Create", class: 'btn btn-primary'
14 = link_to 'Back', announcements_path, class: 'btn btn-default'
21 = link_to 'Back', announcements_path, class: 'btn btn-default'
22 +
@@ -1,24 +1,27
1 %p
1 %p
2 %b Author:
2 %b Author:
3 = h @announcement.author
3 = h @announcement.author
4 %p
4 %p
5 %b Title:
5 %b Title:
6 = h @announcement.title
6 = h @announcement.title
7 %p
7 %p
8 %b Notes:
8 %b Notes:
9 = h @announcement.notes
9 = h @announcement.notes
10 %p
10 %p
11 %b Body:
11 %b Body:
12 = h markdown(@announcement.body)
12 = h markdown(@announcement.body)
13 %p
13 %p
14 %b Published:
14 %b Published:
15 = h @announcement.published
15 = h @announcement.published
16 %p
16 %p
17 %b Show on front page:
17 %b Show on front page:
18 = h @announcement.frontpage
18 = h @announcement.frontpage
19 %p
19 %p
20 + %b Show on top menu bar:
21 + = h @announcement.on_nav_bar
22 + %p
20 %b Show only in contest:
23 %b Show only in contest:
21 = h @announcement.contest_only
24 = h @announcement.contest_only
22 = link_to 'Edit', edit_announcement_path(@announcement)
25 = link_to 'Edit', edit_announcement_path(@announcement)
23 |
26 |
24 = link_to 'Back', announcements_path
27 = link_to 'Back', announcements_path
@@ -1,96 +1,102
1 %header.navbar.navbar-default.navbar-fixed-top
1 %header.navbar.navbar-default.navbar-fixed-top
2 %nav
2 %nav
3 .container-fluid
3 .container-fluid
4 .navbar-header
4 .navbar-header
5 %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} }
5 %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} }
6 %span.sr-only Togggle Navigation
6 %span.sr-only Togggle Navigation
7 %span.icon-bar
7 %span.icon-bar
8 %span.icon-bar
8 %span.icon-bar
9 %span.icon-bar
9 %span.icon-bar
10 %a.navbar-brand{href: list_main_path}
10 %a.navbar-brand{href: list_main_path}
11 %span.glyphicon.glyphicon-home
11 %span.glyphicon.glyphicon-home
12 MAIN
12 MAIN
13 .collapse.navbar-collapse#navbar-collapse
13 .collapse.navbar-collapse#navbar-collapse
14 %ul.nav.navbar-nav
14 %ul.nav.navbar-nav
15 / submission
15 / submission
16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
17 %li.dropdown
17 %li.dropdown
18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
19 = "#{I18n.t 'menu.submissions'}"
19 = "#{I18n.t 'menu.submissions'}"
20 %span.caret
20 %span.caret
21 %ul.dropdown-menu
21 %ul.dropdown-menu
22 = add_menu("View", 'submissions', 'index')
22 = add_menu("View", 'submissions', 'index')
23 = add_menu("Self Test", 'test', 'index')
23 = add_menu("Self Test", 'test', 'index')
24 / hall of fame
24 / hall of fame
25 - if GraderConfiguration['right.user_hall_of_fame']
25 - if GraderConfiguration['right.user_hall_of_fame']
26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
27 / display MODE button (with countdown in contest mode)
27 / display MODE button (with countdown in contest mode)
28 - if GraderConfiguration.analysis_mode?
28 - if GraderConfiguration.analysis_mode?
29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
30 - elsif GraderConfiguration.time_limit_mode?
30 - elsif GraderConfiguration.time_limit_mode?
31 - if @current_user.contest_finished?
31 - if @current_user.contest_finished?
32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
33 - elsif !@current_user.contest_started?
33 - elsif !@current_user.contest_started?
34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
35 - else
35 - else
36 %div.navbar-btn.btn.btn-primary#countdown asdf
36 %div.navbar-btn.btn.btn-primary#countdown asdf
37 :javascript
37 :javascript
38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
39 / admin section
39 / admin section
40 - if (@current_user!=nil) and (session[:admin])
40 - if (@current_user!=nil) and (session[:admin])
41 / management
41 / management
42 %li.dropdown
42 %li.dropdown
43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
44 Manage
44 Manage
45 %span.caret
45 %span.caret
46 %ul.dropdown-menu
46 %ul.dropdown-menu
47 = add_menu( 'Announcements', 'announcements', 'index')
47 = add_menu( 'Announcements', 'announcements', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
49 = add_menu( 'Tags', 'tags', 'index')
49 = add_menu( 'Tags', 'tags', 'index')
50 = add_menu( 'Users', 'user_admin', 'index')
50 = add_menu( 'Users', 'user_admin', 'index')
51 = add_menu( 'User Groups', 'groups', 'index')
51 = add_menu( 'User Groups', 'groups', 'index')
52 = add_menu( 'Graders', 'graders', 'list')
52 = add_menu( 'Graders', 'graders', 'list')
53 = add_menu( 'Message ', 'messages', 'console')
53 = add_menu( 'Message ', 'messages', 'console')
54 %li.divider{role: 'separator'}
54 %li.divider{role: 'separator'}
55 = add_menu( 'System config', 'configurations', 'index')
55 = add_menu( 'System config', 'configurations', 'index')
56 %li.divider{role: 'separator'}
56 %li.divider{role: 'separator'}
57 = add_menu( 'Sites', 'sites', 'index')
57 = add_menu( 'Sites', 'sites', 'index')
58 = add_menu( 'Contests', 'contest_management', 'index')
58 = add_menu( 'Contests', 'contest_management', 'index')
59 / report
59 / report
60 %li.dropdown
60 %li.dropdown
61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
62 Report
62 Report
63 %span.caret
63 %span.caret
64 %ul.dropdown-menu
64 %ul.dropdown-menu
65 = add_menu( 'Current Score', 'report', 'current_score')
65 = add_menu( 'Current Score', 'report', 'current_score')
66 = add_menu( 'Score Report', 'report', 'max_score')
66 = add_menu( 'Score Report', 'report', 'max_score')
67 = add_menu( 'Submission Report', 'report', 'submission')
67 = add_menu( 'Submission Report', 'report', 'submission')
68 = add_menu( 'Login Report', 'report', 'login')
68 = add_menu( 'Login Report', 'report', 'login')
69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
70 =link_to "#{ungraded} backlogs!",
70 =link_to "#{ungraded} backlogs!",
71 graders_list_path,
71 graders_list_path,
72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
73 + / announcement
74 + - @nav_announcement.each do |ann|
75 + %p.navbar-text
76 + = ann.body.html_safe
77 +
78 +
73
79
74 %ul.nav.navbar-nav.navbar-right
80 %ul.nav.navbar-nav.navbar-right
75 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
81 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
76 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
82 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
77 - if GraderConfiguration['system.user_setting_enabled']
83 - if GraderConfiguration['system.user_setting_enabled']
78 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
84 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
79 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
85 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
80
86
81 /
87 /
82 - if (@current_user!=nil) and (session[:admin])
88 - if (@current_user!=nil) and (session[:admin])
83 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
89 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
84 .container-fluid
90 .container-fluid
85 .collapse.navbar-collapse
91 .collapse.navbar-collapse
86 %ul.nav.navbar-nav
92 %ul.nav.navbar-nav
87 = add_menu( '[Announcements]', 'announcements', 'index')
93 = add_menu( '[Announcements]', 'announcements', 'index')
88 = add_menu( '[Msg console]', 'messages', 'console')
94 = add_menu( '[Msg console]', 'messages', 'console')
89 = add_menu( '[Problems]', 'problems', 'index')
95 = add_menu( '[Problems]', 'problems', 'index')
90 = add_menu( '[Users]', 'user_admin', 'index')
96 = add_menu( '[Users]', 'user_admin', 'index')
91 = add_menu( '[Results]', 'user_admin', 'user_stat')
97 = add_menu( '[Results]', 'user_admin', 'user_stat')
92 = add_menu( '[Report]', 'report', 'multiple_login')
98 = add_menu( '[Report]', 'report', 'multiple_login')
93 = add_menu( '[Graders]', 'graders', 'list')
99 = add_menu( '[Graders]', 'graders', 'list')
94 = add_menu( '[Contests]', 'contest_management', 'index')
100 = add_menu( '[Contests]', 'contest_management', 'index')
95 = add_menu( '[Sites]', 'sites', 'index')
101 = add_menu( '[Sites]', 'sites', 'index')
96 = add_menu( '[System config]', 'configurations', 'index')
102 = add_menu( '[System config]', 'configurations', 'index')
@@ -1,216 +1,217
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your
5 # Note that this schema.rb definition is the authoritative source for your
6 # database schema. If you need to create the application database on another
6 # database schema. If you need to create the application database on another
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 - ActiveRecord::Schema.define(version: 2020_08_13_083020) do
13 + ActiveRecord::Schema.define(version: 2021_01_24_101028) do
14
14
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 t.datetime "created_at", null: false
19 t.datetime "created_at", null: false
20 t.datetime "updated_at", null: false
20 t.datetime "updated_at", null: false
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 + t.boolean "on_nav_bar", default: false
25 end
26 end
26
27
27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 t.string "title"
29 t.string "title"
29 t.boolean "enabled"
30 t.boolean "enabled"
30 t.datetime "created_at", null: false
31 t.datetime "created_at", null: false
31 t.datetime "updated_at", null: false
32 t.datetime "updated_at", null: false
32 t.string "name"
33 t.string "name"
33 end
34 end
34
35
35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 t.integer "contest_id"
37 t.integer "contest_id"
37 t.integer "problem_id"
38 t.integer "problem_id"
38 end
39 end
39
40
40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 t.integer "contest_id"
42 t.integer "contest_id"
42 t.integer "user_id"
43 t.integer "user_id"
43 end
44 end
44
45
45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 t.string "name"
47 t.string "name"
47 t.datetime "created_at", null: false
48 t.datetime "created_at", null: false
48 t.datetime "updated_at", null: false
49 t.datetime "updated_at", null: false
49 end
50 end
50
51
51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 t.text "body"
53 t.text "body"
53 t.boolean "markdowned"
54 t.boolean "markdowned"
54 t.datetime "created_at", null: false
55 t.datetime "created_at", null: false
55 t.datetime "updated_at", null: false
56 t.datetime "updated_at", null: false
56 end
57 end
57
58
58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 t.string "key"
60 t.string "key"
60 t.string "value_type"
61 t.string "value_type"
61 t.string "value"
62 t.string "value"
62 t.datetime "created_at", null: false
63 t.datetime "created_at", null: false
63 t.datetime "updated_at", null: false
64 t.datetime "updated_at", null: false
64 t.text "description"
65 t.text "description"
65 end
66 end
66
67
67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 t.string "host"
69 t.string "host"
69 t.integer "pid"
70 t.integer "pid"
70 t.string "mode"
71 t.string "mode"
71 t.boolean "active"
72 t.boolean "active"
72 t.datetime "created_at", null: false
73 t.datetime "created_at", null: false
73 t.datetime "updated_at", null: false
74 t.datetime "updated_at", null: false
74 t.integer "task_id"
75 t.integer "task_id"
75 t.string "task_type"
76 t.string "task_type"
76 t.boolean "terminated"
77 t.boolean "terminated"
77 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 end
79 end
79
80
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
82 t.string "name"
82 t.string "description"
83 t.string "description"
83 t.boolean "enabled", default: true
84 t.boolean "enabled", default: true
84 end
85 end
85
86
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
87 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
87 t.integer "problem_id", null: false
88 t.integer "problem_id", null: false
88 t.integer "group_id", null: false
89 t.integer "group_id", null: false
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
90 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
90 end
91 end
91
92
92 create_table "groups_users", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
93 create_table "groups_users", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
93 t.integer "group_id", null: false
94 t.integer "group_id", null: false
94 t.integer "user_id", null: false
95 t.integer "user_id", null: false
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
96 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
96 end
97 end
97
98
98 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
99 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
99 t.integer "user_id"
100 t.integer "user_id"
100 t.string "ip_address"
101 t.string "ip_address"
101 t.datetime "created_at", null: false
102 t.datetime "created_at", null: false
102 t.datetime "updated_at", null: false
103 t.datetime "updated_at", null: false
103 t.string "status"
104 t.string "status"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
105 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
105 end
106 end
106
107
107 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
108 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
108 t.string "name", limit: 10
109 t.string "name", limit: 10
109 t.string "pretty_name"
110 t.string "pretty_name"
110 t.string "ext", limit: 10
111 t.string "ext", limit: 10
111 t.string "common_ext"
112 t.string "common_ext"
112 end
113 end
113
114
114 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
115 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
115 t.integer "user_id"
116 t.integer "user_id"
116 t.string "ip_address"
117 t.string "ip_address"
117 t.datetime "created_at", null: false
118 t.datetime "created_at", null: false
118 t.datetime "updated_at", null: false
119 t.datetime "updated_at", null: false
119 t.index ["user_id"], name: "index_logins_on_user_id"
120 t.index ["user_id"], name: "index_logins_on_user_id"
120 end
121 end
121
122
122 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
123 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
123 t.integer "sender_id"
124 t.integer "sender_id"
124 t.integer "receiver_id"
125 t.integer "receiver_id"
125 t.integer "replying_message_id"
126 t.integer "replying_message_id"
126 t.text "body"
127 t.text "body"
127 t.boolean "replied"
128 t.boolean "replied"
128 t.datetime "created_at", null: false
129 t.datetime "created_at", null: false
129 t.datetime "updated_at", null: false
130 t.datetime "updated_at", null: false
130 end
131 end
131
132
132 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
133 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
133 t.string "name", limit: 30
134 t.string "name", limit: 30
134 t.string "full_name"
135 t.string "full_name"
135 t.integer "full_score"
136 t.integer "full_score"
136 t.date "date_added"
137 t.date "date_added"
137 t.boolean "available"
138 t.boolean "available"
138 t.string "url"
139 t.string "url"
139 t.integer "description_id"
140 t.integer "description_id"
140 t.boolean "test_allowed"
141 t.boolean "test_allowed"
141 t.boolean "output_only"
142 t.boolean "output_only"
142 t.string "description_filename"
143 t.string "description_filename"
143 t.boolean "view_testcase"
144 t.boolean "view_testcase"
144 end
145 end
145
146
146 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
147 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
147 t.integer "problem_id"
148 t.integer "problem_id"
148 t.integer "tag_id"
149 t.integer "tag_id"
149 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
150 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
150 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
151 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
151 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
152 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
152 end
153 end
153
154
154 create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
155 create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
155 t.string "name"
156 t.string "name"
156 t.string "controller"
157 t.string "controller"
157 t.string "action"
158 t.string "action"
158 end
159 end
159
160
160 create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
161 create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
161 t.integer "right_id"
162 t.integer "right_id"
162 t.integer "role_id"
163 t.integer "role_id"
163 t.index ["role_id"], name: "index_rights_roles_on_role_id"
164 t.index ["role_id"], name: "index_rights_roles_on_role_id"
164 end
165 end
165
166
166 create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
167 create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
167 t.string "name"
168 t.string "name"
168 end
169 end
169
170
170 create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
171 create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
171 t.integer "role_id"
172 t.integer "role_id"
172 t.integer "user_id"
173 t.integer "user_id"
173 t.index ["user_id"], name: "index_roles_users_on_user_id"
174 t.index ["user_id"], name: "index_roles_users_on_user_id"
174 end
175 end
175
176
176 create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
177 create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
177 t.string "session_id"
178 t.string "session_id"
178 t.text "data"
179 t.text "data"
179 t.datetime "updated_at"
180 t.datetime "updated_at"
180 t.index ["session_id"], name: "index_sessions_on_session_id"
181 t.index ["session_id"], name: "index_sessions_on_session_id"
181 t.index ["updated_at"], name: "index_sessions_on_updated_at"
182 t.index ["updated_at"], name: "index_sessions_on_updated_at"
182 end
183 end
183
184
184 create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
185 create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
185 t.string "name"
186 t.string "name"
186 t.boolean "started"
187 t.boolean "started"
187 t.datetime "start_time"
188 t.datetime "start_time"
188 t.datetime "created_at", null: false
189 t.datetime "created_at", null: false
189 t.datetime "updated_at", null: false
190 t.datetime "updated_at", null: false
190 t.integer "country_id"
191 t.integer "country_id"
191 t.string "password"
192 t.string "password"
192 end
193 end
193
194
194 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
195 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
195 t.integer "user_id"
196 t.integer "user_id"
196 t.integer "submission_id"
197 t.integer "submission_id"
197 t.datetime "created_at", null: false
198 t.datetime "created_at", null: false
198 t.datetime "updated_at", null: false
199 t.datetime "updated_at", null: false
199 end
200 end
200
201
201 create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
202 create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
202 t.integer "user_id"
203 t.integer "user_id"
203 t.integer "problem_id"
204 t.integer "problem_id"
204 t.integer "language_id"
205 t.integer "language_id"
205 t.text "source", limit: 16777215
206 t.text "source", limit: 16777215
206 t.binary "binary"
207 t.binary "binary"
207 t.datetime "submitted_at"
208 t.datetime "submitted_at"
208 t.datetime "compiled_at"
209 t.datetime "compiled_at"
209 t.text "compiler_message"
210 t.text "compiler_message"
210 t.datetime "graded_at"
211 t.datetime "graded_at"
211 t.integer "points"
212 t.integer "points"
212 t.text "grader_comment"
213 t.text "grader_comment"
213 t.integer "number"
214 t.integer "number"
214 t.string "source_filename"
215 t.string "source_filename"
215 t.float "max_runtime"
216 t.float "max_runtime"
216 t.integer "peak_memory"
217 t.integer "peak_memory"
You need to be logged in to leave comments. Login now