Skip to content

Commit d94b0fe

Browse files
committed
feat: Support for raw html fields
1 parent 43241de commit d94b0fe

File tree

8 files changed

+91
-3
lines changed

8 files changed

+91
-3
lines changed

lib/tiny_admin/raw_html.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module TinyAdmin
4+
class RawHtml
5+
attr_reader :to_s
6+
7+
def initialize(value)
8+
@to_s = value.to_s
9+
end
10+
end
11+
end

lib/tiny_admin/support.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module TinyAdmin
44
class Support
55
class << self
6+
def raw_html(value)
7+
TinyAdmin::RawHtml.new(value)
8+
end
9+
610
def call(value, options: [])
711
options.inject(value) { |result, message| result&.send(message) } if value && options&.any?
812
end

lib/tiny_admin/views/components/field_value.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,25 @@ def view_template
1818
if field.options[:link_to]
1919
a(href: TinyAdmin.route_for(field.options[:link_to], reference: translated_value)) {
2020
span(class: value_class) {
21-
field.apply_call_option(record) || translated_value
21+
render_value(field.apply_call_option(record) || translated_value)
2222
}
2323
}
2424
else
2525
span(class: value_class) {
26-
translated_value
26+
render_value(translated_value)
2727
}
2828
end
2929
end
30+
31+
private
32+
33+
def render_value(val)
34+
if val.is_a?(TinyAdmin::RawHtml)
35+
unsafe_raw(val.to_s)
36+
else
37+
val
38+
end
39+
end
3040
end
3141
end
3242
end

spec/dummy_rails/app/models/author.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ class Author < ApplicationRecord
3131
def to_s
3232
"#{name} (#{age})"
3333
end
34+
35+
def stats
36+
[
37+
"Posts: <b>#{posts.count}</b>",
38+
"Published: <b>#{published_posts.count}</b>",
39+
"Recent: <b>#{recent_posts.count}</b>"
40+
]
41+
end
3442
end

spec/dummy_rails/app/models/post.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Post < ApplicationRecord
1717
validates :title, allow_blank: false, presence: true
1818

1919
scope :published, -> { where(published: true) }
20-
scope :recents, -> { where('created_at > ?', Date.current - 8.months) }
20+
scope :recents, -> { where('created_at > ?', Time.current - 1.week) }
2121

2222
# # override a field - can be dangerous
2323
# def title
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
class AdminHelper < TinyAdmin::Support
2+
class << self
3+
def multiline(array, options: [])
4+
raw_html array.join("<br/>")
5+
end
6+
end
27
end

spec/dummy_rails/config/tiny_admin.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ sections:
4242
- id
4343
- name
4444
- email
45+
- field: stats
46+
header: Some stats
47+
method: multiline
48+
links:
49+
- show
50+
- sample_mem
51+
show:
52+
attributes:
53+
- id
54+
- name
55+
- email
56+
- age
57+
- field: stats
58+
header: Some stats
59+
method: multiline
60+
- created_at
61+
- updated_at
4562
links:
4663
- show
4764
- sample_mem

spec/lib/tiny_admin/views/components/field_value_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,39 @@
3131
end
3232
end
3333

34+
describe "with a RawHtml value" do
35+
let(:field) { TinyAdmin::Field.new(name: "items", type: :string, title: "Items", options: { method: "multiline" }) }
36+
let(:record) { double("record", id: 1) } # rubocop:disable RSpec/VerifiedDoubles
37+
38+
before do
39+
allow(TinyAdmin.settings.helper_class).to receive(:multiline)
40+
.and_return(TinyAdmin::RawHtml.new("1<br/>2<br/>3"))
41+
end
42+
43+
it "renders the value as raw HTML without escaping", :aggregate_failures do
44+
html = described_class.new(field, [1, 2, 3], record: record).call
45+
expect(html).to include("<span>")
46+
expect(html).to include("1<br/>2<br/>3")
47+
expect(html).not_to include("&lt;br/&gt;")
48+
end
49+
end
50+
51+
describe "with a RawHtml value inside a link" do
52+
let(:field) { TinyAdmin::Field.new(name: "items", type: :string, title: "Items", options: { method: "multiline", link_to: "posts" }) }
53+
let(:record) { double("record", id: 1) } # rubocop:disable RSpec/VerifiedDoubles
54+
55+
before do
56+
allow(TinyAdmin.settings.helper_class).to receive(:multiline)
57+
.and_return(TinyAdmin::RawHtml.new("1<br/>2<br/>3"))
58+
end
59+
60+
it "renders the value as raw HTML inside a link without escaping", :aggregate_failures do
61+
html = described_class.new(field, [1, 2, 3], record: record).call
62+
expect(html).to include("<a")
63+
expect(html).to include("<span>1<br/>2<br/>3</span>")
64+
end
65+
end
66+
3467
describe "with value_class option" do
3568
let(:field) { TinyAdmin::Field.new(name: "status", type: :string, title: "Status", options: { options: ["value_class"] }) }
3669
let(:record) { double("record", id: 1) } # rubocop:disable RSpec/VerifiedDoubles

0 commit comments

Comments
 (0)