From fed13217dc2b0b84e20193882b9a3ea2d081ee8f Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Sat, 7 May 2016 10:32:51 +0000 Subject: [PATCH] Improved misc admin interface --- README.md | 10 ++++----- TODO.md | 6 +++++ orchestra/contrib/miscellaneous/admin.py | 24 +++++++++++++++----- orchestra/contrib/webapps/admin.py | 2 +- orchestra/plugins/forms.py | 28 +++++++++++++++++++----- orchestra/plugins/options.py | 7 ++++++ 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 668b5dd3..792f8147 100644 --- a/README.md +++ b/README.md @@ -71,16 +71,16 @@ Quick Start ```bash orchestra@panel:~ ssh-copy-id root@server.address ``` - Then add the servers using the web interface `/admin/orchestration/servers`, check that the SSH connection is working and Orchestra can report the uptime of the servers. + Then add the servers using the web interface `/admin/orchestration/servers`, check that the SSH connection is working and Orchestra is able to report servers uptimes. -2. Configure the services, one at a time, staring with domains, databases, webapps, websites, ... +2. Configure your services, one at a time, staring with domains, databases, webapps, websites, ... 1. Add related [routes](orchestra/contrib/orchestration) via `/admin/orchestration/route/` 2. Configure related settings on `/admin/settings/setting/` - 3. If required, configure related [resources](orchestra/contrib/resources) like Account disc limit, VPS traffic, etc `/resources/resource/` - 3. Test creating and deleting service instances works as expected + 3. If required, configure related [resources](orchestra/contrib/resources) like *account disk limit*, *VPS traffic*, etc `/resources/resource/` + 3. Test if create and delete service instances works as expected 4. Do the same for the remaining services. You can disable services that you don't want by editing `INSTALLED_APPS` setting -3. Configure billing by adding [services](orchestra/contrib/services) `/admin/services/service/add/` and [plans](orchestra/contrib/plans) `/admin/plans/plan/`. Once a service is created hit the *Update orders* button to create orders for existing service instances. +3. Configure billing by adding [services](orchestra/contrib/services) `/admin/services/service/add/` and [plans](orchestra/contrib/plans) `/admin/plans/plan/`. Once a service is created hit the *Update orders* button to create orders for existing service instances, orders for new instances will be automatically created. diff --git a/TODO.md b/TODO.md index 9a2bd186..39a3827f 100644 --- a/TODO.md +++ b/TODO.md @@ -454,3 +454,9 @@ mkhomedir_helper or create ssh homes with bash.rc and such # exclude from change list action, support for multiple exclusion # breadcrumbs https://orchestra.pangea.org/admin/domains/domain/?account_id=930 + +with open(file) as handler: + os.unlink(file) + + +# change filter By PHP version: by detail diff --git a/orchestra/contrib/miscellaneous/admin.py b/orchestra/contrib/miscellaneous/admin.py index 1393034a..d240dd42 100644 --- a/orchestra/contrib/miscellaneous/admin.py +++ b/orchestra/contrib/miscellaneous/admin.py @@ -21,6 +21,7 @@ from .models import MiscService, Miscellaneous class MiscServicePlugin(PluginModelAdapter): model = MiscService name_field = 'name' + plugin_field = 'service' class MiscServiceAdmin(ExtendedModelAdmin): @@ -56,12 +57,16 @@ class MiscServiceAdmin(ExtendedModelAdmin): return super(MiscServiceAdmin, self).formfield_for_dbfield(db_field, **kwargs) -class MiscellaneousAdmin(AccountAdminMixin, SelectPluginAdminMixin, admin.ModelAdmin): +class MiscellaneousAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin): list_display = ( '__str__', 'service_link', 'amount', 'account_link', 'dispaly_active' ) list_filter = ('service__name', 'is_active') list_select_related = ('service', 'account') + readonly_fields = ('account_link', 'service_link') + add_fields = ('service', 'account', 'description', 'is_active') + fields = ('service_link', 'account', 'description', 'is_active') + change_readonly_fields = ('identifier', 'service') search_fields = ('identifier', 'description', 'account__username') actions = (disable, enable) plugin_field = 'service' @@ -82,19 +87,26 @@ class MiscellaneousAdmin(AccountAdminMixin, SelectPluginAdminMixin, admin.ModelA return obj.service def get_fields(self, request, obj=None): - fields = ['account', 'description', 'is_active'] - if obj is not None: - fields = ['account_link', 'description', 'is_active'] + fields = super().get_fields(request, obj) + fields = list(fields) service = self.get_service(obj) + if obj: + fields.insert(1, 'account_link') if service.has_amount: fields.insert(-1, 'amount') if service.has_identifier: - fields.insert(1, 'identifier') + fields.insert(2, 'identifier') return fields def get_form(self, request, obj=None, **kwargs): - form = super(SelectPluginAdminMixin, self).get_form(request, obj, **kwargs) + if obj: + plugin = self.plugin.get(obj.service.name)() + else: + plugin = self.plugin.get(self.plugin_value)() + self.form = plugin.get_form() + self.plugin_instance = plugin service = self.get_service(obj) + form = super(SelectPluginAdminMixin, self).get_form(request, obj, **kwargs) def clean_identifier(self, service=service): identifier = self.cleaned_data['identifier'] validator_path = settings.MISCELLANEOUS_IDENTIFIER_VALIDATORS.get(service.name, None) diff --git a/orchestra/contrib/webapps/admin.py b/orchestra/contrib/webapps/admin.py index b3eaafe6..12e3aaee 100644 --- a/orchestra/contrib/webapps/admin.py +++ b/orchestra/contrib/webapps/admin.py @@ -55,7 +55,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin) ) list_filter = ('type', HasWebsiteListFilter, PHPVersionListFilter) inlines = [WebAppOptionInline] - readonly_fields = ('account_link', ) + readonly_fields = ('account_link',) change_readonly_fields = ('name', 'type', 'display_websites') search_fields = ('name', 'account__username', 'data', 'website__domains__name') list_prefetch_related = ('content_set__website', 'content_set__website__domains') diff --git a/orchestra/plugins/forms.py b/orchestra/plugins/forms.py index 01286497..0394f742 100644 --- a/orchestra/plugins/forms.py +++ b/orchestra/plugins/forms.py @@ -1,20 +1,26 @@ from django import forms from django.utils.encoding import force_text +from orchestra.admin.utils import admin_link from orchestra.forms.widgets import SpanWidget -class PluginDataForm(forms.ModelForm): - data = forms.CharField(widget=forms.HiddenInput, required=False) - +class PluginForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(PluginDataForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.plugin_field in self.fields: value = self.plugin.get_name() display = '%s change' % force_text(self.plugin.verbose_name) self.fields[self.plugin_field].widget = SpanWidget(original=value, display=display) help_text = self.fields[self.plugin_field].help_text self.fields[self.plugin_field].help_text = getattr(self.plugin, 'help_text', help_text) + + +class PluginDataForm(PluginForm): + data = forms.CharField(widget=forms.HiddenInput, required=False) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) if self.instance: for field in self.declared_fields: initial = self.fields[field].initial @@ -37,7 +43,7 @@ class PluginDataForm(forms.ModelForm): self.fields[field].widget = SpanWidget(original=value, display=display) def clean(self): - super(PluginDataForm, self).clean() + super().clean() data = {} # Update data fields for field in self.declared_fields: @@ -53,3 +59,15 @@ class PluginDataForm(forms.ModelForm): except KeyError: data[field] = value self.cleaned_data['data'] = data + + +class PluginModelAdapterForm(PluginForm): + def __init__(self, *args, **kwargs): + super(PluginForm, self).__init__(*args, **kwargs) + if self.plugin_field in self.fields: + # Provide a link to the related DB object change view + value = self.plugin.related_instance.pk + link = admin_link()(self.plugin.related_instance) + display = '%s change' % link + self.fields[self.plugin_field].widget = SpanWidget(original=value, display=display) + help_text = self.fields[self.plugin_field].help_text diff --git a/orchestra/plugins/options.py b/orchestra/plugins/options.py index 0ff197aa..2dc4db1a 100644 --- a/orchestra/plugins/options.py +++ b/orchestra/plugins/options.py @@ -15,6 +15,8 @@ class Plugin(object): def __init__(self, instance=None): # Related model instance of this plugin self.instance = instance + from .forms import PluginForm + self.form = PluginForm @classmethod def get_name(cls): @@ -92,6 +94,11 @@ class PluginModelAdapter(Plugin): model = None name_field = None + def __init__(self, instance=None): + super().__init__(instance) + from .forms import PluginModelAdapterForm + self.form = PluginModelAdapterForm + @classmethod def get_plugins(cls): plugins = []