kopia lustrzana https://github.com/simonw/datasette
Implemented responsive tables, removed bootstrap
No need for all of bootstrap since we only need to style a few elements. Implemented responsive table pattern from here: https://css-tricks.com/responsive-data-tables/ Refs #16pull/81/head
rodzic
21c9c04310
commit
7d81083d40
|
@ -16,6 +16,7 @@ import time
|
||||||
from .utils import (
|
from .utils import (
|
||||||
build_where_clauses,
|
build_where_clauses,
|
||||||
CustomJSONEncoder,
|
CustomJSONEncoder,
|
||||||
|
escape_css_string,
|
||||||
InvalidSql,
|
InvalidSql,
|
||||||
path_from_row_pks,
|
path_from_row_pks,
|
||||||
path_with_added_args,
|
path_with_added_args,
|
||||||
|
@ -443,6 +444,7 @@ class Datasette:
|
||||||
str(app_root / 'datasette' / 'templates')
|
str(app_root / 'datasette' / 'templates')
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
self.jinja.add_env('escape_css_string', escape_css_string, 'filters')
|
||||||
app.add_route(IndexView.as_view(self), '/')
|
app.add_route(IndexView.as_view(self), '/')
|
||||||
# TODO: /favicon.ico and /-/static/ deserve far-future cache expires
|
# TODO: /favicon.ico and /-/static/ deserve far-future cache expires
|
||||||
app.add_route(favicon, '/favicon.ico')
|
app.add_route(favicon, '/favicon.ico')
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0 1em;
|
||||||
|
font-family: "Helvetica Neue", sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #212529;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
padding: 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 576px) {
|
||||||
|
/* Force table to not be like tables anymore */
|
||||||
|
table, thead, tbody, th, td, tr {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide table headers (but not display: none;, for accessibility) */
|
||||||
|
thead tr {
|
||||||
|
position: absolute;
|
||||||
|
top: -9999px;
|
||||||
|
left: -9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
/* Behave like a "row" */
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding: 0;
|
||||||
|
padding-left: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:before {
|
||||||
|
display: block;
|
||||||
|
margin-left: -10%;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
|
@ -2,21 +2,17 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="/-/static/bootstrap-4.0.0-beta.2.min.css">
|
<link rel="stylesheet" href="/-/static/app.css">
|
||||||
<style>
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% block extra_head %}{% endblock %}
|
{% block extra_head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
|
||||||
{% if error %}
|
{% if error %}
|
||||||
<div style="padding: 1em; margin: 1em; border: 3px solid red;">{{ error }}</div>
|
<div style="padding: 1em; margin: 1em; border: 3px solid red;">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -7,17 +7,13 @@
|
||||||
|
|
||||||
<p><a href="/{{ database }}-{{ database_hash }}.db">download {{ database }}.db</a></p>
|
<p><a href="/{{ database }}-{{ database_hash }}.db">download {{ database }}.db</a></p>
|
||||||
|
|
||||||
<style>
|
|
||||||
td {
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid #666;
|
|
||||||
padding: 2px 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
{% for column in columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
<tr>
|
||||||
</tr>
|
{% for column in columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for row in rows %}
|
{% for row in rows %}
|
||||||
<tr>
|
<tr>
|
||||||
{% for td in row %}
|
{% for td in row %}
|
||||||
|
@ -31,5 +27,6 @@ td {
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,34 +2,36 @@
|
||||||
|
|
||||||
{% block title %}{{ database }}: {{ table }}{% endblock %}
|
{% block title %}{{ database }}: {{ table }}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 576px) {
|
||||||
|
{% for column in columns %}
|
||||||
|
td:nth-of-type({{ loop.index }}):before { content: "{{ column|escape_css_string }}"; }
|
||||||
|
{% endfor %}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}"><a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></h1>
|
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}"><a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></h1>
|
||||||
|
|
||||||
<h2><a href="/{{ database }}-{{ database_hash }}/{{ table }}">{{ table }}</a></h2>
|
<h2><a href="/{{ database }}-{{ database_hash }}/{{ table }}">{{ table }}</a></h2>
|
||||||
|
|
||||||
<style>
|
|
||||||
td {
|
|
||||||
white-space: pre;
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid #666;
|
|
||||||
padding: 2px 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
{% if primary_keys and row_link %}<th scope="col">Link</th>{% endif %}
|
<tr>
|
||||||
{% for column in columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
{% for column in columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for row in rows %}
|
{% for row in rows %}
|
||||||
<tr>
|
<tr>
|
||||||
{% if primary_keys and row_link %}
|
|
||||||
<td><a href="/{{ database }}-{{ database_hash }}/{{ table }}/{{ row_link(row) }}">{{ row_link(row) }}</a></td>
|
|
||||||
{% endif %}
|
|
||||||
{% for td in row %}
|
{% for td in row %}
|
||||||
<td>{{ td }}</td>
|
<td>{{ td }}</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if took_ms %}<small>Took {{ took_ms }}</small>{% endif %}
|
{% if took_ms %}<small>Took {{ took_ms }}</small>{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,37 +2,41 @@
|
||||||
|
|
||||||
{% block title %}{{ database }}: {{ table }}{% endblock %}
|
{% block title %}{{ database }}: {{ table }}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 576px) {
|
||||||
|
td:nth-of-type(1):before { content: "{% if use_rowid %}rowid{% else %}Link{% endif %}"; }
|
||||||
|
{% for column in display_columns %}
|
||||||
|
td:nth-of-type({{ loop.index + 1 }}):before { content: "{{ column|escape_css_string }}"; }
|
||||||
|
{% endfor %}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}"><a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></h1>
|
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}"><a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></h1>
|
||||||
|
|
||||||
<h2>{{ table }}{% if total_rows != None %} ({{ "{:,}".format(total_rows) }} total row{% if total_rows == 1 %}{% else %}s{% endif %} in this table){% endif %}</h2>
|
<h2>{{ table }}{% if total_rows != None %} ({{ "{:,}".format(total_rows) }} total row{% if total_rows == 1 %}{% else %}s{% endif %} in this table){% endif %}</h2>
|
||||||
|
|
||||||
<style>
|
|
||||||
th {
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
td {
|
|
||||||
white-space: pre;
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid #666;
|
|
||||||
padding: 2px 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th scope="col">{% if use_rowid %}rowid{% else %}Link{% endif %}</th>
|
<tr>
|
||||||
{% for column in display_columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
<th scope="col">{% if use_rowid %}rowid{% else %}Link{% endif %}</th>
|
||||||
</tr>
|
{% for column in display_columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for row in rows %}
|
{% for row in rows %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/{{ database }}-{{ database_hash }}/{{ table }}/{{ row_link(row) }}">{{ row_link(row) }}</a></td>
|
<td><a href="/{{ database }}-{{ database_hash }}/{{ table }}/{{ row_link(row) }}">{{ row_link(row) }}</a></td>
|
||||||
{% for td in row %}
|
{% for td in row %}
|
||||||
{% if not use_rowid or (use_rowid and not loop.first) %}
|
{% if not use_rowid or (use_rowid and not loop.first) %}
|
||||||
<td>{{ td }}</td>
|
<td>{{ td or " " }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if after_link %}
|
{% if after_link %}
|
||||||
<p><a href="{{ after_link }}">Next page</a></p>
|
<p><a href="{{ after_link }}">Next page</a></p>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
|
@ -107,3 +108,10 @@ def path_with_added_args(request, args):
|
||||||
current = request.raw_args.copy()
|
current = request.raw_args.copy()
|
||||||
current.update(args)
|
current.update(args)
|
||||||
return request.path + '?' + urllib.parse.urlencode(current)
|
return request.path + '?' + urllib.parse.urlencode(current)
|
||||||
|
|
||||||
|
|
||||||
|
_css_re = re.compile(r'''['"\n\\]''')
|
||||||
|
|
||||||
|
|
||||||
|
def escape_css_string(s):
|
||||||
|
return _css_re.sub(lambda m: '\\{:X}'.format(ord(m.group())), s)
|
||||||
|
|
Ładowanie…
Reference in New Issue