applications: list versions (#69654)
gitea-wip/hobo/pipeline/head There was a failure building this commit Details
gitea/hobo/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Lauréline Guérin 2022-10-20 16:39:21 +02:00
parent 4257eb8968
commit 89b9a5285d
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 115 additions and 5 deletions

View File

@ -16,7 +16,11 @@
{{ app.name }}
</h2>
<span class="actions">
<a class="extra-actions-menu-opener"></a>
<a rel="popup" href="{% url 'application-metadata' app_slug=app.slug %}">{% trans 'Metadata' %}</a>
<ul class="extra-actions-menu">
<li><a href="{% url 'application-versions' app_slug=app.slug %}">{% trans 'See all versions' %}</a></li>
</ul>
</span>
{% endblock %}
@ -45,9 +49,9 @@
<a class="pk-button" href="{% url 'application-scandeps' app_slug=app.slug %}">{% trans "Scan dependencies" %}</a>
&nbsp; &nbsp;
<a class="pk-button" rel="popup" href="{% url 'application-generate' app_slug=app.slug %}">{% trans "Generate application bundle" %}</a>
{% if versions %}
{% if last_version %}
&nbsp; &nbsp;
<a class="pk-button" download href="{% url 'application-download' app_slug=app.slug %}">{% trans "Download" %}</a>
<a class="pk-button" download href="{% url 'application-download' app_slug=app.slug %}">{% blocktrans with number=last_version.number %}Download latest version ({{ number }}){% endblocktrans %}</a>
{% endif %}
</div>
{% else %}

View File

@ -0,0 +1,40 @@
{% extends "hobo/applications/manifest.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'application-versions' app_slug=app.slug %}">{{ app.name }}</a>
{% endblock %}
{% block appbar %}
<h2>{% trans "Versions" %}</h2>
{% endblock %}
{% block content %}
{% if object_list %}
<div id="versions">
{% for version in object_list %}
<div class="version">
<h3>{{ version.number }}</h3>
<p><span>{% blocktrans with cdate=version.creation_timestamp|date:"DATETIME_FORMAT" udate=version.last_update_timestamp|date:"DATETIME_FORMAT" %}created at {{ cdate }}, updated at {{ udate }}{% endblocktrans %}</span></p>
<p>{{ version.notes|default:""|linebreaksbr }}</p>
<div class="buttons">
<a class="button" download href="{% url 'application-download' app_slug=app.slug version_pk=version.pk %}"
>{% trans "Download" %}</a>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div id="no-versions">
<div class="infonotice">
<p>{% trans "No versions generated yet." %}</p>
</div>
</div>
{% endif %}
{% endblock %}
{% block sidebar %}
{% endblock %}

View File

@ -24,10 +24,16 @@ urlpatterns = [
path('install/', views.install, name='application-install'),
re_path(r'^manifest/(?P<slug>[\w-]+)/delete/$', views.delete, name='application-delete'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/$', views.manifest, name='application-manifest'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/versions/$', views.versions, name='application-versions'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/metadata/$', views.metadata, name='application-metadata'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/scandeps/$', views.scandeps, name='application-scandeps'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/generate/$', views.generate, name='application-generate'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/download/$', views.download, name='application-download'),
re_path(
r'^manifest/(?P<app_slug>[\w-]+)/download/(?P<version_pk>\d+)/$',
views.download,
name='application-download',
),
re_path(
r'^manifest/(?P<app_slug>[\w-]+)/add/(?P<type>[\w-]+)/$',
views.add_element,

View File

@ -23,6 +23,7 @@ import urllib.parse
from django.conf import settings
from django.core.files.base import ContentFile
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
from django.views.generic import FormView, ListView, TemplateView
from django.views.generic.edit import CreateView, DeleteView, UpdateView
@ -89,7 +90,7 @@ class ManifestView(TemplateView):
context['app'] = Application.objects.get(slug=self.kwargs['app_slug'])
context['relations'] = context['app'].relation_set.all().select_related('element')
context['versions'] = context['app'].version_set.exists()
context['last_version'] = context['app'].version_set.order_by('last_update_timestamp').last()
context['types_by_service'] = {}
type_labels = {}
@ -111,6 +112,21 @@ class ManifestView(TemplateView):
manifest = ManifestView.as_view()
class VersionsView(ListView):
template_name = 'hobo/applications/versions.html'
def get_queryset(self):
self.app = Application.objects.get(slug=self.kwargs['app_slug'])
return self.app.version_set.order_by('-last_update_timestamp')
def get_context_data(self, **kwargs):
kwargs['app'] = self.app
return super().get_context_data(**kwargs)
versions = VersionsView.as_view()
class MetadataView(UpdateView):
template_name = 'hobo/applications/edit-metadata.html'
model = Application
@ -291,9 +307,12 @@ class GenerateView(FormView):
generate = GenerateView.as_view()
def download(request, app_slug):
def download(request, app_slug, version_pk=None):
app = Application.objects.get(slug=app_slug)
version = app.version_set.order_by('-last_update_timestamp')[0]
if version_pk is None:
version = app.version_set.order_by('last_update_timestamp').last()
else:
version = get_object_or_404(app.version_set, pk=version_pk)
response = HttpResponse(version.bundle, content_type='application/x-tar')
response['Content-Disposition'] = 'attachment; filename="%s"' % '%s.tar' % app_slug
return response

View File

@ -342,3 +342,25 @@ h2.application-title {
vertical-align: middle;
}
}
#versions {
.version {
background: white;
color: #3c3c33;
box-sizing: border-box;
border: 1px solid #ccc;
margin-bottom: 1rem;
padding: 0 1em;
h3 {
margin-top: 1em;
}
p span {
font-size: 1rem;
opacity: 0.6;
font-weight: normal;
}
.buttons {
justify-content: flex-end;
}
}
}

View File

@ -222,6 +222,11 @@ def test_create_application(app, admin_user, settings, analyze):
assert b'"version_number": "1.0"' in resp.content
assert b'"version_notes": "Foo bar blah."' in resp.content
resp = app.get('/applications/manifest/test/versions/')
resp = resp.click(href='/applications/manifest/test/download/%s/' % version.pk)
assert resp.content_type == 'application/x-tar'
assert b'"version_number": "1.0"' in resp.content
# generate again without changing version number
resp = app.get('/applications/manifest/test/generate/')
assert resp.form['number'].value == '1.0' # last one
@ -237,6 +242,11 @@ def test_create_application(app, admin_user, settings, analyze):
assert b'"version_number": "1.0"' in resp.content
assert b'"version_notes": "Foo bar blahha."' in resp.content
resp = app.get('/applications/manifest/test/versions/')
resp = resp.click(href='/applications/manifest/test/download/%s/' % same_version.pk)
assert resp.content_type == 'application/x-tar'
assert b'"version_number": "1.0"' in resp.content
# add an icon
resp = app.get('/applications/manifest/test/metadata/')
resp.form['icon'] = Upload(
@ -274,6 +284,15 @@ def test_create_application(app, admin_user, settings, analyze):
assert version.notes == 'Foo bar blah. But with an icon.'
assert version.pk != same_version.pk
resp = app.get('/applications/manifest/test/versions/')
resp = resp.click(href='/applications/manifest/test/download/%s/' % same_version.pk)
assert resp.content_type == 'application/x-tar'
assert b'"version_number": "1.0"' in resp.content
resp = app.get('/applications/manifest/test/versions/')
resp = resp.click(href='/applications/manifest/test/download/%s/' % version.pk)
assert resp.content_type == 'application/x-tar'
assert b'"version_number": "2.0"' in resp.content
resp = app.get('/applications/manifest/test/generate/')
assert resp.form['number'].value == '2.0' # last one
assert resp.form['notes'].value == 'Foo bar blah. But with an icon.' # last one