Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Ability for plugins to collaborate when adding extra HTML to blocks in default templates #1191

Closed
Tracked by #2251
simonw opened this issue Jan 15, 2021 · 20 comments
Closed
Tracked by #2251

Comments

@simonw
Copy link
Owner

simonw commented Jan 15, 2021

Sometimes a plugin may want to add content to an existing default template - for example datasette-search-all adds a new search box at the top of index.html. I also want datasette-upload-csvs to add a CTA on the database.html page: simonw/datasette-upload-csvs#18

Currently plugins can do this by providing a new version of the index.html template - but if multiple plugins try to do that only one of them will succeed.

It would be better if there were known areas of those templates which plugins could add additional content to, such that multiple plugins can use the same spot.

@simonw simonw added the plugins label Jan 15, 2021
@simonw
Copy link
Owner Author

simonw commented Jan 15, 2021

This relates to #987 (documented HTML hooks for JavaScript plugins) but is not quite the same thing.

@simonw
Copy link
Owner Author

simonw commented Jan 15, 2021

Also related: #857 (comprehensive documentation of variables available to templates) - since then the plugin hook could be fed the full template context and use that to do its thing.

Or maybe the plugin hooks gets to return the name of a template that should be {% include %} into the page at that point? But the plugin may want to add extra context that is available to that template include.

@simonw
Copy link
Owner Author

simonw commented Jan 17, 2021

Plugins that want to provide extra context to the template can already do so using the extra_template_vars() plugin hook.

So this hook could work by returning a list of template filenames to be included. Those templates can be bundled with the plugin. Since they are included they will have access to the template context and to any extra_template_vars() values.

@simonw
Copy link
Owner Author

simonw commented Jan 17, 2021

I think this ends up being a whole collection of new plugin hooks, something like:

  • include_table_top
  • include_table_bottom
  • include_row_top
  • include_row_bottom
  • include_database_top
  • include_database_bottom
  • include_query_bottom
  • include_query_bottom
  • include_index_bottom
  • include_index_bottom

@simonw
Copy link
Owner Author

simonw commented Jan 17, 2021

I'm going to prototype this in a branch.

@simonw
Copy link
Owner Author

simonw commented Jan 17, 2021

I'm going to try using Jinja macros to implement this: https://jinja.palletsprojects.com/en/2.11.x/templates/#macros

Maybe using one of these tricks to auto-load the macro? http://codyaray.com/2015/05/auto-load-jinja2-macros

@simonw
Copy link
Owner Author

simonw commented Jan 22, 2021

Another potential use for this: plugins that provide authentication (like datasette-auth-passwords and datasette-auth-github) could use it to add a chunk of HTML to the "permission denied" page that links to their mechanism of authenticating.

@simonw simonw added this to the Datasette 0.54 milestone Jan 25, 2021
@simonw
Copy link
Owner Author

simonw commented Jan 25, 2021

I can combine this with #987 - each of these areas of the page can be wrapped in a <div> with a class that matches the name of the plugin hook, that way JavaScript plugins can append their content in the same place as Python plugins.

simonw added a commit that referenced this issue Jan 25, 2021
@simonw
Copy link
Owner Author

simonw commented Jan 25, 2021

I've got a good prototype working now, but I'm dropping this from the Datasette 0.54 milestone because it requires a bunch of additional work to make sure it is really well tested and documented.

@simonw simonw mentioned this issue Jan 25, 2021
4 tasks
@simonw
Copy link
Owner Author

simonw commented Jan 25, 2021

More work can happen in the PR: #1204

@brandonrobertz
Copy link
Contributor

I've got a URL shortening plugin that I would like to embed on the query page but I'd like avoid capturing the entire query.html template. A feature like this would solve it. Where's this at and how can I help?

@asg017
Copy link
Contributor

asg017 commented Sep 18, 2023

One note here: this feature could be called "slots", similar to Layout Slots in Vitepress.

In Vitepress, you can add custom components/widget/gadgets into determined named "slots", like so:

doc-top
doc-bottom
doc-footer-before
doc-before
doc-after
...

Would be great to do in both Python and Javascript, with the upcoming JavaScript API #2052. In datasette-write-ui, all we do is add a few "Insert row" and "edit this row" buttons and that required completely capturing the table.html template, which isn't great for other plugins. But having "slots" like table-footer-before or table-row-id or something would be great to work with.

@simonw simonw pinned this issue Jan 30, 2024
@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

Thinking about this again. I think it only needs the top slots for the moment (I do like the term slots). So maybe:

  • slot_homepage_top
  • slot_database_top
  • slot_table_top
  • slot_row_top
  • slot_query_top

I'm not sure the word slot is necessary there. Could do this instead:

  • top_homepage
  • top_database
  • top_table
  • top_row
  • top_query

@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

Originally I thought about having some kind of accompanying template mechanism where you can have a template called top_homepage.html which gets inserted automatically. That could still happen, using a default plugin.

@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

i should probably distinguish between the canned query results page, the database index page and the /database?sql=... page that displays the results of an arbitrary SQL query.

@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

OK, I have a working prototype of the top_homepage() hook now.

Here's a plugin that uses a top_homepage.html template:

from datasette import hookimpl
import jinja2


@hookimpl
def top_homepage(datasette, request):
    async def inner():
        try:
            return await datasette.render_template("top_homepage.html", request=request)
        except jinja2.exceptions.TemplatesNotFound:
            return None

    return inner

@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

@simonw
Copy link
Owner Author

simonw commented Jan 30, 2024

Preview of the documentation, showing all of the planned hooks: https://datasette--2238.org.readthedocs.build/en/2238/plugin_hooks.html#top-homepage-datasette-request

@simonw
Copy link
Owner Author

simonw commented Jan 31, 2024

i should probably distinguish between the canned query results page, the database index page and the /database?sql=... page that displays the results of an arbitrary SQL query.

I'm going to go with top_query and top_canned_query.

@simonw
Copy link
Owner Author

simonw commented Jan 31, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants