mirror of
https://github.com/simonw/datasette.git
synced 2026-06-14 21:16:56 +02:00
Tweaks to delete query flow
Animated demo: https://github.com/simonw/datasette/pull/2764#issuecomment-4655694668 Refs #2760
This commit is contained in:
parent
378b528a95
commit
1359de65c0
4 changed files with 54 additions and 29 deletions
|
|
@ -32,6 +32,16 @@
|
|||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
.query-delete-form input[type=submit] {
|
||||
background: linear-gradient(180deg, #d73a31 0%, #b42318 100%);
|
||||
border-color: #b42318;
|
||||
font-weight: 700;
|
||||
}
|
||||
.query-delete-form input[type=submit]:hover,
|
||||
.query-delete-form input[type=submit]:focus {
|
||||
background: linear-gradient(180deg, #c3342b 0%, #971c14 100%);
|
||||
border-color: #971c14;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -60,7 +70,7 @@
|
|||
<dd><pre>{{ query.sql }}</pre></dd>
|
||||
</dl>
|
||||
|
||||
<form action="{{ query_url }}/-/delete" method="post">
|
||||
<form class="core query-delete-form" action="{{ query_url }}/-/delete" method="post">
|
||||
<p class="query-delete-actions">
|
||||
<input type="submit" value="Delete query">
|
||||
<a href="{{ query_url }}">Cancel</a>
|
||||
|
|
|
|||
|
|
@ -205,32 +205,32 @@
|
|||
|
||||
<h1 style="padding-left: 10px; border-left: 10px solid #{% if database_color %}{{ database_color }}{% else %}666{% endif %}">Queries</h1>
|
||||
|
||||
<form class="query-list-filters core" action="{{ query_list_path }}" method="get">
|
||||
<p class="query-list-search">
|
||||
<label for="query-search">Search</label>
|
||||
<input id="query-search" type="search" name="q" value="{{ filters.q }}">
|
||||
{% if filters.is_write %}<input type="hidden" name="is_write" value="{{ filters.is_write }}">{% endif %}
|
||||
{% if filters.is_private %}<input type="hidden" name="is_private" value="{{ filters.is_private }}">{% endif %}
|
||||
{% if filters.source %}<input type="hidden" name="source" value="{{ filters.source }}">{% endif %}
|
||||
{% if filters.owner_id %}<input type="hidden" name="owner_id" value="{{ filters.owner_id }}">{% endif %}
|
||||
<button type="submit">Search</button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<nav class="query-list-facets" aria-label="Query filters">
|
||||
{% for facet in facets %}
|
||||
<section class="query-list-facet">
|
||||
<h2>{{ facet.title }}</h2>
|
||||
<ul>
|
||||
{% for item in facet["items"] %}
|
||||
<li>{% if item.href %}<a class="query-list-facet-link{% if item.active %} query-list-facet-link-active{% endif %}" href="{{ item.href }}"{% if item.active %} aria-current="true"{% endif %}>{% else %}<span class="query-list-facet-link query-list-facet-disabled">{% endif %}<span>{{ item.label }}</span><span class="query-list-facet-count">{{ item.count }}</span>{% if item.href %}</a>{% else %}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
|
||||
{% if queries %}
|
||||
<form class="query-list-filters core" action="{{ query_list_path }}" method="get">
|
||||
<p class="query-list-search">
|
||||
<label for="query-search">Search</label>
|
||||
<input id="query-search" type="search" name="q" value="{{ filters.q }}">
|
||||
{% if filters.is_write %}<input type="hidden" name="is_write" value="{{ filters.is_write }}">{% endif %}
|
||||
{% if filters.is_private %}<input type="hidden" name="is_private" value="{{ filters.is_private }}">{% endif %}
|
||||
{% if filters.source %}<input type="hidden" name="source" value="{{ filters.source }}">{% endif %}
|
||||
{% if filters.owner_id %}<input type="hidden" name="owner_id" value="{{ filters.owner_id }}">{% endif %}
|
||||
<button type="submit">Search</button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<nav class="query-list-facets" aria-label="Query filters">
|
||||
{% for facet in facets %}
|
||||
<section class="query-list-facet">
|
||||
<h2>{{ facet.title }}</h2>
|
||||
<ul>
|
||||
{% for item in facet["items"] %}
|
||||
<li>{% if item.href %}<a class="query-list-facet-link{% if item.active %} query-list-facet-link-active{% endif %}" href="{{ item.href }}"{% if item.active %} aria-current="true"{% endif %}>{% else %}<span class="query-list-facet-link query-list-facet-disabled">{% endif %}<span>{{ item.label }}</span><span class="query-list-facet-count">{{ item.count }}</span>{% if item.href %}</a>{% else %}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
|
||||
<div class="table-wrapper"><table class="query-list-results">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -641,6 +641,4 @@ class QueryDeleteView(BaseView):
|
|||
"Query “{}” deleted".format(existing.title or query_name),
|
||||
self.ds.INFO,
|
||||
)
|
||||
return Response.redirect(
|
||||
self.ds.urls.path(self.ds.urls.database(db.name) + "/-/queries")
|
||||
)
|
||||
return Response.redirect(self.ds.urls.path(self.ds.urls.database(db.name)))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import re
|
|||
from html import unescape
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup as Soup
|
||||
|
||||
from datasette.app import Datasette
|
||||
from datasette.resources import DatabaseResource, QueryResource
|
||||
|
|
@ -712,6 +713,10 @@ async def test_query_list_search_filter_and_html():
|
|||
"/data/-/queries?is_private=1",
|
||||
actor={"id": "root"},
|
||||
)
|
||||
no_results_response = await ds.client.get(
|
||||
"/data/-/queries?q=nope",
|
||||
actor={"id": "root"},
|
||||
)
|
||||
|
||||
assert html_response.status_code == 200
|
||||
assert "Demo query 02" in html_response.text
|
||||
|
|
@ -799,6 +804,13 @@ async def test_query_list_search_filter_and_html():
|
|||
'<span class="query-list-facet-link query-list-facet-disabled"><span>Not private</span><span class="query-list-facet-count">0</span></span>'
|
||||
not in filtered_private_response.text
|
||||
)
|
||||
assert no_results_response.status_code == 200
|
||||
assert "No queries found." in no_results_response.text
|
||||
assert 'class="query-list-filters core"' not in no_results_response.text
|
||||
assert 'id="query-search"' not in no_results_response.text
|
||||
assert 'class="query-list-facets"' not in no_results_response.text
|
||||
assert "<h2>Mode</h2>" not in no_results_response.text
|
||||
assert "<h2>Visibility</h2>" not in no_results_response.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -1274,6 +1286,11 @@ async def test_query_delete_confirmation_and_form_delete():
|
|||
assert get_response.status_code == 200
|
||||
assert "Are you sure" in get_response.text
|
||||
assert "select * from dogs" in get_response.text
|
||||
soup = Soup(get_response.text, "html.parser")
|
||||
form = soup.select_one("form.query-delete-form")
|
||||
assert form is not None
|
||||
assert "core" in form["class"]
|
||||
assert form.select_one('input[type="submit"][value="Delete query"]') is not None
|
||||
|
||||
post_response = await ds.client.post(
|
||||
"/data/saved/-/delete",
|
||||
|
|
@ -1281,7 +1298,7 @@ async def test_query_delete_confirmation_and_form_delete():
|
|||
data={},
|
||||
)
|
||||
assert post_response.status_code == 302
|
||||
assert post_response.headers["location"] == "/data/-/queries"
|
||||
assert post_response.headers["location"] == "/data"
|
||||
assert await ds.get_query("data", "saved") is None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue