feat: Create and assign host to host set in a single action

This commit is contained in:
Susmitha Girumala committed 2020-10-21 17:26:50 -04:00
1 parent d0d1ef67eb
commit 041f9e2299
14 files changed
+317 -15

No files matched your search

@@ -43,9 +43,9 @@
{{#unless this.hasAvailableHosts}}
<Rose::Layout::Centered>
<Rose::Message @title={{t "resources.host-set.host.messages.add.title"}} as |message|>
<Rose::Message @title={{t "resources.host-set.host.messages.add-none.title"}} as |message|>
<message.description>
{{t "resources.host-set.host.messages.add.description"}}
{{t "resources.host-set.host.messages.add-none.description"}}
</message.description>
<message.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.hosts">
<Rose::Icon @name="chevron-left" />
@@ -0,0 +1,82 @@
<Rose::Form
@onSubmit={{@submit}}
@cancel={{@cancel}}
@disabled={{@model.host.isSaving}}
@error={{@model.host.errors.base}}
as |form|
>
<form.input
@value={{@model.hostSet.displayName}}
@label={{t "form.host_set.label"}}
readonly={{true}}
@disabled={{true}} />
<form.input
@value={{@model.host.type}}
@label={{t "form.type.label"}}
readonly={{true}}
@disabled={{true}} />
<form.input
@name="name"
@type="name"
@value={{@model.host.name}}
@label={{t "form.name.label"}}
@error={{@model.host.errors.name}}
@helperText={{t "form.name.help"}}
readonly={{false}}
as |field|>
{{#if @model.host.errors.name}}
<field.errors as |errors|>
{{#each @model.host.errors.name as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.input>
<form.textarea
@name="description"
@type="description"
@value={{@model.host.description}}
@label={{t "form.description.label"}}
@error={{@model.host.errors.description}}
@helperText={{t "form.description.help"}}
disabled={{@model.host.isSaving}}
readonly={{false}}
as |field|>
{{#if @model.host.errors.description}}
<field.errors as |errors|>
{{#each @model.host.errors.description as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.textarea>
<form.input
@name="address"
@type="text"
@value={{@model.host.attributes.address}}
@label={{t "form.address.label"}}
@error={{@model.host.errors.name}}
@helperText={{t "form.address.help"}}
readonly={{false}}
as |field|>
{{#if @model.host.errors.name}}
<field.errors as |errors|>
{{#each @model.host.errors.name as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.input>
<form.actions
@disabled={{if @model.host.cannotSave @model.host.cannotSave}}
@enableEditText={{t "actions.edit-form"}}
@submitText={{t "actions.save"}}
@cancelText={{t "actions.cancel"}} />
</Rose::Form>
@@ -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');
}
}
+1
View File
@@ -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');
});
@@ -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'
);
}
}
@@ -1,4 +1,7 @@
<Rose::Dropdown @text="{{t 'actions.manage'}}" @dropdownRight={{true}} as |dropdown|>
<dropdown.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.create-host">
{{t 'resources.host-set.actions.create-host'}}
</dropdown.link>
<dropdown.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.add-hosts">
{{t 'resources.host-set.actions.add-hosts'}}
</dropdown.link>
@@ -0,0 +1,7 @@
{{title (t 'resources.host-set.actions.create-host')}}
<Form::HostSet::CreateHost
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
@@ -0,0 +1,4 @@
<h2>
{{t "resources.host-set.actions.create-host"}}
<DocLink @doc="host.new" @iconSize="large" />
</h2>
@@ -62,12 +62,9 @@
<message.description>
{{t "resources.host-set.host.messages.none.description"}}
</message.description>
<message.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.hosts.new">
<message.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.create-host">
<Rose::Icon @name="plus-circle-outline" />
{{t "resources.host-set.host.messages.none.actions.new"}}
</message.link>
<message.link @route="scopes.scope.projects.project.host-catalogs.host-catalog.host-sets.host-set.add-hosts">
{{t "resources.host-set.actions.add-hosts"}}
{{t "resources.host-set.actions.create-host"}}
</message.link>
</Rose::Message>
</Rose::Layout::Centered>
@@ -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"]'));
});
});
@@ -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);
});
});
@@ -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);
});
});
+2
View File
@@ -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
+6 -4
View File
@@ -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: