{"id": 274284246, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUyODcwMDMw", "number": 104, "title": "[WIP] Add publish to heroku support", "user": {"value": 21148, "label": "jacobian"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2017-11-15T19:56:22Z", "updated_at": "2017-11-21T20:55:05Z", "closed_at": "2017-11-21T20:55:05Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/104", "body": "\r\n\r\nRefs #90 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/104/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 274314940, "node_id": "MDU6SXNzdWUyNzQzMTQ5NDA=", "number": 105, "title": "Consider data-package as a format for metadata", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2017-11-15T21:43:34Z", "updated_at": "2017-11-20T19:50:53Z", "closed_at": "2017-11-20T19:50:53Z", "author_association": "OWNER", "pull_request": null, "body": "http://frictionlessdata.io/specs/data-package/", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/105/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274315193, "node_id": "MDU6SXNzdWUyNzQzMTUxOTM=", "number": 106, "title": "Document how pagination works", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-15T21:44:32Z", "updated_at": "2019-06-24T06:42:33Z", "closed_at": "2019-06-24T06:42:33Z", "author_association": "OWNER", "pull_request": null, "body": "I made a start at that in this comment: https://news.ycombinator.com/item?id=15691926", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/106/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274343647, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUyOTE0NDgw", "number": 107, "title": "add support for ?field__isnull=1", "user": {"value": 3433657, "label": "raynae"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2017-11-15T23:36:36Z", "updated_at": "2017-11-17T15:12:29Z", "closed_at": "2017-11-17T13:29:22Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/107", "body": "Is this what you had in mind for [this issue](https://github.com/simonw/datasette/issues/64)?", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/107/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 274374317, "node_id": "MDU6SXNzdWUyNzQzNzQzMTc=", "number": 108, "title": "Include version in python code, output in template", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-16T02:32:40Z", "updated_at": "2017-11-16T15:30:04Z", "closed_at": "2017-11-16T15:30:04Z", "author_association": "OWNER", "pull_request": null, "body": "It would be useful if I could tell which version of datasette was running on a site. Embed version number and include it in maybe a tooltip on the \u201cpowered by datasette\u201d link", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/108/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274378301, "node_id": "MDU6SXNzdWUyNzQzNzgzMDE=", "number": 109, "title": "Set up readthedocs", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-16T02:58:01Z", "updated_at": "2017-11-16T16:53:26Z", "closed_at": "2017-11-16T16:13:56Z", "author_association": "OWNER", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/109/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274578142, "node_id": "MDU6SXNzdWUyNzQ1NzgxNDI=", "number": 110, "title": "Add --load-extension option to datasette for loading extra SQLite extensions", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-16T16:26:19Z", "updated_at": "2017-11-16T18:38:30Z", "closed_at": "2017-11-16T16:58:50Z", "author_association": "OWNER", "pull_request": null, "body": "This would allow users with extra SQLite extensions installed (like spatialite) to load them at runtime.\r\n\r\nInspired by this comment: https://github.com/simonw/datasette/issues/46#issuecomment-344810525", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/110/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274617240, "node_id": "MDU6SXNzdWUyNzQ2MTcyNDA=", "number": 112, "title": "Allow --load-extension to be set via environment variables", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-16T18:28:31Z", "updated_at": "2017-11-17T14:19:23Z", "closed_at": "2017-11-17T14:17:27Z", "author_association": "OWNER", "pull_request": null, "body": "This will make it easier to package up datasette in a Docker container with a bunch of pre-compiled extensions without the user having to remember to include all of the options every time.\r\n\r\nClick has a mechanism for this: http://click.pocoo.org/5/options/#multiple-values-from-environment-values", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/112/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274662378, "node_id": "MDU6SXNzdWUyNzQ2NjIzNzg=", "number": 113, "title": "Fix the   bug on the database custom SQL query view", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 0, "created_at": "2017-11-16T21:01:26Z", "updated_at": "2017-11-17T15:40:52Z", "closed_at": "2017-11-17T15:40:52Z", "author_association": "OWNER", "pull_request": null, "body": "https://sf-film-locations.now.sh/sf-film-locations-57704b7?sql=select+*+from+Film_Locations_in_San_Francisco\r\n\r\n\"sf-film-locations\"\r\n\r\nThis is the bug I fixed in 01e0c3fa18cd0dd7970e208790ffd683a420c924 - but I only fixed it in one place.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/113/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274733145, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUzMjAxOTQ1", "number": 114, "title": "Add spatialite, switch to debian and local build", "user": {"value": 54999, "label": "ingenieroariel"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-17T02:37:09Z", "updated_at": "2017-11-17T03:50:52Z", "closed_at": "2017-11-17T03:50:52Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/114", "body": "Improves the Dockerfile to support spatial datasets, work with the local datasette code (Friendly with git tags and Dockerhub) and moves to slim debian, a small image easy to extend via apt packages for sqlite.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/114/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 274877366, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUzMzA2ODgy", "number": 115, "title": "Add keyboard shortcut to execute SQL query", "user": {"value": 198537, "label": "rgieseke"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-17T14:13:33Z", "updated_at": "2017-11-17T15:16:34Z", "closed_at": "2017-11-17T14:22:56Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/115", "body": "Very cool tool, thanks a lot!\r\n\r\nThis PR adds a `Shift-Enter` short cut to execute the SQL query. I used CodeMirrors keyboard handling.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/115/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 274884209, "node_id": "MDU6SXNzdWUyNzQ4ODQyMDk=", "number": 116, "title": "Add documentation section about SQLite extensions", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-17T14:36:30Z", "updated_at": "2018-05-28T17:23:42Z", "closed_at": "2018-05-28T17:23:41Z", "author_association": "OWNER", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/116/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 274900388, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUzMzI0MzAx", "number": 117, "title": "Don't prevent tabbing to `Run SQL` button", "user": {"value": 198537, "label": "rgieseke"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-17T15:27:50Z", "updated_at": "2017-11-19T20:30:24Z", "closed_at": "2017-11-18T00:53:43Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/117", "body": "Mentioned in #115 \r\n\r\nHere you go!", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/117/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 275048699, "node_id": "MDExOlB1bGxSZXF1ZXN0MTUzNDMyMDQ1", "number": 118, "title": "Foreign key information on row and table pages", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-18T03:13:27Z", "updated_at": "2017-11-18T03:15:57Z", "closed_at": "2017-11-18T03:15:50Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/118", "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/118/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 275082158, "node_id": "MDU6SXNzdWUyNzUwODIxNTg=", "number": 119, "title": "Build an \"export this data to google sheets\" plugin", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-18T14:14:51Z", "updated_at": "2020-06-04T18:46:40Z", "closed_at": "2020-06-04T18:46:39Z", "author_association": "OWNER", "pull_request": null, "body": "Inspired by https://github.com/kren1/tosheets\r\n\r\nIt should be a plug-in because I'd like to keep all interactions with proprietary / non-open-source software encapsulated in plugins rather than shipped as part of core.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/119/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275087397, "node_id": "MDU6SXNzdWUyNzUwODczOTc=", "number": 120, "title": "Plugin that adds an authentication layer of some sort", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2017-11-18T15:39:13Z", "updated_at": "2020-03-16T18:48:06Z", "closed_at": "2020-03-16T18:48:06Z", "author_association": "OWNER", "pull_request": null, "body": "Would allow people who want to host private data to do so.\r\n.sh ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/120/reactions\", \"total_count\": 7, \"+1\": 5, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 2, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275089535, "node_id": "MDU6SXNzdWUyNzUwODk1MzU=", "number": 121, "title": "?_json=foo&_json=bar query string argument ", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2017-11-18T16:09:55Z", "updated_at": "2018-05-31T13:48:12Z", "closed_at": "2018-05-28T18:11:51Z", "author_association": "OWNER", "pull_request": null, "body": "Causes the specified columns in the output to be treated as JSON, and returned deserialized in the .json or .jsono response.\r\n\r\nThis will be particularly powerful when combined with https://sqlite.org/json1.html", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/121/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275092453, "node_id": "MDU6SXNzdWUyNzUwOTI0NTM=", "number": 122, "title": "Redesign JSON output, ditch jsono, offer variants controlled by parameter instead", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 5, "created_at": "2017-11-18T16:52:28Z", "updated_at": "2018-04-08T14:54:09Z", "closed_at": "2018-04-08T14:54:09Z", "author_association": "OWNER", "pull_request": null, "body": "I want to support three variants for the rows output:\r\n\r\n* a list of lists, with a columns key saying what they are\r\n* a list of dictionaries\r\n* a single dictionary where the keys are the primary keys of the rows and the values are the row dictionaries themselves\r\n\r\nI also want to make the various bits of metadata opt-in - so you don't get the SQL statement unless you ask for it.\r\n\r\nThese output options should be controlled by query string arguments.\r\n\r\nI will set the .jsono URL to redirect to .json with the corresponding options. ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/122/reactions\", \"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 1, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275125805, "node_id": "MDU6SXNzdWUyNzUxMjU4MDU=", "number": 124, "title": "Option to open readonly but not immutable", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 5, "created_at": "2017-11-19T02:11:03Z", "updated_at": "2019-06-24T06:43:46Z", "closed_at": "2019-06-24T06:43:46Z", "author_association": "OWNER", "pull_request": null, "body": "Immutable assumes no other process can modify the file. An option to open reqdonly instead would enable other processes to update the file in place.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/124/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275135393, "node_id": "MDU6SXNzdWUyNzUxMzUzOTM=", "number": 125, "title": "Plot rows on a map with Leaflet and Leaflet.markercluster", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-19T06:05:05Z", "updated_at": "2018-04-26T15:14:31Z", "closed_at": "2018-04-26T15:14:31Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/Leaflet/Leaflet.markercluster would allow us to paginate-load in an enormous set of rows with latitude/longitude points, e.g. https://australian-dunnies.now.sh/\r\n\r\nHere's a demo of it loading 50,000 markers: https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.50000.html - and it looks like it's easy to support progress bars for if we were iteratively loading 1,000 markers at a time using datasette pagination.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/125/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275135535, "node_id": "MDU6SXNzdWUyNzUxMzU1MzU=", "number": 126, "title": "Blog entry announcing foreign key support", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 1, "created_at": "2017-11-19T06:09:06Z", "updated_at": "2017-11-30T16:49:24Z", "closed_at": "2017-11-30T16:49:24Z", "author_association": "OWNER", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/126/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275135719, "node_id": "MDU6SXNzdWUyNzUxMzU3MTk=", "number": 127, "title": "Filtered tables should show count of all matching rows, if fast enough", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 2, "created_at": "2017-11-19T06:13:29Z", "updated_at": "2017-11-24T22:02:01Z", "closed_at": "2017-11-24T22:02:01Z", "author_association": "OWNER", "pull_request": null, "body": "Relates to #86. If you are viewing a filtered page e.g. https://fivethirtyeight.datasettes.com/fivethirtyeight-2628db9/bob-ross%2Felements-by-episode?CLOUDS=1 we should show the count of matching rows.\r\n\r\nSince this could be an expensive operation, we will run it with a strict time limit (maybe 50ms). If the time limit is exceeded we will display \"many\" instead, perhaps? Maybe even link to a count(*) query that would get the full 1000ms time limit which the user can click on if they like (that could even Ajax-in the result).", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/127/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275164558, "node_id": "MDU6SXNzdWUyNzUxNjQ1NTg=", "number": 129, "title": "Hide FTS-created tables by default on the database index page", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-19T14:50:42Z", "updated_at": "2017-11-22T20:22:02Z", "closed_at": "2017-11-22T20:19:04Z", "author_association": "OWNER", "pull_request": null, "body": "SQLite databases that use FTS include a number of automatically generated tables, e.g.:\r\n\r\nhttps://sf-trees-search.now.sh/sf-trees-search-a899b92\r\n\r\n\"sf-trees-search_and_sf-trees-search\"\r\n\r\nOf these, only the `Street_Tree_List` table is actually relevant to the user.\r\n\r\nWe can detect which tables are FTS tables by first finding the virtual tables:\r\n\r\n sqlite> .headers on\r\n sqlite> select * from sqlite_master where rootpage = 0;\r\n type|name|tbl_name|rootpage|sql\r\n table|Search|Search|0|CREATE VIRTUAL TABLE \"Street_Tree_List_fts\" USING FTS4 (\"qAddress\", \"qCaretaker\", \"qSpecies\")\r\n\r\nThen parsing the above to figure out which ones are USING FTS? - then assume that any table which starts with that `Street_Tree_List_fts` prefix was created to support search:\r\n\r\n sqlite> select * from sqlite_master where type='table' and tbl_name like 'Street_Tree_List_fts%';\r\n type|name|tbl_name|rootpage|sql\r\n table|Search_content|Search_content|10355|CREATE TABLE 'Street_Tree_List_fts_content'(docid INTEGER PRIMARY KEY, 'c0qAddress', 'c1qCaretaker', 'c2qSpecies')\r\n table|Search_segments|Search_segments|10356|CREATE TABLE 'Street_Tree_List_fts_segments'(blockid INTEGER PRIMARY KEY, block BLOB)\r\n table|Search_segdir|Search_segdir|10357|CREATE TABLE 'Street_Tree_List_fts_segdir'(level INTEGER,idx INTEGER,start_block INTEGER,leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx))\r\n table|Search_docsize|Search_docsize|10359|CREATE TABLE 'Street_Tree_List_fts_docsize'(docid INTEGER PRIMARY KEY, size BLOB)\r\n table|Search_stat|Search_stat|10360|CREATE TABLE 'Street_Tree_List_fts_stat'(id INTEGER PRIMARY KEY, value BLOB)\r\n\r\nWe won't hide these completely - instead, we'll default the database index view to not showing them with a message that says \"5 hidden tables\" and support ?_hidden=1 to display them.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/129/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275166078, "node_id": "MDU6SXNzdWUyNzUxNjYwNzg=", "number": 130, "title": "Rename \"datasette build\" to \"datasette inspect\"", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-19T15:08:02Z", "updated_at": "2017-12-07T16:57:58Z", "closed_at": "2017-12-07T16:57:58Z", "author_association": "OWNER", "pull_request": null, "body": "This command introspects the databases and writes out a JSON summary.\r\n\r\nI think I'd like to use `datasette build` for something more interesting, potentially duplicating functionality from https://github.com/simonw/csvs-to-sqlite\r\n\r\nSince the internal method that does this is called `ds.inspect()` that seems like a reasonable replacement name for the command.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/130/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275166669, "node_id": "MDU6SXNzdWUyNzUxNjY2Njk=", "number": 131, "title": "UI support for running FTS searches", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2017-11-19T15:16:20Z", "updated_at": "2017-11-19T17:18:05Z", "closed_at": "2017-11-19T17:00:12Z", "author_association": "OWNER", "pull_request": null, "body": "Here's an example query that searches all FTS indexed columns in a table: https://sf-trees-search.now.sh/sf-trees-search-a899b92?sql=select+*+from+Street_Tree_List+where+rowid+in+%28select+rowid+from+Street_Tree_List_fts+where+Street_Tree_List_fts+match+%27grove+london+dpw%27%29%0D%0A\r\n\r\nAnd here's a query that searches a specific column: https://sf-trees-search.now.sh/sf-trees-search-a899b92?sql=select+*+from+Street_Tree_List+where+rowid+in+%28select+rowid+from+Street_Tree_List_fts+where+qSpecies+match+%27london%27%29%0D%0A\r\n\r\nIf we detect that a table has FTS enabled (which we can do by looking for it as a content table reference in another FTS table's create definition) we should add a search box to the table page which constructs this query - maybe using `?_search=XXX` in the query string?\r\n\r\nTo support search against specified columns, we can do `?_search__ qSpecies=London`. - not necessary, see comment below.\r\n\r\n- [x] Detect if a table has a FTS index defined against it as a content= parameter\r\n- [x] Decide what to do if there is more than one FTS index (maybe just pick the first one?)\r\n- [x] Add the `?_search=` query string argument\r\n- [x] Add the UI", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/131/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275175929, "node_id": "MDU6SXNzdWUyNzUxNzU5Mjk=", "number": 132, "title": "Row view is not currently expanding foreign keys", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 1, "created_at": "2017-11-19T17:24:25Z", "updated_at": "2017-11-23T21:51:51Z", "closed_at": "2017-11-23T21:51:30Z", "author_association": "OWNER", "pull_request": null, "body": "Eg https://sf-trees.now.sh/sf-trees-ebc2ad9/Street_Tree_List/1", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/132/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275176006, "node_id": "MDU6SXNzdWUyNzUxNzYwMDY=", "number": 133, "title": "If view is filtered, search should apply within those filtered rows", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 3, "created_at": "2017-11-19T17:25:36Z", "updated_at": "2017-11-24T22:30:32Z", "closed_at": "2017-11-24T22:30:15Z", "author_association": "OWNER", "pull_request": null, "body": "Eg on https://sf-trees.now.sh/sf-trees-ebc2ad9/Street_Tree_List?qSpecies=1", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/133/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275176094, "node_id": "MDU6SXNzdWUyNzUxNzYwOTQ=", "number": 134, "title": "Filtered table view should show a count", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 1, "created_at": "2017-11-19T17:26:53Z", "updated_at": "2017-11-19T18:10:49Z", "closed_at": "2017-11-19T18:10:49Z", "author_association": "OWNER", "pull_request": null, "body": "Let's do the thing where we attempt to show an accurate count if it can be done in less than 50ms", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/134/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275179724, "node_id": "MDU6SXNzdWUyNzUxNzk3MjQ=", "number": 135, "title": "?_search=x should work if used directly against a FTS virtual table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 3, "created_at": "2017-11-19T18:17:53Z", "updated_at": "2017-12-07T04:54:41Z", "closed_at": "2017-12-07T04:54:41Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. https://sf-trees.now.sh/sf-trees-ebc2ad9/Street_Tree_List_fts?_search=grove should work", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/135/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275228834, "node_id": "MDU6SXNzdWUyNzUyMjg4MzQ=", "number": 136, "title": "\"Reformat SQL\" button next to SQL editor textarea", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-20T03:42:19Z", "updated_at": "2019-10-14T03:46:13Z", "closed_at": "2019-10-14T03:46:13Z", "author_association": "OWNER", "pull_request": null, "body": "Can use this:\r\n\r\nhttps://github.com/zeroturnaround/sql-formatter\r\nhttps://zeroturnaround.github.io/sql-formatter/\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/136/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275476839, "node_id": "MDU6SXNzdWUyNzU0NzY4Mzk=", "number": 138, "title": "Per-database and per-table metadata, probably using data-package", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-20T19:50:10Z", "updated_at": "2017-12-10T03:08:36Z", "closed_at": "2017-12-10T03:08:26Z", "author_association": "OWNER", "pull_request": null, "body": "Ability to annotate databases and tables with extra metadata describing their purpose, providing source and licensing information and describing individual columns.\r\n\r\nhttp://frictionlessdata.io/specs/data-package/ looks like a great format for this, see #105 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/138/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275493851, "node_id": "MDU6SXNzdWUyNzU0OTM4NTE=", "number": 139, "title": "Build a visualization plugin for Vega", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-20T20:47:41Z", "updated_at": "2018-07-10T17:48:18Z", "closed_at": "2018-07-10T17:48:18Z", "author_association": "OWNER", "pull_request": null, "body": "https://vega.github.io/vega/examples/population-pyramid/ for example looks pretty easy to hook up to Datasette.\r\n\r\nDepends on #14 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/139/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275814941, "node_id": "MDU6SXNzdWUyNzU4MTQ5NDE=", "number": 141, "title": "datasette publish can fail if /tmp is on a different device", "user": {"value": 21148, "label": "jacobian"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 5, "created_at": "2017-11-21T18:28:05Z", "updated_at": "2020-04-29T03:27:54Z", "closed_at": "2017-12-08T16:06:36Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "`datasette publish` uses hard links to avoid copying the db into a tmp directory. This can fail if `/tmp` is on another device, because hardlinks can't cross devices. You'll see something like this:\r\n\r\n```\r\n$ datasette publish heroku whatever.db\r\n...\r\nOSError: [Errno 18] Invalid cross-device link: '/mnt/c/Users/jacob/c/datasette/whatever.db' -> '/tmp/tmpvxq2yof6/whatever.db'\r\n```\r\n[In my case this is failing because I'm on a Windows machine, using WSL, so my code's on a different virtual filesystem from the Linux subsystem, Because Reasons.]\r\n\r\nI'm not sure if it's possible to detect this (can you figure out which device `/tmp` is on?), or what the fallback should be (soft link? copy?).", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/141/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275917760, "node_id": "MDU6SXNzdWUyNzU5MTc3NjA=", "number": 142, "title": "Show extra instructions with the interrupted", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2017-11-22T01:44:29Z", "updated_at": "2018-05-28T21:25:06Z", "closed_at": "2018-05-28T21:24:35Z", "author_association": "OWNER", "pull_request": null, "body": "When you are using Datasette locally for ad-hoc analysis it can be frustrating to hit the time limit.\r\n\r\n If you start it with the correct command line arguments you can disable that time limit. So how about we tell you how to do that anytime you hit the interrupted error provided you are accessing it from localhost.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/142/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 275939188, "node_id": "MDU6SXNzdWUyNzU5MzkxODg=", "number": 143, "title": "Mechanism for \"suggested visualizations\"", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-11-22T04:10:25Z", "updated_at": "2018-07-10T17:48:34Z", "closed_at": "2018-07-10T17:48:34Z", "author_association": "OWNER", "pull_request": null, "body": " Each visualization should have a way of deciding if it might be appropriate for the current view of data. \r\n\r\n We can then offer a \"suggested visualizations\" prompt which shows previews.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/143/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276091279, "node_id": "MDU6SXNzdWUyNzYwOTEyNzk=", "number": 144, "title": "apsw as alternative sqlite3 binding (for full text search)", "user": {"value": 649467, "label": "mhalle"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2017-11-22T14:40:39Z", "updated_at": "2018-05-28T21:29:42Z", "closed_at": "2018-05-28T21:29:42Z", "author_association": "NONE", "pull_request": null, "body": "Hey there,\r\n\r\nHave you considered providing apsw support as an alternative to stock python sqlite3? I use apsw because it keeps up with sqlite3 and is straightforward to bring in extensions like FTS5. FTS really accelerates the kind of searching often done by web clients.\r\n\r\nI may be able to help (it shouldn't be much code), but there are a couple of stylistic questions that come up when supporting an optional package. Also, apsw is tricky in that it doesn't have a pypi package (author says limitations in providing options to setup.py). ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/144/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276192732, "node_id": "MDExOlB1bGxSZXF1ZXN0MTU0MjQ2ODE2", "number": 145, "title": "Fix pytest version conflict", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-22T20:15:34Z", "updated_at": "2017-11-22T20:17:54Z", "closed_at": "2017-11-22T20:17:52Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/145", "body": "https://travis-ci.org/simonw/datasette/jobs/305929426\r\n\r\n pkg_resources.VersionConflict: (pytest 3.2.1 (/home/travis/virtualenv/python3.5.3/lib/python3.5/site-packages), \r\n Requirement.parse('pytest==3.2.3'))", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/145/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 276455748, "node_id": "MDU6SXNzdWUyNzY0NTU3NDg=", "number": 146, "title": "datasette publish gcloud", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-23T18:55:03Z", "updated_at": "2019-06-24T06:48:20Z", "closed_at": "2019-06-24T06:48:20Z", "author_association": "OWNER", "pull_request": null, "body": "See also #103 \r\n\r\nIt looks like you can start a Google Cloud VM with a \"docker container\" option - and the Google Cloud Registry is easy to push containers to. So it would be feasible to have `datasette publish gcloud ...` automatically build a container, push it to GCR, then start a new VM instance with it:\r\n\r\nhttps://cloud.google.com/container-registry/docs/pushing-and-pulling\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/146/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276476670, "node_id": "MDU6SXNzdWUyNzY0NzY2NzA=", "number": 147, "title": "Tidy up design of the header of the table page", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 1, "created_at": "2017-11-23T21:52:58Z", "updated_at": "2017-11-24T22:02:46Z", "closed_at": "2017-11-24T22:02:46Z", "author_association": "OWNER", "pull_request": null, "body": "This is a bit messy:\r\n\r\n\"fatal-police-shootings-data__fatal-police-shootings-data\"\r\n\r\nDepends on #127 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/147/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276477888, "node_id": "MDU6SXNzdWUyNzY0Nzc4ODg=", "number": 148, "title": "Need a != filter", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 0, "created_at": "2017-11-23T22:05:22Z", "updated_at": "2017-11-23T22:10:02Z", "closed_at": "2017-11-23T22:10:01Z", "author_association": "OWNER", "pull_request": null, "body": "https://datasette-demos.now.sh/sf-trees-ebc2ad9/Street_Tree_List?qCareAssistant=1 shows trees managed by FUF - but how about trees that are NOT managed by FUF?", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/148/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276704127, "node_id": "MDU6SXNzdWUyNzY3MDQxMjc=", "number": 149, "title": "Update custom SQL results to match new table view header", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2919870, "label": "Foreign key edition"}, "comments": 1, "created_at": "2017-11-24T22:03:59Z", "updated_at": "2017-11-24T22:42:10Z", "closed_at": "2017-11-24T22:42:09Z", "author_association": "OWNER", "pull_request": null, "body": "Follow-on from #147 - the custom SQL results page should more closely match the design of the table view, which now looks like this:\r\n\r\n\"conventional_power_plants_eu__conventional_power_plants_eu__14_rows_where_company____nuon_\"\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/149/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276704327, "node_id": "MDU6SXNzdWUyNzY3MDQzMjc=", "number": 150, "title": "_group_count= feature improvements", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2017-11-24T22:06:18Z", "updated_at": "2018-05-28T16:41:28Z", "closed_at": "2018-05-28T16:41:28Z", "author_association": "OWNER", "pull_request": null, "body": "- [ ] The \"apply filters\" form should keep you on the _group_count= page\r\n- [ ] Foreign key references should be expand\r\n- [ ] Page title should reflect the view you are on", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/150/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276718605, "node_id": "MDU6SXNzdWUyNzY3MTg2MDU=", "number": 151, "title": "Set up a pattern portfolio", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-11-25T02:09:49Z", "updated_at": "2020-07-02T00:13:24Z", "closed_at": "2020-05-03T03:13:16Z", "author_association": "OWNER", "pull_request": null, "body": "https://www.slideshare.net/nataliedowne/practical-maintainable-css/75\r\n\r\nThis will be a single page that demonstrates all of the different CSS styles and classes available to Datasette.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/151/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276765070, "node_id": "MDU6SXNzdWUyNzY3NjUwNzA=", "number": 152, "title": "Incorrect display of rows page for tables with a primary key", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 0, "created_at": "2017-11-25T17:29:54Z", "updated_at": "2017-12-07T05:23:20Z", "closed_at": "2017-12-07T05:23:19Z", "author_association": "OWNER", "pull_request": null, "body": "This is a regression. Here's the old version:\r\n\r\n\"parlgov__party_family\"\r\n\r\nAnd here's the new, broken one:\r\n\r\nhttps://parlgov-xtxlddmtiz.now.sh/parlgov-25f9855/party_family/1\r\n\r\n\"parlgov__party_family\"\r\n\r\nThe JSON output is the same for both - it's only the HTML representation that exhibits the bug.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/152/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276842536, "node_id": "MDU6SXNzdWUyNzY4NDI1MzY=", "number": 153, "title": "Ability to customize presentation of specific columns in HTML view", "user": {"value": 20264, "label": "ftrain"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 14, "created_at": "2017-11-26T17:46:11Z", "updated_at": "2017-12-10T02:08:45Z", "closed_at": "2017-12-07T06:17:33Z", "author_association": "NONE", "pull_request": null, "body": "This ties into https://github.com/simonw/datasette/issues/3 in some ways. It would be great to have some adaptability in the HTML views and to specific some columns as displaying in certain ways.\r\n\r\n- [x] 1. **Auto-parsing URIs into in-browser links.** Why? Lots of public data around cultural commons stuff links to a specific URL. This would be a great utility to turn on at the command line, just parse everything for URLs. Maybe they need to be underlined or represented in a different way than internal URLs.\r\n- [x] 2. **Ability to identify a column as plain/preformatted text.** Why? Was trying to import the Enron emails, the body collapses. Hard to read. These fields also tend to screw up the ability to scan a table view. If you knew it was text the system could set an `overflow` property on the relevant CSS, so you could still scan.\r\n- [x] 3. **Ability to identify a column as HTML.** Why? I want to spider some stuff and drop sections into SQLite, and just keep them as HTML.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/153/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 276873891, "node_id": "MDU6SXNzdWUyNzY4NzM4OTE=", "number": 154, "title": "Datasette CSS should include content hash in the URL", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 3, "created_at": "2017-11-27T00:57:36Z", "updated_at": "2017-12-09T03:10:23Z", "closed_at": "2017-12-09T03:10:22Z", "author_association": "OWNER", "pull_request": null, "body": "When I deployed the latest version of datasette to https://fivethirtyeight.datasettes.com/ I noticed I was getting served stale CSS since it had been cached. Including the sha of he contents in its URL should fix that.\r\n\r\nI can calculate this on server start.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/154/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 277589569, "node_id": "MDU6SXNzdWUyNzc1ODk1Njk=", "number": 155, "title": "A primary key column that has foreign key restriction associated won't rendering label column", "user": {"value": 388154, "label": "wsxiaoys"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 4, "created_at": "2017-11-29T00:40:02Z", "updated_at": "2017-12-07T05:39:53Z", "closed_at": "2017-12-07T05:39:53Z", "author_association": "NONE", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/155/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278189708, "node_id": "MDU6SXNzdWUyNzgxODk3MDg=", "number": 156, "title": "Document CSS hooks and custom templates", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-11-30T16:43:15Z", "updated_at": "2017-11-30T17:11:34Z", "closed_at": "2017-11-30T17:10:58Z", "author_association": "OWNER", "pull_request": null, "body": "Documentation currently lives in commit messages on https://github.com/simonw/datasette/commit/8ab3a169d42d096f2c7979c6d3d7746618d30f0b and 3cd06729f457d690603b6060dc552b535517ab09", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/156/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278190321, "node_id": "MDU6SXNzdWUyNzgxOTAzMjE=", "number": 157, "title": "Teach \"datasette publish\" about custom template directories", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-11-30T16:44:57Z", "updated_at": "2020-01-15T16:05:13Z", "closed_at": "2017-12-09T18:28:54Z", "author_association": "OWNER", "pull_request": null, "body": "The following command should copy the custom templates into the deployment and ensure `datasette serve` correctly serves them:\r\n\r\n datasette publish now mydb.db --template-dir=custom-templates/", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/157/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278190981, "node_id": "MDU6SXNzdWUyNzgxOTA5ODE=", "number": 158, "title": "Ensure default templates are designed to be extended", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-11-30T16:46:41Z", "updated_at": "2017-12-07T05:41:09Z", "closed_at": "2017-12-07T05:41:08Z", "author_association": "OWNER", "pull_request": null, "body": "Since custom templates can do `{% extends \"default:table.html\" %}` the default templates should include sensible named `{% block %}` components designed to support common extension patterns. Since we already support `{{ super() }}` we may not have much if anything to add here.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/158/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278191223, "node_id": "MDU6SXNzdWUyNzgxOTEyMjM=", "number": 159, "title": "Come up with an elegant mechanism for per-row template customization", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 0, "created_at": "2017-11-30T16:47:26Z", "updated_at": "2017-12-07T06:12:27Z", "closed_at": "2017-12-07T06:12:26Z", "author_association": "OWNER", "pull_request": null, "body": "It would be nice if customizing the display of an individual row in a custom table template was as simple as possible - refs #153 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/159/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278208011, "node_id": "MDU6SXNzdWUyNzgyMDgwMTE=", "number": 160, "title": "Ability to bundle and serve additional static files", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 8, "created_at": "2017-11-30T17:37:51Z", "updated_at": "2019-02-02T00:58:20Z", "closed_at": "2017-12-09T18:29:11Z", "author_association": "OWNER", "pull_request": null, "body": "Since we now have custom templates, we should support including custom static files with them as well. Maybe something like this:\r\n\r\n datasette mydb.db --template-dir=templates/ --static-dir=static/\r\n\r\nThis should also be supported by datasette publish - see also #157 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/160/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 278814220, "node_id": "MDU6SXNzdWUyNzg4MTQyMjA=", "number": 161, "title": "Support WITH query ", "user": {"value": 388154, "label": "wsxiaoys"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2017-12-03T20:00:40Z", "updated_at": "2017-12-08T06:18:12Z", "closed_at": "2017-12-04T04:52:41Z", "author_association": "NONE", "pull_request": null, "body": "Currently datasettle failed with error message: Statement must begin with SELECT\r\n\r\nExample query\r\n```sql\r\nWITH RECURSIVE\r\n cnt(x) AS (\r\n SELECT 1\r\n UNION ALL\r\n SELECT x+1 FROM cnt\r\n LIMIT 1000000\r\n )\r\nSELECT x FROM cnt;\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/161/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 279199916, "node_id": "MDU6SXNzdWUyNzkxOTk5MTY=", "number": 162, "title": "Link should not show up in the column selection dropdowns", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 0, "created_at": "2017-12-05T00:19:04Z", "updated_at": "2017-12-07T05:05:58Z", "closed_at": "2017-12-07T05:05:58Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. on https://san-francisco.datasettes.com/food-trucks-921342f/Applicant\r\n\r\n\"food-trucks__applicant__131_rows\"\r\n\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/162/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 279547886, "node_id": "MDU6SXNzdWUyNzk1NDc4ODY=", "number": 163, "title": "Document the querystring argument for setting a different time limit", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2017-12-05T22:05:08Z", "updated_at": "2021-03-23T02:44:33Z", "closed_at": "2017-12-06T15:06:57Z", "author_association": "OWNER", "pull_request": null, "body": "http://datasette.readthedocs.io/en/latest/sql_queries.html#query-limits\r\n\r\nNeed to explain why this is useful too.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/163/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280013907, "node_id": "MDU6SXNzdWUyODAwMTM5MDc=", "number": 164, "title": "datasette skeleton command for kick-starting database and table metadata", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 3, "created_at": "2017-12-07T06:13:28Z", "updated_at": "2021-03-23T02:45:12Z", "closed_at": "2017-12-07T06:20:45Z", "author_association": "OWNER", "pull_request": null, "body": "Generates an example `metadata.json` file populated with all of the databases and tables inspected from the specified databases.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/164/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280014287, "node_id": "MDU6SXNzdWUyODAwMTQyODc=", "number": 165, "title": "metadata.json support for per-database and per-table information", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 2, "created_at": "2017-12-07T06:15:34Z", "updated_at": "2017-12-07T16:48:34Z", "closed_at": "2017-12-07T16:47:29Z", "author_association": "OWNER", "pull_request": null, "body": "Every database and every table should be able to support the following optional metadata:\r\n\r\n\ttitle\r\n\tdescription\r\n\tdescription_html\r\n\tlicense\r\n\tlicense_url\r\n\tsource\r\n\tsource_url\r\n\r\nIf `description_html` is provided it over-rides `description` and will be displayed unescaped.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/165/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280023225, "node_id": "MDU6SXNzdWUyODAwMjMyMjU=", "number": 166, "title": "Documentation for metadata.json and datasette skeleton", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-12-07T07:02:52Z", "updated_at": "2017-12-07T17:20:35Z", "closed_at": "2017-12-07T17:20:25Z", "author_association": "OWNER", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/166/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280315352, "node_id": "MDU6SXNzdWUyODAzMTUzNTI=", "number": 167, "title": "Nasty bug: last column not being correctly displayed", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 6, "created_at": "2017-12-07T23:23:46Z", "updated_at": "2017-12-10T01:00:21Z", "closed_at": "2017-12-10T01:00:20Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. https://datasette-bwnojrhmmg.now.sh/dk3-bde9a9a/dk?source__contains=http\r\n\r\n![2017-12-07 at 3 22 pm](https://user-images.githubusercontent.com/9599/33743613-7ee97be0-db62-11e7-8e81-9b9ec69d93f0.png)\r\n\r\nThe JSON output shows that the column is there, but is being displayed incorrectly:\r\n\r\nhttps://datasette-bwnojrhmmg.now.sh/dk3-bde9a9a/dk.jsono?source__contains=http\r\n\r\n![2017-12-07 at 3 23 pm](https://user-images.githubusercontent.com/9599/33743645-9489b302-db62-11e7-898b-72e812e8855d.png)\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/167/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280662866, "node_id": "MDExOlB1bGxSZXF1ZXN0MTU3MzY1ODEx", "number": 168, "title": "Upgrade to Sanic 0.7.0", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-12-09T01:25:08Z", "updated_at": "2017-12-09T03:00:34Z", "closed_at": "2017-12-09T03:00:34Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/168", "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/168/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 280744309, "node_id": "MDU6SXNzdWUyODA3NDQzMDk=", "number": 169, "title": "Release v0.14 with templates and static files features", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-12-09T18:52:48Z", "updated_at": "2017-12-10T02:04:56Z", "closed_at": "2017-12-10T02:04:56Z", "author_association": "OWNER", "pull_request": null, "body": "Everything in this milestone https://github.com/simonw/datasette/milestone/6 - plus various other fixes: https://github.com/simonw/datasette/compare/0.13...6bdfcf60760c27e29ff34692d06e62b36aeecc56\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/169/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280745470, "node_id": "MDU6SXNzdWUyODA3NDU0NzA=", "number": 170, "title": "Custom template for named canned query", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 3, "created_at": "2017-12-09T19:07:51Z", "updated_at": "2017-12-09T21:35:30Z", "closed_at": "2017-12-09T21:34:52Z", "author_association": "OWNER", "pull_request": null, "body": "", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/170/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280745746, "node_id": "MDU6SXNzdWUyODA3NDU3NDY=", "number": 171, "title": "HTML comments specifying custom templates for page", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 2949431, "label": "Custom templates edition"}, "comments": 1, "created_at": "2017-12-09T19:11:13Z", "updated_at": "2017-12-09T21:50:50Z", "closed_at": "2017-12-09T21:48:03Z", "author_association": "OWNER", "pull_request": null, "body": " This would make the custom templating system self-documenting, and save people from having to figure out the right template names for customizing specific pages.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/171/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 280896290, "node_id": "MDU6SXNzdWUyODA4OTYyOTA=", "number": 172, "title": "Show size of .db file next to download link", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-12-11T05:12:46Z", "updated_at": "2019-02-06T05:09:06Z", "closed_at": "2019-02-06T05:00:36Z", "author_association": "OWNER", "pull_request": null, "body": "Size in bytes should be calculated by datasette inspect.\r\n\r\nTemplate should display it in KB or MB or GB", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/172/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 281197863, "node_id": "MDU6SXNzdWUyODExOTc4NjM=", "number": 174, "title": "License/Source in footer should inherit from top level", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-12-11T23:01:35Z", "updated_at": "2018-08-11T17:46:51Z", "closed_at": "2018-08-11T17:46:51Z", "author_association": "OWNER", "pull_request": null, "body": "The footer on https://vice-police-shootings.now.sh/vice-bc7c892/ViceNews_FullOISData does not show license and source information... but that Datasette has that information, it's just defined at the top level: https://vice-police-shootings.now.sh/\r\n\r\nThe footer for a row/table page should fall back on information for the database, and if there is none for the database it should fall back on the top-level metadata instead.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/174/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 282971961, "node_id": "MDU6SXNzdWUyODI5NzE5NjE=", "number": 175, "title": "Add project topic \"automatic-api\"", "user": {"value": 3179832, "label": "dbohdan"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2017-12-18T18:09:17Z", "updated_at": "2017-12-21T18:33:55Z", "closed_at": "2017-12-21T18:33:55Z", "author_association": "NONE", "pull_request": null, "body": "Hi there! Could you add the ~~tag~~ topic `automatic-api` to your repository? I am [making a list](https://github.com/dbohdan/automatic-api) of all projects that automatically expose APIs to databases. (Your Show HN made me do it. :-) I knew about PostgREST and PostGraphQL, but it took adding Datasette to sell me on the concept.) They will be easier to discover if there is a standard GitHub tag, and `automatic-api` seems as good a candidate as any. Two projects [already use it](https://github.com/topics/automatic-api).", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/175/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 286938589, "node_id": "MDU6SXNzdWUyODY5Mzg1ODk=", "number": 177, "title": "Publishing to Heroku - metadata file not uploaded?", "user": {"value": 82988, "label": "psychemedia"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-01-09T01:04:31Z", "updated_at": "2018-01-25T16:45:32Z", "closed_at": "2018-01-25T16:45:32Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "Trying to run *datasette* (version 0.14) on Heroku with a `metadata.json` doesn't seem to be picking up the `metadata.json` file? \r\n\r\nOn a Mac with dodgy `tar` support:\r\n\r\n```\r\n \u25b8 Couldn't detect GNU tar. Builds could fail due to decompression errors\r\n \u25b8 See\r\n \u25b8 https://devcenter.heroku.com/articles/platform-api-deploying-slugs#create-slug-archive\r\n \u25b8 Please install it, or specify the '--tar' option\r\n \u25b8 Falling back to node's built-in compressor\r\n```\r\n\r\nCould that be causing the issue?\r\n\r\nAlso, I'm not seeing custom query links anywhere obvious when I run the metadata file with a local *datasette* server?\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/177/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 287240246, "node_id": "MDExOlB1bGxSZXF1ZXN0MTYxOTgyNzEx", "number": 178, "title": "If metadata exists, add it to heroku launch command", "user": {"value": 82988, "label": "psychemedia"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2018-01-09T21:42:21Z", "updated_at": "2018-01-15T09:42:46Z", "closed_at": "2018-01-14T21:05:16Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/178", "body": "The heroku build does seem to make use of any provided `metadata.json` file.\r\n\r\nAdd the `--metadata` switch to the Heroku web launch command if a `metadata.json` file is available.\r\n\r\nAddresses: https://github.com/simonw/datasette/issues/177", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/178/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 289375133, "node_id": "MDExOlB1bGxSZXF1ZXN0MTYzNTIzOTc2", "number": 180, "title": "make html title more readable in query template", "user": {"value": 56477, "label": "ryanpitts"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-01-17T18:56:03Z", "updated_at": "2018-04-03T16:03:38Z", "closed_at": "2018-04-03T15:24:05Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/180", "body": "tiny tweak to make this easier to visually parse\u2014I think it matches your style in other templates", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/180/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 289425975, "node_id": "MDExOlB1bGxSZXF1ZXN0MTYzNTYxODMw", "number": 181, "title": "add \"format sql\" button to query page, uses sql-formatter", "user": {"value": 1957344, "label": "bsmithgall"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2018-01-17T21:50:04Z", "updated_at": "2019-11-11T03:08:25Z", "closed_at": "2019-11-11T03:08:25Z", "author_association": "NONE", "pull_request": "simonw/datasette/pulls/181", "body": "Cool project!\r\n\r\nThis fixes #136 using the suggested [sql formatter](https://github.com/zeroturnaround/sql-formatter) library. I included the minified version in the bundle and added the relevant scripts to the codemirror includes instead of adding new files, though I could also add new files. I wanted to keep it all together, since the result of the format needs access to the editor in order to properly update the codemirror instance.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/181/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 291451116, "node_id": "MDExOlB1bGxSZXF1ZXN0MTY1MDI5ODA3", "number": 182, "title": "Add db filesize next to download link", "user": {"value": 3433657, "label": "raynae"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-01-25T04:58:56Z", "updated_at": "2019-03-22T13:50:57Z", "closed_at": "2019-02-06T04:59:38Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/182", "body": "Took a stab at #172, will this do the trick?", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/182/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 291639118, "node_id": "MDU6SXNzdWUyOTE2MzkxMTg=", "number": 183, "title": "Custom Queries - escaping strings", "user": {"value": 82988, "label": "psychemedia"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2018-01-25T16:49:13Z", "updated_at": "2019-06-24T06:45:07Z", "closed_at": "2019-06-24T06:45:07Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "If a SQLite table column name contains spaces, they are usually referred to in double quotes:\r\n\r\n`SELECT * FROM mytable WHERE \"gappy column name\"=\"my value\";`\r\n\r\nIn the JSON metadata file, this is passed by escaping the double quotes:\r\n\r\n`\"queries\": {\"my query\": \"SELECT * FROM mytable WHERE \\\"gappy column name\\\"=\\\"my value\\\";\"}`\r\n\r\nWhen specifying a custom query in `metadata.json` using double quotes, these are then rendered in the *datasette* query box using single quotes:\r\n\r\n`SELECT * FROM mytable WHERE 'gappy column name'='my value';`\r\n\r\nwhich does not work.\r\n\r\nAlternatively, a valid custom query can be passed using backticks (\\`) to quote the column name and single (unescaped) quotes for the matched value:\r\n\r\n``\"queries\": {\"my query\": \"SELECT * FROM mytable WHERE `gappy column name`='my value';\"}``\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/183/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 292011379, "node_id": "MDU6SXNzdWUyOTIwMTEzNzk=", "number": 184, "title": "500 from missing table name", "user": {"value": 222245, "label": "carlmjohnson"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2018-01-26T19:46:45Z", "updated_at": "2019-05-21T16:17:29Z", "closed_at": "2018-04-13T18:18:59Z", "author_association": "NONE", "pull_request": null, "body": "https://github.com/simonw/datasette/blob/56623e48da5412b25fb39cc26b9c743b684dd968/datasette/app.py#L517-L519 throws an error if it gets an empty list back. Simplest solution is to write a helper func that just says \r\n\r\n```python\r\nresult = list(await self.execute(name, sql, params)\r\nif result:\r\n return result[0][0]\r\n```\r\n\r\nand use it anywhere `[0][0]` is now.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/184/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 306811513, "node_id": "MDU6SXNzdWUzMDY4MTE1MTM=", "number": 186, "title": "proposal new option to disable user agents cache", "user": {"value": 47107, "label": "stefanocudini"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2018-03-20T10:42:20Z", "updated_at": "2018-03-21T09:07:22Z", "closed_at": "2018-03-21T01:28:31Z", "author_association": "NONE", "pull_request": null, "body": "I think it would be very useful for debugging an option of adding headers to http replies\r\n\r\n```\r\nCache-Control: no-cache \r\n```\r\n\r\nespecially in the html output", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/186/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 309033998, "node_id": "MDU6SXNzdWUzMDkwMzM5OTg=", "number": 187, "title": "Windows installation error", "user": {"value": 11855322, "label": "robmarkcole"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2018-03-27T16:04:37Z", "updated_at": "2019-06-15T21:44:23Z", "closed_at": "2019-06-15T21:44:23Z", "author_association": "NONE", "pull_request": null, "body": "On attempting install on a Win 7 PC with py 3.6.2 (Anaconda dist) I get the error:\r\n\r\n```\r\nCollecting uvloop>=0.5.3 (from Sanic==0.7.0->datasette)\r\n Downloading uvloop-0.9.1.tar.gz (1.8MB)\r\n 100% |\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6| 1.8MB 12.8MB/s\r\n Complete output from command python setup.py egg_info:\r\n Traceback (most recent call last):\r\n File \"\", line 1, in \r\n File \"C:\\Users\\RCole\\AppData\\Local\\Temp\\pip-build-juakfqt8\\uvloop\\setup.py\r\n\", line 10, in \r\n raise RuntimeError('uvloop does not support Windows at the moment')\r\n RuntimeError: uvloop does not support Windows at the moment\r\n```\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/187/reactions\", \"total_count\": 4, \"+1\": 4, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 309471814, "node_id": "MDU6SXNzdWUzMDk0NzE4MTQ=", "number": 189, "title": "Ability to sort (and paginate) by column", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": {"value": 9599, "label": "simonw"}, "milestone": null, "comments": 31, "created_at": "2018-03-28T18:04:51Z", "updated_at": "2018-04-15T18:54:22Z", "closed_at": "2018-04-09T05:16:02Z", "author_association": "OWNER", "pull_request": null, "body": "As requested in https://github.com/simonw/datasette/issues/185#issuecomment-376614973\r\n\r\nI've previously avoided this for performance reasons: sort-by-column on a column without an index is likely to perform badly for hundreds of thousands of rows.\r\n\r\nThat's not a good enough reason to avoid the feature entirely though. A few options:\r\n\r\n* Allow sort-by-column by default, give users the option to disable it for specific tables/columns\r\n* Disallow sort-by-column by default, give users option (probably in `metadata.json`) to enable it for specific tables/columns\r\n* Automatically detect if a column either has an index on it OR a table has less than X rows in it\r\n\r\nWe already have the mechanism in place to cut off SQL queries that take more than X seconds, so if someone DOES try to sort by a column that's too expensive it won't actually hurt anything - but it would be nice to not show people a \"sort\" option which is guaranteed to throw a timeout error.\r\n\r\nThe vast majority of datasette usage that I've seen so far is on smaller datasets where the performance penalties of sort-by-column are extremely unlikely to show up.\r\n\r\n----\r\n\r\nStill left to do:\r\n\r\n- [x] UI that shows which sort order is currently being applied (in HTML and in JSON)\r\n- [x] UI for applying a sort order (with rel=nofollow to avoid Google crawling it)\r\n- [x] Sort column names should be escaped correctly in generated SQL\r\n- [x] Validation that the selected sort order is a valid column\r\n- [x] Throw error if user attempts to apply _sort AND _sort_desc at the same time\r\n- [x] Ability to disable sorting (or sort only for specific columns) in metadata.json\r\n- [x] Fix \"201 rows where sorted by sortable_with_nulls \" bug\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/189/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 309558826, "node_id": "MDU6SXNzdWUzMDk1NTg4MjY=", "number": 190, "title": "Keyset pagination doesn't work correctly for compound primary keys", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2018-03-28T22:45:06Z", "updated_at": "2018-03-30T06:31:15Z", "closed_at": "2018-03-30T06:26:28Z", "author_association": "OWNER", "pull_request": null, "body": "Consider https://datasette-issue-190-compound-pks.now.sh/compound-pks-9aafe8f/compound_primary_key\r\n\r\n![2018-03-28 at 3 47 pm](https://user-images.githubusercontent.com/9599/38060388-56da86dc-329f-11e8-9f20-5576153ad55c.png)\r\n\r\nThe next= link is to `d,v`:\r\n\r\nhttps://datasette-issue-190-compound-pks.now.sh/compound-pks-9aafe8f/compound_primary_key?_next=d%2Cv\r\n\r\nBut that page starts with:\r\n\r\n![2018-03-28 at 3 48 pm](https://user-images.githubusercontent.com/9599/38060402-6b0f5984-329f-11e8-85b8-44a666c4ee71.png)\r\n\r\nThe next key in the sequence should be `d,w`. Also we should return the full a-z of the ones that start with the letter e - in this example we only return `e-w`, `e-x`, `e-y` and `e-z`", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/190/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 310533258, "node_id": "MDU6SXNzdWUzMTA1MzMyNTg=", "number": 191, "title": "Figure out how to bundle a more up-to-date SQLite", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2018-04-02T16:33:25Z", "updated_at": "2018-07-10T17:46:13Z", "closed_at": "2018-07-10T17:46:13Z", "author_association": "OWNER", "pull_request": null, "body": "The version of SQLite that ships with Python 3 is a bit limited - it doesn't support row values for example https://www.sqlite.org/rowvalue.html\r\n\r\nFigure out how to bundle a more recent SQLite engine with datasette. We need to figure out two cases:\r\n\r\n* Bundling a recent version in a Dockerfile build. I expect this to be quite easy.\r\n* Making a more recent version available to people hacking around in Mac OS X. I have no idea how to start on this.\r\n\r\nI want it working on Mac OS X too because I don't want to force Docker as a dependency for anyone who just want to hack around with Datasette a little and run the test suite.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/191/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 310850458, "node_id": "MDExOlB1bGxSZXF1ZXN0MTc5MTA4OTYx", "number": 192, "title": "New ?_shape=objects/object/lists param for JSON API", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-03T14:02:58Z", "updated_at": "2018-04-03T14:53:00Z", "closed_at": "2018-04-03T14:52:55Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/192", "body": "Refs #122", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/192/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 310882100, "node_id": "MDU6SXNzdWUzMTA4ODIxMDA=", "number": 193, "title": "Cleaner mechanism for handling custom errors", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2018-04-03T15:19:13Z", "updated_at": "2018-04-13T18:18:59Z", "closed_at": "2018-04-13T18:18:59Z", "author_association": "OWNER", "pull_request": null, "body": "This code is pretty messy:\r\n\r\nhttps://github.com/simonw/datasette/blob/0abd3abacb309a2bd5913a7a2df4e9256585b1bb/datasette/app.py#L245-L265\r\n\r\nInstead, it would be nice if I could raise an exception that would be converted into the appropriate JSON or HTML error message, with a corresponding HTTP code.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/193/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 312312125, "node_id": "MDU6SXNzdWUzMTIzMTIxMjU=", "number": 194, "title": "Rename table_rows and filtered_table_rows to have _count suffix", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2018-04-08T14:53:37Z", "updated_at": "2018-04-09T05:25:22Z", "closed_at": "2018-04-09T05:25:22Z", "author_association": "OWNER", "pull_request": null, "body": "These fields represent counts of items:\r\n\r\n \"table_rows\": 131,\r\n \"filtered_table_rows\": 8,\r\n\r\nBut the names make it sound like they might be arrays full of rows. Adding a `_count` suffix would make this more clear:\r\n\r\n \"table_rows_count\": 131,\r\n \"filtered_table_rows_count\": 8,\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/194/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 312313496, "node_id": "MDU6SXNzdWUzMTIzMTM0OTY=", "number": 195, "title": "Run pks_for_table in inspect, executing once at build time rather than constantly", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2018-04-08T15:12:40Z", "updated_at": "2018-04-10T00:54:43Z", "closed_at": "2018-04-10T00:54:43Z", "author_association": "OWNER", "pull_request": null, "body": "Right now several Datasette views call the `await self.pks_for_table(...)` method to figure out what primary keys are set for a specific table. This executes a `PRAGMA table_info` SQL query.\r\n\r\nIt would be faster and more efficient to execute this query for each table as part of the `inspect()` method.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/195/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 312355154, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgwMTg4Mzk3", "number": 196, "title": "_sort= and _sort_desc= parameters to table view", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-09T00:07:21Z", "updated_at": "2018-04-09T05:10:29Z", "closed_at": "2018-04-09T05:10:23Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/196", "body": "See #189 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/196/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 312620566, "node_id": "MDU6SXNzdWUzMTI2MjA1NjY=", "number": 199, "title": "Ability to apply sort on mobile in portrait mode", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2018-04-09T17:35:04Z", "updated_at": "2018-04-10T00:37:53Z", "closed_at": "2018-04-10T00:34:38Z", "author_association": "OWNER", "pull_request": null, "body": "Missed this in #189... on mobile in portrait mode we hide the column headers, which means you can't click them to sort! You can sort in landscape mode at least.\r\n\r\nNeed to come up with an alternative sort UI for portrait on mobile.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/199/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 313494458, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxMDMzMDI0", "number": 200, "title": "Hide Spatialite system tables", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2018-04-11T21:26:58Z", "updated_at": "2018-04-12T21:34:48Z", "closed_at": "2018-04-12T21:34:48Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/200", "body": "They were getting on my nerves.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/200/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 313512748, "node_id": "MDU6SXNzdWUzMTM1MTI3NDg=", "number": 201, "title": "Support explain select / explain query plan select", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2018-04-11T22:41:26Z", "updated_at": "2018-04-13T21:17:14Z", "closed_at": "2018-04-12T21:32:52Z", "author_association": "OWNER", "pull_request": null, "body": "See https://www.sqlite.org/eqp.html and https://www.sqlite.org/lang_explain.html", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/201/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 313785206, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxMjQ3NTY4", "number": 202, "title": "Raise 404 on nonexistent table URLs", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2018-04-12T15:47:06Z", "updated_at": "2018-04-13T19:22:56Z", "closed_at": "2018-04-13T18:19:15Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/202", "body": "Currently they just 500. Also cleaned the logic up a bit, I hope I didn't miss anything.\r\n\r\nThis is issue #184.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/202/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 313837303, "node_id": "MDU6SXNzdWUzMTM4MzczMDM=", "number": 203, "title": "Support for units", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 10, "created_at": "2018-04-12T18:24:28Z", "updated_at": "2018-04-16T21:59:17Z", "closed_at": "2018-04-16T21:59:17Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "It would be nice to be able to attach a unit to a column in the metadata, and have it rendered with that unit (and SI prefix) when it's displayed.\r\n\r\nIt would also be nice to support entering the prefixes in variables when querying.\r\n\r\nWith my radio licensing app I've put all frequencies in Hz. It's easy enough to special-case the row rendering to add the SI prefixes, but it's pretty unusable when querying by that field.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/203/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 314256802, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNjAwOTI2", "number": 204, "title": "Initial units support", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-13T21:32:49Z", "updated_at": "2018-04-14T09:44:33Z", "closed_at": "2018-04-14T03:32:54Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/204", "body": "Add support for specifying units for a column in metadata.json and rendering them on display using [pint](https://pint.readthedocs.io/en/latest/).\r\n\r\nExample table metadata:\r\n```json\r\n \"license_frequency\": {\r\n \"units\": {\r\n \"frequency\": \"Hz\",\r\n \"channel_width\": \"Hz\",\r\n \"height\": \"m\",\r\n \"antenna_height\": \"m\",\r\n \"azimuth\": \"degrees\"\r\n }\r\n }\r\n```\r\n\r\n[Example result](https://wtr-api.herokuapp.com/wtr-663ea99/license_frequency/1)\r\n\r\nThis works surprisingly well! I'd like to add support for using units when querying but this is PR is pretty usable as-is.\r\n\r\n(Pint doesn't seem to support decibels though - it thinks they're decibytes - which is an annoying omission.)\r\n\r\n(ref ticket #203)", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/204/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314319372, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNjQyMTE0", "number": 205, "title": "Support filtering with units and more", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2018-04-14T10:47:51Z", "updated_at": "2018-04-14T15:24:04Z", "closed_at": "2018-04-14T15:24:04Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/205", "body": "The first commit:\r\n* Adds units to exported JSON\r\n* Adds units key to metadata skeleton\r\n* Adds some docs for units\r\n\r\nThe second commit adds filtering by units by the first method I mentioned in #203:\r\n![image](https://user-images.githubusercontent.com/45057/38767463-7193be16-3fd9-11e8-8a5f-ac4159415c6d.png)\r\n\r\n[Try it here](https://wtr-api.herokuapp.com/wtr-663ea99/license_frequency?frequency__gt=50GHz&height__lt=50ft). I think it integrates pretty neatly.\r\n\r\nThe third commit adds support for registering custom units with Pint from metadata.json. Probably pretty niche, but I need decibels!", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/205/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314323977, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNjQ0ODA1", "number": 206, "title": "Fix sqlite error when loading rows with no incoming FKs", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-14T12:08:17Z", "updated_at": "2018-04-14T14:32:42Z", "closed_at": "2018-04-14T14:24:25Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/206", "body": "This fixes `ERROR: conn=, sql\r\n= 'select ', params = {'id': '1'}` caused by an invalid query loading incoming FKs when none exist.\r\n\r\nThe error was ignored due to async but it still got printed to the console.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/206/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314329002, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNjQ3NzE3", "number": 207, "title": "Link foreign keys which don't have labels", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2018-04-14T13:27:14Z", "updated_at": "2018-04-14T15:00:00Z", "closed_at": "2018-04-14T15:00:00Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/207", "body": "This renders unlabeled FKs as simple links. I can't see why this would cause any major problems.\r\n\r\n![image](https://user-images.githubusercontent.com/45057/38768722-ea15a000-3fef-11e8-8664-ffd7aa4894ea.png)\r\n\r\nAlso includes bonus fixes for two minor issues:\r\n\r\n* In foreign key link hrefs the primary key was escaped using HTML escaping rather than URL escaping. This broke some non-integer PKs.\r\n* Print tracebacks to console when handling 500 errors.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/207/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314340944, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNjU0ODM5", "number": 208, "title": "Return HTTP 405 on InvalidUsage rather than 500", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-14T16:12:50Z", "updated_at": "2018-04-14T18:00:39Z", "closed_at": "2018-04-14T18:00:39Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/208", "body": "This also stops it filling up the logs. This happens for HEAD requests at the moment - which perhaps should be handled better, but that's a different issue.", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/208/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314455877, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNzIzMzAz", "number": 209, "title": " Don't duplicate simple primary keys in the link column", "user": {"value": 45057, "label": "russss"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2018-04-15T21:56:15Z", "updated_at": "2018-04-18T08:40:37Z", "closed_at": "2018-04-18T01:13:04Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/209", "body": "When there's a simple (single-column) primary key, it looks weird to duplicate it in the link column.\r\n\r\nThis change removes the second PK column and treats the link column as if it were the PK column from a header/sorting perspective. \r\n\r\nThis might make it a bit more difficult to tell what the link for the row is, I'm not sure yet. I feel like the alternative is to change the link column to just have the text \"view\" or something, instead of repeating the PK. (I doubt it makes much more sense with compound PKs.)\r\n\r\nBonus change in this PR: fix urlencoding of links in the displayed HTML.\r\n\r\nBefore:\r\n![image](https://user-images.githubusercontent.com/45057/38783830-e2ababb4-40ff-11e8-97fb-25e286a8c920.png)\r\n\r\nAfter:\r\n![image](https://user-images.githubusercontent.com/45057/38783835-ebf6b48e-40ff-11e8-8c47-6a864cf21ccc.png)", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/209/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314469126, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNzMxOTU2", "number": 210, "title": "Start of the plugin system, based on pluggy", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-16T00:51:30Z", "updated_at": "2018-04-16T00:56:16Z", "closed_at": "2018-04-16T00:56:16Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/210", "body": "Refs #14", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/210/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314471743, "node_id": "MDU6SXNzdWUzMTQ0NzE3NDM=", "number": 211, "title": "Load plugins from a `--plugins-dir=plugins/` directory", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2018-04-16T01:17:43Z", "updated_at": "2018-04-16T05:22:02Z", "closed_at": "2018-04-16T05:22:02Z", "author_association": "OWNER", "pull_request": null, "body": "In #14 and 33c7c53ff87c2 I've added working support for setuptools entry_points plugins. These can be installed from PyPI using `pip install ...`.\r\n\r\nI imagine some projects will benefit from being able to add plugins without first publishing them to PyPI. Datasette already supports [loading custom templates](http://datasette.readthedocs.io/en/latest/custom_templates.html#custom-templates) like so:\r\n\r\n datasette serve --template-dir=mytemplates/ mydb.db\r\n\r\nI propose an additional option, `--plugins-dir=` which specifies a directory full of `blah.py` files which will be loaded into Datasette when the application server starts.\r\n\r\n datasette serve --plugins-dir=myplugins/ mydb.db\r\n\r\nThis will also need to be supported by `datasette publish` as those Python files should be copied up as part of the deployment.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/211/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 314504812, "node_id": "MDExOlB1bGxSZXF1ZXN0MTgxNzU1MjIw", "number": 212, "title": "New --plugins-dir=plugins/ option", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-16T05:19:28Z", "updated_at": "2018-04-16T05:22:18Z", "closed_at": "2018-04-16T05:22:01Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/212", "body": "Refs #211", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/212/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 314506033, "node_id": "MDU6SXNzdWUzMTQ1MDYwMzM=", "number": 213, "title": "Documentation for plugins system", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-04-16T05:27:07Z", "updated_at": "2018-04-16T15:12:48Z", "closed_at": "2018-04-16T15:12:48Z", "author_association": "OWNER", "pull_request": null, "body": "Documentation for #14 - how to write plugins, how to ship plugins to PyPI and how to use the `--plugins-dir` option added in #211 ", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/213/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 314506446, "node_id": "MDU6SXNzdWUzMTQ1MDY0NDY=", "number": 214, "title": "Ability for plugins to define extra JavaScript and CSS", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2018-04-16T05:29:34Z", "updated_at": "2020-09-30T20:36:11Z", "closed_at": "2018-04-18T03:13:03Z", "author_association": "OWNER", "pull_request": null, "body": "This can hook in to the existing `extra_css_urls` and `extra_js_urls` mechanism:\r\n\r\nhttps://github.com/simonw/datasette/blob/b2955d9065ea019500c7d072bcd9d49d1967f051/datasette/app.py#L304-L305\r\n\r\nThe plugins should be able to bundle their own assets though, so it will also have to integrate with the `/static/` static mounts mechanism somehow:\r\n\r\nhttps://github.com/simonw/datasette/blob/b2955d9065ea019500c7d072bcd9d49d1967f051/datasette/app.py#L1255-L1257\r\n\r\nRefs #14", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/214/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 314506669, "node_id": "MDU6SXNzdWUzMTQ1MDY2Njk=", "number": 215, "title": "Allow plugins to define additional URL routes and views", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 5512395, "label": "Datasette 0.44"}, "comments": 14, "created_at": "2018-04-16T05:31:09Z", "updated_at": "2020-06-09T03:14:32Z", "closed_at": "2020-06-09T03:12:08Z", "author_association": "OWNER", "pull_request": null, "body": "Might be as simple as having plugins get passed the `app` after the other routes have been defined:\r\n\r\nhttps://github.com/simonw/datasette/blob/b2955d9065ea019500c7d072bcd9d49d1967f051/datasette/app.py#L1270-L1274\r\n\r\nRefs #14", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/215/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}