Skip to content

Commit

Permalink
Improve Data Loading Within the School Manager
Browse files Browse the repository at this point in the history
By pre-loading more of this data in the route we can do less loading and
spinning in the components and significantly reduce the number of
network calls required to manage a school.
  • Loading branch information
jrjohnson committed Jul 17, 2024
1 parent ea94b7a commit 72200dd
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 231 deletions.
278 changes: 137 additions & 141 deletions packages/frontend/app/components/school-session-type-form.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,162 +4,158 @@
data-test-school-session-type-form
...attributes
>
{{#if this.isLoaded}}
<div class="form">
<div class="item" data-test-title>
<label for="title-{{templateId}}">
{{t "general.title"}}:
</label>
{{#if @canEditTitle}}
<input
id="title-{{templateId}}"
type="text"
value={{this.title}}
{{on "input" (pick "target.value" (set this.title))}}
{{on "keyup" (queue (fn this.addErrorDisplayFor "title") (perform this.saveOrCancel))}}
>
<ValidationError @errors={{get-errors-for this.title}} />
{{else}}
<span class="value">
{{this.title}}
</span>
{{/if}}
</div>
<div class="item" data-test-aamc-method>
<label for="aamc-method-{{templateId}}">
{{t "general.aamcMethod"}}
<div class="item" data-test-title>
<label for="title-{{templateId}}">
{{t "general.title"}}:
</label>
{{#if @canEditTitle}}
<input
id="title-{{templateId}}"
type="text"
value={{this.title}}
{{on "input" (pick "target.value" (set this.title))}}
{{on "keyup" (queue (fn this.addErrorDisplayFor "title") (perform this.saveOrCancel))}}
>
<ValidationError @errors={{get-errors-for this.title}} />
{{else}}
<span class="value">
{{this.title}}
</span>
{{/if}}
</div>
<div class="item" data-test-aamc-method>
<label for="aamc-method-{{templateId}}">
{{t "general.aamcMethod"}}
</label>
{{#if @canEditAamcMethod}}
<select id="aamc-method-{{templateId}}" {{on "change" (pick "target.value" (set this.selectedAamcMethodId))}}>
<option selected={{not this.selectedAamcMethodId}}></option>
{{#each (sort-by "description" this.filteredAamcMethods) as |aamcMethod| }}
<option
value={{aamcMethod.id}}
selected={{eq aamcMethod.id this.selectedAamcMethodId}}
>
{{aamcMethod.description}}
{{#unless aamcMethod.active}}
({{t "general.inactive"}})
{{/unless}}
</option>
{{/each}}
</select>
{{else}}
<span class="value">
{{this.selectedAamcMethod.description}}
{{#unless this.selectedAamcMethod.active}}
({{t "general.inactive"}})
{{/unless}}
</span>
{{/if}}
</div>
<div class="item calendar-color" data-test-color>
<label for="color-{{templateId}}">
{{t "general.color"}}:
</label>
{{#if @canEditCalendarColor}}
<input
id="color-{{templateId}}"
type="color"
value={{this.calendarColor}}
{{on "input" (pick "target.value" (set this.calendarColor))}}
{{on "keyup" (queue (fn this.addErrorDisplayFor "calendarColor") (perform this.saveOrCancel))}}
>
<ValidationError @errors={{get-errors-for this.calendarColor}} />
{{else}}
<span class="value">
{{! template-lint-disable no-inline-styles style-concatenation no-triple-curlies}}
<span
class="box"
style={{{concat "background-color: " this.calendarColor}}}
data-test-colorbox
></span>
{{this.calendarColor}}
</span>
{{/if}}
</div>
<div class="item" data-test-assessment>
<label>
{{t "general.assessment"}}:
</label>
{{#if @canEditAssessment}}
<ToggleYesno @yes={{this.assessment}} @toggle={{this.updateAssessment}} />
{{else}}
<span class="value {{if this.assessment "yes" "no"}}">
{{#if this.assessment}}
{{t "general.yes"}}
{{else}}
{{t "general.no"}}
{{/if}}
</span>
{{/if}}
</div>
{{#if this.assessment}}
<div class="item" data-test-assessment-options>
<label for="assessment-option-{{templateId}}">
{{t "general.assessmentOption"}}:
</label>
{{#if @canEditAamcMethod}}
<select id="aamc-method-{{templateId}}" {{on "change" (pick "target.value" (set this.selectedAamcMethodId))}}>
<option selected={{not this.selectedAamcMethodId}}></option>
{{#each (sort-by "description" this.filteredAamcMethods) as |aamcMethod| }}
{{#if @canEditAssessmentOption}}
<select id="assessment-option-{{templateId}}" {{on "change" (pick "target.value" (set this.selectedAssessmentOptionId))}}>
{{#each (sort-by "name" this.assessmentOptions) as |o|}}
<option
value={{aamcMethod.id}}
selected={{eq aamcMethod.id this.selectedAamcMethodId}}
value={{o.id}}
selected={{eq o.id this.selectedAssessmentOptionId}}
>
{{aamcMethod.description}}
{{#unless aamcMethod.active}}
({{t "general.inactive"}})
{{/unless}}
{{o.name}}
</option>
{{/each}}
</select>
{{else}}
<span class="value">
{{this.selectedAamcMethod.description}}
{{#unless this.selectedAamcMethod.active}}
({{t "general.inactive"}})
{{/unless}}
{{this.selectedAssessmentOption.name}}
</span>
{{/if}}
</div>
<div class="item calendar-color" data-test-color>
<label for="color-{{templateId}}">
{{t "general.color"}}:
</label>
{{#if @canEditCalendarColor}}
<input
id="color-{{templateId}}"
type="color"
value={{this.calendarColor}}
{{on "input" (pick "target.value" (set this.calendarColor))}}
{{on "keyup" (queue (fn this.addErrorDisplayFor "calendarColor") (perform this.saveOrCancel))}}
>
<ValidationError @errors={{get-errors-for this.calendarColor}} />
{{else}}
<span class="value">
{{! template-lint-disable no-inline-styles style-concatenation no-triple-curlies}}
<span
class="box"
style={{{concat "background-color: " this.calendarColor}}}
data-test-colorbox
></span>
{{this.calendarColor}}
</span>
{{/if}}
</div>
<div class="item" data-test-assessment>
<label>
{{t "general.assessment"}}:
</label>
{{#if @canEditAssessment}}
<ToggleYesno @yes={{this.assessment}} @toggle={{this.updateAssessment}} />
{{else}}
<span class="value {{if this.assessment "yes" "no"}}">
{{#if this.assessment}}
{{t "general.yes"}}
{{else}}
{{t "general.no"}}
{{/if}}
</span>
{{/if}}
</div>
{{#if this.assessment}}
<div class="item" data-test-assessment-options>
<label for="assessment-option-{{templateId}}">
{{t "general.assessmentOption"}}:
</label>
{{#if @canEditAssessmentOption}}
<select id="assessment-option-{{templateId}}" {{on "change" (pick "target.value" (set this.selectedAssessmentOptionId))}}>
{{#each (sort-by "name" this.assessmentOptions) as |o|}}
<option
value={{o.id}}
selected={{eq o.id this.selectedAssessmentOptionId}}
>
{{o.name}}
</option>
{{/each}}
</select>
{{/if}}
<div class="item" data-test-active>
<label>
{{t "general.active"}}:
</label>
{{#if @canEditActive}}
<ToggleYesno @yes={{this.isActive}} @toggle={{set this.isActive}} />
{{else}}
<span class="value {{if this.isActive "yes" "no"}}">
{{#if this.isActive}}
{{t "general.yes"}}
{{else}}
<span class="value">
{{this.selectedAssessmentOption.name}}
</span>
{{t "general.no"}}
{{/if}}
</div>
</span>
{{/if}}
</div>
<div class="buttons">
{{#if @canUpdate}}
<button
type="button"
class="done text"
disabled={{this.saveSessionType.isRunning}}
{{on "click" (perform this.saveSessionType)}}
data-test-submit
>
{{#if this.saveSessionType.isRunning}}
<LoadingSpinner />
{{else}}
{{t "general.done"}}
{{/if}}
</button>
<button type="button" class="cancel text" {{on "click" @close}} data-test-cancel>
{{t "general.cancel"}}
</button>
{{else}}
<button type="button" class="text" {{on "click" @close}} data-test-close>
{{t "general.close"}}
</button>
{{/if}}
<div class="item" data-test-active>
<label>
{{t "general.active"}}:
</label>
{{#if @canEditActive}}
<ToggleYesno @yes={{this.isActive}} @toggle={{set this.isActive}} />
{{else}}
<span class="value {{if this.isActive "yes" "no"}}">
{{#if this.isActive}}
{{t "general.yes"}}
{{else}}
{{t "general.no"}}
{{/if}}
</span>
{{/if}}
</div>
<div class="buttons">
{{#if @canUpdate}}
<button
type="button"
class="done text"
disabled={{this.saveSessionType.isRunning}}
{{on "click" (perform this.saveSessionType)}}
data-test-submit
>
{{#if this.saveSessionType.isRunning}}
<LoadingSpinner />
{{else}}
{{t "general.done"}}
{{/if}}
</button>
<button type="button" class="cancel text" {{on "click" @close}} data-test-cancel>
{{t "general.cancel"}}
</button>
{{else}}
<button type="button" class="text" {{on "click" @close}} data-test-close>
{{t "general.close"}}
</button>
{{/if}}
</div>
</div>
{{else}}
<LoadingSpinner />
{{/if}}
</div>
</div>
{{/let}}
21 changes: 3 additions & 18 deletions packages/frontend/app/components/school-session-type-form.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import Component from '@glimmer/component';
import { cached, tracked } from '@glimmer/tracking';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { dropTask } from 'ember-concurrency';
import { validatable, IsHexColor, Length, NotBlank } from 'ilios-common/decorators/validation';
import { findById, sortBy } from 'ilios-common/utils/array-helpers';
import { TrackedAsyncData } from 'ember-async-data';

@validatable
export default class SchoolSessionTypeFormComponent extends Component {
Expand All @@ -17,26 +16,12 @@ export default class SchoolSessionTypeFormComponent extends Component {
@tracked selectedAssessmentOptionId = this.args.selectedAssessmentOptionId || null;
@tracked @NotBlank() @Length(1, 100) title = this.args.title || '';

@cached
get assessmentOptionsData() {
return new TrackedAsyncData(this.store.findAll('assessment-option'));
}

get assessmentOptions() {
return this.assessmentOptionsData.isResolved ? this.assessmentOptionsData.value : [];
}

@cached
get aamcMethodData() {
return new TrackedAsyncData(this.store.findAll('aamc-method'));
return this.store.peekAll('assessment-option');
}

get aamcMethods() {
return this.aamcMethodData.isResolved ? this.aamcMethodData.value : [];
}

get isLoaded() {
return this.assessmentOptionsData.isResolved && this.aamcMethodData.isResolved;
return this.store.peekAll('aamc-method');
}

get filteredAamcMethods() {
Expand Down
44 changes: 20 additions & 24 deletions packages/frontend/app/components/school-session-type-manager.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,24 @@
data-test-school-session-type-manager
...attributes
>
{{#if this.isLoaded}}
<div class="session-type-title" data-test-school-session-type-manager-title>
{{@sessionType.title}}
</div>
<SchoolSessionTypeForm
@title={{this.readonlySessionType.title}}
@calendarColor={{this.readonlySessionType.calendarColor}}
@assessment={{this.readonlySessionType.assessment}}
@isActive={{this.readonlySessionType.isActive}}
@selectedAssessmentOptionId={{this.readonlySessionType.selectedAssessmentOptionId}}
@selectedAamcMethodId={{this.readonlySessionType.selectedAamcMethodId}}
@canEditTitle={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditAamcMethod={{@canUpdate}}
@canEditCalendarColor={{@canUpdate}}
@canEditAssessment={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditAssessmentOption={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditActive={{@canUpdate}}
@canUpdate={{@canUpdate}}
@save={{@save}}
@close={{@close}}
/>
{{else}}
<LoadingSpinner />
{{/if}}
<div class="session-type-title" data-test-school-session-type-manager-title>
{{@sessionType.title}}
</div>
<SchoolSessionTypeForm
@title={{this.readonlySessionType.title}}
@calendarColor={{this.readonlySessionType.calendarColor}}
@assessment={{this.readonlySessionType.assessment}}
@isActive={{this.readonlySessionType.isActive}}
@selectedAssessmentOptionId={{this.readonlySessionType.selectedAssessmentOptionId}}
@selectedAamcMethodId={{this.readonlySessionType.selectedAamcMethodId}}
@canEditTitle={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditAamcMethod={{@canUpdate}}
@canEditCalendarColor={{@canUpdate}}
@canEditAssessment={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditAssessmentOption={{and @canUpdate (eq @sessionType.sessionCount 0)}}
@canEditActive={{@canUpdate}}
@canUpdate={{@canUpdate}}
@save={{@save}}
@close={{@close}}
/>
</div>
Loading

0 comments on commit 72200dd

Please sign in to comment.