mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Compare commits
12 commits
main
...
header-foo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677e040979 | ||
|
|
a7b2aabd51 | ||
|
|
114e0be826 | ||
|
|
0b786b023b | ||
|
|
a32216c197 | ||
|
|
b667503944 | ||
|
|
bd80c43b39 | ||
|
|
083d9e41a0 | ||
|
|
70566769f1 | ||
|
|
9f1c844e73 | ||
|
|
ae9cffaf5b | ||
|
|
18b2061cff |
10 changed files with 665 additions and 200 deletions
|
|
@ -1,3 +1,69 @@
|
|||
/* 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;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
/* end reset */
|
||||
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
|
@ -5,12 +71,294 @@ body {
|
|||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
color: #111A35;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
background-color: #F8FAFB;
|
||||
}
|
||||
.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;
|
||||
word-break: break-word;
|
||||
}
|
||||
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 {
|
||||
color: #276890;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:visited {
|
||||
color: #54AC8E;
|
||||
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.tight-bullets,
|
||||
ul.spaced,
|
||||
ol.spaced {
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
ul.bullets,
|
||||
ul.tight-bullets {
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
ul.bullets li,
|
||||
ul.spaced li,
|
||||
ol.spaced li {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
ul.bullets li {
|
||||
list-style-type: circle;
|
||||
}
|
||||
ul.tight-bullets li {
|
||||
list-style-type: disc;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
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 {
|
||||
color: rgba(255,255,244,0.8);
|
||||
}
|
||||
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);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
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 */
|
||||
footer {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
|
||||
/* 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,100 +380,19 @@ td em {
|
|||
}
|
||||
th {
|
||||
padding-right: 1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
table a:link {
|
||||
text-decoration: none;
|
||||
color: #445ac8;
|
||||
}
|
||||
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 +402,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 +451,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 +550,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;
|
||||
|
|
@ -345,6 +585,7 @@ a.not-underlined {
|
|||
width: auto;
|
||||
display: inline-block;
|
||||
box-shadow: 1px 2px 8px 2px rgba(0,0,0,0.08);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.download-sqlite em {
|
||||
|
|
@ -352,9 +593,7 @@ a.not-underlined {
|
|||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
pre.wrapped-sql {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
|
||||
p.zero-results {
|
||||
border: 2px solid #ccc;
|
||||
|
|
@ -368,30 +607,78 @@ 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;
|
||||
border-radius: 10px;
|
||||
background-color: white;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
|
||||
.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 {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
</head>
|
||||
<body class="{% block body_class %}{% endblock %}">
|
||||
|
||||
<nav class="hd">{% block nav %}
|
||||
<header><nav>{% block nav %}
|
||||
{% if actor %}
|
||||
<div class="logout">
|
||||
<strong>{{ display_actor(actor) }}</strong>{% if show_logout %} ·
|
||||
|
|
@ -24,9 +24,9 @@
|
|||
</form>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}</nav>
|
||||
{% endblock %}</nav></header>
|
||||
|
||||
<div class="bd">
|
||||
<section class="content">
|
||||
{% block messages %}
|
||||
{% if show_messages %}
|
||||
{% for message, message_type in show_messages() %}
|
||||
|
|
@ -37,9 +37,9 @@
|
|||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="ft">{% block footer %}{% include "_footer.html" %}{% endblock %}</div>
|
||||
<footer class="ft">{% block footer %}{% include "_footer.html" %}{% endblock %}</footer>
|
||||
|
||||
{% for body_script in body_scripts %}
|
||||
<script>{{ body_script }}</script>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
{% if views %}
|
||||
<h2 id="views">Views</h2>
|
||||
<ul>
|
||||
<ul class="bullets">
|
||||
{% for view in views %}
|
||||
<li><a href="{{ urls.database(database) }}/{{ view.name|urlencode }}">{{ view.name }}</a>{% if view.private %} 🔒{% endif %}</li>
|
||||
{% endfor %}
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
{% if queries %}
|
||||
<h2 id="queries">Queries</h2>
|
||||
<ul>
|
||||
<ul class="bullets">
|
||||
{% for query in queries %}
|
||||
<li><a href="{{ urls.query(database, query.name) }}{% if query.fragment %}#{{ query.fragment }}{% endif %}" title="{{ query.description or query.sql }}">{{ query.title or query.name }}</a>{% if query.private %} 🔒{% endif %}</li>
|
||||
{% endfor %}
|
||||
|
|
|
|||
|
|
@ -5,35 +5,63 @@
|
|||
<link rel="stylesheet" href="{{ base_url }}-/static/app.css?{{ app_css_hash }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="robots" content="noindex">
|
||||
<style>.pattern-heading { padding: 0.4em; border-top: 1px solid red; border-bottom: 1px solid red; background-color: pink }</style>
|
||||
<style></style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="hd"></nav>
|
||||
<div class="bd">
|
||||
|
||||
|
||||
<header>
|
||||
</header>
|
||||
|
||||
<br>
|
||||
|
||||
<!-- .hd is now header -->
|
||||
<header>
|
||||
<nav></nav>
|
||||
</header>
|
||||
|
||||
|
||||
<!-- div.bd is now section.content -->
|
||||
<section class="content">
|
||||
<h1>Pattern Portfolio</h1>
|
||||
</div>
|
||||
<h2 class="pattern-heading">.hd for /database/table/row</h2>
|
||||
<nav class="hd">
|
||||
<p class="crumbs">
|
||||
<a href="/">home</a> /
|
||||
<a href="/fixtures">fixtures</a> /
|
||||
<a href="/fixtures/attraction_characteristic">attraction_characteristic</a>
|
||||
</p>
|
||||
<div class="logout">
|
||||
<strong>testuser</strong> ·
|
||||
<form action="/-/logout" method="post">
|
||||
<button class="button-as-link">Log out</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
<h2 class="pattern-heading">Messages</h2>
|
||||
<div class="bd">
|
||||
<p class="message-info">Example message</p>
|
||||
<p class="message-warning">Example message</p>
|
||||
<p class="message-error">Example message</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">Header for /database/table/row and Messages</h2>
|
||||
|
||||
<header>
|
||||
<nav>
|
||||
<p class="crumbs">
|
||||
<a href="/">home</a> /
|
||||
<a href="/fixtures">fixtures</a> /
|
||||
<a href="/fixtures/attraction_characteristic">attraction_characteristic</a>
|
||||
</p>
|
||||
<div class="logout">
|
||||
<strong>testuser</strong> ·
|
||||
<form action="/-/logout" method="post">
|
||||
<button class="button-as-link">Log out</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<p class="message-info">Example message</p>
|
||||
<p class="message-warning">Example message</p>
|
||||
<p class="message-error">Example message</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">.bd for /</h2>
|
||||
<div class="bd">
|
||||
<section class="content">
|
||||
<h1>Datasette Fixtures</h1>
|
||||
<div class="metadata-description">
|
||||
An example SQLite database demonstrating Datasette
|
||||
|
|
@ -60,9 +88,16 @@
|
|||
6 rows in 2 tables
|
||||
</p>
|
||||
<p><a href="/data/names" title="6 rows">names</a>, <a href="/data/foo">foo</a></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">.bd for /database</h2>
|
||||
<div class="bd">
|
||||
<section class="content">
|
||||
<h1 style="padding-left: 10px; border-left: 10px solid #ff0000">fixtures</h1>
|
||||
<div class="metadata-description">
|
||||
Test tables description
|
||||
|
|
@ -102,9 +137,15 @@
|
|||
<p><em>pk, name</em></p>
|
||||
<p>2 rows</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">.bd for /database/table</h2>
|
||||
<div class="bd">
|
||||
<section class="content">
|
||||
<h1 style="padding-left: 10px; border-left: 10px solid #ff0000">roadside_attraction_characteristics</h1>
|
||||
<p>
|
||||
Data license:
|
||||
|
|
@ -203,9 +244,109 @@
|
|||
<label class="sort_by_desc small-screen-only"><input type="checkbox" name="_sort_by_desc"> descending</label>
|
||||
<input type="submit" value="Apply">
|
||||
</div>
|
||||
</form>
|
||||
<p><a class="not-underlined" title="select rowid, attraction_id, characteristic_id from roadside_attraction_characteristics where "characteristic_id" = :p0 order by rowid limit 101" href="/fixtures?sql=select+rowid%2C+attraction_id%2C+characteristic_id+from+roadside_attraction_characteristics+where+%22characteristic_id%22+%3D+%3Ap0+order+by+rowid+limit+101&p0=2">✎ <span class="underlined">View and edit SQL</span></a></p>
|
||||
<p class="export-links">This data as <a href="/fixtures/roadside_attraction_characteristics.json?characteristic_id=2&_labels=on">json</a>, <a href="/fixtures/roadside_attraction_characteristics.csv?characteristic_id=2&_labels=on&_size=max">CSV</a> (<a href="#export">advanced</a>)</p>
|
||||
</form>
|
||||
|
||||
|
||||
<div class="extra-wheres">
|
||||
<h3>2 extra where clauses</h3>
|
||||
<ul>
|
||||
|
||||
<li><code>planet_int=1</code> [<a href="/fixtures/facetable?_where=state%3D%27CA%27">remove</a>]</li>
|
||||
|
||||
<li><code>state='CA'</code> [<a href="/fixtures/facetable?_where=planet_int%3D1">remove</a>]</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<p><a class="not-underlined" title="select rowid, attraction_id, characteristic_id from roadside_attraction_characteristics where "characteristic_id" = :p0 order by rowid limit 101" href="/fixtures?sql=select+rowid%2C+attraction_id%2C+characteristic_id+from+roadside_attraction_characteristics+where+%22characteristic_id%22+%3D+%3Ap0+order+by+rowid+limit+101&p0=2">✎ <span class="underlined">View and edit SQL</span></a></p>
|
||||
|
||||
<p class="export-links">This data as <a href="/fixtures/roadside_attraction_characteristics.json?characteristic_id=2&_labels=on">json</a>, <a href="/fixtures/roadside_attraction_characteristics.csv?characteristic_id=2&_labels=on&_size=max">CSV</a> (<a href="#export">advanced</a>)</p>
|
||||
|
||||
<p class="suggested-facets">
|
||||
Suggested facets: <a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet=complex_array&_facet=tags#facet-tags">tags</a>, <a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet=complex_array&_facet_date=created#facet-created">created</a> (date), <a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet=complex_array&_facet_array=tags#facet-tags">tags</a> (array)
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="facet-results">
|
||||
|
||||
<div class="facet-info facet-fixtures-facetable-tags" id="facet-tags">
|
||||
<p class="facet-info-name">
|
||||
<strong>tags (array)</strong>
|
||||
|
||||
<a href="/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created" class="cross">✖</a>
|
||||
|
||||
</p>
|
||||
<ul>
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&tags__arraycontains=tag1">tag1</a> 2</li>
|
||||
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&tags__arraycontains=tag2">tag2</a> 1</li>
|
||||
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&tags__arraycontains=tag3">tag3</a> 1</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="facet-info facet-fixtures-facetable-created" id="facet-created">
|
||||
<p class="facet-info-name">
|
||||
<strong>created</strong>
|
||||
|
||||
<a href="/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet_array=tags" class="cross">✖</a>
|
||||
|
||||
</p>
|
||||
<ul>
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&created=2019-01-14+08%3A00%3A00">2019-01-14 08:00:00</a> 4</li>
|
||||
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&created=2019-01-15+08%3A00%3A00">2019-01-15 08:00:00</a> 4</li>
|
||||
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&created=2019-01-16+08%3A00%3A00">2019-01-16 08:00:00</a> 2</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="facet-info facet-fixtures-facetable-city_id" id="facet-city_id">
|
||||
<p class="facet-info-name">
|
||||
<strong>city_id</strong>
|
||||
|
||||
<a href="/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=created&_facet_array=tags" class="cross">✖</a>
|
||||
|
||||
</p>
|
||||
<ul>
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&city_id=1">San Francisco</a> 6</li>
|
||||
|
||||
|
||||
|
||||
<li><a href="http://latest.datasette.io/fixtures/facetable?_where=planet_int%3D1&_where=state%3D%27CA%27&_facet=city_id&_facet=created&_facet_array=tags&city_id=2">Los Angeles</a> 4</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<table class="rows-and-columns">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -266,9 +407,20 @@
|
|||
attraction_id INTEGER REFERENCES roadside_attractions(pk),
|
||||
characteristic_id INTEGER REFERENCES attraction_characteristic(pk)
|
||||
);</pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">.bd for /database/table/row</h2>
|
||||
<div class="bd">
|
||||
<section class="content">
|
||||
<h1 style="padding-left: 10px; border-left: 10px solid #ff0000">roadside_attractions: 2</h1>
|
||||
<p>This data as <a href="/fixtures/roadside_attractions/2.json">json</a></p>
|
||||
<table class="rows-and-columns">
|
||||
|
|
@ -309,9 +461,21 @@
|
|||
from attraction_id in roadside_attraction_characteristics
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 class="pattern-heading">.ft</h2>
|
||||
<div class="ft">Powered by <a href="https://github.com/simonw/datasette" title="Datasette v0+unknown">Datasette</a>
|
||||
|
||||
<footer class="ft">Powered by <a href="https://github.com/simonw/datasette" title="Datasette v0+unknown">Datasette</a>
|
||||
· Data license:
|
||||
<a href="https://github.com/simonw/datasette/blob/master/LICENSE">Apache License 2.0</a>
|
||||
·
|
||||
|
|
@ -322,6 +486,6 @@
|
|||
About:
|
||||
<a href="https://github.com/simonw/datasette">
|
||||
About Datasette</a>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<script src="{{ urls.static('table.js') }}" defer></script>
|
||||
<style>
|
||||
@media only screen and (max-width: 576px) {
|
||||
{% for column in display_columns %}
|
||||
{% for column in display_columns -%}
|
||||
.rows-and-columns td:nth-of-type({{ loop.index }}):before { content: "{{ column.name|escape_css_string }}"; }
|
||||
{% endfor %}
|
||||
{% endfor %}}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
<a href="{{ facet_info.toggle_url }}" class="cross">✖</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<ul>
|
||||
<ul class="tight-bullets">
|
||||
{% for facet_value in facet_info.results %}
|
||||
{% if not facet_value.selected %}
|
||||
<li><a href="{{ facet_value.toggle_url }}">{{ (facet_value.label if facet_value.label is not none else "_") }}</a> {{ "{:,}".format(facet_value.count) }}</li>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue