File

libs/ui/cohort-date-range/src/lib/cohort/cohort-date-range.component.ts

Description

This is the cohort-date-range UI Component

Implements

OnInit OnDestroy

Example

<ts-cohort-date-range
  [allowCustomDates]="true"
  [cohorts]="myCohorts"
  endMaxDate="{{ new Date(2017, 4, 30) }}"
  endMinDate="{{ new Date(2017, 4, 1) }}"
  id="myID"
  startMaxDate="{{ new Date(2017, 4, 30) }}"
  startMinDate="{{ new Date(2017, 4, 1) }}"
  (cohortDateRangeChange)="myFunc($event)"
></ts-cohort-date-range>

<example-url>https://getterminus.github.io/ui-demos-release/components/cohort-date-range</example-url>

Metadata

changeDetection ChangeDetectionStrategy.OnPush
encapsulation ViewEncapsulation.None
exportAs tsCohortDateRange
host {
}
selector ts-cohort-date-range
styleUrls ./cohort-date-range.component.scss
templateUrl ./cohort-date-range.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(formBuilder: FormBuilder)
Parameters :
Name Type Optional
formBuilder FormBuilder No

Inputs

allowCustomDates
Type : boolean

Define whether custom dates are allowed

cohorts

Define the array of date cohorts

dateLocale
Type : string | undefined

Define the date locale

endMaxDate
Type : Date | undefined

Define the max date for the end date

endMinDate
Type : Date | undefined

Define the min date for the end date

id
Type : string

Define an ID for the component

isDisabled
Default value : false

Disable the component

startMaxDate
Type : Date | undefined

Define the max date for the starting date

startMinDate
Type : Date | undefined

Define the min date for the starting date

Outputs

cohortDateRangeChanged
Type : EventEmitter

Cohort change event emitter

Methods

Public formatter
formatter(cohort: TsDateCohort)

The display formatter for TsSelectionListComponent

Parameters :
Name Type Optional Description
cohort TsDateCohort No
  • The cohort
Returns : string

The display value for the cohort

Properties

Protected _id
Type : string
Default value : this.uid
Public formBuilder
Type : FormBuilder
Public Readonly uid
Default value : `ts-cohort-date-range-${nextUniqueId++}`

Define the default component ID

Accessors

allowCustomDates
getallowCustomDates()
setallowCustomDates(value: boolean)

Define whether custom dates are allowed

Parameters :
Name Type Optional
value boolean No
Returns : void
cohorts
getcohorts()
setcohorts(value)

Define the array of date cohorts

Parameters :
Name Optional
value No
Returns : void
id
getid()
setid(value: string)

Define an ID for the component

Parameters :
Name Type Optional
value string No
Returns : void
import {
  ChangeDetectionStrategy,
  Component,
  EventEmitter,
  Input,
  OnDestroy,
  OnInit,
  Output,
  ViewChild,
  ViewEncapsulation,
} from '@angular/core';
import {
  AbstractControl,
  FormBuilder,
  FormControl,
} from '@angular/forms';

import {
  coerceDateProperty,
  untilComponentDestroyed,
} from '@terminus/fe-utilities';
import { TsOption } from '@terminus/ui-option';
import {
  TsSelectionListChange,
  TsSelectionListComponent,
} from '@terminus/ui-selection-list';

/**
 * Represents the range for a {@link TsDateCohort}
 */
export interface TsDateCohortRange {
  start: string | Date;
  end: string | Date;
}

/**
 * Represents the date cohort object that passed in
 */
export interface TsDateCohort extends TsOption {
  active?: boolean;
  display: string;
  range: TsDateCohortRange;
}

/**
 * Cohort date range change event interface
 */
export interface TsCohortDateChangeEvent {
  start: string | Date;
  end: string | Date;
}

/**
 * Event object emitted by {@link TsCohortDateRangeComponent} when there is date range change
 */
