# # This file is part of Plinth. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # """ Main Plinth views """ from django.contrib import messages from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import reverse from django.http.response import HttpResponseRedirect from django.views.generic import TemplateView from django.views.generic.edit import FormView from django.utils.translation import ugettext as _ import time from . import forms import plinth def index(request): """Serve the main index page.""" return HttpResponseRedirect(reverse('apps:index')) class ServiceView(FormView): """A generic view for configuring simple services.""" service_id = None form_class = forms.ServiceForm template_name = 'service.html' # Set diagnostics_module_name to the module name to show diagnostics button diagnostics_module_name = "" # List of paragraphs describing the service description = "" # Display the 'status' block of the service.html template # This block uses information from service.is_running. This method is # optional, so allow not showing this block here. show_status_block = True @property def success_url(self): return self.request.path @property def service(self): if hasattr(self, '_service'): return self._service if not self.service_id: raise ImproperlyConfigured("missing attribute: 'service_id'") service = plinth.service.services.get(self.service_id, None) if service is None: message = "Could not find service %s" % self.service_id raise ImproperlyConfigured(message) self._service = service return service def get_initial(self): """Return the status of the service to fill in the form.""" return {'is_enabled': self.service.is_enabled(), 'is_running': self.service.is_running()} def form_valid(self, form): """Enable/disable a service and set messages.""" old_status = form.initial new_status = form.cleaned_data if old_status['is_enabled'] == new_status['is_enabled']: # TODO: find a more reliable/official way to check whether the # request has messages attached. if not self.request._messages._queued_messages: messages.info(self.request, _('Setting unchanged')) else: if new_status['is_enabled']: self.service.enable() messages.success(self.request, _('Application enabled')) else: self.service.disable() messages.success(self.request, _('Application disabled')) return super().form_valid(form) def get_context_data(self, *args, **kwargs): """Add service to the context data.""" context = super().get_context_data(*args, **kwargs) context['service'] = self.service if self.diagnostics_module_name: context['diagnostics_module_name'] = self.diagnostics_module_name if self.description: context['description'] = self.description context['show_status_block'] = self.show_status_block return context # TODO: remove this view once owncloud is gone. class ConfigurationView(FormView): """A generic view for configuring simple modules.""" form_class = forms.ConfigurationForm module_name = None def __init__(self, module_name=None, *args, **kwargs): """Set the module name on which this configuration view operates.""" self.instance_module_name = module_name def get_module_name(self): """Return the name of the module associated with the view.""" if not self.instance_module_name and not self.module_name: raise ImproperlyConfigured( 'Using ConfigurationView without the "module_name" class ' 'attribute or intialization attribute is prohibited.') else: return self.instance_module_name or self.module_name def get_module(self): """Return the module associated with the view.""" return plinth.module_loader.loaded_modules[self.get_module_name()] def get_initial(self): """Return the status of the module to fill in the form.""" return self.get_module().get_status() def get_prefix(self): """Return prefix for form used in the view.""" return self.get_module_name() def get_template_names(self): """Return the list of template names for the view.""" return [self.get_module_name() + '.html'] def get_context_data(self, **kwargs): """Return the context data for rendering the template view.""" if 'title' not in kwargs: kwargs['title'] = getattr(self.get_module(), 'title', None) if 'description' not in kwargs: kwargs['description'] = \ getattr(self.get_module(), 'description', None) context = super().get_context_data(**kwargs) if 'status' not in context: context['status'] = context['form'].initial return context def form_valid(self, form): """Perform operation when the form submission is valid.""" old_status = form.initial new_status = form.cleaned_data modified = self.apply_changes(old_status, new_status) if not modified: messages.info(self.request, _('Setting unchanged')) context = self.get_context_data() return self.render_to_response(context) def apply_changes(self, old_status, new_status): """Apply the changes submitted in the form.""" if old_status['enabled'] == new_status['enabled']: return False should_enable = new_status['enabled'] self.get_module().enable(should_enable) if should_enable: messages.success(self.request, _('Application enabled')) else: messages.success(self.request, _('Application disabled')) return True class SetupView(TemplateView): """View to prompt and setup applications.""" template_name = 'setup.html' def get_context_data(self, **kwargs): """Return the context data rendering the template.""" context = super(SetupView, self).get_context_data(**kwargs) context['setup_helper'] = self.kwargs['setup_helper'] return context def post(self, *args, **kwargs): """Handle installing/upgrading applications. Start the application setup, and refresh the page every few seconds to keep displaying the status. """ self.kwargs['setup_helper'].run_in_thread() # Give a moment for the setup process to start and show # meaningful status. time.sleep(1) return self.render_to_response(self.get_context_data())