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

Allow deletion of Assignment's with no groups #6880

Merged
merged 30 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
22ad13b
Add #destroy action for Assignment api controller
mimischly7 Dec 24, 2023
e6fdc5e
Refining #destroy action and related rspec tests
mimischly7 Dec 24, 2023
5fd31f2
finishing-details
mimischly7 Dec 24, 2023
fe7dfd6
update-changelog
mimischly7 Dec 24, 2023
351a03a
merge-with-upstream
mimischly7 Jan 6, 2024
fdef002
assignment-destroy-with-associations
mimischly7 Jan 6, 2024
be27f1d
fix-small-i18-problem
mimischly7 Jan 6, 2024
e74d214
Merge branch 'master' into assignment-destroy-task-pt2
mimischly7 Jan 26, 2024
3b89441
destroy-action-in-Assignments-controller
mimischly7 Jan 26, 2024
c6aa66d
create-red-button-for-deleting-assignments
mimischly7 Jan 26, 2024
d69dbb4
css-class-for-assignment-delete-button
mimischly7 Jan 26, 2024
0aadea0
conditional-rendering-correction
mimischly7 Jan 26, 2024
b183f66
Merge branch 'master' of github.com:MarkUsProject/Markus into assignm…
mimischly7 Feb 2, 2024
d2052e5
feat: flash message for successful deletion of assignment
mimischly7 Feb 2, 2024
83170fc
error handling in assignments#destroy
mimischly7 Feb 2, 2024
e539b81
tests-for-assignment#destroy
mimischly7 Feb 2, 2024
0e1d8b3
Merge branch 'master' of github.com:MarkUsProject/Markus into assignm…
mimischly7 Feb 7, 2024
742ba72
destroy-button-improvements
mimischly7 Feb 7, 2024
b2cb58b
updating-changelog
mimischly7 Feb 7, 2024
23da554
fix-changelog
mimischly7 Feb 7, 2024
ead7c57
Merge branch 'master' of github.com:MarkUsProject/Markus into assignm…
mimischly7 Feb 9, 2024
8d8a896
Merge branch 'master' of github.com:MarkUsProject/Markus into assignm…
mimischly7 Feb 12, 2024
70ab805
applying-feedback
mimischly7 Feb 12, 2024
05f3734
removing-redundant-assertion
mimischly7 Feb 12, 2024
b612a5a
Merge branch 'master' into assignment-destroy-task
mimischly7 Feb 15, 2024
3779d5e
merge-master
mimischly7 Feb 16, 2024
23e21d3
applying-feedback
mimischly7 Feb 16, 2024
90603ac
Merge branch 'assignment-destroy-task' of github.com:mimischly7/Marku…
mimischly7 Feb 16, 2024
6540253
normalizing-i18
mimischly7 Feb 16, 2024
ae96585
removing-unused-locales
mimischly7 Feb 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## [unreleased]
- Allow deletion of assignments with no groups (#6880)

## [v2.4.5]
- Add workaround for CSP in Safari < 16 (#6947)
Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/common/_markus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ button,
}
}

#assignment-delete {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay this is better, but (1) make it a class, and (2) call the class danger-button, which is more general.

background: $severe-error;
color: $background-main;
font-weight: bold;
}

/** Fieldset */

