From 20497aeb3940e705acf0edf335298f616fcc89da Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Mon, 27 Nov 2017 16:03:18 +1100 Subject: [PATCH 1/6] CloudSubnet: Convert Controller to Component --- .../cloud_subnet/cloud-subnet-form.js | 85 ++++++++++++ .../cloud_subnet_form_controller.js | 89 ------------ app/controllers/cloud_subnet_controller.rb | 17 +-- app/views/cloud_subnet/_common_new_edit.haml | 53 ------- app/views/cloud_subnet/edit.html.haml | 53 +------ app/views/cloud_subnet/new.html.haml | 71 +--------- .../cloud_subnet/cloud-subnet-form.html.haml | 130 ++++++++++++++++++ .../cloud_subnet_controller_spec.rb | 37 ++++- .../cloud_subnet/cloud_subnet_form_spec.js | 91 ++++++++++++ 9 files changed, 354 insertions(+), 272 deletions(-) create mode 100644 app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js delete mode 100644 app/assets/javascripts/controllers/cloud_subnet/cloud_subnet_form_controller.js delete mode 100644 app/views/cloud_subnet/_common_new_edit.haml create mode 100644 app/views/static/cloud_subnet/cloud-subnet-form.html.haml create mode 100644 spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js diff --git a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js new file mode 100644 index 00000000000..e3478c546aa --- /dev/null +++ b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js @@ -0,0 +1,85 @@ +ManageIQ.angular.app.component('cloudSubnetForm', { + bindings: { + cloudSubnetFormId: '@', + }, + controllerAs: 'vm', + controller: cloudSubnetFormController, + templateUrl: '/static/cloud_subnet/cloud-subnet-form.html.haml', +}); + +cloudSubnetFormController.$inject = ['API', 'miqService']; + +function cloudSubnetFormController(API, miqService) { + var vm = this; + + this.$onInit = function() { + vm.afterGet = false; + + vm.cloudSubnetModel = { name: '' }; + vm.networkProtocols = ['ipv4', 'ipv6']; + + vm.formId = vm.cloudSubnetFormId; + vm.model = 'cloudSubnetModel'; + ManageIQ.angular.scope = vm; + vm.saveable = miqService.saveable; + + vm.newRecord = vm.cloudSubnetFormId === 'new'; + + miqService.sparkleOn(); + if (vm.newRecord) { + vm.cloudSubnetModel.ems_id = ''; + vm.cloudSubnetModel.network_id = ''; + vm.cloudSubnetModel.dhcp_enabled = true; + vm.cloudSubnetModel.network_protocol = 'ipv4'; + API.get("/api/providers?expand=resources&attributes=name&filter[]=type='*NetworkManager'").then(function(data) { + vm.available_ems = data.resources; + vm.afterGet = true; + vm.modelCopy = angular.copy( vm.cloudSubnetModel ); + miqService.sparkleOff(); + }).catch(miqService.handleFailure); + } else { + API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network").then(function(data) { + Object.assign(vm.cloudSubnetModel, data); + vm.afterGet = true; + vm.modelCopy = angular.copy( vm.cloudSubnetModel ); + miqService.sparkleOff(); + }).catch(miqService.handleFailure); + } + }; + + vm.addClicked = function() { + var url = 'create/new?button=add'; + miqService.miqAjaxButton(url, vm.cloudSubnetModel, { complete: false }); + }; + + vm.cancelClicked = function() { + if (vm.newRecord) { + var url = '/cloud_subnet/create/new?button=cancel'; + } else { + var url = '/cloud_subnet/update/' + vm.cloudSubnetFormId + '?button=cancel'; + } + miqService.miqAjaxButton(url); + }; + + vm.saveClicked = function() { + var url = '/cloud_subnet/update/' + vm.cloudSubnetFormId + '?button=save'; + miqService.miqAjaxButton(url, vm.cloudSubnetModel, { complete: false }); + }; + + vm.resetClicked = function(angularForm) { + vm.cloudSubnetModel = angular.copy( vm.modelCopy ); + angularForm.$setPristine(true); + miqService.miqFlash("warn", _('All changes have been reset')); + }; + + vm.filterNetworkManagerChanged = function(id) { + if (id) { + API.get("/api/cloud_networks?expand=resources&attributes=name,ems_ref&filter[]=ems_id=" + id).then(function(data) { + vm.available_networks = data.resources; + }).catch(miqService.handleFailure); + miqService.getProviderTenants(function(data) { + vm.available_tenants = data.resources; + })(id); + } + }; +} diff --git a/app/assets/javascripts/controllers/cloud_subnet/cloud_subnet_form_controller.js b/app/assets/javascripts/controllers/cloud_subnet/cloud_subnet_form_controller.js deleted file mode 100644 index 6cc00162031..00000000000 --- a/app/assets/javascripts/controllers/cloud_subnet/cloud_subnet_form_controller.js +++ /dev/null @@ -1,89 +0,0 @@ -ManageIQ.angular.app.controller('cloudSubnetFormController', ['cloudSubnetFormId', 'miqService', 'API', function(cloudSubnetFormId, miqService, API) { - var vm = this; - - var init = function() { - vm.afterGet = false; - vm.cloudSubnetModel = { - name: "", - ems_id: "", - cloud_tenant_id: "", - network_id: "", - }; - vm.ems = []; - - vm.networkProtocols = ["ipv4", "ipv6"]; - vm.formId = cloudSubnetFormId; - vm.model = "cloudSubnetModel"; - vm.newRecord = cloudSubnetFormId === "new"; - ManageIQ.angular.scope = vm; - vm.saveable = miqService.saveable; - - if (vm.newRecord) { - vm.cloudSubnetModel.dhcp_enabled = true; - vm.cloudSubnetModel.network_protocol = "ipv4"; - vm.afterGet = true; - vm.modelCopy = angular.copy( vm.cloudSubnetModel ); - - miqService.networkProviders() - .then(function(providers) { - vm.ems = providers; - }); - } else { - miqService.sparkleOn(); - API.get("/api/cloud_subnets/" + cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant.name,cloud_network.name").then(function(data) { - vm.cloudSubnetModel.name = data.name; - vm.cloudSubnetModel.ems_name = data.ext_management_system.name; - vm.cloudSubnetModel.tenant_name = angular.isDefined(data.cloud_tenant) ? data.cloud_tenant.name : undefined; - vm.cloudSubnetModel.network_name = data.cloud_network.name; - vm.cloudSubnetModel.dhcp_enabled = data.dhcp_enabled; - vm.cloudSubnetModel.cidr = data.cidr; - vm.cloudSubnetModel.gateway = data.gateway; - vm.cloudSubnetModel.network_protocol = data.network_protocol; - vm.afterGet = true; - vm.modelCopy = angular.copy( vm.cloudSubnetModel ); - miqService.sparkleOff(); - }).catch(miqService.handleFailure); - } - }; - - vm.addClicked = function() { - var url = 'create/new' + '?button=add'; - miqService.miqAjaxButton(url, vm.cloudSubnetModel, { complete: false }); - }; - - vm.cancelClicked = function() { - if (cloudSubnetFormId == 'new') { - var url = '/cloud_subnet/create/new' + '?button=cancel'; - } else { - var url = '/cloud_subnet/update/' + cloudSubnetFormId + '?button=cancel'; - } - miqService.miqAjaxButton(url); - }; - - vm.saveClicked = function() { - var url = '/cloud_subnet/update/' + cloudSubnetFormId + '?button=save'; - miqService.miqAjaxButton(url, vm.cloudSubnetModel, { complete: false }); - }; - - vm.resetClicked = function(angularForm) { - vm.cloudSubnetModel = angular.copy( vm.modelCopy ); - angularForm.$setPristine(true); - miqService.miqFlash("warn", "All changes have been reset"); - }; - - vm.filterNetworkManagerChanged = function(id) { - miqService.sparkleOn(); - if (id) { - API.get("/api/cloud_networks?expand=resources&attributes=name,ems_ref&filter[]=ems_id=" + id).then(function(data) { - vm.available_networks = data.resources; - }).catch(miqService.handleFailure); - - miqService.getProviderTenants(function(data) { - vm.available_tenants = data.resources; - })(id); - } - miqService.sparkleOff(); - }; - - init(); -}]); diff --git a/app/controllers/cloud_subnet_controller.rb b/app/controllers/cloud_subnet_controller.rb index 5888c422536..fb6cfc3fc94 100644 --- a/app/controllers/cloud_subnet_controller.rb +++ b/app/controllers/cloud_subnet_controller.rb @@ -47,12 +47,8 @@ def new assert_privileges("cloud_tenant_show_list") assert_privileges("cloud_network_show_list") - @subnet = CloudSubnet.new @in_a_form = true - drop_breadcrumb( - :name => _("Add New Subnet"), - :url => "/cloud_subnet/new" - ) + drop_breadcrumb(:name => _("Add New Subnet"), :url => "/cloud_subnet/new") end def create @@ -213,14 +209,15 @@ def switch_to_bol(option) end def changed_form_params - # Fields allowed for update are: name, enable_dhcp, dns_nameservers, allocation_pools, host_routes, gateway_ip + # Allowed fields for update: name, enable_dhcp, dns_nameservers, allocation_pools, host_routes, gateway_ip options = {} options[:name] = params[:name] unless @subnet.name == params[:name] - # A gateway address is automatically assigned by Openstack when gateway is null + # Provider to automatically assign gateway address unless provided unless @subnet.gateway == params[:gateway] options[:gateway_ip] = params[:gateway].blank? ? nil : params[:gateway] end + unless @subnet.dhcp_enabled == switch_to_bol(params[:dhcp_enabled]) options[:enable_dhcp] = switch_to_bol(params[:dhcp_enabled]) end @@ -235,15 +232,15 @@ def new_form_params options[:name] = params[:name] if params[:name] options[:ems_id] = params[:ems_id] if params[:ems_id] options[:cidr] = params[:cidr] if params[:cidr] - # An address is automatically assigned by Openstack when gateway is null + # Provider to automatically assign gateway address unless provided if params[:gateway] options[:gateway_ip] = params[:gateway].blank? ? nil : params[:gateway] end options[:ip_version] = params[:network_protocol] =~ /4/ ? 4 : 6 - options[:cloud_tenant] = find_record_with_rbac(CloudTenant, params[:cloud_tenant_id]) if params[:cloud_tenant_id] + options[:cloud_tenant] = find_record_with_rbac(CloudTenant, params[:cloud_tenant][:id]) if params[:cloud_tenant][:id] options[:network_id] = params[:network_id] if params[:network_id] options[:enable_dhcp] = params[:dhcp_enabled] - # TODO: Add extra fields + # TODO: Add dns_nameservers, allocation_pools, host_routes options[:availability_zone_id] = params[:availability_zone_id] if params[:availability_zone_id] if params[:ipv6_router_advertisement_mode] options[:ipv6_router_advertisement_mode] = params[:ipv6_router_advertisement_mode] diff --git a/app/views/cloud_subnet/_common_new_edit.haml b/app/views/cloud_subnet/_common_new_edit.haml deleted file mode 100644 index d3371f6c412..00000000000 --- a/app/views/cloud_subnet/_common_new_edit.haml +++ /dev/null @@ -1,53 +0,0 @@ -.form-horizontal - .form-group - %label.col-md-2.control-label - = _('Subnet Name') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "name", - "ng-model" => "vm.cloudSubnetModel.name", - "ng-maxlength" => 128} - .form-group - %label.col-md-2.control-label - = _('Gateway') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "gateway_ip", - "ng-model" => "vm.cloudSubnetModel.gateway", - "ng-maxlength" => 20} - .form-group - %label.control-label.col-md-2{"for" => "cloud_subnet_dhcp_enabled"} - = _('Enable DHCP') - .col-md-8 - %input{"type" => "checkbox", - "name" => "dhcp_enabled", - "bs-switch" => "", - "data" => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "id" => "cloud_subnet_dhcp_enabled", - "ng-model" => "vm.cloudSubnetModel.dhcp_enabled"} - .form-group{"ng-class" => "{'has-error': angularForm.network_protocol.$invalid}"} - %label.col-md-2.control-label - = _('IP Version') - .col-md-8 - %select{"name" => "network_protocol", - "ng-model" => "vm.cloudSubnetModel.network_protocol", - "required" => "", - "ng-disabled" => "!vm.newRecord", - "ng-options" => "protocol as protocol for protocol in vm.networkProtocols", - "pf-select" => true, - "selectpicker-for-select-tag" => ""} - %span.help-block{"ng-show" => "angularForm.network_protocol.$error.required"} - = _("Required") - - .form-group{"ng-class" => "{'has-error': angularForm.cidr.$invalid}"} - %label.col-md-2.control-label - = _('Subnet CIDR') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "cidr", - "ng-disabled" => "!vm.newRecord", - "ng-model" => "vm.cloudSubnetModel.cidr", - "ng-maxlength" => 20, - "required" => ""} - %span.help-block{"ng-show" => "angularForm.cidr.$error.required"} - = _("Required") diff --git a/app/views/cloud_subnet/edit.html.haml b/app/views/cloud_subnet/edit.html.haml index 8bc7bddee5c..885cb265960 100644 --- a/app/views/cloud_subnet/edit.html.haml +++ b/app/views/cloud_subnet/edit.html.haml @@ -1,51 +1,6 @@ -%form#form_div{"name" => "angularForm", - "form-changed" => true, - "miq-form" => true, - "model" => "vm.cloudSubnetModel", - "model-copy" => "vm.modelCopy", - "ng-cloak" => "", - "ng-controller" => "cloudSubnetFormController as vm", - "ng-show" => "vm.afterGet"} - = render :partial => "layouts/flash_msg" - %h3 - = _('Network Provider') - .form-horizontal - .form-group - %label.col-md-2.control-label - = _('Network Manager') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "ems_name", - "ng-model" => "vm.cloudSubnetModel.ems_name", - "ng-maxlength" => 128, - "readonly" => true} - %h3 - = _('Placement') - .form-horizontal - .form-group - %label.col-md-2.control-label - = _('Cloud Tenant') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "tenant_name", - "ng-model" => "vm.cloudSubnetModel.tenant_name", - "ng-maxlength" => 128, - "readonly" => true} - %h3 - = _('Cloud Subnet details') - .form-horizontal - .form-group - %label.col-md-2.control-label - = _('Network') - .col-md-8 - %input.form-control{"type" => "text", - "name" => "network_name", - "ng-model" => "vm.cloudSubnetModel.network_name", - "ng-maxlength" => 128, - "readonly" => true} - = render :partial => "common_new_edit" - = render :partial => "layouts/angular/generic_form_buttons" += render :partial => "layouts/flash_msg" + +%cloud-subnet-form{'cloud-subnet-form-id' => @subnet.id} :javascript - ManageIQ.angular.app.value('cloudSubnetFormId', '#{@subnet.id}'); - miq_bootstrap('#form_div'); + miq_bootstrap('cloud-subnet-form'); diff --git a/app/views/cloud_subnet/new.html.haml b/app/views/cloud_subnet/new.html.haml index be19fb9fba3..baa43ef1062 100644 --- a/app/views/cloud_subnet/new.html.haml +++ b/app/views/cloud_subnet/new.html.haml @@ -1,69 +1,6 @@ -%form#form_div{"name" => "angularForm", - "form-changed" => true, - "miq-form" => true, - "model" => "vm.cloudSubnetModel", - "model-copy" => "vm.modelCopy", - "ng-cloak" => "", - "ng-controller" => "cloudSubnetFormController as vm", - "ng-show" => "vm.afterGet"} - = render :partial => "layouts/flash_msg" - %h3 - = _('Network Provider') - .form-horizontal - .form-group{"ng-class" => "{'has-error': angularForm.ems_id.$invalid}"} - %label.col-md-2.control-label - = _('Network Manager') - .col-md-8 - %select{'id' => 'ems_id', - 'name' => 'ems_id', - 'ng-change' => "vm.filterNetworkManagerChanged(vm.cloudSubnetModel.ems_id)", - 'ng-model' => "vm.cloudSubnetModel.ems_id", - 'ng-options' => 'ems.id as ems.name for ems in vm.ems', - 'pf-select' => true, - 'required' => ''} - %option{:value => ""} - = "<#{_('Choose')}>" - %span.help-block{"ng-show" => "angularForm.ems_id.$error.required"} - = _("Required") - %h3 - = _('Placement') - .form-horizontal - .form-group{"ng-if" => "vm.cloudSubnetModel.ems_id", - "ng-class" => "{'has-error': angularForm.cloud_tenant_id.$invalid}"} - %label.col-md-2.control-label - = _('Cloud Tenant') - .col-md-8 - %select{"name" => "cloud_tenant_id", - "ng-model" => "vm.cloudSubnetModel.cloud_tenant_id", - "ng-options" => "tenant.id as tenant.name for tenant in vm.available_tenants", - "pf-select" => true, - "required" => "", - "selectpicker-for-select-tag" => ""} - %option{"value" => ""} - = "<#{_('Choose')}>" - %span.help-block{"ng-show" => "angularForm.cloud_tenant_id.$error.required"} - = _("Required") - %h3 - = _('Cloud Subnet details') - .form-horizontal - .form-group{"ng-if" => "vm.cloudSubnetModel.ems_id", - "ng-class" => "{'has-error': angularForm.network_id.$invalid}"} - %label.col-md-2.control-label - = _('Network') - .col-md-8 - %select{"name" => "network_id", - "ng-model" => "vm.cloudSubnetModel.network_id", - "ng-options" => "network.ems_ref as network.name for network in vm.available_networks", - "pf-select" => true, - "required" => "", - "selectpicker-for-select-tag" => ""} - %option{"value" => ""} - = "<#{_('Choose')}>" - %span.help-block{"ng-show" => "angularForm.network_id.$error.required"} - = _("Required") - = render :partial => "common_new_edit" - = render :partial => "layouts/angular/generic_form_buttons" += render :partial => "layouts/flash_msg" + +%cloud-subnet-form{'cloud-subnet-form-id' => 'new'} :javascript - ManageIQ.angular.app.value('cloudSubnetFormId', '#{@subnet.id || "new"}'); - miq_bootstrap('#form_div'); + miq_bootstrap('cloud-subnet-form'); diff --git a/app/views/static/cloud_subnet/cloud-subnet-form.html.haml b/app/views/static/cloud_subnet/cloud-subnet-form.html.haml new file mode 100644 index 00000000000..a01aba2ef32 --- /dev/null +++ b/app/views/static/cloud_subnet/cloud-subnet-form.html.haml @@ -0,0 +1,130 @@ +%form#form_div{'name' => 'angularForm', + 'form-changed' => true, + 'miq-form' => true, + 'model' => 'vm.cloudSubnetModel', + 'model-copy' => 'vm.modelCopy', + 'ng-cloak' => '', + 'ng-show' => 'vm.afterGet'} + + %h3 + = _('Network Management Provider') + .form-horizontal + .form-group{'ng-class' => '{"has-error": angularForm.ems_id.$invalid}'} + %label.col-md-2.control-label + = _('Network Manager') + .col-md-8{'ng-if' => 'vm.newRecord'} + %select{'name' => 'ems_id', + 'ng-change' => 'vm.filterNetworkManagerChanged(vm.cloudSubnetModel.ems_id)', + 'ng-model' => 'vm.cloudSubnetModel.ems_id', + 'ng-options' => 'ems.id as ems.name for ems in vm.available_ems', + 'pf-select' => true, + 'required' => '', + 'selectpicker-for-select-tag' => ''} + %option{'value' => ''} + = "<#{_('Choose')}>" + %span.help-block{'ng-show' => 'angularForm.ems_id.$error.required'} + = _('Required') + .col-md-8{'ng-if' => '!vm.newRecord'} + %input.form-control{'type' => 'text', + 'name' => 'ems_name', + 'disabled' => true, + 'maxlength' => 128, + 'ng-model' => 'vm.cloudSubnetModel.ext_management_system.name'} + .form-group{'ng-class' => '{"has-error": angularForm.cloud_tenant_id.$invalid}', + 'ng-if' => 'vm.cloudSubnetModel.ems_id'} + %label.col-md-2.control-label + = _('Cloud Tenant Placement') + .col-md-8{'ng-if' => 'vm.newRecord'} + %select{'name' => 'cloud_tenant_id', + 'ng-model' => 'vm.cloudSubnetModel.cloud_tenant.id', + 'ng-options' => 'tenant.id as tenant.name for tenant in vm.available_tenants', + 'pf-select' => true, + 'required' => '', + 'selectpicker-for-select-tag' => ''} + %option{'value' => ''} + = "<#{_('Choose')}>" + %span.help-block{'ng-show' => "angularForm.cloud_tenant_id.$error.required"} + = _('Required') + .col-md-8{'ng-if' => '!vm.newRecord'} + %input.form-control{'type' => 'text', + 'name' => ' clout_tenant_name', + 'maxlength' => 128, + 'ng-model' => 'vm.cloudSubnetModel.cloud_tenant.name', + 'disabled' => true} + %h3 + = _('Cloud Subnet details') + .form-horizontal + .form-group{'ng-class' => '{"has-error": angularForm.network_id.$invalid}'} + %label.col-md-2.control-label + = _('Network') + .col-md-8{'ng-if' => 'vm.newRecord'} + %select{'name' => 'network_id', + 'ng-model' => 'vm.cloudSubnetModel.network_id', + 'ng-options' => 'network.ems_ref as network.name for network in vm.available_networks', + 'pf-select' => true, + 'required' => '', + 'selectpicker-for-select-tag' => ''} + %option{'value' => ''} + = "<#{_('Choose')}>" + %span.help-block{'ng-show' => 'angularForm.network_id.$error.required'} + = _('Required') + .col-md-8{'ng-if' => '!vm.newRecord'} + %input.form-control{'type' => 'text', + 'name' => 'network_name', + 'maxlength' => 128, + 'ng-model' => 'vm.cloudSubnetModel.cloud_network.name', + 'disabled' => true} + .form-horizontal + .form-group + %label.col-md-2.control-label + = _('Subnet Name') + .col-md-8 + %input.form-control{'type' => 'text', + 'name' => 'name', + 'ng-model' => 'vm.cloudSubnetModel.name', + 'maxlength' => 128} + .form-group + %label.col-md-2.control-label + = _('Gateway') + .col-md-8 + %input.form-control{'type' => 'text', + 'name' => 'gateway_ip', + 'ng-model' => 'vm.cloudSubnetModel.gateway', + 'maxlength' => 20} + .form-group + %label.control-label.col-md-2{'for' => 'dhcp'} + = _('DHCP') + .col-md-8 + %input{'type' => 'checkbox', + 'name' => 'dhcp', + 'bs-switch' => '', + 'data' => {:on_text => _('Enabled'), :off_text => _('Disabled'), :size => 'mini'}, + 'ng-model' => 'vm.cloudSubnetModel.dhcp_enabled'} + .form-group{'ng-class' => '{"has-error": angularForm.network_protocol.$invalid}'} + %label.col-md-2.control-label + = _('IP Version') + .col-md-8 + %select{'name' => 'network_protocol', + 'ng-model' => 'vm.cloudSubnetModel.network_protocol', + 'ng-disabled' => '!vm.newRecord', + 'ng-options' => 'protocol as protocol for protocol in vm.networkProtocols', + 'pf-select' => true, + 'required' => '', + 'selectpicker-for-select-tag' => ''} + %span.help-block{'ng-show' => 'angularForm.network_protocol.$error.required'} + = _('Required') + + .form-group{'ng-class' => "{'has-error': angularForm.cidr.$invalid}"} + %label.col-md-2.control-label + = _('Subnet CIDR') + .col-md-8 + %input.form-control{'type' => 'text', + 'name' => 'cidr', + 'ng-disabled' => '!vm.newRecord', + 'ng-model' => 'vm.cloudSubnetModel.cidr', + 'maxlength' => 20, + 'required' => ''} + %span.help-block{'ng-show' => 'angularForm.cidr.$error.required'} + = _('Required') + + = render :partial => 'layouts/angular/generic_form_buttons' diff --git a/spec/controllers/cloud_subnet_controller_spec.rb b/spec/controllers/cloud_subnet_controller_spec.rb index 069600dc151..730ccb69c91 100644 --- a/spec/controllers/cloud_subnet_controller_spec.rb +++ b/spec/controllers/cloud_subnet_controller_spec.rb @@ -121,6 +121,15 @@ :userid => controller.current_user.userid } end + + let(:cloud_tenant) do + FactoryGirl.create(:cloud_tenant) + end + + let(:cloud_network) do + FactoryGirl.create(:cloud_network_openstack) + end + let(:queue_options) do { :class_name => @ems.class.name, @@ -129,7 +138,13 @@ :priority => MiqQueue::HIGH_PRIORITY, :role => 'ems_operations', :zone => @ems.my_zone, - :args => [{:name => "test", :ip_version => 4, :enable_dhcp => false}] + :args => [{ + :name => 'test', + :ip_version => 4, + :enable_dhcp => true, + :cloud_tenant => cloud_tenant, + :network_id => cloud_network.ems_ref + }] } end @@ -140,8 +155,16 @@ it "queues the create action" do expect(MiqTask).to receive(:generic_action_with_callback).with(task_options, queue_options) - post :create, :params => { :button => "add", :format => :js, :name => 'test', - :tenant_id => 'id', :ems_id => @ems.id } + post :create, :params => { + :button => 'add', + :format => :js, + :name => 'test', + :cloud_tenant => {:id => cloud_tenant.id}, + :ems_id => @ems.id, + :dhcp_enabled => true, + :network_protocol => 4, + :network_id => cloud_network.ems_ref + } end end end @@ -161,6 +184,7 @@ :userid => controller.current_user.userid } end + let(:queue_options) do { :class_name => @cloud_subnet.class.name, @@ -180,7 +204,12 @@ it "queues the update action" do expect(MiqTask).to receive(:generic_action_with_callback).with(task_options, queue_options) - post :update, :params => { :button => "save", :format => :js, :id => @cloud_subnet.id, :name => "foo2" } + post :update, :params => { + :button => "save", + :format => :js, + :id => @cloud_subnet.id, + :name => "foo2" + } end end end diff --git a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js new file mode 100644 index 00000000000..251dd243e0b --- /dev/null +++ b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js @@ -0,0 +1,91 @@ +describe('cloud-subnet-form', function() { + var $componentController, vm, miqService, API; + + describe('when vm.recordId is not defined', function () { + beforeEach(module('ManageIQ')); + beforeEach(inject(function (_$componentController_, _API_, _miqService_, $q) { + $componentController = _$componentController_; + API = _API_; + miqService = _miqService_; + + spyOn(miqService, 'miqAjaxButton'); + + var deferred = $q.defer(); + spyOn(API, 'get').and.callFake(function() {return deferred.promise;}); + + var bindings = {cloudSubnetFormId: 'new'}; + vm = $componentController('cloudSubnetForm', null, bindings); + vm.$onInit(); + })); + + it('sets newRecord to true', function () { + expect(vm.newRecord).toBe(true); + }); + + it('sets afterGet', function () { + expect(vm.afterGet).toBe(false); + }); + + it('adds a Cloud Subnet record', function () { + vm.cloudSubnetModel.name = 'newSubnet'; + vm.cloudSubnetModel.ip_version = 4; + vm.cloudSubnetModel.ems_id = 1; + vm.addClicked(); + expect(miqService.miqAjaxButton).toHaveBeenCalledWith('create/new?button=add', vm.cloudSubnetModel, { complete: false }); + }); + }); + + describe('when vm.recordId is defined', function () { + beforeEach(module('ManageIQ')); + beforeEach(inject(function (_$componentController_, _API_, _miqService_, $q) { + $componentController = _$componentController_; + API = _API_; + miqService = _miqService_; + + spyOn(miqService, 'miqAjaxButton'); + + var cloudSubnetFormResponse = { + name: 'abc', + gateway_ip: '172.10.1.1' + }; + + spyOn(API, 'get').and.callFake(function() { + return { + then: function (callback) { + callback(cloudSubnetFormResponse); + return {catch: function() {}}; + } + }; + }); + + var bindings = {cloudSubnetFormId: 1111}; + vm = $componentController('cloudSubnetForm', null, bindings); + vm.$onInit(); + })); + + it('sets newRecord to true', function () { + expect(vm.newRecord).toBe(false); + }); + + it('calls API.get with the appropriate URL', function () { + expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system,cloud_tenant,cloud_network'); + }); + + it('sets vm.cloudSubnetModel.name', function () { + expect(vm.cloudSubnetModel.name).toBe('abc'); + }); + + it('sets vm.cloudSubnetModel.gateway_ip', function () { + expect(vm.cloudSubnetModel.gateway_ip).toBe('172.10.1.1'); + }); + + it('updates a Cloud Subnet record', function () { + + vm.cloudSubnetModel.name = 'xyz'; + vm.cloudSubnetModel.gateway_ip = '172.10.1.1'; + vm.saveClicked(); + + expect(miqService.miqAjaxButton).toHaveBeenCalledWith('/cloud_subnet/update/1111?button=save', vm.cloudSubnetModel, { complete: false }); + }); + }); +}); From 7bad257656cf865ad0050d8fe8bbc0b64fe869ab Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Tue, 15 May 2018 11:46:19 +1000 Subject: [PATCH 2/6] controller spec --- .../cloud_subnet_controller_spec.rb | 18 ++++++++++-------- .../cloud_subnet/cloud_subnet_form_spec.js | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/spec/controllers/cloud_subnet_controller_spec.rb b/spec/controllers/cloud_subnet_controller_spec.rb index 730ccb69c91..35de86aa873 100644 --- a/spec/controllers/cloud_subnet_controller_spec.rb +++ b/spec/controllers/cloud_subnet_controller_spec.rb @@ -141,9 +141,9 @@ :args => [{ :name => 'test', :ip_version => 4, - :enable_dhcp => true, :cloud_tenant => cloud_tenant, - :network_id => cloud_network.ems_ref + :network_id => cloud_network.ems_ref, + :enable_dhcp => "true" }] } end @@ -157,12 +157,14 @@ expect(MiqTask).to receive(:generic_action_with_callback).with(task_options, queue_options) post :create, :params => { :button => 'add', + :controller => 'cloud_subnet', :format => :js, - :name => 'test', :cloud_tenant => {:id => cloud_tenant.id}, - :ems_id => @ems.id, :dhcp_enabled => true, - :network_protocol => 4, + :ems_id => @ems.id, + :id => 'new', + :name => 'test', + :network_protocol => 'ipv4', :network_id => cloud_network.ems_ref } end @@ -193,7 +195,7 @@ :priority => MiqQueue::HIGH_PRIORITY, :role => 'ems_operations', :zone => @ems.my_zone, - :args => [{:name => "foo2", :enable_dhcp => false}] + :args => [{:name => 'test2', :enable_dhcp => false}] } end @@ -205,10 +207,10 @@ it "queues the update action" do expect(MiqTask).to receive(:generic_action_with_callback).with(task_options, queue_options) post :update, :params => { - :button => "save", + :button => 'save', :format => :js, :id => @cloud_subnet.id, - :name => "foo2" + :name => 'test2' } end end diff --git a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js index 251dd243e0b..607837d33b2 100644 --- a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js +++ b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js @@ -28,7 +28,7 @@ describe('cloud-subnet-form', function() { it('adds a Cloud Subnet record', function () { vm.cloudSubnetModel.name = 'newSubnet'; - vm.cloudSubnetModel.ip_version = 4; + vm.cloudSubnetModel.ip_version = 'ipv4'; vm.cloudSubnetModel.ems_id = 1; vm.addClicked(); expect(miqService.miqAjaxButton).toHaveBeenCalledWith('create/new?button=add', vm.cloudSubnetModel, { complete: false }); @@ -68,7 +68,7 @@ describe('cloud-subnet-form', function() { }); it('calls API.get with the appropriate URL', function () { - expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system,cloud_tenant,cloud_network'); + expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network'); }); it('sets vm.cloudSubnetModel.name', function () { From 191745446d842a814b351e7c84f8fe875c50c3df Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Tue, 5 Jun 2018 19:35:51 +1000 Subject: [PATCH 3/6] fix scope issue --- .../javascripts/components/cloud_subnet/cloud-subnet-form.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js index e3478c546aa..119f43d98af 100644 --- a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js +++ b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js @@ -53,10 +53,11 @@ function cloudSubnetFormController(API, miqService) { }; vm.cancelClicked = function() { + var url = ''; if (vm.newRecord) { - var url = '/cloud_subnet/create/new?button=cancel'; + url = '/cloud_subnet/create/new?button=cancel'; } else { - var url = '/cloud_subnet/update/' + vm.cloudSubnetFormId + '?button=cancel'; + url = '/cloud_subnet/update/' + vm.cloudSubnetFormId + '?button=cancel'; } miqService.miqAjaxButton(url); }; From 810d47daf4ba7f2891eb099640f06978f63f9dad Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Tue, 5 Jun 2018 19:59:47 +1000 Subject: [PATCH 4/6] use only cloud_network.name --- .../javascripts/components/cloud_subnet/cloud-subnet-form.js | 2 +- .../components/cloud_subnet/cloud_subnet_form_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js index 119f43d98af..9bd05455dc9 100644 --- a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js +++ b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js @@ -38,7 +38,7 @@ function cloudSubnetFormController(API, miqService) { miqService.sparkleOff(); }).catch(miqService.handleFailure); } else { - API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network").then(function(data) { + API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network.name").then(function(data) { Object.assign(vm.cloudSubnetModel, data); vm.afterGet = true; vm.modelCopy = angular.copy( vm.cloudSubnetModel ); diff --git a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js index 607837d33b2..e682def8c76 100644 --- a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js +++ b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js @@ -68,7 +68,7 @@ describe('cloud-subnet-form', function() { }); it('calls API.get with the appropriate URL', function () { - expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network'); + expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network.name'); }); it('sets vm.cloudSubnetModel.name', function () { From 8f8824be15aed200a37842136c18df97dd4ec637 Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Tue, 19 Jun 2018 13:28:21 +1000 Subject: [PATCH 5/6] use only cloud_tenant.name --- .../javascripts/components/cloud_subnet/cloud-subnet-form.js | 2 +- .../components/cloud_subnet/cloud_subnet_form_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js index 9bd05455dc9..7ae2ef085c4 100644 --- a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js +++ b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js @@ -38,7 +38,7 @@ function cloudSubnetFormController(API, miqService) { miqService.sparkleOff(); }).catch(miqService.handleFailure); } else { - API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network.name").then(function(data) { + API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant.name,cloud_network.name").then(function(data) { Object.assign(vm.cloudSubnetModel, data); vm.afterGet = true; vm.modelCopy = angular.copy( vm.cloudSubnetModel ); diff --git a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js index e682def8c76..cf588a65225 100644 --- a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js +++ b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js @@ -68,7 +68,7 @@ describe('cloud-subnet-form', function() { }); it('calls API.get with the appropriate URL', function () { - expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system.name,cloud_tenant,cloud_network.name'); + expect(API.get).toHaveBeenCalledWith('/api/cloud_subnets/1111?expand=resources&attributes=ext_management_system.name,cloud_tenant.name,cloud_network.name'); }); it('sets vm.cloudSubnetModel.name', function () { From fd10dfba37acb1501d670966444d73519233e4f8 Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Mon, 9 Jul 2018 11:52:07 +1000 Subject: [PATCH 6/6] filter data on get; optimized #update in ctrl --- .../components/cloud_subnet/cloud-subnet-form.js | 2 +- app/controllers/cloud_subnet_controller.rb | 2 +- .../components/cloud_subnet/cloud_subnet_form_spec.js | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js index 7ae2ef085c4..2d2caa24a58 100644 --- a/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js +++ b/app/assets/javascripts/components/cloud_subnet/cloud-subnet-form.js @@ -39,7 +39,7 @@ function cloudSubnetFormController(API, miqService) { }).catch(miqService.handleFailure); } else { API.get("/api/cloud_subnets/" + vm.cloudSubnetFormId + "?expand=resources&attributes=ext_management_system.name,cloud_tenant.name,cloud_network.name").then(function(data) { - Object.assign(vm.cloudSubnetModel, data); + Object.assign(vm.cloudSubnetModel, _.pick(data, 'name', 'ext_management_system', 'cloud_network', 'cloud_tenant', 'network_protocol', 'cidr', 'dhcp_enabled', 'gateway')); vm.afterGet = true; vm.modelCopy = angular.copy( vm.cloudSubnetModel ); miqService.sparkleOff(); diff --git a/app/controllers/cloud_subnet_controller.rb b/app/controllers/cloud_subnet_controller.rb index fb6cfc3fc94..6068d1c8803 100644 --- a/app/controllers/cloud_subnet_controller.rb +++ b/app/controllers/cloud_subnet_controller.rb @@ -149,13 +149,13 @@ def edit def update assert_privileges("cloud_subnet_edit") @subnet = find_record_with_rbac(CloudSubnet, params[:id]) - options = changed_form_params case params[:button] when "cancel" cancel_action(_("Edit of Subnet \"%{name}\" was cancelled by the user") % {:name => @subnet.name}) when "save" if @subnet.supports_create? + options = changed_form_params task_id = @subnet.update_cloud_subnet_queue(session[:userid], options) if task_id.kind_of?(Integer) diff --git a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js index cf588a65225..8d460f9c2b2 100644 --- a/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js +++ b/spec/javascripts/components/cloud_subnet/cloud_subnet_form_spec.js @@ -45,8 +45,7 @@ describe('cloud-subnet-form', function() { spyOn(miqService, 'miqAjaxButton'); var cloudSubnetFormResponse = { - name: 'abc', - gateway_ip: '172.10.1.1' + name: 'abc' }; spyOn(API, 'get').and.callFake(function() { @@ -76,13 +75,13 @@ describe('cloud-subnet-form', function() { }); it('sets vm.cloudSubnetModel.gateway_ip', function () { - expect(vm.cloudSubnetModel.gateway_ip).toBe('172.10.1.1'); + expect(vm.cloudSubnetModel.gateway_ip).toBe(undefined); }); it('updates a Cloud Subnet record', function () { vm.cloudSubnetModel.name = 'xyz'; - vm.cloudSubnetModel.gateway_ip = '172.10.1.1'; + vm.cloudSubnetModel.gateway_ip = '172.10.1.2'; vm.saveClicked(); expect(miqService.miqAjaxButton).toHaveBeenCalledWith('/cloud_subnet/update/1111?button=save', vm.cloudSubnetModel, { complete: false });