html_url,issue_url,id,node_id,user,user_label,created_at,updated_at,author_association,body,reactions,issue,issue_label,performed_via_github_app
https://github.com/simonw/datasette/pull/2052#issuecomment-1510423051,https://api.github.com/repos/simonw/datasette/issues/2052,1510423051,IC_kwDOBm6k_c5aBzoL,9020979,hydrosquall,2023-04-16T16:12:14Z,2023-04-20T05:14:39Z,NONE,"# Javascript Plugin Docs (alpha)
## Motivation
The Datasette JS Plugin API allows developers to add interactive features to the UI, without having to modify the Python source code.
## Setup
No external/NPM dependencies are needed.
Plugin behavior is coordinated by the Datasette `manager`. Every page has 1 `manager`.
There are 2 ways to add your plugin to the `manager`.
1. Read `window.__DATASETTE__` if the manager was already loaded.
```js
const manager = window.__DATASETTE__;
```
2. Wait for the `datasette_init` event to fire if your code was loaded before the manager is ready.
```js
document.addEventListener(""datasette_init"", function (evt) {
const { detail: manager } = evt;
// register plugin here
});
```
3. Add plugin to the manager by calling `manager.registerPlugin` in a JS file. Each plugin will supply 1 or more hooks with
- unique name (`YOUR_PLUGIN_NAME`)
- a numeric version (starting at `0.1`),
- configuration value, the details vary by hook. (In this example, `getColumnActions` takes a function)
```js
manager.registerPlugin(""YOUR_PLUGIN_NAME"", {
version: 0.1,
makeColumnActions: (columnMeta) => {
return [
{
label: ""Copy name to clipboard"",
// evt = native click event
onClick: (evt) => copyToClipboard(columnMeta.column),
}
];
},
});
```
There are 2 plugin hooks available to `manager.registerPlugin`:
- `makeColumnActions` - Add items to the cog menu for headers on datasette table pages
- `makeAboveTablePanelConfigs` - Add items to ""tabbed"" panel above the `
` on pages that use the Datasette table template.
While there are additional properties on the `manager`, but it's not advised to depend on them directly as the shape is subject to change.
4. To make your JS file available as a Datasette plugin from the Python side, you can add a python file resembling [this](https://github.com/simonw/datasette/pull/2052/files#diff-c5ecf3d22075a60d04a4e95da2e15c612cf1bc84e38d777b67ba60dbd156e293) to your plugins directory. Note that you could host your JS file anywhere, it doesn't have to be served from the Datasette statics folder.
I welcome ideas for more hooks, or feedback on the current design!
## Examples
See the [example plugins file](https://github.com/simonw/datasette/blob/2d92b9328022d86505261bcdac419b6ed9cb2236/datasette/static/table-example-plugins.js) for additional examples.
## Hooks API Guide
### `makeAboveTablePanelConfigs`
Provide a function with a list of panel objects. Each panel object should contain
1. A unique string `id`
2. A string `label` for the tab
3. A `render` function. The first argument is reference to an HTML [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element).
Example:
```js
manager.registerPlugin(""panel-plugin-graphs"", {
version: 0.1,
makeAboveTablePanelConfigs: () => {
return [
{
id: 'first-panel',
label: ""My new panel"",
render: node => {
const description = document.createElement('p');
description.innerText = 'Hello world';
node.appendChild(description);
}
}
];
},
});
```
### `makeColumnActions`
Provide a function that returns a list of action objects. Each action object has
1. A string `label` for the menu dropdown label
2. An onClick `render` function.
Example:
```js
manager.registerPlugin(""column-name-plugin"", {
version: 0.1,
getColumnActions: (columnMeta) => {
// Info about selected column.
const { columnName, columnNotNull, columnType, isPk } = columnMeta;
return [
{
label: ""Copy name to clipboard"",
onClick: (evt) => copyToClipboard(column),
}
];
},
});
```
The getColumnActions callback has access to an object with metadata about the clicked column. These fields include:
- columnName: string (name of the column)
- columnNotNull: boolean
- columnType: sqlite datatype enum (text, number, etc)
- isPk: Whether this is the primary key: boolean
You can use this column metadata to customize the action config objects (for example, handling different summaries for text vs number columns).
","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1651082214,"feat: Javascript Plugin API (Custom panels, column menu items with JS actions)",
https://github.com/simonw/datasette/pull/2052#issuecomment-1510423215,https://api.github.com/repos/simonw/datasette/issues/2052,1510423215,IC_kwDOBm6k_c5aBzqv,9020979,hydrosquall,2023-04-16T16:12:59Z,2023-04-16T16:12:59Z,NONE,"## Research notes
- I stuck to the ""minimal dependencies"" ethos of datasette (no React, Typescript, JS linting, etc).
- Main threads on JS plugin development
- Main: sketch of pluggy-inspired system: https://github.com/simonw/datasette/issues/983
- Main: provide locations in Datasette HTML that are designed for multiple plugins to safely cooperate with each other (starting with the panel, but eventually could extend to ""search boxes""): https://github.com/simonw/datasette/issues/1191
- Main: HTML hooks for JS plugin authors: https://github.com/simonw/datasette/issues/987
- Prior threads on JS plugins in Datasette for future design directions
- Idea: pass useful strings to JS plugins: https://github.com/simonw/datasette/issues/1565
- Idea: help with plugin dependency loading: https://github.com/simonw/datasette/issues/1542 . (IMO - the plugin providing the dependency can emit an event once it's done. Other plugins can listen for it, or ask the manager to inform them when the dependency is available).
- Idea: help plugins to manage state in shareable URLs (plugins shouldn't have to interact with the URL directly, should have some basic insulation from clobbering each others' keys): https://github.com/simonw/datasette/issues/1144
- Articles on plugins reviewed
- https://css-tricks.com/designing-a-javascript-plugin-system/
- Plugin/Extension systems reviewed (mostly JS).
- Yarn: https://yarnpkg.com/advanced/plugin-tutorial
- Tappable https://github.com/webpack/tapable (used by Auto, webpack)
- Pluggy: https://pluggy.readthedocs.io/en/stable/
- VSCode: https://code.visualstudio.com/api/get-started/your-first-extension
- Chrome: https://developer.chrome.com/docs/extensions/reference/
- Figma/Figjam Widget: https://www.figma.com/widget-docs/
- Datadog Apps: [Programming Model](https://github.com/DataDog/apps/blob/master/docs/en/programming-model.md)
- Storybook: https://storybook.js.org/docs/react/addons/addons-api","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1651082214,"feat: Javascript Plugin API (Custom panels, column menu items with JS actions)",