mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
feat: Add "Requests" filter option for package name
- Add package name textbox for filtering requests (with auto-suggest) - Make "x pending requests" a link for TU/Dev on the package details page Signed-off-by: moson-mo <mo-son@mailbox.org>
This commit is contained in:
parent
acdb2864de
commit
f24fae0ce6
7 changed files with 109 additions and 8 deletions
|
@ -40,13 +40,21 @@ async def requests(
|
||||||
filter_accepted: bool = False,
|
filter_accepted: bool = False,
|
||||||
filter_rejected: bool = False,
|
filter_rejected: bool = False,
|
||||||
filter_maintainer_requests: bool = False,
|
filter_maintainer_requests: bool = False,
|
||||||
|
filter_pkg_name: str = None,
|
||||||
):
|
):
|
||||||
context = make_context(request, "Requests")
|
context = make_context(request, "Requests")
|
||||||
|
|
||||||
context["q"] = dict(request.query_params)
|
context["q"] = dict(request.query_params)
|
||||||
|
|
||||||
|
# Set pending filter by default if no status filter was provided.
|
||||||
|
# In case we got a package name filter, but no status filter,
|
||||||
|
# we enable the other ones too.
|
||||||
if not dict(request.query_params).keys() & FILTER_PARAMS:
|
if not dict(request.query_params).keys() & FILTER_PARAMS:
|
||||||
filter_pending = True
|
filter_pending = True
|
||||||
|
if filter_pkg_name:
|
||||||
|
filter_closed = True
|
||||||
|
filter_accepted = True
|
||||||
|
filter_rejected = True
|
||||||
|
|
||||||
O, PP = util.sanitize_params(str(O), str(PP))
|
O, PP = util.sanitize_params(str(O), str(PP))
|
||||||
context["O"] = O
|
context["O"] = O
|
||||||
|
@ -56,6 +64,7 @@ async def requests(
|
||||||
context["filter_accepted"] = filter_accepted
|
context["filter_accepted"] = filter_accepted
|
||||||
context["filter_rejected"] = filter_rejected
|
context["filter_rejected"] = filter_rejected
|
||||||
context["filter_maintainer_requests"] = filter_maintainer_requests
|
context["filter_maintainer_requests"] = filter_maintainer_requests
|
||||||
|
context["filter_pkg_name"] = filter_pkg_name
|
||||||
|
|
||||||
Maintainer = orm.aliased(User)
|
Maintainer = orm.aliased(User)
|
||||||
# A PackageRequest query
|
# A PackageRequest query
|
||||||
|
@ -78,7 +87,7 @@ async def requests(
|
||||||
rejected_count = 0 + query.filter(PackageRequest.Status == REJECTED_ID).count()
|
rejected_count = 0 + query.filter(PackageRequest.Status == REJECTED_ID).count()
|
||||||
context["rejected_requests"] = rejected_count
|
context["rejected_requests"] = rejected_count
|
||||||
|
|
||||||
# Apply filters
|
# Apply status filters
|
||||||
in_filters = []
|
in_filters = []
|
||||||
if filter_pending:
|
if filter_pending:
|
||||||
in_filters.append(PENDING_ID)
|
in_filters.append(PENDING_ID)
|
||||||
|
@ -89,6 +98,11 @@ async def requests(
|
||||||
if filter_rejected:
|
if filter_rejected:
|
||||||
in_filters.append(REJECTED_ID)
|
in_filters.append(REJECTED_ID)
|
||||||
filtered = query.filter(PackageRequest.Status.in_(in_filters))
|
filtered = query.filter(PackageRequest.Status.in_(in_filters))
|
||||||
|
|
||||||
|
# Name filter
|
||||||
|
if filter_pkg_name:
|
||||||
|
filtered = filtered.filter(PackageBase.Name == filter_pkg_name)
|
||||||
|
|
||||||
# Additionally filter for requests made from package maintainer
|
# Additionally filter for requests made from package maintainer
|
||||||
if filter_maintainer_requests:
|
if filter_maintainer_requests:
|
||||||
filtered = filtered.filter(PackageRequest.UsersID == PackageBase.MaintainerUID)
|
filtered = filtered.filter(PackageRequest.UsersID == PackageBase.MaintainerUID)
|
||||||
|
|
|
@ -2362,3 +2362,7 @@ msgstr ""
|
||||||
#: templates/partials/packages/comment_form.html
|
#: templates/partials/packages/comment_form.html
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/requests.html
|
||||||
|
msgid "Package name"
|
||||||
|
msgstr ""
|
||||||
|
|
6
static/js/typeahead-requests.js
Normal file
6
static/js/typeahead-requests.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const input = document.getElementById('id_filter_pkg_name');
|
||||||
|
const form = document.getElementById('todolist_filter');
|
||||||
|
const type = 'suggest-pkgbase';
|
||||||
|
typeahead.init(type, input, form);
|
||||||
|
});
|
|
@ -97,11 +97,19 @@
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if requests %}
|
{% if requests %}
|
||||||
<li>
|
{% if request.user.has_credential(creds.PKGREQ_LIST) %}
|
||||||
<span class="flagged">
|
<li>
|
||||||
{{ requests | tn("%d pending request", "%d pending requests") | format(requests) }}
|
<a class="flagged" href="/requests?filter_pkg_name={{ pkgbase.Name }}">
|
||||||
</span>
|
{{ requests | tn("%d pending request", "%d pending requests") | format(requests) }}
|
||||||
</li>
|
</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<span class="flagged">
|
||||||
|
{{ requests | tn("%d pending request", "%d pending requests") | format(requests) }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/pkgbase/{{ pkgbase.Name }}/request?{{ {'next': '/pkgbase/%s' | format(pkgbase.Name)} | urlencode }}">
|
<a href="/pkgbase/{{ pkgbase.Name }}/request?{{ {'next': '/pkgbase/%s' | format(pkgbase.Name)} | urlencode }}">
|
||||||
|
|
|
@ -62,7 +62,13 @@
|
||||||
value="True" {{ "checked" if filter_maintainer_requests == true }}/>
|
value="True" {{ "checked" if filter_maintainer_requests == true }}/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button type='submit' class='button' name='submit' value='Filter'>{{ "Filter" | tr }}</button>
|
<label for="id_filter_pkg_name" title="Package name">{{ "Package name" | tr }}</label>
|
||||||
|
<input type="text" name="filter_pkg_name" id="id_filter_pkg_name" autocomplete="off"
|
||||||
|
value="{{ filter_pkg_name if filter_pkg_name }}"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<br/>
|
||||||
|
<input type="submit" class="button" name="filter" value="{{ 'Filter' | tr }}"></input>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
@ -194,4 +200,7 @@
|
||||||
{% include "partials/pager.html" %}
|
{% include "partials/pager.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap typeahead for requests page. -->
|
||||||
|
<script type="text/javascript" src="/static/js/typeahead-requests.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -555,6 +555,16 @@ def test_package_authenticated(client: TestClient, user: User, package: Package)
|
||||||
for expected_text in expected:
|
for expected_text in expected:
|
||||||
assert expected_text in resp.text
|
assert expected_text in resp.text
|
||||||
|
|
||||||
|
# make sure we don't have these. Only for Maintainer/TUs/Devs
|
||||||
|
not_expected = [
|
||||||
|
"Disown Package",
|
||||||
|
"View Requests",
|
||||||
|
"Delete Package",
|
||||||
|
"Merge Package",
|
||||||
|
]
|
||||||
|
for unexpected_text in not_expected:
|
||||||
|
assert unexpected_text not in resp.text
|
||||||
|
|
||||||
# When no requests are up, make sure we don't see the display for them.
|
# When no requests are up, make sure we don't see the display for them.
|
||||||
root = parse_root(resp.text)
|
root = parse_root(resp.text)
|
||||||
selector = '//div[@id="actionlist"]/ul/li/span[@class="flagged"]'
|
selector = '//div[@id="actionlist"]/ul/li/span[@class="flagged"]'
|
||||||
|
@ -586,8 +596,19 @@ def test_package_authenticated_maintainer(
|
||||||
for expected_text in expected:
|
for expected_text in expected:
|
||||||
assert expected_text in resp.text
|
assert expected_text in resp.text
|
||||||
|
|
||||||
|
# make sure we don't have these. Only for TUs/Devs
|
||||||
|
not_expected = [
|
||||||
|
"1 pending request",
|
||||||
|
"Delete Package",
|
||||||
|
"Merge Package",
|
||||||
|
]
|
||||||
|
for unexpected_text in not_expected:
|
||||||
|
assert unexpected_text not in resp.text
|
||||||
|
|
||||||
def test_package_authenticated_tu(client: TestClient, tu_user: User, package: Package):
|
|
||||||
|
def test_package_authenticated_tu(
|
||||||
|
client: TestClient, tu_user: User, package: Package, pkgreq: PackageRequest
|
||||||
|
):
|
||||||
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
|
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
|
||||||
with client as request:
|
with client as request:
|
||||||
request.cookies = cookies
|
request.cookies = cookies
|
||||||
|
@ -603,6 +624,7 @@ def test_package_authenticated_tu(client: TestClient, tu_user: User, package: Pa
|
||||||
"Vote for this package",
|
"Vote for this package",
|
||||||
"Enable notifications",
|
"Enable notifications",
|
||||||
"Manage Co-Maintainers",
|
"Manage Co-Maintainers",
|
||||||
|
"1 pending request",
|
||||||
"Submit Request",
|
"Submit Request",
|
||||||
"Delete Package",
|
"Delete Package",
|
||||||
"Merge Package",
|
"Merge Package",
|
||||||
|
|
|
@ -912,6 +912,44 @@ def test_requests_for_maintainer_requests(
|
||||||
assert len(rows) == 2
|
assert len(rows) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_requests_with_package_name_filter(
|
||||||
|
client: TestClient,
|
||||||
|
tu_user: User,
|
||||||
|
user2: User,
|
||||||
|
packages: list[Package],
|
||||||
|
requests: list[PackageRequest],
|
||||||
|
):
|
||||||
|
# test as TU
|
||||||
|
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
|
||||||
|
with client as request:
|
||||||
|
request.cookies = cookies
|
||||||
|
resp = request.get(
|
||||||
|
"/requests",
|
||||||
|
params={"filter_pkg_name": packages[0].PackageBase.Name},
|
||||||
|
)
|
||||||
|
assert resp.status_code == int(HTTPStatus.OK)
|
||||||
|
|
||||||
|
root = parse_root(resp.text)
|
||||||
|
rows = root.xpath('//table[@class="results"]/tbody/tr')
|
||||||
|
# We only expect 1 request for our first package
|
||||||
|
assert len(rows) == 1
|
||||||
|
|
||||||
|
# test as regular user, not related to our package
|
||||||
|
cookies = {"AURSID": user2.login(Request(), "testPassword")}
|
||||||
|
with client as request:
|
||||||
|
request.cookies = cookies
|
||||||
|
resp = request.get(
|
||||||
|
"/requests",
|
||||||
|
params={"filter_pkg_name": packages[0].PackageBase.Name},
|
||||||
|
)
|
||||||
|
assert resp.status_code == int(HTTPStatus.OK)
|
||||||
|
|
||||||
|
root = parse_root(resp.text)
|
||||||
|
rows = root.xpath('//table[@class="results"]/tbody/tr')
|
||||||
|
# We don't expect to get any requests
|
||||||
|
assert len(rows) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_requests_by_deleted_users(
|
def test_requests_by_deleted_users(
|
||||||
client: TestClient, user: User, tu_user: User, pkgreq: PackageRequest
|
client: TestClient, user: User, tu_user: User, pkgreq: PackageRequest
|
||||||
):
|
):
|
||||||
|
|
Loading…
Add table
Reference in a new issue