diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb
index 285ca6964..2bc7fa08d 100644
--- a/app/controllers/collections_controller.rb
+++ b/app/controllers/collections_controller.rb
@@ -20,8 +20,11 @@ class CollectionsController < ApplicationController
def update
@collection.update! collection_params
@collection.accesses.revise granted: grantees, revoked: revokees if grantees_changed?
-
- redirect_to edit_collection_path(@collection), notice: "Saved"
+ if @collection.accessible_to?(Current.user)
+ redirect_to edit_collection_path(@collection), notice: "Saved"
+ else
+ redirect_to root_path, notice: "Saved (you were removed from the collection)"
+ end
end
def destroy
diff --git a/app/javascript/controllers/collections_form_controller.js b/app/javascript/controllers/collections_form_controller.js
new file mode 100644
index 000000000..2ee872b4c
--- /dev/null
+++ b/app/javascript/controllers/collections_form_controller.js
@@ -0,0 +1,21 @@
+import { Controller } from "@hotwired/stimulus"
+import { nextEventLoopTick } from "helpers/timing_helpers";
+
+export default class extends Controller {
+ static targets = ["meCheckbox"]
+ static values = { selfRemovalPromptMessage: { type: String, default: "Are you sure?" } }
+
+ async submitWithWarning(event) {
+ if (this.hasMeCheckboxTarget && !this.meCheckboxTarget.checked && !this.confirmed) {
+ event.detail.formSubmission.stop()
+
+ const message = this.selfRemovalPromptMessageValue
+
+ if (confirm(message)) {
+ await nextEventLoopTick()
+ this.confirmed = true
+ this.element.requestSubmit()
+ }
+ }
+ }
+}
diff --git a/app/javascript/controllers/toggle_class_controller.js b/app/javascript/controllers/toggle_class_controller.js
index ca29ad771..039ad2e65 100644
--- a/app/javascript/controllers/toggle_class_controller.js
+++ b/app/javascript/controllers/toggle_class_controller.js
@@ -2,6 +2,7 @@ import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static classes = [ "toggle" ]
+ static targets = [ "checkbox" ]
toggle() {
this.element.classList.toggle(this.toggleClass)
@@ -14,4 +15,16 @@ export default class extends Controller {
remove() {
this.element.classList.remove(this.toggleClass)
}
+
+ checkAll() {
+ this.checkboxTargets.forEach(checkbox => {
+ checkbox.checked = true
+ })
+ }
+
+ checkNone() {
+ this.checkboxTargets.forEach(checkbox => {
+ checkbox.checked = false
+ })
+ }
}
diff --git a/app/views/collections/_access_toggle.erb b/app/views/collections/_access_toggle.erb
index 579cb4fc1..9940d6b14 100644
--- a/app/views/collections/_access_toggle.erb
+++ b/app/views/collections/_access_toggle.erb
@@ -9,7 +9,9 @@
<%= icon_tag "check", class: "toggler__visible-when-on margin-inline-end" %>
diff --git a/app/views/collections/edit.html.erb b/app/views/collections/edit.html.erb
index 1b95d3f27..55a7d53e7 100644
--- a/app/views/collections/edit.html.erb
+++ b/app/views/collections/edit.html.erb
@@ -21,7 +21,10 @@
Choose who can access this Collection
- <%= form_with model: @collection, class: "display-contents", data: { controller: "form" } do |form| %>
+ <%= form_with model: @collection, class: "display-contents", data: {
+ controller: "form collections-form",
+ collections_form_self_removal_prompt_message_value: "Are you sure you want to remove yourself from this collection? You won’t be able to get back in unless someone invites you.",
+ action: "turbo:submit-start->collections-form#submitWithWarning" } do |form| %>
<%= render "collections/edit/name", form: form %>
<%= render "collections/edit/users", collection: @collection, selected_users: @selected_users, unselected_users: @unselected_users, form: form %>
diff --git a/app/views/collections/edit/_users.html.erb b/app/views/collections/edit/_users.html.erb
index 884bfc9fe..a9eda26be 100644
--- a/app/views/collections/edit/_users.html.erb
+++ b/app/views/collections/edit/_users.html.erb
@@ -20,6 +20,14 @@
+
+
+
+ ·
+
+
+
+
<%= access_toggles_for selected_users, selected: true %>
<%= access_toggles_for unselected_users, selected: false %>
diff --git a/test/controllers/collections_controller_test.rb b/test/controllers/collections_controller_test.rb
index 870f5dec5..b6be6b2c8 100644
--- a/test/controllers/collections_controller_test.rb
+++ b/test/controllers/collections_controller_test.rb
@@ -34,17 +34,29 @@ class CollectionsControllerTest < ActionDispatch::IntegrationTest
auto_close_period: 1.day,
auto_reconsider_period: 2.days
},
- user_ids: users(:david, :jz).pluck(:id)
+ user_ids: users(:kevin, :jz).pluck(:id)
}
assert_redirected_to edit_collection_path(collections(:writebook))
assert_equal "Writebook bugs", collections(:writebook).reload.name
- assert_equal users(:david, :jz).sort, collections(:writebook).users.sort
+ assert_equal users(:kevin, :jz).sort, collections(:writebook).users.sort
assert_equal 1.day, entropy_configurations(:writebook_collection).auto_close_period
assert_equal 2.days, entropy_configurations(:writebook_collection).auto_reconsider_period
assert_not collections(:writebook).all_access?
end
+ test "update redirects to root when user removes themselves from collection" do
+ collection = collections(:writebook)
+
+ patch collection_path(collection), params: {
+ collection: { name: "Updated name", all_access: false },
+ user_ids: users(:david, :jz).pluck(:id)
+ }
+
+ assert_redirected_to root_path
+ assert_not collection.reload.users.include?(users(:kevin))
+ end
+
test "update collection with granular permissions, submitting no user ids" do
assert_not collections(:private).all_access?