Ontica/Empiria.Land.Intranet

View on GitHub
src/app/views/_access-control/subjects/subject-header.component.ts

Summary

Maintainability
C
7 hrs
Test Coverage
/**
 * @license
 * Copyright (c) La Vía Óntica SC, Ontica LLC and contributors. All rights reserved.
 *
 * See LICENSE.txt in the project root for complete license information.
 */

import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output,
         SimpleChanges } from '@angular/core';

import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';

import { Assertion, EventInfo, Identifiable, isEmpty } from '@app/core';

import { PresentationLayer, SubscriptionHelper } from '@app/core/presentation';

import { AccessControlStateSelector } from '@app/presentation/exported.presentation.types';

import { EmptySubject, Subject, SubjectFields} from '@app/models';

import { MessageBoxService } from '@app/shared/containers/message-box';

import { ArrayLibrary, FormHelper, sendEvent } from '@app/shared/utils';

export enum SubjectHeaderEventType {
  CREATE_SUBJECT    = 'SubjectHeaderComponent.Event.CreateSubject',
  UPDATE_SUBJECT    = 'SubjectHeaderComponent.Event.UpdateSubject',
  DELETE_SUBJECT    = 'SubjectHeaderComponent.Event.DeleteSubject',
  GENERATE_PASSWORD = 'SubjectHeaderComponent.Event.GeneratePassword',
  ACTIVATE_SUBJECT  = 'SubjectHeaderComponent.Event.ActivateSubject',
  SUSPEND_SUBJECT   = 'SubjectHeaderComponent.Event.SuspendSubject',
}

interface SubjectFormModel extends FormGroup<{
  fullName: FormControl<string>;
  userID: FormControl<string>;
  eMail: FormControl<string>;
  employeeNo: FormControl<string>;
  jobPosition: FormControl<string>;
  workareaUID: FormControl<string>;
}> { }

@Component({
  selector: 'emp-ng-subject-header',
  templateUrl: './subject-header.component.html',
})
export class SubjectHeaderComponent implements OnChanges, OnInit, OnDestroy {

  @Input() subject: Subject = EmptySubject;

  @Input() canEdit = false;

  @Input() canGeneratePassword = false;

  @Input() isDeleted = false;

  @Input() isSuspended = false;

  @Output() subjectHeaderEvent = new EventEmitter<EventInfo>();

  form: SubjectFormModel;

  formHelper = FormHelper;

  editionMode = false;

  isLoading = false;

  workareasList: Identifiable[] = [];

  helper: SubscriptionHelper;


  constructor(private messageBox: MessageBoxService,
              private uiLayer: PresentationLayer) {
    this.helper = uiLayer.createSubscriptionHelper();
    this.initForm();
    this.enableEditor(true);
  }


  ngOnChanges(changes: SimpleChanges) {
    if (changes.subject && this.isSaved) {
      this.enableEditor(false);
    }
  }


  ngOnInit() {
    this.loadWorkareas();
  }


  ngOnDestroy() {
    this.helper.destroy();
  }


  get isSaved(): boolean {
    return !isEmpty(this.subject);
  }


  enableEditor(enable: boolean) {
    this.editionMode = enable;

    if (!this.editionMode) {
      this.setFormData();
    }

    const disable = !this.editionMode || this.isDeleted;

    this.formHelper.setDisableForm(this.form, disable);
  }


  onSubmitButtonClicked() {
    if (this.formHelper.isFormReadyAndInvalidate(this.form)) {
      const eventType = this.isSaved ? SubjectHeaderEventType.UPDATE_SUBJECT :
        SubjectHeaderEventType.CREATE_SUBJECT;

      sendEvent(this.subjectHeaderEvent, eventType, { subject: this.getFormData() });
    }
  }


  onGeneratePasswordButtonClicked() {
    this.showConfirmMessage(SubjectHeaderEventType.GENERATE_PASSWORD);
  }


  onActivateButtonClicked() {
    this.showConfirmMessage(SubjectHeaderEventType.ACTIVATE_SUBJECT);
  }


  onSuspendButtonClicked() {
    this.showConfirmMessage(SubjectHeaderEventType.SUSPEND_SUBJECT);
  }


  onDeleteButtonClicked() {
    this.showConfirmMessage(SubjectHeaderEventType.DELETE_SUBJECT);
  }


