diff --git a/app/assets/stylesheets/bubbles.css b/app/assets/stylesheets/bubbles.css
index 932efb262..25b014300 100644
--- a/app/assets/stylesheets/bubbles.css
+++ b/app/assets/stylesheets/bubbles.css
@@ -78,6 +78,7 @@
--rotation: 45deg;
aspect-ratio: 6/9;
+ border-radius: var(--bubble-shape);
display: flex;
font-size: 6cqi;
inset: 70cqi 7cqi auto auto;
@@ -86,22 +87,27 @@
place-items: center;
transform: rotate(var(--rotation));
- span {
+
+ .boost__form {
transform: rotate(calc(var(--rotation) * -1));
}
- form {
- block-size: 100%;
- display: grid;
- inline-size: 100%;
+ .boost__btn {
+ --btn-background: var(--bubble-color);
+ --btn-border-radius: 50%;
+ --btn-color: var(--color-ink-reversed);
+ --btn-size: 0.5em;
+ --btn-padding: 0.3em 0.5em;
+
+ font-weight: 800;
}
- .btn {
- --btn-background: transparent;
- --btn-color: var(--bubble-color);
-
- appearance: none;
+ .boost__input {
+ color: var(--bubble-color);
+ field-sizing: content;
font-weight: 800;
+ padding: 0;
+ text-align: center;
}
&.boosting {
@@ -210,15 +216,6 @@
transition: transform 200ms ease-out;
white-space: nowrap;
z-index: 1;
-
- &:has(.input:not([type="file"], [type="date"], select)) {
- border-radius: 2em;
- padding: 0.2em 0.5em;
-
- .input {
- color: var(--bubble-color);
- }
- }
}
@media (hover: hover) {
diff --git a/app/assets/stylesheets/toggles.css b/app/assets/stylesheets/toggles.css
new file mode 100644
index 000000000..d37f6a21b
--- /dev/null
+++ b/app/assets/stylesheets/toggles.css
@@ -0,0 +1,13 @@
+.toggler--toggled {
+ .toggler__visible-when-off {
+ display: none;
+ }
+
+ .toggler__visible-when-on {
+ display: unset;
+ }
+}
+
+.toggler__visible-when-on {
+ display: none;
+}
diff --git a/app/controllers/boosts_controller.rb b/app/controllers/boosts_controller.rb
index 5f5c95e93..0a6f34f78 100644
--- a/app/controllers/boosts_controller.rb
+++ b/app/controllers/boosts_controller.rb
@@ -2,6 +2,15 @@ class BoostsController < ApplicationController
include BubbleScoped, BucketScoped
def create
- @bubble.boost!
+ count = if params[:boost_count].to_i == @bubble.boosts_count
+ @bubble.boosts_count + 1
+ else
+ params[:boost_count].to_i
+ end
+ @bubble.boost!(count)
+
+ respond_to do |format|
+ format.turbo_stream
+ end
end
end
diff --git a/app/controllers/buckets_controller.rb b/app/controllers/buckets_controller.rb
index 320882381..b6cbe66dc 100644
--- a/app/controllers/buckets_controller.rb
+++ b/app/controllers/buckets_controller.rb
@@ -38,7 +38,7 @@ class BucketsController < ApplicationController
end
def bucket_params
- params.expect(bucket: [ :name ])
+ params.expect(bucket: [ :name, :all_access ]).with_defaults(all_access: false)
end
def grantees
diff --git a/app/helpers/accesses_helper.rb b/app/helpers/accesses_helper.rb
new file mode 100644
index 000000000..e1fb3ad0f
--- /dev/null
+++ b/app/helpers/accesses_helper.rb
@@ -0,0 +1,15 @@
+module AccessesHelper
+ def access_menu_tag(bucket, &)
+ tag.menu class: [ "flex flex-column gap margin-none pad txt-medium", { "toggler--toggled": bucket.all_access? } ], data: {
+ controller: "filter toggle-class",
+ filter_active_class: "filter--active", filter_selected_class: "selected",
+ toggle_class_toggle_class: "toggler--toggled" }, &
+ end
+
+ def access_toggles_for(users, selected:)
+ render partial: "buckets/access_toggle",
+ collection: users, as: :user,
+ locals: { selected: selected },
+ cached: ->(user) { [ user, selected ] }
+ end
+end
diff --git a/app/models/bubble/boostable.rb b/app/models/bubble/boostable.rb
index 226671803..94a530e8e 100644
--- a/app/models/bubble/boostable.rb
+++ b/app/models/bubble/boostable.rb
@@ -5,10 +5,13 @@ module Bubble::Boostable
scope :ordered_by_boosts, -> { order boosts_count: :desc }
end
- def boost!
+ def boost!(count = 1)
+ count = count.to_i
+ count = 1 if count < 1
+
transaction do
- track_event :boosted
- increment! :boosts_count
+ track_event :boosted, count: count
+ update! boosts_count: count
rescore
end
end
diff --git a/app/models/bucket/accessible.rb b/app/models/bucket/accessible.rb
index a5b49e94f..4b21c117b 100644
--- a/app/models/bucket/accessible.rb
+++ b/app/models/bucket/accessible.rb
@@ -15,12 +15,20 @@ module Bucket::Accessible
end
def revoke_from(users)
- destroy_by user: users
+ destroy_by user: users unless proxy_association.owner.all_access?
end
end
has_many :users, through: :accesses
+ scope :all_access, -> { where(all_access: true) }
+
after_create -> { accesses.grant_to creator }
+ after_save_commit :grant_access_to_everyone
end
+
+ private
+ def grant_access_to_everyone
+ accesses.grant_to(account.users) if all_access_previously_changed?(to: true)
+ end
end
diff --git a/app/models/filter/resources.rb b/app/models/filter/resources.rb
index 78c862c9d..bde1a30d1 100644
--- a/app/models/filter/resources.rb
+++ b/app/models/filter/resources.rb
@@ -12,5 +12,11 @@ module Filter::Resources
kind = resource.class.model_name.plural
send "#{kind}=", send(kind).without(resource)
empty? ? destroy! : save!
+ rescue ActiveRecord::RecordNotUnique
+ destroy!
+ end
+
+ def buckets
+ creator.buckets.where id: bucket_ids
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 2baa83876..bfa562008 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -21,6 +21,8 @@ class User < ApplicationRecord
validates_presence_of :email_address
normalizes :email_address, with: ->(value) { value.strip.downcase }
+ after_create_commit :grant_access_to_buckets
+
scope :active, -> { where(active: true) }
scope :alphabetically, -> { order("LOWER(name)") }
@@ -48,4 +50,8 @@ class User < ApplicationRecord
def deactived_email_address
email_address.sub(/@/, "-deactivated-#{SecureRandom.uuid}@")
end
+
+ def grant_access_to_buckets
+ Access.insert_all account.buckets.all_access.pluck(:id).collect { |bucket_id| { bucket_id: bucket_id, user_id: id } }
+ end
end
diff --git a/app/views/boosts/_boosts.html.erb b/app/views/boosts/_boosts.html.erb
index 975684583..6fdf9271d 100644
--- a/app/views/boosts/_boosts.html.erb
+++ b/app/views/boosts/_boosts.html.erb
@@ -5,10 +5,10 @@
toggle_class_toggle_class: "boosting",
action: "animationend->toggle-class#toggle" },
hidden: !bubble.boosts_count.positive? do %>
- <%= button_to bucket_bubble_boosts_path(bubble.bucket, bubble),
- class: "btn btn--plain",
- data: { action: "toggle-class#toggle" },
- form_class: "full-width" do %>
- <%= tag.span("+ #{bubble.boosts_count}") if bubble.boosts_count.positive? %>
+ <%= form_with url: bucket_bubble_boosts_path(bubble.bucket, bubble),
+ class: "boost__form",
+ data: { action: "toggle-class#toggle" } do %>
+ <%= text_field_tag :boost_count, bubble.boosts_count, min: 1, class: "input borderless boost__input", autocomplete: "off" %>
+ <%= tag.button "+", class: "btn btn--plain boost__btn", type: :submit %>
<% end %>
<% end %>
diff --git a/app/views/bubbles/_bubble.html.erb b/app/views/bubbles/_bubble.html.erb
index 09d680c94..4945e02b6 100644
--- a/app/views/bubbles/_bubble.html.erb
+++ b/app/views/bubbles/_bubble.html.erb
@@ -8,12 +8,12 @@
<%= turbo_frame_tag bubble, :edit do %>
<%= link_to bubble.title, edit_bucket_bubble_path(bubble.bucket, bubble), class: "txt-undecorated" %>
+
+
+ <%= render "bubbles/tags", bubble: bubble %>
+
<% end %>
-
-
- <%= render "bubbles/tags", bubble: bubble %>
-
diff --git a/app/views/bubbles/_messages.html.erb b/app/views/bubbles/_messages.html.erb
index 5320e9eeb..446b424c9 100644
--- a/app/views/bubbles/_messages.html.erb
+++ b/app/views/bubbles/_messages.html.erb
@@ -5,6 +5,6 @@
data-created-by-current-user-mine-class="comment--mine">
<%# Template Dependency: comments/comment %>
<%# Template Dependency: event_summaries/event_summary %>
- <%= render bubble.messages, cache: true %>
+ <%= render bubble.messages, cached: true %>
<%= render "comments/new", bubble: bubble %>
diff --git a/app/views/bubbles/_tags.html.erb b/app/views/bubbles/_tags.html.erb
index c38e63103..bf23f575c 100644
--- a/app/views/bubbles/_tags.html.erb
+++ b/app/views/bubbles/_tags.html.erb
@@ -1,6 +1,6 @@
<% bubble.tags.each do |tag| %>
<%= link_to bubbles_path(@filter.to_params.merge(tag_ids: [ tag.id ])),
- class: "bubble__tag btn btn--plain fill-transparent min-width", style: "color: #{bubble.color}" do %>
+ class: "bubble__tag btn btn--plain fill-transparent min-width", style: "color: #{bubble.color}", data: { turbo_frame: "_top" } do %>
<%= tag.hashtag %>
<% end %>
<% end %>
diff --git a/app/views/bubbles/edit.html.erb b/app/views/bubbles/edit.html.erb
index 562bc096b..57bbed5c1 100644
--- a/app/views/bubbles/edit.html.erb
+++ b/app/views/bubbles/edit.html.erb
@@ -1,12 +1,15 @@
<%= turbo_frame_tag @bubble, :edit do %>
- <%= form_with model: @bubble, url: bucket_bubble_path(@bubble.bucket, @bubble), class: "flex flex-column gap full-width", data: { controller: "form" } do |form| %>
+ <%= form_with model: @bubble, url: bucket_bubble_path(@bubble.bucket, @bubble), class: "flex flex-column justify-center gap full-width", data: { controller: "form" } do |form| %>
<%= form.label :title, class: "flex flex-column justify-center align-center" do %>
<%= form.text_area :title, class: "input input--textara txt-align-center full-width borderless",
required: true, rows: 5, autofocus: true, placeholder: "Name it…",
data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel focus->form#select" },
style: "color: var(--spat-color); --input-border-radius: 0" %>
<% end %>
- <%= form.submit "Save", hidden: true %>
+ <%= form.button "Save", class: "btn btn--reversed txt-small center", type: :submit do %>
+ <%= image_tag "check.svg", aria: { hidden: true }, size: 24 %>
+ Save
+ <% end %>
<%= link_to "Close editor and discard changes", bucket_bubble_path(@bubble.bucket, @bubble), data: { form_target: "cancel" }, hidden: true %>
<% end %>
<% end %>
diff --git a/app/views/buckets/_access_toggle.erb b/app/views/buckets/_access_toggle.erb
new file mode 100644
index 000000000..1b2482ef4
--- /dev/null
+++ b/app/views/buckets/_access_toggle.erb
@@ -0,0 +1,21 @@
+
+
+ <%= avatar_tag user, loading: :lazy %>
+
+
+
+
+
+
+ <%= image_tag "check.svg", size: 20, class: "toggler__visible-when-on colorize--black flex-item-no-shrink", aria: { hidden: "true" } %>
+
+
+
diff --git a/app/views/buckets/_user_toggle.html.erb b/app/views/buckets/_user_toggle.html.erb
deleted file mode 100644
index 874dc2ed4..000000000
--- a/app/views/buckets/_user_toggle.html.erb
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
- <%= avatar_tag user, loading: :lazy %>
-
-
-
-
-
-
- <% if user == Current.user %>
- <%= hidden_field_tag "user_ids[]", user.id, id: nil %>
- <%= image_tag "check.svg", size: 20, class: "colorize--black flex-item-no-shrink", aria: { hidden: "true" } %>
- <% else %>
-
- <% end %>
-
diff --git a/app/views/buckets/accesses/edit.html.erb b/app/views/buckets/accesses/edit.html.erb
deleted file mode 100644
index 4a593b72f..000000000
--- a/app/views/buckets/accesses/edit.html.erb
+++ /dev/null
@@ -1,14 +0,0 @@
-Users on <%= @bucket.name %>
-
-<%= form_with url: bucket_access_path, method: :put do |form| %>
-
- <% Current.account.users.active.each do |user| %>
- -
- <%= check_box_tag "user_ids[]", user.id, @bucket.users.include?(user), id: nil, disabled: user == Current.user %>
- <%= user.name %>
-
- <% end %>
-
-
- <%= form.submit %>
-<% end %>
diff --git a/app/views/buckets/edit.html.erb b/app/views/buckets/edit.html.erb
index 48931ac1c..f5c2dab81 100644
--- a/app/views/buckets/edit.html.erb
+++ b/app/views/buckets/edit.html.erb
@@ -17,7 +17,7 @@
<% end %>
- <%= form_with model: @bucket, class: "flex flex-column gap txt-large", controller: "form" do |form| %>
+ <%= form_with model: @bucket, class: "flex flex-column gap txt-large", data: { controller: "form" } do |form| %>
<%= translation_button(:bucket_name) %>
@@ -29,7 +29,7 @@
-
+ <% end %>