From 5b6bed434941f84381011df6be5464cb77015c52 Mon Sep 17 00:00:00 2001 From: Stefan Topfstedt Date: Wed, 14 Aug 2024 15:39:20 -0700 Subject: [PATCH] show the learner group ancestry as tooltip and a11y label. --- .../components/learner-group/user-manager.hbs | 8 ++- .../learner-group/user-manager-test.js | 65 +++++++++++++++++++ .../components/learner-group/user-manager.js | 11 ++++ .../addon/models/learner-group.js | 9 +++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/packages/frontend/app/components/learner-group/user-manager.hbs b/packages/frontend/app/components/learner-group/user-manager.hbs index 8bc7dc5f4b..9c0966c601 100644 --- a/packages/frontend/app/components/learner-group/user-manager.hbs +++ b/packages/frontend/app/components/learner-group/user-manager.hbs @@ -103,11 +103,13 @@ {{user.email}} - + {{user.lowestGroupInTree.title}} @@ -230,11 +232,13 @@ {{user.email}} - + {{user.lowestGroupInTree.title}} diff --git a/packages/frontend/tests/integration/components/learner-group/user-manager-test.js b/packages/frontend/tests/integration/components/learner-group/user-manager-test.js index 1eaab36de5..b73f4daf88 100644 --- a/packages/frontend/tests/integration/components/learner-group/user-manager-test.js +++ b/packages/frontend/tests/integration/components/learner-group/user-manager-test.js @@ -1036,4 +1036,69 @@ module('Integration | Component | learner-group/user-manager', function (hooks) await component.usersInCurrentGroup[0].email.click(); assert.ok(component.usersInCurrentGroup[0].isSelected); }); + + test('learner-group hierarchy is shown in group-title and aria-label', async function (assert) { + const parentGroup = this.server.create('learner-group'); + const learnerGroup = this.server.create('learner-group', { parent: parentGroup }); + const childGroup = this.server.create('learner-group', { parent: learnerGroup }); + const user1 = this.server.create('user', { + learnerGroups: [learnerGroup], + }); + const user2 = this.server.create('user', { + learnerGroups: [childGroup], + }); + const userModel1 = await this.owner.lookup('service:store').findRecord('user', user1.id); + const userModel2 = await this.owner.lookup('service:store').findRecord('user', user2.id); + const learnerGroupModel = await this.owner + .lookup('service:store') + .findRecord('learner-group', learnerGroup.id); + const childGroupModel = await this.owner + .lookup('service:store') + .findRecord('learner-group', childGroup.id); + const userModelProxy1 = ObjectProxy.create({ + content: userModel1, + lowestGroupInTree: learnerGroupModel, + lowestGroupInTreeTitle: learnerGroupModel.title, + }); + const userModelProxy2 = ObjectProxy.create({ + content: userModel2, + lowestGroupInTree: childGroupModel, + lowestGroupInTreeTitle: childGroupModel.title, + }); + + this.set('users', [userModelProxy1, userModelProxy2]); + this.set('learnerGroup', learnerGroupModel); + await render(hbs``); + + assert.strictEqual(component.usersInCurrentGroup.length, 1); + assert.strictEqual( + component.usersInCurrentGroup[0].learnerGroup.linkTitle, + 'learner group 0 > learner group 1', + ); + assert.strictEqual( + component.usersInCurrentGroup[0].learnerGroup.linkAriaLabel, + 'learner group 0 > learner group 1', + ); + assert.strictEqual(component.usersNotInCurrentGroup.length, 1); + assert.strictEqual( + component.usersNotInCurrentGroup[0].learnerGroup.linkTitle, + 'learner group 0 > learner group 1 > learner group 2', + ); + assert.strictEqual( + component.usersNotInCurrentGroup[0].learnerGroup.linkAriaLabel, + 'learner group 0 > learner group 1 > learner group 2', + ); + }); }); diff --git a/packages/frontend/tests/pages/components/learner-group/user-manager.js b/packages/frontend/tests/pages/components/learner-group/user-manager.js index 148553beae..91eb35e967 100644 --- a/packages/frontend/tests/pages/components/learner-group/user-manager.js +++ b/packages/frontend/tests/pages/components/learner-group/user-manager.js @@ -1,4 +1,5 @@ import { + attribute, clickable, collection, create, @@ -46,6 +47,11 @@ const definition = { isClickable: isPresent('button'), click: clickable('button'), }, + learnerGroup: { + scope: '[data-test-learnergroup]', + linkTitle: attribute('title', 'a'), + linkAriaLabel: attribute('aria-label', 'a'), + }, isDisabled: isPresent('td:nth-of-type(1) [data-test-is-disabled]'), remove: clickable('[data-test-remove-user]'), canBeRemoved: isPresent('[data-test-remove-user]'), @@ -70,6 +76,11 @@ const definition = { isClickable: isPresent('button'), click: clickable('button'), }, + learnerGroup: { + scope: '[data-test-learnergroup]', + linkTitle: attribute('title', 'a'), + linkAriaLabel: attribute('aria-label', 'a'), + }, isDisabled: isPresent('td:nth-of-type(1) [data-test-is-disabled]'), add: clickable('[data-test-add-user]'), canBeAdded: isPresent('[data-test-add-user]'), diff --git a/packages/ilios-common/addon/models/learner-group.js b/packages/ilios-common/addon/models/learner-group.js index 1b0475d63d..3ed79447d8 100644 --- a/packages/ilios-common/addon/models/learner-group.js +++ b/packages/ilios-common/addon/models/learner-group.js @@ -473,6 +473,15 @@ export default class LearnerGroup extends Model { return parentTitles.join(' > ') + ' > ' + this.title; } + @cached + get titleWithParentTitlesData() { + return new TrackedAsyncData(this.getTitleWithParentTitles()); + } + + get titleWithParentTitles() { + return this.titleWithParentTitlesData.isResolved ? this.titleWithParentTitlesData.value : ''; + } + /** * Adds a user to a group and then traverses parent groups recursively * to add the user to them as well. Will only modify groups where the