packages/ilios-common/addon/components/detail-learning-materials.js
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { cached, tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { dropTask } from 'ember-concurrency';
import { all } from 'rsvp';
import scrollIntoView from 'scroll-into-view';
import { TrackedAsyncData } from 'ember-async-data';
import { mapBy } from 'ilios-common/utils/array-helpers';
import sortableByPosition from 'ilios-common/utils/sortable-by-position';
export default class DetailCohortsComponent extends Component {
@service currentUser;
@service store;
@service intl;
@tracked isSorting = false;
@tracked managingMaterial;
@tracked totalMaterialsToSave;
@tracked currentMaterialsSaved;
@tracked displayAddNewForm = false;
@tracked type;
@tracked learningMaterialStatuses;
@tracked learningMaterialUserRoles;
@tracked title;
@cached
get lmData() {
return new TrackedAsyncData(this.args.subject.learningMaterials);
}
constructor() {
super(...arguments);
this.learningMaterialStatuses = this.store.peekAll('learning-material-status');
this.learningMaterialUserRoles = this.store.peekAll('learning-material-user-role');
}
@cached
get materials() {
if (!this.lmData.isResolved) {
return [];
}
return this.lmData.value.slice().sort(sortableByPosition);
}
get parentMaterialIds() {
return this.materials.map((lm) => {
return lm.belongsTo('learningMaterial').id();
});
}
get isManaging() {
return !!this.managingMaterial;
}
get isSession() {
return !this.args.isCourse;
}
get displaySearchBox() {
return !this.isManaging && !this.displayAddNewForm && !this.isSorting && this.args.editable;
}
get hasMoreThanOneLearningMaterial() {
return this.materials && this.materials.length > 1;
}
@action
setManagedMaterial(lm) {
this.managingMaterial = lm;
}
@action
addNewLearningMaterial(type) {
this.type = type;
this.displayAddNewForm = true;
}
@action
closeLearningmaterialManager() {
this.setManagedMaterial(null);
scrollIntoView(this.title, {
align: { top: 0 },
});
}
@action
closeNewLearningmaterial() {
this.displayAddNewForm = false;
scrollIntoView(this.title, {
align: { top: 0 },
});
}
saveNewLearningMaterial = dropTask(async (lm) => {
const savedLm = await lm.save();
let lmSubject;
let position = 0;
if (this.materials && this.materials.length) {
const positions = mapBy(this.materials, 'position');
position = Math.max(...positions) + 1;
}
if (this.args.isCourse) {
lmSubject = this.store.createRecord('course-learning-material', {
course: this.args.subject,
position,
});
} else {
lmSubject = this.store.createRecord('session-learning-material', {
session: this.args.subject,
position,
});
}
lmSubject.set('learningMaterial', savedLm);
await lmSubject.save();
this.displayAddNewForm = false;
this.type = null;
scrollIntoView(this.title, {
align: { top: 0 },
});
});
saveSortOrder = dropTask(async (learningMaterials) => {
const materialsToSave = [];
for (let i = 0, n = learningMaterials.length; i < n; i++) {
const lm = learningMaterials[i];
const position = i + 1;
if (lm.position != position) {
lm.set('position', position);
materialsToSave.push(lm);
}
}
await this.saveSomeMaterials(materialsToSave);
this.isSorting = false;
scrollIntoView(this.title, {
align: { top: 0 },
});
});
addLearningMaterial = dropTask(async (parentLearningMaterial) => {
let newLearningMaterial;
if (this.args.isCourse) {
newLearningMaterial = this.store.createRecord('course-learning-material', {
course: this.args.subject,
learningMaterial: parentLearningMaterial,
position: 0,
});
} else {
newLearningMaterial = this.store.createRecord('session-learning-material', {
session: this.args.subject,
learningMaterial: parentLearningMaterial,
position: 0,
});
}
let position = 0;
if (this.materials && this.materials.length > 1) {
const positions = mapBy(this.materials, 'position');
position = Math.max(...positions) + 1;
}
newLearningMaterial.set('position', position);
await newLearningMaterial.save();
});
remove = dropTask(async (lm) => {
lm.deleteRecord();
return await lm.save();
});
async saveSomeMaterials(arr) {
const chunk = arr.splice(0, 5);
const savedMaterials = await all(chunk.map((o) => o.save()));
let moreMaterials = [];
if (arr.length) {
moreMaterials = await this.saveSomeMaterials(arr);
}
return [].concat(savedMaterials, moreMaterials);
}
}