upgrades: Add status section showing version and upgrade status

Closes: #1939.

- Force a delay before returning the upgrade result to allow upgrade to kick in.
Otherwise when the flow returns, get_context_data() creates the context too
early and finds the upgrade not yet busy, causing the refresh loop to miss it.
The page renders static and the user gets no clue to the upgrade executing in
the background.

Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com>
[sunil: Retain the styling for the remainder of the page]
[sunil: Re-style the status section as a simple web-page]
[sunil: Drop unused running-status CSS styles]
[sunil: Rename CSS variables, minor changes to color values]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
Fioddor Superconcentrado 2020-10-07 19:28:10 +02:00 committed by Sunil Mohan Adapa
parent f88ced9706
commit f1f84a2509
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
4 changed files with 106 additions and 38 deletions

View File

@ -16,6 +16,7 @@ from django.utils.translation import get_language_from_request
from django.utils.translation import ugettext as _
from plinth import __version__, actions, cfg
from plinth.modules.upgrades.views import get_os_release
def index(request):
@ -50,7 +51,7 @@ def about(request):
'title': _('About {box_name}').format(box_name=_(cfg.box_name)),
'version': __version__,
'new_version': not freedombox.candidate.is_installed,
'os_release': get_os_release(),
'os_release': get_os_release()
}
return TemplateResponse(request, 'help_about.html', context)
@ -120,15 +121,3 @@ def status_log(request):
output = actions.superuser_run('help', ['get-logs'])
context = {'num_lines': 100, 'data': output}
return TemplateResponse(request, 'statuslog.html', context)
def get_os_release():
"""Returns the Debian release number and name"""
output = 'Error: Cannot read PRETTY_NAME in /etc/os-release.'
with open('/etc/os-release', 'r') as release_file:
for line in release_file:
if 'PRETTY_NAME=' in line:
line = line.replace('"', '').strip()
line = line.split('=')
output = line[1]
return output

View File

@ -7,6 +7,54 @@
{% load i18n %}
{% load static %}
{% block page_head %}
<style type="text/css">
.warning {
color: var(--warning-color);
}
.processing {
color: var(--progress-color);
}
.normal {
color: var(--neutral-dark-color);
}
</style>
{% endblock %}
{% block status %}
{{ block.super}} {% comment %} To extend instead of overwrite {% endcomment %}
<h3>{% trans "Status" %}</h3>
<div class="upgrades-status-frame clearfix">
<div class="upgrade-status-icon pull-left">
{% if is_busy %}
<span class="fa fa-refresh fa-spin fa-3x fa-pull-left processing"></span>
{% elif new_version %}
<span class="fa fa-frown-o fa-3x fa-pull-left warning"></span>
{% else %}
<span class="fa fa-smile-o fa-3x fa-pull-left normal"></span>
{% endif %}
</div>
<p>
{% blocktrans trimmed %}
You are running {{ os_release }} and {{ box_name }} version {{ version }}.
{% endblocktrans %}
{% if is_busy %}
<strong>{% trans "Updating..." %}</strong>
{% elif new_version %}
{% blocktrans trimmed %}
There is a new {{ box_name }} version available.
{% endblocktrans %}
<strong>{% trans "Your Freedombox needs an update!" %}</strong>
{% else %}
{% blocktrans %}{{ box_name }} is up to date.{% endblocktrans %}
{% endif %}
</p>
</div>
{% endblock %}
{% block extra_content %}
<h3>{% trans "Frequent Feature Updates" %}</h3>
<p>

View File

@ -2,7 +2,9 @@
"""
FreedomBox app for upgrades.
"""
import time
from apt.cache import Cache
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
@ -10,7 +12,7 @@ from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormView
from plinth import actions, package
from plinth import __version__, actions, package
from plinth.errors import ActionError
from plinth.modules import first_boot, upgrades
from plinth.views import AppView
@ -29,12 +31,17 @@ class UpgradesConfigurationView(AppView):
return {'auto_upgrades_enabled': upgrades.is_enabled()}
def get_context_data(self, *args, **kwargs):
cache = Cache()
freedombox = cache['freedombox']
context = super().get_context_data(*args, **kwargs)
context['can_activate_backports'] = upgrades.can_activate_backports()
context['is_backports_requested'] = upgrades.is_backports_requested()
context['is_busy'] = package.is_package_manager_busy()
context['log'] = get_log()
context['refresh_page_sec'] = 3 if context['is_busy'] else None
context['version'] = __version__
context['new_version'] = not freedombox.candidate.is_installed
context['os_release'] = get_os_release()
return context
def form_valid(self, form):
@ -66,6 +73,21 @@ class UpgradesConfigurationView(AppView):
return super().form_valid(form)
def get_os_release():
"""Returns the Debian release number and name
Note: The Help module calls this function also.
"""
output = 'Error: Cannot read PRETTY_NAME in /etc/os-release.'
with open('/etc/os-release', 'r') as release_file:
for line in release_file:
if 'PRETTY_NAME=' in line:
line = line.replace('"', '').strip()
line = line.split('=')
output = line[1]
return output
def get_log():
"""Return the current log for unattended upgrades."""
return actions.superuser_run('upgrades', ['get-log'])
@ -73,10 +95,16 @@ def get_log():
def upgrade(request):
"""Serve the upgrade page."""
secs_for_package_to_get_busy = 2
if request.method == 'POST':
try:
actions.superuser_run('upgrades', ['run'])
messages.success(request, _('Upgrade process started.'))
# Give the Package module some time to get busy so the page enters
# the refreshing loop. XXX: Remove after changing the busy check
# implementation include activating state of
# freedombox-manual-upgrade.service.
time.sleep(secs_for_package_to_get_busy)
except ActionError:
messages.error(request, _('Starting upgrade failed.'))

