diff --git a/datasette/app.py b/datasette/app.py index c9605af3..088403e0 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -2039,22 +2039,6 @@ class Datasette: links.extend(extra_links) return links - async def jump_start(): - html_bits = [] - for hook in pm.hook.jump_start( - datasette=self, - actor=request.actor if request else None, - request=request or None, - ): - extra_html = await await_me_maybe(hook) - if not extra_html: - continue - if isinstance(extra_html, (list, tuple)): - html_bits.extend(extra_html) - else: - html_bits.append(extra_html) - return Markup("").join(Markup(html) for html in html_bits) - template_context = { **context, **{ @@ -2063,7 +2047,6 @@ class Datasette: "urls": self.urls, "actor": request.actor if request else None, "menu_links": menu_links, - "jump_start": jump_start, "display_actor": display_actor, "show_logout": request is not None and "ds_actor" in request.cookies diff --git a/datasette/hookspecs.py b/datasette/hookspecs.py index a4d8143b..cf95abcb 100644 --- a/datasette/hookspecs.py +++ b/datasette/hookspecs.py @@ -159,12 +159,7 @@ def menu_links(datasette, actor, request): @hookspec def jump_items_sql(datasette, actor, request): - """SQL fragments for extra items in the jump menu, optionally with display_name""" - - -@hookspec -def jump_start(datasette, actor, request): - """HTML to display in the jump menu before the user types""" + """SQL fragments for extra items in the jump menu""" @hookspec diff --git a/datasette/jump.py b/datasette/jump.py index 96e18547..6ec7ae13 100644 --- a/datasette/jump.py +++ b/datasette/jump.py @@ -9,7 +9,6 @@ from typing import Any class JumpSQL: sql: str params: dict[str, Any] | None = None - has_display_name: bool = False _PARAM_RE = re.compile(r"(? { + let jumpSections = []; + + datasetteManager.plugins.forEach((plugin) => { + if (plugin.makeJumpSections) { + const sections = plugin.makeJumpSections(context) || []; + jumpSections.push(...sections); + } + }); + + return jumpSections; + }, + /** * In MVP, each plugin can only have 1 instance. * In future, panels could be repeated. We omit that for now since so many plugins depend on @@ -192,7 +205,6 @@ const initializeDatasette = () => { // DATASETTE_EVENTS.INIT event to avoid the habit of reading from the window. window.__DATASETTE__ = datasetteManager; - console.debug("Datasette Manager Created!"); const initDatasetteEvent = new CustomEvent(DATASETTE_EVENTS.INIT, { detail: datasetteManager, diff --git a/datasette/static/navigation-search.js b/datasette/static/navigation-search.js index 49cc172c..9e24681b 100644 --- a/datasette/static/navigation-search.js +++ b/datasette/static/navigation-search.js @@ -447,9 +447,46 @@ class NavigationSearch extends HTMLElement { this.renderResults(); } - startContentHtml() { - const template = this.querySelector("template[data-jump-start]"); - return template ? template.innerHTML.trim() : ""; + jumpSections() { + const manager = window.__DATASETTE__; + if (!manager || typeof manager.makeJumpSections !== "function") { + return []; + } + const sections = manager.makeJumpSections({ + navigationSearch: this, + }); + return Array.isArray(sections) + ? sections.filter( + (section) => section && typeof section.render === "function", + ) + : []; + } + + jumpSectionsHtml(jumpSections) { + return jumpSections + .map((section, index) => { + const id = section.id + ? ` data-jump-section-id="${this.escapeHtml(section.id)}"` + : ""; + return `
`; + }) + .join(""); + } + + renderJumpSections(container, jumpSections) { + jumpSections.forEach((section, index) => { + const node = container.querySelector( + `[data-jump-section-index="${index}"]`, + ); + if (!node) { + return; + } + section.render(node, { + navigationSearch: this, + container, + input: this.shadowRoot.querySelector(".search-input"), + }); + }); } resultItemHtml(match, index) { @@ -484,9 +521,9 @@ class NavigationSearch extends HTMLElement { const container = this.shadowRoot.querySelector(".results-container"); const input = this.shadowRoot.querySelector(".search-input"); const showStartContent = !input.value.trim(); - const startContent = showStartContent ? this.startContentHtml() : ""; - const startBlock = startContent - ? `