ilios/frontend

View on GitHub
packages/frontend/app/components/school-competencies-expanded.js

Summary

Maintainability
A
0 mins
Test Coverage
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { all } from 'rsvp';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { dropTask, restartableTask } from 'ember-concurrency';
import { filterBy, uniqueValues } from 'ilios-common/utils/array-helpers';

export default class SchoolCompetenciesExpandedComponent extends Component {
  @service store;
  @tracked competenciesToAdd = [];
  @tracked competenciesToRemove = [];
  @tracked schoolCompetencies;

  load = restartableTask(async () => {
    this.cleanup();
    this.schoolCompetencies = await this.args.school.competencies;
  });

  get competencies() {
    if (!this.schoolCompetencies) {
      return [];
    }
    const arr = [...this.schoolCompetencies.slice(), ...this.competenciesToAdd];
    return uniqueValues(
      arr.filter((competency) => !this.competenciesToRemove.includes(competency)),
    );
  }

  get domains() {
    return this.competencies.filter((competency) => {
      return !competency.belongsTo('parent').id();
    });
  }

  get childCompetencies() {
    return this.competencies.filter((competency) => {
      return competency.belongsTo('parent').id();
    });
  }

  get showCollapsible() {
    return this.competencies.length && !this.args.isManaging;
  }

  cleanup() {
    this.competenciesToAdd = [];
    this.competenciesToRemove = [];
  }

  @action
  collapse() {
    if (this.competencies.length) {
      this.args.collapse();
      this.cleanup();
    }
  }

  @action
  stopManaging() {
    this.cleanup();
    this.args.setSchoolManageCompetencies(false);
  }

  @action
  addCompetency(domain, title) {
    const competency = this.store.createRecord('competency', {
      title,
      active: true,
    });
    if (domain) {
      competency.set('parent', domain);
    }
    this.competenciesToAdd = [...this.competenciesToAdd, competency];
  }
  @action
  removeCompetency(competency) {
    this.competenciesToAdd = this.competenciesToAdd.filter((c) => c !== competency);
    this.competenciesToRemove = [...this.competenciesToRemove, competency];
  }

  save = dropTask(async () => {
    const domainsToRemove = this.schoolCompetencies.filter((competency) => {
      return !competency.belongsTo('parent').id() && !this.competencies.includes(competency);
    });
    const competenciesToRemove = this.schoolCompetencies.filter((competency) => {
      return competency.belongsTo('parent').id() && !this.competencies.includes(competency);
    });

    // delete all removed competencies first, then all removed domains
    await all(competenciesToRemove.map((competency) => competency.destroyRecord()));
    await all(domainsToRemove.map((domain) => domain.destroyRecord()));

    // set the school on new competencies
    filterBy(this.competencies, 'isNew').forEach((competency) => {
      competency.set('school', this.args.school);
    });

    // update all modified competencies (this will include new ones).
    await all(
      filterBy(this.competencies, 'hasDirtyAttributes').map((competency) => competency.save()),
    );

    // cleanup
    this.cleanup();
    this.args.setSchoolManageCompetencies(false);
    this.schoolCompetencies = await this.args.school.competencies;
  });
}