Skip to content

Commit cbad870

Browse files
NevelitoPaul-Bob
andauthored
feature: copyable field option (#3468)
* add new feature, copy field value * make display changes * fix bug in text_area field * run rubocop, and make small changes * Fix sugestion by Rubocop and include buttons text in test_helpers_spec * Request changes * Fix failing checks * Fix specs * fix failing check * Self code review * Fix copy firld content spec * Fix spec * Final fix spec * Self check changes and fix what user can copy * refactor * re-organize imports * revert dependencies downgrade * revert schema * rm unwanted styles * lint * fix test * adjust position * tippy * bundle --------- Co-authored-by: Paul Bob <[email protected]> Co-authored-by: Paul Bob <[email protected]>
1 parent e4aa5e5 commit cbad870

33 files changed

+157
-25
lines changed

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ gem "amazing_print"
114114
group :development, :test do
115115
gem "faker", require: false
116116
gem "i18n-tasks", "~> 1.0.12"
117+
gem "ruby-openai"
117118
gem "erb-formatter", require: false
118119
# https://thoughtbot.com/blog/a-standard-way-to-lint-your-views
119120
gem "erb_lint", require: false

Gemfile.lock

+17-6
Original file line numberDiff line numberDiff line change
@@ -267,19 +267,27 @@ GEM
267267
rubocop (>= 1)
268268
smart_properties
269269
erubi (1.13.0)
270+
event_stream_parser (1.0.0)
270271
factory_bot (6.5.0)
271272
activesupport (>= 5.0.0)
272273
factory_bot_rails (6.4.4)
273274
factory_bot (~> 6.5)
274275
railties (>= 5.0.0)
275276
faker (3.5.1)
276277
i18n (>= 1.8.11, < 2)
278+
faraday (2.12.2)
279+
faraday-net_http (>= 2.0, < 3.5)
280+
json
281+
logger
282+
faraday-multipart (1.1.0)
283+
multipart-post (~> 2.0)
284+
faraday-net_http (3.4.0)
285+
net-http (>= 0.5.0)
277286
ferrum (0.15)
278287
addressable (~> 2.5)
279288
concurrent-ruby (~> 1.1)
280289
webrick (~> 1.7)
281290
websocket-driver (~> 0.7)
282-
ffi (1.17.0)
283291
ffi (1.17.0-x86_64-linux-gnu)
284292
flay (2.13.3)
285293
erubi (~> 1.10)
@@ -379,7 +387,6 @@ GEM
379387
mini_histogram (0.3.1)
380388
mini_magick (4.13.2)
381389
mini_mime (1.1.5)
382-
mini_portile2 (2.8.8)
383390
minitest (5.25.4)
384391
monetize (1.13.0)
385392
money (~> 6.12)
@@ -391,6 +398,9 @@ GEM
391398
money (~> 6.13)
392399
railties (>= 3.0)
393400
msgpack (1.7.5)
401+
multipart-post (2.4.1)
402+
net-http (0.6.0)
403+
uri
394404
net-imap (0.5.2)
395405
date
396406
net-protocol
@@ -401,9 +411,6 @@ GEM
401411
net-smtp (0.5.0)
402412
net-protocol
403413
nio4r (2.7.4)
404-
nokogiri (1.17.2)
405-
mini_portile2 (~> 2.8.2)
406-
racc (~> 1.4)
407414
nokogiri (1.17.2-x86_64-linux)
408415
racc (~> 1.4)
409416
orm_adapter (0.5.0)
@@ -537,6 +544,10 @@ GEM
537544
rubocop-ast (>= 1.31.1, < 2.0)
538545
rubocop-shopify (2.15.1)
539546
rubocop (~> 1.51)
547+
ruby-openai (7.3.1)
548+
event_stream_parser (>= 0.3.0, < 2.0.0)
549+
faraday (>= 1)
550+
faraday-multipart (>= 1)
540551
ruby-progressbar (1.13.0)
541552
ruby-statistics (3.0.2)
542553
ruby-vips (2.2.2)
@@ -662,7 +673,6 @@ GEM
662673
zeitwerk (2.7.1)
663674

664675
PLATFORMS
665-
ruby
666676
x86_64-linux
667677

668678
DEPENDENCIES
@@ -730,6 +740,7 @@ DEPENDENCIES
730740
rspec-retry (~> 0.6.2)
731741
rubocop
732742
rubocop-shopify
743+
ruby-openai
733744
ruby-statistics (< 4)
734745
rubycritic
735746
simplecov
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<%= content_tag :div,
2+
class: "opacity-0 group-hover:opacity-100 transition-opacity duration-200",
3+
data: {
4+
controller: "clipboard",
5+
clipboard_success_duration_value: @duration_value,
6+
clipboard_success_content_value: @content_value
7+
} do %>
8+
<div class="hidden" data-clipboard-target="source"><%= @value %></div>
9+
<div class="text-xs xl:text-sm">
10+
<%= content_tag :button,
11+
type: "button",
12+
data: {
13+
action: "clipboard#copy",
14+
clipboard_target: "button",
15+
tippy: "tooltip",
16+
tippy_content: I18n.t("avo.copy")
17+
} do %>
18+
<%= helpers.svg "heroicons/outline/clipboard", class: "h-4 inline" %>
19+
<% end %>
20+
</div>
21+
<% end %>
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
3+
class Avo::ClipboardComponent < Avo::BaseComponent
4+
prop :value
5+
6+
def before_render
7+
@duration_value = 2500
8+
@content_value = helpers.svg("heroicons/outline/clipboard-document-check", class: "h-4 inline").tr('"', "'")
9+
end
10+
11+
def render?
12+
@value.present?
13+
end
14+
end

app/components/avo/field_wrapper_component.html.erb

+10-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,16 @@
2626
}), data: {slot: "value"} do %>
2727
<div class="self-center w-full break-words <% unless full_width? || compact? || stacked? %> md:w-8/12 has-sidebar:w-full <% end %>">
2828
<% if on_show? %>
29-
<% if render_dash? %>
30-
31-
<% else %>
32-
<%= content %>
33-
<% end %>
29+
<div class="flex flex-row items-center group gap-x-1">
30+
<% if render_dash? %>
31+
32+
<% else %>
33+
<%= content %>
34+
<% end %>
35+
<% if @field.copyable %>
36+
<%= render Avo::ClipboardComponent.new(value: @field.value) %>
37+
<% end %>
38+
</div>
3439
<% elsif on_edit? %>
3540
<%= content %>
3641
<% if record.present? and record.errors.include? @field.id %>

app/components/avo/index/field_wrapper_component.html.erb

+11-6
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@
99
<% if render_dash? %>
1010
1111
<% else %>
12-
<% if @center_content %>
13-
<div class="flex items-center justify-center">
12+
<div class="flex flex-row items-center gap-x-1 group">
13+
<% if @center_content %>
14+
<div class="flex items-center justify-center">
15+
<%= content %>
16+
</div>
17+
<% else %>
1418
<%= content %>
15-
</div>
16-
<% else %>
17-
<%= content %>
18-
<% end %>
19+
<% end %>
20+
<% if @field.copyable %>
21+
<%= render Avo::ClipboardComponent.new(value: @field.value) %>
22+
<% end %>
23+
</div>
1924
<% end %>
2025
<% if params[:avo_debug].present? %>
2126
<!-- Raw value: -->

app/javascript/js/application.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { Alert, Popover } from 'tailwindcss-stimulus-components'
22
import { Application } from '@hotwired/stimulus'
3-
import TextareaAutogrow from 'stimulus-textarea-autogrow'
3+
import Clipboard from '@stimulus-components/clipboard'
44
import PasswordVisibility from '@stimulus-components/password-visibility'
5+
import TextareaAutogrow from 'stimulus-textarea-autogrow'
56
import TurboPower from 'turbo_power'
67

78
TurboPower.initialize(window.Turbo.StreamActions)
89

910
const application = Application.start()
10-
application.register('textarea-autogrow', TextareaAutogrow)
11-
application.register('password-visibility', PasswordVisibility)
1211

1312
// Configure Stimulus development experience
1413
application.debug = window?.localStorage.getItem('avo.debug')
@@ -17,5 +16,8 @@ window.Stimulus = application
1716
// Register stimulus-components controller
1817
application.register('alert', Alert)
1918
application.register('popover', Popover)
19+
application.register('clipboard', Clipboard)
20+
application.register('password-visibility', PasswordVisibility)
21+
application.register('textarea-autogrow', TextareaAutogrow)
2022

2123
export { application }

lib/avo/fields/base_field.rb

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class BaseField
4848
attr_reader :computable # if allowed to be computable
4949
attr_reader :computed # if block is present
5050
attr_reader :computed_value # the value after computation
51+
attr_reader :copyable # if allowed to be copyable
5152

5253
# Hydrated payload
5354
attr_accessor :record
@@ -87,6 +88,7 @@ def initialize(id, **args, &block)
8788
@components = args[:components] || {}
8889
@for_attribute = args[:for_attribute]
8990
@meta = args[:meta]
91+
@copyable = args[:copyable] || false
9092

9193
@args = args
9294

lib/generators/avo/templates/locales/avo.ar.yml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ ar:
3030
click_to_reveal_filters: انقر لإظهار المرشحات
3131
close_modal: أغلق النافذة
3232
confirm: تأكيد
33+
copy: نسخ
3334
create_new_item: إنشاء %{item} جديد
3435
dashboard: لوحة القيادة
3536
dashboards: لوحات القيادة

lib/generators/avo/templates/locales/avo.de.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ de:
2424
click_to_reveal_filters: Klicken, um Filter anzuzeigen
2525
close_modal: Modal schließen
2626
confirm: Bestätigen
27+
copy: Kopieren
2728
create_new_item: Neues %{item} erstellen
2829
dashboard: Dashboard
2930
dashboards: Dashboards

lib/generators/avo/templates/locales/avo.en.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ en:
2424
click_to_reveal_filters: Click to reveal filters
2525
close_modal: Close modal
2626
confirm: Confirm
27+
copy: Copy
2728
create_new_item: Create new %{item}
2829
dashboard: Dashboard
2930
dashboards: Dashboards

lib/generators/avo/templates/locales/avo.es.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ es:
2626
click_to_reveal_filters: Pulsa para mostrar los filtros
2727
close_modal: Cerrar modal
2828
confirm: Confirmar
29+
copy: Copiar
2930
create_new_item: Crear nuevo/a %{item}
3031
dashboard: Panel
3132
dashboards: Paneles

lib/generators/avo/templates/locales/avo.fr.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ fr:
2626
click_to_reveal_filters: Cliquez pour révéler les filtres
2727
close_modal: Fermer la fenêtre modale
2828
confirm: Confirmer
29+
copy: Copier
2930
create_new_item: Créer un nouveau %{item}
3031
dashboard: Tableau de bord
3132
dashboards: Tableaux de bord

lib/generators/avo/templates/locales/avo.it.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ it:
2424
click_to_reveal_filters: Clicca per mostrare i filtri
2525
close_modal: Chiudi modale
2626
confirm: Conferma
27+
copy: Copia
2728
create_new_item: Crea nuovo %{item}
2829
dashboard: Cruscotto
2930
dashboards: Cruscotti

lib/generators/avo/templates/locales/avo.ja.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ja:
2626
click_to_reveal_filters: フィルターを表示するにはクリック
2727
close_modal: モーダルを閉じる
2828
confirm: 確認
29+
copy: コピー
2930
create_new_item: 新しい%{item}を作成
3031
dashboard: ダッシュボード
3132
dashboards: ダッシュボード

lib/generators/avo/templates/locales/avo.nb.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ nb:
2626
click_to_reveal_filters: Vis filter
2727
close_modal: Lukk modal
2828
confirm: Bekreft
29+
copy: Kopier
2930
create_new_item: Lag ny %{item}
3031
dashboard: Dashboard
3132
dashboards: Dashboards

lib/generators/avo/templates/locales/avo.nl.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ nl:
2424
click_to_reveal_filters: Klik om filters te tonen
2525
close_modal: Modaal sluiten
2626
confirm: Bevestigen
27+
copy: Kopie
2728
create_new_item: Nieuw %{item} aanmaken
2829
dashboard: Dashboard
2930
dashboards: Dashboards

lib/generators/avo/templates/locales/avo.nn.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ nn:
2626
click_to_reveal_filters: Vis filter
2727
close_modal: Lukk modal
2828
confirm: Stadfest
29+
copy: Kopier
2930
create_new_item: Lag ny %{item}
3031
dashboard: Dashboard
3132
dashboards: Dashboards

lib/generators/avo/templates/locales/avo.pl.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pl:
2424
click_to_reveal_filters: Kliknij, aby pokazać filtry
2525
close_modal: Zamknij okno modalne
2626
confirm: Potwierdź
27+
copy: Kopiuj
2728
create_new_item: Utwórz nowy %{item}
2829
dashboard: Pulpit nawigacyjny
2930
dashboards: Pulpity nawigacyjne

lib/generators/avo/templates/locales/avo.pt-BR.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pt-BR:
2626
click_to_reveal_filters: Clique para revelar os filtros
2727
close_modal: Fechar modal
2828
confirm: Confirmar
29+
copy: Copiar
2930
create_new_item: Criar novo %{item}
3031
dashboard: Painel
3132
dashboards: Painéis

lib/generators/avo/templates/locales/avo.pt.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pt:
2626
click_to_reveal_filters: Clique para mostrar os filtros
2727
close_modal: Fechar modal
2828
confirm: Confirmar
29+
copy: Copiar
2930
create_new_item: Criar novo %{item}
3031
dashboard: Painel
3132
dashboards: Painéis

lib/generators/avo/templates/locales/avo.ro.yml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ ro:
2727
click_to_reveal_filters: Faceți clic pentru a afișa filtrele
2828
close_modal: Închide modalul
2929
confirm: Confirm
30+
copy: Copiază
3031
create_new_item: Creează %{item}
3132
dashboard: Panou de control
3233
dashboards: Panouri de control

lib/generators/avo/templates/locales/avo.ru.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ru:
2424
click_to_reveal_filters: Нажмите, чтобы открыть фильтры
2525
close_modal: Закрыть модальное окно
2626
confirm: Подтвердить
27+
copy: Копировать
2728
create_new_item: Создать новый %{item}
2829
dashboard: Панель управления
2930
dashboards: Панели управления

lib/generators/avo/templates/locales/avo.tr.yml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ tr:
2626
click_to_reveal_filters: Filtreleri ortaya çıkarmak için tıklayın
2727
close_modal: Modali kapat
2828
confirm: Onayla
29+
copy: Kopya
2930
create_new_item: Yeni bir %{item} oluşturun
3031
dashboard: Yönetim Paneli
3132
dashboards: Yönetim Panelleri

lib/generators/avo/templates/locales/avo.uk.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ uk:
2424
click_to_reveal_filters: Натисніть, щоб показати фільтри
2525
close_modal: Закрити вікно
2626
confirm: Підтвердити
27+
copy: Копіювати
2728
create_new_item: Створити новий %{item}
2829
dashboard: Панель керування
2930
dashboards: Панелі керування

lib/generators/avo/templates/locales/avo.zh.yml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ zh:
2424
click_to_reveal_filters: 点击以显示筛选器
2525
close_modal: 关闭模态框
2626
confirm: 确认
27+
copy: 复制
2728
create_new_item: 创建新的 %{item}
2829
dashboard: 仪表盘
2930
dashboards: 仪表盘

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@hotwired/stimulus": "^3.2.2",
2626
"@hotwired/turbo-rails": "^8.0.12",
2727
"@rails/activestorage": "^6.1.710",
28+
"@stimulus-components/clipboard": "^5.0.0",
2829
"@stimulus-components/password-visibility": "^3.0.0",
2930
"@tailwindcss/forms": "^0.5.9",
3031
"@tailwindcss/typography": "^0.5.15",

spec/dummy/app/avo/resources/city.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def base_fields
7474
# This is because we want to be able to edit them using the tool.
7575
# When submitting the form, we need this fields declared on the resource in order to know how to process them and fill the record.
7676
def tool_fields
77-
field :name, as: :text, hide_on: [:index, :forms]
77+
field :name, as: :text, hide_on: [:index, :forms], copyable: true
7878
with_options hide_on: :forms do
7979
field :name, as: :text, filterable: true, name: "name (click to edit)", only_on: :index do
8080
path, data = Avo::Actions::City::Update.link_arguments(

spec/dummy/app/avo/resources/comment.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Avo::Resources::Comment < Avo::BaseResource
1212

1313
def fields
1414
field :id, as: :id
15-
field :body, as: :textarea
15+
field :body, as: :textarea, copyable: true
1616
field :tiny_name, as: :text, only_on: :index
1717
field :posted_at,
1818
as: :date_time,

0 commit comments

Comments
 (0)