home / github

Menu
  • Search all tables
  • GraphQL API

issues

Table actions
  • GraphQL API for issues

3 rows where assignee = 9599 and type = "pull" sorted by updated_at descending

✖
✖
✖

✎ View and edit SQL

This data as json, CSV (advanced)

Suggested facets: user, author_association, created_at (date), updated_at (date), closed_at (date)

type 1

  • pull · 3 ✖

state 1

  • closed 3

repo 1

  • datasette 3
id node_id number title user state locked assignee milestone comments created_at updated_at ▲ closed_at author_association pull_request body repo type active_lock_reason performed_via_github_app reactions draft state_reason
1651082214 PR_kwDOBm6k_c5NcFCf 2052 feat: Javascript Plugin API (Custom panels, column menu items with JS actions) hydrosquall 9020979 closed 0 simonw 9599   20 2023-04-02T20:23:44Z 2023-10-14T17:49:03Z 2023-10-13T00:00:27Z CONTRIBUTOR simonw/datasette/pulls/2052

Motivation

  • Allow plugins that add data visualizations datasette-vega, datasette-leaflet, and datasette-nteract-data-explorer to co-exist safely
  • Standardize APIs / hooks to ease development for new JS plugin developers (better compat with datasette-lite) through standardized DOM selectors, methods for extending the existing Table UI. This has come up as a feature request several times (see research notes for examples)
  • Discussion w/ @simonw about a general-purpose Datasette JS API

Changes

Summary: Provide 2 new surface areas for Datasette JS plugin developers. See alpha documentation

  1. Custom column header items: https://a.cl.ly/Kou97wJr
  2. Basic "panels" controlled by buttons: https://a.cl.ly/rRugWobd

User Facing Changes

  • Allow creating menu items under table header that triggers JS (instead of opening hrefs per the existing menu_link hook). Items can respond to any column metadata provided by the column header (e.g. label). The proof of concept plugins log data to the console, or copy the column name to clipboard.
  • Allow plugins to register UI elements in a panel controller. The parent component handles switching the visibility of active plugins.
  • Because native button elements are used, the panel is keyboard-accessible - use tab / shift-tab to cycle through tab options, and enter to select.
  • There's room to improve the styling, but the focus of this PR is on the API rather than the UX.

(plugin) Developer Facing Changes

  • Dispatch a datasette_init CustomEvent when the datasetteManager is finished loading.
  • Provide manager.registerPlugin API for adding new functionality that coordinates with Datasette lifecycle events.
  • Provide a manager.selectors map of DOM elements that users may want to hook into.
  • Updated table.js to use refer to these to motivating keeping things in sync
  • Allow plugins to register themselves with 2 hooks:
  • makeColumnActions: Add items to menu in table column headers. Users can provide a label, and either href or onClick with full access to the metadata for the clicked column (name, type, misc. booleans)
  • makeAboveTablePanelConfigs: Add items to the panel. Each panel has a unique ID (namespaced within that plugin), a render function, and a string label.

See this file for example plugin usage.

Core Developer Facing Changes

  • Modified table.js to make use of the datasetteManager API.
  • Added example plugins to the demos/plugins folder, and stored the test js in the statics/ folder

Testing

For Datasette plugin developers, please see the alpha-level documentation .

To run the examples:

bash datasette serve fixtures.db --plugins-dir=demos/plugins/

Open local server: http://127.0.0.1:8001/fixtures/facetable

Open to all feedback on this PR, from API design to variable naming, to what additional hooks might be useful for the future.

My focus was more on the general shape of the API for developers, rather than on the UX of the test plugins.

