Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

How do plugins add search and query constraints or change the way they're rendered? #2977

Closed
hackartisan opened this issue Feb 2, 2023 · 1 comment

Comments

@hackartisan
Copy link
Contributor

This issue serves as a record of discussion that took place on https://github.com/projectblacklight/blacklight/wiki/Upgrading-to-Blacklight-8. In order to clean up that page and present a succinct summary of the current upgrade recommendations, much of the discussion and comment was lost. It is pasted below.


Scenarios

Adding elements to "constraints"

  • "constraints" is what Blacklight calls the area above search results that tells you all the queries/limits/filters at play in your search, and lets you remove them individually. Sometimes called a kind of "breadcrumbs".
  • Plugins often want to add elements to this "constraints" area.
    • They have traditionally done this by over-riding helper methods either render_constraints or render_constraints_filters to call super and concatenate their own additional content.
    • Multiple different plugins can and have done this simultaneously without stepping on each others toes, each adding something to super.
    • This will no longer work in Blacklight 8, those methods are not available for over-riding.
    • Additionally, when a plugin wants to supply it's own "constraint", it has often traditionaly called the render_constraint_element helper method, to say "render this constraint in whatever the application style is, even if it's been customized". That method is also no longer available.
  • Examples:
  • Upgrade Path:
    • In BL 8 all the constraints are rendered by app/view/catalog/_constraints.html.erb That renders the following components:
      • Blacklight::ConstraintsComponent this used to be render_constraints
      • Blacklight::ConstraintLayoutComponent this used to be render_constraints_element
      • We could override the view partial to render a new subclass of Blacklight::ConstraintsComponent
        • Q: How? I think it requires overriding a chain "up to the top" at present
    • Another possibility is to move the ConstraintsComponent class to a configuration variable and have the partial use that variable.
      • I am intrigued by this. But there's still a challenge when multiple different plug-ins all want to add elements to constraints -- which is our actually existing use-case. How do they avoid fighting for control over this component, stepping on each other's toes? blacklight_range_limit, geoblacklight, and blacklight_maps all want to add an element to constraints.

Change the way the "query" constraint is rendered

  • Unlike "adding element to constraints" above, only one thing at a time can do this, there's only one "query" constraint. But plugins have
    sometimes done this, and so have local apps.
  • By over-riding the render_constraints_query helper method -- this is no longer available.
  • Examples:
  • Upgrade Path:
    • In BL 8 the constraints query is rendered by the query_constraint_component argument (default Blacklight::ConstraintLayoutComponent), which is passed into the Blacklight::Constrains component:
      query_constraint_component: Blacklight::ConstraintLayoutComponent, facet_constraint_component: Blacklight::ConstraintComponent)
      ; To customize, provide a different component.
      • Q: The challenge for me is "how". I think it may require over-riding a chain of parent components which we aren't actually interested in customizing, to get to the point where a different component can be provided here.

Render Constraints in a new page in plugin or app

  • A plugin or app may want to render search constraints on it's own new page.
  • Previously, it could call the helper method render_constraints to render the constraints including any customizations added by plugins or local app, as above.
  • This is no longer available as a method.
  • Examples:
  • Upgrade Path:
    • In BL 8. Render Blacklight::ConstraintsComponent.
      • Q: The challenge for me is how this interacts with above scenarios -- right now, a plugin wants to render search constraints 'however it may have been customized by the app and it's plugins', and can do so by calling the helper method (which may have been customized with overrides). But in the new scenario, if a plugin renders Blacklight::ConstraintsComponent -- this does not get customizations made by above suggestions to "provide a different component" for Blacklight::ConstraintsComponent

Proposal for above scenarios

After trying to wrap my head around the scenarios for a while, and let it role around in there... what if we provide some additional configuration variables, specifically targeted at these constraints-customizing use-cases? [I think this essentially a means of what they call "dependency inversion", via the blacklight configuration object].

There is a little step into the precedent of providing component classes in Blacklight configuration already exists in the BL 8 codebase.

For instance, a document_component configuration value (with default) is set here and here, and then referenced here and here.

This way, an application (or possibly plugin) can set a document_component to a new component, via configuration, and have this new component be used by Blacklight... without the need to try to customize every single place that renders a "document_component" (which may require customizing the things that render the things that render a "document_component", etc).

If we keep going with the idea of components in configuration to allow the specific use cases identified to be achieved in a precisely targetted way, we might have:

  • config.query_constraint_component = Blacklight::ConstraintLayoutComponent: Can be set to customize the query constraint as blacklight_advanced_search and some local applications do

  • config.additional_constraints_components = []: A default empty array, that you can add 0 or more component classes to, to add additional constraints. This way multiple different plugins can add something to this array, and have their thing rendered on the end of constraints area, without having to fight for control of the ConstraintsComponent or interfere with each other.

  • Now a plugin that wants to render constraints can just render Blacklight::ConstraintsComponents, and still get all the customizations

  • But how do all these things actually render the little boxes? Before they could call the render_constraint_element helper, to render a constraint element in a standard way -- that if a local app wanted to change that standard way by overriding that helper, the plugins would use the new changed standard way. Now... they can render the new Blacklight::ConstraintLayoutComponent, but there's no way for an app to change what that does. Do we need a config.constraint_element_component too, or is that getting too crazy?

This plan does have some complexity downsides. And I guess the exact initialization arguments of each of these configurable components would have to become part of Blacklight API. As I guess is already the case for the document_component configuration.

But this is the only reasonable way I've been able to come up with to support these use cases no worse than previous Blacklight. It is eg a very popular use case for plugins to want to add an element to the "constraints" area, and you might have multiple plugins all wanting to add their own element.

@hackartisan
Copy link
Contributor Author

Through code read I believe I've summarized the current recommendations on https://github.com/projectblacklight/blacklight/wiki/Upgrading-to-Blacklight-8#plugin-upgrade-scenarios. Please make corrections there where required. For further discussion or alternate proposals moving forward please reopen this issue or create a new issue, or add an agenda item to the committer's call.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant