moh-common-lib
Version:
A library of Angular components, services, and styles for B.C. Government Ministry of Health (MoH).
1,183 lines (1,171 loc) • 436 kB
JavaScript
import { CommonModule } from '@angular/common';
import * as zxcvbn_ from 'zxcvbn';
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
import getDaysInMonth from 'date-fns/getDaysInMonth';
import isAfter from 'date-fns/isAfter';
import isBefore from 'date-fns/isBefore';
import startOfToday from 'date-fns/startOfToday';
import addYears from 'date-fns/addYears';
import subYears from 'date-fns/subYears';
import { NgxMyDatePickerModule } from 'ngx-mydatepicker';
import * as PDFJS_ from 'pdfjs-dist/legacy/build/pdf';
import { pdfJsWorker } from 'pdfjs-dist/legacy/build/pdf.worker.entry';
import { TextMaskModule } from 'angular2-text-mask';
import { NgSelectModule } from '@ng-select/ng-select';
import { UUID } from 'angular2-uuid';
import * as moment_ from 'moment';
import { AccordionModule } from 'ngx-bootstrap/accordion';
import { compareAsc, startOfDay, addDays, format, startOfToday as startOfToday$1, differenceInYears } from 'date-fns';
import { ModalModule } from 'ngx-bootstrap/modal';
import { filter, map, catchError, tap, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { throwError, Subject, of, BehaviorSubject } from 'rxjs';
import { ControlContainer, NgForm, NgControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { __extends, __awaiter, __generator, __spread, __values } from 'tslib';
import { Router, NavigationEnd, RouterModule } from '@angular/router';
import { Component, Input, Output, EventEmitter, forwardRef, ViewEncapsulation, HostListener, ViewChild, ViewChildren, ChangeDetectionStrategy, ChangeDetectorRef, Optional, Self, Inject, NgZone, ViewContainerRef, Injectable, Directive, NgModule, InjectionToken, Injector, defineInjectable, inject, INJECTOR } from '@angular/core';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
*
* The base styles for a breadcrumb with slots for content to go. If you need a
* complex breadcrumb, the idea is you can extend this CoreBreadcrumb and use
* the base styles. There are 3 slots: left, center, and right - all are
* optional and any configuration works. You select the slot by adding it as an
* attribute to the top level elements inside of the breadcrumb element.
*
* Example usage:
*
* <common-core-breadcrumb>
* <div left>
* <a routerLink="/provisioner/">Dashboard</a> /
* <strong>Provision by {{ IS_SHOWING_PERSON ? "User" : "Site" }}</strong>
* </div>
* <div center></div>
* <div right></div>
* </common-core-breadcrumb>
*
* @export
*/
var CoreBreadcrumbComponent = /** @class */ (function () {
function CoreBreadcrumbComponent() {
}
CoreBreadcrumbComponent.decorators = [
{ type: Component, args: [{
selector: 'common-core-breadcrumb',
template: "<nav class=\"breadcrumb d-flex justify-content-between horizontal-scroll\" aria-label=\"breadcrumb\">\r\n <ng-content select=\"[left]\"></ng-content>\r\n <ng-content class='d-flex' select=\"[center]\"></ng-content>\r\n <ng-content select=\"[right]\"></ng-content>\r\n</nav>\r\n",
styles: [".breadcrumb{display:flex;justify-content:space-between;background-color:transparent}@media (min-width:992px){.breadcrumb{flex-wrap:nowrap}}.horizontal-scroll{overflow-x:scroll;overflow-y:hidden}.horizontal-scroll::-webkit-scrollbar{background:0 0;height:5px}.horizontal-scroll::-webkit-scrollbar-thumb{background:#5475a7;border-radius:10px}"]
}] }
];
/** @nocollapse */
CoreBreadcrumbComponent.ctorParameters = function () { return []; };
return CoreBreadcrumbComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?=} top
* @return {?}
*/
function scrollTo(top) {
if (top === void 0) { top = 0; }
/** @type {?} */
var supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style;
if (supportsNativeSmoothScroll) {
window.scrollTo({ top: top, behavior: 'smooth' });
}
else {
/**
* IE does not support ScrollToOptions (behavior, top, left), but does support
* scrollTo() with parameters for x and y coorindiates.
*/
window.scrollTo(0, top);
}
}
/**
* Get the first visible common-error-container and smoothly scroll to it.
* @param {?=} yOffset
* @return {?}
*/
function scrollToError(yOffset) {
if (yOffset === void 0) { yOffset = -75; }
/** @type {?} */
var el = document.querySelector('common-error-container .text-danger');
if (el) {
/** @type {?} */
var top_1 = el.getBoundingClientRect().top + window.pageYOffset + yOffset;
scrollTo(top_1);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var FormActionBarComponent = /** @class */ (function () {
function FormActionBarComponent() {
this.submitLabel = 'Continue';
this.canContinue = true;
this.isLoading = false;
this.defaultColor = true;
this.btnClick = new EventEmitter();
this.scrollToErrorsOnSubmit = true;
}
/**
* @return {?}
*/
FormActionBarComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
};
/**
* @param {?} $event
* @return {?}
*/
FormActionBarComponent.prototype.onClick = /**
* @param {?} $event
* @return {?}
*/
function ($event) {
if (!this.isLoading && this.canContinue) {
this.btnClick.emit($event);
if (this.scrollToErrorsOnSubmit) {
// Scroll to error after 50ms, give time for errors to display etc.
// This timeout is outside of Angular change detection.
setTimeout(scrollToError, 50);
}
}
$event.stopPropagation();
return false;
};
FormActionBarComponent.decorators = [
{ type: Component, args: [{
selector: 'common-form-action-bar',
template: "<div class=\"form-action-bar form-bar\" [ngClass]=\"{disabled: !canContinue}\">\r\n <button class=\"btn btn-lg {{defaultColor ? 'btn-primary' : 'btn-secondary' }} submit\"\r\n (click)=\"onClick($event)\"\r\n [ngClass]=\"{disabled: !canContinue || isLoading}\">\r\n <ng-container *ngIf=\"!isLoading; else loadingSpinner\"> {{submitLabel}} </ng-container>\r\n \r\n </button>\r\n</div>\r\n\r\n<ng-template #loadingSpinner>\r\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\r\n</ng-template>",
// TODO: Figure out why this is required.
viewProviders: [{ provide: ControlContainer, useExisting: forwardRef((/**
* @return {?}
*/
function () { return NgForm; })) }],
styles: [".form-action-bar{display:flex;justify-content:flex-end;padding:1em;background-color:#cdd9e4;transition:background-color .3s;position:-webkit-sticky;position:-moz-sticky;position:-ms-sticky;position:-o-sticky;position:sticky;bottom:0;z-index:10;left:5rem;right:5rem}.form-action-bar.disabled{background-color:#d5d9dd}@media (max-width:991.98px){.form-action-bar{left:2.5rem;right:2.5rem}}.submit{min-width:240px}@media (max-width:767.98px){.form-action-bar{width:calc(100% + 30px);margin-left:-15px}.submit{min-width:100%}}.btn{white-space:normal!important;word-wrap:break-word}.btn-secondary.disabled{color:#000}"]
}] }
];
/** @nocollapse */
FormActionBarComponent.ctorParameters = function () { return []; };
FormActionBarComponent.propDecorators = {
submitLabel: [{ type: Input }],
canContinue: [{ type: Input }],
isLoading: [{ type: Input }],
defaultColor: [{ type: Input }],
btnClick: [{ type: Output }],
scrollToErrorsOnSubmit: [{ type: Input }]
};
return FormActionBarComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The "Page Framework" is a template to be used on FPCare pages to ensure
* consistent layout. It should be used on every page unless there is a good
* exception.
*
* Note: CommonFormActionBar (and SubmitBar) must come *AFTER* this element, not
* inside in version 2.0.0 and above.
*
* \@example
* <common-page-framework>
* <div>This will go in the middle column</div>
* <p>So will this</p>
* <div aside> This will go in the side column, or tips.</div>
* </common-page-framework>
* <common-form-action-bar></common-form-action-bar>
*
* @export
*/
var PageFrameworkComponent = /** @class */ (function () {
function PageFrameworkComponent() {
this.layout = 'default';
}
/**
* @return {?}
*/
PageFrameworkComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
};
PageFrameworkComponent.decorators = [
{ type: Component, args: [{
selector: 'common-page-framework',
template: "<div class=\"row\" [ngSwitch]=\"layout\">\r\n\r\n <ng-container *ngSwitchCase=\"'default'\">\r\n <div class=\"col-md-8\">\r\n <div class=\"px-lg-4 px-md-3 py-3\">\r\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\r\n </div>\r\n </div>\r\n <div class=\"col-md-4 aside-col\">\r\n <div class='pr-lg-5 pr-md-4 py-2'>\r\n <ng-container *ngTemplateOutlet=\"aside\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n\r\n <ng-container *ngSwitchCase=\"'double'\">\r\n <div class=\"col-md-6\">\r\n <div class=\"px-lg-5 px-md-3 py-3\">\r\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <div class='px-lg-5 px-md-3 py-3'>\r\n <ng-container *ngTemplateOutlet=\"aside\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'single'\">\r\n <div class=\"col-md-8 offset-lg-2\">\r\n <div class=\"px-lg-5 px-md-3 py-3\">\r\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'blank'\">\r\n <div class=\"col-sm-12\">\r\n <div class=\"px-lg-5 px-md-3 py-3\">\r\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-container>\r\n</div>\r\n<ng-container *ngTemplateOutlet=\"submit\"></ng-container>\r\n\r\n\r\n<!-- We use ng-template here to get around a bug with having multiple ng-contents in one template. By default, if there are duplicate ng-contents in a template Angular will select the very first one - even if latter ones are 'removed' by ngSwitch or ngIf.-->\r\n<ng-template #content>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n<ng-template #aside>\r\n <ng-content select='aside'></ng-content>\r\n</ng-template>\r\n\r\n<ng-template #submit>\r\n <ng-content select='common-form-action-bar'></ng-content>\r\n <ng-content select='common-form-submit-bar'></ng-content>\r\n</ng-template>\r\n",
encapsulation: ViewEncapsulation.None,
styles: ["common-page-framework{background:#fcfcfc;display:block;padding-left:30px;padding-right:30px;min-height:calc(100vh - 280px)}common-page-framework common-form-action-bar>.form-bar,common-page-framework common-form-submit-bar>.form-bar{background-color:red!important}common-page-framework common-form-action-bar .btn,common-page-framework common-form-submit-bar .btn{font-size:0}common-page-framework common-form-action-bar .btn:after,common-page-framework common-form-submit-bar .btn:after{font-size:1rem;content:\"FORM BAR MUST BE PLACED OUTSIDE OF COMMON-PAGE-FRAMEWORK\"}.h5,h5{font-size:1rem;font-weight:700;margin-bottom:0}p+.h5,p+h5{margin-top:1.5rem}.aside-col aside{background:#f2f2f2;padding:1em;border-radius:5px}@media (min-width:768px){.aside-col aside{margin-top:1rem}}"]
}] }
];
PageFrameworkComponent.propDecorators = {
layout: [{ type: Input }]
};
return PageFrameworkComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Base class. Components extend this class to have object IDs.
* NPM package dependencies:
* a) moment
*/
var /**
* Base class. Components extend this class to have object IDs.
* NPM package dependencies:
* a) moment
*/
Base = /** @class */ (function () {
function Base() {
/**
* An identifier for parents to keep track of components
*/
this.objectId = UUID.UUID();
}
return Base;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// Awkward necessary workaround due to bug in build tools
// https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207
/** @type {?} */
var zxcvbn = zxcvbn_;
/**
* PasswordComponent is a text input for a user's password. It includes:
*
* - A password strength bar
* - Minimum length validations
*
* Note - if your application has requirements to check things like username is not
* present in password, we recommend doing this in the (passwordChange) callback.
*
* \@example
* <common-password componentLabel="{{newPwdLabel}}"
* [showPasswordStrength]="true"
* [minLen]="pwdMinLen"
* [pwdCriteria]="pwdValidChars"
* [password]="data.password"
* (passwordChange)="setNewPassword($event)"></common-password>
*
* @export
*/
var PasswordComponent = /** @class */ (function (_super) {
__extends(PasswordComponent, _super);
function PasswordComponent() {
var _this = _super.call(this) || this;
// Inputs for the component
_this.label = 'Password';
_this.isRequired = true;
_this.isDisabled = false;
_this.minLen = '8';
_this.maxLen = '32';
_this.showPasswordStrength = false;
_this.objectID = 'password_' + _this.objectId;
// Output from the component
_this.passwordChange = new EventEmitter();
_this.blurEvent = new EventEmitter();
// Flag for the fa-eye to show or hide password
_this.hideValue = true;
_this.strengthPercentage = 0;
// default messages
_this.requiredMsgSeg = ' is required.';
_this.minLenMsgSeg1 = ' must be at least ';
_this.minLenMsgSeg2 = ' characters in length.';
_this.criteriaMsg = ' contains invalid characters.';
return _this;
}
/**
* @return {?}
*/
PasswordComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
// Set default messages
this.errMsg = {
required: this.label + this.requiredMsgSeg,
minLength: this.label + this.minLenMsgSeg1 + this.minLen + this.minLenMsgSeg2,
criteria: this.label + this.criteriaMsg
};
// Replace default message if provided
if (this.errorMessages) {
if (this.errorMessages.required) {
this.errMsg.required = this.errorMessages.required;
}
if (this.errorMessages.minLength) {
this.errMsg.minLength = this.errorMessages.minLength;
}
if (this.errorMessages.criteria) {
this.errMsg.criteria = this.errorMessages.criteria;
}
}
};
/**
* @param {?} changes
* @return {?}
*/
PasswordComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes.password && this.password) {
// Check strength of password
this.pswdStrength = this.getPasswordStrength(this.password);
this.strengthPercentage = ((this.pswdStrength + 1) / 5) * 100;
}
};
/**
* Passes the value entered back to the calling component
* @param password value the was entered by
*/
/**
* Passes the value entered back to the calling component
* @param {?} password value the was entered by
* @return {?}
*/
PasswordComponent.prototype.setPassword = /**
* Passes the value entered back to the calling component
* @param {?} password value the was entered by
* @return {?}
*/
function (password) {
this.passwordChange.emit(password);
};
/**
* @param {?} $event
* @return {?}
*/
PasswordComponent.prototype.onInputBlur = /**
* @param {?} $event
* @return {?}
*/
function ($event) {
this.blurEvent.emit(event);
};
// Prevent user from pasting data into the text box
// Prevent user from pasting data into the text box
/**
* @param {?} event
* @return {?}
*/
PasswordComponent.prototype.onPaste =
// Prevent user from pasting data into the text box
/**
* @param {?} event
* @return {?}
*/
function (event) {
return false;
};
/**
* Get the strength of the password
* 0 = too guessable: risky password. (guesses < 10^3)
* 1 = very guessable: protection from throttled online attacks. (guesses < 10^6)
* 2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
* 3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
* 4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
*
* https://github.com/dropbox/zxcvbn
*/
/**
* Get the strength of the password
* 0 = too guessable: risky password. (guesses < 10^3)
* 1 = very guessable: protection from throttled online attacks. (guesses < 10^6)
* 2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
* 3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
* 4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
*
* https://github.com/dropbox/zxcvbn
* @private
* @param {?} password
* @return {?}
*/
PasswordComponent.prototype.getPasswordStrength = /**
* Get the strength of the password
* 0 = too guessable: risky password. (guesses < 10^3)
* 1 = very guessable: protection from throttled online attacks. (guesses < 10^6)
* 2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
* 3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
* 4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
*
* https://github.com/dropbox/zxcvbn
* @private
* @param {?} password
* @return {?}
*/
function (password) {
// Password strength feedback
/** @type {?} */
var pswdFeedback = zxcvbn(password);
return pswdFeedback.score;
};
PasswordComponent.decorators = [
{ type: Component, args: [{
selector: 'common-password',
template: "<label class=\"control-label\" for=\"{{objectID}}\">{{label}}</label>\r\n<input #pswdRef=\"ngModel\"\r\n type=\"{{hideValue? 'password': 'text'}}\"\r\n class=\"form-control password-field\"\r\n name=\"{{objectID}}\"\r\n id=\"{{objectID}}\"\r\n [ngModel]=\"password\"\r\n (ngModelChange)=\"setPassword($event)\"\r\n (blur)=\"onInputBlur($event)\"\r\n [pattern]=\"pwdCriteria\"\r\n [required]=\"isRequired\"\r\n [minlength]=\"minLen\"\r\n [maxlength]=\"maxLen\"\r\n [disabled]=\"isDisabled\"\r\n autocomplete=\"off\"/>\r\n<span class=\"fa fa-fw {{hideValue? 'fa-eye' : 'fa-eye-slash'}} password-field-icon\"\r\n (click)='hideValue = !hideValue'></span>\r\n<div *ngIf='password && showPasswordStrength'>\r\n<!-- The progress bar -->\r\n <div class=\"progress password-strength-bar\" >\r\n <div class=\"progress-bar {{pswdStrength >= 4? 'bg-success' : (pswdStrength >= 3? 'bg-warning' : 'bg-danger')}}\"\r\n role=\"progressbar\"\r\n [style.width]='strengthPercentage + \"%\"'\r\n [attr.aria-valuenow]=\"strengthPercentage\"\r\n aria-valuemin=\"0\"\r\n aria-valuemax=\"100\">\r\n </div>\r\n </div>\r\n <span class=\"password-progress-label {{pswdStrength >= 4? 'text-success' : (pswdStrength >= 3? 'text-warning' : 'text-danger')}}\"></span>\r\n</div>\r\n<!-- Error messages for component -->\r\n<div *ngIf=\"!pswdRef.disabled && (pswdRef.touched || pswdRef.dirty)\"\r\n role=\"alert\"\r\n class='error-container'\r\n aria-live=\"assertive\">\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.required\">\r\n {{errMsg.required}}\r\n </div>\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.minlength\">\r\n {{errMsg.minLength}}\r\n </div>\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.pattern && !pswdRef?.errors?.minlength\">\r\n {{errMsg.criteria}}\r\n </div>\r\n</div>\r\n\r\n",
/* Re-use the same ngForm that it's parent is using. The component will show
* up in its parents `this.form`, and will auto-update `this.form.valid`
*/
viewProviders: [{ provide: ControlContainer, useExisting: forwardRef((/**
* @return {?}
*/
function () { return NgForm; })) }],
styles: [".password-field-icon{float:right;margin-left:-25px;margin-top:-25px;margin-right:.5rem;position:relative;z-index:2}.password-field{padding-right:2rem}.password-strength-bar{min-width:0;max-width:75%;height:.5rem;margin-top:1em}.password-progress-label{float:right;margin-left:-15px;margin-top:-15px;position:relative;z-index:2}.password-strength-bar+.text-success::after{content:'Good'}.password-strength-bar+.text-warning::after{content:'OK'}.password-strength-bar+.text-danger::after{content:'Bad'}input{width:100%}input[type=password]::-ms-clear,input[type=password]::-ms-reveal{display:none}"]
}] }
];
/** @nocollapse */
PasswordComponent.ctorParameters = function () { return []; };
PasswordComponent.propDecorators = {
label: [{ type: Input }],
isRequired: [{ type: Input }],
isDisabled: [{ type: Input }],
password: [{ type: Input }],
pwdCriteria: [{ type: Input }],
minLen: [{ type: Input }],
maxLen: [{ type: Input }],
errorMessages: [{ type: Input }],
showPasswordStrength: [{ type: Input }],
objectID: [{ type: Input }],
passwordChange: [{ type: Output }],
blurEvent: [{ type: Output }],
onPaste: [{ type: HostListener, args: ['document:paste', ['$event'],] }]
};
return PasswordComponent;
}(Base));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* NPM Dependencies:
* a) rxjs
* b) ngx-bootstrap
*/
var WizardProgressBarComponent = /** @class */ (function () {
function WizardProgressBarComponent(router, cd) {
this.router = router;
this.cd = cd;
this.progressSteps = [];
}
/**
* @return {?}
*/
WizardProgressBarComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
// Update the progress bar view on route change and _only_ route chaange.
// Skip most of Angular's ChangeDetection in favour of manually optimizing.
this.routerEvents$ = this.router.events.pipe(filter((/**
* @param {?} ev
* @return {?}
*/
function (ev) { return ev instanceof NavigationEnd; })), map((/**
* @param {?} ev
* @return {?}
*/
function (ev) { return ev.url; }))).subscribe((/**
* @param {?} url
* @return {?}
*/
function (url) {
_this.activeIndex = _this.getActiveIndex(url);
_this.cd.detectChanges();
_this.scrollStepIntoView();
}));
// Must schedule first run manually, or bar won't be set.
this.activeIndex = this.getActiveIndex(this.router.url);
};
/**
* @return {?}
*/
WizardProgressBarComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.cd.detach();
this.routerEvents$.unsubscribe();
};
/**
* @return {?}
*/
WizardProgressBarComponent.prototype.calculateProgressPercentage = /**
* @return {?}
*/
function () {
/** @type {?} */
var denominator = this.progressSteps.length;
/** @type {?} */
var numerator = this.activeIndex + 1;
if (denominator === 0 || numerator > denominator) {
return 100;
}
// Because we've switched from space-evenly to space-around (for IE), we
// have to handle the half-space that space-around adds to the start/end of
// the container
/** @type {?} */
var halfSpace = 1 / (denominator * 2);
return Math.round(((numerator / denominator) - halfSpace) * 100);
};
/**
* @param {?} url
* @return {?}
*/
WizardProgressBarComponent.prototype.getActiveIndex = /**
* @param {?} url
* @return {?}
*/
function (url) {
return this.progressSteps.findIndex((/**
* @param {?} x
* @return {?}
*/
function (x) { return url.endsWith(x.route); }));
};
/**
* Primarily for mobile, this horizontally scrolls the step into view.
*
* Note - be very careful with any changes to this function because it steps
* outside of Angular to call native browser functions.
*/
/**
* Primarily for mobile, this horizontally scrolls the step into view.
*
* Note - be very careful with any changes to this function because it steps
* outside of Angular to call native browser functions.
* @private
* @return {?}
*/
WizardProgressBarComponent.prototype.scrollStepIntoView = /**
* Primarily for mobile, this horizontally scrolls the step into view.
*
* Note - be very careful with any changes to this function because it steps
* outside of Angular to call native browser functions.
* @private
* @return {?}
*/
function () {
/** @type {?} */
var target = this.steps.toArray()[this.activeIndex];
/** @type {?} */
var container = document.getElementsByClassName('horizontal-scroll');
if (container.length === 1) {
// Since we're already breaking out of Angular, we try and be safe by using a try/catch.
// Otherwise an error here could halt execution,
try {
container[0].scrollLeft = Math.abs(target.nativeElement.offsetLeft - (window.outerWidth / 2));
}
catch (error) { }
}
};
WizardProgressBarComponent.decorators = [
{ type: Component, args: [{
selector: 'common-wizard-progress-bar',
template: "<progressbar\r\n [value]=\"calculateProgressPercentage()\"\r\n [max]=\"100\"\r\n [animate]=\"true\">\r\n</progressbar>\r\n\r\n<div class=\"step-container\" #stepContainer>\r\n\r\n <a #steps *ngFor=\"let step of progressSteps; let i = index;\" [routerLink]=\"step.route\">\r\n\r\n <div class=\"step\" [ngClass]=\"{active: i === activeIndex}\">\r\n <span class=\"step-text\">{{step.title}}</span>\r\n </div>\r\n\r\n </a>\r\n\r\n</div>\r\n",
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [":host{flex:1;padding:1em 2em;min-height:2em;min-width:650px}.step-container{display:flex;justify-content:space-around}progressbar{background-color:#adb5bd;height:.5rem}.step{position:relative;-webkit-transform:translateX(-.5em);transform:translateX(-.5em);margin-top:.25rem}.step:before{content:\" \";position:absolute;width:1em;height:1em;border-radius:100%;background:#fff;border:3px solid #036;right:0;left:0;margin:0 auto;bottom:100%}.step:not(.active) .step-text{opacity:.8}.step:not(.active):before{background:#ced4da}.step .step-text{position:absolute;-webkit-transform:translateX(-33%);transform:translateX(-33%);white-space:nowrap;font-size:small;color:#164d80}"]
}] }
];
/** @nocollapse */
WizardProgressBarComponent.ctorParameters = function () { return [
{ type: Router },
{ type: ChangeDetectorRef }
]; };
WizardProgressBarComponent.propDecorators = {
progressSteps: [{ type: Input }],
stepContainer: [{ type: ViewChild, args: ['stepContainer',] }],
steps: [{ type: ViewChildren, args: ['steps',] }]
};
return WizardProgressBarComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* In most cases this will be the part of the error message that will appear after the field label.
*
* {{label}} is required.
*
* Date component will subsitute '{label}' for the label in the component.
* Ex. { required: '{label} is required.' }
*
* Note: '{label}' is exported in constant 'LabelReplacementTag'.
* @type {?}
*/
var LabelReplacementTag = '{label}';
// To catch all occurances of the label tag in the message
/** @type {?} */
var regExpLabel = new RegExp(LabelReplacementTag, 'g');
// Function only used with library
/**
* @param {?} str
* @param {?} value
* @return {?}
*/
function replaceLabelTag(str, value) {
return str.replace(regExpLabel, value);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var MoHCommonLibraryError = /** @class */ (function (_super) {
__extends(MoHCommonLibraryError, _super);
function MoHCommonLibraryError(message) {
var _newTarget = this.constructor;
var _this = _super.call(this, message) || this;
Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain
return _this;
}
return MoHCommonLibraryError;
}(Error));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// Class does not get exported - used internally
/**
* @abstract
*/
var AbstractFormControl = /** @class */ (function (_super) {
__extends(AbstractFormControl, _super);
function AbstractFormControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
// Default messages - must be defined in each component
_this._defaultErrMsg = {};
_this.disabled = false;
// Required for implementing ControlValueAccessor
_this._onChange = (/**
* @param {?} _
* @return {?}
*/
function (_) { });
_this._onTouched = (/**
* @param {?=} _
* @return {?}
*/
function (_) { });
return _this;
}
/**
* @return {?}
*/
AbstractFormControl.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.setErrorMsg();
};
// Register change function
// Register change function
/**
* @param {?} fn
* @return {?}
*/
AbstractFormControl.prototype.registerOnChange =
// Register change function
/**
* @param {?} fn
* @return {?}
*/
function (fn) {
this._onChange = fn;
};
// Register touched function
// Register touched function
/**
* @param {?} fn
* @return {?}
*/
AbstractFormControl.prototype.registerOnTouched =
// Register touched function
/**
* @param {?} fn
* @return {?}
*/
function (fn) {
this._onTouched = fn;
};
// Disable control
// Disable control
/**
* @param {?} isDisabled
* @return {?}
*/
AbstractFormControl.prototype.setDisabledState =
// Disable control
/**
* @param {?} isDisabled
* @return {?}
*/
function (isDisabled) {
this.disabled = isDisabled;
};
/**
* @protected
* @return {?}
*/
AbstractFormControl.prototype.setErrorMsg = /**
* @protected
* @return {?}
*/
function () {
var _this = this;
this.validateLabel();
// Some components have logic based off no label being submitted - strip off '(optional)'
/** @type {?} */
var _label = this.label ? this.label.replace(/\s*\(.*?\)\s*/g, '') : 'Field';
if (this.errorMessage) {
Object.keys(this.errorMessage).map((/**
* @param {?} x
* @return {?}
*/
function (x) { return _this._defaultErrMsg[x] = _this.errorMessage[x]; }));
}
// Replace label tags with label
Object.keys(this._defaultErrMsg).map((/**
* @param {?} x
* @return {?}
*/
function (x) { return _this._defaultErrMsg[x] = replaceLabelTag(_this._defaultErrMsg[x], _label); }));
};
/**
* Register self validating method
* @param control control directive
* @param fn function for validating self
*/
/**
* Register self validating method
* @protected
* @param {?} ngControl
* @param {?} fn function for validating self
* @return {?}
*/
AbstractFormControl.prototype.registerValidation = /**
* Register self validating method
* @protected
* @param {?} ngControl
* @param {?} fn function for validating self
* @return {?}
*/
function (ngControl, fn) {
// Register validateSelf validator so that it will be added on component initialization.
// Makes the component a self validating component.
var _this = this;
return Promise.resolve().then((/**
* @return {?}
*/
function () {
if (ngControl) {
/** @type {?} */
var allValidators = [fn.bind(_this)];
if (ngControl.control.validator) {
allValidators.push(ngControl.control.validator);
}
ngControl.control.setValidators(allValidators);
ngControl.control.updateValueAndValidity();
return ngControl;
}
}));
};
/**
* @private
* @return {?}
*/
AbstractFormControl.prototype.validateLabel = /**
* @private
* @return {?}
*/
function () {
/** @type {?} */
var labelType = typeof this.label;
// If labelType is falsy, do not throw the error, since we have a backup label in case it's falsy.
if (labelType !== 'string' && this.label) {
/** @type {?} */
var typeMsg = "<AbstractFormControl> Invalid input provided to [label]. Label must be a string and you provided a " + labelType;
throw new MoHCommonLibraryError(typeMsg);
}
};
AbstractFormControl.propDecorators = {
label: [{ type: Input }],
disabled: [{ type: Input }],
errorMessage: [{ type: Input }]
};
return AbstractFormControl;
}(Base));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* DateComponent
* You cannot use "[restrictDate]" in combination with either "[dateRangeEnd]" or "[dateRangeStart]".
* You must use either [restrictDate] or the [dateRange*] inputs.
*
* \@example
* To trigger 'no future dates allowed' using date ranges set the range end date to yesterday's date.
* <common-date name='effectiveDate'
* label="Effective Date"
* [dateRangeEnd]='yesterday'
* formControlName="effectiveDate"></common-date>
* '
* To trigger 'no past dates allowed' using date ranges set the range start date to today's date.
* <common-date name='effectiveDate'
* label="Effective Date"
* [dateRangeStart]="today"
* formControlName="effectiveDate"></common-date>
*
* To allow instructions under label.
* <common-date name='effectiveDate'
* label="Effective Date"
* [dateRangeEnd]='yesterday'
* formControlName="effectiveDate">
* <p>This is a test.</p>
* </common-date>
* @export
*
* @type {?}
*/
var MAX_YEAR_RANGE = 150;
/** @type {?} */
var distantFuture = addYears(startOfToday(), MAX_YEAR_RANGE);
/** @type {?} */
var distantPast = subYears(startOfToday(), MAX_YEAR_RANGE);
var DateComponent = /** @class */ (function (_super) {
__extends(DateComponent, _super);
function DateComponent(controlDir, injectedValidators) {
var _this = _super.call(this) || this;
_this.controlDir = controlDir;
_this.injectedValidators = injectedValidators;
_this.dateChange = new EventEmitter();
_this.label = 'Date';
/**
* Can be one of: "future", "past". "future" includes today, "past" does not.
*/
_this.restrictDate = 'any';
_this._month = 'null'; // this makes it so the blank option is selected in the input
// variables for date ranges
_this._dateRangeStart = null;
_this._dateRangeEnd = null;
_this.monthList = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
];
_this.monthLabelforId = 'month_' + _this.objectId;
_this.dayLabelforId = 'day_' + _this.objectId;
_this.yearLabelforId = 'year_' + _this.objectId;
// Abstact variable defined
_this._defaultErrMsg = {
required: LabelReplacementTag + " is required.",
dayOutOfRange: "Invalid " + LabelReplacementTag + ".",
yearDistantPast: "Invalid " + LabelReplacementTag + ".",
yearDistantFuture: "Invalid " + LabelReplacementTag + ".",
noPastDatesAllowed: "Invalid " + LabelReplacementTag + ".",
noFutureDatesAllowed: "Invalid " + LabelReplacementTag + ".",
invalidValue: "Invalid " + LabelReplacementTag + ".",
invalidRange: "Invalid " + LabelReplacementTag + "."
};
_this.today = startOfToday();
_this.tomorrow = addDays(_this.today, 1);
if (controlDir) {
controlDir.valueAccessor = _this;
}
return _this;
}
Object.defineProperty(DateComponent.prototype, "dateRangeStart", {
/**
* The earliest valid date that can be used.
* Do NOT combine with restrictDates, as they set the same underlying values.
*/
set: /**
* The earliest valid date that can be used.
* Do NOT combine with restrictDates, as they set the same underlying values.
* @param {?} dt
* @return {?}
*/
function (dt) {
// Set time on date to 00:00:00 for comparing later
this._dateRangeStart = dt ? startOfDay(dt) : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DateComponent.prototype, "dateRangeEnd", {
/**
* The latest valid date that can be used.
* Do NOT combine with restrictDates, as they set the same underlying values.
*/
set: /**
* The latest valid date that can be used.
* Do NOT combine with restrictDates, as they set the same underlying values.
* @param {?} dt
* @return {?}
*/
function (dt) {
// Set time on date to 00:00:00 for comparing later
this._dateRangeEnd = dt ? startOfDay(dt) : null;
},
enumerable: true,
configurable: true
});
/**
* @param {?} changes
* @return {?}
*/
DateComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
/*
* Works, creates new object literall
* obj = {
* errorMessage: 'new'message';
* }
*
* Doesn't work, modifies existing object. Would have to manually call cd.detectChanges() afterwards.
* obj.errorMessage = 'newMessage';
*/
if (changes['errorMessage']) {
this.setErrorMsg();
}
};
/**
* @return {?}
*/
DateComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.setErrorMsg();
// Set to midnight, so we don't accidentally compare against hours/minutes/seconds
if (this.restrictDate !== 'any' && (this._dateRangeEnd || this._dateRangeStart)) {
/** @type {?} */
var msg = "<common-date> - Invalid @Input() option configuration.\nYou cannot use \"[restrictDate]\" in combination with either \"[dateRangeEnd]\" or \"[dateRangeStart]\".\nYou must use either [restrictDate] or the [dateRange*] inputs.\n\n <common-date name='effectiveDate'\n label=\"Effective Date\"\n [restrictDate]=\"'past'\" <<< problem, choose one\n [dateRangeEnd]='today' <<< problem, choose one\n formControlName=\"effectiveDate\"\n ></common-date>\n\n ";
throw new MoHCommonLibraryError(msg);
}
// Initialize date range logic
if (this.restrictDate === 'past') {
// past does allow for today
this._dateRangeEnd = this.today;
this._dateRangeStart = null;
}
else if (this.restrictDate === 'future') {
// future does NOT allow for today
this._dateRangeEnd = null;
this._dateRangeStart = this.tomorrow;
}
this.registerValidation(this.controlDir, this.validateSelf)
.then((/**
* @param {?} _
* @return {?}
*/
function (_) {
if (_this.injectedValidators && _this.injectedValidators.length) {
// TODO: Potentially move to AbstractFormControl
// Inspect the validator functions for one that has a {required: true}
// property. Importantly, we are inspecting the validator function
// itself and NOT the current state of the NgControl. -- Does not work for reactive forms
_this.isRequired = _this.injectedValidators
.filter((/**
* @param {?} x
* @return {?}
*/
function (x) { return x.required; }))
.length >= 1;
}
}));
};
Object.defineProperty(DateComponent.prototype, "month", {
get: /**
* @return {?}
*/
function () {
if (this.date) {
return this.date.getMonth();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DateComponent.prototype, "day", {
get: /**
* @return {?}
*/
function () {
if (this.date) {
return this.date.getDate();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DateComponent.prototype, "year", {
get: /**
* @return {?}
*/
function () {
if (this.date) {
return this.date.getFullYear();
}
},
enumerable: true,
configurable: true
});
/**
* Handles creating / destroying date and emitting changes based on user behaviour.
*/
/**
* Handles creating / destroying date and emitting changes based on user behaviour.
* @private
* @return {?}
*/
DateComponent.prototype.processDate = /**
* Handles creating / destroying date and emitting changes based on user behaviour.
* @private
* @return {?}
*/
function () {
if (this.canCreateDate()) {
/** @type {?} */
var year = this.getNumericValue(this._year);
/** @type {?} */
var month = this.getNumericValue(this._month);
/** @type {?} */
var day = this.getNumericValue(this._day);
// Date function appears to use setYear() so any year 0-99 results in year 1900 to 1999
// Set each field individually, use setFullYear() instead of setYear()
// Set time on date to 00:00:00 for comparing later
this.date = startOfDay(new Date(year, month, day));
this.date.setFullYear(year);
}
else {
// Trigger validator for emptying fields use case. This is to remove the 'Invalid date' error.
if (this.date ||
(!this._year && !this._day && this._month === 'null')) {
// Destroys the internal Date object.
this.date = null;
}
}
this._onChange(this.date);
this._onTouched(this.date);
this.dateChange.emit(this.date);
};
/**
* Returns true if and only if the day/month/year fields are all filled out.
*/
/**
* Returns true if and only if the day/month/year fields are all filled out.
* @private
* @return {?}
*/
DateComponent.prototype.canCreateDate = /**
* Returns true if and only if the day/month/year fields are all filled out.
* @private
* @return {?}
*/
function () {
// special because "0" is valid (Jan)
/** @type {?} */
var monthCheck = (typeof this._month === 'string' && this._month !== 'null')
|| typeof this._month === 'number';
if (!!this._year && !!this._day && monthCheck) {
return true;
}
return false;
};
/**
* @private
* @param {?} dt
* @return {?}
*/
DateComponent.prototype._triggerOnChange = /**
* @private
* @param {?} dt
* @return {?}
*/
function (dt) {
this._onChange(dt);
this.dateChange.emit(dt);
};
/** Convert string to numeric value or null if not */
/**
* Convert string to numeric value or null if not
* @private
* @param {?} value
* @return {?}
*/
DateComponent.prototype.getNumericValue = /**
* Convert string to numeric value or null if not
* @private
* @param {?} value
* @return {?}
*/
function (value) {
/** @type {?} */
var parsed = parseInt(value, 10);
return (isNaN(parsed) ? null : parsed);
};
/**
* @private
* @return {?}
*/
DateComponent.prototype.setDisplayVariables = /**
* @private
* @return {?}
*/
function () {
this._day = this.date.getDate().toString();
this._month = this.date.getMonth().toString();
this._year = this.date.getFullYear().toString();
};
/**
* @param {?} value
* @return {?}
*/
DateComponent.prototype.writeValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (value) {
this.date = value;
this.setDisplayVariables();
}
};
/**
* @param {?} value
* @return {?}
*/
DateComponent.prototype.onBlurDay = /**
* @param {?} value
* @return {?}
*/
function (value) {
this._day = value;
this.processDate();
};
/**
* @param {?} value
* @return {?}
*/
DateComponent.prototype.onBlurYear = /