Design notes

  • The manager tab panel could be a separate plugin if the implementation is too custom.
  • The makeColumnHeaderItems benefits from hooking into the logic of table.js
  • I wanted to offer this to the Datasette core, since the datasette-manager would be more powerful if it were connected to lifecycle and JS events that are part of the existing table.js.
  • Non-goals:
  • Dependency management (for now) - there's no "build" step, we don't know when new plugins will be added. While there are some valid use cases (for example, allow multiple plugins to wait for a global leaflet object to be loaded), I don't see enough use-cases to justify doing this yet.
  • Enabling single-page-app features - for now, most datasette actions lead to a new page being loaded. SPA development offers some benefits (no page jumping after clicking on a link), but also complexity that doesn't need to be in the core Datasette project.

Research Notes

  • Relocated to a comment, as this isn't required to review when evaluating the plugin. Including it just for those who are curious.
datasette 107914493 pull    
{
    "url": "https://api.github.com/repos/simonw/datasette/issues/2052/reactions",
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
0  
717746043 MDExOlB1bGxSZXF1ZXN0NTAwMjU2NDg1 1000 datasette.client internal requests mechanism simonw 9599 closed 0 simonw 9599 Datasette 0.50 5971510 18 2020-10-08T23:58:25Z 2020-10-09T16:11:26Z 2020-10-09T16:11:25Z OWNER simonw/datasette/pulls/1000

Refs #943

datasette 107914493 pull    
{
    "url": "https://api.github.com/repos/simonw/datasette/issues/1000/reactions",
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
0  
459587155 MDExOlB1bGxSZXF1ZXN0MjkwODk3MTA0 518 Port Datasette from Sanic to ASGI + Uvicorn simonw 9599 closed 0 simonw 9599 Datasette 1.0 3268330 12 2019-06-23T15:18:42Z 2019-06-24T13:42:50Z 2019-06-24T03:13:09Z OWNER simonw/datasette/pulls/518

Most of the code here was fleshed out in comments on #272 (Port Datasette to ASGI) - this pull request will track the final pieces:

  • [x] Update test harness to more correctly simulate the raw_path issue
  • [x] Use raw_path so table names containing / can work correctly
  • [x] Bug: JSON not served with correct content-type
  • [x] Get ?_trace=1 working again
  • [x] Replacement for @app.listener("before_server_start")
  • [x] Bug: /fixtures/table%2Fwith%2Fslashes.csv?_format=json downloads as CSV
  • [x] Replace Sanic request and response objects with my own classes, so I can remove Sanic dependency
  • [x] Final code tidy-up before merging to master
datasette 107914493 pull    
{
    "url": "https://api.github.com/repos/simonw/datasette/issues/518/reactions",
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
0  

Advanced export

JSON shape: default, array, newline-delimited, object

CSV options:

CREATE TABLE [issues] (
   [id] INTEGER PRIMARY KEY,
   [node_id] TEXT,
   [number] INTEGER,
   [title] TEXT,
   [user] INTEGER REFERENCES [users]([id]),
   [state] TEXT,
   [locked] INTEGER,
   [assignee] INTEGER REFERENCES [users]([id]),
   [milestone] INTEGER REFERENCES [milestones]([id]),
   [comments] INTEGER,
   [created_at] TEXT,
   [updated_at] TEXT,
   [closed_at] TEXT,
   [author_association] TEXT,
   [pull_request] TEXT,
   [body] TEXT,
   [repo] INTEGER REFERENCES [repos]([id]),
   [type] TEXT
, [active_lock_reason] TEXT, [performed_via_github_app] TEXT, [reactions] TEXT, [draft] INTEGER, [state_reason] TEXT);
CREATE INDEX [idx_issues_repo]
                ON [issues] ([repo]);
CREATE INDEX [idx_issues_milestone]
                ON [issues] ([milestone]);
CREATE INDEX [idx_issues_assignee]
                ON [issues] ([assignee]);
CREATE INDEX [idx_issues_user]
                ON [issues] ([user]);
Powered by Datasette · Queries took 30.205ms · About: github-to-sqlite
  • Sort ascending
  • Sort descending
  • Facet by this
  • Hide this column
  • Show all columns
  • Show not-blank rows