From 18b2061cff1b137ed0740fe784375ceb9e13c796 Mon Sep 17 00:00:00 2001 From: Natalie Downe Date: Thu, 27 Aug 2020 14:59:34 -0700 Subject: [PATCH 01/12] New header and footer --- datasette/static/app.css | 561 ++++++++++++++++++++++-------- datasette/templates/patterns.html | 238 +++++++++++-- 2 files changed, 615 insertions(+), 184 deletions(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index bef27ac7..87ec5f01 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -1,3 +1,64 @@ +/* Reset and Page Setup ==================================================== */ + +/* Reset from http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +th { + padding-right: 1em; + white-space: nowrap; +} + +/* end reset */ + + body { margin: 0; padding: 0; @@ -5,12 +66,279 @@ body { font-size: 1rem; font-weight: 400; line-height: 1.5; - color: #212529; + color: #111A35; text-align: left; - background-color: #fff; + background-color: #fefdf4; } -.bd { - margin: 0 1em; + +/* Helper Styles ===========================================================*/ + +.intro { + font-size: 1rem; +} +p { + margin: 0 0 0.75rem 0; + padding: 0; +} +.meta { + color: rgba(0,0,0,0.3); + font-size: 0.75rem +} +.intro { + font-size: 1.5rem; + margin-bottom: 0.75rem; +} +.context-text { + /* for accessibility and hiden from sight */ + text-indent: -999em; + display: block; + width:0; + overflow: hidden; + margin: 0; + padding: 0; + line-height: 0; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.header1, +.header2, +.header3, +.header4, +.header5, +.header6 { + font-weight: 700; + font-size: 1rem; + margin: 0; + padding: 0 +} +h1, +.header1 { + font-size: 2rem; + margin-bottom: 0.75rem; + margin-top: 1rem; +} +h2, +.header2 { + font-size: 1.5rem; + margin-bottom: 0.75rem; + margin-top: 1rem; +} +h3, +.header3 { + font-size: 1.25rem; + margin: 1rem 0 0.25rem 0; +} +h4, +.header4 { + margin: 1rem 0 0.25rem 0; + font-weight: 400; + text-decoration: underline; +} +h5, +.header5 { + margin: 1rem 0 0.25rem 0; + font-weight: 700; + text-decoration: underline; +} +h6, +.header6 { + margin: 1rem 0 0.25rem 0; + font-weight: 400; + font-style: italic; + text-decoration: underline; +} + +div, +section, +article, +header, +nav, +footer, +.wrapper { + display: block; + box-sizing: border-box; +} + +a:link, +a:visited { + color: #276890; + text-decoration: underline; +} +a:hover, +a:focus, +a:active { + color: #67C98D; + text-decoration: underline; +} + +button.button-as-link { + background: none; + border: none; + padding: 0; + color: #276890; + text-decoration: underline; + cursor: pointer; + font-size: 1rem; +} +button.button-as-link:hover, +button.button-as-link:focus { + color: #67C98D; +} + +a img { + display: block; + max-width: 100%; + border: 0; +} + +code, +pre { + font-family: monospace; +} + +ul.bullets, +ul.spaced, +ol.spaced { + margin-bottom: 0.8rem; +} +ul.bullets { + padding-left: 0.9rem; +} +ul.bullets li, +ul.spaced li, +ol.spaced li { + margin-bottom: 0.4rem; +} +ul.bullets li { + list-style-type: circle; +} +a.not-underlined { + text-decoration: none; +} +.not-underlined .underlined { + text-decoration: underline; +} + +/* Page Furniture ========================================================= */ +/* Header */ +header, +footer { + padding: 0.6rem 1rem 0.5rem 1rem; + background-color: #276890; + color: rgba(255,255,244,0.9); + overflow: hidden; + box-sizing: border-box; + min-height: 2.6rem; +} +header p, +footer p { + margin: 0; + padding: 0; +} +header .crumbs { + float: left; +} +header .logout { + float: right; + text-align: right; + padding-left: 1rem; +} +header .logout form { + display: inline; +} + +footer a:link, +footer a:visited, +footer a:hover, +footer a:focus, +footer a:active, +footer button.button-as-link, +header a:link, +header a:visited, +header a:hover, +header a:focus, +header a:active, +header button.button-as-link { + color: rgba(255,255,244,0.8); +} + +footer a:hover, +footer a:focus, +footer a:active, +footer.button-as-link:hover, +footer.button-as-link:focus, +header a:hover, +header a:focus, +header a:active, +button.button-as-link:hover, +button.button-as-link:focus { + color: rgba(255,255,244,1); +} + + +/* Body */ +section.content { + margin: 0 1rem; +} + +/* Footer */ + + + +/* Components ============================================================== */ + + +h2 em { + font-style: normal; + font-weight: lighter; +} + +/* Messages */ + +.message-info, +.message-warning, +.message-error { + padding: 1rem; + margin-bottom: 1rem; + background-color: rgba(103,201,141,0.3); +} +.message-warning { + background-color: rgba(245,166,35,0.3); +} +.message-error { + background-color: rgba(208,2,27,0.3); +} + +.pattern-heading { + padding: 1rem; + margin-top: 2rem; + border-top: 1px solid rgba(208,2,27,0.8); + border-bottom: 1px solid rgba(208,2,27,0.8); + background-color: rgba(208,2,27,0.2) +} + +/* URL arguments */ +.extra-wheres ul, +.extra-wheres li { + list-style-type: none; + padding: 0; + margin: 0; +} + +.wrapped-sql { + white-space: pre-wrap; + margin: 1rem 0; + font-family: monospace; +} + +/* Tables ================================================================== */ +.table-wrapper { + overflow-x: auto; } table { border-collapse: collapse; @@ -32,7 +360,6 @@ td em { } th { padding-right: 1em; - white-space: nowrap; } table a:link { text-decoration: none; @@ -41,91 +368,15 @@ table a:link { table a:visited { color: #8f54c4; } -.table-wrapper { - overflow-x: auto; -} -.small-screen-only, -.select-wrapper.small-screen-only { - display: none; -} -@media only screen and (max-width: 576px) { - .small-screen-only { - display: initial; - } - /* Force table to not be like tables anymore */ - table.rows-and-columns, - .rows-and-columns thead, - .rows-and-columns tbody, - .rows-and-columns th, - .rows-and-columns td, - .rows-and-columns tr { - display: block; - } - - /* Hide table headers (but not display: none;, for accessibility) */ - .rows-and-columns thead tr { - position: absolute; - top: -9999px; - left: -9999px; - } - - .rows-and-columns tr { - border: 1px solid #ccc; - margin-bottom: 1em; - } - - .rows-and-columns td { - /* Behave like a "row" */ - border: none; - border-bottom: 1px solid #eee; - padding: 0; - padding-left: 10%; - } - - .rows-and-columns td:before { - display: block; - color: black; - margin-left: -10%; - font-size: 0.8em; - } - a.blob-download { - display: inline-block; - } -} - -.hd { - border-bottom: 2px solid #ccc; - padding: 0.2em 1em; - background-color: #eee; - overflow: hidden; - box-sizing: border-box; - min-height: 2rem; -} -.hd p { - margin: 0; - padding: 0; -} -.hd .crumbs { - float: left; -} -.hd .logout { - float: right; - text-align: right; - padding-left: 1em; -} -.hd .logout form { - display: inline; -} -.ft { - margin: 1em 0; - padding: 0.5em 1em 0 1em; - border-top: 1px solid #ccc; +.rows-and-columns td:before { + display: block; + color: black; + margin-left: -10%; font-size: 0.8em; } -.hd :link { - text-decoration: none; +a.blob-download { + display: inline-block; } - .db-table p { margin-top: 0; margin-bottom: 0.3em; @@ -135,15 +386,10 @@ table a:visited { margin-bottom: 0; } -h2 em { - font-style: normal; - font-weight: lighter; -} -.extra-wheres ul, .extra-wheres li { - list-style-type: none; - padding: 0; - margin: 0; -} + +/* Forms =================================================================== */ + + form.sql textarea { border: 1px solid #ccc; width: 70%; @@ -189,11 +435,7 @@ input[type="search"]::-webkit-search-results-button, input[type="search"]::-webkit-search-results-decoration { display: none; } -@media only screen and (max-width: 576px) { - form.sql textarea { - width: 95%; - } -} + form input[type=submit], form button[type=button] { font-weight: 400; cursor: pointer; @@ -292,27 +534,9 @@ form button[type=button] { font-size: 1em; font-family: Helvetica, sans-serif; } -@media only screen and (max-width: 576px) { - .select-wrapper.small-screen-only { - display: inline-block; - } - .select-wrapper { - width: 100px; - } - .select-wrapper.filter-op { - width: 60px; - } - .filters input.filter-value { - width: 140px; - } -} -a.not-underlined { - text-decoration: none; -} -.not-underlined .underlined { - text-decoration: underline; -} + + .facet-results { display: flex; @@ -352,9 +576,7 @@ a.not-underlined { font-size: 0.8em; } -pre.wrapped-sql { - white-space: pre-wrap; -} + p.zero-results { border: 2px solid #ccc; @@ -368,30 +590,75 @@ p.zero-results { color: #666; } -.message-info { - padding: 1em; - border: 1px solid green; - background-color: #c7fbc7; -} -.message-warning { - padding: 1em; - border: 1px solid #ae7100; - background-color: #fbdda5; -} -.message-error { - padding: 1em; - border: 1px solid red; - background-color: pink; -} -button.button-as-link { - background: none; - border: none; - padding: 0; - color: blue; - text-decoration: none; - cursor: pointer; - font-size: 1em; + + + + +/* Overrides ===============================================================*/ + +.small-screen-only, +.select-wrapper.small-screen-only { + display: none; +} +@media only screen and (max-width: 576px) { + + .small-screen-only { + display: initial; + } + .select-wrapper.small-screen-only { + display: inline-block; + } + + form.sql textarea { + width: 95%; + } + /* Force table to not be like tables anymore */ + table.rows-and-columns, + .rows-and-columns thead, + .rows-and-columns tbody, + .rows-and-columns th, + .rows-and-columns td, + .rows-and-columns tr { + display: block; + } + + /* Hide table headers (but not display: none;, for accessibility) */ + .rows-and-columns thead tr { + position: absolute; + top: -9999px; + left: -9999px; + } + + .rows-and-columns tr { + border: 1px solid #ccc; + margin-bottom: 1em; + } + + .rows-and-columns td { + /* Behave like a "row" */ + border: none; + border-bottom: 1px solid #eee; + padding: 0; + padding-left: 10%; + } + + .rows-and-columns td:before { + display: block; + color: black; + margin-left: -10%; + font-size: 0.8em; + } + + .select-wrapper { + width: 100px; + } + .select-wrapper.filter-op { + width: 60px; + } + .filters input.filter-value { + width: 140px; + } } svg.dropdown-menu-icon { diff --git a/datasette/templates/patterns.html b/datasette/templates/patterns.html index 15c54709..ac9e2e46 100644 --- a/datasette/templates/patterns.html +++ b/datasette/templates/patterns.html @@ -5,35 +5,63 @@ - + - -
+ + +
+
+ +
+ + +
+ +
+ + + +

Pattern Portfolio

-
-

.hd for /database/table/row

- -

Messages

-
-

Example message

-

Example message

-

Example message

-
+ + + + + +

Header for /database/table/row and Messages

+ +
+ +
+ +

Example message

+

Example message

+

Example message

+ + + + + + + + + +

.bd for /

-
+

Datasette Fixtures

+
+ + + + + + +

.bd for /database

-
+

fixtures

-
+ + + + + + +

.bd for /database/table

-
+

roadside_attraction_characteristics

Data license: @@ -203,9 +244,109 @@

- -

View and edit SQL

- + + + +
+

2 extra where clauses

+ +
+ + +

View and edit SQL

+ + + +

+ Suggested facets: tags, created (date), tags (array) +

+ + + + + + +
+ +
+

+ tags (array) + + + +

+ +
+ +
+

+ created + + + +

+ +
+ +
+

+ city_id + + + +

+ +
+ +
+ @@ -266,9 +407,20 @@ attraction_id INTEGER REFERENCES roadside_attractions(pk), characteristic_id INTEGER REFERENCES attraction_characteristic(pk) ); - + + + + + + + + + + + +

.bd for /database/table/row

-
+

roadside_attractions: 2

This data as json

@@ -309,9 +461,21 @@ from attraction_id in roadside_attraction_characteristics - + + + + + + + + + + + +

.ft

-
Powered by Datasette + +
+ From ae9cffaf5bce2f0ee281b14272d3a534e69d2b1e Mon Sep 17 00:00:00 2001 From: Natalie Downe Date: Tue, 27 Oct 2020 11:39:35 -0700 Subject: [PATCH 02/12] Visited link colours --- datasette/static/app.css | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index 87ec5f01..1ad04618 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -164,11 +164,14 @@ footer, box-sizing: border-box; } -a:link, -a:visited { +a:link { color: #276890; text-decoration: underline; } +a:visited { + color: #54AC8E; + text-decoration: underline; +} a:hover, a:focus, a:active { @@ -363,10 +366,6 @@ th { } table a:link { text-decoration: none; - color: #445ac8; -} -table a:visited { - color: #8f54c4; } .rows-and-columns td:before { display: block; From 9f1c844e735e679c21e70f54fdd4c63868ac196b Mon Sep 17 00:00:00 2001 From: Natalie Downe Date: Tue, 27 Oct 2020 11:40:08 -0700 Subject: [PATCH 03/12] Implemented new Natalie design --- datasette/static/app.css | 7 +++++-- datasette/templates/base.html | 10 +++++----- datasette/templates/database.html | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index 1ad04618..dff882af 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -210,7 +210,7 @@ ol.spaced { margin-bottom: 0.8rem; } ul.bullets { - padding-left: 0.9rem; + padding-left: 1.25rem; } ul.bullets li, ul.spaced li, @@ -290,7 +290,9 @@ section.content { } /* Footer */ - +footer { + margin-top: 1rem; +} /* Components ============================================================== */ @@ -568,6 +570,7 @@ form button[type=button] { width: auto; display: inline-block; box-shadow: 1px 2px 8px 2px rgba(0,0,0,0.08); + background-color: white; } .download-sqlite em { diff --git a/datasette/templates/base.html b/datasette/templates/base.html index 84708325..03de2115 100644 --- a/datasette/templates/base.html +++ b/datasette/templates/base.html @@ -14,7 +14,7 @@ - -
+
{% block messages %} {% if show_messages %} {% for message, message_type in show_messages() %} @@ -37,9 +37,9 @@ {% block content %} {% endblock %} -
+ -
{% block footer %}{% include "_footer.html" %}{% endblock %}
+
{% block footer %}{% include "_footer.html" %}{% endblock %}
{% for body_script in body_scripts %} diff --git a/datasette/templates/database.html b/datasette/templates/database.html index 2f844b6a..3b89d68b 100644 --- a/datasette/templates/database.html +++ b/datasette/templates/database.html @@ -49,7 +49,7 @@ {% if views %}

Views

-
    +
      {% for view in views %}
    • {{ view.name }}{% if view.private %} 🔒{% endif %}
    • {% endfor %} @@ -58,7 +58,7 @@ {% if queries %}

      Queries

      -
        +
          {% for query in queries %}
        • {{ query.title or query.name }}{% if query.private %} 🔒{% endif %}
        • {% endfor %} From 70566769f118106279dd55313681d3ec3bca9e5e Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 11:57:34 -0700 Subject: [PATCH 04/12] Styled facets with different bullets --- datasette/static/app.css | 15 +++++++++++++-- datasette/templates/table.html | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index dff882af..2dfc6b15 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -55,7 +55,12 @@ th { padding-right: 1em; white-space: nowrap; } - +strong { + font-weight: bold; +} +em { + font-style: italic; +} /* end reset */ @@ -205,11 +210,13 @@ pre { } ul.bullets, +ul.tight-bullets, ul.spaced, ol.spaced { margin-bottom: 0.8rem; } -ul.bullets { +ul.bullets, +ul.tight-bullets { padding-left: 1.25rem; } ul.bullets li, @@ -220,6 +227,10 @@ ol.spaced li { ul.bullets li { list-style-type: circle; } +ul.tight-bullets li { + list-style-type: disc; + margin-bottom: 0; +} a.not-underlined { text-decoration: none; } diff --git a/datasette/templates/table.html b/datasette/templates/table.html index 3f8c2fee..bc8cfc0a 100644 --- a/datasette/templates/table.html +++ b/datasette/templates/table.html @@ -132,7 +132,7 @@ {% endif %}

          -
            +
              {% for facet_value in facet_info.results %} {% if not facet_value.selected %}
            • {{ (facet_value.label if facet_value.label is not none else "_") }} {{ "{:,}".format(facet_value.count) }}
            • From 083d9e41a0cdca595912860515eb6f2f261e29df Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:01:44 -0700 Subject: [PATCH 05/12] Tighten up table column CSS --- datasette/templates/table.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datasette/templates/table.html b/datasette/templates/table.html index bc8cfc0a..6c27beee 100644 --- a/datasette/templates/table.html +++ b/datasette/templates/table.html @@ -8,9 +8,9 @@ {% endblock %} From bd80c43b39be7466ed32d818e7bede97183a04d1 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:07:25 -0700 Subject: [PATCH 06/12] White cards on mobile --- datasette/static/app.css | 1 + 1 file changed, 1 insertion(+) diff --git a/datasette/static/app.css b/datasette/static/app.css index 2dfc6b15..c89f412b 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -654,6 +654,7 @@ p.zero-results { border-bottom: 1px solid #eee; padding: 0; padding-left: 10%; + background-color: white; } .rows-and-columns td:before { From b66750394426df84ee7fc17b7586ac04ea753886 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:20:28 -0700 Subject: [PATCH 07/12] word-break: break-word; --- datasette/static/app.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index c89f412b..7988252e 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -119,7 +119,8 @@ h6, font-weight: 700; font-size: 1rem; margin: 0; - padding: 0 + padding: 0; + word-break: break-word; } h1, .header1 { From a32216c1970e883f10964abb5c5b693e128e79ad Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:27:14 -0700 Subject: [PATCH 08/12] Mobile view cards now have rounded corners --- datasette/static/app.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index 7988252e..adbfccab 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -647,6 +647,9 @@ p.zero-results { .rows-and-columns tr { border: 1px solid #ccc; margin-bottom: 1em; + border-radius: 10px; + background-color: white; + padding: 0.2rem; } .rows-and-columns td { @@ -655,7 +658,6 @@ p.zero-results { border-bottom: 1px solid #eee; padding: 0; padding-left: 10%; - background-color: white; } .rows-and-columns td:before { From 0b786b023b90bef7217e72040ebc5d92cc657126 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:28:50 -0700 Subject: [PATCH 09/12] Off-white yellow is now off-white blue --- datasette/static/app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index adbfccab..085d829c 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -73,7 +73,7 @@ body { line-height: 1.5; color: #111A35; text-align: left; - background-color: #fefdf4; + background-color: #F8FAFB; } /* Helper Styles ===========================================================*/ From 114e0be82624b91d3409e2b559bb6d880146cff2 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:30:40 -0700 Subject: [PATCH 10/12] No underline on nav links in header --- datasette/static/app.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index 085d829c..b6dfd7f3 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -272,7 +272,9 @@ footer a:visited, footer a:hover, footer a:focus, footer a:active, -footer button.button-as-link, +footer button.button-as-link { + color: rgba(255,255,244,0.8); +} header a:link, header a:visited, header a:hover, @@ -280,6 +282,7 @@ header a:focus, header a:active, header button.button-as-link { color: rgba(255,255,244,0.8); + text-decoration: none; } footer a:hover, From a7b2aabd5148c0ee382b583de68a4f0538f7dfb1 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 12:34:35 -0700 Subject: [PATCH 11/12] Fixed broken footer test --- tests/test_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_html.py b/tests/test_html.py index 3af9816f..06b11de5 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1058,7 +1058,7 @@ def assert_querystring_equal(expected, actual): def assert_footer_links(soup): - footer_links = soup.find("div", {"class": "ft"}).findAll("a") + footer_links = soup.find("footer").findAll("a") assert 4 == len(footer_links) datasette_link, license_link, source_link, about_link = footer_links assert "Datasette" == datasette_link.text.strip() From 677e0409797660fd0d92deb22c306d7eafee031b Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 27 Oct 2020 13:39:07 -0700 Subject: [PATCH 12/12] --cors for /name.db downloads, refs #1057 --- datasette/utils/asgi.py | 17 +++++++++++++---- datasette/views/database.py | 4 ++++ tests/fixtures.py | 2 +- tests/test_api.py | 1 + 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/datasette/utils/asgi.py b/datasette/utils/asgi.py index 911038ab..bd388390 100644 --- a/datasette/utils/asgi.py +++ b/datasette/utils/asgi.py @@ -247,9 +247,9 @@ async def asgi_start(send, status, headers=None, content_type="text/plain"): async def asgi_send_file( - send, filepath, filename=None, content_type=None, chunk_size=4096 + send, filepath, filename=None, content_type=None, chunk_size=4096, headers=None ): - headers = {} + headers = headers or {} if filename: headers["content-disposition"] = 'attachment; filename="{}"'.format(filename) first = True @@ -395,13 +395,22 @@ class Response: class AsgiFileDownload: def __init__( - self, filepath, filename=None, content_type="application/octet-stream" + self, + filepath, + filename=None, + content_type="application/octet-stream", + headers=None, ): + self.headers = headers or {} self.filepath = filepath self.filename = filename self.content_type = content_type async def asgi_send(self, send): return await asgi_send_file( - send, self.filepath, filename=self.filename, content_type=self.content_type + send, + self.filepath, + filename=self.filename, + content_type=self.content_type, + headers=self.headers, ) diff --git a/datasette/views/database.py b/datasette/views/database.py index 74509278..025e853d 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -144,10 +144,14 @@ class DatabaseDownload(DataView): if not db.path: raise DatasetteError("Cannot download database", status=404) filepath = db.path + headers = {} + if self.ds.cors: + headers["Access-Control-Allow-Origin"] = "*" return AsgiFileDownload( filepath, filename=os.path.basename(filepath), content_type="application/octet-stream", + headers=headers, ) diff --git a/tests/fixtures.py b/tests/fixtures.py index d8c92561..7786ca8c 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -227,7 +227,7 @@ def app_client_with_dot(): @pytest.fixture(scope="session") def app_client_with_cors(): - with make_app_client(cors=True) as client: + with make_app_client(is_immutable=True, cors=True) as client: yield client diff --git a/tests/test_api.py b/tests/test_api.py index 1d454ea1..461d3f81 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1739,6 +1739,7 @@ def test_trace(app_client): @pytest.mark.parametrize( "path,status_code", [ + ("/fixtures.db", 200), ("/fixtures.json", 200), ("/fixtures/no_primary_key.json", 200), # A 400 invalid SQL query should still have the header: