mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
feat(FastAPI): add /packages (get) search
In terms of performance, most queries on this page win over PHP in query times, with the exception of sorting by Voted or Notify (https://gitlab.archlinux.org/archlinux/aurweb/-/issues/102). Otherwise, there are a few modifications: described below. * Pagination * The `paginate` Python module has been used in the FastAPI project here to implement paging on the packages search page. This changes how pagination is displayed, however it serves the same purpose. We'll take advantage of this module in other places as well. * Form action * The form action for actions now use `POST /packages` to perform. This is currently implemented and will be addressed in a follow-up commit. * Input names and values * Input names and values have been modified to satisfy the snake_case naming convention we'd like to use as much as possible. * Some input names and values were modified to comply with FastAPI Forms: (IDs[<id>]) -> (IDs, <id>). Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
6298b1228a
commit
5cf7062092
11 changed files with 1081 additions and 30 deletions
84
templates/packages.html
Normal file
84
templates/packages.html
Normal file
|
@ -0,0 +1,84 @@
|
|||
{% extends "partials/layout.html" %}
|
||||
|
||||
{% block pageContent %}
|
||||
{% if errors %}
|
||||
|
||||
<ul class="errorlist">
|
||||
{% for error in errors %}
|
||||
<li>{{ error | tr }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% include "partials/packages/search.html" %}
|
||||
|
||||
{% else %}
|
||||
|
||||
{% set pages = (packages_count / PP) | ceil %}
|
||||
{% set page = O / PP %}
|
||||
|
||||
{% if success %}
|
||||
<ul class="success">
|
||||
{% for message in success %}
|
||||
<li>{{ message | tr }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Search form #}
|
||||
{% include "partials/packages/search.html" %}
|
||||
<div id="pkglist-results" class="box">
|
||||
|
||||
{# /packages does things a bit roundabout-wise:
|
||||
|
||||
If SeB is not given, "nd" is the default.
|
||||
If SB is not given, "n" is the default.
|
||||
If SO is not given, "d" is the default.
|
||||
|
||||
However, we depend on flipping SO for column sorting.
|
||||
|
||||
This section sets those defaults for the context if
|
||||
they are not already setup. #}
|
||||
{% if not SeB %}
|
||||
{% set SeB = "nd" %}
|
||||
{% endif %}
|
||||
{% if not SB %}
|
||||
{% set SB = "n" %}
|
||||
{% endif %}
|
||||
{% if not SO %}
|
||||
{% set SO = "d" %}
|
||||
{% endif %}
|
||||
|
||||
{# Pagination widget #}
|
||||
{% with total = packages_count,
|
||||
singular = "%d package found.",
|
||||
plural = "%d packages found.",
|
||||
prefix = "/packages" %}
|
||||
{% include "partials/widgets/pager.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{# Package action form #}
|
||||
<form id="pkglist-results-form"
|
||||
action="/packages/?{{ q | urlencode }}"
|
||||
method="post">
|
||||
|
||||
{# Search results #}
|
||||
{% with voted = packages_voted, notified = packages_notified %}
|
||||
{% include "partials/packages/search_results.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{# Pagination widget #}
|
||||
{% with total = packages_count,
|
||||
singular = "%d package found.",
|
||||
plural = "%d packages found.",
|
||||
prefix = "/packages" %}
|
||||
{% include "partials/widgets/pager.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% if request.user.is_authenticated() %}
|
||||
{# Package actions #}
|
||||
{% include "partials/packages/search_actions.html" %}
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -8,61 +8,65 @@
|
|||
<div>
|
||||
<label for="id_method">{{ "Search by" | tr }}</label>
|
||||
<select name='SeB'>
|
||||
<option value="nd">{{ "Name, Description" | tr }}</option>
|
||||
<option value="n">{{ "Name Only" | tr }}</option>
|
||||
<option value="b">{{ "Package Base" | tr }}</option>
|
||||
<option value="N">{{ "Exact Name" | tr }}</option>
|
||||
<option value="B">{{ "Exact Package Base" | tr }}</option>
|
||||
<option value="k">{{ "Keywords" | tr }}</option>
|
||||
<option value="m">{{ "Maintainer" | tr }}</option>
|
||||
<option value="c">{{ "Co-maintainer" | tr }}</option>
|
||||
<option value="M">{{ "Maintainer, Co-maintainer" | tr }}</option>
|
||||
<option value="s">{{ "Submitter" | tr }}</option>
|
||||
<option value="nd" {% if SeB == "nd" %}selected{% endif %}>{{ "Name, Description" | tr }}</option>
|
||||
<option value="n" {% if SeB == "n" %}selected{% endif %}>{{ "Name Only" | tr }}</option>
|
||||
<option value="b" {% if SeB == "b" %}selected{% endif%}>{{ "Package Base" | tr }}</option>
|
||||
<option value="N" {% if SeB == "N" %}selected{% endif %}>{{ "Exact Name" | tr }}</option>
|
||||
<option value="B" {% if SeB == "B" %}selected{% endif %}>{{ "Exact Package Base" | tr }}</option>
|
||||
<option value="k" {% if SeB == "k" %}selected{% endif %}>{{ "Keywords" | tr }}</option>
|
||||
<option value="m" {% if SeB == "m" %}selected{% endif %}>{{ "Maintainer" | tr }}</option>
|
||||
<option value="c" {% if SeB == "c" %}selected{% endif %}>{{ "Co-maintainer" | tr }}</option>
|
||||
<option value="M" {% if SeB == "M" %}selected{% endif %}>{{ "Maintainer, Co-maintainer" | tr }}</option>
|
||||
<option value="s" {% if SeB == "s" %}selected{% endif %}>{{ "Submitter" | tr }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_q">{{ "Keywords" | tr }}</label>
|
||||
<input type='text' name='K' size='30' value="" maxlength='35'/>
|
||||
<input type='text' name='K' size='30' value="{{ K or '' }}" maxlength='35'/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_out_of_date">{{ "Out of Date" | tr }}</label>
|
||||
<select name='outdated'>
|
||||
<option value=''>{{ "All" | tr }}</option>
|
||||
<option value='on'>{{ "Flagged" | tr }}</option>
|
||||
<option value='off'>{{ "Not Flagged" | tr }}</option>
|
||||
<option value='on' {% if outdated == "on" %}selected{% endif %}>{{ "Flagged" | tr }}</option>
|
||||
<option value='off' {% if outdated == "off" %}selected{% endif %}>{{ "Not Flagged" | tr }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_sort_by">{{ "Sort by" | tr }}</label>
|
||||
<select name='SB'>
|
||||
<option value='n'>{{ "Name" | tr }}</option>
|
||||
<option value='v'>{{ "Votes" | tr }}</option>
|
||||
<option value='p'>{{ "Popularity" | tr }}</option>
|
||||
<option value='w'>{{ "Voted" | tr }}</option>
|
||||
<option value='o'>{{ "Notify" | tr }}</option>
|
||||
<option value='m'>{{ "Maintainer" | tr }}</option>
|
||||
<option value='l'>{{ "Last modified" | tr }}</option>
|
||||
<option value='n' {% if SB == "n" %}selected{% endif %}>{{ "Name" | tr }}</option>
|
||||
<option value='v' {% if SB == "v" %}selected{% endif %}>{{ "Votes" | tr }}</option>
|
||||
<option value='p' {% if SB == "p" %}selected{% endif %}>{{ "Popularity" | tr }}</option>
|
||||
<option value='w' {% if SB == "w" %}selected{% endif %}>{{ "Voted" | tr }}</option>
|
||||
<option value='o' {% if SB == "o" %}selected{% endif %}>{{ "Notify" | tr }}</option>
|
||||
<option value='m' {% if SB == "m" %}selected{% endif %}>{{ "Maintainer" | tr }}</option>
|
||||
<option value='l' {% if SB == "l" %}selected{% endif %}>{{ "Last modified" | tr }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_order_by">{{ "Sort order" | tr }}</label>
|
||||
<select name='SO'>
|
||||
<option value='a'>{{ "Ascending" | tr }}</option>
|
||||
<option value='d'>{{ "Descending" | tr }}</option>
|
||||
<option value='a' {% if SO == "a" %}selected{% endif %}>{{ "Ascending" | tr }}</option>
|
||||
<option value='d' {% if SO == "d" %}selected{% endif %}>{{ "Descending" | tr }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_per_page">{{ "Per page" | tr }}</label>
|
||||
<select name='PP'>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
<option value="250">250</option>
|
||||
<option value="50" {% if PP == 50 %}selected{% endif %}>50</option>
|
||||
<option value="100" {% if PP == 100 %}selected{% endif %}>100</option>
|
||||
<option value="250" {% if PP == 250 %}selected{% endif %}>250</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label> </label>
|
||||
<input type='submit' class='button' name='do_Search' value='{{ "Go" | tr }}'/>
|
||||
<input type='submit' class='button' name='do_Orphans' value='{{ "Orphans" | tr }}'/>
|
||||
<button type='submit' class='button' name='submit' value='Go'>
|
||||
{{ "Go" | tr }}
|
||||
</button>
|
||||
<button type='submit' class='button' name='submit' value='Orphans'>
|
||||
{{ "Orphans" | tr }}
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
25
templates/partials/packages/search_actions.html
Normal file
25
templates/partials/packages/search_actions.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<p>
|
||||
<select name="action">
|
||||
<option value="">{{ "Actions" | tr }}</option>
|
||||
<option value="unflag">{{ "Unflag Out-of-date" | tr }}</option>
|
||||
<option value="adopt">{{ "Adopt Packages" | tr }}</option>
|
||||
<option value="disown">{{ "Disown Packages" | tr }}</option>
|
||||
{% if request.user.is_trusted_user() or request.user.is_developer() %}
|
||||
<option value="delete">{{ "Delete Packages" | tr }}</option>
|
||||
{% endif %}
|
||||
<option value="notify">{{ "Notify" | tr }}</option>
|
||||
<option value="unnotify">{{ "UnNotify" | tr }}</option>
|
||||
</select>
|
||||
|
||||
{% if request.user.is_trusted_user() or request.user.is_developer() %}
|
||||
<label for="merge_into">{{ "Merge into" | tr }}</label>
|
||||
<input id="merge_into" type="text" name="merge_into" />
|
||||
{% endif %}
|
||||
|
||||
<label class="confirmation">
|
||||
<input type="checkbox" name="confirm" />
|
||||
Confirm
|
||||
</label>
|
||||
|
||||
<input id="search-action-submit" class="button" type="submit" value="Go" />
|
||||
</p>
|
114
templates/partials/packages/search_results.html
Normal file
114
templates/partials/packages/search_results.html
Normal file
|
@ -0,0 +1,114 @@
|
|||
<table {% if table_id %}id="{{ table_id }}"{% endif %} class="results">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if request.user.is_authenticated() %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "n" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=n&SO={{ order }}">
|
||||
{{ "Name" | tr }}
|
||||
</a>
|
||||
</th>
|
||||
<th>{{ "Version" | tr }}</th>
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "v" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=v&SO={{ order }}">
|
||||
{{ "Votes" | tr }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "p" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=p&SO={{ order }}">{{ "Popularity" | tr }}</a><span title="{{ 'Popularity is calculated as the sum of all votes with each vote being weighted with a factor of %.2f per day since its creation.' | format(0.98) }}" class="hover-help"><sup>?</sup></span>
|
||||
</th>
|
||||
{% if request.user.is_authenticated() %}
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "w" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=w&SO={{ order }}">
|
||||
{{ "Voted" | tr }}
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "o" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=o&SO={{ order }}">
|
||||
{{ "Notify" | tr }}
|
||||
</a>
|
||||
</th>
|
||||
{% endif %}
|
||||
<th>{{ "Description" | tr }}</th>
|
||||
<th>
|
||||
{% set order = SO %}
|
||||
{% if SB == "m" %}
|
||||
{% set order = "d" if order == "a" else "a" %}
|
||||
{% endif %}
|
||||
<a href="/packages/?SB=m&SO={{ order }}">
|
||||
{{ "Maintainer" | tr }}
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pkg in packages %}
|
||||
{% set flagged = pkg.PackageBase.OutOfDateTS %}
|
||||
<tr>
|
||||
{% if request.user.is_authenticated() %}
|
||||
<td>
|
||||
<input type="checkbox" name="IDs" value="{{ pkg.ID }}" />
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
<a href="/packages/{{ pkg.Name }}">
|
||||
{{ pkg.Name }}
|
||||
</a>
|
||||
</td>
|
||||
{% if flagged %}
|
||||
<td class="flagged">{{ pkg.Version }}</td>
|
||||
{% else %}
|
||||
<td>{{ pkg.Version }}</td>
|
||||
{% endif %}
|
||||
<td>{{ pkg.PackageBase.NumVotes }}</td>
|
||||
<td>
|
||||
{{ pkg.PackageBase.Popularity | number_format(2) }}
|
||||
</td>
|
||||
{% if request.user.is_authenticated() %}
|
||||
<td>
|
||||
{% if pkg.PackageBase.ID in voted %}
|
||||
{{ "Yes" | tr }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if pkg.PackageBase.ID in notified %}
|
||||
{{ "Yes" | tr }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td class="wrap">{{ pkg.Description or '' }}</td>
|
||||
<td>
|
||||
{% set maintainer = pkg.PackageBase.Maintainer %}
|
||||
{% if maintainer %}
|
||||
<a href="/account/{{ maintainer.Username }}">
|
||||
{{ maintainer.Username }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="error">{{ "orphan" | tr }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
Loading…
Add table
Add a link
Reference in a new issue