View File

@ -2,6 +2,17 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
*/
:root {
--background-color: #f1f1f1; /* Light grey */
--neutral-light-color: #f5f5f5; /* Light grey */
--neutral-dark-color: #d4d4d4; /* Grey */
--info-color: #5bc0de; /* Pale blue, almost turquoise */
--freedombox-blue-color: #4989D4; /* Blue */
--progress-color: #3498db; /* Blue */
--error-color: #d9534f; /* Red */
--warning-color: #ec971f; /* Orange */
}
@font-face {
font-family: 'Lato';
src: url('../lato/Lato-Italic.woff2') format('woff2');
@ -64,7 +75,7 @@ body {
position: relative;
font-family: Lato, sans-serif;
font-size: 15px;
background: url('../img/noise.png') #f1f1f1;
background: url('../img/noise.png') var(--background-color);
}
@media (max-width: 767px) {
@ -75,7 +86,7 @@ body {
body.index-page,
body.apps-page,
body.system-page {
background: url('../img/noise.png') #f1f1f1;
background: url('../img/noise.png') var(--background-color);
}
}
@ -114,17 +125,9 @@ body {
display: inline-block;
}
.running-status.active {
background-color: rgb(0, 167, 0);
}
.running-status.inactive {
background-color: rgb(228, 66, 66);
}
.running-status.loading {
border: 4px solid #f3f3f3; /* Light grey */
border-top: 4px solid #3498db; /* Blue */
border: 4px solid var(--neutral-light-color);
border-top: 4px solid var(--progress-color);
border-radius: 50%;
width: 16px;
height: 16px;
@ -159,7 +162,7 @@ body {
.form-diagnostics-button .btn:hover,
.form-diagnostics-button .btn:focus {
background-color:#f5f5f5
background-color: var(--neutral-light-color)
}
/* Hide log out button if user dropdown is available */
@ -272,7 +275,7 @@ footer {
/* applying styles to header - begin */
.main-header {
background: #4989D4;
background: var(--freedombox-blue-color);
box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.25);
border: none;
}
@ -325,7 +328,7 @@ footer {
color: white;
content: '';
flex: 1;
border-bottom: #d4d4d4 solid 2px;
border-bottom: var(--neutral-dark-color) solid 2px;
margin: auto 1.8rem;
}
@ -514,7 +517,7 @@ a.menu_link_active {
}
.toggle-button--toggled {
background: #4989D4;
background: var(--freedombox-blue-color);
}
.toggle-button--toggled::before {
@ -527,8 +530,8 @@ a.menu_link_active {
*/
.running-status-button-before {
display: inline-block;
border: 4px solid #f3f3f3; /* Light grey */
border-top: 4px solid #3498db; /* Blue */
border: 4px solid var(--neutral-light-color);
border-top: 4px solid var(--progress-color);
border-radius: 50%;
width: 16px;
height: 16px;
@ -686,27 +689,27 @@ img.notification-icon {
}
.badge-exception, .badge-error {
background-color: #d9534f;
background-color: var(--error-color);
}
.badge-warning {
background-color: #ec971f;
background-color: var(--warning-color);
}
.badge-info, .badge-debug {
background-color: #5bc0de;
background-color: var(--info-color);
}
.notification-exception, .notification-error {
border-left-color: #d9534f;
border-left-color: var(--error-color);
}
.notification-warning {
border-left-color: #ec971f;
border-left-color: var(--warning-color);
}
.notification-info, .notification-debug {
border-left-color: #5bc0de;
border-left-color: var(--info-color)
}
/* Don't collapse notifications on small screens */