diff --git a/.gitignore b/.gitignore index a873e526f..753b67f2e 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ features/test_reports/*.png coverage/ -app/assets/builds/ +app/assets/builds/* !/app/assets/builds/.keep /node_modules diff --git a/Gemfile b/Gemfile index 9d12c0685..e3399a2a9 100644 --- a/Gemfile +++ b/Gemfile @@ -42,12 +42,12 @@ gem "redcarpet", "~> 3.6" gem "gretel", "~> 5.0" # Better UI components gem "lookbook", ">= 2.0.0.beta.4" -gem "view_component", "~> 3.10" +gem "view_component", "~> 3.11" # QR Code Generation! gem "rqrcode", "~> 2.2" # Pagination! -gem "pagy", "~> 6.4" +gem "pagy", "~> 7.0" # Database Layer # @@ -129,7 +129,7 @@ group :development, :test do gem "rubocop-rails" gem "rubocop-rspec" - gem "standard", "~> 1.33" + gem "standard", "~> 1.34" end group :development do @@ -137,7 +137,7 @@ group :development do gem "binding_of_caller" # Outputs i18n lookup key debug logs gem "i18n-debug" - gem "listen", "~> 3.8" + gem "listen", "~> 3.9" gem "rails-erd" # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem "web-console", "~> 4.2" diff --git a/Gemfile.lock b/Gemfile.lock index 349f4dc4d..3f9c58b0a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,11 +90,10 @@ GEM tzinfo (~> 2.0) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) - apimatic_core (0.3.4) + apimatic_core (0.3.5) apimatic_core_interfaces (~> 0.2.0) certifi (~> 2018.1, >= 2018.01.18) faraday-multipart (~> 1.0) - json-pointer nokogiri (~> 1.10, >= 1.10.10) apimatic_core_interfaces (0.2.0) apimatic_faraday_client_adapter (0.1.4) @@ -153,13 +152,13 @@ GEM coderay (1.1.3) concurrent-ruby (1.2.3) connection_pool (2.4.1) - crack (0.4.6) + crack (1.0.0) bigdecimal rexml crass (1.0.6) css_parser (1.16.0) addressable - cssbundling-rails (1.1.2) + cssbundling-rails (1.4.0) railties (>= 6.0.0) date (3.3.3) debug_inspector (1.1.0) @@ -230,12 +229,11 @@ GEM jsbundling-rails (1.3.0) railties (>= 6.0.0) json (2.7.1) - json-pointer (0.0.1) json-schema (4.1.1) addressable (>= 2.8) language_server-protocol (3.17.0.3) lint_roller (1.1.0) - listen (3.8.0) + listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) lockbox (1.3.3) @@ -276,7 +274,7 @@ GEM money (~> 6.13) railties (>= 3.0) msgpack (1.7.2) - multipart-post (2.3.0) + multipart-post (2.4.0) mutex_m (0.2.0) net-http (0.4.1) uri @@ -295,12 +293,12 @@ GEM nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) - pagy (6.4.3) + pagy (7.0.8) parallel (1.24.0) - parser (3.3.0.0) + parser (3.3.0.5) ast (~> 2.4.1) racc - pg (1.5.4) + pg (1.5.6) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) @@ -315,7 +313,7 @@ GEM pundit (2.3.1) activesupport (>= 3.0.0) racc (1.7.3) - rack (2.2.8) + rack (2.2.8.1) rack-session (1.0.2) rack (< 3) rack-test (2.1.0) @@ -371,7 +369,7 @@ GEM rdoc (6.6.2) psych (>= 4.0.0) redcarpet (3.6.0) - redis-client (0.19.1) + redis-client (0.20.0) connection_pool regexp_parser (2.9.0) reline (0.4.2) @@ -411,11 +409,11 @@ GEM rswag-ui (2.13.0) actionpack (>= 3.1, < 7.2) railties (>= 3.1, < 7.2) - rubocop (1.59.0) + rubocop (1.60.2) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.4) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) @@ -428,7 +426,7 @@ GEM rubocop (~> 1.41) rubocop-factory_bot (2.25.0) rubocop (~> 1.33) - rubocop-performance (1.20.1) + rubocop-performance (1.20.2) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.30.0, < 2.0) rubocop-rails (2.23.1) @@ -447,7 +445,7 @@ GEM ffi (~> 1.12) ruby2_keywords (0.0.5) rubyzip (2.3.2) - selenium-webdriver (4.17.0) + selenium-webdriver (4.18.1) base64 (~> 0.2) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -459,7 +457,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) shoulda-matchers (6.1.0) activesupport (>= 5.2.0) - sidekiq (7.2.1) + sidekiq (7.2.2) concurrent-ruby (< 2) connection_pool (>= 2.3.0) rack (>= 2.2.4) @@ -478,33 +476,33 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - square.rb (35.0.1.20240118) + square.rb (36.0.0.20240222) apimatic_core (~> 0.3.0) apimatic_core_interfaces (~> 0.2.0) apimatic_faraday_client_adapter (~> 0.1.0) - standard (1.33.0) + standard (1.34.0) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) - rubocop (~> 1.59.0) + rubocop (~> 1.60) standard-custom (~> 1.0.0) standard-performance (~> 1.3) standard-custom (1.0.2) lint_roller (~> 1.0) rubocop (~> 1.50) - standard-performance (1.3.0) + standard-performance (1.3.1) lint_roller (~> 1.1) - rubocop-performance (~> 1.20.1) + rubocop-performance (~> 1.20.2) stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.0) strip_attributes (1.13.0) activemodel (>= 3.0, < 8.0) - stripe (10.8.0) + stripe (10.11.0) strong_migrations (1.7.0) activerecord (>= 5.2) thor (1.3.0) timeout (0.4.1) - turbo-rails (2.0.2) + turbo-rails (2.0.4) actionpack (>= 6.0.0) activejob (>= 6.0.0) railties (>= 6.0.0) @@ -512,7 +510,7 @@ GEM concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) uri (0.13.0) - view_component (3.10.0) + view_component (3.11.0) activesupport (>= 5.2.0, < 8.0) concurrent-ruby (~> 1.0) method_source (~> 1.0) @@ -521,7 +519,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webmock (3.20.0) + webmock (3.23.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -532,7 +530,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - yard (0.9.34) + yard (0.9.36) zeitwerk (2.6.13) zlib (2.1.1) @@ -560,11 +558,11 @@ DEPENDENCIES image_processing jbuilder (~> 2.11) jsbundling-rails - listen (~> 3.8) + listen (~> 3.9) lockbox (= 1.3.3) lookbook (>= 2.0.0.beta.4) money-rails - pagy (~> 6.4) + pagy (~> 7.0) pg (~> 1.5) pry-byebug puma (~> 6.4) @@ -592,14 +590,14 @@ DEPENDENCIES spring-watcher-listen! sprockets-rails square.rb - standard (~> 1.33) + standard (~> 1.34) stimulus-rails strip_attributes (~> 1.13) stripe strong_migrations (~> 1.7) turbo-rails tzinfo-data (~> 1.2021) - view_component (~> 3.10) + view_component (~> 3.11) web-console (~> 4.2) webmock diff --git a/app/assets/builds/.keep b/app/assets/builds/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/stylesheets/actiontext.css b/app/assets/stylesheets/actiontext.css new file mode 100644 index 000000000..f325379b3 --- /dev/null +++ b/app/assets/stylesheets/actiontext.css @@ -0,0 +1,36 @@ +/* + * 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 + * 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; +} diff --git a/app/assets/stylesheets/application.postcss.css b/app/assets/stylesheets/application.postcss.css index 43128e8b4..5bb120d4d 100644 --- a/app/assets/stylesheets/application.postcss.css +++ b/app/assets/stylesheets/application.postcss.css @@ -1,4 +1,5 @@ /* Entry point for your PostCSS build */ +@import "trix"; @import "./tailwind.scss"; @@ -7,3 +8,5 @@ @import "./utilities.scss"; @import "./components.scss"; +@import "actiontext.css"; +@import "./extensions/pagy.scss"; diff --git a/app/assets/stylesheets/base/layout.scss b/app/assets/stylesheets/base/layout.scss index ab5b3b3f8..fd0b29baf 100644 --- a/app/assets/stylesheets/base/layout.scss +++ b/app/assets/stylesheets/base/layout.scss @@ -5,7 +5,7 @@ } main { - @apply mx-2 flex-1 flex flex-col; + @apply flex-1 flex flex-col; > :last-child { @apply mb-2; } diff --git a/app/assets/stylesheets/extensions/pagy.scss b/app/assets/stylesheets/extensions/pagy.scss new file mode 100644 index 000000000..f0e347199 --- /dev/null +++ b/app/assets/stylesheets/extensions/pagy.scss @@ -0,0 +1,8 @@ +.pagy-nav { + @apply flex justify-between; + + .page.active a, + .page.disabled a { + @apply no-underline; + } +} diff --git a/app/components/card_component.html.erb b/app/components/card_component.html.erb index dd83e6f4f..860ab3ed4 100644 --- a/app/components/card_component.html.erb +++ b/app/components/card_component.html.erb @@ -1,7 +1,14 @@ -
> - <% if header? %> - <%= header%> - <%- end %> +
> + <%- if head_image.present? %> +
+ <%= image_tag head_image, class: "rounded-t-lg w-full" %> +
+ <%= header %> +
+
+ <%- else %> + <%= header %> + <%- end %> <%# NOTE: content? is not always working as described, and is returning a proc in some cases rather than a boolean %> @@ -10,7 +17,6 @@ <%= content %>
<% end %> - <% if footer? %> <%= footer %> <% end %> diff --git a/app/components/card_component.rb b/app/components/card_component.rb index c305f9f8a..20ce1a2a2 100644 --- a/app/components/card_component.rb +++ b/app/components/card_component.rb @@ -1,5 +1,16 @@ class CardComponent < ApplicationComponent - HEADER_VARIANTS = {default: "p-2 sm:p-4", no_padding: ""} + attr_accessor :media + + def initialize(media: nil, **kwargs) + super(**kwargs) + + self.media = media + end + + HEADER_VARIANTS = { + default: "p-2 sm:p-4", + no_padding: "" + } renders_one :header, ->(variant: :default, &block) { content_tag(:header, class: HEADER_VARIANTS.fetch(variant), &block) } @@ -14,4 +25,8 @@ class CardComponent < ApplicationComponent classes += " rounded-t-none" unless content? || header? content_tag(:footer, class: classes, &block) } + + def head_image + media&.upload&.variant(resize_to_fill: Media::FULL_WIDTH_16_BY_9) + end end diff --git a/app/components/svg_component.rb b/app/components/svg_component.rb index 8c5dff9fc..08f68c7ea 100644 --- a/app/components/svg_component.rb +++ b/app/components/svg_component.rb @@ -1,27 +1,6 @@ class SvgComponent < ApplicationComponent - # Mapping of icon name symbols to methods returning the SVG path for that icon. - # - # We've been getting these SVG paths from https://heroicons.com/, using - # the "Outline" style. - # Feel free to add more as needed, from other libraries as appropriate, - # as long as they match the intended aesthetic and are appropriately licensed. - # - # Format: { symbol: method returning path for symbol } - ICON_MAPPINGS = { - cake: :cake, - cart: :cart, - money: :money, - exclamation_triangle: :exclamation_triangle, - gear: :gear, - map: :map, - receipt_percent: :receipt_percent, - bell: :ringing_bell, - tag: :tag, - plus: :plus, - trash: :trash, - pencil: :pencil - }.with_indifferent_access.freeze - + # We've been getting SVG paths from https://heroicons.com/, using the + # "Outline" style. Add more as needed. attr_reader :icon def initialize(icon: nil, **kwargs) @@ -35,7 +14,7 @@ def call def content if icon.present? - raw(send(ICON_MAPPINGS[icon])) # rubocop:disable Rails/OutputSafety + raw(send(icon)) # rubocop:disable Rails/OutputSafety else super end @@ -53,6 +32,12 @@ def options }) end + def building_storefront + <<~SVG + + SVG + end + def gear <<~SVG @@ -91,7 +76,7 @@ def cart SVG end - def ringing_bell + def bell_alert <<~SVG SVG @@ -123,10 +108,14 @@ def pencil def cake <<~SVG - - - + + SVG + end + def qr_code + <<~SVG + + SVG end end diff --git a/app/furniture/journal/journals/_journal.html.erb b/app/furniture/journal/journals/_journal.html.erb index 485fa7bde..2b37d4016 100644 --- a/app/furniture/journal/journals/_journal.html.erb +++ b/app/furniture/journal/journals/_journal.html.erb @@ -7,7 +7,7 @@ <%= render Journal::EntryComponent.with_collection(@entries) %>
- <%== pagy_nav(@pagy, nav_extra: 'flex justify-between') %> + <%== pagy_nav(@pagy) %> <%= render Journal::NewEntryButtonComponent.new(journal: journal) %> diff --git a/app/furniture/journal/keywords/show.html.erb b/app/furniture/journal/keywords/show.html.erb index cd431c7c6..0c2c481bc 100644 --- a/app/furniture/journal/keywords/show.html.erb +++ b/app/furniture/journal/keywords/show.html.erb @@ -1,9 +1,9 @@

<%= keyword.canonical_keyword %>

<%- if keyword.aliases.present? %> -

Also known as <%= to_sentence(keyword.aliases) %>

+

Also known as <%= to_sentence(keyword.aliases) %>

<%- end %> -

Entries about <%= keyword.canonical_keyword %>

+

Entries about <%= keyword.canonical_keyword %>

<%= render Journal::NewEntryButtonComponent.new(keyword: keyword) %>