Baseline replacing collection with board across code

This commit is contained in:
Jorge Manrubia
2025-11-05 13:31:54 +01:00
parent 8caaad0105
commit 03a345609e
269 changed files with 990 additions and 990 deletions
+1 -1
View File
@@ -45,7 +45,7 @@
.bubble__number {
display: grid;
font-size: clamp(10px, 50cqi, var(--bubble-number-max)); /* FF bug: https://app.fizzy.do/5986089/collections/2/cards/1373 */
font-size: clamp(10px, 50cqi, var(--bubble-number-max)); /* FF bug: https://app.fizzy.do/5986089/boards/2/cards/1373 */
font-weight: 900;
inset: 0;
place-content: center;
+5 -5
View File
@@ -492,7 +492,7 @@
}
}
.card__collection {
.card__board {
background-color: transparent;
color: var(--card-content-color);
}
@@ -519,10 +519,10 @@
}
}
/* Collection tools
/* Board tools
/* -------------------------------------------------------------------------- */
.collection-tools.card {
.board-tools.card {
--border-color: var(--color-selected-dark);
--border-size: 1px;
--card-padding-block: var(--block-space);
@@ -560,7 +560,7 @@
}
}
.collection-tools__watching {
.board-tools__watching {
--btn-size: 32px;
--gap: 0.5ch;
@@ -572,7 +572,7 @@
position: relative;
}
.collection-tools__watching-dialog {
.board-tools__watching-dialog {
--panel-padding: 2ch;
--panel-size: 100%;
+1 -1
View File
@@ -85,7 +85,7 @@
}
}
.collection-picker__button {
.board-picker__button {
--btn-border-size: 0;
font-size: 0.5em;
+5 -5
View File
@@ -55,7 +55,7 @@
}
}
.card__collection {
.card__board {
background-color: var(--card-color);
border-radius: var(--border-radius) 0 var(--border-radius) 0;
color: var(--color-ink-inverted);
@@ -66,7 +66,7 @@
padding-block: 0.25lh;
padding-inline: var(--card-padding-inline) 1ch;
&:has(.collection-picker__button) {
&:has(.board-picker__button) {
cursor: pointer;
transition: background-color 100ms ease-out;
@@ -92,7 +92,7 @@
}
}
.card__collection-name {
.card__board-name {
border-inline-start: 1px solid color-mix(in hsl, transparent 75%, currentColor);
color: currentColor;
display: flex;
@@ -404,7 +404,7 @@
padding-block-end: 0;
}
.card__collection {
.card__board {
font-size: var(--text-xx-small);
padding-block: 0.5ch;
padding-inline-start: var(--inline-space-double);
@@ -487,7 +487,7 @@
}
}
.card__collection-public-description {
.card__board-public-description {
max-inline-size: 66ch;
> *:first-child { margin-block-start: 0; }
+2 -2
View File
@@ -270,7 +270,7 @@
z-index: 0;
}
.card__collection {
.card__board {
background-color: transparent;
color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));
font-size: 0.7em;
@@ -278,7 +278,7 @@
translate: 0 -0.3em;
}
.card__collection-name {
.card__board-name {
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));
margin: 0 0 0 calc(var(--inline-space) * 0.75);
+2 -2
View File
@@ -42,8 +42,8 @@
.icon--clipboard { --svg: url("clipboard.svg "); }
.icon--close { --svg: url("close.svg "); }
.icon--close-circle { --svg: url("close-circle.svg "); }
.icon--collection { --svg: url("collection.svg "); }
.icon--collection-add { --svg: url("collection-add.svg "); }
.icon--board { --svg: url("board.svg "); }
.icon--board-add { --svg: url("board-add.svg "); }
.icon--column-left { --svg: url("column-left.svg "); }
.icon--column-right { --svg: url("column-right.svg "); }
.icon--comment { --svg: url("comment.svg "); }
+3 -3
View File
@@ -63,7 +63,7 @@
}
.card {
.card__collection {
.card__board {
background: var(--color-canvas);
border-block-end: var(--border-light);
border-inline-end: var(--border-light);
@@ -118,7 +118,7 @@
}
}
/* Collections
/* Boards
/* ------------------------------------------------------------------------ */
.filters,
@@ -181,7 +181,7 @@
.card__meta-avatars--assignees > div > div:last-child,
.steps > .step:last-child,
div:has(> .tag-picker__button),
div:has(> .collection-picker__button),
div:has(> .board-picker__button),
.delete-card,
.header--card .header__title {
display: none;
+1 -1
View File
@@ -314,7 +314,7 @@
padding-block-end: 0;
}
.card__collection {
.card__board {
padding-block: 0.25ch;
}
@@ -2,11 +2,11 @@ class Cards::AssignmentsController < ApplicationController
include CardScoped
def new
@users = @collection.users.active.alphabetically
@users = @board.users.active.alphabetically
fresh_when @users
end
def create
@card.toggle_assignment @collection.users.active.find(params[:assignee_id])
@card.toggle_assignment @board.users.active.find(params[:assignee_id])
end
end
@@ -1,16 +1,16 @@
class Cards::CollectionsController < ApplicationController
include CollectionScoped
class Cards::BoardsController < ApplicationController
include BoardScoped
skip_before_action :set_collection, only: %i[ edit ]
skip_before_action :set_board, only: %i[ edit ]
before_action :set_card
def edit
@collections = Current.user.collections.ordered_by_recently_accessed
fresh_when @collections
@boards = Current.user.boards.ordered_by_recently_accessed
fresh_when @boards
end
def update
@card.move_to(@collection)
@card.move_to(@board)
redirect_to @card
end
+1 -1
View File
@@ -1,7 +1,7 @@
class Cards::ColumnsController < ApplicationController
def edit
@card = Current.user.accessible_cards.find(params[:card_id])
@columns = @card.collection.columns
@columns = @card.board.columns
fresh_when etag: [ @card, @columns ]
end
@@ -5,9 +5,9 @@ class Cards::PublishesController < ApplicationController
@card.publish
if add_another_param?
redirect_to @collection.cards.create!, notice: "Card added"
redirect_to @board.cards.create!, notice: "Card added"
else
redirect_to @card.collection
redirect_to @card.board
end
end
+3 -3
View File
@@ -5,11 +5,11 @@ class Cards::ReadingsController < ApplicationController
def create
@notifications = @card.read_by(Current.user)
record_collection_access
record_board_access
end
private
def record_collection_access
@card.collection.accessed_by(Current.user)
def record_board_access
@card.board.accessed_by(Current.user)
end
end
+1 -1
View File
@@ -2,7 +2,7 @@ class Cards::TriagesController < ApplicationController
include CardScoped
def create
column = @card.collection.columns.find(params[:column_id])
column = @card.board.columns.find(params[:column_id])
@card.triage_into(column)
redirect_to @card
+6 -6
View File
@@ -1,7 +1,7 @@
class CardsController < ApplicationController
include FilterScoped
before_action :set_collection, only: %i[ create ]
before_action :set_board, only: %i[ create ]
before_action :set_card, only: %i[ show edit update destroy ]
def index
@@ -9,7 +9,7 @@ class CardsController < ApplicationController
end
def create
card = @collection.cards.find_or_create_by!(creator: Current.user, status: "drafted")
card = @board.cards.find_or_create_by!(creator: Current.user, status: "drafted")
redirect_to card
end
@@ -30,12 +30,12 @@ class CardsController < ApplicationController
def destroy
@card.destroy!
redirect_to @card.collection, notice: "Card deleted"
redirect_to @card.board, notice: "Card deleted"
end
private
def set_collection
@collection = Current.user.collections.find params[:collection_id]
def set_board
@board = Current.user.boards.find params[:board_id]
end
def set_card
@@ -46,7 +46,7 @@ class CardsController < ApplicationController
if card.published?
yield
else
Collection.suppressing_turbo_broadcasts(&block)
Board.suppressing_turbo_broadcasts(&block)
end
end
@@ -1,8 +1,8 @@
class Collections::Columns::ClosedsController < ApplicationController
include CollectionScoped
class Boards::Columns::ClosedsController < ApplicationController
include BoardScoped
def show
set_page_and_extract_portion_from @collection.cards.closed.recently_closed_first
set_page_and_extract_portion_from @board.cards.closed.recently_closed_first
fresh_when etag: @page.records
end
end
@@ -1,8 +1,8 @@
class Collections::Columns::NotNowsController < ApplicationController
include CollectionScoped
class Boards::Columns::NotNowsController < ApplicationController
include BoardScoped
def show
set_page_and_extract_portion_from @collection.cards.postponed.reverse_chronologically.with_golden_first
set_page_and_extract_portion_from @board.cards.postponed.reverse_chronologically.with_golden_first
fresh_when etag: @page.records
end
end
@@ -1,8 +1,8 @@
class Collections::Columns::StreamsController < ApplicationController
include CollectionScoped
class Boards::Columns::StreamsController < ApplicationController
include BoardScoped
def show
set_page_and_extract_portion_from @collection.cards.awaiting_triage.latest.with_golden_first
set_page_and_extract_portion_from @board.cards.awaiting_triage.latest.with_golden_first
fresh_when etag: @page.records
end
end
@@ -1,5 +1,5 @@
class Collections::ColumnsController < ApplicationController
include CollectionScoped
class Boards::ColumnsController < ApplicationController
include BoardScoped
before_action :set_column, only: %i[ show update destroy ]
@@ -9,7 +9,7 @@ class Collections::ColumnsController < ApplicationController
end
def create
@column = @collection.columns.create!(column_params)
@column = @board.columns.create!(column_params)
end
def update
@@ -22,7 +22,7 @@ class Collections::ColumnsController < ApplicationController
private
def set_column
@column = @collection.columns.find(params[:id])
@column = @board.columns.find(params[:id])
end
def column_params
@@ -1,12 +1,12 @@
class Collections::EntropiesController < ApplicationController
include CollectionScoped
class Boards::EntropiesController < ApplicationController
include BoardScoped
def update
@collection.entropy.update!(entropy_params)
@board.entropy.update!(entropy_params)
end
private
def entropy_params
params.expect(collection: [ :auto_postpone_period ])
params.expect(board: [ :auto_postpone_period ])
end
end
@@ -1,7 +1,7 @@
class Collections::InvolvementsController < ApplicationController
include CollectionScoped
class Boards::InvolvementsController < ApplicationController
include BoardScoped
def update
@collection.access_for(Current.user).update!(involvement: params[:involvement])
@board.access_for(Current.user).update!(involvement: params[:involvement])
end
end
@@ -1,12 +1,12 @@
class Collections::PublicationsController < ApplicationController
include CollectionScoped
class Boards::PublicationsController < ApplicationController
include BoardScoped
def create
@collection.publish
@board.publish
end
def destroy
@collection.unpublish
@collection.reload
@board.unpublish
@board.reload
end
end
+21 -21
View File
@@ -1,10 +1,10 @@
class CollectionsController < ApplicationController
class BoardsController < ApplicationController
include FilterScoped
before_action :set_collection, except: %i[ new create ]
before_action :set_board, except: %i[ new create ]
def show
if @filter.used?(ignore_collections: true)
if @filter.used?(ignore_boards: true)
show_filtered_cards
else
show_columns
@@ -12,53 +12,53 @@ class CollectionsController < ApplicationController
end
def new
@collection = Collection.new
@board = Board.new
end
def create
@collection = Collection.create! collection_params.with_defaults(all_access: true)
redirect_to collection_path(@collection)
@board = Board.create! board_params.with_defaults(all_access: true)
redirect_to board_path(@board)
end
def edit
selected_user_ids = @collection.users.pluck :id
selected_user_ids = @board.users.pluck :id
@selected_users, @unselected_users = \
User.active.alphabetically.partition { |user| selected_user_ids.include? user.id }
end
def update
@collection.update! collection_params
@collection.accesses.revise granted: grantees, revoked: revokees if grantees_changed?
@board.update! board_params
@board.accesses.revise granted: grantees, revoked: revokees if grantees_changed?
if @collection.accessible_to?(Current.user)
redirect_to edit_collection_path(@collection), notice: "Saved"
if @board.accessible_to?(Current.user)
redirect_to edit_board_path(@board), notice: "Saved"
else
redirect_to root_path, notice: "Saved (you were removed from the collection)"
redirect_to root_path, notice: "Saved (you were removed from the board)"
end
end
def destroy
@collection.destroy
@board.destroy
redirect_to root_path
end
private
def set_collection
@collection = Current.user.collections.find params[:id]
def set_board
@board = Current.user.boards.find params[:id]
end
def show_filtered_cards
@filter.collection_ids = [ @collection.id ]
@filter.board_ids = [ @board.id ]
set_page_and_extract_portion_from @filter.cards
end
def show_columns
set_page_and_extract_portion_from @collection.cards.awaiting_triage.latest.with_golden_first
fresh_when etag: [ @collection, @page.records, @user_filtering ]
set_page_and_extract_portion_from @board.cards.awaiting_triage.latest.with_golden_first
fresh_when etag: [ @board, @page.records, @user_filtering ]
end
def collection_params
params.expect(collection: [ :name, :all_access, :auto_postpone_period, :public_description ])
def board_params
params.expect(board: [ :name, :all_access, :auto_postpone_period, :public_description ])
end
def grantees
@@ -66,7 +66,7 @@ class CollectionsController < ApplicationController
end
def revokees
@collection.users.where.not id: grantee_ids
@board.users.where.not id: grantee_ids
end
def grantee_ids
@@ -2,7 +2,7 @@ class Columns::Cards::Drops::ColumnsController < ApplicationController
include CardScoped
def create
@column = @card.collection.columns.find(params[:column_id])
@column = @card.board.columns.find(params[:column_id])
@card.triage_into(@column)
end
end
@@ -3,6 +3,6 @@ class Columns::Cards::Drops::StreamsController < ApplicationController
def create
@card.send_back_to_triage
set_page_and_extract_portion_from @collection.cards.awaiting_triage.latest.with_golden_first
set_page_and_extract_portion_from @board.cards.awaiting_triage.latest.with_golden_first
end
end
+3 -3
View File
@@ -2,7 +2,7 @@ module CardScoped
extend ActiveSupport::Concern
included do
before_action :set_card, :set_collection
before_action :set_card, :set_board
end
private
@@ -10,8 +10,8 @@ module CardScoped
@card = Current.user.accessible_cards.find(params[:card_id])
end
def set_collection
@collection = @card.collection
def set_board
@board = @card.board
end
def render_card_replacement
@@ -1,12 +1,12 @@
module CollectionScoped
module BoardScoped
extend ActiveSupport::Concern
included do
before_action :set_collection
before_action :set_board
end
private
def set_collection
@collection = Current.user.collections.find(params[:collection_id])
def set_board
@board = Current.user.boards.find(params[:board_id])
end
end
+2 -2
View File
@@ -1,7 +1,7 @@
class LandingsController < ApplicationController
def show
if Current.user.collections.one?
redirect_to collection_path(Current.user.collections.first)
if Current.user.boards.one?
redirect_to board_path(Current.user.boards.first)
else
redirect_to events_path
end
@@ -2,7 +2,7 @@ class Notifications::SettingsController < ApplicationController
before_action :set_settings
def show
@collections = Current.user.collections.alphabetically
@boards = Current.user.boards.alphabetically
end
def update
@@ -1,8 +1,8 @@
class Prompts::Collections::UsersController < ApplicationController
include CollectionScoped
class Prompts::Boards::UsersController < ApplicationController
include BoardScoped
def index
@users = @collection.users.alphabetically
@users = @board.users.alphabetically
if stale? etag: @users
render layout: false
+4 -4
View File
@@ -1,17 +1,17 @@
class Public::BaseController < ApplicationController
allow_unauthenticated_access
before_action :set_collection, :set_card, :set_public_cache_expiration
before_action :set_board, :set_card, :set_public_cache_expiration
layout "public"
private
def set_collection
@collection = Collection.find_by_published_key(params[:collection_id] || params[:id])
def set_board
@board = Board.find_by_published_key(params[:board_id] || params[:id])
end
def set_card
@card = @collection.cards.find(params[:id]) if params[:collection_id] && params[:id]
@card = @board.cards.find(params[:id]) if params[:board_id] && params[:id]
end
def set_public_cache_expiration
@@ -1,5 +1,5 @@
class Public::Collections::Columns::ClosedsController < Public::BaseController
class Public::Boards::Columns::ClosedsController < Public::BaseController
def show
set_page_and_extract_portion_from @collection.cards.closed.recently_closed_first
set_page_and_extract_portion_from @board.cards.closed.recently_closed_first
end
end
@@ -1,5 +1,5 @@
class Public::Collections::Columns::NotNowsController < Public::BaseController
class Public::Boards::Columns::NotNowsController < Public::BaseController
def show
set_page_and_extract_portion_from @collection.cards.postponed.reverse_chronologically.with_golden_first
set_page_and_extract_portion_from @board.cards.postponed.reverse_chronologically.with_golden_first
end
end
@@ -1,5 +1,5 @@
class Public::Collections::Columns::StreamsController < Public::BaseController
class Public::Boards::Columns::StreamsController < Public::BaseController
def show
set_page_and_extract_portion_from @collection.cards.awaiting_triage.latest.with_golden_first
set_page_and_extract_portion_from @board.cards.awaiting_triage.latest.with_golden_first
end
end
@@ -1,4 +1,4 @@
class Public::Collections::ColumnsController < Public::BaseController
class Public::Boards::ColumnsController < Public::BaseController
before_action :set_column
def show
@@ -11,6 +11,6 @@ class Public::Collections::ColumnsController < Public::BaseController
end
def set_column
@column = @collection.columns.find(params[:id])
@column = @board.columns.find(params[:id])
end
end
@@ -1,5 +1,5 @@
class Public::CollectionsController < Public::BaseController
class Public::BoardsController < Public::BaseController
def show
set_page_and_extract_portion_from @collection.cards.awaiting_triage.latest.with_golden_first
set_page_and_extract_portion_from @board.cards.awaiting_triage.latest.with_golden_first
end
end
+7 -7
View File
@@ -1,22 +1,22 @@
class WebhooksController < ApplicationController
include CollectionScoped
include BoardScoped
before_action :ensure_admin
before_action :set_webhook, except: %i[ index new create ]
def index
set_page_and_extract_portion_from @collection.webhooks.ordered
set_page_and_extract_portion_from @board.webhooks.ordered
end
def show
end
def new
@webhook = @collection.webhooks.new
@webhook = @board.webhooks.new
end
def create
webhook = @collection.webhooks.create!(webhook_params)
webhook = @board.webhooks.create!(webhook_params)
redirect_to webhook
end
@@ -30,17 +30,17 @@ class WebhooksController < ApplicationController
def destroy
@webhook.destroy!
redirect_to collection_webhooks_path
redirect_to board_webhooks_path
end
private
def set_webhook
@webhook = @collection.webhooks.find(params[:id])
@webhook = @board.webhooks.find(params[:id])
end
def webhook_params
params
.expect(webhook: [ :name, :url, subscribed_actions: [] ])
.merge(collection_id: @collection.id)
.merge(board_id: @board.id)
end
end
+16 -16
View File
@@ -1,8 +1,8 @@
module AccessesHelper
MAX_DISPLAYED_WATCHERS = 8
def access_menu_tag(collection, **options, &)
tag.menu class: [ options[:class], { "toggler--toggled": collection.all_access? } ], data: {
def access_menu_tag(board, **options, &)
tag.menu class: [ options[:class], { "toggler--toggled": board.all_access? } ], data: {
controller: "filter toggle-class navigable-list",
action: "keydown->navigable-list#navigate filter:changed->navigable-list#reset",
navigable_list_focus_on_selection_value: true,
@@ -11,35 +11,35 @@ module AccessesHelper
end
def access_toggles_for(users, selected:)
render partial: "collections/access_toggle",
collection: users, as: :user,
render partial: "boards/access_toggle",
board: users, as: :user,
locals: { selected: selected },
cached: ->(user) { [ user, selected ] }
end
def access_involvement_advance_button(collection, user, show_watchers: true, icon_only: false)
access = collection.access_for(user)
def access_involvement_advance_button(board, user, show_watchers: true, icon_only: false)
access = board.access_for(user)
turbo_frame_tag dom_id(collection, :involvement_button) do
concat collection_watchers_list(collection) if show_watchers
concat involvement_button(collection, access, show_watchers, icon_only)
turbo_frame_tag dom_id(board, :involvement_button) do
concat board_watchers_list(board) if show_watchers
concat involvement_button(board, access, show_watchers, icon_only)
end
end
def collection_watchers_list(collection)
watchers = collection.watchers
def board_watchers_list(board)
watchers = board.watchers
displayed_watchers = watchers.limit(MAX_DISPLAYED_WATCHERS)
overflow_count = watchers.count - MAX_DISPLAYED_WATCHERS
safe_join([
tag.strong(displayed_watchers.any? ? "Watching for new cards" : "No one is watching for new cards", class: "txt-uppercase"),
tag.div(class: "collection-tools__watching") do
tag.div(class: "board-tools__watching") do
safe_join([
safe_join(displayed_watchers.map { |watcher| avatar_tag(watcher) }),
(tag.div(data: { controller: "dialog", action: "keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" }) do
concat tag.button("+#{overflow_count}", class: "overflow-count btn btn--circle borderless", data: { action: "dialog#open" }, aria: { label: "Show #{overflow_count} more watchers" })
concat(tag.dialog(class: "collection-tools__watching-dialog dialog panel", data: { dialog_target: "dialog" }, aria: { hidden: "true" }) do
concat(tag.dialog(class: "board-tools__watching-dialog dialog panel", data: { dialog_target: "dialog" }, aria: { hidden: "true" }) do
safe_join(watchers.map { |watcher| avatar_tag(watcher) })
end)
end if overflow_count > 0)
@@ -48,11 +48,11 @@ module AccessesHelper
])
end
def involvement_button(collection, access, show_watchers, icon_only)
involvement_label_id = dom_id(collection, :involvement_label)
def involvement_button(board, access, show_watchers, icon_only)
involvement_label_id = dom_id(board, :involvement_label)
button_to(
collection_involvement_path(collection),
board_involvement_path(board),
method: :put,
aria: { labelledby: involvement_label_id },
class: class_names("btn", { "btn--reversed": access.watching? && icon_only }),
+2 -2
View File
@@ -27,14 +27,14 @@ module CardsHelper
title = [
card.title,
"added by #{card.creator.name}",
"in #{card.collection.name}"
"in #{card.board.name}"
]
title << "assigned to #{card.assignees.map(&:name).to_sentence}" if card.assignees.any?
title.join(" ")
end
def card_social_tags(card)
tag.meta(property: "og:title", content: "#{card.title} | #{card.collection.name}") +
tag.meta(property: "og:title", content: "#{card.title} | #{card.board.name}") +
tag.meta(property: "og:description", content: format_excerpt(@card&.description, length: 200)) +
tag.meta(property: "og:image", content: @card.image.attached? ? "#{request.base_url}#{url_for(@card.image)}" : "#{request.base_url}/app-icon.png") +
tag.meta(property: "og:url", content: card_url(@card))
+7 -7
View File
@@ -1,14 +1,14 @@
module CollectionsHelper
def link_back_to_collection(collection)
link_to collection, class: "btn borderless txt-medium",
module BoardsHelper
def link_back_to_board(board)
link_to board, class: "btn borderless txt-medium",
data: { controller: "hotkey", action: "keydown.esc@document->hotkey#click click->turbo-navigation#backIfSamePath" } do
tag.span ("&larr;" + tag.strong(collection.name, class: "overflow-ellipsis")).html_safe
tag.span ("&larr;" + tag.strong(board.name, class: "overflow-ellipsis")).html_safe
end
end
def link_to_edit_collection(collection)
link_to edit_collection_path(collection), class: "btn", data: { controller: "tooltip" } do
icon_tag("settings") + tag.span("Settings for #{collection.name}", class: "for-screen-reader")
def link_to_edit_board(board)
link_to edit_board_path(board), class: "btn", data: { controller: "tooltip" } do
icon_tag("settings") + tag.span("Settings for #{board.name}", class: "for-screen-reader")
end
end
end
+3 -3
View File
@@ -102,8 +102,8 @@ module EventsHelper
"#{event_creator_name(event)} resumed #{event_card_title(card)}"
when "card_title_changed"
"#{event_creator_name(event)} renamed #{event_card_title(card)} (was: “#{h event.particulars.dig('particulars', 'old_title')}”)"
when "card_collection_changed"
"#{event_creator_name(event)} moved #{event_card_title(card)} to “#{h event.particulars.dig('particulars', 'new_collection')}"
when "card_board_changed"
"#{event_creator_name(event)} moved #{event_card_title(card)} to “#{h event.particulars.dig('particulars', 'new_board')}"
when "card_triaged"
"#{event_creator_name(event)} moved #{event_card_title(card)} to “#{h event.particulars.dig('particulars', 'column')}"
when "card_sent_back_to_triage"
@@ -129,7 +129,7 @@ module EventsHelper
"comment"
when "card_title_changed"
"rename"
when "card_collection_changed"
when "card_board_changed"
"move"
else
"person"
+2 -2
View File
@@ -11,8 +11,8 @@ module FiltersHelper
hidden_field_tag name, value, id: nil
end
def filter_selected_collections_title(user_filtering)
user_filtering.selected_collection_titles.collect { tag.strong it }.to_sentence.html_safe
def filter_selected_boards_title(user_filtering)
user_filtering.selected_board_titles.collect { tag.strong it }.to_sentence.html_safe
end
def filter_place_menu_item(path, label, icon, new_window: false, current: false)
+1 -1
View File
@@ -3,7 +3,7 @@ module My::MenuHelper
text_field_tag :search, nil,
type: "search",
role: "combobox",
placeholder: "Type to jump to a collection, person, place, or tag…",
placeholder: "Type to jump to a board, person, place, or tag…",
class: "input input--transparent txt-small",
autofocus: true,
autocorrect: "off",
+4 -4
View File
@@ -1,6 +1,6 @@
module RichTextHelper
def mentions_prompt(collection)
content_tag "lexxy-prompt", "", trigger: "@", src: prompts_collection_users_path(collection), name: "mention"
def mentions_prompt(board)
content_tag "lexxy-prompt", "", trigger: "@", src: prompts_board_users_path(board), name: "mention"
end
def global_mentions_prompt
@@ -19,7 +19,7 @@ module RichTextHelper
content_tag "lexxy-code-language-picker"
end
def general_prompts(collection)
safe_join([ mentions_prompt(collection), cards_prompt, code_language_picker ])
def general_prompts(board)
safe_join([ mentions_prompt(board), cards_prompt, code_language_picker ])
end
end
+4 -4
View File
@@ -2,7 +2,7 @@ module WebhooksHelper
ACTION_LABELS = {
card_published: "Card added",
card_title_changed: "Card title changed",
card_collection_changed: "Card collection changed",
card_board_changed: "Card board changed",
comment_created: "Comment added",
card_assigned: "Card assigned",
card_unassigned: "Card unassigned",
@@ -22,9 +22,9 @@ module WebhooksHelper
ACTION_LABELS[action] || action.to_s.humanize
end
def link_to_webhooks(collection, &)
link_to collection_webhooks_path(collection_id: collection),
class: [ "btn", { "btn--reversed": collection.webhooks.any? } ],
def link_to_webhooks(board, &)
link_to board_webhooks_path(board_id: board),
class: [ "btn", { "btn--reversed": board.webhooks.any? } ],
data: { controller: "tooltip" } do
icon_tag("world") + tag.span("Webhooks", class: "for-screen-reader")
end
@@ -5,7 +5,7 @@ export default class extends Controller {
static classes = [ "collapsed", "noTransitions" ]
static targets = [ "column", "button" ]
static values = {
collection: String
board: String
}
initialize() {
@@ -104,6 +104,6 @@ export default class extends Controller {
}
#localStorageKeyFor(column) {
return `expand-${this.collectionValue}-${column.getAttribute("id")}`
return `expand-${this.boardValue}-${column.getAttribute("id")}`
}
}
@@ -24,7 +24,7 @@ export default class extends Controller {
checkNone() {
this.checkboxTargets.forEach(checkbox => {
if (checkbox.dataset.collectionsFormTarget === "meCheckbox") return
if (checkbox.dataset.boardsFormTarget === "meCheckbox") return
checkbox.checked = false
})
}
@@ -1,5 +1,5 @@
class Collection::CleanInaccessibleDataJob < ApplicationJob
def perform(user, collection)
collection.clean_inaccessible_data_for(user)
class Board::CleanInaccessibleDataJob < ApplicationJob
def perform(user, board)
board.clean_inaccessible_data_for(user)
end
end
+2 -2
View File
@@ -1,5 +1,5 @@
class Access < ApplicationRecord
belongs_to :collection, touch: true
belongs_to :board, touch: true
belongs_to :user, touch: true
enum :involvement, %i[ access_only watching ].index_by(&:itself), default: :access_only
@@ -18,6 +18,6 @@ class Access < ApplicationRecord
end
def clean_inaccessible_data_later
Collection::CleanInaccessibleDataJob.perform_later(user, collection)
Board::CleanInaccessibleDataJob.perform_later(user, board)
end
end
+3 -3
View File
@@ -26,9 +26,9 @@ class Account::Seeder
def populate
# ---------------
# Playground Collection
# Playground Board
# ---------------
playground = Collection.create! name: "Playground", creator: creator, all_access: true
playground = Board.create! name: "Playground", creator: creator, all_access: true
# Cards
playground.cards.create! creator: creator, title: "Watch this: Fizzy orientation video", status: "published", description: <<~HTML
@@ -105,7 +105,7 @@ class Account::Seeder
def delete_everything
Current.set session: session do
Collection.destroy_all
Board.destroy_all
end
end
end
+13 -13
View File
@@ -3,7 +3,7 @@ class Card < ApplicationRecord
Eventable, Golden, Mentions, Multistep, Pinnable, Postponable, Promptable,
Readable, Searchable, Stallable, Statuses, Taggable, Triageable, Watchable
belongs_to :collection, touch: true
belongs_to :board, touch: true
belongs_to :creator, class_name: "User", default: -> { Current.user }
has_many :comments, dependent: :destroy
@@ -12,7 +12,7 @@ class Card < ApplicationRecord
has_rich_text :description
before_save :set_default_title, if: :published?
after_update :handle_collection_change, if: :saved_change_to_collection_id?
after_update :handle_board_change, if: :saved_change_to_board_id?
scope :reverse_chronologically, -> { order created_at: :desc, id: :desc }
scope :chronologically, -> { order created_at: :asc, id: :asc }
@@ -39,16 +39,16 @@ class Card < ApplicationRecord
end
end
delegate :accessible_to?, to: :collection
delegate :accessible_to?, to: :board
def card
self
end
def move_to(new_collection)
def move_to(new_board)
transaction do
card.update!(collection: new_collection)
card.events.update_all(collection_id: new_collection.id)
card.update!(board: new_board)
card.events.update_all(board_id: new_board.id)
end
end
@@ -61,23 +61,23 @@ class Card < ApplicationRecord
self.title = "Untitled" if title.blank?
end
def handle_collection_change
old_collection = Collection.find_by(id: collection_id_before_last_save)
def handle_board_change
old_board = Board.find_by(id: board_id_before_last_save)
transaction do
update! column: nil
track_collection_change_event(old_collection.name)
grant_access_to_assignees unless collection.all_access?
track_board_change_event(old_board.name)
grant_access_to_assignees unless board.all_access?
end
remove_inaccessible_notifications_later
end
def track_collection_change_event(old_collection_name)
track_event "collection_changed", particulars: { old_collection: old_collection_name, new_collection: collection.name }
def track_board_change_event(old_board_name)
track_event "board_changed", particulars: { old_board: old_board_name, new_board: board.name }
end
def grant_access_to_assignees
collection.accesses.grant_to(assignees)
board.accesses.grant_to(assignees)
end
end
+3 -3
View File
@@ -4,19 +4,19 @@ module Card::Entropic
included do
scope :due_to_be_postponed, -> do
active
.left_outer_joins(collection: :entropy)
.left_outer_joins(board: :entropy)
.where("last_active_at <= DATETIME('now', '-' || COALESCE(entropies.auto_postpone_period, ?) || ' seconds')",
Account.sole.entropy.auto_postpone_period)
end
scope :postponing_soon, -> do
active
.left_outer_joins(collection: :entropy)
.left_outer_joins(board: :entropy)
.where("last_active_at > DATETIME('now', '-' || COALESCE(entropies.auto_postpone_period, ?) || ' seconds')", Account.sole.entropy.auto_postpone_period)
.where("last_active_at <= DATETIME('now', '-' || CAST(COALESCE(entropies.auto_postpone_period, ?) * 0.75 AS INTEGER) || ' seconds')", Account.sole.entropy.auto_postpone_period)
end
delegate :auto_postpone_period, to: :collection
delegate :auto_postpone_period, to: :board
end
class_methods do
@@ -28,8 +28,8 @@ class Card::Eventable::SystemCommenter
"<strong>Closed</strong> as “Not Now” due to inactivity"
when "card_title_changed"
"#{event.creator.name} <strong>changed the title</strong> from “#{event.particulars.dig('particulars', 'old_title')}” to “#{event.particulars.dig('particulars', 'new_title')}”."
when "card_collection_changed"
"#{event.creator.name} <strong>moved</strong> this from “#{event.particulars.dig('particulars', 'old_collection')}” to “#{event.particulars.dig('particulars', 'new_collection')}”."
when "card_board_changed"
"#{event.creator.name} <strong>moved</strong> this from “#{event.particulars.dig('particulars', 'old_board')}” to “#{event.particulars.dig('particulars', 'new_board')}”."
when "card_triaged"
"#{event.creator.name} <strong>moved</strong> this to “#{event.particulars.dig('particulars', 'column')}"
when "card_sent_back_to_triage"
+2 -2
View File
@@ -21,8 +21,8 @@ module Card::Promptable
* Assigned to: #{assignees.map(&:name).join(", ")}
* Column: #{column_prompt_label}
* Created at: #{created_at}}
* Collection id: #{collection_id}
* Collection name: #{collection.name}
* Board id: #{board_id}
* Board name: #{board.name}
* Number of comments: #{comments.count}
* Path: #{card_path(self, script_name: Account.sole.slug)}
+1 -1
View File
@@ -17,7 +17,7 @@ module Card::Triageable
end
def triage_into(column)
raise "The column must belong to the card collection" unless collection == column.collection
raise "The column must belong to the card board" unless board == column.board
transaction do
resume
+1 -1
View File
@@ -1,4 +1,4 @@
class Collection < ApplicationRecord
class Board < ApplicationRecord
include AutoClosing, Accessible, Broadcastable, Cards, Entropic, Filterable, Publishable, Triageable
belongs_to :creator, class_name: "User", default: -> { Current.user }
+5 -5
View File
@@ -1,4 +1,4 @@
module Collection::Accessible
module Board::Accessible
extend ActiveSupport::Concern
included do
@@ -11,7 +11,7 @@ module Collection::Accessible
end
def grant_to(users)
Access.insert_all Array(users).collect { |user| { collection_id: proxy_association.owner.id, user_id: user.id } }
Access.insert_all Array(users).collect { |user| { board_id: proxy_association.owner.id, user_id: user.id } }
end
def revoke_from(users)
@@ -69,7 +69,7 @@ module Collection::Accessible
.joins("LEFT JOIN cards ON mentions.source_id = cards.id AND mentions.source_type = 'Card'")
.joins("LEFT JOIN comments ON mentions.source_id = comments.id AND mentions.source_type = 'Comment'")
.joins("LEFT JOIN cards AS comment_cards ON comments.card_id = comment_cards.id")
.where("(mentions.source_type = 'Card' AND cards.collection_id = ?) OR (mentions.source_type = 'Comment' AND comment_cards.collection_id = ?)", id, id)
.where("(mentions.source_type = 'Card' AND cards.board_id = ?) OR (mentions.source_type = 'Comment' AND comment_cards.board_id = ?)", id, id)
end
def notifications_for_user(user)
@@ -85,8 +85,8 @@ module Collection::Accessible
.joins("LEFT JOIN cards AS event_cards ON events.eventable_id = event_cards.id AND events.eventable_type = 'Card'")
.joins("LEFT JOIN comments AS event_comments ON events.eventable_id = event_comments.id AND events.eventable_type = 'Comment'")
.joins("LEFT JOIN cards AS event_comment_cards ON event_comments.card_id = event_comment_cards.id")
.where("(notifications.source_type = 'Event' AND events.eventable_type = 'Card' AND event_cards.collection_id = ?) OR
(notifications.source_type = 'Event' AND events.eventable_type = 'Comment' AND event_comment_cards.collection_id = ?)",
.where("(notifications.source_type = 'Event' AND events.eventable_type = 'Card' AND event_cards.board_id = ?) OR
(notifications.source_type = 'Event' AND events.eventable_type = 'Comment' AND event_comment_cards.board_id = ?)",
id, id)
end
end
+1 -1
View File
@@ -1,4 +1,4 @@
module Collection::AutoClosing
module Board::AutoClosing
extend ActiveSupport::Concern
included do
+2 -2
View File
@@ -1,8 +1,8 @@
module Collection::Broadcastable
module Board::Broadcastable
extend ActiveSupport::Concern
included do
broadcasts_refreshes
broadcasts_refreshes_to ->(_) { :all_collections }
broadcasts_refreshes_to ->(_) { :all_boards }
end
end
+1 -1
View File
@@ -1,4 +1,4 @@
module Collection::Cards
module Board::Cards
extend ActiveSupport::Concern
included do
+1 -1
View File
@@ -1,4 +1,4 @@
module Collection::Entropic
module Board::Entropic
extend ActiveSupport::Concern
included do
+2 -2
View File
@@ -1,5 +1,5 @@
class Collection::Publication < ApplicationRecord
belongs_to :collection
class Board::Publication < ApplicationRecord
belongs_to :board
has_secure_token :key
end
+3 -3
View File
@@ -1,14 +1,14 @@
module Collection::Publishable
module Board::Publishable
extend ActiveSupport::Concern
included do
has_one :publication, class_name: "Collection::Publication", dependent: :destroy
has_one :publication, class_name: "Board::Publication", dependent: :destroy
scope :published, -> { joins(:publication) }
end
class_methods do
def find_by_published_key(key)
Collection::Publication.find_by!(key: key).collection
Board::Publication.find_by!(key: key).board
end
end
+1 -1
View File
@@ -1,4 +1,4 @@
module Collection::Triageable
module Board::Triageable
extend ActiveSupport::Concern
included do
+2 -2
View File
@@ -1,10 +1,10 @@
class Column < ApplicationRecord
include Positioned
belongs_to :collection, touch: true
belongs_to :board, touch: true
has_many :cards, dependent: :nullify
before_validation -> { self.color ||= Card::DEFAULT_COLOR }
after_save_commit -> { cards.touch_all }, if: -> { saved_change_to_name? || saved_change_to_color? }
after_destroy_commit -> { collection.cards.touch_all }
after_destroy_commit -> { board.cards.touch_all }
end
+3 -3
View File
@@ -16,11 +16,11 @@ module Column::Positioned
end
def left_column
collection.columns.where("position < ?", position).sorted.last
board.columns.where("position < ?", position).sorted.last
end
def right_column
collection.columns.where("position > ?", position).sorted.first
board.columns.where("position > ?", position).sorted.first
end
def leftmost?
@@ -33,7 +33,7 @@ module Column::Positioned
private
def set_position
max_position = collection.columns.maximum(:position) || 0
max_position = board.columns.maximum(:position) || 0
self.position = max_position + 1
end
+1 -1
View File
@@ -14,7 +14,7 @@ class Comment < ApplicationRecord
after_create_commit :watch_card_by_creator
delegate :collection, :watch_by, to: :card
delegate :board, :watch_by, to: :card
def to_partial_path
"cards/#{super}"
+1 -1
View File
@@ -17,6 +17,6 @@ module Comment::Eventable
end
def track_creation
track_event("created", collection: card.collection, creator: creator)
track_event("created", board: card.board, creator: creator)
end
end
+1 -1
View File
@@ -41,7 +41,7 @@ module Mentions
end
def mentionable_users
collection.users
board.users
end
def rich_text_associations
+1 -1
View File
@@ -1,7 +1,7 @@
class Event < ApplicationRecord
include Notifiable, Particulars, Promptable
belongs_to :collection
belongs_to :board
belongs_to :creator, class_name: "User"
belongs_to :eventable, polymorphic: true
+2 -2
View File
@@ -5,9 +5,9 @@ module Eventable
has_many :events, as: :eventable, dependent: :destroy
end
def track_event(action, creator: Current.user, collection: self.collection, **particulars)
def track_event(action, creator: Current.user, board: self.board, **particulars)
if should_track_event?
collection.events.create!(action: "#{eventable_prefix}_#{action}", creator:, collection:, eventable: self, particulars:)
board.events.create!(action: "#{eventable_prefix}_#{action}", creator:, board:, eventable: self, particulars:)
end
end
+5 -5
View File
@@ -27,7 +27,7 @@ class Filter < ApplicationRecord
result = result.unassigned if assignment_status.unassigned?
result = result.assigned_to(assignees.ids) if assignees.present?
result = result.where(creator_id: creators.ids) if creators.present?
result = result.where(collection: collections.ids) if collections.present?
result = result.where(board: boards.ids) if boards.present?
result = result.tagged_with(tags.ids) if tags.present?
result = result.where("cards.created_at": creation_window) if creation_window
result = result.closed_at_window(closure_window) if closure_window
@@ -44,16 +44,16 @@ class Filter < ApplicationRecord
self.class.normalize_params(as_params).blank?
end
def single_collection
collections.first if collections.one?
def single_board
boards.first if boards.one?
end
def single_workflow
collections.first.workflow if collections.pluck(:workflow_id).uniq.one?
boards.first.workflow if boards.pluck(:workflow_id).uniq.one?
end
def cacheable?
collections.exists?
boards.exists?
end
def cache_key
+4 -4
View File
@@ -11,7 +11,7 @@ module Filter::Params
assignee_ids: [],
creator_ids: [],
closer_ids: [],
collection_ids: [],
board_ids: [],
tag_ids: [],
terms: []
]
@@ -40,9 +40,9 @@ module Filter::Params
before_save { self.params_digest = self.class.digest_params(as_params) }
end
def used?(ignore_collections: false)
def used?(ignore_boards: false)
tags.any? || assignees.any? || creators.any? || closers.any? ||
terms.any? || card_ids&.any? || (!ignore_collections && collections.present?) ||
terms.any? || card_ids&.any? || (!ignore_boards && boards.present?) ||
assignment_status.unassigned? || !indexed_by.all? || !sorted_by.latest?
end
@@ -57,7 +57,7 @@ module Filter::Params
params[:assignment_status] = assignment_status
params[:terms] = terms
params[:tag_ids] = tags.ids
params[:collection_ids] = collections.ids
params[:board_ids] = boards.ids
params[:card_ids] = card_ids
params[:assignee_ids] = assignees.ids
params[:creator_ids] = creators.ids
+9 -9
View File
@@ -3,7 +3,7 @@ module Filter::Resources
included do
has_and_belongs_to_many :tags
has_and_belongs_to_many :collections
has_and_belongs_to_many :boards
has_and_belongs_to_many :assignees, class_name: "User", join_table: "assignees_filters", association_foreign_key: "assignee_id"
has_and_belongs_to_many :creators, class_name: "User", join_table: "creators_filters", association_foreign_key: "creator_id"
has_and_belongs_to_many :closers, class_name: "User", join_table: "closers_filters", association_foreign_key: "closer_id"
@@ -17,19 +17,19 @@ module Filter::Resources
destroy!
end
def collections
creator.collections.where id: super.ids
def boards
creator.boards.where id: super.ids
end
def collection_titles
if collections.none?
Collection.one? ? [ Collection.first.name ] : [ "all boards" ]
def board_titles
if boards.none?
Board.one? ? [ Board.first.name ] : [ "all boards" ]
else
collections.map(&:name)
boards.map(&:name)
end
end
def collections_label
collection_titles.to_sentence
def boards_label
board_titles.to_sentence
end
end
+3 -3
View File
@@ -1,6 +1,6 @@
class Notifier::CardEventNotifier < Notifier
delegate :creator, to: :source
delegate :collection, to: :card
delegate :board, to: :card
private
def recipients
@@ -8,11 +8,11 @@ class Notifier::CardEventNotifier < Notifier
when "card_assigned"
source.assignees.excluding(creator)
when "card_published"
collection.watchers.without(creator, *card.mentionees)
board.watchers.without(creator, *card.mentionees)
when "comment_created"
card.watchers.without(creator, *source.eventable.mentionees)
else
collection.watchers.without(creator)
board.watchers.without(creator)
end
end
+2 -2
View File
@@ -21,7 +21,7 @@ class Search
"highlight(cards_search_index, 0, '#{HIGHLIGHT_OPENING_MARK}', '#{HIGHLIGHT_CLOSING_MARK}') AS card_title",
"snippet(cards_search_index, 1, '#{HIGHLIGHT_OPENING_MARK}', '#{HIGHLIGHT_CLOSING_MARK}', '...', 20) AS card_description",
"null as comment_body",
"collections.name as collection_name",
"boards.name as board_name",
"cards.creator_id",
"cards.created_at",
"bm25(cards_search_index, 10.0, 2.0) AS score"
@@ -34,7 +34,7 @@ class Search
"cards.title AS card_title",
"null AS card_description",
"snippet(comments_search_index, 0, '#{HIGHLIGHT_OPENING_MARK}', '#{HIGHLIGHT_CLOSING_MARK}', '...', 20) AS comment_body",
"collections.name as collection_name",
"boards.name as board_name",
"comments.creator_id",
"comments.created_at",
"bm25(comments_search_index, 1.0) AS score"
+5 -5
View File
@@ -3,15 +3,15 @@ module User::Accessor
included do
has_many :accesses, dependent: :destroy
has_many :collections, through: :accesses
has_many :accessible_cards, through: :collections, source: :cards
has_many :boards, through: :accesses
has_many :accessible_cards, through: :boards, source: :cards
has_many :accessible_comments, through: :accessible_cards, source: :comments
after_create_commit :grant_access_to_collections, unless: :system?
after_create_commit :grant_access_to_boards, unless: :system?
end
private
def grant_access_to_collections
Access.insert_all Collection.all_access.pluck(:id).collect { |collection_id| { collection_id: collection_id, user_id: id } }
def grant_access_to_boards
Access.insert_all Board.all_access.pluck(:id).collect { |board_id| { board_id: board_id, user_id: id } }
end
end
+4 -4
View File
@@ -40,7 +40,7 @@ class User::DayTimeline
card_published
card_closed
card_reopened
card_collection_changed
card_board_changed
card_postponed
card_triaged
card_sent_back_to_triage
@@ -57,12 +57,12 @@ class User::DayTimeline
def timelineable_events
Event
.where(collection: collections)
.where(board: boards)
.where(action: TIMELINEABLE_ACTIONS)
end
def collections
filter.collections.presence || user.collections
def boards
filter.boards.presence || user.boards
end
def latest_event_before
+13 -13
View File
@@ -1,23 +1,23 @@
class User::Filtering
attr_reader :user, :filter, :expanded
delegate :as_params, :single_collection, to: :filter
delegate :as_params, :single_board, to: :filter
delegate :only_closed?, to: :filter
def initialize(user, filter, expanded: false)
@user, @filter, @expanded = user, filter, expanded
end
def collections
@collections ||= user.collections.ordered_by_recently_accessed
def boards
@boards ||= user.boards.ordered_by_recently_accessed
end
def selected_collection_titles
filter.collection_titles
def selected_board_titles
filter.board_titles
end
def selected_collections_label
filter.collections_label
def selected_boards_label
filter.boards_label
end
def tags
@@ -37,7 +37,7 @@ class User::Filtering
end
def any?
filter.used?(ignore_collections: true)
filter.used?(ignore_boards: true)
end
def show_indexed_by?
@@ -65,16 +65,16 @@ class User::Filtering
filter.closers.any?
end
def show_collections?
filter.collections.any?
def show_boards?
filter.boards.any?
end
def single_collection_or_first
def single_board_or_first
# Default to the first selected or, when no selection, to the first one
filter.collections.first || collections.first
filter.boards.first || boards.first
end
def cache_key
ActiveSupport::Cache.expand_cache_key([ user, filter, expanded?, collections, tags, users, filters ], "user-filtering")
ActiveSupport::Cache.expand_cache_key([ user, filter, expanded?, boards, tags, users, filters ], "user-filtering")
end
end
+1 -1
View File
@@ -2,7 +2,7 @@ module User::Timelined
extend ActiveSupport::Concern
included do
has_many :accessible_events, through: :collections, source: :events
has_many :accessible_events, through: :boards, source: :events
end
def timeline_for(day, filter:)
+2 -2
View File
@@ -11,7 +11,7 @@ class Webhook < ApplicationRecord
card_closed
card_postponed
card_auto_postponed
card_collection_changed
card_board_changed
card_published
card_reopened
card_sent_back_to_triage
@@ -25,7 +25,7 @@ class Webhook < ApplicationRecord
has_many :deliveries, dependent: :delete_all
has_one :delinquency_tracker, dependent: :delete
belongs_to :collection
belongs_to :board
serialize :subscribed_actions, type: Array, coder: JSON
+1 -1
View File
@@ -2,7 +2,7 @@ module Webhook::Triggerable
extend ActiveSupport::Concern
included do
scope :triggered_by, ->(event) { where(collection: event.collection).triggered_by_action(event.action) }
scope :triggered_by, ->(event) { where(board: event.board).triggered_by_action(event.action) }
scope :triggered_by_action, ->(action) { where("subscribed_actions LIKE ?", "%\"#{action}\"%") }
end
+1 -1
View File
@@ -13,7 +13,7 @@
<input placeholder="Filter…" class="input input--transparent full-width txt-small" type="search" autocorrect="off" autocomplete="off" data-1p-ignore="true" data-filter-target="input" data-action="input->filter#filter">
<ul class="settings__user-list margin-block-half" data-filter-target="list">
<%= render partial: "account/settings/user", collection: users %>
<%= render partial: "account/settings/user", board: users %>
</ul>
</div>
+4 -4
View File
@@ -1,7 +1,7 @@
<% if filter.collections.any? %>
<% filter.collections.each do |collection| %>
<%= turbo_stream_from collection %>
<% if filter.boards.any? %>
<% filter.boards.each do |board| %>
<%= turbo_stream_from board %>
<% end %>
<% else %>
<%= turbo_stream_from :all_collections %>
<%= turbo_stream_from :all_boards %>
<% end %>
+2 -2
View File
@@ -8,8 +8,8 @@ json.cache! [ card, card.column&.color ] do
json.url card_url(card)
json.collection do
json.partial! "collections/collection", locals: { collection: card.collection }
json.board do
json.partial! "boards/board", locals: { board: card.board }
end
json.column do
+1 -1
View File
@@ -8,7 +8,7 @@
<div class="card-perma__bg">
<%= card_article_tag card, class: "card" do %>
<header class="card__header">
<%= render "cards/display/perma/collection", card: card %>
<%= render "cards/display/perma/board", card: card %>
<%= render "cards/display/perma/tags", card: card %>
</header>
+1 -1
View File
@@ -1,6 +1,6 @@
<%= messages_tag(card) do %>
<% if card.published? %>
<%= render partial: "cards/comments/comment", collection: card.comments.chronologically, cached: true %>
<%= render partial: "cards/comments/comment", board: card.comments.chronologically, cached: true %>
<%= render "cards/comments/new", card: card %>
<%= render "cards/comments/watchers", card: card %>
+5 -5
View File
@@ -1,4 +1,4 @@
<%= turbo_frame_tag "collection_picker" do %>
<%= turbo_frame_tag "board_picker" do %>
<%= tag.div class: "max-width full-width", data: {
action: "turbo:before-cache@document->dialog#close dialog:show@document->navigable-list#reset keydown->navigable-list#navigate filter:changed->navigable-list#reset",
controller: "filter navigable-list",
@@ -11,12 +11,12 @@
type: "search", autocorrect: "off", autocomplete: "off", data: { "1p-ignore": "true", filter_target: "input", action: "input->filter#filter" } %>
<ul class="popup__list margin-block-start-half margin-none-block-end" data-filter-target="list">
<% @collections.each do |collection| %>
<li class="popup__item" data-filter-target="item" data-navigable-list-target="item" aria-checked="<%= @card.collection == collection %>">
<%= button_to card_collection_path(@card, params: { collection_id: collection.id }), method: :patch,
<% @boards.each do |board| %>
<li class="popup__item" data-filter-target="item" data-navigable-list-target="item" aria-checked="<%= @card.board == board %>">
<%= button_to card_board_path(@card, params: { board_id: board.id }), method: :patch,
class: "popup__btn btn",
form_class: "max-width flex-item-grow" do %>
<span class="overflow-ellipsis flex-item-grow"><%= collection.name %></span>
<span class="overflow-ellipsis flex-item-grow"><%= board.name %></span>
<%= icon_tag "check", size: 18, class: "checked flex-item-no-shrink flex-item-justify-end", style: "--icon-size: 1em" %>
<% end %>
</li>
+1 -1
View File
@@ -11,7 +11,7 @@
action: "turbo:submit-end->local-save#submit keydown.ctrl+enter->form#debouncedSubmit:prevent keydown.meta+enter->form#debouncedSubmit:prevent keydown.esc->form#cancel:stop" } do |form| %>
<%= form.rich_textarea :body, required: true, placeholder: new_comment_placeholder(card),
data: { local_save_target: "input", action: "lexxy:change->form#disableSubmitWhenInvalid lexxy:change->local-save#save turbo:morph-element->local-save#restoreContent" } do %>
<%= general_prompts(@card.collection) %>
<%= general_prompts(@card.board) %>
<% end %>
<%= form.button class: "comment__submit btn btn--reversed flex-item-justify-start", data: { form_target: "submit" }, disabled: true do %>
<span>Post this comment</span>
+1 -1
View File
@@ -9,7 +9,7 @@
<%= form_with model: [ @card, @comment ], class: "flex flex-column gap full-width",
data: { controller: "form", action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do |form| %>
<%= form.rich_textarea :body, required: true, autofocus: true, placeholder: new_comment_placeholder(@card) do %>
<%= general_prompts(@card.collection) %>
<%= general_prompts(@card.board) %>
<% end %>
<div class="flex gap-half justify-start">
<%= form.button class: "btn btn--reversed", type: :submit do %>
@@ -1,7 +1,7 @@
<%= turbo_frame_tag comment, :reacting do %>
<div class="reactions">
<div id="<%= dom_id(comment, :reactions) %>" class="reactions__list">
<%= render partial: "cards/comments/reactions/reaction", collection: comment.reactions.includes(:reacter).ordered %>
<%= render partial: "cards/comments/reactions/reaction", board: comment.reactions.includes(:reacter).ordered %>
</div>
<%= turbo_frame_tag comment, :new_reaction do %>
+1 -1
View File
@@ -22,7 +22,7 @@
<%= form.rich_textarea :description, class: "card-field__description rich-text-content",
placeholder: "Add some notes, context, pictures, or video about this…",
data: { action: "lexxy:change->auto-save#change focusout->auto-save#submit" } do %>
<%= general_prompts(card.collection) %>
<%= general_prompts(card.board) %>
<% end %>
<% end %>
<% end %>
+1 -1
View File
@@ -3,7 +3,7 @@
<%= card_article_tag card, class: "card", draggable: draggable, data: { id: card.id, drag_and_drop_target: "item" } do %>
<div class="flex flex-column flex-item-grow max-inline-size">
<header class="card__header">
<%= render "cards/display/preview/collection", card: card %>
<%= render "cards/display/preview/board", card: card %>
<%= render "cards/display/preview/tags", card: card %>
<%= render "cards/display/preview/steps", card: card %>
<%= icon_tag "attachment", class: "card__attachments-indicator translucent" if card.has_attachments? %>
+1 -1
View File
@@ -1 +1 @@
<%= render partial: "cards/display/preview", collection: cards, as: :card, locals: { draggable: local_assigns.fetch(:draggable, false) }, cached: true %>
<%= render partial: "cards/display/preview", board: cards, as: :card, locals: { draggable: local_assigns.fetch(:draggable, false) }, cached: true %>
@@ -1,13 +1,13 @@
<%= card_article_tag card, class: "card" do %>
<div class="flex flex-column flex-item-grow max-inline-size">
<header class="card__header">
<div class="card__collection flex align-start">
<div class="card__board flex align-start">
<span class="card__id">
<span class="for-screen-reader">Card number</span>
<%= card.id %>
</span>
<span class="card__collection-name">
<span class="overflow-ellipsis"><%= card.collection.name %></span>
<span class="card__board-name">
<span class="overflow-ellipsis"><%= card.board.name %></span>
</span>
</div>
@@ -37,6 +37,6 @@
<% if card.entropic? %>
<%= render "cards/display/preview/bubble", card: card %>
<span class="card__collection-name">
<span class="card__board-name">
<% end %>
<% end %>
@@ -1 +1 @@
<%= render partial: "cards/display/public_preview", collection: cards, as: :card, cached: true %>
<%= render partial: "cards/display/public_preview", board: cards, as: :card, cached: true %>
@@ -1,10 +1,10 @@
<label class="card__collection">
<label class="card__board">
<span class="card__id">
<span class="for-screen-reader">Card number</span>
<%= card.id %>
</span>
<span class="card__collection-name">
<span class="overflow-ellipsis"><%= card.collection.name %></span>
<span class="card__board-name">
<span class="overflow-ellipsis"><%= card.board.name %></span>
</span>
<%= yield %>
</label>
@@ -1,12 +1,12 @@
<%= render "cards/display/common/collection", card: card do %>
<%= render "cards/display/common/board", card: card do %>
<div class="align-self-center position-relative txt-small" data-controller="dialog" data-action="keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" <%= "hidden" if card.closed? %>>
<button class="collection-picker__button btn btn--reversed card__hide-on-index fill-transparent" data-action="click->dialog#open:stop">
<button class="board-picker__button btn btn--reversed card__hide-on-index fill-transparent" data-action="click->dialog#open:stop">
<%= icon_tag "caret-down" %>
<span class="for-screen-reader">Choose a collection for this card</span>
<span class="for-screen-reader">Choose a board for this card</span>
</button>
<dialog class="popup panel flex-column align-start gap-half fill-white shadow margin-block-double" data-dialog-target="dialog" data-action="turbo:before-morph-attribute->dialog#preventCloseOnMorphing turbo:submit-end->dialog#close">
<%= turbo_frame_tag "collection_picker", src: edit_card_collection_path(card), target: "_top", refresh: "morph" %>
<%= turbo_frame_tag "board_picker", src: edit_card_board_path(card), target: "_top", refresh: "morph" %>
</dialog>
</div>
<% end %>
@@ -1,5 +1,5 @@
<ol class="steps txt-small margin-block-start-auto">
<%= render partial: "cards/steps/step", collection: card.steps, as: :step %>
<%= render partial: "cards/steps/step", board: card.steps, as: :step %>
<li id="<%= dom_id(card, :new_step) %>" class="step">
<input type="checkbox" class="step__checkbox" disabled>
+1 -1
View File
@@ -13,7 +13,7 @@
<% if card.tags.any? %>
<div class="min-width overflow-ellipsis">
<% card.tags.each_with_index do |tag, index| %>
<%= link_to cards_path(collection_ids: [ card.collection ], tag_ids: [ tag.id ]),
<%= link_to cards_path(board_ids: [ card.board ], tag_ids: [ tag.id ]),
class: "card__tag btn btn--plain min-width txt-uppercase fill-transparent" do %>
<%= tag.title %>
<% end %><%= "," unless index == card.tags.size - 1 %>

Some files were not shown because too many files have changed in this diff Show More