From 041f9e2299f4cecf111876457e862cc5c902c6f7 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 21 Oct 2020 17:26:50 -0400 Subject: [PATCH] feat: Create and assign host to host set in a single action --- .../form/host-set/add-hosts/index.hbs | 4 +- .../form/host-set/create-host/index.hbs | 82 +++++++++++++++++ .../host-sets/host-set/create-host.js | 18 ++++ ui/core/app/router.js | 1 + .../host-sets/host-set/create-host.js | 90 +++++++++++++++++++ .../host-sets/host-set/-actions.hbs | 3 + .../host-sets/host-set/create-host.hbs | 7 ++ .../host-set/create-host/-header.hbs | 4 + .../host-catalog/host-sets/host-set/hosts.hbs | 7 +- .../tests/acceptance/host-sets/hosts-test.js | 81 ++++++++++++++++- .../host-sets/host-set/create-host-test.js | 12 +++ .../host-sets/host-set/create-host-test.js | 11 +++ ui/core/translations/form/en-us.yaml | 2 + ui/core/translations/resources/en-us.yaml | 10 ++- 14 files changed, 317 insertions(+), 15 deletions(-) create mode 100644 ui/core/app/components/form/host-set/create-host/index.hbs create mode 100644 ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js create mode 100644 ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js create mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs create mode 100644 ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs create mode 100644 ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js diff --git a/ui/core/app/components/form/host-set/add-hosts/index.hbs b/ui/core/app/components/form/host-set/add-hosts/index.hbs index bb1cb7a91..0ff9064ee 100644 --- a/ui/core/app/components/form/host-set/add-hosts/index.hbs +++ b/ui/core/app/components/form/host-set/add-hosts/index.hbs @@ -43,9 +43,9 @@ {{#unless this.hasAvailableHosts}} - + - {{t "resources.host-set.host.messages.add.description"}} + {{t "resources.host-set.host.messages.add-none.description"}} diff --git a/ui/core/app/components/form/host-set/create-host/index.hbs b/ui/core/app/components/form/host-set/create-host/index.hbs new file mode 100644 index 000000000..e12cabec9 --- /dev/null +++ b/ui/core/app/components/form/host-set/create-host/index.hbs @@ -0,0 +1,82 @@ + + + + + + + + {{#if @model.host.errors.name}} + + {{#each @model.host.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.host.errors.description}} + + {{#each @model.host.errors.description as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + {{#if @model.host.errors.name}} + + {{#each @model.host.errors.name as |error|}} + {{error.message}} + {{/each}} + + {{/if}} + + + + + diff --git a/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js new file mode 100644 index 000000000..e5ff5fa35 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js @@ -0,0 +1,18 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetCreateHostController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * Translated new host set breadcrumb + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.host-set.actions.create-host'); + } +} diff --git a/ui/core/app/router.js b/ui/core/app/router.js index f6ee0871a..192b9d8c5 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -29,6 +29,7 @@ Router.map(function () { this.route('host-set', { path: ':host_set_id' }, function () { this.route('hosts'); this.route('add-hosts'); + this.route('create-host'); }); this.route('new'); }); diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js new file mode 100644 index 000000000..05aa6ed6f --- /dev/null +++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.js @@ -0,0 +1,90 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { hash } from 'rsvp'; +import loading from 'ember-loading/decorator'; +import { notifySuccess, notifyError } from '../../../../../../../../../decorators/notify'; + +export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHostSetCreateHostRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Creates a new unsaved host in current host catalog scope. + * @return {Promise{HostSetModel,HostModel}} + */ + async model() { + const { id: host_catalog_id } = this.modelFor( + 'scopes.scope.projects.project.host-catalogs.host-catalog' + ); + + return hash({ + hostSet: this.modelFor( + 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set' + ), + host: this.store.createRecord('host', { + type: 'static', + host_catalog_id, + }), + }); + } + + /** + * Renders the create-host-specific header template. + * Empties the actions and navigation outlets and renders a custom empty header. + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render( + 'scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header', + { + into: 'scopes/scope/projects/project/host-catalogs/host-catalog', + outlet: 'header', + } + ); + + this.render('-empty', { + into: 'scopes/scope/projects/project/host-catalogs/host-catalog', + outlet: 'navigation', + }); + + this.render('-empty', { + into: 'scopes/scope/projects/project/host-catalogs/host-catalog', + outlet: 'actions', + }); + } + + // =actions + + /** + * Saves host and add it to current host set. + * @param {HostSetModel,HostModel} model + */ + @action + @loading + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.add-success') + async save(model) { + await model.host.save(); + await model.hostSet.addHost(model.host.id); + await this.replaceWith( + 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } + + /** + * Redirect to hosts in host set as if nothing ever happened. + */ + @action + cancel() { + this.replaceWith( + 'scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts' + ); + } +} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs index f2ccb5875..2eb61121a 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs @@ -1,4 +1,7 @@ + + {{t 'resources.host-set.actions.create-host'}} + {{t 'resources.host-set.actions.add-hosts'}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs new file mode 100644 index 000000000..455daa19b --- /dev/null +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host.hbs @@ -0,0 +1,7 @@ +{{title (t 'resources.host-set.actions.create-host')}} + + \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs new file mode 100644 index 000000000..c8ea81660 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host/-header.hbs @@ -0,0 +1,4 @@ +

+ {{t "resources.host-set.actions.create-host"}} + +

diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs index 6f34d763a..50b35d364 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -62,12 +62,9 @@ {{t "resources.host-set.host.messages.none.description"}} - + - {{t "resources.host-set.host.messages.none.actions.new"}} - - - {{t "resources.host-set.actions.add-hosts"}} + {{t "resources.host-set.actions.create-host"}}
diff --git a/ui/core/tests/acceptance/host-sets/hosts-test.js b/ui/core/tests/acceptance/host-sets/hosts-test.js index 2bd0d6997..f7ca0eb8b 100644 --- a/ui/core/tests/acceptance/host-sets/hosts-test.js +++ b/ui/core/tests/acceptance/host-sets/hosts-test.js @@ -1,5 +1,5 @@ import { module, test } from 'qunit'; -import { visit, currentURL, click, find, findAll } from '@ember/test-helpers'; +import { visit, currentURL, click, find, findAll, fillIn } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import a11yAudit from 'ember-a11y-testing/test-support/audit'; @@ -32,7 +32,9 @@ module('Acceptance | host-sets | hosts', function (hooks) { hostCatalog: null, hostSets: null, hostSet: null, - hostSetHosts: null + hostSetHosts: null, + addHosts: null, + newHost: null, }; let hostSetHostsCount; @@ -62,6 +64,7 @@ module('Acceptance | host-sets | hosts', function (hooks) { urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`; urls.hostSetHosts = `${urls.hostSet}/hosts`; urls.addHosts = `${urls.hostSet}/add-hosts`; + urls.newHost = `${urls.hostSet}/create-host`; // Counts hostSetHostsCount = instances.hostSet.hosts.length; }); @@ -114,7 +117,7 @@ module('Acceptance | host-sets | hosts', function (hooks) { instances.hostSet.update({ hostIds: [] }); await visit(urls.hostSetHosts); assert.equal(findAll('tbody tr').length, 0); - await click('.rose-layout-page-actions a') + await click('.rose-layout-page-actions a:nth-child(2)') assert.equal(currentURL(), urls.addHosts); // Click three times to select, unselect, then reselect (for coverage) await click('tbody label'); @@ -131,7 +134,7 @@ module('Acceptance | host-sets | hosts', function (hooks) { assert.equal(findAll('tbody tr').length, hostSetHostsCount); await click('tbody tr .rose-dropdown-button-danger'); assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1); - await click('.rose-layout-page-actions a') + await click('.rose-layout-page-actions a:nth-child(2)') assert.equal(currentURL(), urls.addHosts); await click('tbody label'); await click('form [type="button"]'); @@ -159,4 +162,74 @@ module('Acceptance | host-sets | hosts', function (hooks) { await click('form [type="submit"]'); assert.ok(find('[role="alert"]')); }); + + test('visiting host creation from a host set', async function (assert) { + assert.expect(1); + await visit(urls.newHost); + await a11yAudit(); + assert.equal(currentURL(), urls.newHost); + }); + + test('create and add host to host set', async function (assert) { + assert.expect(3); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.hostSet); + assert.equal(findAll('tbody tr').length, 0); + await click('.rose-layout-page-actions a:nth-child(1)') + assert.equal(currentURL(), urls.newHost); + await fillIn('[name="name"]', 'Test Name'); + await fillIn('[name="description"]', 'description'); + await click('form [type="submit"]:not(:disabled)'); + await visit(urls.hostSetHosts); + assert.equal(findAll('tbody tr').length, 1); + }); + + test('create and cancel host add to host set', async function (assert) { + assert.expect(1); + await visit(urls.newHost); + await click('form [type="button"]'); + assert.equal(currentURL(), urls.hostSetHosts); + }); + + test('shows error message on host creation error', async function (assert) { + assert.expect(1); + this.server.post('/hosts', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.newHost); + await fillIn('[name="name"]', 'New Host'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); + + test('shows error message on host addition to host set error', async function (assert) { + assert.expect(1); + this.server.post('/host-sets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.hostSet.update({ hostIds: [] }); + await visit(urls.newHost); + await fillIn('[name="name"]', 'New Host'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); }); diff --git a/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js new file mode 100644 index 000000000..aba1c7c22 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host'); + assert.ok(controller); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js new file mode 100644 index 000000000..ad9e0c61e --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/create-host'); + assert.ok(route); + }); +}); diff --git a/ui/core/translations/form/en-us.yaml b/ui/core/translations/form/en-us.yaml index 1c91e98f5..de24444fc 100644 --- a/ui/core/translations/form/en-us.yaml +++ b/ui/core/translations/form/en-us.yaml @@ -41,3 +41,5 @@ session_max_seconds: session_connection_limit: label: Maximum Connections help: The maximum number of connections allowed per session. For unlimited, specify "-1". +host_set: + label: Host Set diff --git a/ui/core/translations/resources/en-us.yaml b/ui/core/translations/resources/en-us.yaml index fd83bb202..a19916d43 100644 --- a/ui/core/translations/resources/en-us.yaml +++ b/ui/core/translations/resources/en-us.yaml @@ -67,7 +67,8 @@ host-set: add: Add Host Set create: New Host Set delete: Delete Host Set - add-hosts: Add Hosts + create-host: Create and Add Host + add-hosts: Add Existing Host messages: welcome: title: Welcome to Host Sets @@ -75,12 +76,13 @@ host-set: messages: none: title: No Hosts - description: No hosts available in this host set. Create hosts in a host catalog before assigning them to this host set. - actions: - new: New Host + description: No hosts available in this host set. add: title: Add Hosts description: Select hosts that belong to this host set. + add-none: + title: No Hosts Available + description: No hosts available for selection. types: static: Static host: