Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Break: Can set visible after for lesson #33869

Merged
merged 10 commits into from
Mar 31, 2020
14 changes: 14 additions & 0 deletions dashboard/app/controllers/scripts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ def show
@section = current_user&.sections&.find_by(id: params[:section_id])&.summarize
sections = current_user.try {|u| u.sections.where(hidden: false).select(:id, :name, :script_id, :course_id)}
@sections_with_assigned_info = sections&.map {|section| section.attributes.merge!({"isAssigned" => section[:script_id] == @script.id})}

# Warn levelbuilder if a lesson will not be visible to users because 'visible_after' is set to a future day
if current_user && current_user.levelbuilder?
notice_text = ""
@script.stages.each do |stage|
dmcavoy marked this conversation as resolved.
Show resolved Hide resolved
next unless stage.visible_after && Time.parse(stage.visible_after) > Time.now

formatted_time = Time.parse(stage.visible_after).strftime("%I:%M %p %A %B %d %Y %Z")
num_days_away = ((Time.parse(stage.visible_after) - Time.now) / 1.day).ceil.to_s
lesson_visible_after_message = "The lesson #{stage.name} will be visible after #{formatted_time} (#{num_days_away} Days)"
notice_text = notice_text.empty? ? lesson_visible_after_message : "#{notice_text} <br/> #{lesson_visible_after_message}"
end
flash[:notice] = notice_text.html_safe
end
end

def index
Expand Down
19 changes: 19 additions & 0 deletions dashboard/app/dsl/script_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def initialize
@stage = nil
@stage_flex_category = nil
@stage_lockable = false
@stage_visible_after = nil
@concepts = []
@skin = nil
@current_scriptlevel = nil
Expand Down Expand Up @@ -82,19 +83,36 @@ def stage(name, properties = {})
if @stage
@stages << {
stage: @stage,
visible_after: @stage_visible_after,
scriptlevels: @scriptlevels,
stage_extras_disabled: @stage_extras_disabled,
}.compact
end
@stage = name
@stage_flex_category = properties[:flex_category]
@stage_lockable = properties[:lockable]
@stage_visible_after = determine_visible_after_time(properties[:visible_after])
@scriptlevels = []
@concepts = []
@skin = nil
@stage_extras_disabled = nil
end

# If visible_after value is blank default to next wednesday at 8am PDT
# Otherwise use the supplied time
def determine_visible_after_time(visible_after_value)
if visible_after_value == ''
current_time = Time.now
raw_diff_to_wed = 3 - current_time.wday
# Make sure it is the next wednesday not the one that just passed
diff_to_next_wed = raw_diff_to_wed % 7
next_wednesday = current_time + diff_to_next_wed.day
visible_after_value = Time.new(next_wednesday.year, next_wednesday.month, next_wednesday.day, 8, 0, 0, '-07:00').to_s
end

visible_after_value
end

