Merge branch 'main' into fizzy-menu-everywhere
* main: Add a focus effect when hovering columns Fix up hotkeys test: backfill hotkeys helper tests refactor: remove unused routes associated with "resource :account" test: backfill account route tests to prepare for refactor Alphabetically order concerns (#992) Copy Don't show the filter if there aren't any tags Add clearer labels for sorting options Prevent deleting the last collection Don't show "All collections" when there's only the default collection Rename engagement columns
This commit is contained in:
@@ -119,6 +119,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
.cards--related:not(:hover):not(.drag-and-drop__hover-container) {
|
||||
.card {
|
||||
box-shadow: 0 0 1px var(--color-ink-medium);
|
||||
opacity: 0.9;
|
||||
transition: box-shadow 450ms ease-in-out, opacity 150ms ease-in-out;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
opacity: 0.8;
|
||||
transition: opacity 150ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Column elements
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class Accounts::EntropyConfigurationsController < ApplicationController
|
||||
class Account::EntropyConfigurationsController < ApplicationController
|
||||
def update
|
||||
Entropy::Configuration.default.update!(entropy_configuration_params)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class Accounts::JoinCodesController < ApplicationController
|
||||
class Account::JoinCodesController < ApplicationController
|
||||
def show
|
||||
render svg: RQRCode::QRCode.new(join_url(Account.sole.join_code)).as_svg(viewbox: true, fill: :white, color: :black)
|
||||
end
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class Accounts::SettingsController < ApplicationController
|
||||
class Account::SettingsController < ApplicationController
|
||||
include FilterScoped
|
||||
|
||||
def show
|
||||
@@ -43,4 +43,17 @@ module FiltersHelper
|
||||
concat tag.kbd(key)
|
||||
end
|
||||
end
|
||||
|
||||
def sorted_by_label(sort_value)
|
||||
case sort_value
|
||||
when "newest"
|
||||
"Newest to oldest"
|
||||
when "oldest"
|
||||
"Oldest to newest"
|
||||
when "latest"
|
||||
"Recently updated"
|
||||
else
|
||||
sort_value.humanize
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
module HotkeysHelper
|
||||
# Pass in an array of chorded keys, e.g. ["ctrl", "shift", "J"]
|
||||
def hotkey_label(hotkey)
|
||||
hotkey.split(",").first if hotkey
|
||||
case hotkey
|
||||
when Array
|
||||
hotkey.map { |key|
|
||||
if key == "ctrl" && platform.mac?
|
||||
"⌘"
|
||||
elsif key == "enter"
|
||||
platform.mac? ? "return" : "enter"
|
||||
else
|
||||
key
|
||||
end
|
||||
}.join()
|
||||
else
|
||||
hotkey.split(",").first if hotkey
|
||||
end
|
||||
hotkey.map do |key|
|
||||
if key == "ctrl" && platform.mac?
|
||||
"⌘"
|
||||
elsif key == "enter"
|
||||
platform.mac? ? "return" : "enter"
|
||||
else
|
||||
key
|
||||
end.capitalize
|
||||
end.join("+").gsub(/⌘\+/, "⌘")
|
||||
end
|
||||
end
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
class User < ApplicationRecord
|
||||
include Accessor, Attachable, Assignee, Mentionable, Named, Role, Searcher,
|
||||
SignalUser, Staff, Transferable, Conversational, AiQuota
|
||||
include Accessor, AiQuota, Assignee, Attachable, Mentionable, Named, Role,
|
||||
Searcher, SignalUser, Staff, Transferable, Conversational
|
||||
include Timelined # Depends on Accessor
|
||||
|
||||
has_one_attached :avatar
|
||||
|
||||
@@ -56,6 +56,7 @@ class User::Filtering
|
||||
end
|
||||
|
||||
def show_tags?
|
||||
return unless Tag.any?
|
||||
expanded? || filter.tags.any?
|
||||
end
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<div class="settings__panel panel shadow center">
|
||||
<h2 class="divider txt-large">Do or Die</h2>
|
||||
<h2 class="divider txt-large">Sink or Swim</h2>
|
||||
<p class="margin-none-block-start">Choose default settings for this account. You can override them in individual collections.</p>
|
||||
<%= render "entropy/auto_close", model: account.default_entropy_configuration, url: account_entropy_configuration_path %>
|
||||
</div>
|
||||
+2
-2
@@ -5,13 +5,13 @@
|
||||
navigable_list_actionable_items_value: true
|
||||
} do %>
|
||||
<h2 class="divider txt-large">People on the account</h2>
|
||||
<%#= render "accounts/invite" # Scheduled work in https://3.basecamp.com/2914079/buckets/37331921/todos/8746162337 %>
|
||||
<%#= render "account/invite" # Scheduled work in https://3.basecamp.com/2914079/buckets/37331921/todos/8746162337 %>
|
||||
|
||||
<div class="settings__user-filter">
|
||||
<input placeholder="Filter…" class="input input--transparent full-width" type="search" autocorrect="off" autocomplete="off" data-1p-ignore="true" data-filter-target="input" data-action="input->filter#filter">
|
||||
|
||||
<ul class="settings__user-list" data-filter-target="list">
|
||||
<%= render partial: "accounts/user", collection: users %>
|
||||
<%= render partial: "account/user", collection: users %>
|
||||
</ul>
|
||||
|
||||
<footer class="settings__user-list-tips">
|
||||
+2
-2
@@ -12,6 +12,6 @@
|
||||
<% end %>
|
||||
|
||||
<section class="settings">
|
||||
<%= render "accounts/settings/users", users: @users %>
|
||||
<%= render "accounts/settings/entropy_configuration", account: @account %>
|
||||
<%= render "account/settings/users", users: @users %>
|
||||
<%= render "account/settings/entropy_configuration", account: @account %>
|
||||
</section>
|
||||
@@ -5,7 +5,7 @@
|
||||
<%= form.hidden_field :engagement, value: "on_deck" %>
|
||||
<%= form.label :engagement, value: "on_deck", class: "btn", aria: { label: "Move to On Deck"} do %>
|
||||
<%= form.radio_button :engagement, "on_deck", checked: @card.on_deck?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
|
||||
<span>Maybe?</span>
|
||||
<span>On Deck</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<%= form.hidden_field :engagement, value: "doing" %>
|
||||
<%= form.label :engagement, value: "doing", class: "btn", aria: { label: "Move to Doing"} do %>
|
||||
<%= form.radio_button :engagement, "doing", checked: @card.doing?, class: "for-screen-reader", data: { action: "change->form#submit" } %>
|
||||
<span style="min-inline-size: 8ch">Yes!</span>
|
||||
<span style="min-inline-size: 8ch">Working On</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
dragover->drag-and-drop#dragOver
|
||||
drop->drag-and-drop#drop
|
||||
dragend->drag-and-drop#dragEnd" } do %>
|
||||
<div class="card-columns">
|
||||
<div class="card-columns" data-controller="related-element" data-related-element-highlight-class="cards--related">
|
||||
<%= render "cards/index/engagement/on_deck", **@on_deck.to_h %>
|
||||
<%= render "cards/index/engagement/considering", **@considering.to_h %>
|
||||
<%= render "cards/index/engagement/doing", **@doing.to_h %>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="cards__heading" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="cards__filter btn input input--select borderless overflow-ellipsis" data-action="click->dialog#open:stop">
|
||||
<% if filter.stages.any? %>
|
||||
Yes!: <%= filter.stages.map(&:name).to_sentence %>
|
||||
Working On: <%= filter.stages.map(&:name).to_sentence %>
|
||||
<% else %>
|
||||
Yes!
|
||||
Working On
|
||||
<% end %>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
<section id="considering-cards" class="cards cards--considering" data-drag-and-drop-target="container" data-drop-target="considering">
|
||||
<section id="considering-cards" class="cards cards--considering"
|
||||
data-drag-and-drop-target="container"
|
||||
data-drop-target="considering"
|
||||
data-related-element-target="related"
|
||||
data-related-element-group-value="card-columns"
|
||||
data-action="mouseover->related-element#highlight mouseout->related-element#unhighlight">
|
||||
<div class="cards__decoration"></div>
|
||||
<%= render "cards/index/add_card_button", user_filtering: @user_filtering %>
|
||||
<% if page.used? %>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<section id="doing-cards" class="cards cards--doing" style="view-transition-name: cards-container;" data-drag-and-drop-target="container" data-drop-target="doing">
|
||||
<section id="doing-cards" class="cards cards--doing"
|
||||
data-drag-and-drop-target="container"
|
||||
data-drop-target="doing"
|
||||
data-related-element-target="related"
|
||||
data-related-element-group-value="card-columns"
|
||||
data-action="mouseover->related-element#highlight mouseout->related-element#unhighlight">
|
||||
<% if workflow = filter.single_workflow %>
|
||||
<%= render "cards/index/workflow_filter", workflow: workflow, filter: filter %>
|
||||
<% else %>
|
||||
<h2 class="cards__heading">
|
||||
Yes!
|
||||
Working On
|
||||
</h2>
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<section id="on-deck-cards" class="cards cards--on-deck" data-drag-and-drop-target="container" data-drop-target="on_deck">
|
||||
<h2 class="cards__heading">Maybe?</h2>
|
||||
<section id="on-deck-cards" class="cards cards--on-deck"
|
||||
data-drag-and-drop-target="container"
|
||||
data-drop-target="on_deck"
|
||||
data-related-element-target="related"
|
||||
data-related-element-group-value="card-columns"
|
||||
data-action="mouseover->related-element#highlight mouseout->related-element#unhighlight">
|
||||
<h2 class="cards__heading">On Deck</h2>
|
||||
|
||||
<% if page.used? %>
|
||||
<%= render partial: "cards/display/preview", collection: page.records, as: :card, locals: { draggable: true }, cached: true %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= turbo_frame_tag @collection, :entropy_configuration do %>
|
||||
<h2 class="divider txt-large">Do or Die</h2>
|
||||
<h2 class="divider txt-large">Sink or Swim</h2>
|
||||
<%= render "entropy/auto_close", model: collection, url: collection_entropy_configuration_path(collection) %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<%= form_with model: collection, class: "txt-align-center margin-block-start-auto", method: :delete do |form| %>
|
||||
<%= form.button class: "btn txt-negative borderless txt-small", data: { turbo_confirm: "Are you sure you want to permanently delete this Collection?" } do %>
|
||||
<%= icon_tag "trash" %>
|
||||
<span>Delete this Collection</span>
|
||||
<% if Current.user.collections.many? %>
|
||||
<%= form_with model: collection, class: "txt-align-center margin-block-start-auto", method: :delete do |form| %>
|
||||
<%= form.button class: "btn txt-negative borderless txt-small", data: { turbo_confirm: "Are you sure you want to permanently delete this Collection?" } do %>
|
||||
<%= icon_tag "trash" %>
|
||||
<span>Delete this Collection</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<div class="separator margin-block-half" style="--border-color: var(--color-ink-light); min-block-size: 3lh;"></div>
|
||||
|
||||
<div class="flex flex-column full-width" style="flex-basis: 48%">
|
||||
<strong>Cards in Maybe?/Yes!</strong>
|
||||
<strong>Cards in On Deck/Working On</strong>
|
||||
<p class="txt-x-small margin-none-block-start">Back to The Stream after…</p>
|
||||
<%= form_with model: model, url: url, data: { controller: "form" } do |form| %>
|
||||
<%= render "entropy/knob",
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
<% clear_url_path = user_filtering.self_filter_path(user_filtering.as_params.except(:collection_ids)) %>
|
||||
|
||||
<% if Current.user.collections.one? %>
|
||||
<%= link_to clear_url_path, class: "popup__group", id: "filter-collection-init", data: { filter_target: "item", navigable_list_target: "item" } do %>
|
||||
<%= tag.div class: "popup__item btn" do %>
|
||||
<span class="overflow-ellipsis"><%= Current.user.collections.first.name %></span>
|
||||
<span class="txt-ink translucent flex-item-no-shrink flex-item-justify-end"><span class="txt-x-small txt-uppercase">GO TO</span> ›</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% elsif Current.user.collections.many? %>
|
||||
<% if Current.user.collections.many? %>
|
||||
<li class="popup__group" data-filter-target="item" data-navigable-list-target="item" id="filter-collection-all">
|
||||
<%= link_to clear_url_path, class: "btn txt-xx-small flex-item-no-shrink" do %>
|
||||
<%= check_box_tag "filter_collections", nil, user_filtering.collections.blank?, class: "form-checkbox" %>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="quick-filter position-relative <%= "default-value" if filter.sorted_by.latest? %>" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
<%= filter.sorted_by.humanize %>
|
||||
<%= sorted_by_label(filter.sorted_by) %>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "popup__item btn" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= sort.humanize %></span>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= sorted_by_label(sort) %></span>
|
||||
<% if filter.sorted_by == sort %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<section id="doing-cards" class="cards cards--doing" style="view-transition-name: cards-container;">
|
||||
<section id="doing-cards" class="cards cards--doing">
|
||||
<h2 class="cards__heading">
|
||||
Yes!
|
||||
Working On
|
||||
</h2>
|
||||
|
||||
<% if page.used? %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<section id="considering-cards" class="cards cards--on-deck">
|
||||
<h2 class="cards__heading">
|
||||
Maybe?
|
||||
On Deck
|
||||
</h2>
|
||||
|
||||
<% if page.used? %>
|
||||
|
||||
+4
-7
@@ -1,11 +1,8 @@
|
||||
Rails.application.routes.draw do
|
||||
resource :account do
|
||||
resource :join_code, module: :accounts
|
||||
|
||||
scope module: :accounts do
|
||||
resource :settings
|
||||
resource :entropy_configuration
|
||||
end
|
||||
namespace :account do
|
||||
resource :join_code
|
||||
resource :settings
|
||||
resource :entropy_configuration
|
||||
end
|
||||
|
||||
resources :users do
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require "test_helper"
|
||||
|
||||
class Accounts::EntropyConfigurationsControllerTest < ActionDispatch::IntegrationTest
|
||||
class Account::EntropyConfigurationsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in_as :kevin
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require "test_helper"
|
||||
|
||||
class Accounts::SettingsControllerTest < ActionDispatch::IntegrationTest
|
||||
class Account::SettingsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in_as :kevin
|
||||
end
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
require "test_helper"
|
||||
|
||||
class HotkeysHelperTest < ActionView::TestCase
|
||||
include SetPlatform
|
||||
|
||||
test "mac modifier key" do
|
||||
emulate_mac
|
||||
|
||||
assert_equal "⌘J", hotkey_label([ "⌘", "J" ])
|
||||
end
|
||||
|
||||
test "linux modifier key" do
|
||||
emulate_linux
|
||||
|
||||
assert_equal "Ctrl+J", hotkey_label([ "ctrl", "J" ])
|
||||
end
|
||||
|
||||
test "mac enter" do
|
||||
emulate_mac
|
||||
|
||||
assert_equal "Return+J", hotkey_label([ "enter", "J" ])
|
||||
end
|
||||
|
||||
test "linux enter" do
|
||||
emulate_linux
|
||||
|
||||
assert_equal "Enter+J", hotkey_label([ "enter", "J" ])
|
||||
end
|
||||
|
||||
test "mac hyper" do
|
||||
emulate_mac
|
||||
|
||||
assert_equal "Hyper+J", hotkey_label([ "hyper", "J" ])
|
||||
end
|
||||
|
||||
test "linux hyper" do
|
||||
emulate_linux
|
||||
|
||||
assert_equal "Hyper+J", hotkey_label([ "hyper", "J" ])
|
||||
end
|
||||
|
||||
private
|
||||
def emulate_mac
|
||||
stub_platform = ApplicationPlatform.new("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36")
|
||||
self.stubs(:platform).returns(stub_platform)
|
||||
end
|
||||
|
||||
def emulate_linux
|
||||
stub_platform = ApplicationPlatform.new("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36")
|
||||
self.stubs(:platform).returns(stub_platform)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
require "test_helper"
|
||||
|
||||
class RouteTest < ActionDispatch::IntegrationTest
|
||||
test "account/join_code" do
|
||||
assert_recognizes({ controller: "account/join_codes", action: "show" }, "/account/join_code")
|
||||
end
|
||||
|
||||
test "account/settings" do
|
||||
assert_recognizes({ controller: "account/settings", action: "show" }, "/account/settings")
|
||||
end
|
||||
|
||||
test "account/entropy_configuration" do
|
||||
assert_recognizes({ controller: "account/entropy_configurations", action: "show" }, "/account/entropy_configuration")
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user