Skip to content

Commit

Permalink
Merge pull request #2690 from projectblacklight/7.x-base-component
Browse files Browse the repository at this point in the history
Extract a base component for blacklight
  • Loading branch information
barmintor committed Apr 26, 2022
2 parents 982e3e5 + 8f043d8 commit 6955a36
Show file tree
Hide file tree
Showing 33 changed files with 114 additions and 30 deletions.
2 changes: 1 addition & 1 deletion app/components/blacklight/constraint_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class ConstraintComponent < ::ViewComponent::Base
class ConstraintComponent < Blacklight::Component
with_collection_parameter :facet_item_presenter

def initialize(facet_item_presenter:, classes: 'filter', layout: Blacklight::ConstraintLayoutComponent)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/constraint_layout_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class ConstraintLayoutComponent < ::ViewComponent::Base
class ConstraintLayoutComponent < Blacklight::Component
def initialize(value:, label: nil, remove_path: nil, classes: nil, search_state: nil)
@value = value
@label = label
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/constraints_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class ConstraintsComponent < ::ViewComponent::Base
class ConstraintsComponent < Blacklight::Component
include Blacklight::ContentAreasShim

renders_many :query_constraints_area
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/action_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render a bookmark widget to bookmark / unbookmark a document
class ActionComponent < ::ViewComponent::Base
class ActionComponent < Blacklight::Component
with_collection_parameter :action

# @param [Blacklight::Document] document
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/actions_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render a bookmark widget to bookmark / unbookmark a document
class ActionsComponent < ::ViewComponent::Base
class ActionsComponent < Blacklight::Component
renders_many :actions, (lambda do |action:, component: nil, **kwargs|
component ||= action.component || Blacklight::Document::ActionComponent
component.new(action: action, document: @document, options: @options, url_opts: @url_opts, link_classes: @link_classes, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/bookmark_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render a bookmark widget to bookmark / unbookmark a document
class BookmarkComponent < ::ViewComponent::Base
class BookmarkComponent < Blacklight::Component
# @param [Blacklight::Document] document
# @param [Boolean] checked
# @param [Object] bookmark_path the rails route to use for bookmarks
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/citation_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render citations for the document
class CitationComponent < ::ViewComponent::Base
class CitationComponent < Blacklight::Component
DEFAULT_FORMATS = {
'blacklight.citation.mla': :export_as_mla_citation_txt,
'blacklight.citation.apa': :export_as_apa_citation_txt,
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/group_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render the 'more like this' results from the response
class GroupComponent < ::ViewComponent::Base
class GroupComponent < Blacklight::Component
with_collection_parameter :group

# @param [Blacklight::Solr::Response::Group] group
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render the 'more like this' results from the response
class MoreLikeThisComponent < ::ViewComponent::Base
class MoreLikeThisComponent < Blacklight::Component
with_collection_parameter :document

# @param [Blacklight::Document] document
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document/thumbnail_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Document
# Render the thumbnail for the document
class ThumbnailComponent < ::ViewComponent::Base
class ThumbnailComponent < Blacklight::Component
with_collection_parameter :presenter

# @param [Blacklight::DocumentPresenter] presenter
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class DocumentComponent < ::ViewComponent::Base
class DocumentComponent < Blacklight::Component
include Blacklight::ContentAreasShim

# Content appearing before the document
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document_metadata_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class DocumentMetadataComponent < ::ViewComponent::Base
class DocumentMetadataComponent < Blacklight::Component
renders_many :fields, (lambda do |component: nil, **kwargs|
(component || Blacklight::MetadataFieldComponent).new(**kwargs)
end)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/document_title_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class DocumentTitleComponent < ::ViewComponent::Base
class DocumentTitleComponent < Blacklight::Component
renders_many :before_title
renders_many :after_title
renders_many :actions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldCheckboxesComponent < ::ViewComponent::Base
class FacetFieldCheckboxesComponent < Blacklight::Component
def initialize(facet_field:, layout: nil)
@facet_field = facet_field
@layout = layout == false ? FacetFieldNoLayoutComponent : Blacklight::FacetFieldComponent
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/facet_field_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldComponent < ::ViewComponent::Base
class FacetFieldComponent < Blacklight::Component
include Blacklight::ContentAreasShim

renders_one :label
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/facet_field_filter_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldFilterComponent < ::ViewComponent::Base
class FacetFieldFilterComponent < Blacklight::Component
def initialize(facet_field:)
@facet_field = facet_field
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldInclusiveConstraintComponent < ::ViewComponent::Base
class FacetFieldInclusiveConstraintComponent < Blacklight::Component
with_collection_parameter :facet_field

def initialize(facet_field:, values: nil)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/facet_field_list_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldListComponent < ::ViewComponent::Base
class FacetFieldListComponent < Blacklight::Component
def initialize(facet_field:, layout: nil)
@facet_field = facet_field
@layout = layout == false ? FacetFieldNoLayoutComponent : Blacklight::FacetFieldComponent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldNoLayoutComponent < ::ViewComponent::Base
class FacetFieldNoLayoutComponent < Blacklight::Component
include Blacklight::ContentAreasShim

renders_one :label
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetFieldPaginationComponent < ::ViewComponent::Base
class FacetFieldPaginationComponent < Blacklight::Component
def initialize(facet_field:)
@facet_field = facet_field
end
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/facet_item_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class FacetItemComponent < ::ViewComponent::Base
class FacetItemComponent < Blacklight::Component
extend Deprecation

with_collection_parameter :facet_item
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/facet_item_pivot_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Blacklight
# Render facet items and any subtree
class FacetItemPivotComponent < ::ViewComponent::Base
class FacetItemPivotComponent < Blacklight::Component
# Somewhat arbitrary number; the only important thing is that
# it is bigger than the number of leaf nodes in any collapsing
# pivot facet on the page.
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/hidden_search_state_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Blacklight
# Writes out zero or more <input type="hidden"> elements, completely
# representing a hash passed in using Rails-style request parameters
# for hashes nested with arrays and other hashes.
class HiddenSearchStateComponent < ::ViewComponent::Base
class HiddenSearchStateComponent < Blacklight::Component
# @param [Hash] params
def initialize(params:)
Deprecation.warn(self, "Passing page as a parameter to HiddenSearchStateComponent is deprecated and will not be supported in Blacklight 8") if params.key?(:page)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/metadata_field_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class MetadataFieldComponent < ::ViewComponent::Base
class MetadataFieldComponent < Blacklight::Component
with_collection_parameter :field

# @param field [Blacklight::FieldPresenter]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class MetadataFieldLayoutComponent < ::ViewComponent::Base
class MetadataFieldLayoutComponent < Blacklight::Component
include Blacklight::ContentAreasShim

with_collection_parameter :field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Response
# Render a group of facet fields
class FacetGroupComponent < ::ViewComponent::Base
class FacetGroupComponent < Blacklight::Component
# @param [Blacklight::Response] response
# @param [Array<String>] fields facet fields to render
# @param [String] title the title of the facet group section
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/response/pagination_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Blacklight
module Response
# Render a pagination widget for search results
class PaginationComponent < ::ViewComponent::Base
class PaginationComponent < Blacklight::Component
# @param [Blacklight::Response] response
# @param [Hash] html html options for the pagination container
def initialize(response:, html: {}, **pagination_args)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/search_bar_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class SearchBarComponent < ::ViewComponent::Base
class SearchBarComponent < Blacklight::Component
include Blacklight::ContentAreasShim

renders_one :append
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/search_context_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class SearchContextComponent < ::ViewComponent::Base
class SearchContextComponent < Blacklight::Component
with_collection_parameter :search_context

def initialize(search_context:, search_session:)
Expand Down
2 changes: 1 addition & 1 deletion app/components/blacklight/start_over_button_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Blacklight
class StartOverButtonComponent < ::ViewComponent::Base
class StartOverButtonComponent < Blacklight::Component
def call
link_to t('blacklight.search.start_over'), start_over_path, class: 'catalog_startOverLink btn btn-primary'
end
Expand Down
1 change: 1 addition & 0 deletions lib/blacklight.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

module Blacklight
autoload :AbstractRepository, 'blacklight/abstract_repository'
autoload :Component, 'blacklight/component'
autoload :Configuration, 'blacklight/configuration'
autoload :Exceptions, 'blacklight/exceptions'
autoload :Parameters, 'blacklight/parameters'
Expand Down
40 changes: 40 additions & 0 deletions lib/blacklight/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Blacklight
class Component < ViewComponent::Base
class << self
# rubocop:disable Naming/MemoizedInstanceVariableName
def compiler
@__vc_compiler ||= EngineCompiler.new(self)
end
# rubocop:enable Naming/MemoizedInstanceVariableName
end

class EngineCompiler < ::ViewComponent::Compiler
# ViewComponent::Compiler locates and caches templates from sidecar files to the component source file.
# While this is sensible in a Rails application, it prevents component templates defined in an Engine
# from being overridden by an installing application without subclassing the component, which may also
# require modifying any partials rendering the component. This subclass of compiler overrides the template
# location algorithm to take the sidecar file names from the Engine, but look to see if a file of the
# same name existing in the installing application (ie, under Rails.root). If the latter exists, this
# compiler will cache that template instead of the engine-defined file; if not, the compiler will fall
# back to the engine-defined file.
def templates
@templates ||= begin
extensions = ActionView::Template.template_handler_extensions

component_class._sidecar_files(extensions).each_with_object([]) do |path, memo|
pieces = File.basename(path).split(".")
app_path = "#{Rails.root}/#{path.slice(path.index(component_class.view_component_path)..-1)}"

memo << {
path: File.exist?(app_path) ? app_path : path,
variant: pieces.second.split("+").second&.to_sym,
handler: pieces.last
}
end
end
end
end
end
end
43 changes: 43 additions & 0 deletions spec/lib/blacklight/component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

RSpec.describe Blacklight::Component do
let(:component_class) { Blacklight::DocumentTitleComponent }

context "subclassed" do
it "returns our Compiler implementation" do
expect(component_class.ancestors).to include described_class
expect(component_class.compiler).to be_a Blacklight::Component::EngineCompiler
end
end

describe Blacklight::Component::EngineCompiler do
subject(:compiler) { described_class.new(component_class) }

let(:original_compiler) { ViewComponent::Compiler.new(component_class) }
let(:original_path) { original_compiler.send(:templates).first[:path] }
let(:resolved_path) { compiler.templates.first[:path] }

context "without overrides" do
it "links to engine template" do
expect(resolved_path).not_to include(".internal_test_app")
expect(resolved_path).to eql(original_path)
end
end

context "with overrides" do
let(:path_match) do
Regexp.new(Regexp.escape(File.join(".internal_test_app", component_class.view_component_path)))
end

before do
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with(path_match).and_return(true)
end

it "links to application template" do
expect(resolved_path).to include(".internal_test_app")
expect(resolved_path).not_to eql(original_path)
end
end
end
end

0 comments on commit 6955a36

Please sign in to comment.