export class TsCohortDateRangeChanged {
  constructor(
    public start: string | Date,
    public end: string | Date,
    public source: TsCohortDateRangeComponent,
  ) { }
}

// Unique ID for each instance
let nextUniqueId = 0;

/**
 * This is the cohort-date-range UI Component
 *
 * @example
 * <ts-cohort-date-range
 *              [allowCustomDates]="true"
 *              [cohorts]="myCohorts"
 *              endMaxDate="{{ new Date(2017, 4, 30) }}"
 *              endMinDate="{{ new Date(2017, 4, 1) }}"
 *              id="myID"
 *              startMaxDate="{{ new Date(2017, 4, 30) }}"
 *              startMinDate="{{ new Date(2017, 4, 1) }}"
 *              (cohortDateRangeChange)="myFunc($event)"
 * ></ts-cohort-date-range>
 *
 * <example-url>https://getterminus.github.io/ui-demos-release/components/cohort-date-range</example-url>
 */
@Component({
  selector: 'ts-cohort-date-range',
  templateUrl: './cohort-date-range.component.html',
  styleUrls: ['./cohort-date-range.component.scss'],
  host: {
    'class': 'ts-cohort-date-range',
    '[class.ts-cohort-date-range--disabled]': 'isDisabled',
    '[attr.disabled]': 'isDisabled',
    '[attr.aria-disabled]': 'isDisabled',
    '[id]': 'id',
  },
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  exportAs: 'tsCohortDateRange',
})
export class TsCohortDateRangeComponent implements OnInit, OnDestroy {
  /**
   * Define the custom date cohort
   *
   * @internal
   */
  public customDateCohort: TsDateCohort = {
    display: 'Custom Dates',
    range: {
      start: '',
      end: '',
    },
  };

  /**
   * Initialize the date range with empty start and end date
   *
   * @internal
   */
  public formGroup = this.formBuilder.group({
    dateRange: this.formBuilder.group({
      startDate: [''],
      endDate: [''],
    }),
    cohort: new FormControl([]),
  });

  /**
   * Define the default component ID
   */
  public readonly uid = `ts-cohort-date-range-${nextUniqueId++}`;

  /**
   * Get reference to the date range form group
   *
   * @internal
   */
  public get dateRangeFormGroup(): AbstractControl {
    return this.formGroup.get('dateRange');
  }

  /**
   * Get a reference to the cohort form control
   *
   * @internal
   */
  public get cohortControl(): FormControl {
    return this.formGroup.get('cohort') as FormControl;
  }

  /**
   * Define a reference to the {@link TsSelectionListComponent}
   *
   * @internal
   */
  @ViewChild(TsSelectionListComponent, { static: true })
  public selectionListComponent!: TsSelectionListComponent;

  /**
   * Define whether custom dates are allowed
   *
   * @param value
   */
  @Input()
  public set allowCustomDates(value: boolean) {
    this._allowCustomDates = value;

    // If this flag is being toggled, set the original cohorts again which will add or remove the custom cohort option as needed.
    this.cohorts = this.originalCohorts;
  }
  public get allowCustomDates(): boolean {
    return this._allowCustomDates;
  }
  private _allowCustomDates = true;

  /**
   * Define the array of date cohorts
   *
   * @param value
   */
  @Input()
  public set cohorts(value: ReadonlyArray<TsDateCohort>) {
    if (!value) {
      return;
    }
    this.originalCohorts = value;
    this._cohorts = value.slice();
    if (this.allowCustomDates) {
      this._cohorts.push(this.customDateCohort);
    }
    const activeCohort = value.filter(c => c.active);
    if (activeCohort.length) {
      this.cohortControl.setValue(activeCohort);
      this.setDateRangeValues(activeCohort[0].range);
    }
  }
  public get cohorts(): ReadonlyArray<TsDateCohort> {
    return this._cohorts;
  }
  private _cohorts!: TsDateCohort[];
  private originalCohorts!: ReadonlyArray<TsDateCohort>;

