Skip to content

Commit

Permalink
Merge branch '7809-add-actiontext-to-notes' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
gbp committed Apr 9, 2024
2 parents 1d183d8 + ddaff31 commit 61b02a6
Show file tree
Hide file tree
Showing 28 changed files with 387 additions and 66 deletions.
1 change: 1 addition & 0 deletions app/assets/javascripts/admin.js
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
@@ -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();
});
35 changes: 35 additions & 0 deletions app/assets/stylesheets/actiontext.css
@@ -0,0 +1,35 @@
/*
* Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and
* the trix-editor content (whether displayed or under editing). Feel free to incorporate this
* inclusion directly in any other asset bundle and remove this file.
*
*= require trix
*/

/*
* We need to override trix.css’s image gallery styles to accommodate the
* <action-text-attachment> element we wrap around attachments. Otherwise,
* images in galleries will be squished by the max-width: 33%; rule.
*/
.trix-content .attachment-gallery > action-text-attachment,
.trix-content .attachment-gallery > .attachment {
flex: 1 0 33%;
padding: 0 0.5em;
max-width: 33%;
}

.trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment,
.trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment,
.trix-content .attachment-gallery.attachment-gallery--4 > .attachment {
flex-basis: 50%;
max-width: 50%;
}

.trix-content action-text-attachment .attachment {
padding: 0 !important;
max-width: 100% !important;
}

.trix-button-group--file-tools {
display: none !important;
}
2 changes: 2 additions & 0 deletions app/assets/stylesheets/admin.scss
@@ -1,3 +1,5 @@
//= require "actiontext"

