implemented partial batch update for exercises

This commit is contained in:
Hauke Klement
2015-03-12 11:05:11 +01:00
parent f1de18141a
commit 6ee0b6bf81
9 changed files with 105 additions and 4 deletions

View File

@ -15,11 +15,45 @@ $(function() {
$('body, html').scrollTo('#add-file');
};
var ajaxError = function(response) {
$.flash.danger({
text: $('#flash').data('message-failure')
});
};
var buildCheckboxes = function() {
$('tbody tr').each(function(index, element) {
var td = $('td.public', element);
var checkbox = $('<input>', {
checked: td.data('value'),
type: 'checkbox'
});
td.on('click', function(event) {
event.preventDefault();
checkbox.prop('checked', !checkbox.prop('checked'));
});
td.html(checkbox);
});
};
var discardFile = function(event) {
event.preventDefault();
$(this).parents('li').remove();
};
var enableBatchUpdate = function() {
$('thead .batch a').on('click', function(event) {
event.preventDefault();
if (!$(this).data('toggled')) {
$(this).data('toggled', true);
$(this).text($(this).data('text'));
buildCheckboxes();
} else {
performBatchUpdate();
}
});
};
var enableInlineFileCreation = function() {
$('#add-file').on('click', addFileForm);
$('#files').on('click', 'li .discard-file', discardFile);
@ -84,6 +118,23 @@ $(function() {
});
};
var performBatchUpdate = function() {
var jqxhr = $.ajax({
data: {
exercises: _.map($('tbody tr'), function(element) {
return {
id: $(element).data('id'),
public: $('.public input', element).prop('checked')
};
})
},
dataType: 'json',
method: 'PUT'
});
jqxhr.done(window.CodeOcean.refresh);
jqxhr.fail(ajaxError);
};
var toggleCodeHeight = function() {
$('code').on('click', function() {
$(this).css({
@ -93,7 +144,9 @@ $(function() {
};
if ($.isController('exercises')) {
if ($('.edit_exercise, .new_exercise').isPresent()) {
if ($('table').isPresent()) {
enableBatchUpdate();
} else if ($('.edit_exercise, .new_exercise').isPresent()) {
execution_environments = $('form').data('execution-environments');
file_types = $('form').data('file-types');
new MarkdownEditor('#exercise_instructions');

View File

@ -15,6 +15,17 @@ class ExercisesController < ApplicationController
end
private :authorize!
def batch_update
@exercises = Exercise.all
authorize!
@exercises = params[:exercises].values.map do |exercise_params|
exercise = Exercise.find(exercise_params.delete(:id))
exercise.update(exercise_params)
exercise
end
render(json: {exercises: @exercises})
end
def clone
exercise = @exercise.duplicate(public: false, token: nil, user: current_user)
exercise.send(:generate_token)

View File

@ -4,6 +4,10 @@ class ExercisePolicy < AdminOrAuthorPolicy
end
private :author?
def batch_update?
admin?
end
[:clone?, :destroy?, :edit?, :show?, :statistics?, :update?].each do |action|
define_method(action) { admin? || author? || team_member? }
end

View File

@ -17,17 +17,21 @@ h1 = Exercise.model_name.human(count: 2)
th = sort_link(@search, :execution_environment_id, t('activerecord.attributes.exercise.execution_environment'))
th = t('.test_files')
th = t('activerecord.attributes.exercise.maximum_score')
th = t('activerecord.attributes.exercise.public')
th
= t('activerecord.attributes.exercise.public')
- if policy(Exercise).batch_update?
br
span.batch = link_to(t('shared.batch_update'), '#', 'data-text' => t('shared.update', model: t('activerecord.models.exercise.other')))
th colspan=6 = t('shared.actions')
tbody
- @exercises.each do |exercise|
tr
tr data-id=exercise.id
td = exercise.title
td = link_to(exercise.author, exercise.author)
td = link_to(exercise.execution_environment, exercise.execution_environment)
td = exercise.files.teacher_defined_tests.count
td = exercise.maximum_score
td = symbol_for(exercise.public?)
td.public data-value=exercise.public? = symbol_for(exercise.public?)
td = link_to(t('shared.show'), exercise)
td = link_to(t('shared.edit'), edit_exercise_path(exercise))
td = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete)