diff --git a/ui/core/app/components/form/group/add-members/index.hbs b/ui/core/app/components/form/group/add-members/index.hbs
new file mode 100644
index 000000000..fef2f383c
--- /dev/null
+++ b/ui/core/app/components/form/group/add-members/index.hbs
@@ -0,0 +1,48 @@
+{{#if this.availableUsers}}
+
+
+
+
+
+
+
+ {{t 'form.label.id'}}
+ {{t 'form.label.name'}}
+
+
+
+ {{#each this.availableUsers as |user|}}
+
+
+
+
+ {{user.name}}
+
+ {{/each}}
+
+
+
+
+{{/if}}
+
+{{#unless this.availableUsers}}
+
+
+
+ {{t "descriptions.no-available-users"}}
+
+
+
+{{/unless}}
diff --git a/ui/core/app/components/form/group/add-members/index.js b/ui/core/app/components/form/group/add-members/index.js
new file mode 100644
index 000000000..dbf5256bb
--- /dev/null
+++ b/ui/core/app/components/form/group/add-members/index.js
@@ -0,0 +1,42 @@
+import Component from '@glimmer/component';
+import { computed, action } from '@ember/object';
+import { A } from '@ember/array';
+
+export default class FormGroupAddMembersComponent extends Component {
+
+ // =properties
+
+ /**
+ * Array of selected user IDs.
+ * @type {EmberArray}
+ */
+ selectedMemberIDs = A();
+
+ /**
+ * Host sets not already added to the target.
+ * @type {[UserModel]}
+ */
+ @computed('args.{model.members_ids.[],users.[]}')
+ get availableUsers() {
+ const memberIDs = this.args.model.member_ids;
+ const users = this.args.users;
+ return users.filter(({ id }) => !memberIDs.includes(id));
+ }
+
+ // =actions
+
+ @action
+ toggleMember(user) {
+ if (!this.selectedMemberIDs.includes(user.id)) {
+ this.selectedMemberIDs.addObject(user.id);
+ } else {
+ this.selectedMemberIDs.removeObject(user.id);
+ }
+ }
+
+ @action
+ submit(fn) {
+ fn(this.selectedMemberIDs);
+ }
+
+}
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
index 7ad1a8280..f3b8717a9 100644
--- a/ui/core/app/routes/scopes/scope/groups/group/add-members.js
+++ b/ui/core/app/routes/scopes/scope/groups/group/add-members.js
@@ -1,6 +1,7 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
+import { hash } from 'rsvp';
export default class ScopesScopeGroupsGroupAddMembersRoute extends Route {
@@ -18,6 +19,18 @@ export default class ScopesScopeGroupsGroupAddMembersRoute extends Route {
this.store.unloadAll('user');
}
+ /**
+ * Loads all users and returns them with the group.
+ * @return {Promise{GroupModel, [UserModel]}}
+ */
+ model() {
+ const { id: scopeID } = this.modelFor('scopes.scope');
+ return hash({
+ group: this.modelFor('scopes.scope.groups.group'),
+ users: this.store.findAll('user', { adapterOptions: { scopeID } })
+ });
+ }
+
/**
* Renders the route-set specific page sections
* @override
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
index d8ca3dcef..6f674b02d 100644
--- a/ui/core/app/templates/scopes/scope/groups/group/add-members.hbs
+++ b/ui/core/app/templates/scopes/scope/groups/group/add-members.hbs
@@ -1,3 +1,8 @@
{{title (t "actions.add-members")}}
-{{outlet}}
+
diff --git a/ui/core/tests/acceptance/groups-test.js b/ui/core/tests/acceptance/groups-test.js
index c33014378..a6ad6ccd9 100644
--- a/ui/core/tests/acceptance/groups-test.js
+++ b/ui/core/tests/acceptance/groups-test.js
@@ -221,5 +221,17 @@ module('Acceptance | groups', function (hooks) {
test('can view group members', async function (assert) {
assert.expect(0);
});
-
+
+ test('can delete members', async function(assert) {
+ assert.expect(0);
+ });
+
+ test('select and save members to add', async function (assert) {
+ assert.expect(0);
+ });
+
+ test('select and cancel members to add', async function (assert) {
+ assert.expect(0);
+ });
+
});
diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml
index c5b005d53..581610766 100644
--- a/ui/core/translations/en-us.yaml
+++ b/ui/core/translations/en-us.yaml
@@ -96,6 +96,7 @@ titles:
role-principals-welcome: No Principals Associated
members: Members
group-members-welcome: Welcome to Members
+ no-available-users: No Users Available
descriptions:
host-catalogs: Overview of collections of hosts and host sets.
empty-set: There are no items to display yet. You may be able to add items or try back later.
@@ -113,6 +114,7 @@ descriptions:
no-host-sets-for-target: No host sets are available to add to this target.
role-principals-welcome: No principals are available in this role.
group-members-welcome: Users belonging to this group appear here.
+ no-available-users: No users are available to add to this group.
states:
info: Info
success: Success