From 4ee145bdb38f294aaef31591e0441e252b02476e Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Fri, 27 Feb 2026 21:41:34 -0800 Subject: [PATCH] New ILM Manager To make ILM management in a session easier I've wrapped everything in a fieldset and added a confirmation step for removing ILMs. --- .../acceptance/course/session/ilm-test.js | 8 +- .../course/session/overview-test.js | 13 +- .../page-objects/components/session/ilm.js | 16 +- .../addon/components/session/ilm.gjs | 257 +++++++++++++----- .../app/styles/ilios-common/components.scss | 1 + .../components/session-overview.scss | 13 - .../ilios-common/components/session/ilm.scss | 96 +++++++ packages/ilios-common/translations/en-us.yaml | 2 + packages/ilios-common/translations/es.yaml | 2 + packages/ilios-common/translations/fr.yaml | 2 + .../components/session/ilm-test.gjs | 162 ++++++++++- 11 files changed, 461 insertions(+), 111 deletions(-) create mode 100644 packages/ilios-common/app/styles/ilios-common/components/session/ilm.scss diff --git a/packages/frontend/tests/acceptance/course/session/ilm-test.js b/packages/frontend/tests/acceptance/course/session/ilm-test.js index 0454823389..3773afe048 100644 --- a/packages/frontend/tests/acceptance/course/session/ilm-test.js +++ b/packages/frontend/tests/acceptance/course/session/ilm-test.js @@ -610,14 +610,18 @@ module('Acceptance | Session - Independent Learning', function (hooks) { assert.ok(page.details.learnersAreVisible); assert.ok(page.details.instructorsAreVisible); + assert.ok(page.details.overview.ilm.isIlm); - await page.details.overview.ilm.toggleIlm.yesNoToggle.click(); + await page.details.overview.ilm.removeIlm(); + await page.details.overview.ilm.confirm(); + assert.notOk(page.details.overview.ilm.isIlm); assert.notOk(page.details.learnersAreVisible); assert.notOk(page.details.instructorsAreVisible); - await page.details.overview.ilm.toggleIlm.yesNoToggle.click(); + await page.details.overview.ilm.addIlm(); + assert.ok(page.details.overview.ilm.isIlm); assert.ok(page.details.learnersAreVisible); assert.ok(page.details.instructorsAreVisible); }); diff --git a/packages/frontend/tests/acceptance/course/session/overview-test.js b/packages/frontend/tests/acceptance/course/session/overview-test.js index 0ad1459938..e2d3565673 100644 --- a/packages/frontend/tests/acceptance/course/session/overview-test.js +++ b/packages/frontend/tests/acceptance/course/session/overview-test.js @@ -58,7 +58,8 @@ module('Acceptance | Session - Overview', function (hooks) { assert.strictEqual(currentRouteName(), 'session.index'); assert.ok(page.details.overview.ilm.ilmHours.isVisible); assert.ok(page.details.overview.ilm.ilmDueDateAndTime.isVisible); - assert.strictEqual(parseInt(page.details.overview.ilm.ilmHours.value, 10), ilmSession.hours); + assert.ok(page.details.overview.ilm.isIlm); + assert.strictEqual(Number(page.details.overview.ilm.ilmHours.value), ilmSession.hours); assert.strictEqual( page.details.overview.ilm.ilmDueDateAndTime.value, this.intl.formatDate(ilmSession.dueDate, { @@ -71,8 +72,10 @@ module('Acceptance | Session - Overview', function (hooks) { }), ); - await page.details.overview.ilm.toggleIlm.yesNoToggle.click(); + await page.details.overview.ilm.removeIlm(); + await page.details.overview.ilm.confirm(); + assert.notOk(page.details.overview.ilm.isIlm); assert.notOk(page.details.overview.ilm.ilmHours.isVisible); assert.notOk(page.details.overview.ilm.ilmDueDateAndTime.isVisible); }); @@ -94,12 +97,14 @@ module('Acceptance | Session - Overview', function (hooks) { assert.strictEqual(currentRouteName(), 'session.index'); assert.notOk(page.details.overview.ilm.ilmHours.isVisible); assert.notOk(page.details.overview.ilm.ilmDueDateAndTime.isVisible); + assert.notOk(page.details.overview.ilm.isIlm); - await page.details.overview.ilm.toggleIlm.yesNoToggle.click(); + await page.details.overview.ilm.addIlm(); assert.ok(page.details.overview.ilm.ilmHours.isVisible); assert.ok(page.details.overview.ilm.ilmDueDateAndTime.isVisible); - assert.strictEqual(parseInt(page.details.overview.ilm.ilmHours.value, 10), 1); + assert.ok(page.details.overview.ilm.isIlm); + assert.strictEqual(Number(page.details.overview.ilm.ilmHours.value), 1); assert.strictEqual( page.details.overview.ilm.ilmDueDateAndTime.value, this.intl.formatDate(DateTime.fromObject({ hour: 17, minute: 0 }).plus({ weeks: 6 }), { diff --git a/packages/ilios-common/addon-test-support/ilios-common/page-objects/components/session/ilm.js b/packages/ilios-common/addon-test-support/ilios-common/page-objects/components/session/ilm.js index 5616c770b7..152691e787 100644 --- a/packages/ilios-common/addon-test-support/ilios-common/page-objects/components/session/ilm.js +++ b/packages/ilios-common/addon-test-support/ilios-common/page-objects/components/session/ilm.js @@ -1,5 +1,4 @@ import { clickable, create, fillable, hasClass, isVisible, text } from 'ember-cli-page-object'; -import yesNoToggle from '../toggle-yesno'; import ilmDueDateAndTime from '../session-overview-ilm-duedate'; const definition = { @@ -13,11 +12,18 @@ const definition = { hasError: isVisible('.validation-error-message'), }, ilmDueDateAndTime, - toggleIlm: { - scope: '[data-test-ilm-value]', - yesNoToggle, + addIlm: clickable('[data-test-add]'), + removeIlm: clickable('[data-test-remove]'), + canAdd: isVisible('[data-test-add]'), + canRemove: isVisible('[data-test-remove]'), + message: text('[data-test-message]'), + confirmationMessage: { + scope: '[data-test-confirmation-message]', }, - isIlm: hasClass('add', '[data-test-ilm-value] span'), + confirm: clickable('[data-test-confirm]'), + cancel: clickable('[data-test-cancel]'), + undo: clickable('[data-test-undo]'), + isIlm: hasClass('is-ilm', '[data-test-session-ilm]'), }; export default definition; diff --git a/packages/ilios-common/addon/components/session/ilm.gjs b/packages/ilios-common/addon/components/session/ilm.gjs index cbbf4d0822..9b966a99dc 100644 --- a/packages/ilios-common/addon/components/session/ilm.gjs +++ b/packages/ilios-common/addon/components/session/ilm.gjs @@ -5,10 +5,8 @@ import { guidFor } from '@ember/object/internals'; import { TrackedAsyncData } from 'ember-async-data'; import YupValidations from 'ilios-common/classes/yup-validations'; import { number } from 'yup'; -import { task } from 'ember-concurrency'; -import { DateTime } from 'luxon'; +import { task, timeout } from 'ember-concurrency'; import t from 'ember-intl/helpers/t'; -import ToggleYesno from 'ilios-common/components/toggle-yesno'; import perform from 'ember-concurrency/helpers/perform'; import EditableField from 'ilios-common/components/editable-field'; import { on } from '@ember/modifier'; @@ -17,10 +15,18 @@ import set from 'ember-set-helper/helpers/set'; import YupValidationMessage from 'ilios-common/components/yup-validation-message'; import SessionOverviewIlmDuedate from 'ilios-common/components/session-overview-ilm-duedate'; import focus from 'ilios-common/modifiers/focus'; +import FaIcon from '@fortawesome/ember-fontawesome/components/fa-icon'; +import { faPlus, faSpinner, faTrash, faUndo } from '@fortawesome/free-solid-svg-icons'; +import { DateTime } from 'luxon'; +import { and, not } from 'ember-truth-helpers'; +import LoadingSpinner from 'ilios-common/components/loading-spinner'; export default class SessionIlmComponent extends Component { @service store; @tracked localHours; + @tracked showRemoveConfirmation = false; + @tracked isNew = false; + @tracked isRecentlyAdded = false; get hours() { if (this.localHours !== undefined) { @@ -51,26 +57,67 @@ export default class SessionIlmComponent extends Component { return this.ilmSession !== null; } - saveIndependentLearning = task({ drop: true }, async (value) => { - if (!value) { - const ilmSession = await this.args.session.ilmSession; - this.args.session.set('ilmSession', null); - await ilmSession.destroyRecord(); - await this.args.session.save(); - } else { - const hours = 1; - const dueDate = DateTime.now().plus({ week: 6 }).set({ hour: 17, minute: 0 }).toJSDate(); - this.localHours = hours; - const ilmSession = this.store.createRecord('ilm-session', { - session: this.args.session, - hours, - dueDate, - }); - this.args.session.set('ilmSession', await ilmSession.save()); - await this.args.session.save(); + get showAddNew() { + return !this.isIndependentLearning || this.addIlm.isRunning; + } + + get hasLinkedData() { + if (!this.ilmSession) { + return true; } + + return ( + this.ilmSession.hasMany('learnerGroups').ids().length || + this.ilmSession.hasMany('learners').ids().length || + this.ilmSession.hasMany('instructorGroups').ids().length || + this.ilmSession.hasMany('instructors').ids().length + ); + } + + addIlm = task({ drop: true }, async () => { + const hours = 1; + const dueDate = DateTime.now().plus({ week: 6 }).set({ hour: 17, minute: 0 }).toJSDate(); + this.localHours = hours; + const ilmSession = this.store.createRecord('ilm-session', { + session: this.args.session, + hours, + dueDate, + }); + await ilmSession.save(); + this.isNew = true; + this.isRecentlyAdded = true; + await timeout(100); + this.isNew = false; }); + removeIlm = task({ drop: true }, async () => { + const ilmSession = await this.args.session.ilmSession; + this.args.session.set('ilmSession', null); + await ilmSession.destroyRecord(); + await this.args.session.save(); + this.showRemoveConfirmation = false; + this.isRecentlyAdded = false; + }); + + get status() { + if (!this.isIndependentLearning && !this.args.editable) { + return 'hidden'; + } + + if (this.showRemoveConfirmation) { + return 'confirm-removal'; + } + + let status = this.showAddNew ? 'not-ilm' : 'is-ilm'; + if (this.isNew) { + status += ' is-new'; + } + if (this.isRecentlyAdded) { + status += ' recently-added'; + } + return status; + } + changeIlmHours = task({ restartable: true }, async () => { this.validations.addErrorDisplayFor('hours'); const isValid = await this.validations.isValid(); @@ -91,63 +138,127 @@ export default class SessionIlmComponent extends Component { this.validations.removeErrorDisplayFor('hours'); this.localHours = undefined; }; + + clickDelete = () => { + this.isRecentlyAdded = false; + if (this.hasLinkedData) { + this.showRemoveConfirmation = true; + } else { + this.removeIlm.perform(); + } + }; + } diff --git a/packages/ilios-common/app/styles/ilios-common/components.scss b/packages/ilios-common/app/styles/ilios-common/components.scss index 74b5a09285..02264873d6 100644 --- a/packages/ilios-common/app/styles/ilios-common/components.scss +++ b/packages/ilios-common/app/styles/ilios-common/components.scss @@ -126,6 +126,7 @@ @forward "components/course/visualize-objectives-graph"; @forward "components/session/collapsed-objectives"; +@forward "components/session/ilm"; @forward "components/session/objectives"; @forward "components/session/manage-objective-descriptors"; @forward "components/session/manage-objective-parents"; diff --git a/packages/ilios-common/app/styles/ilios-common/components/session-overview.scss b/packages/ilios-common/app/styles/ilios-common/components/session-overview.scss index 32a22b9e26..6ff9908a0f 100644 --- a/packages/ilios-common/app/styles/ilios-common/components/session-overview.scss +++ b/packages/ilios-common/app/styles/ilios-common/components/session-overview.scss @@ -112,13 +112,6 @@ grid-column: 1/-1; } - hr { - background: 0; - grid-column: 1 / -1; - height: 0; - margin: 1rem; - } - .sessiondescription, .instructional-notes { grid-column: 1 / -1; @@ -131,10 +124,4 @@ .fa-copy { color: var(--green); } - - @include m.for-desktop-and-up { - .session-overview-ilm-duedate { - grid-column: 2 / -1; - } - } } diff --git a/packages/ilios-common/app/styles/ilios-common/components/session/ilm.scss b/packages/ilios-common/app/styles/ilios-common/components/session/ilm.scss new file mode 100644 index 0000000000..d55de7ab89 --- /dev/null +++ b/packages/ilios-common/app/styles/ilios-common/components/session/ilm.scss @@ -0,0 +1,96 @@ +@use "../../mixins" as m; + +.session-ilm { + @include m.ilios-fieldset; + display: flex; + flex-direction: column; + margin: 0.25rem 0.5rem 0.25rem 0; + align-items: flex-start; + + @include m.for-tablet-and-up { + flex-direction: row; + align-items: center; + justify-content: space-around; + } + + legend { + display: flex; + align-items: center; + + button { + background-color: transparent; + padding: 0; + margin-left: 0.25rem; + color: var(--blue); + + &.remove { + color: var(--red); + } + } + } + + &.hidden { + display: none; + } + + &.not-ilm { + justify-content: flex-start; + button { + background-color: var(--green); + margin-left: 1rem; + } + } + + &.is-ilm { + @include m.for-tablet-and-up { + min-height: 4rem; + } + + &.recently-added { + transition: background-color 3s ease-in; + } + + div { + display: flex; + justify-content: center; + align-items: baseline; + } + + .hours { + input { + width: 3rem; + } + } + } + + &.is-new { + background-color: var(--transparent-green); + } + + &.confirm-removal { + flex-direction: column; + background-color: var(--lightest-red); + color: var(--light-red); + font-weight: 600; + + p { + text-align: center; + } + + .confirm-buttons { + button { + margin: 0.5rem; + } + + .remove { + background-color: var(--white); + color: var(--light-red); + + &:hover { + background-color: var(--light-red); + color: white; + } + } + } + } +} diff --git a/packages/ilios-common/translations/en-us.yaml b/packages/ilios-common/translations/en-us.yaml index 58b6304ee8..c4ef00ca65 100644 --- a/packages/ilios-common/translations/en-us.yaml +++ b/packages/ilios-common/translations/en-us.yaml @@ -4,6 +4,7 @@ general: actions: Actions activeFilters: Active Filters add: Add + addIlm: Add ILM to {session} addNew: Add New admin: Admin administratorCount: "There {count, plural, =1 {is 1 administrator} other {are # administrators}}" @@ -51,6 +52,7 @@ general: competencies: Competencies complete: Complete completeSessions: "Sessions Complete: ready to publish" + confirmRemoveIlm: Are you sure you want to delete this ILM? This action cannot be undone and will remove all learners and instructors linked directly to this ILM. confirmRemoveLearningMaterial: Are you sure you want to remove this learning material? This action cannot be undone. confirmRemoveObjective: Are you sure you want to delete this objective? This action cannot be undone. confirmRemoveSession: Are you sure you want to delete this session? This action cannot be undone. diff --git a/packages/ilios-common/translations/es.yaml b/packages/ilios-common/translations/es.yaml index 9608892661..4fe86d9b74 100644 --- a/packages/ilios-common/translations/es.yaml +++ b/packages/ilios-common/translations/es.yaml @@ -4,6 +4,7 @@ general: actions: Acciones activeFilters: Filtros Activos add: Agregue + addIlm: Añadir ILM a {session} addNew: Agregue Nuevo admin: Admin administratorCount: "Hay {count, plural, =1 {1 administrador} other {# administradores}}" @@ -52,6 +53,7 @@ general: complete: Completo completeSessions: "Sesiónes Completas: Listo a Publicar" confirmRemoveLearningMaterial: ¿Está seguro que desea eliminar este material de aprendizaje? Esta acción no se puede deshacer. + confirmRemoveIlm: ¿Está seguro de que quieres borrar este ILM? Esta acción no se puede deshacer y eliminará a todos los alumnos e instructores vinculados directamente a este ILM. confirmRemoveObjective: ¿Está seguro que desea eliminar este objetivo? Esta acción no se puede deshacer. confirmRemoveSession: ¿Está seguro que desea eliminar este sessión? Esta acción no se puede deshacer. confirmRemoveSessionOffering: "¿Estás seguro que quieres borrar este ofrecimiento con {learnerGroupCount} grupos de aprendedores? Esta acción no se puede deshacer." diff --git a/packages/ilios-common/translations/fr.yaml b/packages/ilios-common/translations/fr.yaml index f01fc87f79..c80874bfe9 100644 --- a/packages/ilios-common/translations/fr.yaml +++ b/packages/ilios-common/translations/fr.yaml @@ -4,6 +4,7 @@ general: actions: Actions activeFilters: Filtres actifs admin: Admin + addIlm: Ajouté ILM à {session} add: Ajouté addNew: Ajouté Neuf administratorCount: "Il y a {count, plural, =1 { un administrateur} other {# administrateurs}}" @@ -52,6 +53,7 @@ general: complete: Accompli completeSessions: "Séances complète: prêt à publier" confirmRemoveLearningMaterial: "Êtes-vous sûr vous voulez supprimer cette matériel d'étude? Ça action ne peut pas être défait." + confirmRemoveIlm: Êtes-vous sûr de vouloir supprimer cet ILM ? Cette action est irréversible et supprimera tous les apprenants et instructeurs directement liés à cet ILM. confirmRemoveObjective: Êtes vous sûr de vouloir supprimer cet objectif? Ça action ne peut pas être défait. confirmRemoveSession: Êtes vous sûr de vouloir supprimer cette séance? Ça action ne peut pas être défait. confirmRemoveSessionOffering: "Êtes-vous sûr vous voulez supprimer cette offre avec {learnerGroupCount} groupes d'apprenants? Ça action ne peut pas être défait." diff --git a/packages/test-app/tests/integration/components/session/ilm-test.gjs b/packages/test-app/tests/integration/components/session/ilm-test.gjs index f95887f04a..71af629e26 100644 --- a/packages/test-app/tests/integration/components/session/ilm-test.gjs +++ b/packages/test-app/tests/integration/components/session/ilm-test.gjs @@ -11,7 +11,7 @@ module('Integration | Component | session/ilm', function (hooks) { setupMirage(hooks); test('it renders and is accessible when not editable with ILM', async function (assert) { - const ilmSession = this.server.create('ilmSession', { hours: 8 }); + const ilmSession = this.server.create('ilm-session', { hours: 8 }); this.set('session', this.server.create('session', { ilmSession })); await render(); assert.ok(component.ilmHours.isVisible); @@ -19,33 +19,31 @@ module('Integration | Component | session/ilm', function (hooks) { assert.notOk(component.ilmHours.edit.isVisible); assert.ok(component.ilmDueDateAndTime.isVisible); assert.notOk(component.ilmDueDateAndTime.isEditable); - assert.notOk(component.toggleIlm.yesNoToggle.isVisible); + assert.notOk(component.canAdd); + assert.notOk(component.canRemove); assert.ok(component.isIlm); await a11yAudit(this.element); assert.ok(true, 'no a11y errors found!'); }); - test('it renders and is accessible when not editable with no ILM', async function (assert) { + test('it does not render when not editable with no ILM', async function (assert) { this.set('session', this.server.create('session')); await render(); - assert.notOk(component.ilmHours.isVisible); - assert.notOk(component.ilmDueDateAndTime.isVisible); - assert.notOk(component.toggleIlm.yesNoToggle.isVisible); - assert.notOk(component.isIlm); + assert.notOk(component.isVisible); await a11yAudit(this.element); assert.ok(true, 'no a11y errors found!'); }); test('it renders and is accessible when editable with ILM', async function (assert) { - const ilmSession = this.server.create('ilmSession'); + const ilmSession = this.server.create('ilm-session'); this.set('session', this.server.create('session', { ilmSession })); await render(); assert.ok(component.ilmHours.isVisible); assert.ok(component.ilmDueDateAndTime.isVisible); - assert.ok(component.toggleIlm.yesNoToggle.isVisible); - assert.strictEqual(component.toggleIlm.yesNoToggle.checked, 'true'); + assert.notOk(component.canAdd); + assert.ok(component.canRemove); await a11yAudit(this.element); assert.ok(true, 'no a11y errors found!'); @@ -56,15 +54,15 @@ module('Integration | Component | session/ilm', function (hooks) { await render(); assert.notOk(component.ilmHours.isVisible); assert.notOk(component.ilmDueDateAndTime.isVisible); - assert.ok(component.toggleIlm.yesNoToggle.isVisible); - assert.strictEqual(component.toggleIlm.yesNoToggle.checked, 'false'); + assert.ok(component.canAdd); + assert.notOk(component.canRemove); await a11yAudit(this.element); assert.ok(true, 'no a11y errors found!'); }); test('shows error with hours less than zero', async function (assert) { - const ilmSession = this.server.create('ilmSession'); + const ilmSession = this.server.create('ilm-session'); this.set('session', this.server.create('session', { ilmSession })); await render(); await component.ilmHours.edit(); @@ -74,7 +72,7 @@ module('Integration | Component | session/ilm', function (hooks) { }); test('error clears with close and re-open', async function (assert) { - const ilmSession = this.server.create('ilmSession'); + const ilmSession = this.server.create('ilm-session'); this.set('session', this.server.create('session', { ilmSession })); await render(); await component.ilmHours.edit(); @@ -84,4 +82,140 @@ module('Integration | Component | session/ilm', function (hooks) { await component.ilmHours.edit(); assert.notOk(component.ilmHours.hasError); }); + + test('remove and cancel', async function (assert) { + const learnerGroup = this.server.create('learner-group'); + const ilmSession = this.server.create('ilm-session', { + learnerGroups: [learnerGroup], + }); + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + + await a11yAudit(this.element); + + await component.cancel(); + + assert.ok(component.isIlm); + assert.notOk(component.canAdd); + assert.ok(component.canRemove); + assert.strictEqual(this.server.db.ilmSessions.length, 1); + }); + + test('remove and undo', async function (assert) { + const learnerGroup = this.server.create('learner-group'); + const ilmSession = this.server.create('ilm-session', { + learnerGroups: [learnerGroup], + }); + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + await component.undo(); + + assert.ok(component.isIlm); + assert.notOk(component.canAdd); + assert.ok(component.canRemove); + assert.strictEqual(this.server.db.ilmSessions.length, 1); + }); + + test('remove with no linked data', async function (assert) { + const ilmSession = this.server.create('ilm-session'); + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.notOk(component.isIlm); + assert.ok(component.canAdd); + assert.strictEqual(this.server.db.ilmSessions.length, 0); + }); + + test('remove and confirm with linked learner groups', async function (assert) { + const learnerGroup = this.server.create('learner-group'); + const ilmSession = this.server.create('ilm-session', { + learnerGroups: [learnerGroup], + }); + + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + await component.confirm(); + + assert.notOk(component.isIlm); + assert.ok(component.canAdd); + assert.strictEqual(this.server.db.ilmSessions.length, 0); + }); + + test('remove and confirm with linked learner', async function (assert) { + const user = this.server.create('user'); + const ilmSession = this.server.create('ilm-session', { + learners: [user], + }); + + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + await component.confirm(); + + assert.notOk(component.isIlm); + assert.ok(component.canAdd); + assert.strictEqual(this.server.db.ilmSessions.length, 0); + }); + + test('remove and confirm with linked instructor groups', async function (assert) { + const instructorGroup = this.server.create('instructor-group'); + const ilmSession = this.server.create('ilm-session', { + instructorGroups: [instructorGroup], + }); + + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + await component.confirm(); + + assert.notOk(component.isIlm); + assert.ok(component.canAdd); + assert.strictEqual(this.server.db.ilmSessions.length, 0); + }); + + test('remove and confirm with linked instructor', async function (assert) { + const user = this.server.create('user'); + const ilmSession = this.server.create('ilm-session', { + instructors: [user], + }); + + const session = this.server.create('session', { ilmSession }); + this.set('session', await this.owner.lookup('service:store').findRecord('session', session.id)); + await render(); + assert.ok(component.isIlm); + assert.ok(component.canRemove); + await component.removeIlm(); + assert.ok(component.confirmationMessage.isVisible); + await component.confirm(); + + assert.notOk(component.isIlm); + assert.ok(component.canAdd); + assert.strictEqual(this.server.db.ilmSessions.length, 0); + }); });