  /**
   * Define the date locale
   */
  @Input()
  public dateLocale: string | undefined;

  /**
   * Define the max date for the end date
   */
  @Input()
  public endMaxDate: Date | undefined;

  /**
   * Define the min date for the end date
   */
  @Input()
  public endMinDate: Date | undefined;

  /**
   * Define an ID for the component
   *
   * @param value
   */
  @Input()
  public set id(value: string) {
    this._id = value || this.uid;
  }
  public get id(): string {
    return this._id;
  }
  protected _id: string = this.uid;

  /**
   * Disable the component
   */
  @Input()
  public isDisabled = false;

  /**
   * Define the max date for the starting date
   */
  @Input()
  public startMaxDate: Date | undefined;

  /**
   * Define the min date for the starting date
   */
  @Input()
  public startMinDate: Date | undefined;

  /**
   * Cohort change event emitter
   */
  @Output()
  public readonly cohortDateRangeChanged = new EventEmitter<TsCohortDateRangeChanged>();

  constructor(public formBuilder: FormBuilder) {}

  public ngOnInit(): void {
    this.updateSelectOnRangeChange();
  }

  /**
   * Needed for untilComponentDestroyed
   */
  public ngOnDestroy(): void {}

  /**
   * Emit the change event
   *
   * @internal
   * @param event - triggered by date range change
   */
  public cohortDateRangeChange(event: TsCohortDateChangeEvent): void {
    this.cohortDateRangeChanged.emit(new TsCohortDateRangeChanged(event.start, event.end, this));
  }

  /**
   * Called when selection changed
   *
   * @internal
   * @param event - TsSelectChangeEvent
   */
  public selectionChange(event: TsSelectionListChange<TsDateCohort>): void {
    this.setDateRangeValues(event.value[0].range);
  }

  /**
   * Function for tracking for-loops changes
   *
   * @internal
   * @param index - The item index
   * @returns The index
   */
  public trackByFn(index): number {
    return index;
  }

  /**
   * The display formatter for {@link TsSelectionListComponent}
   *
   * @param cohort - The cohort
   * @returns The display value for the cohort
   */
  public formatter(cohort: TsDateCohort): string {
    return cohort.display;
  }

  /**
   * Update the date range form values
   *
   * @param range - The new range
   */
  private setDateRangeValues(range: TsDateCohortRange): void {
    const newValues = {
      startDate: range.start,
      endDate: range.end,
    };

    // istanbul ignore else
    if (newValues.startDate && newValues.endDate) {
      this.dateRangeFormGroup.setValue(newValues);
      this.cohortDateRangeChange(range);
    }
  }

  /**
   * Update the select when the date is manually changed to not match a cohort
   */
  private updateSelectOnRangeChange(): void {
    // eslint-disable-next-line deprecation/deprecation
    this.formGroup.get('dateRange')?.valueChanges.pipe(untilComponentDestroyed(this)).subscribe(results => {
      if (!this.cohorts || !this.cohorts.length) {
        return;
      }
      const resultsStartTime = coerceDateProperty(results.startDate).getTime();
      const resultsEndTime = coerceDateProperty(results.endDate).getTime();

      const matchedCohorts = this.cohorts.filter(cohort => {
        const cohortStartTime = coerceDateProperty(cohort.range.start).getTime();
        const cohortEndTime = coerceDateProperty(cohort.range.end).getTime();
        const cohortStartMatches = resultsStartTime === cohortStartTime;
        const cohortEndMatches = resultsEndTime === cohortEndTime;

        // istanbul ignore else
        if (cohortStartMatches && cohortEndMatches) {
          return cohort;
        }
      });

      // istanbul ignore else
      if (matchedCohorts.length === 0) {
        this.cohortControl.setValue([this.customDateCohort]);
      }
    });
  }
}

result-matching ""

    No results matching ""