diff --git a/Gemfile b/Gemfile
--- a/Gemfile
+++ b/Gemfile
@@ -2,6 +2,8 @@
gem 'rails', '3.2.21'
+gem 'select2-rails'
+
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
@@ -45,11 +47,26 @@
gem 'jquery-ui-sass-rails'
gem 'jquery-timepicker-addon-rails'
gem 'jquery-tablesorter'
+gem 'jquery-countdown-rails'
#syntax highlighter
gem 'rouge'
+#add bootstrap
+gem 'bootstrap-sass', '~> 3.2.0'
+gem 'bootstrap-switch-rails'
+gem 'bootstrap-toggle-rails'
+gem 'autoprefixer-rails'
+
+#bootstrap sortable
+gem 'momentjs-rails'
+gem 'rails_bootstrap_sortable'
+
+#ace editor
+gem 'ace-rails-ap'
+
gem 'haml'
+gem 'haml-rails'
gem 'mail'
gem 'rdiscount'
gem 'test-unit'
diff --git a/Gemfile.lock b/Gemfile.lock
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -9,6 +9,7 @@
GEM
remote: https://rubygems.org/
specs:
+ ace-rails-ap (4.0.2)
actionmailer (3.2.21)
actionpack (= 3.2.21)
mail (~> 2.5.4)
@@ -37,9 +38,16 @@
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
arel (3.0.3)
+ autoprefixer-rails (6.0.3)
+ execjs
+ json
best_in_place (3.0.3)
actionpack (>= 3.2)
railties (>= 3.2)
+ bootstrap-sass (3.2.0.2)
+ sass (~> 3.2)
+ bootstrap-switch-rails (3.3.3)
+ bootstrap-toggle-rails (2.2.1.0)
builder (3.0.4)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
@@ -54,10 +62,16 @@
execjs (2.3.0)
haml (4.0.6)
tilt
+ haml-rails (0.4)
+ actionpack (>= 3.1, < 4.1)
+ activesupport (>= 3.1, < 4.1)
+ haml (>= 3.1, < 4.1)
+ railties (>= 3.1, < 4.1)
hike (1.2.3)
i18n (0.7.0)
in_place_editing (1.2.0)
journey (1.0.4)
+ jquery-countdown-rails (2.0.2)
jquery-rails (3.1.2)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
@@ -77,6 +91,8 @@
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.25.1)
+ momentjs-rails (2.11.1)
+ railties (>= 3.1)
multi_json (1.10.1)
mysql2 (0.3.20)
polyglot (0.3.5)
@@ -98,6 +114,8 @@
activesupport (= 3.2.21)
bundler (~> 1.0)
railties (= 3.2.21)
+ rails_bootstrap_sortable (2.0.0)
+ momentjs-rails (~> 2, >= 2.8.3)
railties (3.2.21)
actionpack (= 3.2.21)
activesupport (= 3.2.21)
@@ -130,6 +148,8 @@
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
+ select2-rails (4.0.1)
+ thor (~> 0.14)
sprockets (2.2.3)
hike (~> 1.2)
multi_json (~> 1.0)
@@ -152,23 +172,33 @@
ruby
DEPENDENCIES
+ ace-rails-ap
+ autoprefixer-rails
best_in_place (~> 3.0.1)
+ bootstrap-sass (~> 3.2.0)
+ bootstrap-switch-rails
+ bootstrap-toggle-rails
coffee-rails (~> 3.2.2)
dynamic_form
haml
+ haml-rails
in_place_editing
+ jquery-countdown-rails
jquery-rails
jquery-tablesorter
jquery-timepicker-addon-rails
jquery-ui-sass-rails
mail
+ momentjs-rails
mysql2
prototype-rails
rails (= 3.2.21)
+ rails_bootstrap_sortable
rdiscount
rouge
rspec-rails (~> 2.99.0)
sass-rails (~> 3.2.6)
+ select2-rails
test-unit
uglifier
verification!
diff --git a/app/assets/javascripts/announcements.js.coffee b/app/assets/javascripts/announcements.js.coffee
new file mode 100644
--- /dev/null
+++ b/app/assets/javascripts/announcements.js.coffee
@@ -0,0 +1,6 @@
+#js for announcement
+$ ->
+ $(document).ajaxError (event, jqxhr, settings, exception) ->
+ if jqxhr.status
+ alert 'We\'re sorry, but something went wrong (' + jqxhr.status + ')'
+ return
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -10,8 +10,35 @@
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
-//= require prototype
-//= require prototype_ujs
-//= require effects
-//= require dragdrop
-//= require controls
+//= require jquery
+//= require jquery_ujs
+//= require jquery.ui.all
+//= require bootstrap-sprockets
+//= require moment
+//= require bootstrap-sortable
+//= require select2
+//= require ace-rails-ap
+//= require ace/mode-c_cpp
+//= require ace/mode-python
+//= require ace/mode-ruby
+//= require ace/mode-pascal
+//= require ace/mode-javascript
+//= require ace/mode-java
+//= require ace/theme-merbivore
+//= require custom
+//= require jquery.countdown
+//-------------- addition from local_jquery -----------
+//= require jquery.ui.datepicker
+//= require jquery.ui.slider
+//= require jquery-ui-timepicker-addon
+//= require jquery-tablesorter
+//= require best_in_place
+//= require best_in_place.jquery-ui
+//= require brython
+
+// since this is after blank line, it is not downloaded
+//x= require prototype
+//x= require prototype_ujs
+//x= require effects
+//x= require dragdrop
+//x= require controls
diff --git a/app/assets/javascripts/configurations.js.coffee b/app/assets/javascripts/configurations.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/contest_management.js.coffee b/app/assets/javascripts/contest_management.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/contests.js.coffee b/app/assets/javascripts/contests.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/custom.js.coffee b/app/assets/javascripts/custom.js.coffee
new file mode 100644
--- /dev/null
+++ b/app/assets/javascripts/custom.js.coffee
@@ -0,0 +1,52 @@
+$(document).on 'change', '.btn-file :file', ->
+ input = $(this)
+ numFiles = if input.get(0).files then input.get(0).files.length else 1
+ label = input.val().replace(/\\/g, '/').replace(/.*\//, '')
+ input.trigger 'fileselect', [
+ numFiles
+ label
+ ]
+ return
+
+
+# document ready
+
+$ ->
+ $(".select2").select2()
+ #$(".bootstrap-switch").bootstrapSwitch()
+ #$(".bootstrap-toggle").bootstrapToggle()
+ $('.btn-file :file').on 'fileselect', (event, numFiles, label) ->
+ input = $(this).parents('.input-group').find(':text')
+ log = if numFiles > 1 then numFiles + ' files selected' else label
+ if input.length
+ input.val log
+ else
+ if log
+ alert log
+ return
+ $(".go-button").on 'click', (event) ->
+ link = $(this).attr("data-source")
+ url = $(link).val()
+ if url
+ window.location.href = url
+ return
+ $('.ajax-toggle').on 'click', (event) ->
+ target = $(event.target)
+ target.removeClass 'btn-default'
+ target.removeClass 'btn-success'
+ target.addClass 'btn-warning'
+ target.text '...'
+ return
+
+
+ #ace editor
+ if $("#editor").length > 0
+ e = ace.edit("editor")
+ e.setTheme('ace/theme/merbivore')
+ e.getSession().setTabSize(2)
+ e.getSession().setUseSoftTabs(true)
+
+ #best in place
+ jQuery(".best_in_place").best_in_place()
+
+ return
diff --git a/app/assets/javascripts/graders.js.coffee b/app/assets/javascripts/graders.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/heartbeat.js.coffee b/app/assets/javascripts/heartbeat.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/login.js.coffee b/app/assets/javascripts/login.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/messages.js.coffee b/app/assets/javascripts/messages.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/problems.js.coffee b/app/assets/javascripts/problems.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/report.js.coffee b/app/assets/javascripts/report.js.coffee
--- a/app/assets/javascripts/report.js.coffee
+++ b/app/assets/javascripts/report.js.coffee
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/javascripts/site.js.coffee b/app/assets/javascripts/site.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/sites.js.coffee b/app/assets/javascripts/sites.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/sources.js.coffee b/app/assets/javascripts/sources.js.coffee
new file mode 100644
--- /dev/null
+++ b/app/assets/javascripts/sources.js.coffee
@@ -0,0 +1,32 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
+
+
+$ ->
+ $("#live_submit").on "click", (event) ->
+ h = $("#editor_text")
+ e = ace.edit("editor")
+ h.val(e.getValue())
+
+ $("#language_id").on "change", (event) ->
+ text = $("#language_id option:selected").text()
+ mode = 'ace/mode/c_cpp'
+ switch text
+ when 'Pascal' then mode = 'ace/mode/pascal'
+ when 'C++','C' then mode = 'ace/mode/c_cpp'
+ when 'Ruby' then mode = 'ace/mode/ruby'
+ when 'Python' then mode = 'ace/mode/python'
+ when 'Java' then mode = 'ace/mode/java'
+ editor = ace.edit('editor')
+ editor.getSession().setMode(mode)
+
+ e = ace.edit("editor")
+ e.setValue($("#text_haha").val())
+ e.gotoLine(1)
+ $("#language_id").trigger('change')
+
+
+
+
+ return
diff --git a/app/assets/javascripts/tasks.js.coffee b/app/assets/javascripts/tasks.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/test.js.coffee b/app/assets/javascripts/test.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/user_admin.js.coffee b/app/assets/javascripts/user_admin.js.coffee
new file mode 100644
diff --git a/app/assets/javascripts/users.js.coffee b/app/assets/javascripts/users.js.coffee
new file mode 100644
diff --git a/app/assets/stylesheets/announcements.css.scss b/app/assets/stylesheets/announcements.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass
--- a/app/assets/stylesheets/application.css.sass
+++ b/app/assets/stylesheets/application.css.sass
@@ -1,19 +1,150 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any styles
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
+ * file per style scope.
+ *
+ // bootstrap says that we should not do this, but @import each file instead
+ # *= require_tree .
+ # *= require_self
+ */
+@import jquery.ui.all
@import jquery.ui.core
@import jquery.ui.theme
@import jquery.ui.datepicker
@import jquery.ui.slider
@import jquery-ui-timepicker-addon
@import jquery-tablesorter/theme.metro-dark
+@import jquery.countdown
@import tablesorter-theme.cafe
+//bootstrap
+@import bootstrap-sprockets
+@import bootstrap
+@import select2
+@import select2-bootstrap
+//@import bootstrap3-switch
+@import bootstrap-toggle
+@import bootstrap-sortable
+
+//bootstrap navbar color (from)
+$bgDefault : #19197b
+$bgHighlight : #06064b
+$colDefault : #8e8eb4
+$colHighlight : #ffffff
+$dropDown : false
+.navbar-default
+ background-color: $bgDefault
+ border-color: $bgHighlight
+ .navbar-brand
+ color: $colDefault
+ &:hover, &:focus
+ color: $colHighlight
+ .navbar-text
+ color: $colDefault
+ .navbar-nav
+ > li
+ > a
+ color: $colDefault
+ &:hover, &:focus
+ color: $colHighlight
+ @if $dropDown
+ > .dropdown-menu
+ background-color: $bgDefault
+ > li
+ > a
+ color: $colDefault
+ &:hover, &:focus
+ color: $colHighlight
+ background-color: $bgHighlight
+ > .divider
+ background-color: $bgHighlight
+ @if $dropDown
+ .open .dropdown-menu > .active
+ > a, > a:hover, > a:focus
+ color: $colHighlight
+ background-color: $bgHighlight
+ > .active
+ > a, > a:hover, > a:focus
+ color: $colHighlight
+ background-color: $bgHighlight
+ > .open
+ > a, > a:hover, > a:focus
+ color: $colHighlight
+ background-color: $bgHighlight
+ .navbar-toggle
+ border-color: $bgHighlight
+ &:hover, &:focus
+ background-color: $bgHighlight
+ .icon-bar
+ background-color: $colDefault
+ .navbar-collapse,
+ .navbar-form
+ border-color: $colDefault
+ .navbar-link
+ color: $colDefault
+ &:hover
+ color: $colHighlight
+@media (max-width: 767px)
+ .navbar-default .navbar-nav .open .dropdown-menu
+ > li > a
+ color: $colDefault
+ &:hover, &:focus
+ color: $colHighlight
+ > .active
+ > a, > a:hover, > a:focus
+ color: $colHighlight
+ background-color: $bgHighlight
+
+.secondnavbar
+ top: 50px
+
+
+// --------------- bootstrap file upload ----------------------
+.btn-file
+ position: relative
+ overflow: hidden
+
+.btn-file input[type=file]
+ position: absolute
+ top: 0
+ right: 0
+ min-width: 100%
+ min-height: 100%
+ font-size: 100px
+ text-align: right
+ filter: alpha(opacity=0)
+ opacity: 0
+ outline: none
+ background: white
+ cursor: inherit
+ display: block
+
body
background: white image-url("topbg.jpg") repeat-x top center
- font-size: 13px
- font-family: Tahoma, "sans-serif"
+ //font-size: 13px
+ //font-family: Tahoma, "sans-serif"
margin: 10px
padding: 10px
+ padding-top: 60px
+// ------------------ bootstrap sortable --------------------
+table.sortable th
+ padding-right: 20px !important
+ span.sign
+ right: -15px !important
+ &.text-right
+ padding-left: 20px !important
+ padding-right: 8px !important
+ &:after, span.sign
+ left: -15px !important
input
font-family: Tahoma, "sans-serif"
@@ -36,17 +167,17 @@
border-bottom: 1px solid #eeeeee
-a
- color: #6666cc
- text-decoration: none
-
- &:link, &:visited
- color: #6666cc
- text-decoration: none
-
- &:hover, &:focus
- color: #111166
- text-decoration: none
+//#a
+// color: #6666cc
+// text-decoration: none
+//
+// &:link, &:visited
+// color: #6666cc
+// text-decoration: none
+//
+// &:hover, &:focus
+// color: #111166
+// text-decoration: none
div
diff --git a/app/assets/stylesheets/configurations.css.scss b/app/assets/stylesheets/configurations.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/contest_management.css.scss b/app/assets/stylesheets/contest_management.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/contests.css.scss b/app/assets/stylesheets/contests.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/graders.css.scss b/app/assets/stylesheets/graders.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/heartbeat.css.scss b/app/assets/stylesheets/heartbeat.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/login.css.scss b/app/assets/stylesheets/login.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/main.css.scss b/app/assets/stylesheets/main.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/messages.css.scss b/app/assets/stylesheets/messages.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/problems.css.scss b/app/assets/stylesheets/problems.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/site.css.scss b/app/assets/stylesheets/site.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/sites.css.scss b/app/assets/stylesheets/sites.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/sources.css.scss b/app/assets/stylesheets/sources.css.scss
new file mode 100644
--- /dev/null
+++ b/app/assets/stylesheets/sources.css.scss
@@ -0,0 +1,4 @@
+// Place all the styles related to the sources controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
diff --git a/app/assets/stylesheets/tablesorter-theme.cafe.css b/app/assets/stylesheets/tablesorter-theme.cafe.css
--- a/app/assets/stylesheets/tablesorter-theme.cafe.css
+++ b/app/assets/stylesheets/tablesorter-theme.cafe.css
@@ -3,7 +3,7 @@
*************/
/* overall */
.tablesorter-cafe {
- // font: 12px/18px 'Segoe UI Semilight', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
+ /* font: 12px/18px 'Segoe UI Semilight', 'Open Sans', Verdana, Arial, Helvetica, sans-serif; */
color: #000;
background-color: #777;
margin: 10px 0 15px;
@@ -25,8 +25,10 @@
.tablesorter-cafe thead td,
.tablesorter-cafe tfoot th,
.tablesorter-cafe tfoot td {
+ /*
//font-weight: 300;
//font-size: 15px;
+ */
color: #fff;
background-color: #777;
padding: 2px;
diff --git a/app/assets/stylesheets/tasks.css.scss b/app/assets/stylesheets/tasks.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/test.css.scss b/app/assets/stylesheets/test.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/user_admin.css.scss b/app/assets/stylesheets/user_admin.css.scss
new file mode 100644
diff --git a/app/assets/stylesheets/users.css.scss b/app/assets/stylesheets/users.css.scss
new file mode 100644
diff --git a/app/controllers/announcements_controller.rb b/app/controllers/announcements_controller.rb
--- a/app/controllers/announcements_controller.rb
+++ b/app/controllers/announcements_controller.rb
@@ -69,14 +69,34 @@
if @announcement.update_attributes(params[:announcement])
flash[:notice] = 'Announcement was successfully updated.'
format.html { redirect_to(@announcement) }
+ format.js {}
format.xml { head :ok }
else
format.html { render :action => "edit" }
+ format.js {}
format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
end
end
end
+ def toggle
+ @announcement = Announcement.find(params[:id])
+ @announcement.update_attributes( published: !@announcement.published? )
+ respond_to do |format|
+ format.js { render partial: 'toggle_button',
+ locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
+ end
+ end
+
+ def toggle_front
+ @announcement = Announcement.find(params[:id])
+ @announcement.update_attributes( frontpage: !@announcement.frontpage? )
+ respond_to do |format|
+ format.js { render partial: 'toggle_button',
+ locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
+ end
+ end
+
# DELETE /announcements/1
# DELETE /announcements/1.xml
def destroy
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,9 +1,17 @@
class ApplicationController < ActionController::Base
protect_from_forgery
+ before_filter :current_user
+
SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
+ # Returns the current logged-in user (if any).
+ def current_user
+ return nil unless session[:user_id]
+ @current_user ||= User.find(session[:user_id])
+ end
+
def admin_authorization
return false unless authenticate
user = User.find(session[:user_id], :include => ['roles'])
@@ -39,12 +47,17 @@
# check if run in single user mode
if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
- user = User.find(session[:user_id])
+ user = User.find_by_id(session[:user_id])
if user==nil or (not user.admin?)
flash[:notice] = 'You cannot log in at this time'
redirect_to :controller => 'main', :action => 'login'
return false
end
+ unless user.enabled?
+ flash[:notice] = 'Your account is disabled'
+ redirect_to :controller => 'main', :action => 'login'
+ return false
+ end
return true
end
diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb
--- a/app/controllers/main_controller.rb
+++ b/app/controllers/main_controller.rb
@@ -69,6 +69,14 @@
@submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
@submission.source_filename = params['file'].original_filename
end
+
+ if (params[:editor_text])
+ language = Language.find_by_id(params[:language_id])
+ @submission.source = params[:editor_text]
+ @submission.source_filename = "live_edit.#{language.ext}"
+ @submission.language = language
+ end
+
@submission.submitted_at = Time.new.gmtime
@submission.ip_address = request.remote_ip
@@ -123,8 +131,8 @@
@problem = nil
@submissions = nil
else
- @problem = Problem.find_by_name(params[:id])
- if not @problem.available
+ @problem = Problem.find_by_id(params[:id])
+ if (@problem == nil) or (not @problem.available)
redirect_to :action => 'list'
flash[:notice] = 'Error: submissions for that problem are not viewable.'
return
diff --git a/app/controllers/problems_controller.rb b/app/controllers/problems_controller.rb
--- a/app/controllers/problems_controller.rb
+++ b/app/controllers/problems_controller.rb
@@ -7,8 +7,7 @@
in_place_edit_for :problem, :full_score
def index
- list
- render :action => 'list'
+ @problems = Problem.find(:all, :order => 'date_added DESC')
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
@@ -17,11 +16,7 @@
:do_manage,
:do_import,
:update ],
- :redirect_to => { :action => :list }
-
- def list
- @problems = Problem.find(:all, :order => 'date_added DESC')
- end
+ :redirect_to => { :action => :index }
def show
@problem = Problem.find(params[:id])
@@ -45,7 +40,7 @@
@problem.description = @description
if @problem.save
flash[:notice] = 'Problem was successfully created.'
- redirect_to :action => 'list'
+ redirect_to action: :index
else
render :action => 'new'
end
@@ -61,10 +56,10 @@
@problem.date_added = Time.new
if @problem.save
flash[:notice] = 'Problem was successfully created.'
- redirect_to :action => 'list'
+ redirect_to action: :index
else
flash[:notice] = 'Error saving problem'
- redirect_to :action => 'list'
+ redirect_to action: :index
end
end
@@ -121,13 +116,23 @@
def destroy
Problem.find(params[:id]).destroy
- redirect_to :action => 'list'
+ redirect_to action: :index
end
def toggle
@problem = Problem.find(params[:id])
- @problem.available = !(@problem.available)
- @problem.save
+ @problem.update_attributes(available: !(@problem.available) )
+ respond_to do |format|
+ format.js { }
+ end
+ end
+
+ def toggle_test
+ @problem = Problem.find(params[:id])
+ @problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
+ respond_to do |format|
+ format.js { }
+ end
end
def turn_all_off
@@ -136,7 +141,7 @@
problem.available = false
problem.save
end
- redirect_to :action => 'list'
+ redirect_to action: :index
end
def turn_all_on
@@ -145,7 +150,7 @@
problem.available = true
problem.save
end
- redirect_to :action => 'list'
+ redirect_to action: :index
end
def stat
diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb
--- a/app/controllers/report_controller.rb
+++ b/app/controllers/report_controller.rb
@@ -12,6 +12,36 @@
admin_authorization
}
+ def score
+ if params[:commit] == 'download csv'
+ @problems = Problem.all
+ else
+ @problems = Problem.find_available_problems
+ end
+ @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
+ @scorearray = Array.new
+ @users.each do |u|
+ ustat = Array.new
+ ustat[0] = u
+ @problems.each do |p|
+ sub = Submission.find_last_by_user_and_problem(u.id,p.id)
+ if (sub!=nil) and (sub.points!=nil) and p and p.full_score
+ ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
+ else
+ ustat << [0,false]
+ end
+ end
+ @scorearray << ustat
+ end
+ if params[:commit] == 'download csv' then
+ csv = gen_csv_from_scorearray(@scorearray,@problems)
+ send_data csv, filename: 'last_score.csv'
+ else
+ render template: 'user_admin/user_stat'
+ end
+
+ end
+
def login_stat
@logins = Array.new
@@ -73,12 +103,7 @@
Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
if @submissions[s.user_id]
if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
- a = nil
- begin
- a = Problem.find(s.problem_id)
- rescue
- a = nil
- end
+ a = Problem.find_by_id(s.problem_id)
@submissions[s.user_id][:sub][s.problem_id] =
{ prob_name: (a ? a.full_name : '(NULL)'),
sub_ids: [s.id] }
diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb
new file mode 100644
--- /dev/null
+++ b/app/controllers/sources_controller.rb
@@ -0,0 +1,27 @@
+class SourcesController < ApplicationController
+ before_filter :authenticate
+
+ def direct_edit
+ @problem = Problem.find(params[:pid])
+ @source = ''
+ end
+
+ def direct_edit_submission
+ @submission = Submission.find(params[:sid])
+ @source = @submission.source.to_s
+ @problem = @submission.problem
+ @lang_id = @submission.language.id
+ render 'direct_edit'
+ end
+
+ def get_latest_submission_status
+ @problem = Problem.find(params[:pid])
+ @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
+ puts User.find(params[:uid]).login
+ puts Problem.find(params[:pid]).name
+ puts 'nil' unless @submission
+ respond_to do |format|
+ format.js
+ end
+ end
+end
diff --git a/app/controllers/user_admin_controller.rb b/app/controllers/user_admin_controller.rb
--- a/app/controllers/user_admin_controller.rb
+++ b/app/controllers/user_admin_controller.rb
@@ -17,7 +17,6 @@
def index
list
- render :action => 'list'
end
def list
@@ -56,7 +55,7 @@
@user.activated = true
if @user.save
flash[:notice] = 'User was successfully created.'
- redirect_to :action => 'list'
+ redirect_to :action => 'index'
else
render :action => 'new'
end
@@ -66,7 +65,7 @@
@user = User.find(params[:id])
@user.last_ip = nil
@user.save
- redirect_to action: 'list', page: params[:page]
+ redirect_to action: 'index', page: params[:page]
end
def create_from_list
@@ -114,7 +113,7 @@
flash[:notice] = 'User(s) ' + note.join(', ') +
' were successfully created. ' +
'( (+) - created with random passwords.)'
- redirect_to :action => 'list'
+ redirect_to :action => 'index'
end
def edit
@@ -133,7 +132,7 @@
def destroy
User.find(params[:id]).destroy
- redirect_to :action => 'list'
+ redirect_to :action => 'index'
end
def user_stat
@@ -200,7 +199,7 @@
def import
if params[:file]==''
flash[:notice] = 'Error importing no file'
- redirect_to :action => 'list' and return
+ redirect_to :action => 'index' and return
end
import_from_file(params[:file])
end
@@ -253,7 +252,7 @@
if user and contest
user.contests << contest
end
- redirect_to :action => 'list'
+ redirect_to :action => 'index'
end
def remove_from_contest
@@ -262,7 +261,7 @@
if user and contest
user.contests.delete(contest)
end
- redirect_to :action => 'list'
+ redirect_to :action => 'index'
end
def contest_management
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -133,6 +133,24 @@
problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
end
+ def toggle_activate
+ @user = User.find(params[:id])
+ @user.update_attributes( activated: !@user.activated? )
+ respond_to do |format|
+ format.js { render partial: 'toggle_button',
+ locals: {button_id: "#toggle_activate_user_#{@user.id}",button_on: @user.activated? } }
+ end
+ end
+
+ def toggle_enable
+ @user = User.find(params[:id])
+ @user.update_attributes( enabled: !@user.enabled? )
+ respond_to do |format|
+ format.js { render partial: 'toggle_button',
+ locals: {button_id: "#toggle_enable_user_#{@user.id}",button_on: @user.enabled? } }
+ end
+ end
+
protected
def verify_online_registration
@@ -192,4 +210,5 @@
admin_authorization
end
+
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,6 +1,38 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
+ def navbar_user_header
+ left_menu = ''
+ right_menu = ''
+ user = User.find(session[:user_id])
+
+ if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
+ left_menu << add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
+ left_menu << add_menu("#{I18n.t 'menu.submissions'}", 'main', 'submission')
+ left_menu << add_menu("#{I18n.t 'menu.test'}", 'test', 'index')
+ end
+
+ if GraderConfiguration['right.user_hall_of_fame']
+ left_menu << add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
+ end
+
+ right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
+ right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
+ if GraderConfiguration['system.user_setting_enabled']
+ right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
+ end
+ right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
+
+
+ result = content_tag(:ul,left_menu.html_safe,class: 'nav navbar-nav') + content_tag(:ul,right_menu.html_safe,class: 'nav navbar-nav navbar-right')
+ end
+
+ def add_menu(title, controller, action,html_option = {})
+ link_option = {controller: controller, action: action}
+ html_option[:class] = (html_option[:class] || '') + " active" if current_page?(link_option)
+ content_tag(:li, link_to(title,link_option),html_option)
+ end
+
def user_header
menu_items = ''
user = User.find(session[:user_id])
@@ -75,6 +107,34 @@
end
end
+ def toggle_button(on,toggle_url,id, option={})
+ btn_size = option[:size] || 'btn-xs'
+ link_to (on ? "Yes" : "No"), toggle_url,
+ {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
+ id: id,
+ data: {remote: true, method: 'get'}}
+ end
+
+ def get_ace_mode(language)
+ # return ace mode string from Language
+
+ case language.pretty_name
+ when 'Pascal'
+ 'ace/mode/pascal'
+ when 'C++','C'
+ 'ace/mode/c_cpp'
+ when 'Ruby'
+ 'ace/mode/ruby'
+ when 'Python'
+ 'ace/mode/python'
+ when 'Java'
+ 'ace/mode/java'
+ else
+ 'ace/mode/c_cpp'
+ end
+ end
+
+
def user_title_bar(user)
header = ''
time_left = ''
diff --git a/app/helpers/sources_helper.rb b/app/helpers/sources_helper.rb
new file mode 100644
--- /dev/null
+++ b/app/helpers/sources_helper.rb
@@ -0,0 +1,2 @@
+module SourcesHelper
+end
diff --git a/app/models/problem.rb b/app/models/problem.rb
--- a/app/models/problem.rb
+++ b/app/models/problem.rb
@@ -61,6 +61,10 @@
result[:total_sub] = Submission.where(problem_id: self.id).count
result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
end
+
+ def long_name
+ "[#{name}] #{full_name}"
+ end
protected
diff --git a/app/models/user.rb b/app/models/user.rb
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -239,7 +239,7 @@
def update_start_time
stat = self.contest_stat
- if stat == nil or stat.started_at == nil
+ if (stat.nil?) or (stat.started_at.nil?)
stat ||= UserContestStat.new(:user => self)
stat.started_at = Time.now.gmtime
stat.save
diff --git a/app/views/announcements/index.html.erb b/app/views/announcements/index.html.erb
deleted file mode 100644
--- a/app/views/announcements/index.html.erb
+++ /dev/null
@@ -1,40 +0,0 @@
-
Listing announcements
-
-<%= link_to 'New announcement', new_announcement_path %>
-
-
-
- Updated
- Announcement
- Author
- Published
-
-
-
-
-
-<% for announcement in @announcements %>
-
- <% @announcement = announcement %>
- <%= time_ago_in_words announcement.updated_at %>
-
- <% if !announcement.title.blank? %>
- Title: <%=h announcement.title %>
- <% end %>
- <% if !announcement.notes.blank? %>
- Notes: <%=h announcement.notes %>
- <% end %>
- <%=h announcement.body %>
-
- <%=h announcement.author %>
- <%= in_place_editor_field :announcement, :published, {}, :rows => 1 %>
- <%= link_to 'Show', announcement %>
- <%= link_to 'Edit', edit_announcement_path(announcement) %>
- <%= link_to 'Destroy', announcement, :confirm => 'Are you sure?', :method => :delete %>
-
-<% end %>
-
-
-
-
-<%= link_to 'New announcement', new_announcement_path %>
diff --git a/app/views/announcements/index.html.haml b/app/views/announcements/index.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/announcements/index.html.haml
@@ -0,0 +1,37 @@
+%h1 Listing announcements
+
+= link_to '+ Add announcement', new_announcement_path, class: 'btn btn-success'
+%br
+%br
+
+%table.table.table-striped
+ %thead
+ %th Updated
+ %th Announcement
+ %th Author
+ %th{style: 'width: 100px'} Published?
+ %th{style: 'width: 100px'}Front?
+ %th
+ %th
+ - for announcement in @announcements
+ %tr
+ - @announcement = announcement
+ %td= time_ago_in_words announcement.updated_at
+ %td
+ - if !announcement.title.blank?
+ %b Title:
+ = h announcement.title
+ %br/
+ - if !announcement.notes.blank?
+ %b
+ Notes: #{h announcement.notes}
+ %br/
+ = h announcement.body
+ %td= h announcement.author
+ %td= toggle_button(announcement.published?, toggle_announcement_url(@announcement), "announcement_toggle_#{@announcement.id}", {size: 'btn-sm'})
+ %td= toggle_button(announcement.frontpage?, toggle_front_announcement_url(@announcement), "announcement_toggle_front_#{@announcement.id}", {size: 'btn-sm'})
+ %td= link_to 'Edit', edit_announcement_path(announcement), class: 'btn btn-block btn-sm btn-info'
+ %td= link_to 'Destroy', announcement, :confirm => 'Are you sure?', :method => :delete, class: "btn btn-block btn-sm btn-danger"
+%br
+
+= link_to '+ Add announcement', new_announcement_path, class: 'btn btn-success'
diff --git a/app/views/application/_submission_short.html.haml b/app/views/application/_submission_short.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/application/_submission_short.html.haml
@@ -0,0 +1,26 @@
+
+- if submission.nil?
+ = "-"
+- else
+ - if submission.graded_at.nil?
+ =t 'main.submitted_at'
+ = format_short_time(submission.submitted_at.localtime)
+ - else
+ = t 'main.graded_at'
+ = "#{format_short_time(submission.graded_at.localtime)}, "
+ - if GraderConfiguration['ui.show_score']
+ = t 'main.score'
+ = "#{(submission.points*100/submission.problem.full_score).to_i} "
+ = " ["
+ %tt
+ = submission.grader_comment
+ = "]"
+ - if GraderConfiguration.show_grading_result
+ = " | "
+ = link_to '[detailed result]', :action => 'result', :id => submission.id
+ = " | "
+ = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
+ = " | "
+ = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
+ //= " | "
+ //= link_to "[#{t 'main.submissions_link'}]", main_submission_path(submission.problem.id)
diff --git a/app/views/application/_toggle_button.js.haml b/app/views/application/_toggle_button.js.haml
new file mode 100644
--- /dev/null
+++ b/app/views/application/_toggle_button.js.haml
@@ -0,0 +1,7 @@
+:plain
+ var t = $("#{button_id}");
+ t.removeClass('btn-default');
+ t.removeClass('btn-success');
+ t.removeClass('btn-warning');
+ t.addClass("btn-#{button_on ? 'success' : 'default'}");
+ t.text("#{button_on ? 'Yes' : 'No'}");
diff --git a/app/views/configurations/index.html.haml b/app/views/configurations/index.html.haml
--- a/app/views/configurations/index.html.haml
+++ b/app/views/configurations/index.html.haml
@@ -1,5 +1,5 @@
-- content_for :header do
- = javascript_include_tag 'local_jquery'
+/- content_for :header do
+/ = javascript_include_tag 'local_jquery'
%h1 System configuration
@@ -13,9 +13,11 @@
- @grader_configuration = conf
%tr{:class => cycle("info-odd", "info-even")}
%td
- = in_place_editor_field :grader_configuration, :key, {}, :rows=>1
+ /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1
+ = @grader_configuration.key
%td
- = in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1
+ /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1
+ = @grader_configuration.value_type
%td
= best_in_place @grader_configuration, :value, ok_button: "ok", cancel_button: "cancel"
%td= conf.description
diff --git a/app/views/graders/_grader.html.haml b/app/views/graders/_grader.html.haml
--- a/app/views/graders/_grader.html.haml
+++ b/app/views/graders/_grader.html.haml
@@ -2,10 +2,10 @@
%td= grader.host
%td= grader.pid
%td= grader.mode
-%td= grader.updated_at.strftime("%H:%M:%S") if grader.updated_at!=nil
+%td= grader.updated_at.strftime("%H:%M:%S") unless grader.updated_at.nil?
%td= grader.task_type
%td
- - if grader.task_id==nil
+ - if grader.task_id.nil?
idle
- else
= link_to "#{grader.task_id}", :action => 'view', :id => grader.task_id, :type => grader.task_type
diff --git a/app/views/graders/_grader_list.html.haml b/app/views/graders/_grader_list.html.haml
--- a/app/views/graders/_grader_list.html.haml
+++ b/app/views/graders/_grader_list.html.haml
@@ -1,5 +1,5 @@
- if grader_list.length!=0
- %table.graders
+ %table.table.table-striped.table-condensed
%tr
%th host
%th pid
@@ -7,6 +7,7 @@
%th last updated
%th type
%th task
+ %th
- grader_list.each do |grader|
- if grader.active
- c = 'active'
@@ -16,9 +17,9 @@
= render :partial => 'grader', :locals => {:grader => grader}
- if not grader.terminated
- if GraderScript.grader_control_enabled?
- %td= link_to 'stop', {:action => 'stop', :id => grader}
+ %td= link_to 'stop', {:action => 'stop', :id => grader}, class: 'btn btn-danger btn-xs btn-block'
- else
- %td= link_to 'clear', {:action => 'clear', :id => grader}
+ %td= link_to 'clear', {:action => 'clear', :id => grader}, class: 'btn btn-danger btn-xs btn-block'
- else
%ul
%li None
diff --git a/app/views/graders/list.html.haml b/app/views/graders/list.html.haml
--- a/app/views/graders/list.html.haml
+++ b/app/views/graders/list.html.haml
@@ -1,12 +1,19 @@
- content_for :head do
- = stylesheet_link_tag 'graders'
- = javascript_include_tag 'local_jquery'
%h1 Grader information
-= link_to '[Refresh]', :action => 'list'
-%br/
+%p
+ = link_to 'Refresh', { :action => 'list' }, class: 'btn btn-info'
+
+.panel.panel-primary
+ .panel-heading
+ Grader control:
+ .panel-body
+ =link_to 'Start Graders in grading env', { action: 'start_grading'}, class: 'btn btn-default', method: 'post'
+ =link_to 'Start Graders in exam env', { action: 'start_exam'}, class: 'btn btn-default', method: 'post'
+ =link_to 'Stop all running Graders', { action: 'stop_all'}, class: 'btn btn-default', method: 'post'
+ =link_to 'Clear all data', { action: 'clear_all'}, class: 'btn btn-default', method: 'post'
.submitbox
.item
@@ -25,49 +32,50 @@
= submit_tag 'Clear all data'
%br{:style => 'clear:both'}/
-%div{style: 'width:500px; float: left;'}
- - if @last_task
- Last task:
- = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
+.row
+ .col-md-6
+ - if @last_task
+ Last task:
+ = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
- %br/
+ %br/
- - if @last_test_request
- Last test_request:
- = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
+ - if @last_test_request
+ Last test_request:
+ = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
- %h2 Current graders
+ %h2 Current graders
- = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
+ = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
- %h2 Stalled graders
+ %h2 Stalled graders
- = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
+ = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
- %h2 Terminated graders
+ %h2 Terminated graders
- = form_for :clear, :url => {:action => 'clear_terminated'} do |f|
- = submit_tag 'Clear data for terminated graders'
+ %p= link_to 'Clear data for terminated graders', { action: 'clear_terminated'}, class: 'btn btn-default', method: 'post'
- = render :partial => 'grader_list', :locals => {:grader_list => @terminated_processes}
-%div{}
- %h2 Last 20 submissions
- %table.graders
- %thead
- %th ID
- %th User
- %th Problem
- %th Submitted
- %th Graded
- %th Result
- %tbody
- - @submission.each do |sub|
- %tr.inactive
- %td= link_to sub.id, controller: 'graders' ,action: 'submission', id: sub.id
- %td= sub.try(:user).try(:full_name)
- %td= sub.try(:problem).try(:full_name)
- %td= "#{time_ago_in_words(sub.submitted_at)} ago"
- %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
- %td= sub.grader_comment
+ = render :partial => 'grader_list', :locals => {:grader_list => @terminated_processes}
+ .col-md-6
+ %h2 Last 20 submissions
+ %table.table.table-striped.table-condensed
+ %thead
+ %th ID
+ %th User
+ %th Problem
+ %th Submitted
+ %th Graded
+ %th Result
+ %th
+ %tbody
+ - @submission.each do |sub|
+ %tr.inactive
+ %td= link_to sub.id, controller: 'graders' ,action: 'submission', id: sub.id
+ %td= sub.try(:user).try(:full_name)
+ %td= sub.try(:problem).try(:full_name)
+ %td= "#{time_ago_in_words(sub.submitted_at)} ago"
+ %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
+ %td= sub.grader_comment
diff --git a/app/views/graders/submission.html.haml b/app/views/graders/submission.html.haml
--- a/app/views/graders/submission.html.haml
+++ b/app/views/graders/submission.html.haml
@@ -1,67 +1,90 @@
-%style{type: "text/css"}
- = @css_style
-:css
- .field {
- font-weight: bold;
- text-align: right;
- padding: 3px;
- }
-
+//%style{type: "text/css"}
+// = @css_style
%h1= "Submission: #{@submission.id}"
-
-%h2 Stat
+%textarea#data{style: "display:none;"}
+ :preserve
+ #{@submission.source}
-%table.info
- %thead
- %tr.info-head
- %th Field
- %th Value
- %tbody
- %tr{class: cycle('info-even','info-odd')}
- %td.field User:
- %td.value
- - if @submission.user
- = link_to "(#{@submission.user.login})", controller: "users", action: "profile", id: @submission.user
- = @submission.user.full_name
- - else
- = "(n/a)"
- %tr{class: cycle('info-even','info-odd')}
- %td.field Problem:
- %td.value
- - if @submission.problem!=nil
- = link_to "(#{@submission.problem.name})", controller: "problems", action: "stat", id: @submission.problem
- = @submission.problem.full_name
- - else
- = "(n/a)"
- %tr{class: cycle('info-even','info-odd')}
- %td.field Tries:
- %td.value= @submission.number
- %tr{class: cycle('info-even','info-odd')}
- %td.field Submitted:
- %td.value #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
- %tr{class: cycle('info-even','info-odd')}
- %td.field Graded:
- %td.value #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
- %tr{class: cycle('info-even','info-odd')}
- %td.field Points:
- %td.value #{@submission.points}/#{@submission.problem.full_score}
- %tr{class: cycle('info-even','info-odd')}
- %td.field Comment:
- %td.value #{@submission.grader_comment}
- %tr{class: cycle('info-even','info-odd')}
- %td.field Runtime (s):
- %td.value #{@submission.max_runtime}
- %tr{class: cycle('info-even','info-odd')}
- %td.field Memory (kb):
- %td.value #{@submission.peak_memory}
- - if session[:admin]
- %tr{class: cycle('info-even','info-odd')}
- %td.field IP:
- %td.value #{@submission.ip_address}
+//%div.highlight{:style => "border: 1px solid black;"}
+//=@formatted_code.html_safe
+.containter
+ .row
+ .col-md-7
+ %h2 Source Code
+ .col-md-5
+ %h2 Stat
+ .row
+ .col-md-7
+ %div#editor{ style: "font-size: 14px; height: 400px; border-radius:5px;" }
+ :javascript
+ e = ace.edit("editor")
+ e.setOptions({ maxLines: Infinity })
+ e.setValue($("#data").text())
+ e.gotoLine(1)
+ e.getSession().setMode("#{get_ace_mode(@submission.language)}")
+ e.setReadOnly(true)
+ .col-md-5
+ %table.table.table-striped
+ %tr
+ %td.text-right
+ %strong User
+ %td
+ - if @submission.user
+ = link_to "(#{@submission.user.login})", controller: "users", action: "profile", id: @submission.user
+ = @submission.user.full_name
+ - else
+ = "(n/a)"
+ %tr
+ %td.text-right
+ %strong Task
+ %td
+ - if @submission.problem!=nil
+ = link_to "(#{@submission.problem.name})", controller: "problems", action: "stat", id: @submission.problem
+ = @submission.problem.full_name
+ - else
+ = "(n/a)"
+ %tr
+ %td.text-right
+ %strong Tries
+ %td= @submission.number
+ %tr
+ %td.text-right
+ %strong Language
+ %td= @submission.language.pretty_name
+ %tr
+ %td.text-right
+ %strong Submitted
+ %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
+ %tr
+ %td.text-right
+ %strong Graded
+ - if @submission.graded_at
+ %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
+ - else
+ %td -
+ %tr
+ %td.text-right
+ %strong Points
+ %td #{@submission.points}/#{@submission.problem.full_score}
+ %tr
+ %td.text-right
+ %strong Comment
+ %td #{@submission.grader_comment}
+ %tr
+ %td.text-right
+ %strong Runtime (s)
+ %td #{@submission.max_runtime}
+ %tr
+ %td.text-right
+ %strong Memory (kb)
+ %td #{@submission.peak_memory}
+ - if session[:admin]
+ %tr
+ %td.text-right
+ %strong IP
+ %td #{@submission.ip_address}
-%h2 Source code
-//%div.highlight{:style => "border: 1px solid black;"}
-=@formatted_code.html_safe
+
diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/layouts/_header.html.haml
@@ -0,0 +1,84 @@
+%header.navbar.navbar-default.navbar-fixed-top
+ %nav
+ .container-fluid
+ .navbar-header
+ %a.navbar-brand{href: main_list_path}
+ %span.glyphicon.glyphicon-home
+ MAIN
+ .collapse.navbar-collapse
+ %ul.nav.navbar-nav
+ - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
+ //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
+ %li.dropdown
+ %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
+ = "#{I18n.t 'menu.submissions'}"
+ %span.caret
+ %ul.dropdown-menu
+ = add_menu("View", 'main', 'submission')
+ = add_menu("Self Test", 'test', 'index')
+ - if GraderConfiguration['right.user_hall_of_fame']
+ = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
+ / display MODE button (with countdown in contest mode)
+ - if GraderConfiguration.analysis_mode?
+ %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
+ - elsif GraderConfiguration.time_limit_mode?
+ - if @current_user.contest_finished?
+ %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
+ - elsif !@current_user.contest_started?
+ %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
+ - else
+ %div.navbar-btn.btn.btn-primary#countdown asdf
+ :javascript
+ $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
+ / admin section
+ - if (@current_user!=nil) and (session[:admin])
+ %li.dropdown
+ %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
+ Manage
+ %span.caret
+ %ul.dropdown-menu
+ = add_menu( 'Announcements', 'announcements', 'index')
+ = add_menu( 'Problems', 'problems', 'index')
+ = add_menu( 'Users', 'user_admin', 'index')
+ = add_menu( 'Graders', 'graders', 'list')
+ = add_menu( 'Message ', 'messages', 'console')
+ %li.divider{role: 'separator'}
+ = add_menu( 'System config', 'configurations', 'index')
+ %li.divider{role: 'separator'}
+ = add_menu( 'Sites', 'sites', 'index')
+ = add_menu( 'Contests', 'contest_management', 'index')
+ %li.dropdown
+ %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
+ Report
+ %span.caret
+ %ul.dropdown-menu
+ = add_menu( 'Results', 'user_admin', 'user_stat')
+ = add_menu( 'Report', 'report', 'multiple_login')
+ - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
+ =link_to "#{ungraded} backlogs!",
+ grader_list_path,
+ class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
+
+ %ul.nav.navbar-nav.navbar-right
+ = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
+ = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
+ - if GraderConfiguration['system.user_setting_enabled']
+ = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
+ = 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'}})
+
+/
+ - if (@current_user!=nil) and (session[:admin])
+ %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
+ .container-fluid
+ .collapse.navbar-collapse
+ %ul.nav.navbar-nav
+ = add_menu( '[Announcements]', 'announcements', 'index')
+ = add_menu( '[Msg console]', 'messages', 'console')
+ = add_menu( '[Problems]', 'problems', 'index')
+ = add_menu( '[Users]', 'user_admin', 'index')
+ = add_menu( '[Results]', 'user_admin', 'user_stat')
+ = add_menu( '[Report]', 'report', 'multiple_login')
+ = add_menu( '[Graders]', 'graders', 'list')
+ = add_menu( '[Contests]', 'contest_management', 'index')
+ = add_menu( '[Sites]', 'sites', 'index')
+ = add_menu( '[System config]', 'configurations', 'index')
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
deleted file mode 100644
--- a/app/views/layouts/application.html.erb
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- <%= GraderConfiguration['contest.name'] %>
- <%= stylesheet_link_tag "application", :media => "all" %>
- <%= javascript_include_tag "application" %>
- <%= csrf_meta_tags %>
- <%= content_for :header %>
- <%= yield :head %>
-
-
-
-
-
-<%= user_header %>
-
-
-<%= content_tag(:p,flash[:notice],:style => "color:green") if flash[:notice]!=nil %>
-
-<%= yield %>
-
-
-
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/layouts/application.html.haml
@@ -0,0 +1,15 @@
+
+%html
+%head
+ %title= GraderConfiguration['contest.name']
+ = stylesheet_link_tag "application", params[:controller], :media => "all"
+ = javascript_include_tag "application", params[:controller]
+ = csrf_meta_tags
+ = content_for :header
+ = yield :head
+
+%body
+ = render 'layouts/header'
+
+ = content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
+ = yield
diff --git a/app/views/main/_announcement.html.haml b/app/views/main/_announcement.html.haml
--- a/app/views/main/_announcement.html.haml
+++ b/app/views/main/_announcement.html.haml
@@ -1,19 +1,13 @@
-.announcement{:id => "announcement-#{announcement.id}", :style => "#{'display: none; opacity: 0' if (defined? announcement_effect) and announcement_effect }"}
- %div
- .announcement-title
- -# .toggles
- -# %a{:href => '#', :onclick => "$(\"announcement-body-#{announcement.id}\").blindUp({duration: 0.2}); return false;"}
- -# [hide]
- -# %a{:href => '#', :onclick => "$(\"announcement-body-#{announcement.id}\").blindDown({duration: 0.2}); return false;"}
- -# [show]
- = announcement.title
- .announcement-body{:id => "announcement-body-#{announcement.id}"}
- = markdown(announcement.body)
- -#.pub-info
- -# %p= "#{announcement.author}, #{announcement.created_at}"
+%li.list-group-item
+ %strong
+ = announcement.title
+ %small= "(updated #{time_ago_in_words(announcement.updated_at)} ago on #{announcement.updated_at})"
+
+ %br
+ = markdown(announcement.body)
+ :javascript
+ Announcement.updateRecentId(#{announcement.id});
+ - if (defined? announcement_effect) and announcement_effect
:javascript
- Announcement.updateRecentId(#{announcement.id});
- - if (defined? announcement_effect) and announcement_effect
- :javascript
- $("announcement-#{announcement.id}").blindDown({duration: 0.2});
- $("announcement-#{announcement.id}").appear({duration: 0.5, queue: 'end'});
+ $("announcement-#{announcement.id}").blindDown({duration: 0.2});
+ $("announcement-#{announcement.id}").appear({duration: 0.5, queue: 'end'});
diff --git a/app/views/main/_problem.html.erb b/app/views/main/_problem.html.erb
deleted file mode 100644
--- a/app/views/main/_problem.html.erb
+++ /dev/null
@@ -1,21 +0,0 @@
-">
-
- <%= "#{problem_counter+1}" %>
-
-
- <%= "#{problem.name}"%>
-
-
- <%= "#{problem.full_name}" %>
- <%= link_to_description_if_any "[#{t 'main.problem_desc'}]", problem %>
-
-
- <%= @prob_submissions[problem.id][:count] %>
-
-
- <%= render :partial => 'submission_short',
- :locals => {
- :submission => @prob_submissions[problem.id][:submission],
- :problem_name => problem.name }%>
-
-
diff --git a/app/views/main/_problem.html.haml b/app/views/main/_problem.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/main/_problem.html.haml
@@ -0,0 +1,17 @@
+%tr
+ %td
+ = "#{problem.name}"
+ %td
+ = "#{problem.full_name}"
+ = link_to_description_if_any "[#{t 'main.problem_desc'}] ".html_safe, problem
+ %td
+ = @prob_submissions[problem.id][:count]
+ = link_to "[subs]", main_submission_path(problem.id)
+ %td
+ = render :partial => 'submission_short',
+ :locals => {:submission => @prob_submissions[problem.id][:submission], :problem_name => problem.name }
+ %td
+ - if @prob_submissions[problem.id][:submission]
+ = link_to 'Edit', direct_edit_submission_path(@prob_submissions[problem.id][:submission]), class: 'btn btn-success'
+ - else
+ = link_to 'New', direct_edit_path(problem.id), class: 'btn btn-success'
diff --git a/app/views/main/_submission.html.haml b/app/views/main/_submission.html.haml
--- a/app/views/main/_submission.html.haml
+++ b/app/views/main/_submission.html.haml
@@ -1,18 +1,18 @@
-%tr{:class => ((submission_counter%2==0) ? "info-even" : "info-odd")}
- %td.info{:align => "center"}
+%tr
+ %td{:align => "center"}
= submission_counter+1
- %td.info{:align => "center"}
+ %td{:align => "center"}
= link_to "##{submission.id}", controller: :graders, action: :submission, id: submission.id
- %td.info
+ %td
= l submission.submitted_at, format: :long
= "( #{time_ago_in_words(submission.submitted_at)} ago)"
- %td.info{:align => "center"}
+ %td
= submission.source_filename
= " (#{submission.language.pretty_name}) "
= link_to('[load]',{:action => 'source', :id => submission.id})
- %td.info
- - if submission.graded_at!=nil
+ %td
+ - if submission.graded_at
= "Graded at #{format_short_time(submission.graded_at)}."
%br/
= "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
@@ -20,5 +20,7 @@
%tt
= submission.grader_comment
= "]"
- %td.info
+ %td
= render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
+ %td
+ = link_to 'Edit', direct_edit_submission_path(submission.id), class: 'btn btn-success'
diff --git a/app/views/main/_submission_box.html.erb b/app/views/main/_submission_box.html.erb
deleted file mode 100644
--- a/app/views/main/_submission_box.html.erb
+++ /dev/null
@@ -1,8 +0,0 @@
-<%= form_tag({:action => 'submit'}, :multipart => true) do %>
-Problem: <%= select 'submission', 'problem_id',
- [[(t 'main.specified_in_header'),'-1']] +
- @problems.collect {|p| [p.full_name, p.id]},
- :selected => '-1' %>
-File: <%= file_field_tag 'file' %>
-<%= submit_tag 'Submit' %>
-<% end %>
diff --git a/app/views/main/_submission_box.html.haml b/app/views/main/_submission_box.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/main/_submission_box.html.haml
@@ -0,0 +1,20 @@
+= form_tag({:action => 'submit'}, :multipart => true, class: 'form') do
+ - if @submission and @submission.errors.any?
+ #error_explanation
+ .alert.alert-danger
+ %h3= "#{pluralize(@submission.errors.count, "error")} prohibited this user from being saved:"
+ %ul
+ - @submission.errors.full_messages.each do |msg|
+ %li= msg
+ .form-group
+ = label_tag :submission, 'Problem:'
+ = select 'submission', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control' }
+ .form-group
+ = label_tag :file, 'File:'
+ .input-group
+ %span.input-group-btn
+ %span.btn.btn-default.btn-file
+ Browse
+ = file_field_tag 'file'
+ = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
+ = submit_tag 'Submit', class: 'btn btn-default'
diff --git a/app/views/main/_submission_short.html.haml b/app/views/main/_submission_short.html.haml
--- a/app/views/main/_submission_short.html.haml
+++ b/app/views/main/_submission_short.html.haml
@@ -1,8 +1,8 @@
-- if submission==nil
+- if submission.nil?
= "-"
- else
- - if submission.graded_at==nil
+ - if submission.graded_at.nil?
=t 'main.submitted_at'
= format_short_time(submission.submitted_at.localtime)
- else
@@ -22,5 +22,5 @@
= link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
= " | "
= link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
- = " | "
- = link_to "[#{t 'main.submissions_link'}]", :action => 'submission', :id => problem_name
+ //= " | "
+ //= link_to "[#{t 'main.submissions_link'}]", main_submission_path(submission.problem.id)
diff --git a/app/views/main/list.html.haml b/app/views/main/list.html.haml
--- a/app/views/main/list.html.haml
+++ b/app/views/main/list.html.haml
@@ -3,49 +3,48 @@
= user_title_bar(@user)
-.announcementbox{:style => (@announcements.length==0 ? "display:none" : "")}
- %span{:class => 'title'}
- Announcements
- #announcementbox-body
- = render :partial => 'announcement', :collection => @announcements
-
-- if GraderConfiguration.show_submitbox_to?(@user)
- .submitbox
- = error_messages_for 'submission'
- = render :partial => 'submission_box'
-
-
-%hr/
-
- if (GraderConfiguration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
%p=t 'main.start_soon'
-- if GraderConfiguration.show_tasks_to?(@user)
- - if not GraderConfiguration.multicontests?
- %table.info
- %tr.info-head
- %th
- %th Tasks name
- %th Full name
- %th # of sub(s)
- %th Results
- = render :partial => 'problem', :collection => @problems
- - else
- - @contest_problems.each do |cp|
- - if cp[:problems].length > 0
- %h2{:class =>'contest-title'}
- = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
- %table.info
- %tr.info-head
- %th
- %th Tasks name
- %th Full name
- %th # of sub(s)
- %th Results
- = render :partial => 'problem', :collection => cp[:problems]
-
-
-%hr/
+.row
+ .col-md-7
+ - if GraderConfiguration.show_submitbox_to?(@user)
+ .panel.panel-primary
+ .panel-heading
+ Submission
+ .panel-body
+ = render :partial => 'submission_box'
+ - if GraderConfiguration.show_tasks_to?(@user)
+ - if not GraderConfiguration.multicontests?
+ %table.table.table-striped.table-condensed
+ %thead
+ %tr
+ %th Task name
+ %th Full name
+ %th # of sub(s)
+ %th Results
+ %th
+ %tbody
+ = render :partial => 'problem', :collection => @problems
+ - else
+ - @contest_problems.each do |cp|
+ - if cp[:problems].length > 0
+ %h2{:class =>'contest-title'}
+ = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
+ %table.info
+ %tr.info-head
+ %th Task name
+ %th Full name
+ %th # of sub(s)
+ %th Results
+ %th
+ = render :partial => 'problem', :collection => cp[:problems]
+ .col-md-5
+ .panel.panel-info
+ .panel-heading
+ Announcement
+ %ul.list-group
+ = render :partial => 'announcement', :collection => @announcements
%script{:type => 'text/javascript'}
= "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
diff --git a/app/views/main/submission.html.haml b/app/views/main/submission.html.haml
--- a/app/views/main/submission.html.haml
+++ b/app/views/main/submission.html.haml
@@ -1,25 +1,31 @@
= user_title_bar(@user)
-.task-menu
- Task List
- %br/
- - @problems.each do |problem|
- = link_to problem.name, :action => 'submission', :id => problem.name
+.panel.panel-info
+ .panel-heading
+ Select Problems
+ .panel-body
+ .form-inline
+ = select 'submission',
+ 'problem_id',
+ @problems.collect {|p| ["[#{p.name}] #{p.full_name}", main_submission_url(p.id)]},
+ { selected: (@problem ? main_submission_url(@problem) : -1) },
+ { class: 'select2 form-control'}
+ %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: '#submission_problem_id'}} Go
- if @problem!=nil
%h2= "Task: #{@problem.full_name} (#{@problem.name})"
- if @submissions!=nil
- if @submissions.length>0
- %table.info
- %tr.info-head
- %th.info No.
- %th.info #
- %th.info At
- %th.info Source
- %th.info Result
- %th.info{:width => "300px"}
- Compiler message
+ %table.table
+ %thead
+ %th No.
+ %th #
+ %th At
+ %th Source
+ %th Result
+ %th{:width => "300px"} Compiler message
+ %th
= render :partial => 'submission', :collection => @submissions
- else
No submission
diff --git a/app/views/problems/index.html.haml b/app/views/problems/index.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/problems/index.html.haml
@@ -0,0 +1,50 @@
+- content_for :head do
+ = stylesheet_link_tag 'problems'
+%h1 Listing problems
+%p
+ = link_to 'New problem', new_problem_path, class: 'btn btn-default btn-sm'
+ = link_to 'Manage problems', { action: 'manage'}, class: 'btn btn-default btn-sm'
+ = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-default btn-sm'
+ = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
+ = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
+.submitbox
+ = form_tag :action => 'quick_create' do
+ %b Quick New:
+ %label{:for => "problem_name"} Name
+ = text_field 'problem', 'name'
+ |
+ %label{:for => "problem_full_name"} Full name
+ = text_field 'problem', 'full_name'
+ = submit_tag "Create"
+%table.table.table-condense.table-hover
+ %thead
+ %th Name
+ %th Full name
+ %th.text-right Full score
+ %th Date added
+ %th.text-center
+ Avail?
+ %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
+ %th.text-center
+ Test?
+ %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
+ - if GraderConfiguration.multicontests?
+ %th Contests
+ - for problem in @problems
+ %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
+ - @problem=problem
+ %td= in_place_editor_field :problem, :name, {}, :rows=>1
+ %td= in_place_editor_field :problem, :full_name, {}, :rows=>1
+ %td.text-right= in_place_editor_field :problem, :full_score, {}, :rows=>1
+ %td= problem.date_added
+ %td= toggle_button(@problem.available?, toggle_problem_url(@problem), "problem-avail-#{@problem.id}")
+ %td= toggle_button(@problem.test_allowed?, toggle_test_problem_url(@problem), "problem-test-#{@problem.id}")
+ - if GraderConfiguration.multicontests?
+ %td
+ = problem.contests.collect { |c| c.name }.join(', ')
+ %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
+ %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
+ %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
+ %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :post, class: 'btn btn-danger btn-xs btn-block'
+%br/
+= link_to '[New problem]', :action => 'new'
diff --git a/app/views/problems/list.html.erb b/app/views/problems/list.html.erb
deleted file mode 100644
--- a/app/views/problems/list.html.erb
+++ /dev/null
@@ -1,66 +0,0 @@
-<% content_for :head do %>
- <%= stylesheet_link_tag 'problems' %>
-<% end %>
-
-Listing problems
-
-
-<%= link_to '[New problem]', :action => 'new' %>
-<%= link_to '[Manage problems]', :action => 'manage' %>
-<%= link_to '[Import problems]', :action => 'import' %>
-<%= link_to '[Turn off all problems]', :action => 'turn_all_off' %>
-<%= link_to '[Turn on all problems]', :action => 'turn_all_on' %>
-
-
-
- <%= form_tag :action => 'quick_create' do %>
- Quick New:
- Name
- <%= text_field 'problem', 'name' %> |
- Full name
- <%= text_field 'problem', 'full_name' %>
- <%= submit_tag "Create" %>
- <% end %>
-
-
-
-
- Name
- Full name
- Full score
- Date added
- Avail?
- Test?
- <% if GraderConfiguration.multicontests? %>
- Contests
- <% end %>
-
-
-<% for problem in @problems %>
- ">
- <% @problem=problem %>
- <%= in_place_editor_field :problem, :name, {}, :rows=>1 %>
- <%= in_place_editor_field :problem, :full_name, {}, :rows=>1 %>
- <%= in_place_editor_field :problem, :full_score, {}, :rows=>1 %>
- <%= problem.date_added %>
- <%= problem.available %>
- <%= problem.test_allowed %>
-
- <% if GraderConfiguration.multicontests? %>
-
- <%= problem.contests.collect { |c| c.name }.join(', ') %>
-
- <% end %>
-
- <%= link_to '[Toggle]', {:action => 'toggle', :id => problem.id }, :remote => true %>
- <%= link_to '[Stat]', :action => 'stat', :id => problem.id %>
- <%= link_to '[Show]', :action => 'show', :id => problem %>
- <%= link_to '[Edit]', :action => 'edit', :id => problem %>
- <%= link_to '[Destroy]', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :post %>
-
-<% end %>
-
-
-
-
-<%= link_to '[New problem]', :action => 'new' %>
diff --git a/app/views/problems/toggle.js.haml b/app/views/problems/toggle.js.haml
new file mode 100644
--- /dev/null
+++ b/app/views/problems/toggle.js.haml
@@ -0,0 +1,8 @@
+= render partial: 'toggle_button',
+ locals: {button_id: "#problem-avail-#{@problem.id}",button_on: @problem.available }
+:plain
+ r = $("#prob-#{@problem.id}");
+ r.removeClass('success');
+ r.removeClass('danger');
+ r.addClass("#{@problem.available? ? 'success' : 'danger'}");
+
diff --git a/app/views/problems/toggle.js.rjs b/app/views/problems/toggle.js.rjs
deleted file mode 100644
--- a/app/views/problems/toggle.js.rjs
+++ /dev/null
@@ -1,6 +0,0 @@
-if @problem.available
- page["prob-#{@problem.id}"].className = "available"
-else
- page["prob-#{@problem.id}"].className = "not-available"
-end
-page["prob-#{@problem.id}-avail"].innerHTML = @problem.available.to_s
diff --git a/app/views/problems/toggle_test.js.haml b/app/views/problems/toggle_test.js.haml
new file mode 100644
--- /dev/null
+++ b/app/views/problems/toggle_test.js.haml
@@ -0,0 +1,2 @@
+= render partial: 'toggle_button',
+ locals: {button_id: "#problem-test-#{@problem.id}",button_on: @problem.test_allowed?}
diff --git a/app/views/report/_task_hof.html.haml b/app/views/report/_task_hof.html.haml
--- a/app/views/report/_task_hof.html.haml
+++ b/app/views/report/_task_hof.html.haml
@@ -1,14 +1,3 @@
-- content_for :header do
- = javascript_include_tag 'local_jquery'
-
-:javascript
- $(document).ready( function() {
- $("#mem_remark").hover( function() {
- $("#mem_remark_box").show();
- }, function() {
- $("#mem_remark_box").hide();
- });
- });
:css
.hof_user { color: orangered; font-style: italic; }
.hof_language { color: green; font-style: italic; }
@@ -34,94 +23,114 @@
overflow: auto;
}
-%h1 (#{Problem.find(params[:id]).name}) #{Problem.find(params[:id]).full_name}
-%h2 Problem Stat
-%table.info
- %thead
- %tr.info-head
- %th Stat
- %th Value
- %tbody
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param Submissions
- %td= @summary[:count]
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param Solved/Attempted User
- %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
- - if @best
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param Best Runtime
- %td
- by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
- using #{@best[:runtime][:lang]}
- with #{@best[:runtime][:value] * 1000} milliseconds
- at submission
- = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
+.container
+ .row
+ .col-md-4
+ %h2 Overall Stat
+ %table.table.table-hover
+ %thead
+ %tr
+ %th
+ %th
+ %tbody
+ %tr
+ %td.info_param Submissions
+ %td= @summary[:count]
+ %tr
+ %td.info_param Solved/Attempted User
+ %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
+ - if @best
+ %tr
+ %td.info_param Best Runtime
+ %td
+ by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
+ %br
+ using #{@best[:runtime][:lang]}
+ %br
+ with #{@best[:runtime][:value] * 1000} milliseconds
+ %br
+ at submission
+ = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param
- Best Memory Usage
- %sup{ id: "mem_remark", style: "position:relative; color: blue;"}
- [?]
- %span.tooltip#mem_remark_box
- This counts only for submission with 100% score.
- Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
- %td
- by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
- using #{@best[:memory][:lang]}
- with #{number_with_delimiter(@best[:memory][:value])} kbytes
- at submission
- = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
+ %tr
+ %td.info_param
+ Best Memory Usage
+ %sup{ id: "xmem_remark",
+ style: "position:relative; color: blue;",
+ data: {toggle: 'tooltip', placement: 'top', animation: 'false', delay: 20},
+ title: "This counts only for submission with 100% score. Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)"}
+ [?]
+ %td
+ by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
+ %br
+ using #{@best[:memory][:lang]}
+ %br
+ with #{number_with_delimiter(@best[:memory][:value])} kbytes
+ %br
+ at submission
+ = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param Shortest Code
- %td
- by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
- using #{@best[:length][:lang]}
- with #{@best[:length][:value]} bytes
- at submission
- = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
-
- %tr{class: cycle('info-even','info-odd')}
- %td.info_param First solver
- %td
- #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
- using #{@best[:first][:lang]}
- on #{@best[:first][:value]}
- at submission
- = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
-
-- if @best
- %h2 By language
+ %tr
+ %td.info_param Shortest Code
+ %td
+ by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
+ %br
+ using #{@best[:length][:lang]}
+ %br
+ with #{@best[:length][:value]} bytes
+ %br
+ at submission
+ = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
- %table.info
- %thead
- %tr.info-head
- %th Language
- %th Best runtime (ms)
- %th Best memory (kbytes)
- %th Shortest Code (bytes)
- %th First solver
- %tbody
- - @by_lang.each do |lang,value|
- %tr{class: cycle('info-even','info-odd')}
- %td= lang
- %td
- = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
- = "(#{(value[:runtime][:value] * 1000).to_i} @"
- = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
- %td
- = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
- = "(#{number_with_delimiter(value[:memory][:value])} @"
- = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
- %td
- = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
- = "(#{value[:length][:value]} @"
- = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
- %td
- - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
- = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
- = "(#{value[:first][:value]} @"
- = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
+ %tr
+ %td.info_param First solver
+ %td
+ - if @best[:first][:user] != '(NULL)'
+ #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
+ %br
+ using #{@best[:first][:lang]}
+ %br
+ on #{@best[:first][:value]}
+ %br
+ at submission
+ = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
+ - else
+ no first solver
+ .col-md-8
+ - if @best
+ %h2 By Language
+ %table.table.table-hover
+ %thead
+ %tr
+ %th Language
+ %th Best runtime (ms)
+ %th Best memory (kbytes)
+ %th Shortest Code (bytes)
+ %th First solver
+ %tbody
+ - @by_lang.each do |lang,value|
+ %tr
+ %td= lang
+ %td
+ = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
+ %br
+ = "(#{(value[:runtime][:value] * 1000).to_i} @"
+ = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
+ %td
+ = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
+ %br
+ = "(#{number_with_delimiter(value[:memory][:value])} @"
+ = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
+ %td
+ = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
+ %br
+ = "(#{value[:length][:value]} @"
+ = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
+ %td
+ - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
+ = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
+ %br
+ = "(#{value[:first][:value]} @"
+ = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
diff --git a/app/views/report/problem_hof.html.haml b/app/views/report/problem_hof.html.haml
--- a/app/views/report/problem_hof.html.haml
+++ b/app/views/report/problem_hof.html.haml
@@ -5,19 +5,25 @@
/- else
/ %h1 All-Time Hall of Fame
+.panel.panel-info
+ .panel-heading
+ Select Task
+ .panel-body
+ .form-inline
+ = select 'report',
+ 'problem_id',
+ @problems.collect {|p| ["[#{p.name}] #{p.full_name}", report_problem_hof_url(p.id)]},
+ {:selected => report_problem_hof_url(@problem)},
+ { class: 'select2 form-control' }
+ %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: "#report_problem_id"}} Go
-%h1 Hall of Fame
-.task-menu
- Tasks
- %br/
- - @problems.each do |prob|
- = link_to( "[#{prob.name}]", {id: prob.id})
- unless params[:id]
/=render partial: 'all_time_hof'
Please select a problem.
- else
- =render partial: 'task_hof'
+ %h1 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
%h2 Submission History
=render partial: 'application/bar_graph', locals: { histogram: @histogram }
+ =render partial: 'task_hof'
diff --git a/app/views/sites/edit.html.erb b/app/views/sites/edit.html.erb
deleted file mode 100644
--- a/app/views/sites/edit.html.erb
+++ /dev/null
@@ -1,32 +0,0 @@
-Editing site
-
-<%= error_messages_for :site %>
-
-<%= form_for(@site) do |f| %>
-
- Name
- <%= f.text_field :name %>
-
-
-
- Password
- <%= f.text_field :password %>
-
-
-
- Started
- <%= f.check_box :started %>
-
-
-
- Start time
- <%= f.datetime_select :start_time %>
-
-
-
- <%= f.submit "Update" %>
-
-<% end %>
-
-<%= link_to 'Show', @site %> |
-<%= link_to 'Back', sites_path %>
diff --git a/app/views/sites/edit.html.haml b/app/views/sites/edit.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sites/edit.html.haml
@@ -0,0 +1,24 @@
+%h1 Editing site
+= error_messages_for :site
+= form_for(@site) do |f|
+ %p
+ %b Name
+ %br/
+ = f.text_field :name
+ %p
+ %b Password
+ %br/
+ = f.text_field :password
+ %p
+ %b Started
+ %br/
+ = f.check_box :started
+ %p
+ %b Start time
+ %br/
+ = f.datetime_select :start_time, :include_blank => true
+ %p
+ = f.submit "Update"
+= link_to 'Show', @site
+|
+= link_to 'Back', sites_path
diff --git a/app/views/sites/index.html.erb b/app/views/sites/index.html.erb
deleted file mode 100644
--- a/app/views/sites/index.html.erb
+++ /dev/null
@@ -1,29 +0,0 @@
-Listing sites
-
-
-
- Name
- Password
- Started
- Start time
-
-
-<% for site in @sites %>
- <% background = "white" %>
- <% background = "grey" if (site.started==true) and (site.finished? == true) %>
- <% background = "lightgreen" if (site.started==true) and (site.finished? != true) %>
-
- <%=h site.name %>
- <%=h site.password %>
- <%=h site.started %>
- <%=h site.start_time %>
- <%= link_to 'Show', site %>
- <%= link_to 'Edit', edit_site_path(site) %>
- <%= link_to 'Destroy', site, :confirm => 'Are you sure?', :method => :delete %>
-
-<% end %>
-
-
-
-
-<%= link_to 'New site', new_site_path %>
diff --git a/app/views/sites/index.html.haml b/app/views/sites/index.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sites/index.html.haml
@@ -0,0 +1,24 @@
+%h1 Listing sites
+%table.table.table-striped
+ %tr
+ %th Name
+ %th Password
+ %th Started
+ %th Start time
+ %th
+ %th
+ %th
+ - for site in @sites
+ - background = "white"
+ - background = "grey" if (site.started==true) and (site.finished? == true)
+ - background = "lightgreen" if (site.started==true) and (site.finished? != true)
+ %tr{:style => "background: #{background};"}
+ %td= h site.name
+ %td= h site.password
+ %td= h site.started
+ %td= h site.start_time
+ %td= link_to 'Show', site, class: 'btn btn-default'
+ %td= link_to 'Edit', edit_site_path(site), class: 'btn btn-default'
+ %td= link_to 'Destroy', site, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-default'
+%br/
+= link_to '+ New site', new_site_path, class: 'btn btn-success'
diff --git a/app/views/sites/new.html.erb b/app/views/sites/new.html.erb
deleted file mode 100644
--- a/app/views/sites/new.html.erb
+++ /dev/null
@@ -1,31 +0,0 @@
-New site
-
-<%= error_messages_for :site %>
-
-<%= form_for(@site) do |f| %>
-
- Name
- <%= f.text_field :name %>
-
-
-
- Password
- <%= f.text_field :password %>
-
-
-
- Started
- <%= f.check_box :started %>
-
-
-
- Start time
- <%= f.datetime_select :start_time %>
-
-
-
- <%= f.submit "Create" %>
-
-<% end %>
-
-<%= link_to 'Back', sites_path %>
diff --git a/app/views/sites/new.html.haml b/app/views/sites/new.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sites/new.html.haml
@@ -0,0 +1,22 @@
+%h1 New site
+= error_messages_for :site
+= form_for(@site) do |f|
+ %p
+ %b Name
+ %br/
+ = f.text_field :name
+ %p
+ %b Password
+ %br/
+ = f.text_field :password
+ %p
+ %b Started
+ %br/
+ = f.check_box :started
+ %p
+ %b Start time
+ %br/
+ = f.datetime_select :start_time
+ %p
+ = f.submit "Create"
+= link_to 'Back', sites_path
diff --git a/app/views/sites/show.html.erb b/app/views/sites/show.html.erb
deleted file mode 100644
--- a/app/views/sites/show.html.erb
+++ /dev/null
@@ -1,23 +0,0 @@
-
- Name:
- <%=h @site.name %>
-
-
-
- Password:
- <%=h @site.password %>
-
-
-
- Started:
- <%=h @site.started %>
-
-
-
- Start time:
- <%=h @site.start_time %>
-
-
-
-<%= link_to 'Edit', edit_site_path(@site) %> |
-<%= link_to 'Back', sites_path %>
diff --git a/app/views/sites/show.html.haml b/app/views/sites/show.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sites/show.html.haml
@@ -0,0 +1,15 @@
+%p
+ %b Name:
+ = h @site.name
+%p
+ %b Password:
+ = h @site.password
+%p
+ %b Started:
+ = h @site.started
+%p
+ %b Start time:
+ = h @site.start_time
+= link_to 'Edit', edit_site_path(@site)
+|
+= link_to 'Back', sites_path
diff --git a/app/views/sources/direct_edit.html.haml b/app/views/sources/direct_edit.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sources/direct_edit.html.haml
@@ -0,0 +1,264 @@
+%h2 Live submit
+%br
+
+%textarea#text_haha{style: "display:none"}~ @source
+.container
+ .row
+ .col-md-12
+ .alert.alert-info
+ Write your code in the following box, choose language, and click submit button when finished
+ .row
+ .col-md-8
+ %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
+ .col-md-4
+ = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
+
+ = hidden_field_tag 'editor_text', @source
+ = hidden_field_tag 'submission[problem_id]', @problem.id
+ .form-group
+ = label_tag "Task:"
+ = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
+
+ .form-group
+ = label_tag 'Language'
+ = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
+ .form-group
+ = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
+ data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
+ .panel.panel-info
+ .panel-heading
+ Latest Submission Status
+ .panel-body
+ - if @submission
+ = render :partial => 'submission_short',
+ :locals => {:submission => @submission, :problem_name => @problem.name }
+ .row
+ .col-md-12
+ %h2 Console
+ %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
+
+:javascript
+ $(document).ready(function() {
+ brython();
+ });
+
+
+%script#__main__{type:'text/python3'}
+ :plain
+ import sys
+ import traceback
+
+ from browser import document as doc
+ from browser import window, alert, console
+
+ _credits = """ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
+ for supporting Python development. See www.python.org for more information."""
+
+ _copyright = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
+ All Rights Reserved.
+
+ Copyright (c) 2001-2013 Python Software Foundation.
+ All Rights Reserved.
+
+ Copyright (c) 2000 BeOpen.com.
+ All Rights Reserved.
+
+ Copyright (c) 1995-2001 Corporation for National Research Initiatives.
+ All Rights Reserved.
+
+ Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
+ All Rights Reserved."""
+
+ _license = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer. Redistributions in binary
+ form must reproduce the above copyright notice, this list of conditions and
+ the following disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ Neither the name of the nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ """
+
+ def credits():
+ print(_credits)
+ credits.__repr__ = lambda:_credits
+
+ def copyright():
+ print(_copyright)
+ copyright.__repr__ = lambda:_copyright
+
+ def license():
+ print(_license)
+ license.__repr__ = lambda:_license
+
+ def write(data):
+ doc['console'].value += str(data)
+
+
+ sys.stdout.write = sys.stderr.write = write
+ history = []
+ current = 0
+ _status = "main" # or "block" if typing inside a block
+
+ # execution namespace
+ editor_ns = {'credits':credits,
+ 'copyright':copyright,
+ 'license':license,
+ '__name__':'__main__'}
+
+ def cursorToEnd(*args):
+ pos = len(doc['console'].value)
+ doc['console'].setSelectionRange(pos, pos)
+ doc['console'].scrollTop = doc['console'].scrollHeight
+
+ def get_col(area):
+ # returns the column num of cursor
+ sel = doc['console'].selectionStart
+ lines = doc['console'].value.split('\n')
+ for line in lines[:-1]:
+ sel -= len(line) + 1
+ return sel
+
+
+ def myKeyPress(event):
+ global _status, current
+ if event.keyCode == 9: # tab key
+ event.preventDefault()
+ doc['console'].value += " "
+ elif event.keyCode == 13: # return
+ src = doc['console'].value
+ if _status == "main":
+ currentLine = src[src.rfind('>>>') + 4:]
+ elif _status == "3string":
+ currentLine = src[src.rfind('>>>') + 4:]
+ currentLine = currentLine.replace('\n... ', '\n')
+ else:
+ currentLine = src[src.rfind('...') + 4:]
+ if _status == 'main' and not currentLine.strip():
+ doc['console'].value += '\n>>> '
+ event.preventDefault()
+ return
+ doc['console'].value += '\n'
+ history.append(currentLine)
+ current = len(history)
+ if _status == "main" or _status == "3string":
+ try:
+ _ = editor_ns['_'] = eval(currentLine, editor_ns)
+ if _ is not None:
+ write(repr(_)+'\n')
+ doc['console'].value += '>>> '
+ _status = "main"
+ except IndentationError:
+ doc['console'].value += '... '
+ _status = "block"
+ except SyntaxError as msg:
+ if str(msg) == 'invalid syntax : triple string end not found' or \
+ str(msg).startswith('Unbalanced bracket'):
+ doc['console'].value += '... '
+ _status = "3string"
+ elif str(msg) == 'eval() argument must be an expression':
+ try:
+ exec(currentLine, editor_ns)
+ except:
+ traceback.print_exc()
+ doc['console'].value += '>>> '
+ _status = "main"
+ elif str(msg) == 'decorator expects function':
+ doc['console'].value += '... '
+ _status = "block"
+ else:
+ traceback.print_exc()
+ doc['console'].value += '>>> '
+ _status = "main"
+ except:
+ traceback.print_exc()
+ doc['console'].value += '>>> '
+ _status = "main"
+ elif currentLine == "": # end of block
+ block = src[src.rfind('>>>') + 4:].splitlines()
+ block = [block[0]] + [b[4:] for b in block[1:]]
+ block_src = '\n'.join(block)
+ # status must be set before executing code in globals()
+ _status = "main"
+ try:
+ _ = exec(block_src, editor_ns)
+ if _ is not None:
+ print(repr(_))
+ except:
+ traceback.print_exc()
+ doc['console'].value += '>>> '
+ else:
+ doc['console'].value += '... '
+
+ cursorToEnd()
+ event.preventDefault()
+
+ def myKeyDown(event):
+ global _status, current
+ if event.keyCode == 37: # left arrow
+ sel = get_col(doc['console'])
+ if sel < 5:
+ event.preventDefault()
+ event.stopPropagation()
+ elif event.keyCode == 36: # line start
+ pos = doc['console'].selectionStart
+ col = get_col(doc['console'])
+ doc['console'].setSelectionRange(pos - col + 4, pos - col + 4)
+ event.preventDefault()
+ elif event.keyCode == 38: # up
+ if current > 0:
+ pos = doc['console'].selectionStart
+ col = get_col(doc['console'])
+ # remove current line
+ doc['console'].value = doc['console'].value[:pos - col + 4]
+ current -= 1
+ doc['console'].value += history[current]
+ event.preventDefault()
+ elif event.keyCode == 40: # down
+ if current < len(history) - 1:
+ pos = doc['console'].selectionStart
+ col = get_col(doc['console'])
+ # remove current line
+ doc['console'].value = doc['console'].value[:pos - col + 4]
+ current += 1
+ doc['console'].value += history[current]
+ event.preventDefault()
+ elif event.keyCode == 8: # backspace
+ src = doc['console'].value
+ lstart = src.rfind('\n')
+ if (lstart == -1 and len(src) < 5) or (len(src) - lstart < 6):
+ event.preventDefault()
+ event.stopPropagation()
+
+
+ doc['console'].bind('keypress', myKeyPress)
+ doc['console'].bind('keydown', myKeyDown)
+ doc['console'].bind('click', cursorToEnd)
+ v = sys.implementation.version
+ doc['console'].value = "Brython %s.%s.%s on %s %s\n>>> " % (
+ v[0], v[1], v[2], window.navigator.appName, window.navigator.appVersion)
+ #doc['console'].value += 'Type "copyright", "credits" or "license" for more information.'
+ doc['console'].focus()
+ cursorToEnd()
+
+
+
+
diff --git a/app/views/sources/get_latest_submission_status.js.haml b/app/views/sources/get_latest_submission_status.js.haml
new file mode 100644
--- /dev/null
+++ b/app/views/sources/get_latest_submission_status.js.haml
@@ -0,0 +1,2 @@
+:javascript
+ $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}")
diff --git a/app/views/user_admin/index.html.haml b/app/views/user_admin/index.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/user_admin/index.html.haml
@@ -0,0 +1,100 @@
+%h1 Listing users
+
+.panel.panel-primary
+ .panel-title.panel-heading
+ Quick Add
+ .panel-body
+ = form_tag( {method: 'post'}, {class: 'form-inline'}) do
+ .form-group
+ = label_tag 'user_login', 'Login'
+ = text_field 'user', 'login', :size => 10,class: 'form-control'
+ .form-group
+ = label_tag 'user_full_name', 'Full Name'
+ = text_field 'user', 'full_name', :size => 10,class: 'form-control'
+ .form-group
+ = label_tag 'user_password', 'Password'
+ = text_field 'user', 'password', :size => 10,class: 'form-control'
+ .form-group
+ = label_tag 'user_password_confirmation', 'Confirm'
+ = text_field 'user', 'password_confirmation', :size => 10,class: 'form-control'
+ .form-group
+ = label_tag 'user_email', 'email'
+ = text_field 'user', 'email', :size => 10,class: 'form-control'
+ =submit_tag "Create", class: 'btn btn-primary'
+
+.panel.panel-primary
+ .panel-title.panel-heading
+ Import from site management
+ .panel-body
+ = form_tag({:action => 'import'}, :multipart => true,class: 'form form-inline') do
+ .form-group
+ = label_tag :file, 'File:'
+ .input-group
+ %span.input-group-btn
+ %span.btn.btn-default.btn-file
+ Browse
+ = file_field_tag 'file'
+ = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
+ = submit_tag 'Submit', class: 'btn btn-default'
+
+
+%p
+ = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
+ = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
+ = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '}
+ = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
+ = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
+ = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-default '}
+
+- if GraderConfiguration.multicontests?
+ %br/
+ %b Multi-contest:
+ = link_to '[Manage bulk users in contests]', :action => 'contest_management'
+ View users in:
+ - @contests.each do |contest|
+ = link_to "[#{contest.name}]", :action => 'contests', :id => contest.id
+ = link_to "[no contest]", :action => 'contests', :id => 'none'
+
+Total #{@user_count} users |
+- if !@paginated
+ Display all users.
+ \#{link_to '[show in pages]', :action => 'index', :page => '1'}
+- else
+ Display in pages.
+ \#{link_to '[display all]', :action => 'index', :page => 'all'} |
+ \#{will_paginate @users, :container => false}
+
+
+%table.table.table-hover.table-condense
+ %thead
+ %th Login
+ %th Full name
+ %th email
+ %th Remark
+ %th
+ Activated
+ %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'User has already confirmed the email?' } [?]
+ %th
+ Enabled
+ %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'Allow the user to login?' } [?]
+ %th Last IP
+ %th
+ %th
+ %th
+ %th
+ - for user in @users
+ %tr
+ %td= link_to user.login, controller: :users, :action => 'profile', :id => user
+ %td= user.full_name
+ %td= user.email
+ %td= user.remark
+ %td= toggle_button(user.activated?, toggle_activate_user_url(user),"toggle_activate_user_#{user.id}")
+ %td= toggle_button(user.enabled?, toggle_enable_user_url(user),"toggle_enable_user_#{user.id}")
+ %td= user.last_ip
+ %td= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?', class: 'btn btn-default btn-xs btn-block'
+ %td= link_to 'Show', {:action => 'show', :id => user}, class: 'btn btn-default btn-xs btn-block'
+ %td= link_to 'Edit', {:action => 'edit', :id => user}, class: 'btn btn-default btn-xs btn-block'
+ %td= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post, class: 'btn btn-danger btn-xs btn-block'
+%br/
+= link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
+= link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
diff --git a/app/views/user_admin/list.html.erb b/app/views/user_admin/list.html.erb
deleted file mode 100644
--- a/app/views/user_admin/list.html.erb
+++ /dev/null
@@ -1,89 +0,0 @@
-Listing users
-
-
-
Quick add
- <%= form_tag :action => 'create' do %>
-
-
- Login
- Full name
- Password
- Confirm
- Email
-
-
- <%= text_field 'user', 'login', :size => 10 %>
- <%= text_field 'user', 'full_name', :size => 30 %>
- <%= password_field 'user', 'password', :size => 10 %>
- <%= password_field 'user', 'password_confirmation', :size => 10 %>
- <%= email_field 'user', 'email', :size => 15 %>
- <%= submit_tag "Create" %>
-
-
- <% end %>
-
-
Import from site management
- <%= form_tag({:action => 'import'}, :multipart => true) do %>
- File: <%= file_field_tag 'file' %> <%= submit_tag 'Import' %>
- <% end %>
-
-
What else:
- <%= link_to '[New user]', :action => 'new' %>
- <%= link_to '[New list of users]', :action => 'new_list' %>
- <%= link_to '[View administrators]', :action => 'admin' %>
- <%= link_to '[Random passwords]', :action => 'random_all_passwords' %>
- <%= link_to '[View active users]', :action => 'active' %>
- <%= link_to '[Mass mailing]', :action => 'mass_mailing' %>
- <% if GraderConfiguration.multicontests? %>
-
Multi-contest:
- <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
- View users in:
- <% @contests.each do |contest| %>
- <%= link_to "[#{contest.name}]", :action => 'contests', :id => contest.id %>
- <% end %>
- <%= link_to "[no contest]", :action => 'contests', :id => 'none' %>
- <% end %>
-
-
-Total <%= @user_count %> users |
-<% if !@paginated %>
- Display all users.
- <%= link_to '[show in pages]', :action => 'list', :page => '1' %>
-<% else %>
- Display in pages.
- <%= link_to '[display all]', :action => 'list', :page => 'all' %> |
- <%= will_paginate @users, :container => false %>
-<% end %>
-
-
- <% for column in User.content_columns %>
- <% if !@hidden_columns.index(column.name) %>
- <%= column.human_name %>
- <% end %>
- <% end %>
-
-
-
-
-
-
-<% for user in @users %>
- ">
- <%= link_to user.login, controller: :users, :action => 'profile', :id => user %>
- <% for column in User.content_columns %>
- <% if !@hidden_columns.index(column.name) and column.name != 'login' %>
- <%=h user.send(column.name) %>
- <% end %>
- <% end %>
- <%= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?' %>
- <%= link_to 'Show', :action => 'show', :id => user %>
- <%= link_to 'Edit', :action => 'edit', :id => user %>
- <%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %>
-
-<% end %>
-
-
-
-
-<%= link_to '[New user]', :action => 'new' %>
-<%= link_to '[New list of users]', :action => 'new_list' %>
diff --git a/app/views/user_admin/user_stat.html.haml b/app/views/user_admin/user_stat.html.haml
--- a/app/views/user_admin/user_stat.html.haml
+++ b/app/views/user_admin/user_stat.html.haml
@@ -1,12 +1,12 @@
-- content_for :header do
- = javascript_include_tag 'local_jquery'
- = stylesheet_link_tag 'tablesorter-theme.cafe'
+/- content_for :header do
+/ = javascript_include_tag 'local_jquery'
+/ = stylesheet_link_tag 'tablesorter-theme.cafe'
%script{:type=>"text/javascript"}
$(function () {
$('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
$('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
- $('#my_table').tablesorter({widgets: ['zebra']});
+ /$('#my_table').tablesorter({widgets: ['zebra']});
});
%h1 User grading results
@@ -26,22 +26,22 @@
= link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
= link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat_max, commit: 'download csv'
-%table.tablesorter-cafe#my_table
+%table.table.sortable.table-striped.table-bordered
%thead
%tr
- %th User
+ %th Login
%th Name
%th Activated?
- %th Logged in
+ %th Logged_in
%th Contest(s)
%th Remark
- @problems.each do |p|
- %th= p.name
- %th Total
- %th Passed
+ %th.text-right= p.name
+ %th.text-right Total
+ %th.text-right Passed
%tbody
- @scorearray.each do |sc|
- %tr{class: cycle('info-even','info-odd')}
+ %tr
- total,num_passed = 0,0
- sc.each_index do |i|
- if i == 0
@@ -52,8 +52,10 @@
%td= sc[i].contests.collect {|c| c.name}.join(', ')
%td= sc[i].remark
- else
- %td= sc[i][0]
+ %td.text-right= sc[i][0]
- total += sc[i][0]
- num_passed += 1 if sc[i][1]
- %td= total
- %td= num_passed
+ %td.text-right= total
+ %td.text-right= num_passed
+:javascript
+ $.bootstrapSortable(true,'reversed')
diff --git a/config/application.rb.SAMPLE b/config/application.rb.SAMPLE
--- a/config/application.rb.SAMPLE
+++ b/config/application.rb.SAMPLE
@@ -59,7 +59,12 @@
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
- config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js','graders.css','problems.css']
+ config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
+ %w( announcements configurations contests contest_management graders heartbeat
+ login main messages problems report site sites sources tasks
+ test user_admin users ).each do |controller|
+ config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
+ end
end
end
diff --git a/config/environments/development.rb b/config/environments/development.rb
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -36,5 +36,5 @@
config.assets.debug = true
# Prevents assets from rendering twice
- config.serve_static_assets = false
+ config.serve_static_assets = true
end
diff --git a/config/initializers/abstract_mysql2_adapter.rb.SAMPLE b/config/initializers/abstract_mysql2_adapter.rb.SAMPLE
new file mode 100644
--- /dev/null
+++ b/config/initializers/abstract_mysql2_adapter.rb.SAMPLE
@@ -0,0 +1,3 @@
+class ActiveRecord::ConnectionAdapters::Mysql2Adapter
+ NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -19,7 +19,7 @@
messages: 'Messages'
tasks: 'Tasks'
submissions: 'Submissions'
- test: 'Test Interface'
+ test: 'Test'
hall_of_fame: 'Hall of Fame'
help: 'Help'
settings: 'Settings'
diff --git a/config/routes.rb b/config/routes.rb
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,70 +1,59 @@
CafeGrader::Application.routes.draw do
- get "report/login"
+ get "sources/direct_edit"
+
+ root :to => 'main#login'
resources :contests
- resources :announcements
resources :sites
+ resources :announcements do
+ member do
+ get 'toggle','toggle_front'
+ end
+ end
+
+ resources :problems do
+ member do
+ get 'toggle'
+ get 'toggle_test'
+ end
+ collection do
+ get 'turn_all_off'
+ get 'turn_all_on'
+ get 'import'
+ get 'manage'
+ end
+ end
+
resources :grader_configuration, controller: 'configurations'
- # The priority is based upon order of creation:
- # first created -> highest priority.
-
- # Sample of regular route:
- # match 'products/:id' => 'catalog#view'
- # Keep in mind you can assign values other than :controller and :action
-
- # Sample of named route:
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
- # This route can be invoked with purchase_url(:id => product.id)
-
- # Sample resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
-
- # Sample resource route with options:
- # resources :products do
- # member do
- # get 'short'
- # post 'toggle'
- # end
- #
- # collection do
- # get 'sold'
- # end
- # end
+ resources :users do
+ member do
+ get 'toggle_activate', 'toggle_enable'
+ end
+ end
- # Sample resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
+ #source code edit
+ get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit'
+ get 'sources/direct_edit_submission/:sid', to: 'sources#direct_edit_submission', as: 'direct_edit_submission'
+ get 'sources/get_latest_submission_status/:uid/:pid', to: 'sources#get_latest_submission_status', as: 'get_latest_submission_status'
- # Sample resource route with more complex sub-resources
- # resources :products do
- # resources :comments
- # resources :sales do
- # get 'recent', :on => :collection
- # end
- # end
-
- # Sample resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
-
- # You can have the root of your site routed with "root"
- # just remember to delete public/index.html.
- # root :to => 'welcome#index'
-
- root :to => 'main#login'
match 'tasks/view/:file.:ext' => 'tasks#view'
match 'tasks/download/:id/:file.:ext' => 'tasks#download'
+ match 'heartbeat/:id/edit' => 'heartbeat#edit'
- match 'heartbeat/:id/edit' => 'heartbeat#edit'
+ #main
+ get "main/list"
+ get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
+
+ #report
+ get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
+ get "report/login"
+
+ #grader
+ get 'graders/list', to: 'graders#list', as: 'grader_list'
# See how all your routes lay out with "rake routes"
diff --git a/db/schema.rb b/db/schema.rb
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -15,12 +15,12 @@
create_table "announcements", :force => true do |t|
t.string "author"
- t.text "body", :limit => 16777215
+ t.text "body"
t.boolean "published"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.boolean "frontpage", :default => false
- t.boolean "contest_only", :default => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.boolean "frontpage", :default => false
+ t.boolean "contest_only", :default => false
t.string "title"
t.string "notes"
end
@@ -50,19 +50,19 @@
end
create_table "descriptions", :force => true do |t|
- t.text "body", :limit => 16777215
+ t.text "body"
t.boolean "markdowned"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
create_table "grader_configurations", :force => true do |t|
t.string "key"
t.string "value_type"
t.string "value"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.text "description", :limit => 16777215
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.text "description"
end
create_table "grader_processes", :force => true do |t|
@@ -107,10 +107,10 @@
t.integer "sender_id"
t.integer "receiver_id"
t.integer "replying_message_id"
- t.text "body", :limit => 16777215
+ t.text "body"
t.boolean "replied"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
create_table "problems", :force => true do |t|
@@ -152,7 +152,7 @@
create_table "sessions", :force => true do |t|
t.string "session_id"
- t.text "data", :limit => 16777215
+ t.text "data"
t.datetime "updated_at"
end
@@ -180,14 +180,14 @@
t.integer "user_id"
t.integer "problem_id"
t.integer "language_id"
- t.text "source", :limit => 16777215
+ t.text "source"
t.binary "binary"
t.datetime "submitted_at"
t.datetime "compiled_at"
- t.text "compiler_message", :limit => 16777215
+ t.text "compiler_message"
t.datetime "graded_at"
t.integer "points"
- t.text "grader_comment", :limit => 16777215
+ t.text "grader_comment"
t.integer "number"
t.string "source_filename"
t.float "max_runtime"
@@ -208,10 +208,10 @@
create_table "test_pairs", :force => true do |t|
t.integer "problem_id"
- t.text "input", :limit => 2147483647
- t.text "solution", :limit => 2147483647
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.text "input", :limit => 16777215
+ t.text "solution", :limit => 16777215
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
create_table "test_requests", :force => true do |t|
@@ -222,13 +222,13 @@
t.string "output_file_name"
t.string "running_stat"
t.integer "status"
- t.datetime "updated_at", :null => false
+ t.datetime "updated_at", :null => false
t.datetime "submitted_at"
t.datetime "compiled_at"
- t.text "compiler_message", :limit => 16777215
+ t.text "compiler_message"
t.datetime "graded_at"
t.string "grader_comment"
- t.datetime "created_at", :null => false
+ t.datetime "created_at", :null => false
t.float "running_time"
t.string "exit_status"
t.integer "memory_usage"
@@ -256,7 +256,6 @@
t.boolean "activated", :default => false
t.datetime "created_at"
t.datetime "updated_at"
- t.string "section"
t.boolean "enabled", :default => true
t.string "remark"
t.string "last_ip"
diff --git a/spec/controllers/sources_controller_spec.rb b/spec/controllers/sources_controller_spec.rb
new file mode 100644
--- /dev/null
+++ b/spec/controllers/sources_controller_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe SourcesController do
+
+ describe "GET 'direct_edit'" do
+ it "returns http success" do
+ get 'direct_edit'
+ response.should be_success
+ end
+ end
+
+end
diff --git a/spec/helpers/sources_helper_spec.rb b/spec/helpers/sources_helper_spec.rb
new file mode 100644
--- /dev/null
+++ b/spec/helpers/sources_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the SourcesHelper. For example:
+#
+# describe SourcesHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+describe SourcesHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/sources/direct_edit.html.haml_spec.rb b/spec/views/sources/direct_edit.html.haml_spec.rb
new file mode 100644
--- /dev/null
+++ b/spec/views/sources/direct_edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "sources/direct_edit.html.haml" do
+ pending "add some examples to (or delete) #{__FILE__}"
+end