From cda20600b1fb72cee65fc63de80469823b41302a Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 12:16:32 +0200 Subject: [PATCH 01/19] Show mentions in the editor --- Gemfile | 2 +- Gemfile.lock | 13 ++++---- app/assets/stylesheets/actiontext-lexical.css | 32 ++++++++++++++++++- app/assets/stylesheets/rich-text-content.css | 22 +++++++++++-- app/controllers/prompts/users_controller.rb | 6 ++++ app/helpers/rich_text_helper.rb | 5 +++ app/models/user.rb | 6 +++- app/views/cards/edit.html.erb | 4 ++- app/views/prompts/users/_user.html.erb | 10 ++++++ app/views/prompts/users/index.html.erb | 1 + app/views/users/_attachable.html.erb | 2 ++ config/routes.rb | 4 +++ 12 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 app/controllers/prompts/users_controller.rb create mode 100644 app/helpers/rich_text_helper.rb create mode 100644 app/views/prompts/users/_user.html.erb create mode 100644 app/views/prompts/users/index.html.erb create mode 100644 app/views/users/_attachable.html.erb diff --git a/Gemfile b/Gemfile index 8c43ff533..4935a7c87 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "rqrcode" gem "redcarpet" gem "rouge" gem "jbuilder" -gem "actiontext-lexical", bc: "actiontext-lexical" +gem "actiontext-lexical", path: "/Users/jorge/Work/jorgemanrubia/actiontext-lexical" gem "image_processing", "~> 1.14" gem "platform_agent" gem "aws-sdk-s3", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 696e77ae4..27b510c14 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -GIT - remote: https://github.com/basecamp/actiontext-lexical - revision: 3f1ec3916f468ac2bb626091bcb97469c2c52483 - specs: - actiontext-lexical (0.1.0) - rails (>= 8.0.2) - GIT remote: https://github.com/basecamp/active_record-tenanted revision: f6fca189655ae6609d10ecad7cceed61592320c4 @@ -154,6 +147,12 @@ GIT thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) +PATH + remote: /Users/jorge/Work/jorgemanrubia/actiontext-lexical + specs: + actiontext-lexical (0.1.0) + rails (>= 8.0.2) + GEM remote: https://rubygems.org/ specs: diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index a8a3e227a..db03addc8 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -1,5 +1,9 @@ lexical-editor { - .node--selected { + display: block; + position: relative; + overflow: visible; + + .node--selected:not(.attachment--custom) { &:not(:has(img)) { box-shadow: 0 0 0 var(--hover-size) var(--hover-color); } @@ -134,3 +138,29 @@ lexical-toolbar { } } } + +/* Debug styles by Jorge */ +.lexical-prompt-menu { + background: white; + border: 2px solid black; + list-style: none; + + margin: 0; + padding: 0; + min-height: 100px; + min-width: 300px; + + visibility: hidden; + + &.lexical-prompt-menu--visible { + visibility: initial; + } + + [aria-selected] { + border: 1px solid red; + } +} + +.attachment--custom.node--selected { + box-shadow: 0 0 0 var(--hover-size) var(--hover-color); +} diff --git a/app/assets/stylesheets/rich-text-content.css b/app/assets/stylesheets/rich-text-content.css index 9b8c91cf6..1652b4cbb 100644 --- a/app/assets/stylesheets/rich-text-content.css +++ b/app/assets/stylesheets/rich-text-content.css @@ -20,7 +20,7 @@ :where(h5) { font-size: 0.83em; } :where(h6) { font-size: 0.67em; } - :where(p, ul, ol, dl, blockquote, figure, .attachment) { + :where(p, ul, ol, dl, blockquote, figure:not(.attachment--custom), .attachment:not(.attachment--custom)) { margin-block: var(--block-margin); overflow-wrap: break-word; text-wrap: pretty; @@ -54,7 +54,7 @@ } /* Attachments */ - .attachment { + .attachment:not(.attachment--custom) { block-size: auto; display: inline-block; inline-size: 100%; @@ -221,7 +221,7 @@ } /* Attachment junk gets wrapped in a paragraph causing unwanted space */ - p:has(action-text-attachment) { + p:has(action-text-attachment[src]) { display: none; + * { @@ -330,4 +330,20 @@ } } } + + /* Debug styles by Jorge */ + /* Custom attachments such as mentions, etc. */ + .attachment--custom { + display: inline; + padding: 0; + margin: 0; + white-space: normal; + } + + .attachment--custom, .lexical-prompt-menu__item, action-text-attachment { + img { + display: inline; + width: 24px; + } + } } diff --git a/app/controllers/prompts/users_controller.rb b/app/controllers/prompts/users_controller.rb new file mode 100644 index 000000000..1aaf995c4 --- /dev/null +++ b/app/controllers/prompts/users_controller.rb @@ -0,0 +1,6 @@ +class Prompts::UsersController < ApplicationController + def index + @users = User.all + render layout: false + end +end diff --git a/app/helpers/rich_text_helper.rb b/app/helpers/rich_text_helper.rb new file mode 100644 index 000000000..e3ac46c83 --- /dev/null +++ b/app/helpers/rich_text_helper.rb @@ -0,0 +1,5 @@ +module RichTextHelper + def mentions_prompt + content_tag "lexical-prompt", "", trigger: "@", src: prompts_users_path, name: "mention" + end +end diff --git a/app/models/user.rb b/app/models/user.rb index d68ccff46..c1dbc8c83 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ class User < ApplicationRecord - include Accessor, Assignee, Mentionable, Named, Role, Transferable + include Accessor, ActionText::Attachable, Assignee, Mentionable, Named, Role, Transferable include Timelined # Depends on Accessor has_one_attached :avatar @@ -25,6 +25,10 @@ class User < ApplicationRecord update! active: false, email_address: deactived_email_address end + def to_attachable_partial_path + "users/attachable" + end + private def deactived_email_address email_address.sub(/@/, "-deactivated-#{SecureRandom.uuid}@") diff --git a/app/views/cards/edit.html.erb b/app/views/cards/edit.html.erb index d7cbe9e6c..4a6043125 100644 --- a/app/views/cards/edit.html.erb +++ b/app/views/cards/edit.html.erb @@ -10,7 +10,9 @@ <%= form.rich_textarea :description, class: "card-field__description rich-text-content", placeholder: "Add some notes, context, pictures, or video about this…", - data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } %> + data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do %> + <%= mentions_prompt %> + <% end %> <%= form.button "Save changes", type: :submit, class: "btn btn--reversed", style: "--btn-background: #{@card.color}" %> <%= link_to "Close editor and discard changes", collection_card_path(@card.collection, @card), data: { form_target: "cancel" }, hidden: true %> diff --git a/app/views/prompts/users/_user.html.erb b/app/views/prompts/users/_user.html.erb new file mode 100644 index 000000000..7204e5162 --- /dev/null +++ b/app/views/prompts/users/_user.html.erb @@ -0,0 +1,10 @@ +" sgid="<%= user.attachable_sgid %>"> + + + diff --git a/app/views/prompts/users/index.html.erb b/app/views/prompts/users/index.html.erb new file mode 100644 index 000000000..4d78c50f9 --- /dev/null +++ b/app/views/prompts/users/index.html.erb @@ -0,0 +1 @@ +<%= render partial: "prompts/users/user", collection: @users %> diff --git a/app/views/users/_attachable.html.erb b/app/views/users/_attachable.html.erb new file mode 100644 index 000000000..0f973fc6f --- /dev/null +++ b/app/views/users/_attachable.html.erb @@ -0,0 +1,2 @@ +<%= avatar_image_tag user %> +<%= user.name %> diff --git a/config/routes.rb b/config/routes.rb index 3e9761dd4..dc00a8766 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -103,6 +103,10 @@ Rails.application.routes.draw do resources :pins end + namespace :prompts do + resources :users + end + namespace :public do resources :collections do scope module: :collections do From 0b8d93be020e06accb3743917f003685373edf65 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 12:28:00 +0200 Subject: [PATCH 02/19] Prefer first names for now --- app/views/prompts/users/_user.html.erb | 2 +- app/views/users/_attachable.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/prompts/users/_user.html.erb b/app/views/prompts/users/_user.html.erb index 7204e5162..836467bca 100644 --- a/app/views/prompts/users/_user.html.erb +++ b/app/views/prompts/users/_user.html.erb @@ -5,6 +5,6 @@ diff --git a/app/views/users/_attachable.html.erb b/app/views/users/_attachable.html.erb index 0f973fc6f..d6e474b6c 100644 --- a/app/views/users/_attachable.html.erb +++ b/app/views/users/_attachable.html.erb @@ -1,2 +1,2 @@ <%= avatar_image_tag user %> -<%= user.name %> +<%= user.first_name %> From 6446e5b409eb6df2ab23eb7e8d13d4a6a979e96c Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 13:00:26 +0200 Subject: [PATCH 03/19] Select cards with # --- app/controllers/prompts/cards_controller.rb | 15 +++++++++++++++ app/helpers/rich_text_helper.rb | 4 ++++ app/models/card/searchable.rb | 2 +- app/models/concerns/searchable.rb | 1 + app/views/cards/edit.html.erb | 1 + app/views/prompts/cards/_card.html.erb | 8 ++++++++ app/views/prompts/cards/index.html.erb | 1 + config/routes.rb | 1 + db/schema.rb | 1 + db/schema_cache.yml | 18 +++++++++++++++++- 10 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 app/controllers/prompts/cards_controller.rb create mode 100644 app/views/prompts/cards/_card.html.erb create mode 100644 app/views/prompts/cards/index.html.erb diff --git a/app/controllers/prompts/cards_controller.rb b/app/controllers/prompts/cards_controller.rb new file mode 100644 index 000000000..04737be76 --- /dev/null +++ b/app/controllers/prompts/cards_controller.rb @@ -0,0 +1,15 @@ +class Prompts::CardsController < ApplicationController + def index + @cards = if filter_param.present? + Current.user.accessible_cards.mentioning(filter_param) + else + Current.user.accessible_cards.latest.limit(10) + end + render layout: false + end + + private + def filter_param + params[:filter] + end +end diff --git a/app/helpers/rich_text_helper.rb b/app/helpers/rich_text_helper.rb index e3ac46c83..42c7cf5f1 100644 --- a/app/helpers/rich_text_helper.rb +++ b/app/helpers/rich_text_helper.rb @@ -2,4 +2,8 @@ module RichTextHelper def mentions_prompt content_tag "lexical-prompt", "", trigger: "@", src: prompts_users_path, name: "mention" end + + def cards_prompt + content_tag "lexical-prompt", "", trigger: "#", src: prompts_cards_path, name: "card", "insert-editable-text": true, "remote-filtering": true + end end diff --git a/app/models/card/searchable.rb b/app/models/card/searchable.rb index af2d3dbc9..97fb5b665 100644 --- a/app/models/card/searchable.rb +++ b/app/models/card/searchable.rb @@ -45,7 +45,7 @@ module Card::Searchable private # TODO: Temporary until we stabilize the search API def title_and_description - [ title, description.to_plain_text ].join(" ") + [ id.to_s, title, description.to_plain_text ].join(" ") end def search_embedding_content diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb index 5946212dd..9a6b03bc0 100644 --- a/app/models/concerns/searchable.rb +++ b/app/models/concerns/searchable.rb @@ -68,3 +68,4 @@ module Searchable search_embedding&.destroy end end + diff --git a/app/views/cards/edit.html.erb b/app/views/cards/edit.html.erb index 4a6043125..03b1ae325 100644 --- a/app/views/cards/edit.html.erb +++ b/app/views/cards/edit.html.erb @@ -12,6 +12,7 @@ placeholder: "Add some notes, context, pictures, or video about this…", data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do %> <%= mentions_prompt %> + <%= cards_prompt %> <% end %> <%= form.button "Save changes", type: :submit, class: "btn btn--reversed", style: "--btn-background: #{@card.color}" %> diff --git a/app/views/prompts/cards/_card.html.erb b/app/views/prompts/cards/_card.html.erb new file mode 100644 index 000000000..ebecb20a6 --- /dev/null +++ b/app/views/prompts/cards/_card.html.erb @@ -0,0 +1,8 @@ + + + + diff --git a/app/views/prompts/cards/index.html.erb b/app/views/prompts/cards/index.html.erb new file mode 100644 index 000000000..253e6e543 --- /dev/null +++ b/app/views/prompts/cards/index.html.erb @@ -0,0 +1 @@ +<%= render partial: "prompts/cards/card", collection: @cards %> diff --git a/config/routes.rb b/config/routes.rb index dc00a8766..8032e842d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -105,6 +105,7 @@ Rails.application.routes.draw do namespace :prompts do resources :users + resources :cards end namespace :public do diff --git a/db/schema.rb b/db/schema.rb index d27ab0295..dff0ccb02 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -324,6 +324,7 @@ ActiveRecord::Schema[8.1].define(version: 2025_06_09_102553) do t.datetime "created_at", null: false t.string "title" t.datetime "updated_at", null: false + t.index ["title"], name: "index_tags_on_account_id_and_title", unique: true end create_table "users", force: :cascade do |t| diff --git a/db/schema_cache.yml b/db/schema_cache.yml index 479604bf0..89fca8331 100644 --- a/db/schema_cache.yml +++ b/db/schema_cache.yml @@ -2200,7 +2200,23 @@ indexes: nulls_not_distinct: comment: valid: true - tags: [] + tags: + - !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition + table: tags + name: index_tags_on_account_id_and_title + unique: true + columns: + - title + lengths: {} + orders: {} + opclasses: {} + where: + type: + using: + include: + nulls_not_distinct: + comment: + valid: true users: - !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition table: users From 68dededbca09f4c8fc02bb8eb902e026f4dc703d Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 13:34:36 +0200 Subject: [PATCH 04/19] CSS tweak for clickable elements --- app/assets/stylesheets/actiontext-lexical.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index db03addc8..be0ab2fcd 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -159,6 +159,10 @@ lexical-toolbar { [aria-selected] { border: 1px solid red; } + + .lexical-prompt-menu__item { + cursor: pointer; + } } .attachment--custom.node--selected { From 2dbb53da1f145a999c6d2bcc6fa668e045481881 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 13:34:44 +0200 Subject: [PATCH 05/19] Add prompts to the rest of rich text editors --- app/models/user.rb | 4 ---- app/models/user/mentionable.rb | 9 +++++++++ app/views/cards/comments/_new.html.erb | 9 ++++++--- app/views/cards/comments/edit.html.erb | 7 +++++-- app/views/cards/container/_title.html.erb | 5 ++++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index c1dbc8c83..23b2f1cb2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,10 +25,6 @@ class User < ApplicationRecord update! active: false, email_address: deactived_email_address end - def to_attachable_partial_path - "users/attachable" - end - private def deactived_email_address email_address.sub(/@/, "-deactivated-#{SecureRandom.uuid}@") diff --git a/app/models/user/mentionable.rb b/app/models/user/mentionable.rb index 7a930ab02..be82f3d95 100644 --- a/app/models/user/mentionable.rb +++ b/app/models/user/mentionable.rb @@ -3,6 +3,11 @@ module User::Mentionable included do has_many :mentions, dependent: :destroy, inverse_of: :mentionee + + # Need to set in the included block so that it overrides Action Text's + def to_attachable_partial_path + "users/attachable" + end end def mentioned_by(mentioner, at:) @@ -13,6 +18,10 @@ module User::Mentionable [ initials, first_name, first_name_with_last_name_initial ].collect(&:downcase) end + def content_type + "application/vnd.actiontext.mention" + end + private def first_name_with_last_name_initial "#{first_name}#{last_name&.first}" diff --git a/app/views/cards/comments/_new.html.erb b/app/views/cards/comments/_new.html.erb index 68659dd38..8237fda1e 100644 --- a/app/views/cards/comments/_new.html.erb +++ b/app/views/cards/comments/_new.html.erb @@ -7,10 +7,13 @@
<%= form_with model: Comment.new, url: card_comments_path(card), class: "flex flex-column gap full-width", data: { controller: "form local-save", - local_save_key_value: "comment-#{card.id}", - action: "turbo:submit-end->local-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do |form| %> + local_save_key_value: "comment-#{card.id}", + action: "turbo:submit-end->local-save#submit 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, placeholder: new_comment_placeholder(card), - data: { local_save_target: "input", action: "actiontext:change->local-save#save turbo:morph-element->local-save#restoreContent" } %> + data: { local_save_target: "input", action: "actiontext:change->local-save#save turbo:morph-element->local-save#restoreContent" } do %> + <%= mentions_prompt %> + <%= cards_prompt %> + <% end %> <%= form.button class: "comment__submit btn btn--reversed flex-item-justify-start" do %> Post this comment <% end %> diff --git a/app/views/cards/comments/edit.html.erb b/app/views/cards/comments/edit.html.erb index 726693c47..ebf55a8b1 100644 --- a/app/views/cards/comments/edit.html.erb +++ b/app/views/cards/comments/edit.html.erb @@ -8,7 +8,10 @@
<%= 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) %> + <%= form.rich_textarea :body, required: true, autofocus: true, placeholder: new_comment_placeholder(@card) do %> + <%= mentions_prompt %> + <%= cards_prompt %> + <% end %>
<%= form.button class: "btn btn--reversed", type: :submit do %> Save changes @@ -18,7 +21,7 @@ <% end %> <%= tag.button type: :submit, class: "btn btn--negative flex-item-justify-end", form: dom_id(@comment, :delete_form), - data: { turbo_confirm: "Are you sure you want to delete this comment?" } do %> + data: { turbo_confirm: "Are you sure you want to delete this comment?" } do %> <%= icon_tag "trash" %> Delete <% end %> diff --git a/app/views/cards/container/_title.html.erb b/app/views/cards/container/_title.html.erb index 0a45685e9..e95064726 100644 --- a/app/views/cards/container/_title.html.erb +++ b/app/views/cards/container/_title.html.erb @@ -20,7 +20,10 @@
<%= form.rich_textarea :description, class: "card-field__description", placeholder: "Add some notes, context, pictures, or video about this…", - data: { action: "actiontext:change->auto-save#change focusout->auto-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } %> + data: { action: "actiontext:change->auto-save#change focusout->auto-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do %> + <%= mentions_prompt %> + <%= cards_prompt %> + <% end %>
<% end %> <% end %> From a6324f22f22623318c955c010adbe3d053f81fda Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 19 Jun 2025 14:32:34 +0200 Subject: [PATCH 06/19] Use remote version from branch --- Gemfile | 2 +- Gemfile.lock | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index 4935a7c87..a914cd42b 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "rqrcode" gem "redcarpet" gem "rouge" gem "jbuilder" -gem "actiontext-lexical", path: "/Users/jorge/Work/jorgemanrubia/actiontext-lexical" +gem "actiontext-lexical", bc: "actiontext-lexical", branch: "prompts" gem "image_processing", "~> 1.14" gem "platform_agent" gem "aws-sdk-s3", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 27b510c14..eeff67ab0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,11 @@ +GIT + remote: https://github.com/basecamp/actiontext-lexical + revision: 34d8d1bafede56feb5c8a01c939d0c7f6c181e8b + branch: prompts + specs: + actiontext-lexical (0.1.0) + rails (>= 8.0.2) + GIT remote: https://github.com/basecamp/active_record-tenanted revision: f6fca189655ae6609d10ecad7cceed61592320c4 @@ -147,12 +155,6 @@ GIT thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) -PATH - remote: /Users/jorge/Work/jorgemanrubia/actiontext-lexical - specs: - actiontext-lexical (0.1.0) - rails (>= 8.0.2) - GEM remote: https://rubygems.org/ specs: From e51b47ad40fa6516e401cbf6c1ffefb35b7d826d Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 19 Jun 2025 13:48:08 -0500 Subject: [PATCH 07/19] Style the prompt --- app/assets/stylesheets/actiontext-lexical.css | 288 ++++++++++-------- app/assets/stylesheets/rich-text-content.css | 8 +- 2 files changed, 161 insertions(+), 135 deletions(-) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index be0ab2fcd..ec2cfecb3 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -1,170 +1,192 @@ -lexical-editor { - display: block; - position: relative; - overflow: visible; +@layer components { + lexical-editor { + display: block; + position: relative; + overflow: visible; - .node--selected:not(.attachment--custom) { - &:not(:has(img)) { - box-shadow: 0 0 0 var(--hover-size) var(--hover-color); + .node--selected:not(.attachment--custom) { + &:not(:has(img)) { + box-shadow: 0 0 0 var(--hover-size) var(--hover-color); + } + + &:has(img) { + img { + box-shadow: 0 0 0 var(--hover-size) var(--hover-color); + } + } } - &:has(img) { - img { - box-shadow: 0 0 0 var(--hover-size) var(--hover-color); + &.lexical-editor--empty { + .lexical-editor__content::before { + content: attr(placeholder); + color: currentColor; + cursor: text; + opacity: 0.66; + pointer-events: none; + position: absolute; + white-space: pre-line; } } } - &.lexical-editor--empty { - .lexical-editor__content::before { - content: attr(placeholder); - color: currentColor; - cursor: text; - opacity: 0.66; - pointer-events: none; - position: absolute; - white-space: pre-line; + .lexical-dialog-actions { + display: flex; + font-size: var(--text-x-small); + flex: 1 1 0%; + gap: var(--inline-space-half); + margin-block-start: var(--block-space-half); + + .btn { + --radius: 0.3em; + + inline-size: 100%; + justify-content: center; + + &:is([type="submit"]) { + --btn-background: var(--card-color, var(--color-link)); + --btn-color: var(--color-ink-inverted); + --outline-color: var(--card-color, var(--color-link)); + } } - } -} -.lexical-dialog-actions { - display: flex; - font-size: var(--text-x-small); - flex: 1 1 0%; - gap: var(--inline-space-half); - margin-block-start: var(--block-space-half); - - .btn { - --radius: 0.3em; - - inline-size: 100%; - justify-content: center; - - &:is([type="submit"]) { - --btn-background: var(--card-color, var(--color-link)); - --btn-color: var(--color-ink-inverted); - --outline-color: var(--card-color, var(--color-link)); + span { + inline-size: 100%; } } - span { - inline-size: 100%; - } -} + .lexical-editor__content { + --outline-size: max(2px, 0.08em); -.lexical-editor__content { - --outline-size: max(2px, 0.08em); + margin: var(--block-space-half) 0; + min-block-size: calc(7lh + var(--block-space)); + outline: 0; + padding: var(--block-space-half) var(--inline-space); - margin: var(--block-space-half) 0; - min-block-size: calc(7lh + var(--block-space)); - outline: 0; - padding: var(--block-space-half) var(--inline-space); + * { + &:first-child { + margin-block-start: 0; + } - * { - &:first-child { - margin-block-start: 0; - } - - &:last-child { - margin-block-end: 0; - } - } -} - -.lexical-editor--drag-over { - background-color: var(--color-selected); - border-radius: 4px; - outline: 2px dashed var(--color-selected-dark); -} - -lexical-toolbar { - background-color: inherit; - border-block-end: 1px solid var(--color-ink-light); - color: currentColor; - display: flex; - font-size: inherit; - margin: 0; - max-inline-size: 100%; - padding: 0.2em 0; - position: relative; - - dialog { - background-color: var(--color-canvas); - border: 1px solid var(--color-ink-lighter); - border-radius: 0.5em; - box-shadow: var(--shadow); - color: var(--color-ink); - padding: var(--block-space) calc(var(--inline-space) * 1.5); - position: absolute; - z-index: 1; - - .input[type="url"] { - min-inline-size: 30ch; + &:last-child { + margin-block-end: 0; + } } } - > button { - aspect-ratio: 4/3.5; - appearance: none; - background-color: transparent; - block-size: 2em; - border: none; - border-radius: 0.2em; + .lexical-editor--drag-over { + background-color: var(--color-selected); + border-radius: 4px; + outline: 2px dashed var(--color-selected-dark); + } + + lexical-toolbar { + background-color: inherit; + border-block-end: 1px solid var(--color-ink-light); color: currentColor; - cursor: pointer; - display: grid; + display: flex; font-size: inherit; - inline-size: auto; - place-items: center; - transition: background-color 300ms ease; + margin: 0; + max-inline-size: 100%; + padding: 0.2em 0; + position: relative; - svg { - -webkit-touch-callout: none; - block-size: 0.85em; - fill: currentColor; - grid-area: 1/1; + dialog { + background-color: var(--color-canvas); + border: 1px solid var(--color-ink-lighter); + border-radius: 0.5em; + box-shadow: var(--shadow); + color: var(--color-ink); + padding: var(--block-space) calc(var(--inline-space) * 1.5); + position: absolute; + z-index: 1; + + .input[type="url"] { + min-inline-size: 30ch; + } + } + + > button { + aspect-ratio: 4/3.5; + appearance: none; + background-color: transparent; + block-size: 2em; + border: none; + border-radius: 0.2em; + color: currentColor; + cursor: pointer; + display: grid; + font-size: inherit; inline-size: auto; - user-select: none; - } + place-items: center; + transition: background-color 300ms ease; - &:is(:focus, :hover) { - background-color: var(--color-ink-lighter); - box-shadow: none; - } + svg { + -webkit-touch-callout: none; + block-size: 0.85em; + fill: currentColor; + grid-area: 1/1; + inline-size: auto; + user-select: none; + } - &:is(:active) { - background-color: var(--color-selected); + &:is(:focus, :hover) { + background-color: var(--color-ink-lighter); + box-shadow: none; + } + + &:is(:active) { + background-color: var(--color-selected); + } } } -} -/* Debug styles by Jorge */ -.lexical-prompt-menu { - background: white; - border: 2px solid black; - list-style: none; + /* Prompt + /* ------------------------------------------------------------------------ */ - margin: 0; - padding: 0; - min-height: 100px; - min-width: 300px; + .lexical-prompt-menu { + --lexical-prompt-avatar-size: 24px; + --lexical-prompt-min-height: 5lh; + --lexical-prompt-min-width: 20ch; + --lexical-prompt-padding: 0.5ch; - visibility: hidden; + background-color: var(--color-canvas); + border-radius: calc(var(--lexical-prompt-padding) * 2); + box-shadow: var(--shadow); + font-size: var(--text-small); + list-style: none; + margin: 0; + min-block-size: var(--lexical-prompt-min-height); + min-inline-size: var(--lexical-prompt-min-width); + padding: var(--lexical-prompt-padding); + visibility: hidden; + } - &.lexical-prompt-menu--visible { + .lexical-prompt-menu--visible { visibility: initial; } - [aria-selected] { - border: 1px solid red; - } - .lexical-prompt-menu__item { + align-items: center; + border-radius: 0.5ch; cursor: pointer; + display: flex; + gap: var(--lexical-prompt-padding); + padding: var(--lexical-prompt-padding); + + &[aria-selected] { + background-color: var(--color-ink-lighter); + } + + img { + block-size: var(--lexical-prompt-avatar-size); + border-radius: 50%; + flex-shrink: 0; + inline-size: var(--lexical-prompt-avatar-size); + margin: 0; + } + } + + .attachment--custom.node--selected { + box-shadow: 0 0 0 var(--hover-size) var(--hover-color); } } - -.attachment--custom.node--selected { - box-shadow: 0 0 0 var(--hover-size) var(--hover-color); -} diff --git a/app/assets/stylesheets/rich-text-content.css b/app/assets/stylesheets/rich-text-content.css index 1652b4cbb..89357b036 100644 --- a/app/assets/stylesheets/rich-text-content.css +++ b/app/assets/stylesheets/rich-text-content.css @@ -340,10 +340,14 @@ white-space: normal; } - .attachment--custom, .lexical-prompt-menu__item, action-text-attachment { + .attachment--custom, + action-text-attachment { + --attachment-image-size: 24px; + img { + block-size: var(--attachment-image-size); display: inline; - width: 24px; + inline-size: var(--attachment-image-size); } } } From 123b7de0892b9422dc6abee81912b372e450612e Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 19 Jun 2025 14:05:41 -0500 Subject: [PATCH 08/19] Style inserted mentions --- app/assets/stylesheets/actiontext-lexical.css | 2 -- app/assets/stylesheets/rich-text-content.css | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index ec2cfecb3..8ce554b6d 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -145,7 +145,6 @@ .lexical-prompt-menu { --lexical-prompt-avatar-size: 24px; - --lexical-prompt-min-height: 5lh; --lexical-prompt-min-width: 20ch; --lexical-prompt-padding: 0.5ch; @@ -155,7 +154,6 @@ font-size: var(--text-small); list-style: none; margin: 0; - min-block-size: var(--lexical-prompt-min-height); min-inline-size: var(--lexical-prompt-min-width); padding: var(--lexical-prompt-padding); visibility: hidden; diff --git a/app/assets/stylesheets/rich-text-content.css b/app/assets/stylesheets/rich-text-content.css index 89357b036..d96e76d11 100644 --- a/app/assets/stylesheets/rich-text-content.css +++ b/app/assets/stylesheets/rich-text-content.css @@ -342,11 +342,16 @@ .attachment--custom, action-text-attachment { - --attachment-image-size: 24px; + --attachment-image-size: 1em; + + align-items: center; + display: inline-flex; + gap: 0.25ch; + vertical-align: bottom; img { block-size: var(--attachment-image-size); - display: inline; + border-radius: 50%; inline-size: var(--attachment-image-size); } } From c9db74bb6fe883b5ec64521e10037d498d5fb76b Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 19 Jun 2025 14:22:37 -0500 Subject: [PATCH 09/19] Style the selected state --- app/assets/stylesheets/actiontext-lexical.css | 4 -- app/assets/stylesheets/rich-text-content.css | 54 ++++++++++++------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index 8ce554b6d..f68c1c833 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -183,8 +183,4 @@ margin: 0; } } - - .attachment--custom.node--selected { - box-shadow: 0 0 0 var(--hover-size) var(--hover-color); - } } diff --git a/app/assets/stylesheets/rich-text-content.css b/app/assets/stylesheets/rich-text-content.css index d96e76d11..897ab0127 100644 --- a/app/assets/stylesheets/rich-text-content.css +++ b/app/assets/stylesheets/rich-text-content.css @@ -329,30 +329,44 @@ } } } - } - /* Debug styles by Jorge */ - /* Custom attachments such as mentions, etc. */ - .attachment--custom { - display: inline; - padding: 0; - margin: 0; - white-space: normal; - } + /* Custom attachments such as mentions, etc. */ + .attachment--custom { + display: inline; + padding: 0; + margin: 0; + white-space: normal; + } - .attachment--custom, - action-text-attachment { - --attachment-image-size: 1em; + .attachment--custom, + action-text-attachment { + --attachment-image-size: 1em; + --attachment-selected-color: oklch(var(--lch-blue-dark)); - align-items: center; - display: inline-flex; - gap: 0.25ch; - vertical-align: bottom; + align-items: center; + display: inline-flex; + gap: 0.25ch; + position: relative; + vertical-align: bottom; - img { - block-size: var(--attachment-image-size); - border-radius: 50%; - inline-size: var(--attachment-image-size); + lexical-editor & { + cursor: pointer; + } + + img { + block-size: var(--attachment-image-size); + border-radius: 50%; + inline-size: var(--attachment-image-size); + } + + &.node--selected { + background: var(--attachment-selected-color); + box-shadow: + -0.25ch 0 0 var(--attachment-selected-color), + 0.5ch 0 0 var(--attachment-selected-color); + border-radius: 99rem; + color: var(--color-ink-inverted); + } } } } From b0f3404eb8ac59f0d543ee6833c2bfc70d4fb83c Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 19 Jun 2025 14:27:55 -0500 Subject: [PATCH 10/19] Add z-index to the menu --- app/assets/stylesheets/actiontext-lexical.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index f68c1c833..27e1286a2 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -157,6 +157,7 @@ min-inline-size: var(--lexical-prompt-min-width); padding: var(--lexical-prompt-padding); visibility: hidden; + z-index: var(--z-popup); } .lexical-prompt-menu--visible { From 87f70f93c4e90b3987c559ece2cbb3c200f875f3 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 19 Jun 2025 15:33:04 -0500 Subject: [PATCH 11/19] Differentiate hover and select states --- app/assets/stylesheets/actiontext-lexical.css | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/actiontext-lexical.css b/app/assets/stylesheets/actiontext-lexical.css index 27e1286a2..5e1ab771e 100644 --- a/app/assets/stylesheets/actiontext-lexical.css +++ b/app/assets/stylesheets/actiontext-lexical.css @@ -172,8 +172,16 @@ gap: var(--lexical-prompt-padding); padding: var(--lexical-prompt-padding); + &:hover { + background-color: var(--color-selected); + } + &[aria-selected] { - background-color: var(--color-ink-lighter); + box-shadow: 0 0 0 var(--hover-size) var(--color-selected-dark) inset; + + &:hover { + --hover-size: 0; + } } img { From 076a30a37f1b52b39ca9c66a9c649642d0589d31 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 06:46:11 +0200 Subject: [PATCH 12/19] More predictable approach to match cards by ID Always place them at the top. Our current search support in SQLite is based on standalone fields. We should add a field for IDs and make it work with prefixes. Going with something simpler for now. https://3.basecamp.com/2914079/buckets/37331921/todos/8773497815#__recording_8775856927 --- app/controllers/prompts/cards_controller.rb | 19 +++++++++++++++++-- app/models/card/searchable.rb | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/controllers/prompts/cards_controller.rb b/app/controllers/prompts/cards_controller.rb index 04737be76..a83a26353 100644 --- a/app/controllers/prompts/cards_controller.rb +++ b/app/controllers/prompts/cards_controller.rb @@ -1,10 +1,13 @@ class Prompts::CardsController < ApplicationController + MAX_RESULTS = 10 + def index @cards = if filter_param.present? - Current.user.accessible_cards.mentioning(filter_param) + prepending_exact_matches_by_id(published_cards.mentioning(params[:filter])) else - Current.user.accessible_cards.latest.limit(10) + @cards = published_cards.latest end + render layout: false end @@ -12,4 +15,16 @@ class Prompts::CardsController < ApplicationController def filter_param params[:filter] end + + def published_cards + Current.user.accessible_cards.published.limit(MAX_RESULTS) + end + + def prepending_exact_matches_by_id(cards) + if card_by_id = Current.user.accessible_cards.find_by_id(params[:filter]) + [ card_by_id ] + cards + else + cards + end + end end diff --git a/app/models/card/searchable.rb b/app/models/card/searchable.rb index 97fb5b665..af2d3dbc9 100644 --- a/app/models/card/searchable.rb +++ b/app/models/card/searchable.rb @@ -45,7 +45,7 @@ module Card::Searchable private # TODO: Temporary until we stabilize the search API def title_and_description - [ id.to_s, title, description.to_plain_text ].join(" ") + [ title, description.to_plain_text ].join(" ") end def search_embedding_content From ec77228b800b6d65cea60e7a4e5ab7dd95e051e8 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 09:42:28 +0200 Subject: [PATCH 13/19] Update lexical editor --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index eeff67ab0..eb8cd09c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/basecamp/actiontext-lexical - revision: 34d8d1bafede56feb5c8a01c939d0c7f6c181e8b + revision: e6a47a42272d9e9250b47f6ea90caef8e8807c55 branch: prompts specs: actiontext-lexical (0.1.0) From 5c987447430d53b0d83cf4aebcc31192ee10f20e Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 10:39:22 +0200 Subject: [PATCH 14/19] Support rich text mentions --- Gemfile.lock | 2 +- app/models/concerns/mentions.rb | 12 ++++++++++++ test/models/concerns/mentions_test.rb | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index eb8cd09c4..5c3b6877b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/basecamp/actiontext-lexical - revision: e6a47a42272d9e9250b47f6ea90caef8e8807c55 + revision: d372bcc8ecc5e725086a68992387b86f80210605 branch: prompts specs: actiontext-lexical (0.1.0) diff --git a/app/models/concerns/mentions.rb b/app/models/concerns/mentions.rb index 79ca110bd..86d017533 100644 --- a/app/models/concerns/mentions.rb +++ b/app/models/concerns/mentions.rb @@ -19,6 +19,10 @@ module Mentions private def scan_mentionees + mentionees_from_plain_text | mentionees_from_rich_text + end + + def mentionees_from_plain_text scan_mentioned_handles.filter_map do |mention| mentionable_users.find { |user| user.mentionable_handles.include?(mention) } end @@ -28,6 +32,14 @@ module Mentions mentionable_content.scan(/(? { Mention.count }, +1 do perform_enqueued_jobs only: Mention::CreateJob do collections(:writebook).cards.create title: "Cleanup", description: "Did you finish up with the cleanup, @david?" @@ -13,6 +13,27 @@ class MentionsTest < ActiveSupport::TestCase end end + test "create mentions from rich text mentions" do + assert_difference -> { Mention.count }, +1 do + perform_enqueued_jobs only: Mention::CreateJob do + attachment = ActionText::Attachment.from_attachable(users(:david)) + collections(:writebook).cards.create title: "Cleanup", description: "Did you finish up with the cleanup, #{attachment.to_html}?" + end + end + end + + test "can't mention users that don't have access to the collection" do + collections(:writebook).update! all_access: false + collections(:writebook).accesses.revoke_from(users(:david)) + + assert_no_difference -> { Mention.count }, +1 do + perform_enqueued_jobs only: Mention::CreateJob do + attachment = ActionText::Attachment.from_attachable(users(:david)) + collections(:writebook).cards.create title: "Cleanup", description: "Did you finish up with the cleanup, #{attachment.to_html}?" + end + end + end + test "mentionees are added as watchers of the card" do perform_enqueued_jobs only: Mention::CreateJob do card = collections(:writebook).cards.create title: "Cleanup", description: "Did you finish up with the cleanup @kevin?" From 9ddb18792ba5b71b89c31ec8a6ef50a6106992f7 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 10:44:42 +0200 Subject: [PATCH 15/19] Only offer users accessible in the collection --- app/controllers/prompts/collections/users_controller.rb | 8 ++++++++ app/controllers/prompts/users_controller.rb | 6 ------ app/helpers/rich_text_helper.rb | 4 ++-- app/views/cards/comments/_new.html.erb | 2 +- app/views/cards/comments/edit.html.erb | 2 +- app/views/cards/container/_title.html.erb | 2 +- app/views/cards/edit.html.erb | 2 +- app/views/prompts/{ => collections}/users/_user.html.erb | 0 app/views/prompts/collections/users/index.html.erb | 1 + app/views/prompts/users/index.html.erb | 1 - config/routes.rb | 6 +++++- 11 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 app/controllers/prompts/collections/users_controller.rb delete mode 100644 app/controllers/prompts/users_controller.rb rename app/views/prompts/{ => collections}/users/_user.html.erb (100%) create mode 100644 app/views/prompts/collections/users/index.html.erb delete mode 100644 app/views/prompts/users/index.html.erb diff --git a/app/controllers/prompts/collections/users_controller.rb b/app/controllers/prompts/collections/users_controller.rb new file mode 100644 index 000000000..22c74cd58 --- /dev/null +++ b/app/controllers/prompts/collections/users_controller.rb @@ -0,0 +1,8 @@ +class Prompts::Collections::UsersController < ApplicationController + include CollectionScoped + + def index + @users = @collection.users + render layout: false + end +end diff --git a/app/controllers/prompts/users_controller.rb b/app/controllers/prompts/users_controller.rb deleted file mode 100644 index 1aaf995c4..000000000 --- a/app/controllers/prompts/users_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Prompts::UsersController < ApplicationController - def index - @users = User.all - render layout: false - end -end diff --git a/app/helpers/rich_text_helper.rb b/app/helpers/rich_text_helper.rb index 42c7cf5f1..2e0b63a93 100644 --- a/app/helpers/rich_text_helper.rb +++ b/app/helpers/rich_text_helper.rb @@ -1,6 +1,6 @@ module RichTextHelper - def mentions_prompt - content_tag "lexical-prompt", "", trigger: "@", src: prompts_users_path, name: "mention" + def mentions_prompt(collection) + content_tag "lexical-prompt", "", trigger: "@", src: prompts_collection_users_path(collection), name: "mention" end def cards_prompt diff --git a/app/views/cards/comments/_new.html.erb b/app/views/cards/comments/_new.html.erb index 8237fda1e..07802b0f0 100644 --- a/app/views/cards/comments/_new.html.erb +++ b/app/views/cards/comments/_new.html.erb @@ -11,7 +11,7 @@ action: "turbo:submit-end->local-save#submit 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, placeholder: new_comment_placeholder(card), data: { local_save_target: "input", action: "actiontext:change->local-save#save turbo:morph-element->local-save#restoreContent" } do %> - <%= mentions_prompt %> + <%= mentions_prompt(@card.collection) %> <%= cards_prompt %> <% end %> <%= form.button class: "comment__submit btn btn--reversed flex-item-justify-start" do %> diff --git a/app/views/cards/comments/edit.html.erb b/app/views/cards/comments/edit.html.erb index ebf55a8b1..d236e1b79 100644 --- a/app/views/cards/comments/edit.html.erb +++ b/app/views/cards/comments/edit.html.erb @@ -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 %> - <%= mentions_prompt %> + <%= mentions_prompt(@card.collection) %> <%= cards_prompt %> <% end %>
diff --git a/app/views/cards/container/_title.html.erb b/app/views/cards/container/_title.html.erb index e95064726..fe66f6020 100644 --- a/app/views/cards/container/_title.html.erb +++ b/app/views/cards/container/_title.html.erb @@ -21,7 +21,7 @@ <%= form.rich_textarea :description, class: "card-field__description", placeholder: "Add some notes, context, pictures, or video about this…", data: { action: "actiontext:change->auto-save#change focusout->auto-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do %> - <%= mentions_prompt %> + <%= mentions_prompt(card.collection) %> <%= cards_prompt %> <% end %>
diff --git a/app/views/cards/edit.html.erb b/app/views/cards/edit.html.erb index 03b1ae325..e438dbbdb 100644 --- a/app/views/cards/edit.html.erb +++ b/app/views/cards/edit.html.erb @@ -11,7 +11,7 @@ <%= form.rich_textarea :description, class: "card-field__description rich-text-content", placeholder: "Add some notes, context, pictures, or video about this…", data: { action: "keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do %> - <%= mentions_prompt %> + <%= mentions_prompt(@card.collection) %> <%= cards_prompt %> <% end %>
diff --git a/app/views/prompts/users/_user.html.erb b/app/views/prompts/collections/users/_user.html.erb similarity index 100% rename from app/views/prompts/users/_user.html.erb rename to app/views/prompts/collections/users/_user.html.erb diff --git a/app/views/prompts/collections/users/index.html.erb b/app/views/prompts/collections/users/index.html.erb new file mode 100644 index 000000000..3ece68eab --- /dev/null +++ b/app/views/prompts/collections/users/index.html.erb @@ -0,0 +1 @@ +<%= render partial: "prompts/collections/users/user", collection: @users %> diff --git a/app/views/prompts/users/index.html.erb b/app/views/prompts/users/index.html.erb deleted file mode 100644 index 4d78c50f9..000000000 --- a/app/views/prompts/users/index.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render partial: "prompts/users/user", collection: @users %> diff --git a/config/routes.rb b/config/routes.rb index 8032e842d..db0cf3cd6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -104,8 +104,12 @@ Rails.application.routes.draw do end namespace :prompts do - resources :users resources :cards + resources :collections do + scope module: :collections do + resources :users + end + end end namespace :public do From ba225f5b4f713ce22020a066ddb245bc11c6aa43 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 10:46:21 +0200 Subject: [PATCH 16/19] Format --- app/models/concerns/searchable.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb index 9a6b03bc0..5946212dd 100644 --- a/app/models/concerns/searchable.rb +++ b/app/models/concerns/searchable.rb @@ -68,4 +68,3 @@ module Searchable search_embedding&.destroy end end - From c5304870c70292e0b0d05b0c92a2cb094513f2e7 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 11:19:28 +0200 Subject: [PATCH 17/19] Add http caching for prompts --- app/controllers/prompts/cards_controller.rb | 6 ++++-- app/controllers/prompts/collections/users_controller.rb | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/prompts/cards_controller.rb b/app/controllers/prompts/cards_controller.rb index a83a26353..3f0491314 100644 --- a/app/controllers/prompts/cards_controller.rb +++ b/app/controllers/prompts/cards_controller.rb @@ -8,7 +8,9 @@ class Prompts::CardsController < ApplicationController @cards = published_cards.latest end - render layout: false + if stale? etag: @cards + render layout: false + end end private @@ -22,7 +24,7 @@ class Prompts::CardsController < ApplicationController def prepending_exact_matches_by_id(cards) if card_by_id = Current.user.accessible_cards.find_by_id(params[:filter]) - [ card_by_id ] + cards + [card_by_id] + cards else cards end diff --git a/app/controllers/prompts/collections/users_controller.rb b/app/controllers/prompts/collections/users_controller.rb index 22c74cd58..1802f8fd1 100644 --- a/app/controllers/prompts/collections/users_controller.rb +++ b/app/controllers/prompts/collections/users_controller.rb @@ -3,6 +3,9 @@ class Prompts::Collections::UsersController < ApplicationController def index @users = @collection.users - render layout: false + + if stale? etag: @users + render layout: false + end end end From 7286d03f57dc0542f13748128542cae3375addb2 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 11:35:23 +0200 Subject: [PATCH 18/19] Format --- app/controllers/prompts/cards_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/prompts/cards_controller.rb b/app/controllers/prompts/cards_controller.rb index 3f0491314..e20ae39a2 100644 --- a/app/controllers/prompts/cards_controller.rb +++ b/app/controllers/prompts/cards_controller.rb @@ -24,7 +24,7 @@ class Prompts::CardsController < ApplicationController def prepending_exact_matches_by_id(cards) if card_by_id = Current.user.accessible_cards.find_by_id(params[:filter]) - [card_by_id] + cards + [ card_by_id ] + cards else cards end From 42ea57a8c892666fa3b4ddcbb8caa7649c3dedb2 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Fri, 20 Jun 2025 14:34:06 +0200 Subject: [PATCH 19/19] Point to last version merged in main branch --- Gemfile | 2 +- Gemfile.lock | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index a914cd42b..8c43ff533 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "rqrcode" gem "redcarpet" gem "rouge" gem "jbuilder" -gem "actiontext-lexical", bc: "actiontext-lexical", branch: "prompts" +gem "actiontext-lexical", bc: "actiontext-lexical" gem "image_processing", "~> 1.14" gem "platform_agent" gem "aws-sdk-s3", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 5c3b6877b..ce2e21e67 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,6 @@ GIT remote: https://github.com/basecamp/actiontext-lexical - revision: d372bcc8ecc5e725086a68992387b86f80210605 - branch: prompts + revision: ea4a511a27db4718fdd7db61d7235c3a374cb1ab specs: actiontext-lexical (0.1.0) rails (>= 8.0.2)