diff --git a/app/models/assignment.rb b/app/models/assignment.rb old mode 100644 new mode 100755 index efa0c457329..0dd2dbd1e61 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -11,6 +11,7 @@ class Assignment < ApplicationRecord include ReviewAssignment include QuizAssignment include AssignmentHelper + include DueDateMixIn has_paper_trail # When an assignment is created, it needs to # be created as an instance of a subclass of the Assignment (model) class; @@ -186,38 +187,6 @@ def path path_text end - # Check whether review, metareview, etc.. is allowed - # The permissions of TopicDueDate is the same as AssignmentDueDate. - # Here, column is usually something like 'review_allowed_id' - def check_condition(column, topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return false if next_due_date.nil? - - right_id = next_due_date.send column - right = DeadlineRight.find(right_id) - right && (right.name == 'OK' || right.name == 'Late') - end - - # Determine if the next due date from now allows for submissions - def submission_allowed(topic_id = nil) - check_condition('submission_allowed_id', topic_id) - end - - # Determine if the next due date from now allows to take the quizzes - def quiz_allowed(topic_id = nil) - check_condition('quiz_allowed_id', topic_id) - end - - # Determine if the next due date from now allows for reviews - def can_review(topic_id = nil) - check_condition('review_allowed_id', topic_id) - end - - # Determine if the next due date from now allows for metareviews - def metareview_allowed(topic_id = nil) - check_condition('review_of_review_allowed_id', topic_id) - end - # Deletes all instances created as part of assignment and finally destroys itself. def delete(force = nil) begin @@ -294,15 +263,6 @@ def create_node node.save end - # if current stage is submission or review, find the round number - # otherwise, return 0 - def number_of_current_round(topic_id) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 0 if next_due_date.nil? - - next_due_date.round ||= 0 - end - # For varying rubric feature def current_stage_name(topic_id = nil) if staggered_deadline? @@ -323,17 +283,6 @@ def varying_rubrics_by_round? AssignmentQuestionnaire.where(assignment_id: id, used_in_round: 2).size > 1 end - def link_for_current_stage(topic_id = nil) - return nil if staggered_and_no_topic?(topic_id) - - due_date = find_current_stage(topic_id) - if due_date.nil? || (due_date == 'Finished') || due_date.is_a?(TopicDueDate) - return nil - end - - due_date.description_url - end - def stage_deadline(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -341,22 +290,6 @@ def stage_deadline(topic_id = nil) due_date.nil? || due_date == 'Finished' ? due_date : due_date.due_at.to_s end - def num_review_rounds - due_dates = AssignmentDueDate.where(parent_id: id) - rounds = 0 - due_dates.each do |due_date| - rounds = due_date.round if due_date.round > rounds - end - rounds - end - - def find_current_stage(topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 'Finished' if next_due_date.nil? - - next_due_date - end - # Zhewei: this method is almost the same as 'stage_deadline' def current_stage(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -566,39 +499,6 @@ def self.export_fields(options) fields end - def find_due_dates(type) - due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } - end - - # Method find_review_period is used in answer_helper.rb to get the start and end dates of a round - def find_review_period(round) - # If round is nil, it means the same questionnaire is used for every round. Thus, we return all periods. - # If round is not nil, we return only the period of that round. - - submission_type = DeadlineType.find_by(name: 'submission').id - review_type = DeadlineType.find_by(name: 'review').id - - due_dates = [] - due_dates += find_due_dates('submission') - due_dates += find_due_dates('review') - due_dates.sort_by!(&:id) - - start_dates = [] - end_dates = [] - - if round.nil? - round = 1 - while self.due_dates.exists?(round: round) - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - round += 1 - end - else - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - end - [start_dates, end_dates] - end # for program 1 like assignment, if same rubric is used in both rounds, # the 'used_in_round' field in 'assignment_questionnaires' will be null, diff --git a/app/views/sign_up_sheet/review_bids_others_work.html.erb b/app/views/sign_up_sheet/review_bids_others_work.html.erb index bb6d95c3cfa..539406b588a 100644 --- a/app/views/sign_up_sheet/review_bids_others_work.html.erb +++ b/app/views/sign_up_sheet/review_bids_others_work.html.erb @@ -67,7 +67,7 @@ <% last_response_round = @latest_response.round %> <%end%> - <% current_round = @assignment.number_of_current_round(topic_id) %> + <% current_round = @assignment.number_of_current_round(@participant.user_id) %> <%= link_to "View", {:controller => 'response', :action => 'view', :id => @latest_response.id} %> diff --git a/app/views/student_review/list.html.erb b/app/views/student_review/list.html.erb index ccd4a49c43c..28fa08f45f8 100755 --- a/app/views/student_review/list.html.erb +++ b/app/views/student_review/list.html.erb @@ -21,7 +21,7 @@ <%= render :partial => 'responses', :locals => {:mappings => @review_mappings, :title => 'Review'} %> - <% if @assignment.staggered_deadline? or @assignment.number_of_current_round(@topic_id) == 1 or (@assignment.number_of_current_round(@topic_id) > 1 and @assignment.allow_selecting_additional_reviews_after_1st_round) %> + <% if @assignment.staggered_deadline? or @assignment.number_of_current_round(@participant.user_id) == 1 or (@assignment.number_of_current_round(@participant.user_id) > 1 and @assignment.allow_selecting_additional_reviews_after_1st_round) %> <% if @assignment.dynamic_reviewer_assignment? %> <% if @num_reviews_in_progress >= Assignment.max_outstanding_reviews %>