  private loadWorkareas() {
    this.isLoading = true;

    this.helper.select<Identifiable[]>(AccessControlStateSelector.WORKAREAS_LIST)
      .subscribe(x => {
        this.workareasList = x;
        this.validateSubjectWorkareaInList();
        this.isLoading = false;
      });
  }


  private validateSubjectWorkareaInList() {
    if (!isEmpty(this.subject.workarea)) {
      this.workareasList =
        ArrayLibrary.insertIfNotExist(this.workareasList ?? [], this.subject.workarea, 'uid');
    }
  }


  private initForm() {
    const fb = new FormBuilder();

    this.form = fb.group({
      fullName: ['', Validators.required],
      userID: ['', Validators.required],
      eMail: ['', Validators.required],
      employeeNo: [''],
      jobPosition: ['', Validators.required],
      workareaUID: ['', Validators.required],
    });
  }


  private setFormData() {
    this.form.reset({
      fullName: this.subject.fullName,
      userID: this.subject.userID,
      eMail: this.subject.eMail,
      employeeNo: this.subject.employeeNo,
      jobPosition: this.subject.jobPosition,
      workareaUID: this.subject.workarea.uid,
    });

    this.validateSubjectWorkareaInList();
  }


  private getFormData(): SubjectFields {
    Assertion.assert(this.form.valid,
      'Programming error: form must be validated before command execution.');

    const formModel = this.form.getRawValue();

    const data: SubjectFields = {
      fullName: formModel.fullName ?? '',
      userID: formModel.userID ?? '',
      eMail: formModel.eMail ?? '',
      employeeNo: formModel.employeeNo ?? '',
      jobPosition: formModel.jobPosition ?? '',
      workareaUID: formModel.workareaUID ?? '',
    };

    return data;
  }


  private showConfirmMessage(eventType: SubjectHeaderEventType) {
    const confirmType: 'AcceptCancel' | 'DeleteCancel' =
      eventType === SubjectHeaderEventType.DELETE_SUBJECT ? 'DeleteCancel' : 'AcceptCancel';
    const title = this.getConfirmTitle(eventType);
    const message = this.getConfirmMessage(eventType);

    this.messageBox.confirm(message, title, confirmType)
      .firstValue()
      .then(x => {
        if (x) {
          sendEvent(this.subjectHeaderEvent, eventType, {subject: this.subject});
        }
      });
  }


  private getConfirmTitle(eventType: SubjectHeaderEventType): string {
    switch (eventType) {
      case SubjectHeaderEventType.GENERATE_PASSWORD: return 'Generar contraseña';
      case SubjectHeaderEventType.ACTIVATE_SUBJECT: return 'Desbloquear cuenta';
      case SubjectHeaderEventType.SUSPEND_SUBJECT: return 'Suspender cuenta';
      case SubjectHeaderEventType.DELETE_SUBJECT: return 'Dar de baja la cuenta';
      default: return '';
    }
  }


  private getConfirmMessage(eventType: SubjectHeaderEventType): string {
    switch (eventType) {
      case SubjectHeaderEventType.GENERATE_PASSWORD:
        return `Esta operación generará la contraseña y se enviará al correo:
                <strong> ${this.subject.eMail} </strong>.
                <br><br>¿Genero la contraseña?`;

      case SubjectHeaderEventType.ACTIVATE_SUBJECT:
        return `Esta operación desbloqueará la cuenta:
                <strong> (${this.subject.userID}) ${this.subject.fullName} - ${this.subject.employeeNo} </strong>.
                <br><br>¿Desbloqueo la cuenta?`;

      case SubjectHeaderEventType.SUSPEND_SUBJECT:
        return `Esta operación suspenderá la cuenta:
                <strong> (${this.subject.userID}) ${this.subject.fullName} - ${this.subject.employeeNo} </strong>.
                <br><br>¿Suspendo la cuenta?`;

      case SubjectHeaderEventType.DELETE_SUBJECT:
        return `Esta operación <strong>dará de baja / eliminará</strong> la cuenta
                <strong> (${this.subject.userID}) ${this.subject.fullName} - ${this.subject.employeeNo} </strong>.
                <br><br>¿Doy de baja la cuenta?`;

      default: return '';
    }
  }

}