def parse_output
stage(nil)
{
Expand Down Expand Up @@ -314,6 +332,7 @@ def self.serialize_stages(script)
t = "stage '#{escape(stage.name)}'"
t += ', lockable: true' if stage.lockable
t += ", flex_category: '#{escape(stage.flex_category)}'" if stage.flex_category
t += ", visible_after: '#{escape(stage.visible_after)}'" if stage.visible_after
s << t
stage.script_levels.each do |sl|
type = 'level'
Expand Down
1 change: 1 addition & 0 deletions dashboard/app/models/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,7 @@ def self.add_script(options, raw_stages, new_suffix: nil, editor_experiment: nil

raw_stage = raw_stages.find {|rs| rs[:stage].downcase == stage.name.downcase}
stage.stage_extras_disabled = raw_stage[:stage_extras_disabled]
stage.visible_after = raw_stage[:visible_after]
stage.save! if stage.changed?
end

Expand Down
1 change: 1 addition & 0 deletions dashboard/app/models/stage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Stage < ActiveRecord::Base

serialized_attrs %w(
stage_extras_disabled
visible_after
)

# A stage has an absolute position and a relative position. The difference between the two is that relative_position
Expand Down
64 changes: 64 additions & 0 deletions dashboard/test/controllers/scripts_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -542,4 +542,68 @@ class ScriptsControllerTest < ActionController::TestCase
assert elements.first['data-levelbuildereditscript'].match?(/"beta":false/)
end
end

test "levelbuilder does not see visible after warning if stage does not have visible_after property" do
sign_in @levelbuilder

get :show, params: {id: 'course1'}
assert_response :success
refute response.body.include? 'The lesson Stage 1 will be visible after'
end

test "levelbuilder does not see visible after warning if stage has visible_after property that is in the past" do
Timecop.freeze(Time.new(2020, 4, 2))
sign_in @levelbuilder

create(:level, name: "Level 1")
script_file = File.join(self.class.fixture_path, "test-fixture-visible-after.script")
Script.setup([script_file])

get :show, params: {id: 'test-fixture-visible-after'}
assert_response :success
refute response.body.include? 'The lesson Stage 1 will be visible after'
Timecop.return
end

test "levelbuilder sees visible after warning if stage has visible_after property that is in the future" do
Timecop.freeze(Time.new(2020, 3, 27))
sign_in @levelbuilder

create(:level, name: "Level 1")
script_file = File.join(self.class.fixture_path, "test-fixture-visible-after.script")
Script.setup([script_file])

get :show, params: {id: 'test-fixture-visible-after'}
assert_response :success
assert response.body.include? 'The lesson Stage 1 will be visible after'
Timecop.return
end

test "student does not see visible after warning if stage has visible_after property" do
Timecop.freeze(Time.new(2020, 3, 27))
sign_in create(:student)

create(:level, name: "Level 1")
script_file = File.join(self.class.fixture_path, "test-fixture-visible-after.script")
Script.setup([script_file])

get :show, params: {id: 'test-fixture-visible-after'}
assert_response :success
refute response.body.include? 'The lesson Stage 1 will be visible after'
Timecop.return
end

test "teacher does not see visible after warning if stage has visible_after property" do
Timecop.freeze(Time.new(2020, 3, 27))
sign_in create(:teacher)

create(:level, name: "Level 1")
script_file = File.join(self.class.fixture_path, "test-fixture-visible-after.script")
Script.setup([script_file])

get :show, params: {id: 'test-fixture-visible-after'}
assert_response :success
refute response.body.include? 'The lesson Stage 1 will be visible after'
Timecop.return
end
end
66 changes: 66 additions & 0 deletions dashboard/test/dsl/script_dsl_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,72 @@ def setup
assert_equal expected, output
end

test 'Script DSL with blank stage visible after date with set visible after to next wednesday at 8 am PST' do
Timecop.freeze(Time.new(2020, 3, 27))

input_dsl = <<~DSL
stage 'Stage1', visible_after: ''
level 'Level 1'
level 'Level 2'
DSL
expected = DEFAULT_PROPS.merge(
{
stages: [
{
stage: "Stage1",
visible_after: '2020-04-01 08:00:00 -0700',
scriptlevels: [
{stage: "Stage1", levels: [{name: "Level 1"}]},
{stage: "Stage1", levels: [{name: "Level 2"}]},
]
}
]
}
)

output, _ = ScriptDSL.parse(input_dsl, 'test.script', 'test')
assert_equal expected, output
Timecop.return
end

test 'Script DSL with stage visible after date' do
input_dsl = <<~DSL
stage 'Stage1', visible_after: '2020-04-01 10:00:00 -0700'
level 'Level 1'
level 'Level 2'
DSL
expected = DEFAULT_PROPS.merge(
{
stages: [
{
stage: "Stage1",
visible_after: '2020-04-01 10:00:00 -0700',
scriptlevels: [
{stage: "Stage1", levels: [{name: "Level 1"}]},
{stage: "Stage1", levels: [{name: "Level 2"}]},
]
}
]
}
)

output, _ = ScriptDSL.parse(input_dsl, 'test.script', 'test')
assert_equal expected, output
end

test 'serialize visible after for stage' do
level = create :maze, name: 'maze 1', level_num: 'custom'
script = create :script, hidden: true
stage = create :stage, name: 'stage 1', script: script, visible_after: '2020-04-01 08:00:00 -0800'
script_level = create :script_level, levels: [level], stage: stage, script: script
script_text = ScriptDSL.serialize_to_string(script_level.script)
expected = <<~SCRIPT
stage 'stage 1', visible_after: '2020-04-01 08:00:00 -0800'
level 'maze 1'
SCRIPT
assert_equal expected, script_text
end

test 'Script DSL with project_sharing' do
input_dsl = 'project_sharing true'
expected = DEFAULT_PROPS.merge(
Expand Down
2 changes: 2 additions & 0 deletions dashboard/test/fixtures/test-fixture-visible-after.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
stage 'Stage 1', visible_after: '2020-04-01 08:00:00 -0700'
level 'Level 1'