diff --git a/app/views/student_task/view.html.erb b/app/views/student_task/view.html.erb index 06407fcd03f..396a671ff6e 100644 --- a/app/views/student_task/view.html.erb +++ b/app/views/student_task/view.html.erb @@ -27,7 +27,7 @@ <% if @use_bookmark %>
  • - <% if @topic_id and @assignment.submission_allowed(@topic_id) %> + <% if @topic_id and @assignment.submission_allowed(@participant.user_id) %> <%= link_to "View bookmarks", :controller=>'bookmarks', :action=> 'list', :id => @topic_id %> <%=t ".view_bookmarks_lengthy" %> <% else %> <%=t ".view_bookmarks" %><%=t ".choose_topic" %> @@ -53,14 +53,14 @@ to display the label "Your team" in the student assignment tasks-->
  • <% if @team %> <% if @topics.size > 0 %> - <% if @topic_id && @assignment.submission_allowed(@topic_id) %> + <% if @topic_id && @assignment.submission_allowed(@participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".choose_topic" %> <% end %> <% else %> - <% if @assignment.submission_allowed(@topic_id) %> + <% if @assignment.submission_allowed(@participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".not_allowed" %> @@ -105,7 +105,7 @@ to display the label "Your team" in the student assignment tasks--> <%if @assignment.require_quiz%> <% if @authorization == 'participant' or @can_take_quiz == true %>
  • - <% if @assignment.require_quiz and (@assignment.quiz_allowed(@topic_id) or @assignment.current_stage(@topic_id) == "Finished") %> + <% if @assignment.require_quiz and (@assignment.quiz_allowed(@participant.user_id) or @assignment.current_stage(@topic_id) == "Finished") %> <%= link_to t(".take_quizzes"), student_quizzes_path(:id => @participant.id) %> <% else %> <%=t ".take_quizzes" %> diff --git a/app/views/submitted_content/_self_review.html.erb b/app/views/submitted_content/_self_review.html.erb index 32073e13423..9e05c654a4b 100644 --- a/app/views/submitted_content/_self_review.html.erb +++ b/app/views/submitted_content/_self_review.html.erb @@ -36,7 +36,7 @@ <% last_response_round = @latest_response.round %> <% end %> - <% current_round = @assignment.number_of_current_round(@topic_id) %> + <% current_round = @assignment.number_of_current_round(@participant.user_id) %>    <%= link_to 'View', {:controller => 'response', :action => 'view', :id => @latest_response.id} %> diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb new file mode 100755 index 00000000000..3edeec31b7f --- /dev/null +++ b/lib/due_date_mix_in.rb @@ -0,0 +1,143 @@ +# frozen_String_literal: true + +# lib/due_date_mix_in.rb +module DueDateMixIn + # finds the topic_id given the participant user_id + def find_topic_id(participant_id) + topic_id = if participant_id.nil? + nil + else + SignedUpTeam.topic_id(id, participant_id) + end + end + + # Determine if the next due date from now allows for submissions + def submission_allowed(participant_id = nil) + # Find topic id for given participant for selected assignment + # Return nil if no participant is given + topic_id = find_topic_id(participant_id) + # only need to pass @participiant to search, can this be done locally + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.submission_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') + end + + # Determine if the next due date from now allows for reviews + # Should be renamed to review_allowed from can_review + def can_review(participant_id = nil) + topic_id = find_topic_id(participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.review_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') + end + + # Determine if the next due date from now allows for metareviews + def metareview_allowed(participant_id = nil) + topic_id = find_topic_id(participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.review_of_review_allowed_id # meta-review id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') + end + + # Determine if the next due date from now allows to take the quizzes + def quiz_allowed(participant_id = nil) + topic_id = find_topic_id(participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.quiz_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') + end + + # if current stage is submission or review, find the round number + # otherwise, return 0 + def number_of_current_round(participant_id = nil) + topic_id = find_topic_id(participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return 0 if next_due_date.nil? + + next_due_date.round ||= 0 + end + + def link_for_current_stage(topic_id = nil) + return nil if staggered_and_no_topic?(topic_id) + + due_date = find_current_stage(topic_id) + if due_date.nil? || (due_date == 'Finished') || due_date.is_a?(TopicDueDate) + return nil + end + + due_date.description_url + end + + def num_review_rounds + due_dates = AssignmentDueDate.where(parent_id: id) + rounds = 0 + due_dates.each do |due_date| + rounds = due_date.round if due_date.round > rounds + end + rounds + end + + def find_current_stage(participant_id = nil) + topic_id = find_topic_id(participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return 'Finished' if next_due_date.nil? + + next_due_date + end + + def find_due_dates(type) + due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } + end + + # Method find_review_period is used in answer_helper.rb to get the start and end dates of a round + def find_review_period(round) + # If round is nil, it means the same questionnaire is used for every round. Thus, we return all periods. + # If round is not nil, we return only the period of that round. + + submission_type = DeadlineType.find_by(name: 'submission').id + review_type = DeadlineType.find_by(name: 'review').id + + due_dates = [] + due_dates += find_due_dates('submission') + due_dates += find_due_dates('review') + due_dates.sort_by!(&:id) + + start_dates = [] + end_dates = [] + + if round.nil? + round = 1 + while self.due_dates.exists?(round: round) + start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last + end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last + round += 1 + end + else + start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last + end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last + end + [start_dates, end_dates] + end + + # END OF MODULE # +end diff --git a/spec/lib/due_date_mix_in_test.rb b/spec/lib/due_date_mix_in_test.rb new file mode 100644 index 00000000000..444bb60a67b --- /dev/null +++ b/spec/lib/due_date_mix_in_test.rb @@ -0,0 +1,73 @@ +describe Assignment do + let(:assignment) { build(:assignment, id: 1, name: 'no assignment', participants: [participant], teams: [team], max_team_size: 2) } + let(:instructor) { build(:instructor, id: 6) } + let(:student) { build(:student, id: 3, name: 'no one') } + let(:review_response_map) { build(:review_response_map, response: [response], reviewer: build(:participant), reviewee: build(:assignment_team)) } + let(:teammate_review_response_map) { build(:review_response_map, type: 'TeammateReviewResponseMap') } + let(:participant) { build(:participant, id: 1) } + let(:question) { double('Question') } + let(:team) { build(:assignment_team, id: 1, name: 'no team') } + let(:response) { build(:response) } + let(:course) { build(:course) } + let(:assignment_due_date) do + build(:assignment_due_date, due_at: '2011-11-11 11:11:11', deadline_name: 'Review', + description_url: 'https://expertiza.ncsu.edu/', round: 1) + end + let(:topic_due_date) { build(:topic_due_date, deadline_name: 'Submission', description_url: 'https://github.com/expertiza/expertiza') } + let(:deadline_type) { build(:deadline_type, id: 1) } + let(:assignment_questionnaire1) { build(:assignment_questionnaire, id: 1, assignment_id: 1, questionnaire_id: 1) } + let(:assignment_questionnaire2) { build(:assignment_questionnaire, id: 2, assignment_id: 1, questionnaire_id: 2) } + let(:questionnaire1) { build(:questionnaire, id: 1, type: 'ReviewQuestionnaire') } + let(:questionnaire2) { build(:questionnaire, id: 2, type: 'MetareviewQuestionnaire') } + + describe '#submission_allowed' do + it 'returns true when the next topic due date is allowed to submit sth' do + #allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) + #expect(assignment.submission_allowed(123)).to be true + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:submission_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.submission_allowed(1)).to be true + end + end + + describe '#quiz_allowed' do + it 'returns false when the next topic due date is not allowed to do quiz' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:quiz_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.quiz_allowed(1)).to be true + end + end + + describe '#metareview_allowed' do + it 'returns true when the next assignment due date is not allowed to do metareview' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:review_of_review_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.metareview_allowed(1)).to be true + end + end + + describe '#can_review' do + it 'returns true when the next assignment due date is not allowed to do metareview' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:review_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.can_review(1)).to be true + end + end + +end diff --git a/spec/models/assignment_spec.rb b/spec/models/assignment_spec.rb index 0bb5f50fb12..0c27ac1947e 100644 --- a/spec/models/assignment_spec.rb +++ b/spec/models/assignment_spec.rb @@ -245,53 +245,6 @@ end end - describe '#check_condition' do - context 'when the next due date is nil' do - it 'returns false ' do - allow(DueDate).to receive(:get_next_due_date).with(1, nil).and_return(nil) - expect(assignment.check_condition('review_allowed_id')).to be false - end - end - - context 'when the next due date is allowed to review submissions' do - it 'returns true' do - assignment_due_date = double('AssignmentDueDate') - allow(DueDate).to receive(:get_next_due_date).with(1, nil).and_return(assignment_due_date) - allow(assignment_due_date).to receive(:send).with('review_allowed_id').and_return(1) - allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) - expect(assignment.check_condition('review_allowed_id')).to be true - end - end - end - - describe '#submission_allowed' do - it 'returns true when the next topic due date is allowed to submit sth' do - allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) - expect(assignment.submission_allowed(123)).to be true - end - end - - describe '#quiz_allowed' do - it 'returns false when the next topic due date is not allowed to do quiz' do - allow(assignment).to receive(:check_condition).with('quiz_allowed_id', 456).and_return(false) - expect(assignment.quiz_allowed(456)).to be false - end - end - - describe '#can_review' do - it "returns false when the next assignment due date is not allowed to review other's work" do - allow(assignment).to receive(:check_condition).with('review_allowed_id', nil).and_return(true) - expect(assignment.can_review).to be true - end - end - - describe '#metareview_allowed' do - it 'returns true when the next assignment due date is not allowed to do metareview' do - allow(assignment).to receive(:check_condition).with(any_args).and_return(false) - expect(assignment.metareview_allowed).to be false - end - end - describe '#delete' do before(:each) do allow(ReviewResponseMap).to receive(:where).with(reviewed_object_id: 1).and_return([review_response_map])