rvalenciano/ngx-cron-jobs

View on GitHub
src/app/lib/cron-jobs/cron-jobs.component.ts

Summary

Maintainability
A
1 hr
Test Coverage
import {
  Component, forwardRef, Injector, Input, OnChanges, OnDestroy, OnInit,
  SimpleChanges
} from '@angular/core';
import {
  CronJobsConfig, CronJobsFrequency, CronJobsSelectOption,
  CronJobsValidationConfig
} from '../contracts/contracts';
import { DataService } from '../services/data.service';
import { ControlValueAccessor, FormBuilder, FormControl, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/takeUntil';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/publishReplay';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/do';
import { PosixService } from '../services/posix.service';
import { QuartzService } from '../services/quartz.service';

@Component({
  selector: 'cron-jobs',
  templateUrl: './cron-jobs.component.html',
  styleUrls: ['./cron-jobs.component.css'],
  providers: [
    PosixService,
    QuartzService,
    DataService,
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CronJobsComponent),
      multi: true
    }
  ]
})
export class CronJobsComponent implements OnInit, OnChanges, OnDestroy, ControlValueAccessor {
  @Input() config: CronJobsConfig;
  @Input() validate: CronJobsValidationConfig;
  @Input() isValid = true;
  @Input() formControl: FormControl;

  public isDisabled = false;
  public baseFrequencyData: Array<CronJobsSelectOption>;
  public baseFrequency$: Observable<number>;
  public daysOfWeekData: Array<CronJobsSelectOption> = [];
  public daysOfMonthData: Array<CronJobsSelectOption> = [];
  public monthsData: Array<CronJobsSelectOption> = [];
  public hoursData: Array<CronJobsSelectOption> = [];
  public minutesData: Array<CronJobsSelectOption> = [];
  public onChange: (cronValue: string) => {};
  public onTouched: () => {};
  public cronJobsForm: FormGroup;

  private isPatching = false;
  private unSubscribe = new Subject();
  private cronService: PosixService;

  constructor(private dataService: DataService,
              private injector: Injector,
              private formBuilder: FormBuilder) {

    this.cronJobsForm = this.formBuilder.group({
      baseFrequency: 0,
      daysOfWeek: '',
      daysOfMonth: '',
      months: '',
      hours: '',
      minutes: ''
    });

    this.config = this.dataService.getConfig();
    this.validate = this.dataService.getValidate();
    this.setService();
  }

  ngOnInit() {
    this.baseFrequency$ = this.cronJobsForm.get('baseFrequency')
      .valueChanges
      .takeUntil(this.unSubscribe)
      .map(v => +v)
      .publishReplay(1)
      .refCount();

    this.cronJobsForm
      .valueChanges
      .takeUntil(this.unSubscribe)
      .filter(() => !this.isPatching)
      .map((freq: CronJobsFrequency) => {
        freq.baseFrequency = +freq.baseFrequency;
        return freq;
      })
      .subscribe((values: CronJobsFrequency) => {
        if (!values.baseFrequency) {
          values = this.cronService.getDefaultFrequenceWithDefault();
          this.cronJobsForm.patchValue(values, {emitEvent: false});
        }
        this.onChange(this.cronService.setCron(values));
      });

    let baseFreq = this.dataService.baseFrequency;

    if (this.config.option) {
      baseFreq = baseFreq.filter(x => !(this.config.option.hasOwnProperty(x.label.toString().toLowerCase()) && !this.config.option[x.label])
      );
    }

    this.baseFrequencyData = baseFreq;
    this.daysOfMonthData = this.dataService.daysOfMonth;
    this.daysOfWeekData = this.dataService.getDaysOfWeek(false);
    this.monthsData = this.dataService.months;
    this.hoursData = this.dataService.hours;
    this.minutesData = this.dataService.minutes;

    this.isPatching = true;
    setTimeout(() => {
      this.cronJobsForm.patchValue(this.cronService.getDefaultFrequenceWithDefault());
      this.isPatching = false;
    });
  }

  onBlur() {
    this.onTouched();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['config']) {
      this.config = this.dataService.getConfig(<CronJobsConfig>changes['config'].currentValue);
      setTimeout(() => {
        if (!changes['config'].previousValue ||
          changes['config'].previousValue['quartz'] !== changes['config'].currentValue['quartz']) {
          this.daysOfWeekData = this.dataService.getDaysOfWeek(this.config.quartz);
          this.cronJobsForm.patchValue({daysOfWeek: this.daysOfWeekData[0].value});
        }
      });
      this.setService();
    }

    if (changes['validate']) {
      this.validate = this.dataService.getValidate(<CronJobsValidationConfig>changes['validate'].currentValue);
    }
  }

  setService() {
    if (this.config.quartz) {
      this.cronService = this.injector.get(QuartzService);
    } else {
      this.cronService = this.injector.get(PosixService);
    }
  }

  writeValue(cronValue: string): void {
    this.isPatching = true;
    let valueToPatch: CronJobsFrequency;
    if (cronValue) {
      valueToPatch = this.cronService.fromCronWithDefault(cronValue);
    } else {
      valueToPatch = this.cronService.getDefaultFrequenceWithDefault();
    }

    setTimeout(() => {
      this.cronJobsForm.patchValue(valueToPatch);
      this.isPatching = false;
    });
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
    if (this.isDisabled) {
      this.cronJobsForm.disable();
    } else {
      this.cronJobsForm.enable();
    }
  }

  getIsValid(): boolean {
    return this.validate.validate ? this.getValid() : false;
  }

  getIsInvalid(): boolean {
    return this.validate.validate ? !this.getValid() : false;
  }

  getValid(): boolean {
    return this.formControl ? this.formControl.valid : this.isValid;
  }

  ngOnDestroy() {
    this.unSubscribe.next();
    this.unSubscribe.complete();
  }

}