diff options
author | Radomir Dopieralski <openstack@sheep.art.pl> | 2013-10-09 14:16:49 +0200 |
---|---|---|
committer | Radomir Dopieralski <openstack@sheep.art.pl> | 2013-10-23 15:52:13 +0200 |
commit | ddc6b1f60427b6cfb2b2113ddc6a489a47203579 (patch) | |
tree | add1991dfd55852a2ccbe27a606a5fb7a9e0dc46 | |
parent | 887e7459fd9117b6d734f605d19b18e099e34b7d (diff) | |
download | tuskar-ui-ddc6b1f60427b6cfb2b2113ddc6a489a47203579.tar.gz |
Separate flavors step
The flavors table is moved to a separate step in the resource class
creation workflow, and that step appears and disappears depending on
what class type is selected.
Change-Id: I44e63572a9acb73606d0c20a9fe3bc528ee3cc41
6 files changed, 126 insertions, 132 deletions
diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py index 572255fc..69a7c72a 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py @@ -70,18 +70,14 @@ class ResourcesClassFilterAction(tables.FilterAction): class ResourceClassesTable(tables.DataTable): - name = tables.Column("name", - link=('horizon:infrastructure:' - 'resource_management:resource_classes:detail'), - verbose_name=_("Class Name")) - service_type = tables.Column("service_type", - verbose_name=_("Class Type")) - racks_count = tables.Column("racks_count", - verbose_name=_("Racks"), - empty_value="0") - nodes_count = tables.Column("nodes_count", - verbose_name=_("Nodes"), - empty_value="0") + name = tables.Column("name", link=("horizon:infrastructure:" + "resource_management:resource_classes:detail"), + verbose_name=_("Class Name")) + service_type = tables.Column("service_type", verbose_name=_("Class Type")) + racks_count = tables.Column("racks_count", verbose_name=_("Racks"), + empty_value="0") + nodes_count = tables.Column("nodes_count", verbose_name=_("Nodes"), + empty_value="0") class Meta: name = "resource_classes" @@ -133,8 +129,8 @@ class UpdateRacksClass(tables.LinkAction): classes = ("ajax-modal", "btn-edit") def get_link_url(self, datum=None): - url = "horizon:infrastructure:resource_management:resource_classes:"\ - "update_racks" + url = ("horizon:infrastructure:resource_management:resource_classes:" + "update_racks") return "%s?step=%s" % ( urlresolvers.reverse( url, @@ -148,13 +144,12 @@ class UpdateFlavorsClass(tables.LinkAction): classes = ("ajax-modal", "btn-edit") def get_link_url(self, datum=None): - url = "horizon:infrastructure:resource_management:resource_classes:"\ - "update_flavors" + url = ("horizon:infrastructure:resource_management:resource_classes:" + "update_flavors") + resource_class_id = self.table.kwargs.get('resource_class_id') return "%s?step=%s" % ( - urlresolvers.reverse( - url, - args=(self.table.kwargs.get('resource_class_id'),)), - resource_classes.workflows.ResourceClassInfoAndFlavorsAction.slug) + urlresolvers.reverse(url, args=(resource_class_id,)), + resource_classes.workflows.ResourceClassFlavorsAction.slug) class FlavorsTable(tables.DataTable): @@ -162,15 +157,15 @@ class FlavorsTable(tables.DataTable): # FIXME - horizon Column.get_link_url does not allow to access GET # params resource_class_id = re.findall("[0-9]+", datum.request.path)[-1] - return urlresolvers.reverse("horizon:infrastructure:" - "resource_management:resource_classes:" - "flavors:detail", - args=(resource_class_id, datum.id)) - - name = tables.Column('name', - link=get_flavor_detail_link, - verbose_name=_('Flavor Name')) + return urlresolvers.reverse( + "horizon:infrastructure:resource_management:resource_classes:" + "flavors:detail", args=(resource_class_id, datum.id)) + name = tables.Column( + 'name', + link=get_flavor_detail_link, + verbose_name=_('Flavor Name'), + ) cpu = tables.Column( "cpu", verbose_name=_('VCPU'), @@ -196,9 +191,7 @@ class FlavorsTable(tables.DataTable): verbose_name=_('Swap Disk (MB)'), filters=(lambda x: getattr(x, 'value', ''),) ) - - max_vms = tables.Column("max_vms", - verbose_name=_("Max. VMs")) + max_vms = tables.Column("max_vms", verbose_name=_("Max. VMs")) class Meta: name = "flavors" @@ -207,7 +200,7 @@ class FlavorsTable(tables.DataTable): class FlavorsFormsetTable(tuskar_ui.tables.FormsetDataTableMixin, - FlavorsTable): + FlavorsTable): name = tables.Column( 'name', diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py index 17fd3af3..763b62ac 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py +++ b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py @@ -1,4 +1,3 @@ - # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -29,7 +28,11 @@ from tuskar_ui.infrastructure.resource_management.resource_classes\ import tuskar_ui.workflows -class ResourceClassInfoAndFlavorsAction(workflows.Action): +TEMPLATE_PREFIX = 'infrastructure/resource_management/resource_classes/' +URL_PREFIX = 'horizon:infrastructure:resource_management:' + + +class ResourceClassInfoAction(workflows.Action): name = forms.CharField(max_length=255, label=_("Class Name"), help_text="", @@ -57,20 +60,18 @@ class ResourceClassInfoAndFlavorsAction(workflows.Action): ) def __init__(self, *args, **kwargs): - super(ResourceClassInfoAndFlavorsAction, - self).__init__(*args, **kwargs) + super(ResourceClassInfoAction, self).__init__(*args, **kwargs) try: images, more = glance.image_list_detailed(self.request) except Exception: exceptions.handle(self.request, - _('Unable to retrieve image list.')) + _('Unable to retrieve image list.')) else: self.fields['image_id'].choices = [ (image.id, image.name) for image in images] def clean(self): - cleaned_data = super(ResourceClassInfoAndFlavorsAction, - self).clean() + cleaned_data = super(ResourceClassInfoAction, self).clean() name = cleaned_data.get('name') resource_class_id = self.initial.get('resource_class_id', None) @@ -89,6 +90,21 @@ class ResourceClassInfoAndFlavorsAction(workflows.Action): ' another resource class.') % name ) + return cleaned_data + + class Meta: + name = _("Class Settings") + help_text = _("From here you can fill in the class settings.") + + +class CreateResourceClassInfo(workflows.Step): + action_class = ResourceClassInfoAction + contributes = ("name", "service_type", "image_id") + + +class ResourceClassFlavorsAction(workflows.Action): + def clean(self): + cleaned_data = super(ResourceClassFlavorsAction, self).clean() table = self.initial.get('_tables', {}).get('flavors') if table: formset = table.get_formset() @@ -96,42 +112,36 @@ class ResourceClassInfoAndFlavorsAction(workflows.Action): cleaned_data['flavors'] = [form.cleaned_data for form in formset if form.cleaned_data - and not - form.cleaned_data.get('DELETE')] + and not form.cleaned_data['DELETE']] else: - raise forms.ValidationError( - _('Errors in the flavors list.'), - ) + raise forms.ValidationError(_('Errors in the flavors list.')) return cleaned_data class Meta: - name = _("Class Settings") - help_text = _("From here you can fill the class " - "settings and add flavors to class.") + name = _("Flavors") + help_text = _("From here you can add flavors to the class.") -class CreateResourceClassInfoAndFlavors(tuskar_ui.workflows.TableStep): +class CreateResourceClassFlavors(tuskar_ui.workflows.TableStep): table_classes = (tables.FlavorsFormsetTable,) - action_class = ResourceClassInfoAndFlavorsAction - template_name = 'infrastructure/resource_management/resource_classes/'\ - '_resource_class_info_and_flavors_step.html' - contributes = ("name", "service_type", "image_id", "flavors") + action_class = ResourceClassFlavorsAction + template_name = TEMPLATE_PREFIX + '_flavors_step.html' + contributes = ("flavors",) def get_flavors_data(self): try: resource_class_id = self.workflow.context.get("resource_class_id") if resource_class_id: resource_class = tuskar.ResourceClass.get( - self.workflow.request, - resource_class_id) + self.workflow.request, resource_class_id) flavors = resource_class.list_flavors else: flavors = [] except Exception: flavors = [] exceptions.handle(self.workflow.request, - _('Unable to retrieve resource flavors list.')) + _('Unable to retrieve resource flavors list.')) return flavors @@ -151,9 +161,7 @@ class RacksAction(workflows.Action): form.cleaned_data.get('selected') and not form.cleaned_data.get('DELETE')] else: - raise forms.ValidationError( - _('Errors in the racks table.'), - ) + raise forms.ValidationError(_('Errors in the racks table.')) return cleaned_data @@ -162,8 +170,7 @@ class CreateRacks(tuskar_ui.workflows.TableStep): action_class = RacksAction contributes = ("racks_object_ids") - template_name = 'infrastructure/resource_management/'\ - 'resource_classes/_racks_step.html' + template_name = TEMPLATE_PREFIX + '_table_step.html' def contribute(self, data, context): context.update(data) @@ -198,10 +205,9 @@ class ResourceClassWorkflowMixin: # tab it should redirect after action, until the coflict will # be fixed in Horizon. def get_index_url(self): - """This url is used both as success and failure url""" - return "%s?tab=resource_management_tabs__resource_classes_tab" %\ - urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index') + # This url is used both as success and failure url + return "%s?tab=resource_management_tabs__resource_classes_tab" % ( + urlresolvers.reverse(URL_PREFIX + 'index')) def get_success_url(self): return self.get_index_url() @@ -239,7 +245,7 @@ class ResourceClassWorkflowMixin: class CreateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): - default_steps = (CreateResourceClassInfoAndFlavors, + default_steps = (CreateResourceClassInfo, CreateResourceClassFlavors, CreateRacks) slug = "create_resource_class" @@ -273,7 +279,11 @@ class CreateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): return True -class UpdateResourceClassInfoAndFlavors(CreateResourceClassInfoAndFlavors): +class UpdateResourceClassInfo(CreateResourceClassInfo): + depends_on = ("resource_class_id",) + + +class UpdateResourceClassFlavors(CreateResourceClassFlavors): depends_on = ("resource_class_id",) @@ -282,7 +292,7 @@ class UpdateRacks(CreateRacks): class UpdateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): - default_steps = (UpdateResourceClassInfoAndFlavors, + default_steps = (UpdateResourceClassInfo, UpdateResourceClassFlavors, UpdateRacks) slug = "update_resource_class" @@ -319,29 +329,26 @@ class UpdateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): class DetailUpdateWorkflow(UpdateResourceClass): def get_index_url(self): - """This url is used both as success and failure url""" - url = "horizon:infrastructure:resource_management:resource_classes:"\ - "detail" + # This url is used both as success and failure url + url = URL_PREFIX + "resource_classes:detail" + resource_class_id = self.context["resource_class_id"] return "%s?tab=resource_class_details__overview" % ( - urlresolvers.reverse(url, - args=(self.context["resource_class_id"]))) + urlresolvers.reverse(url, args=(resource_class_id,))) -class UpdateRacksWorkflow(UpdateResourceClass): +class UpdateFlavorsWorkflow(UpdateResourceClass): def get_index_url(self): - """This url is used both as success and failure url""" - url = "horizon:infrastructure:resource_management:resource_classes:"\ - "detail" - return "%s?tab=resource_class_details__racks" % ( - urlresolvers.reverse(url, - args=(self.context["resource_class_id"]))) + # This url is used both as success and failure url + url = URL_PREFIX + "resource_classes:detail" + resource_class_id = self.context["resource_class_id"] + return "%s?tab=resource_class_details__flavors" % ( + urlresolvers.reverse(url, args=(resource_class_id,))) -class UpdateFlavorsWorkflow(UpdateResourceClass): +class UpdateRacksWorkflow(UpdateResourceClass): def get_index_url(self): - """This url is used both as success and failure url""" - url = "horizon:infrastructure:resource_management:resource_classes:"\ - "detail" - return "%s?tab=resource_class_details__flavors" % ( - urlresolvers.reverse(url, - args=(self.context["resource_class_id"]))) + # This url is used both as success and failure url + url = URL_PREFIX + "resource_classes:detail" + resource_class_id = self.context["resource_class_id"] + return "%s?tab=resource_class_details__racks" % ( + urlresolvers.reverse(url, args=(resource_class_id,))) diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html new file mode 100644 index 00000000..a75c6d9f --- /dev/null +++ b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html @@ -0,0 +1,35 @@ +{% extends "infrastructure/resource_management/resource_classes/_table_step.html" %} +{% block table_step %} + <div id="flavors-table-block"> + {{ block.super }} + </div> + <script> + (window.$ || window.addHorizonLoadEvent)(function () { + 'use strict'; + + var $select = $('select#id_service_type'), + $table_block = $('#flavors-table-block'), + $tab = $( + 'a[data-target="#create_resource_class__' + + 'resourceclassflavorsaction"], ' + + 'a[data-target="#update_resource_class__' + + 'resourceclassflavorsaction"]' + ).parent('li'); + + $select.change(function () { + if ($select.val() === 'compute') { + $table_block.show(); + $tab.show(300); + } else { + $table_block.hide(); + $tab.hide(300); + }; + }); + + if ($select.val() !== 'compute') { + $table_block.hide(); + $tab.hide(); + }; + }); + </script> +{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_racks_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_racks_step.html deleted file mode 100644 index 2c6d885b..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_racks_step.html +++ /dev/null @@ -1,3 +0,0 @@ -<noscript><h3>{{ step }}</h3></noscript> - -{{ racks_table.render }} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_resource_class_info_and_flavors_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_resource_class_info_and_flavors_step.html deleted file mode 100644 index c7f5059a..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_resource_class_info_and_flavors_step.html +++ /dev/null @@ -1,43 +0,0 @@ -<noscript><h3>{{ step }}</h3></noscript> -<table class="table-fixed"> - <tbody> - <tr> - <td class="actions"> - {% include "horizon/common/_form_fields.html" %} - </td> - <td class="help_text"> - {{ step.get_help_text }} - </td> - </tr> - </tbody> -</table> - -<div id="id_resource_class_flavors_table"> - {{ flavors_table.render }} -</div> - -<script type="text/javascript"> -(function () { - // show the flavors table only when service_type is compute - var init_table = function () { - var toggle_table = function (value) { - if (value === 'compute') { - $('#id_resource_class_flavors_table').show(); - } else { - $('#id_resource_class_flavors_table').hide(); - } - }; - - toggle_table($('#id_service_type').val()) - $('#id_service_type').change(function () { - toggle_table($('#id_service_type').val()); - }); - }; - - if (typeof($) !== 'undefined') { - $(init_table); - } else { - addHorizonLoadEvent(init_table); - } -} ()); -</script> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html new file mode 100644 index 00000000..55bfb116 --- /dev/null +++ b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html @@ -0,0 +1,5 @@ +{% block table_step %} +<noscript><h3>{{ step }}</h3></noscript> + +{{ table.render }} +{% endblock %} |