Skip to content

Commit

Permalink
Add Note#rich_body
Browse files Browse the repository at this point in the history
Use ActionText Trix editor to allow rich text notes. We render the rich
text body when the note isn't in the original style.

This commit also hides the image attachment button in the Trix editor
as we will need to store the files correctly which won't work currently
with the current ActiveStorage setup.
  • Loading branch information
gbp committed Mar 6, 2024
1 parent 3ae4646 commit fbe219b
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 40 deletions.
1 change: 1 addition & 0 deletions app/assets/javascripts/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
//= require admin/category-order
//= require admin/censor-rules
//= require admin/holidays
//= require admin/notes
//= require jquery_ujs
19 changes: 19 additions & 0 deletions app/assets/javascripts/admin/notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
document.addEventListener('DOMContentLoaded', function () {
var selectElement = document.getElementById('note_style');
var bodyInput = document.getElementById('bodyInput');
var richBodyInput = document.getElementById('richBodyInput');

function updateBodyVisibility() {
if (selectElement.value === 'original') {
bodyInput.style.display = 'block';
richBodyInput.style.display = 'none';
} else {
bodyInput.style.display = 'none';
richBodyInput.style.display = 'block';
}
}

selectElement.addEventListener('change', updateBodyVisibility);

updateBodyVisibility();
});
4 changes: 4 additions & 0 deletions app/assets/stylesheets/actiontext.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@
padding: 0 !important;
max-width: 100% !important;
}

.trix-button-group--file-tools {
display: none !important;
}
2 changes: 1 addition & 1 deletion app/controllers/admin/notes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def scope
def note_params
translatable_params(
params.require(:note),
translated_keys: [:locale, :body],
translated_keys: [:locale, :body, :rich_body],
general_keys: [:notable_tag, :notable_id, :notable_type, :style]
)
end
Expand Down
7 changes: 2 additions & 5 deletions app/helpers/notes_helper.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
module NotesHelper
def note_as_text(note)
strip_tags(note.body)
end

def note_as_html(note, batch: false)
allowed_tags = batch ? batch_notes_allowed_tags : notes_allowed_tags
sanitize(note.body, tags: allowed_tags)
content = note.original_style? ? note.body : note.rich_body.to_trix_html
sanitize(content, tags: allowed_tags)
end

def render_notes(notes, batch: false, **options)
Expand Down
15 changes: 14 additions & 1 deletion app/models/note.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ class Note < ApplicationRecord
include AdminColumn

translates :body
translates :rich_body, touch: true
include Translatable
delegate :rich_body, :rich_body=, :rich_body?, to: :translation
after_save { rich_body.save if rich_body.changed? }

cattr_accessor :default_style, default: 'original'
cattr_accessor :style_labels, default: {
Expand All @@ -34,17 +37,27 @@ class Note < ApplicationRecord

belongs_to :notable, polymorphic: true

validates :body, presence: true
validates :body, presence: true, if: ->(n) { n.original_style? }
validates :rich_body, presence: true, unless: ->(n) { n.original_style? }
validates :style, presence: true
validates :notable_or_notable_tag, presence: true

def self.sort(notes)
notes.sort_by! { Note.style_labels.values.index(_1.style) }
end

def to_plain_text
b = original_style? ? ActionText::Fragment.wrap(body) : rich_body
b.to_plain_text
end

private

def notable_or_notable_tag
notable || notable_tag
end

class Translation # :nodoc:
has_rich_text :rich_body
end
end
2 changes: 1 addition & 1 deletion app/models/public_body.rb
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ def notes
end

def notes_as_string
notes.map(&:body).join(' ')
notes.map(&:to_plain_text).join(' ')
end

def has_notes?
Expand Down
11 changes: 9 additions & 2 deletions app/views/admin/notes/_locale_fields.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<div class="control-group">
<div id="bodyInput" class="control-group">
<%= t.label :body, class: 'control-label' %>
<div class="controls">
<%= t.text_area :body, class: 'span6', rows: 10 %>
<%= t.text_area :body, class: 'input-block-level', rows: 10 %>
</div>
</div>

<div id="richBodyInput" class="control-group">
<%= t.label :rich_body, 'Body', class: 'control-label' %>
<div class="controls">
<%= t.rich_text_area :rich_body %>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/admin/notes/_note.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="accordion-heading accordion-toggle row">
<span class="item-title span6">
<%= link_to chevron_right, "##{dom_id(note)}", data: { toggle: 'collapse', parent: 'notes' } %>
<%= link_to(note_as_text(note), edit_admin_note_path(note), title: 'view full details') %>
<%= link_to(note.to_plain_text, edit_admin_note_path(note), title: 'view full details') %>
</span>

<span class="item-metadata span6">
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/notes/_show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<td class="id"><%= h note.id %></td>
<td class="notable_id"><%= h note.notable_id %></td>
<td class="style"><%= note.style %></td>
<td class="body_snippet"><%= truncate(note_as_text(note), length: 50) %></td>
<td class="body_snippet"><%= truncate(note.to_plain_text, length: 50) %></td>
<td class="notable_type"><%= h note.notable_type %></td>
<td class="notable_tag"><%= h note.notable_tag %></td>
<td><%= link_to "Edit", edit_admin_note_path(note) %></td>
Expand Down
18 changes: 9 additions & 9 deletions spec/controllers/admin/notes_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
end

it 'creates the note' do
expect(assigns[:note].body).to eq('New body')
expect(assigns[:note].rich_body.to_plain_text).to eq('New body')
end

it 'sets a notice' do
Expand All @@ -64,7 +64,7 @@
{
id: note.id,
note: {
body: 'New body',
rich_body: 'New body',
notable_id: public_body.id,
notable_type: public_body.class.name,
style: 'blue'
Expand All @@ -86,7 +86,7 @@
let(:params) do
{
id: note.id,
note: { body: 'New body', notable_tag: tag, style: 'blue' }
note: { rich_body: 'New body', notable_tag: tag, style: 'blue' }
}
end

Expand All @@ -97,7 +97,7 @@

context 'on an unsuccessful create' do
let(:params) do
{ note: { body: '', style: '' } }
{ note: { rich_body: '', style: '' } }
end

it 'assigns the note' do
Expand Down Expand Up @@ -145,7 +145,7 @@
end

it 'updates the note' do
expect(note.reload.body).to eq('New body')
expect(note.reload.rich_body.to_plain_text).to eq('New body')
end

it 'sets a notice' do
Expand All @@ -163,7 +163,7 @@
{
id: note.id,
note: {
body: 'New body',
rich_body: 'New body',
notable_id: public_body.id,
notable_type: public_body.class.name,
style: 'blue'
Expand All @@ -185,7 +185,7 @@
let(:params) do
{
id: note.id,
note: { body: 'New body', notable_tag: tag, style: 'blue' }
note: { rich_body: 'New body', notable_tag: tag, style: 'blue' }
}
end

Expand All @@ -196,15 +196,15 @@

context 'on an unsuccessful update' do
let(:params) do
{ id: note.id, note: { body: '', style: '' } }
{ id: note.id, note: { rich_body: '', style: '' } }
end

it 'assigns the note' do
expect(assigns[:note]).to eq(note)
end

it 'does not update the note' do
expect(note.reload.body).not_to be_blank
expect(note.reload.rich_body).not_to be_blank
end

it 'renders the form again' do
Expand Down
7 changes: 6 additions & 1 deletion spec/factories/notes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

FactoryBot.define do
factory :note do
body { 'Test note' }
rich_body { 'Test note' }
association :notable, factory: :public_body
notable_tag { 'some_tag' }
style { 'blue' }
Expand All @@ -29,5 +29,10 @@
notable { nil }
notable_tag { 'foo' }
end

trait :original do
body { 'Test note' }
style { 'original' }
end
end
end
2 changes: 1 addition & 1 deletion spec/factories/public_bodies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
end

concrete_notes do
[association(:note, body: note_body)]
[association(:note, rich_body: note_body)]
end
end

Expand Down
17 changes: 8 additions & 9 deletions spec/helpers/notes_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
RSpec.describe NotesHelper do
include NotesHelper

describe '#note_as_text' do
subject { note_as_text(note) }

let(:note) { FactoryBot.build(:note, body: '<h1>title</h1>') }
describe '#note_as_html' do
let(:note) { FactoryBot.build(:note, rich_body: '<h1>title</h1>') }

it { is_expected.to eq('title') }
end
it { expect(note_as_html(note)).to eq('<h1>title</h1>') }

describe '#note_as_html' do
let(:note) { FactoryBot.build(:note, body: '<h1>title</h1>') }
context 'with original style note' do
let(:note) { FactoryBot.build(:note, :original, body: '<h1>title</h1>') }
it { expect(note_as_html(note)).to eq('<h1>title</h1>') }
end

context 'when not a batch' do
subject { note_as_html(note, batch: false) }
Expand All @@ -32,7 +31,7 @@
end

describe '#render_notes' do
let(:note) { FactoryBot.build(:note, body: '<h1>title</h1>') }
let(:note) { FactoryBot.build(:note, rich_body: '<h1>title</h1>') }

it 'wrap notes in aside and article tags' do
expect(self).to receive(:note_as_html).with(note, batch: false).
Expand Down
39 changes: 33 additions & 6 deletions spec/models/note_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,17 @@
describe 'validations' do
specify { expect(note).to be_valid }

it 'requires body' do
note.body = nil
context 'original style' do
let(:note) { FactoryBot.build(:note, :original) }

it 'requires body' do
note.body = nil
expect(note).not_to be_valid
end
end

it 'requires rich body' do
note.rich_body = nil
expect(note).not_to be_valid
end

Expand Down Expand Up @@ -54,10 +63,14 @@
describe 'translations' do
before { note.save! }

it 'adds translated body' do
expect(note.body_translations).to_not include(es: 'body')
AlaveteliLocalization.with_locale(:es) { note.body = 'body' }
expect(note.body_translations).to include(es: 'body')
def plain_body
note.rich_body_translations.transform_values(&:to_plain_text)
end

it 'adds translated rich_body' do
expect(plain_body).to_not include(es: 'content')
AlaveteliLocalization.with_locale(:es) { note.rich_body = 'content' }
expect(plain_body).to include(es: 'content')
end
end

Expand Down Expand Up @@ -87,4 +100,18 @@
is_expected.to match_array([original, blue_1, blue_2, red, green, yellow])
end
end

describe '#to_plain_text' do
subject { note.to_plain_text }

context 'with original style note' do
let(:note) { FactoryBot.build(:note, :original, body: '<h1>title</h1>') }
it { is_expected.to eq('title') }
end

context 'with styled note' do
let(:note) { FactoryBot.build(:note, rich_body: '<h1>title</h1>') }
it { is_expected.to eq('title') }
end
end
end
5 changes: 3 additions & 2 deletions spec/models/public_body_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -597,11 +597,12 @@

let!(:concrete_note) do
FactoryBot.create(:note, :for_public_body,
body: 'bar', notable: public_body)
rich_body: 'bar', notable: public_body)
end

let!(:tagged_note) do
FactoryBot.create(:note, :tagged, body: 'baz', notable_tag: 'important')
FactoryBot.create(:note, :tagged,
rich_body: 'baz', notable_tag: 'important')
end

it 'concaterates note bodies' do
Expand Down

0 comments on commit fbe219b

Please sign in to comment.