fieldset {
Expand Down
18 changes: 18 additions & 0 deletions app/controllers/api/assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,24 @@ def submit_file
upload_file(grouping, only_required_files: assignment.only_required_files)
end

def destroy
assignment = record
if assignment.nil?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check isn't necessary, you can remove it. The check_record helper is sufficient to check for this

render 'shared/http_status', locals: { code: '404', message:
I18n.t('assignments.assignment_not_found',
invalid_id: assignment_id) }, status: :not_found
else
begin
assignment.destroy
render 'shared/http_status',
locals: { code: '200', message: I18n.t('assignments.successful_deletion') }, status: :ok
rescue ActiveRecord::DeleteRestrictionError
render 'shared/http_status',
locals: { code: :conflict, message: I18n.t('assignments.assignment_has_groupings') }, status: :conflict
end
end
end

protected

def implicit_authorization_target
Expand Down
11 changes: 11 additions & 0 deletions app/controllers/assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,17 @@ def lti_settings
render layout: 'assignment_content'
end

def destroy
@assignment = @record
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use record (as with the other methods)

begin
@assignment.destroy
respond_with @assignment, location: -> { course_assignments_path(current_course, @assignment) }
rescue ActiveRecord::DeleteRestrictionError
flash_message(:error, I18n.t('assignments.assignment_has_groupings'))
redirect_back fallback_location: { action: :edit, id: @assignment.id }
end
end

private

# Configures the automated test files and settings for an +assignment+ provided in the +zip_file+
Expand Down
2 changes: 1 addition & 1 deletion app/models/assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Assignment < Assessment
has_many :student_memberships, through: :groupings

has_many :submissions, through: :groupings
has_many :groups, through: :groupings
has_many :groups, through: :groupings, dependent: :restrict_with_exception

has_many :notes, as: :noteable, dependent: :destroy

Expand Down
18 changes: 18 additions & 0 deletions app/views/assignments/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,22 @@
data: { disable_with: t('working') } %>
</p>
<% end %>

<% if (action_name=="edit") %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If statements don't need parentheses in Ruby. Also, put spaces around ==

<% has_groups = @assignment.groups.length != 0 %>
<%= button_to t(:delete),
course_assignment_path(@current_course, @assignment),
{
data: { confirm: "Are you sure you want to delete this assignment?" },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string also needs to be internationalized

method: 'delete',
class: has_groups ? nil : 'button',
id: has_groups ? nil : 'assignment-delete',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following my above comment, don't use an id here, instead conditionally add a second class to 'button' above

form_class: 'display-inline-block',
title: has_groups ? I18n.t('assignments.assignment_has_groupings') :
I18n.t('helpers.submit.delete', model: Assignment.model_name.human),
disabled: has_groups
}
%>
<%end %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a space missing after the <%


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete this line

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line hasn't been deleted

<% end %>
3 changes: 3 additions & 0 deletions config/locales/views/assignments/en.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
en:
assignments:
assignment_has_groupings: Assignment has groupings.
assignment_not_found: No assignment with id '%{invalid_id}'.
average_annotations: "%{average_annotations} annotations per marked submission"
configuration_zip_file: Configuration Zip File
deadline_with_extension: You have an extension until %{extension_deadline}.
Expand Down Expand Up @@ -63,6 +65,7 @@ en:
title: Starter Files
upload_confirmation: The starter files for this assignment have changed since you last downloaded them. Are you sure you want to continue?
use_original_filename: Use original filename
successful_deletion: Assignment with id '%{invalid_id}' has been successfully deleted.
timed:
before_start_instructions: Once you start this timed assessment, you will have %{duration_string} to complete it without penalty.
before_start_instructions_extension: Once you start this timed assessment, you will have %{duration_string} to complete it without penalty (this includes a duration extension of %{extension_string}).
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@

resources :annotation_categories, only: [:show, :destroy, :update]

resources :assignments, except: [:destroy] do
resources :assignments do
collection do
get 'delete_rejected'
get 'batch_runs'
Expand Down
48 changes: 48 additions & 0 deletions spec/controllers/api/assignments_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@
put :update, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(403)
end

it 'should fail to authenticate a DELETE destroy request' do
delete :destroy, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(403)
end
end

context 'An authenticated instructor request requesting' do
Expand Down Expand Up @@ -502,6 +507,35 @@
expect(response).to have_http_status(403)
end
end
context 'DELETE assignment' do
it 'should successfully delete assignment because the assignment has no groups' do
assignment # since lazy let is used for creating an assignment, I invoke it here to trigger its execution
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't necessary, as assignment is immediately used on the next line

expect(assignment.groups).to be_empty
delete :destroy, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(200)
expect(Assignment.exists?(assignment.id)).to eq(false)
end
it 'fails to delete assignment because assignment has groups' do
assignment # since lazy let is used for creating an assignment, I invoke it here to trigger its execution
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above

# creates a grouping (and thus a group) for the assignment
create :grouping, assignment: assignment, start_time: nil
expect(assignment.groups).to_not be_empty
original_size = Assignment.all.length
delete :destroy, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(409)
expect(Assignment.all.length).to eq(original_size)
expect(assignment.persisted?).to eq(true)
end
it 'fails to delete assignment because of invalid id' do
assignment # since lazy let is used for creating an assignment, I invoke it here to trigger its execution
original_size = Assignment.all.length
# Since we only have one assignment, it is guaranteed that assignment.id + 1 is an invalid id
delete :destroy, params: { id: assignment.id + 1, course_id: course.id }
expect(response).to have_http_status(404)
expect(Assignment.all.length).to eq(original_size)
expect(assignment.persisted?).to eq(true)
end
end
end

context 'An authenticated student request' do
Expand Down Expand Up @@ -670,6 +704,13 @@
end
end
end

context 'DELETE destroy' do
it 'should fail to authenticate a DELETE destroy request' do
delete :destroy, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(403)
end
end
end

context 'An authenticated ta request' do
Expand Down Expand Up @@ -704,5 +745,12 @@
end
end
end

context 'DELETE destroy' do
it 'should fail to authenticate a DELETE destroy request' do
delete :destroy, params: { id: assignment.id, course_id: course.id }
expect(response).to have_http_status(403)
end
end
end
end
28 changes: 28 additions & 0 deletions spec/controllers/assignments_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2038,4 +2038,32 @@
expect(response).to have_http_status(200)
end
end

context '#destroy' do
let!(:instructor) { create :instructor }
let!(:course) { instructor.course }
let!(:assignment) { create :assignment }
let(:grouping) { create :grouping, assignment: assignment }
it 'should fail to DELETE because of unauthorized request' do
delete :destroy, params: { course_id: course.id, id: assignment.id }
expect(Assignment.exists?(assignment.id)).to be(true)
end
it 'should fail to DELETE because assignment has groups' do
grouping # lazy initialization
delete_as instructor, :destroy, params: { course_id: course.id, id: assignment.id }
expect(Assignment.exists?(assignment.id)).to be(true)
expect(flash[:error]).to eq(["<p>#{I18n.t('assignments.assignment_has_groupings')}</p>"])
expect(flash.to_hash.length).to eq(1)
expect(flash[:error].length).to eq(1)
expect(response).to have_http_status(302)
end
it 'should successfully DELETE assignment (no groups)' do
delete_as instructor, :destroy, params: { course_id: course.id, id: assignment.id }
expect(Assignment.exists?(assignment.id)).to be(false)
expect(flash[:success]).to eq(I18n.t('flash.actions.destroy.success',
resource_name: assignment.short_identifier))
expect(flash.to_hash.length).to eq(1)
expect(response).to have_http_status(302)
end
end
end