Merge branch 'webpython-hybrid' of ssh://github.com/openHPI/codeocean into webpython-hybrid
This commit is contained in:
16
Gemfile.lock
16
Gemfile.lock
@ -50,8 +50,6 @@ GEM
|
||||
bootstrap-will_paginate (0.0.10)
|
||||
will_paginate
|
||||
builder (3.2.2)
|
||||
byebug (4.0.5)
|
||||
columnize (= 0.9.0)
|
||||
capistrano (3.3.5)
|
||||
capistrano-stats (~> 1.1.0)
|
||||
i18n
|
||||
@ -96,7 +94,6 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.9.1)
|
||||
colorize (0.7.7)
|
||||
columnize (0.9.0)
|
||||
concurrent-ruby (0.8.0)
|
||||
ref (~> 1.0, >= 1.0.5)
|
||||
concurrent-ruby (0.8.0-java)
|
||||
@ -110,6 +107,7 @@ GEM
|
||||
excon (>= 0.38.0)
|
||||
json
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.8)
|
||||
excon (0.45.2)
|
||||
execjs (2.5.2)
|
||||
factory_girl (4.5.0)
|
||||
@ -119,6 +117,9 @@ GEM
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.9.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faye-websocket (0.10.0)
|
||||
eventmachine (>= 0.12.0)
|
||||
websocket-driver (>= 0.5.1)
|
||||
ffi (1.9.8)
|
||||
ffi (1.9.8-java)
|
||||
forgery (0.6.0)
|
||||
@ -302,6 +303,9 @@ GEM
|
||||
thread_safe (0.3.5)
|
||||
thread_safe (0.3.5-java)
|
||||
tilt (1.4.1)
|
||||
tubesock (0.2.5)
|
||||
rack (>= 1.5.0)
|
||||
websocket (>= 1.1.0)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
tzinfo (1.2.2)
|
||||
@ -315,6 +319,9 @@ GEM
|
||||
railties (>= 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
websocket (1.2.1)
|
||||
websocket-driver (0.6.2)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
will_paginate (3.0.7)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
@ -330,7 +337,6 @@ DEPENDENCIES
|
||||
better_errors
|
||||
binding_of_caller
|
||||
bootstrap-will_paginate
|
||||
byebug
|
||||
capistrano (~> 3.3.0)
|
||||
capistrano-rails
|
||||
capistrano-rvm
|
||||
@ -345,6 +351,7 @@ DEPENDENCIES
|
||||
database_cleaner
|
||||
docker-api (~> 1.21.1)
|
||||
factory_girl_rails (~> 4.0)
|
||||
faye-websocket
|
||||
forgery
|
||||
highline
|
||||
ims-lti
|
||||
@ -375,6 +382,7 @@ DEPENDENCIES
|
||||
sorcery
|
||||
spring
|
||||
thread_safe
|
||||
tubesock
|
||||
turbolinks
|
||||
uglifier (>= 1.3.0)
|
||||
web-console (~> 2.0)
|
||||
|
@ -11,6 +11,7 @@ $(function() {
|
||||
var FILENAME_URL_PLACEHOLDER = '{filename}';
|
||||
var SUCCESSFULL_PERCENTAGE = 90;
|
||||
var THEME = 'ace/theme/textmate';
|
||||
var REMEMBER_TAB = false;
|
||||
var AUTOSAVE_INTERVAL = 15 * 1000;
|
||||
|
||||
var editors = [];
|
||||
@ -59,7 +60,7 @@ $(function() {
|
||||
|
||||
if (event.type === 'error' || JSON.parse(event.data).code !== 200) {
|
||||
ajaxError();
|
||||
showTab(1);
|
||||
showTab(0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -262,13 +263,11 @@ $(function() {
|
||||
|
||||
var handleKeyPress = function(event) {
|
||||
if (event.which === ALT_1_KEY_CODE) {
|
||||
showTab(0);
|
||||
} else if (event.which === ALT_2_KEY_CODE) {
|
||||
showWorkspaceTab(event);
|
||||
} else if (event.which === ALT_2_KEY_CODE) {
|
||||
showTab(1);
|
||||
} else if (event.which === ALT_3_KEY_CODE) {
|
||||
showTab(2);
|
||||
} else if (event.which === ALT_4_KEY_CODE) {
|
||||
showTab(3);
|
||||
} else if (event.which === ALT_R_KEY_CODE) {
|
||||
$('#run').trigger('click');
|
||||
} else if (event.which === ALT_S_KEY_CODE) {
|
||||
@ -311,7 +310,7 @@ $(function() {
|
||||
}, 0).toFixed(2);
|
||||
$('#score').data('score', score);
|
||||
renderScore();
|
||||
showTab(3);
|
||||
showTab(2);
|
||||
};
|
||||
|
||||
var stderrOutput = '';
|
||||
@ -364,7 +363,7 @@ $(function() {
|
||||
qa_api.executeCommand('syncOutput', [response]);
|
||||
}
|
||||
showStatus(response[0]);
|
||||
showTab(2);
|
||||
showTab(1);
|
||||
};
|
||||
|
||||
var hideSpinner = function() {
|
||||
@ -719,7 +718,7 @@ $(function() {
|
||||
clearOutput();
|
||||
$('#hint').fadeOut();
|
||||
$('#flowrHint').fadeOut();
|
||||
showTab(2);
|
||||
showTab(1);
|
||||
}
|
||||
|
||||
var printOutput = function(output, colorize, index) {
|
||||
@ -820,7 +819,7 @@ $(function() {
|
||||
stderr: message
|
||||
}, true, 0);
|
||||
sendError(message, response.id);
|
||||
showTab(2);
|
||||
showTab(1);
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -943,16 +942,21 @@ $(function() {
|
||||
|
||||
var showOutput = function(event) {
|
||||
event.preventDefault();
|
||||
showTab(2);
|
||||
showTab(1);
|
||||
$('#output').scrollTo($(this).attr('href'));
|
||||
};
|
||||
|
||||
var showRequestedTab = function() {
|
||||
var regexp = /tab=(\d+)/;
|
||||
if (regexp.test(window.location.search)) {
|
||||
var index = regexp.exec(window.location.search)[1] - 1;
|
||||
if(REMEMBER_TAB){
|
||||
var regexp = /tab=(\d+)/;
|
||||
if (regexp.test(window.location.search)) {
|
||||
var index = regexp.exec(window.location.search)[1] - 1;
|
||||
} else {
|
||||
var index = localStorage.tab;
|
||||
}
|
||||
} else {
|
||||
var index = localStorage.tab;
|
||||
// else start with first tab.
|
||||
var index = 0;
|
||||
}
|
||||
showTab(index);
|
||||
};
|
||||
@ -1008,7 +1012,7 @@ $(function() {
|
||||
|
||||
var showWorkspaceTab = function(event) {
|
||||
event.preventDefault();
|
||||
showTab(1);
|
||||
showTab(0);
|
||||
};
|
||||
|
||||
var stopCode = function(event) {
|
||||
@ -1156,7 +1160,8 @@ $(function() {
|
||||
if (!msg.data) {
|
||||
return;
|
||||
}
|
||||
msg.data = msg.data.replace(/(\r\n|\n|\r)/gm, "</br>");
|
||||
//msg.data = msg.data.replace(/(\r\n|\n|\r)/gm, "<br />");
|
||||
msg.data = msg.data.replace(/(\r)/gm, "\n");
|
||||
var stream = {};
|
||||
stream[msg.stream] = msg.data;
|
||||
printOutput(stream, true, 0);
|
||||
|
@ -62,7 +62,7 @@ class ExercisesController < ApplicationController
|
||||
end
|
||||
|
||||
def exercise_params
|
||||
params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :team_id, :title, files_attributes: file_attributes).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :team_id, :title, files_attributes: file_attributes).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
private :exercise_params
|
||||
|
||||
|
@ -138,8 +138,10 @@ class SubmissionsController < ApplicationController
|
||||
if (/^exit/.match(message))
|
||||
kill_socket(tubesock)
|
||||
else
|
||||
# Filter out information about user and working directory
|
||||
if !(/root|workspace/.match(message))
|
||||
# Filter out information about run_command, test_command, user or working directory
|
||||
run_command = @submission.execution_environment.run_command
|
||||
test_command = @submission.execution_environment.test_command
|
||||
if !(/root|workspace|#{run_command}|#{test_command}/.match(message))
|
||||
parse_message(message, 'stdout', tubesock)
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
|
||||
.col-sm-3 = render('editor_file_tree', files: @files)
|
||||
#frames.col-sm-9
|
||||
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
|
||||
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
|
||||
- @files.each do |file|
|
||||
= render('editor_frame', exercise: exercise, file: file)
|
||||
#autosave-label
|
||||
|
@ -23,6 +23,10 @@
|
||||
label
|
||||
= f.check_box(:public)
|
||||
= t('activerecord.attributes.exercise.public')
|
||||
.checkbox
|
||||
label
|
||||
= f.check_box(:hide_file_tree)
|
||||
= t('activerecord.attributes.exercise.hide_file_tree')
|
||||
h2 = t('activerecord.attributes.exercise.files')
|
||||
ul#files.list-unstyled
|
||||
= f.fields_for :files do |files_form|
|
||||
|
@ -13,39 +13,29 @@
|
||||
#development-environment
|
||||
ul.nav.nav-justified.nav-tabs role='tablist'
|
||||
li.active
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#instructions' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 1')
|
||||
i.fa.fa-question
|
||||
= t('activerecord.attributes.exercise.instructions')
|
||||
li
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#workspace' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 2')
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#workspace' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 1')
|
||||
i.fa.fa-code
|
||||
= t('.workspace')
|
||||
li
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#outputInformation' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 3')
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#outputInformation' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 2')
|
||||
i.fa.fa-terminal
|
||||
= t('.output')
|
||||
li
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#progress' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 4')
|
||||
a data-placement='top' data-toggle='tab' data-tooltip=true href='#progress' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 3')
|
||||
i.fa.fa-line-chart
|
||||
= t('.progress')
|
||||
|
||||
hr
|
||||
|
||||
.tab-content
|
||||
#instructions.tab-pane.active
|
||||
p = render_markdown(@exercise.instructions)
|
||||
br
|
||||
p.text-center
|
||||
a#start.btn.btn-lg.btn-success
|
||||
i.fa.fa-code
|
||||
= t('.start')
|
||||
#workspace.tab-pane = render('editor', exercise: @exercise, files: @files, submission: @submission)
|
||||
#workspace.tab-pane.active = render('editor', exercise: @exercise, files: @files, submission: @submission)
|
||||
#outputInformation.tab-pane data-message-no-output=t('.no_output')
|
||||
#hint
|
||||
.panel.panel-warning
|
||||
.panel-heading = t('.hint')
|
||||
.panel-body
|
||||
.row
|
||||
/ #output-col1.col-sm-12
|
||||
#output-col1
|
||||
// todo set to full width if turtle isnt used
|
||||
#prompt.input-group.hidden
|
||||
@ -62,7 +52,7 @@
|
||||
#output-col2.col-lg-5.col-md-5
|
||||
#turtlediv
|
||||
// todo what should the canvas default size be?
|
||||
canvas#turtlecanvas.hidden style='border-style:solid;border-width:thin'
|
||||
canvas#turtlecanvas.hidden width=400 height=400 style='border-style:solid;border-width:thin'
|
||||
#progress.tab-pane
|
||||
#results
|
||||
h2 = t('.results')
|
||||
|
@ -14,6 +14,7 @@ h1
|
||||
= row(label: 'exercise.team', value: @exercise.team ? link_to(@exercise.team, @exercise.team) : nil)
|
||||
= row(label: 'exercise.maximum_score', value: @exercise.maximum_score)
|
||||
= row(label: 'exercise.public', value: @exercise.public?)
|
||||
= row(label: 'exercise.hide_file_tree', value: @exercise.hide_file_tree?)
|
||||
= row(label: 'exercise.embedding_parameters') do
|
||||
= content_tag(:input, nil, class: 'form-control', readonly: true, value: embedding_parameters(@exercise))
|
||||
|
||||
|
@ -7,7 +7,9 @@ default: &default
|
||||
development:
|
||||
<<: *default
|
||||
host: tcp://192.168.59.104:2376
|
||||
workspace_root: <%= File.join('/', 'shared', Rails.env) %>
|
||||
ws_host: ws://192.168.59.104:2376
|
||||
#workspace_root: <%= File.join('/', 'shared', Rails.env) %>
|
||||
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
|
@ -28,6 +28,7 @@ de:
|
||||
execution_environment: Ausführungsumgebung
|
||||
execution_environment_id: Ausführungsumgebung
|
||||
files: Dateien
|
||||
hide_file_tree: Dateibaum verstecken
|
||||
instructions: Anweisungen
|
||||
maximum_score: Erreichbare Punktzahl
|
||||
public: Öffentlich
|
||||
|
@ -28,6 +28,7 @@ en:
|
||||
execution_environment: Execution Environment
|
||||
execution_environment_id: Execution Environment
|
||||
files: Files
|
||||
hide_file_tree: Hide File Tree
|
||||
instructions: Instructions
|
||||
maximum_score: Maximum Score
|
||||
public: Public
|
||||
|
@ -0,0 +1,5 @@
|
||||
class AddHideFileTreeToExercises < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :exercises, :hide_file_tree, :boolean
|
||||
end
|
||||
end
|
@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20150903152727) do
|
||||
ActiveRecord::Schema.define(version: 20150922125415) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@ -79,6 +79,7 @@ ActiveRecord::Schema.define(version: 20150903152727) do
|
||||
t.string "user_type"
|
||||
t.string "token"
|
||||
t.integer "team_id"
|
||||
t.boolean "hide_file_tree"
|
||||
end
|
||||
|
||||
create_table "external_users", force: true do |t|
|
||||
|
@ -1,5 +1,5 @@
|
||||
class PyUnitAdapter < TestingFrameworkAdapter
|
||||
COUNT_REGEXP = /Ran (\d+) tests/
|
||||
COUNT_REGEXP = /Ran (\d+) test/
|
||||
FAILURES_REGEXP = /FAILED \(failures=(\d+)\)/
|
||||
|
||||
def self.framework_name
|
||||
|
@ -2,10 +2,11 @@ FROM ubuntu:14.04
|
||||
MAINTAINER "Martin v. Löwis"
|
||||
RUN locale-gen en_US.UTF-8
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV PYTHONPATH $PYTHONPATH:/usr/lib/python3.4:/workspace
|
||||
ENV PATH $PATH:/usr/lib/python3.4
|
||||
ADD assess.py /usr/lib/python3.4/assess.py
|
||||
ADD webpython.py /usr/lib/python3.4/webpython.py
|
||||
RUN rm /usr/lib/python3.4/turtle.py
|
||||
ADD turtle.py /usr/lib/python3.4/turtle.py
|
||||
RUN adduser --disabled-password --gecos Python python
|
||||
USER python
|
||||
WORKDIR /usr/lib/python3.4
|
||||
USER python
|
Reference in New Issue
Block a user