mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
[FastAPI] Basic pkgbase template
Co-author: Kevin Morris <kevr@0cost.org> Signed-off-by: Leonidas Spyropoulos <artafinde@gmail.com> Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
9197f86a03
commit
1e1c0c3fe5
6 changed files with 303 additions and 1 deletions
|
@ -18,7 +18,7 @@ from aurweb.auth import BasicAuthBackend
|
|||
from aurweb.db import get_engine, query
|
||||
from aurweb.models.accepted_term import AcceptedTerm
|
||||
from aurweb.models.term import Term
|
||||
from aurweb.routers import accounts, auth, errors, html, rss, sso, trusted_user
|
||||
from aurweb.routers import accounts, auth, errors, html, packages, rss, sso, trusted_user
|
||||
|
||||
# Setup the FastAPI app.
|
||||
app = FastAPI(exception_handlers=errors.exceptions)
|
||||
|
@ -51,6 +51,7 @@ async def app_startup():
|
|||
app.include_router(accounts.router)
|
||||
app.include_router(trusted_user.router)
|
||||
app.include_router(rss.router)
|
||||
app.include_router(packages.router)
|
||||
|
||||
# Initialize the database engine and ORM.
|
||||
get_engine()
|
||||
|
|
37
aurweb/routers/packages.py
Normal file
37
aurweb/routers/packages.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from http import HTTPStatus
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
|
||||
import aurweb.models.package
|
||||
import aurweb.models.package_comment
|
||||
import aurweb.models.package_keyword
|
||||
|
||||
from aurweb import db
|
||||
from aurweb.models.package_base import PackageBase
|
||||
from aurweb.templates import make_variable_context, render_template
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/packages/{package}")
|
||||
async def package_base(request: Request, package: str):
|
||||
package = db.query(PackageBase).filter(PackageBase.Name == package).first()
|
||||
if not package:
|
||||
raise HTTPException(status_code=int(HTTPStatus.NOT_FOUND))
|
||||
|
||||
context = await make_variable_context(request, package.Name)
|
||||
context["git_clone_uri_anon"] = aurweb.config.get("options", "git_clone_uri_anon")
|
||||
context["git_clone_uri_priv"] = aurweb.config.get("options", "git_clone_uri_priv")
|
||||
context["pkgbase"] = package
|
||||
context["packages"] = package.packages.all()
|
||||
context["packages_count"] = package.packages.count()
|
||||
context["keywords"] = package.keywords.all()
|
||||
context["comments"] = package.comments.all()
|
||||
|
||||
return render_template(request, "pkgbase.html", context)
|
||||
|
||||
|
||||
@router.get("/pkgbase/{package}")
|
||||
async def package_base_redirect(request: Request, package: str):
|
||||
return RedirectResponse(f"/packages/{package}")
|
73
templates/partials/packages/comments.html
Normal file
73
templates/partials/packages/comments.html
Normal file
|
@ -0,0 +1,73 @@
|
|||
<!--
|
||||
This partial requires the following to render properly
|
||||
- pkgname
|
||||
- pkgbase-id
|
||||
- comments (list)
|
||||
-->
|
||||
|
||||
<div id="generic-form" class="box">
|
||||
<h2>Add Comment</h2>
|
||||
<form action="/pkgbase/{{ pkgname }}/" method="post">
|
||||
<fieldset>
|
||||
<div>
|
||||
<input type="hidden" name="action" value="do_AddComment"/>
|
||||
<input type="hidden" name="ID" value="{{ pkgbase_id }}"/>
|
||||
</div>
|
||||
<p>
|
||||
Git commit identifiers referencing commits in the AUR package
|
||||
repository and URLs are converted to links automatically.
|
||||
<a href="https://daringfireball.net/projects/markdown/syntax">
|
||||
Markdown syntax
|
||||
</a>
|
||||
is partially supported.
|
||||
</p>
|
||||
<p>
|
||||
<textarea id="id_comment" name="comment" cols="80" rows="10"></textarea>
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" value="Add Comment"/>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="comments package-comments">
|
||||
<div class="comments-header">
|
||||
<h3>
|
||||
<span class="text">Latest Comments</span>
|
||||
<span class="arrow"></span>
|
||||
</h3>
|
||||
</div>
|
||||
{% for comment in comments %}
|
||||
<h4 id="comment-{{ comment.ID }}" class="comment-header">
|
||||
{% set commentTimestamp = comment.CommentTS | dt | as_timezone(timezone) %}
|
||||
<a href="/account/{{ comment.User.Username }}" title="View account information for {{ comment.User.Username }}">{{ comment.User.Username }}</a>
|
||||
commented on <a href="#comment-{{ comment.ID }}" class="date">{{ "%s" | tr | format(commentTimestamp.strftime("%Y-%m-%d %H:%M")) }}</a>
|
||||
{% if request.user.is_authenticated() and pkgbase.Maintainer.Username == request.user.Username %}
|
||||
<form class="delete-comment-form" method="post" action="/pkgbase/{{ pkgname }}/">
|
||||
<fieldset style="display:inline;">
|
||||
<input type="hidden" name="action" value="do_DeleteComment" />
|
||||
<input type="hidden" name="comment_id" value="{{ comment.ID }}"/>
|
||||
<input type="hidden" name="return_to" value="/pkgbase/{{ pkgname }}/"/>
|
||||
<input type="image" class="delete-comment" src="/images/x.min.svg" width="11" height="11" alt="Delete comment" title="Delete comment" name="submit" value="1" />
|
||||
</fieldset>
|
||||
</form>
|
||||
<a href="/pkgbase/{{ pkgname }}/edit-comment/?comment_id={{ comment.ID }}" class="edit-comment" title="Edit comment"><img src="/images/pencil.min.svg" alt="Edit comment" width="11" height="11"></a>
|
||||
{% endif %}
|
||||
<form class="pin-comment-form" method="post" action="/pkgbase/{{ pkgname }}/">
|
||||
<fieldset style="display:inline;">
|
||||
<input type="hidden" name="action" value="do_PinComment"/>
|
||||
<input type="hidden" name="comment_id" value="{{ comment.ID }}"/>
|
||||
<input type="hidden" name="package_base" value="{{ pkgbase_id }}"/>
|
||||
<input type="hidden" name="return_to" value="/pkgbase/{{ pkgname }}/"/>
|
||||
<input type="image" class="pin-comment" src="/images/pin.min.svg" width="11" height="11" alt="Pin comment" title="Pin comment" name="submit" value="1"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</h4>
|
||||
<div id="comment-{{ comment.ID }}-content" class="article-content">
|
||||
<div>
|
||||
<p>{{ comment.Comments }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
33
templates/partials/packages/package_actions.html
Normal file
33
templates/partials/packages/package_actions.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!--
|
||||
This partial requires pkgname to render
|
||||
-->
|
||||
<div id="detailslinks" class="listing">
|
||||
<div id="actionlist">
|
||||
<h4>Package Actions</h4>
|
||||
<ul class="small">
|
||||
<li>
|
||||
<a href="/cgit/aur.git/tree/PKGBUILD?h={{ pkgname }}">View PKGBUILD</a> /
|
||||
<a href="/cgit/aur.git/log/?h={{ pkgname }}">View Changes</a>
|
||||
</li>
|
||||
<li><a href="/cgit/aur.git/snapshot/{{ pkgname }}.tar.gz">Download snapshot</a>
|
||||
<li><a href="https://wiki.archlinux.org/title/Special:Search?search={{ pkgname }}">Search wiki</a></li>
|
||||
<li><span class="flagged"></span></li>
|
||||
<li><a href="/pkgbase/{{ pkgname }}/flag/">Flag package out-of-date</a></li>
|
||||
<li>
|
||||
<form action="/pkgbase/{{ pkgname }}/vote/" method="post"><input type="submit" class="button text-button" name="do_Vote" value="Vote for this package"/></form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="/pkgbase/{{ pkgname }}/unnotify/" method="post"><input type="submit" class="button text-button" name="do_UnNotify" value="Disable notifications"/>
|
||||
</form>
|
||||
</li>
|
||||
<li><a href="/pkgbase/{{ pkgname }}/comaintainers/">Manage Co-Maintainers</a></li>
|
||||
<li><span class="flagged"></span></li>
|
||||
<li><a href="/pkgbase/{{ pkgname }}/request/">Submit Request</a></li>
|
||||
<li><a href="/pkgbase/{{ pkgname }}/delete/">Delete Package</a></li>
|
||||
<li><a href="/pkgbase/{{ pkgname }}/merge/">Merge Package</a></li>
|
||||
<li>
|
||||
<form action="/pkgbase/{{ pkgname }}/disown/" method="post"><input type="submit" class="button text-button" name="do_Disown" value="Disown Package"/></form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
69
templates/partials/packages/search.html
Normal file
69
templates/partials/packages/search.html
Normal file
|
@ -0,0 +1,69 @@
|
|||
<div id="pkglist-search" class="box filter-criteria">
|
||||
<h2>{% trans %}Search Criteria{% endtrans %}</h2>
|
||||
<form action='/packages/' method='get'>
|
||||
<p><input type='hidden' name='O' value='0'/></p>
|
||||
|
||||
<fieldset>
|
||||
<legend>Enter search criteria</legend>
|
||||
<div>
|
||||
<label for="id_method">Search by</label>
|
||||
<select name='SeB'>
|
||||
<option value="nd">Name, Description</option>
|
||||
<option value="n">Name Only</option>
|
||||
<option value="b">Package Base</option>
|
||||
<option value="N">Exact Name</option>
|
||||
<option value="B">Exact Package Base</option>
|
||||
<option value="k">Keywords</option>
|
||||
<option value="m">Maintainer</option>
|
||||
<option value="c">Co-maintainer</option>
|
||||
<option value="M">Maintainer, Co-maintainer</option>
|
||||
<option value="s">Submitter</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_q">Keywords</label>
|
||||
<input type='text' name='K' size='30' value="" maxlength='35'/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_out_of_date">Out of Date</label>
|
||||
<select name='outdated'>
|
||||
<option value=''>All</option>
|
||||
<option value='on'>Flagged</option>
|
||||
<option value='off'>Not Flagged</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_sort_by">Sort by</label>
|
||||
<select name='SB'>
|
||||
<option value='n'>Name</option>
|
||||
<option value='v'>Votes</option>
|
||||
<option value='p'>Popularity</option>
|
||||
<option value='w'>Voted</option>
|
||||
<option value='o'>Notify</option>
|
||||
<option value='m'>Maintainer</option>
|
||||
<option value='l'>Last modified</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_order_by">Sort order</label>
|
||||
<select name='SO'>
|
||||
<option value='a'>Ascending</option>
|
||||
<option value='d'>Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_per_page">Per page</label>
|
||||
<select name='PP'>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
<option value="250">250</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label> </label>
|
||||
<input type='submit' class='button' name='do_Search' value='Go'/>
|
||||
<input type='submit' class='button' name='do_Orphans' value='Orphans'/>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
89
templates/pkgbase.html
Normal file
89
templates/pkgbase.html
Normal file
|
@ -0,0 +1,89 @@
|
|||
{% extends "partials/layout.html" %}
|
||||
|
||||
{% block pageContent %}
|
||||
{% include "partials/packages/search.html" %}
|
||||
<div id="pkgdetails" class="box">
|
||||
<h2>Package Base Details: {{ pkgbase.Name }}</h2>
|
||||
|
||||
{% set result = pkgbase %}
|
||||
{% set pkgname = "result.Name" %}
|
||||
{% include "partials/packages/package_actions.html" %}
|
||||
|
||||
<table id="pkginfo">
|
||||
<tr>
|
||||
<th>Git Clone URL: </th>
|
||||
<td>
|
||||
<a class="copy" href="{{ git_clone_uri_anon | format(pkgbase.Name) }}">{{ git_clone_uri_anon | format(pkgbase.Name) }}</a> (read-only, click to copy)
|
||||
{% if request.user.is_authenticated() and pkgbase.Maintainer.Username == request.user.Username %}
|
||||
<br /> <a class="copy" href="{{ git_clone_uri_priv | format(pkgbase.Name) }}">{{ git_clone_uri_priv | format(pkgbase.Name) }}</a> (click to copy)
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Keywords: </th>
|
||||
{% if request.user.is_authenticated() and pkgbase.Maintainer.Username == request.user.Username %}
|
||||
<td>
|
||||
<form method="post" action="/pkgbase/{{ pkgbase.Name }}/">
|
||||
<div>
|
||||
<input type="hidden" name="action" value="do_SetKeywords" />
|
||||
<input type="text" name="keywords" value="{{ pkgbase.keywords | join(' ', attribute='Keyword') }}"/>
|
||||
<input type="submit" value="Update"/>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>
|
||||
{% for item in pkgbase.keywords %}
|
||||
<a class="keyword" href="/packages/?K={{ item.Keyword }}&SB=p">{{ item.Keyword }}</a>
|
||||
{% endfor %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Submitter: </th>
|
||||
<td>{{ pkgbase.Submitter.Username | default("None") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Maintainer: </th>
|
||||
<td>{{ pkgbase.Maintainer.Username | default("None") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Last Packager: </th>
|
||||
<td>{{ pkgbase.Packager.Username | default("None") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Votes: </th>
|
||||
<td>{{ pkgbase.NumVotes }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Popularity: </th>
|
||||
<td>{{ '%0.2f' % pkgbase.Popularity | float }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% set submitted = pkgbase.SubmittedTS | dt | as_timezone(timezone) %}
|
||||
<th>First Submitted: </th>
|
||||
<td>{{ "%s" | tr | format(submitted.strftime("%Y-%m-%d %H:%M")) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Last Updated: </th>
|
||||
{% set updated = pkgbase.ModifiedTS | dt | as_timezone(timezone) %}
|
||||
<td>{{ "%s" | tr | format(updated.strftime("%Y-%m-%d %H:%M")) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div id="metadata">
|
||||
<div id="pkgs" class="listing">
|
||||
<h3>Packages ({{ packages_count }})</h3>
|
||||
<ul>
|
||||
{% for result in packages %}
|
||||
<li><a href="/packages/{{ result.Name }}/" title="View packages details for {{ result.Name }}">{{ result.Name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% set pkgname = result.Name %}
|
||||
{% set pkgbase_id = result.ID %}
|
||||
{% set comments = comments %}
|
||||
{% include "partials/packages/comments.html" %}
|
||||
{% endblock %}
|
Loading…
Add table
Reference in a new issue