diff --git a/app/assets/images/move.svg b/app/assets/images/move.svg new file mode 100644 index 000000000..cbce644c3 --- /dev/null +++ b/app/assets/images/move.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/card-perma.css b/app/assets/stylesheets/card-perma.css index 59cb99900..27b096f29 100644 --- a/app/assets/stylesheets/card-perma.css +++ b/app/assets/stylesheets/card-perma.css @@ -41,6 +41,17 @@ max-inline-size: 32ch; } + .collection-picker__button { + --btn-border-size: 0; + + font-size: 0.5em; + margin-inline-start: 1ch; + + + .panel { + --panel-size: 18ch; + } + } + @media (max-width: 800px) { --padding-inline: 3cqmin; diff --git a/app/assets/stylesheets/cards.css b/app/assets/stylesheets/cards.css index bb74bc503..92e540165 100644 --- a/app/assets/stylesheets/cards.css +++ b/app/assets/stylesheets/cards.css @@ -81,7 +81,12 @@ color: var(--color-ink-inverted); font-weight: 800; padding: var(--block-space-half) var(--inline-space) var(--block-space-half) var(--inline-space-double); - text-transform: uppercase; + + .cards--considering & { + background-color: var(--color-canvas); + color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink)); + padding: 0 0 0 var(--inline-space); + } } .card__id { @@ -100,6 +105,12 @@ display: inline-flex; margin-inline-start: var(--inline-space-half); padding-inline-start: calc(var(--inline-space) * 0.75); + text-transform: uppercase; + + .cards--considering & { + border-inline-start: 1px solid color-mix(in srgb, var(--color-ink) 33%, var(--color-canvas)); + color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink)); + } } .card__tags { diff --git a/app/assets/stylesheets/icons.css b/app/assets/stylesheets/icons.css index bc6f9e77f..be4f36e3d 100644 --- a/app/assets/stylesheets/icons.css +++ b/app/assets/stylesheets/icons.css @@ -44,6 +44,7 @@ .icon--menu { --svg: url("menu.svg "); } .icon--menu-dots-horizontal { --svg: url("menu-dots-horizontal.svg "); } .icon--minus { --svg: url("minus.svg "); } + .icon--move { --svg: url("move.svg "); } .icon--notification-bell-access-only { --svg: url("notification-bell-access-only.svg "); } .icon--notification-bell-everything { --svg: url("notification-bell-everything.svg "); } .icon--notification-bell-watching { --svg: url("notification-bell-watching.svg "); } diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index d535f26d9..8993fdb2c 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -28,7 +28,9 @@ class CardsController < ApplicationController def update @card.update! card_params - if @card.published? + if params[:card][:collection_id].present? + redirect_to collection_card_path(@card.collection, @card) + elsif @card.published? render_card_replacement else redirect_to @card @@ -54,7 +56,7 @@ class CardsController < ApplicationController end def card_params - params.expect(card: [ :status, :title, :description, :image, tag_ids: [] ]) + params.expect(card: [ :collection_id, :status, :title, :description, :image, tag_ids: [] ]) end def render_card_replacement diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 54c0c4678..a6a25c5b5 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -96,6 +96,8 @@ module EventsHelper "#{event_creator_name(event)} removed the date on #{ title }" when "card_title_changed" "#{event_creator_name(event)} renamed #{ title } (was: '#{event.particulars.dig('particulars', 'old_title')})'".html_safe + when "card_collection_changed" + "#{event_creator_name(event)} moved #{ title } to '#{event.particulars.dig('particulars', 'new_collection')}'".html_safe end end @@ -113,6 +115,8 @@ module EventsHelper "comment" when "card_title_changed" "rename" + when "card_collection_changed" + "move" else "person" end diff --git a/app/models/card.rb b/app/models/card.rb index bbb5e5843..656a51b12 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -12,6 +12,7 @@ class Card < ApplicationRecord has_rich_text :description before_save :set_default_title, if: :published? + after_save :handle_collection_change, if: :saved_change_to_collection_id? scope :reverse_chronologically, -> { order created_at: :desc, id: :desc } scope :chronologically, -> { order created_at: :asc, id: :asc } @@ -39,4 +40,21 @@ class Card < ApplicationRecord def set_default_title self.title = "Untitled" if title.blank? end + + def handle_collection_change + transaction do + old_collection = Collection.find_by(id: collection_id_before_last_save) + if old_collection.present? + track_event "collection_changed", particulars: { + old_collection: old_collection.name, + new_collection: collection.name + } + end + grant_access_to_assignees unless collection.all_access? + end + end + + def grant_access_to_assignees + collection.accesses.grant_to(assignees) + end end diff --git a/app/models/card/eventable/system_commenter.rb b/app/models/card/eventable/system_commenter.rb index 73247d2a3..bcc48ba85 100644 --- a/app/models/card/eventable/system_commenter.rb +++ b/app/models/card/eventable/system_commenter.rb @@ -24,6 +24,8 @@ class Card::Eventable::SystemCommenter "Closed as “#{ card.closure.reason }” by #{ event.creator.name }" when "card_title_changed" "#{event.creator.name} changed the title from '#{event.particulars.dig('particulars', 'old_title')}' to '#{event.particulars.dig('particulars', 'new_title')}'." + when "card_collection_changed" + "#{event.creator.name} moved this from '#{event.particulars.dig('particulars', 'old_collection')}' to '#{event.particulars.dig('particulars', 'new_collection')}'." end end end diff --git a/app/views/cards/_container.html.erb b/app/views/cards/_container.html.erb index 83242589a..9d326af6a 100644 --- a/app/views/cards/_container.html.erb +++ b/app/views/cards/_container.html.erb @@ -10,12 +10,7 @@
<%= card_article_tag card, class: "card" do %>
- - <%= card.id %> - <%= link_to card.collection.name, cards_path(collection_ids: [ card.collection ]), - class: "card__collection-name overflow-ellipsis" %> - - + <%= render "cards/display/perma/collection", card: card %> <%= render "cards/display/perma/tags", card: card %>
diff --git a/app/views/cards/display/_preview.html.erb b/app/views/cards/display/_preview.html.erb index f976117a8..767d54a82 100644 --- a/app/views/cards/display/_preview.html.erb +++ b/app/views/cards/display/_preview.html.erb @@ -3,11 +3,7 @@
- - <%= card.id %> - <%= link_to card.collection.name, cards_path(collection_ids: [ card.collection ]), - class: "card__collection-name overflow-ellipsis" %> - + <%= render "cards/display/preview/collection", card: card %> <%= render "cards/display/preview/tags", card: card %>
diff --git a/app/views/cards/display/common/_collection.html.erb b/app/views/cards/display/common/_collection.html.erb new file mode 100644 index 000000000..aacabb869 --- /dev/null +++ b/app/views/cards/display/common/_collection.html.erb @@ -0,0 +1,6 @@ +
+ <%= card.id %> + <%= link_to card.collection.name, cards_path(collection_ids: [ card.collection ]), + class: "card__collection-name overflow-ellipsis" %> + <%= yield %> +
\ No newline at end of file diff --git a/app/views/cards/display/perma/_collection.html.erb b/app/views/cards/display/perma/_collection.html.erb new file mode 100644 index 000000000..bde20356e --- /dev/null +++ b/app/views/cards/display/perma/_collection.html.erb @@ -0,0 +1,38 @@ +<%= render "cards/display/common/collection", card: card do %> +
> + + + + <%= tag.div class: "max-width full-width", data: { + controller: "filter", + dialog_target: "dialog", + filter_active_class: "filter--active", + filter_selected_class: "selected"} do %> + Put this card in… + + <% if Current.user.collections.count > 20 %> + + <% end %> + + <%= form_with(model: card, url: collection_card_path(card.collection, card), method: :patch, class: "full-width", data: { controller: "form" }) do |form| %> + + <% end %> + <% end %> + +
+<% end %> \ No newline at end of file diff --git a/app/views/cards/display/preview/_collection.html.erb b/app/views/cards/display/preview/_collection.html.erb new file mode 100644 index 000000000..ffbb7c3f7 --- /dev/null +++ b/app/views/cards/display/preview/_collection.html.erb @@ -0,0 +1 @@ +<%= render "cards/display/common/collection", card: card %> \ No newline at end of file diff --git a/test/fixtures/collections.yml b/test/fixtures/collections.yml index b7919cf36..2f00b7646 100644 --- a/test/fixtures/collections.yml +++ b/test/fixtures/collections.yml @@ -4,3 +4,9 @@ writebook: all_access: true auto_close_period: <%= 30.days.to_i %> workflow: qa + +private: + name: Private collection + creator: kevin + all_access: false + auto_close_period: <%= 30.days.to_i %> diff --git a/test/models/card_test.rb b/test/models/card_test.rb index 94fc9ab86..f99bdec70 100644 --- a/test/models/card_test.rb +++ b/test/models/card_test.rb @@ -128,4 +128,16 @@ class CardTest < ActiveSupport::TestCase card.publish assert_equal "Untitled", card.reload.title end + + test "grants access to assignees when moved to a new collection" do + card = cards(:logo) + assignee = users(:david) + card.toggle_assignment(assignee) + + collection = collections(:private) + assert_not_includes collection.users, assignee + + card.update!(collection: collection) + assert_includes collection.users.reload, assignee + end end