/* As we're namespacing bootstrap to class admin, which is applied to the body
element in the admin interface (no id or class allowed on the HTML element
in HTML 4.01) and to the navbar also, so it can be styled with bootstrap
Expand Down
15 changes: 8 additions & 7 deletions app/assets/stylesheets/responsive/_notes_layout.scss
@@ -1,20 +1,21 @@
#notes {
// Variables to keep consistency speacilly with the spacing.
// Variables to keep consistency specially with the spacing.
$padding-x: 1em;
$border: 1px solid rgba(0, 0, 0, 0.1);
$border: 1px solid rgba(0, 0, 0, 0);
$border-top-size: 8px;

padding: 0 $padding-x;
padding: $border-top-size $padding-x 0;
margin-bottom: 2em;

border-top: 8px solid $primary-color;

article {
.note {
margin: 0 -#{$padding-x};
padding: $padding-x $padding-x;
border: $border;
border-top: none;
word-break: break-word;

&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 rgba(0, 0, 0, 0); }
border-top-width: 0;

h1, h2, h3, h4, h5, h6 {
margin-bottom: 0.5em;
margin-top: 0;
Expand Down
67 changes: 65 additions & 2 deletions app/assets/stylesheets/responsive/_notes_styles.scss
@@ -1,7 +1,61 @@
$note-text: $oil;
$note-bg: lighten($primary-color, 60%);
$note-border: $primary-color;

$note-red-text: darken($alert-color, 10%);
$note-red-bg: lighten($alert-color, 40%);
$note-red-border: $alert-color;

$note-green-text: darken($success-color, 10%);
$note-green-bg: lighten($success-color, 40%);
$note-green-border: $success-color;

$note-blue-text: darken($primary-color, 10%);
$note-blue-bg: lighten($primary-color, 60%);
$note-blue-border: $primary-color;

$note-yellow-text: darken($warning-color, 10%);
$note-yellow-bg: lighten($warning-color, 40%);
$note-yellow-border: $warning-color;

$border-top-size: 8px;

#notes {
background-color: lighten($primary-color, 60%);
.note {
color: $note-text;
background-color: $note-bg;
border-color: rgba(0, 0, 0, 0.1);

&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 $note-border; }

&.note--style-red {
color: $note-red-text;
background-color: $note-red-bg;
&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 $note-red-border; }
h1 { color: $note-red-text; }
}

&.note--style-green {
color: $note-green-text;
background-color: $note-green-bg;
&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 $note-green-border; }
h1 { color: $note-green-text; }
}

&.note--style-blue {
color: $note-blue-text;
background-color: $note-blue-bg;
&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 $note-blue-border; }
h1 { color: $note-blue-text; }
}

&.note--style-yellow {
color: $note-yellow-text;
background-color: $note-yellow-bg;
&:first-child { box-shadow: 0 -#{$border-top-size} 0 0 $note-yellow-border; }
h1 { color: $note-yellow-text; }
}

article {
h1 {
font-size: 1.5em;
}
Expand All @@ -21,5 +75,14 @@
font-size: 0.9em;
text-transform: uppercase;
}

&.note--style-red,
&.note--style-green,
&.note--style-blue,
&.note--style-yellow {
h1 {
font-size: 1.3em;
}
}
}
}
4 changes: 2 additions & 2 deletions app/controllers/admin/notes_controller.rb
Expand Up @@ -54,8 +54,8 @@ def scope
def note_params
translatable_params(
params.require(:note),
translated_keys: [:locale, :body],
general_keys: [:notable_tag, :notable_id, :notable_type]
translated_keys: [:locale, :body, :rich_body],
general_keys: [:notable_tag, :notable_id, :notable_type, :style]
)
end
end
13 changes: 9 additions & 4 deletions app/helpers/notes_helper.rb
@@ -1,15 +1,20 @@
module NotesHelper
def note_as_html(note, batch: false)
allowed_tags = batch ? batch_notes_allowed_tags : notes_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)
return unless notes.present?

allowed_tags = batch ? batch_notes_allowed_tags : notes_allowed_tags

tag.aside(**options.merge(id: 'notes')) do
notes.each do |note|
Note.sort(notes).each do |note|
note_classes = ['note']
note_classes << "note--style-#{note.style}"
note_classes << "tag-#{note.notable_tag}" if note.notable_tag

concat tag.article sanitize(note.body, tags: allowed_tags),
concat tag.article note_as_html(note, batch: batch),
id: dom_id(note),
class: note_classes
end
Expand Down
36 changes: 34 additions & 2 deletions app/models/note.rb
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20220720085105
# Schema version: 20240227080436
#
# Table name: notes
#
Expand All @@ -9,23 +9,55 @@
# notable_tag :string
# created_at :datetime not null
# updated_at :datetime not null
# style :string default("original"), not null
# body :text
#

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: {
'🔵 Blue': 'blue',
'🔴 Red': 'red',
'🟢 Green': 'green',
'🟡 Yellow': 'yellow',
'Original': 'original'
}

enum :style, Note.style_labels.values.index_by(&:itself),
default: Note.default_style,
suffix: true

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
4 changes: 2 additions & 2 deletions app/models/public_body.rb
Expand Up @@ -662,11 +662,11 @@ def self.extract_domain_from_email(email)
end

def notes
all_notes
Note.sort(all_notes)
end

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

def has_notes?
Expand Down
14 changes: 14 additions & 0 deletions app/views/active_storage/blobs/_blob.html.erb
@@ -0,0 +1,14 @@
<figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
<% if blob.representable? %>
<%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
<% end %>

<figcaption class="attachment__caption">
<% if caption = blob.try(:caption) %>
<%= caption %>
<% else %>
<span class="attachment__name"><%= blob.filename %></span>
<span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
<% end %>
</figcaption>
</figure>
7 changes: 7 additions & 0 deletions app/views/admin/notes/_form.html.erb
Expand Up @@ -11,6 +11,13 @@
<% end %>
</div>

<div class="control-group">
<%= f.label :style, class: 'control-label' %>
<div class="controls">
<%= f.select :style, Note.style_labels %>
</div>
</div>

<% f.translated_fields do |t| %>
<%= render partial: 'locale_fields', locals: { t: t } %>
<% end %>
11 changes: 9 additions & 2 deletions app/views/admin/notes/_locale_fields.html.erb
@@ -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
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.body, 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
4 changes: 3 additions & 1 deletion app/views/admin/notes/_show.html.erb
Expand Up @@ -4,6 +4,7 @@
<tr>
<th>ID</th>
<th>Notable ID</th>
<th>Style</th>
<th>Note Body</th>
<th>Notable type</th>
<th>Notable tag</th>
Expand All @@ -14,7 +15,8 @@
<tr class="<%= cycle('odd', 'even') %>">
<td class="id"><%= h note.id %></td>
<td class="notable_id"><%= h note.notable_id %></td>
<td class="body_snippet"><%= truncate(h(note.body), length: 50) %></td>
<td class="style"><%= note.style %></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
3 changes: 3 additions & 0 deletions app/views/layouts/action_text/contents/_content.html.erb
@@ -0,0 +1,3 @@
<div class="trix-content">
<%= yield -%>
</div>
3 changes: 3 additions & 0 deletions app/views/layouts/admin.html.erb
Expand Up @@ -11,6 +11,9 @@
<%= javascript_include_tag "admin" %>
<%= stylesheet_link_tag "admin", :title => "Main", :rel => "stylesheet" %>
<%= stylesheet_link_tag 'admin/print', :rel => "stylesheet", :media => "print" %>

<script type="text/javascript" src="https://unpkg.com/trix@2.0.8/dist/trix.umd.min.js"></script>

<%= render :partial => 'layouts/favicon' %>

</head>
Expand Down
3 changes: 2 additions & 1 deletion config/application.rb
Expand Up @@ -9,7 +9,7 @@
require "action_controller/railtie"
require "action_mailer/railtie"
# require "action_mailbox/engine"
# require "action_text/engine"
require "action_text/engine"
require "action_view/railtie"
# require "action_cable/engine"
require "sprockets/railtie"
Expand All @@ -34,6 +34,7 @@ class Application < Rails::Application
config.autoloader = :zeitwerk
config.active_record.legacy_connection_handling = false
config.active_support.use_rfc4122_namespaced_uuids = true
config.active_storage.replace_on_assign_to_many = true

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20240227080436_add_style_to_notes.rb
@@ -0,0 +1,5 @@
class AddStyleToNotes < ActiveRecord::Migration[7.0]
def change
add_column :notes, :style, :string, default: 'original', null: false
end
end

0 comments on commit 61b02a6

Please sign in to comment.