From 504196341c49840270bd75ea1a1871ef386ba7ea Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 14 May 2020 22:51:39 -0700 Subject: [PATCH] Visually distinguish float/int columns, closes #729 --- datasette/static/app.css | 5 ++ datasette/templates/_table.html | 2 +- datasette/views/table.py | 12 ++- tests/test_html.py | 133 ++++++++++++++++---------------- 4 files changed, 85 insertions(+), 67 deletions(-) diff --git a/datasette/static/app.css b/datasette/static/app.css index bae091b8..cc33277a 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -345,3 +345,8 @@ p.zero-results { padding: 0.5em; font-style: italic; } + +/* Value types */ +.type-float, .type-int { + color: #666; +} \ No newline at end of file diff --git a/datasette/templates/_table.html b/datasette/templates/_table.html index 42c37c55..8fee77b2 100644 --- a/datasette/templates/_table.html +++ b/datasette/templates/_table.html @@ -21,7 +21,7 @@ {% for row in display_rows %} {% for cell in row %} - {{ cell.value }} + {{ cell.value }} {% endfor %} {% endfor %} diff --git a/datasette/views/table.py b/datasette/views/table.py index c07447d3..51b7aa2f 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -112,6 +112,7 @@ class RowTableShared(DataView): cells.append( { "column": pks[0] if len(pks) == 1 else "Link", + "value_type": "link", "is_special_link_column": is_special_link_column, "raw": pk_path, "value": jinja2.Markup( @@ -192,7 +193,16 @@ class RowTableShared(DataView): if truncate_cells and len(display_value) > truncate_cells: display_value = display_value[:truncate_cells] + u"\u2026" - cells.append({"column": column, "value": display_value, "raw": value}) + cells.append( + { + "column": column, + "value": display_value, + "raw": value, + "value_type": "none" + if value is None + else str(type(value).__name__), + } + ) cell_rows.append(Row(cells)) if link_column: diff --git a/tests/test_html.py b/tests/test_html.py index 564365ce..a3388c2d 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -505,16 +505,16 @@ def test_table_html_simple_primary_key(app_client): assert ["nofollow"] == a["rel"] assert [ [ - '1', - 'hello', + '1', + 'hello', ], [ - '2', - 'world', + '2', + 'world', ], [ - '3', - '\xa0', + '3', + '\xa0', ], ] == [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] @@ -578,9 +578,12 @@ def test_row_html_simple_primary_key(app_client): assert response.status == 200 table = Soup(response.body, "html.parser").find("table") assert ["id", "content"] == [th.string.strip() for th in table.select("thead th")] - assert [['1', 'hello']] == [ - [str(td) for td in tr.select("td")] for tr in table.select("tbody tr") - ] + assert [ + [ + '1', + 'hello', + ] + ] == [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] def test_table_not_exists(app_client): @@ -599,14 +602,14 @@ def test_table_html_no_primary_key(app_client): ] expected = [ [ - '{}'.format( + '{}'.format( i, i ), - '{}'.format(i), - '{}'.format(i), - 'a{}'.format(i), - 'b{}'.format(i), - 'c{}'.format(i), + '{}'.format(i), + '{}'.format(i), + 'a{}'.format(i), + 'b{}'.format(i), + 'c{}'.format(i), ] for i in range(1, 51) ] @@ -633,11 +636,11 @@ def test_row_html_no_primary_key(app_client): ] expected = [ [ - '1', - '1', - 'a1', - 'b1', - 'c1', + '1', + '1', + 'a1', + 'b1', + 'c1', ] ] assert expected == [ @@ -658,10 +661,10 @@ def test_table_html_compound_primary_key(app_client): assert a["href"].endswith("/compound_primary_key?_sort={}".format(expected_col)) expected = [ [ - 'a,b', - 'a', - 'b', - 'c', + 'a,b', + 'a', + 'b', + 'c', ] ] assert expected == [ @@ -675,14 +678,14 @@ def test_table_html_foreign_key_links(app_client): table = Soup(response.body, "html.parser").find("table") expected = [ [ - '1', - 'hello\xa01', - '1', + '1', + 'hello\xa01', + '1', ], [ - '2', - '\xa0', - '\xa0', + '2', + '\xa0', + '\xa0', ], ] assert expected == [ @@ -696,9 +699,9 @@ def test_table_html_disable_foreign_key_links_with_labels(app_client): table = Soup(response.body, "html.parser").find("table") expected = [ [ - '1', - '1', - '1', + '1', + '1', + '1', ] ] assert expected == [ @@ -712,8 +715,8 @@ def test_table_html_foreign_key_custom_label_column(app_client): table = Soup(response.body, "html.parser").find("table") expected = [ [ - '1', - 'world2\xa01', + '1', + 'world2\xa01', ] ] assert expected == [ @@ -754,9 +757,9 @@ def test_row_html_compound_primary_key(app_client): ] expected = [ [ - 'a', - 'b', - 'c', + 'a', + 'b', + 'c', ] ] assert expected == [ @@ -771,14 +774,14 @@ def test_compound_primary_key_with_foreign_key_references(app_client): table = Soup(response.body, "html.parser").find("table") expected = [ [ - '1,feline', - '1\xa01', - 'feline', + '1,feline', + '1\xa01', + 'feline', ], [ - '2,canine', - '2\xa02', - 'canine', + '2,canine', + '2\xa02', + 'canine', ], ] assert expected == [ @@ -799,16 +802,16 @@ def test_view_html(app_client): assert ths[1].string.strip() == "upper_content" expected = [ [ - 'hello', - 'HELLO', + 'hello', + 'HELLO', ], [ - 'world', - 'WORLD', + 'world', + 'WORLD', ], [ - '\xa0', - '\xa0', + '\xa0', + '\xa0', ], ] assert expected == [ @@ -1079,9 +1082,9 @@ def test_binary_data_display(app_client): table = Soup(response.body, "html.parser").find("table") expected_tds = [ [ - '1', - '1', - '<Binary\xa0data:\xa019\xa0bytes>', + '1', + '1', + '<Binary\xa0data:\xa019\xa0bytes>', ] ] assert expected_tds == [ @@ -1154,20 +1157,20 @@ def test_metadata_sort(app_client): rows = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] expected = [ [ - '3', - 'Detroit', + '3', + 'Detroit', ], [ - '2', - 'Los Angeles', + '2', + 'Los Angeles', ], [ - '4', - 'Memnonia', + '4', + 'Memnonia', ], [ - '1', - 'San Francisco', + '1', + 'San Francisco', ], ] assert expected == rows @@ -1189,12 +1192,12 @@ def test_metadata_sort_desc(app_client): rows = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] expected = [ [ - '2', - 'Paranormal', + '2', + 'Paranormal', ], [ - '1', - 'Museum', + '1', + 'Museum', ], ] assert expected == rows