Add support for running CodeOcean under a subpath
* Also refactor (JavaScript) routes
This commit is contained in:
@ -46,7 +46,8 @@ In order to execute code submissions using Docker, source code files are written
|
|||||||
|
|
||||||
## Production Setup
|
## Production Setup
|
||||||
|
|
||||||
- We recommend using [Capistrano](http://capistranorb.com/) for deployment
|
- We recommend using [Capistrano](http://capistranorb.com/) for deployment.
|
||||||
|
- Once deployed, CodeOcean assumes to run exclusively under a (sub)domain. If you want to use it under a custom subpath, you can specify the desired path using an environment variable: `RAILS_RELATIVE_URL_ROOT=/codeocean`. Please ensure to rebuild all assets and restart the server to apply the new path.
|
||||||
|
|
||||||
## Monitoring
|
## Monitoring
|
||||||
- We use a [Prometheus Exporter](https://github.com/discourse/prometheus_exporter) and a [Telegraf Client](https://github.com/jgraichen/telegraf-ruby)
|
- We use a [Prometheus Exporter](https://github.com/discourse/prometheus_exporter) and a [Telegraf Client](https://github.com/jgraichen/telegraf-ruby)
|
||||||
|
@ -51,7 +51,7 @@ $(document).on('turbolinks:load', function() {
|
|||||||
} else {
|
} else {
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
url: '/admin/dashboard',
|
url: Routes.admin_dashboard_path(),
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
});
|
});
|
||||||
jqxhr.done(function(response) {
|
jqxhr.done(function(response) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
var CodeOceanEditor = {
|
var CodeOceanEditor = {
|
||||||
//ACE-Editor-Path
|
//ACE-Editor-Path
|
||||||
// ruby part adds the relative_url_root, if it is set.
|
// ruby part adds the relative_url_root, if it is set.
|
||||||
ACE_FILES_PATH: '<%= (defined? Rails.application.config.relative_url_root) && Rails.application.config.relative_url_root != nil && Rails.application.config.relative_url_root != "" ? Rails.application.config.relative_url_root : "" %>' + '/assets/ace/',
|
ACE_FILES_PATH: '<%= "#{Rails.application.config.relative_url_root.chomp('/')}/assets/ace/" %>',
|
||||||
THEME: 'ace/theme/textmate',
|
THEME: 'ace/theme/textmate',
|
||||||
|
|
||||||
//Color-Encoding for Percentages in Progress Bars (For submissions)
|
//Color-Encoding for Percentages in Progress Bars (For submissions)
|
||||||
|
@ -142,7 +142,7 @@ CodeOceanEditorRequestForComments = {
|
|||||||
var createRequestForComments = function (submission) {
|
var createRequestForComments = function (submission) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/request_for_comments',
|
url: Routes.request_for_comments_path(),
|
||||||
data: {
|
data: {
|
||||||
request_for_comment: {
|
request_for_comment: {
|
||||||
exercise_id: exercise_id,
|
exercise_id: exercise_id,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
$(document).on('turbolinks:load', function () {
|
$(document).on('turbolinks:load', function () {
|
||||||
// ruby part adds the relative_url_root, if it is set.
|
// ruby part adds the relative_url_root, if it is set.
|
||||||
var ACE_FILES_PATH = '<%= (defined? Rails.application.config.relative_url_root) && Rails.application.config.relative_url_root != nil && Rails.application.config.relative_url_root != "" ? Rails.application.config.relative_url_root : "" %>' + '/assets/ace/';
|
var ACE_FILES_PATH = '<%= "#{Rails.application.config.relative_url_root.chomp('/')}/assets/ace/" %>';
|
||||||
var THEME = 'ace/theme/textmate';
|
var THEME = 'ace/theme/textmate';
|
||||||
|
|
||||||
var TAB_KEY_CODE = 9;
|
var TAB_KEY_CODE = 9;
|
||||||
@ -351,7 +351,7 @@ $(document).on('turbolinks:load', function () {
|
|||||||
|
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/exercises/' + exerciseID + '/export_external_check',
|
url: Routes.export_external_check_exercise_path(exerciseID),
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
$messageDiv.html(response.message);
|
$messageDiv.html(response.message);
|
||||||
@ -370,7 +370,7 @@ $(document).on('turbolinks:load', function () {
|
|||||||
|
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/exercises/' + exerciseID + '/export_external_confirm',
|
url: Routes.export_external_confirm_exercise_path(exerciseID),
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
$messageDiv.html(response.message)
|
$messageDiv.html(response.message)
|
||||||
@ -427,9 +427,8 @@ $(document).on('turbolinks:load', function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var updateFileTemplates = function (fileType) {
|
var updateFileTemplates = function (fileType) {
|
||||||
var rel_url_root = '<%= (defined? Rails.application.config.relative_url_root) && Rails.application.config.relative_url_root != nil && Rails.application.config.relative_url_root != "" ? Rails.application.config.relative_url_root : "" %>';
|
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
url: rel_url_root + '/file_templates/by_file_type/' + fileType + '.json',
|
url: Routes.by_file_type_file_templates_path(fileType),
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
});
|
});
|
||||||
jqxhr.done(function (response) {
|
jqxhr.done(function (response) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var ACE_FILES_PATH = '/assets/ace/';
|
var ACE_FILES_PATH = '<%= "#{Rails.application.config.relative_url_root.chomp('/')}/assets/ace/" %>';
|
||||||
|
|
||||||
window.MarkdownEditor = function(selector) {
|
window.MarkdownEditor = function(selector) {
|
||||||
ace.config.set('modePath', ACE_FILES_PATH);
|
ace.config.set('modePath', ACE_FILES_PATH);
|
@ -1,6 +1,6 @@
|
|||||||
$(document).on('turbolinks:load', function() {
|
$(document).on('turbolinks:load', function() {
|
||||||
|
|
||||||
var ACE_FILES_PATH = '/assets/ace/';
|
var ACE_FILES_PATH = '<%= "#{Rails.application.config.relative_url_root.chomp('/')}/assets/ace/" %>';
|
||||||
var THEME = 'ace/theme/textmate';
|
var THEME = 'ace/theme/textmate';
|
||||||
|
|
||||||
var currentSubmission = 0;
|
var currentSubmission = 0;
|
@ -44,7 +44,7 @@ module StatisticsHelper
|
|||||||
data: ExternalUser.joins(:submissions)
|
data: ExternalUser.joins(:submissions)
|
||||||
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
||||||
.distinct('external_users.id').count,
|
.distinct('external_users.id').count,
|
||||||
url: 'statistics/graphs',
|
url: statistics_graphs_path,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -148,7 +148,7 @@ javascript:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// set file paths for ace
|
// set file paths for ace
|
||||||
var ACE_FILES_PATH = '/assets/ace/';
|
var ACE_FILES_PATH = "#{Rails.application.config.relative_url_root.chomp('/')}/assets/ace/";
|
||||||
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
||||||
ace.config.set(attribute, ACE_FILES_PATH);
|
ace.config.set(attribute, ACE_FILES_PATH);
|
||||||
});
|
});
|
||||||
@ -231,7 +231,7 @@ javascript:
|
|||||||
var jqrequest = $.ajax({
|
var jqrequest = $.ajax({
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/comments',
|
url: Routes.comments_path(),
|
||||||
data: {
|
data: {
|
||||||
file_id: fileid
|
file_id: fileid
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ javascript:
|
|||||||
function deleteComment(commentId, editor, file_id, callback) {
|
function deleteComment(commentId, editor, file_id, callback) {
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
url: "/comments/" + commentId
|
url: Routes.comments_path(commentId)
|
||||||
});
|
});
|
||||||
jqxhr.done(function () {
|
jqxhr.done(function () {
|
||||||
setAnnotations(editor, file_id);
|
setAnnotations(editor, file_id);
|
||||||
@ -266,7 +266,7 @@ javascript:
|
|||||||
function updateComment(commentId, text, editor, file_id, callback) {
|
function updateComment(commentId, text, editor, file_id, callback) {
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
type: 'PATCH',
|
type: 'PATCH',
|
||||||
url: "/comments/" + commentId,
|
url: Routes.comments_path(commentId),
|
||||||
data: {
|
data: {
|
||||||
comment: {
|
comment: {
|
||||||
text: text
|
text: text
|
||||||
@ -293,7 +293,7 @@ javascript:
|
|||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: "/comments"
|
url: Routes.comments_path()
|
||||||
});
|
});
|
||||||
jqxhr.done(function(){
|
jqxhr.done(function(){
|
||||||
setAnnotations(editor, file_id);
|
setAnnotations(editor, file_id);
|
||||||
@ -312,7 +312,7 @@ javascript:
|
|||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: "/subscriptions.json"
|
url: Routes.subscriptions_path({format: 'json'})
|
||||||
});
|
});
|
||||||
jqxhr.done(function(subscription) {
|
jqxhr.done(function(subscription) {
|
||||||
checkbox.data('subscription', subscription.id);
|
checkbox.data('subscription', subscription.id);
|
||||||
@ -329,7 +329,7 @@ javascript:
|
|||||||
checkbox.attr("disabled", true);
|
checkbox.attr("disabled", true);
|
||||||
var subscriptionId = checkbox.data('subscription');
|
var subscriptionId = checkbox.data('subscription');
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
url: '/subscriptions/' + subscriptionId + '/unsubscribe.json'
|
url: Routes.unsubscribe_subscription_path(subscriptionId, {format: 'json'})
|
||||||
});
|
});
|
||||||
jqxhr.done(function(response) {
|
jqxhr.done(function(response) {
|
||||||
checkbox.prop('checked', false);
|
checkbox.prop('checked', false);
|
||||||
|
@ -4,5 +4,7 @@
|
|||||||
|
|
||||||
require_relative 'config/environment'
|
require_relative 'config/environment'
|
||||||
|
|
||||||
|
map Rails.application.config.relative_url_root do
|
||||||
run Rails.application
|
run Rails.application
|
||||||
Rails.application.load_server
|
Rails.application.load_server
|
||||||
|
end
|
||||||
|
@ -40,7 +40,9 @@ module CodeOcean
|
|||||||
config.autoload_paths += extra_paths
|
config.autoload_paths += extra_paths
|
||||||
config.eager_load_paths += extra_paths
|
config.eager_load_paths += extra_paths
|
||||||
|
|
||||||
config.action_cable.mount_path = '/cable'
|
config.relative_url_root = ENV.fetch('RAILS_RELATIVE_URL_ROOT', '/').to_s
|
||||||
|
|
||||||
|
config.action_cable.mount_path = "#{ENV.fetch('RAILS_RELATIVE_URL_ROOT', '')}/cable"
|
||||||
|
|
||||||
config.telegraf.tags = {application: 'codeocean'}
|
config.telegraf.tags = {application: 'codeocean'}
|
||||||
|
|
||||||
|
@ -100,7 +100,4 @@ Rails.application.configure do
|
|||||||
|
|
||||||
# Do not dump schema after migrations.
|
# Do not dump schema after migrations.
|
||||||
config.active_record.dump_schema_after_migration = false
|
config.active_record.dump_schema_after_migration = false
|
||||||
|
|
||||||
# Run on subfolder in production environment.
|
|
||||||
# config.relative_url_root = '/co-staging'
|
|
||||||
end
|
end
|
||||||
|
@ -2,4 +2,7 @@
|
|||||||
|
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
Rails.application.config.session_store :cookie_store, key: '_code_ocean_session', expire_after: 1.month
|
Rails.application.config.session_store :cookie_store,
|
||||||
|
key: '_code_ocean_session',
|
||||||
|
expire_after: 1.month,
|
||||||
|
path: Rails.application.config.relative_url_root
|
||||||
|
@ -25,6 +25,14 @@ environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This setting will change the absolute path used to refer
|
||||||
|
// external files (images, fonts, ...) in the generated assets
|
||||||
|
const relative_url_root = process.env.RAILS_RELATIVE_URL_ROOT || '';
|
||||||
|
const public_output_path = environment.config.output.publicPath;
|
||||||
|
environment.loaders.get('file')
|
||||||
|
.use.find(item => item.loader === 'file-loader')
|
||||||
|
.options.publicPath = relative_url_root + public_output_path;
|
||||||
|
|
||||||
environment.loaders.append('erb', erb)
|
environment.loaders.append('erb', erb)
|
||||||
|
|
||||||
const envConfig = module.exports = environment
|
const envConfig = module.exports = environment
|
||||||
|
Reference in New Issue
Block a user