diff --git a/ui/core/app/controllers/scopes/scope/groups/group/add-members.js b/ui/core/app/controllers/scopes/scope/groups/group/add-members.js
new file mode 100644
index 000000000..7a94c1034
--- /dev/null
+++ b/ui/core/app/controllers/scopes/scope/groups/group/add-members.js
@@ -0,0 +1,20 @@
+import Controller from '@ember/controller';
+import { inject as service } from '@ember/service';
+
+export default class ScopesScopeGroupsGroupAddMembersController extends Controller {
+
+ // =services
+
+ @service intl;
+
+ // =attributes
+
+ /**
+ * Translated new group breadcrumb
+ * @type {string}
+ */
+ get breadCrumb() {
+ return this.intl.t('actions.add-members');
+ }
+
+}
diff --git a/ui/core/app/router.js b/ui/core/app/router.js
index 6800b5103..a8699d517 100644
--- a/ui/core/app/router.js
+++ b/ui/core/app/router.js
@@ -56,6 +56,7 @@ Router.map(function () {
this.route('groups', function () {
this.route('group', { path: ':group_id' }, function () {
this.route('members');
+ this.route('add-members');
});
this.route('new');
});
diff --git a/ui/core/app/routes/scopes/scope/groups/group.js b/ui/core/app/routes/scopes/scope/groups/group.js
index 6231ab13f..bd638b343 100644
--- a/ui/core/app/routes/scopes/scope/groups/group.js
+++ b/ui/core/app/routes/scopes/scope/groups/group.js
@@ -1,6 +1,7 @@
import Route from '@ember/routing/route';
export default class ScopesScopeGroupsGroupRoute extends Route {
+
// =methods
/**
@@ -9,10 +10,33 @@ export default class ScopesScopeGroupsGroupRoute extends Route {
* @param {string} params.group_id
* @return {groupModel}
*/
- async model({ group_id }) {
+ model({ group_id }) {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findRecord('group', group_id, {
adapterOptions: { scopeID },
});
}
+
+ /**
+ * Renders the route-set specific page sections
+ * @override
+ */
+ renderTemplate() {
+ super.renderTemplate(...arguments);
+
+ this.render('scopes/scope/groups/group/-header', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'header'
+ });
+
+ this.render('scopes/scope/groups/group/-actions', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'actions'
+ });
+
+ this.render('scopes/scope/groups/group/-navigation', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'navigation'
+ });
+ }
}
diff --git a/ui/core/app/routes/scopes/scope/groups/group/add-members.js b/ui/core/app/routes/scopes/scope/groups/group/add-members.js
new file mode 100644
index 000000000..7ad1a8280
--- /dev/null
+++ b/ui/core/app/routes/scopes/scope/groups/group/add-members.js
@@ -0,0 +1,72 @@
+import Route from '@ember/routing/route';
+import { inject as service } from '@ember/service';
+import { action } from '@ember/object';
+
+export default class ScopesScopeGroupsGroupAddMembersRoute extends Route {
+
+ // =services
+
+ @service intl;
+ @service notify;
+
+ // =methods
+
+ /**
+ * Emtpy out any previously loaded users.
+ */
+ beforeModel() {
+ this.store.unloadAll('user');
+ }
+
+ /**
+ * Renders the route-set specific page sections
+ * @override
+ */
+ renderTemplate() {
+ super.renderTemplate(...arguments);
+
+ this.render('scopes/scope/groups/group/add-members/-header', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'header'
+ });
+
+ this.render('-empty', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'actions'
+ });
+
+ this.render('-empty', {
+ into: 'scopes/scope/groups/group',
+ outlet: 'navigation'
+ });
+ }
+
+ // =actions
+
+ /**
+ * Adds members to the group and saves, replaces with the members index
+ * route, and notifies the user of success or error.
+ * @param {GroupModel} group
+ * @param {[string]} userIDs
+ */
+ @action
+ async addMembers(group, userIDs) {
+ try {
+ await group.addMembers(userIDs);
+ await this.replaceWith('scopes.scope.groups.group.members');
+ this.notify.success(this.intl.t('notify.save-success'));
+ } catch (error) {
+ // TODO: replace with translated strings
+ this.notify.error(error.message, { closeAfter: null });
+ }
+ }
+
+ /**
+ * Redirect to group members as if nothing ever happened.
+ */
+ @action
+ cancel() {
+ this.replaceWith('scopes.scope.groups.group.members');
+ }
+
+}
diff --git a/ui/core/app/templates/scopes/scope/groups/group.hbs b/ui/core/app/templates/scopes/scope/groups/group.hbs
index bb0ba8b8a..2a878ff51 100644
--- a/ui/core/app/templates/scopes/scope/groups/group.hbs
+++ b/ui/core/app/templates/scopes/scope/groups/group.hbs
@@ -7,30 +7,15 @@
- {{t "resources.group"}}
+ {{outlet "header"}}
-
-
- {{t 'titles.details'}}
-
-
- {{t 'titles.members'}}
-
-
+ {{outlet "navigation"}}
-
-
- {{t 'actions.delete-group'}}
-
-
+ {{outlet "actions"}}
diff --git a/ui/core/app/templates/scopes/scope/groups/group/-actions.hbs b/ui/core/app/templates/scopes/scope/groups/group/-actions.hbs
new file mode 100644
index 000000000..1ebd9d2c6
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/groups/group/-actions.hbs
@@ -0,0 +1,12 @@
+
+
+ {{t "actions.add-members"}}
+
+
+ {{t 'actions.delete-group'}}
+
+
diff --git a/ui/core/app/templates/scopes/scope/groups/group/-header.hbs b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs
new file mode 100644
index 000000000..6631940a3
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs
@@ -0,0 +1 @@
+{{t "resources.group"}}
diff --git a/ui/core/app/templates/scopes/scope/groups/group/-navigation.hbs b/ui/core/app/templates/scopes/scope/groups/group/-navigation.hbs
new file mode 100644
index 000000000..6dc45b637
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/groups/group/-navigation.hbs
@@ -0,0 +1,8 @@
+
+
+ {{t 'titles.details'}}
+
+
+ {{t 'titles.members'}}
+
+
diff --git a/ui/core/app/templates/scopes/scope/groups/group/add-members.hbs b/ui/core/app/templates/scopes/scope/groups/group/add-members.hbs
new file mode 100644
index 000000000..d8ca3dcef
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/groups/group/add-members.hbs
@@ -0,0 +1,3 @@
+{{title (t "actions.add-members")}}
+
+{{outlet}}
diff --git a/ui/core/app/templates/scopes/scope/groups/group/add-members/-header.hbs b/ui/core/app/templates/scopes/scope/groups/group/add-members/-header.hbs
new file mode 100644
index 000000000..48dca079b
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/groups/group/add-members/-header.hbs
@@ -0,0 +1 @@
+{{t "actions.add-members"}}
diff --git a/ui/core/tests/unit/controllers/scopes/scope/groups/group/add-members-test.js b/ui/core/tests/unit/controllers/scopes/scope/groups/group/add-members-test.js
new file mode 100644
index 000000000..17daef1db
--- /dev/null
+++ b/ui/core/tests/unit/controllers/scopes/scope/groups/group/add-members-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Controller | scopes/scope/groups/group/add-members', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let controller = this.owner.lookup('controller:scopes/scope/groups/group/add-members');
+ assert.ok(controller);
+ });
+});
diff --git a/ui/core/tests/unit/routes/scopes/scope/groups/group/add-members-test.js b/ui/core/tests/unit/routes/scopes/scope/groups/group/add-members-test.js
new file mode 100644
index 000000000..8500b2957
--- /dev/null
+++ b/ui/core/tests/unit/routes/scopes/scope/groups/group/add-members-test.js
@@ -0,0 +1,11 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | scopes/scope/groups/group/add-members', function(hooks) {
+ setupTest(hooks);
+
+ test('it exists', function(assert) {
+ let route = this.owner.lookup('route:scopes/scope/groups/group/add-members');
+ assert.ok(route);
+ });
+});
diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml
index d33ec0514..c5b005d53 100644
--- a/ui/core/translations/en-us.yaml
+++ b/ui/core/translations/en-us.yaml
@@ -23,6 +23,7 @@ actions:
add-host-set: Create Host Set
add-host: Create Host
add-host-sets: Add Host Sets
+ add-members: Add Members
auth:
titles:
no-scopes: No Scopes Available