diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-04-13 20:25:24 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-04-13 20:25:24 -0400 |
commit | c266efc7fc73f94995bffcdf8e0ef7a4aeb563c3 (patch) | |
tree | 2b96d2ff0f7e0a0d164a28b152b51fbb2f87b76f | |
parent | ea00a099dffd7157c93af54b5817734348d2bbc6 (diff) | |
parent | 9589a7eadeb05e82c2d63f6fe128316fdb6dcc8a (diff) |
Merge tag 'release_2014-10-19' into archweb-generic
Jinja2 switch for some templates, exact matches in package search
22 files changed, 399 insertions, 360 deletions
diff --git a/devel/views.py b/devel/views.py index 92cb098e..66f6a965 100644 --- a/devel/views.py +++ b/devel/views.py @@ -197,6 +197,7 @@ def report(request, report_name, username=None): maints = User.objects.filter(id__in=PackageRelation.objects.filter( type=PackageRelation.MAINTAINER).values('user')) + packages = report.packages(packages, username) arches = {pkg.arch for pkg in packages} repos = {pkg.repo for pkg in packages} context = { @@ -204,7 +205,7 @@ def report(request, report_name, username=None): 'title': report.description, 'report': report, 'maintainer': user, - 'packages': report.packages(packages, username), + 'packages': packages, 'arches': sorted(arches), 'repos': sorted(repos), 'column_names': report.names, diff --git a/packages/models.py b/packages/models.py index dd69e7d3..03f03422 100644 --- a/packages/models.py +++ b/packages/models.py @@ -379,6 +379,13 @@ class RelatedToBase(models.Model): given criteria. It will not search provisions, but will find packages named and matching repo characteristics if possible.''' pkgs = Package.objects.normal().filter(pkgname=self.name) + # TODO: this may in fact be faster- select only the fields we know will + # actually get used, saving us some bandwidth and hopefully query + # construction time. However, reality hasn't quite proved it out yet. + #pkgs = Package.objects.select_related('repo', 'arch').only( + # 'id', 'pkgname', 'epoch', 'pkgver', 'pkgrel', + # 'repo__id', 'repo__name', 'repo__testing', 'repo__staging', + # 'arch__id', 'arch__name').filter(pkgname=self.name) if not self.pkg.arch.agnostic: # make sure we match architectures if possible arches = self.pkg.applicable_arches() diff --git a/packages/templatetags/jinja2.py b/packages/templatetags/jinja2.py new file mode 100644 index 00000000..22f9914b --- /dev/null +++ b/packages/templatetags/jinja2.py @@ -0,0 +1,72 @@ +from urllib import urlencode, quote as urlquote, unquote +from django.utils.html import escape +from django_jinja import library +from main.templatetags import pgp + + +@library.filter +def url_unquote(original_url): + try: + url = original_url + if isinstance(url, unicode): + url = url.encode('ascii') + url = unquote(url).decode('utf-8') + return url + except UnicodeError: + return original_url + + +def link_encode(url, query): + # massage the data into all utf-8 encoded strings first, so urlencode + # doesn't barf at the data we pass it + query = {k: unicode(v).encode('utf-8') for k, v in query.items()} + data = urlencode(query) + return "%s?%s" % (url, data) + + +@library.global_function +def pgp_key_link(key_id, link_text=None): + return pgp.pgp_key_link(key_id, link_text) + + +@library.global_function +def scm_link(package, operation): + parts = (package.repo.svn_root, operation, package.pkgbase) + linkbase = ( + "https://projects.archlinux.org/svntogit/%s.git/%s/trunk?" + "h=packages/%s") + return linkbase % tuple(urlquote(part.encode('utf-8')) for part in parts) + + +@library.global_function +def wiki_link(package): + url = "https://wiki.archlinux.org/index.php/Special:Search" + data = { + 'search': package.pkgname, + } + return link_encode(url, data) + + +@library.global_function +def bugs_list(package): + url = "https://bugs.archlinux.org/" + data = { + 'project': package.repo.bugs_project, + 'cat[]': package.repo.bugs_category, + 'string': package.pkgname, + } + return link_encode(url, data) + + +@library.global_function +def bug_report(package): + url = "https://bugs.archlinux.org/newtask" + data = { + 'project': package.repo.bugs_project, + 'product_category': package.repo.bugs_category, + 'item_summary': '[%s] PLEASE ENTER SUMMARY' % package.pkgname, + } + return link_encode(url, data) + + +# vim: set ts=4 sw=4 et: diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py index 3ce64748..73a39092 100644 --- a/packages/templatetags/package_extras.py +++ b/packages/templatetags/package_extras.py @@ -1,33 +1,13 @@ -from urllib import urlencode, quote as urlquote, unquote +from urllib import urlencode try: from urlparse import parse_qs except ImportError: from cgi import parse_qs from django import template -from django.utils.html import escape - -register = template.Library() - - -def link_encode(url, query): - # massage the data into all utf-8 encoded strings first, so urlencode - # doesn't barf at the data we pass it - query = {k: unicode(v).encode('utf-8') for k, v in query.items()} - data = urlencode(query).replace('&', '&') - return "%s?%s" % (url, data) -@register.filter -def url_unquote(original_url): - try: - url = original_url - if isinstance(url, unicode): - url = url.encode('ascii') - url = unquote(url).decode('utf-8') - return url - except UnicodeError: - return original_url +register = template.Library() class BuildQueryStringNode(template.Node): @@ -79,74 +59,4 @@ def pkg_details_link(pkg, link_title=None, honor_flagged=False): return link % (pkg.get_absolute_url(), pkg.pkgname, link_content) -@register.simple_tag -def multi_pkg_details(pkgs): - return ', '.join([pkg_details_link(pkg) for pkg in pkgs]) - - -@register.simple_tag -def maintainer_link(user): - if user: - # TODO don't hardcode - title = escape('View packages maintained by ' + user.get_full_name()) - return '<a href="/packages/?maintainer=%s" title="%s">%s</a>' % ( - user.username, - title, - user.get_full_name(), - ) - return '' - - -@register.simple_tag -def packager_link(user): - if user: - # TODO don't hardcode - title = escape('View packages packaged by ' + user.get_full_name()) - return '<a href="/packages/?packager=%s" title="%s">%s</a>' % ( - user.username, - title, - user.get_full_name(), - ) - return '' - - -@register.simple_tag -def scm_link(package, operation): - parts = (package.repo.svn_root, operation, package.pkgbase) - linkbase = ( - "https://projects.archlinux.org/svntogit/%s.git/%s/trunk?" - "h=packages/%s") - return linkbase % tuple(urlquote(part.encode('utf-8')) for part in parts) - - -@register.simple_tag -def get_wiki_link(package): - url = "https://wiki.archlinux.org/index.php/Special:Search" - data = { - 'search': package.pkgname, - } - return link_encode(url, data) - - -@register.simple_tag -def bugs_list(package): - url = "https://bugs.archlinux.org/" - data = { - 'project': package.repo.bugs_project, - 'cat[]': package.repo.bugs_category, - 'string': package.pkgname, - } - return link_encode(url, data) - - -@register.simple_tag -def bug_report(package): - url = "https://bugs.archlinux.org/newtask" - data = { - 'project': package.repo.bugs_project, - 'product_category': package.repo.bugs_category, - 'item_summary': '[%s] PLEASE ENTER SUMMARY' % package.pkgname, - } - return link_encode(url, data) - # vim: set ts=4 sw=4 et: diff --git a/packages/views/search.py b/packages/views/search.py index b3778172..0b776d79 100644 --- a/packages/views/search.py +++ b/packages/views/search.py @@ -45,6 +45,12 @@ class PackageSearchForm(forms.Form): [('', 'All'), ('unknown', 'Unknown')] + \ [(m.username, m.get_full_name()) for m in maints] + def exact_matches(self): + # only do exact match search if 'q' is sole parameter + if self.changed_data != ['q']: + return [] + return Package.objects.normal().filter(pkgname=self.cleaned_data['q']) + def parse_form(form, packages): if form.cleaned_data['repo']: diff --git a/requirements.txt b/requirements.txt index eff75bad..e2b49aba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,10 @@ -e git+git://github.com/SmileyChris/django-countries.git@a2c924074dbe2f0b9b3059bf70064aeadf5643ed#egg=django-countries Django==1.7 IPy==0.81 +Jinja2==2.7.3 Markdown==2.4.1 bencode==1.0 +django-jinja==1.0.4 jsmin==2.0.11 pgpdump==1.5 pytz>=2014.7 diff --git a/requirements_prod.txt b/requirements_prod.txt index c181c3af..020a5ac4 100644 --- a/requirements_prod.txt +++ b/requirements_prod.txt @@ -2,8 +2,10 @@ -e git+git://github.com/SmileyChris/django-countries.git@a2c924074dbe2f0b9b3059bf70064aeadf5643ed#egg=django-countries Django==1.7 IPy==0.81 +Jinja2==2.7.3 Markdown==2.4.1 bencode==1.0 +django-jinja==1.0.4 jsmin==2.0.11 pgpdump==1.5 psycopg2==2.5.4 diff --git a/settings.py b/settings.py index 8ab95421..c3ffcdce 100644 --- a/settings.py +++ b/settings.py @@ -61,11 +61,13 @@ TEMPLATE_DIRS = ( ) TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.eggs.Loader', - 'django.template.loaders.app_directories.Loader', + 'django_jinja.loaders.FileSystemLoader', + 'django_jinja.loaders.AppLoader', ) +# Send templates matching the following to the Jinja2 engine +DEFAULT_JINJA2_TEMPLATE_EXTENSION = '.jinja' + MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -116,6 +118,7 @@ INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.staticfiles', 'django_countries', + 'django_jinja', 'main', 'mirrors', @@ -203,6 +206,7 @@ if not TEMPLATE_DEBUG: TEMPLATE_LOADERS = ( ('django.template.loaders.cached.Loader', TEMPLATE_LOADERS), ) + JINJA2_BYTECODE_CACHE_ENABLE = True # Enable the debug toolbar if requested if DEBUG_TOOLBAR: diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css index 53fa6274..edabcfb7 100644 --- a/sitestatic/archweb.css +++ b/sitestatic/archweb.css @@ -701,6 +701,10 @@ table.results { color: red; } + .results tr.empty td { + text-align: center; + } + /* pkglist: layout */ #pkglist-about { margin-top: 1.5em; diff --git a/templates/packages/details.html b/templates/packages/details.html index 07406fa2..82f2c604 100644 --- a/templates/packages/details.html +++ b/templates/packages/details.html @@ -1,234 +1,11 @@ {% extends "base.html" %} {% load static from staticfiles %} -{% load package_extras %} -{% load pgp %} {% block title %}{{ BRANDING_DISTRONAME }} - {{ pkg.pkgname }} {{ pkg.full_version }} ({{ pkg.arch.name }}){% endblock %} {% block navbarclass %}anb-packages{% endblock %} -{% load package_extras %} {% block content %} -<div id="pkgdetails" class="box"> - - <h2>{{ pkg.pkgname }} {{ pkg.full_version }}</h2> - - <div id="detailslinks" class="listing"> - <div id="actionlist"> - <h4>Package Actions</h4> - <ul class="small"> - <li> - <a href="{% scm_link pkg 'tree' %}" title="View source files for {{ pkg.pkgname }}">Source Files</a> / - <a href="{% scm_link pkg 'log' %}" title="View changes for {{ pkg.pkgname }}">View Changes</a> - </li> - <li> - <a href="{% bugs_list pkg %}" title="View existing bug tickets for {{ pkg.pkgname }}">Bug Reports</a> / - <a href="{% bug_report pkg %}" title="Report new bug for {{ pkg.pkgname }}">Add New Bug</a> - </li> - <li><a href="{% get_wiki_link pkg %}" title="Search wiki for {{ pkg.pkgname }}">Search Wiki</a></li> - {% if pkg.flag_date %} - <li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date }}</span></li> - {% with pkg.in_testing as tp %}{% if tp %} - <li><span class="flagged">Version - <a href="{{ tp.get_absolute_url }}" - title="Testing package details for {{ tp.pkgname }}">{{ tp.full_version }}</a> - in testing</span></li> - {% endif %}{% endwith %} - {% if perms.main.change_package %} - <li><a href="unflag/" title="Unflag this package">Click here to unflag</a></li> - <li><a href="unflag/all/" title="Unflag all matching pkgbase">Click here to unflag all split packages</a></li> - {% endif %} - {% else %} - <li><a href="flag/" title="Flag {{ pkg.pkgname }} as out-of-date">Flag Package Out-of-Date</a> - <a href="/packages/flaghelp/" - title="Get help on package flagging" - onclick="return !window.open('/packages/flaghelp/','FlagHelp', - 'height=350,width=450,location=no,scrollbars=yes,menubars=no,toolbars=no,resizable=no');">(?)</a></li> - {% endif %} - <li><a href="download/" rel="nofollow" title="Download {{ pkg.pkgname }} from mirror">Download From Mirror</a></li> - </ul> - - {% if perms.main.change_package %} - <form id="pkg-action" method="post" action="/packages/update/">{% csrf_token %} - <div><input type="hidden" name="pkgid" value="{{ pkg.id }}" /></div> - <p>{% if user in pkg.maintainers %} - <input title="Orphan this package" type="submit" name="disown" value="Disown"/> - {% else %} - <input title="Adopt this package" type="submit" name="adopt" value="Adopt"/> - {% endif %}</p> - </form> - {% endif %} - </div> - - {% with pkg.elsewhere as others %}{% if others %} - <div id="elsewhere" class="widget"> - <h4>Versions Elsewhere</h4> - <ul> - {% for o in others %} - <li><a href="{{ o.get_absolute_url }}" - title="Package details for {{ o.pkgname }}">{{ o.pkgname }} {{ o.full_version }} [{{ o.repo.name|lower }}] ({{ o.arch.name }})</a></li> - {% endfor %} - </ul> - </div> - {% endif %}{% endwith %} - </div> - - <div itemscope itemtype="http://schema.org/SoftwareApplication"> - <meta itemprop="name" content="{{ pkg.pkgname|escape }}"/> - <meta itemprop="version" content="{{ pkg.full_version|escape }}"/> - <meta itemprop="softwareVersion" content="{{ pkg.full_version|escape }}"/> - <meta itemprop="fileSize" content="{{ pkg.compressed_size }}"/> - <meta itemprop="dateCreated" content="{{ pkg.build_date|date:"Y-m-d" }}"/> - <meta itemprop="datePublished" content="{{ pkg.last_update|date:"Y-m-d" }}"/> - <meta itemprop="operatingSystem" content="Linux"/> - <div style="display:none" itemprop="provider" itemscope itemtype="http://schema.org/Person"> - <meta itemprop="name" content="{{ pkg.packager.get_full_name|escape }}"/> - </div> - <table id="pkginfo"> - <tr> - <th>Architecture:</th> - <td><a href="/packages/?arch={{ pkg.arch.name }}" - title="Browse packages for {{ pkg.arch.name }} architecture">{{ pkg.arch.name }}</a></td> - </tr><tr> - <th>Repository:</th> - <td><a href="/packages/?repo={{ pkg.repo.name|capfirst }}" - title="Browse the {{ pkg.repo.name|capfirst }} repository">{{ pkg.repo.name|capfirst }}</a></td> - </tr> - {% ifequal pkg.pkgname pkg.pkgbase %} - {% with pkg.split_packages as splits %}{% if splits %} - <tr> - <th>Split Packages:</th> - <td class="wrap relatedto">{% for s in splits %}<span class="related">{% pkg_details_link s %}{% if not forloop.last %}, {% endif %}</span>{% endfor %}</td> - </tr> - {% endif %}{% endwith %} - {% else %} - <tr> - <th>Base Package:</th> - {% with pkg.base_package as base %}{% if base %} - <td>{% pkg_details_link base %}</td> - {% else %} - <td><a href="../{{ pkg.pkgbase }}/" - title="Split package details for {{ pkg.pkgbase }}">{{ pkg.pkgbase }}</a></td> - {% endif %}{% endwith %} - </tr> - {% endifequal %} - <tr> - <th>Description:</th> - <td class="wrap" itemprop="description">{{ pkg.pkgdesc|default:"" }}</td> - </tr><tr> - <th>Upstream URL:</th> - <td>{% if pkg.url %}<a itemprop="url" href="{{ pkg.url }}" - title="Visit the website for {{ pkg.pkgname }}">{{ pkg.url|url_unquote }}</a>{% endif %}</td> - </tr><tr> - <th>License(s):</th> - <td class="wrap">{{ pkg.licenses.all|join:", " }}</td> - </tr> - {% with pkg.groups.all as groups %}{% if groups %} - <tr> - <th>Groups:</th> - <td class="wrap">{% for g in groups %} - <a href="/groups/{{ pkg.arch.name }}/{{ g.name }}/" - title="Group details for {{ g.name }}">{{ g.name }}</a>{% if not forloop.last %}, {% endif %}{% endfor %} - </td> - </tr> - {% endif %}{% endwith %} - {% with pkg.provides.all as all_related %}{% if all_related %} - <tr> - <th>Provides:</th> - <td class="wrap relatedto">{% include "packages/details_relatedto.html" %}</td> - </tr> - {% endif %}{% endwith %} - {% with pkg.replaces.all as all_related %}{% if all_related %} - <tr> - <th>Replaces:</th> - <td class="wrap relatedto">{% include "packages/details_relatedto.html" %}</td> - </tr> - {% endif %}{% endwith %} - {% with pkg.conflicts.all as all_related %}{% if all_related %} - <tr> - <th>Conflicts:</th> - <td class="wrap relatedto">{% include "packages/details_relatedto.html" %}</td> - </tr> - {% endif %}{% endwith %} - {% with pkg.reverse_conflicts as rev_conflicts %}{% if rev_conflicts %} - <tr> - <th>Reverse Conflicts:</th> - <td class="wrap relatedto">{% for conflict in rev_conflicts %} - <span class="related">{% pkg_details_link conflict %}{% if not forloop.last %}, {% endif %}</span>{% endfor %}</td> - </tr> - {% endif %}{% endwith %} - <tr> - <th>Maintainers:</th> - {% with pkg.maintainers as maints %} - <td>{% if maints %} - {% for m in maints %} - {% maintainer_link m %}<br/> - {% endfor %} - {% else %}Orphan{% endif %} - </td> - {% endwith %} - </tr><tr> - <th>Package Size:</th> - <td>{{ pkg.compressed_size|filesizeformat }}</td> - </tr><tr> - <th>Installed Size:</th> - <td>{{ pkg.installed_size|filesizeformat }}</td> - </tr><tr> - <th>Last Packager:</th> - <td>{% with pkg.packager as pkgr %}{% if pkgr %}{% packager_link pkgr %}{% else %}{{ pkg.packager_str }}{% endif %}{% endwith %}</td> - </tr><tr> - <th>Build Date:</th> - <td>{{ pkg.build_date|date:"DATETIME_FORMAT" }} UTC</td> - </tr>{% if pkg.signature %}<tr> - <th>Signed By:</th> - <td>{% with pkg.signer as signer %}{% if signer %}{% pgp_key_link pkg.signature.key_id signer.get_full_name %}{% else %}Unknown ({% pgp_key_link pkg.signature.key_id %}){% endif %}{% endwith %}</td> - </tr><tr> - <th>Signature Date:</th> - <td>{{ pkg.signature.creation_time|date:"DATETIME_FORMAT" }} UTC</td> - </tr>{% else %}<tr> - <th>Signed By:</th> - <td>Unsigned</td> - </tr>{% endif %}<tr> - <th>Last Updated:</th> - <td>{{ pkg.last_update|date:"DATETIME_FORMAT" }} UTC</td> - </tr> - {% if user.is_authenticated %}{% with pkg.flag_request as flag_request %}{% if flag_request %}<tr> - <th>Last Flag Request:</th> - <td class="wrap">From {{ flag_request.who }} on {{ flag_request.created|date }}:<br/> - <div class="userdata">{{ flag_request.message|linebreaksbr|default:"{no message}" }}</div></td> - </tr>{% endif %}{% endwith %}{% endif %} - </table> - </div> - - <div id="metadata"> - {% with pkg.get_depends as deps %} - <div id="pkgdeps" class="listing"> - <h3 title="{{ pkg.pkgname }} has the following dependencies"> - Dependencies ({{deps|length}})</h3> - {% if deps %}<ul id="pkgdepslist"> - {% for depend in deps %}{% include "packages/details_depend.html" %}{% endfor %} - </ul>{% endif %} - </div> - {% endwith %} - {% with pkg.get_requiredby as rqdby %} - <div id="pkgreqs" class="listing"> - <h3 title="Packages that require {{ pkg.pkgname }}"> - Required By ({{rqdby|length}})</h3> - {% if rqdby %}<ul id="pkgreqslist"> - {% for req in rqdby %}{% include "packages/details_requiredby.html" %}{% endfor %} - </ul>{% endif %} - </div> - {% endwith %} - <div id="pkgfiles" class="listing"> - <h3 title="Complete list of files contained within this package"> - Package Contents</h3> - <div id="pkgfilelist"> - <p><a id="filelink" href="files/" - title="Click to view the complete file list for {{ pkg.pkgname }}"> - View the file list for {{ pkg.pkgname }}</a></p> - </div> - </div> - </div> -</div> +{% include "packages/details.html.jinja" %} {% endblock %} {% block script_block %} diff --git a/templates/packages/details.html.jinja b/templates/packages/details.html.jinja new file mode 100644 index 00000000..21be80f5 --- /dev/null +++ b/templates/packages/details.html.jinja @@ -0,0 +1,223 @@ +{% import 'packages/details_link.html.jinja' as details %} +<div id="pkgdetails" class="box"> + <h2>{{ pkg.pkgname }} {{ pkg.full_version }}</h2> + + <div id="detailslinks" class="listing"> + <div id="actionlist"> + <h4>Package Actions</h4> + <ul class="small"> + <li> + <a href="{{ scm_link(pkg, 'tree') }}" title="View source files for {{ pkg.pkgname }}">Source Files</a> / + <a href="{{ scm_link(pkg, 'log') }}" title="View changes for {{ pkg.pkgname }}">View Changes</a> + </li> + <li> + <a href="{{ bugs_list(pkg) }}" title="View existing bug tickets for {{ pkg.pkgname }}">Bug Reports</a> / + <a href="{{ bug_report(pkg) }}" title="Report new bug for {{ pkg.pkgname }}">Add New Bug</a> + </li> + <li><a href="{{ wiki_link(pkg) }}" title="Search wiki for {{ pkg.pkgname }}">Search Wiki</a></li> + {% if pkg.flag_date %} + <li><span class="flagged">Flagged out-of-date on {{ pkg.flag_date|date }}</span></li> + {% with tp = pkg.in_testing() %}{% if tp %} + <li><span class="flagged">Version + <a href="{{ tp.get_absolute_url() }}" + title="Testing package details for {{ tp.pkgname }}">{{ tp.full_version }}</a> + in testing</span></li> + {% endif %}{% endwith %} + {% if perms.main.change_package %} + <li><a href="unflag/" title="Unflag this package">Click here to unflag</a></li> + <li><a href="unflag/all/" title="Unflag all matching pkgbase">Click here to unflag all split packages</a></li> + {% endif %} + {% else %} + <li><a href="flag/" title="Flag {{ pkg.pkgname }} as out-of-date">Flag Package Out-of-Date</a> + <a href="/packages/flaghelp/" + title="Get help on package flagging" + onclick="return !window.open('/packages/flaghelp/','FlagHelp', + 'height=350,width=450,location=no,scrollbars=yes,menubars=no,toolbars=no,resizable=no');">(?)</a></li> + {% endif %} + <li><a href="download/" rel="nofollow" title="Download {{ pkg.pkgname }} from mirror">Download From Mirror</a></li> + </ul> + + {% if perms.main.change_package %} + <form id="pkg-action" method="post" action="/packages/update/">{% csrf_token %} + <div><input type="hidden" name="pkgid" value="{{ pkg.id }}" /></div> + <p>{% if user in pkg.maintainers %} + <input title="Orphan this package" type="submit" name="disown" value="Disown"/> + {% else %} + <input title="Adopt this package" type="submit" name="adopt" value="Adopt"/> + {% endif %}</p> + </form> + {% endif %} + </div> + + {% with others = pkg.elsewhere() %}{% if others %} + <div id="elsewhere" class="widget"> + <h4>Versions Elsewhere</h4> + <ul> + {% for o in others %} + <li><a href="{{ o.get_absolute_url() }}" + title="Package details for {{ o.pkgname }}">{{ o.pkgname }} {{ o.full_version }} [{{ o.repo.name|lower }}] ({{ o.arch.name }})</a></li> + {% endfor %} + </ul> + </div> + {% endif %}{% endwith %} + </div> + + <div itemscope itemtype="http://schema.org/SoftwareApplication"> + <meta itemprop="name" content="{{ pkg.pkgname|escape }}"/> + <meta itemprop="version" content="{{ pkg.full_version|escape }}"/> + <meta itemprop="softwareVersion" content="{{ pkg.full_version|escape }}"/> + <meta itemprop="fileSize" content="{{ pkg.compressed_size }}"/> + <meta itemprop="dateCreated" content="{{ pkg.build_date|date("Y-m-d") }}"/> + <meta itemprop="datePublished" content="{{ pkg.last_update|date("Y-m-d") }}"/> + <meta itemprop="operatingSystem" content="Arch Linux"/> + {% if pkg.packager %}<div style="display:none" itemprop="provider" itemscope itemtype="http://schema.org/Person"> + <meta itemprop="name" content="{{ pkg.packager.get_full_name()|escape }}"/> + </div>{% endif %} + <table id="pkginfo"> + <tr> + <th>Architecture:</th> + <td><a href="/packages/?arch={{ pkg.arch.name }}" + title="Browse packages for {{ pkg.arch.name }} architecture">{{ pkg.arch.name }}</a></td> + </tr><tr> + <th>Repository:</th> + <td><a href="/packages/?repo={{ pkg.repo.name|capfirst }}" + title="Browse the {{ pkg.repo.name|capfirst }} repository">{{ pkg.repo.name|capfirst }}</a></td> + </tr> + {% if pkg.pkgname == pkg.pkgbase %} + {% with splits = pkg.split_packages() %}{% if splits %} + <tr> + <th>Split Packages:</th> + <td class="wrap relatedto">{% for s in splits %}<span class="related">{{ details.details_link(s) }}{% if not loop.last %}, {% endif %}</span>{% endfor %}</td> + </tr> + {% endif %}{% endwith %} + {% else %} + <tr> + <th>Base Package:</th> + {% with base = pkg.base_package() %}{% if base %} + <td>{{ details.details_link(base) }}</td> + {% else %} + <td><a href="../{{ pkg.pkgbase }}/" + title="Split package details for {{ pkg.pkgbase }}">{{ pkg.pkgbase }}</a></td> + {% endif %}{% endwith %} + </tr> + {% endif %} + <tr> + <th>Description:</th> + <td class="wrap" itemprop="description">{{ pkg.pkgdesc|default("") }}</td> + </tr><tr> + <th>Upstream URL:</th> + <td>{% if pkg.url %}<a itemprop="url" href="{{ pkg.url }}" + title="Visit the website for {{ pkg.pkgname }}">{{ pkg.url|url_unquote }}</a>{% endif %}</td> + </tr><tr> + <th>License(s):</th> + <td class="wrap">{{ pkg.licenses.all()|join(", ") }}</td> + </tr> + {% with groups = pkg.groups.all() %}{% if groups %} + <tr> + <th>Groups:</th> + <td class="wrap">{% for g in groups %} + <a href="/groups/{{ pkg.arch.name }}/{{ g.name }}/" + title="Group details for {{ g.name }}">{{ g.name }}</a>{% if not loop.last %}, {% endif %}{% endfor %} + </td> + </tr> + {% endif %}{% endwith %} + {% with all_related = pkg.provides.all() %}{% if all_related %} + <tr> + <th>Provides:</th> + <td class="wrap relatedto">{% include "packages/details_relatedto.html.jinja" %}</td> + </tr> + {% endif %}{% endwith %} + {% with all_related = pkg.replaces.all() %}{% if all_related %} + <tr> + <th>Replaces:</th> + <td class="wrap relatedto">{% include "packages/details_relatedto.html.jinja" %}</td> + </tr> + {% endif %}{% endwith %} + {% with all_related = pkg.conflicts.all() %}{% if all_related %} + <tr> + <th>Conflicts:</th> + <td class="wrap relatedto">{% include "packages/details_relatedto.html.jinja" %}</td> + </tr> + {% endif %}{% endwith %} + {% with rev_conflicts = pkg.reverse_conflicts() %}{% if rev_conflicts %} + <tr> + <th>Reverse Conflicts:</th> + <td class="wrap relatedto">{% for conflict in rev_conflicts %} + <span class="related">{{ details.details_link(conflict) }}{% if not loop.last %}, {% endif %}</span>{% endfor %}</td> + </tr> + {% endif %}{% endwith %} + <tr> + <th>Maintainers:</th> + {% with maints = pkg.maintainers %} + <td>{% if maints %}{% for m in maints %} + <a href="/packages/?maintainer={{ m.username }}" + title="View packages maintained by {{ m.get_full_name() }}">{{ m.get_full_name() }}</a><br/> + {% endfor %}{% else %}Orphan{% endif %} + </td> + {% endwith %} + </tr><tr> + <th>Package Size:</th> + <td>{{ pkg.compressed_size|filesizeformat }}</td> + </tr><tr> + <th>Installed Size:</th> + <td>{{ pkg.installed_size|filesizeformat }}</td> + </tr><tr> + <th>Last Packager:</th> + <td>{% with pkgr = pkg.packager %}{% if pkgr %} + <a href="/packages/?packager={{ pkgr.username }}" + title="View packages packaged by {{ pkgr.get_full_name() }}">{{ pkgr.get_full_name() }}</a> + {% else %}{{ pkg.packager_str }}{% endif %}{% endwith %}</td> + </tr><tr> + <th>Build Date:</th> + <td>{{ pkg.build_date|date("DATETIME_FORMAT") }} UTC</td> + </tr>{% if pkg.signature %}<tr> + <th>Signed By:</th> + <td>{% with signer = pkg.signer %}{% if signer %}{{ pgp_key_link(pkg.signature.key_id, signer.get_full_name())|safe }}{% else %}Unknown ({{ pgp_key_link(pkg.signature.key_id)|safe }}){% endif %}{% endwith %}</td> + </tr><tr> + <th>Signature Date:</th> + <td>{{ pkg.signature.creation_time|date("DATETIME_FORMAT") }} UTC</td> + </tr>{% else %}<tr> + <th>Signed By:</th> + <td>Unsigned</td> + </tr>{% endif %}<tr> + <th>Last Updated:</th> + <td>{{ pkg.last_update|date("DATETIME_FORMAT") }} UTC</td> + </tr> + {% if user.is_authenticated %}{% with flag_request = pkg.flag_request() %}{% if flag_request %}<tr> + <th>Last Flag Request:</th> + <td class="wrap">From {{ flag_request.who() }} on {{ flag_request.created|date }}:<br/> + <div class="userdata">{{ flag_request.message|linebreaksbr|default("{no message}") }}</div></td> + </tr>{% endif %}{% endwith %}{% endif %} + </table> + </div> + + <div id="metadata"> + {% with deps = pkg.get_depends() %} + <div id="pkgdeps" class="listing"> + <h3 title="{{ pkg.pkgname }} has the following dependencies"> + Dependencies ({{deps|length}})</h3> + {% if deps %}<ul id="pkgdepslist"> + {% for depend in deps %}{% include "packages/details_depend.html.jinja" %}{% endfor %} + </ul>{% endif %} + </div> + {% endwith %} + {% with rqdby = pkg.get_requiredby() %} + <div id="pkgreqs" class="listing"> + <h3 title="Packages that require {{ pkg.pkgname }}"> + Required By ({{rqdby|length}})</h3> + {% if rqdby %}<ul id="pkgreqslist"> + {% for req in rqdby %}{% include "packages/details_requiredby.html.jinja" %}{% endfor %} + </ul>{% endif %} + </div> + {% endwith %} + <div id="pkgfiles" class="listing"> + <h3 title="Complete list of files contained within this package"> + Package Contents</h3> + <div id="pkgfilelist"> + <p><a id="filelink" href="files/" + title="Click to view the complete file list for {{ pkg.pkgname }}"> + View the file list for {{ pkg.pkgname }}</a></p> + </div> + </div> + </div> +</div> diff --git a/templates/packages/details_depend.html b/templates/packages/details_depend.html.jinja index b89ffbfa..404793b6 100644 --- a/templates/packages/details_depend.html +++ b/templates/packages/details_depend.html.jinja @@ -1,11 +1,11 @@ -{% load package_extras %}<li>{% ifequal depend.pkg None %} -{% if depend.providers %}{{ depend.dep.name }}{{ depend.dep.comparison|default:"" }}{{ depend.dep.version|default:"" }} <span class="virtual-dep">({% multi_pkg_details depend.providers %})</span> -{% else %}{{ depend.dep.name }}{{ depend.dep.comparison|default:"" }}{{ depend.dep.version|default:"" }} <span class="virtual-dep">(virtual)</span> +{% import 'packages/details_link.html.jinja' as details %}<li>{% if depend.pkg == None %} +{% if depend.providers %}{{ depend.dep.name }}{{ depend.dep.comparison|default("") }}{{ depend.dep.version|default("") }} <span class="virtual-dep">({% for pkg in depend.providers %}{{ details.details_link(pkg) }}{% if not loop.last %}, {% endif %}{% endfor %})</span> +{% else %}{{ depend.dep.name }}{{ depend.dep.comparison|default("") }}{{ depend.dep.version|default("") }} <span class="virtual-dep">(virtual)</span> {% endif %}{% else %} -{% pkg_details_link depend.pkg %}{{ depend.dep.comparison|default:"" }}{{ depend.dep.version|default:"" }} +{{ details.details_link(depend.pkg) }}{{ depend.dep.comparison|default("") }}{{ depend.dep.version|default("") }} {% if depend.pkg.repo.testing %} <span class="testing-dep"> (testing)</span> {% endif %}{% if depend.pkg.repo.staging %} <span class="staging-dep"> (staging)</span> -{% endif %}{% endifequal %} +{% endif %}{% endif %} {% if depend.dep.deptype == 'O' %} <span class="opt-dep"> (optional)</span> {% endif %}{% if depend.dep.deptype == 'M' %} <span class="make-dep"> (make)</span> {% endif %}{% if depend.dep.deptype == 'C' %} <span class="check-dep"> (check)</span> diff --git a/templates/packages/details_link.html.jinja b/templates/packages/details_link.html.jinja new file mode 100644 index 00000000..b7e75fe5 --- /dev/null +++ b/templates/packages/details_link.html.jinja @@ -0,0 +1 @@ +{% macro details_link(pkg) %}<a href="{{ pkg.get_absolute_url() }}" title="View package details for {{ pkg.pkgname }}">{{ pkg.pkgname }}</a>{% endmacro %} diff --git a/templates/packages/details_relatedto.html b/templates/packages/details_relatedto.html deleted file mode 100644 index e14375d3..00000000 --- a/templates/packages/details_relatedto.html +++ /dev/null @@ -1,2 +0,0 @@ -{% load package_extras %}{% for related in all_related %}{% with related.get_best_satisfier as best_satisfier %}<span class="related">{% ifequal best_satisfier None %}{{ related.name }}{% else %}{% pkg_details_link best_satisfier %}{% endifequal %}{{ related.comparison|default:"" }}{{ related.version|default:"" }}{% if not forloop.last %}, {% endif %}</span> -{% endwith %}{% endfor %} diff --git a/templates/packages/details_relatedto.html.jinja b/templates/packages/details_relatedto.html.jinja new file mode 100644 index 00000000..955fdd37 --- /dev/null +++ b/templates/packages/details_relatedto.html.jinja @@ -0,0 +1,3 @@ +{% import 'packages/details_link.html.jinja' as details %}{% for related in all_related %}{% with best_satisfier = related.get_best_satisfier() %} +<span class="related">{% if best_satisfier == None %}{{ related.name }}{% else %}{{ details.details_link(best_satisfier) }}{% endif %}{{ related.comparison|default("") }}{{ related.version|default("") }}{% if not loop.last %}, {% endif %}</span> +{% endwith %}{% endfor %} diff --git a/templates/packages/details_requiredby.html b/templates/packages/details_requiredby.html.jinja index 504a322f..b083a7fc 100644 --- a/templates/packages/details_requiredby.html +++ b/templates/packages/details_requiredby.html.jinja @@ -1,4 +1,4 @@ -{% load package_extras %}<li>{% pkg_details_link req.pkg %} +{% import 'packages/details_link.html.jinja' as details %}<li>{{ details.details_link(req.pkg) }} {% if req.name != pkg.pkgname %}<span class="virtual-dep"> (requires {{ req.name }})</span> {% endif %}{% if req.pkg.repo.testing %}<span class="testing-dep"> (testing)</span> {% endif %}{% if req.pkg.repo.staging %}<span class="staging-dep"> (staging)</span> diff --git a/templates/packages/files.html b/templates/packages/files.html index e2987e5f..667a77cb 100644 --- a/templates/packages/files.html +++ b/templates/packages/files.html @@ -9,7 +9,7 @@ <p>Package has {{ files_count }} file{{ files_count|pluralize }} and {{ dir_count }} director{{ dir_count|pluralize:"y,ies" }}.</p> <p><a href="{{ pkg.get_absolute_url }}">Back to Package</a></p> <div id="metadata"><div id="pkgfilelist"> - {% include "packages/files_list.html" %} + {% include "packages/files_list.html.jinja" %} </div></div> </div> diff --git a/templates/packages/files_list.html b/templates/packages/files_list.html.jinja index 93a2c847..c8fc3b1a 100644 --- a/templates/packages/files_list.html +++ b/templates/packages/files_list.html.jinja @@ -6,7 +6,7 @@ of the package; it may be out of date.</p> {% if files|length %} <ul> {% for file in files %} -<li class="{% if file.is_directory %}d{% else %}f{% endif %}">{{ file.directory }}{{ file.filename|default:'' }}</li>{% endfor %} +<li class="{% if file.is_directory %}d{% else %}f{% endif %}">{{ file.directory }}{{ file.filename|default('') }}</li>{% endfor %} </ul> {% else %} <p class="message">Package has no files.</p> diff --git a/templates/packages/search.html b/templates/packages/search.html index ec913ed6..a7433934 100644 --- a/templates/packages/search.html +++ b/templates/packages/search.html @@ -2,7 +2,7 @@ {% load cycle from future %} {% load package_extras %} -{% block title %}{{ BRANDING_DISTRONAME }} - Package Database{% endblock %} +{% block title %}{{ BRANDING_DISTRONAME }} - Package Search{% endblock %} {% block navbarclass %}anb-packages{% endblock %} {% block head %} @@ -12,10 +12,7 @@ {% block content %} <div id="pkglist-search" class="box filter-criteria"> - - <h2>Package Database</h2> - - <h3>Package Search</h3> + <h2>Package Search</h2> <form id="pkg-search" method="get" action="/packages/"> <p>{{ search_form.sort }}</p> @@ -41,14 +38,49 @@ type="submit" value="Search" /></div> </fieldset> </form> +</div> -</div><!-- #pkglist-search --> +{% if not is_paginated or page_obj.number == 1 %}{% with search_form.exact_matches as exact_matches %}{% if exact_matches %} +<div id="exact-matches" class="box"> + <div class="pkglist-stats"> + <p>{{ exact_matches|length }} exact match{{ exact_matches|pluralize:"es" }} found.</p> + </div> + <table class="results"> + <thead> + <tr> + <th>Arch</th> + <th>Repo</th> + <th>Name</th> + <th>Version</th> + <th>Description</th> + <th>Last Updated</th> + <th>Flag Date</th> + </tr> + </thead> + <tbody> + {% for pkg in exact_matches %} + <tr class="{% cycle 'odd' 'even' %}"> + <td>{{ pkg.arch.name }}</td> + <td>{{ pkg.repo.name|capfirst }}</td> + <td>{% pkg_details_link pkg %}</td> + {% if pkg.flag_date %} + <td><span class="flagged">{{ pkg.full_version }}</span></td> + {% else %} + <td>{{ pkg.full_version }}</td> + {% endif %} + <td class="wrap">{{ pkg.pkgdesc }}</td> + <td>{{ pkg.last_update|date }}</td> + <td>{{ pkg.flag_date|date }}</td> + </tr> + {% endfor %} + </tbody> + </table> +</div> +{% endif %}{% endwith %}{% endif %} -{% if package_list %} <div id="pkglist-results" class="box"> {% include "packages/search_paginator.html" %} <form id="pkglist-results-form" method="post" action="/packages/update/">{% csrf_token %} - <table class="results"> <thead> <tr> @@ -70,7 +102,8 @@ </tr> </thead> <tbody> - {% for pkg in package_list %}<tr class="{% cycle 'odd' 'even' %}"> + {% for pkg in package_list %} + <tr class="{% cycle 'odd' 'even' %}"> {% if perms.main.change_package %} <td><input type="checkbox" name="pkgid" value="{{ pkg.id }}" /></td> {% endif %} @@ -85,7 +118,10 @@ <td class="wrap">{{ pkg.pkgdesc }}</td> <td>{{ pkg.last_update|date }}</td> <td>{{ pkg.flag_date|date }}</td> - </tr>{% endfor %} + </tr> + {% empty %} + <tr class="empty"><td colspan="{% if perms.main.change_package %}9{% else %}8{% endif %}"><em>No matching packages found</em></td></tr> + {% endfor %} </tbody> </table> {% include "packages/search_paginator.html" %} @@ -96,25 +132,18 @@ <input title="Orphan selected packages" type="submit" id="disown-btn" name="disown" value="Disown Packages" /></p> {% endif %} - </form> +</div> -</div><!-- #pkglist-results --> -{% else %} -<div class="box"> - <p>We couldn't find any packages matching your query. Try searching again +<div id="pkglist-about" class="box"> + <p>Can't find what you are looking for? Try searching again using different criteria, or try {% if search_form.q.data %} <a href="https://aur.archlinux.org/packages.php?K={{ search_form.q.data|urlencode }}">searching the AUR</a> {% else %}searching the <a href="https://aur.archlinux.org/">AUR</a>{% endif %} to see if the package can be found there.</p> -</div> -{% endif %} -<div id="pkglist-about" class="box"> <p>You are browsing the {{ BRANDING_DISTRONAME }} package database. From here you can find - detailed information about packages located in the official supported repositories. - For unsupported packages, browse the <a href="https://aur.archlinux.org/" - title="AUR package database">Arch User Repository (AUR).</a></p> + detailed information about packages located in the official supported repositories.</p> </div> {% endblock %} diff --git a/templates/packages/search_paginator.html b/templates/packages/search_paginator.html index 3c368b82..a748d26b 100644 --- a/templates/packages/search_paginator.html +++ b/templates/packages/search_paginator.html @@ -1,6 +1,6 @@ <div class="pkglist-stats"> {% if is_paginated %} - <p>{{ paginator.count }} packages found. + <p>{{ paginator.count }} matching packages found. Page {{ page_obj.number }} of {{ paginator.num_pages }}.</p> <div class="pkglist-nav"> @@ -22,6 +22,6 @@ </span> </div> {% else %} - <p>{{ package_list.count }} packages found.</p> + <p>{{ package_list|length }} matching package{{ package_list|pluralize }} found.</p> {% endif %} </div> diff --git a/templates/packages/stale_relations.html b/templates/packages/stale_relations.html index 91ea033e..949b563e 100644 --- a/templates/packages/stale_relations.html +++ b/templates/packages/stale_relations.html @@ -37,7 +37,7 @@ <td>{{ relation.created }}</td> </tr> {% empty %} - <tr class="empty"><td colspan="5"><em>No inactive user relations.</em></td></tr> + <tr class="empty"><td colspan="6"><em>No inactive user relations.</em></td></tr> {% endfor %} </tbody> </table> @@ -66,7 +66,7 @@ <td>{{ relation.last_update.created }}</td> </tr> {% empty %} - <tr class="empty"><td colspan="4"><em>No non-existent pkgbase relations.</em></td></tr> + <tr class="empty"><td colspan="6"><em>No non-existent pkgbase relations.</em></td></tr> {% endfor %} </tbody> </table> @@ -100,7 +100,7 @@ <td class="wrap">{{ relation.repositories|join:", " }}</td> </tr> {% empty %} - <tr class="empty"><td colspan="6"><em>No relations with wrong permissions.</em></td></tr> + <tr class="empty"><td colspan="7"><em>No relations with wrong permissions.</em></td></tr> {% endfor %} </tbody> </table> @@ -117,13 +117,13 @@ <script type="text/javascript" src="{% static "archweb.js" %}"></script> <script type="text/javascript"> $(document).ready(function() { - $('#inactive-user:not(:has(tbody tr.empty))').tablesorter({widgets: ['zebra'], headers: { 0: { sorter: false } }, sortList: [[3,0]]}); + $('#inactive-user:not(:has(tbody tr.empty))').tablesorter({widgets: ['zebra'], headers: { 0: { sorter: false }, 2: { sorter: false } }, sortList: [[1,0]]}); $('#missing-pkgbase:not(:has(tbody tr.empty))').tablesorter({widgets: ['zebra'], headers: { 0: { sorter: false } }, sortList: [[1,0]]}); -}); - $('#wrong-permissions:not(:has(tbody tr.empty))').tablesorter({widgets: ['zebra'], headers: { 0: { sorter: false } }, sortList: [[3,0]]}); + $('#wrong-permissions:not(:has(tbody tr.empty))').tablesorter({widgets: ['zebra'], headers: { 0: { sorter: false }, 2: { sorter: false } }, sortList: [[1,0]]}); $('table.results').bind('sortEnd', function() { $('input.relation-checkbox').enableCheckboxRangeSelection(); }); $('input.relation-checkbox').enableCheckboxRangeSelection(); +}); </script> {% endblock %} diff --git a/todolists/utils.py b/todolists/utils.py index 7b98c887..e04c2e5e 100644 --- a/todolists/utils.py +++ b/todolists/utils.py @@ -6,7 +6,7 @@ from packages.models import Package def todo_counts(): sql = """ -SELECT todolist_id, count(*), sum(CASE WHEN status = %s THEN 1 ELSE 0 END) +SELECT todolist_id, count(*), SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) FROM todolists_todolistpackage WHERE removed IS NULL GROUP BY todolist_id |