diff --git a/packages/frontend/app/components/reports/new-subject.hbs b/packages/frontend/app/components/reports/new-subject.hbs index 5d2b6b11ff..16ad12e4a1 100644 --- a/packages/frontend/app/components/reports/new-subject.hbs +++ b/packages/frontend/app/components/reports/new-subject.hbs @@ -71,7 +71,7 @@ - {{#each this.prepositionalObjectList as |o|}} + {{#each (sort-by "label" this.prepositionalObjectList) as |o|}}
diff --git a/packages/frontend/app/components/reports/subject/new/academic-year.js b/packages/frontend/app/components/reports/subject/new/academic-year.js new file mode 100644 index 0000000000..3adfaf9c83 --- /dev/null +++ b/packages/frontend/app/components/reports/subject/new/academic-year.js @@ -0,0 +1,46 @@ +import Component from '@glimmer/component'; +import { TrackedAsyncData } from 'ember-async-data'; +import { cached } from '@glimmer/tracking'; +import { service } from '@ember/service'; +import { task, timeout } from 'ember-concurrency'; + +export default class ReportsSubjectNewAcademicYearComponent extends Component { + @service store; + @service iliosConfig; + + @cached + get data() { + return new TrackedAsyncData(this.store.findAll('academic-year')); + } + + crossesBoundaryConfig = new TrackedAsyncData( + this.iliosConfig.itemFromConfig('academicYearCrossesCalendarYearBoundaries'), + ); + + @cached + get academicYearCrossesCalendarYearBoundaries() { + return this.crossesBoundaryConfig.isResolved ? this.crossesBoundaryConfig.value : false; + } + + get academicYears() { + return this.data.value; + } + + get isLoaded() { + return this.data.isResolved; + } + + @task + *setInitialValue() { + yield timeout(1); //wait a moment so we can render before setting + const ids = this.academicYears.map(({ id }) => id); + if (ids.includes(this.args.currentId)) { + return; + } + if (!this.academicYears.length) { + this.args.changeId(null); + } else { + this.args.changeId(this.academicYears[0].id); + } + } +} diff --git a/packages/frontend/app/services/reporting.js b/packages/frontend/app/services/reporting.js index 6fedaf0c22..40ef22663a 100644 --- a/packages/frontend/app/services/reporting.js +++ b/packages/frontend/app/services/reporting.js @@ -32,6 +32,7 @@ const objectTranslations = { session: 'general.session', school: 'general.school', term: 'general.term', + 'academic year': 'general.academicYear', }; export default class ReportingService extends Service { diff --git a/packages/frontend/tests/acceptance/reports/subjects-test.js b/packages/frontend/tests/acceptance/reports/subjects-test.js index 1742ba794d..b39659101c 100644 --- a/packages/frontend/tests/acceptance/reports/subjects-test.js +++ b/packages/frontend/tests/acceptance/reports/subjects-test.js @@ -201,7 +201,7 @@ module('Acceptance | Reports - Subject Reports', function (hooks) { }); test('get all courses associated with mesh term #3419', async function (assert) { - assert.expect(14); + assert.expect(15); await page.visit(); assert.strictEqual(page.root.list.table.reports.length, 2); assert.strictEqual( @@ -248,6 +248,7 @@ module('Acceptance | Reports - Subject Reports', function (hooks) { subjectReportPage.report.title.text, 'All Courses for descriptor 0 in school 0', ); + assert.ok(subjectReportPage.report.academicYears.isVisible); assert.strictEqual(subjectReportPage.report.results.length, 2); assert.strictEqual( subjectReportPage.report.results[0].text, @@ -411,4 +412,82 @@ module('Acceptance | Reports - Subject Reports', function (hooks) { 'All Sessions for term 0 in school 0', ); }); + + test('create new report for instructors by academic year #3594', async function (assert) { + assert.expect(14); + this.server.createList('user', 3); + await page.visit(); + assert.strictEqual(page.root.list.table.reports.length, 2); + assert.ok(page.root.list.newReportLinkIsHidden); + await page.root.list.toggleNewSubjectReportForm(); + await page.root.list.newSubject.schools.choose('1'); + await page.root.list.newSubject.subjects.choose('instructor'); + await page.root.list.newSubject.objects.choose('academic year'); + await page.root.list.newSubject.save(); + assert.notOk(page.root.list.newReportLinkIsHidden); + assert.strictEqual(page.root.list.table.reports.length, 3); + assert.strictEqual( + page.root.list.table.reports[0].title, + 'All Instructors for 2015 - 2016 in school 0', + ); + assert.strictEqual(page.root.list.newReportLink, 'All Instructors for 2015 - 2016 in school 0'); + + this.server.post('api/graphql', ({ db }, { requestBody }) => { + const { query } = JSON.parse(requestBody); + + assert.strictEqual( + query, + 'query { users(schools: [1], instructedAcademicYears: [2015]) { firstName,middleName,lastName,displayName } }', + ); + return { + data: { + users: db.users.map(({ firstName, middleName, lastName, displayName }) => { + return { firstName, middleName, lastName, displayName }; + }), + }, + }; + }); + await page.root.list.table.reports[0].select(); + assert.strictEqual(currentURL(), '/reports/subjects/3'); + assert.strictEqual( + subjectReportPage.report.title.text, + 'All Instructors for 2015 - 2016 in school 0', + ); + assert.strictEqual(subjectReportPage.report.results.length, 4); + assert.strictEqual(subjectReportPage.report.results[0].text, '0 guy M. Mc0son'); + assert.strictEqual(subjectReportPage.report.results[1].text, '1 guy M. Mc1son'); + assert.strictEqual(subjectReportPage.report.results[2].text, '2 guy M. Mc2son'); + assert.strictEqual(subjectReportPage.report.results[3].text, '3 guy M. Mc3son'); + }); + + test('courses by academic year hides year', async function (assert) { + assert.expect(5); + await page.visit(); + await page.root.list.toggleNewSubjectReportForm(); + await page.root.list.newSubject.schools.choose(''); + await page.root.list.newSubject.subjects.choose('course'); + await page.root.list.newSubject.objects.choose('academic year'); + await page.root.list.newSubject.prepositionalObjects.choose('2015'); + await page.root.list.newSubject.save(); + this.server.post('api/graphql', ({ db }, { requestBody }) => { + const { query } = JSON.parse(requestBody); + assert.strictEqual( + query, + 'query { courses(academicYears: [2015]) { id, title, year, externalId } }', + ); + const coursesIn2015 = db.courses.filter(({ year }) => year === 2015); + return { + data: { + courses: coursesIn2015.map(({ id, title, year, externalId }) => { + return { id, title, year, externalId }; + }), + }, + }; + }); + await page.root.list.table.reports[0].select(); + assert.strictEqual(currentURL(), '/reports/subjects/3'); + assert.notOk(subjectReportPage.report.academicYears.isVisible); + assert.strictEqual(subjectReportPage.report.results.length, 1); + assert.strictEqual(subjectReportPage.report.results[0].text, 'course 0 (Theoretical Phys Ed)'); + }); }); diff --git a/packages/frontend/tests/integration/components/reports/new-subject-test.js b/packages/frontend/tests/integration/components/reports/new-subject-test.js index 23b53235d8..153032395f 100644 --- a/packages/frontend/tests/integration/components/reports/new-subject-test.js +++ b/packages/frontend/tests/integration/components/reports/new-subject-test.js @@ -128,27 +128,29 @@ module('Integration | Component | reports/new-subject', function (hooks) { }); test('choosing course selects correct objects', function (assert) { - assert.expect(8); + assert.expect(9); return checkObjects(this, assert, 0, 'course', [ - 'program', + 'academic year', + 'competency', 'instructor', 'instructor group', 'learning material', - 'competency', 'mesh term', + 'program', ]); }); test('choosing session selects correct objects', function (assert) { - assert.expect(10); + assert.expect(11); return checkObjects(this, assert, 1, 'session', [ + 'academic year', + 'competency', 'course', - 'program', 'instructor', 'instructor group', 'learning material', - 'competency', 'mesh term', + 'program', 'session type', ]); }); @@ -164,23 +166,25 @@ module('Integration | Component | reports/new-subject', function (hooks) { }); test('choosing instructor selects correct objects', function (assert) { - assert.expect(7); + assert.expect(8); return checkObjects(this, assert, 4, 'instructor', [ + 'academic year', 'course', - 'session', 'instructor group', 'learning material', + 'session', 'session type', ]); }); test('choosing instructor group selects correct objects', function (assert) { - assert.expect(7); + assert.expect(8); return checkObjects(this, assert, 5, 'instructor group', [ + 'academic year', 'course', - 'session', 'instructor', 'learning material', + 'session', 'session type', ]); }); @@ -189,53 +193,60 @@ module('Integration | Component | reports/new-subject', function (hooks) { assert.expect(8); return checkObjects(this, assert, 6, 'learning material', [ 'course', - 'session', 'instructor', 'instructor group', 'mesh term', + 'session', 'session type', ]); }); test('choosing competency selects correct objects', function (assert) { - assert.expect(5); - return checkObjects(this, assert, 7, 'competency', ['course', 'session', 'session type']); + assert.expect(6); + return checkObjects(this, assert, 7, 'competency', [ + 'academic year', + 'course', + 'session', + 'session type', + ]); }); test('choosing mesh term selects correct objects', function (assert) { assert.expect(6); return checkObjects(this, assert, 8, 'mesh term', [ 'course', - 'session', 'learning material', + 'session', 'session type', ]); }); test('choosing term selects correct objects', function (assert) { - assert.expect(10); + assert.expect(11); return checkObjects(this, assert, 9, 'term', [ + 'academic year', + 'competency', 'course', - 'session', - 'program year', - 'program', 'instructor', 'learning material', - 'competency', 'mesh term', + 'program', + 'program year', + 'session', ]); }); test('choosing session type selects correct objects', function (assert) { - assert.expect(10); + assert.expect(11); return checkObjects(this, assert, 10, 'session type', [ + 'academic year', + 'competency', 'course', - 'program', 'instructor', 'instructor group', 'learning material', - 'competency', 'mesh term', + 'program', 'term', ]); }); diff --git a/packages/frontend/tests/integration/components/reports/subject/course-test.js b/packages/frontend/tests/integration/components/reports/subject/course-test.js index 8c2ce2740f..48694f368a 100644 --- a/packages/frontend/tests/integration/components/reports/subject/course-test.js +++ b/packages/frontend/tests/integration/components/reports/subject/course-test.js @@ -221,4 +221,31 @@ module('Integration | Component | reports/subject/course', function (hooks) { @prepositionalObjectTableRowId={{this.report.prepositionalObjectTableRowId}} />`); }); + + test('filter by academic year', async function (assert) { + assert.expect(1); + this.server.post('api/graphql', function (schema, { requestBody }) { + const { query } = JSON.parse(requestBody); + assert.strictEqual( + query, + 'query { courses(academicYears: [2015]) { id, title, year, externalId } }', + ); + return { + data: { + courses: [{ id: 1, title: 'First Course', year: 2015 }], + }, + }; + }); + const { id } = this.server.create('report', { + subject: 'course', + prepositionalObject: 'academic year', + prepositionalObjectTableRowId: '2015', + }); + this.set('report', await this.owner.lookup('service:store').findRecord('report', id)); + await render(hbs`