Skip to content

Commit

Permalink
Merge pull request #7419 from jrjohnson/4358-subject-search
Browse files Browse the repository at this point in the history
Add Search for course, session, and lm reports
  • Loading branch information
dartajax authored Sep 22, 2023
2 parents 6bf2ade + 45a8f04 commit e0e8523
Show file tree
Hide file tree
Showing 21 changed files with 588 additions and 654 deletions.
42 changes: 23 additions & 19 deletions app/components/reports/new-subject.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,23 @@
<label for="associated-{{templateId}}">
{{t "general.associatedWith"}}
</label>
<div>
<select
id="associated-{{templateId}}"
{{on "change" (pick "target.value" this.changePrepositionalObject)}}
>
<option value="" selected={{eq null this.currentPrepositionalObject}}>
{{t "general.anything"}}
<select
id="associated-{{templateId}}"
{{on "change" (pick "target.value" this.changePrepositionalObject)}}
>
<option value="" selected={{eq null this.currentPrepositionalObject}}>
{{t "general.anything"}}
</option>
{{#each this.prepositionalObjectList as |o|}}
<option
value={{o.value}}
selected={{eq o.value this.currentPrepositionalObject}}
>
{{o.label}}
</option>
{{#each this.prepositionalObjectList as |o|}}
<option
value={{o.value}}
selected={{eq o.value this.currentPrepositionalObject}}
>
{{o.label}}
</option>
{{/each}}
</select>
<ValidationError @errors={{get-errors-for this.currentPrepositionalObject}} />
</div>
{{/each}}
</select>
<ValidationError @errors={{get-errors-for this.currentPrepositionalObject}} />
</p>
<this.newPrepositionalObjectComponent
@school={{this.currentSchool}}
Expand All @@ -92,7 +90,13 @@
/>
<ValidationError @errors={{get-errors-for this.currentPrepositionalObjectId}} data-test-validation-error />
<div class="input-buttons">
<button type="button" class="done text" {{on "click" (perform this.save)}} data-test-save>
<button
type="button"
class="done text"
{{on "click" (perform this.save)}}
disabled={{this.save.isRunning}}
data-test-save
>
{{#if this.save.isRunning}}
<LoadingSpinner />
{{else}}
Expand Down
104 changes: 46 additions & 58 deletions app/components/reports/subject/new/course.hbs
Original file line number Diff line number Diff line change
@@ -1,64 +1,52 @@
<div data-test-reports-subject-new-course>
<p data-test-year>
<label>
{{t "general.in"}}
</label>
{{#if this.isLoaded}}
<select
aria-label={{t "general.year"}}
data-test-report-academic-years
{{on "change" (pick "target.value" this.changeSelectedYear)}}
>
<option selected={{is-empty this.selectedYear}} value="">
{{t "general.allAcademicYears"}}
</option>
{{#each
(sort-by
"title:desc" this.filteredYears
) as |year|
}}
<option
selected={{eq year.id this.selectedYear}}
value={{year.id}}
>
{{year.title}}
</option>
{{/each}}
</select>
{{else}}
<LoadingSpinner />
{{/if}}
</p>

<p data-test-course>
<label for="new-course">
<div class="new-subject-search" data-test-reports-subject-new-course>
<p data-test-search>
<label for="{{this.uniqueId}}-course-search">
{{t "general.whichIs"}}
</label>
{{#if this.isLoaded}}
<select
id="new-course"
data-test-prepositional-objects
{{on "change" (pick "target.value" @changeId)}}
{{did-insert (perform this.setInitialValue)}}
{{did-update (perform this.setInitialValue) @school}}
>
{{#each this.sortedCourses as |course|}}
<option
selected={{eq course.id @currentId}}
value={{course.id}}
>
{{#unless this.selectedYear}}
{{course.year}}
{{/unless}}
{{#if course.externalId}}
[{{course.externalId}}] |
{{/if}}
{{course.title}}
</option>
{{/each}}
</select>
{{#if @currentId}}
{{#let (load this.loadCourse) as |p|}}
{{#if p.isResolved}}
{{#let p.value as |course|}}
<button
class="link-button"
type="button"
{{on "click" this.clear}}
data-test-selected-course
>
{{course.year}}&nbsp;
{{#if course.externalId}}
[{{course.externalId}}]&nbsp;
{{/if}}
{{course.title}}
<FaIcon @icon="xmark" class="remove"/>
</button>
{{/let}}
{{else}}
<LoadingSpinner />
{{/if}}
{{/let}}
{{else}}
<LoadingSpinner />
<Reports::Subject::New::Search::Input
@search={{perform this.search}}
@searchIsRunning={{this.search.isRunning}}
@searchIsIdle={{this.search.isIdle}}
@searchReturned={{is-array this.courses}}
@results={{this.sortedCourses}}
as |course|
>
<button
class="link-button"
type="button"
{{on "click" (fn @changeId course.id)}}
>
{{course.year}}&nbsp;
{{#if course.externalId}}
[{{course.externalId}}]&nbsp;
{{/if}}
{{course.title}}
</button>

</Reports::Subject::New::Search::Input>
{{/if}}
</p>
</div>
87 changes: 33 additions & 54 deletions app/components/reports/subject/new/course.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,61 @@
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';
import { restartableTask } from 'ember-concurrency';
import { tracked } from '@glimmer/tracking';
import { hash } from 'rsvp';
import { action } from '@ember/object';
import { sortBy } from 'ilios-common/utils/array-helpers';
import { guidFor } from '@ember/object/internals';

export default class ReportsSubjectNewCourseComponent extends Component {
@service store;
@tracked courses;

@tracked selectedYear;

@cached
get data() {
return new TrackedAsyncData(
hash({
courses: this.store.findAll('course'),
years: this.store.findAll('academic-year'),
}),
);
}

get isLoaded() {
return this.data.isResolved;
}

get courses() {
return this.data.value.courses;
get loadCourse() {
return this.store.findRecord('course', this.args.currentId);
}

get years() {
return this.data.value.years;
}

get filteredYears() {
const courseYears = this.filteredCoursesBySchool.map((c) => Number(c.year));
return this.years.filter(({ id }) => courseYears.includes(Number(id)));
get uniqueId() {
return guidFor(this);
}

get filteredCourses() {
if (this.selectedYear) {
return this.filteredCoursesBySchool.filter((c) => c.year === Number(this.selectedYear));
if (!this.courses) {
return [];
}

return this.filteredCoursesBySchool;
}

get filteredCoursesBySchool() {
if (this.args.school) {
return this.courses.filter((c) => c.belongsTo('school').id() === this.args.school.id);
const schoolId = Number(this.args.school.id);
return this.courses.filter((c) => {
return Number(c.belongsTo('school').id()) === schoolId;
});
}

return this.courses;
}

get sortedCourses() {
return sortBy(this.filteredCourses, ['year', 'title']);
}
return this.filteredCourses.toSorted((a, b) => {
if (a.year !== b.year) {
return b.year - a.year;
}

@action
changeSelectedYear(year) {
this.selectedYear = year;
this.setInitialValue.perform();
return a.title.localeCompare(b.title);
});
}

@task
*setInitialValue() {
yield timeout(1); //wait a moment so we can render before setting
const ids = this.sortedCourses.map(({ id }) => id);
if (ids.includes(this.args.currentId)) {
@restartableTask
*search(q) {
if (!q.length) {
this.courses = false;
return;
}
if (!this.sortedCourses.length) {
this.args.changeId(null);
} else {
this.args.changeId(this.sortedCourses[0].id);
}

this.courses = yield this.store.query('course', {
q,
});
}

@action
clear() {
this.courses = false;
this.args.changeId(null);
}
}
68 changes: 44 additions & 24 deletions app/components/reports/subject/new/learning-material.hbs
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
<p data-test-reports-subject-new-learning-material>
<label for="new-learning-material">
{{t "general.whichIs"}}
</label>
{{#if this.isLoaded}}
<select
id="new-learning-material"
data-test-prepositional-objects
{{on "change" (pick "target.value" @changeId)}}
{{did-insert (perform this.setInitialValue)}}
{{did-update (perform this.setInitialValue) @school}}
>
{{#each this.sortedLearningMaterials as |learningMaterial|}}
<option
selected={{eq learningMaterial.id @currentId}}
value={{learningMaterial.id}}
<div class="new-subject-search" data-test-reports-subject-new-learning-material>
<p data-test-search>
<label for="{{this.uniqueId}}-learning-material-search">
{{t "general.whichIs"}}
</label>
{{#if @currentId}}
{{#let (load this.loadMaterial) as |p|}}
{{#if p.isResolved}}
{{#let p.value as |material|}}
<button
class="link-button"
type="button"
{{on "click" this.clear}}
data-test-selected-learning-material
>
{{material.title}}
<FaIcon @icon="xmark" class="remove"/>
</button>
{{/let}}
{{else}}
<LoadingSpinner />
{{/if}}
{{/let}}
{{else}}
<Reports::Subject::New::Search::Input
id="{{this.uniqueId}}-learning-material-search"
@search={{perform this.search}}
@searchIsRunning={{this.search.isRunning}}
@searchIsIdle={{this.search.isIdle}}
@searchReturned={{is-array this.materials}}
@results={{this.sortedMaterials}}
as |material|
>
<button
class="link-button"
type="button"
{{on "click" (fn @changeId material.id)}}
>
{{learningMaterial.title}}
</option>
{{/each}}
</select>
{{else}}
<LoadingSpinner />
{{/if}}
</p>
{{material.title}}
</button>

</Reports::Subject::New::Search::Input>
{{/if}}
</p>
</div>
Loading

0 comments on commit e0e8523

Please sign in to comment.