diff --git a/basic/srv/vm/mgr/wsgiapp.py b/basic/srv/vm/mgr/wsgiapp.py index 79aad2e..2566798 100644 --- a/basic/srv/vm/mgr/wsgiapp.py +++ b/basic/srv/vm/mgr/wsgiapp.py @@ -77,6 +77,7 @@ class WSGIApp(object): Rule('/update-app-autostart', endpoint='update_app_autostart_action'), Rule('/start-app', endpoint='start_app_action'), Rule('/stop-app', endpoint='stop_app_action'), + Rule('/install-app', endpoint='install_app_action'), Rule('/update-password', endpoint='update_password_action'), Rule('/shutdown-vm', endpoint='shutdown_vm_action'), Rule('/reboot-vm', endpoint='reboot_vm_action'), @@ -138,9 +139,13 @@ class WSGIApp(object): # Application manager view. pkgmgr = PackageManager() pkgmgr.fetch_online_packages() - all_apps = sorted(set([p for p in pkgmgr.online_packages if 'title' in p] + self.vmmgr.conf['apps'].keys())) + all_apps = sorted(set([k for k,v in pkgmgr.online_packages.items() if 'host' in v] + list(self.vmmgr.conf['apps'].keys()))) return self.render_template('setup-apps.html', request, all_apps=all_apps, online_packages=pkgmgr.online_packages) + def render_setup_apps_row(self, app, app_title): + t = self.jinja_env.get_template('setup-apps-row.html') + return t.render({'app': app, 'app_title': app_title, 'conf': self.vmmgr.conf}) + def update_host_action(self, request): # Update domain and port, then restart nginx try: @@ -250,22 +255,39 @@ class WSGIApp(object): def start_app_action(self, request): # Starts application along with its dependencies try: - self.vmmgr.start_app(request.form['app']) + app = request.form['app'] + self.vmmgr.start_app(app) except (BadRequest, InvalidValueException): return self.render_json({'error': request.session.lang.malformed_request()}) except: return self.render_json({'error': request.session.lang.stop_start_error()}) - return self.render_json({'ok': request.session.lang.app_started()}) + app_title = self.vmmgr.conf['apps'][app]['title'] + return self.render_json({'ok': self.render_setup_apps_row(app, app_title)}) def stop_app_action(self, request): # Stops application along with its dependencies try: - self.vmmgr.stop_app(request.form['app']) + app = request.form['app'] + self.vmmgr.stop_app(app) except (BadRequest, InvalidValueException): return self.render_json({'error': request.session.lang.malformed_request()}) except: return self.render_json({'error': request.session.lang.stop_start_error()}) - return self.render_json({'ok': request.session.lang.app_stopped()}) + app_title = self.vmmgr.conf['apps'][app]['title'] + return self.render_json({'ok': self.render_setup_apps_row(app, app_title)}) + + def install_app_action(self, request): + # Installs application + try: + app = request.form['app'] + pkgmgr = PackageManager() + pkgmgr.install_package(app) + except (BadRequest, InvalidValueException): + return self.render_json({'error': request.session.lang.malformed_request()}) + except: + return self.render_json({'error': request.session.lang.package_manager_error()}) + app_title = self.vmmgr.conf['apps'][app]['title'] + return self.render_json({'ok': self.render_setup_apps_row(app, app_title)}) def update_password_action(self, request): # Updates password for both HDD encryption (LUKS-on-LVM) and web interface admin account diff --git a/basic/srv/vm/mgr/wsgilang.py b/basic/srv/vm/mgr/wsgilang.py index 65b892c..a202fdc 100644 --- a/basic/srv/vm/mgr/wsgilang.py +++ b/basic/srv/vm/mgr/wsgilang.py @@ -18,9 +18,8 @@ class WSGILang: 'cert_request_error': 'Došlo k chybě při žádosti o certifikát. Zkontrolujte, zda je virtuální stroj dostupný z internetu na portu 80.', 'cert_installed': 'Certifikát byl úspěšně nainstalován. Přejděte na URL {} nebo restartujte webový prohlížeč pro jeho načtení.', 'common_updated': 'Nastavení aplikací bylo úspěšně změněno.', - 'app_started': 'Spuštěna (zastavit)', - 'app_stopped': 'Zastavena (spustit)', 'stop_start_error': 'Došlo k chybě při spouštění/zastavování. Zkuste akci opakovat nebo restartuje virtuální stroj.', + 'package_manager_error': 'Došlo k chybě při instalaci aplikace', 'bad_password': 'Nesprávné heslo', 'password_mismatch': 'Zadaná hesla se neshodují', 'password_empty': 'Nové heslo nesmí být prázdné', diff --git a/basic/srv/vm/static/js/admin.js b/basic/srv/vm/static/js/admin.js index 3ea833b..e2b3a24 100644 --- a/basic/srv/vm/static/js/admin.js +++ b/basic/srv/vm/static/js/admin.js @@ -8,7 +8,10 @@ $(function() { $('#update-common').on('submit', update_common); $('.app-visible').on('click', update_app_visibility); $('.app-autostart').on('click', update_app_autostart); - $('tr[data-app]').on('click', '.app-start', start_app).on('click', '.app-stop', stop_app); + $('#app-manager') + .on('click', '.app-start', start_app) + .on('click', '.app-stop', stop_app) + .on('click', '.app-install', install_app); $('#update-password').on('submit', update_password); $('#reboot-vm').on('click', reboot_vm); $('#shutdown-vm').on('click', shutdown_vm); @@ -139,14 +142,14 @@ function update_app_autostart(ev) { function start_app(ev) { var el = $(ev.target); - var app = el.closest('tr').data('app'); + var tr = el.closest('tr'); var td = el.closest('td'); td.html('
'); - $.post('/start-app', {'app': app}, function(data) { + $.post('/start-app', {'app': tr.data('app')}, function(data) { if (data.error) { td.attr('class','error').html(data.error); } else { - td.removeAttr('class').html(data.ok); + tr.replaceWith(data.ok); } }); return false; @@ -154,14 +157,29 @@ function start_app(ev) { function stop_app(ev) { var el = $(ev.target); - var app = el.closest('tr').data('app'); + var tr = el.closest('tr'); var td = el.closest('td'); td.html('
'); - $.post('/stop-app', {'app': app}, function(data) { + $.post('/stop-app', {'app': tr.data('app')}, function(data) { if (data.error) { td.attr('class','error').html(data.error); } else { - td.removeAttr('class').html(data.ok); + tr.replaceWith(data.ok); + } + }); + return false; +} + +function install_app(ev) { + var el = $(ev.target); + var tr = el.closest('tr'); + var td = el.closest('td'); + td.html('
'); + $.post('/install-app', {'app': tr.data('app')}, function(data) { + if (data.error) { + td.attr('class','error').html(data.error); + } else { + tr.replaceWith(data.ok); } }); return false; diff --git a/basic/srv/vm/templates/setup-apps-row.html b/basic/srv/vm/templates/setup-apps-row.html new file mode 100644 index 0000000..378e1de --- /dev/null +++ b/basic/srv/vm/templates/setup-apps-row.html @@ -0,0 +1,7 @@ + + {{ app_title }} + + + {% if app not in conf['apps'] %} Není nainstalována{% elif is_service_started(app) %}Spuštěna{% else %}Zastavena{% endif %} + {% if app not in conf['apps'] %}Instalovat{% else %}{% if is_service_started(app) %}Zastavit{% else %}Spustit{% endif %}, Odinstalovat{% endif %} + diff --git a/basic/srv/vm/templates/setup-apps.html b/basic/srv/vm/templates/setup-apps.html index 234641a..4ecc441 100644 --- a/basic/srv/vm/templates/setup-apps.html +++ b/basic/srv/vm/templates/setup-apps.html @@ -34,50 +34,20 @@

Správce aplikací

Vyberte které aplikace mají být nainstalovány, které se mají zobrazovat na hlavní straně portálu a které mají být automaticky spuštěny při startu virtuálního stroje.

- +
- + {% for app in all_apps %} - - - - - - - - {% endfor %} - -
AplikaceNainstalována Zobrazena Autostart StavAkce
{{ conf['apps'][app]['title'] if app in conf['apps'] else online_packages[app]['title'] }}{% if is_service_started(app) %}Spuštěna (zastavit){% else %}Zastavena (spustit){% endif %}
-
- -
-

Správce balíků

-

Vyberte které aplikace mají být nainstalovány nebo aktualizovány z distribučního serveru.

- - - - - - - - - - {% for pkg in online_packages|sort %} - {% if 'title' in online_packages[pkg] %} - - - - - - {% endif %} + {% set app_title = conf['apps'][app]['title'] if app in conf['apps'] else online_packages[app]['title'] %} + {% include 'setup-apps-row.html' %} {% endfor %}
AplikaceNainstalovánaStav
{{ online_packages[pkg]['title'] }}