From 87798212ada38fc32ee2cca23e8eab5e89fc4727 Mon Sep 17 00:00:00 2001 From: Karol Date: Fri, 11 Oct 2019 16:28:50 +0200 Subject: [PATCH] add unpublished to views --- app/assets/javascripts/exercises.js.erb | 31 +++++++++++++++++++++++++ app/controllers/exercises_controller.rb | 3 ++- app/models/exercise.rb | 2 +- app/views/exercises/_form.html.slim | 8 +++++-- app/views/exercises/show.html.slim | 3 ++- config/locales/en.yml | 3 +++ 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/exercises.js.erb b/app/assets/javascripts/exercises.js.erb index efe110d2..8eb64f4f 100644 --- a/app/assets/javascripts/exercises.js.erb +++ b/app/assets/javascripts/exercises.js.erb @@ -208,6 +208,35 @@ $(document).on('turbolinks:load', function() { } }); }; + var old_execution_environment = $('#exercise_execution_environment_id').val(); + var observeExecutionEnvironment = function() { + $('#exercise_execution_environment_id').on('change', function(){ + new_execution_environment = $('#exercise_execution_environment_id').val(); + + if(new_execution_environment == '' && !$('#exercise_unpublished').prop('checked')){ + if(confirm('<%= I18n.t('exercises.form.unpublish_warning') %>')){ + $('#exercise_unpublished').prop('checked', true); + } else { + return $('#exercise_execution_environment_id').val(old_execution_environment).trigger("chosen:updated"); + } + } + old_execution_environment = new_execution_environment; + }); + }; + + var observeUnpublishedState = function() { + $('#exercise_unpublished').on('change', function(){ + if($('#exercise_unpublished').prop('checked')){ + if(!confirm('<%= I18n.t('exercises.form.unpublish_warning') %>')){ + $('#exercise_unpublished').prop('checked', false); + } + } else if($('#exercise_execution_environment_id').val() == '') { + alert('<%= I18n.t('exercises.form.no_execution_environment_selected') %>'); + $('#exercise_unpublished').prop('checked', true); + } + }) + + }; var overrideTextareaTabBehavior = function() { $('.form-group textarea[name$="[content]"]').on('keydown', function(event) { @@ -271,6 +300,8 @@ $(document).on('turbolinks:load', function() { enableInlineFileCreation(); inferFileAttributes(); observeFileRoleChanges(); + observeExecutionEnvironment(); + observeUnpublishedState(); overrideTextareaTabBehavior(); } else if ($('#files.jstree').isPresent()) { var fileTypeSelect = $('#code_ocean_file_file_type_id'); diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index d3a5b31c..d3d98675 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -160,7 +160,7 @@ class ExercisesController < ApplicationController private :user_by_codeharbor_token def exercise_params - params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :allow_file_creation, :allow_auto_completion, :title, :expected_difficulty, files_attributes: file_attributes, :tag_ids => []).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:exercise].present? + params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :unpublished, :hide_file_tree, :allow_file_creation, :allow_auto_completion, :title, :expected_difficulty, files_attributes: file_attributes, :tag_ids => []).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:exercise].present? end private :exercise_params @@ -182,6 +182,7 @@ class ExercisesController < ApplicationController private :handle_file_uploads def implement + redirect_to(@exercise, alert: t('exercises.implement.unpublished')) if @exercise.unpublished? # TODO TESTESTEST redirect_to(@exercise, alert: t('exercises.implement.no_files')) unless @exercise.files.visible.exists? user_solved_exercise = @exercise.has_user_solved(current_user) count_interventions_today = UserExerciseIntervention.where(user: current_user).where("created_at >= ?", Time.zone.now.beginning_of_day).count diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 71ec0afb..bf4364db 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -31,7 +31,7 @@ class Exercise < ApplicationRecord validate :valid_main_file? validates :description, presence: true - validates :execution_environment_id, presence: true, if: -> { !unpublished? } # TODO make this conditional - but based on what? + validates :execution_environment_id, presence: true, if: -> { !unpublished? } validates :public, boolean_presence: true validates :unpublished, boolean_presence: true validates :title, presence: true diff --git a/app/views/exercises/_form.html.slim b/app/views/exercises/_form.html.slim index b6d0980b..d9ad42f6 100644 --- a/app/views/exercises/_form.html.slim +++ b/app/views/exercises/_form.html.slim @@ -11,7 +11,7 @@ = f.pagedown :description, input_html: { preview: true, rows: 10 } .form-group = f.label(:execution_environment_id) - = f.collection_select(:execution_environment_id, @execution_environments, :id, :name, {}, class: 'form-control') + = f.collection_select(:execution_environment_id, @execution_environments, :id, :name, {include_blank: 'None'}, class: 'form-control') /.form-group = f.label(:instructions) = f.hidden_field(:instructions) @@ -20,6 +20,10 @@ label.form-check-label = f.check_box(:public, class: 'form-check-input') = t('activerecord.attributes.exercise.public') + .form-check + label.form-check-label + = f.check_box(:unpublished, class: 'form-check-input') + = t('activerecord.attributes.exercise.unpublished') .form-check label.form-check-label = f.check_box(:hide_file_tree, class: 'form-check-input') @@ -66,4 +70,4 @@ ul#dummies.d-none = f.fields_for(:files, CodeOcean::File.new, child_index: 'index') do |files_form| = render('file_form', f: files_form) - .actions = render('shared/submit_button', f: f, object: @exercise) \ No newline at end of file + .actions = render('shared/submit_button', f: f, object: @exercise) diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index b75417c7..cd56fff1 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -16,6 +16,7 @@ h1 /= row(label: 'exercise.instructions', value: render_markdown(@exercise.instructions)) = row(label: 'exercise.maximum_score', value: @exercise.maximum_score) = row(label: 'exercise.public', value: @exercise.public?) += row(label: 'exercise.unpublished', value: @exercise.unpublished?) = row(label: 'exercise.hide_file_tree', value: @exercise.hide_file_tree?) = row(label: 'exercise.allow_file_creation', value: @exercise.allow_file_creation?) = row(label: 'exercise.allow_auto_completion', value: @exercise.allow_auto_completion?) @@ -23,7 +24,7 @@ h1 = row(label: 'exercise.uuid', value: @exercise.uuid) = row(label: 'exercise.tags', value: @exercise.exercise_tags.map{|et| "#{et.tag.name} (#{et.factor})"}.sort.join(", ")) = row(label: 'exercise.embedding_parameters', class: 'mb-4') do - = content_tag(:input, nil, class: 'form-control mb-4', readonly: true, value: embedding_parameters(@exercise)) + = content_tag(:input, nil, class: 'form-control mb-4', readonly: true, value: @exercise.unpublished? ? 'Exercise is unpublished' : embedding_parameters(@exercise)) h2.mt-4 = t('activerecord.attributes.exercise.files') diff --git a/config/locales/en.yml b/config/locales/en.yml index 493dd631..881af49e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -45,6 +45,7 @@ en: difficulty: Difficulty token: "Exercise Token" uuid: UUID + unpublished: Unpublished proxy_exercise: title: Title files_count: Exercises Count @@ -332,6 +333,8 @@ en: add_file: Add file tags: "Tags" click_to_collapse: "Click to expand/collapse..." + unpublish_warning: This will unpublish the exercise. Any student trying to implement it will get an error message, until it is published again. + no_execution_environment_selected: Select an execution environment before publishing the exercise. implement: alert: text: 'Your browser does not support features required for using %{application_name}. Please access %{application_name} using a modern browser.'